当前位置: 首页 > news >正文

windows内核研究(软件调试-调试事件的处理)

软件调试


调试事件的处理

调试器如何对调试事件进行处理?

  • 关联(把调试进程和被调试进程关联起来)
  • 调试循环

代码测试:

#include<iostream>
#include<Windows.h>
#define DEBUGGR_PROCESS L"C:\\Users\\BananaLi\\Desktop\\其他软件\\dbgview64.exe"int main() {BOOL nIsContinue = TRUE;DEBUG_EVENT debugEvent = { 0 };BOOL bRet = TRUE;// 1.创建调试进程STARTUPINFO startUpInfo = { 0 };PROCESS_INFORMATION pInfo = { 0 };GetStartupInfo(&startUpInfo);bRet = CreateProcess(DEBUGGR_PROCESS, NULL, NULL, NULL, TRUE, DEBUG_PROCESS || DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &startUpInfo, &pInfo);if (bRet == FALSE) {printf("创建调试进程失败,错误码:%d\n",GetLastError());return 0;}// 调试循环(主框架)while (nIsContinue) {// 2.等待调试事件bRet = WaitForDebugEvent(&debugEvent, INFINITE);if (bRet == FALSE) {printf("等待调试事件失败,错误码:%d\n", GetLastError());return 0;}switch (debugEvent.dwDebugEventCode) {case EXCEPTION_DEBUG_EVENT: {printf("捕获到异常事件\n");// 处理异常break;}case CREATE_PROCESS_DEBUG_EVENT: {printf("创建进程事件\n");break;}case EXIT_PROCESS_DEBUG_EVENT: {printf("退出进程事件\n");nIsContinue = FALSE;break;}case CREATE_THREAD_DEBUG_EVENT: {printf("创建线程事件\n");break;}case EXIT_THREAD_DEBUG_EVENT: {printf("退出线程事件\n");break;}case LOAD_DLL_DEBUG_EVENT: {printf("加载DLL事件\n");break;}case UNLOAD_DLL_DEBUG_EVENT: {printf("卸载DLL事件\n");break;}default:break;// 让被调试程序继续运行bRet = ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);}}return 0;
}

可以看到已经为我们捕获到了调试事件

在这里插入图片描述

通过上面的打印信息可以发现,进程在一创建时,就会把创建进程的事件添加到事件链表中,紧接着就是一堆DLL的加载事件,然后又创建了几个线程,最后发现还捕获到了一个异常事件,这个异常事件是谁触发的呢?

我们打印一下捕获到的异常信息结构体

...
case EXCEPTION_DEBUG_EVENT: {printf("捕获到异常事件\n");printf("异常代码:%llx\n", debugEvent.u.Exception.ExceptionRecord.ExceptionCode);printf("异常地址:%llx\n", debugEvent.u.Exception.ExceptionRecord.ExceptionAddress);printf("异常参数个数:%llx\n", debugEvent.u.Exception.ExceptionRecord.NumberParameters);// 处理异常break;
}
...

在这里插入图片描述

我们用dbg看一下这个地址

在这里插入图片描述
系统断点

在创建进程时

  • LdrInitializeThunk
    • LdrpInitializeProcess
    • DbgBreakPoint()方法会写入一个int3,这个在以调试模式打开时才会写入

以附加的形式调试进程

#include<iostream>
#include<Windows.h>
#define DEBUGGR_PROCESS 29132int main() {BOOL nIsContinue = TRUE;DEBUG_EVENT debugEvent = { 0 };BOOL bRet = TRUE;// 1.创建调试进程STARTUPINFO startUpInfo = { 0 };PROCESS_INFORMATION pInfo = { 0 };GetStartupInfo(&startUpInfo);//bRet = CreateProcess(DEBUGGR_PROCESS, NULL, NULL, NULL, TRUE, DEBUG_PROCESS || DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &startUpInfo, &pInfo);//if (bRet == FALSE) {//	printf("创建调试进程失败,错误码:%d\n",GetLastError());//	return 0;//}if (!DebugActiveProcess(DEBUGGR_PROCESS)) {return 0;}// 调试循环(主框架)while (nIsContinue) {// 2.等待调试事件bRet = WaitForDebugEvent(&debugEvent, INFINITE);if (bRet == FALSE) {printf("等待调试事件失败,错误码:%d\n", GetLastError());return 0;}switch (debugEvent.dwDebugEventCode) {case EXCEPTION_DEBUG_EVENT: {printf("捕获到异常事件\n");printf("异常代码:%llx\n", debugEvent.u.Exception.ExceptionRecord.ExceptionCode);printf("异常地址:%llx\n", debugEvent.u.Exception.ExceptionRecord.ExceptionAddress);printf("异常参数个数:%llx\n", debugEvent.u.Exception.ExceptionRecord.NumberParameters);// 处理异常break;}case CREATE_PROCESS_DEBUG_EVENT: {printf("创建进程事件\n");break;}case EXIT_PROCESS_DEBUG_EVENT: {printf("退出进程事件\n");nIsContinue = FALSE;break;}case CREATE_THREAD_DEBUG_EVENT: {printf("创建线程事件\n");break;}case EXIT_THREAD_DEBUG_EVENT: {printf("退出线程事件\n");break;}case LOAD_DLL_DEBUG_EVENT: {printf("加载DLL事件\n");break;}case UNLOAD_DLL_DEBUG_EVENT: {printf("卸载DLL事件\n");break;}default:break;}// 让被调试程序继续运行bRet = ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);}return 0;
}

在这里插入图片描述

可以发现是一样的,但是有一个疑问,我们之前在打开一个进程进行调试时,当前进程的创建,加载DLL,这些我们能捕获到这没问题,但是我们附加这个进程时,为什么也能捕获到当前被调试进程的创建,加载DLL这些事件呢?答案是这是假的杜撰调试事件消息

要保证调试器无论是新打开一个进程还是附加的形式进行调试,我都能获取到所有的调试事件

http://www.dtcms.com/a/309971.html

相关文章:

  • 无图形界面的CentOS 7网络如何配置
  • 大模型结构比较
  • QT中字符串加tr u8的意思
  • Flink Checkpoint机制:大数据流处理的坚固护盾
  • mongodb中的哈希索引详解
  • Windows11 WSL安装Ubntu22.04,交叉编译C语言应用程序
  • Java集合框架:LinkedList
  • 【Jetson orin-nx】使用Tensorrt并发推理四个Yolo模型 (python版)
  • tensorflow目标分类:分绍(二)
  • 树莓派硬件介绍
  • 提示+掩膜+注意力=Mamba三连击,跨模态任务全面超越
  • 安检机危险品识别准确率↑23.7%:陌讯多模态融合算法实战解析
  • Python爬虫库性能与选型实战指南:从需求到落地的全链路解析
  • 神经网络的基础
  • 工业级蓝光三维扫描仪:汽车零部件高精度检测的利器
  • 研华PCI-1622C 使用RS-422通讯1主多从通讯中断
  • 【QT开发手册】对象模型(对象树) 窗⼝坐标体系
  • EXE加密软件(EXE一机一码加密大师) 最新版1.6.0更新 (附2025最新版本CSDN下载地址)
  • windows mamba-ssm环境配置指南
  • 网络层协议IP
  • 运维端口管理闭环:从暴露面测绘到自动化封禁!
  • 【AI问答记录】grafana接收query请求中未携带step参数,后端基于intervalMs和maxDataPoints等参数计算step的逻辑
  • AcWing 897:最长公共子序列 ← 子序列问题(n≤1e3)
  • “数据管理” 一场高风险的游戏
  • 民航领域数据分类分级怎么做?|《民航领域数据分类分级要求》标准解读
  • 第13届蓝桥杯Python青少组中/高级组选拔赛(STEMA)2022年3月13日真题
  • ip去重小脚本
  • uniapp基础 (一)
  • git pull和git fetch的区别
  • Python爬虫实战:研究OpenCV技术构建图像数据处理系统