欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

趋势科技 tmactmon.sys DOS漏洞分析(0day)

趋势科技 tmactmon.sys DOS漏洞分析(0day)

当tmactmon.sys接收到ioctl_code=0x9100444f的IRP时,会调用Dispatch函数进行进行处理,如下所示。
.text:00011116 ; int __stdcall BugDispatch(int, PIRP Irp)
.text:00011116 BugDispatch     proc near               ; DATA XREF: sub_11C4C+16D o
.text:00011116
.text:00011116 inbuffer        = dword ptr -1Ch
.text:00011116 UserBuffer      = dword ptr -18h
.text:00011116 IoStatus        = dword ptr -10h
.text:00011116 outbufferLength = dword ptr -0Ch
.text:00011116 inbufferLength  = dword ptr -8
.text:00011116 var_4           = dword ptr -4
.text:00011116 Irp             = dword ptr  0Ch
.text:00011116
.text:00011116                 mov     edi, edi
.text:00011118                 push    ebp
.text:00011119                 mov     ebp, esp
.text:0001111B                 sub     esp, 1Ch
在该处理函数的最后,会将inLength、outLength、inbuffer、UserBuffer等信息保存,并调用sub_12BE2函数。可以看到传入的参数即为栈中存放inbuffer的地址。
.text:0001115E loc_1115E:                ; CODE XREF: BugDispatch+2A j
.text:0001115E                 mov     edx, [eax+10h]
.text:00011161                 mov     [ebp+inbuffer], edx
.text:00011164                 mov     edx, [esi+3Ch]
.text:00011167                 mov     [ebp+UserBuffer], edx
.text:0001116A                 mov     edx, [eax+8]
.text:0001116D                 mov     [ebp+outbufferLength], edx
.text:00011170                 mov     edx, [eax+4]
.text:00011173                 mov     [ebp+inbufferLength], edx
.text:00011176                 mov     [ebp+IoStatus], ecx
.text:00011179                 mov     eax, [eax+0Ch]
.text:0001117C                 mov     [ebp+var_4], eax
.text:0001117F                 lea     eax, [ebp+inbuffer]
.text:00011182                 push    eax
.text:00011183                 call    sub_12BE2
sub_12BE2函数完成的主要功能是调用sub_12AE8函数对ring3传来的缓冲区进行检查。对sub_12AE8函数进行反编译后的代码如下。可以看到,该函数使用ProbeForRead 和ProbeForWrite对输入和输出缓冲区进行了严格的检查,同时还检查了发送ioctl是否是趋势本身的进程。
signed int __thiscall sub_12AE8(int this, int a2)
{
  if ( &inbuffer && (inLength || !inbuffer) && (outLength || !outBuffer ))
  {
    if ( ExGetPreviousMode() == 1 )
    {
      ProbeForRead(*(const void **)v3, *(_DWORD *)(v3 + 16), 1u);
      ProbeForWrite(*(PVOID *)(v3 + 4), *(_DWORD *)(v3 + 20), 1u);
    }
    //省略无关代码
LABEL_13:
    if ( !v7 )
    {
      v5 = *(_DWORD *)(v3 + 8);
      if ( v5 && *(_BYTE *)(v5 + 24) )
        v2 = *(_DWORD *)(v5 + 8) != (_DWORD)PsGetCurrentProcessId() ? 0xC00000BB : 0;      
     else
        v2 = -1073741637;
    }
    result = v2;
  }
  else
  {
    result = -1073741811;
  }
  return result;
}
当检查通过后,就会调用sub_1291C,sub_1291C将会继续调用sub_19814函数,sub_19814的执行过程如下。注意观察红色部分的汇编代码,由于ebp+arg_4的内容为inbuffer中的dword[1],可以任意指定,不妨指定为0x12210005,所以将会调用sub_19554执行。
.text:00019814 ; int __stdcall sub_19814(int, int, PVOID Object)
.text:00019814 sub_19814       proc near       ; CODE XREF: v6+29 p
.text:00019814 var_20          = dword ptr -20h
.text:00019814 ms_exc          = CPPEH_RECORD ptr -18h
.text:00019814 arg_0           = dword ptr  8
.text:00019814 arg_4           = dword ptr  0Ch
.text:00019814 Object          = dword ptr  10h
.text:00019814
.text:00019814                 push    10h
.text:00019816                 push    offset unk_1E1A8
.text:0001981B                 call    __SEH_prolog4
.text:00019820                 mov     esi, ecx
.text:00019822                 lea     eax, [esi+14h]
.text:00019825                 mov     [ebp+var_20], eax
.text:00019828                 xor     ecx, ecx
.text:0001982A                 inc     ecx
.text:0001982B                 lock xadd [eax], ecx
.text:0001982F                 cmp     [ebp+arg_4], 1221A007h
.text:00019836                 jnz     short loc_19885

.text:00019885 loc_19885:                  ; CODE XREF: sub_19814+22 j
.text:00019885                 mov     ebx, [ebp+Object]
.text:00019888                 push    ebx             ; Object
.text:00019889                 push    [ebp+arg_4]     ; int
.text:0001988C                 mov     ecx, esi
.text:0001988E                 call    sub_19554
sub_19554的执行过程如下所示,标红几处为重要的跳转。由于ecx=0x12210005,最终会执行到.text:00019591。ebp+Object的内容为inbuffer中的dword[3],可以被任意指定,不妨指定为0xffff0000,最终在push  dword ptr [esi]执行出错,内存0xffff0000不可读。
.text:00019554 ; int __stdcall sub_19554(int, PVOID Object)
.text:00019554 sub_19554    proc near      ; CODE XREF: sub_19814+7A p
.text:00019554 arg_0           = dword ptr  8
.text:00019554 Object          = dword ptr  0Ch
.text:00019554
.text:00019554                 mov     edi, edi
.text:00019556                 push    ebp
.text:00019557                 mov     ebp, esp
.text:00019559                 mov     ecx, [ebp+arg_0]  ;ecx=0x12210005
.text:0001955C                 push    ebx
.text:0001955D                 push    esi
.text:0001955E                 push    edi
.text:0001955F                 mov     eax, 12210006h
.text:00019564                 cmp     ecx, eax
.text:00019566                 mov     edi, 0E0000001h
.text:0001956B                 mov     ebx, edi
.text:0001956D                 ja      loc_19670
.text:00019573                 jz      loc_19645
.
text:00019579                 sub     ecx, 12210001h
.text:0001957F                 jz      loc_1961B
.text:00019585                 dec     ecx
.text:00019586                 jz      short loc_195E0
.text:00019588                 sub     ecx, 3
.text:0001958B                 jnz     loc_196AC
.text:00019591                 mov     esi, [ebp+Object]
.text:00019594                 test    esi, esi
.text:00019596                 jz      loc_196B1
.text:0001959C                 and     [ebp+Object], ecx
.text:0001959F                 lea     eax, [ebp+Object]
.text:000195A2                 push    eax
.text:000195A3                 push    dword ptr [esi]
.text:000195A5                 call    sub_194E6
从整个漏洞的分析过程可以看到,触发该漏洞需要注入到趋势自身的ring3进程,并向tmactmon.sys发送恶意构造的IRP请求,其中ioctl_code=0x9100444f, inLength=0x10, outLength=0x10, inbuffer为0,0,0,0,5,0,0x21,0x12,0,0,0,0,0,0,0xff,0xff。以上就是整个分析过程。
Happy Hacking~
~~~~~~~~~~~~~~~~~~~~~~免责声明~~~~~~~~~~~~~~~~~~~~~
本文所涉及内容仅用于软件安全技术研究、学习,严禁用于不良动机。
任何个人、团体、组织不得将其用于非法目的,否则后果自负。
本人不承担由这些代码造成的用户计算机崩溃,数据丢失等责任及连带责任。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功