美文网首页
在反汇编中还原C++ SEH

在反汇编中还原C++ SEH

作者: 静析机言 | 来源:发表于2022-10-27 17:32 被阅读0次

反汇编时如果遇到C++ SEH,会遇到如何快速还原程序流程的问题?

假设有如下代码,我们用VS 2015将其编译为release版本:crack5.exe

int main()

{

try

{

throw 3;//抛出3整形的异常

}

catch (int)

{

printf("%d\r\n", 3);

}

return 0;

}

一、要解决的问题

IDA静态分析crack5.exe

1)怎样找到SEH异常处理回调?

2)怎样找到正确的catch处理函数?

二、理解原理并实战

IDA打开crack5.exe,可以一眼找到SEH异常处理结构:_main_SEH

双击_main_SEH,可以看到结构体402548,__CxxFrameHandler3根据结构体402548对程序进行处理。

(1)原理介绍,上半部分表

注:图片是从别的地方拷贝的,个别字段名称与下面讲的有所不同,意义相同不影响理解。

下面我们来看看结构体 402548

stru_402548对应的为函数信息表FuncInfo。

struct FuncInfo {

    DWORD magicNumber;  // 编译器版本

    int maxState;      // 栈展开描述表中的入口数量

    UnwindMapEntry* pUnwindMap;  // 栈展开处理方法绑定表

    DWORD nTryBlocks;    // 函数中的 try 语句块数量

    TryBlockMapEntry* pTryBlockMap;  // try-catch 映射表

DWORD nIPMapEntries;

    void* pIPtoStateMap;

    ESTypeList* pESTypeList;

    int EHFlags;

}

重要字段就是dwTryCount以及pTryBlockMap,我们说过一个函数可以有多个try,所以函数信息就记录了try的个数.以及每个try的try块结构,关于上面的成员,都是SEH的异常展开的.

pTryBlockMap对应为stru_40257C,点击如下所示

TryBlockMapEntry 的定义如下。一个try可以有多个catch,显然,try块信息表也要记录catch的个数。

如果存在多个catch,如何区分?需要查看 tryLow、tryHight、catchHigh进行比对,就是看作用域最终确定catch函数。

struct TryBlockMapEntry {

    int tryLow;

    int tryHigh;    // this try {} covers states ranging from tryLow to tryHigh

    int catchHigh;  // highest state inside catch handlers of this try

    int nCatches;  // number of catch handlers

    HandlerType* pHandlerArray;  //catch handlers table

};

点击stru_402590,它为HandlerType结构,有时IDA识别为__msRttiDscr,两者相同。 可以看这个try由loc_401047进行处理,对应的数据项为addressOfHandler。

401047指向了sub_401080,做打印处理。

HandlerType的定义如下

struct HandlerType {

    DWORD adjectives;

    TypeDescriptor* pType;

    int dispCatchObj;

    void* addressOfHandler;

};

到这里,上半部分就看完了。

总结一下:对于上半部分,主要着重于函数信息表,try块信息表和catch信息表。顺藤摸瓜找到catch函数地址。

(2)原理介绍,下半部分表

下半部分用来快速定位异常由谁接收,哪个catch块处理。

实战演练

记得最开始C代码有一个throe吗?其位置就是抛出异常表的位置

首先,找到被抛异常的信息表

struct ThrowInfo {

    DWORD attributes;

    void (*pmfnUnwind)();

    int (*pForwardCompat)();

    CatchableTypeArray* pCatchableTypeArray;

};

接着,找到与之匹配的CatchableTypeArray。从中可以看到由1个匹配的CatchableTypes

struct CatchableTypeArray {

    int nCatchableTypes;  // number of entries in the following array

    CatchableType* arrayOfCatchableTypes[0];

};

接着,找catch 这种异常的类型为int型。IDA显示为??_R0H@8

struct CatchableType {

    DWORD properties;

    TypeDescriptor* pType;

    PMD thisDisplacement;

    int sizeOrOffset;

    void (*copyFunction)();

};

最后,选择??_R0H@8,按x,看到??_R0H@8类型被stru_402590交叉引用了

最终,异常被 loc_401047处理。

相关文章

网友评论

      本文标题:在反汇编中还原C++ SEH

      本文链接:https://www.haomeiwen.com/subject/iepttdtx.html