> # ♻️ 资源
> **大小:** 184KB
> **文档链接:**[**https://www.yuque.com/sxbn/ks/100010456**](https://www.yuque.com/sxbn/ks/100010456)
> **➡️ 资源下载:**[**https://download.csdn.net/download/s1t16/87390793**](https://download.csdn.net/download/s1t16/87390793)
> **注:更多内容可关注微信公众号【神仙别闹】,如当前文章或代码侵犯了您的权益,请私信作者删除!**
> ![qrcode_for_gh_d52056803b9a_344.jpg](https://cdn.nlark.com/yuque/0/2023/jpeg/2469055/1692147256036-49ec7e0c-5434-4963-b805-47e7295c9cbc.jpeg#averageHue=%23a3a3a3&clientId=u8fb96484-770e-4&from=paste&height=140&id=u237e511a&originHeight=344&originWidth=344&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=8270&status=done&style=none&taskId=ud96bf5f7-fe85-4848-b9c2-82251181297&title=&width=140.1999969482422)
# 基于单步调试器
## 一 实验目的:在 Debuger Main Loop 示例代码的基础上,完成一个具备单步跟踪功能的调试器开发
## 二 实验内容:
1. 主进程通过创建远程进程来进行调试
2. 设置 eFlag 寄存器中的 tf 标志位,使程序执行一条指令后,产生单步执行异常。
3. 在异常处理过程中,记录程序执行时所有数据(每一步的 EIP、八个寄存器的值等)。
## 三 实验过程
流程图:
![30c426ab4c311e3710085ddb9b9c8052.PNG](https://cdn.nlark.com/yuque/0/2024/png/2469055/1711593337708-2f790466-d1e6-4fea-a02d-5d4a168e8b38.png#averageHue=%23f3f3f3&clientId=u8a73ae3b-1fc1-4&from=paste&height=154&id=u1ef887da&originHeight=193&originWidth=159&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=12228&status=done&style=none&taskId=u03173645-c74e-407a-92f5-bbb0c08a09b&title=&width=127.2)
1、通过主进程创建子进程(被调试进程)
所用函数:CreateProcess()
使用说明:
```cpp
CreateProcess(
TEXT("xx.exe"),//被调试进程
NULL, // 命令行字符串
NULL, // 指向一个NULL结尾的、用来指定可执行模块的宽字节字符串
NULL, // 指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承。
false,// 指示新进程是否从调用进程处继承了句柄。
DEBUG_PROCESS,//如果这个标志被设置,调用进程将被当做一个调试程序,并且新进程会被当做被调试的进程(DEBUG_EVENT)。系统把被调试程序发生的所有调试事件通知给调试器。调用进程可以调用WaitForDebugEvent函数接收调试信息。
NULL, // 指向一个新进程的环境块。如果此参数为空,新进程使用调用进程的环境
NULL, // 指定子进程的工作路径
&si, // 决定新进程的主窗体如何显示的STARTUPINFO结构体
&pi // 接收新进程的识别信息的PROCESS_INFORMATION结构体
)
```
2、单步调试目标进程
(1)获取被调试进程的主线程的上下文环境
所用函数:GetThreadContext()
说明:
```
//设置 CONTEXT 变量结构体,指明想要收回哪些寄存器,CONTEXT_FULL:包含 CPU 的控制寄存器,比如指今指针,堆栈指针,标志和函数返回地址、用于标识 CPU 的整数寄存器、用于标识 CPU 的段寄存器
```
(2)将 eFlag 寄存器中的 tf 标志位设置为 1,使被调试进程产生单步异常
所用函数:SetThreadContext()
说明:
```cpp
WaitForDebugEvent(DebugEv, INFINITE);
//等待调试事件通知的到来,INFINITE 表示持续等待(the function does not return until a debugging event has occurred.)
switch (DebugEv->dwDebugEventCode)//描述了调试事件的类型,总共有 9 类调试事件
{
case EXCEPTION_DEBUG_EVENT://被调试事件发生异常
switch (DebugEv->u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_SINGLE_STEP://单步调试,tf 位为 1 时单步中断
single = 1;
step_through(context);
//将进程上下文的相关信息输出
break;
...
context.EFlags |= 0x100;
//16 进制的 100 转化为二进制为 1 0000 0000,而 TF 位是 EFLAGS 寄存器中的第 8 位(从 0 开始算),通过异或运算可以使 TF 位为 1
SetThreadContext(pi.hThread, pContext)//重新设置线程寄存器的值*
}
...
}
```
(3)捕获异常
所用函数:WaitForDebugEvent()
说明:
```cpp
WaitForDebugEvent(DebugEv, INFINITE);
//等待调试事件通知的到来,INFINITE 表示持续等待(the function does not return until a debugging event has occurred.)
switch (DebugEv->dwDebugEventCode)//描述了调试事件的类型,总共有 9 类调试事件
{
case EXCEPTION_DEBUG_EVENT://被调试事件发生异常
switch (DebugEv->u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_SINGLE_STEP://单步调试,tf 位为 1 时单步中断
single = 1;
step_through(context);
//将进程上下文的相关信息输出
break;
...
}
...
}
```
(4)在异常处理过程中,记录程序执行时数据(如 EIP 和八个寄存器的值)
所用函数:void step_through(CONTEXT context)- 自编
说明:
```cpp
< "EIP :"<< uppercase << hex << context.Eip << endl;
//输出EIP,存储的是下次要执行的void step_through(CONTEXT context)
{
cout <令的地址
cout << endl;
//八个寄存器值
cout << "寄存器值 :" << endl;
cout << "eax:" << uppercase << hex << context.Eax << endl;
//通用寄存器(eax、ebx、ecx、edx)
cout << "ebx:" << uppercase << hex << context.Ebx << endl;
cout << "ecx:" << uppercase << hex << context.Ecx << endl;
cout << "edx:" << uppercase << hex << context.Edx << endl;
cout << "esi:" << uppercase << hex << context.Esi << endl;
//索引寄存器
cout << "edi:" << uppercase << hex << context.Edi << endl;
cout << "esp:" << uppercase << hex << context.Esp << endl;
//栈顶指针
cout << "ebp:" << uppercase << hex << context.Ebp << endl;
cout << endl;
cout << "显示内存内容:"<<endl;
unsigned int address = 0;
unsigned int length = 128;
address = context.Eip;
DumpHex(address, length);
cout << endl << endl;
}
```
## 四 实验效果
![e737b8639f5ae49ebd1c9c73d1443b0a.PNG](https://cdn.nlark.com/yuque/0/2024/png/2469055/1711593401644-68699134-64c5-4bc4-a4a4-3763cb3435b8.png#averageHue=%231a1a1a&clientId=u8a73ae3b-1fc1-4&from=paste&height=234&id=u14e9063d&originHeight=292&originWidth=554&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=83533&status=done&style=none&taskId=u669e2425-dfe1-4dcf-8445-5a8b6fe80f3&title=&width=443.2)
## 五 问题
1、被调试程序 main()函数地址的确定
Q:调试时下的第一个断点位置如下:
![1a3b75af71be5182ad74bdaba580b460.PNG](https://cdn.nlark.com/yuque/0/2024/png/2469055/1711593429673-2e9909c0-d687-425f-a74e-0ca8481ca7ff.png#averageHue=%23e6e5e2&clientId=u8a73ae3b-1fc1-4&from=paste&height=136&id=udaa0476e&originHeight=170&originWidth=553&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=64661&status=done&style=none&taskId=u2884314b-d25d-47dc-a519-298d6acf29f&title=&width=442.4)
并没有定位到被调试程序的入口函数处,当有符号表文件时,考虑利用 API 函数 SymFromName 获取被调试程序 main 函数地址,进而从 main 函数地址开始下断点:
![836e745dbf689af4337fd44726288bdf.PNG](https://cdn.nlark.com/yuque/0/2024/png/2469055/1711593445672-0d537b1c-b54e-4cb7-b809-f2cc10cf9c94.png#averageHue=%23e7e5df&clientId=u8a73ae3b-1fc1-4&from=paste&height=138&id=u1710481e&originHeight=172&originWidth=440&originalType=binary&ratio=1.25&r
没有合适的资源?快使用搜索试试~ 我知道了~
使用C++实现基于单步调试器【100010456】
共11个文件
filters:1个
h:1个
vcxproj:1个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 135 浏览量
2023-01-18
10:27:07
上传
评论
收藏 186KB ZIP 举报
温馨提示
详情介绍:https://www.yuque.com/sxbn/ks/100010456 实验目的:在 Debuger Main Loop 示例代码的基础上,完成一个具备单步跟踪功能的调试器开发 实验内容: 主进程通过创建远程进程来进行调试 设置 eFlag 寄存器中的 tf 标志位,使程序执行一条指令后,产生单步执行异常。 在异常处理过程中,记录程序执行时所有数据(每一步的 EIP、八个寄存器的值等)。
资源推荐
资源详情
资源评论
收起资源包目录
100010456-使用C++实现基于单步调试器.zip (11个子文件)
dbts
LICENSE 1KB
.vs
单步调试器
v14
.suo 32KB
单步调试器.sln 1KB
大作业之单步调试.docx 152KB
单步调试器
单步调试器.vcxproj.filters 1KB
debugger.cpp 15KB
fussing 测试.exe 37KB
vc140.pdb 84KB
单步调试器.vcxproj 6KB
debugger.h 2KB
README.md 9KB
共 11 条
- 1
资源评论
神仙别闹
- 粉丝: 3783
- 资源: 7469
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功