ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > ИНФО > Статьи > Авторские статьи
   
 
 
Опции темы Поиск в этой теме Опции просмотра

Unpacking PESpin
  #1  
Старый 26.04.2007, 00:29
Аватар для taha
taha
Постоянный
Регистрация: 20.08.2006
Сообщений: 327
Провел на форуме:
2472378

Репутация: 1077
По умолчанию 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
004170D6   |68 60E80000     PUSH 0E860
004170DB    0000            ADD BYTE PTR DS:[EAX],AL
004170DD    8B1C24          MOV EBX,DWORD PTR SS:[ESP]
Сразу виден древний фокус “прыжок в середину команды”. Суть в том, что когда дизассемблер Olly проанализирует JMP SHORT UnPackMe.004170D7, то естественно примется за следущий байт - следущую комманду, а следущий байт 68h - оппкод команды push xxx. Врезультате чего, дизасемблерный листинг будет неверным. Этого бы не произошло, еслиб команды эмулировались (как в IDA) и байт 68h был бы проанализирован как db 68h. Тут на помощь Olly придёт плагин AnalyzeThis.

Код:
004170D4 > $ /EB 01         JMP SHORT UnPackMe.004170D7
004170D6     |68            DB 68                                                  ;  CHAR 'h'
004170D7   > \60            PUSHAD
004170D8   .  E8 00000000   CALL UnPackMe.004170DD
004170DD   $  8B1C24        MOV EBX,DWORD PTR SS:[ESP]
Вот так... Вдальнейшем этот плагин будет нераз выручать нас от такого рода приёмов.
Сразу же в глаза бросается команда 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            POPAD
00418AF6   .  87D2          XCHG EDX,EDX                                           ;  ntdll.KiFastSystemCallRet
00418AF8   .  4A            DEC EDX
00418AF9   .  C7C1 67639244 MOV ECX,44926367
00418AFF   .  85C1          TEST ECX,EAX
Сразу видно, что после popad идёт ненужный мусор, так что смело шагаем по F8.

Stolen 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],CL
004194B6    75 03           JNZ SHORT UnPackMe.004194BB
EAX 7C80B6A1 kernel32.GetModuleHandleA
ECX FFFF2BCC

Этот кусок кода проверяет первый байт API на присутсвие breakpoint’а, установленного помещением int3. Вот зачем нужно использовать hardware breakpoint’ы. Идём дальше...

Код:
00417BE7    8B18            MOV EBX,DWORD PTR DS:[EAX]
...
00417BF5    80FB EB         CMP BL,0EB
Протектор проверяет наличие переходов вначале API. Кстати если в начало поставить jmp 401000, то байты украдены не будут. Идём дальше...

Мы окажемся где то здесь

Код:
004181B9   .  C0EC 04       SHR AH,4
004181BC   .  2AC4          SUB AL,AH
004181BE   .^ 73 F6         JNB SHORT UnPackMe.004181B6
004181C0   .  8A47 FF       MOV AL,BYTE PTR DS:[EDI-1]
004181C3   .  24 0F         AND AL,0F
004181C5   .  3C 0C         CMP AL,0C
004181C7   .  75 03         JNZ SHORT UnPackMe.004181CC
004181C9   .  5A            POP EDX
004181CA   .  F7D2          NOT EDX
004181CC   >  42            INC EDX
004181CD   .  3C 00         CMP AL,0
004181CF   .  74 42         JE SHORT UnPackMe.00418213
004181D1   .  3C 01         CMP AL,1
004181D3   .^ 74 DB         JE SHORT UnPackMe.004181B0
004181D5   .  83C7 51       ADD EDI,51
004181D8   .  3C 0A         CMP AL,0A
Мы явно в какойто функции... Нужно обследовать её снчала. А что бы узнать где начало нужно проанализировать стек.

0012FF64 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
004180F4   .  FC            CLD
004180F5   .  33D2          XOR EDX,EDX
004180F7   .  8B7424 24     MOV ESI,DWORD PTR SS:[ESP+24]
004180FB   .  8BEC          MOV EBP,ESP
004180FD   .  68 1CF79710   PUSH 1097F71C
00418102   .  68 80671CF7   PUSH F71C6780
00418107   .  68 18973817   PUSH 17389718
0041810C   .  68 18B71C10   PUSH 101CB718
Как только я это увидел, у меня сразу же возникло чувство, что где-то я это уже встречал. Точнее я знал где. Что то подобное было в сорце VirXasm32 (это дизассемблер длин такой). Смотрите таблица заносится в стек, затем идут проверки на наличие префикса, затем разбор, поиск в таблице. В итоге функция вернет длину опкода.
Вообще если протектор ворует байты, то в него 100% должен быть встроен дизассемблер длин. Его задача найти длину комманды. Потому что длина команд нефиксированна, а протектеру нужно знать сколько байт копировать. Если скопировать меньше то программа упадёт, что крайне нежелательно. Ну вот с этой функцией разобрались, пройдём её по F8.

Код:
00417C54   > \50            PUSH EAX
00417C55   .  E8 99040000   CALL UnPackMe.004180F3
00417C5A   .  83C4 04       ADD ESP,4
00417C5D   .  91            XCHG EAX,ECX
Заметьте в eax лежит размер “mov edi,edi” – два байта. Идём дальше...

Код:
00417CA3   > \F3:A4         REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
00417CA5   .  8BC6          MOV EAX,ESI
00417CA7   .  8BF7          MOV ESI,EDI
Вот копируется первый оппкод в 008900EС. Дальше покругу, длина команды <–> копипаст. Следовательно где-то впереди должен заноситься адрес 008900E9 в 4011F4. Поставим breakpoint на доступ к 4011F4. И вот оно:

Код:
00417F77   .  8902          MOV DWORD PTR DS:[EDX],EAX
Но вот встаёт проблема! Между

Код:
00417C54   > \50            PUSH EAX
и
Код:
00417F77   .  8902          MOV DWORD PTR DS:[EDX],EAX
протектор так активно работает со стеком и нарезает такие круги, что патчить будет себе дороже. Но ведь можно написать скрипт! Мы знаем где взять настоящий адрес и куда кладётся левый.

Scripting
Собственно всё как я сказал: ставим breakpoint на 00417c54, чтобы получить адрес API, убираем бряк, чтобы не тормазиться при работе дизассемблера длин, ставим breakpoint на 00417F77, чтобы поместить в eax настоящий адрес. Сравнение с 7C834D41 сделано для того чтоб не пропустить конец таблицы и выгрузить скрипт. 7C834D41 – это последняя используемая функция.

Код:
       var func
       var IAT
       var addr

       mov func,00417c54
       mov IAT,00417F77

       bphws func,"x"

next:
       run
       mov addr,eax
       bphwc func
       bphws IAT,"x"
       run
       mov eax,addr
       bphwc IAT
       bphws func,"x"
       cmp eax,7C834D41
       jne next
       bphwc func
       ret
Не забудьте удалить все ненужные breakpoint’ы. Оставить нужно только один – на oep. Запускаем скрипт, тормазимся на oep.

Ну вот...

Код:
00418B43   > \55            PUSH EBP
00418B44   .  EB 01         JMP SHORT UnPackMe.00418B47
00418B46      34            DB 34                                                  ;  CHAR '4'
00418B47   >  89E5          MOV EBP,ESP
00418B49   .  EB 01         JMP SHORT UnPackMe.00418B4C
00418B4B      0C            DB 0C
00418B4C   >  68 568B4100   PUSH UnPackMe.00418B56
00418B51   .- E9 2F19FFFF   JMP UnPackMe.0040A485
00418B56   .  68 220340D1   PUSH D1400322                                          ; /pModule = D1400322 ???
00418B5B   .  810424 DEFCBF>ADD DWORD PTR SS:[ESP],2EBFFCDE                        ; |
00418B62   .  FF15 F4114000 CALL NEAR DWORD PTR DS:[4011F4]                        ; \GetModuleHandleA
00418B68   .  EB 01         JMP SHORT UnPackMe.00418B6B
У меня всё определилось. =)

Dump & Rebuild Import
Снимаем дамп с помощью плагина OllyDump (галочку с Rebuild Import убрать).
Чтож, теперь ImpRec’ом восстановим импорт. Выбираем процесс..

Код:
Target: D:\Cracking\lab\PESpin\UnPackMe_PeSpin1.3.f.exe
OEP: 00018B43	IATRVA: 0000119C	IATSize: 00000034

FThunk: 0000119C	NbFunc: 00000007
1	0000119C	user32.dll	001B	CallNextHookEx
1	000011A0	user32.dll	010F	GetDesktopWindow
1	000011A4	user32.dll	0175	GetWindowRect
1	000011A8	user32.dll	01DD	MessageBoxA
1	000011AC	user32.dll	028B	SetWindowsHookExA
1	000011B0	user32.dll	029A	SystemParametersInfoA
1	000011B4	user32.dll	02AF	UnhookWindowsHookEx

FThunk: 000011EC	NbFunc: 0000000B
1	000011EC	kernel32.dll	00B7	ExitProcess
1	000011F0	kernel32.dll	013F	GetCurrentThreadId
1	000011F4	kernel32.dll	0176	GetModuleHandleA
1	000011F8	kernel32.dll	01EB	GlobalAlloc
1	000011FC	kernel32.dll	01F2	GlobalFree
1	00001200	kernel32.dll	0203	HeapAlloc
1	00001204	kernel32.dll	0204	HeapCompact
1	00001208	kernel32.dll	0205	HeapCreate
1	0000120C	kernel32.dll	0207	HeapDestroy
1	00001210	kernel32.dll	0209	HeapFree
1	00001214	kernel32.dll	03A4	lstrcat
Теперь Fix Dump. Готово! У меня работает!

Links
www.tuts4you.com
www.reversing.be
arteam.accessroot.com

PS
С Вами был taha. О ошибках и неточностях писать в ПМ.
 
Ответить с цитированием
 



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Распаковка PESpin 0.7 taha Авторские статьи 1 11.12.2006 01:10



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


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




ANTICHAT.XYZ