您的位置:首页 > 其它

windbg中通过文件句柄查找设备(!handle/!fileobj/!devobj命令)

2017-02-09 15:08 495 查看
   有时,在驱动程序中会调用ZwCreateFile获得设备句柄,然后保存在设备扩展区域中供其他例程使用。由于驱动程序经常被动调用----执行的上下文可能不是同一个线程----会获得错误的句柄。那么是否存在某些调试命令供我们在开发阶段判断所用句柄正是某个设备的句柄?强大的windbg提供了!handle/!fileobj/!devobj这些扩展命令来实现这个目的(注意这些命令要正确设置调试符号的路径)。
    为了演示这些功能,我写了2个驱动:a.SampleChar,一个挂载在root总线之上的字符驱动,创建了一个名为\\Deivce\SampleChar的虚拟设备;b.FilterSampleChar,同样是挂载在root总线之上的虚拟字符驱动,创建了一个名为\\Device\FilterSample设备。应用程序打开设备\\Device\FilterSample时,FilterSampleChar在Create派遣函数中调用ZwCreateFile打开设备\\Deivce\SampleChar并获得句柄。下面是FilterSampleChar代码片段:

[cpp]
view plain
copy
print?





NTSTATUS FilterSampleCharCreateClose(PDEVICE_OBJECT devObj, PIRP irp)  
{  
    HANDLE sampleCharDev;  
    IO_STACK_LOCATION* currStack = IoGetCurrentIrpStackLocation(irp);  
    NTSTATUS status = STATUS_SUCCESS;  
    UNICODE_STRING devName;  
    OBJECT_ATTRIBUTES fileAttr;  
    IO_STATUS_BLOCK ioStatus;  
    FilterSampleDriverCtx* devCtx = (FilterSampleDriverCtx*)devObj->DeviceExtension;  
  
    RtlInitUnicodeString(&devName, L"\\Device\\SampleChar");  
    InitializeObjectAttributes(&fileAttr,   
                            &devName,  
                            OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,   
                            NULL,NULL);  
  
    switch (currStack->MajorFunction)  
    {  
    case IRP_MJ_CREATE:  
        status = ZwCreateFile(&sampleCharDev,   
                        GENERIC_READ|SYNCHRONIZE,   
                        &fileAttr,   
                        &ioStatus,NULL,  
                        FILE_ATTRIBUTE_NORMAL,  
                        FILE_SHARE_READ,  
                        FILE_OPEN_IF,   
                        FILE_SYNCHRONOUS_IO_NONALERT,   
                        NULL, 0);  
  
        if (status != STATUS_SUCCESS)    ----> 1)  
        {  
            irp->IoStatus.Information = 0;  
            irp->IoStatus.Status = status;  
            IoCompleteRequest(irp, IO_NO_INCREMENT);  
            return status;  
        }  
        else  
        {  
            devCtx->targetDevHd = sampleCharDev;  
        }  
        break;  
    case IRP_MJ_CLEANUP:  
        ZwClose(devCtx->targetDevHd);  
        break;  
    }  
    irp->IoStatus.Information = 0;  
    irp->IoStatus.Status = STATUS_SUCCESS;  
    IoCompleteRequest(irp, IO_NO_INCREMENT);  
  
    return status;  
}  



NTSTATUS FilterSampleCharCreateClose(PDEVICE_OBJECT devObj, PIRP irp)
{
HANDLE sampleCharDev;
IO_STACK_LOCATION* currStack = IoGetCurrentIrpStackLocation(irp);
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING devName;
OBJECT_ATTRIBUTES fileAttr;
IO_STATUS_BLOCK ioStatus;
FilterSampleDriverCtx* devCtx = (FilterSampleDriverCtx*)devObj->DeviceExtension;

RtlInitUnicodeString(&devName, L"\\Device\\SampleChar");
InitializeObjectAttributes(&fileAttr,
&devName,
OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
NULL,NULL);

switch (currStack->MajorFunction)
{
case IRP_MJ_CREATE:
status = ZwCreateFile(&sampleCharDev,
GENERIC_READ|SYNCHRONIZE,
&fileAttr,
&ioStatus,NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0);

if (status != STATUS_SUCCESS)    ----> 1)
{
irp->IoStatus.Information = 0;
irp->IoStatus.Status = status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return status;
}
else
{
devCtx->targetDevHd = sampleCharDev;
}
break;
case IRP_MJ_CLEANUP:
ZwClose(devCtx->targetDevHd);
break;
}
irp->IoStatus.Information = 0;
irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(irp, IO_NO_INCREMENT);

return status;
}
在1)处下断点,然后执行测试程序,windbg马上就会停留在断点处:

[cpp]
view plain
copy
print?





int main()  
{  
    char interfaceBuff[128] = { 0 };  
    DWORD lstErr;  
    char readBuff[4096] = { 0 };  
    DWORD len = 0, writeLen, readLen;  
  
    hDev = CreateFileA("\\\\.\\filterSampleChar",  
        GENERIC_ALL,  
        FILE_SHARE_READ | FILE_SHARE_WRITE,  
        NULL, OPEN_EXISTING, 0, NULL);  



int main()
{
char interfaceBuff[128] = { 0 };
DWORD lstErr;
char readBuff[4096] = { 0 };
DWORD len = 0, writeLen, readLen;

hDev = CreateFileA("\\\\.\\filterSampleChar",
GENERIC_ALL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);




首先查看返回句柄sampleCharDev的值:

[cpp]
view plain
copy
print?





kd> ?? sampleCharDev  
void * 0x80000918  



kd> ?? sampleCharDev
void * 0x80000918
句柄值0x80000918。随后,用!handle命令查看句柄信息

[cpp]
view plain
copy
print?





kd> !handle 80000918   
  
PROCESS 877bbd40  SessionId: 1  Cid: 027c    Peb: 7ffda000  ParentCid: 08e0  
    DirBase: 7ffd9480  ObjectTable: a1da6070  HandleCount:  13.  
    Image: TestFilterSampleChar.exe  
  
Kernel handle table at 9d800000 with 485 entries in use  
  
80000918: Object: 86d0f650  GrantedAccess: 00120089 Entry: 9d801230  
Object: 86d0f650  Type: (87602938) File  
    ObjectHeader: 86d0f638 (new version)  
        HandleCount: 1  PointerCount: 1  



kd> !handle 80000918

PROCESS 877bbd40  SessionId: 1  Cid: 027c    Peb: 7ffda000  ParentCid: 08e0
DirBase: 7ffd9480  ObjectTable: a1da6070  HandleCount:  13.
Image: TestFilterSampleChar.exe

Kernel handle table at 9d800000 with 485 entries in use

80000918: Object: 86d0f650  GrantedAccess: 00120089 Entry: 9d801230
Object: 86d0f650  Type: (87602938) File
ObjectHeader: 86d0f638 (new version)
HandleCount: 1  PointerCount: 1
这个命令显示了句柄所属的进程信息,对象信息:object 86d0f650,对象类型:file

知道这是文件对象后,可以通过!fileobj获得文件本身的信息:

[cpp]
view plain
copy
print?





kd> !fileobj 86d0f650    
  
Device Object: 0x89bf1b18   \Driver\SampleChar  
Vpb is NULL  
Event signalled  
  
Flags:  0x40002  
    Synchronous IO  
    Handle Created  
  
CurrentByteOffset: 0  



kd> !fileobj 86d0f650

Device Object: 0x89bf1b18   \Driver\SampleChar
Vpb is NULL
Event signalled

Flags:  0x40002
Synchronous IO
Handle Created

CurrentByteOffset: 0
通过这个命令,可知:这个文件是打开设备对象Device Object:0x89bf1b18时产生的文件句柄,该设备对象由驱动\Driver\SampleChar创建;另外还有一些文件指针信息,如CurrentByteOffset。

有了设备对象的地址,就可以通过!devstack命令获得设备信息:

[cpp]
view plain
copy
print?





kd> !devstack 0x89bf1b18     
  !DevObj   !DrvObj            !DevExt   ObjectName  
> 89bf1b18  \Driver\SampleChar 89bf1bd0  SampleChar  
  8761b980  \Driver\PnpManager 8761ba38  00000045  
!DevNode 8761b7c8 :  
  DeviceInst is "Root\SYSTEM\0003"  
  ServiceName is "SampleChar"  



kd> !devstack 0x89bf1b18
!DevObj   !DrvObj            !DevExt   ObjectName
> 89bf1b18  \Driver\SampleChar 89bf1bd0  SampleChar
8761b980  \Driver\PnpManager 8761ba38  00000045
!DevNode 8761b7c8 :
DeviceInst is "Root\SYSTEM\0003"
ServiceName is "SampleChar"
!devstack输出的设备栈信息和文章开头所列的代码意图一致,应该足以判断ZwCreateFile返回的设备句柄背后就是设备对象\\Device\SampleChar
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐