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

📄 lion-tut-c29.htm

📁 内有一些代码
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<html>

<head>
<link rel="stylesheet" href="../../asm.css">

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Iczelion's win32 asm tutorial</title>
</head>

<body bgcolor="#FFFFFF" background="../../images/back01.jpg">
<p align="center">第29课: Win32调试API 第二部分</p>
<hr size="1">
我们继续Win32调试API的话题。在本章中,我们将要学习如何修改被调试程序。<br>
下载 <b><a href="files/tut29.zip" style="text-decoration:none">the example</a></b> 
<h3>理论:</h3>
<p>在前面一章中,我们学会了如何装载被调试的进程以及如何处理进程中发生的事件。
为了有实际用途,我们的程序应具有修改被调试程序的能力。有好几个API函数用于这
一目的。</p>
<ul>
  <li><b>ReadProcessMemory</b>该函数允许你去读指定的进程的内存。函数原型如下: 
    <p><b>ReadProcessMemory proto hProcess:DWORD, lpBaseAddress:DWORD, lpBuffer:DWORD, 
      nSize:DWORD, lpNumberOfBytesRead:DWORD</b></p>
    <p><b>hProcess</b> 待读进程的句柄.<br>
      <b>lpBaseAddress</b> 目标进程中待读内存起始地址。例如,如果你想要读目标
      进程中从地址401000h开始的4个字节,该参数值应置为401000h。<br>
      <b>lpBuffer</b> 接收缓冲区地址<br>
      <b>nSize</b> 想要读的字节数。<br>
      <b>lpNumberOfBytesRead</b> 记录实际读取的字节数的变量地址。如果对这个值
      不关心,填入NULL即可。</p>
  </li>
  <li><b>WriteProcessMemory</b> 是对应于<b>ReadProcessMemory</b>的函数,通过它
    可以写目标进程的内存。其参数和<b>ReadProcessMemory</b> 相同。
    <p>理解接下去的两个函数需要一些进程上下文的有关背景知识。在象Windows这样的
      多任务操作系统中,同一时间里可能运行着几个程序。Windows分配给每个线程一个
      时间片,当时间片结束后,Windows将冻结当前线程并切换到下一具有最高优先级的
      线程。在切换之前,Windows将保存当前进程的寄存器的 内容,这样当在该线程再
      次恢复运行时,Windows可以恢复最近一次线程运行的*环境*。保存的寄存器内容总
      称为进程上下文。<br>
      现在回到我们的主题。当一个调试事件发生时,Windows暂停被调试进程,并保存其
      进程上下文。由于进程被暂停运行,我们可以确信其进程上下文内容将保持不变。
      可以用<b>GetThreadContext</b>来获取进程上下文内容,并且也可以用<b>GetThreadContext</b>
      来修改进程上下文内容。<br>
      这两个函数威力非凡。有了他们,对被调试进程你就具有象VxD的能力: 如改变其寄
      存器内容,而在被调试程序恢复运行前,这些值将会写回寄存器中。在进程上下文中
      所做的任何改动,将都会反映到被调试程序中。想象一下: 甚至可以改变eip寄存器
      的内容,这样你可以让程序运行到你想要的任何地方! 在正常情况下是不可能做到这
      一点的。</p>
    <p><b>GetThreadContext proto hThread:DWORD, lpContext:DWORD </b></p>
    <p><b>hThread</b> 你想要获得上下文的线程句柄<br>
      <b>lpContext</b> 函数成功返回时用来保存<b>上下文</b>内容的结构指针。</p>
    <p><b>SetThreadContext</b> 参数相同。让我们来看看上下文的结构: </p>
  </li>
  <li><b>CONTEXT STRUCT <br>
    </b></li>
  <li><b>ContextFlags dd ? <br>
    ;----------------------------------------------------------------------------------------------------------<br>
	;当ContextFlags包含CONTEXT_DEBUG_REGISTERS,返回本部分</b></li>
  <li><b>;-----------------------------------------------------------------------------------------------------------<br>
    iDr0 dd ? <br>
    iDr1 dd ? <br>
    iDr2 dd ? <br>
    iDr3 dd ? <br>
    iDr6 dd ? <br>
    iDr7 dd ? <br>
    </b></li>
  <li><b>;----------------------------------------------------------------------------------------------------------<br>
	;当ContextFlags包含CONTEXT_FLOATING_POINT,返回本部分</b></li>
  <li><b>;-----------------------------------------------------------------------------------------------------------<br>
    </b></li>
  <li><b>FloatSave FLOATING_SAVE_AREA <> <br>
    </b></li>
  <li><b>;----------------------------------------------------------------------------------------------------------<br>
	;当ContextFlags包含CONTEXT_SEGMENTS,返回本部分</b></li>
  <li><b>;-----------------------------------------------------------------------------------------------------------</b></li>
  <li><b>regGs dd ? <br>
    regFs dd ? <br>
    regEs dd ? <br>
    regDs dd ? <br>
    </b></li>
  <li><b>;----------------------------------------------------------------------------------------------------------<br>
	;当ContextFlags包含CONTEXT_INTEGER,返回本部分</b></li>
  <li><b>;-----------------------------------------------------------------------------------------------------------</b></li>
  <li><b>regEdi dd ? <br>
    regEsi dd ? <br>
    regEbx dd ? <br>
    regEdx dd ? <br>
    regEcx dd ? <br>
    regEax dd ? <br>
    </b></li>
  <li><b>;----------------------------------------------------------------------------------------------------------<br>
	;当ContextFlags包含CONTEXT_CONTROL,返回本部分</b></li>
  <li><b>;-----------------------------------------------------------------------------------------------------------</b></li>
  <li><b>regEbp dd ? <br>
    regEip dd ? <br>
    regCs dd ? <br>
    regFlag dd ? <br>
    regEsp dd ? <br>
    regSs dd ? <br>
    </b></li>
  <li><b>;----------------------------------------------------------------------------------------------------------<br>
	;当ContextFlags包含CONTEXT_EXTENDED_REGISTERS,返回本部分</b></li>
  <li><b>;-----------------------------------------------------------------------------------------------------------</b></li>
  <li><b>ExtendedRegisters db MAXIMUM_SUPPORTED_EXTENSION dup(?) CONTEXT ENDS 
    </b> 
    <p>可以看出,该结构中的成员是对实际处理器的寄存器的模仿。在使用该结构之前
    要在<b>ContextFlags</b> 中指定哪些寄存器组用来读写。如要访问所有的寄存器,
    你可以置<b>ContextFlags</b> 为<b>CONTEXT_FULL</b> 。或者只访问regEbp, 
    regEip, regCs, regFlag, regEsp 或 regSs, 应置<b>ContextFlags</b> 为
    <b>CONTEXT_CONTROL</b> 。</p>
    <p>在使用结构<b>CONTEXT </b>时还应记住: 它必须是双字对齐的,否则在NT下将得
    到奇怪的结果。可以在定义前加上&quot;align dword&quot。例如: </p>
    <p><b>align dword<br>
      MyContext CONTEXT &lt;&gt;</b></p>
  </li>
</ul>
<h3>例:</h3>
<p>第一个例子演示<b>DebugActiveProcess</b>的使用。首先,需要在Windows显示在屏
幕上以前运行一个待调试程序win.exe,该程序将处于无限循环运行状态中。然后你运行
例子程序,它将把自己与win.exe连接起来,并且修改win.exe的代码,这样win.exe将退
出无限循环状态而显示自己的窗口。</p>
<p>.386 <br>
  .model flat,stdcall <br>
  option casemap:none <br>
  include \masm32\include\windows.inc <br>
  include \masm32\include\kernel32.inc <br>
  include \masm32\include\comdlg32.inc <br>
  include \masm32\include\user32.inc <br>
  includelib \masm32\lib\kernel32.lib <br>
  includelib \masm32\lib\comdlg32.lib <br>
  includelib \masm32\lib\user32.lib <br>
  <br>
  .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>
  <br>
  .data? <br>
  DBEvent DEBUG_EVENT <> <br>
  ProcessId dd ? <br>

⌨️ 快捷键说明

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