...Explanation Continued...
Rebuilding / Resolvign the IAT:
There are 11 unresolved entries with RV. The 5 ones labelled to_Resolve can be Traced with EnableTrace/Trace. The trace function seems to actually work with this version! The API address should resolve, but the name doesn't. I use Exescope to match up the addresses with the names, then edit in the dll name and api name. If you select ResolveAgain the Hints column should update correctly.
These 5 entries are usually duplicate GetProcAddress and GetModuleHandleA. This used to be the extent of Asprotect tricks, now you have to deal with the other ones on the other 6 IAT entries.
20 0010D208 011FC468 0000 ?????? to_Resolve
21 0010D20C 011FC818 0000 ?????? to_Resolve
25 0010D21C 011FC86C 0000 ?????? ??????
63 0010D2C4 011FC818 0000 ?????? to_Resolve
105 0010D374 011FC874 0000 ?????? ??????
122 0010D3B8 011FC834 0000 ?????? ??????
130 0010D3D8 011FC468 0000 ?????? to_Resolve
132 0010D3E0 011FC818 0000 ?????? to_Resolve
147 0010D41C 011FC864 0000 ?????? ??????
148 0010D420 011FC85C 0000 ?????? ??????
150 0010D428 011FC87C 0000 ?????? ??????
Should be:
20 0010D208 BFF76DA8 01A3 KERNEL32.dll GetProcAddress
21 0010D20C BFF77716 018D KERNEL32.dll GetModuleHandleA
25 0010D21C BFF8C5DA 0149 KERNEL32.dll GetCommandLineA
63 0010D2C4 BFF77716 018D KERNEL32.dll GetModuleHandleA
105 0010D374 BFF92F1B 01DC KERNEL32.dll GetVersion
122 0010D3B8 BFF92F1B 01DC KERNEL32.dll GetVersion
130 0010D3D8 BFF76DA8 01A3 KERNEL32.dll GetProcAddress
132 0010D3E0 BFF77716 018D KERNEL32.dll GetModuleHandleA
147 0010D41C BFF84948 015B KERNEL32.dll GetCurrentProcessId
148 0010D420 BFF96347 015A KERNEL32.dll GetCurrentProcess
150 0010D428 BFF92F1B 01DC KERNEL32.dll GetVersion
--------------------------------------
There's part of the unpacking code that has this routine:
0167:011FC7D8 6A00 PUSH 00
0167:011FC7DA E82D7CFFFF CALL KERNEL32!GetModuleHandleA
0167:011FC7DF A3D4352001 MOV [012035D4],EAX
0167:011FC7E4 E83B7CFFFF CALL KERNEL32!GetVersion
0167:011FC7E9 A3D8352001 MOV [012035D8],EAX
0167:011FC7EE 68E4352001 PUSH 012035E4
0167:011FC7F3 E8347CFFFF CALL KERNEL32!GetVersionExA
0167:011FC7F8 E8DF7BFFFF CALL KERNEL32!GetCurrentProcess
0167:011FC7FD A3DC352001 MOV [012035DC],EAX
0167:011FC802 E8DD7BFFFF CALL KERNEL32!GetCurrentProcessId
0167:011FC807 A3E0352001 MOV [012035E0],EAX
0167:011FC80C E8C37BFFFF CALL KERNEL32!GetCommandLineA
0167:011FC811 A378362001 MOV [01203678],EAX
0167:011FC816 C3 RET
The values returned from each of these calls are stored in variables that the program accesses later on after it's unpacked, rather than making the calls directly. There's a few ways you could approach the next problem.
You could trace in packed and unpacked code to find where the call to the variable is made and change it directly to a Call to the api, opcode bytes are preserved.
Or write yourself the return value in unpacked code somewhere and change the call address. You might have to do this if the app is really tricky and runs some code that is *only* in unpacking code, you'd need to duplicate the code.
I've learned that the easiest way is to access the memory of the original proggy and unassemble the redirected address pointed to in the IAT. Then decide what API name and address you want to set each unresolved IAT entry to and edit it into Revirgin and then update the .bin file. I set a break on some early api like GetStartupInfoA so it breaks in unpacked code and then unassemble each address.
Take the 1st example:
25 0010D21C 011FC86C 0000 ?????? ??????
:u 11FC86C
mov eax,[1203678]
ret
[1203678] = 8171AD30 ; return value from GetCommandLineA
That's it for the redirected code that's there. Knowing this you can go back to Revirgin and edit in the name and address for this api.
2nd example:
105 0010D374 011FC874 0000 ?????? ??????
:u 11FC874
push ebp
mov ebp, esp
pop ebp
ret 4
This is another new Asprotect twist, a short piece of garbage code made only to confuse Revirgin et al. What I do is replace the api with something that pushes no parameters, such as GetVersion. Or you could just nop out the call in the unpacked code. If I remember correctly, ALL of above 6 unresolved entries can be replaced with a simple ret. I think in most cases the api return value is never used in any important code, this is just an Asprotect routine that comes up all the time now.
There is another one that's kind of interesting. FindResourceA, Load/FreeResource, are also other unresolved apis that come up sometimes. These caused some problems with Revirgin because FindResourceA is a Kernel32 function that was grouped with the User32 calls. The rebuilt file wouldn't even load with this one.
Once you've edited in all the missing api's, create a new .bin file ready for pasting. There's an auto-fix feature in RV, but I've never used it, I like to do everything manually so I know exactly what is going on. Uncheck the Autofix Sections feature and set the IT RVA to the end of the file (170000), then click IAT Generator and create a .bin file ready to be pasted into your file at 170000.
Then use PEditor to add a section (I call mine .kayaker of course

, and manually insert enough bytes to the end of your dumped file to create a section large enough to hold the .bin file. (I used 3000 filled with 0's). Then just paste it in.
You still need to fix up the pointer to the IAT table and its size in the PE header. This is at offset PE+80
00000180 0000 1700 7C01 0000 ....|...
which points to RVA 170000 and size 17C. (The size isn't really critical). Notice why I like doing raw dumps to work with rather that using Procdump or whatever. WYSIWYG when it comes to raw and virtual addresses, makes rebuilding the file so much easier. You can always repack the file with Asprotect if you want
Now if you're really lucky the proggy should run as is. In many cases however you may still have some work to do, this depends on what the programmer has implemented. There may be crippled functions and there may be a nag. There may be something else happening that causes a crash which you need to ferret out. Asprotect has options to be set as a time trial and/or requiring a keyfile. Or the programmer may have used his own protection routine.
There's 2 interesting things that happens when you skin Asprotect alive like this (I've used the phrase Like peeling a banana). If it's set as a time trial, the #days you have left at the time you dump it will be hardcoded into the dumped file. I've dumped at 1 day and 30 days left in an app and was told so by the nag box. Then I compared the 2 files and saw where that was stored. (Just don't change it to 00)
The other thing is that the registry, where the CLSID value is stored, is no longer read. This was all done in Asprotect code and this is where is checks your days left/key code. You can set a bp on RegQueryValueExA and break in unpacking code and watch it happen.
To prove that Asprotect code is no longer used, try deleting those sections at the end of the file and rebuild the PE header to reflect this. You can clean out a lot of the crap and make the file smaller this way. You need to make sure your IAT is referenced to the correct address of course.