Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 12 ноября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Снимаем таймер подключения в Garena Client (last version)

Обсудить статью на форуме

Очень удобно, когда все крэкерские инструменты, книги и статьи в одном месте. Используйте сборник от EXELAB - вот тут.

Автор: [PNZ]human <pnz.human@xakep.ru>

Инструменты

OllyDbg
HIEW32

Вступление или Немного о жертве


Доброго всем времени суток! Наша жертва - Garena Client (http://www.garena.com/) - это клиент игровой сетевой платформы, позволяющая играть в различные игры по интернету без лагов. Вообще вещь достаточно популярная, поэтому она и вызвала у меня особый интерес для реверса. Чтобы поиграть, нужно сначала зайти в комнату, но первые комнаты вечно забиты и прорваться туда очень сложно (но нужно, ибо именно там лучшие соперники). После попытки зайти в комнату и сообщении о том, что данная рума переполнена, нам нельзя пытаться зайти в неё снова ещё 5 секунд, что существенно снижает процент захода. Для меня стало целью убрать это ограничение дабы повысить процент захода в топовые румы (не себе, конечно, сам то я не гамаю =)

На портале и вообще в крэкинге я только "чайник продвинутый", хехе, а посему буду рад выслушать любую критику.

Ну чтож, начнем-с!

Часть 1 - Поиск и удаление "таймера"


Запустив Garena.exe в пропатченной и "проплагиненной" Ольке (по урокам Рикардо Нарвахи) у меня почему то не запускается Garena - виснет на загрузке Chenyx.dll из папки pluginsUI. Кто может объяснить или высказать свои мнения по этому поводу, пожалуста пишите.

Поэтому я поставил чистую Ольку, на которой все прекрасно грузится =). Итак, после повторного входа в комнату, появляется окошко с надписью "Sorry, you can only try join a room every 5 seconds". Можно попробовать поставить бряки на MessageBox, но это не поможет: 1). Это не "великое сообщение" =) 2). видимо, гарена ставит VirtualProtect, поэтому ставить обычные бряки не получится, ну и пусть, воспользуемся аппаратными.
Лично я нашёл такой способ: до начала появления первого пятисекундного предупреждения, ищем в памяти юникод-строку, она находится в секции .rsrc модуля Garena.
Далее ставим на неё Hardware Breakpoint on access на первый байт и пытаемся повторно зайти в комнату, останавливаемся тут:

7E369E0B   .  66:F3:A5      REP MOVS WORD PTR ES:[EDI],WORD PTR DS:[>
7E369E0E   .  8B7D 10       MOV EDI,DWORD PTR SS:[EBP+10]
7E369E11   >  FF75 08       PUSH DWORD PTR SS:[EBP+8]


Если посмотреть в стек, то можно понять, что мы находимся где то в USER32.LoadStringW, о чем свидетельствует адрес возврата и коммент Ольки

0012B09C  |00F6411D  RETURN to Language.00F6411D from USER32.LoadStringW


Выходим по этому адресу возврата: Right_Click -> Follow in Disassembler (Enter) и оказываемся здесь


00F64117    FF15 64E1F800   CALL DWORD PTR DS:[<&USER32.LoadStringW>>; USER32.LoadStringW
00F6411D    8D4424 20       LEA EAX,DWORD PTR SS:[ESP+20]
00F64121    8D50 02         LEA EDX,DWORD PTR DS:[EAX+2]
00F64124    66:8B08         MOV CX,WORD PTR DS:[EAX]
00F64127    83C0 02         ADD EAX,2


Мы находимся в модуле Language - чисто по названию можно предположить, что это модуль "общение с юзером", или что то в этом роде, но врядли тут окажется проверка на конец таймера. Кстати, таймер организован не через функцию вроде SetTimer, а других я пока не знал =) Так же и не дал каких то результатов и поиск в коде "PUSH 1388" (5000 в dec).
Так как мы предположили, что этот модуль нам не нужен, идем дальше до "RETN 8" (если идти по F7F8 то прога опять у меня виснет, так что я поставил hr на эту инструкцию). После выхода из Language, оказываемся тут:

004E0B7D  |.  FFD0          CALL EAX
004E0B7F  |.  8B4424 14     MOV EAX,DWORD PTR SS:[ESP+14]
004E0B83  |.  3BC7          CMP EAX,EDI
004E0B85  |.  75 1A         JNZ SHORT Garena.004E0BA1
004E0B87  |.  8B7424 30     MOV ESI,DWORD PTR SS:[ESP+30]


Ок, теперь мы в основном модуле, его мы и будем копать. Мы находимся в функции, о чем свидетельствует жирная дуга слева от опкода. Видим, что кроме CALL'a, из которого мы вышли, в этой функции больше ничего сверху нету (код выполняется линейно), а поэтому поставим hr на на PUSH -1 и посмотрим в стеке, откуда вызывается сиё чудо (не забывайте удалять ненужные hr бряки, ибо их всего четыре) :

004E0B30  /$  6A FF         PUSH -1
004E0B32  |.  68 386E5900   PUSH Garena.00596E38
004E0B37  |.  64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
004E0B3D  |.  50            PUSH EAX
004E0B3E  |.  83EC 10       SUB ESP,10
004E0B41  |.  53            PUSH EBX
004E0B42  |.  56            PUSH ESI
004E0B43  |.  57            PUSH EDI
004E0B44  |.  A1 50596100   MOV EAX,DWORD PTR DS:[615950]
004E0B49  |.  33C4          XOR EAX,ESP
004E0B4B  |.  50            PUSH EAX
004E0B4C  |.  8D4424 20     LEA EAX,DWORD PTR SS:[ESP+20]
004E0B50  |.  64:A3 0000000>MOV DWORD PTR FS:[0],EAX
004E0B56  |.  33FF          XOR EDI,EDI
004E0B58  |.  897C24 10     MOV DWORD PTR SS:[ESP+10],EDI
004E0B5C  |.  897C24 1C     MOV DWORD PTR SS:[ESP+1C],EDI
004E0B60  |.  897C24 18     MOV DWORD PTR SS:[ESP+18],EDI
004E0B64  |.  897C24 14     MOV DWORD PTR SS:[ESP+14],EDI
004E0B68  |.  8B09          MOV ECX,DWORD PTR DS:[ECX]
004E0B6A  |.  8B01          MOV EAX,DWORD PTR DS:[ECX]
004E0B6C  |.  8B40 0C       MOV EAX,DWORD PTR DS:[EAX+C]
004E0B6F  |.  8D5424 14     LEA EDX,DWORD PTR SS:[ESP+14]
004E0B73  |.  52            PUSH EDX
004E0B74  |.  8B5424 38     MOV EDX,DWORD PTR SS:[ESP+38]
004E0B78  |.  52            PUSH EDX
004E0B79  |.  897C24 30     MOV DWORD PTR SS:[ESP+30],EDI
004E0B7D  |.  FFD0          CALL EAX


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

0012E358   00499227  RETURN to Garena.00499227 from Garena.004E0B30


Запоминаем его, теперь надо выполнить следующую вещь: пытаемся зайти в комнату, и когда всплывает отладчик быстро жмем F9 и снова заходим в руму, тем самым спровоцировав появление окошка. Отладчик всплывает и в этом случае, но сейчас адрес возврата уже другой:

0012D91C   00540954  RETURN to Garena.00540954 from Garena.004E0B30


Так так,немного поразмыслив, можно предположить, что есть некая функция и в зависимости от каких то действий происходит её вызов с различными параметрами (так как функция вызывается в обоих случаях).
Дальше всё очевидно: ставим курсор на esp (строка выше) и давим на Enter, оказываемся тут (попадаем в место вызова процедуры с плохими параметрами):

0054092B   > 8B35 CC135A00 MOV ESI,DWORD PTR DS:[<&KERNEL32.GetTick>;  kernel32.GetTickCount
00540931   .  FFD6          CALL ESI                                 ; [GetTickCount
00540933   .  2B05 109E6100 SUB EAX,DWORD PTR DS:[619E10]
00540939   .  3D 88130000   CMP EAX,1388
0054093E   .  73 60         JNB SHORT Garena.005409A0                ; 
00540940   .  68 AE010000   PUSH 1AE                                 ; /Arg2 = 000001AE
00540945   .  8D4C24 58     LEA ECX,DWORD PTR SS:[ESP+58]            ; |
00540949   .  51            PUSH ECX                                 ; |Arg1
0054094A   .  B9 40F86000   MOV ECX,Garena.0060F840                  ; |
0054094F   .  E8 DC01FAFF   CALL Garena.004E0B30                     ; Garena.004E0B30


Ок, кажется, мы нашли то, что нужно: вызывается функция GetTickCount, затем высчитывается какая то разность и сравнивается с ... 1388!!! (для тех, что не помнит, это 5000 в dec). И как я мог забыть поискать кроме пуша ещё и сравнение ;)
По адресу 0054093E находится переход, который ведет на 005409A0, в Ольке очень хорошо видно, что этот переход как раз и пропускает вызов функции с "плохими параметрами" =).
Пробуем, ставим hr бряк по адресу 0054093E, ломимся в комнату, отладчик всплывает и сейчас всё TRUE (мы пролетаем через функцию). Теперь быстренько (надо успеть за пять секунд) жмакаем F9 и опять ломимся -> отладчик всплывает, но теперь уже не True, меняем флаг C и, отпустив прогу на волю, видим, что мы пытаемся зайти второй раз!! Ура товарищи, у нас всё получилось!!!

Если вы подумали, что это всё, то ошиблись, хехе.
Давайте сделаем патч: очевидно надо заменить JNB переход на JMP, но когда прога уже загружена, сделать это не удастся, поэтому запоминаем адрес перехода - 0054093E, нажимаем Ctrl+F2, переходим по адресу (Ctrl+G -> 0054093E -> Enter) и меняем переходик. После чего жмакаем правой кнопкой по листингу -> Copy to Executable -> All modifications -> Copy All. Сохраняем под новым именем, и... нет, ещё не закрываем статью, потому что дальше будет поинтереснее =).

Часть 2 - Убираем проверку на "вшивость" патченного EXE


Те, кто уже обрадовались, что всё закончено, ошибались, ибо после запуска Garena.exe появляется окошко с надписью "You are using a cracked version of Garena. Garena will close shortly ...". Эх, а я то уж обрадовался...
Снова загружаем Garen'у в Ольгу, и ставим hr на USER32.CreateDialogParamW (для этого нажимаем Ctrk+N, набираем "cre", оказываемся на функции, далее правай кнопка-> Follow import in disassembler и мы в первой строке кода данной API). Запускаем прогу и пропускаем все ненужные срабатывания бряка. Как только прога запустилась, сидим и ждем всплытие отладчика ;).
Ок, отладчик всплыл, вот стек:

0012E630   04E793F7  /CALL to CreateDialogParamW from AvoidCra.04E793F1
0012E634   04E70000  |hInst = 04E70000
0012E638   00000065  |pTemplate = 65
0012E63C   00000000  |hOwner = NULL
0012E640   04E79640  |pDlgProc = AvoidCra.04E79640
0012E644   00000000  lParam = 0
0012E648   04E94A88  AvoidCra.04E94A88
0012E64C   04E7918E  RETURN to AvoidCra.04E7918E from AvoidCra.04E79360


Итак, вся соль в AvoidCrackPlugin.dll, которая находится в папке с плагинами(пусть можно узнать, нажав Alt+E в Ольке). Её название говорит само за себя, чтоб постараемся устранить проверку на вшивость ЕХЕ-шника. Выходим к тому месту, где была вызвана брякнутай апишка:

0012E630   04E793F7  /CALL to CreateDialogParamW from AvoidCra.04E793F1

Left click -> Enter. Теперь мы тут

04E7935F    CC              INT3
04E79360    837F 14 00      CMP DWORD PTR DS:[EDI+14],0
04E79364    75 10           JNZ SHORT AvoidCra.04E79376
04E79366    E8 A1140000     CALL AvoidCra.04E7A80C
04E7936B    85C0            TEST EAX,EAX
04E7936D    8947 14         MOV DWORD PTR DS:[EDI+14],EAX
04E79370    0F84 83000000   JE AvoidCra.04E793F9
04E79376    8B47 14         MOV EAX,DWORD PTR DS:[EDI+14]
...
04E793F0    50              PUSH EAX
04E793F1    FF15 B0C1E804   CALL DWORD PTR DS:[<&USER32.CreateDialog>; USER32.CreateDialogParamW
04E793F7    5E              POP ESI
04E793F8    C3              RETN
04E793F9    6A 0E           PUSH 0E
04E793FB    FF15 4CC0E804   CALL DWORD PTR DS:[<&KERNEL32.SetLastErr>; ntdll.RtlSetLastWin32Error
04E79401    33C0            XOR EAX,EAX
04E79403    C3              RETN
04E79404    6A 00           PUSH 0
04E79406    6A 00           PUSH 0
04E79408    6A 01           PUSH 1
04E7940A    68 050000C0     PUSH C0000005
04E7940F    FF15 50C0E804   CALL DWORD PTR DS:[<&KERNEL32.RaiseExcep>; kernel32.RaiseException


Дальше по логике вещей надо посмотреть выше вызова USER32.CreateDialogParamW на переходы, которые перескакивают через этот самый вызов =)
Здесь их три штуки, и все они прыгают на один и тот же код, следовательно, проверка проверяется по трем критериям, и если первое правильное, то проверяем второй и т.д. Кароче нам надо заменить самый старший (читай стоящий выше) условный переход на безусловный. Чтобы убедится, что нам нужно менять именно этот переход, можно поставить hr бряк на него :

04E79370   /0F84 83000000   JE AvoidCra.04E793F9

Рестартуем Garena -> Ctrl+F2, и запускаем -> F9. Останавливаемся на бряке, и видим, что он сейчас не сработает, меняем флаг Z и никакого окошка не появляется! Ура, товарищи!

Теперь есть один момент по поводу того, как сделать так, чтобы был jmp а не je. Как вы знаете, править то нам сейчас нельзя, а при рестарте прога ещё не загрузила DLL. Есть, конечно всевозможные методы инлайна, но мы воспользуемся более простым - замена опкода команды в файле. Как вы уже поняли, менять будем не опкод команды jmp на je, а "xor eax, eax" на "test eax,eax", стоящий выше перехода. Почему? Да потому что у test и xor всегда одинаковый опкод, независимо от из расположения по какому либо смещению, потому что они не работают со смещениями (не пользуются ими), а у je и jmp опкод высчитывается исходя из того, на каком месте стоит команда и куда она прыгает (для проверки сами попробуйте расположить эти команды по разным местам и увидите различия в опкоде).
Итак, меняем "test eax, eax" на "xor eax,eax" (85С0 меняем на 33С0). Я буду юзать HIEW32. Открываем файл в HIEW32, жмем F4, выбираем HEX и нажимаем F7 для поиска, теперь пишем опкоды команд (желательно брать побольше, чтобы нашлось только одно уникальное совпадение, в данном случае достаточно ввести опкоды test'a и следующего mov'a - 85 C0 89 47 14). Ок, теперь нажимаем F3, вводим 33 и нажимаем F9, а затем и F10 для выхода. "Теперь можно спокойно играть? ", - нет нет, есть ещё одна проверочка, хехе.

Часть 3 - Убираем проверку в EXE на вшивость DLL'ок xD


Теперь если мы попытаемся запустить ЕХЕ, то выдается ошибка "Check File (...AvoidCrackPlugin.dll)Error". Хехе, наблюдаем мат Garen'ы, которая обнаружила вторжение во владение DLL. Давайте исправлять... Попытаемся найти проверку в EXE на валидность DLL'ок. Грузим в Ольку наш ранее патченный EXE.

Существует несколько способов снятия защиты проверки DLL, я напишу тот, который попроще:
Можно предположить, что сначала происходит проверка, а потом, если DLL в норме, то она загружается. Ок, ставим hr бряк на функцию LoadLibraryW вышеописанным способом, и запускаем прогу.
Видим, что сразу происходит остановка, и если чуть придавить F9 кирпичом, то можно заметить, что все DLL, лежащие в папке plugins грузятся из одного места (смотрим на адрес возврата):

0012E710   004FC673  /CALL to LoadLibraryW from Garena1.004FC66D
0012E714   001F5178  FileName = "C:ProgramsGarenapluginsUI/ViwawaPlugin.dll"


Выходим по адресу возврата и оказываемся тут:

004FC66A   . /74 5D         JE SHORT Garena1.004FC6C9                ;  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
004FC66C   > |57            PUSH EDI                                 ; /FileName
004FC66D   . |FF15 F8125A00 CALL DWORD PTR DS:[<&KERNEL32.LoadLibrar>; LoadLibraryW


Выше есть переход, который я и попробовал первым делом: ставим бряк (хардварный, конечно) и смотрим, что же происходит: АГА, прыжка не происходит никогда, кроме... хехе, догадайтесь сами)
Инвертируем флаг Z и... УРА! Garena успешно стартовала!!!

Остается дело за малым: запоминаем адрес перехода, давим на Ctrl+F2, затем переходим по адресу и забиваем переход командами nop.
Чтож, теперь всё работает и таймер убран) Можно играть в доту и не пытаться войти в топовые комнаты по полчаса, теперь шанс значительно увеличен.


Заключение


Это моя первая статья по крэкингу, поэтому не судите строго) Вся критика, пожелания, исправления пожете кинуть на мыло (написано в заголовке) или в аську - 398442444. Спасибо за прочтение ;)



Обсуждение статьи: Снимаем таймер подключения в Garena Client (last version) >>>


Комментарии к статье: Снимаем таймер подключения в Garena Client (last version)

LoCo 17.05.2009 01:31:00
.
---
vxcoder 31.10.2009 19:40:19
хммм не плоха коокрас для моего брата =)
---
DirecTwiX 02.08.2010 13:51:21
Можно поподробней вот про это:
"ищем в памяти юникод-строку, она находится в секции .rsrc модуля Garena."?
Как зайти в секцию rsrc модуля? Если в ольке тыкнуть по кнопке Модули, то там будут только дллки и сам ЕХЕ...
---
Anti_Tip 01.11.2010 11:09:04
Хорошая статья. Можно добавить сюда, следующее, при попытке зайти в полную руму, выскакивает сообщение, что она переполнена. Убрать его и "шанс значительно увеличится" - как говорит автор. Спасибо за статью.

---
PE_Kill 06.11.2010 08:33:57
Я бы лучше сделал Loader и хукал GetTickCount, ну а там возвращал большое значение, если нас вызывают для проверки таймера. Просто клиент обновляется, могут скрытые проверки и прочее, поэтому лучше такие вещи ломать динамически и незаметно.
---

Материалы находятся на сайте https://exelab.ru



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS