Monday, February 27 2006 @ 09:47 PM CET Contributed by: haggar Views: 7080
Level : 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.
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:
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:
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:
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):
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:
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:
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 :)