..
                       ::
                ____ _ :: _ ____      _ ____    _ ____
            ____\  (________) _/________) _ |_____)   \  _____
           \\__    _______/  _|   /__     |     _      \/    /___
              /   |      _   |       _    |     \      |      __//
           … \\___|      \___|       \____|      \_____|       \ …
          +-------|______//--|_______//---|______//pO!i|_______//-----+
                       ..                      ____ _ ____ _
<<:::::::::::::::::::: ::   … tEAM-fT …   ____|   (___\  (_______
             ___ ___ ___ ___ ___ ___   ___\         _    _______/__
            \\__\\__\\__\\__\\__\\__\ \\___      ___/   |      ___//
                       ..             …  /      |__/\___|       \ …
                       ::         +-----\\______|-------|_______//--+
                       ::
                       :: TEAM FIFTY THREE TUTORiALS #12
                       ::

======================================
 SLV Code Protector 0.61 - распаковка
======================================


Это обычный тутор. У меня есть какой-то крякмис.exe, который запакован SLVc0deProtector 0.61. Протектор мне не известен, наверное какой-то проект "от балды". Я переименовал exe в target.exe и файл в при запуске показывает, что имя было изменено. Olly сообщает, что файл повреждён или вообще не 32-bit. Это значит, что заголовок PE похерили.




1. Проблемы с заголовком PE


Я открыл target.exe в LordPE "PE editor" и увидел вот такие странные/неправильные значения:

NumOfRvaandSizes = 48632ABD --> Я должно быть =10(h)

Другие вообще-то опционально, но я их тоже исправлю:

SizeOfImage   = 0000B001 ---> должно быть = 17000
BaseOfCode    = 0000000F ---> 00001000
BaseOfData    = 0000000F ---> 00005000
TimeDateStamp = DEADC0DE ---> 0 (не важно)
CheckSumm     = FFFFFFFF ---> 0 (не важно)

Секции так же похерили и я исправлю их VirtualSize с -> в (section alignment = 1000):

.text   = 2A2E -> 3000
.rdata  = 07E8 -> 1000
.data   = 0ADC -> 1000
.rsrc   = 01A8 -> 1000
::ICU:: = 4001 -> 4000


Заголовок PE, вообще-то DOS, выглядит странно в Olly:

00400000   4D 5A        ASCII "MZ"           ; DOS EXE Signature
00400002   9000         DW 0090              ;  DOS_PartPag = 90 (144.)
00400004   1A4E         DW 4E1A              ;  DOS_PageCnt = 4E1A (19994.)
00400006   4E21         DW 214E              ;  DOS_ReloCnt = 214E (8526.)
00400008   767D         DW 7D76              ;  DOS_HdrSize = 7D76 (32118.)
0040000A   70AF         DW AF70              ;  DOS_MinMem = AF70 (44912.)
0040000C   98FE         DW FE98              ;  DOS_MaxMem = FE98 (65176.)
0040000E   8E74         DW 748E              ;  DOS_ReloSS = 748E
00400010   09EE         DW EE09              ;  DOS_ExeSP = EE09
00400012   F0FB         DW FBF0              ;  DOS_ChkSum = FBF0
00400014   5320         DW 2053              ;  DOS_ExeIP = 2053
00400016   0224         DW 2402              ;  DOS_ReloCS = 2402
00400018   A6F4         DW F4A6              ;  DOS_TablOff = F4A6
0040001A   215D         DW 5D21              ;  DOS_Overlay = 5D21

Любой другой файл на моей машине имеет такие значения в DOS заголовке:

00400000   4D 5A        ASCII "MZ"           ; DOS EXE Signature
00400002   9000         DW 0090              ;  DOS_PartPag = 90 (144.)
00400004   0300         DW 0003              ;  DOS_PageCnt = 3
00400006   0000         DW 0000              ;  DOS_ReloCnt = 0
00400008   0400         DW 0004              ;  DOS_HdrSize = 4
0040000A   0000         DW 0000              ;  DOS_MinMem = 0
0040000C   FFFF         DW FFFF              ;  DOS_MaxMem = FFFF (65535.)
0040000E   0000         DW 0000              ;  DOS_ReloSS = 0
00400010   B800         DW 00B8              ;  DOS_ExeSP = B8
00400012   0000         DW 0000              ;  DOS_ChkSum = 0
00400014   0000         DW 0000              ;  DOS_ExeIP = 0
00400016   0000         DW 0000              ;  DOS_ReloCS = 0
00400018   4000         DW 0040              ;  DOS_TablOff = 40
0040001A   0000         DW 0000              ;  DOS_Overlay = 0

Я не знаю влияет ли это на нашу цель, так что я оставлю это. Я заметил еще кое-что тут:

004000F4   0F000000     DD 0000000F          ;  SizeOfCode = F (15.)

Это странно потому что я выставил SizeOfCode в LordPE равным 3000 и я не знаю, почему здесь F, а LordPE показывает 3000. Я это так же оставлю. Позже я могу это изменить, если будет нужно. Теперь файл запускается прекрасно в Оlly и выскакивает то самое сообщение об имени.






2. Первая проверки дебагера

Чтобы попасть на проверку имени мне нужно пройти немного обфускации и декриптовки, но я могу немного ускорить этот процесс, потому что там нет ничего интересного. Убираем галки на всех исключениях и жмём Shift+F9 3 раза и в итоге попадём на то самое сообщение. Теперь я жму Shift+F9 два раза и приземляюсь тут:

0040776B  DIV EDX
0040776D  RDTSC <---------------------- получаем какое-то временнОе значение,
0040776F  MOV ECX,EAX <---------------- записываем в ECX,
00407771  RDTSC <---------------------- снова получаем время,
00407774  SUB EAX,ECX <---------------- отнимаем,
00407776  JMP SHORT target.0040777B 
00407778  JMP SHORT target.0040777D
0040777A  FUCOMIP ST,ST(3)
0040777C  STI
0040777D  CMP EAX,100000 <------------- проверяем разницу,
00407782  PREFIX REP:
00407783  JA 787686FF <---------------- если больше 100000, прыгаем к "плохому мальчику".
00407789  LEA EAX,DWORD PTR SS:[EBP+40231C] <-- А вот это интересно! Это еще какая-то проверка,
0040778F  CMP BYTE PTR DS:[EAX],1 <------------ потому что если EAX!=1, то мы прыгнем
00407792  JNZ target.0040795E <---------------- к сообщению, что задетекчен дебаггер.
00407798  JMP target.004078E7 <---------------- Если поставить брейкпоинт сюда, то я всё это обойду!
0040779D  ADD BYTE PTR DS:[EAX],AL
0040779F  ADD BYTE PTR DS:[EAX],AL
004077A1  ADD BYTE PTR DS:[EAX],AL

Тут есть две проверки; стандартная RDTSC-проверка с проверкой прошедшего времени в случае, что трейсился через код и вторая проверка, которая мне не известна. Чтобы всё это обойти мне нужно поставить "bp" на последний джамп и запустить прогу. Затем продолжаем трейситься.





3. Проверка имени

После прыжка я приземлился на проверке времени. Сперва GetModuleFilenameA возвращает имя нашей цели (target.exe) затем выполняется сравнение тут:

00407912  REPE CMPS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]

Проверим окно регистров, посмотрим EDI и ESI:

ESI 004077DA ASCII "target.exe"
EDI 00408378 ASCII "Copie de Original.exe"

Как вы видите, "target" сравнивается с "Copie de Original" (.exe, само расширение, не сравнивается), т.е. с оригинальным названием крякмиса. Потрейситесь и вы найдёте хороший джамп, который должен быть выполнен (если нет, то выскакивает MessageBoxTimeoutA и крякми закрывается):

0040791E  JE SHORT target.0040794D

Но этот джамп прыгает на вторую проверку, которая сперва меня смутила:

0040794D  CMP BYTE PTR DS:[EDI],2E
00407950  JE SHORT target.0040795E <--- Хороший Джамп!

После того, как имя сравнено эта проверка посмотрит есть ли в конце файла символ ".". Это просто трюк, в случае, если мы изменили только первый джамп. Так что я изменил имя файла на "Copie de Original.exe" и запустил. Получил другое сообщение: "PE header has been modified!...".





4. И еще анти-дебаг

Заголовку PE придётс я подождать, потому что существуют еще анти-дебаг трюки:

IsDebuggerPresent  - детектим дебаггер, используйте плагин, чтобы спрятать Оlly.
FindWindowA        - ищем известные крэк-тулзы, поставьте hw bp на api.
OutputDebugStringA - убираем Олльку, пропачьте этот  api.

Чтобы избавиться от OutputDebugStringA просто поместите последний опкод api в kernel в начало(For OutputDebugStringA just place last opcode of api in kernel to beggining. - слегка не понял, что хотел автор - прим. NCat). У меня это RETN 4. Затем жмём F9 и останавливаемся на FindWindowA... много раз, но вот это интересно:

0012FF9C   00144FA1  /CALL to FindWindowA from 00144F9B
0012FFA0   00143E47  |Class = "OllyDbg"
0012FFA4   00000000  \Title = NULL

После выхода из api, просто установите EAX=0, чтобы убить проверку. Остальные тулзы, которые проверяются:

0012FF9C   0014524F  /CALL to FindWindowA from 00145249
0012FFA0   00000000  |Class = 0
0012FFA4   00143E8F  \Title = "Import REConstructor v1.6 FINAL (C) 2001-2003 MackT/uCF"

0012FF9C   001452B2  /CALL to FindWindowA from 001452AC
0012FFA0   00000000  |Class = 0
0012FFA4   00143EC7  \Title = "Resource Hacker"

0012FF9C   00145315  /CALL to FindWindowA from 0014530F
0012FFA0   00000000  |Class = 0
0012FFA4   00143ED7  \Title = "[ LordPE Deluxe ] by yoda"

0012FF9C   00145378  /CALL to FindWindowA from 00145372
0012FFA0   00000000  |Class = 0
0012FFA4   00143EF1  \Title = "PEiD v0.93"

0012FF9C   001453DB  /CALL to FindWindowA from 001453D5
0012FFA0   00000000  |Class = 0
0012FFA4   00143EFC  \Title = "PE Tools v1.5 Xmas Edition - by NEOx/[uinC], http://www.uinc.ru/"

0012FF9C   0014543E  /CALL to FindWindowA from 00145438
0012FFA0   00000000  |Class = 0
0012FFA4   00143F3D  \Title = "BDASM"

0012FF9C   001454A1  /CALL to FindWindowA from 0014549B
0012FFA0   00000000  |Class = 0
0012FFA4   00143F43  \Title = "Process Hunter v1.0"

0012FF9C   00145504  /CALL to FindWindowA from 001454FE
0012FFA0   00000000  |Class = 0
0012FFA4   00143F57  \Title = "[ PEditor 1.7 ]  by yoda & M.o.D."

0012FF9C   00145567  /CALL to FindWindowA from 00145561
0012FFA0   00000000  |Class = 0
0012FFA4   00143F79  \Title = "PROTECTiON iD v5.0 FiNAL - the ultimate Protection Scanner - 100% ASM !"

0012FF9C   001455CA  /CALL to FindWindowA from 001455C4
0012FFA0   00000000  |Class = 0
0012FFA4   00143FC1  \Title = "Import REConstructor v1.4.3 BETA5 (C) 2001-2002 MackT/uCF"




5. Проверка заголовка PE

Возвращаемся в код и трейсимся дальше. Я нашёл где проверяется значение NumberOfRvaAndSizes в заголовке:

001437EA   FF95 E52C4000    CALL DWORD PTR SS:[EBP+402CE5]           ; kernel32.VirtualProtect
001437F0   B8 BD2A6348      MOV EAX,48632ABD
001437F5   8B57 74          MOV EDX,DWORD PTR DS:[EDI+74]
001437F8   3BC2             CMP EAX,EDX <----------------------------- Проверка!!!
001437FA   74 7F            JE SHORT 0014387B <----------------------- Хороший Джамп!!!
001437FC   6A 00            PUSH 0
001437FE   8B85 B52C4000    MOV EAX,DWORD PTR SS:[EBP+402CB5]        ; kernel32.FatalExit
00143804   50               PUSH EAX
00143805   8D85 EE204000    LEA EAX,DWORD PTR SS:[EBP+4020EE]
0014380B   8D95 99204000    LEA EDX,DWORD PTR SS:[EBP+402099]
00143811   6A FF            PUSH -1
00143813   6A 00            PUSH 0
00143815   6A 30            PUSH 30
00143817   50               PUSH EAX
00143818   52               PUSH EDX
00143819   6A 00            PUSH 0
0014381B   FF95 CB2C4000    CALL DWORD PTR SS:[EBP+402CCB]           ; USER32.MessageBoxTimeoutA
00143821   C3               RETN




6. Снова проверка дебагера и прыжок на OEP

Теперь снова используется FindWindowA-проверка и проверяются кое-какие файлы (softice и т.д.) с использованием CreateFileA. После прохождения этих проверок будет пара декриптовочных циклов, которые расшифровывают секции и после всего этого будет один JMP EAX, который и есть наш прыжок к OEP:

00143A4E  -FFE0             JMP EAX                                  ; Copie_de.004011B0
00143A50   2851 03          SUB BYTE PTR DS:[ECX+3],DL
00143A53   6D               INS DWORD PTR ES:[EDI],DX                ; I/O command
00143A54   51               PUSH ECX
00143A55   B6 CA            MOV DH,0CA
00143A57   33BA 49A02535    XOR EDI,DWORD PTR DS:[EDX+3525A049]
00143A5D   8399 9112B461 C3 SBB DWORD PTR DS:[ECX+61B41291],-3D
00143A64  -FFE0             JMP EAX                                  ; Copie_de.004011B0
00143A66   C3               RETN


Вот и всё. Всё, что осталось: сдампить файл и использовать ImpREC, чтобы пофиксить импорт.


Автор  : [haggar]
Перевод: nightcat