C reating Load ers & D umpers - C rackers G uide to Program F low C ontrol ______________________ B y [yAtE s] June 26, 2004
[h ttp://w w w .yates2k.net] [h ttp://w w w .reteam.org]
If you did not find any files accompanying th is paper you can dow nload th em at: h ttp://w w w .yates2k.net/lad_files.rar or h ttp://w w w .w oodmann.net/yates/lad_files.rar
Introd uction So you w ant to unpack a program, aspack? asprotect? even safedisc? To accomplish such a task a degree of know ledge is needed in many, many different areas, over th e years I h ave been w riting small tutorials on th ese areas b efore I ever w rite a compreh ensive tutorial on a single sub ject. Ok, so one th ing th at I’ve noticed is th at 'new bies' h ave no sense of h ow th ey're going to carry out all th e tasks needed to repair a exe, most plan to just d ump an exe image and try and fix bits as th ey go along, but a much more structured w ay can be taken and th is is to create a 'dumper' w h ich effectively launch es your target exe and h alts it in certain places so you can read some memory areas and save data, and eventually end up at OE P w h en you can dump th e sections to disk and make your necessary ch anges. Ok th is is common know ledge to 80% of crackers excluding th e ones th at message me ;-) so I doubt many people w ill be reading th is paper, w ith th at let’s begin one of my rare essays h eh e.
emon n stration w ill h appen H ow th e d emo F or th is example I’m going to take a U PX packed notepad and sh ow you h ow to code a program to stop it at th e point w h ere th e imports are being resolved, th en I’m going to output th e data to screen as th ey get resolved just as an example, at th is point really if you w ere unpacking th e exe you w ould grab th e data and prod uce a fresh import table. After outputting th e import data I’m going to th en let th e program continue to OE P, h alt it th ere and sh ow a msgbox.
E xaming th e target Ok before I explain th e process of controlling th e program flow let’s look at our target and find w h at w e h ave to do. I've protected my notepad w ith upx and took 5mins to study h ow it w orks. I'll now briefly explain:
U PX entry point looks like th is, U PX 1:010 116 51 U PX 1:010 116 56 U PX 1:010 116 5C U PX 1:010 116 5D U PX 1:010 116 60
mov esi, offset dw ord_100D 000 lea edi, [esi-0C 00 0h ] push edi or ebp, 0F F F F F F F F h jmp sh ort loc_101167 2
Now if you scroll d ow n 4 pages in ida you can clearly see th e OE P U PX 1:010 117 9E loc_1 011 79E : ; C OD E X R E F : start+ 11 0_j U PX 1:010 117 9E popa ; resore registers U PX 1:010 117 9F jmp near ptr dw ord_10064 20 U PX 1:010 117 9F start endp So 0101 179 F is our final destination. Th e import load er code looks like th is
U PX 1:010 117 5C G E T_D LLNAM E _AND _TH U NK : ; C OD E X R E F : start+ 12E _j U PX 1:010 117 5C mov eax, [edi] ; NO U PX 1:010 117 5E or eax, eax U PX 1:010 117 60 jz sh ort loc_10117 9E U PX 1:010 117 62 mov ebx, [edi+ 4] U PX 1:010 117 65 lea eax, [eax+ esi+ 11C F 4h ] U PX 1:010 117 6C add ebx, esi U PX 1:010 117 6E push eax ; D LL NAM E U PX 1:010 117 6F add edi, 8 U PX 1:010 117 72 call dw ord ptr [esi+ 11 D A8h ] ; LOAD LIB R AR Y U PX 1:010 117 78 xch g eax, ebp U PX 1:010 117 79 U PX 1:010 117 79 B U ILD _TH U NK : ; C OD E X R E F : start+ 1 46_j U PX 1:010 117 79 mov al, [edi] U PX 1:010 117 7B inc edi U PX 1:010 117 7C or al, al U PX 1:010 117 7E jz sh ort G E T_D LLNAM E _AND _TH U NK ; NO U PX 1:010 117 80 mov ecx, edi U PX 1:010 117 82 push edi ; PTR ASC II NAM E U PX 1:010 117 83 dec eax U PX 1:010 117 84 repne scasb U PX 1:010 117 86 push ebp U PX 1:010 117 87 call dw ord ptr [esi+ 11 D AC h ] ; G E TPR OC AD D R E SS U PX 1:010 117 8D or eax, eax ; AD D R E SS U PX 1:010 117 8F jz sh ort loc_10117 98 U PX 1:010 117 91 mov [ebx], eax ; W R ITE TO TH U NK U PX 1:010 117 93 add ebx, 4 U PX 1:010 117 96 jmp sh ort B U ILD _TH U NK
It starts off by reading a block of d ata stored in E D I, e.g. U PX 1:010 100 00 U PX 1:010 100 04
dd 0F C h dd 80h
; D LL NAM E POINTE R ; TH U NK STAR T
U PX 1:010 100 08 U PX 1:010 100 09 U PX 1:010 100 15 U PX 1:010 100 16 U PX 1:010 100 23 U PX 1:010 100 24 U PX 1:010 100 2F U PX 1:010 100 30
db aLocalunlock db aG lobalunlock db aG loballock db aG etlasterror
1 db 'LocalU nlock',0 1 db 'G lobalU nlock',0 1 db 'G lobalLock',0 1 db 'G etLastE rror',0
As you can see by my comments th e structure is pointer to name, th unk location and th en a list of functions for th at dll. Th e dll pointer is fixed up and read and U PX loads th e library h ere, U PX 1:010 117 6E U PX 1:010 117 6F U PX 1:010 117 72
push eax ; D LL NAM E add edi, 8 call dw ord ptr [esi+ 11 D A8h ] ; LOAD LIB R AR Y
It th en reads th e 80h and add s th e section base to it and puts it in E B X th is w ill be th e th unk for th e current dll and w h ere all th e resolved address for th e api list w ill be placed, if you understand import tables th en you know th is is th e point you sh ould replace th e api address w ith a pointer to th e name. Anyw ay, so th en furth er dow n it reads th e api name th en performs getprocad dress U PX 1:010 117 82 U PX 1:010 117 83 U PX 1:010 117 84 U PX 1:010 117 86 U PX 1:010 117 87 U PX 1:010 117 8D U PX 1:010 117 8F U PX 1:010 117 91
push edi ; PTR ASC II NAM E dec eax repne scasb push ebp ; current dll base call dw ord ptr [esi+ 11 D AC h ] ; G E TPR OC AD D R E SS or eax, eax ; AD D R E SS jz sh ort loc_10117 98 mov [ebx], eax ; W R ITE TO TH U NK
Ok so for fun w e w ill stop th e program at 010 117 82 , output th e current function th en continue to 01011 78D and output th e api ad dress :-)
Ob jectives Ok h ere is our mission plan: * Start E xecutable * place a stop point at oep - 010117 9E * stop at 010 117 6C print th e dll name * stop at 010 117 80 print th e ascii name * stop at 010 117 96 print th e api address * loop th ese stop points until w e get to oep I’m going to be sh ow ing my examples in ASM using th e compiler TASM , I w ill also try and include C + + source codes in th e final source for you new generation coders ;-)
Th eory In order to control th e program th e idea is w e start th e application in a suspended mode th en w e w rite into th e programs memory th e bytes 0E B h 0F E h w h ere w e w ant to stop, th ese 2 bytes are th e opcodes for JM P -2 and since th e instruction is 2 bytes long th is causes a constant loop and th e instruction keeps executing it self, so w e insert th ese w h ere w e w ant to stop th en resume th e program, if w e w ait a few millisecond s th e program w ill become trapped in th is loop, w e can ch eck w h at ad dress is currently b eing executed using an API, so once w e detect w e've stopped at our target address w e can th en take action. Th e APIs you need to know are th e follow ing: C reateProcess - Load an external executable. h ttp://msdn.microsoft.com/library/default.asp?url= /library/enus/dllproc/base/createprocess.asp R esumeTh read / Suspend Th read - U sed to stop and start th e process th read in its current state h ttp://msdn.microsoft.com/library/default.asp?url= /library/enus/dllproc/base/resumeth read.asp h ttp://msdn.microsoft.com/library/default.asp?url= /library/enus/dllproc/base/suspendth read.asp W riteProcessM emory / R eadProcessM emory - U sed to insert our JM P -2 and read process memory h ttp://msdn.microsoft.com/library/default.asp?url= /library/enus/d ebug/b ase/w riteprocessmemory.asp h ttp://msdn.microsoft.com/library/default.asp?url= /library/enus/d ebug/b ase/read processmemory.asp G etTh readC ontext / SetTh read C ontext - U sed to get th e R egister values from th e running process. h ttp://msdn.microsoft.com/library/default.asp?url= /library/enus/d ebug/b ase/getth readcontext.asp h ttp://msdn.microsoft.com/library/default.asp?url= /library/enus/d ebug/b ase/setth readcontext.asp
Pratice * place a stop point at oep - 010117 9E * stop at 010 117 6C print th e dll name * stop at 010 117 80 print th e ascii name * stop at 010 117 96 print th e api address So w e h ave 4 stop points, it important to plan w h en placing th ese, in a proper cracking process you migh t perh aps inject a dll into th e process (see my h ooking import table tut) and th en patch in jumps at th e h ook points so th e target jumps into your dll and performs some operations and jumps back. In th is case w e are inserting E B F E into th e exe, but w e are inserting th em inside a loop th at resolves imports. W h en w e place th e E B F E w e are destroying data, so it’s a good idea to find a suitable place to put th em. F or example, over a 2 byte instruction w e can emulate. Let’s now look for good places to put our h ooks.
1 . OE P. It doesnt matter w h ere w e place it since w e are terminating th e program w h en w e reach it so let’s ch oose: 01 011 79E 61 popa 2 . D LLNAM E U PX 1:010 117 6C 01 F 3 U PX 1:010 117 6E 5 0
add push
ebx, esi eax
; D LL NAM E
0101 176 C is a good place because w e can read E AX to get th e dll, and also grab ebx, esi Ad d th em and insert th e result b ack into ebx, ok get th e idea? 3 . ASC II NAM E U PX 1:010 117 80 89 F 9 U PX 1:010 117 82 57
mov ecx, edi push edi ; PTR ASC II NAM E
Same again 010 117 80 w ill do, w e can emulate th is mov 4 . API AD D R E SS U PX 1:010 117 87 F F 96 AC 1D 01+ G E TPR OC AD D R E SS U PX 1:010 117 8D 09 C 0 U PX 1:010 117 8F 74 0 7 U PX 1:010 117 91 89 0 3 U PX 1:010 117 93 83 C 3 04 U PX 1:010 117 96 E B E 1
call
dw ord ptr [esi+ 11D AC h ] ;
or eax, eax ; AD D R E SS jz sh ort loc_1011 798 mov [ebx], eax ; W R ITE TO TH U NK add ebx, 4 jmp sh ort B U ILD _TH U NK
Th e address goes into eax after getprocad dress so I’m going to ch oose 0101 179 6 E B E 1 jmp sh ort B U ILD _TH U NK for my h ook and update eip w ith th e address of B U ILD _TH U NK to simulate th e jump w h en I’m done.
C od ing th e program Ok I th ink th e important bit is over, now w e need to code th is idea, now I’m no coding teach er, but perh aps for some of you coding is new , and it’s important to find a language your going to be h appy learning and using, w h ilst coding th e program you w ould normally code small sections first and test th em but since its going to be h ard to put th is dow n on paper, I’m now going to paste my source cod e file in sections and explain it as much as I can, you may learn to cod e in a similar style to try port th e idea to anoth er language, or perh aps your an excellent coder anyw ay, b ut I never assume anyth ing :-) Ok th e source file is upx_d ump.asm you sh ould open th is as I go th rough it, th e first top bit is just th e defining of some APIS and C onstants, th en th e .data section sets up some variables w e need, w e w ill see th em in use as w e go along. Th e first part is th at w e Load th e notepad upx file b ut in suspended mod e, th is means th e program isn’t running but all of its memory is mapped.
Now w e patch our E B F E into all th e addresses th at w e decided on earlier, take a look at th e code below , if your new to using th ese apis you sh ould look at th e M SN links I provided earlier w h ich sh ow w h at all th e parameters are, but it sh ould be fairly straigh t forw ard.
C all C reateProcessA,o progname,0,0,0,0,C R E ATE _SU SPE ND E D ,0,0,o tStartupInfo,o tProcessInfo mov eax, 01 011 79E h ; OE P call W riteProcessM emory,[tProcessInfo],eax,o H ALT_C OD E ,H ALT_SIZ E ,0 mov eax, 01 011 76C h ; D LL NAM E H OOK call W riteProcessM emory,[tProcessInfo],eax,o H ALT_C OD E ,H ALT_SIZ E ,0 mov eax, 01 011 780h ; ASC II NAM E H OOK call W riteProcessM emory,[tProcessInfo],eax,o H ALT_C OD E ,H ALT_SIZ E ,0 mov eax, 01 011 796h ; API AD D R E SS H OOK call W riteProcessM emory,[tProcessInfo],eax,o H ALT_C OD E ,H ALT_SIZ E ,0
Ok so now our process is loaded and w e our h ooks patch ed in. Th e next stage is let th e process run, th en code a M AIN B OD Y w h ich w ill be a loop w h ere G etTh read C ontext is constantly called, G etTh readC ontext w ill retrieve all th e running processes registers, so if w e are calling th is in a loop w e can monitor w h en E IP h its one of our h ooks th en take action, easy eh ? Ok h ere it is:
call R esumeTh read, [tProcessInfo+ 4] C all Sleep, 100h mov [my_context], 000 1000 0h + 1+ 2+ 4+ 8+ 1 0h ; SE T U P PE R M ISSIONS C ontextLoop: call G etTh readC ontext, [tProcessInfo+ 4], o my_context test eax, eax jz CERR mov eax, [my_context+ R E G _E IP] cmp eax, 01011 79 E h jz OE P_R E AC H E D cmp eax, 01011 76 C h jz D LLNAM E _H OOK E D cmp eax, 0101178 0h jz ASC IINAM E _H OOK E D cmp eax, 0101179 6h jz APIAD D R _H OOK jmp C ontextLoop
; C H E C K ING E IP
Pretty straigh t forw ard I th ink th at is, now someth ing to note is th at I’ve h ardcod ed th e addresses, perh aps sometimes it is best to subtract th e imagebase th en get th e imagebase of th e running program and add th em to our values just in case of relocation, th is w ould be essential for example if w e h ad h ooked after some loadlibrary and got th e base address and w ere planning to place more h ooks in th is dll, but anyw ay I kept it simple. Now w e h ave a main bod y, now run th rough th e process in your h ead, th e first th ing th at w ill h appen is w e w ill get a h ooked detected at th e D LLNAM E , since if you ch ecked th e upx code snipped at th e start th e first th ing upx does is load a dll, so let’s cod e th e D LLNAM E _H OOK E D procedure.
D LLNAM E _H OOK E D : call SuspendTh read, [tProcessInfo+ 4 ] call G etTh readC ontext, [tProcessInfo+ 4], o my_context mov eax, [my_context+ R E G _E AX ] ; G E T TH E C ONTE NTS OF E AX (PTR TO ASC II D LL) call R eadProcessM emory,[tProcessInfo],eax,o myB uffer,30,0 ; R E AD D LL NAM E F R OM PTR ; emulate U PX 1:0 101 176 C
add
ebx, esi
mov ebx, [my_context+ R E G _E B X ] mov esi, [my_context+ R E G _E SI] add ebx, esi mov [my_context+ R E G _E B X ], ebx ; skip instruction mov eax, [my_context+ R E G _E IP] add eax, 2 mov [my_context+ R E G _E IP], eax ; set context call SetTh readC ontext, [tProcessInfo+ 4], o my_context call R esumeTh read, [tProcessInfo+ 4] call dll1 db 13,1 0,13,10,'-> Loading D LL ',0 dll1: call dbg_string call dbg_string, o myB uffer call dbg_string, o new line jmp C ontextLoop
U PX 1:010 117 6C 01 F 3 U PX 1:010 117 6E 5 0
add push
ebx, esi eax
; D LL NAM E
Ok h ere w e stop th e process w ith suspendth read so w e stop th e cpu going crazy, th en w e get th e context so h ave all th e current registers, now th e dll name is stored in E AX , so w e read
th is value from th e context structure, now w e h ave a pointer to th e dllname in th e oth er process, so w e read from th is address into a buffer. Next w e need to fix th e instruction w e destroyed w h ich w as AD D E B X , E SI, now if you never needed to h ook th is point again you could patch th e instruction back but since w e w ant to break h ere again w e must emulate it, so I grab ebx and esi from th e context struct add th em and insert it back into ebx, th en I also get th e eip value and ad d 2, th is is so w e skip th e E B F E and start at th e PU SH , th en i use SetTh readC ontext to update th e process's memory, R esumeTh read th en sets it back on its w ay, i've th en used my ow n internal functions dbg_xx to w rite out text and th e contents of th e buffer into a file called deb ug.txt. Now w e jump back to our main context ch ecking loop. Th e next th ing th at w ill h appen is w e'll break on th e ASC IINAM E _H OOK E D , so let’s code th at, you can almost copy paste th e ab ove function and make minor tw eaks.
ASC IINAM E _H OOK E D : call SuspendTh read, [tProcessInfo+ 4 ] call G etTh readC ontext, [tProcessInfo+ 4], o my_context mov eax, [my_context+ R E G _E D I] OF E D I(PTR TO ASC II API) call R eadProcessM emory,[tProcessInfo],eax,o myB uffer,200,0 F R OM PTR ; emulate U U PX 1:010 117 80 89 F 9 mov
ecx, edi
mov edi, [my_context+ R E G _E D I] mov [my_context+ R E G _E C X ], edi ; skip instruction mov eax, [my_context+ R E G _E IP] add eax, 2 mov [my_context+ R E G _E IP], eax ; set context call SetTh readC ontext, [tProcessInfo+ 4], o my_context call R esumeTh read, [tProcessInfo+ 4] call dll2 db ' F U NC : ',0 dll2: call dbg_string call dbg_string, o myB uffer jmp C ontextLoop
U PX 1:010 117 80 89 F 9 U PX 1:010 117 82 57
mov ecx, edi push edi ; PTR ASC II NAM E
; G E T TH E C ONTE NTS ; R E AD D LL NAM E
Ok so th e same as before, stop th e process and th en get th e pointer to th e ascii name from edi and read it into our buffer, now I emulate th e M OV E C X , E D I and update E IP Next is th e API function address h ook APIAD D R _H OOK
APIAD D R _H OOK : call SuspendTh read, [tProcessInfo+ 4 ] call G etTh readC ontext, [tProcessInfo+ 4], o my_context mov eax, [my_context+ R E G _E AX ] OF E D I(PTR TO ASC II API)
; G E T TH E C ONTE NTS
call dll3 db 9,9,9,'AD D R : ',0 dll3: call dbg_string call dbg_dw ord,eax,0 call dbg_string, o new line ; emulate 01 011 796 E B E 1
jmp
sh ort B U ILD _TH U NK
mov eax, 01 011 779h mov [my_context+ R E G _E IP], eax ; set context call SetTh readC ontext, [tProcessInfo+ 4], o my_context call R esumeTh read, [tProcessInfo+ 4] jmp C ontextLoop
U PX 1:010 117 87 F F 96 AC 1D 01+ G E TPR OC AD D R E SS U PX 1:010 117 8D 09 C 0 U PX 1:010 117 8F 74 0 7 U PX 1:010 117 91 89 0 3 U PX 1:010 117 93 83 C 3 04 U PX 1:010 117 96 E B E 1
call
dw ord ptr [esi+ 11D AC h ] ;
or eax, eax ; AD D R E SS jz sh ort loc_1011 798 mov [ebx], eax ; W R ITE TO TH U NK add ebx, 4 jmp sh ort B U ILD _TH U NK
Since th e api address is E AX all I need do is get th e value from th e context structure, th en w e h ad our h ook at 0101 1796, so I emulate th e 'jmp sh ort B U ILD _TH U NK ' by placing th e address of B U ILD _TH U NK into E IP and continue. Last of all w e need some code for OE P_R E AC H E D
OE P_R E AC H E D : call M essageB oxA,0,o msgOE P,o msgok, 0 call TerminateProcess, [tProcessInfo]
jmp E nd_Process
Just a simple messagebox to say h ello :) and th e end of th e code looks like,
CE RR: call M essageB oxA,0,o msgcontext,o msgerr, 0 E nd_Process: call exitprocess, 0 end main
Ta da! Th at’s it, now since w e are messing around w ith a program during a small loop th at resolves th e imports it considerably slow s th e app d ow n, if you test th e example it w ill take about 1 minute until th e message b ox appears, click ok th en view debug.txt I've provided ASM and C PP code, and b oth compiled exes for you to test, th e C PP one seems to run much faster, it also screen output, reading th e C PP code is probably easier to understand th an th e ASM as you can see th e program structure much b etter. Now don’t take th is tutorial as a literal w ay of cracking someth ing, it merely d escribes a common tech nique used my dumpers, you sh ould reverse your target application and find good h ook points, like after some decryption, th en make use of your d umper to run th rough th e target collecting information needed for a final unpacked target, so h ave fun and w atch out for C R C s ;-) regards, yates. yates@ reverse-engineering.info