反调试——Windows异常-SEH

概念:

SEH:Structured Exception Handling

SEH是Windows默认的异常处理机制

如何使用

在代码中使用

__try


__except()//结构类型的语句

__except()小括号里面填写表达式,表达式为真的时候执行里面的内容

__try里面包含的是可能触发异常的语句,except里面包含的是出现了异常后执行的操作。

例子:

int main()
{
__try
{
cout<<"hello,world"<<endl;
}
__except(1)
{
cout<<"异常"<<endl;
}
return 0;
}

异常的作业

1 便于查找错误

2 可以用在反调试里面

异常处理机制

当我们在非调试状态下运行一个程序,程序如果触发了异常,会先判断是否有异常处理器,如果存在则跳转到异常处理函数去执行,如果不存在则退出程序

如果程序处于被调试状态,触发异常时,操作系统会先把异常抛给调试进程,也就是让调试器来处理异常。可以看到的现象就是触发了异常后,程序会暂停下来,也就是断下来,也就是断点的原理。当异常抛给调试器后,调试器可以选择:

1 修改触发异常的代码继续执行(程序会停在触发异常的代码处,导致异常的代码无法执行)

2 忽略异常交给SEH执行

也就是说Windows发生异常后的处理顺序为:1、调试器处理。2、SEH处理 3、崩溃

剖析SEH

SEH结构:

typedef struct _EXCEPTION_REGISTRATION_RECORD {
  struct _EXCEPTION_REGISTRATION_RECORD *Next;
  PEXCEPTION_ROUTINE Handler;//异常处理器,异常处理函数
} EXCEPTION_REGISTRATION_RECORD;

SEH在程序中实际上是以链表形式存在,每一个next都指向下一个SEH,这个链表也叫SEH链(如图):

每次添加一个异常就会添加该异常到异常链的头结点的位置

观察SEH是如何生成和使用的

生成两个程序观察,两个程序的区别就是一个有异常SEH,一个没有

//有异常的程序代码
#include<Windows.h>
#include<iostream>
int main()
{
__try
{
char* str = NULL;
str[0] = 'a';
}
__except(1)
{
printf("触发异常了\n");
}
printf("Sna1lGo\n");
return 0;
}
//没有异常的程序代码
#include<Windows.h>
#include<iostream>
int main()
{
char* str = NULL;
str[0] = 'a';
printf("Sna1lGo\n");
return 0;
}

分别生成后,都用od打开调试比对

然后都进入main函数

重点查看SEH的代码:

这四条指令就是SEH的关键代码,这一系列操作相当于创建了一个异常的结构体,然后添加到异常链的表头里面。

分析为什么是这样:

首先,大概画一个堆栈图:

先存进来了一个0x01293609,然后调用了fs:[0]这个东西,这个东西有点眼熟之前的TEP-PEB查找核心模块的时候有用过,但是这里,可以将fs:[0]直接理解为SEH链的表头。

这里取出来fs:[0]给eax后又把eax入栈,然后将fs:[0]赋值为esp

可以理解为在栈中创建了一个SEH变量,然后第一个字段存放了函数地址也就是0x01293690,next字段指向了fs:[0]也就是SEH链的第一个节点,然后再把fs:[0]的值修改为该节点的首地址,也就是让fs:[0]指向新的节点。(可能你的代码有点不一样,但是稍微分析下,对于异常处理这里也是一样的)

下面进入异常处理函数的地址查看(这里是0x01293690)

然后再运行会暂停下来,因为出现了异常,异常优先给调试器处理,但是调试器也是可以选择处理异常的:

在od的选项中选择调试选项,再选择异常:

就可以设置要捕获的异常类型了,选择忽略掉一些异常后再遇到就不会中断下来了。

也可以选择插件的StrongOD:

在取消掉Skip Some Exceptions之后,OD就会捕获所有异常了

SEH链存放的位置

经过上面的分析可以知道了,SEH存放的位置在fs:[0]这里

操作系统如何使用SEH

创建异常后,操作系统会自动把异常添加到头结点,然后把头指针指向新的异常节点

反调试——Windows异常-SEH的更多相关文章

  1. Windows反调试技术(下)

    OD的DBGHELP模块 检测DBGHELP模块,此模块是用来加载调试符号的,所以一般加载此模块的进程的进程就是调试器.绕过方法也很简单,将DBGHELP.DLL改名. #include <Wi ...

  2. Windows 下常见的反调试方法

    稍稍总结一下在Crack或Rervese中比较常见的一些反调试方法,实现起来也比较简单,之后有写的Demo源码参考,没有太大的难度. ①最简单也是最基础的,Windows提供的API接口:IsDebu ...

  3. Windows反调试技术(上)

    写在前面 在逆向工程中为了防止破解者调试软件,通常都会在软件中采用一些反调试技术来防破解.下面就是一些在逆向工程中常见的反调试技巧与示例. BeingDebuged 利用调试器加载程序时调试器会通过C ...

  4. Windows 32位-调试与反调试

    1.加载调试符号链接文件并放入d:/symbols目录下. 0:000> .sympath srv*d:\symbols*http://msdl.microsoft.com/download/s ...

  5. Windows 反调试技术——OpenProcess 权限过滤 - ObRegisterCallback

    转载: https://blog.xpnsec.com/anti-debug-openprocess/ 看雪翻译:https://bbs.pediy.com/thread-223857.htm 本周我 ...

  6. windows的SEH异常处理以及顶层异常处理

    前言 windows的SEH结构化异常处理是基于线程的,传统的SEH结构化异常会基于堆栈形成一条包含异常回调函数地址的链(SEH链).而fs:[0](TEB的第一个字段)指向这条链的链头,当有异常发生 ...

  7. 反调试技术常用API,用来对付检测od和自动退出程序

    在调试一些病毒程序的时候,可能会碰到一些反调试技术,也就是说,被调试的程序可以检测到自己是否被调试器附加了,如果探知自己正在被调试,肯定是有人试图反汇编啦之类的方法破解自己.为了了解如何破解反调试技术 ...

  8. WinDbg调试流程的学习及对TP反调试的探索

    基础知识推荐阅读<软件调试>的第十八章 内核调试引擎 我在里直接总结一下内核调试引擎的几个关键标志位,也是TP进行反调试检测的关键位. KdPitchDebugger : Boolean ...

  9. 基于TLS的反调试技术

    TLS(Thread Local Storage 线程局部存储) 一个进程中的每个线程在访问同一个线程局部存储时,访问到的都是独立的绑定于该线程的数据块.在PEB(进程环境块)中TLS存储槽共64个( ...

随机推荐

  1. StrictMode 检测应用

     Application, Activity, or other application component's onCreate() method:if (BuildConfig.SHOW_LOG) ...

  2. redis数据结构和对象一

    1. SDS:简单动态字符串(simple dynamic string) Redis没有直接使用C语言的字符串,而是自己构建了一种名为简单动态字符串类型,并将SDS用作Redis的默认字符串. SD ...

  3. tcpdump后台抓包并输出给wireshark

    # 先进到/tmp 目录执行,方便Filezila 传输 # 开启抓包 nohup tcpdump -i eth0 -s0 -nnA 'port 22' -w dump22.pcap & [1 ...

  4. XAPKInstaller - XAPK游戏包安装器

    XAPKInstaller 一个用于安装XAPK游戏包的安装器. 程序需要读写存储与获取已安装应用权限才可正常运行. 长按条目可显示文件的详细信息. SDK小于24(Android N)的设备会显示应 ...

  5. Microsoft Teams 最新功能发布:协作篇

    正在进行的2021年的Microsoft Ignite大会,发布了一系列跟Microsoft Teams相关的新功能,英文介绍请参考 https://techcommunity.microsoft.c ...

  6. 手把手教你Spring Boot2.x整合Elasticsearch(ES)

    文末会附上完整的代码包供大家下载参考,码字不易,如果对你有帮助请给个点赞和关注,谢谢! 如果只是想看java对于Elasticsearch的操作可以直接看第四大点 一.docker部署Elastics ...

  7. 选择 FreeBSD 而不是 Linux 的技术性原因2

    ZFSZFS 文件系统是 FreeBSD 上的一等公民.这不仅意味着可以在 ZFS 上安装根目录,安装程序也支持这一点,而且还意味着很多基础系统工具都已经紧密地集成或构建了对 ZFS 的支持.在 Fr ...

  8. unittest系列(一)unittest简介和示例

    unittest - 单元测试框架 单元测试框架是受到 JUnit 的启发,与其他语言中的主流单元测试框架有着相似的风格.其支持测试自动化,配置共享和关机代码测试.支持将测试样例聚合到测试集中,并将测 ...

  9. weblogic之cve-2015-4852分析(重写)

    前言 有时间打算分析weblogic历史漏洞,但是又要面试啥的,没空.又刚好最近面试会问weblogic反序列化.具体啥时候分析weblogic反序列化,可能会在护网后,或者我开学了再分析.期间可能我 ...

  10. python-实现输出乘法口诀表

    list1 = [1,2,3,4,5,6,7,8,9] 2 def number(num): 3 for i in list1[:num]: 4 result = 1 * i 5 print(&quo ...