软件调试学习笔记(四)—— 异常的处理流程

  • 要点回顾
  • 异常的处理流程
    • 实验1:理解调试器与异常的关系
  • 未处理异常:最后一道防线
    • 实验2:理解UnhandledExceptionFilter执行流程
    • 实验3:利用UnhandledExceptionFilter实现反调试

要点回顾

调试事件有多重类型、例如DLL加载、进程创建、线程创建等等。

其中最关键的调试事件是”异常“。

在调试过程中,不论是软件断点、硬件断点还是INT 3断点,都是通过异常来实现的。

异常的处理流程

流程图:

实验1:理解调试器与异常的关系

1)编译并运行以下代码:

#include <stdio.h>
#include <windows.h>int main ()
{int x = 100;int y = 0;int z;_try{z = x / y;     //除0异常printf("无法执行的代码 \n");}_except(1){printf("SEH异常处理代码 \n");}return 0;
}

执行结果:

2)设置调试器选项

3)使用调试器运行程序

程序停在40104E处,由于调试器没有除0异常处理代码,因此无法继续向下执行。

4)手动模拟异常处理,将[ebp-0x20]的值改为1,继续运行

程序成功向下运行。

思考:会不会存在某种异常没人处理的情况
答案:不存在,因为有UnhandledExceptionFilter(未处理异常)

未处理异常:最后一道防线

描述:在前面异常相关章节已经学习,任何一个线程,在启动时都会先布置最后一道防线。

__try
{}
__except(UnhandledExceptionFilter(GetExceptionInformation())
{//终止线程//终止进程
}

UnhandledExceptionFilter执行流程:
1)通过NtQueryInformationProcess查询当前进程是否正在被调试,如果是,返回EXCEPTION_CONTINUE_SEARCH,此时会进入第二轮分发。
2)如果没有被调试:

  1. 查询是否通过SetUnhandledExceptionFilter注册处理函数,如果就调用。
  2. 如果没有通过SetUnhandledExceptionFilter注册处理函数,弹出窗口,让用户选择终止程序还是启动即时调试器。
  3. 如果用户没有启用即时调试器,那么该函数返回EXCEPTION_EXECUTE_HANDLER。

实验2:理解UnhandledExceptionFilter执行流程

1)编译以下代码

#include <stdio.h>
#include <windows.h>int main ()
{int x = 100;int y = 0;int z;_try{z = x / y;     //除0异常printf("无法执行的代码 \n");}_except(0){printf("SEH异常处理代码 \n");}getchar();return 0;
}

2)双击运行程序

结论
1)由于当前进程并未处于调试状态,因此不会调用UnhandledExceptionFilter
2)由于当前程序并未使用SetUnhandledExceptionFilter注册处理函数,因此会让用户选择是否启动调试器。

通过UnhandledExceptionFilter的这个性质,可以借此实现反调试。

实验3:利用UnhandledExceptionFilter实现反调试

1)编译并运行以下代码:

#include <stdio.h>
#include <windows.h>DWORD g_Test = 0;LONG NTAPI TopLevelExcepFilter(PEXCEPTION_POINTERS pExcepInfo)
{printf("顶级异常处理器修复异常 \n");g_Test = 1;return EXCEPTION_CONTINUE_EXECUTION;
}int main ()
{int r = 0;int x = 100;SetUnhandledExceptionFilter(&TopLevelExcepFilter);r = x / g_Test;     //除0异常printf("正常逻辑开始执行 \n");for(int i=0; i<10; i++){Sleep(1000);printf("%d \n", i);}getchar();return 0;
}

编译器运行结果:

双击运行结果:

由于调试器不会触发SetUnhandledExceptionFilter设置的顶层异常,因此程序处于被调试状态时无法回归到正常逻辑;且调试器在处理异常时,若处理结果与程序所需不符,程序也将无法得以正常执行。

软件调试学习笔记(四)—— 异常的处理流程相关推荐

  1. 软件调试学习笔记(三)—— 调试事件的处理

    软件调试学习笔记(三)-- 调试事件的处理 要点回顾 调试事件的处理 实验一:实现简单调试器(创建进程) 实验二:分析异常来源 实验三:实现简单调试器(附加进程) 实验四:分析NtDebugActiv ...

  2. 软件调试学习笔记(七)—— 单步步入单步步过

    软件调试学习笔记(七)-- 单步步入&单步步过 单步步入 设置单步异常 处理单步异常 实验1:单步异常的设置与处理 单步步过 实现思路 实验2:实现单步步过 单步步入 描述: 单步步入的实现依 ...

  3. 软件调试学习笔记(六)—— 硬件断点

    软件调试学习笔记(六)-- 硬件断点 硬件断点 设置硬件断点 触发硬件断点 处理硬件断点 实验:硬件断点的设置与处理 硬件断点 描述: 与软件断点与内存断点不同,硬件断点不依赖被调试程序,而是依赖于C ...

  4. 软件调试学习笔记(五)—— 软件断点内存断点

    软件调试学习笔记(五)-- 软件断点&内存断点 调试的本质 软件断点 软件断点的执行流程 分析INT 3执行流程 实验:处理软件断点 内存断点 内存断点的执行流程 实验:处理内存断点 调试的本 ...

  5. 软件调试学习笔记(二)—— 调试事件的采集

    软件调试学习笔记(二)-- 调试事件的采集 要点回顾 调试事件的种类 调试事件采集函数 例:分析PspUserThreadStartup 例:分析PspExitThread 总结 要点回顾 调试器与被 ...

  6. 软件调试学习笔记(一)—— 调试对象

    软件调试学习笔记(一)-- 调试对象 准备工作 调试器与被调试程序 DebugActiveProcess 连接调试器 分析kernel32!DebugActiveProcess 分析ntdll!Dbg ...

  7. TDDFT计算软件Octopus学习笔记(四):带隙优化方法

    密度泛函理论是一种基态的理论,然而能带结构和带隙属于物质的激发态特性.因此DFT的固有缺点就是会低估带隙能量.这一缺点可以通过不同的方式加以修正.本文介绍两种方法. (一) DFT+U方法 (以ZnO ...

  8. 敏捷软件开发学习笔记(四)之结构型设计模式

    PHP结构型设计模式 参考 设计模式 PHP 设计模式全集 2018 什么是结构型是设计模式 结构型模式讲的是如何将类和对象按照某种布局组成更大的结构.它分为类结构型模式和对象结构型模式,其中类结构型 ...

  9. Windows软件调试学习笔记(1)

    --WINDBG中的表达式 WINDBG接受两种表达式,C++表达式和MASM表达式. 1. MASM表达式中的数值: MASM表达式中的数值可以基于16,10,8,2四种进制.用n命令可以设置WIN ...

最新文章

  1. (017)java后台开发之客户端通过HTTP获取接口Json数据
  2. turbo c图形方式下编程小技巧
  3. boost::intrusive::bucket_traits用法的测试程序
  4. HDU4911 Inversion 解题报告
  5. JDK8新特性(十)之Stream流的map和reduce组合使用、mapToInt()、concat()方法
  6. 简洁/易用/灵活/高效-RecyclerView适配器封装
  7. Python-密码字典生成
  8. 米字格图片可打印_练字本米字格模板可打印行楷书
  9. Spring Boot 集成maven和Spring boot的profile功能
  10. MATLAB基础知识零基础到入门(第一期 基础内容)
  11. android闹铃唤醒软件,温柔唤醒闹钟app_温柔的闹钟铃声有哪些_华为智能闹钟智能唤醒-多特软件站安卓网...
  12. Fiddler数据抓包试玩改包工具使用畅享
  13. 利用阿里大鱼发送短信验证
  14. 28 电子商务风险控制
  15. 2021 ICPC 四川省赛 L - Spicy Restaurant(多源BFS,DP)
  16. 怎样编写html购物车结算页面,原生JS实现购物车结算功能
  17. 这9道软件测试面试题,就能刷掉90%的软件测试员
  18. SSH + Lucene + 分页 + 排序 + 高亮 模拟简单新闻网站搜索引擎
  19. java tcp 心跳机制_Java实现心跳机制的方法
  20. 2012年北航研究生入学考试机试题

热门文章

  1. Blockchain:《Blockchain applications in insurance》Deloitte—德勤区块链技术研究报告正文版—听课记录
  2. SQL:使用备份向导、SQL命令、导出数据三种方式对已建立的数据库进行备份
  3. 关于ML.NET v0.7的发布说明
  4. Python基础教程【读书笔记】 - 2016/7/5
  5. ubuntu14.04LS中安装sogouPingyin
  6. STM32F系列USART的IDLE中断要注意了
  7. STM32的CAN总线的接收双FIFO使用方法
  8. 原野小年总共拍了多少_开一家羽毛球馆大概需要投资多少钱
  9. Keras学习代码—github官网examples
  10. stdthread(1)thread概述