![]() |
Unpacking PESpin
Unpacking PESpin 1.3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Author: taha Level: для продвинутых новичков Date: 25.o4.2oo7 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Довольно приличный протектор. На мой взгляд один из самых интересных. Tutorial’ов на русском не встечал, а те что были на английском даже читать не стал. Что можно почерпнуть для себя из статьи состоящей из фраз “листните на пару экранов вверх”, “патичть здесь”? Для меня в первую очередь важна логика действий,а не “scroll waaaay up”. Жертву нашёл тут Content - Tools - Anti-deb - Finding OEP * The ESP trick * Stolen bytes - Fixing IAT * Length disassembler * Scripting - Dump & Rebuild Import - links - PS Tools - Shadow (модификация OllyDbg) * plugin AnalyzeThis * plugin ODBGScript * plugin OllyDump * plugin OllyPad * plugin CommandLine - OllyScript Editor (необязательно) - ImpRec Anti-deb Первое, что необходимо сделать проверить содержит ли жертва антиотладочные приёмы. Для этого необходимо просто запустить файл в Olly. Не забудьте отключить остановку на исключениях! Запускаем (F9). Где то всеже останавливаемся, но это не важно, идём дальше Shift-F9, файл запустился. Хм.. Меня, если често, это смутило. Потому что редкий протектор не использует хотябы IsDebuggerPresent. Ну раз нет так нет... Finding OEP Начнём с EP. Точка входа выглядит вот так Код:
004170D4 > /EB 01 JMP SHORT UnPackMe.004170D7Код:
004170D4 > $ /EB 01 JMP SHORT UnPackMe.004170D7Сразу же в глаза бросается команда pushad. И естественно сразу вспоминаем “The ESP trick”. The ESP trick Суть в том, что протектор не должен наследить, тоесть ему необходимо вернуть значения регистров и выравнить стек. Здесь мне нравится следущее сравнение: “Вы работаете с некоторым текстовым документом, Вы выделяете и копируете первый параграф. Переписываете его, немного меняете как вдруг приходите к заключению, что старый был лучше. Вы вновь выделяете первый параграф и жмёте “paste”.” Естественно pushad – будет играть роль “copy”, а popad – “paste”. В CommandLine пишем команду “hr esp-4”, он поместит hardware breakpoint на кадр стека, в котором будет лежать первый сохранившийся регистр (это будет eax). Проходим pushad по F8 и запускаем программу (F9). Опять возникает исключение, но мы смело жмём Shift-F9. В результате чего окажемся здесь: Код:
00418AF5 . 61 POPADStolen bytes Однако здесь стоит останоиться. Типичная точка входа.. Кроме переходов и мусорных байтов естественно. 00418B43 PUSH EBP 00418B44 JMP SHORT UnPackMe.00418B47 00418B46 DB 34 00418B47 MOV EBP,ESP 00418B49 JMP SHORT UnPackMe.00418B4C 00418B4B DB 0C 00418B4C PUSH UnPackMe.00418B56 00418B51 JMP UnPackMe.0040A485 Скорее всего – это украденые байты. Для полной уверенности я прошёлся по jump’ам до первого call’а. Fixing IAT Как Вы наверно уже заметили, протектор ворует байты не только у точки входа, но и у API. Нужно его отучить это делать. Для этого нам понадобиться вызов какой-нибудь функции. Возьмём к примеру следущую Код:
00418B62 . FF15 F4114000 CALL NEAR DWORD PTR DS:[4011F4]008900E9 JMP SHORT 008900EC … 008900EC MOV EDI,EDI 008900EE PUSH EBP 008900EF MOV EBP,ESP 008900F1 CMP DWORD PTR SS:[EBP+8],0 008900F5 JMP SHORT 008900FE … 008900FE JMP SHORT 008900F8 … 008900F8 JMP kernel32.7C80B6AA … 7C80B6AA JE SHORT kernel32.7C80B6C4 7C80B6AC PUSH DWORD PTR SS:[EBP+8] 7C80B6AF CALL kernel32.7C80E074 7C80B6B4 TEST EAX,EAX 7C80B6B6 JE SHORT kernel32.7C80B6C0 7C80B6B8 PUSH DWORD PTR DS:[EAX+4] 7C80B6BB CALL kernel32.GetModuleHandleW 7C80B6C0 POP EBP 7C80B6C1 RETN 4 7C80B6C4 MOV EAX,DWORD PTR FS:[18] 7C80B6CA MOV EAX,DWORD PTR DS:[EAX+30] 7C80B6CD MOV EAX,DWORD PTR DS:[EAX+8] 7C80B6D0 JMP SHORT kernel32.7C80B6C0 Это вызов GetModuleHandleA! Только вот первые 9 байт перенесены по адресу 008900EC. Итак, запоминаем адеса 4011F4,8900E9, 7C80B6A1(GetModuleHandleA). Поставим hardware breakpoint на GetModuleHandleA. В результате мы будем знать когда и зачем PESpin обращается к GetModuleHandleA. Запускаем программу (F9). И останавливаемся вот здесь: Код:
004194B4 3808 CMP BYTE PTR DS:[EAX],CLECX FFFF2BCC Этот кусок кода проверяет первый байт API на присутсвие breakpoint’а, установленного помещением int3. Вот зачем нужно использовать hardware breakpoint’ы. Идём дальше... Код:
00417BE7 8B18 MOV EBX,DWORD PTR DS:[EAX]Мы окажемся где то здесь Код:
004181B9 . C0EC 04 SHR AH,40012FF64 004186BB UnPackMe.004186BB 0012FF68 7C80B6A1 kernel32.GetModuleHandleA 0012FF6C 00417C5A RETURN to UnPackMe.00417C5A from UnPackMe.004180F3 0012FF70 7C80B6A1 kernel32.GetModuleHandleA 0012FF74 004010E7 UnPackMe.004010E7 Функция получает на вход адрес API! Уже интересно! Посмотрим начало функции... Length disassembler Код:
004180F3 $ 60 PUSHADВообще если протектор ворует байты, то в него 100% должен быть встроен дизассемблер длин. Его задача найти длину комманды. Потому что длина команд нефиксированна, а протектеру нужно знать сколько байт копировать. Если скопировать меньше то программа упадёт, что крайне нежелательно. Ну вот с этой функцией разобрались, пройдём её по F8. Код:
00417C54 > \50 PUSH EAXКод:
00417CA3 > \F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]Код:
00417F77 . 8902 MOV DWORD PTR DS:[EDX],EAXКод:
00417C54 > \50 PUSH EAXКод:
00417F77 . 8902 MOV DWORD PTR DS:[EDX],EAXScripting Собственно всё как я сказал: ставим breakpoint на 00417c54, чтобы получить адрес API, убираем бряк, чтобы не тормазиться при работе дизассемблера длин, ставим breakpoint на 00417F77, чтобы поместить в eax настоящий адрес. Сравнение с 7C834D41 сделано для того чтоб не пропустить конец таблицы и выгрузить скрипт. 7C834D41 – это последняя используемая функция. Код:
var funcНу вот... Код:
00418B43 > \55 PUSH EBPDump & Rebuild Import Снимаем дамп с помощью плагина OllyDump (галочку с Rebuild Import убрать). Чтож, теперь ImpRec’ом восстановим импорт. Выбираем процесс.. Код:
Target: D:\Cracking\lab\PESpin\UnPackMe_PeSpin1.3.f.exeLinks www.tuts4you.com www.reversing.be arteam.accessroot.com PS С Вами был taha. О ошибках и неточностях писать в ПМ. |
| Время: 15:33 |