Contribute  :  Web Resources  :  Past Polls  :  Site Statistics  :  Downloads  :  Forum  
    BiW ReversingThe challenge is yours    
 Welcome to BiW Reversing
 Thursday, March 21 2019 @ 03:17 AM CET

ASProtect 2.0 - unpacking and repairing IAT

   

TutorialsLevel : 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.

- Windows XP
- OllyDbg 1.10
- ImpREC
- LordPE
- hex editor
- target , here http://www.reversing.be/binaries/articles/20060226193711870.rar




2. OEP and stolen code

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:

00406E1A E8 E1918900 CALL 00CA0000
00406E1F 36:31D2 XOR EDX,EDX
00406E22 8AD4 MOV DL,AH
00406E24 8915 B4D04000 MOV DWORD PTR DS:[40D0B4],EDX
00406E2A 89C1 MOV ECX,EAX
00406E2C 81E1 FF000000 AND ECX,0FF
00406E32 890D B0D04000 MOV DWORD PTR DS:[40D0B0],ECX
00406E38 C1E1 08 SHL ECX,8
00406E3B 01D1 ADD ECX,EDX
00406E3D 890D ACD04000 MOV DWORD PTR DS:[40D0AC],ECX
00406E43 C1E8 10 SHR EAX,10
...
...

First call that you see is some redirected import and that will be explained in next part, but scroll up to see what happened with OEP code:

00406DF4 -E9 7F937100 JMP 00B20178
00406DF9 54 PUSH ESP
00406DFA DEC0 FADDP ST,ST
00406DFC 888F 99E23384 MOV BYTE PTR DS:[EDI+8433E299],CL
00406E02 AD LODS DWORD PTR DS:[ESI]
00406E03 0F71B7 30B961C3 >PSLLW QWORD PTR DS:[EDI+C361B930],0C4
00406E0B 1B27 SBB ESP,DWORD PTR DS:[EDI]
00406E0D 3A5E 01 CMP BL,BYTE PTR DS:[ESI+1]
00406E10 A3 AA614693 MOV DWORD PTR DS:[934661AA],EAX
00406E15 B1 4B MOV CL,4B
00406E17 2F DAS
00406E18 FA CLI
00406E19 81E8 E1918900 SUB EAX,8991E1
...
...


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:

00406E1A E8 E1918900 CALL 00CA0000
00406E1F 36:31D2 XOR EDX,EDX

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:

00973780 66:C700 FF15 MOV WORD PTR DS:[EAX],15FF
00973785 40 INC EAX ; ASProtec.004011A4
00973786 40 INC EAX ; ASProtec.004011A4
00973787 8910 MOV DWORD PTR DS:[EAX],EDX
00973789 892A MOV DWORD PTR DS:[EDX],EBP ; kernel32.GetVersionExA
0097378B 90 NOP
0097378C 90 NOP
0097378D 90 NOP
0097378E 90 NOP
0097378F 90 NOP
00973790 90 NOP
00973791 C3 RETN

66 C7 00 FF 15 40 40 89 10 89 2A 90 90 90 90 90 90

Now , our call will look like this:

00406E1A . FF15 0000CA00 CALL DWORD PTR DS:[CA0000] ; kernel32.GetVersion
00406E20 . 31D2 XOR EDX,EDX

Not bad for start, keygenme works OK with all these calls changed altough this is not yet good for ImpREC.


3.b) Second way:

00401043 FF15 FC489B00 CALL DWORD PTR DS:[9B48FC] ; kernel32.CreateFileA

Well, this is same thing as to what we bring our first example. We are skipping this for now.


3.c) Third way:

004030A8 FF15 8C499B00 CALL DWORD PTR DS:[9B498C]

Again, memory bp on it and find the routine:

0097CEAD 8B5424 0C MOV EDX,DWORD PTR SS:[ESP+C]
0097CEB1 8902 MOV DWORD PTR DS:[EDX],EAX
0097CEB3 8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C]
0097CEB7 8906 MOV DWORD PTR DS:[ESI],EAX <------- Here it writes pointer!
0097CEB9 0FB74424 04 MOVZX EAX,WORD PTR SS:[ESP+4]
0097CEBE 0143 08 ADD DWORD PTR DS:[EBX+8],EAX
0097CEC1 ^E9 ADFDFFFF JMP 0097CC73 <--------------------- I have decided to redirect this jump.
0097CEC6 3C 04 CMP AL,4
0097CEC8 0F85 F4000000 JNZ 0097CFC2

Again, check registeres:

EAX 009B498C
ECX 00000000
EDX 009B498C <------------------------- Destination.
EBX 009B04D4
ESP 0012FEF8
EBP 77D47DE3 user32.ReleaseCapture <--- API.
ESI 004030AA ASProtec.004030AA <------- CALL pointer.
EDI 009B48E8
EIP 0097CEB7

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.

After this , our api call looks:

004030A8 FF15 8C499B00 CALL DWORD PTR DS:[9B498C] ; user32.ReleaseCapture


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.


3.d) Fourth way:

Dump crashes at:

00408208 8B2D F44A9B00 MOV EBP,DWORD PTR DS:[9B4AF4]

I checked that line under Olly after using script:

00408208 8B2D F44A9B00 MOV EBP,DWORD PTR DS:[9B4AF4] ; kernel32.GetEnvironmentStringsW

Import is there. I should include it my script to move pointer in main image. Couple more examples:

0040827D 8B3D 0C4B9B00 MOV EDI,DWORD PTR DS:[9B4B0C]
0040344E 8B35 F8499B00 MOV ESI,DWORD PTR DS:[9B49F8]


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 ;)



haggar




What's Related

Story Options

ASProtect 2.0 - unpacking and repairing IAT | 1 comments | Create New Account
The following comments are owned by whomever posted them. This site is not responsible for what they say.
ASProtect 2.0 - unpacking and repairing IAT
Authored by: detten on Wednesday, March 01 2006 @ 08:33 AM CET
The scripts have been added to the tutorial attachment.
Another great tutorial haggar! We love ya! ;)
 Copyright © 2019 BiW Reversing
 All trademarks and copyrights on this page are owned by their respective owners.
Powered By Geeklog 
Created this page in 0.07 seconds