Contribute  :  Web Resources  :  Past Polls  :  Site Statistics  :  Downloads  :  Forum  
    BiW ReversingThe challenge is yours    
 Welcome to BiW Reversing
 Wednesday, June 28 2017 @ 09:12 PM CEST

ExeCryptor 2.3.9 - Unpacking

   

TutorialsLevel : intermediate

This is very short tutorial that brings just some small update for previous ones. Target is ExeCryptor 2.3.9 itself which can be found on official protector site. Tutorial shows unpacking and not cracking target. You will need OllyDbg (some script plugin, and some hide plugin), LordPE, ImpREC and Windows XP.





- Loading in Olly and preparing for debugging -

First open Olly and in "Debugging options", under "events" set "Make first pause at: System breakpoint". That will prevent auto start that is coused by TLS callback. Now load target in Olly.

Open breakpoint window and delete breakpoint that Olly has placed on OEP:
0076E427 EXECrypt One-shot CALL EXECrypt.0076E323

Use some plugin to hide Olly from (or check previous tutorials to learn manually way):
IsDebuggerPresent/BeingDebugged
NtGlobalFlag
HeapFlag
CheckRemoteDebuggerPresent

Do not check anything else in your plugin because EC (ExeCryptor) might detect it. EC detects hooks on APIs.

Go to OutputDebugStringA API and place RETN 4 opcode at it's start. This is to prevent "s%s%" exploit.




- Hardware exception trick -

This is new trick. It seams that EC sets temporary hardware breakpoint somehow. I do not know yet how this is performed, but within Olly this will couse file crushing/detection.

Under exceptions options in Olly, CHECK ALL boxes. But delete all custom exceptions! Be sure that you didn't place any memory, software or hardware breakpoint. Now hit Shift+F9 to run target under Olly. You will stop on first exception:

007637D0 F0:F1 LOCK INT1

Hit Shift+F9 three more times and then check hardware breakpoints (Debug menu -> Hardware breakpoints). You will see that one hardware breakpoint is placed:

Hardware breakpoints
# Base Size Stop on
1 0076098F Temporary

This is new trick in EC. If you continue to running with this hwbp, target will crush eventualy. Therefor, delete it at this point. Also, go to exception options and add last exception (C000001E INVALID LOCK SEQUENCE) to custom ones.




- FindWindowA check -

Hardware breakpoint rick is defeated. Next we have IsDebuggerPresent check which is defeated by our plugin. Then FindWindowA check which searches for window with "OLLYDBG" class. Place memory breakpoint on first opcode in FindWindowA API and run. You will stop on breakpoint check on API that is performed as small calculus to not be so obvious (junk removed from snippet):

0055A3DB 8A00 MOV AL,BYTE PTR DS:[EAX]
00595A6F 2C 99 SUB AL,99
00595A71 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4]
00595A74 F62A IMUL BYTE PTR DS:[EDX]
005DEE5C 3C A4 CMP AL,0A4
005DEE5E ^0F85 2BFFF7FF JNZ EXECrypt.0055ED8F
005DEE64 E9 598A0000 JMP EXECrypt.005E78C2

Then some EC checks for type of first opcode for some reason:

005F8C87 0FB600 MOVZX EAX,BYTE PTR DS:[EAX]
005F8C8A 833C85 00004E00 >CMP DWORD PTR DS:[EAX*4+4E0000],0
005F8C92 ^0F84 D4A2F1FF JE EXECrypt.00512F6C
005F8C98 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; user32.FindWindowA
005F8C9B 8038 CF CMP BYTE PTR DS:[EAX],0CF
005F8C9E ^0F84 C1A2F1FF JE EXECrypt.00512F65
005F8CA4 ^E9 8571FFFF JMP EXECrypt.005EFE2E

Then it checks API for possible hooks or redirections:

005EFE2E 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; user32.FindWindowA
005EFE31 8038 E9 CMP BYTE PTR DS:[EAX],0E9 ; Is JMP?
005EFE34 ^0F84 2B31F2FF JE EXECrypt.00512F65
005EFE3A 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; user32.FindWindowA
005EFE3D 8038 EB CMP BYTE PTR DS:[EAX],0EB ; Is JMP SHORT?
005EFE40 ^0F84 1F31F2FF JE EXECrypt.00512F65
005EFE46 E9 38770100 JMP EXECrypt.00607583

Checks is API patched with RETN xxxx:

004EB930 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; user32.FindWindowA
004EB933 8A00 MOV AL,BYTE PTR DS:[EAX]
004EB935 24 F6 AND AL,0F6
004EB937 3C C2 CMP AL,0C2
0060CCB1 ^0F84 AE62F0FF JE EXECrypt.00512F65

Checks is first opcode JMP DWORD [EAX] which is again redirection:

0060CCBA 66:8B00 MOV AX,WORD PTR DS:[EAX]
0060CCBD 66:25 FF38 AND AX,38FF
005F0C95 66:3D FF20 CMP AX,20FF
005F0C99 ^0F84 C622F2FF JE EXECrypt.00512F65

Checks for CALL XXXXXXXX type redirection:

00546361 8038 E8 CMP BYTE PTR DS:[EAX],0E8
00546364 0F85 DBED0300 JNZ EXECrypt.00585145
0054636A ^E9 5DF7FCFF JMP EXECrypt.00515ACC

Some more examning is performed and then it jumps to FindWindowA that finds "OLLYDBG" class in memory. Just set EAX=0 when retrning from this API and this check is killed.




- ReadProcessMemory check -

EC examnes all processes in order to find Olly running. It uses GetWindowThreadProcessId to retrieve PID of processes, then it opens each proces. It uses ReadProcessMemory to examne them. We cannot place bp on ReadProcessMemory since it will be detected, we could use memory breakpoints but that would be too slow. Since ReadProcessMemory uses ZwReadVirtualMemory, we can place bp on this one that is not checked. Then we can run. When we break at that API, return to kernel and then to EC code trace little untill you see that some bytes are checked (if you cannot find that check, hit F9 to break on new memory reading):

005ABBE2 81BD 38FEFFFF 45>CMP DWORD PTR SS:[EBP-1C8],2B584245
005ABBEC ^0F85 8A8BFAFF JNZ EXECrypt.0055477C
005ABBF2 ^E9 6371F6FF JMP EXECrypt.00512D5A

Follow in dump that opcode:

005ABBE2 81 BD 38 FE FF FF 45 42 58 2B ..8...EBX+

It checks for one string in Olly , "EBX+". Change 2B584245 bytes to something as 12345678 so it will fail to detect Olly. EC doesn't check this code for bp's or with checksums.

You will find similar checks if you search all EC sections. Search for CMP DWORD[EAX],CONST and you'll get results:

Found commands
Address Disassembly Comment
00514CDB CMP DWORD PTR DS:[EAX],47424454 ; TDBG
0053A13B CMP DWORD PTR DS:[EAX],47424454
0055DF80 CMP DWORD PTR DS:[EAX],4742444F ; ODBG
0057FD31 CMP DWORD PTR DS:[EAX],47424454
00599B86 CMP DWORD PTR DS:[EAX],4742444F
005A6EC7 CMP DWORD PTR DS:[EAX],4742444F
005AF1DF CMP DWORD PTR DS:[EAX],4742444F
005BA618 CMP DWORD PTR DS:[EAX],47424454
005C88BD CMP DWORD PTR DS:[EAX],47424454
005C96FF CMP DWORD PTR DS:[EAX],4742444F
005D77C5 CMP DWORD PTR DS:[EAX],4742444F
005E0B5A CMP DWORD PTR DS:[EAX],4742444F
005EC439 CMP DWORD PTR DS:[EAX],4742444F
005EEDDE CMP DWORD PTR DS:[EAX],47424454
005F6512 CMP DWORD PTR DS:[EAX],47424454
006004FA CMP DWORD PTR DS:[EAX],47424454


There are more similar checks for sysinternals tools:

Found commands
Address Disassembly Comment
00525A2A CMP DWORD PTR SS:[EBP-10C],656C6946 ;File
0056A41F CMP DWORD PTR SS:[EBP-10C],6D676552 ;Regm
00593828 CMP DWORD PTR SS:[EBP-10C],6D676552
005BE5A2 CMP DWORD PTR SS:[EBP-10C],76676264 ;dbgv
005DF3F9 CMP DWORD PTR SS:[EBP-10C],36343831 ;1846
005E95A7 CMP DWORD PTR SS:[EBP-10C],36343831
0060BCE9 CMP DWORD PTR SS:[EBP-10C],76676264




- Threads -

Threads are used to perform continious protection. Just NOP whole CreateThread API (except last RETN xxxx).





- OEP -

This is Delphi program and OEP should be at the end of code section. But OEP is scrambled and on OEP there will be jump to moved OEP. Use memory breakpoints to land in code section as described in previous tutorials. OEP should be here:

004D2AB8 -E9 81560D00 JMP EXECrypt.005A813E
004D2ABD 45 INC EBP
004D2ABE 91 XCHG EAX,ECX ; EXECrypt.005A8100
004D2ABF 3D 6F43525F CMP EAX,5F52436F
004D2AC4 35 92C3E6E9 XOR EAX,E9E6C392
004D2AC9 DA87 0900D6AD FIADD DWORD PTR DS:[EDI+ADD60009]
004D2ACF 9E SAHF
004D2AD0 D7 XLAT BYTE PTR DS:[EBX+AL]
...

Jump leads to good OEP:

005A813E 55 PUSH EBP
005A813F ^E9 7C52FAFF JMP EXECrypt.0054D3C0
005A8144 ^FF25 58D74D00 JMP DWORD PTR DS:[4DD758] ; EXECrypt.0051256B
005A814A ^0F88 670CF7FF JS EXECrypt.00518DB7
...

From here we can start fixing imports.




- Imports -

This protection is already explained. Use my script to fix them, then dump file and rebuild new IAT with ImpREC.

//-------------------------------- SCRIPT START -----------------------------------------
//ExeCryptor 2.x IAT for asm/Delphi/BorlandC++ type - by haggar
var addr
var oep
var pointer
var counter
var esp_ref
var temp

mov addr,401000
mov oep,eip

LABEL_01:
find addr,#ff25????4D00#
cmp $RESULT,0
je END_01
mov addr,$RESULT
add addr,2
mov pointer,addr
mov pointer,[pointer]
mov pointer,[pointer]
cmp pointer,10000000 //Check is import placed in thunk, or redirection.
ja LABEL_01
cmp pointer,0 //For delphi!!!!!!!!!!!!!!!!
je LABEL_01

sub addr,2
mov eip,addr
add addr,2

mov esp_ref,esp //Stack reference.
mov counter,0
LABEL_02: //Trace some code.
sti
add counter,1
cmp counter,30
jne LABEL_02

mov temp,esp
LABEL_03: //Find referenced stack value.
add temp,4
cmp temp,esp_ref
jne LABEL_03
sub temp,4

mov temp,[temp] //Go to "Magic address".
bp temp
esto
bc eip

mov temp,[eip]
and temp,0ffff
cmp temp,025ff //SelfWriting import type? No need to fix it then.
je LABEL_01

cmp eax,10000000 //If EAX=!IMPORT, then it is a first type.
jb LABEL_01

mov temp,addr //In this case EAX=IMPORT.
mov temp,[temp]
mov [temp],eax
jmp LABEL_01

END_01:
mov eip,oep
ret
//------------------------- END SCRIPT ------------------------------------------------




- Fixing dump -

Change TLS pointer with LordPE to 000E2000. Dump should work now, but probably with some problems. Problem is with serial so you will get exception message, plus dump might not work on other machines. Read official Excryptor crackme solution for more info about that.




- The End -

And that would be all.






What's Related

Story Options

ExeCryptor 2.3.9 - Unpacking | 1 comments | Create New Account
The following comments are owned by whomever posted them. This site is not responsible for what they say.
ExeCryptor 2.3.9 - Unpacking
Authored by: thorpe on Sunday, December 10 2006 @ 11:19 AM CET
very nice. thanks
 Copyright © 2017 BiW Reversing
 All trademarks and copyrights on this page are owned by their respective owners.
Powered By Geeklog 
Created this page in 0.06 seconds