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. Linux内核模块驱动加载与dmesg调试

    因为近期用到了Linux内核的相关知识,下面随笔将给出内核模块的编写记录,供大家参考. 1.运行环境 Ubuntu 版本:20.04 Linux内核版本:5.4.0-42-generic gcc版本: ...

  2. python学习9 函数的基础知识

    1.函数的定义 def  func(): 2.函数的调用 func() 3.函数的返回值 #1.没有返回值 # (1)不写return # (2)只写return后面的代码不在继续执行,返回空,代表结 ...

  3. PTA 二叉树的三种遍历(先序、中序和后序)

    6-5 二叉树的三种遍历(先序.中序和后序) (6 分)   本题要求实现给定的二叉树的三种遍历. 函数接口定义: void Preorder(BiTree T); void Inorder(BiTr ...

  4. 攻防世界 reverse 进阶 9-re1-100

    9.re1-100 1 if ( numRead ) 2 { 3 if ( childCheckDebugResult() ) 4 { 5 responseFalse(); 6 } 7 else if ...

  5. odoo 安装配置

    Linux ubuntu 环境 1.建个python虚环境 也可用其他替代 virtualenv env 2.找个稳定版本下载 wget https://nightly.odoo.com/8.0/ni ...

  6. istio sidecar使用自定义镜像源

    Istio 和 sidecar 配置保存在 istio 和 istio-sidecar-injector 这两个 ConfigMap 中,其中包含了 Go template,所谓自动 sidecar ...

  7. web编辑工具 - Brackets - 强大免费的开源跨平台Web前端开发工具IDE

      简单使用可以参考: https://blog.csdn.net/melon19931226/article/details/68066971/ https://www.iplaysoft.com/ ...

  8. 仅使用css实现点击 控制元素的显示与隐藏!

    视频教程:https://www.bilibili.com/video/BV1uE411Q7tx?p=15&spm_id_from=pageDriver 大致方法:在被点击的元素后面 放一个c ...

  9. (十)VMware Harbor 日志管理

    VMware Harbor 日志管理 1. 项目日志 每个项目下都有一个"日志"页签. 单击"日志"可以列出所有日志.可以按用户名或"高级搜索&quo ...

  10. JAVAEE_Servlet_22_Cookie实现十天内免登录

    Cookie实现十天内免登录 代码: - CheckLogin 查看是否获取到了Cookie,如果获取到了连接数据库验证Cookie发过来的用户名和密码,如果没有获取到Cookie信息,那么就跳转到登 ...