全局SEH HOOK

先放代码:https://github.com/coNgY1/global-seh-hook

之前看到过VEH HOOK,就一直想能不能用SEH进行HOOK,这里就写了一个:

VEH HOOK主要好处是进程相关,而SEH是每个线程相关,每个线程的SEH chain是不同的,所以要弄SEH HOOK就必须将每个线程都添加一个seh handle,如果有新线程要创建,就必须在新线程创建后执行前进行添加我们自己的seh handle。

那么有两个地方需要处理:

1、新线程创建后执行前添加seh handle。

2、seh handle不通过push handle;  push fs:[0];  mov fs:[0],esp这种来创建。

针对1问题:

windows线程在创建后到达R3层上首先是LdrpInitialize这个位置,我最开始HOOK这个地方进行添加SEH handle,但是发现线程执行时候会有一个系统的seh handle在我添加的handle之前。也就是在LdrpInitialize后会进行一次添加,经过分析发现LdrpInitialize最后会调用ZwContinue

而ZwContinue的第一个参数是CONTEXT结构体,ZwContinue就是跳转到这个线程上下文去执行,+0xB8是EIP指向的地址是NTDLL.RtlUserThreadStart

分析RtlUserThreadStart发现它会调用RtlInitializeExceptionChain这个api对线程添加一个系统SEH handle,这个handle就是出现异常时候弹一个程序崩溃,终止程序。继续跟踪发现会调用BaseThreadInitThunk

这个函数作用就是初始化_tiddata然后call ThreadProc,并在线程函数返回后进行ExitThread操作。

所以我选择HOOK BaseThreadInitThunk这个API,因为此时系统的SEH已经被安装,我们可以将自己的SEH Handle添加到链表头部了。需要注意的是BaseThreadInitThunk函数的__fastcall调用约定。

针对问题2:

以前分析后SEH的调用部分,SEH调用前会判断handle是否在堆栈上,如果不是则不会处理,这里我将seh handle放在了tib->StackLimit处,这里是线程堆栈的底部,这样就不用通过push handle,push fs:[0],mov fs:[0],esp来处理了。

猜你喜欢

转载自blog.csdn.net/a893574301/article/details/86538006