Contribute  :  Web Resources  :  Past Polls  :  Site Statistics  :  Downloads  :  Forum  
    BiW ReversingThe challenge is yours    
 Welcome to BiW Reversing
 Thursday, April 17 2014 @ 08:58 AM CEST

PolyCrypt PE 2.1.4/2.1.5 - manually unpacking tutorial


TutorialsLevel : newbie

PolyCrypt PE 2.1.4/2.1.5 - manually unpacking tutorial

I heard for this packer at PEiD forum where it's author was bragging about his untedectable packer.
Ofcourse, that is not so true and this packer can be recognized like any other. Crypter is not hard
to unpack, altough it has some tricks. It has standard debug check which you can avoid using HideOlly
or IsDebuggerPresent plugins, and it has file locking what can be frustrating to fix, but lucky for us,
we can bypass this.

You need :

- OllyDbg 1.10
- ImpREC
- LordPE
- target , here in this archive attachment

Ok, grab target and load it in olly. Ignore all exceptions under olly options. You are here:

0040700D > 60               PUSHAD
0040700E   E8 EDFFFFFF      CALL RICHEDIT.00407000
00407013  ^EB F3            JMP SHORT RICHEDIT.00407008
00407015   864D 86          XCHG BYTE PTR SS:[EBP-7A],CL
00407018   D323             SHL DWORD PTR DS:[EBX],CL
0040701A   864B E2          XCHG BYTE PTR DS:[EBX-1E],CL
Trace with F7 two times and you'll climb up a little to the beggining of section:

00407000   91               XCHG EAX,ECX
00407001   8BF4             MOV ESI,ESP
00407003   AD               LODS DWORD PTR DS:[ESI]
00407004   FEC9             DEC CL
00407006   803408 E0        XOR BYTE PTR DS:[EAX+ECX],0E0
0040700A  ^E2 FA            LOOPD SHORT RICHEDIT.00407006
0040700C   C3               RETN
That is the first decryptor loop. Place bp on RETN and run target. Remove bp and take look below:

00407015   66:AD            LODS WORD PTR DS:[ESI]
00407017   66:33C3          XOR AX,BX
0040701A   66:AB            STOS WORD PTR ES:[EDI]
0040701C   02DF             ADD BL,BH
0040701E   86DF             XCHG BH,BL
00407020   66:D1CB          ROR BX,1
00407023   66:43            INC BX
00407025  ^E2 EE            LOOPD SHORT RICHEDIT.00407015
00407027   C3               RETN
That is another decryptor loop. Place bp on RETN again, press F9 two times to decrypt code and then
remove bp. Now our target is fully decrypted and we can search something that would indicate where
we can find OEP. Take look at this part of code:

00407407   32C0             XOR AL,AL
00407409   B9 33010000      MOV ECX,133
0040740E   8B85 396D4000    MOV EAX,DWORD PTR SS:[EBP+406D39]
00407414   0385 516D4000    ADD EAX,DWORD PTR SS:[EBP+406D51]
0040741A   8985 2B664000    MOV DWORD PTR SS:[EBP+40662B],EAX
00407420   8B0424           MOV EAX,DWORD PTR SS:[ESP]               ; RICHEDIT.00407077
00407423   64:67:A3 0000    MOV DWORD PTR FS:[0],EAX
00407428   83C4 08          ADD ESP,8
0040742B   5D               POP EBP                                  ; RICHEDIT.00407077
0040742C   9D               POPFD
0040742D   61               POPAD
0040742E   68 00000000      PUSH 0
00407433   C3               RETN
This POPFD and POPAD looks very interesting, here packer pops all flags and registeres. Place bp
on that RETN and use olly plugin to hide debugger, then run target. After some time olly will
break on our bp. Notice that PUSH opcode above RETN has changed it's value:

0040742E   68 6E1B4000      PUSH RICHEDIT.00401B6E
00407433   C3               RETN
That value is address where we will return now. Execute RETN with F8 and you'll land in code section
on OEP (press Ctrl+A then):

00401B6E   . 6A 00          PUSH 0
00401B70   . E8 BB0E0000    CALL RICHEDIT.00402A30
00401B75   . A3 E8414000    MOV DWORD PTR DS:[4041E8],EAX
00401B7A   . E8 9F0E0000    CALL RICHEDIT.00402A1E                   ; [GetCommandLineA
00401B7F   . A3 E0414000    MOV DWORD PTR DS:[4041E0],EAX
00401B84   . E8 DD0E0000    CALL RICHEDIT.00402A66                   ; [InitCommonControls
00401B89   . C705 08424000 >MOV DWORD PTR DS:[404208],1
00401B93   . C705 0C424000 >MOV DWORD PTR DS:[40420C],0
Ha, that was easy indeed. Yes but try dump file now with LordPE or OllyDump, or try use ImpREC. LordPE
will sad "Cannot paste original PE header", OllyDump "cannot create file" and ImpREC "Invalid PE header".
So what's the problem with PE header? Open memory window in olly and double click on PE header to see
what we have there. Ups, something weird is happening there, Olly is slowing down like hell and have
problems showing PE header. What's going on? Wait some time for olly to back to normal and don't scroll
else Olly will again go crazy, and then right click and select hex -> 16 bytes. Now you'll see dump without
problem. Take look and will see that, instead of sections info, packer has filled PE header with lot of
FFFFFFF bytes. That makes olly behave weird but that shouldn't prevent LordPE from reading header because
all tools read header from hard disk. So what's the problem? Don't close olly and try to open same target
file with another instance of Olly, you'll fail. Ok, reason is that this packer has locked file to prevent
opening by any tool or proces while first istance of program is running. We could just copy original header
as we open target first time in olly and the just paste it when we reach OEP, but still we cannot dump file
due to this locking feature. There is one more thing that could be problem. Scroll down to the import jumps
and notice that some jumps leads to packer section instead to dll's:

00402A06   $-FF25 0C314000  JMP DWORD PTR DS:[40310C] ;  USER32.UpdateWindow
00402A0C   $-FF25 64304000  JMP DWORD PTR DS:[403064] ;  RICHEDIT.004078F6   
However, altough this is not imports redirection in a way that is purpose is to hide imports, it still can
give us problems. I dumped couple files and most of them worked properly jumping to packer section and
returning back, but some files crashed after that. Thing is that in case of locking file, packer provides
support for opening file by hooking some API's like GetModuleHandle, CreateFileA, etc. in case that file
needs access to itself. You can read that in help file of packer ;)

And now unpacking.

Lucky for us, packer provides options for locking and hooking, and in packer code it has simple JNZ jumps
to jump over that features if they are not wanted. So we can just change couple jumps and get non-locked
, non-hooked file that we can dump with ease. Restart target in Olly again and pass that two decryptor loops.
Packer is very anoying to trace because it uses lot of INT 3 exceptions. If you pack file about 4MB is size,
it takes lot of time to reach OEP because of that. Ok, here you will find two debug checks, this is first one:

00407130   33C0             XOR EAX,EAX
00407132   64:8B40 30       MOV EAX,DWORD PTR FS:[EAX+30]
00407136   0FB658 02        MOVZX EBX,BYTE PTR DS:[EAX+2]
0040713A   0ADB             OR BL,BL
0040713C   0F85 28030000    JNZ RICHEDIT.0040746A 
this one is second:

004070CD   64:67:A1 3000    MOV EAX,DWORD PTR FS:[30]
004070D2   0FB658 02        MOVZX EBX,BYTE PTR DS:[EAX+2]
004070D6   0ADB             OR BL,BL
004070D8   0F85 8C030000    JNZ RICHEDIT.0040746A 
But interesting part is how we can avoid file locking and API hookis. Scroll here:

0040719F   80BD 316E4000 00 CMP BYTE PTR SS:[EBP+406E31],0
004071A6   74 47            JE SHORT RICHEDIT.004071EF
004071A8   68 04010000      PUSH 104
004071AD   6A 40            PUSH 40
004071AF   FF95 056C4000    CALL DWORD PTR SS:[EBP+406C05]           ; RICHEDIT.00406CD5
004071B5   8985 336E4000    MOV DWORD PTR SS:[EBP+406E33],EAX
004071BB   68 04010000      PUSH 104
004071C0   FFB5 336E4000    PUSH DWORD PTR SS:[EBP+406E33]
004071C6   6A 00            PUSH 0
004071C8   FF95 F16B4000    CALL DWORD PTR SS:[EBP+406BF1]           ; RICHEDIT.00406C8C
004071CE   6A 00            PUSH 0
004071D0   6A 00            PUSH 0
004071D2   6A 04            PUSH 4
004071D4   6A 00            PUSH 0
004071D6   6A 00            PUSH 0
004071D8   68 00000080      PUSH 80000000
004071DD   FFB5 336E4000    PUSH DWORD PTR SS:[EBP+406E33]
004071E3   FF95 ED6B4000    CALL DWORD PTR SS:[EBP+406BED]           ; RICHEDIT.00406C80
This part is responsable for locking part. Check at the beggining of this procedure just checking does
file needs to be locked. Just follow that address in memory and place 0 byte instea1 and jump will be
executed and file will not be locked. Now you can dump file without problem when you find OEP. With
API hooks is similar thing:

0040737D   80BD 326E4000 01 CMP BYTE PTR SS:[EBP+406E32],1
00407384   75 5E            JNZ SHORT RICHEDIT.004073E4
00407386   3B85 0D6C4000    CMP EAX,DWORD PTR SS:[EBP+406C0D]        ; RICHEDIT.00406CEC
0040738C   75 08            JNZ SHORT RICHEDIT.00407396
0040738E   8D85 40674000    LEA EAX,DWORD PTR SS:[EBP+406740]
00407394   EB 4E            JMP SHORT RICHEDIT.004073E4
00407396   3B85 1D6C4000    CMP EAX,DWORD PTR SS:[EBP+406C1D]        ; RICHEDIT.00406D19
0040739C   75 08            JNZ SHORT RICHEDIT.004073A6
0040739E   8D85 026A4000    LEA EAX,DWORD PTR SS:[EBP+406A02]
004073A4   EB 3E            JMP SHORT RICHEDIT.004073E4
004073A6   3B85 ED6B4000    CMP EAX,DWORD PTR SS:[EBP+406BED]        ; RICHEDIT.00406C80
004073AC   75 08            JNZ SHORT RICHEDIT.004073B6
004073AE   8D85 726A4000    LEA EAX,DWORD PTR SS:[EBP+406A72]
004073B4   EB 2E            JMP SHORT RICHEDIT.004073E4
004073B6   3B85 D16B4000    CMP EAX,DWORD PTR SS:[EBP+406BD1]        ; RICHEDIT.00406C29
004073BC   75 08            JNZ SHORT RICHEDIT.004073C6
004073BE   8D85 256B4000    LEA EAX,DWORD PTR SS:[EBP+406B25]
004073C4   EB 1E            JMP SHORT RICHEDIT.004073E4
004073C6   3B85 F16B4000    CMP EAX,DWORD PTR SS:[EBP+406BF1]        ; RICHEDIT.00406C8C
004073CC   75 08            JNZ SHORT RICHEDIT.004073D6
004073CE   8D85 566B4000    LEA EAX,DWORD PTR SS:[EBP+406B56]
004073D4   EB 0E            JMP SHORT RICHEDIT.004073E4
004073D6   3B85 F96B4000    CMP EAX,DWORD PTR SS:[EBP+406BF9]        ; RICHEDIT.00406CB7
004073DC   75 06            JNZ SHORT RICHEDIT.004073E4
004073DE   8D85 F26A4000    LEA EAX,DWORD PTR SS:[EBP+406AF2]
004073E4   8907             MOV DWORD PTR DS:[EDI],EAX
Just change byte at SS:[EBP+406E32] to 0 and there will be no hooked API's. Now you can use ImpREC to
repair IAT. Do all that and your unpacked target should run just nice :)

In the archive you'll find script for unpacking this version of PolyCrypt along with PEiD signatures
for this version. Until next tutorial....

Greets flies to BIW crew, good folks on, arteam members.... and many more.

What's Related

Story Options

PolyCrypt PE 2.1.4/2.1.5 - manually unpacking tutorial | 4 comments | Create New Account
The following comments are owned by whomever posted them. This site is not responsible for what they say.
PolyCrypt PE 2.1.4/2.1.5 - manually unpacking tutorial
Authored by: thorpe on Saturday, August 27 2005 @ 11:10 PM CEST
haggar I always look forward to reading your unpacking tutorials - thanks and good work
PolyCrypt PE 2.1.4/2.1.5 - manually unpacking tutorial
Authored by: haggar on Sunday, August 28 2005 @ 03:01 PM CEST
I'm glad that you like it :)
 Copyright © 2014 BiW Reversing
 All trademarks and copyrights on this page are owned by their respective owners.
Powered By Geeklog 
Created this page in 0.09 seconds