首页
论坛
课程
招聘
[原创]MS11-092补丁分析
2011-12-23 21:45 4759

[原创]MS11-092补丁分析

2011-12-23 21:45
4759
这个补丁出来有几天了,以前没DIFF比较过,所以这次很感兴趣,欢迎指出错误。
由于IDA版本问题。用不起来BINDIFF,只好用DarunGrim了。也蛮强的,结果如下

改动较大的是这个:sub_147CF40A      sub_147CF412     6

又是添加又是修改,我们近IDA看,整理后,如下
signed int __thiscall sub_147CF40A(void *this, int temp2)
{
......
  v19 = this;
  result_1 = 0;
  if ( temp2 )
  {
    src_copy = temp2 + 16;
    if ( *temp2 == 'ilaV' && (parm1 = *(temp2 + 4), parm1_ = *(temp2 + 4), parm2 = *(temp2 + 8), parm2 <= 512) )
    {                                           // Vali
      offset = 0;
      v21 = 0;
      if ( parm1 > 0 )
      {
        while ( v21 < 128 )
        {
          total_size_ = *(src_copy + 16);
          v5 = total_size_ + offset;
          total_size = *(src_copy + 16);        // 拷贝大小
          offset += total_size_;
          if ( total_size_ < 0 || v5 < 0 || v5 > parm2 )
          {
            result_1 = -2147024809;
            break;
          }
          mem_address = alloc_bstr_0x20u();
          mem_address_ = mem_address;
          mem_address__ = mem_address;
          if ( !mem_address )
          {
            result_1 = -2147024882;
            goto error;
          }
          result_1 = adapt_new_mem(mem_address, *src_copy, *(src_copy + 4), 0);
          if ( result_1 < 0 )
            goto error;
          data_size = total_size_ - 32;
          if ( total_size_ - 32 > 0 )
          {
            length = (data_size + 1) >> 1;      // BSTR长度
            BSTR_address = SysAllocStringLen_(&bstrString, (data_size + 1) >> 1);
            parm3 = (mem_address_ + 24);
            sub_147CE7E8(parm3, BSTR_address);
            SysFreeString(bstrString);          // if ( !*v12 || !SysStringLen(*v12) ){error!}
            (*parm3)[length - 1] = 0;           // V11 指针?
            memcpy(*parm3, (src_copy + 32), total_size - 32);
            SysStringByteLen(*parm3);
            SysStringByteLen(*parm3);
            total_size_ = total_size;
            mem_address_ = mem_address__;
          }
          sub_147CF06A(mem_address_);
          src_copy += total_size_;
          ++v21;
          if ( v21 >= parm1_ )
            break;
        }
        if ( result_1 >= 0 )
          goto LABEL_21;
error:
        sub_147CF3EE(v19);
      }
LABEL_21:
      result = result_1;
    }
    else
    {
      result = -2147024809;
    }
  }
  else
  {
    result = -2147024809;
  }
  return result;
}


修改后
signed int __thiscall sub_147CF412(void *this, int temp2)
{
 .....
  v19 = this;
  result_1 = 0;
  if ( temp2 )
  {
    check_file = *temp2 == 'ilaV';
    src_copy_ = temp2 + 16;
    src_copy = temp2 + 16;
    if ( check_file && (parm1 = *(temp2 + 4), parm1_ = *(temp2 + 4), parm2 = *(temp2 + 8), parm2 <= 512) )
    {
      offset = 0;
      v22 = 0;
      if ( parm1 > 0 )
      {
        while ( v22 < 128 )
        {
          total_size = *(src_copy_ + 16);
          v6 = total_size + offset;
          v14 = *(src_copy_ + 16);
          offset += total_size;
          if ( total_size < 0 || v6 < 0 || v6 > parm2 )
          {
            result_1 = -2147024809;
            break;
          }
          mem_address = alloc_bstr_0x20u();
          mem_address_ = mem_address;
          mem_address__ = mem_address;
          if ( !mem_address )
            goto error;
          result_1 = adapt_new_mem(mem_address, *src_copy_, *(src_copy_ + 4), 0);//传递地址
          if ( result_1 < 0 )
            goto LABEL_21;
          data_size = total_size - 32;          // 拷贝大小
          if ( data_size > 0 )
          {
            BSTR_address = SysAllocStringLen_(&bstrString, (data_size + 1) >> 1);
            parm3 = (mem_address_ + 24);//可控参数,直接读文件
            [COLOR="DarkOrange"]sub_147CE7F0(parm3, BSTR_address);//进去!!!,此函数修改了[/COLOR]
            SysFreeString(bstrString);
            if ( !*parm3 || !SysStringLen(*parm3) )//这里!!补丁添加的校验
            {
error:
              result_1 = -2147024882;
              goto LABEL_21;
            }
            (*parm3)[((data_size + 1) >> 1) - 1] = 0;
            memcpy(*parm3, (src_copy + 32), data_size);
            SysStringByteLen(*parm3);
            SysStringByteLen(*parm3);
            src_copy_ = src_copy;
            mem_address_ = mem_address__;
          }
          sub_147CF072(mem_address_);
          src_copy_ += v14;
          ++v22;
          src_copy = src_copy_;
          if ( v22 >= parm1_ )
            break;
        }

补丁对parm3进行了校验,看来错误就在这里了。
这个parm3怎么来的呢。我们网上看到如此字样:
check_file = *temp2 == 'ilaV';
    src_copy_ = temp2 + 16;
同时随便找一个样本文件打开,这里用的是http://samples.mplayerhq.hu/dvr_ms/microsoft-new-way-to-shove-mpeg2-in-asf.dvr-ms
成功查找到如下字段

我们在进
sub_147CE7F0(parm3, BSTR_address);看一看

改动影响不大。于是,
memcpy(*parm3, (src_copy + 32), total_size - 32);3个参数都可控,任意地址写任意数据最终造成漏洞

附件为encdec.dll 补丁前后

第五届安全开发者峰会(SDC 2021)议题征集正式开启!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (7)
雪    币: 4
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
MRCDG 活跃值 2011-12-23 22:31
2
0
沙发,前排留名
雪    币: 427
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
cscoder 活跃值 5 2011-12-24 10:47
3
0
楼主能不能把DarunGrim3的使用方式简单说说?不知道为什么我在使用DarunGrim3的时候Files Import那一步DarunGrim3Server总提示如图所示错误,不知道楼主在使用过程中遇到此类问题了吗?
上传的附件:
  • 1.jpg (44.60kb,338次下载)
雪    币: 427
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
cscoder 活跃值 5 2011-12-24 11:50
4
0
我从MS补丁里面抽取出来的encdec.dll怎么只有182kb~
雪    币: 199
活跃值: 活跃值 (25)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
hellok 活跃值 3 2011-12-24 12:16
5
0
文件路径什么的都不能有中文字符好像,然后如果导入后还是找不到此文件,
找个SQLLITE修改器,修改目录下的index.db数据库。
发现里面字符有错误。或什么的,呵呵。

我是直接找那个文件的。没管补丁。
雪    币: 755
活跃值: 活跃值 (82)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
古河 活跃值 6 2011-12-24 13:49
6
0
谢谢楼主的分享,工具挺好用的

这里应该也是个关键点吧,原来的是有符号比较,导致可以让TotalSize>80000000,从而可以将之后的字符串size设很大来触发漏洞,补丁后变成了无符号比较

上传的附件:
雪    币: 199
活跃值: 活跃值 (25)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
hellok 活跃值 3 2011-12-24 15:13
7
0
确实哈。好细心啊
+1+1
雪    币: 427
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
cscoder 活跃值 5 2011-12-24 19:56
8
0
为了让DarunGrim3发挥其彪悍的所用,建议兄弟们在英文版的系统中运行。谢谢古河!
游客
登录 | 注册 方可回帖
返回