MoleBoxPro 2.2.5 - manually unpacking

Monday, October 17 2005 @ 11:58 PM CEST

Contributed by: haggar

Level : beginner

========================
MoleBoxPro 2.2.5 - manually unpacking
========================


This tutorial will cover unpacking of MoleBoxPro 2.2.5 packer. This packer is particulary interesting because it supports packing an application with all its data files (dll's , etc..) into a single executable file.






1. Introduction

Hi folks and welcome to new tutorial! This time we will deal with MoleBoxPro 2.2.5.

MoleBox is more simple packer than protector because it doesn't have any kind of anti-debug meashures except one CRC check. But MoleBox support packing all kind of files that comes along with main executable into one file. That include dll's too. When we start exe that is actually packed aplication, MoleBox extracts packed dll's into temp folder. From what I noticed it doesn't extract whole dll, just small crippled part. Also that dll doesn't have original name as before packing, but some random name (on every execution name is little different) like MBX@7A0@7C14B8.###. Original dll is loaded into memory under that name. So you see our problem, if we remove MoleBox envelope, we will also remove nedded dll's. Because that we need to dump those dll too and repair them.

For this tutorial I have packed my windows XP regedit.exe together with one dll from system folder that regedit needs. When you unpack this file, you will need to dump that dll from memory and repair it.

The tools that we need are:

- OllyDbg 1.10
- LordPE
- ImpREC
- Target, here http://www.reversing.be/binaries/articles/20051017235136932.rar




2. OEP and IAT

In olly options ignore all exceptions and if our packed file stop on some just add it to custom ones. Load RegPack.exe (packed regedit.exe) in Olly:

010642EC PUSHAD
010642ED CALL RegPack.01064341
010642F2 RCR DWORD PTR DS:[EDI+1ED8A3E2],1E
010642F9 POPAD
010642FA XOR EBX,DWORD PTR DS:[EDI-2B]
010642FD HLT
010642FE PUSH EBP
010642FF LOOPDE SHORT RegPack.01064334
01064301 NOP
01064302 PUSH ES
01064303 RETN
01064305 XCHG EAX,EBP
...
...

That is our EntryPoint. Press F7 three times and you will see:

01064290 CALL RegPack.01063E70
01064295 POP EAX
01064296 CALL RegPack.01064610
0106429B POP EAX
0106429C MOV DWORD PTR SS:[ESP+1C],EAX
010642A0 POPAD
010642A1 JMP EAX <------------------------- Jump to OEP!!!
010642A3 INT3
010642A4 INT3
010642A5 INT3
010642A6 INT3
010642A7 INT3
010642A8 INT3
010642A9 INT3
010642AA INT3
010642AB INT3
010642AC INT3
010642AD INT3
010642AE INT3
010642AF INT3
010642B0 ADD BYTE PTR DS:[EAX],AL
010642B2 ADD BYTE PTR DS:[EAX],AL
...
...

And you have found jump to OEP! JMP EAX is our jump. Place bp there , run , remove bp and execute that jump with F7 (you will probably see one "EntryPoint warning" from olly, just click OK):

01008AC5 PUSH EBP
01008AC6 MOV EBP,ESP
01008AC8 SUB ESP,24
01008ACB PUSH EBX
01008ACC PUSH ESI
01008ACD PUSH EDI
01008ACE CALL DWORD PTR DS:[10011D0] ; [GetThreadLocale
01008AD4 XOR EBX,EBX
01008AD6 PUSH EBX
01008AD7 CALL DWORD PTR DS:[10011D4] <---------- Missing import!!!
01008ADD MOV DWORD PTR DS:[10164F0],EAX
01008AE2 LEA EAX,DWORD PTR SS:[EBP-8]
...
...

This is our OEP. First problem that we have is missing imports. MoleBox has replaced some imports with it's own code. I don't think that is protection meashure, probably those imports are one that original file was used to interact with files that main exe needs (dll's and rest of files that are now packed in MoleBox package) like CreateFileA, LoadLibraryA, etc... So we need to fix that imports. Check code snippet above, at 01008AD7 we have one missing import. Foolow that DS:[10011D4] address in dump window:

010011D4 AC E3 06 01 C8 25 E7 77 EE E4 E7 77 D2 B6 E7 77 .....%.w...w...w
010011E4 D5 A5 E7 77 0C E6 E7 77 08 E0 06 01 CB 60 E7 77 ...w...w.....`.w
010011F4 73 3B E7 77 1A E1 E7 77 EA E0 E7 77 22 3B E7 77 s;.w...w...w";.w
...
...

You can see that most of other addresses point to some dll's, but our points to MoleBox SFX section. We will not dump until we fix this. Place hardware breakpoint on access, on first byte at 010011D4 address in dump. Now restart packed target in olly and keep pressing Shift+F9 untill you stop here:

0106A152 JE RegPack.0106A1DF <-------------- You are here!!!
0106A158 MOV EAX,DWORD PTR SS:[EBP-8]
0106A15B MOV ECX,DWORD PTR DS:[EAX]
0106A15D AND ECX,80000000
0106A163 TEST ECX,ECX
0106A165 JNZ SHORT RegPack.0106A18A
0106A167 MOV EDX,DWORD PTR SS:[EBP-8]
0106A16A MOV EAX,DWORD PTR SS:[EBP+C]
0106A16D ADD EAX,DWORD PTR DS:[EDX]
0106A16F MOV DWORD PTR SS:[EBP-20],EAX
0106A172 MOV ECX,DWORD PTR SS:[EBP-20]
0106A175 ADD ECX,2
0106A178 PUSH ECX
0106A179 MOV EDX,DWORD PTR SS:[EBP-10]
0106A17C PUSH EDX
0106A17D CALL DWORD PTR DS:[1075994] ; kernel32.GetProcAddress
0106A183 MOV ECX,DWORD PTR SS:[EBP-18]
0106A186 MOV DWORD PTR DS:[ECX],EAX
0106A188 JMP SHORT RegPack.0106A1B6
0106A18A MOV EDX,DWORD PTR SS:[EBP-8]
0106A18D MOV EAX,DWORD PTR DS:[EDX]
0106A18F AND EAX,0FFFF
0106A194 MOV DWORD PTR SS:[EBP-28],EAX
0106A197 MOV ECX,DWORD PTR SS:[EBP-28]
0106A19A PUSH ECX
0106A19B MOV EDX,DWORD PTR SS:[EBP-10]
0106A19E PUSH EDX
0106A19F CALL DWORD PTR DS:[1075994] ; kernel32.GetProcAddress
0106A1A5 MOV DWORD PTR SS:[EBP-24],EAX
0106A1A8 CMP DWORD PTR SS:[EBP-24],0
0106A1AC JE SHORT RegPack.0106A1B6
0106A1AE MOV EAX,DWORD PTR SS:[EBP-18]
0106A1B1 MOV ECX,DWORD PTR SS:[EBP-24]
0106A1B4 MOV DWORD PTR DS:[EAX],ECX
0106A1B6 MOV EDX,DWORD PTR SS:[EBP-C]
0106A1B9 AND EDX,0FF <---------------------- Here MoleBox check imports!
0106A1BF TEST EDX,EDX <--------------------- Place hardware bp on execution here!!
0106A1C1 JE SHORT RegPack.0106A1DA <-------- "Magic jump" !!!
0106A1C3 MOV EAX,DWORD PTR SS:[EBP-1C]
0106A1C6 PUSH EAX
0106A1C7 MOV ECX,DWORD PTR DS:[1074BB8]
0106A1CD PUSH ECX
0106A1CE MOV EDX,DWORD PTR SS:[EBP-18]
0106A1D1 PUSH EDX
0106A1D2 CALL RegPack.0106A8A0
0106A1D7 ADD ESP,0C
0106A1DA JMP RegPack.0106A13A
...
...

First remove hardware breakpoint that you had placed before (click "Debug" menu, "Hardware breakpoints" and delete it). When you break here, you are in procedure that filling thunks with imports. MoleBox first find API with GetProcAddress and place it import table. Then it checks does that API needs to be substituted with MoleBox own code. That check is at 0106A1BF. If API doesn't need to be replaced , jump at 0106A1C1 will be executed and API will stay in thunk. So, to prevent API replacing you need to change JE to JMP. But now is too late because some jumps are already replaced, so place hardware breakpoint on execution on 0106A1BF line and restart our packed target. Now first go to our JMP EAX oep jump and place bp there, then run target untill you break on our API check:

0106A1BF TEST EDX,EDX
0106A1C1 JE SHORT RegPack.0106A1DA

Remove hw breakpoint and change JE to JMP:

0106A1BF TEST EDX,EDX
0106A1C1 JMP SHORT RegPack.0106A1DA


There! Imports are fixed now :) just run to Break at our OEP jump and then go to OEP:

01008AC5 PUSH EBP
01008AC6 MOV EBP,ESP
01008AC8 SUB ESP,24
01008ACB PUSH EBX
01008ACC PUSH ESI
01008ACD PUSH EDI
01008ACE CALL DWORD PTR DS:[10011D0] ; [GetThreadLocale
01008AD4 XOR EBX,EBX
01008AD6 PUSH EBX ; /pModule = ""
01008AD7 CALL DWORD PTR DS:[10011D4] ; GetModuleHandleW
01008ADD MOV DWORD PTR DS:[10164F0],EAX ; RegPack.01008AC5
01008AE2 LEA EAX,DWORD PTR SS:[EBP-8]
01008AE5 PUSH EAX ; /pInitEx = RegPack.01008AC5
...
...

As you see, API is now there. Dump file with LordPE and use ImpREC to grab imported API's. There shouldn't be neither one invalid import. Fix dumped file. Don't close ImpREC yet, check names of modules. One module should have name simmilar to "mbx@1dc@7c14b0.###". That is dll that is packed within main exe. You will find that file in temp folder, but you don't need it. What you need is to dump that file from memory, just write it's name down. You can close ImpREC but leave Olly and LordPE.


If you try to run dumped file, you will get warning message that "mbx@1dc@7c14b0.###" is not found and exe cannot start without it. If you copy-paste that file from temp folder, you will get error message saying that some function cannot be found in it and again you cannot start dump. Problem is that file from temp folder is just crippled junk. We need to dump valid file from memory.





3. Dumping and repairing dll's

There can be lot of this files, in our example we have only one, but procedure is same for all files. In LordPE click on our RegPack.exe process, go to bottom window and right click on our file that is in temp folder (c:docume~...mbx@1dc@7c14b0.###) and do full dump. Save dump as dumped.dll. For more that one temp file you would just save them as dumped1.dll, dumped2.dll, etc... so you don't overwrite them.

Ok, you dumped file but you need to fix it's IAT. For that you must know OEP of that file. That information you will find in it's PE header. Open memory map window and double click on it's PE header:

76CC0000 00001000 MBX@1DC@ PE header Imag R RWE <-- Double click!!!
76CC1000 0000C000 MBX@1DC@ .text code,exports Imag R RWE
76CCD000 00001000 MBX@1DC@ .data data Imag R RWE
76CCE000 00001000 MBX@1DC@ .rsrc resources Imag R RWE
76CCF000 00001000 MBX@1DC@ .reloc Imag R RWE
76CD0000 00001000 MBX@1DC@ _BOX_ SFX,relocati Imag R RWE

When you see PE header dump, scroll down to:

76CC0100 0B01 DW 010B ; MagicNumber = PE32
76CC0102 07 DB 07 ; MajorLinkerVersion = 7
76CC0103 00 DB 00 ; MinorLinkerVersion = 0
76CC0104 00100000 DD 00001000 ; SizeOfCode = 1000 (4096.)
76CC0108 00000000 DD 00000000 ; SizeOfInitializedData = 0
76CC010C 00F00000 DD 0000F000 ; SizeOfUninitializedData = F000 (61440.)
76CC0110 00000100 DD 00010000 ; AddressOfEntryPoint = 10000 <----------- OEP!!!
76CC0114 00100000 DD 00001000 ; BaseOfCode = 1000
76CC0118 00D00000 DD 0000D000 ; BaseOfData = D000
76CC011C 0000CC76 DD 76CC0000 ; ImageBase = 76CC0000 <--------------- Image base!!!

There you see where OEP is and what is Image Base. But we have problem now. It sems that dll is packed and we cannot find reall OEP in PE header. After spending some time I found what is going on. Remember this OEP, 76cd0000=76cc0000+10000 and restart Olly. Place bp on CreateFileA and run target untill you see in stack window that MoleBox has create our temp file:

0006FC8C 0106B93B /CALL to CreateFileA from RegPack.0106B935
0006FC90 007C1838 |FileName = "C:DOCUME~1HAGGAR~1LOCALS~1TEMPMBX@36C@7C14B0.###"
0006FC94 40000000 |Access = GENERIC_WRITE
0006FC98 00000000 |ShareMode = 0
0006FC9C 00000000 |pSecurity = NULL
0006FCA0 00000002 |Mode = CREATE_ALWAYS
0006FCA4 00000000 |Attributes = 0
0006FCA8 00000000 hTemplateFile = NULL

Return to MoleBox code and you will see some WriteFile API's. Place bp below them on next line:
...
...
0106B998 CALL DWORD PTR DS:[1075A20] ; kernel32.WriteFile
0106B99E PUSH DWORD PTR SS:[EBP-4C]
0106B9A1 CALL DWORD PTR DS:[1075944] ; kernel32.FlushFileBuffers
0106B9A7 PUSH DWORD PTR SS:[EBP-4C]
0106B9AA CALL DWORD PTR DS:[1075910] ; kernel32.CloseHandle
0106B9B0 PUSH DWORD PTR SS:[EBP-24]
0106B9B3 CALL DWORD PTR DS:[10759C0] ; kernel32.LoadLibraryA
0106B9B9 MOV DWORD PTR SS:[EBP-A4],EAX
0106B9BF CMP DWORD PTR SS:[EBP-A4],0 <------------------------ Place bp here and run!!!
0106B9C6 JNZ SHORT RegPack.0106B9EC

You can conclude that our dll has some code inside now. Go to that OEP value that you sow in PE header, you know 77cd0000:

76CD0000 POP EAX <----------- This is OEP!!
76CD0001 PUSH CABEE8EC
76CD0006 PUSH 7C1718
76CD000B PUSH 44
76CD0010 PUSH EAX
76CD0011 PUSH 106AE82 <----- You see that it will return to main exe code!
76CD0016 RETN
76CD0017 NOP
76CD0018 NOP
76CD0019 NOP
76CD001A NOP
76CD001B NOP
76CD001C NOP
76CD001D NOP
76CD001E NOP
76CD001F NOP
...
...

You see that PUSH 106AE82 and then RETN ? It will remove to main exe code so follow that address and place hardware bp on execution, then run Olly. You will break there:

0106AE82 PUSH EBP <--------------------- Place hw bp on execution here and run, then remove bp!
0106AE83 MOV EBP,ESP
0106AE85 PUSH -1
0106AE87 PUSH RegPack.01072468
0106AE8C PUSH RegPack.010631B0
0106AE91 MOV EAX,DWORD PTR FS:[0]
0106AE97 PUSH EAX
0106AE98 MOV DWORD PTR FS:[0],ESP
0106AE9F PUSH ECX
0106AEA0 PUSH ECX
0106AEA1 SUB ESP,40
0106AEA4 PUSH EBX
0106AEA5 PUSH ESI
...
...

Remove bp from there. What is going on? It seams that MoleBox code that is in main exe will unpack this dll and then jump to it's original OEP. So we just need to find when it will jump to OEP or break at OEP. After using lot of memory bp's and tracing, I found that jump to OEP is just below this procedure:

0106B08B CALL DWORD PTR SS:[EBP-20] <------------ Here!!!
0106B08E MOV DWORD PTR SS:[EBP-1C],EAX
0106B091 MOV EAX,DWORD PTR SS:[EBP-1C]
0106B094 MOV ECX,DWORD PTR SS:[EBP-10]
0106B097 MOV DWORD PTR FS:[0],ECX
0106B09E POP EDI
0106B09F POP ESI
0106B0A0 POP EBX
0106B0A1 LEAVE
0106B0A2 RETN 18

And when you follow that CALL you will see our OEP:

76CC1190 PUSH EBP <----------------------- Dll OEP!!!
76CC1191 MOV EBP,ESP
76CC1193 PUSH EBX
76CC1194 MOV EBX,DWORD PTR SS:[EBP+8]
76CC1197 PUSH ESI
76CC1198 MOV ESI,DWORD PTR SS:[EBP+C]
76CC119B TEST ESI,ESI
76CC119D PUSH EDI
76CC119E MOV EDI,DWORD PTR SS:[EBP+10]
76CC11A1 JE 76CC4270
76CC11A7 CMP ESI,1
76CC11AA JE SHORT 76CC11B1
76CC11AC CMP ESI,2
...
...






Ok, let's stop for a second now. We have good dumped.exe, then non fixed dumped.dll, but we now have it's OEp and we can find it's imports with ImpREC. But we have one more problem, our dumped.dll has also some invalid imports due MoleBox API replacing. Ha ha, I hate this! But I don't have to repeat all over again. I need just to prevent import replacing so I will just place bp on main exe OEP jump and import "magic jump" that needs to be fixed:

010642A1 JMP EAX <---- OEP jump.

0106A1C1 POP EDI <---- "Magic jump" is still encrypted but you just place hw bp there.

Then run, change JE to JMP when you break to our jump, then run and you'll break on JMP EAX. That is it, you need just to repair IAT of dumped.dll and that is easy since you know dll OEP=1190 and ImageBase=76cc0000. Open ImpREC, attach to RegPack.exe, click on "Pick DLL" button and there select mbx@... module. In OEP window enter 1190 and click "IAT aoutosearch" and then "Get imports". You will see 5 modules with all valid imports. Fix dumped.dll and close all tools. And that's it! Or not? He he, run dumped_.exe and you will get error message that mbx@......### is missing. So just rename your dll to that name which windows are complaining. Run dumped_.exe now and it will work perfect!







4. Final words

If you don't want that your dumped dll has that mbx@... name, you can change it to whatever you like, but then you must open dumped_.exe and find that name and change it to new one. You will find that name in import section ofcourse.

Greets to all folks on BIW. See you in the next tutorial.




[ haggar ]

3 comments



http://www.reversing.be/article.php?story=20051017235819353