收集点关于FS寄存器的资料:
FS寄存器指向当前活动线程的TEB结构(线程结构) 偏移 说明 000 指向SEH链指针 004 线程堆栈顶部 008 线程堆栈底部 00C SubSystemTib 010 FiberData 014 ArbitraryUserPointer 018 FS段寄存器在内存中的镜像地址 020 进程PID 024 线程ID 02C 指向线程局部存储指针 030 PEB结构地址(进程结构) 034 上个错误号
得到KERNEL32.DLL基址的方法 assume fs:nothing ;打开FS寄存器 mov eax,fs:[30h] ;得到PEB结构地址 mov eax,[eax + 0ch] ;得到PEB_LDR_DATA结构地址 mov esi,[eax + 1ch] ;InInitializationOrderModuleList lodsd ;得到KERNEL32.DLL所在LDR_MODULE结构的InInitializationOrderModuleList地址 mov edx,[eax + 8h] ;得到BaseAddress,既Kernel32.dll基址
S.E.H结构原理:
首先确定自己的链表知识回调函数知识已经补充.
S.E.H结构包含两个DWORD指针:SEH链表指针和异常处理函数句柄,8个字节,8个要点.
1)SEH结构体存放在系统栈;
2)线程初始化将自动向栈里安装一个SEH结构,作为默认线程异常处理.
3)如果程序源代码中使用了_try{}和_excopt{}或者宏等异常处理机制,编译器将最终通过向当前函数栈安装一个SEH来实现异常处理.
4)栈中一般会同时存在多个SEH.
5)栈中的多个SEH通过链表指针在栈内由栈顶向栈底穿成单向链表,位于链表最顶端的SEH通过TEB 0字节处的指针来标识.
6)当异常发生时,操作系统会中断程序,并首先从TEB的 0字节偏移处取得最近的SEH,使用异常处理函数句柄所指向的代码来处理异常.
7)当离异常最近的异常处理函数不能处理时,将沿顺SEH链表逐步尝试.
8)如果程序所安装的异常处理函数都不能解决,系统将采用默认的异常处理函数来处理,通常弹出错误对话框,强制关闭程序.
根据以上8个要点可以总结出以下处理顺序:
①--->首先执行线程异常处理函数及最近的SEH.
②失败后将执行链表中的下一个异常处理函数,只止于NULL而不能解决.
③执行进程异常处理SEH
④执行系统异常处理SEH.
线程异常处理:2个状态值,参数无须解释.值得一提的是unwind操作.清理现场,释放资源技巧可以借鉴.
unwind操作通过kernerl.32中的函数rtlunwind()来实现.
进程异常处理:3种状态值.进程的异常处理回调函数需要使用kernerl32.dll中的函数setunhandledexceptionfliter()函数来注册.
系统默认异常处理:终极BOSS也称UEF.如果进程异常处理函数失败或者进程异常处理函数没有注册,系统异常处理函数unhandledexptionfilter()将被调用,所有的异常都将被捕获.
首先这个函数检查注册表,HKLM\SOFTWARE\MICROSOFT\windowsnt\cv\aedebug.其中值得一提的是其中的参数.指定了程序调试器.
ring3中第一个异常处理函数为kiuserexceptiondispatcher(),其首先检查调试状态,遍历SEH表,unwind操作,
然后失败调用终极BOSS.winxp增加了VEH.其中VEH与SEH不同的一个显著特点是,其为双向链表.其处理级别要高于SEH并保存在堆内.unwind操作对起不起作用.