突破SafeSEH机制之二——利用未启用SafeSEH模块绕过SafeSEH
2017-08-07 09:22
471 查看
敲黑板敲黑板~~今天我们继续~
上次讲到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] 纯文本查看 复制代码
?
现将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布置到覆盖点的后面,通过ret等指令拿回控制权
就想到jmp esp这种类似的跳转指令了,考虑用pop pop ret之类的指令,后面调试的时候告诉你为什么。
shellcode布置200个90,调试:
还是直接运行到strcpy后面,搜索9090,记下shellcode首地址A:0x0012FE84
拉到栈下面,就是200个字节覆盖的尽头~查看还有多远才能覆盖到SEH:
得到B地址 溢出点地址:0x0012FF60
B-A=220字节
第三步
布置shellcode
我们遇到了无法直接跳往shellcode的情况,考虑跳板指令,用跳板指令,一般shellcode就在覆盖地址的后面,要不就是jmp esp 或者ret
在调试的时候,我们发现在test函数刚进入的时候,会在Security cookie+4的地方压入一个-2,在准备出try{}的时候,又把这个值改动成0。原理我也不太清楚,只要我们知道,这里有一个值,他是在溢出点B下方(+8的高地址)
这就出现问题了,我们如果想把shellcode布置在溢出点后面,用跳板指令跳到接下来的地址,但是shellcode有可能被这样一个机制修改,导致shellcode被破坏,怎么办?
幸亏shellcode被破坏的地方不多,也是仅仅溢出点后面2个DWORD,所以这两个DWORD我们用无关的90填充,接下来再填充shellcode。
接下来就是跳转指令的选择了,怎么能在执行溢出点的异常处理函数后,再跳回来呢,这就需要我们的SafeSEH OFF的模块了
如果shellcode紧邻着溢出点B,我们可以直接找ret指令的函数,跳回来继续执行shellcode,由于用了两个DWORD填充shellcode前两个字节,所以考虑选择pop
pop ret指令(其实后面发现这个pop不是为了pop掉这两个填充字符)
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] 纯文本查看 复制代码
?
可以看出了,这个dll就包含了一个pop pop ret的内容
怎么验证这个dll没有开启SafeSEH呢?两种方法,一种是利用vs里面的工具,vs 2008 command prompt命令行工具,利用"dumpbin /loadconfig"+dll名称
另一个方法就是,用我们开头的程序,直接OD调试,待LoadLibrary后,有一个插件叫做SafeSEH能够直接查看加载的模块SafeSEH情况,还有一个插件叫ODFindaddr,里面有一个unprotected modules——without SafeSEH都能查看
接下来我们查找pop pop ret的地址,OD调试
直接搜索0x58 0x58 0xC3
问题:不知道为什么,没有找到pop eax,找到了pop ecx,pop ecx,ret
有同学遇到相同的问题了吗。
这里就能够确定这个跳转指令地址:0x111211B6
完善代码和shellcode:
[C] 纯文本查看 复制代码
?
运行~完美溢出... ... 等会,不对啊,咋没反应... ...
尴尬... ...同学们,我们调试一下看一下。
直接F9,看看错误发生在哪里,OD显示0x130000写入错误。
我们来计算一下,0x130000-0x12FE84=148<168.所以shellcode根本拷贝不完... ...栈空间不足
——————————————————————————手工割———————————————————————
上次调试发现栈空间不足,原来是因为main函数中,有一个str[200]的字符数组定义,用来提高栈顶,我们还将这个“没用的”str数组恢复。这样是不是就可以了?
更新shellcode首地址A:0x0012FDB8 溢出点B:0x0012FE94(其实算出来shellcode怎么填充的,这个怎么变都没用了)
一定要记下来这个覆盖的SEH结构地址0x0012FE90
前面我没有讲清楚这个跳转的流程,这个跳转稍微麻烦点,我们现在一点点来看,我尽量多截图
(1)pop pop
ret
发生除0异常后,OD接管异常,我们按shift+F9,果然进入到我们覆盖的异常处理函数地址0x111211B6
这时我们观察栈顶,发现pop两次之后,就会return到之前覆盖的SEH头0x0012FE90,继续执行看看会发生什么
这里有个问题,也是我过了一阵子再次回来看的时候发现的,觉得应该说明一下。其实真正的shellcode并不在这个ret碰到的12FE90这个地方,他仅仅只是说位于shellcode低地址的地方,与shellcode的距离其实相差16个字节(90909090
90909090 111211B6 90909090),在执行几句这16哥字节形成的无关指令就能继续执行shellcode了。而至于说为什么这里要用到pop pop,可能是因为刚好发现pop两次后,才是一个离shellcode比较近的地方吧
(2)ret之后的事情
现在终于来到了临近shellcode的地方,先是4个0x90,然后就是我们找到的0x111211B6跳板指令地址,接下来是8个字节的0x90,只不过后4个已经在try分支处理的时候被置为0了
本来这些无关紧要的数值被当成代码执行的时候,一般情况下是不会影响shellcode执行的,但是很不幸,我们就遇到了这种情况:
显然,这些变动的字节,对我们的shellcode造成了污染,直接影响了代码的正常执行,所以必须想办法,怎么办,那就跳过去吧
(3)jmp过去
位于0x0012FE90的4个90没用,我们想办法把这个4个字节改造一下,想办法直接跳到shellcode处
我们看到shellcode的地址距离当前有16个字节的长度,无条件转移指令jmp 16个字节就可以了,根据汇编指令,是\xEB\x0E
所以这个4个字节就成了"\xEB\x0E\x90\x90”
修改之后,我们再次调试程序到这里:
看见没,可以直接跳转到shellcode了!
再继续运行:
本次调试实验到此结束。
你学会了吗????
上次讲到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] 纯文本查看 复制代码
?
那么我们将程序劫持到哪里呢?shellcode?恐怕不行,因为在进行有效性检查之前,会查看这个地址,如果这个指针指向栈,就会直接终止调用。
所以,我们必须将程序劫持到一个栈外的地址,并且没有SafeSEH表的模块中,执行这个模块的某一个指令(一般是跳板指令),再跳回到shellcode执行。完美~
第二步
找地址!
找什么地址?
shellcode字符串在栈中的首地址A
需要溢出的异常处理函数指针位置,也就是溢出点B
根据B-A+4确定(溢出点上半部分的)shellcode的大小(划重点,划重点了!!!)
为什么说,这次B-A+4不是shellcode 的大小?因为shellcode的布置不再是shellcode+若干90+覆盖地址
因为覆盖的指针不能直接跳往shellcode啊(不能使用固定地址进行跳转了),所以我们得用一个栈外地址、并且没有SafeSEH的模块中的跳转指令跳到shellcode,把shellcode布置到覆盖点的后面,通过ret等指令拿回控制权
就想到jmp esp这种类似的跳转指令了,考虑用pop pop ret之类的指令,后面调试的时候告诉你为什么。
shellcode布置200个90,调试:
还是直接运行到strcpy后面,搜索9090,记下shellcode首地址A:0x0012FE84
拉到栈下面,就是200个字节覆盖的尽头~查看还有多远才能覆盖到SEH:
得到B地址 溢出点地址:0x0012FF60
B-A=220字节
第三步
布置shellcode
我们遇到了无法直接跳往shellcode的情况,考虑跳板指令,用跳板指令,一般shellcode就在覆盖地址的后面,要不就是jmp esp 或者ret
在调试的时候,我们发现在test函数刚进入的时候,会在Security cookie+4的地方压入一个-2,在准备出try{}的时候,又把这个值改动成0。原理我也不太清楚,只要我们知道,这里有一个值,他是在溢出点B下方(+8的高地址)
这就出现问题了,我们如果想把shellcode布置在溢出点后面,用跳板指令跳到接下来的地址,但是shellcode有可能被这样一个机制修改,导致shellcode被破坏,怎么办?
幸亏shellcode被破坏的地方不多,也是仅仅溢出点后面2个DWORD,所以这两个DWORD我们用无关的90填充,接下来再填充shellcode。
接下来就是跳转指令的选择了,怎么能在执行溢出点的异常处理函数后,再跳回来呢,这就需要我们的SafeSEH OFF的模块了
如果shellcode紧邻着溢出点B,我们可以直接找ret指令的函数,跳回来继续执行shellcode,由于用了两个DWORD填充shellcode前两个字节,所以考虑选择pop
pop ret指令(其实后面发现这个pop不是为了pop掉这两个填充字符)
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] 纯文本查看 复制代码
?
怎么验证这个dll没有开启SafeSEH呢?两种方法,一种是利用vs里面的工具,vs 2008 command prompt命令行工具,利用"dumpbin /loadconfig"+dll名称
另一个方法就是,用我们开头的程序,直接OD调试,待LoadLibrary后,有一个插件叫做SafeSEH能够直接查看加载的模块SafeSEH情况,还有一个插件叫ODFindaddr,里面有一个unprotected modules——without SafeSEH都能查看
接下来我们查找pop pop ret的地址,OD调试
直接搜索0x58 0x58 0xC3
问题:不知道为什么,没有找到pop eax,找到了pop ecx,pop ecx,ret
有同学遇到相同的问题了吗。
这里就能够确定这个跳转指令地址:0x111211B6
完善代码和shellcode:
[C] 纯文本查看 复制代码
?
尴尬... ...同学们,我们调试一下看一下。
直接F9,看看错误发生在哪里,OD显示0x130000写入错误。
我们来计算一下,0x130000-0x12FE84=148<168.所以shellcode根本拷贝不完... ...栈空间不足
——————————————————————————手工割———————————————————————
上次调试发现栈空间不足,原来是因为main函数中,有一个str[200]的字符数组定义,用来提高栈顶,我们还将这个“没用的”str数组恢复。这样是不是就可以了?
更新shellcode首地址A:0x0012FDB8 溢出点B:0x0012FE94(其实算出来shellcode怎么填充的,这个怎么变都没用了)
一定要记下来这个覆盖的SEH结构地址0x0012FE90
前面我没有讲清楚这个跳转的流程,这个跳转稍微麻烦点,我们现在一点点来看,我尽量多截图
(1)pop pop
ret
发生除0异常后,OD接管异常,我们按shift+F9,果然进入到我们覆盖的异常处理函数地址0x111211B6
这时我们观察栈顶,发现pop两次之后,就会return到之前覆盖的SEH头0x0012FE90,继续执行看看会发生什么
这里有个问题,也是我过了一阵子再次回来看的时候发现的,觉得应该说明一下。其实真正的shellcode并不在这个ret碰到的12FE90这个地方,他仅仅只是说位于shellcode低地址的地方,与shellcode的距离其实相差16个字节(90909090
90909090 111211B6 90909090),在执行几句这16哥字节形成的无关指令就能继续执行shellcode了。而至于说为什么这里要用到pop pop,可能是因为刚好发现pop两次后,才是一个离shellcode比较近的地方吧
(2)ret之后的事情
现在终于来到了临近shellcode的地方,先是4个0x90,然后就是我们找到的0x111211B6跳板指令地址,接下来是8个字节的0x90,只不过后4个已经在try分支处理的时候被置为0了
本来这些无关紧要的数值被当成代码执行的时候,一般情况下是不会影响shellcode执行的,但是很不幸,我们就遇到了这种情况:
显然,这些变动的字节,对我们的shellcode造成了污染,直接影响了代码的正常执行,所以必须想办法,怎么办,那就跳过去吧
(3)jmp过去
位于0x0012FE90的4个90没用,我们想办法把这个4个字节改造一下,想办法直接跳到shellcode处
我们看到shellcode的地址距离当前有16个字节的长度,无条件转移指令jmp 16个字节就可以了,根据汇编指令,是\xEB\x0E
所以这个4个字节就成了"\xEB\x0E\x90\x90”
修改之后,我们再次调试程序到这里:
看见没,可以直接跳转到shellcode了!
再继续运行:
本次调试实验到此结束。
你学会了吗????
相关文章推荐
- 突破SafeSEH机制之三——利用加载模块之外的地址绕过SafeSEH
- 利用未启用SafeSEH模块绕过SafeSEH
- 利用未启用SafeSEH模块绕过SafeSEH
- 突破SafeSEH机制之一——利用堆绕过SafeSEH
- <Oday安全 11.6利用加载模块之外的地址绕过SafeSEH>一节注记---jmp [ebp+N] (下)
- 利用加载模块之外的地址绕过SafeSEH
- <Oday安全 11.6利用加载模块之外的地址绕过SafeSEH>一节注记---jmp [ebp+N] (上)
- 利用加载模块之外的地址绕过SafeSEH
- 利用Adobe Flash Player ActiveX控件绕过SafeSEH
- 利用Adobe Flash Player ActiveX 控件绕过SafeSEH
- 伪造SEH链表最后一项躲过SEHOP/利用未启用SEHOP的模块
- 利用bigpipe机制实现页面模块的异步渲染
- 利用nodejs模块缓存机制创建“全局变量”
- 伪造SEH链表最后一项躲过SEHOP/利用未启用SEHOP的模块
- SafeSEH Exploit——利用未启用SafeSEH的DLL
- 利用bigpipe机制实现页面模块的异步渲染 chunked技术
- C++虚函数系列之二:绕过class的访问机制访问虚函数
- 利用ROP链突破DEP保护机制
- ngx_lua_waf利用HPP完全绕过防御机制
- 利用 PHP 扩展模块突破 Disable_functions 执行命令