此处需要注意两点:
a. 由于seh handler需要是绝对地址,故需要重定位
b. 如果被感染文件有SEH保护,还需要修改PE文件中的SEH表。因为被感染后的可执行文件发生异常,控制权转移到系统,要调用SEH处理函数时,系统会判断该SEH处理函数有没有在PE文件的SEH表中。我感染后调试时发现异常处理函数总是未被调用才意识到该问题。
三、SEH在exploit中的应用
在看exploit tutorial part 3 SEH Based Exploit时,我产生了很大的困惑。使用了SEH的函数栈的结构如下:
图中Params下面的Address of exception handler,完整的来说,是一个EXCEPTION_REGISTRATION结构。所谓的SEH exploit就是覆EXCEPTION_REGISTRATION结构,让系统执行我们的shellcode。
exploit tutorial part 3 SEH Based Exploit 中给予的覆盖时的流程解释如下:
a. 覆盖的eip产生一个异常
b. 当前的SE Handler地址被修改成进程空间里某个dll中的pop,pop,ret的地址
c. 系统执行pop,pop,ret。在exception handler执行前,下一个SEH的地址被放在了ESP+8的位置上。通过pop.pop,ret 将这个地址放到eip中,执行在next SEH地址中的代码
a,b两步比较容易理解。c乍看之下,让人云里雾里的,尤其后面作者反复提到fake exception,我这种菜鸟就彻底晕了。其实,将c联系我们前面提到的异常处理函数原型,异常处理函数调用时栈的布局就不难理解了。
pop ;esp+0 被弹出
pop ;esp+4 被弹出
ret ;esp+8被弹出,作为eip
esp+8存储的是EXCEPTION_REGISTRATION的地址。通过pop,pop,ret ,函数将会跳转到EXCEPTION_REGISTRATION地址处执行。我们写在EXCEPTION_REGISTRATION的prev中的数据将会被当成代码执行。
于是乎,我们的seh exploit就能构造成如下的形式了:
[Junk][nSEH][SEH][Nop-Shellcode]
其中nSEH=jmp xxx的机器码
SEH=某个dll中pop,pop,ret的地址