反转 PECompact 打包代码(SEH 的工作原理)

逆向工程 例外
2021-06-23 17:24:00

我目前正在反转用 PECompact 打包器打包的文件。我对实际算法如何解包而不是解包文件感兴趣。

它使用 SEH 来修改程序流程。所以我想问一下SEH。

所以我有: 步骤1

所以我在0x4517E4将异常传递到应用程序后添加断点我去这里

在此处输入图片说明

它做一些代码修改和返回0ExceptionContinueExecutionEXCEPTION_DISPOSITION枚举)。它返回到内核函数,但是在它返回到应用程序之后应该从哪里继续执行?我试过在断点处设置断点,0x401016因为它是发生异常并在那里停止的点,我想问这是否只是巧合,还是应该这样工作?

我相信它与EXCEPTION_RECORD结构ExceptionAddress值有关。我对吗?

所以我真的很想知道异常处理如何确定点,根据处理程序函数的不同返回值应该从哪个程序继续执行。

我正在处理的文件也可以在这里下载

2个回答

我认为这是一个伟大的时刻给你介绍这个伟大的文章写早在1997年,但仍持有了。我真的建议你阅读它,因为它会向你解释关于 SEH 的一切。为了回答您关于继续执行的问题,我将引用文章中的一段:

当操作系统看到ExceptionContinueExecution被返回时,它会解释这意味着您已经修复了问题并且 应该重新启动错误指令由于我的 _except_handler 函数调整了 EAX 寄存器以指向有效内存,因此 MOV EAX,1 指令第二次工作并且函数 main 继续正常运行。看,这并没有那么复杂,是吗?

MOV     EAX, F0450569
LEA     ECX, DWORD PTR DS:[EAX+1000129E]   ;  ecx will be 00451807
MOV     DWORD PTR DS:[ECX+1], EAX          ;  451808 will hold f0450569
MOV     EDX, DWORD PTR SS:[ESP+4]          ;  ExceptionRecord
MOV     EDX, DWORD PTR DS:[EDX+C]          ;  ExceptionRecord->ExceptionAddress == 401016
MOV     BYTE PTR DS:[EDX], 0E9             ;  byte@exceptionAddress to e9 five byte jump
ADD     EDX, 5                             ;  ExceptionAddress+5 ==40101b
SUB     ECX, EDX                           ;  451807-edx = 507ec
MOV     DWORD PTR DS:[EDX-4], ECX          ;  assembles jmp 507ec @exception address
XOR     EAX, EAX                           ;  retn 0 == exception has been handled
RETN                                       ; 401016 == jmp 507ec instead of mov [eax],ecx

由于异常处理程序不会修改 eip 而是更改旧 eip 的操作码,您最终将执行相同的旧 eip
纯巧合
通常您应该在退出 seh 处理程序之前检查 ContextRecord->Eip 这包含将在 retun 时执行的 eip从内核检查 [[ESP+C]+0XB8] 在 retn 上查看 seh 处理程序中的 Context->Eip

您还可以在 ntdll.NtContinue 中设置断点,这是
在命中时在 seh 出口上跨越 um->km 边界的函数,您可以在 CONTEXT->Eip 上设置 bp(x86 32 位上的 xxx* + 0xb8)