⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tut29.html

📁 WINDOWS程序员使用指南--汇编基础
💻 HTML
📖 第 1 页 / 共 2 页
字号:
  .data <br>
  AppName db "Win32 Debug Example no.2",0 <br>
  ClassName db "SimpleWinClass",0 <br>
  SearchFail db "Cannot find the target process",0 <br>
  TargetPatched db "Target patched!",0 <br>
  buffer dw 9090h<br>
  </font><font face="Fixedsys" size="-1"><br>
  .data? <br>
  DBEvent DEBUG_EVENT <> <br>
  ProcessId dd ? <br>
  ThreadId dd ? <br>
  align dword <br>
  context CONTEXT <> <br>
  <br>
  .code <br>
  start: <br>
  invoke FindWindow, addr ClassName, NULL <br>
  .if eax!=NULL <br>
  &nbsp;&nbsp;&nbsp; invoke GetWindowThreadProcessId, eax, addr ProcessId <br>
  &nbsp;&nbsp;&nbsp; mov ThreadId, eax <br>
  &nbsp;&nbsp;&nbsp; invoke DebugActiveProcess, ProcessId <br>
  &nbsp;&nbsp;&nbsp; .while TRUE <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke WaitForDebugEvent, addr DBEvent, 
  INFINITE <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .break .if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov context.ContextFlags, 
  CONTEXT_CONTROL <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke GetThreadContext,DBEvent.u.CreateProcessInfo.hThread, 
  addr context &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke WriteProcessMemory, 
  DBEvent.u.CreateProcessInfo.hProcess, context.regEip ,addr buffer, 2, NULL<br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke MessageBox, 0, 
  addr TargetPatched, addr AppName, MB_OK+MB_ICONINFORMATION <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke 
  ContinueDebugEvent, DBEvent.dwProcessId,DBEvent.dwThreadId, DBG_CONTINUE <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .continue 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .endif <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .endif <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke ContinueDebugEvent, DBEvent.dwProcessId, 
  DBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED <br>
  &nbsp;&nbsp;&nbsp;.endw <br>
  .else <br>
  &nbsp;&nbsp;&nbsp; invoke MessageBox, 0, addr SearchFail, addr AppName,MB_OK+MB_ICONERROR 
  .endif <br>
  invoke ExitProcess, 0 <br>
  end start </font></p>
<p><font face="Fixedsys"><font size="-1">;--------------------------------------------------------------------<br>
  ; The partial source code of win.asm, our debuggee. It's actually<br>
  ; the simple window example in tutorial 2 with an infinite loop inserted<br>
  ; just before it enters the message loop.<br>
  ;----------------------------------------------------------------------</font></font></p>
<p><font face="Fixedsys">......<br>
  mov wc.hIconSm,eax <br>
  invoke LoadCursor,NULL,IDC_ARROW <br>
  mov wc.hCursor,eax <br>
  invoke RegisterClassEx, addr wc <br>
  INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\ WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\ 
  CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\ hInst,NULL <br>
  mov hwnd,eax <br>
  <font color="#FF6666">jmp $ &lt;---- Here's our infinite loop. It assembles 
  to EB FE</font><br>
  invoke ShowWindow, hwnd,SW_SHOWNORMAL <br>
  invoke UpdateWindow, hwnd <br>
  .while TRUE <br>
  &nbsp;&nbsp;&nbsp;invoke GetMessage, ADDR msg,NULL,0,0 <br>
  &nbsp;&nbsp;&nbsp;.break .if (!eax) <br>
  &nbsp;&nbsp;&nbsp;invoke TranslateMessage, ADDR msg <br>
  &nbsp;&nbsp;&nbsp;invoke DispatchMessage, ADDR msg <br>
  .endw <br>
  mov eax,msg.wParam <br>
  ret <br>
  WinMain endp </font></p>
<h3><font face="Arial, Helvetica, sans-serif">Analysis:</font></h3>
<p><font face="Fixedsys" size="-1">invoke FindWindow, addr ClassName, NULL </font></p>
<p><font face="MS Sans Serif" size="-1">Our program needs to attach itself to 
  the debuggee with <font color="#FFFFCC"><b>DebugActiveProcess </b></font>which 
  requires the process Id of the debuggee. We can obtain the process Id by calling 
  <font color="#FFFFCC"> <b>GetWindowThreadProcessId </b></font>which in turn 
  needs the window handle as its parameter. So we need to obtain the window handle 
  first. <br>
  With <font color="#FFFFCC"><b>FindWindow</b></font>, 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<font color="#CCFFCC"><b> NULL</b></font>, no 
  window of that class is present.</font></p>
<p><font face="Fixedsys" size="-1"> .if eax!=NULL <br>
  &nbsp;&nbsp;&nbsp; invoke GetWindowThreadProcessId, eax, addr ProcessId <br>
  &nbsp;&nbsp;&nbsp; mov ThreadId, eax <br>
  &nbsp;&nbsp;&nbsp; invoke DebugActiveProcess, ProcessId </font></p>
<p><font face="MS Sans Serif" size="-1">After we obtain the process Id, we can 
  call <font color="#FFFFCC"><b>DebugActiveProcess</b></font>. Then we enter the 
  debug loop waiting for the debug events.</font></p>
<p><font face="Fixedsys" size="-1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov context.ContextFlags, 
  CONTEXT_CONTROL <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke GetThreadContext,DBEvent.u.CreateProcessInfo.hThread, 
  addr context &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></p>
<p><font face="MS Sans Serif" size="-1">When we get<font color="#CCFFCC"><b> CREATE_PROCESS_DEBUG_INFO</b></font>, 
  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). <br>
  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 
  <font color="#FFFFCC"> <b>GetThreadContext</b></font> to achieve that goal. 
  We set the <font color="#CCFFCC"><b>ContextFlags</b></font> member to <font color="#CCFFCC"><b>CONTEXT_CONTROL 
  </b></font>so as to tell <font color="#FFFFCC"><b>GetThreadContext</b></font> 
  that we want it to fill the &quot;control&quot; register members of the<font color="#CCFFCC"><b> 
  CONTEXT</b></font> structure.</font></p>
<p><font face="Fixedsys" size="-1"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  invoke WriteProcessMemory, DBEvent.u.CreateProcessInfo.hProcess, context.regEip 
  ,addr buffer, 2, NULL</font></p>
<p><font face="Fixedsys" size="-1"> </font><font face="MS Sans Serif" size="-1">Now 
  that we get the value of eip, we can call <font color="#FFFFCC"><b>WriteProcessMemory</b></font> 
  to overwrite the &quot;jmp $&quot; instruction with NOPs, thus effectively help 
  the debuggee exit the infinite loop. After that we display the message to the 
  user and then call <font color="#FFFFCC"><b>ContinueDebugEvent</b></font> to 
  resume the debuggee. Since the &quot;jmp $&quot; 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.</font></p>
<p><font face="MS Sans Serif" size="-1">The other example uses a slightly different 
  approach to break the debuggee out of the infinite loop.</font></p>
<p> <font face="Fixedsys">.......<br>
  .......<br>
  .if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT <br>
  &nbsp;&nbsp;&nbsp;mov context.ContextFlags, CONTEXT_CONTROL <br>
  &nbsp;&nbsp;&nbsp;invoke GetThreadContext,DBEvent.u.CreateProcessInfo.hThread, 
  addr context <br>
  &nbsp;&nbsp;&nbsp;add context.regEip,2 <br>
  &nbsp;&nbsp;&nbsp;invoke SetThreadContext,DBEvent.u.CreateProcessInfo.hThread, 
  addr context <br>
  &nbsp;&nbsp;&nbsp;invoke MessageBox, 0, addr LoopSkipped, addr AppName, MB_OK+MB_ICONINFORMATION 
  <br>
  .......<br>
  ....... </font></p>
<p><font face="MS Sans Serif" size="-1">It still calls <font color="#FFFFCC"><b>GetThreadContext</b></font> 
  to obtain the current value of eip but instead of overwriting the &quot;jmp 
  $&quot; instruction, it increments the value of<font color="#FFCCCC"><b> regEip</b></font> 
  by 2 to &quot;skip over&quot; the instruction. The result is that when the debuggee 
  regains control , it resumes execution at the next instruction after &quot;jmp 
  $&quot;. </font></p>
<p><font face="MS Sans Serif" size="-1">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.</font></p>
<hr>
<div align="center"><br>
  <font color="#FFFFFF"><b><font face="MS Sans Serif" size="-1">[<a href="http://win32asm.cjb.net">Iczelion's 
  Win32 Assembly Homepage</a>] </font></b></font></div>
<p>&nbsp;</p>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -