栈溢出笔记1.11 SafeSEH

在上节写示例的过程中,我把要用到的POP+POP+RET指令写在了自己的一个DLL中。POP+POP+RET指令是很常见的指令,一般函数的末尾都是这种形式,因此,系统DLL中应该是有该指令的,比如ntdll.dll中就有:
这里写图片描述
图73

我们把上节示例中的地址改成这个地址试试,没有弹出MessageBox,说明Shellcode失效了,在调试器中看看:
这里写图片描述
图74

提示说无法处理异常,说明改了地址后的异常处理函数没有被运行。下面我们继续用我自己的DLL,但是重新编译它,这次在编译时加上“/SAFESEH”选项:
这里写图片描述
图75

再来尝试一下(注意,重新编译后,指令地址发生变化),还是同样的提示。用Immunity Debugger的mona插件查看以下加载的模块:
这里写图片描述
图76

只有exe不是SafeSEH,其它DLL都是,包括ntdll.dll。这就是本节的内容了。

为了防止基于SEH的栈溢出,Windows改进了SEH,称为SafeSEH。从前面我们至少看到一点,启用SafeSEH编译的模块,我们的Shellcode是无法利用的,系统并不会调用我们伪造的这个“异常处理函数”。

事实上,启用SafeSEH之后,模块中使用的异常处理函数都要提前注册,注册的地方就在加载配置目录(Load Config Directory)。前面我们接触过导出表,导入表,这个加载配置目录也类似,属于16中数据目录中的一种。这样的话,发生异常之后,调用异常处理函数前,系统会对异常处理函数地址进行检验,如果没有注册,说明这个异常处理函数有问题,就直接忽略该异常处理函数。就如我们前面所看到的,我们伪造的异常处理函数被忽略,后面的又被我们所覆盖,因此异常无法被处理。

怎么办呢?第一个办法如我前面所做的,如果程序中有模块没有启用SafeSEH,我们还是可以利用它来加载Shellcode。第二个办法就是SafeSEH有个例外,就是如果异常处理函数位于已加载模块地址范围之外,则异常处理函数依旧会被调用。这样机会就来了,即使程序中所有模块都启用了SafeSEH,或者虽然没有启用,但无法找到合适的指令块做跳板。我们还可以尝试其它不属于该进程的模块。

具体的做法在这篇文章中:https://www.corelan.be/index.php/2009/09/21/exploit-writing-tutorial-part-6-bypassing-stack-cookies-safeseh-hw-dep-and-aslr/
按他的做,很简单,这里就不重复了。

NLS,全称National Language Support,即本地语言支持。这个语言支持不只是文字,还有键盘,时间日期格式等,那么.nls后缀的文件就是相关的资源文件。这些资源文件使用的方式为内存映射,即读取其内存空间相当于读文件。进程结构PEB中有相应的成员:
这里写图片描述
图77

这些成员指针在进程初始化的时候指向资源文件映射之后相应的地址。

需要注意的是,虽然我们在unicode.nls找到了需要的“指令”,但unicode.nls是数据,只不过是其中的数据正好和指令操作码相同。这与我们把Shellcode放在栈上执行时相同的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值