tutorial 29: win32 debug api part 2
we continue with the subject of win32 debug api. in this tutorial, we will learn how to modify the debuggee process.
theory:
in the previous tutorial, we know how to load the debuggee and handle debug events that occur in its process. in order to be useful, our program must be able to modify the debuggee process. there are several apis just for this purpose.
- readprocessmemory this function allows you to read memory in the specified process. the function prototype is as follows:
readprocessmemory proto hprocess:dword, lpbaseaddress:dword, lpbuffer:dword, nsize:dword, lpnumberofbytesread:dword
hprocess is the handle to the process you want to read.
lpbaseaddress is the address in the target process you want to start reading. for example, if you want to read 4 bytes from the debuggee process starting at 401000h, the value in this parameter must be 401000h.
lpbuffer is the address of the buffer to receive the bytes read from the process.
nsize is the number of bytes you want to read
lpnumberofbytesread is the address of the variable of dword size that receives the number of bytes actually read. if you don't care about it, you can use null. - writeprocessmemory is the counterpart of readprocessmemory. it enables you to write memory of the target process. its parameters are exactly the same as those of readprocessmemory
the next two api functions need a little background on context. under a multitasking os like windows, there can be several programs running at the same time. windows gives each thread a timeslice. when that timeslice expires, windows freezes the present thread and switches to the next thread that has the highest priority. just before switching to the other thread, windows saves values in registers of the present thread so that when the time comes to resume the thread, windows can restore the last *environment* of that thread. the saved values of the registers are collectively called a context.
back to our subject. when a debug event occurs, windows suspends the debuggee. the debuggee's context is saved. since the debuggee is suspended, we can be sure that the values in the context will remain unchanged . we can get the values in the context with getthreadcontext and we can change them with setthreadcontext.
these two apis are very powerful. with them, you have at your fingertips the vxd-like power over the debuggee: you can alter the saved register values and just before the debuggee resumes execution, the values in the context will be written back into the registers. any change you made to the context is reflected back to the debuggee. think about it: you can even alter the value of the eip register and divert the flow of execution to anywhere you like! you won't be able to do that under normal circumstance.getthreadcontext proto hthread:dword, lpcontext:dword
hthread is the handle to the thread that you want to obtain the context from
lpcontext is the address of the context structure that will be filled when the function returns successfully.setthreadcontext has exactly the same parameters. let's see what a context structure looks like:
- context struct
- contextflags dd ?
;----------------------------------------------------------------------------------------------------------
; this section is returned if contextflags contains the value context_debug_registers - ;-----------------------------------------------------------------------------------------------------------
idr0 dd ?
idr1 dd ?
idr2 dd ?
idr3 dd ?
idr6 dd ?
idr7 dd ?
- ;----------------------------------------------------------------------------------------------------------
; this section is returned if contextflags contains the value context_floating_point - ;-----------------------------------------------------------------------------------------------------------
- floatsave floating_save_area <>
- ;----------------------------------------------------------------------------------------------------------
; this section is returned if contextflags contains the value context_segments - ;-----------------------------------------------------------------------------------------------------------
- reggs dd ?
regfs dd ?
reges dd ?
regds dd ?
- ;----------------------------------------------------------------------------------------------------------