参考 《windows 驱动开发技术详解》,部分关于对象的结构,请看上节windbg命令 中介绍
公用头文件:
// IOCTLS.H -- IOCTL code definitions for fileio driver
// Copyright (C) 1999 by Walter Oney
// All rights reserved
#ifndef IOCTLS_H
#define IOCTLS_H
#ifndef CTL_CODE
#pragma message("CTL_CODE undefined. Include winioctl.h or wdm.h")
#endif
#define IOCTL_DUMP_DEVICE_STACK CTL_CODE(\
FILE_DEVICE_UNKNOWN, \
0x800, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#endif
ring3级代码
#include <stdio.h>
#include <windows.h>
#include <winioctl.h>
#include "..\Ioctls.h"
int main()
{
HANDLE hDevice = CreateFile("\\\\.\\KeListDeviceSL",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hDevice == INVALID_HANDLE_VALUE)
{
printf("Failed to obtain file handle to device: "
"%s with Win32 error code: %d\n",
"MyWDMDevice", GetLastError() );
return 0;
}
WCHAR* InputBuffer = L"\\Driver\\ACPI";
DWORD dwOutput;
BOOL bRet;
bRet = DeviceIoControl(hDevice,
IOCTL_DUMP_DEVICE_STACK,
InputBuffer,
wcslen(InputBuffer)*2+2,
NULL,
0,
&dwOutput,
NULL);
CloseHandle(hDevice);
return 1;
}
ring0级代码
ListDevice.h
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include <ntddk.h>
NTKERNELAPI
NTSTATUS
ObReferenceObjectByName(
IN PUNICODE_STRING ObjectName,
IN ULONG Attributes,
IN PACCESS_STATE PassedAccessState OPTIONAL,
IN ACCESS_MASK DesiredAccess OPTIONAL,
IN POBJECT_TYPE ObjectType,
IN KPROCESSOR_MODE AccessMode,
IN OUT PVOID ParseContext OPTIONAL,
OUT PVOID *Object
);
NTKERNELAPI
PDEVICE_OBJECT
NTAPI
IoGetBaseFileSystemDeviceObject(
IN PFILE_OBJECT FileObject
);
extern POBJECT_TYPE IoDeviceObjectType;
extern POBJECT_TYPE *IoDriverObjectType;
#ifdef __cplusplus
}
#endif
#include "..\Ioctls.h"
#define MAX_FILE_LENGTH 1024
typedef struct _DEVICE_EXTENSION{
PDEVICE_OBJECT pDevice;
UNICODE_STRING ustrDeviceName;
UNICODE_STRING ustrSymLinkName;
PUCHAR buffer; //缓冲区
ULONG file_length; //模拟文件长度,必须小于MAX_FILE_LENGTH
}DEVICE_EXTENSION, *PDEVICE_EXTENSION;
//函数声明
//创建设备
NTSTATUS CreateDevice(PDRIVER_OBJECT pDriverObject, UNICODE_STRING devname, UNICODE_STRING symLinkName);
//卸载驱动
VOID DriverUnload(PDRIVER_OBJECT pDriverObject);
//IRP请求处理函数
NTSTATUS MyDispatchFunction(PDEVICE_OBJECT device, PIRP pIrp);
//处理消息
NTSTATUS DeviceIoControlDispatch(PDEVICE_OBJECT pDevObj, PIRP pIrp);
//枚举设备栈
PDRIVER_OBJECT EnumDeviceStack(PWSTR pwszDeviceName);
typedef struct _OBJECT_CREATE_INFORMATION
{
ULONG Attributes;
HANDLE RootDirectory;
PVOID ParseContext;
KPROCESSOR_MODE ProbeMode;
ULONG PagedPoolCharge;
ULONG NonPagedPoolCharge;
ULONG SecurityDescriptorCharge;
PSECURITY_DESCRIPTOR SecurityDescriptor;
PSECURITY_QUALITY_OF_SERVICE SecurityQos;
SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
}OBJECT_CREATE_INFORMATION, *POBJECT_CREATE_INFORMATION;
typedef struct _OBJECT_HEADER
{
LONG PointerCount;
union
{
LONG HandleCount;
PSINGLE_LIST_ENTRY SEntry;
};
POBJECT_TYPE Type;
UCHAR NameInfoOffset;
UCHAR HandleInfoOffset;
UCHAR QuotaInfoOffset;
UCHAR Flags;
union
{
POBJECT_CREATE_INFORMATION ObjectCreateInfo;
PVOID QuotaBlockCharged;
};
PSECURITY_DESCRIPTOR SecurityDescriptor;
QUAD Body;
}OBJECT_HEADER, * POBJECT_HEADER;
#define NUMBER_HASH_BUCKETS 37
typedef struct _OBJECT_DIRECTORY
{
struct _OBJECT_DIRECTORY_ENTRY* HashBuckets[NUMBER_HASH_BUCKETS];
struct _OBJECT_DIRECTORY_ENTRY** LookupBucket;
BOOLEAN LookupFound;
USHORT SymbolicLinkUsageCount;
struct _DEVICE_MAP* DeviceMap;
} OBJECT_DIRECTORY, * POBJECT_DIRECTORY;
typedef struct _OBJECT_HEADER_NAME_INFO
{
POBJECT_DIRECTORY Directory;
UNICODE_STRING Name;
ULONG QueryReferences;
#if DBG
ULONG QueryReferences2 ;
LONG DbgDereferenceCount ;
#endif
} OBJECT_HEADER_NAME_INFO, * POBJECT_HEADER_NAME_INFO;
//
// ----OBJECT----
// ----------------------------
// | Object_Header |
// ----------------------------
// | Object_Body(QUAD Body) |
// ----------------------------
//example(device object):
//
//dt nt!_object_header
// +0x000 PointerCount : Int4B
// +0x004 HandleCount : Int4B
// +0x004 NextToFree : Ptr32 Void
// +0x008 Type : Ptr32 _OBJECT_TYPE
// +0x00c NameInfoOffset : UChar
// +0x00d HandleInfoOffset : UChar
// +0x00e QuotaInfoOffset : UChar
// +0x00f Flags : UChar
// +0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION
// +0x010 QuotaBlockCharged : Ptr32 Void
// +0x014 SecurityDescriptor : Ptr32 Void
// +0x018 Body : _QUAD //此处内容即下面的对象
//
//dt nt!_DEVICE_OBJECT
// +0x000 Type : Int2B
// +0x002 Size : Uint2B
// +0x004 ReferenceCount : Int4B
// +0x008 DriverObject : Ptr32 _DRIVER_OBJECT
// +0x00c NextDevice : Ptr32 _DEVICE_OBJECT
// +0x010 AttachedDevice : Ptr32 _DEVICE_OBJECT
// +0x014 CurrentIrp : Ptr32 _IRP
// +0x018 Timer : Ptr32 _IO_TIMER
// +0x01c Flags : Uint4B
// +0x020 Characteristics : Uint4B
// +0x024 Vpb : Ptr32 _VPB
// +0x028 DeviceExtension : Ptr32 Void
// +0x02c DeviceType : Uint4B
// +0x030 StackSize : Char
// +0x034 Queue : <unnamed-tag>
// +0x05c AlignmentRequirement : Uint4B
// +0x060 DeviceQueue : _KDEVICE_QUEUE
// +0x074 Dpc : _KDPC
// +0x094 ActiveThreadCount : Uint4B
// +0x098 SecurityDescriptor : Ptr32 Void
// +0x09c DeviceLock : _KEVENT
// +0x0ac SectorSize : Uint2B
// +0x0ae Spare1 : Uint2B
// +0x0b0 DeviceObjectExtension : Ptr32 _DEVOBJ_EXTENSION
// +0x0b4 Reserved : Ptr32 Void
//
//
#define OBJECT_TO_OBJECT_HEADER( o ) \
CONTAINING_RECORD( (o), OBJECT_HEADER, Body )
#define OBJECT_HEADER_TO_NAME_INFO( oh ) ((POBJECT_HEADER_NAME_INFO) \
((oh)->NameInfoOffset == 0 ? NULL : ((PCHAR)(oh) - (oh)->NameInfoOffset)))
ListDevice.cpp
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// . ' \\| |// `.
// / \\||| : |||// \
// / _||||| -:- |||||- \
// | | \\\ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
//
// .............................................
// 佛祖镇楼 BUG辟易
// 佛曰:
// 写字楼里写字间,写字间里程序员;
// 程序人员写程序,又拿程序换酒钱。
// 酒醒只在网上坐,酒醉还来网下眠;
// 酒醉酒醒日复日,网上网下年复年。
// 但愿老死电脑间,不愿鞠躬老板前;
// 奔驰宝马贵者趣,公交自行程序员。
// 别人笑我忒疯癫,我笑自己命太贱;
// 不见满街漂亮妹,哪个归得程序员?
#include "ListDevice.h"
NTSTATUS
DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath)
{
DbgPrint("Enter DriverEntry\n");
NTSTATUS status;
pDriverObject->DriverUnload = DriverUnload;
for (int i = 0; i< IRP_MJ_MAXIMUM_FUNCTION; i++)
{
pDriverObject->MajorFunction[i] = MyDispatchFunction;
}
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceIoControlDispatch;
//准备创建设备
UNICODE_STRING ustrDevName, ustrSymbolicName;
RtlInitUnicodeString(&ustrDevName, L"\\Device\\KeListDevice");
RtlInitUnicodeString(&ustrSymbolicName, L"\\DosDevices\\KeListDeviceSL");
status = CreateDevice(pDriverObject, ustrDevName, ustrSymbolicName);
if(!NT_SUCCESS(status))
{
KdPrint(("Failed to Create Device ...\n"));
return STATUS_UNSUCCESSFUL;
}
KdPrint(("Exit DriverEntry\n"));
return STATUS_SUCCESS;
}
NTSTATUS CreateDevice(PDRIVER_OBJECT pDriverObject, UNICODE_STRING devname, UNICODE_STRING symLinkName)
{
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;
//创建设备
status = IoCreateDevice(pDriverObject,
sizeof(DEVICE_EXTENSION),
&devname,
FILE_DEVICE_UNKNOWN,
0,
TRUE,
&pDevObj);
if(!NT_SUCCESS(status))
return status;
pDevObj->Flags |= DO_BUFFERED_IO;
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
pDevExt->pDevice = pDevObj;
pDevExt->ustrDeviceName = devname;
pDevExt->ustrSymLinkName = symLinkName;
//创建设备连接
status = IoCreateSymbolicLink(&symLinkName, &devname);
if(!NT_SUCCESS(status))
{
KdPrint(("Failed to IoCreateSymbolicLink and delete DeviceObject --- errorcode = %d ...\n",status));
IoDeleteDevice(pDevObj);
return status;
}
return status;
}
//卸载驱动
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pNextObj;
KdPrint(("Enter DriverUnload...\n"));
pNextObj = pDriverObject->DeviceObject;
//循环遍历删除所有该驱动上的设备
while(pNextObj != NULL)
{
//设备的名称和链接名称均在扩展结构中存储
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pNextObj->DeviceExtension;
//删除符号链接
UNICODE_STRING LinkName = pDevExt->ustrSymLinkName;
IoDeleteSymbolicLink(&LinkName);
pNextObj = pNextObj->NextDevice;
IoDeleteDevice(pDevExt->pDevice);
}
}
//IRP请求处理函数
NTSTATUS MyDispatchFunction(PDEVICE_OBJECT device, PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
//完成IRP,此处不做任何特殊处理
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
KdPrint(("Leave MyDispatchFunction\n"));
return status;
}
//处理消息
NTSTATUS DeviceIoControlDispatch(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
KdPrint(("Enter DeviceIoControlDispatch...\n"));
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
//得到IOCTL码
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
ULONG info = 0;
switch(code)
{
case IOCTL_DUMP_DEVICE_STACK:
{
KdPrint(("IOCTL_DUMP_DEVICE_STACK\n"));
WCHAR* InputBuffer = (WCHAR*)pIrp->AssociatedIrp.SystemBuffer; //ring3级传入的是WCHAR类型的字符串
EnumDeviceStack(InputBuffer);
}
default:
status = STATUS_INVALID_VARIANT;
}
//完成IRP,此处不做任何特殊处理
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = info;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
KdPrint(("Leave MyDispatchFunction\n"));
return status;
}
//获取设备对象的信息
VOID GetDeviceObjectInfo(PDEVICE_OBJECT DevObj)
{
POBJECT_HEADER ObjectHeader;
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
if(DevObj == NULL)
{
DbgPrint("DevObj is NULL!\n");
return;
}
ObjectHeader = OBJECT_TO_OBJECT_HEADER(DevObj); //由对象得到对象头
if(ObjectHeader)
{
//查询设备对象名称并打印
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
if(ObjectNameInfo && ObjectNameInfo->Name.Buffer)
{
//打印设备相关信息
DbgPrint(" Driver Name : %wZ - Device Name :%wZ -Driver Address :0x%x - Device Address: 0x%x\n",
&(DevObj->DriverObject->DriverName),
&(ObjectNameInfo->Name),
DevObj->DriverObject,
DevObj);
}
//无名子设备处理
else if (DevObj->DriverObject)
{
//打印设备相关信息
DbgPrint(" Driver Name : %wZ - Device Name :%wZ -Driver Address :0x%x - Device Address: 0x%x\n",
&(DevObj->DriverObject->DriverName),
L"NULL",
DevObj->DriverObject,
DevObj);
}
}
}
//遍历一个设备上所有的附加设备
VOID GetAttachedDeviceInfo(PDEVICE_OBJECT DevObj)
{
PDEVICE_OBJECT AtDeviceObject; //附加的设备
if(DevObj == NULL)
{
DbgPrint("DevObj is NULL!\n");
return;
}
AtDeviceObject = DevObj->AttachedDevice;
while(AtDeviceObject)
{
DbgPrint( "Attached Driver Name:%wZ,Attached Driver Address:0x%x,Attached DeviceAddress:0x%x\n",
&(AtDeviceObject->DriverObject->DriverName),
AtDeviceObject->DriverObject,
AtDeviceObject );
AtDeviceObject = AtDeviceObject->AttachedDevice;
}
}
//枚举设备栈
PDRIVER_OBJECT EnumDeviceStack(PWSTR pwszDeviceName)
{
UNICODE_STRING DriverName;
PDRIVER_OBJECT DriverObject = NULL;
PDEVICE_OBJECT DeviceObject = NULL;
RtlInitUnicodeString(&DriverName, pwszDeviceName); //本例是获得 高级电源管理驱动的设备栈
ObReferenceObjectByName(&DriverName,
OBJ_CASE_INSENSITIVE,
NULL,
0,
(POBJECT_TYPE)IoDriverObjectType,
KernelMode,
NULL,
(PVOID*)&DriverObject);
if(DriverObject == NULL)
return NULL;
DeviceObject = DriverObject->DeviceObject;
while(DeviceObject)
{
GetDeviceObjectInfo(DeviceObject);
//判断是否有过滤驱动(附加驱动)
if(DeviceObject->AttachedDevice)
GetAttachedDeviceInfo(DeviceObject);
//进一步判断设备上的VPB 中设备
if(DeviceObject->Vpb && DeviceObject->Vpb->DeviceObject)
{
GetDeviceObjectInfo(DeviceObject->Vpb->DeviceObject);
if(DeviceObject->Vpb->DeviceObject->AttachedDevice)
GetAttachedDeviceInfo(DeviceObject->Vpb->DeviceObject);
}
//得到驱动上的下一个设备DEVICE_OBJECT
DeviceObject = DeviceObject->NextDevice;
}
return DriverObject;
}