上一章讲解了如何用调试API来打开一个被调试程序,并给出了一个简单的例子,这一章将祥细
讲解调试消息包含的内容.
类似于消息处理中的消息结构TMessage一样,调试事件也有自己特定的事件结构,那就是TDeb
ugEvent, TDebugEvent在Delphi中的定义为:
TDebugEvent = _DEBUG_EVENT;
_DEBUG_EVENT = record
dwDebugEventCode: DWORD;
dwProcessId: DWORD;
dwThreadId: DWORD;
case Integer of
0: (Exception: TExceptionDebugInfo);
1: (CreateThread: TCreateThreadDebugInfo);
2: (CreateProcessInfo: TCreateProcessDebugInfo);
3: (ExitThread: TExitThreadDebugInfo);
4: (ExitProcess: TExitThreadDebugInfo);
5: (LoadDll: TLoadDLLDebugInfo);
6: (UnloadDll: TUnloadDLLDebugInfo);
7: (DebugString: TOutputDebugStringInfo);
8: (RipInfo: TRIPInfo);
end;
这个结构很复杂,包含了三个基本类型和一个联合类型的数据.dwProcessId和dwThreadId指明
了产生调试事件的进程和线程的ID,dwDebugEventCode指明了产生了何种调试事件,可能的取值
如下表(摘自<<Win32汇编程序设计>>):
1.CREATE_PROCESS_DEBUG_EVENT:进程被创建.当被调试进程刚被创建(还未运行) 或我们的程
序刚以DebugActiveProcess捆绑到一个运行中的进程时该事件发生. 这是我们的程序应该获得
的第一个事件.
2.EXIT_PROCESS_DEBUG_EVENT:被调试进程退出时产生此消息.
3.CREATE_THEAD_DEBUG_EVENT:当一个新线程在被调试进程中创建或我们的程序首次捆绑到运
行中的进程时该事件发生.要注意的是当被调试进程的主线程被创建时不会收到该通知.
4.EXIT_THREAD_DEBUG_EVENT:被调试进程中的线程退出时事件发生.被调试进程的主线程退出
时不会收到该通知.我们可以认为被调试进程的主线程与被调试进程是同义词. 因此, 当我们
的程序看到CREATE_PROCESS_DEBUG_EVENT标志时,对主线程来说,就是CREATE_THREAD_DEBUG_E
VENT标志.
5.LOAD_DLL_DEBUG_EVENT:被调试进程装入一个DLL.当PE装载器第一次分解指向DLL的链接时
,我们将收到这一事件. (当调用CreateProcess装入 被调试进程时)并且当被调试进程调用Lo
adLibrary时也会发生.
6.UNLOAD_DLL_DEBUG_EVENT:一个DLL从被调试进程中卸载时此事件发生.
7.EXCEPTION_DEBUG_EVENT:在被调试进程中发生异常时事件发生.异常实际上是一个调试中断
(int 3h).如果想恢复被调试进程事,以 DBG_CONTINUE 标志调用ContinueDebugEvent 函数.
不要使用DBG_EXCEPTION_NOT_HANDLED 标志否则被调试进程会在NT下拒绝运行(Win98下运行得
很好).
8.OUTPUT_DEBUG_STRING_EVENT:当被调试进程调用DebugOutputString函数向我们的程序发送
消息字符串时该事件发生.
9.RIP_EVENT:系统调试发生错误.
根据dwDebugEventCode的不同,应调用联合中相应的结构来获得相关的调试信息.例如我们有
个名为Debug的TDebguEvent的结构,在调用WaitForDebugEvent(Debug, INFINITE)后接收到调
试信息时,并且dwDebugEventCode的值为CREATE_PROCESS_DEBUG_EVENT,我们就可以通过仿问D
ebug.CreateProcessInfo.hProcess来获得刚创建的被调试进程的进程句柄.
下面将祥细讲解TDebugEvent结构中可能包括的每个结构的含义.因为没有相关的祥细资料,大
部分结果是靠测试所得,如有错漏敬请指正.
一.CreateProcessInfo结构: 对应的调试消息CREATE_PROCESS_DEBUG_EVENT.
CreateProcessInfo.hFile:被调试进程的EXE文件被映射到内存中的内存文件映射句柄,可以
通过打开这个句柄(用OpenFileMapping和MapViewOfFile)来读取此EXE文件的相关信息.如引入
引出表等.
CreateProcessInfo.hProcess:被调试进程的进程句柄,如果要使用ReadProcessMemory和Wri
teProcessMemory等函数来修改被调试进程,就需要用到这个句柄,可以用一个变量保存起来供
以后使用.
CreateProcessInfo.hThread:主线程句柄.
CreateProcessInfo.lpBaseOfImage:可执行文件被装载到虚似地址空间中的基址.
CreateProcessInfo.dwDebugInfoFileOffset:调试信息在可执行文件中的偏移地址(一般为0
,即没有调试信息).
CreateProcessInfo.nDebugInfoSize:调试信息的长度.
CreateProcessInfo.lpThreadLocalBase:主线程基址.
CreateProcessInfo.lpStartAddress:主线程的线程函数地址.
CreateProcessInfo.lpImageName:文件映像名,注意这是一个RVA地址(相对虚拟地址).
CreateProcessInfo.fUnicode:如果此值大于0,则lpImageName指向的文件名为UNICODE码.
二.ExitProcess结构: 对应的调试消息EXIT_PROCESS_DEBUG_EVENT.
ExitProcess.dwExitCode:即被调试程序调用ExitProcess函数时传入的退出代码.
三.CreateThread结构: 对应的调试消息CREATE_THEAD_DEBUG_EVENT.
CreateThread.hThread:新建线程的句柄.线程句柄,如果以后会涉及到对线程的操作,如挂起
线程等,则可以用一个TList来保存进程ID(TDebugEvent.dwThreadId)和相对应的句柄.再在其
它调试事件发生时,根据dwThreadId得到线程句柄.
CreateThread.lpThreadLocalBase:新线程的基址.
CreateThread.lpStartAddress:新线程的线程函数地址.
四.ExitThread结构: 对应的调试消息EXIT_THREAD_DEBUG_EVENT.
ExitThread.dwExitCode:即退出的线程调用ExitThread函数时传入的退出代码.
五.LoadDll结构: 对应的调试消息LOAD_DLL_DEBUG_EVENT.
LoadDll.hFile:被加载的DLL文件映射到内存中的内存文件映射句柄,可以通过打开这个句柄
来读取此DLL文件的相关信息.
LoadDll.lpBaseOfDll:DLL文件被装载到虚似地址空间中的基址.这个地址加上DLL文件引出的
函数的地址,就是这个函数在内存中的地址.
LoadDll.dwDebugInfoFileOffset:调试信息在DLL文件中的偏移地址.
LoadDll.nDebugInfoSize:调试信息的长度.
LoadDll.lpImageName:DLL文件名的地址,是一个RVA地.
LoadDll.fUnicode:如果此值大于0,则lpImageName指向的文件名为UNICODE码.
六.UnLoadDll结构: 对应的调试消息UNLOAD_DLL_DEBUG_EVENT.
UnloadDll.lpBaseOfDll:卸载的DLL文件的基址,可以通过在处理LOAD_DLL_DEBUG_EVENT消息
中保存DLL信息和对应的基址的方法,来得到卸载的DLL信息.
七.Exception结构: 对应的调试消息EXCEPTION_DEBUG_EVENT.
Exception.ExceptionRecord: 这是一个TExceptionRecord结构,里面包含了被调试程序产生
的中断或异常的代码,产生的中断或异常的地址等信息.
八.DebugString结构: 对应的调试消息OUTPUT_DEBUG_STRING_EVENT.
DebugString.lpDebugStringData:被调试进程调用DebugOutputString函数发送的消息字符串
的地址.
DebugString.nDebugStringLength:被调试进程调用DebugOutputString函数发送的消息字符
串的长度.
DebugString.fUnicode:如果此值大于0,则消息字符串为UNICODE码.
九.RipInfo结构: 对应的调试消息RIP_EVENT.
RipInfo.dwError:错误代码.
RipInfo.dwType:错误类型.
了解了以上的知识,我们就可以在调试器中监视这些调试消息,并获得我们感兴趣的信息.但这
仅仅实现了对被调试调试程序的监视.下一章将讲解如何修改被调试程序.
附:一个监视目标程序启动,加载DLL,退出的例子,并演示了如何读取RVA地址,获得加载的DLL
文件名的方法.请到下面的地址下载.
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!
Win32调试API学习心得(二)
来源:互联网
作者:西部数码
时间:2008-04-10
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!
热点关注
- AnsiString?PChar?赋值
- Report Machine 3.0 (报表
- MapX v5.02.25 破解文件
- WDBOX v1.0 多选下拉列表
- 用Delphi开发视频聊天软件
- Delphi客户服务器应用开发
- AES 加密算法函数包及演示
- ACCESS/SQL 数据库存取图
- 熊猫烧香核心源码(Delphi
- 把整个网页保存成JPG图片(
- 高级计算器 V1.0 (含代码)
- Delphi版模仿熊猫烧香病毒
- 精确定位打印程序 (含源代
- Delphi文件管理(六)
- 将数字四舍五入保留两位小
- 绝地程序编辑器 v1.0.1.4
- 关于自定义界面的方案(Eas
- Delphi 对象链接与嵌入(
- 用HTML页面做程序界面演示
- Delphi模拟最小化恢复关闭
- 用Delphi实现24位真彩色图
- 限制客户机运行程序 (有关
- Delphi中用API实现在MSN的
- DELPHI数据库应用程序的开
- Delphi 动态链接库编程(
- QQ号码自动申请器及源代码
- Win9x 下调整系统时钟控件
- delphi中的XML解析控件TXM
- 几个游戏内存修改器代码
- TT8 DevExpress 最新系列
- Tnt Delphi Unicode Contr
- DelphiTwain 2004-1-20 (
- Delphi中数据的自动录入
- 经验技巧:分享两条Delphi
- Delphi中Hash表的使用方法
IDC资讯
虚拟主机
域名注册
托管租用
vps主机
智能建站
网站运营 建站经验 策划盈利 搜索优化 网站推广 免费资源
网站联盟 联盟新闻 联盟介绍 联盟点评 网赚技巧
行业资讯 业界动态 搜索引擎 网络游戏 门户动态 电子商务 广告传媒
网络编程 Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术 Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷 Internet Explorer
网页制作 FrontPages Dreamweaver Javascript css photoshop fireworks Flash
程序设计 Java技术 C/C++ VB delphi
网络知识 网络协议 网络安全 网络管理 组网方案 Cisco技术
操作系统 Win2000 WinXP Win2003 Mac OS Linux FreeBSD
网站运营 建站经验 策划盈利 搜索优化 网站推广 免费资源
网站联盟 联盟新闻 联盟介绍 联盟点评 网赚技巧
行业资讯 业界动态 搜索引擎 网络游戏 门户动态 电子商务 广告传媒
网络编程 Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术 Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷 Internet Explorer
网页制作 FrontPages Dreamweaver Javascript css photoshop fireworks Flash
程序设计 Java技术 C/C++ VB delphi
网络知识 网络协议 网络安全 网络管理 组网方案 Cisco技术
操作系统 Win2000 WinXP Win2003 Mac OS Linux FreeBSD



