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断点引发异常的思考的更多相关文章

  1. ssis package 在调试状态中设置断点,程序 不进入断点 的解决方案

    原文:ssis package 在调试状态中设置断点,程序 不进入断点 的解决方案 针对 SSIS intergation 项目 > 属性 > Debug >Run64bITRunt ...

  2. 在Visual Studio调试器中显示Unreal的数据类型的值

    转自:https://blog.csdn.net/witton/article/details/5977766 在Unreal引擎中大量使用了自定义的数据类型如:FName,FString,TArra ...

  3. 用DebuggerDisplay在Visual Studio的调试器中定制类的显示方式

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:用DebuggerDisplay在Visual Studio的调试器中定制类的显示方式.

  4. 在VisualStudio调试器中使用内存窗口和查看内存分布

    调试模式下内存窗口的使用 在调试期间,"内存"窗口显示应用使用的内存空间.调试器窗口(如"监视"."自动"."局部变量" ...

  5. 在 Visual Studio 调试器中指定符号 (.pdb) 和源文件

    查找并指定符号文件和源文件:指定符号加载行为.使用符号和源服务器上:加载符号自动或在要求.   内容 查找符号 (.pdb) 文件 查找源文件   查找符号 (.pdb) 文件 说明 在之前的 Vis ...

  6. @清晰掉 GDB调试器中的战斗机

    GDB 的命令很多,本文不会全部介绍,仅会介绍一些最常用的.在介绍之前,先介绍GDB中的一个非常有用的功能:补齐功能.它就如同Linux下SHELL中的命令补齐一样.当你输入一个命令的前几个字符,然后 ...

  7. 自定义Visual Studio调试器中的对象显示方式

    你有没有盯着调试器窗口中的对象,并希望你可以通过其他类型的东西来查看这些对象?我当然有!扩展项目以确定每个人的身份可能会非常快速.理想情况下,通过特定的属性值快速定位它们会很棒.对我们来说幸运的是,V ...

  8. 在Chrome调试器中引入jQuery

    在Console中输入以下代码并回车,Console显示"function (a,b){return new m.fn.init(a,b)}"说明导入成功,就可以在Console中 ...

  9. xcode 调试器 LLDB

    本文完全转载,转载地址:点击这里 你是否曾经苦恼于理解你的代码,而去尝试打印一个变量的值? NSLog(@"%@", whatIsInsideThisThing); 或者跳过一个函 ...

随机推荐

  1. CSS浮动布局带来的高度塌陷以及其解决办法

    1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...

  2. [系统重装日志2]win10系统安装pytorch0.4.1(gpu版本)

    目录 0,资源整理 1,安装最新版的显卡驱动 2,安装visual studio 3,安装cuda 4,安装cudnn,配置环境变量 5,安装pytorch 6,安装torchvision 7,验证 ...

  3. Java框架Spring Boot & 服务治理框架Dubbo & 应用容器引擎Docker 实现微服务发布

    微服务系统架构实践 开发语言Java 8 框架使用Spring boot 服务治理框架Dubbo 容器部署Docker 持续集成Gitlab CI 持续部署Piplin 注册中心Zookeeper 服 ...

  4. HTML5获取地理位置定位信息

    如何使用HTML5地理位置定位功能 定位功能(Geolocation)是HTML5的新特性,因此只有在支持HTML5的现代浏览器上运行,特别是手持设备如iphone,地理定位更加精确.首先我们要检测用 ...

  5. 带你全面认识CMMI V2.0(二)

    CMMI V2.0成熟度等级 CMMI V2.0的一大变化是,所有实践领域均适用于成熟度三级(ML3),并具有特定的附加必需实践水平. 例如,在ML3上需要进行因果分析和解决,但在CMMI成熟度四级( ...

  6. es的分布式架构原理能说一下么(es是如何实现分布式的啊)?

    在搜索这块,lucene是最流行的搜索库.几年前业内一般都问,你了解lucene吗?你知道倒排索引的原理吗?现在早已经out了,因为现在很多项目都是直接用基于lucene的分布式搜索引擎--elast ...

  7. iview中table多选、加载更多、下载等使用

    记录工作中的点点滴滴,为回忆过往添加片片记忆... 一.Table 1.使用render函数多层渲染以及表格可展开使用 源码地址:https://gitee.com/Mandy_wang/iview- ...

  8. RPC理论介绍

    目录 RPC概述 RPC是什么 和本地调用有什么区别 RPC模式 RPC的三个过程 为什么要使用RPC RPC和其他协议的区别 RPC使用场景 RPC的流程 RPC核心概念术语 RPC协议 RPC框架 ...

  9. 有了CopyOnWrite为何又要有ReadWriteLock?

    引言 前文我们有介绍<看了CopyOnWriteArrayList后自己实现了一个CopyOnWriteHashMap> 关于CopyOnWrite容器的,但是它也有一些缺点: 内存占用问 ...

  10. Scrapy的流程

    Scrapy框架的架构如下图 具体部分说明: Engine:引擎,处理整个系统的数据流处理,出发事物,是整个框架的核心 Item:项目.定义了爬取结果的数据结构,爬取的数据会被赋值成该Item对象 S ...