CVE-2012-0158 漏洞分析

一 样本概况

一个基于栈内存越界拷贝的office漏洞。

样本信息

测试环境

Win7 x86
office 2003
windbg
火绒剑

漏洞原理

MSCOMCTL.OCX模块是office解析ActiveX控件用到的一个动态库,当一个office相关文档中包含ActiveX这类的控件元素的话,比如按钮、列表、树形控件等,当文档通过office打开时,MSCOMCTL.OCX就会被载入到office程序的进程空间,调用其来解析显示空间,当office解析到一个被构造好的控件,比如列表控件,就会发生栈内存越界拷贝。

分析目标

漏洞利用原理

行为分析

拿到POC,运行一下发现弹出错误,如下图:
1
然后运行一下样本,会弹出计算器,如下图:
2
所以这个exp的shellcode在运行时候会释放文件,用火绒剑观察一下,如下图:
3
感染PE文件,启动自释放文件。去路径下去看a.exe就是计算器。

打开样本弹出计算器,所以Shellcode应该会调用WinExec函数。用Windbg附加WINWORD.EXE,bp kernel32!WinExec下断

0:009> bp kernel32!WInExec
0:009> bl
 0 e 76d9e695     0001 (0001)  0:**** kernel32!WinExec
0:009> g

然后g,把样本拖进word。

ModLoad: 27580000 27685000   C:\Windows\system32\MSCOMCTL.OCX
Breakpoint 0 hit
eax=0012163b ebx=0001c000 ecx=00121568 edx=77cc64f4 esi=0001c000 edi=0c00afe6
eip=76d9e695 esp=00121588 ebp=001215a0 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
kernel32!WinExec:
76d9e695 8bff            mov     edi,edi

程序断在WinExec入口点。这时候计算器还没弹出来,看一下WinExec的参数,发现是a.exe。我去到这个目录,发现它就是一个计算器。
看来shellcode应该是把系统的calc复制到别的目录再运行它。

0:000> dd esp
00121588  00121852 0beaca80 00000000 0beaca80
00121598  0001c000 00000744 001215f0 00121a78
001215a8  0bfec2a8 0c00aff0 0001c000 00000001
001215b8  275c8a0a 0c00aff0 0bfec2a8 0001c000
001215c8  00000000 0bf27078 0bfec290 00002d26
001215d8  00002d26 0bfe9a48 00002841 0002159e
001215e8  00000000 00000744 00000000 00121669
001215f8  1005c48b c7000001 4d032400 005ae908
0:000> da 0beaca80
0beaca80  "C:\Users\15pb-win7\a.exe"

WinExec的返回地址是0x00121852。往上翻翻,没发现shellcode从哪开始。Kb打印堆栈

0:000> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
00121584 00121852 0beaca80 00000000 0beaca80 kernel32!WinExec
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\system32\MSCOMCTL.OCX - 
001215b4 275c8a0a 0c00aff0 0bfec2a8 0001c000 0x121852
001215f0 00121669 1005c48b c7000001 4d032400 MSCOMCTL!DllGetClassObject+0x41cc6
00000000 00000000 00000000 00000000 00000000 0x121669

重新载入,在MSCOMCTL!DllGetClassObject+0x41cc0下断

275c89fd ff75f4          push    dword ptr [ebp-0Ch]
275c8a00 8d45f8          lea     eax,[ebp-8]
275c8a03 53              push    ebx
275c8a04 50              push    eax
275c8a05 e863fdffff      call    MSCOMCTL!DllGetClassObject+0x41a29 (275c876d)
275c8a0a 8bf0            mov     esi,eax
275c8a0c 83c40c          add     esp,0Ch
275c8a0f 85f6            test    esi,esi
275c8a11 7c3d            jl      MSCOMCTL!DllGetClassObject+0x41d0c (275c8a50)
275c8a13 837df800        cmp     dword ptr [ebp-8],0
275c8a17 8b7d08          mov     edi,dword ptr [ebp+8]

断在这个call的上一句,Kb

ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
001215e8 275e701a 06642584 0d9a08e8 00000000 MSCOMCTL!DllGetClassObject+0x41cc0
00121610 275e7361 06642584 0d9a08e8 0d9a08e8 MSCOMCTL!DLLGetDocumentation+0xd08
00121630 275ca8b6 0bfabe80 0d9a08e8 0bfabcd8 MSCOMCTL!DLLGetDocumentation+0x104f
001216b0 2758aee8 0bfabc88 00000000 0d9a08e8 MSCOMCTL!DllGetClassObject+0x43b72
001216e0 27600908 0bfabcd8 0d9a08e8 00000000 MSCOMCTL!DllGetClassObject+0x41a4
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Microsoft Office\OFFICE11\WINWORD.EXE - 
001216f4 301ecdcd 0bfabcdc 0d9a08e8 00000000 MSCOMCTL!DllUnregisterServer+0xc31

发现这一层函数的返回地址是0x 275e701a,它前面一个call是

0:000> u 275e701a -5
MSCOMCTL!DLLGetDocumentation+0xd03:
275e7015 e8ad19feff      call    MSCOMCTL!DllGetClassObject+0x41c83 (275c89c7)
275e701a 85c0            test    eax,eax
275e701c 7c27            jl      MSCOMCTL!DLLGetDocumentation+0xd33 (275e7045)

判断溢出点就是这个call里面。

5

发现了熟悉的发现万能跳转0x7ffa4512和shellcode。并且在

275c8a05 e863fdffff      call    MSCOMCTL!DllGetClassObject+0x41a29 (275c876d)

之前这里还没有被shellcode覆盖,显然,溢出发生在此
几个单步
6

Shellcode通过jmp esp覆盖返回地址利用。
接下来用IDA打开有漏洞的MSCOMCTL.OCX。定位前面那两个关键call,先看上层call,直接跳到文章后面打开IDA处,下面这段是另一种定位关键call的方法。

因为释放文件时需要调用kernel32.dll中的GetFileSize函数来判断需要释放的文件。所以Windbg开始调试POC时候,在GetFileSize函数下断,

bp kernel32!GetFileSize

但是Word运行时会调用很多次GetFileSize,直接下断点的话,会执行很多次。
我们知道漏洞出现MSCOMCTL.OCX,因此我们可以在加载MSCOMCTL.OCX后在对GetFileSize下断点。用到命令

sxe ld:MSCOMCTL.OCX

加载MSCOMCTL.OCX时候会断下来。bp

0:013> sxe ld:MSCOMCTL.OCX
0:013> g
ModLoad: 27580000 27685000   C:\Windows\system32\MSCOMCTL.OCX
eax=00000000 ebx=00000000 ecx=30036f04 edx=77cc64f4 esi=7ffdf000 edi=0012049c
eip=77cc64f4 esp=001203b4 ebp=00120408 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCallRet:
77cc64f4 c3              ret
0:000> bp kernel32!GetFileSize
0:000> bl
 0 e 768f0273     0001 (0001)  0:**** kernel32!GetFileSize

然后g运行程序,程序停在GetFileSize处

0:000> g
Breakpoint 0 hit
eax=00121617 ebx=0dff08e8 ecx=00000049 edx=000001af esi=0012164f edi=0012165b
eip=76d55d47 esp=001215ac ebp=001215f0 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
kernel32!GetFileSize:
76d55d47 8bff            mov     edi,edi

反汇编窗口如下

76d55d47 8bff            mov     edi,edi
76d55d49 55              push    ebp
76d55d4a 8bec            mov     ebp,esp
76d55d4c 5d              pop     ebp
76d55d4d eb05            jmp     kernel32!GetFileSize+0xd (76d55d54)
76d55d4f 90              nop
76d55d50 90              nop
76d55d51 90              nop
76d55d52 90              nop
76d55d53 90              nop
76d55d54 ff25d419d176    jmp     dword ptr [kernel32+0x19d4 (76d119d4)]
76d55d5a 83c00a          add     eax,0Ah
76d55d5d 83c10a          add     ecx,0Ah
76d55d60 e907ab0000      jmp     kernel32!DuplicateHandle+0x236 (76d6086c)
76d55d65 83c00c          add     eax,0Ch
76d55d68 83c10c          add     ecx,0Ch
76d55d6b e9fcaa0000      jmp     kernel32!DuplicateHandle+0x236 (76d6086c)
76d55d70 90              nop
76d55d71 90              nop
76d55d72 90              nop
76d55d73 90              nop
76d55d74 90              nop

然后gu跳出GetFileSize函数,程序已经进入shellcode区域

4

观察堆栈调用上一层是MSCOMCTL!DllGetClassObject+0x41cc6 处

观察下

0:000> u MSCOMCTL!DllGetClassObject+0x41cc6
MSCOMCTL!DllGetClassObject+0x41cc6:
275c8a0a 8bf0            mov     esi,eax
275c8a0c 83c40c          add     esp,0Ch
275c8a0f 85f6            test    esi,esi
275c8a11 7c3d            jl      MSCOMCTL!DllGetClassObject+0x41d0c (275c8a50)
275c8a13 837df800        cmp     dword ptr [ebp-8],0
275c8a17 8b7d08          mov     edi,dword ptr [ebp+8]
275c8a1a 742a            je      MSCOMCTL!DllGetClassObject+0x41d02 (275c8a46)
275c8a1c 83650c00        and     dword ptr [ebp+0Ch],0

IDA查看

猜测是判断出问题溢出,然后观察地址275c8a50处,猜测问题出在此处附近,打开IDA打开MSCOMCTL.OCX模块,定位到此处。此处反汇编如下

.text:275C89C7 ; int __stdcall sub_275C89C7(int, BSTR bstrString)
.text:275C89C7 sub_275C89C7    proc near               ; CODE XREF: sub_275C8807+10p
.text:275C89C7                                         ; sub_275E7004+11p ...
.text:275C89C7
.text:275C89C7 var_14          = dword ptr -14h
.text:275C89C7 dwBytes         = dword ptr -0Ch
.text:275C89C7 var_8           = dword ptr -8
.text:275C89C7 var_4           = dword ptr -4
.text:275C89C7 arg_0           = dword ptr  8
.text:275C89C7 bstrString      = dword ptr  0Ch
.text:275C89C7
.text:275C89C7 ; FUNCTION CHUNK AT .text:275D3085 SIZE 0000001D BYTES
.text:275C89C7
.text:275C89C7                 push    ebp
.text:275C89C8                 mov     ebp, esp
.text:275C89CA                 sub     esp, 14h
.text:275C89CD                 push    ebx
.text:275C89CE                 mov     ebx, [ebp+bstrString]
.text:275C89D1                 push    esi
.text:275C89D2                 push    edi
.text:275C89D3                 push    0Ch             ; dwBytes
.text:275C89D5                 lea     eax, [ebp+var_14]
.text:275C89D8                 push    ebx             ; lpMem
.text:275C89D9                 push    eax             ; int
.text:275C89DA                 call    sub_275C876D
.text:275C89DF                 add     esp, 0Ch
.text:275C89E2                 test    eax, eax
.text:275C89E4                 jl      short loc_275C8A52
.text:275C89E6                 cmp     [ebp+var_14], 6A626F43h
.text:275C89ED                 jnz     loc_275D3085
.text:275C89F3                 cmp     [ebp+dwBytes], 8
.text:275C89F7                 jb      loc_275D3085
.text:275C89FD                 push    [ebp+dwBytes]   ; dwBytes
.text:275C8A00                 lea     eax, [ebp+var_8]
.text:275C8A03                 push    ebx             ; lpMem
.text:275C8A04                 push    eax             ; int
.text:275C8A05                 call    sub_275C876D
.text:275C8A0A                 mov     esi, eax
.text:275C8A0C                 add     esp, 0Ch
.text:275C8A0F                 test    esi, esi
.text:275C8A11                 jl      short loc_275C8A50
.text:275C8A13                 cmp     [ebp+var_8], 0
.text:275C8A17                 mov     edi, [ebp+arg_0]
.text:275C8A1A                 jz      short loc_275C8A46
.text:275C8A1C                 and     [ebp+bstrString], 0
.text:275C8A20                 lea     eax, [ebp+bstrString]
.text:275C8A23                 push    ebx             ; int
.text:275C8A24                 push    eax             ; len
.text:275C8A25                 call    sub_275C8A59
.text:275C8A2A                 mov     esi, eax
.text:275C8A2C                 pop     ecx
.text:275C8A2D                 test    esi, esi
.text:275C8A2F                 pop     ecx
.text:275C8A30                 jl      short loc_275C8A50
.text:275C8A32                 push    [ebp+bstrString] ; strIn
.text:275C8A35                 lea     ecx, [edi-24h]
.text:275C8A38                 call    sub_27585BE7
.text:275C8A3D                 push    [ebp+bstrString] ; bstrString
.text:275C8A40                 call    ds:SysFreeString
.text:275C8A46
.text:275C8A46 loc_275C8A46:                           ; CODE XREF: sub_275C89C7+53j
.text:275C8A46                 cmp     [ebp+var_4], 0
.text:275C8A4A                 jnz     loc_275D308F
.text:275C8A50
.text:275C8A50 loc_275C8A50:                           ; CODE XREF: sub_275C89C7+4Aj
.text:275C8A50                                         ; sub_275C89C7+69j ...
.text:275C8A50                 mov     eax, esi
.text:275C8A52
.text:275C8A52 loc_275C8A52:                           ; CODE XREF: sub_275C89C7+1Dj
.text:275C8A52                                         ; sub_275C89C7+A6C3j
.text:275C8A52                 pop     edi
.text:275C8A53                 pop     esi
.text:275C8A54                 pop     ebx
.text:275C8A55                 leave
.text:275C8A56                 retn    8
.text:275C8A56 sub_275C89C7    endp

F5反编译一下如下:

int __stdcall sub_275C89C7(int a1, BSTR bstrString)
{
  BSTR v2; // ebx@1
  int result; // eax@1
  int v4; // esi@4
  int v5; // [sp+Ch] [bp-14h]@1
  SIZE_T dwBytes; // [sp+14h] [bp-Ch]@3
  int v7; // [sp+18h] [bp-8h]@4
  int v8; // [sp+1Ch] [bp-4h]@8

  v2 = bstrString;
  result = sub_275C876D((int)&v5, bstrString, 0xCu);
  if ( result >= 0 )
  {
    if ( v5 == 1784835907 && dwBytes >= 8 )
    {
      v4 = sub_275C876D((int)&v7, v2, dwBytes);
      if ( v4 >= 0 )
      {
        if ( !v7 )
          goto LABEL_8;
        bstrString = 0;
        v4 = sub_275C8A59((UINT)&bstrString, (int)v2);
        if ( v4 >= 0 )
        {
          sub_27585BE7(bstrString);
          SysFreeString(bstrString);
LABEL_8:
          if ( v8 )
            v4 = sub_275C8B2B(a1 + 20, v2);
          return v4;
        }
      }
      return v4;
    }
    result = -2147418113;
  }
  return result;
}
int __cdecl sub_275C876D(int a1, LPVOID lpMem, SIZE_T dwBytes)
{
  LPVOID v3; // ebx@1
  int result; // eax@1
  LPVOID v5; // eax@3
  int v6; // esi@4
  int v7; // [sp+Ch] [bp-4h]@1
  const void *lpMema; // [sp+1Ch] [bp+Ch]@3

  v3 = lpMem;
  result = (*(int (__stdcall **)(LPVOID, int *, signed int, _DWORD))(*(_DWORD *)lpMem + 12))(lpMem, &v7, 4, 0);
  if ( result >= 0 )
  {
    if ( v7 == dwBytes )
    {
      v5 = HeapAlloc(hHeap, 0, dwBytes);
      lpMema = v5;
      if ( v5 )
      {
        v6 = (*(int (__stdcall **)(LPVOID, LPVOID, SIZE_T, _DWORD))(*(_DWORD *)v3 + 12))(v3, v5, dwBytes, 0);
        if ( v6 >= 0 )
        {
          qmemcpy((void *)a1, lpMema, dwBytes);
          v6 = (*(int (__stdcall **)(LPVOID, void *, SIZE_T, _DWORD))(*(_DWORD *)v3 + 12))(
                 v3,
                 &unk_27632368,
                 ((dwBytes + 3) & 0xFFFFFFFC) - dwBytes,
                 0);
        }
        HeapFree(hHeap, 0, (LPVOID)lpMema);
        result = v6;
      }
      else
      {
        result = -2147024882;
      }
    }
    else
    {
      result = -2147418113;
    }
  }
  return result;
}

分部来看:

275e7015 e8ad19feff      call    MSCOMCTL!DllGetClassObject+0x41c83 (275c89c7)

7

首先分配20个字节空间

275C89CA sub     esp, 14h        ; 分配20字节局部空间

然后调用

275C89DA call    sub_275C876D

这个call的功能是从样本读取dwBytes,这里是0CH字节返回到eax指向的内存地址。

关键call就是sub_275C876,进去看

.text:275C877C lea     ecx, [ebp+var_4]
.text:275C877F push    4
.text:275C8781 push    ecx
.text:275C8782 push    ebx
.text:275C8783 call    dword ptr [eax+0Ch]
.text:275C8786 cmp     eax, esi
.text:275C8788 jl      short loc_275

读取4个字节到[ebp+var_4],返回值和0比较,如果小于0,读取失败,转到失败处理,否则
8
分配0x8282字节空间,接着
9

我们看到:275C87CB rep movsd此时edi就是前面读取的0x8082字节,然后复制过去,
返回值就是我们的shellcode;
ep movsd 所在的这层函数在溢出后能正常返回,上上层函数在返回时候才跳去执行shellcode。分析完成,我们看到其实漏洞发生的根本原因在于

.text:275C89F3 cmp     [ebp+dwBytes], 8
.text:275C89F7 jb      loc_275D

比较从样本读取过来的数据时候处理错误,这里应该是大于8个字节就转到错误处理,它写成了小于8个字节转到错误处理。而这个字节大小是我们可以控制的,所以当我们传递比如0x8282,那么程序就会读取样本相应位置可控的0x8282字节到堆空间,然后把这0x8282字节复制到0x127b7c地址,进而覆盖掉函数的返回地址,执行我们的shellcode。

参考资料:

帖子:

https://www.52pojie.cn/thread-453723-1-1.html
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CVE-2023-24055是一个安全漏洞的标识符,通常由网络安全专家分配给具有潜在威胁的应用程序、系统或服务中的错误。由于它是2023年新发现的漏洞,具体的细节可能会有所变化,但一般来说,这类漏洞可能涉及到软件的代码缺陷,可能导致未经授权的访问、数据泄露或其他形式的安全风险。 漏洞分析涉及以下几个关键步骤: 1. **漏洞描述**:这个漏洞可能是关于代码注入、权限提升、拒绝服务攻击等类型的漏洞,取决于它的性质和受影响的组件。 2. **影响范围**:分析者会确定漏洞影响的产品版本、平台以及用户群体,这有助于确定哪些系统需要紧急更新。 3. **利用向量**:研究人员会揭示黑客如何利用这个漏洞的具体方法,比如攻击者的输入要求、触发条件等。 4. **缓解措施**:开发者会修复该漏洞并提供补丁,用户应安装这些补丁以保护系统免受攻击。 5. **漏洞分类**:可能归类为本地漏洞(仅限于物理设备)或远程漏洞(可通过网络进行攻击)。 6. **严重程度评估**:根据漏洞的易用性和可能造成的破坏程度,它会被标记为低危、中危、高危或Critical。 具体到CVE-2023-24055,为了获取更准确的信息,建议查看相关的官方公告、安全通报或厂商发布的详细说明,因为这些来源会提供最新和最全面的漏洞详情。如果你想知道如何防范此类漏洞,或者你的系统是否受到影响,你应该密切关注安全更新通知,并及时采取相应的安全策略。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值