10.0 探索API调试事件原理
本章笔者将通过Windows平台下自带的调试API接口实现对特定进程的动态转存功能,首先简单介绍一下关于调试事件的相关信息,调试事件的建立需要依赖于DEBUG_EVENT这个特有的数据结构,该结构用于向调试器报告调试事件。当一个程序发生异常事件或者被调试器附加时,就会产生对应的DEBUG_EVENT调试事件,通常DEBUG_EVENT包含了多种调试类型,包括异常事件、进程创建事件、线程创建事件、进程退出事件和线程退出事件等等,我们只需要动态捕捉这些调试事件并作相应的处理即可实现更多有用的功能。
调试事件通常可以分为如下几种类型;
- 异常事件 (Exception Event) - 发生了异常,例如访问非法的内存、除以零或调用了无效的函数。
- 进程创建事件 (Process Creation Event) - 当一个新进程被创建时发送此事件。
- 进程退出事件 (Process Exit Event) - 当一个进程退出时发送此事件。
- 线程创建事件 (Thread Creation Event) - 当一个新线程被创建时发送此事件。
- 线程退出事件 (Thread Exit Event) - 当一个线程退出时发送此事件。
- 调试字符串事件 (Debug String Event) - 当一个进程向其调试器发送字符串消息时发送此事件。
- 输出字符串事件 (Output String Event) - 当输出调试字符串时发送此事件。
- 动态链接库加载事件(LOAD_DLL_DEBUG_EVENT) - 当进程装载 DLL 时发送此事件。
当我们需要调试一个程序时有两种方式可以实现,第一种方式是通过CreateProcess()函数创建一个进程,并在调用函数时指定DEBUG_PROCESS || DEBUG_ONLY_THIS_PROCESS则当程序被运行起来后自动进入到调试状态,另一种方式则是通过DebugActiveProcess()函数,该函数接受一个正在运行的进程PID号,可动态附加到一个已运行程序上而对其进行调试。
一旦调试器通过CreateProcess()附加并运行,下一步则是通过WaitForDebugEvent()用于等待一个调试事件,当有调试事件到达后系统会将调试类型存储到debugEvent.dwDebugEventCode这个变量内,此时我们可以通过判断该变量内的参数来对特定的事件做出自定义处理操作,接着会通过ContinueDebugEvent()继续等待下一个调试事件的到来,我们以打开一个进程并创建调试为例,看一下如下代码片段;
#include <iostream>
#include <windows.h>
int main(int argc, char* argv[])
{
DEBUG_EVENT debugEvent = { 0 };
BOOL bRet = TRUE;
// 创建调试进程
STARTUPINFO startupInfo = { 0 };
PROCESS_INFORMATION pInfo = { 0 };
GetStartupInfo(&startupInfo);
// 创建调试进程并设置 DEBUG_PROCESS || DEBUG_ONLY_THIS_PROCESS 调试事件
bRet = CreateProcess("d://lyshark.exe", NULL, NULL, NULL, TRUE, DEBUG_PROCESS || DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &startupInfo, &pInfo);
if (!bRet)
{
return 0;
}
// 附加调试进程
// DebugActiveProcess(13940)
// 无限循环等待调试事件
while (WaitForDebugEvent(&debugEvent, INFINITE))
{
// 根据调试事件判断
switch (debugEvent.dwDebugEventCode)
{
// 异常调试事件
case EXCEPTION_DEBUG_EVENT:
printf("异常处理事件 \n");
break;
// 线程创建调试事件
case CREATE_THREAD_DEBUG_EVENT:
printf("线程创建调试事件 \n");
break;
// 进程创建调试事件
case CREATE_PROCESS_DEBUG_EVENT:
printf("进程创建调试事件 \n");
break;
// 线程退出调试事件
case EXIT_THREAD_DEBUG_EVENT:
printf("线程退出调试事件 \n");
break;
// 进程退出调试事件
case EXIT_PROCESS_DEBUG_EVENT:
printf("进程退出调试事件 \n");
break;
// 装载DLL调试事件
case LOAD_DLL_DEBUG_EVENT:
printf("装载DLL调试事件 \n");
break;
// 卸载DLL调试事件
case UNLOAD_DLL_DEBUG_EVENT:
printf("卸载DLL调试事件 \n");
break;
// 输出调试信息事件
case OUTPUT_DEBUG_STRING_EVENT:
printf("输出调试信息事件 \n");
break;
}
// 使调试器能够继续以前报告调试事件的线程
bRet = ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
}
system("pause");
return 0;
}
当编译并运行上述程序后,读者应该能看到如下图所示的输出效果,其中包括了各类调试事件被触发时的提示信息,由于在调试事件内没有做任何操作,程序在加载后就被自动运行起来了;

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/b8eecce4.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
10.0 探索API调试事件原理的更多相关文章
- IE升级到10.0,VS2010启动调试时报“未能将脚本调试器附加到计算机..”
IE升级到10.0,VS2010启动调试时报“未能将脚本调试器附加到计算机..” 今天,在调试代码时,调试器弹出提示框,报:未能将脚本调试器附加到计算机XXX上的进程iexplore.exe . 已附 ...
- Java 动态调试技术原理及实践
本文转载自Java 动态调试技术原理及实践 导语 断点调试是我们最常使用的调试手段,它可以获取到方法执行过程中的变量信息,并可以观察到方法的执行路径.但断点调试会在断点位置停顿,使得整个应用停止响应. ...
- Web jquery表格组件 JQGrid 的使用 - 4.JQGrid参数、ColModel API、事件及方法
系列索引 Web jquery表格组件 JQGrid 的使用 - 从入门到精通 开篇及索引 Web jquery表格组件 JQGrid 的使用 - 4.JQGrid参数.ColModel API.事件 ...
- iOS 10.0 更新点(开发者视角)
html, body {overflow-x: initial !important;}html { font-size: 14px; } body { margin: 0px; padding: 0 ...
- Kafka 0.10.0
2.1 Producer API We encourage all new development to use the new Java producer. This client is produ ...
- 还在期待安卓9.0吗?Android 10.0要来了
目前,美国 Google公司的 AndroidP (安卓9.0),已经正式全面推出有几个多月了.众多手机品牌厂商也都在积极的进行更新适配 Android 9.0 系统(修改UI界面也算是二次开发,嗯) ...
- Atitit web remote远程调试的原理attilax总结
Atitit web remote远程调试的原理attilax总结 Jvm是vm打开一个debug port,然后ide先连接..然后执行url,就会vm会与ide沟通.. Php的xdebug po ...
- Dottrace 10.0.2 使用心得
开发环境vs2015 软件:JetBrains dotTrace 10.0.2 刚开始不知道怎么下手,多看了一会还有一位仁兄的解释.算是对某个功能小有入门了. 当前会查看某个方法在抓取快照时间它的执行 ...
- 调试寄存器 原理与使用:DR0-DR7
调试寄存器 原理与使用:DR0-DR7 下面介绍的知识性信息来自intel IA-32手册(可以在intel的开发手册或者官方网站查到),提示和补充来自学习调试器实现时的总结. 希望能给你带去有用的信 ...
- 非寻常方式学习ApacheTomcat架构及10.0.12源码编译
概述 开启博客分享已近三个月,感谢所有花时间精力和小编一路学习和成长的伙伴们,有你们的支持,我们继续再接再厉 **本人博客网站 **IT小神 www.itxiaoshen.com 定义 Tomcat官 ...
随机推荐
- 使用 nuxt3 开发简约优雅的个人 blog
起因 很早前我就有过搭建个人博客的想法,但是我希望使用纯前端实现,这样就不需要付出额外的后端维护成本,维护成本又低,而且更加安全.网上也有很多博客框架但是也不符合我的需求,所以我使用了nuxt3 + ...
- Linux下Redis集群部署
一.Redis集群介绍 Redis 集群是一个提供在多个Redis节点间共享数据的程序集.Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性 ...
- 【.NET源码解读】深入剖析中间件的设计与实现
.NET本身就是一个基于中间件(middleware)的框架,它通过一系列的中间件组件来处理HTTP请求和响应.在之前的文章<.NET源码解读kestrel服务器及创建HttpContext对象 ...
- 国标GB28181协议客户端开发(三)查询和实时视频画面
国标GB28181协议客户端开发(三)查询和实时视频画面 本文是<国标GB28181协议设备端开发>系列的第三篇,探讨了信息查询和实时视频在GB28181协议中的应用.首先,介绍了设备目录 ...
- Flutter upgrade 卡死问题
使用 到本地的flutter sdk的目录下 $flutter upgrade --force 降低到指定版本 : $flutter version 1.22.4
- Auto.Core
Auto Core (基于AspectCore) 介绍 AutoCore是基于 .Net Standard 2.1用于简化 ASP.NET Core开发,AutoCore 在 AspectCore 的 ...
- 将SQL从phpmyadmin导入到自己的Navicat
数据库名称太有指向性了 容易把自己给干没了 一码得码的一塌糊涂 就不放图了 进入你的phpmyadmin 注意一定要好好的进到数据库里面 点击导出 如果提示是 正在导出数据库"{你的数据库名 ...
- Python数据分析易错知识点归纳(六):机器学习
六.机器学习 分类和聚类的区别 分类是有监督学习,聚类是无监督学习 分类算法用于预测新样本,聚类用于理解已知数据 标准化/归一化 type_se_num = type_se[type_se!= 'ob ...
- FPGA学习之乒乓操作
乒乓操作学习记录如下: 乒乓操作" 是一个常常应用于数据流控制的设计思想, 典型的乒乓操作方法如下图 所示: 乒乓操作的处理流程为:输入数据流通过" 输入数据选择单元"将 ...
- Fastjson1.2.24漏洞复现-基于vulhub漏洞平台(文件上传写入-反弹shell)
Fastjson1.2.24漏洞复现-基于vulhub漏洞平台 环境准备: 192.168.59.130 攻击机 window10 192.168.59.135 靶机 centos8 声明:不涉及互联 ...