driver verifier查找隐藏的内存泄露BUG

    转自看雪论坛:http://bbs.pediy.com/showthread.php?t=186922 在原文上略作改动

    verifier是微软提供的驱动测试工具,可以用来识别内存损坏、错误处理的 I/O 请求包 (IRP)、无效的直接内存访问 (DMA) 缓冲区占用、可能的死锁以及低资源模拟等情况。在开始菜单->运行中输入 verifier后,可以弹出如下菜单:

选择默认选项Create standard settings并点击下一步后,出现如下菜单:

选择Automatically select unsigned 并点击下一步后,出现可进行检查的驱动:

点击完成按钮,并重启后verifier便对驱动进行检查。也可以配置verifier对驱动进行更详细地检查(选择Create custom settings->Select individual settings from a full list)

本文要介绍的是使用verifier对驱动内存泄露的检查。做法比较简单,加载驱动并挂verifier后,卸载驱动,若没蓝屏说明驱动没有内存泄露,蓝屏了说明有内存泄露。
测试代码在DriverEntry中申请一块内存并且不做释放,代码如下:

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryString)
{
  NTSTATUS Status = STATUS_SUCCESS;
  UNICODE_STRING ustrLinkName;
  UNICODE_STRING ustrDevName;    
  PDEVICE_OBJECT DeviceObject;
  PVOID pTest;
  
  pTest = ExAllocatePoolWithTag(NonPagedPool, 2000, 'a');
  
  DbgPrint("[ObCallback] DriverEntry: %wZ\n",RegistryString);
// Create dispatch points for device control, create, close.
  DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
  DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
  DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
  DriverObject->DriverUnload = DriverUnload;
  //
  RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);
  Status = IoCreateDevice(DriverObject, 
              0,
              &ustrDevName, 
              FILE_DEVICE_UNKNOWN,
              0,
              FALSE,
              &DeviceObject
              );
  DbgPrint("[ObCallback] Device Name: %wZ\n",&ustrDevName);

  if(!NT_SUCCESS(Status)){
    DbgPrint("[ObCallback] IoCreateDevice = 0x%x\n", Status);
    return Status;
  }
  RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
  Status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);  
  if(!NT_SUCCESS(Status)){
    DbgPrint("[ObCallback] IoCreateSymbolicLink = 0x%x\n", Status);
    IoDeleteDevice(DeviceObject);  
    return Status;
  }
  DeviceObject->Flags |= DO_BUFFERED_IO;
  DbgPrint("[ObCallback] SymbolicLink: %wZ\n",&ustrLinkName);
  return STATUS_SUCCESS;
}

编译生成文件后,并在verifier中选择此驱动并重启,然后用驱动加载工具加载此驱动,并点击安装、启动按钮,随后点击卸载按钮后,果然蓝屏了(附注,原作者可能蓝屏了,不过我在Win7上测试,并没有发生这个现象)。

Windbg.exe加载此蓝屏dump,信息如下:

kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

DRIVER_VERIFIER_DETECTED_VIOLATION (c4)
A device driver attempting to corrupt the system has been caught.  This is
because the driver was specified in the registry as being suspect (by the
administrator) and the kernel has enabled substantial checking of this driver.
If the driver attempts to corrupt the system, bugchecks 0xC4, 0xC1 and 0xA will
be among the most commonly seen crashes.
Arguments:
Arg1: 00000060, A driver has forgotten to free its pool allocations prior to unloading.
Arg2: 00000000, paged bytes
Arg3: 000007d0, nonpaged bytes,
Arg4: 00000001, total # of (paged+nonpaged) allocations that weren't freed.
  To get the name of the driver at fault, type
  dp ViBadDriver l1; dS @$p
  Then type !verifier 3 drivername.sys for info on the allocations
  that were leaked that caused the bugcheck.

Debugging Details:
------------------
Unable to map view of image file
BUGCHECK_STR:  0xc4_60
IMAGE_NAME:  ObCallback.sys
DEBUG_FLR_IMAGE_TIMESTAMP:  53578229
MODULE_NAME: ObCallback
FAULTING_MODULE: f885f000 ObCallback
DEFAULT_BUCKET_ID:  DRIVER_FAULT
PROCESS_NAME:  services.exe
LAST_CONTROL_TRANSFER:  from 80650d0c to 804f9cdb

STACK_TEXT:  
ef52cacc 80650d0c 000000c4 00000060 00000000 nt!KeBugCheckEx+0x1b
ef52caf4 805a45b5 819ce270 81d2b740 81d2b768 nt!MiVerifyingDriverUnloading+0x12a
ef52cb20 80579c88 819ce270 81d2b750 ef52cb4c nt!MmUnloadSystemImage+0x183
ef52cb30 805b1cf4 81d2b768 81d2b750 00000000 nt!IopDeleteDriver+0x32
ef52cb4c 80523cb5 81d2b768 00000000 ef52cc30 nt!ObpRemoveObjectRoutine+0xe0
ef52cb70 804f57c2 ef52cc30 ef52ccac efc94902 nt!ObfDereferenceObject+0x5f
ef52cc14 8057a937 ef52cd0c 00000000 ef52cc30 nt!IopUnloadDriver+0x28a
ef52cc24 8053e854 ef52cd0c ef52cd48 80500255 nt!NtUnloadDriver+0xf
ef52cc24 80500255 ef52cd0c ef52cd48 80500255 nt!KiSystemServicePostCall
ef52cca0 804f5629 ef52cd0c ef52cd64 00d3f868 nt!ZwUnloadDriver+0x11
ef52cd48 8057a937 00d3f870 00000000 ef52cd64 nt!IopUnloadDriver+0xf1
ef52cd58 8053e854 00d3f870 00d3f878 7c92e514 nt!NtUnloadDriver+0xf
ef52cd58 7c92e514 00d3f870 00d3f878 7c92e514 nt!KiSystemServicePostCall
WARNING: Frame IP not in any known module. Following frames may be wrong.
00d3f878 00000000 00000000 00000000 00000000 0x7c92e514


STACK_COMMAND:  kb
FOLLOWUP_NAME:  MachineOwner
FAILURE_BUCKET_ID:  0xc4_60_VRF_IMAGE_ObCallback.sys_RECENT
BUCKET_ID:  0xc4_60_VRF_IMAGE_ObCallback.sys_RECENT
Followup: MachineOwner

键入!verifier 3 ObCallback.sys命令:

kd> !verifier 3 ObCallback.sys
Verify Level ff ... enabled options are:
  Special pool
  Special irql
  Inject random low-resource API failures
  All pool allocations checked on unload
  Io subsystem checking enabled
  Deadlock detection enabled
  Enhanced Io checking enabled
  DMA checking enabled

Summary of All Verifier Statistics

RaiseIrqls                             0x0
AcquireSpinLocks                       0x0
Synch Executions                       0x0
Trims                                  0x0

Pool Allocations Attempted             0x1
Pool Allocations Succeeded             0x1
Pool Allocations Succeeded SpecialPool 0x1
Pool Allocations With NO TAG           0x0
Pool Allocations Failed                0x0
Resource Allocations Failed Deliberately   0x0

Current paged pool allocations         0x0 for 00000000 bytes
Peak paged pool allocations            0x0 for 00000000 bytes
Current nonpaged pool allocations      0x1 for 000007D0 bytes
Peak nonpaged pool allocations         0x1 for 000007D0 bytes

Driver Verification List

Entry     State           NonPagedPool   PagedPool   Module

81f95f00 Loaded           000007d0       00000000    ObCallback.sys

Current Pool Allocations  00000001    00000000
Current Pool Bytes        000007d0    00000000
Peak Pool Allocations     00000001    00000000
Peak Pool Bytes           000007d0    00000000

PoolAddress  SizeInBytes    Tag       CallersAddress
829e0830     0x000007d0     a...      f8860129

f8860129便是内存泄露地址的下一句汇编地址,反汇编上一句(call调用)汇编地址:
kd> u f8860129-6
ObCallback+0x1123:
f8860123 ff151c1086f8    call    dword ptr [ObCallback+0x201c (f886101c)]
f8860129 ff750c          push    dword ptr [ebp+0Ch]
f886012c 68420386f8      push    offset ObCallback+0x1342 (f8860342)
f8860131 e8d2000000      call    ObCallback+0x1208 (f8860208)
f8860136 8b7508          mov     esi,dword ptr [ebp+8]
f8860139 8b3d0c1086f8    mov     edi,dword ptr [ObCallback+0x200c (f886100c)]
f886013f 59              pop     ecx
f8860140 59              pop     ecx
kd> 
ObCallback+0x1123:
f8860123 ff151c1086f8    call    dword ptr [ObCallback+0x201c (f886101c)]
f8860129 ff750c          push    dword ptr [ebp+0Ch]
f886012c 68420386f8      push    offset ObCallback+0x1342 (f8860342)
f8860131 e8d2000000      call    ObCallback+0x1208 (f8860208)
f8860136 8b7508          mov     esi,dword ptr [ebp+8]
f8860139 8b3d0c1086f8    mov     edi,dword ptr [ObCallback+0x200c (f886100c)]
f886013f 59              pop     ecx
f8860140 59              pop     ecx

f8860123地址处便是内存泄露的地方。查看call  dword ptr [ObCallback+0x201c (f886101c)]中的f886101c的内容,并反汇编:

kd> dd f886101c  l1
f886101c  80651a68
kd> u 80651a68
nt!VerifierAllocatePoolWithTag:
80651a68 8bff            mov     edi,edi
80651a6a 55              push    ebp
80651a6b 8bec            mov     ebp,esp
80651a6d 51              push    ecx
80651a6e 51              push    ecx
80651a6f 8d45f8          lea     eax,[ebp-8]
80651a72 50              push    eax
80651a73 8d45fc          lea     eax,[ebp-4]

对应的函数是VerifierAllocatePoolWithTag,源代码其实是ExAllocatePoolWithTag。因为driver verifier Hook了驱动的输入表,把ExAllocatePoolWithTag函数替换为verifier 的VerifierAllocatePoolWithTag函数。
所以用上文所述的方法可以查找隐藏的内存泄露。

----------------------------------------------------------------

文本作者后记:

    这几天同事测试我的驱动时,开着driver  verifier加载驱动检测代码完整性(win10加入的新特性),结果蓝屏了。这个驱动其实已经过了WHCK测试(含HVCI测试项),调试dump文件时发现确实有个别函数不符合代码完整性测试。WHCK测试时仅仅加载驱动,并没有覆盖驱动程序的所有功能,因此,虽然过了WHCK测试,但做Driver verifier时失败了。看来Driver verifer做了很多API hook来实现检测功能

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: driver_verifier_dma_violation是一个Windows操作系统的错误代码,通常发生在设备驱动程序中存在DMA(直接内存访问)错误时。这可能是由于驱动程序中的错误代码或硬件故障引起的。为了解决这个问题,可以尝试更新或卸载驱动程序,或者检查硬件是否正常工作。如果问题仍然存在,建议联系技术支持或专业人员进行进一步的故障排除。 ### 回答2: Driver Verifier DMA Violation是Windows系统的一种蓝屏错误,其原因可能是驱动程序在处理直接内存存取(DMA)时发生了错误或难以管理。 DMA是一种用于在集成电路之间传输数据的技术,它可以比处理器更快地进行数据传输。然而,在操作系统中,驱动程序需要负责管理DMA过程。如果驱动程序出现问题,可能会导致数据传输错误或内存访问冲突。这就是Driver Verifier DMA Violation错误的可能原因之一。 在Windows系统中,可以使用驱动程序验证器(Driver Verifier)来检查驱动程序是否存在错误。如果出现DMA Violation错误,驱动程序验证器将停止该驱动程序并向用户显示错误信息。用户可以尝试更新驱动程序或卸载有问题的驱动程序来解决此错误。 另一种可能导致此错误的情况是硬件故障。由于DMA涉及直接内存存取,因此如果硬件存在问题,例如损坏的内存或I/O设备,也可能导致DMA Violation错误。用户可以尝试使用Windows系统自带的故障排除工具来检测硬件问题,或者联系厂商进行更进一步的检测和修复。 总之,如果您在使用Windows操作系统时遇到Driver Verifier DMA Violation错误,需要及时采取措施,例如更新驱动程序或诊断硬件问题。在处理此错误时,如果需要更多帮助和支持,请联系Windows技术支持团队。 ### 回答3: driver_verifier_dma_violation是Windows操作系统中的一个错误代码,通常是由于驱动程序的内存泄漏或错误使用Direct Memory Access(DMA)操作引起的。DMA是一种硬件技术,允许设备直接访问主板的内存,从而提高数据传输速度。当设备驱动程序使用DMA操作时,它需要遵循一些规则以确保正确的内存访问和释放,否则就会导致driver_verifier_dma_violation错误。 常见的导致DMA错误的原因包括: 1.驱动程序过时或不兼容。驱动程序应该是最新版本,并且与操作系统兼容。 2.设备驱动程序没有正确配置DMA操作。要执行DMA操作,必须正确配置DMA通道,并使用正确的缓冲区大小。 3.内存泄漏。如果驱动程序没有适当地释放内存,那么可以导致DMA错误。 如果发现driver_verifier_dma_violation错误,可以采取以下步骤: 1.更新驱动程序。确定驱动程序是否过时,如果是,则需要更新。 2.使用设备管理器检查设备。用设备管理器检查设备是否正常工作,是否有任何出错或警告信息。 3.检查系统日志。检查系统事件日志是否包含有关DMA错误的信息和详细信息。 4.运行系统文件检查器。使用系统文件检查器扫描系统文件是否有损坏或缺失。 5.检查硬件。检查硬件是否与操作系统兼容,是否需要维修或更换。 在进行这些步骤之后,如果driver_verifier_dma_violation错误仍然存在,则可能需要进行更深入的故障排除,或者寻求专业技术支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值