informations
the fleur patcher is a generic patcher that permits to add functionalities to any pe file. the patcher has been written for masm.
required files
patcher - the generic patcher files and the patcher generator
target - a simple pe file target
linked files
notepad 98 patcher - an sample of patcher made with the fleur patcher
target patcher - the files of the target patcher that we create in this tutorial
tools used
masm
patcher
patcher generator
softice
tutorial
I. purpose of the tutorial
this tutorial is meant to show you how you can easily add functions to an already compiled executable using your own patcher, and what are the advantages of this method.
i assume you are using masm, you have the required tools, and you know how to use softice.
II. presentation
our target will be a small program, wich has a good code understandability. however, you can add functionalities to any program you want. to show you an example of what can be done, you can try the notepad patcher that you can download in the linked file section. this tutorial will teach you all the knowledge you have to get in order to use all the possibilities of the patcher. making a patcher like the notepad 98 patcher will the be just a matter of time and perseverance.
the patcher will allow you to have a clear code, that is stored in a file, and compilable when you want. if we were using the comparing byte patching method, that is, you change the code directly with an hexeditor like hiew, and then let a program find wich bytes have been changed into what, then generate a patch that automatize these changes, we would have to recode everything if we forgot to code something, or if we want to add something.
the patcher adds a section at the end of the executable, and change some code in the target to jumps that jump to our code. instead of having the patcher try to localize the last section, and compute all the offsets needed to add that section, i coded another program, patcher generator, that you can download in the required files section. this program gives you the important informations about the target that are needed by the patcher and gives you the list of the imported functions you can use. this program also permits you to add your own imports to the target.
the patcher files you will have to modify are stored in the root directory of the patcher. ASMcode.asm is the file where you put your added code, ASMcodechange.asm is the file where you put your direct code change, ASMlocations.asm is the file where you put the addresses of the jumps to our code, or the addresses of the direct code changes, DATcodedata.asm is the data of your code, and there is also a conf directory that contains DATpatcher.asm wich holds informations to customize the patcher, and the patcher resource files.
III. configuration
copy the entire directory of the patcher, that you can download in the required files section, to your patcher directory, for example in a myPatcher directory. do not edit the files in the patcher directory, because it is a template, edit them only after having copied the directory to your patcher directory.
you can edit !!comm.bat to change all the references to app by the name of the executable you want to patch. the reason why there is a reference to !!app.exe is that i always copy the original executable to a !!app.exe copy so there' s always an unpatched copy of the program in the directory. the batch automatically copies !!app.exe to app.exe, so you can directly patch app.exe.
open DATpatcher.asm in the conf directory. change the name in bfFile by target.exe. this name is the default name that is shown in the edit boxes of the patcher, if there' s no file on the commandline. change dtSectionName to the name of the section that will be added on the target. this name must be 8 characters long, for example, if the name is .mySec, you will have to change it to :
dtSectionName db '.mySec',0,0then you can change the about caption and text, the patcher caption, szPatched is the the message shown in the messagebox that indicates a sucessful patch, szSuccess is it' s caption, szOpenCaption is the caption of the browse dialog.
you can delete the patcherversion.txt file if you want, but do not delete the patcher.ver file.
launch patcher generator. click on browse and select the !!target.exe file. always choose the backup copy, because if you choose the file that has been patched, the informations retrieved by the patcher generator will be the wrong ones. now click save and save the project in your patcher directory. click on generate files and choose the patcher.ver file at the root of your patcher directory. the program has generated some information files about the target, and has created a TXTpeinfo.txt file at the root of your patcher directory, that shows the informations you can access by clicking the pe informations button. later, we' ll see how to add imports.
IV. code
now we will see two aspects of the patcher. the first is the direct code change. i mean that we will directly change the code of the target to another code, to avoid the messagebox that pops-up when we click the button. the second is code adding. we will jump from the code of the target to our section. we will use this method to make a messagebox pops-up when the program starts, and then we will see how to add imports in order to make the program beeps before showing the messagebox.
we will start by avoiding the messagebox when clicking the button. so bpx messageboxa and click the button. softice will break. you see that at 00401063 there' s a cmp ax,64h that checks if the button has been clicked, if not, it continues, if yes, there' s a call to messageboxa, and the a jump to 0040104c that returns to the proc. so we' ll have to change the code at 00401069 in a jump to 0040104c.
open ASMlocations.asm. you see a generic ccode and a generic wjmp. since we don' t use the code adding yet, comment out the wjmp, open ASMcode.asm and comment out the fjmpb for now, so if you compile the patcher, there won' t be any problem with the undeclared startrva and destinationrva constants, that you' ll have to change to the one you want.
now, we have to get the offsets of the location of the code, 00401069, so open TXTpeinfo.txt. look at the sections :
name vSize vAddress rSize rOffset characteristics .text 000000d8h 00001000h 00000200h 00000400h 60000020h .rdata 00000108h 00002000h 00000200h 00000600h 40000040h .data 00000018h 00003000h 00000200h 00000800h c0000040h .rsrc 00000480h 00004000h 00000600h 00000a00h 40000040hif we look at the vAddresses, we see that 1069h belongs to the .text section, wich is the code section of the target, because 1000h (vAddress of .text)<1069h (vAddress of code)<2000h (vAddress of .rdata). so the offset of our code is vAddress(code) - vAddress(.text) + rOffset(.text), 1069h-1000h+400h=469h.
in ASMlocations.asm, change the :
ccode change1start,change1end,codeoffsetto :
ccode jumpmessageboxstart,jumpmessageboxend,469hbeware, if the offset begins with a letter, like for example b56h, don' t forget to put a 0 before, you would write :
ccode jumpmessageboxstart,jumpmessageboxend,0b56hthe syntax of the ccode macro is the following :
ccode startcodelabel,endcodelabel,offset of codeand in the ASMcodechange.asm, add the following lines :
jumpmessageboxstart: jmp $+(104ch - 1069h) jumpmessageboxend:the jump is jmp $+(rva of destination - rva of start). here we just needed a jump, but you could add anything you want. just proceed the same way : add your code in ASMcodechange.asm, between a mycodestart and a mycodeend labels, and add the following line in ASMlocations.asm :
ccode mycodestart,mycodeend,myoffsetnow we' ll add the messageboxa when the program launches. to add code, we need to jump from the program to our code. the jump will modify 5 bytes of the program, that we will have to execute at the end of our code. to jump, we need to have the offset of the start of the jump and it' s virtual address. to add the code, we' ll have to use the wjmp macro to jump to our code, and the fjmpb macro to jump back to the code. the syntax of these macros is the following :
wjmp codesnippet,offset of start,rva of start fjmpb rva of destinationbpx getmodulehandlea, and launch the program. softice breaks. note that the handle is stored in the dword at [00403014], we will use it to show how to use variales stored by the program. there' s a push 0040102bh at 0040100e wich is exactly 5 bytes, so we can replace it exactly with a jmp and then return from our code to 00401013. so the rva of start is 100eh, it' s offset is 100eh-1000h+400h=40eh, and the rva of destination of the return jump is 1013h. uncomment the wjmpb and the fjmpb and change the :
wjmp snip1start,locationoffset,locationrvato :
wjmp snip1start,40eh,100ehedit ASMcode.asm. you will see a standard function code. the getdelta is a macro that gets the delta offset of the code. uncomment the fjmpb and change the :
fjmpb locationrvato :
fjmpb 1013hthe messageboxa api is imported in the program. you can check it by looking at the list of the imports in TXTpeinfo.txt. to call an api, we need to have the address of the thunk of this api in the program. the addresses of the thunks of the imported apis or of the apis you add are automatically generated by the patcher generator as constants. the constant name is the full name of the api, in capital letters, with an underscore before the name to prevent error of already declared constants. the ordinals are imported with the prefix _ORD followed by the address in capitals of the ordinal. to call the apis, we' ll use the callpr macro, whose syntax is the following :
callpr _APINAMEsince we' ll use the handle of the instance, stored in the dword at [00403014], add the following line in DATcodedata.asm :
HTARGET equ 3014hwe also need to add the data of the messagebox, the caption and the text, so add the following lines too :
szMessageCaption db 'my caption',0 szMessageText db 'my text',0we have all we want for the messageboxa. beware that the variable you use in the code must not have been already declared in the patcher data.
edit ASMcode.asm. getdelta puts the delta offset of our code in ebp. i usually add a pushad before my code and a popad after, so i' m sure the registers will not cause problems when returning to the code. but note that you can also add code without pushad, popad and getdelta, anyway, getdelta is needed to use the variables of your added code. so after getdelta, add the following lines :
push MB_ICONINFORMATION pushl szMessageCaption pushl szMessageText push [ebp + offset codestart - VIRTUALADDRESS + HTARGET] callpr _MESSAGEBOXAyou see, at first, the patcher might seem a bit hard to use, but calling functions is very easy. there are several macros described in the lines. these are :
pushl variablepush the offset of the variable of your added code, beware, this macro uses edx.
pushv variablenot used here, push the value of the variable of your added code. the line :
push [ebp + offset codestart - VIRTUALADDRESS + HTARGET]pushes the value at the offset HTARGET in the notepad code. if you want to push the location of the variable instead of the variable itself, you would add these lines :
lea eax,[ebp + offset codestart - VIRTUALADDRESS + HTARGET] push eaxas we replaced the push 0040102bh, we will have to add it in our code. add the following line after the popad :
push 0040102bhdo never forget to replace the code you have overwritten, or the program might crash. you better try to choose correctly the places were you jump from, because some instructions that are overwritten are hard to rewrite in our code. you better jump on a mov eax,something or a push something, or instructions like that. you can try to compile the patcher.
now we' ll see how to add imports. open the patcher generator, and load the project. in the dll editbox, write kernel32.dll, the push the add button. to delete a dll, select it and push del, and to rename it, select it, change the name in the editbox, and push ren. it' s the same process to add, delete or rename a function. make sure that kernel32.dll is selected, and in the function editbox, type Beep. beware, the apis names must be the exact ones, with all the capital letters. for example, you can add MessageBoxA, but not messageboxa, nor MessageBox. click the add button, save the project, and click on generate files and select the patcher.ver file in the root of your patcher directory.
now, just before the code that calls the messagebox, write the following line :
callpr _BEEPyou can compile the patcher.
to use variables located in your data, you will do that :
mov [ebp + offset myvar],eaxto store eax in the variable myvar
mov eax,dword ptr [ebp + offset myvar]to put in eax the content of the variable myvar, or you could also do that :
lea eax,[ebp + offset myvar] mov dword ptr [eax],ebxto store ebx in the variable myvar
V. final words
you can use and modify the patcher as you like.
roy, fleur
main::fleur