PDA

Просмотр полной версии : [Руководство] Снимаем 5тисекундный таймер сами.


localhost_
10.03.2010, 17:26
Инструменты
OllyDbg
HIEW32

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

Доброго всем времени суток! Наша жертва - Garena Client ([Ссылки могут видеть только зарегистрированные и активированные пользователи]) - это клиент игровой сетевой платформы, позволяющая играть в различные игры по интернету без лагов. Вообще вещь достаточно популярная, поэтому она и вызвала у меня особый интерес для реверса. Чтобы поиграть, нужно сначала зайти в комнату, но первые комнаты вечно забиты и прорваться туда очень сложно (но нужно, ибо именно там лучшие соперники). После попытки зайти в комнату и сообщении о том, что данная рума переполнена, нам нельзя пытаться зайти в неё снова ещё 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 *****ed 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


Итак, вся соль в Avoid*****Plugin.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 (...Avoid*****Plugin.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.
Чтож, теперь всё работает и таймер убран) Можно играть в доту и не пытаться войти в топовые комнаты по полчаса, теперь шанс значительно увеличен.

Взято с *****lab.ru, Автор: [PNZ]human <[Ссылки могут видеть только зарегистрированные и активированные пользователи]>

От себя добавлю: если вы хотите заниматься реверсингом, но не знаете с чего начать - этот минигайд для Вас.

DeHuCoK
10.03.2010, 17:30
а не легче голд акк сделать

KilanKill
10.03.2010, 21:52
Лучше 5 сек Подождать чем так парится..
Кстати Голд Акки Оч Быстро Можно Взламывать))

AdrenalinMan
12.03.2010, 17:33
поставь гарена мастер...и живи спокойно))