收集点关于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操作对起不起作用.