Unpacking asprotect (I used ElcomSoft Advanced eBook Processor v2.2 )
by NchantA [PGC] [EVC]
published by +Tsehp
Im afraid it started out as being a tutor for newbies, but I have a feeling they wont be able to follow some of the steps in this. I apologise, but feel free to blame alexy hehe.
PART I
Tools used :
- to numerous to mention … (just joking)
- softice
- icedump + iceload
- ImpREC ( I love it ) J (Tsehp : you can also use revirgin : tsehp.cjb.net)
- IDA / Windasm
- Fingers ( to type silly! )
Well well well. Elcomsoft, the bane of the average cracker. Every release is invariably protected by the newest available version of asprotect, and it also has some funky limits as well as a serial protection based on encryption (I think ;P), the serial doesn’t apply to this version as the eBook processor was a ‘demo’ version only and therefore unable to be registered. So I cracked it the old fashioned way. Patching ;). Now, to patch the program we first must unpack this annoying asprotect right? Strap your wigs on and ready your toenails here we go:
Asprotect.
For those of you that don’t know what this is, continue reading, as the way I unpack it is universal to many unpackers. For those of you that do know what asprotect is, then you probably know that it’s, in general, an utter prick. ;) (Hi alexy)
Now fire up our favourite tool (softice) and the best ever sister software (icedump)
Our goal is too unpack this program so it runs, so also load up iceload (get it from the icedump page) and load the aebpr.exe into it.
You will be sitting in a softice screen with invalid’s everywhere. Press F8 four or five times to get to the asprotect code. Notice the memory address
(like 0177:00514678 ). Your OEP will generally be inside the range 400000 (image base) and the memory address you will be sitting at so u can do this:
/tracex 400000 eip-8
This may take a while… another quicker way to do it with asprotect is to do a bpx getvolumeinformationa and then do your /tracex with the range of 400000 and the memory address u recorded earlier ;) (i.e 514678)
NOTE: If for any reason your tracex is interrupted by a ‘ret’ or a small amount of code, just trace over it and exit the small routine, then press up a few times to RESTART the tracex routine.
After a while u will get
to a weird piece of code kinda like this (if u don’t, and you end up at a PUSH
EBP or similar, then it must be an older version of asprotect, and u can simply
dump from there with /pedump 400000
eip-400000 c:\blah_un.exe)
NOTE: Before you do ANY /pedump with aspr it is in your best interest’s to do a /option p i0 to set the import rebuilding to none, because we will be doing that ourselves!
:00401000 EB10 jmp 00401012 ßßßßßßß U ARE HERE
…
:00401012 A1BFA44B00 mov eax, dword ptr [004BA4BF]
:00401017 C1E002 shl eax, 02
:0040101A A3C3A44B00 mov dword ptr [004BA4C3], eax
:0040101F 52 push edx
:00401020 6A00 push 00000000
* Reference To: KERNEL32.KERNEL32.dll, Ord:0000h
|
:00401022 E869800B00 Call 004B9090
:00401027 8BD0 mov edx, eax
:00401029 E85EA90A00 call 004AB98C
:0040102E 5A pop edx
:0040102F E8BCA80A00 call 004AB8F0
:00401034 E893A90A00 call 004AB9CC
:00401039 6A00 push 00000000
:0040103B E864BC0A00 call 004ACCA4
:00401040 59 pop ecx
:00401041 6868A44B00 push 004BA468
:00401046 6A00 push 00000000
* Reference To: KERNEL32.KERNEL32.dll, Ord:0000h
|
:00401048 E843800B00 Call 004B9090
:0040104D A3C7A44B00 mov dword ptr [004BA4C7], eax
:00401052 6A00 push 00000000
:00401054 E95B360B00 jmp 004B46B4
:00401059 E992BC0A00 jmp 004ACCF0
This is some initialisation code that aspr uses, don’t worry bout it, what u do is this: without tracing a single step more look down in softice (CTRL+DOWN) until you see the first jmp (i.e 401054), note where its jumping too, this is your OEP. Without tracing again work out the OEP RVA (i.e the OEP – IMAGE_BASE, which in this case is 400000 (if in doubt, use 400000)) so. 004B46B4 – 400000 = OEP RVA = B46B4.
Now do: “/pedump IMAGE_BASE OEP_RVA FILENAME”
Example:
/pedump 400000 B46B4
c:\blah_un.exe
done that? Good. Now you will have a nicely dumped executable with fucked up imports ;) now we load ImpREC (or RV as you prefer). Load the program if it isn’t running, and select it in the combobox at the top of the form. I generally use OEP = 1000 as my first go in ImpREC, if nothing is found then use your OEP RVA. Its dodgy but it works. Hit the ‘IAT AutoSeach’ button. Hmm size seems a little small. Hit ‘Get Import’. What? Only one thunk?? Aspr is being mean again! Ok see the ‘Size’ edit box put in 1000 and press ‘Get Import’ again wow, there they all are ;)
(Tsehp: in revirgin.Exe you just put 4b46b4 as OEP and click fetch IAT, then all is filled)
NOTE: Lucky for us import sections are generally rounded off into 0x1000 or 0x2000 byte sections you can of course work our the exact number, but why bother eh ;) if you get a lot of crap at the end of the import thunks, just reduce the size. And if you don’t have enough, enlarge it.
STOP HERE!
After writing this tutorial I was told my unpacked executables didn’t run on anyone else’s system. Luckily r!sc genius helped me out, and we found out that asprotect was being naughty again, making ImpREC give me the WRONG IAT RVA! So I am sorry but you will have to get the IAT RVA starting position manually. Heres how to do it if you don’t know how (thanks predator for this ;))
Load the program and set a breakpoint in softice on any api u want (createwindowexa or hmemcpy or whatever), make sure you can somehow get inside the programs internal code. Once you are in the code keep pressing F8 until you trace into a call and end up in a large table of jmps like this:
Jmp [405612]
Jmp [405616]
…
etc. hold CTRL+UP until you get to the top of the list of JMP’s and you will probably see a list of Jmp’s with actual Api names there (ADVAPI32!RegistryCalls probably), instead of numbers like the rest. Why does it do this? Its because asprotect is bypassing the IAT table and has calculated the API’s address’s and is jumping directly to the API. This is not what we want to happen! Now type ‘CODE ON’ and you should see the opcodes of each jump. Look at the topmost JMP [API name] it will be something like:
F9 25 03 02 01 00 jmp
[OpenRegKeyBLahwhatever]
reverse the last 4 bytes to form an address and this will be the the new IAT RVA to put into ImpREC. For example IAT RVA would be 00010203 from above. Try it!
Now. Lots of bad API’s press ‘Show Invalid’ and then ‘AutoTrace’ (if its not there, then back click on the highlighted API’s and select Trace Level 1).
(Tsehp: on revirgin , select on combo box show unresolved, then select the unresolved iat entries end right click “tracer” )
Press ‘Show Invalid’ yet again. It seems we have 2 invalid thunks to contend with. We will deal with the USER32.dll one first because it’s a little trick I have only seen in elcomsoft products. Look under the USER32.dll thunk and find the invalid API. There is probably 3 highlighted but the middle one is the wrong one. Looks like this:
000F6DB0 USER32.dll 008E DestroyWindow
000F6DB4 KERNEL32.dll 0123 FindResourceA
000F6DB8 USER32.dll 0093 DispatchMessageA
that’s a bit silly! Well what happened here, is the program
is being redirected to a simple call, which is in turn calling a few kernel
calls simply to confuse us ;) no problems thanks to ImpREC!!!!
firstly back click on the kernel32.dll function ‘FindResourceA’ and select invalidate. Select it again.
hold SHIFT
while holding shift back-click on the invalidated function and select Trace Level 1. A message box will popup with the FindResource API. Look in the caption of the box to see the DLL its from, we want a USER32.dll so that’s not it. Keep holding shift and click OK, until you see USER32.dll in the caption, the API should be ‘DialogBoxIndirectParamA’, let go of shift and press OK. Now its fixed!!!
Phew, nearly there guys, don’t stress ;D
Last but not least the kernel imports. There is an easy way and a hard way for doing this, I will tell you both.
Easy Way
Select ‘Show Invalid’ and you will be sitting here:
0017D3D8 KERNEL32.dll 0133 FreeLibrary
0017D3DC ? 0000 012BC87C ß here
0017D3E0 KERNEL32.dll 0138 GetACP
0017D3E4 KERNEL32.dll 013E GetCPInfo
0017D3E8 ? 0000 012BC86C
0017D3EC KERNEL32.dll 0158 GetCurrentDirectoryA
0017D3F0 ? 0000 012BC864
0017D3F4 KERNEL32.dll 015C GetCurrentThread
The names of the missing functions go as follow:
FreeResource
GetCommandLineA
GetCurrentProcess
ß
NOTE: may not be there.
GetCurrentProcessID
GetVersion
LockResource
Ususally in that order. Simply look at the API above and underneath and slot in the one that fits alphabetically. Believe It or not this works. When your done, click ‘Show Invalid’ for the last time, and nothing shows. Everything is there fine and dandy.
Hard Way
You will see a list of bad apis. Their RVAs and where the bad api actually points to. Now. Write down the first PTR that you see and remember it. Go back to your program and get to its code somehow (set a bpx createwindowex or something. ;P) type ‘u PTR’ where PTR is the pointer you wrote down before. You will see the code that executes when that API is called. Keep doing that until you see something like this:
push ebp
mov ebp, esp
pop ebp
ret
or something close to it. These API’s you will fix as ‘LockResource’ and ‘FreeResource’. It doesnt matter which is which. You should be left with only 3 or 4 API’s. write down their PTR’s. now close the program. Load it in iceload and set a ‘bpx getversionexa’ and then ‘F5’. You should break on this code:
CALL KERNEL32!GetModuleHandleA
MOV [look here],EAX
CALL KERNEL32!GetVersion
MOV [look here],EAX
PUSH 00F635E4
CALL
KERNEL32!GetVersionExA
CALL KERNEL32!GetCurrentProcess
MOV
[maybe_not_used],EAX
CALL KERNEL32!GetCurrentProcessId
MOV
[look_here],EAX
CALL KERNEL32!GetCommandLineA
MOV [look_here],EAX
once there, note the address’s in memory where these different api return values are being pushed and compare them with yours you wrote down earlier. You should be able to figure it out from here, but if for any reason the values are not the same , bpmd on the address’ that the values are being pushed into and you may find a small routine which is moving the values somewhere else ;)
To Finish
Now to ‘Fix Dump’. Select the file you dumped earlier, you should have copied it to the programs dir already. Now the program runs! Or not?
A little box pops up saying API no found? Wtf???
Hah
another aspr+elcomsoft trick. bpx messageboxa and make the jump above it always jump
with a hardcoded patch of EB.
Whew. Aspr is a prick. No doubt about it, poor brave alexy gets knocked down again. Elcomsoft make some pretty useful products so you should buy them.
Well. This tutor originally intended to be about cracking the poor program, but I got sidetracked and it turned into an unpacking asprotect one ;) I know there are a lot of crackers out there that think I shouldn’t be making this tutorial, so I have left it up to someone else to wether it gets published or not. Any valid objections shall be noted, but I truly think the cracking community will benefit from this tutor. Anyway, im kinda bored with the current aspr, and once I release this alexy will kindly churn up a new version that this tutor will be useless against so go live a little. When I can be buggered I will write the tutor on how I actually cracked the example program.
Look out for Part II of this tiny series!
Greetz: nroc *G*, doufas, Warezpup, _y, r!sc, nu, MackT, splaj+, Kilby, death, webby, bl00dbath, mindphaze, predator, hackwizz, DAEMON, SV, tsehp+, KW, rizz, everyone in #cracking4newbies + #pgc-force on eFNET
Group Greetz: UCF PC EVC CORE CLS UG um. Ive gone blank again ;/
NchantA
p.s if you have any problems with this tutorial, elcomsoft, just email me at nchanta@nchanta.com and I wont release part II.
p.p.s thanks to nroc for helpfully forcing my face into the fact that I used windasm in my tutorial but said I rathered IDA for cracking. The truth is hes a bit of a plonker :D haha, but he was right. I used windasm for the tutorial because its faster and I didn’t save my IDA listing.