PatchGuard与异常处理密切相关,所以先看看x64的SEH
关于x86中内核如何捕获异常,分发异常,可以看 http://blog.youkuaiyun.com/shevacoming/article/details/7580350
上面那篇没有跟进分析RtlDispatchException,这里跟进以复习x86 seh的结构,也看经典的这一篇 http://bbs.pediy.com/showthread.php?threadid=14042
x86的异常处理是链式存储,存储在FS[0]中的
cPublicProc _RtlpGetRegistrationHead ,0
;cPublicFpo 0,0
mov eax,fs:PcExceptionList
stdRET _RtlpGetRegistrationHead
stdENDP _RtlpGetRegistrationHead
seh的结构包含下一个嵌套的seh和回调函数地址
typedef struct _EXCEPTION_REGISTRATION_RECORD {
struct _EXCEPTION_REGISTRATION_RECORD *Next;
PEXCEPTION_ROUTINE Handler;
} EXCEPTION_REGISTRATION_RECORD;
EXCEPTION_DISPOSITION
__cdecl _except_handler(
struct _EXCEPTION_RECORD *ExceptionRecord,
void * EstablisherFrame,
struct _CONTEXT *ContextRecord,
void * DispatcherContext
);
PE64里面的IMAGE_RUNTIME_FUNCTION_ENTRY记录了一些信息
typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY {
DWORD BeginAddress;
DWORD EndAddress;
DWORD UnwindInfoAddress;
} _IMAGE_RUNTIME_FUNCTION_ENTRY, *_PIMAGE_RUNTIME_FUNCTION_ENTRY;
为此我写了一个小程序
void MyPeView()
{
MAP_FILE_STRUCT FileContext;
LoadFileR(L"notepad.exe",&FileContext);
PIMAGE_RUNTIME_FUNCTION_ENTRY pRtlFunc = (PIMAGE_RUNTIME_FUNCTION_ENTRY)GetDirectoryEntryToData(FileContext.ImageBase,IMAGE_DIRECTORY_ENTRY_EXCEPTION);
for (int i=0;pRtlFunc[i].BeginAddress;i++)
{
printf("BeginAddress 0x%x EndAddress 0x%x UnwindData 0x%x \n",pRtlFunc[i].BeginAddress,pRtlFunc[i].EndAddress,pRtlFunc[i].UnwindInfoAddress);
}
UnLoadFile(&FileContext);
}
他输出的前几行与ida中一致,这个值是相对于基址的偏移。他记录了每一个函数的开头结尾以及异常信息。
BeginAddress 0x1000 EndAddress 0x10c8 UnwindData 0x13235
BeginAddress 0x10c8 EndAddress 0x11