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;
}
[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);
首先查看返回句柄sampleCharDev的值:
[cpp]
view plain
copy
print?
kd> ?? sampleCharDev
void * 0x80000918
[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
知道这是文件对象后,可以通过!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
有了设备对象的地址,就可以通过!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"
为了演示这些功能,我写了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
相关文章推荐
- windbg中通过文件句柄查找设备(!handle/!fileobj/!devobj命令)
- 在linux环境中,通过监听端口查找进程号命令
- linux c 编程 通过shell中的system命令,根据文件名查找进程号,
- Bash 通过上下键更有效的查找历史命令
- [latex]通过画图来查找符号的latex命令
- 用 Linux blkid 命令查找块设备详情
- 怎样通过iisapp命令查找pid来解决IIS的cpu占用率过高问题
- Android ADB命令大全(通过ADB命令查看wifi密码、MAC地址、设备信息、操作文件、查看文件、日志信息、卸载、启动和安装APK等)
- 用 Linux blkid 命令查找块设备详情
- 用 Linux blkid 命令查找块设备详情
- 在Linux Bash通过上下键快速查找历史命令
- 通过命令查找源码的方法
- find命令查找特定文件,并通过-exec 选项将其按照原来的目录树打包成压缩文件
- linux 启动设备时出现 Stale NFS file handle 错误 解决方法
- Android ADB命令大全(通过ADB命令查看wifi密码、MAC地址、设备信息、操作文件、查看文件、日志信息、卸载、启动和安装APK等)
- 怎样通过iisapp命令查找pid来解决IIS的cpu占用率过高问题
- 通过PC机的MAC地址来查找集联设备所在位置
- windows8中怎么查看显卡设备信息通过dxdiag命令可办到
- Bash 通过上下键更有效的查找历史命令
- Android ADB命令大全(通过ADB命令查看wifi密码、MAC地址、设备信息、操作文件、查看文件、日志信息、卸载、启动和安装APK等)