24.1 远程拒绝服务内核漏洞

  • 漏洞分析例子:[2009-09-08][Microsoft][SMB2][SRV2.SYS][远程拒绝服务内核漏洞][36299]
  • 漏洞点:远程攻击者在发送的 SMB 报文的 Process Id High头字段(在SMB Base Header结构中)中包含有畸形数据的话,就会在 SRV2.SYS 驱动中的_Smb2ValidateProviderCallback 函数中触发越界内存引用,导致以内核态执行任意指令或发生系统崩溃。

    SMB协议数据格式

  • SMB协议的数据包格式可以看成是:NETBIOS Header + SMB Base Header + SMB Command Header + SMB DATA。

image.png

  • NETBIOS Header的结构:

image.png

  • SMB Base Header的结构:
    • “Protocol”域包含协议(SMB)的名字,即’\xFF’, ‘S’, ‘M’, ‘B’。
    • “Command”域包含请求命令的数据。例如 0x72 就是“磋商协议”命令。
    • “Status”域用来从服务端到客户端传达错误消息。
    • “Flags”域和“Flags2”域是表示一些标志。
    • “PIDHigh”域表示 PID 的高 16 位,和下面的“PIDLow”域表示的低 16 位,组合成一个完整的 4 字节 PID 值
    • “SecurityFeatures”域包含和安全有关的信息。
    • “Reserved”域必须为 0,是保留字段。
    • “TID”域在客户端成功和一台 SMB 服务器上的资源建立连接后被使用的。TID 数字用来鉴别资源。
    • “PIDLow”域在客户端成功在服务器上创建一个进程时使用。PID 数字用来鉴别进程。
    • “UID”域在一个用户被成功通过验证后被使用。UID 数字用来鉴别用户。
    • “MID”域在客户端拥有几个请求(进程,线程,文件访问等)是和 PID 同时使用的。

image.pngimage.png

  • SMB Command Header的结构:
    • “WordCount”域表示后面 Words 数组中的元素个数。
    • “Words”域是一个 USHORT 数组,元素个数为 WordCount。

image.png
image.png

  • SMB DATA的结构:
    • “ByteCount”域表示后面 Bytes 数组中的元素个数。
    • “Bytes”域是一个 UCHAR 数组,元素个数为 ByteCount。

image.pngimage.png

SRV2.SYS驱动中的漏洞点

  • 使用IDA打开SRV2.SYS驱动,进行反编译代码。具有漏洞函数是Smb2ValidateProviderCallback,函数的漏洞位置如下所示:

image.png

  • 上述代码中,v1指向的是SMB Base Header结构,所以v1+12的位置就指向了PIDHigh域,在上述代码中的*(v1+12)相当于取了PIGHigh域中的值作为ValidateRoutines数组元素的下标,所以可能会导致数组越界。

    24.2 本地拒绝服务内核漏洞

  • 本地拒绝服务内核漏洞—是指能够利用来使得本地系统崩溃或资源耗尽的内核程序 bug或缺陷。

  • 漏洞实例:[2010-04-22][Microsoft][SfnINSTRING][Win32k.sys][本地拒绝服务内核漏洞]。
  • 漏洞点:因为 Win32k.sys 模块在 DispatchMessage 时,会最后调用到 xxxDefWindowProc,这个函数在处理某些消息时,会调用 gapfnScSendMessage 这个函数表中的函数来处理,其中 Windows 2000/xp/2003 在处理 0x18d 号消息时,会有一个名为SfnINSTRING 的函数,这个函数当 lParam 不为空时,直接认为 lParam 是内存指针,并直接从地址中取出数据,尽管函数内使用了 SEH,但是只要传递错误的内核地址,仍然会引发系统崩溃。

    xxxDefWindowProc函数

  • xxxDefWindowProc函数中的gapfnScSendMessage是一个函数列表,MessageTable是一个已经定义好的二维数组。

image.png

  • 首先,MessageTable[(unsigned __int16)a2]中,该漏洞a2的输入是0x18d,MessageTable[0x18d]的值为 0x45,然后MessageTable[0x18d] & 0x3F = 0x45 & 0x3F = 0x5;所以最终调用的函数应该是gapfnScSendMessage[0x05],如下图所示:

image.png
image.png
image.png

  • 再看SfnINSTRING函数,SfnINSTRING 函数的前 4 个参数等同于 xxxDefWindowProc 函数的 4 个参数,在SfnINSTRING 函数开头的 if 语句中,当 a4 不为 0 时,直接访问 a4+8 这个内存地址指向的DWORD 数据。这实际上是有漏洞的,如果 a4+8 是一个非法的内核地址,例如 0x80000000,就会引发系统崩溃,达到本地拒绝服务的效果。

image.png

24.3 缓冲区溢出内核漏洞

  • 缓冲区溢出内核漏洞—是指能够利用来使得本地或远程系统运行过程中缓冲区溢出,进而执行任意代码的内核程序 bug 或缺陷。
  • 漏洞实例:[2009-07-31][ALWIL][avast4.8.1335_Professionnel][aswmon2.sys][本地缓冲区溢出内核漏洞][本地权限提升]。
  • 漏洞点:该漏洞存在于 avast! 4.8.1335 Professionnel 软件的 aswmon2.sys 驱动对派遣例程的处理中,在对 IoControlCode 为 0xb2c8000c 的处理中存在缓冲区溢出漏洞,当两次调用这个 IoControl处理函数后,会导致内存中的函数指针被覆盖成一个固定的 DWORD,该值为 0x57523c00,而这个地址开始的内存是可以在用户态申请分配的,那么攻击者可以在此存放 Ring0 shellcode,等该函数指针指向的函数在攻击进程中被调用时,Ring0 shellcode 就会被执行。如果在别的进程上下文中被调用,就会造成内存非法访问,导致蓝屏进而崩溃。