Логотип игрового форума RF-Cheats.ru    
Новости онлайн игр Правила форума Чёрный рынок Реклама и привилегии Гаранты Арбитраж

Регистрация Бан-лист Сообщество ПОПУЛЯРНОЕ
Вернуться   RF-Cheats.ru - форум читеров и ботоводов > > >

Взлом программ (крэкинг, реверс, обход защит)

: Всё, что касается исследования программного обеспечения.
Читы и обход фроста для RF Online без хайдаБоты и читы для Perfect World бесплатно без хайдаМоды и читы для World of Tanks (WoT) бесплатно без хайдаМоды и читы для Armored Warfare бесплатно без хайдаБоты и читы для DOTA 2 бесплатно без хайдаБоты и читы для Black Desert Online бесплатно без хайдаЧиты на ArcheAge бесплатно без хайдаЧиты для Warface бесплатно без хайдаВзлом ВКонтакте и ОдноклассниковСписок разделов со всеми играмиЧиты для онлайн игр




Ответ
 
Сделать тему важной Опции темы
Старый 10.02.2009, 16:49   #1
SHTrassEr
Гость
Аватар для SHTrassEr
Сообщений: n/a
Благодарностей:
0 всего

[СТАТЬЯ] Использование отладчика для изучения RFOnline на примере разбора авотризации


Данная статься предназначена для тех, кто хочет научиться исследовать программы, но не знает, с чего начать. В этой статье покажу простой пример использования отладчика на примере изучения протокола связи с логин сервером РФО.

После того, как вы ввели имя и пароль, логин программа РФО посылает введенную вами информацию в зашифрованном виде. В этой статье я покажу, как узнать применяемый при этом алгоритм шифрования.

Перед тем, как исследовать программы желательо научиться:
1. программироать хотя бы на 1-м языке программирования
2. понимать язык ассемблера (хорошо бы научиться программировать и на нем)
3. прочитать про регистры процессора, хотя бы здесь


Для работы понадобятся 3 программы:
1. OllyDbg 1.09b - отладчик
2. WPE PRO Alpha 0.9a - сниффер
3. родная логин программа РФО (в дальнейшем ЛП)

Версии программ могут отличаться от приведенных выше.

часть 1
Первым делом запускаем логин-прогу РФ'а.
Пускаем WPE и пускаем прослушивание трафика ЛП.
в ЛП в качестве логина и пароля указываем "1111111111" и тыкаем войти, естественно получим сообшение вроде: логин или пароль неверны.
Смотрим на перехваченный с помошью WPE трафик, получаем что-то вроде (стрелкой > обозначен входящий пакет, < - исходящий):

>05 00 15 0C FF
<07 00 15 0D 02 D3 02
>1F 00 15 03 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 D5 D5 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 E2 D5 00
<0E 00 15 04 06 CC CC CC CC 00 00 00 00 CC

Повторяем процедуру и получаем (например)

>05 00 15 0C FF
<07 00 15 0D 03 F8 02
>1F 00 15 03 CE CE CE CE CE CE CE CE CE CE CE FF FF CE CE CE CE CE CE CE CE CE CE CE CE FF 00
<0E 00 15 04 06 CC CC CC CC 00 00 00 00 CC

жирным указаны заголовки пакетов, справа от них - тело пакета.

Как можно видеть, 1-й пакет в обоих случаях одинаковый, 2-й отличается только последними 3-мя байтами. Логично предположить следующий протокол:
1. Клиент запрашивает у сервера ключ (1-й пакет)
2. Сервер ключ пересылает клиенту (2-й пакет)
3. Клиент полученным ключом шифрует имя и пасс и отсылает эту инфу серверу (3-й пакет)
4. сервер высылает клиенту результат проверки (4-й пакет)

В принципе, все это можно вычитать в описании форматов пакетов:
Цитата:
c150C=CryptyKeyRequest:h(psize)h(ID:Get.ID) (1-й пакет)
s150D=CryptyKeyInform:h(psize)h(ID:Get.ID)c(key1)h (key2) (2-й пакет)
c1503=LoginAccountRequest:h(psize)h(ID:Get.ID)a(00 12Login [crypted])-(0001)a(0012Password [crypted])-(2) (3-й пакет)
s1504=LoginAccountResult:h(psize)h(ID:Get.ID)c(res ult:Get.LRes)d(AccountID)d('1'=premium)c(c?) (4-й пакет)
Итак, ключ есть. Теперь основная задача выяснить, каким образом ЛП шифрует пакет. Есть несколько способов это сделать:
1. повторить часть 1 раз 100 и выявить закономерность.
2. Посмотреть, как это делает ЛП.

Будем действовать 2-м путем (естественно )) ).
Можно заметить, что алгоритм шифрования представляет собой обычный шифр гамирования с длиной гаммы = 1 и переменным ключом. Простенький алгоритм в общем-то.

часть 2
Первым делом выключаем ЛП (если она была запущена)
1. Запускаем OllyDb
2. File->Open выбираем rf.exe. Olly напишет нам дизассемблированный код ЛП.
3. Запускаем (тычем F9).

Теперь нужно найти кусод кода, в котором происходит кодирование пакета. Для этого проще всего найти код, в котором происходит прием пакета с ключем, а затем посмотреть, где данные этого пакета используются.
Связь с сервером осуществляется посредством TCP протокола. В Windows этот протокол реализован в API функциях. Для приема пакета используется функция recv. Т.о. нужно найти место в программе, где вызывается эта функция.

Заметим, что ключ передается ЛП во 2-м пакете. Т.е. первый присланный пакет и будет содержать ключ.

4. ищем.
Правой кнопкой мыши тычем на код ЛП, в отмывшемся меню выбираем: Search for -> All intermodular calls. нам выпадает большой список всех вызываемых программой внешних функций. Среди них ищем (в поле Destanation)
WS2_32.recv.
и дважды кликаем по ней.
Код:
MOV EAX,DWORD PTR SS:[ESP+C]
PUSH ESI
PUSH EDI
PUSH 0                                   ; /Flags = 0
PUSH EAX                                 ; |BufSize
MOV EAX,DWORD PTR SS:[ESP+14]            ; |
MOV ESI,ECX                              ; |
MOV ECX,DWORD PTR SS:[ESP+18]            ; |
LEA EDX,DWORD PTR DS:[EAX+EAX*8]         ; |
MOV EAX,DWORD PTR DS:[ESI+10]            ; |
PUSH ECX                                 ; |Buffer
SHL EDX,4                                ; |
MOV ECX,DWORD PTR DS:[EDX+EAX]           ; |
PUSH ECX                                 ; |Socket
CALL DWORD PTR DS:[<&WS2_32.#16>]        ; \recv
MOV EDI,DWORD PTR SS:[ESP+18]
CMP EAX,-1
MOV DWORD PTR DS:[EDI],EAX
JNZ SHORT rf.00488CCB
CALL DWORD PTR DS:[<&WS2_32.#111>]       ; [WSAGetLastError
CMP EAX,2733
MOV DWORD PTR DS:[EDI],EAX
JE SHORT rf.00488CC4
INC DWORD PTR DS:[ESI+48]
POP EDI
XOR AL,AL
POP ESI
RETN 10
POP EDI
MOV AL,1
POP ESI
RETN 10
Вот эта функция и принимает пакет. Кое-что о ней: начиная с 4-й строчки (PUSH 0) в стек заталкиваются параметры API функции recv. Сама функция вызывается на 15-й строчке (CALL DWORD PTR DS:[<&WS2_32.#16>] ). Важно: в качестве параметра функции передается адрес на область памяти, куда нужно положить принятый пакет. Это происходит на 11-й строчке (PUSH ECX помещаем в стек значение регистра ECX). Дебаггер эту команду пометил справа словом Buffer. После исполнения функции recv в памяти по адресу, помещенному в стек на 11-й строчке, будет находится принятый пакет. Этот адрес нужно узнать.

5. Ставим брекпоинт на 11-ю строчку функции (на команду PUSH ECX). Для этого выделяем нужную строчку и тычем F2. Брекпоинт обозначается слева красным прямоугольником.

6. Вспоминаем, что у нас есть запущенная из-под OllyDb логин прогарамма. Переходим на нее указываем логин и пароль (лучше всего указать "11111111111"). и нажимаем "войти".

Если все сделали правильно, то выполнение ЛП прекратится.

7. Переходим на дебаггер. Смотрим адрес, написанный в регистре ECX (запоминаем его). Значение регистров описаны справа. Выделяем значение справа от ECX -> ПКМ -> Follow in Dump. В нижнем левом разделе находится дамп памяти ЛП. После выполнения команды recv по адресу, указанному в ECX будет находится содержмое пакета.

8. Ставим брекпоинт на последнюю строчку функции.

9. продолжаем выполнение ЛП (тычем F9)

10. Срабатывает последний поставленный нами брекпоинт.
Смотрим на дамп памяти. Пакет появился там где и должен.
Мой соответствующий дамп: 04164E40 07 00 15 0D 04 2C 03

Вспоминаем: 1-е 4 байта - описание пакета. Нам же нужен сам ключ, т.е. последние 3 байта.

11. убираем проставленные брекпоинты

12. в дампе памяти для 5-го байта принятого пакета устанавливаем брекпоинт на чтение памяти. Для этого выделяем 5-й пакет, ПКМ -> breakpoint -> memory, on access

Брекпоинт сработает в тот момент, когда ЛП прочитает содержимое пакета.

13. Продолжаем выполнение программы.

14. Если все сделано верно, то выполнение программы опять прервется на следующей функции:

Функция RecvCryptKeyRequest
Код:
PUSH ESI
MOV ESI,ECX
PUSH rf.004D31B4                         ;  ASCII "<4> RecvCryptKeyRequest"
MOV EAX,DWORD PTR DS:[ESI+435F4]
PUSH EAX
CALL rf.00451A70
PUSH EAX
CALL rf.00451D00
MOV EAX,DWORD PTR SS:[ESP+18]
ADD ESP,0C
0MOV CX,WORD PTR DS:[EAX+1]
MOV DL,BYTE PTR DS:[EAX]
ADD CX,3
INC DL
PUSH ECX
PUSH EDX
MOV ECX,ESI
CALL rf.???????? - сохраняет значения ключа в память (на месте ? - число)
MOV ECX,ESI
CALL rf.????????  - <- в этой функции шифруется пакет
MOV AL,1
POP ESI
RETN 8
в этой функции производятся некороые преобразования ключа. на 11-й строке функции (0MOV CX,WORD PTR DS:[EAX+1]) в регистр CX заносится 7-й и 6-й байты принятого пакета (именно в таком порядке), на 12-й строчке (MOV DL,BYTE PTR DS:[EAX]) в регистр DL заносится 5-й байт.
13-18 строки:

Код:
ADD CX,3    прибавили к CX 3
INC DL    прибавили к DL 1
PUSH ECX     поместили в стек значение регистра ECX 
PUSH EDX     поместили в стек значение регистра EDX 
MOV ECX,ESI        ECX=ESI        хз зачем, не разбирался)
CALL rf.???????? вызывается функция rf.???????? (на месте ? - числа)
в функции rf.???????? полученные значения для ECX и EDX (которые были сохранены в стеке), запмсываются в память, а из стека удаляются.

Код:
MOV BYTE PTR DS:[ECX+435E0],AL   AL содержит 5-й байт пакета+3
MOV WORD PTR DS:[ECX+435E2],DX    DX содержит 7-й 6-й байт пакета +1
15. Теперь ставим брекпоинт на 19-й строчке функции RecvCryptKeyRequest (см выше, эта строка выделена жирным).

16. тычем F9

17.Выполнение программы прервалось на 19-й строчке. Дальше будем выполнять программу пошагово. Для выполнения следующего шага нажимаем F7.

18. После 1-го нажатия F7 происходит вызов функции, в которой кодируется пакет. Привожу начало этой функции с небольшими комментами. Жирным выделен цикл, в котором кодируется пакет.

Код:
SUB ESP,20
XOR EAX,EAX
PUSH EBX
PUSH ESI
MOV EBX,ECX
PUSH EDI
MOV ECX,6
LEA EDI,DWORD PTR SS:[ESP+10]
REP STOS DWORD PTR ES:[EDI]
STOS WORD PTR ES:[EDI]
STOS BYTE PTR ES:[EDI]
MOV EAX,DWORD PTR DS:[EBX+435F4]
PUSH rf.004D31FC                         ;  ASCII "<5> SendLoginAccept Normal"
PUSH EAX
CALL rf.00451A70
PUSH EAX
CALL rf.00451D00
MOV EDI,DWORD PTR DS:[EBX+435EC]
OR ECX,FFFFFFFF
XOR EAX,EAX
ADD ESP,0C
REPNE SCAS BYTE PTR ES:[EDI]
NOT ECX
SUB EDI,ECX
LEA EDX,DWORD PTR SS:[ESP+10]
MOV EAX,ECX
MOV ESI,EDI
MOV EDI,EDX
LEA EDX,DWORD PTR SS:[ESP+1D]
SHR ECX,2
REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>
MOV ECX,EAX
XOR EAX,EAX
AND ECX,3
REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
MOV EDI,DWORD PTR DS:[EBX+435F0]
OR ECX,FFFFFFFF
REPNE SCAS BYTE PTR ES:[EDI]
NOT ECX
SUB EDI,ECX
MOV EAX,ECX
MOV ESI,EDI
MOV EDI,EDX
SHR ECX,2
REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>
MOV ECX,EAX
MOV AX,WORD PTR DS:[EBX+435E2]           ;  Здесь в AX заносятся 7-й и 6-й байты пакета, к ним прибавили 3
AND ECX,3
REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
MOV CL,BYTE PTR DS:[EBX+435E0]           ;  В CL заносятся 5-й байт пакета, к нему прибавили 1 (см выше)
LEA ESI,DWORD PTR SS:[ESP+10]
MOV EDI,1B
/MOV DL,BYTE PTR DS:[ESI]     - поместили очередной байт пакета в DL
|ADD DL,CL        - прибавили к DL значение регистра Cl
|XOR DL,AL        - Исключающее ИЛИ
|MOV BYTE PTR DS:[ESI],DL        - разультат запомнили
|INC ESI
|DEC EDI
\JNZ SHORT rf.0044ABF6


Вот пожалуй и все. Итак, алгорим шифрования:
X - байт, который нужно зашифровать
Y - зашифрованный байт

Y = (X + 6-й байт пакета + 3) XOR (5-й байт пакета +1)

Как видите, ничего сложного. Заметим, что перед циклом а в регистр AX заносятся 7-й и 6-й байты пакета (+3), Однако в цикле участвует не AX, а AL. Т.е. старший байт регистра AX, он называтся AH и он содержит 7-й байт принятого пакета (возможно +1 в некоторых случаях), в шифровании не участвует.

7-й байт не участвует в шифровании.

На сегодня все. Если тема покатит, напишу еще что-нибудь подобное.

Если чего-нибудь непонятно - юзайте гугл.

Последний раз редактировалось Тигрь; 24.05.2012 в 10:12.
 
Ответить с цитированием
Сказали спасибо:
Недоступно (23.05.2012), ne0-n (09.04.2012), MoXxX (08.05.2011), QelED (30.06.2009), Недоступно (14.03.2009), Недоступно (08.03.2009), Недоступно (21.02.2009), Stormraider (17.02.2009), saaleb (17.02.2009), sashblo (16.02.2009), Недоступно (16.02.2009), Недоступно (11.02.2009), Джони (10.02.2009), traxinator (10.02.2009)


Старый 20.04.2009, 08:07   #2
Dr.Frank
Гость
Аватар для Dr.Frank
Сообщений: n/a
Благодарностей:
0 всего

Код:
>1f 00 15 03 e2 e2 e2 e2 e2 e2 e2 e2 e2 e2 e2 d5 d5 e2 e2 e2 e2 e2 e2 e2 e2 e2 e2 e2 e2 d5 00
А как определить, откуда появляются(в данном случае) байты d5 ?

Последний раз редактировалось Dr.Frank; 20.04.2009 в 08:16.
 
Ответить с цитированием
Старый 28.01.2011, 01:25   #3
AnderSon
Гость
Аватар для AnderSon
Сообщений: n/a
Благодарностей:
0 всего

Кто-нить знает, в 2.2.3 поменяли ключ шифрования? И кстати, здесь вроде ошибка должно быть Y = (X + 5-й байт пакета + 1) XOR (6-й байт пакета +3). Но всеравно шифр ни тот , ни автора не подходит, разве что я не так понял формулу :(
 
Ответить с цитированием
Старый 01.02.2011, 09:22   #4
SHTrassEr
Гость
Аватар для SHTrassEr
Сообщений: n/a
Благодарностей:
0 всего

Помнится, в приведенной мной формуле была какая-то ошибка, это я уже после того, как написал этот пост обнаружил.

Сейчас посмотрел, похоже так привильно:
Y = (X+5-й байт + 3) XOR (6-й байт+1)

по крайней мере по этой формуле получается закодировать пакеты из поста:

E2 = (31 + 02 + 3) XOR (D3+1)
(31 - символ '1', 02 - 5-й байт, D3 - 6-й байт)

CE = (31 + 03 + 3) XOR (F8 + 1)

То есть на момент написания поста последняя формула скорее всего верна. Но может быть формула изменилась, да.
 
Ответить с цитированием
Старый 01.02.2011, 10:29   #5
AnderSon
Гость
Аватар для AnderSon
Сообщений: n/a
Благодарностей:
0 всего

Спс большое. Еще вопрос, посылаю я пакет с логином и пассом, а сервак отвечает пакетом у которого первые четыре байта цифрами а остальное все нули, ето может быть запрос на пересылку логина и паса изза неправильной шифровки?
Да и алгоритм странный какой-то, оба подходят

Последний раз редактировалось AnderSon; 01.02.2011 в 10:37.
 
Ответить с цитированием
Старый 22.05.2012, 23:09   #6
demo
Читер со стажем
Аватар для demo
OFFLINE
Регистрация: 03.08.2007
Возраст: 35
Сообщений: 481
Благодарностей:
726 всего
Мнения: + 4014
Репутация: 3119
Отправить сообщение для demo с помощью ICQ

Ничего не понимаю, у меня цифра 1 равна не 31 а 49... чё делать???

Попробуй убей меня тут!

Приложение для андроид для игроков руоффа: https://market.android.com/details?i...rfstatuserfree
 
Ответить с цитированием
Старый 22.05.2012, 23:31   #7
Тигрь
Крестный отец всех читеров
Аватар для Тигрь
OFFLINE
Регистрация: 02.04.2008
Сообщений: 4,027
Благодарностей:
37,693 всего
Мнения: + 29193
Репутация: 106451

Цитата:
Сообщение от demo Посмотреть сообщение
Ничего не понимаю, у меня цифра 1 равна не 31 а 49... чё делать???
Сережа ты головой случайно нигде не ударялся недавно? Ты что единица это 31 в хексе, а 49 в десятичной. Тебе акк случаем не взломали?


Я летаю снаружи всех измерений.



 
Ответить с цитированием
Старый 23.05.2012, 11:12   #8
demo
Читер со стажем
Аватар для demo
OFFLINE
Регистрация: 03.08.2007
Возраст: 35
Сообщений: 481
Благодарностей:
726 всего
Мнения: + 4014
Репутация: 3119
Отправить сообщение для demo с помощью ICQ

нет, тигрь. Привет. Я просто давно не программировал, вот и немного подзабылось. Я уже допёр до этого, но проблема в другом. Пишу мини консольную прогу на си шарпе. Не могу никак зашифровать логин и пароль. Сможешь помочь? А то эрроры выдаёт...

Кстати по поводу 31 и 49. Тут в статье вогела про написание ланчера использована делфёвая функция ord, она возвращает по идее не hex значение, а аски код буквы.

А вообще у меня проблема с тем что не вдупляю почему на си шарпе (новый для меня язык) крашится приложение. Точнее я понимаю почему крашится, но не понимаю почему не правильно. в общем опишу ситуёвину.

Отправил 1 пакет, в ответ получил пакет с ключом. А вот дальше начинается жопа. Пытаюсь зашифровать логин и пароль, а в результате получаю ошибку, которая говорит что значение слишком большое чтоб сконвертить его в байт (в моём случае там значение 360 получается).

входящие данные:
логин 1111
пароль 1111
плюс ключ 0x04
ксор ключ 0xFF

Вот код на шарпе:

Код:
public static byte[] CryptLoginPassword(string login, string passowrd, byte aPlusKey, byte aXORKey) {
			int maxPasswordLength = 13;
			int MyByte = 0;
			byte[] resylt1 = new byte[13];//задаю массив под логин
			byte[] resylt2 = new byte[13];//задаю массив под пароль
			
			for (int i = 0; i < maxPasswordLength; i++) {
				if (i < login.Length) { 
					MyByte = ORD(login[i]);//тут беру очередную букву, получаю аски код и использую его
				} else {
					MyByte = 0;
				}
				
				MyByte = MyByte + aPlusKey+1; //плюсую 1 ключ
				MyByte = (MyByte) ^ (aXORKey+3); //ксорю ксор-ключом
				resylt1[i] = Convert.ToByte(MyByte); //Вот тут возникает ошибка, тут майбайт имеет значение 360
			}
			
			for (int i = 0; i < maxPasswordLength; i++) {
				if (i < passowrd.Length) { 
					MyByte = ORD(passowrd[i]);
				} else {
					MyByte = 0;
				}
				
				MyByte = MyByte + aPlusKey +1;
				MyByte = (MyByte) ^ (aXORKey+3);
				resylt2[i] = Convert.ToByte(MyByte);
			}
			
			byte[] resultfinal = new byte[26];
			resylt1.CopyTo(resultfinal, 0);
			resylt2.CopyTo(resultfinal, resylt1.Length);
			return resultfinal;
			
		}
Я понимаю что значение май байт не должно быть больше 255, но не понимаю что я не так сделал.

Прошу не кидаться какахами, так как от такого программирования я отдыхал очень долго и всё забыл почти.

Добавлено через 27 минут
точный текст ошибки:

System.OverflowException: Значение было недопустимо малым или недопустимо большим для беззнакового байта.
в System.Convert.ToByte(Int32 value)

Это в строке с resylt1[i] = Convert.ToByte(MyByte);
Кстати под хекс я переделал

Добавлено через 41 минуту
в идеале конечно чтоб кто нибудь поделился функцией шифрования пароля, с меня б тогда пиво...

Последний раз редактировалось demo; 23.05.2012 в 11:54. Причина: Добавлено сообщение

Попробуй убей меня тут!

Приложение для андроид для игроков руоффа: https://market.android.com/details?i...rfstatuserfree
 
Ответить с цитированием
Старый 23.05.2012, 12:49   #9
Тигрь
Крестный отец всех читеров
Аватар для Тигрь
OFFLINE
Регистрация: 02.04.2008
Сообщений: 4,027
Благодарностей:
37,693 всего
Мнения: + 29193
Репутация: 106451

да и шарп я не оч люблю, ну через пару неделек можно попробовать, если конечно сам уже не сделаешь.

Последний раз редактировалось Тигрь; 23.05.2012 в 22:12.


Я летаю снаружи всех измерений.



 
Ответить с цитированием
Старый 23.05.2012, 12:51   #10
demo
Читер со стажем
Аватар для demo
OFFLINE
Регистрация: 03.08.2007
Возраст: 35
Сообщений: 481
Благодарностей:
726 всего
Мнения: + 4014
Репутация: 3119
Отправить сообщение для demo с помощью ICQ

сам врят ли, хотя кто его знает. Но за помощь отблагодарю ;)

я си шарп взял только потому что он больше на яву похож, и с него не так сложно перенести исходники под андроид, что является моей финальной целью :)

Попробуй убей меня тут!

Приложение для андроид для игроков руоффа: https://market.android.com/details?i...rfstatuserfree
 
Ответить с цитированием
Ответ



Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Мир танков | Проект "Армата" | ArcheAge | Black Desert | РФ Онлайн | Айон | Майнкрафт | Браузерные игры
Элдер скролс | Р2 Онлайн | Реквием Онлайн | ПУБГ | Роял Квест | ГТА Санадреас | Контра | Дота 2
Мир кораблей | Лост Арк | Arma2 DayZ mod | The War Z | Карос: Начало | Tera Online
Читы для всех Онлайн-игр