Tuesday, October 04 2005 @ 10:15 PM CEST Contributed by: haggar Views: 2186
Level : beginner
==============================
Alex Protector v1.0 beta2 - manually unpacking
==============================
Alex Protector is simple freeware protector for PE files. It has IAT redirection very simular to Armadillo's Import Eliminator feature and a very interesting way of stealing bytes from OEP.
It is always intersting to trace trough code and see what exactly protector does, but that kind of approach is very hard and time consuming. I was going to write that kind of tutorial, but I put aside this project to examne some others protectors and lost will for continuing. So I decide that I will wrote tutorial that will "just" explain how to quick unpack some target.
Protector doesn't have some fancy anti-debug tricks and we can just run protected file trough debugger without problem. Debug tricks in this protector are based on exceptions and RDTSC opcodes. I already told you that the most interesting part is OEP stealing and IAT redirection.
Protector will redirect imports to some allocated block of memory and obfuscate it there. Also it gona steal couple first bytes from OEP and mix them with junk in another separate allocaded memory block.
Let see what we have there. Open target in Olly. You will get "Bad or unknown format..." message. This is minor anoyance because we cannot see sections properly in memory map window. Now, place breakpoint on the last opcode in the VirtualAlloc API , click "go to" -> "expression" and enter VirtualAlloc, then place bp on first RETN opcode (in my case it is RETN 10):
Now run olly with Shift+F9 and you will break on that bp. EAX register will hold now some value, that value is base address of some allocated memory block. Write down that value, keep pressing and do that every time when you stop untill crackme opens. Then in memory map check every block that has been allocated. There are couple interesting (select disassemble view on each dump window):
Block with stolen OEP's code:
This block holds stolen OEP code mixed with junk. You will easy recognized it because it has only on jump in whole block and that jump is at the end and leads in code section to place after stolen bytes:
003B0000 MOV EDI,DFB4AF72
003B0006 LEA EDI,DWORD PTR DS:[1A58BA5F]
003B000C DEC EDI
003B000E SHRD EDI,ESI,0F2
003B0012 BSR EDI,ESI
...
...
lot of similar code here
...
...
003B0C5C TEST EDI,ESI
003B0C5E TEST EDI,874CDC1C
003B0C64 AND EDI,9378C643
003B0C6A JMP packed.004079DE <---------------- Jump to code section!!!
003B0C6F ADD BYTE PTR DS:[EAX],AL
003B0C71 ADD BYTE PTR DS:[EAX],AL
003B0C73 ADD BYTE PTR DS:[EAX],AL
003B0C75 ADD BYTE PTR DS:[EAX],AL
003B0C77 ADD BYTE PTR DS:[EAX],AL
We will not try to find original bytes here, we going just to append this code to our main dump. Most of files will work properly even if you don't add this code. Stolen code are usually 2-3 bytes, never more.
Block with obfuscated imports:
This block looks like this: It has lot of jumps and you will notice RDTSC opcodes which checks are program is debugged. You will also notice some API values. This block you can easy find just by following some import in unpacked crackme:
003A0000 ADD AL,0
003A0002 CMP AL,BYTE PTR DS:[EAX]
003A0004 JMP SHORT 003A0007
003A0006 LEAVE
003A0007 PUSHAD
003A0008 RDTSC
003A000A JMP SHORT 003A000D
003A000C LEAVE
003A000D MOV EBX,EAX
003A000F JMP SHORT 003A0012
003A0011 LEAVE
003A0012 MOV ECX,EDX
003A0014 RDTSC
003A0016 SUB EAX,EBX
003A0018 SBB EDX,ECX
003A001A JMP SHORT 003A001D
003A001C ???
003A001D RDTSC
003A001F ADD EAX,EBX
003A0021 ADC EDX,ECX
003A0023 RDTSC
003A0025 JMP SHORT 003A0028
003A0027 ???
003A0028 SUB EAX,EBX
003A002A JMP SHORT 003A002D
003A002C ???
003A002D SBB EDX,ECX
003A002F TEST EDX,EDX
003A0031 JNZ SHORT 003A0040
003A0033 POPAD
003A0034 JMP SHORT 003A0037
003A0036 ???
003A0037 PUSH ntdll.RtlDeleteCriticalSection <--- Here is API value pushed!
003A003C JMP SHORT 003A003F
003A003E JMP E93BEC06
There is one more block that holds API names, but it is not important for us. Ofcourse, above addresses will probably be different on your computer.
To fix all that we need some section where we will place our import thunks because ImpREC cannot read those which are not in main image. Problem is that we don't know which one section to use because we cannot see them in Olly. But good thing is that protector doesn't check PE header and file size, so we can add couple sections with LordPE. Close olly and open our target in hex editor (make backup before) and add to the end of file 4000h bytes. Open then file in LordPE's pe editor and add one section that you will name NewOEP. Set it's VirtualSize=2000 ans RawSize=1500. Then create one more section, call it NewIAT and enter sizes same as NewOEP. Run target and it will work normall :) Good! Now we gona unpack that modified target.
2. OEP and stolen code
Ok, do you remember that block that has stolen code? Common sense tell us that block will be executed last, before jumping to code section. So we need to break there somehow. That is really easy, you need to use memory and hardware breakpoints and you will catch it easy. You can do it in this way: Place bp on the end of VirtualAlloc and keep pressing Shift+F9 untill you see in EAX value that is address of your stolen OEP block. At my computer that is b30000, for you it can be different so you just follow way how did I do it and not exactly values. But keep pressing untill that value changes to another and then stop. Now go to that 3b0000 (or whatever) in the CPU window:
As you can see there is nothing there. Normally because nothing is written there yet. Place on first line breakpoint memory on write and and the same spot, hardware bp on execution. That is so we will stop when protector writes here and when this code is being executed. Remove bp from VirtualAlloc and presShift+F9. First you will break two times here in this unpacking procedure:
00411316 MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] <--- First time here.
00411317 MOV BL,2
00411319 CALL packed.0041138B
...
... <-------------------------------------------------- One more time somewhere here.
...
0041139D ADC ECX,ECX
0041139F CALL packed.0041138B
004113A4 JB SHORT packed.00411398
004113A6 RETN
004113A7 SUB EDI,DWORD PTR SS:[ESP+28]
004113AB MOV DWORD PTR SS:[ESP+1C],EDI
004113AF POPAD
004113B0 RETN
Press Shift+F9 once more and you will break on hardware bp on execution in our block:
003B0000 MOV EDI,DFB4AF72 <---------------------- Hre you are! Binary copy from here...
003B0006 LEA EDI,DWORD PTR DS:[1A58BA5F]
003B000C DEC EDI
...
...
003B0C5E TEST EDI,874CDC1C
003B0C64 AND EDI,9378C643 <---------------------- ...to here!
003B0C6A JMP packed.004079DE <------------------- This jump you will assemble.
003B0C6F ADD BYTE PTR DS:[EAX],AL
You can remove all breakpoints now. You are at the place before jumping to "false" OEP and execution of packed target. We will first deal with this stolen code. What we gona do is just binary copy-paste all that code to our NewOEP section, so select all from 3b0000 to 3b0c64 and binary copy it. Last jump we will change manually. Dou you remember where starts our NewOEP section? If not check file with LordPE, it satarts from 14000+400000=414000 so go there in olly:
00414000 MOV EDI,DFB4AF72
00414006 LEA EDI,DWORD PTR DS:[1A58BA5F]
0041400C DEC EDI
...
...
00414C64 AND EDI,9378C643
00414C6A ADD BYTE PTR DS:[EAX],AL <------ And just here you need to place jump to false OEP.
00414C6C ADD BYTE PTR DS:[EAX],AL
00414C6E ADD BYTE PTR DS:[EAX],AL
And just assemble at the end that jump to false OEP. We couldn't binary copy it because value would be different, you have now:
This is little harder part but it's not problem. First you must see how obfuscated import looks. Follow this address to see one example:
00401084 JMP DWORD PTR DS:[3A0784]
That is one import jump. So jump reads value that is stored at 3a0784 and jumps to that value. But interesting is, that value is just 4 bytes below first one DS:[003A0784]=003A0788. if we follow that in dump we will see this:
We will fix this: we just take API value from push opcode 003A07BB 68 A1AAE777 PUSH kernel32.ReadFile and that value A1AAE777 we place instead our first 4 bytes of this obfuscated API call. But we will not do that manually, we will just use ollyscript for that. Lusky for us, all impoct jumps use this same pattern. After using script, we have:
But that is not done since ImpREc still cannot recognize such API jump. We will now use other script for making new IAT in our main image. First remember that we made NewIAT section at 16000+400000=416000 and we will redirect jumps there. Script will ask you where OEP is, that is 401000 section and where is newIAt section, that is 416000, and then it will rebuild new thunks. Your API jump will have new value:
Dump it from there. Use ImpREC, as OEP enter 79de and find imports. You will have all imports in 6 modules without any invalid. Fix dump and close ImpREC. If you start dumped file, it will probably run normaly because protector has stole just couple bytes, but I was testing some files that have important first few bytes and file would crush. So what we need is to change Original Entry Point to that NewOEP block where we have pasted stolen code. Open dump in LordPE and for EntryPoint enter 14000, save changes and run. File works ok :) That is all, I have included my dump and you can examne it so you can see what and how did I do it.
4. Couple more words
I have included in archive next files: packed.exe - original packed target; packed+2.exe - packed file which I added two new sections before unpacking; dumped.exe - unpacked and dumped target; "AlexProtector1.0 - tutorial.txt" - this tutorial.
I have included two scripts for fixing IAT. First Script "AlexProt I.txt" will fix obfuscation from IAT block. You need just enter base address of that block. Second script "AlexProt II.txt" is one that will make new IAT in some section that you chose. You need enter base address of code section so script can find jumps/calls and base of new section where you want to make new IAT. Scrip also needs to be manually changed in some parts for every new file. Actually, this script is one from my Armadillo tutorial.
Btw, for unpacking AlexProtextor 1.0 you have loveboom's script that can unpack and fix IAT on the fly. You can find that script on the forum in topic where I posted OllyScript plugin. But that script will fail in this example.
In this example we have unpacked delphi program where import jumps where JMP DWORD[xxxxxxxx]. In some other apps like ASM compiled, or C++, you can find CALL DWORD[xxxxxxxx].
Greets goes to all BIW crew, especialy to detten for publishing my tutorials on biw site. See you in the next tutorial :)
Authored by:
Rumour on
Saturday, October 15 2005 @ 04:04 PM CEST
I tried to follow this Alex Protector tut. When HW breakpointing in the memory block with the stolen bytes, my HW BP on execution (at same place as the mem BP) was allways ignored and the code ran till showing the crackme. I then tried to place a HW BP on execution at another place in this memory block .... it gets allways ignored. Any idea why or how to avoid it ?
BTW, nice tut (so far). Unfortunately I couldn't finish it due to the above reason.
Authored by:
haggar on
Saturday, October 15 2005 @ 07:51 PM CEST
It can be done without hw bp, I checked it now.
- You placed bp at the end of VirtualAlloc, on last RETN 10 and you break there, right? So keep bp there and keep pressing Shift+F9 untill EAX holds value that is address of block where stolen code is. Did you do it? Wrote down that value, for example X.
- Now keep pressing Shift+F9 untill EAX change that value to some Y. I pressed Shift+F9 5 times, maybe it will not be the same for you.
- Then follow that X value in dump and place memory bp on access on first byte. Now press Shift+F9 once and you should break here:
Authored by:
haggar on
Sunday, October 16 2005 @ 02:51 PM CEST
First you need to run \"AlexProt I.txt\" which will fix obfuscation in first block. You must enter correct block address as input.
Then you need to run second script that will create new IAT. BUT, you need to change something in script so script can find IAT in your case! Script has this two lines inside:
findop code,#ff25????3a00#
This is searching for this opcodes:
00401084 -FF25 84073A00 JMP DWORD PTR DS:[3A0784]
Dou you see this hex bytes FF25 84073A00? That is equal to search signature #ff25????3a00#. In your case it will probably be different so you need to change a little. ????3a00 is a base address of block where is IAT placed in my computer = 3a0000. If this block is in your computer at 5D0000 for example, than you need to change search signatures to #ff25????5D00#. You got it? Then try. It would be good that you read readme.txt that comes with OllyScript plugin and learn how to write scripts. It is very easy and simple.
Btw, I was realy silly with OEP search. There is much easier way. You know that stolen code block and that last jump to false OEP JMP packed.004079DE. Since you know where false OEP is, you just can load target in olly, go to that false OEP in CPU window where will be only zeroes, place there hardware bp on execution and just run target. You will break at false OEP.
Excellent!!!