Unpacking: a generic approach, including IT rebuilding.
Accessible for newbie and more advanced crackers

Tutorial written by Predator [PC/pGC]

published by +Tsehp March 2001

Aim: learn how to unpack almost any program, any packer.

INTRO

Welp, it's been quite some time since I wrote my last tutorial.
I've written 3 tutorials now including this one, funny enough all 3 were explaining an ASProtect
packed target. It's quite interesting IMO :-)

Keep in mind that this tutorial won't tell you how to crack this program, it will show you instead
how to unpack it and this method is quite "generic" for any packed application.

So, the idea of this tutorial is that by using it, you'll be able to unpack many more programs -
using many different kinds of packers.

I'm NOT saying that if you have the knowledge explained you can just unpack everything.
This means you'll have to use your brain ;-)

 

TARGET INFO

Cool Mouse v3.4 - http://www.shelltoys.com/files/cmset.exe - 450kb
It's a program that uses your middle-mousebutton to do funny stuff with open windows, like
shadowing them. The protection is total crap (besides that it's packed with ASProtect).

 

INDEX

1. Dumping the app, fixing the sections (tools: IceDump & PEditor)
2. Adding a section for the newly created IT (tool: PEditor, which is the name of a PE Editor ;)
3. Create the new IT (tool: Revirgin)
4. Combine the dump and IT (tool: HexWorkshop)
5. Update entrypoint, update IT rva and size (tool: PEditor)
6. Run and find out: 1 last change needed (tool: SoftICE).

Tools urls: http://protools.cjb.net/ and http://tsehp.cjb.net/ for Revirgin.

 

1. DUMPING THE APP, FIXING THE SECTIONS

We'll dump the app using IceDump, and realign the sections using PEditor. This is
the best way, IMHO. First we've got to find the OEP (Original program EntryPoint).
How? Well, you could use IceDump's /TRACEX command for this. Second way would be
tracing the whole damn thing. Third way, which we will use, is bpx on GetVersion and
use some Zen feeling (or just a combination of logical thinking/guessing, haha).

bpx GetVersion in softice, run CMOUSE.EXE, the 3rd occurence of GetVersion is the one
we are interested in (inside CMOUSE itself). Scroll up a little, and you'll see something
like "PUSH EBP" followed by "MOV EBP, ESP". The RVA of PUSH EBP would be our OEP.
It's 876B (40876B in softice).

Now, we have to make the program loop so it can't hurt us and then we dump.
Type BPM 40876B X. Re-run CMOUSE.EXE and you'll land at the OEP. Type: A EIP and enter
"JMP EIP". You'll have to remember the 2 bytes you've just overwritten (55h,8Bh). Now
dump: /DUMP 400000 51000 c:/temp/dump.exe. Why 51000? If you use a PE editor (PEditor or
ProcDump for example) on CMOUSE.EXE you'll encounter an ImageSize of 51000h.

Ok, we've got a sweet dump now. First we'll fix the sections using PEditor. We use this tool because
it works fast for our aims. PEditor is -not- Procdump's build-in PE Editor btw.
Load dump.exe in PEditor and go to sections. Right-click on the first section (which has no name)
and choose the sweet option DUMPFIXER. Do so for every section please ;)

Don't close PEditor yet.

For those interested in IceDump's tracex command, it works like this. You just 'guess' where the OEP
could be located, for example somewhere between VA 401000 and 500000. Now be sure you are
currently debugging the process you want to unpack and type: /TraceX 401000 500000 <enter>. Now,
go make yourself some coffee, because this could very well take a while. Now, as soon as softice breaks,
it means that you are now looking at the first instruction executed between 401000 and 500000 area.
You could assume that this is the OEP.

 

2. ADDING A SECTION FOR THE FUTURE NEW IMPORT TABLE (IT)

Still in PEditor, we'll create a new section for our (not yet created) new Import Table
(IT). Do so by rightclicking on any section and choose "add a section" - give it a name,
and rightclick on the new section and choose edit. Change both the Virtual Size and Raw Size
to about 4000 (this should be more than enough). Remember the RVA of the section,
it was 51000 for me. That's all, exit PEditor please ;)

 

3. CREATE THE NEW IT

Fire up Revirgin and then fire up CMOUSE.EXE. Now click on the CMOUSE.EXE process in Revirgin
and click on OK when you get the sweet errormessage ;)
Revirgin needs an IAT start + Size so we'll have to retreive those values somewhere.
Launch your hexeditor and edit your DUMP.EXE. Search for the following 2 bytes: FFh,25h
Look at the address it jumps to on the first occurence (or any other occurence). For example:
JMP DWORD PTR [40D2AC].
Now go to offset D2AC (offset and RVA is the same now). Scroll up a little and see. The IAT
starts at 40D000.
Now for the length; scroll down untill you see 9x '00' bytes. I'm not sure if 9 is a magic
number with this shit but it seems so ;) Furthermore after those 9x00 you'll see stuff that
doesn't look like the above anymore. IAT start: RVA D000, end: D2AE. D2AE - D000 = 2AE.
IAT length: 2AE.
So, let's enter these values in Revirgin. Press the IAT Resolver button. Now press
Resolve Again.
Only 2 entries remain unresolved. We can fix last entry, which is not resolved yet,
like this: rightclick on it - choose Tracer (be sure you copied tracer.dll+thread.dll to
your windows\system directory). After tracing, click on Resolve Again. Woah, there it is :)
Now, the very last entry. I've tried reconstructing this one with Revirgin but had no luck.
How to fix this, then? Well, quite easy. Look at the address: B0C218 for me. Load CMOUSE.EXE
and for example do bpx getversion again (wait for the 3rd occurence so you are inside
CMOUSE). Now type "U B0C218". You'll see a call to GetProcAddress a few lines below.
Go back to revirgin, rightclick on the entry and choose Edit. Change the "Module" to
KERNEL32.DLL (while GetProcAddress is an API located inside KERNEL32.DLL - look it up
in your API reference if you want) and change the Name to GetProcAddress. Now, press
Resolve Again. Woah, that's it. Everything is there now. You can save this as text with
Save Resolved, if you want. Well now, let's create our IT.bin then! Remember 51000? It's
the RVA of the beginning of our newly created section. Enter 51000 in the "IT RVA" field
and click on IAT Generator. Save the file, I used for filename "IT.BIN". Please remember
the value of IT Length inside Revirgin!

Before I forget, you might ask yourself the question - why rebuild the Import Table. And what the fuck
is it anyway? Well it's a part in the executable that leads to the addresses of the API's the program uses;
for example GetWindowTextA. We rebuild it now, while ASProtect (and other packers, too) fucks it
up which causes the program to crash if we don't fix it.

Secondly, it could happen you find an IAT that ends with a lot of 00-bytes (more than 9) but right after
it looks like the IAT continues! Well, not a biggie problem, it's just an IAT with big holes in it. It can
happen. Try scrolling down untill you see so many 00-bytes you are absolutely sure it's the end of the IAT.

4. COMBINE DUMP.EXE & IT.BIN

Well, this is quite easy and quite fun ;) Dunno why.. it just is ;)
Run HexWorkshop (or another hexeditor that supports copy/paste in a sweet way) and open
DUMP.EXE and IT.BIN. Completely select all bytes in IT.BIN and copy it into memory. Now
go to the very end of DUMP.EXE (cursor -after- the -last- byte) - you'll see the offset:
51000 ;-) Now paste.. b00m. Now save. b0000m. ;)

 

5. FIX THE PE, MAKE IT RUN

Now run PEditor again and open DUMP.EXE. First fix the entrypoint, remember? OEP=876B.
Now click on "directory" button and change the IT RVA to 51000 and the IT SIZE to E0
(remember, E0 was calculated by and shown in Revirgin as IT Length). Well, that's about it.
The unpacked file DUMP.EXE should run in the same way as the packed file CMOUSE.EXE now.

So, run it!

If, when following these steps on a packed target, you get an error message when running the unpacked
app saying "Not Enough Memory" then increase the ImageSize of the PE using PEditor. Increase it by
at least the size of the new section containing the new IT. ;-) Makes sense, doesn't it?

 

6. ONE LAST CHANGE NEEDED

Well, by running it you'll find out it crashes ;) How is this possible? Well, let's use
SoftICE to check this out. Inside the ice type FAULTS ON. Now run DUMP.EXE. Softice will
"break" at VA: 40821C. So uhm, right... WTF ;) Well, what if we just NOP this line. It's
2 bytes which means 2 nops. Type A 40821C and then: NOP <enter> NOP <enter>. Exit the ice
and woah..... target runs ;) Now run your hexeditor for the last time, go to VA 40821C
and change the 2 bytes overthere into 2x 90h.

( Well now, why is this nescessary? It seems that ASProtect in this case is being checked for by the
target - if ASProtect isn't in memory (like now) the program crashes. That's all. )

That's it. DUMP.EXE runs, exactly like CMOUSE.EXE - the difference is that DUMP.EXE is
UNPACKED which means you can have a party and invite all your friends and drink a lot of
beer... or it just means you can disassemble/patch it now....

 

SHORT SUMMARY

To unpack a packed application, in short, proceed like this. For the "how to" you should read the
above ofcourse. Start by finding the OEP. Dump the application. Realign the sections. Create a new
Import Table if this is nescessary (you'll find out if the app doesn't run, most probably the IT is
screwed up). Now merge the new IT with the dump you made. Finish by editing in the new OEP and
new IT + IT size. Now, close your eyes and run the file - hope it works ;) If it doesn't, just think for
a while what could be the problem. Like for example in section 6 of this tutorial

 

CONCLUSION

ASProtect's real protection is in fact the "hey let's fuck up the Import Table" part, it's becoming a
popular way of protecting files which are packed. With a tool like Revirgin it's not a real problem
anymore to get around -it doesn't just solve everything for you though.

Oh and btw, what if you can't find the RVA of the IAT in the way I just explained. This could happen
for example with an app I saw that calls a VA that you can't reach using your hexeditor.

Eg: call dword ptr [0D0193B0]. This VA doesn't exist on disk right now. Therefor you can't look it up
with your hexeditor. Solution: run the packed app and bpx on any api you can think of, just hope
SoftICE breaks ;) Now remember the VA of the call ApiName. Dump the process fully and go to the
VA in your hexeditor. Now proceed like you'd do when searching for FF,25 etc.
The only difference is that you should hexedit the dumped file instead of the packed file - and make
sure you got a "valid" FF,25 occurence.

Oh and btw (2): the unpacked exe will not run on every computer, as +Tsehp writes
in his readme.doc of Revirgin. It will run on most win9x computers though.
You can also see in the readme that this will be fixed in a future version hopefully.

Oh ;) and uhm ;) you can try packing the app after you applied your patches with UPX. Use like:
UPX -9 -f filename.exe. The -9 is for best compression ratio, the -f is for FORCE. ;)

Last but not least, always keep your tools UP2DATE.

 

GREETINGS

All PC and all pGC members.
HackWizz for being a good friend.
CoDe_InSiDe (for the FF25->IAT trick)
Spectre because if I don't greet him he'll be pissed;)
+Tsehp and +Splaj (for Revirgin and Info)
And everyone else.. I hope noone will feel left out. All who know me are hereby greeted ;)

 

CONTACT

Feel free to contact me for anything you can think of. I don't take requests though and I will not
send you files. Visit my page http://rotaderp.cjb.net/ please and go to 'about me' for a link to my email
address.

-- Predator [PC/pGC]
March 24, 2001

 


-- MY RESOLVED.TXT - produced by Revirgin --

cmouse.exe
00E0
index IAT_address value hint module function 
--- -------- -------- ---- -------- -------- 
0 0000D000 BFE81644 00D8 ADVAPI32.dll RegCloseKey
1 0000D004 BFE81376 00E1 ADVAPI32.dll RegDeleteValueA
2 0000D008 BFE81AF2 00F2 ADVAPI32.dll RegQueryInfoKeyA
3 0000D00C BFE813B7 00E7 ADVAPI32.dll RegEnumValueA
4 0000D010 BFE815EA 0103 ADVAPI32.dll RegSetValueExA
5 0000D014 BFE8182B 00E4 ADVAPI32.dll RegEnumKeyExA
6 0000D018 BFE8167D 00DC ADVAPI32.dll RegCreateKeyExA
7 0000D01C BFE81787 00DF ADVAPI32.dll RegDeleteKeyA
8 0000D020 BFE81534 00F7 ADVAPI32.dll RegQueryValueExA
9 0000D028 00461890 000B CMHOOK.dll ActivateRightRoll
10 0000D02C 00461010 0002 CMHOOK.dll InstallMouseHook
11 0000D030 00461830 0005 CMHOOK.dll ActivateIt
12 0000D034 00461EE0 000C CMHOOK.dll TellHookCustWin
13 0000D038 00461870 0007 CMHOOK.dll ActivateScroll
14 0000D03C 00461850 0008 CMHOOK.dll ActivateCaptionFeature
15 0000D040 00461880 000A CMHOOK.dll ActivateRightTray
16 0000D044 00461860 0009 CMHOOK.dll ActivateBodyFeature
17 0000D048 00461790 0003 CMHOOK.dll UninstallMouseHook
18 0000D050 BFEB1BF4 0046 COMCTL32.dll ImageList_ReplaceIcon
19 0000D054 BFE983FE 0011 COMCTL32.dll InitCommonControls
20 0000D058 BFEB1877 002D COMCTL32.dll ImageList_Create
21 0000D05C BFEEFC75 0010 COMCTL32.dll CreateUpDownControl
22 0000D064 BFF223C3 00AA GDI32.dll CreateSolidBrush
23 0000D068 BFF2289E 018B GDI32.dll SetMapMode
24 0000D06C BFF2148D 011A GDI32.dll GetObjectA
25 0000D070 BFF22621 0095 GDI32.dll CreateFontA
26 0000D074 BFF2507B 00A5 GDI32.dll CreateRectRgn
27 0000D078 BFF224D8 0089 GDI32.dll CreateCompatibleDC
28 0000D07C BFF247BF 0112 GDI32.dll GetMapMode
29 0000D080 BFF2254C 01AC GDI32.dll TextOutA
30 0000D084 BFF22842 00B0 GDI32.dll DeleteObject
31 0000D088 BFF22D2D 0088 GDI32.dll CreateCompatibleBitmap
32 0000D08C BFF22293 0072 GDI32.dll BitBlt
33 0000D090 BFF2283A 00AD GDI32.dll DeleteDC
34 0000D094 BFF224FE 0173 GDI32.dll SelectObject
35 0000D09C 10001720 0002 KBDHOOK.dll SendKeys
36 0000D0A4 BFF77039 027E KERNEL32.dll ReadFile
37 0000D0A8 BFF776D0 0229 KERNEL32.dll LoadLibraryA
38 0000D0AC BFF77ADB 00B9 KERNEL32.dll CreateFileA
39 0000D0B0 BFF77D63 0226 KERNEL32.dll LCMapStringA
40 0000D0B4 BFF757B4 02E0 KERNEL32.dll SetStdHandle
41 0000D0B8 BFF9100F 0196 KERNEL32.dll GetOEMCP
42 0000D0BC BFF9C947 0128 KERNEL32.dll FlushFileBuffers
43 0000D0C0 BFF77DCE 013E KERNEL32.dll GetCPInfo
44 0000D0C4 BFFA94BE 00B7 KERNEL32.dll CreateEventW
45 0000D0C8 BFF8E150 0138 KERNEL32.dll GetACP
46 0000D0CC BFF77D81 0252 KERNEL32.dll MultiByteToWideChar
47 0000D0D0 BFF7713B 02CF KERNEL32.dll SetFilePointer
48 0000D0D4 BFF77D3D 01BC KERNEL32.dll GetStringTypeA
49 0000D0D8 BFF88388 0291 KERNEL32.dll RtlUnwind
50 0000D0DC BFF75881 0179 KERNEL32.dll GetFileType
51 0000D0E0 BFF76FD1 0336 KERNEL32.dll WriteFile
52 0000D0E4 BFF9C63C 02D2 KERNEL32.dll SetHandleCount
53 0000D0E8 BFFA9464 00A1 KERNEL32.dll CloseProfileUserMapping
54 0000D0EC BFF75770 01BB KERNEL32.dll GetStdHandle
55 0000D0F0 BFF77D9F 032B KERNEL32.dll WideCharToMultiByte
56 0000D0F4 BFFA946D 0076 KERNEL32.dll AddAtomW
57 0000D0F8 BFF8ABBC 016A KERNEL32.dll GetEnvironmentStrings
58 0000D0FC BFF9DB34 0310 KERNEL32.dll UnhandledExceptionFilter
59 0000D100 BFF96347 015A KERNEL32.dll GetCurrentProcess
60 0000D104 BFF9600D 0130 KERNEL32.dll FreeEnvironmentStringsA
61 0000D108 BFF7E06D 00A0 KERNEL32.dll CloseHandle
62 0000D10C BFF8516B 0181 KERNEL32.dll GetLastError
63 0000D110 BFF95DD3 02FD KERNEL32.dll TerminateProcess
64 0000D114 BFF7FFF0 0319 KERNEL32.dll VirtualAlloc
65 0000D118 BFF841CB 031B KERNEL32.dll VirtualFree
66 0000D11C BFF76EA3 0200 KERNEL32.dll HeapDestroy
67 0000D120 BFF8D4F8 00F8 KERNEL32.dll ExitProcess
68 0000D124 BFF88BF2 01FF KERNEL32.dll HeapCreate
69 0000D128 BFF8C5DA 0149 KERNEL32.dll GetCommandLineA
70 0000D12C BFF777AD 01B9 KERNEL32.dll GetStartupInfoA
71 0000D130 BFF92F1B 01DC KERNEL32.dll GetVersion
72 0000D134 BFF76EC4 01FD KERNEL32.dll HeapAlloc
73 0000D138 BFF76F10 0201 KERNEL32.dll HeapFree
74 0000D13C BFF76EE5 0203 KERNEL32.dll HeapReAlloc
75 0000D140 BFF76DA8 01A3 KERNEL32.dll GetProcAddress
76 0000D144 BFF77716 018D KERNEL32.dll GetModuleHandleA
77 0000D148 BFF813EC 015D KERNEL32.dll GetCurrentThreadId
78 0000D14C BFF776F7 018B KERNEL32.dll GetModuleFileNameA
79 0000D150 BFF773A9 035F KERNEL32.dll lstrlen
80 0000D154 BFF772BE 0356 KERNEL32.dll lstrcmpi
81 0000D158 BFFA0DA8 032C KERNEL32.dll WinExec
82 0000D15C BFF9C7F8 02C6 KERNEL32.dll SetEndOfFile
83 0000D160 BFFA94E2 0080 KERNEL32.dll BackupSeek
84 0000D168 7FD07109 0109 SHELL32.dll SHBrowseForFolder
85 0000D16C 7FD16AFF 0142 SHELL32.dll ShellExecuteA
86 0000D170 7FCB3BC4 011F SHELL32.dll SHGetPathFromIDList
87 0000D174 7FD18BE2 0148 SHELL32.dll Shell_NotifyIcon
88 0000D17C BFF55072 01EE USER32.dll ScreenToClient
89 0000D180 BFF54EFC 00FC USER32.dll GetDlgItem
90 0000D184 BFF51800 00E8 USER32.dll GetClassNameA
91 0000D188 BFF54FC5 00EB USER32.dll GetClientRect
92 0000D18C BFF51EEE 00F6 USER32.dll GetCursorPos
93 0000D190 BFF51BAD 018C USER32.dll KillTimer
94 0000D194 BFF5248D 0200 USER32.dll SetCapture
95 0000D198 BFF5156B 0239 USER32.dll SetWindowPos
96 0000D19C BFF524BF 01D1 USER32.dll PostQuitMessage
97 0000D1A0 BFF5252B 0159 USER32.dll GetWindowThreadProcessId
98 0000D1A4 BFF52FD5 0091 USER32.dll DialogBoxParamA
99 0000D1A8 BFF524BB 0212 USER32.dll SetForegroundWindow
100 0000D1AC BFF526FC 01E7 USER32.dll ReleaseCapture
101 0000D1B0 BFF55C71 005B USER32.dll CreateWindowExA
102 0000D1B4 BFF55171 018A USER32.dll IsWindowVisible
103 0000D1B8 BFF51C9F 0259 USER32.dll TrackPopupMenuEx
104 0000D1BC BFF524F7 008D USER32.dll DestroyMenu
105 0000D1C0 BFF52471 012F USER32.dll GetParent
106 0000D1C4 BFF525C5 000A USER32.dll AttachThreadInput
107 0000D1C8 BFF55708 01CF USER32.dll PostMessageA
108 0000D1CC BFF544C1 0258 USER32.dll TrackPopupMenu
109 0000D1D0 BFF52098 0246 USER32.dll ShowWindow
110 0000D1D4 BFF524E7 026A USER32.dll UpdateWindow
111 0000D1D8 BFF559F9 0195 USER32.dll LoadIconA
112 0000D1DC BFF54362 01D8 USER32.dll RegisterClassA
113 0000D1E0 BFF55918 00D3 USER32.dll FindWindowA
114 0000D1E4 BFF5573D 0123 USER32.dll GetMessageA
115 0000D1E8 BFF55769 025E USER32.dll TranslateMessage
116 0000D1EC BFF54733 0093 USER32.dll DispatchMessageA
117 0000D1F0 BFF51BA9 00B7 USER32.dll EndDialog
118 0000D1F4 BFF5235E 0219 USER32.dll SetMenuDefaultItem
119 0000D1F8 BFF551F5 0102 USER32.dll GetForegroundWindow
120 0000D1FC BFF51804 0155 USER32.dll GetWindowTextA
121 0000D200 BFF52356 023A USER32.dll SetWindowRgn
122 0000D204 BFF55674 00E6 USER32.dll GetClassLongA
123 0000D208 BFF5178C 0039 USER32.dll CheckRadioButton
124 0000D20C BFF5569E 0203 USER32.dll SetClassLongA
125 0000D210 BFF52D8A 0208 USER32.dll SetCursor
126 0000D214 BFF51990 0182 USER32.dll IsDlgButtonChecked
127 0000D218 BFF520A4 00B5 USER32.dll EnableWindow
128 0000D21C BFF51BD4 023B USER32.dll SetWindowTextA
129 0000D220 BFF55A0F 0191 USER32.dll LoadCursorA
130 0000D224 BFF5325A 0269 USER32.dll UnregisterHotKey
131 0000D228 BFF5176D 0036 USER32.dll CheckDlgButton
132 0000D22C BFF51269 024D USER32.dll SystemParametersInfoA
133 0000D230 BFF55591 0285 USER32.dll wsprintfA
134 0000D234 BFF5171D 020E USER32.dll SetDlgItemTextA
135 0000D238 BFF512DE 0197 USER32.dll LoadImageA
136 0000D23C BFF54C52 013C USER32.dll GetSysColor
137 0000D240 BFF55A38 018F USER32.dll LoadBitmapA
138 0000D244 BFF5216A 00D9 USER32.dll FrameRect
139 0000D248 BFF51E88 00A8 USER32.dll DrawIconEx
140 0000D24C BFF51AE0 00A3 USER32.dll DrawEdge
141 0000D250 BFF511C4 027C USER32.dll WinHelpA
142 0000D254 BFF521BC 005A USER32.dll CreatePopupMenu
143 0000D258 BFF54460 0007 USER32.dll AppendMenuA
144 0000D25C BFF556DE 00CE USER32.dll EnumWindows
145 0000D260 BFF52DF4 0038 USER32.dll CheckMenuRadioItem
146 0000D264 BFF551B1 00F9 USER32.dll GetDesktopWindow
147 0000D268 BFF515D1 01B9 USER32.dll MoveWindow
148 0000D26C BFF51B3F 014A USER32.dll GetWindow
149 0000D270 BFF54F53 0153 USER32.dll GetWindowRect
150 0000D274 BFF55836 01F7 USER32.dll SendMessageA
151 0000D278 BFF52491 0272 USER32.dll VkKeyScanA
152 0000D27C BFF524CF 008E USER32.dll DestroyWindow
153 0000D280 BFF552F6 013F USER32.dll GetSystemMetrics
154 0000D284 BFF5322F 01E0 USER32.dll RegisterHotKey
155 0000D288 BFF5308E 022F USER32.dll SetTimer
156 0000D28C BFF555A7 014E USER32.dll GetWindowLongA
157 0000D290 BFF5412E 01AD USER32.dll MessageBoxA
158 0000D294 BFF52FA0 0051 USER32.dll CreateDialogParamA
159 0000D298 BFF55BCD 0085 USER32.dll DefWindowProcA
160 0000D29C BFF5564D 0236 USER32.dll SetWindowLongA
161 0000D2A0 BFF51670 00D4 USER32.dll FindWindowExA
162 0000D2A4 BFF524EF 00DE USER32.dll GetAsyncKeyState
163 0000D2AC 7FE16112 006E comdlg32.dll GetOpenFileNameA


The End.