We continue with the subject of win32 
  debug API. In this tutorial, we will learn how to modify the debuggee process.
  Download the example
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 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.
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:
As you can observe, the members of this structures are mimics of the real processor's registers. Before you can use this structure, you need to specify which groups of registers you want to read/write in ContextFlags member. For example, if you want to read/write all registers, you must specify CONTEXT_FULL in ContextFlags. If you want only to read/write regEbp, regEip, regCs, regFlag, regEsp or regSs, you must specify CONTEXT_CONTROL in ContextFlags.
One thing you must remember when using the CONTEXT structure: it must be aligned on dword boundary else you'd get strange results under NT. You must put "align dword" just above the line that declares it, like this:
align dword
      MyContext CONTEXT <>
The first example demonstrates the use of DebugActiveProcess. First, you need to run a target named win.exe which goes in an infinite loop just before the window is shown on the screen. Then you run the example, it will attach itself to win.exe and modify the code of win.exe such that win.exe exits the infinite loop and shows its own window.
.386 
  .model flat,stdcall 
  option casemap:none 
  include \masm32\include\windows.inc 
  include \masm32\include\kernel32.inc 
  include \masm32\include\comdlg32.inc 
  include \masm32\include\user32.inc 
  includelib \masm32\lib\kernel32.lib 
  includelib \masm32\lib\comdlg32.lib 
  includelib \masm32\lib\user32.lib 
  
  .data 
  AppName db "Win32 Debug Example no.2",0 
  ClassName db "SimpleWinClass",0 
  SearchFail db "Cannot find the target process",0 
  TargetPatched db "Target patched!",0 
  buffer dw 9090h
  
  .data? 
  DBEvent DEBUG_EVENT <> 
  ProcessId dd ? 
  ThreadId dd ? 
  align dword 
  context CONTEXT <> 
  
  .code 
  start: 
  invoke FindWindow, addr ClassName, NULL 
  .if eax!=NULL 
      invoke GetWindowThreadProcessId, eax, addr ProcessId 
      mov ThreadId, eax 
      invoke DebugActiveProcess, ProcessId 
      .while TRUE 
         invoke WaitForDebugEvent, addr DBEvent, 
  INFINITE 
         .break .if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT 
  
         .if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT 
  
            mov context.ContextFlags, 
  CONTEXT_CONTROL 
            invoke GetThreadContext,DBEvent.u.CreateProcessInfo.hThread, 
  addr context           
            invoke WriteProcessMemory, 
  DBEvent.u.CreateProcessInfo.hProcess, context.regEip ,addr buffer, 2, NULL
            invoke MessageBox, 0, 
  addr TargetPatched, addr AppName, MB_OK+MB_ICONINFORMATION 
         .elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT 
  
            .if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT 
  
               invoke 
  ContinueDebugEvent, DBEvent.dwProcessId,DBEvent.dwThreadId, DBG_CONTINUE 
               .continue 
  
            .endif 
         .endif 
         invoke ContinueDebugEvent, DBEvent.dwProcessId, 
  DBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED 
     .endw 
  .else 
      invoke MessageBox, 0, addr SearchFail, addr AppName,MB_OK+MB_ICONERROR 
  .endif 
  invoke ExitProcess, 0 
  end start 
;--------------------------------------------------------------------
  ; The partial source code of win.asm, our debuggee. It's actually
  ; the simple window example in tutorial 2 with an infinite loop inserted
  ; just before it enters the message loop.
  ;----------------------------------------------------------------------
......
  mov wc.hIconSm,eax 
  invoke LoadCursor,NULL,IDC_ARROW 
  mov wc.hCursor,eax 
  invoke RegisterClassEx, addr wc 
  INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\ WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\ 
  CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\ hInst,NULL 
  mov hwnd,eax 
  jmp $ <---- Here's our infinite loop. It assembles 
  to EB FE
  invoke ShowWindow, hwnd,SW_SHOWNORMAL 
  invoke UpdateWindow, hwnd 
  .while TRUE 
     invoke GetMessage, ADDR msg,NULL,0,0 
     .break .if (!eax) 
     invoke TranslateMessage, ADDR msg 
     invoke DispatchMessage, ADDR msg 
  .endw 
  mov eax,msg.wParam 
  ret 
  WinMain endp 
invoke FindWindow, addr ClassName, NULL
Our program needs to attach itself to 
  the debuggee with DebugActiveProcess which 
  requires the process Id of the debuggee. We can obtain the process Id by calling 
   GetWindowThreadProcessId which in turn 
  needs the window handle as its parameter. So we need to obtain the window handle 
  first. 
  With FindWindow, we can specify the name 
  of the window class we need. It returns the handle to the window created by 
  that window class. If it returns NULL, no 
  window of that class is present.
 .if eax!=NULL 
      invoke GetWindowThreadProcessId, eax, addr ProcessId 
      mov ThreadId, eax 
      invoke DebugActiveProcess, ProcessId 
After we obtain the process Id, we can call DebugActiveProcess. Then we enter the debug loop waiting for the debug events.
       .if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT 
  
            mov context.ContextFlags, 
  CONTEXT_CONTROL 
            invoke GetThreadContext,DBEvent.u.CreateProcessInfo.hThread, 
  addr context           
When we get CREATE_PROCESS_DEBUG_INFO, 
  it means the debuggee is suspended, ready for us to do surgery upon its process. 
  In this example, we will overwrite the infinite loop instruction in the debuggee 
  (0EBh 0FEh) with NOPs ( 90h 90h). 
  First, we need to obtain the address of the instruction. Since the debuggee 
  is already in the loop by the time our program attached to it, eip will always 
  point to the instruction. All we need to do is obtain the value of eip. We use 
   GetThreadContext to achieve that goal. 
  We set the ContextFlags member to CONTEXT_CONTROL 
  so as to tell GetThreadContext 
  that we want it to fill the "control" register members of the 
  CONTEXT structure.
invoke WriteProcessMemory, DBEvent.u.CreateProcessInfo.hProcess, context.regEip ,addr buffer, 2, NULL
Now that we get the value of eip, we can call WriteProcessMemory to overwrite the "jmp $" instruction with NOPs, thus effectively help the debuggee exit the infinite loop. After that we display the message to the user and then call ContinueDebugEvent to resume the debuggee. Since the "jmp $" instruction is overwritten by NOPs, the debuggee will be able to continue with showing its window and enter the message loop. The evidence is we will see its window on screen.
The other example uses a slightly different approach to break the debuggee out of the infinite loop.
 .......
  .......
  .if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT 
     mov context.ContextFlags, CONTEXT_CONTROL 
     invoke GetThreadContext,DBEvent.u.CreateProcessInfo.hThread, 
  addr context 
     add context.regEip,2 
     invoke SetThreadContext,DBEvent.u.CreateProcessInfo.hThread, 
  addr context 
     invoke MessageBox, 0, addr LoopSkipped, addr AppName, MB_OK+MB_ICONINFORMATION 
  
  .......
  ....... 
It still calls GetThreadContext to obtain the current value of eip but instead of overwriting the "jmp $" instruction, it increments the value of regEip by 2 to "skip over" the instruction. The result is that when the debuggee regains control , it resumes execution at the next instruction after "jmp $".
Now you can see the power of Get/SetThreadContext. You can also modify the other register images as well and their values will be reflected back to the debuggee. You can even insert int 3h instruction to put breakpoints in the debuggee process.