遍历驱动设备栈


参考 《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;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值