Monday, February 27 2006 @ 04:41 PM CET Contributed by: haggar Views: 5912
Level : intermediate
==============================================
ASProtect 2.0 - unpacking and repairing IAT
==============================================
1. Tools and stuff
In this tutorial we will see how can ASPR 2.0 be unpacked manually. It is not so hard , but you should have experience in manually unpacking, some knowledge about PE structure, and ASProtect shouldn't be new to you. If you never played with ASPR before, check my tutrial about ASPR 1.23RC4 that will intruduce you.
Target for this tutorial is black-eye's "nightmare keygenme". I think that it is protected with all options that ASPR2.0 has.
After loading target in Olly, I ignored all exceptions and just runned target trough olly. After keygenme opened, I checked log window to see what exceptions ASPR produced:
**********************************************************************
Log data
Address Message
77C00000 Module C:WINDOWSsystem32version.dll
71AD0000 Module C:WINDOWSSystem32wsock32.dll
71AB0000 Module C:WINDOWSSystem32WS2_32.dll
00987758 Access violation when writing to [00000000]
00986BE6 Access violation when writing to [00000000]
00986C6B Access violation when writing to [00000000]
00986EA2 Access violation when writing to [00000000]
0098703B Access violation when writing to [00000000]
00987174 Access violation when writing to [00000000]
009871BD Access violation when writing to [00000000]
00984760 Access violation when writing to [00000000]
009847D8 Access violation when writing to [00000000]
00984966 Access violation when writing to [00000000]
00984C0F Access violation when writing to [00000000]
00984D5B Access violation when writing to [00000000]
00984E3D Access violation when writing to [00000000]
009872D8 Access violation when writing to [00000000]
0098732F Access violation when writing to [00000000]
009874F1 Access violation when writing to [00000000]
009875AA Access violation when writing to [00000000]
00987683 Access violation when writing to [00000000]
0098341E INT3 command at 0098341E
009850B4 Access violation when writing to [00000000]
0098418C Access violation when writing to [00000000]
00984328 Access violation when writing to [00000000]
00985268 Access violation when writing to [00000000]
00985389 Access violation when writing to [00000000]
00986487 Access violation when writing to [00000000]
00985616 Access violation when writing to [00000000]
00985AAF Access violation when writing to [00000000]
00985BF0 Access violation when writing to [00000000]
0097CC59 Access violation when writing to [00000000]
00985DD4 Access violation when writing to [00000000]
00985F95 Access violation when writing to [00000000]
00986050 Access violation when writing to [00000000]
00987995 Access violation when writing to [00000000]
00987A9A Access violation when writing to [00000000]
00987C95 Access violation when writing to [00000000]
00987EAD Access violation when writing to [00000000]
0098806A Access violation when writing to [00000000]
009881EF Access violation when writing to [00000000]
009833BC INT3 command at 009833BC
0098341E INT3 command at 0098341E
00986807 Access violation when writing to [00000000]
00986A16 Access violation when writing to [00000000]
71AA0000 Module C:WINDOWSSystem32WS2HELP.dll
*********************************************************************
What we can see from this log? ASPR produces lot of memory acces violation exceptions and three INT3 ones. In many tutorials you can read "uncheck all exceptions and press Shift+F9 untill you reach last one...". In ASPR we can use exceptions for getting close to OEP, that is correct, but we can make that little bit easier. Since we have only three INT3 exceptions and two of them are very close to the end, we can ignore all exceptions and uncheck only INT3. Then we press Shift+F9 3 times to stop on last INT3, we place memory bp on CODE section, Shift+F9 again and we will break on false OEP:
We can see lot of weird junky code. That is just garbage. Real code is redirected and obfuscated. Real OEP should be on this address instead this jump:
00406DF4 -E9 7F937100 JMP 00B20178
That jump leads to some block where stolen code is hidden. Follow that jump and you will find it:
00B20178 55 PUSH EBP
00B20179 89E5 MOV EBP,ESP
00B2017B 6A FF PUSH -1
00B2017D F3: PREFIX REP:
00B2017E EB 02 JMP SHORT 00B20182
00B20180 CD 20 INT 20
00B20182 FF7424 1C PUSH DWORD PTR SS:[ESP+1C]
...
...
00B20242 5E POP ESI
00B20243 5B POP EBX
00B20244 F3: PREFIX REP:
00B20245 EB 02 JMP SHORT 00B20249
00B20247 CD 20 INT 20
00B20249 66:9D POPFW
00B2024B ^E9 62FFFFFF JMP 00B201B2
00B20250 F4 HLT
00B20251 6D INS DWORD PTR ES:[EDI],DX
00B20252 0000 ADD BYTE PTR DS:[EAX],AL
00B20254 0000 ADD BYTE PTR DS:[EAX],AL
00B20256 0000 ADD BYTE PTR DS:[EAX],AL
...
...
Ofcourse, code is obfuscated. There is two ways for fixing stolen code. First way is to binary copy all that bytes and after dumping just attach them to main dump and set OEP there. Second way is to find exact bytes which is not hard, app is VC++ and since we know how VC++ OEP looks we know what to look for. I will leave this for end. That is easy job. But lets write down some important information:
00406DF4 - jump to stolen code
3. Import problems
There is couple different ways how imports are processed.
3.a) First way:
First is that ASPR replaces import jumps/calls with calls:
Instead this CALL CONSTANT (which is 5 bytes long opcode), in original file was CALL DWORD[IMPORT] (6 bytes long). Restarting target and placing memory breakpoint on that line will get us to place where ASPR writes this calls (we will break couple times before this location):
0097377E 8BC0 MOV EAX,EAX
00973780 53 PUSH EBX
00973781 8BD8 MOV EBX,EAX
00973783 8BC3 MOV EAX,EBX
00973785 E8 56FFFFFF CALL 009736E0
0097378A C603 E8 MOV BYTE PTR DS:[EBX],0E8 <----- Here it writes CALL
0097378D 43 INC EBX
0097378E 8903 MOV DWORD PTR DS:[EBX],EAX <---- And here it writes destination.
00973790 5B POP EBX
00973791 C3 RETN
But check registers window:
EAX 008991E1 <------------------------ Redirection destination.
ECX 0012FF01
EDX 008991E1
EBX 00406E1A ASProtec.00406E1A <------ Address where import jump is.
ESP 0012FEF0
EBP 77E7D095 kernel32.GetVersion <---- This is API that is beeing redirected!
ESI 00406E1C ASProtec.00406E1C
EDI 009B48E8
EIP 0097378A
Since we see what API call should be there, we can change this code to write good import:
I will redirect jump to beggining of loader section because it has empty space there. Then I will inject code there that will write API where call points. Changing this:
0097CEC1 ^E9 ADFDFFFF JMP 0097CC73
to this:
0097CEC1 ^E9 3A31FEFF JMP 00960000
And there, injection:
00960000 892A MOV DWORD PTR DS:[EDX],EBP <---- Place API to destination.
00960002 E9 6CCC0100 JMP 0097CC73 <------------------ Return to normal ASPR code.
Now I made one script that can do all these changes. After using it, target runs fine under Olly. Problem is that all this pointer needs to be placed inside main image of file. I explained how and way in many tutorials before, so I made new script that will do that. So I fixed IAT, then I dumped and attached OEP stolen code, and I used ImpREC to rebuild new IAT, but dump crashed. Why? Because VC++ has one more way to access imports.
You see, usually imports are acessed via JMP DWORD PTR[API_HERE] or CALL DWORD PTR[API_HERE], but VC++ also uses
MOV REGISTER,address
JMP REGISTER
where REGISTER holds API address, and couple more variations.
After including it in script, I used it, dumped, rebuilded IAT with ImpREC, attached stolen code and saved all that. I double clicked on keygenme and it opened just fine :)! Yep, ASProtect 2.0 is defeated! Now try to keygen this crackme...
4. Couple words for end
Scripts that I have included here my not work for all other files packed with ASProtect 2.0. There are lot of builds of ASPR 2.0 which has some small differences that can disturb scripts. For example, script for finding OEP will not work if there is no stolen code. But this way of unpacking is pretty much the same for all ASPR 2.0 versions. Acctually, almost every ASPR version before 2.0 can be unpacked like this.
And that would be all for this tutorial. See you in next one ;)
Another great tutorial haggar! We love ya! ;)