调试器开发实例_调试器框架设计

作为一个安全开发人员离不开调试器,它可以动态显示程序的执行过程,对于解决程序问题有极大的帮助,这些文章记录了我开发一个调试器雏形的过程,希望对你有帮助。或许我写的代码很拙劣,还请大家多多见谅!

我们使用  Microsoft Visual Studio 6.0 VC编译器来作为我们的开发工具
想对一个程序进行调试,首先要做的当然是启动这个程序,这要使用CreateProcess这个Windows API来完成。
例如:

 1 // LilisiDebug.cpp : Defines the entry point for the console application.
 2 //
 3
 4 #include "stdafx.h"
 5 #include <windows.h>
 6
 7 int main(int argc, char* argv[])
 8 {
 9     STARTUPINFO si = { 0 };
10     si.cb = sizeof(si);
11     PROCESS_INFORMATION pi = { 0 };
12
13     BOOL bRet = CreateProcess(TEXT("C:\\windows\\system32\\calc.exe"),
14                               NULL,
15                               NULL,
16                               NULL,
17                               FALSE,
18                               DEBUG_ONLY_THIS_PROCESS | CREATE_NEW_CONSOLE,
19                               NULL,
20                               NULL,
21                               &si,
22                               &pi);
23
24         if ( bRet == FALSE)
25         {
26
27             printf("Open Debug Process Error!");
28             return -1;
29         }
30         CloseHandle(pi.hThread);
31         CloseHandle(pi.hProcess);
32         return 0;
33 }

CreateProcess的第六个参数使用了DEBUG_ONLY_THIS_PROCESS,这意味着调用CreateProcess的进程成为了调试器,而它启动的子进程成了被调试的进程。
在第六个参数之中也可以加上CREATE_NEW_CONSOLE ,他的作用在于如果被调试程序是一个控制台程序的话,调试器和被调试程序的输出都在同一个控制台窗口内,显得很混乱,加上这个标记之后,被调试程序就会在一个新的控制台窗口中输出信息。如果被调试程序是一个窗口程序,这个标记没有影响。(个人推荐)

以上的代码仅仅是启动了被调试进程,然后就立即退出了。要注意的是,如果调试器进程结束了,那么被它调试的所有子进程都会随着结束。这就是为什么虽然CreateProcess调用成功了,却看不到计算器窗口的原因。

那么调试器如何知道被调试进程内部发生了什么?其实当一个进程成为被调试进程之后,在完成了某些操作或者发生异常时,它会发送通知给调试器,然后将自身挂起,直到调试器命令它继续执行。所以接下来我们开始调用调试循环事件对被调试程序进行事件的处理。
被调试进程发送的通知称为调试事件,在DEBUG_EVENT结构体中详细描述了调试事件的内容:

 1 typedef struct _DEBUG_EVENT
 2 {
 3    DWORD dwDebugEventCode;
 4    DWORD dwProcessId;
 5    DWORD dwThreadId;
 6    union {
 7      EXCEPTION_DEBUG_INFO Exception;
 8      CREATE_THREAD_DEBUG_INFO CreateThread;
 9      CREATE_PROCESS_DEBUG_INFO CreateProcessInfo;
10      EXIT_THREAD_DEBUG_INFO ExitThread;
11      EXIT_PROCESS_DEBUG_INFO ExitProcess;
12      LOAD_DLL_DEBUG_INFO LoadDll;
13      UNLOAD_DLL_DEBUG_INFO UnloadDll;
14      OUTPUT_DEBUG_STRING_INFO DebugString;
15      RIP_INFO RipInfo;
16    } u;
17  } DEBUG_EVENT,  

其结构体中的dwDebugEventCode描述了调试事件的类型,总共有9类调试事件:


CREATE_PROCESS_DEBUG_EVENT


创建进程的时候会来到该调试事件.


CREATE_THREAD_DEBUG_EVENT


创建一个线程之后发送此类调试事件.


EXCEPTION_DEBUG_EVENT


发生异常时发送此类调试事件.


EXIT_PROCESS_DEBUG_EVENT


进程结束后发送此类调试事件.


EXIT_THREAD_DEBUG_EVENT


一个线程结束后发送此类调试事件.


LOAD_DLL_DEBUG_EVENT


装载一个DLL模块之后发送此类调试事件.


OUTPUT_DEBUG_STRING_EVENT


被调试进程调用OutputDebugString之类的函数时发送此类调试事件.


RIP_EVENT


发生系统调试错误时发送此类调试事件.


UNLOAD_DLL_DEBUG_EVENT


卸载一个DLL模块之后发送此类调试事件.

而在结构体中的u联合体来记录每种调试事件,通过u的字段的名称可以很快地判断哪个字段与哪种事件关联。
 dwProcessId和dwThreadId分别是触发调试事件的进程ID和线程ID。
 调试器则通过WaitForDebugEvent,通过ContinueDebugEvent继续被调试进程的执行。

以下代码摘要于微软帮助文档MSDN

 1 DEBUG_EVENT DebugEv;                   // debugging event information
 2 DWORD dwContinueStatus = DBG_CONTINUE; // exception continuation
 3 for(;;)
 4 {
 5
 6 // Wait for a debugging event to occur. The second parameter indicates
 7 // that the function does not return until a debugging event occurs.
 8
 9     WaitForDebugEvent(&DebugEv, INFINITE);
10
11 // Process the debugging event code.
12 switch (DebugEv.dwDebugEventCode)
13     {
14         case EXCEPTION_DEBUG_EVENT:
15         // Process the exception code. When handling
16         // exceptions, remember to set the continuation
17         // status parameter (dwContinueStatus). This value
18         // is used by the ContinueDebugEvent function.
19
20             switch (DebugEv.u.Exception.ExceptionRecord.ExceptionCode)
21             {
22                 case EXCEPTION_ACCESS_VIOLATION:
23                 // First chance: Pass this on to the system.
24                 // Last chance: Display an appropriate error.
25
26                 case EXCEPTION_BREAKPOINT:
27                 // First chance: Display the current
28                 // instruction and register values.
29
30                 case EXCEPTION_DATATYPE_MISALIGNMENT:
31                 // First chance: Pass this on to the system.
32                 // Last chance: Display an appropriate error.
33
34                 case EXCEPTION_SINGLE_STEP:
35                 // First chance: Update the display of the
36                 // current instruction and register values.
37
38                 case DBG_CONTROL_C:
39                 // First chance: Pass this on to the system.
40                 // Last chance: Display an appropriate error.
41
42                 // Handle other exceptions.
43             }
44         case CREATE_THREAD_DEBUG_EVENT:
45         // As needed, examine or change the thread‘s registers
46         // with the GetThreadContext and SetThreadContext functions;
47         // and suspend and resume thread execution with the
48         // SuspendThread and ResumeThread functions.
49
50         case CREATE_PROCESS_DEBUG_EVENT:
51         // As needed, examine or change the registers of the
52         // process‘s initial thread with the GetThreadContext and
53         // SetThreadContext functions; read from and write to the
54         // process‘s virtual memory with the ReadProcessMemory and
55         // WriteProcessMemory functions; and suspend and resume
56         // thread execution with the SuspendThread and ResumeThread
57         // functions.
58
59         case EXIT_THREAD_DEBUG_EVENT:
60         // Display the thread‘s exit code.
61
62         case EXIT_PROCESS_DEBUG_EVENT:
63         // Display the process‘s exit code.
64
65         case LOAD_DLL_DEBUG_EVENT:
66         // Read the debugging information included in the newly
67         // loaded DLL.
68
69         case UNLOAD_DLL_DEBUG_EVENT:
70         // Display a message that the DLL has been unloaded.
71
72         case OUTPUT_DEBUG_STRING_EVENT:
73         // Display the output debugging string.
74         }
75     // Resume executing the thread that reported the debugging event.
76        ContinueDebugEvent(DebugEv.dwProcessId,
77                    DebugEv.dwThreadId, dwContinueStatus);
78 } 

这样一个循环就是所谓的调试循环。要注意这里是如何退出循环的:引入一个BOOL类型的bRetEvent变量,在处理
EXIT_PROCESS_DE BUG_EVENT

调试器开发实例_调试器框架设计

时间: 2024-08-26 17:10:55

调试器开发实例_调试器框架设计的相关文章

调试器开发实例_调试器事件处理(一.事件到达)

上一章既然说到了调试循环事件,那么接下来我们该说说对调试器事件的处理了. 调试器的事件处理虽然有很多,但是并不是每一个都用得上的,接下来的文章中我们挑选一些经常用到的来给大家说说. CREATE_PROCESS_DEBUG_EVENT  创建进程之后的第一个调试事件,CREATE_PROCESS_DEBUG_INFO结构体描述了该类调试事件的详细信息. 该结构体有三个字段是句柄,分别是hFile,hProcess和hThread,同样要记得使用CloseHandle关闭它们! EXIT_PROC

安卓MP3播放器开发实例(1)之音乐列表界面

学习安卓开发有一年了,想想这一年的努力,确实也收获了不少.也找到了比較如意的工作. 今天准备分享一个以前在初学阶段练习的一个项目.通过这个项目我真正的找到了开发安卓软件的感觉,从此逐渐步入安卓开发的正规.这个项目是当时借鉴Mars老师的初学视频做的安州手机的MP3播放器.自己又进行了改进,特别在歌词的优化和加入进度条方面的.因为是8个月前做的,水平非常0基础,bug应该非常多,如今自己又懒得再一次改进,仅仅希望可以给初学的朋友们提供一些帮助.或者起到抛砖引玉的效果.那我就心惬意足了. 先整体介绍

WPF和Expression Blend开发实例:Adorner(装饰器)应用实例

装饰器-- 表示用于修饰 UIElement 的 FrameworkElement 的抽象类 简单来说就是,在不改变一个UIElement结构的情况下,将一个Visual对象加到它上面. 应用举例: 现在我们拥有一个文本框,但是我们需要限定输入的字符串,当输入的是非法字符串的时候,要求将文本框的四周包裹一个红色的边框.通常我们可以用Border将文本框包裹在里面,然后动态地改变它的颜色来实现功能.那么现在我们可以直接在文本框上面加一个装饰器来实现. Adorner类 AdornerLayer类

安卓MP3播放器开发实例(3)之进度条和歌词更新的实现

上一次谈了音乐播放的实现,这次说下最复杂的进度条和歌词更新.因为须要在播放的Activity和播放的Service间进行交互,所以就涉及了Activity对Service的绑定以及绑定后数据的传输,这个须要对服务绑定熟悉才干够理解.原理不复杂.可是步骤略微繁琐,代码贴起来可能会非常混乱. 进度条和歌词放在一起说比較好,不然比較混乱.进度条的调整大家都懂的,就是进度条调到哪里歌曲的播放就跟到哪里,歌词也得跟到哪里.首先看下上一篇看过的開始button监听事件中服务的绑定代码: //绑定播放服务 b

com.panie 项目开发随笔_不使用框架(2016.12.29)

(一) 最近做的框架一直在 spring + springmvc + mybatis 的基础上,使用框架的好处自然是 简化了自己的开发工作,定义好大的结构体系后就在里面套用方法了! 可是框架的毛病同样存在于jar 包过多,同样的功能的方法被不同的jar反复的写,最后整个项目显得很大. 如果我只是想要一个很简单的页面功能,那么 就没有必要去使用框架了. (二) 那么就搭建一个简单的 Servlet3.1 + JDBC 的结构来实现吧! (三) --

Python_装饰器,生成器_干货哦

import timeimport calendarimport os # 时间格式熟悉"""# 格式化成2016-03-20 11:45:39形式time01 = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())print()# 格式化成Sat Mar 28 22:24:24 2016形式print(time.strftime("%a %b %d %H:%M:%S %Y", ti

Linux设备驱动框架设计

引子 Linux操作系统的一大优势就是支持数以万计的芯片设备,大大小小的芯片厂商工程师都在积极地向Linux kernel提交设备驱动代码.能让这个目标得以实现,这背后隐藏着一个看不见的技术优势:Linux内核提供了一套易于扩展和维护的设备驱动框架.Linux内核本身提供一套设备驱动模型,此模型提供了Linux内核对设备的一般性抽象描述,包括设备的电源管理.对象生命周期管理.用户空间呈现等等.在设备模型的帮助下,设备驱动开发工程师从设备的一般性抽象中解脱出来.但是每个设备的具体功能实现还需要大量

【iOS】小项目框架设计(ReactiveCocoa+MVVM+AFNetworking+FMDB)

网址: http://www.saitjr.com/ios/ios-framework-reactivecocoa-mvvmafnetworking-fmdb.html 上一个项目使用到了ReactiveCocoa+MVVM+AFNetworking+FMDB框架设计,从最初的尝试,到后来不断思考和学习,现在对这样一个整体设计还是有了一定了理解与心得.在此与大家分享下. 本文将不再过多的描述ReactiveCocoa.MVVM.FMDB的使用细节.关于ReactiveCocoa,我有一篇实用案例

【嵌入式开发】 嵌入式开发工具简介 (裸板调试示例 | 交叉工具链 | Makefile | 链接器脚本 | eclipse JLink 调试环境)

作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42239705  参考博客 : [嵌入式开发]嵌入式 开发环境 (远程登录 | 文件共享 | NFS TFTP 服务器 | 串口连接 | Win8.1 + RedHat Enterprise 6.3 + Vmware11) 开发环境 : -- 操作系统 : Vmware11 + RedHat6.3 企业版 + Win8.1; -- 硬件 : OK-6410-A 开发