关于SEH局部展开的一点思考

逆向分析kernel32.dll!__local_unwind2函数 引言:__local_unwind2函数是结构化异常处理的局部展开函数.7C80DF7F int __cdecl _local_unwind2(int argEstablisherFrame, int argTryLevel); CODE XREF: sub_7C80DF44+22p7C80DF7F ; BasepGetTempPa 阅读详情

最近读了Matt Pietrek的《A Crash Course on the Depths of Win32 Structured Exception Handling》,有如醍醐灌顶,尤其是编译器级的SEH,如果是SEH的初学者,推荐读一下这篇文章,不要先去看《windows核心编程》的异常处理章节,那样只会越搞越乱。如果把SEH帧链和_SCOPETABLE链这两条链搞清了基本就OK了,至于细节部分值得深究的地方还是很多的。但在这篇文章中一个没有具体提到的问题就是SEH的局部展开,也就是_local_unwind函数,由于这是一个与编译器相关的函数,所以对研究系统的SEH没有障碍。后来我在张银奎的《软件调试》补编的异常编译章节中找到了一段该函数的伪码,摘录如下:

 

这段伪码中最主要的是12行开始的那个while循环,第18行判断pCurScopeEntry->lpfnFilter是否为NULL,原因是在VC中try_finally块和try_except块一样,都对应一个scopetable中的_SCOPETABLE表项,区别在于try_finally对应表项的lpfnFilter值为NULL,也就是说没有过滤表达式。因此以上代码可以看出,局部展开的任务主要是搜索_SCOPETABLE链中的try_finally节点并执行finally处理代码。为了验证这个说法,我写了一小段代码

#include <windows.h>
#include <stdio.h>

void ViewScopeTable(DWORD* pSEHFrame)
{
     DWORD* Scopetable = (DWORD*)*(pSEHFrame+2);
     DWORD TryLevel = *(pSEHFrame+3);
     DWORD* pCurTable = (DWORD*)(Scopetable + TryLevel*3);
     while( TRUE )
     {
          printf("prevTryLevel:%x/nlpfnfilter:%x/nlpfnHandler:%x/n/n",
                   *pCurTable,
                   *(pCurTable+1),
                   *(pCurTable+2)
                   );
          if( ( TryLevel = *(pCurTable) ) == 0xFFFFFFFF)
                   break;
          pCurTable = (DWORD*)(Scopetable + TryLevel*3);
       }
}

 

void ShowSEHFrame()
{
          DWORD pSEHHead;
          _asm mov eax, fs:[0]
          _asm mov pSEHHead, eax
          printf("fs:[0]:%x/n/n", pSEHHead);
          DWORD* pHead = (DWORD*)pSEHHead;
          while(TRUE)
          {
                 printf("Frame addr:%x/nprev:%x/nhandler:%x/nscopetable:%x/ntrylevel:%x/n/n",
                          Head,
                         *pHead,
                         *(pHead+1),
                         *(pHead+2),
                         *(pHead+3)
                         );
                ViewScopeTable(pHead);
                if( *pHead == 0xFFFFFFFF )
                      break;
                pHead = (DWORD*)*pHead;
            }
}

void func1()
{
     _try{
              _try{
                           _try{
                                          ShowSEHFrame();
                          }_except( EXCEPTION_CONTINUE_SEARCH )    //except块
                          {

 

                           }
               }_finally   //有意设置成finally块

               {

 

               }
      }_except( EXCEPTION_CONTINUE_SEARCH )     //except块
      {

 

      }
}

 

int main()
{
 func1();
}

 

执行结果如下:

 

 

可见try_finally块和try_except一样被插入到_SCOPETABLE链中,只是lpfnFilter为0。

在Matt Pietrek的_except_handler3的伪码中有这样一句:

if ( pRegistrationFrame->scopetable[trylevel].lpfnFilter )

        .......

即判断_SCOPETABLE项的lpfnFilter,若是try_finally块则直接略过该节点,查询下一节点。而在上述的_local_unwind2伪码中,若是try_except节点则略过,查询下一节点。由此可以总结出:

try_except节点在发生异常时搜索异常处理块时被使用,而try_finally节点则用于局部展开的时候。

 

由于VC中的异常handler都指向_except_handler3,不是一个异常处理块对应一个异常处理帧,故没有办法在全局展开时直接用_except_handler3完成清理工作,所以有了try_finally结构,这样看来这个结构的出现也是在情理之中的。

SEH局部展开详解:异常处理中的栈展开机制与调试实战 在Windows系统开发与逆向工程中,异常处理(SEH)是保障程序稳健运行的核心机制。当异常被抛出后,系统并非直接跳转到处理函数,而是先经历一场复杂的栈展开过程。局部展开作为其中关键的一环,负责在异常发生帧与目标处理帧之间拆除栈帧,并顺路执行所有未退出的__finally清理逻辑。理解这一原理,对于排查诡异的“finally不执行”“异常处理后仍崩溃”等问题至关重要。本文从异常分派的两趟流程出发,深入剖析x86与x64两种体系结构下局部展开的实现差异,包括作用域表、try level、RtlUnwind以及 阅读详情

相关推荐

SEH源码赏析之C篇

1.起因    C++程序员对try,catch,throw都应该很熟悉,能知道VC怎么实现它的人就不多了,不过网络世界使很多人知道了它与SEH (structured exception      handling)有密切关系,我也不例外,也是在若干年前从网络知道了SEH,并且大致也知道 SEH的流程.但是和多数人一样在我的实践也很少直接使用SEH,对SEH也就仅限于网络上一些文章的介绍.曾经在

2314

windows SEH读书笔记

结构化异常SEH包括两个部分:终止处理和异常处理1.异常终止处理程序语法:__try/__finally1)从try块到finally的正常代码控制流 2)局部展开:从try块中的提前退出(由goto、longjump、continue、break、return等语句引起)将呈现控制流转入finally块。 3)全局展开:找try块对应except,从最里层找,没有则着上层,找到except进入

undeadyql的专栏 356

《Windows核心编程》之“SEH”

SEH,Structured Exception Handling(结构化异常处理),包括两种类型:一是Termination Handling,即终止处理;另一个是Exception Handling。本文主要介绍Termination Handling。 一、Advantages of Termination

Sagittarius_Warrior的博客 1466

Windows异常学习笔记(四)—— 编译器扩展SEH

Windows异常学习笔记(四)—— 编译器扩展SEH前言要点回顾编译器支持的SEH过滤表达式 前言 一、学习自滴水编程达人中级班课程,官网:https://bcdaren.com 二、海东老师牛逼! 要点回顾 当我们通过编程实现windows的异常处理方式使用SEH结构化异常时,我们必须做如下几件事情 将异常处理函数挂入SEH链表 需要自定义一个异常处理函数(异常过滤,异常处理) 注意:这种方式相对而言不太方便,因此现在的编译器都对SEH结构化异常提供了语法支持,并在其之上做了一定的拓展 编译器支

lzyddf的博客 791

深入解析数据通信中的码元速率与比特率:从基础到实战应用

本文深入解析了数据通信中的核心概念码元速率与比特率,通过生动的比喻和公式(比特率=波特率×log₂(M))揭示其本质关系。文章结合BPSK、QPSK、16QAM等调制技术,剖析了从4G/5G到LoRa等实战场景中如何权衡速率、距离与可靠性,并提供了软考真题解析与系统设计建议,帮助读者从理论到应用全面掌握数据速率优化。

weixin_29324877的博客 214

立创·庐山派-K230-CanMV(嘉楠勘智)开发板通过ATK-ESP8266实现图像识别数据无线传输至原子云

本文详细介绍了如何使用立创·庐山派-K230-CanMV开发板,通过ATK-ESP8266 WIFI模块实现图像识别数据的无线传输至原子云平台。内容包括硬件连接、软件环境搭建、AT指令控制、原子云连接及数据上传的全过程,并提供了实用的调试技巧和常见问题解决方案,为物联网应用开发提供了完整实践指南。

potato的博客 743

Windows SEH中的局部展开与全局展开

<br />经过阅读windows核心编程一书,对SEH中的局部展开和全局展开终于有了一个比较清晰的概念。<br />先说说__finally块的语义,__finally块语义就是只要是指令流将要流出其对应的__try块时,则__finally块中的代码将得到执行。那么所谓展开就是保证__finally块中的代码得到执行。下面详细解释下局部展开和全局展开<br />。<br /> <br />局部展开就是指某个函数中的__try块中的代码因为执行了return,break,goto,continue等指令使

2466

PaddleOCR实战:从零开始打造专属OCR模型的完整指南

本文提供了一份从零开始使用PaddleOCR打造专属OCR模型的完整实战指南。内容涵盖环境搭建、数据标注与准备、模型训练与调优,以及最终的模型转换与部署。重点介绍了如何利用PaddleOCR进行模型训练,并整合PPOCRLabel等工具高效准备数据集,帮助开发者快速构建适用于特定场景的高精度OCR识别能力。

rl6adventurer的博客 733

对于结构化异常处理(SEH)的进一步探索

写本文的起因 Matt Pietrek 关于结构化异常处理的文章 A Crash Course on the Depths of Win32 Structured Exception Handling 是一篇很棒的文章(在本文末的“相关文章”中有我整理过的中文版文章链接),对于我了解 Win32 下的这种异常处理机制帮助很大。在仔细读完整篇文章、跟踪过相关代码的执行流程后,仍有意犹未尽的感觉。本文

Victor 的专栏 1748

提升RAG效果:为何 JSON 格式远胜 Markdown?

在构建强大的 RAG (检索增强生成) 系统时,文档解析是至关重要的第一步。它直接影响着后续的检索效率和生成质量。在众多文档格式中,JSON (JavaScript Object Notation) 格式正逐渐展现出其相对于传统 Markdown 格式的巨大优势。本文将深入探讨 JSON 在 RAG 系统文档解析中的卓越之处,并结合具体案例,让你理解为何 JSON 才是构建下一代智能应用的更优选择。RAG 系统的核心目标是让模型能够利用外部知识库,生成更精准、更贴合实际的答案。

simoncool23的博客 2719

DDM-MIMO-FMCW雷达速度模糊与解模糊MATLAB仿真

本文深入解析了DDM-MIMO-FMCW雷达中的速度模糊现象及其解模糊方法,通过MATLAB仿真详细展示了相位编码解调、速度扩展算法和混合波形设计三大解决方案。文章还提供了参数配置、信号建模和结果可视化的实用技巧,并分享了工程实践中的避坑指南,帮助开发者高效解决雷达信号处理中的速度模糊问题。

weixin_31528001的博客 350

SEH:局部展开(八)

之所以能保证“离开 try 前一定执行 finally”,并不是因为编译器偷偷把 finally 插到 return 前面那么简单,而是因为运行时提供了 __local_unwind4 这样一套真正的“局部展开”机制:它会按照 ``ScopeTable +TryLevel的关系,把当前函数里沿途该执行的 __finally 一层层跑完,然后控制流才能真正离开当前 try。

取个名字太难了a的博客 235

STM32开发工具链选型:MDK、CubeIDE、VSCode与IAR深度对比

嵌入式开发工具链是连接软件逻辑与硬件行为的核心枢纽,其选择直接影响代码可靠性、调试效率与量产稳定性。从编译器优化能力、调试协议支持(如ARM CoreSight、SWO)、硬件抽象层级(寄存器/LL/HAL)到跨平台构建能力,不同工具在实时性保障、静态分析合规性(如MISRA-C)、WCET可预测性及生态开放度上存在本质差异。尤其在STM32平台,Keil MDK凭借深度调试能力成为HardFault定位首选,STM32CubeIDE依托图形化配置加速外设初始化,而VSCode+PlatformIO则以LS

weixin_42602368的博客 429

SEH局部展开:Windows异常处理中栈对象析构的关键机制

在Windows系统级开发中,结构化异常处理(SEH)是构建稳定底层程序的重要基石。当异常发生时,系统不仅需要完成栈帧回卷,还必须协调语言运行时按逆序析构局部对象,这一过程即局部展开。其核心原理在于系统与编译器通过函数表与语言特定数据区(LSDA)协作,将指令地址映射到活跃对象清单,进而在栈指针恢复前安全执行析构逻辑。这一机制直接支撑了C++的RAII资源管理语义,确保文件句柄、互斥锁等自动释放。对于运行时开发、动态插桩及复杂崩溃排查,理解局部展开有助于快速定位析构顺序异常或资源泄漏问题。在实际工程中,关注

weixin_27134495的博客 126

万字长文告诉新手如何学习Python图像处理(上篇完结 四十四) | 「Python」有奖征文

这篇文章是图像处理的最后一篇文章,后面我们将进入新的章节。图像处理文章主要讲解的图像处理方法包括图像几何运算、图像量化采样、图像点运算、图像形态学处理、图像增强、图像平滑、图像锐化、图像特效、图像分割、傅里叶变换与霍夫变换、图像分类等。个人感觉如果你是编程初学者、Python初学者或图像处理爱好者,这个系列真心适合你学习,并且这篇文章算是Python图像处理的学习路线,希望您喜欢。

杨秀璋的专栏 2万+

MacBook 长期挂机 OpenClaw:电池保护 + 防休眠设置

本文介绍了MacBook长期挂机运行OpenClaw时的电池保护和防休眠设置方案。主要内容包括:1)电池保护策略,通过电源连接、充电限制和定期充放电维护电池健康;2)防休眠设置,禁用系统休眠、自动休眠和屏幕休眠;3)OpenClaw的Docker部署方法。文章提供了详细的命令行脚本和配置说明,帮助用户实现MacBook的长期稳定运行,同时保护电池寿命。

一键难忘的博客 1695

Windows SEH机制(一)

SEH全称为结构化异常处理。通过使用SEH,我们可以将软件的主要功能的编写和软件异常处理这两个任务分开。这样就可以先集中注意力完成手上的工作,稍后再去处理可能遇到的各种错误情况。异常处理应该用来处理那些不常出现的异常,对于一般的问题应该显式地检查以提高运行效率。

静下心来,做好每一件事 1190

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SEH

When SEH is used there is a registration process where an exception structure is created for every function as a local variable. The last field of the structure overlaps the location where frame poi...

weixin_33970449的博客 477

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Windows_SEH终止处理

在分享中学习,才能让自己跑得更快。   SEH(structured exception handing),中文叫做结构化异常处理。 我们使用SEH,不是意味着可以完全无视代码之中可能出现的那一些异常,但是可以将程序的功能实现和程序的异常处理区分开来。也就是说我们先把程序的功能都实现起来,到后面再去处理程序在运行的时候可能遇到的一系列情况。 Microsoft把SEH加入Windows的原...

做一个快乐学习者 683

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

走进SEH(Structured Exception Handling)

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

韵苑23栋工作室 2250

内核学习——VEH / SEH

VEH全局链表:与线程无关 在这里插入代码片 SEH局部链表:在堆栈中 在这里插入代码片 ExceptionRecord结构体 异常结构体要在当前线程 汇编就只有一个 原结构体(基础结构体) 优化(debug,release,堆栈方式等)少因为要维持堆栈结构 ebp当前堆栈栈底 几个try几个成员,存的是地址 再嵌套一个level是2 结合原始过程分析 这里自...

q1uTruth的博客 1549

6.编译器拓展SEH

//1.挂入链表相当于这部分 //fs[0]-&amp;amp;amp;gt; Exception _asm { mov eax, fs:[0] mov temp,eax lea ecx,Exception mov fs:[0],ecx } //为SEH成员赋值 Exception.Next = (_EXCEPTION*)temp; Exception.Handler = (DWORD)&amp;amp;amp;am...

My classmates 649

SEH结构化异常处理

千言万语从何说起呢?嗯,还是先说说SEH的特点吧:SEH的优点在于当你编写代码的时候,可以集中注意力完成任务,如果在运行的时候出现了问题,系统会捕获到错误并且通知你出了问题.使得SEH工作的任务主要落在编译器而不是操作系统上.当进入,退出异常块时候,你的编译器必须产生特殊的代码.编译器必须产生处理SEH的数据结构,还必须提供操作系统能调用的回调函数来使得异常块能被遍历.编译器还负责准备栈框

anikan_yu的专栏 2678

结构化异常处理(SEH)

结构化异常处理(SEH) 结构化异常处理(SEH) __try : 保护代码块,该代码块产生异常会抛出该异常 __finally : 终结处理器,只要离开保护代码块,就会执行finaly内的语句 __except : 异常过滤, 1 :执行异常处理块,不回到产生异常处 0 :寻找下一个异常处理 -1:回到产生异常处再次执行 unsigned long GetExceptionCo

mslieng1011的博客 542

《谈谈windows核心编程系列》 结构化异常处理SEH之__finally终止处理

转载自:http://blog.youkuaiyun.com/ithzhang/article/details/8790567 结构化异常处理SEH:__finally终止处理。     结构化异常处理(Structuredexception handling)简称SEH。是windows系统提供的异常处理机制。促使windows将SEH加入到windows系统的一个关键原因就是

收集学习过程中对自己有帮助的牛人文章 721

Windows异常世界历险记(二)——Win32用户层下SEH机制之对RtlUnwind的逆向分析

RtlUnwind函数是一个用户层的Windows API函数,其作用是执行SEH的展开操作(正是由于Windows的SEH机制不自动进行展开操作,才提供了此API,供需要执行该操作的用户调用)。下面介绍其用处并进行逆向分析。

LPWSTR的博客 3192
上一篇: 启用PAE机制下虚拟地址到物理地址的转换
cuagain
博客等级 码龄17年 3粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值