[2021]x64 SEH分析 huoji 异常处理,PE模拟器,SEH,X64 2021-03-27 1701 次浏览 0 次点赞 最近在给沙箱增加异常处理 然后打算学习一下异常处理的内容,,搜索了一下 网上都是莫名其妙复制粘贴的,我们直接从原理上解决这个问题: 首先是try catch ![](https://key08.com/usr/uploads/2021/03/3198721258.png) ------------ ### 简单看一看 ------------ 然后逆向代码如下: ![](https://key08.com/usr/uploads/2021/03/1023769283.png) X64下 编译器会为程序生成一个叫做 expection table的区段,这里面包含了一大堆RUNTIME_FUNCTION结构的异常处理函数列表: ```cpp typedef struct _RUNTIME_FUNCTION { DWORD BeginAddress; // Start RVA of SEH code chunk DWORD EndAddress; // End RVA of SEH code chunk DWORD UnwindData; // Rva of an UNWIND_INFO structure that describes this code frame } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION; ``` ![](https://key08.com/usr/uploads/2021/03/2862189061.png) 而try catch会被解析成RVA ![](https://key08.com/usr/uploads/2021/03/2196768153.png) 比如这个就是从sub_140001DA0开始到loc_140001DCB结束,对应汇编: ![](https://key08.com/usr/uploads/2021/03/1344502086.png) (我用throw抛出异常,对应的是_CxxThrowException) 而_RUNTIME_FUNCTION还有一个UnwindData是指向UNWIND_INFO这个结构: ```cpp // Unwind info flags #define UNW_FLAG_EHANDLER 0x01 #define UNW_FLAG_UHANDLER 0x02 #define UNW_FLAG_CHAININFO 0x04 // UNWIND_CODE 3 bytes structure typedef union _UNWIND_CODE { struct { UBYTE CodeOffset; UBYTE UnwindOp : 4; UBYTE OpInfo : 4; }; USHORT FrameOffset; } UNWIND_CODE, *PUNWIND_CODE; typedef struct _UNWIND_INFO { UBYTE Version : 3; // + 0x00 - Unwind info structure version UBYTE Flags : 5; // + 0x00 - Flags (see above) UBYTE SizeOfProlog; // + 0x01 UBYTE CountOfCodes; // + 0x02 - Count of unwind codes UBYTE FrameRegister : 4; // + 0x03 UBYTE FrameOffset : 4; // + 0x03 UNWIND_CODE UnwindCode[1]; // + 0x04 - Unwind code array UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1]; union { OPTIONAL ULONG ExceptionHandler; // Exception handler routine OPTIONAL ULONG FunctionEntry; }; OPTIONAL ULONG ExceptionData[]; // C++ Scope table structure } UNWIND_INFO, *PUNWIND_INFO; ``` 让我们解析一下: 得到exception table: ```cpp if (process.is_x64) { //64在exception table里面 auto exception_table_base = RtlImageDirectoryEntryToData((PVOID)process.m_image_base,TRUE,IMAGE_DIRECTORY_ENTRY_EXCEPTION,(PULONG)&process.exception_table_size); process.exception_table_base = process.m_image_base + ((PUCHAR)exception_table_base - (PUCHAR)process.m_image_base); printf("[PE] process.exception_table_base: %p process.exception_table_size %p \n", process.exception_table_base, process.exception_table_size); } ``` ![](https://key08.com/usr/uploads/2021/03/2592006354.png) 与ida里面的对应 ------------ ### 异常处理函数 ------------ 说了那么多,异常处理函数在哪? 如果有pruntimefunction结构,则系统会调用RtlVirtualUnwind展开unwind,至于怎么展开,会再下文说明. 本文由 huoji 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。 点赞 0
还不快抢沙发