Sometimes it is necessary to extend the functionality of a program to which you don't have the source code. This tutorial focuses on adding functionality to a compiled Windows Portable Executable file, but the idea can probably be implemented on other compiled binaries.
Adding simple functionality can be achieved directly in 'code caves' within the PE file by adding the assembly code directly to the exe to perform the operation (i.e. use a hex editor with assembler to render the opcodes directly into some empty space in the exe file)
The more complex the functionality, the more assembly code this will require, which needs bigger code caves and takes more coding on your part. You can create bigger code caves by adding new sections to the file, but that is not the topic of this tutorial.
An easier way, I have found, is to code the extra functionality in a DLL, which is best coded in C++/C as these are easier to import into the target app. You should use the extern "C"
macro on your exports to make them asm friendly (no mangling) and specify 'declspec(dllexport)' to make the compiler put the function in the exports..
#define ADDONS_API extern "C" __declspec(dllexport)
#define ADDONS_API __declspec(dllimport)
ADDONS_API bool someFunction(LPCTSTR someTextParam);
You can code the core of the functionality in the methods defined in your DLL and then the only assembly you need to code is loading your DLL and calling the functions.
The above function for example, will be in a DLL called 'AddOns.dll' and take 1 paramater (a pointer to a string).
In assembly code you can load the dll using the LoadLibrary
function and find the address of the function using GetProcAddress
. If the exe does not import these functions, read my other blog post on Finding the address of GetProcAddress
push &"AddOns.dll" ; address of string for the DLL, in a code cave
call &LoadLibraryA ; address of the imported/loaded LoadLibraryA function
push &"someFunction" ; address of string for the function, in a code cave
push eax ; HMODULE AddOns.dll (returned from LoadLibrary)
call &GetProcAddressA ; address of the imported/loaded GetProcAddressA function
push &"SomeString" ; address in the app to the parameter you want to pass
call eax ; call the function in the dll (returned from GetProcAddress)
add esp, 4 ; clear the stack
jmp &returnAddress ; go back to the original code?
Since C functions use the cdecl calling convention by default, you have to clean the stack of your params when you are finished and if your function returns a value, it will be in EAX.
Once you have put the above code in a cave somewhere, you simply need to jmp to it at the appropriate point in the original exe and then have it jmp back to the best place in the code to give control back to the normal program flow when you have finished.