首页
社区
课程
招聘
[原创]《0day安全第二版》样章发布5:第24章 内核漏洞案例分析
发表于: 2011-2-28 16:20 6399

[原创]《0day安全第二版》样章发布5:第24章 内核漏洞案例分析

2011-2-28 16:20
6399
第24章  内核漏洞案例分析 1
24.1  远程拒绝服务内核漏洞 1
24.2  本地拒绝服务内核漏洞 1
24.3  缓冲区溢出内核漏洞 1
24.4  任意地址写任意数据内核漏洞 6
24.5  任意地址写固定数据内核漏洞 6

[LEFT][LEFT] [/LEFT][/LEFT]
24  内核漏洞案例分析
一般的,内核漏洞大多出没于ring3ring0的交互中。我们能想到的从ring3进入ring0的通道,以及操作系统提供的API都有可能存在漏洞。例如:驱动程序中IoControl的处理函数,SSDTShadow SSDT中的系统服务函数(无论是否被hook都有可能存在漏洞),系统回调函数,内核钩子程序等。从漏洞数量来看,驱动程序中IoControl的处理函数中的漏洞最为多见,尤其是第三方的驱动程序。
前面21.3.1节中,内核漏洞按照严重程度和利用原理分别进行了分类,本节将对几种典型的内核漏洞,用几个真实的内核漏洞案例来详细分析。
24.1  远程拒绝服务内核漏洞

样章中省略
24.2  本地拒绝服务内核漏洞

样章中省略
24.3  缓冲区溢出内核漏洞

缓冲区溢出内核漏洞——是指能够利用来使得本地或远程系统运行过程中缓冲区溢出,进而执行任意代码的内核程序bug或缺陷。
这里以“[2009-07-31][ALWIL][avast4.8.1335_Professionnel][aswmon2.sys][本地缓冲区溢出内核漏洞][本地权限提升]”漏洞为例分析这种漏洞的具体细节。
该漏洞存在于avast! 4.8.1335 Professionnel软件的aswmon2.sys驱动对派遣例程的处理中,在对IoControlCode0xb2c8000c的处理中存在缓冲区溢出漏洞,当两次调用这个IoControl处理函数后,会导致内存中的函数指针被覆盖成一个固定的DWORD,该值为0x57523c00,而这个地址开始的内存是可以在用户态申请分配的,那么攻击者可以在此存放Ring0 shellcode,等该函数指针指向的函数在攻击进程中被调用时,Ring0 shellcode就会被执行。如果在别的进程上下文中被调用,就会造成内存非法访问,导致蓝屏崩溃。
首先我们定位aswmon2.sys驱动中IoControlCode0xb2c8000c的处理程序,反汇编整理后的代码如下:
//省略部分代码......
    if ( IoControlCode != (PCSZ)0xB2C80008 )
    {
      if ( IoControlCode != (PCSZ)0xB2C8000C )
      {
      //省略部分代码......
      }
      if ( InputBufferLength != 0x1448u )
        goto LABEL_92;
      memcpy(&dword_18BD8, InputBuffer, 0x1448u);
      sub_108F0();
      return 0;
}
//省略部分代码......
从以上代码可以看出,当IoControlCode0xb2c8000c时,首先检查输入缓冲区长度是否等于0x1448,如果不等,则直接返回;如果相等,会将输入缓冲区中的0x1448字节复制到&dword_18BD8指向的内存中,然后调用sub_108F0函数并返回。
下面我们再来分析分析sub_108F0函数的逻辑。sub_108F0函数如下:
char __cdecl sub_108F0()
{
  const char *v0; // esi@1
  const char *v1; // esi@3
  const char *v2; // edi@5
  int v4; // edi@7
  //省略部分代码......
  v2 = &byte_19418;
  if ( byte_19418 )
  {
    do
    {
      sub_143EC(v2);
      v2 += strlen(v2) + 1;
    }
    while ( *v2 );
  }
  *(_DWORD *)v2 = *(_DWORD *)aRw_fon;
  v4 = (int)(v2 + 4);
  *(_DWORD *)v4 = *(_DWORD *)&aRw_fon[4];
  v4 += 4;
  *(_WORD *)v4 = *(_WORD *)&aRw_fon[8];
  *(_BYTE *)(v4 + 2) = aRw_fon[10];
  sub_12374(0, 1);
  return 1;
}
sub_108F0函数中,首先让v2指针指向byte_19418这个变量,如果byte_19418不为空字节,则进入do-while循环,循环的条件是v2指向的字符不为空,这里暂且不考虑循环体中的sub_143EC函数,每次循环会移动v2指针到v2指向的字符串'\0'结尾的下一个字符处,即上面代码中的“v2 += strlen(v2) + 1”。直到v2指向的字符为空时,退出循环。接着后面几行很好理解,即将aRw_fon指针指向的11个字节写入v2指向的内存中。
上面我们要注意的是,在调用sub_108F0函数之前,从&dword_18BD8(即aswmon2+18BD8)开始的0x1448字节是我们可以控制的,而在sub_108F0函数中引用到的&byte_19418(即aswmon2+19418)开始的内存正好处于其中。这也就是说至少我们可以控制sub_108F0函数中do-while循环这段代码。另一方面,aRw_fon所指向的是一个静态字符串"<RW>*.FON"

。。。。。。(详见附件中的样章)

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
2
前排支持,期待出版中……
2011-2-28 16:30
0
雪    币: 322
活跃值: (113)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
认真听课,期待出版
2011-2-28 16:35
0
游客
登录 | 注册 方可回帖
返回
//