📄 lion-tut-c29.htm
字号:
<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下将得
到奇怪的结果。可以在定义前加上"align dword"。例如: </p>
<p><b>align dword<br>
MyContext CONTEXT <></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 + -