Contribute  :  Web Resources  :  Past Polls  :  Site Statistics  :  Downloads  :  Forum  
    BiW ReversingThe challenge is yours    
 Welcome to BiW Reversing
 Wednesday, August 12 2020 @ 06:33 AM CEST

PESpin 1.304 public - repairing IAT

   

TutorialsLevel : beginner

=======================
PESpin 1.304 public - repairing IAT
=======================



This version of PESpin is completly indentical as previous 1.3. There are no new things in this public version interesting for unpacking, because this version is out just for compability issues. But in previous tutorials there was no explanation for proper IAT fixing , just some tricks to run dump on user machine, so that part will be covered in this tutorial better.




1. Tools and stuff

Tools are usual:

- OllyDbg 1.10
- ImpREC
- LordPE
- Windows XP
- target is here http://www.reversing.be/binaries/articles/20060224214414479.rar


This tutorial will be short, so it would not be bad that you check previous ones which are more detailed.




2. OEP and stolen code

If you remember from past tutorials, last API that PESpin will use before jumping to OEP is GetTickCount. It will probably use it to get some random value, to destroy code/data that it doesn't need anymore. So we can place breakpoint at the end of that API (PESpin checks first bytes for CC bytes) and return to protectors code. So we are now very close to OEP jump. PESpin will use long jump to jump into original code section. So we can go to beggining of this PESpin section and search for bytes E9??????FF which corespond to long jump. Then we find all those possible jumps and first one that jumps in 401000 section is good one. I found this jump:

00417BC4 -E9 0F9AFEFF JMP KeygenMe.004015D8

But PESpin also can stole some bytes from OEP, as said before. That stolen code is obfuscated, but it always start with POPAD opcode which is 61 in hexadecimal. So scroll up and search for this byte. You will find it obfuscated within call opcode:

00417AD8 E8 61F7D239 CALL 3A14723E

Patch first byte:

00417AD8 90 NOP
00417AD9 61 POPAD

Now place bp on POPAD , run and you will break there. There starts execution of stolen code, right after POPAD. But stolen bytes are obfuscated with junk code. It is not big problem to find it if we know that our target is Visual C++ program. Code obfuscation isn't hard and I can find exact bytes:


00417B36 55 PUSH EBP
00417B3A 8BEC MOV EBP,ESP
00417B3F 6A FF PUSH -1

00417B44 68 3482111F PUSH 1F118234 <------------------ These 4 opcodes are just obfuscation of two PUSH.
00417B49 812C24 6421D11E SUB DWORD PTR SS:[ESP],1ED12164
00417B50 68 48F020F7 PUSH F720F048
00417B55 810424 B03D1F09 ADD DWORD PTR SS:[ESP],91F3DB0

00417B5C 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
00417B65 50 PUSH EAX
00417B69 64:8925 00000000 MOV DWORD PTR FS:[0],ESP
00417B73 83EC 58 SUB ESP,58
00417B79 53 PUSH EBX
00417B7D 56 PUSH ESI
00417B81 57 PUSH EDI
00417B85 8965 E8 MOV DWORD PTR SS:[EBP-18],ESP
00417B8B FF15 CDA44100 CALL DWORD PTR DS:[41A4CD] <---- Obfuscated API call!
00417B94 33D2 XOR EDX,EDX
00417B99 8AD4 MOV DL,AH
00417B9E 8915 5C764000 MOV DWORD PTR DS:[40765C],EDX
00417BA7 8BC8 MOV ECX,EAX
00417BAC 81E1 FF000000 AND ECX,0FF
00417BB5 890D 58764000 MOV DWORD PTR DS:[407658],ECX
00417BBE C1E1 08 SHL ECX,8
00417BC4 -E9 0F9AFEFF JMP KeygenMe.004015D8 <------ Not stolen, it's jump to false OEP.

And we can restore later those bytes. But these 4 ones:

PUSH 1F118234
SUB DWORD PTR SS:[ESP],1ED12164
PUSH F720F048
ADD DWORD PTR SS:[ESP],91F3DB0

with:

PUSH 4060D0
PUSH 402DF8


But all that is not necessery at all. We could just dump at this line:

00417B36 55 PUSH EBP

and dump would be good. Just OEP would be in PESpin section and not in first one.




3. Redirected code

If we execute OEP jump:

00417BC4 -E9 0F9AFEFF JMP KeygenMe.004015D8

we will be in code section where we can see redirected code

004015EB . E8 E8EBFFFF CALL KeygenMe.004001D8

It is all well known from previous version. CALL leads to

004001D8 -E9 E6160000 JMP KeygenMe.004018C3

and that JMP just returns to some location. So CALL to PE header was in original file CALL to some address.



Second redirection looks like this:

0040169E .-E9 95EBFFFF JMP KeygenMe.00400238

jumps to

00400238 68 FF000000 PUSH 0FF <--------------- This is redirected opcode.
0040023D -E9 61140000 JMP KeygenMe.004016A3 <-- Returning back.

Jumps are substitution pushes.



There is new redirection that I didn't see in 1.3 version of PEspin:

00401687 $-E9 94EBFFFF JMP KeygenMe.00400220
0040168C 90 NOP
0040168D 90 NOP

jumps to

00400220 833D 38764000 01 CMP DWORD PTR DS:[407638],1 <------ Redirected code.
00400227 -E9 62140000 JMP KeygenMe.0040168E <------------ Returning back.



And now I can write small script for OllyScrip plugn that can fix that code. See it in attachment. That script will work (it should) for all 1.x versions of PESpin.

Blocks of code that are decrypted during runtime, so called "clear and crypt markers" will not be discussed in this tutorial. Check last one for that.

And that is almost all. Just IAT is left to fix :)




4. Problem with IAT

This is not hard problem, but in previous tutorial I didn't have enough knowlege about ImpREC, PE structure, etc. First we need to see what happened with our imports and then we will think how to fix them. I was placing breakpoints on LoadLibraryA and GetProcAddress to catch where imports are being processed, but I found nothing. That means PESpin doesn't use use those api's to load libraries and find api's, instead it may have custom coded functions to do such job. Then I checked already loaded modules when target is opened in olly and sow that all needed dll's are already loaded by windows loader:

Executable modules
Base Size Entry Name File version Path
00400000 0001C000 004160D4 KeygenMe D:PESpinPESpin v1.304KeygenMe.exe
77340000 0008B000 773419ED COMCTL32 5.82 (xpsp1.0208 C:WINDOWSsystem32COMCTL32.DLL
77D40000 0008C000 77D53A05 USER32 5.1.2600.1561 (x C:WINDOWSsystem32USER32.DLL
77DD0000 0008D000 77DD1D3D ADVAPI32 5.1.2600.1106 (x C:WINDOWSsystem32ADVAPI32.dll
77E60000 000E6000 77E7ADB3 kernel32 5.1.2600.1560 (x C:WINDOWSsystem32kernel32.dll
77F50000 000A7000 ntdll 5.1.2600.1106 (x C:WINDOWSSystem32ntdll.dll
78000000 00087000 78001E0D RPCRT4 5.1.2600.1361 (x C:WINDOWSsystem32RPCRT4.dll
7F000000 00041000 GDI32 5.1.2600.1561 (x C:WINDOWSsystem32GDI32.dll

If I just run target in olly, no new module is loaded. That give us first possible answer why LoadLibraryA isn't used. Actually it is used couple times, but not for API redirecting purpose. GetProcAddress is also used couple times but not for our api's. So I tok another approach to save time tracing trough code.


Let's find OEP and see where first import jump leads. This is first import jump, ie. call:

00401605 . FF15 C8A44100 CALL DWORD PTR DS:[41A4C8]

we see that is points to PESpin section and not to 406000 which should be IAT one. Check dump at that address:

0041A4C8 4B 02 3B 00 00 6A 02 3B 00 00 8E 02 3B 00 00 A9 K.;..j.;....;..
0041A4D8 02 3B 00 00 BD 02 3B 00 00 DD 02 3B 00 00 F9 02 .;....;....;....
0041A4E8 3B 00 00 11 03 3B 00 00 30 03 3B 00 00 48 03 3B ;....;..0.;..H.;
...

We see that PESpin created table with pointers to 003B0000 section. Pointer dwords are separated with 0 bytes. That probably disturb ImpREC to get table, because pointers should be separated with zero terminating dword. And pointer leads to obfuscated api jump, or whole emulated api (if it's very small one, just one line):

003B024B EB 01 JMP SHORT 003B024E
003B024D D9A1 1476ED77 FLDENV (28-BYTE) PTR DS:[ECX+77ED7614]
003B0253 C3 RETN

It is easy to write small script for Olly that could rebuild new table, but we can remove obfuscation from import jumps. As easies option, I decide to place memory breakpoint on 003B0000 section so I could find place where PESpin writes obfuscated code there. Ok, bp on VirtualAlloc, and wait untill it allocates that section. Then memory bp on it. And I stopped here:

00416BCE 66:C706 EB01 MOV WORD PTR DS:[ESI],1EB
00416BD3 C646 02 D9 MOV BYTE PTR DS:[ESI+2],0D9
00416BD7 83C6 03 ADD ESI,3
00416BDA 2BD2 SUB EDX,EDX
00416BDC EB 01 JMP SHORT KeygenMe.00416BDF
00416BDE EA EB04EAEB 0400 JMP FAR 0004:EBEA04EB
...
...

PESpin writes here something. We are in part of code where obfuscation is in progress. If we remember from previous tutorial, this procedure starts with POPAD and ends with PUSHAD. Scroll up to find PUSHAD:

00416BAF 60 PUSHAD <----------------------- Yep, here it is.
00416BB0 EB 01 JMP SHORT KeygenMe.00416BB3
00416BB2 ^71 EB JNO SHORT KeygenMe.00416B9F
00416BB4 04 D5 ADD AL,0D5
00416BB6 EB 04 JMP SHORT KeygenMe.00416BBC
00416BB8 6BEB FB IMUL EBP,EBX,-5
...
...

We are very close to the end of our task, Place hardware bp on execution on that PUSHAD and restart target. Run it in Olly and you should break there. Ance again, in previous tutorial we sow that this procedure can be NOP-ed from PUSHAD to POPAD and we will kill obfuscation:

00416BAF 60 PUSHAD
00416BB0 90 NOP
00416BB1 90 NOP
00416BB2 90 NOP
...
...
...
00416C95 90 NOP
00416C96 90 NOP
00416C97 90 NOP
00416C98 61 POPAD
00416C99 C9 LEAVE
00416C9A C2 0800 RETN 8

This code also isn't checked with integrity checks so we can just leave it. Now we find stolen code like described in first part of this tutorial (beware, GetTickCount is already used so you need find address of code before this step), and we restore it on right OEP:

00401591 /. 55 PUSH EBP
00401592 |. 8BEC MOV EBP,ESP
00401594 |. 6A FF PUSH -1
00401596 |. 68 D0604000 PUSH KeygenMe.004060D0
0040159B |. 68 F82D4000 PUSH KeygenMe.00402DF8 ; SE handler installation
004015A0 |. 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
004015A6 |. 50 PUSH EAX
004015A7 |. 64:8925 000000>MOV DWORD PTR FS:[0],ESP
004015AE |. 83EC 58 SUB ESP,58
004015B1 |. 53 PUSH EBX
004015B2 |. 56 PUSH ESI
004015B3 |. 57 PUSH EDI ; KeygenMe.004188EA
004015B4 |. 8965 E8 MOV DWORD PTR SS:[EBP-18],ESP
004015B7 |. FF15 CDA44100 CALL DWORD PTR DS:[41A4CD] ; kernel32.GetVersion
004015BD |. 33D2 XOR EDX,EDX
004015BF |. 8AD4 MOV DL,AH
004015C1 |. 8915 5C764000 MOV DWORD PTR DS:[40765C],EDX
004015C7 |. 8BC8 MOV ECX,EAX
004015C9 |. 81E1 FF000000 AND ECX,0FF
004015CF |. 890D 58764000 MOV DWORD PTR DS:[407658],ECX
004015D5 |. C1E1 08 SHL ECX,8

Then we use script for fixing redirected code.




5. Fixing IAT

And now we can fix IAT. I wrote small script just for this VC++ app that will change all pointers to new tab. Example, this call:

004015B7 |. FF15 CDA44100 CALL DWORD PTR DS:[41A4CD] ; kernel32.GetVersion

will now point to new place

004015B7 |. FF15 90604100 CALL DWORD PTR DS:[416090] ; kernel32.GetVersion

and there I created new tab:

00416000 00 00 00 00 00 00 00 00 E0 56 D6 77 00 00 00 00 .........V.w....
00416010 1F 97 D4 77 00 00 00 00 1D 5F D4 77 00 00 00 00 ...w....._.w....
00416020 52 65 D6 77 00 00 00 00 52 65 D6 77 00 00 00 00 Re.w....Re.w....
00416030 52 65 D6 77 00 00 00 00 E4 D9 D4 77 00 00 00 00 Re.w.......w....
00416040 FE 65 D6 77 00 00 00 00 FE 65 D6 77 00 00 00 00 .e.w.....e.w....
00416050 >FE 65 D6 77 00 00 00 00 0F 6E D5 77 00 00 00 00 .e.w.....n.w....
00416060 >0F 6E D5 77 00 00 00 00 0F 6E D5 77 00 00 00 00 .n.w.....n.w....
00416070 93 5A E7 77 00 00 00 00 0C 16 E6 77 00 00 00 00 .Z.w.......w....
00416080 53 95 E7 77 00 00 00 00 A1 16 F5 77 00 00 00 00 S..w.......w....
00416090 95 D0 E7 77 00 00 00 00 AB E2 E7 77 00 00 00 00 ...w.......w....
004160A0 7E 17 E6 77 00 00 00 00 D9 AC E7 77 00 00 00 00 ~..w.......w....
004160B0 63 98 E7 77 00 00 00 00 25 E2 E7 77 00 00 00 00 c..w....%..w....
004160C0 7C 88 E7 77 00 00 00 00 A1 16 F5 77 00 00 00 00 |..w.......w....
004160D0 6B 15 F5 77 00 00 00 00 5F 8C F5 77 00 00 00 00 k..w...._..w....
004160E0 A1 16 F5 77 00 00 00 00 C5 AB E7 77 00 00 00 00 ...w.......w....
004160F0 6B 15 F5 77 00 00 00 00 C5 AB E7 77 00 00 00 00 k..w.......w....
00416100 0C E6 E7 77 00 00 00 00 B8 16 E6 77 00 00 00 00 ...w.......w....
00416110 63 98 E7 77 00 00 00 00 95 9B E9 77 00 00 00 00 c..w.......w....
00416120 FC AC E7 77 00 00 00 00 3B 95 E6 77 00 00 00 00 ...w....;..w....
00416130 E8 E4 E7 77 00 00 00 00 3B 95 E6 77 00 00 00 00 ...w....;..w....
00416140 2F E0 E9 77 00 00 00 00 7E 17 E6 77 00 00 00 00 /..w....~..w....
00416150 4E E3 E7 77 00 00 00 00 E7 E3 E7 77 00 00 00 00 N..w.......w....
00416160 4E E3 E7 77 00 00 00 00 A4 E2 E7 77 00 00 00 00 N..w.......w....
00416170 FC AC E7 77 00 00 00 00 E7 E3 E7 77 00 00 00 00 ...w.......w....
00416180 8D F0 E7 77 00 00 00 00 53 95 E7 77 00 00 00 00 ...w....S..w....
00416190 1B E0 E7 77 00 00 00 00 7F C9 E6 77 00 00 00 00 ...w.......w....
004161A0 7F C9 E6 77 00 00 00 00 4F A7 E7 77 00 00 00 00 ...w....O..w....
004161B0 4F A7 E7 77 00 00 00 00 1B E0 E7 77 00 00 00 00 O..w.......w....
004161C0 B1 E2 E7 77 00 00 00 00 B1 E2 E7 77 00 00 00 00 ...w.......w....
004161D0 6B 15 F5 77 00 00 00 00 A1 16 F5 77 00 00 00 00 k..w.......w....
004161E0 B4 D8 E7 77 00 00 00 00 D1 DD E7 77 00 00 00 00 ...w.......w....
004161F0 84 9F E7 77 00 00 00 00 84 9F E7 77 00 00 00 00 ...w.......w....
00416200 4F A7 E7 77 00 00 00 00 4F A7 E7 77 00 00 00 00 O..w....O..w....
00416210 D1 DD E7 77 00 00 00 00 D1 DD E7 77 00 00 00 00 ...w.......w....
00416220 D1 DD E7 77 00 00 00 00 9C A8 E7 77 00 00 00 00 ...w.......w....
00416230 E8 D8 E7 77 00 00 00 00 23 5D E7 77 00 00 00 00 ...w....#].w....
00416240 23 5D E7 77 00 00 00 00 B1 E2 E7 77 00 00 00 00 #].w.......w....
00416250 4F A7 E7 77 00 00 00 00 4F A7 E7 77 00 00 00 00 O..w....O..w....
00416260 E8 D8 E7 77 00 00 00 00 B4 90 E6 77 00 00 00 00 ...w.......w....
00416270 A1 16 F5 77 00 00 00 00 5F 8C F5 77 00 00 00 00 ...w...._..w....
00416280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00416290 C2 25 E7 77 00 00 00 00 DE AF E7 77 00 00 00 00 .%.w.......w....
004162A0 44 0C F6 77 00 00 00 00 00 00 00 00 00 00 00 00 D..w............
004162B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...............


Now we have thunks where every import value is separated with 4 zero terminating bytes and ImpREC can easily read this. Now we just run ImpREC and fix dumped file. Save file, run,..., yep, it works :)


It is not perfect work because thunks that belong to same dll should be sticked together which would reduce size of file, also we could remove PESpin section, but hey, now dump works on every machine :)



Greets and see you!



haggar




What's Related

Story Options

PESpin 1.304 public - repairing IAT | 0 comments | Create New Account
The following comments are owned by whomever posted them. This site is not responsible for what they say.
 Copyright © 2020 BiW Reversing
 All trademarks and copyrights on this page are owned by their respective owners.
Powered By Geeklog 
Created this page in 0.71 seconds