关于调试器中int3断点引发异常的思考
INT3断点
INT3断点是利用0Xcc指令实现的,cpu在执行0xcc指令时会引发断点异常调试器会捕捉这个异常。
INT3断点引发的异常属于陷阱型异常,在执行完0xcc指令后eip指向下一条指令。但是系统对int3有特殊处理,当异常第一次分发时如果调试器没有处理那么第二次异常分发之前系统会令eip-1。
下面写个调试程序来看一下。
#include <Windows.h>
#include <iostream>using namespace std;
int flag = 0; //标志是第一次断点异常,还是第二次断点异常
int main()
{
char a[256] = {0};
cout<<"请输入需要调试的目标程序的路径:";
cin>>a;
PROCESS_INFORMATION pi; //接受新进程的一些有关信息
STARTUPINFO si; //指定新进程的主窗体如何显示
DEBUG_EVENT devent; //消息事件
CONTEXT stContext; //线程信息块
GetStartupInfo(&si);
CreateProcessA(
a,
NULL,
NULL,
NULL,
FALSE, // 不可继承
DEBUG_ONLY_THIS_PROCESS | DEBUG_PROCESS, // 调试模式启动
NULL,
NULL,
&si,
&pi );
cout<<"创建进程成功"<<endl;
while(TRUE)
{
if(WaitForDebugEvent(&devent, INFINITE))
{
switch(devent.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
switch(devent.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_BREAKPOINT: //断点异常
if(devent.u.Exception.dwFirstChance == 1) //第一次异常分发
{
cout<<"第一次异常。 ";
cout<<"eip:";
stContext.ContextFlags = CONTEXT_FULL;
GetThreadContext(pi.hThread, &stContext);
int n1 = GetLastError();
cout<<stContext.Eip<<endl;
flag = 1;
}
if(devent.u.Exception.dwFirstChance == 0) //第二次异常分发
{
cout<<"第二次异常。 ";
cout<<"eip:";
GetThreadContext(pi.hThread, &stContext);
cout<<stContext.Eip<<endl;
flag = 0;
}
break;
}
break;
}
}
if(flag == 1) //如果是第一次碰见int3断点异常,我们不处理他,让他直接继续进行第二次异常分发
ContinueDebugEvent(devent.dwProcessId, devent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
else //如果是第二次碰见int3断点异常或者是其他调试事件我们直接返回让程序继续运行
{
flag = 0;
ContinueDebugEvent(devent.dwProcessId, devent.dwThreadId, DBG_CONTINUE);
}
}
return 0;
}
将一个不存在异常处理的程序第一条指令变为int3指令。
用上方程序作为例子进行调试,因为我们在第二次异常分发的时候返回DBG_CONTINUE来让系统认为我们处理了异常所以eip又会指向int3指令处,至此以后一直循环产生异常
OD中对int3的处理
我们把刚才的例子程序在od中运行并设置int3异常不交给程序处理
运行程序发现eip指向int3的下一条指令,这说明OD在int3异常第一次分发时因为eip指向了下一条指令,这时od返回DBG_CONTINUE意思是异常不交给程序处理直接返回。
如果设置忽略int3异常,即int3异常传递给程序处理。
因为程序没有异常处理所以第一次异常传给程序后,异常又会进行二次分发。我们运行程序发现eip依然指向int3指令处,继续运行发现程序依然指向int3处,这说明od默认第二次异常返回DBG_CONTINUE然后一直循环产生int异常(和我们文章开始写的那个调试程序一样)。
如果第二次异常时od没有返回DBG_CONTINUE来向系统说明异常已处理,而返回DBG_EXCEPTION_NOT_HANDLED的话异常将不会继续分发,程序将会被终止运行。(异常传到顶层异常处理处,执行了默认的异常处理函数结束运行)
我们把文章开始的调试器修改一下,把让第二次异常处理时返回DBG_EXCEPTION_NOT_HANDLED。
if(flag == 1) //如果是第一次碰见int3断点异常,我们不处理他,让他直接继续进行第二次异常分发
ContinueDebugEvent(devent.dwProcessId, devent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
else //如果是第二次碰见int3断点异常或者是其他调试事件我们直接返回让程序继续运行
{
flag = 0;
ContinueDebugEvent(devent.dwProcessId, devent.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);
}
再次拿原来的那个程序当例子进行调试,我们发现在第二次异常调试器返回DBG_EXCEPTION_NOT_HANDLED后调试程序结束运行。
开始调试前
开始调试后,异常第二次分发后异常没有继续分发,并且程序结束运行
关于调试器中int3断点引发异常的思考的更多相关文章
- ssis package 在调试状态中设置断点,程序 不进入断点 的解决方案
原文:ssis package 在调试状态中设置断点,程序 不进入断点 的解决方案 针对 SSIS intergation 项目 > 属性 > Debug >Run64bITRunt ...
- 在Visual Studio调试器中显示Unreal的数据类型的值
转自:https://blog.csdn.net/witton/article/details/5977766 在Unreal引擎中大量使用了自定义的数据类型如:FName,FString,TArra ...
- 用DebuggerDisplay在Visual Studio的调试器中定制类的显示方式
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:用DebuggerDisplay在Visual Studio的调试器中定制类的显示方式.
- 在VisualStudio调试器中使用内存窗口和查看内存分布
调试模式下内存窗口的使用 在调试期间,"内存"窗口显示应用使用的内存空间.调试器窗口(如"监视"."自动"."局部变量" ...
- 在 Visual Studio 调试器中指定符号 (.pdb) 和源文件
查找并指定符号文件和源文件:指定符号加载行为.使用符号和源服务器上:加载符号自动或在要求. 内容 查找符号 (.pdb) 文件 查找源文件 查找符号 (.pdb) 文件 说明 在之前的 Vis ...
- @清晰掉 GDB调试器中的战斗机
GDB 的命令很多,本文不会全部介绍,仅会介绍一些最常用的.在介绍之前,先介绍GDB中的一个非常有用的功能:补齐功能.它就如同Linux下SHELL中的命令补齐一样.当你输入一个命令的前几个字符,然后 ...
- 自定义Visual Studio调试器中的对象显示方式
你有没有盯着调试器窗口中的对象,并希望你可以通过其他类型的东西来查看这些对象?我当然有!扩展项目以确定每个人的身份可能会非常快速.理想情况下,通过特定的属性值快速定位它们会很棒.对我们来说幸运的是,V ...
- 在Chrome调试器中引入jQuery
在Console中输入以下代码并回车,Console显示"function (a,b){return new m.fn.init(a,b)}"说明导入成功,就可以在Console中 ...
- xcode 调试器 LLDB
本文完全转载,转载地址:点击这里 你是否曾经苦恼于理解你的代码,而去尝试打印一个变量的值? NSLog(@"%@", whatIsInsideThisThing); 或者跳过一个函 ...
随机推荐
- 安全计算环境之剩余信息保护-windows
参考https://blog.csdn.net/ubjewen/article/details/107587951 应保证鉴别信息所在的存储空间被释放或重新分配前得到完全清除 交互式登录: 之前登录到 ...
- kmp&字典树 模板
kmp: const int maxn=1e5+5; char s[maxn],p[maxn]; int nex[maxn]; int KmpSearch(char* s, char* p) { in ...
- 2019看雪CTF 晋级赛Q2第四题wp
上次参加2019看雪CTF 晋级赛Q2卡在了这道题上,虽然逆出算法,但是方程不会解,哈哈哈哈,果然数学知识很重要呀,现在记录一下. 首先根据关键信息,根据错误提示字符串定位到这里: 1 int __t ...
- 攻防世界 reverse debug
debug XCTF 3rd-GCTF-2017 .net程序,这里我用的dnspy,当然.net Reflector也很好用. 查看程序,发现是明文比较,下断,debug,完成. flag{967 ...
- CentOS离线安装Nginx
在医院搭建项目环境时,因为医院通常都是内网的,访问不了外网,所以很多服务都得通过离线的方式安装,下面讲讲CentOs系统中如何离线安装Nginx. 安装准备 Nginx离线安装依赖gcc.g++环境, ...
- java例题_41 利用递归给猴子分桃
1 /*41 [程序 41 猴子分桃] 2 题目:海滩上有一堆桃子,五只猴子来分.第一只猴子把这堆桃子平均分为五份,多了一个,这只猴子把 3 多的一个扔入海中,拿走了一份.第二只猴子把剩下的桃子又平均 ...
- 全面了解Vue3的 reactive 和相关函数
Vue3的 reactive 怎么用,原理是什么,官网上和reactive相关的那些函数又都是做什么用处的?这里会一一解答. ES6的Proxy Proxy 是 ES6 提供的一个可以拦截对象基础操作 ...
- limanmanExp数据库审计设计思路与重要代码
目的 在代码审计的时候经常会想看看某个访问会触发哪些数据库操作.目前已知的数据库审计有多家大型厂商的设备,还有seay源码审计系统中的数据库监控1.0 但是.开源的已知的就只有seay源码审计系统中的 ...
- 使用 nodejs 中的 http 模块实现几个超实用的工具
nodejs 方便了我们前端开发者进行一些服务端上的操作,可以进行无缝地衔接.像其他一些后端语言,如 php, golang, java 等,都需要一定的学习成本,而 nodejs 则就是为前端开发者 ...
- (十一)struts2的未知处理器
从struts2.1开始,struts2增加了未知处理器. 当用户请求未知Action,或指定Action里的未知方法,或Action处理结束后返回一个未知的result.struts2允许使用未知处 ...