SEH源码赏析之C篇

(笔记)逆向工程核心原理——SEH SEH异常机制学习记录 阅读详情
1.起因
    C++程序员对try,catch,throw都应该很熟悉,能知道VC怎么实现它的人就不多了,不过网络世界使很多人知道了它与SEH (structured exception      handling)有密切关系,我也不例外,也是在若干年前从网络知道了SEH,并且大致也知道 SEH的流程.但是和多数人一样在我的实践也很少直接使用SEH,对SEH也就仅限于网络上一些文章的介绍.曾经在用Windbg对某些软件作分析,我遇到了断点失效的情况,查找资料介绍是SEH中的Handler清除了调试寄存器,在分析SEH代码中由于VC没有SEH的源码,于是我产生了一种想法,详细完整地翻译VC的SEH的代码,一劳永逸的解决问题.C和C++的SEH有所不同,C++的要复杂些,我在此介绍的仅为C的SEH代码,也就是 __try,__finally,__except,__leave所产生的SEH代码,C++篇有时间的话我再作.我以前看过的资料大都以比较专业的语言介绍,在此我仅以我自己感觉比较通俗的语言介绍,希望能有更多的人能认识,认清SEH.
2.SEH术语:SEH中术语虽然不多,但由于没有SDK的明确定义有时很难区别,各家说的表述也不太统一,因此为此文特定义如下术语,这些术语可能与其它文献有点冲突或细微差别,有的也是我自己的定义:
  A.SEH(structured exception handling): 在C语言中关键字是__try(_try),__finally (_finally),_except(__except),而C++使用的关键字是try,catch.在以下的表述中所有的try均不再特别声明为C 关键字,一律默认为C关键字.
  B. EH3_List:_EH3_EXCEPTION_REGISTRATION链表,表头位于FS:[0],0xFFFFFFFF为链表结束标志.编译器在编译一个函数时只要检测到含有_try或__try则为此函数生成一个_EH3_EXCEPTION_REGISTRATION节点,并插入到表头.因为每个函数编译只生成一个节点,因此在一个函数中C和C++的SEH不能同时存在,如果代码中同时有catch和except则不能通过编译就是此原因.
  C. EH3_ScopeTable:是一个由编译器在data section生成的一张表(数组),实质可看作是二叉树结构(可能有多个二叉树顺序存放),节点为_SCOPETABLE_ENTRY类型,其中_SCOPETABLE_ENTRY.ParentLevel是父节点在数组中的位置, EH3_ScopeTable[0]是根节点,_SCOPETABLE_ENTRY.ParentLevel=0xFFFFFFFF.由此可见 ParentLevel很重要,是SEH判断try嵌套层次的唯一依据.编译器从函数入口点开始遍历try,每遇到一个try生成一个节点 _SCOPETABLE_ENTRY,并放在表最后,注意节点的先后与try的嵌套层次无关.
  D. filter handler:是异常发生后让用户决定是否认识此异常,通过修改异常语句的上下文环境(CONTEXT)可使应用程序能继续正常运行.其返回值有三.
  EXCEPTION_EXECUTE_HANDLER(1): 去执行exception handler,然后进程终止,且不显示出错提示框.
    EXCEPTION_CONTINUE_SEARCH(0): 不执行exception handler,显示出错提示框,进程终止或者进入调试器进行调试.
    EXCEPTION_CONTINUE_EXECUTION(-1): 不执行exception handler,系统用CONTEXT重新设置CPU环境,进程继续执行,如果修改了EIP则从新的EIP开始执行,否则从原异常点开始执行.

    E. exception handler:是异常发生后检测到该异常无法被处理,而进程终止前提醒应用程序执行的收尾工作
  F. termination handler:如果try语句被过早终止,不管是正常离开或者是非正常离开,包括goto,leave及异常时均执行此handler,具体执行过程可查MSDN.
  G. 展开(unwind):这个名词很让人费解,翻译也确实不好命名,我也沿用此名.展开的目的是执行finally对应的 termination handler,对照在下面的源代码中我们就能很容易理解MSDN关于finally的解释了.展开分为本地局部展开 (_local_unwind)和全局展开(_global_unwind);本地展开:展开此try所在函数try嵌套关系并分别执行其finally 对应的termination handler;全局展开:当exception handler不在本try函数时,执行 exception handler前需要先执行这之前的termination handler,全局展开就是查找这些 termination handler并执行它.需要说明的是全局展开不含本地展开.
3.SEH数据结构
  typedef struct  // (sizeof=0xC)
  {
    DWORD ParentLevel ;     // 当前Handler父层TRY在EH3_ScopeTable中的位置,根没有上一层,故值=-1
                 // 形成TRY层次的二叉树结构,与_EH3_EXCEPTION_REGISTRATION.TryLevel物理意义一样
    DWORD FilterFunc;      // 非NULL则HandlerFunc是exception handler,否则termination handler
    DWORD HandlerFunc;     // exception handler or termination handler
  } _SCOPETABLE_ENTRY;
  typedef struct  // (sizeof=0x10)
  {
    _EH3_EXCEPTION_REGISTRATION* pPrev;// 栈上一级EH3_List节点,=0xFFFFFFFF则为最后一个节点
    EXCE_HANDLER ExceptionHandler;     // VC7.1中统一指向_except_handler3
    _SCOPETABLE_ENTRY* pScopeTable;     // 指向一个_SCOPETABLE_ENTRY数组,函数有n个TRY,则数组有n个元素
                       // p[0]->Try0为根,p[1]->Try1,p[2]->Try2...
    DWORD TryLevel;     // 指示当前指令在Try的层次级别,-1未进入TRY,进第一个TRY为0,第二个为1,...
              // 但它与嵌套层次无关,在编译时确定,从函数代码开始处开始计数
  } _EH3_EXCEPTION_REGISTRATION;
  typedef struct  // (sizeof=0x10)还有待进一步分析其用处
  {
    DWORD unKnown;    // 未知:被编译器赋值
    DWORD HandlerFunc;  // _SCOPETABLE_ENTRY.HandlerFunc
    DWORD firstPara;    // Try所在函数第一个参数:crtMain!EBP+8
    DWORD TryEBP;    // Try所在函数EBP
  }_NLGDestination;
  // 以下在MSDN中均有定义,不再作解释
  typedef struct _EXCEPTION_RECORD
  {
    DWORD    ExceptionCode;
    DWORD ExceptionFlags;
    struct _EXCEPTION_RECORD *ExceptionRecord;
    PVOID ExceptionAddress;
    DWORD NumberParameters;
    ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
  } EXCEPTION_RECORD,*PEXCEPTION_RECORD;
  typedef struct _CONTEXT
  {
    ...         // 依据CPU类型有不同定义,具体可见winnt.h
  } CONTEXT,*PCONTEXT;
  typedef struct _EXCEPTION_POINTERS
  {
    PEXCEPTION_RECORD ExceptionRecord;
    PCONTEXT ContextRecord;
  } EXCEPTION_POINTERS,*PEXCEPTION_POINTERS;
4.SEH汇编要点
  A. 函数中try的数据模型:VC将会为有try函数在栈上首先建立三个变量:
    EBP-18h:    SaveESP          // TRY前保存当时ESP,因此有:SaveESP<&Eh3Exception
    EBP-14h:    pExceInfo        // GetExceptionPointers(),在handler中调用filter前赋值
    EBP-10h:    Eh3Exception      // 一个_EH3_EXCEPTION_REGISTRATION,其大小刚好为10h哦
    EBP+00h:    ebp            // 上一frame的EBP
    EBP+04h:    EIP            // CALL返回地址
    在这里我们应该注意到这个公式是成立的:
          EBP=&Eh3Exception+10h
    而在_except_handler3中参数: pEh3Exce刚好为&Eh3Exception,所以每当在 _except_handler3中要回调filter,exception,termination handler时,在这之前汇编中均有一句:
          lea     ebp, [ebx+10h]    // ebx=_except_handler3!arg_pEh3Exception
    明白了这点就不难明白如何在
SEH不起作用的问题跟踪 关建词 _except_handler4、_except_handler3、_ValidateEH3RN 问题: 写了一个程序(shell,你懂的),发现SEH捕捉不到异常,网上搜了一下没找到相关内容,下面的代码是为了写文章简单写的例子代码 __try { _asm int 3; } __except(1) { printf("except\r\n"); } 阅读详情

相关推荐

深入解析结构化异常处理(SEH) - by Matt Pietrek

深入解析结构化异常处理(SEH) - by Matt Pietrek

dvlinker的技术专栏 5万+

[原创]windows-SEH详解

SEH是window操作系统默认的异常处理机制,逆向分析中,SEH除了基本的异常处理功能外,还大量用于反调试程序(这里SEH时保存在栈中的,漏洞利用的时候会用到) 1.SEH SEH是windows操作系统异常处理机制,在程序源代码中使用__try,__except,__finally关键字来具体实现。 2.OS异常处理的办法 2.1正常运行时候的异常处理方法 进程运行过程中若发生异常,OS会委托进程进行处理。若进程代码中存在具体的异常处理(如SEH异常处理器)...

whl0071的专栏 4822

SEH的介绍及实战

根据我们上节的异常讲解中,我们说过了SEH(Structured Exception Handler)是在无调试器接手的情况下,系统会遍历SE链,然后寻找相应的SEH函数来处理异常。 首先稍微复习下我们的TEB kd> dt _teb ntdll!_TEB +0x000 NtTib : _NT_TIB +0x01c EnvironmentPointer : ...

For Geek 1万+

异常与调试之SEH、UEH、VEH、VCH以及SEH的区别总结——简单好理解

1.VEH (向量异常) // VEH: 向量化异常处理的一种,被保存在一个全局的链表中,进程内的所有线程都可 // 以使用这个函数,是第一个处理异常的函数。 异常处理函数: LONG NTAPI AddVectoredExceptionHandler( _In_UlON First, 异常处理函数被调用的顺序 _In_PVECTORED_EXECUTE_HANDLER Handler 异常处理回调函数 ) AddVectoredExceptionHandler(TRUE...

TCP_321的博客 7559

【逆向工程核心原理:SEH

reverse

qq_42363151的博客 1810

SEH异常处理机制

1.SEH是windows操作系统提供的异常处理机制。 2.在程序中可以使用__try、__except、__finally关键来实现异常处理。 3.SEH属于系统级的异常处理,是不同于C++中try、catch的。SEH诞生的更早一些。 4.异常处理过程: 正常情况:程序执行->抛出异常->程序SEH处理函数->系统默认SEH处理函数。 调试情况:程序执行->抛出异常->调试器中断处理->程序SEH异常处理->系统默认异常处理 如果程序没有异常处理函数

谈成(C/C++) 2193

Windows异常世界历险记(四)——VC6中结构化异常处理机制的反汇编分析(中)

本文主要分析VC6中结构化异常处理机制的tryLevel含义,栈结构并给出except_handler3函数的逆向还原结果。

LPWSTR的博客 564

SEH(结构化异常处理)

内容回顾: 当用户异常产生后,内核函数KiDispatchException并不是像处理内核异常那样在0环直接处理,而是修正3环EIP为KiUSerExceptionDispatcher函数后就结束了。 这样,当线程再次回到3环时,将会从KiUserExceptionDispatcher函数开始执行。 KiUserExceptionDispatcher会调用RtlDispatchException函数来查找并调用异常处理函数,查找的顺序: 先查全局链表:VEH 再查句柄链表:SEH 它是与线程有关的,

寻梦&之璐 5993

SEH

@author: dlive SEH是Windows的异常处理机制,在程序源代码中使用__try,__catch,__finally关键字来具体实现。 但SEH与C++的try, catch异常处理不同,从时间上看,与C++的try, catch相比,微软先创建了SEH机制,然后才将它搭载到VC++中。 SEH大量应用于压缩器,保护器,恶意程序用来反调试 0x01 OS的异常处理方法 正常运行时的...

weixin_30507269的博客 492

走进SEH(Structured Exception Handling)

最近手头上工作比较轻松,于是继续充点电。本系列主要从核心编程里面学来,同时外加网上的搜集整理得来。文章主要以应用为主,所以对已经了解的人可能不会有太大帮助,但学习的总结分享出来总会有其用武之地。如发现内容表述有误,请指正。由于幅较长,为便于阅读故斩其首分上中下以述之~ 前言         SEH("Structured Exception Handling"),即结构化异常

韵苑23栋工作室 2243

掀起你的盖头来——Windows SEH

将浏览器宽度调窄些有利于阅读本文 掀起你的盖头来——Windows SEH SEH(Structured Exception Handling)亦即结构化异常处理,是Windows操作系统提供处理程序错误或异常的机制。相应的在C/C++中也提供了__try{}、__except{}、__try{}、__finally{}结构,但这些并不完全是由编译器本身提供的,编译器只不过是将Windows

nlqlove的专栏 4114

SEH结构

首先有几点问题 1.在后文中看到的PE的节中的配置信息表Load configuration是对SEH回调函数的注册,那么Exception Table是加载的什么信息。 2.什么时候走进系统异常,什么时候走进自己注册的异常回调函数。 摘自 《加密与解密》和《Windows PE权威指南》 0x01 Windows结构化异常处理   结构化异常处理是Windows OS处理程序错误...

weixin_30768175的博客 479

SEH及逆向调试

SEH 文章目录SEH1. 异常处理方法正常运行的异常处理调试运行的异常处理2. 常见异常EXCEPTION_ACCESS_VIOLATIONEXCEPTION_BREAKPOINTEXCEPTION_ILLEGAL_INSTRUCTIONEXCEPTION_INT_DIVIDE_BY_ZEROEXCEPTION_SINGLE_STEP3. SEH详细说明回调函数ExceptionRecordEs...

Starr 3448

A Crash Course on the Depths of Win32 Structured Exception Handling

Matt Pietrek 著  董岩 译在所有 Win32 操作系统提供的机制中,使用最广泛的未公开的机制恐怕就要数结构化异常处理(structured exception handling,SEH)了。一提到结构化异常处理,可能就会令人想起 _try、_finally 和 _except 之类的词儿。在任何一本不错的 Win32 书中都会有对 SEH 详细的介绍。甚至连 Win32 SDK 里都

程序员的梦 1258

内核学习-异常

内核学习-异常 异常产生后,首先是要记录异常信息(异常的类型、异常发生的位置等),然后要寻找异常的处理函数,称为异常的分发,最后找到异常处理函数并调用,称为异常处理。 围绕 异常处理,异常分发,异常处理展开 异常的分类: (1)cpu产生的异常 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZYiH89U2-1635589257293)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-202110

weixin_45880501的博客 728

5.6 在栈溢出中利用S.E.H

栈溢出 S.E.H

qq_55202378的博客 832

VC异常处理

转自:http://blog.csdn.net/dyf7970268/article/details/6413327 SEH定义   SEH("Structured Exception Handling"),即结构化异常处理.是(windows)操作系统提供给程序设计者的强有力的处理程序错误或异常的武器。   在VISUAL C++中你或许已经熟悉了_try{} _finally{} 和_tr

游侠之魂的专栏 1647

学习心得----seh(4)

解读cih进入ring0的秘密   看了大家对前面几的评论,觉得有点怪异,看来大家对技术的追求还不是那么强烈,声明以下,我写的这些东西或许永远也不会对你的实际应用有帮助,这只是黑客们对技术的研究,如果你的愿望只是一般的编程,这文章不适合你。   这几天开始编一个游戏,以前没有接触过游戏编程,觉得很有意思,还有directX的编程,真得很爽,我估计也就几天的热情吧,呵呵。   还有,我知道我的老

sssa2000的专栏 1298
上一篇: 一种注入进程,获得完全操控的方法
下一篇: PE结构是那一类!获取导入表和导出表的类
iiprogram
博客等级 码龄25年 1066粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值