Saturday, March 05 2005 @ 08:21 PM CET Contributed by: detten Views: 15600
Level : beginner
OS : windows
Language : ASM
How to code a basic loader that pauses a process, alters some process memory and continues execution.
TARGET = attachment
TOOLS USED = Assembler : MASM 7.0
What is a loader, and why do we need it?
A loader is a little standalone program that is used to load another program.
Of course we will only use a loader if we want to change something in the program
after it is loaded in the memory. (patching in memory)
A well known example of a loader is a trainer used to cheat in games.
The reasons why we choose for a loader instead of a regular patch can be various.
We might only want to change something after the CRC is done, or we might want to
change something and later in the program restore the original bytes,...
I'm sure you can find some use for it :)
How does a loader work?
Ok, grab your win32.hlp and fasten your seatbelt :)
First of all, the loader has to create a new process and start the target. We will use
the CreateProcess API for that (pretty obvious ;)
When the target is loaded in memory we want to pause the process, so we can change the
things we want.
Let's check out what win32.hlp can tell us about this API :
LPCTSTR lpApplicationName, // pointer to name of executable module
LPTSTR lpCommandLine, // pointer to command line string
LPSECURITY_ATTRIBUTES lpProcessAttributes, // pointer to process security attributes
LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to thread security attributes
BOOL bInheritHandles, // handle inheritance flag
DWORD dwCreationFlags, // creation flags
LPVOID lpEnvironment, // pointer to new environment block
LPCTSTR lpCurrentDirectory, // pointer to current directory name
LPSTARTUPINFO lpStartupInfo, // pointer to STARTUPINFO
LPPROCESS_INFORMATION lpProcessInformation // pointer to PROCESS_INFORMATION
Check all the API's I mention here in your win32.hlp document, because I will only discuss
the things that are important for our loader.
lpApplicationName is the path + name of our target program. (eg c:somedircrackme.exe)
lpCommandLine can be used if you want to add some commandline parameters to the target.
dwCreationFlags is important for us, because we want to pause the process as soon as it is
loaded. To accomplish that, we use CREATE_SUSPENDED here.
lpStartupInfo points to a struct with startup information (again check win32.hlp for more info)
lpProcessInformation points to an empty struct that will be filled when the target is loaded in
memory. This struct contains the process handle, thread handle and process/thread ID.
NOTE : The advantage of using the process handle instead of the thread handle, is that when using
the process handle you have PROCESS_ALL_ACCESS access to the process object. Meaning that you have
read/write access for the entire process. When using the thread handle, you will need to enable
write access manualy.
Ok, now that the target is loaded, we can easily let the thread run/pause with the following API's :
HANDLE hThread // identifies thread to restart
to let it run, and
HANDLE hThread // handle to the thread
to pause it again.
The hThread handle can be found in the LPPROCESS_INFORMATION struct.
Finally we can read and write from/to the process using these API's :
HANDLE hProcess, // handle to process whose memory is written to
LPVOID lpBaseAddress, // address to start writing to
LPVOID lpBuffer, // pointer to buffer to write data to
DWORD nSize, // number of bytes to write
LPDWORD lpNumberOfBytesWritten // actual number of bytes written
This is pretty self-explanatory. The hProcess handle is the one from the LPPROCESS_INFORMATION struct.
To read from the process :
HANDLE hProcess, // handle of the process whose memory is read
LPCVOID lpBaseAddress, // address to start reading
LPVOID lpBuffer, // address of buffer to place read data
DWORD nSize, // number of bytes to read
LPDWORD lpNumberOfBytesRead // address of number of bytes read
This information should be enough to understand the following example.
A loader example
In the example below I will open a crackme (in target.zip) and change the caption text to
"Detten's Caption". I will show the process for 5 seconds, and then terminate the process.
So here we patch a simple string, but with the same method we can also patch code bytes or dwords
of course ;)
As preparation for the loader we need to know the address where the caption string is saved
in the target. So fire up your favorite disassembler, and find this address : 004050FCh
FileName db "C:\somedircrackme.exe",0
notloaded db "It did not work :-(",0
Letsgo db "The process is started",13,10,
"Let's change smthg and run it now :-)",0
NewText db "Dettens Caption",0
Startup STARTUPINFO <>
processinfo PROCESS_INFORMATION <>
hInstance HINSTANCE ?
byteswritten dd ?
uExitCode dd ?
invoke GetModuleHandleA, NULL
; Create a process and load the crackme in it, and
; immediatly suspend the thread (pause it)
invoke CreateProcess, ADDR FileName, NULL, NULL, NULL, NULL, CREATE_SUSPENDED,
NULL, NULL, ADDR Startup, ADDR processinfo
.IF eax == NULL ; Creation of new process failed?
invoke MessageBox, NULL, ADDR notloaded, NULL, MB_ICONEXCLAMATION
invoke MessageBox, NULL, ADDR Letsgo, NULL, MB_OK ; Display Message
; I will change the text string in the crackme used in
; the captionbar (004050FCh)
invoke WriteProcessMemory, processinfo.hProcess, 004050FCh, ADDR NewText,
; Let the process run happily ;)
invoke ResumeThread, processinfo.hThread
;Let the process run for 5 sec. and then terminate it
invoke Sleep, 5000
invoke TerminateProcess, processinfo.hProcess, uExitCode
That's all it takes to create a loader ;)
In the next loader tutorial I will discuss some more advanced loader techniques, like
reading and changing the process context (all registers and flags).
If you have questions, remarks, or suggestions contact me at detten(at)reversing(dot)be