驱动列举进程输出到应用层
本篇算是前两篇的综合,驱动列举出进程,并将进程名加入到一个链表中,
最后应用层程序通过IOCTL读出驱动传递出来的数据。
驱动irp3.h文件:
#include <ntddk.h>
//采用缓冲区内存模式IOCTL,
//MY_DVC_BUFFERED_CODE是自定义的控制码
#define MY_DVC_BUFFERED_CODE /
(ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, /
0x900, /
METHOD_BUFFERED, /
FILE_ANY_ACCESS)
#define DWORD unsigned long
#define BOOL int
//---------系统信息结构---------
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation,
SystemProcessorInformation,
SystemPerformanceInformation,
SystemTimeOfDayInformation,
SystemNotImplemented1,
SystemProcessesAndThreadsInformation,
SystemCallCounts,
SystemConfigurationInformation,
SystemProcessorTimes,
SystemGlobalFlag,
SystemNotImplemented2,
SystemModuleInformation,
SystemLockInformation,
SystemNotImplemented3,
SystemNotImplemented4,
SystemNotImplemented5,
SystemHandleInformation,
SystemObjectInformation,
SystemPagefileInformation,
SystemInstructionEmulationCounts,
SystemInvalidInfoClass1,
SystemCacheInformation,
SystemPoolTagInformation,
SystemProcessorStatistics,
SystemDpcInformation,
SystemNotImplemented6,
SystemLoadImage,
SystemUnloadImage,
SystemTimeAdjustment,
SystemNotImplemented7,
SystemNotImplemented8,
SystemNotImplemented9,
SystemCrashDumpInformation,
SystemExceptionInformation,
SystemCrashDumpStateInformation,
SystemKernelDebuggerInformation,
SystemContextSwitchInformation,
SystemRegistryQuotaInformation,
SystemLoadAndCallImage,
SystemPrioritySeparation,
SystemNotImplemented10,
SystemNotImplemented11,
SystemInvalidInfoClass2,
SystemInvalidInfoClass3,
SystemTimeZoneInformation,
SystemLookasideInformation,
SystemSetTimeSlipEvent,
SystemCreateSession,
SystemDeleteSession,
SystemInvalidInfoClass4,
SystemRangeStartInformation,
SystemVerifierInformation,
SystemAddVerifier,
SystemSessionProcessesInformation
} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;
//------------------------------
//---------线程信息结构---------
typedef struct _SYSTEM_THREAD {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
LONG BasePriority;
ULONG ContextSwitchCount;
ULONG State;
KWAIT_REASON WaitReason;
} SYSTEM_THREAD, *PSYSTEM_THREAD;
//------------------------------
//---------进程信息结构---------
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER Reserved[3];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
HANDLE ProcessId;
HANDLE InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
ULONG PrivatePageCount;
VM_COUNTERS VirtualMemoryCounters;
IO_COUNTERS IoCounters;
SYSTEM_THREAD Threads[0];
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
//------------------------------
//------自定义我们的结构体------
typedef struct _MYPROCESSDATA
{
LIST_ENTRY myListEntry; //在结构体中插入LIST_ENTRY结构,使之成为链表节点,放在开头最合适。
//ULONG uID; //进程ID
UNICODE_STRING usImageName; //线程名称
} MYPROCESSDATA, *PMYPROCESSDATA;
//------------------------------
//------------函数声明----------
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING registryPath);
NTSTATUS
MyDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
MyCreateClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
VOID
MyDriverOnUnload(IN PDRIVER_OBJECT DriverObject);
NTSYSAPI
NTSTATUS
NTAPI
NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL);
//-----------------------------
PMYPROCESSDATA pMyData; //全局变量
LIST_ENTRY ProcessListHead; //进程链表头
#include <ntddk.h>
//采用缓冲区内存模式IOCTL,
//MY_DVC_BUFFERED_CODE是自定义的控制码
#define MY_DVC_BUFFERED_CODE /
(ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, /
0x900, /
METHOD_BUFFERED, /
FILE_ANY_ACCESS)
#define DWORD unsigned long
#define BOOL int
//---------系统信息结构---------
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation,
SystemProcessorInformation,
SystemPerformanceInformation,
SystemTimeOfDayInformation,
SystemNotImplemented1,
SystemProcessesAndThreadsInformation,
SystemCallCounts,
SystemConfigurationInformation,
SystemProcessorTimes,
SystemGlobalFlag,
SystemNotImplemented2,
SystemModuleInformation,
SystemLockInformation,
SystemNotImplemented3,
SystemNotImplemented4,
SystemNotImplemented5,
SystemHandleInformation,
SystemObjectInformation,
SystemPagefileInformation,
SystemInstructionEmulationCounts,
SystemInvalidInfoClass1,
SystemCacheInformation,
SystemPoolTagInformation,
SystemProcessorStatistics,
SystemDpcInformation,
SystemNotImplemented6,
SystemLoadImage,
SystemUnloadImage,
SystemTimeAdjustment,
SystemNotImplemented7,
SystemNotImplemented8,
SystemNotImplemented9,
SystemCrashDumpInformation,
SystemExceptionInformation,
SystemCrashDumpStateInformation,
SystemKernelDebuggerInformation,
SystemContextSwitchInformation,
SystemRegistryQuotaInformation,
SystemLoadAndCallImage,
SystemPrioritySeparation,
SystemNotImplemented10,
SystemNotImplemented11,
SystemInvalidInfoClass2,
SystemInvalidInfoClass3,
SystemTimeZoneInformation,
SystemLookasideInformation,
SystemSetTimeSlipEvent,
SystemCreateSession,
SystemDeleteSession,
SystemInvalidInfoClass4,
SystemRangeStartInformation,
SystemVerifierInformation,
SystemAddVerifier,
SystemSessionProcessesInformation
} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;
//------------------------------
//---------线程信息结构---------
typedef struct _SYSTEM_THREAD {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
LONG BasePriority;
ULONG ContextSwitchCount;
ULONG State;
KWAIT_REASON WaitReason;
} SYSTEM_THREAD, *PSYSTEM_THREAD;
//------------------------------
//---------进程信息结构---------
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER Reserved[3];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
HANDLE ProcessId;
HANDLE InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
ULONG PrivatePageCount;
VM_COUNTERS VirtualMemoryCounters;
IO_COUNTERS IoCounters;
SYSTEM_THREAD Threads[0];
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
//------------------------------
//------自定义我们的结构体------
typedef struct _MYPROCESSDATA
{
LIST_ENTRY myListEntry; //在结构体中插入LIST_ENTRY结构,使之成为链表节点,放在开头最合适。
//ULONG uID; //进程ID
UNICODE_STRING usImageName; //线程名称
} MYPROCESSDATA, *PMYPROCESSDATA;
//------------------------------
//------------函数声明----------
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING registryPath);
NTSTATUS
MyDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
MyCreateClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
VOID
MyDriverOnUnload(IN PDRIVER_OBJECT DriverObject);
NTSYSAPI
NTSTATUS
NTAPI
NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL);
//-----------------------------
PMYPROCESSDATA pMyData; //全局变量
LIST_ENTRY ProcessListHead; //进程链表头
驱动irp3.c文件:
#include "irp3.h"
//------------列举进程----------
NTSTATUS EnumProcess()
{
int iCount = 1; //进程计数
NTSTATUS status; //返回值
PVOID pSi = NULL; //指向SystemInformationClass的指针,此处为SystemProcessesAndThreadsInformation,即我们所要获取的信息
PSYSTEM_PROCESS_INFORMATION pSpiNext = NULL; //同上
ULONG uSize; //pSi的大小,以BYTE为单位
ULONG pNeededSize = 0; //系统返回所需长度,因在WIN2000下不会返回,故不只用,设置为0
BOOL bOver = FALSE; //标识是否列举完成
//设定pSi大小uSize初始为32K,并为pSi分配uSize的内存,根据返回值逐步累加uSize,步长为32K
for (uSize = 0x8000; ((pSi = ExAllocatePoolWithTag(NonPagedPool, uSize, 'tag1')) != NULL); uSize += 0x8000)
{
//检索指定的系统信息,这里是有关进程的信息
status = NtQuerySystemInformation(SystemProcessesAndThreadsInformation,
pSi,
uSize,
&pNeededSize);
if (STATUS_SUCCESS == status) //NtQuerySystemInformation返回成功
{
pSpiNext = (PSYSTEM_PROCESS_INFORMATION)pSi; //使用pSpiNext操作,pSi要留到后面释放所分配的内存
while (TRUE)
{
if (pSpiNext->ProcessId == 0)
{
//pMyData是全局变量,为其申请内存,注意是sizeof(MYPROCESSDATA),非sizeof(PMYPROCESSDATA)!下同
pMyData = (PMYPROCESSDATA)ExAllocatePoolWithTag(PagedPool, sizeof(MYPROCESSDATA), 'tag2');
RtlInitUnicodeString(&pMyData->usImageName, L"System Idle Process");
InsertTailList(&ProcessListHead, (PLIST_ENTRY)&pMyData->myListEntry); //将进程名插入链表
//DbgPrint("[Aliwy] %wZ(%.8X)/n", &pMyData->usImageName, pMyData);
}
else
{
pMyData = (PMYPROCESSDATA)ExAllocatePoolWithTag(PagedPool, sizeof(MYPROCESSDATA), 'tag2');
pMyData->usImageName = pSpiNext->ImageName; //将进程名赋值到我们的结构元素中
InsertTailList(&ProcessListHead, (PLIST_ENTRY)&pMyData->myListEntry); //将进程名插入链表
//DbgPrint("[Aliwy] %wZ(%.8X)/n", &pMyData->usImageName, pMyData);
}
if (pSpiNext->NextEntryOffset == 0) //如果NextEntryOffset为0即表示进程已列举完
{
pMyData = (PMYPROCESSDATA)ExAllocatePoolWithTag(PagedPool, sizeof(MYPROCESSDATA), 'tag2');
RtlInitUnicodeString(&pMyData->usImageName, L"EnumProcess Over"); //进程列举完成
InsertTailList(&ProcessListHead, (PLIST_ENTRY)&pMyData->myListEntry); //将进程名插入链表
//DbgPrint("[Aliwy] %wZ(%.8X)/n", &pMyData->usImageName, pMyData);
bOver = TRUE; //标识进程列举已完成
break; //跳出列举循环(while循环)
}
pSpiNext = (PSYSTEM_PROCESS_INFORMATION)((ULONG)pSpiNext + pSpiNext->NextEntryOffset); //指向下一个进程的信息
iCount++; //计数累加
}
ExFreePool(pSi); //释放为sPi分配的内存
if (bOver) //进程列举完成
{
break; //跳出内存分配循环(for循环)
}
}
}
return STATUS_SUCCESS;
}
//------------------------------
//------------驱动入口----------
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING registryPath)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT Device;
UNICODE_STRING DeviceName, DeviceLink; //设备名,符号链接名
DbgPrint("[Aliwy] DriverEntry/n");
InitializeListHead(&ProcessListHead); //初始化链表头
EnumProcess(); //列举进程,将进程名全部加入到链表中
RtlInitUnicodeString(&DeviceName, L"//Device//Aliwy"); //初始化设备名
RtlInitUnicodeString(&DeviceLink, L"//DosDevices//IamAliwy"); //初始化符号链接名
/* IoCreateDevice 生成设备对象 */
ntStatus = IoCreateDevice(DriverObject, //生成设备的驱动对象
0, //设备扩展区内存大小
&DeviceName, //设备名,/Device/Aliwy
FILE_DEVICE_UNKNOWN, //设备类型
0, //填写0即可
FALSE, //必须为FALSE
&Device); //设备对象指针返回到DeviceObject中
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("[Aliwy] IoCreateDevice FALSE: %.8X/n", ntStatus);
return ntStatus; //生成失败就返回
}
else
DbgPrint("[Aliwy] IoCreateDevice SUCCESS/n");
/* IoCreateSymbolicLink 生成符号链接 */
ntStatus = IoCreateSymbolicLink(&DeviceLink, &DeviceName);
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("[Aliwy] IoCreateSymbolicLink FALSE: %.8X/n", ntStatus);
IoDeleteDevice(Device); //删除设备
return ntStatus;
}
else
DbgPrint("[Aliwy] IoCreateSymbolicLink SUCCESS/n");
Device->Flags &= ~DO_DEVICE_INITIALIZING; //设备初始化完成标记
DriverObject->DriverUnload = MyDriverOnUnload;
/*设备控制请求,对应Ring3 DeviceIoControl*/
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyDeviceIoControl;
/*设备打开请求,对应Ring3 CreateFile*/ //
DriverObject->MajorFunction[IRP_MJ_CREATE] = MyCreateClose; // 要与应用层通信,
/*设备关闭请求,对应Ring3 CloseHandle*/ // 必须有打开、关闭请求!
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MyCreateClose; //
return ntStatus;
}
//------------------------------
//---------设备请求处理---------
NTSTATUS MyDeviceIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION irpSp; //当前IRP调用栈空间
ULONG code; //功能号
ULONG outBufLength; //输出缓冲区长度
PCHAR outBuf; //输出缓冲区
PCHAR outData ; //要向应用层输出的信息
ULONG outDataLen; //信息长度
ANSI_STRING asData; //临时用到的变量
CHAR tmpData[128]; //临时用到的变量
DbgPrint("[Aliwy] MyDeviceIoControl/n");
irpSp = IoGetCurrentIrpStackLocation(Irp); //获得当前IRP调用栈空间
code = irpSp->Parameters.DeviceIoControl.IoControlCode; //得到功能号,即控制码
outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength; //得到输出缓冲区长度
outBuf = Irp->AssociatedIrp.SystemBuffer; //输出缓冲区
if (code == MY_DVC_BUFFERED_CODE) //我们自定义的控制码
{
if (IsListEmpty(&ProcessListHead)) //链表头指向自身,链表为空既不再输入到用户层了
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("[Aliwy] List is Empty. MyDeviceIoControl Over/n");
return Irp->IoStatus.Status;
}
pMyData = CONTAINING_RECORD(RemoveHeadList(&ProcessListHead), //用RemoveHeadList从链表头删除一个元素,
MYPROCESSDATA, //从返回的指针中用CONTAINING_RECORD宏读取该链表元素数据
myListEntry);
//DbgPrint("[Aliwy] %wZ(%.8X)/n", &pMyData->usImageName, pMyData);
RtlInitEmptyAnsiString(&asData, tmpData, sizeof(tmpData)); //初始化一个空的AnsiString
RtlUnicodeStringToAnsiString(&asData, &pMyData->usImageName, TRUE); //将UnicodeString转化成AnsiString
outData = (PCHAR)asData.Buffer; //输出的信息
outDataLen = asData.Length + 1; //输出的长度
RtlCopyBytes(outBuf, outData, outBufLength); //复制我们要传入的内容到输出缓冲区
DbgPrint("[Aliwy] asData: %Z(%d) outData: %s(%d) outBuf: %s(%d)/n", &asData, asData.Length,outData, outDataLen, outBuf, outBufLength);
Irp->IoStatus.Information = (outBufLength < outDataLen ? outBufLength : outDataLen);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT); //结束IRP请求
ExFreePool(pMyData); //释放为pMyData申请的内存,此处pMyData的内存指针与申请时的是对应的,故无需再用变量保存原始指针
}
else
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
DbgPrint("[Aliwy] MyDeviceIoControl Over/n");
return Irp->IoStatus.Status;
}
//------------------------------
//----------打开关闭------------
NTSTATUS MyCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
DbgPrint("[Aliwy] MyCreateClose/n");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}
//------------------------------
//----------驱动卸载------------
VOID MyDriverOnUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING DeviceLink; //符号链接名
DbgPrint("[Aliwy] MyDriverOnUnload/n");
RtlInitUnicodeString(&DeviceLink, L"//DosDevices//IamAliwy");
IoDeleteSymbolicLink(&DeviceLink); //删除符号链接
if (DriverObject->DeviceObject != NULL)
{
IoDeleteDevice(DriverObject->DeviceObject); //删除设备
}
}
//------------------------------
#include "irp3.h"
//------------列举进程----------
NTSTATUS EnumProcess()
{
int iCount = 1; //进程计数
NTSTATUS status; //返回值
PVOID pSi = NULL; //指向SystemInformationClass的指针,此处为SystemProcessesAndThreadsInformation,即我们所要获取的信息
PSYSTEM_PROCESS_INFORMATION pSpiNext = NULL; //同上
ULONG uSize; //pSi的大小,以BYTE为单位
ULONG pNeededSize = 0; //系统返回所需长度,因在WIN2000下不会返回,故不只用,设置为0
BOOL bOver = FALSE; //标识是否列举完成
//设定pSi大小uSize初始为32K,并为pSi分配uSize的内存,根据返回值逐步累加uSize,步长为32K
for (uSize = 0x8000; ((pSi = ExAllocatePoolWithTag(NonPagedPool, uSize, 'tag1')) != NULL); uSize += 0x8000)
{
//检索指定的系统信息,这里是有关进程的信息
status = NtQuerySystemInformation(SystemProcessesAndThreadsInformation,
pSi,
uSize,
&pNeededSize);
if (STATUS_SUCCESS == status) //NtQuerySystemInformation返回成功
{
pSpiNext = (PSYSTEM_PROCESS_INFORMATION)pSi; //使用pSpiNext操作,pSi要留到后面释放所分配的内存
while (TRUE)
{
if (pSpiNext->ProcessId == 0)
{
//pMyData是全局变量,为其申请内存,注意是sizeof(MYPROCESSDATA),非sizeof(PMYPROCESSDATA)!下同
pMyData = (PMYPROCESSDATA)ExAllocatePoolWithTag(PagedPool, sizeof(MYPROCESSDATA), 'tag2');
RtlInitUnicodeString(&pMyData->usImageName, L"System Idle Process");
InsertTailList(&ProcessListHead, (PLIST_ENTRY)&pMyData->myListEntry); //将进程名插入链表
//DbgPrint("[Aliwy] %wZ(%.8X)/n", &pMyData->usImageName, pMyData);
}
else
{
pMyData = (PMYPROCESSDATA)ExAllocatePoolWithTag(PagedPool, sizeof(MYPROCESSDATA), 'tag2');
pMyData->usImageName = pSpiNext->ImageName; //将进程名赋值到我们的结构元素中
InsertTailList(&ProcessListHead, (PLIST_ENTRY)&pMyData->myListEntry); //将进程名插入链表
//DbgPrint("[Aliwy] %wZ(%.8X)/n", &pMyData->usImageName, pMyData);
}
if (pSpiNext->NextEntryOffset == 0) //如果NextEntryOffset为0即表示进程已列举完
{
pMyData = (PMYPROCESSDATA)ExAllocatePoolWithTag(PagedPool, sizeof(MYPROCESSDATA), 'tag2');
RtlInitUnicodeString(&pMyData->usImageName, L"EnumProcess Over"); //进程列举完成
InsertTailList(&ProcessListHead, (PLIST_ENTRY)&pMyData->myListEntry); //将进程名插入链表
//DbgPrint("[Aliwy] %wZ(%.8X)/n", &pMyData->usImageName, pMyData);
bOver = TRUE; //标识进程列举已完成
break; //跳出列举循环(while循环)
}
pSpiNext = (PSYSTEM_PROCESS_INFORMATION)((ULONG)pSpiNext + pSpiNext->NextEntryOffset); //指向下一个进程的信息
iCount++; //计数累加
}
ExFreePool(pSi); //释放为sPi分配的内存
if (bOver) //进程列举完成
{
break; //跳出内存分配循环(for循环)
}
}
}
return STATUS_SUCCESS;
}
//------------------------------
//------------驱动入口----------
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING registryPath)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT Device;
UNICODE_STRING DeviceName, DeviceLink; //设备名,符号链接名
DbgPrint("[Aliwy] DriverEntry/n");
InitializeListHead(&ProcessListHead); //初始化链表头
EnumProcess(); //列举进程,将进程名全部加入到链表中
RtlInitUnicodeString(&DeviceName, L"//Device//Aliwy"); //初始化设备名
RtlInitUnicodeString(&DeviceLink, L"//DosDevices//IamAliwy"); //初始化符号链接名
/* IoCreateDevice 生成设备对象 */
ntStatus = IoCreateDevice(DriverObject, //生成设备的驱动对象
0, //设备扩展区内存大小
&DeviceName, //设备名,/Device/Aliwy
FILE_DEVICE_UNKNOWN, //设备类型
0, //填写0即可
FALSE, //必须为FALSE
&Device); //设备对象指针返回到DeviceObject中
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("[Aliwy] IoCreateDevice FALSE: %.8X/n", ntStatus);
return ntStatus; //生成失败就返回
}
else
DbgPrint("[Aliwy] IoCreateDevice SUCCESS/n");
/* IoCreateSymbolicLink 生成符号链接 */
ntStatus = IoCreateSymbolicLink(&DeviceLink, &DeviceName);
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("[Aliwy] IoCreateSymbolicLink FALSE: %.8X/n", ntStatus);
IoDeleteDevice(Device); //删除设备
return ntStatus;
}
else
DbgPrint("[Aliwy] IoCreateSymbolicLink SUCCESS/n");
Device->Flags &= ~DO_DEVICE_INITIALIZING; //设备初始化完成标记
DriverObject->DriverUnload = MyDriverOnUnload;
/*设备控制请求,对应Ring3 DeviceIoControl*/
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyDeviceIoControl;
/*设备打开请求,对应Ring3 CreateFile*/ //
DriverObject->MajorFunction[IRP_MJ_CREATE] = MyCreateClose; // 要与应用层通信,
/*设备关闭请求,对应Ring3 CloseHandle*/ // 必须有打开、关闭请求!
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MyCreateClose; //
return ntStatus;
}
//------------------------------
//---------设备请求处理---------
NTSTATUS MyDeviceIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION irpSp; //当前IRP调用栈空间
ULONG code; //功能号
ULONG outBufLength; //输出缓冲区长度
PCHAR outBuf; //输出缓冲区
PCHAR outData ; //要向应用层输出的信息
ULONG outDataLen; //信息长度
ANSI_STRING asData; //临时用到的变量
CHAR tmpData[128]; //临时用到的变量
DbgPrint("[Aliwy] MyDeviceIoControl/n");
irpSp = IoGetCurrentIrpStackLocation(Irp); //获得当前IRP调用栈空间
code = irpSp->Parameters.DeviceIoControl.IoControlCode; //得到功能号,即控制码
outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength; //得到输出缓冲区长度
outBuf = Irp->AssociatedIrp.SystemBuffer; //输出缓冲区
if (code == MY_DVC_BUFFERED_CODE) //我们自定义的控制码
{
if (IsListEmpty(&ProcessListHead)) //链表头指向自身,链表为空既不再输入到用户层了
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("[Aliwy] List is Empty. MyDeviceIoControl Over/n");
return Irp->IoStatus.Status;
}
pMyData = CONTAINING_RECORD(RemoveHeadList(&ProcessListHead), //用RemoveHeadList从链表头删除一个元素,
MYPROCESSDATA, //从返回的指针中用CONTAINING_RECORD宏读取该链表元素数据
myListEntry);
//DbgPrint("[Aliwy] %wZ(%.8X)/n", &pMyData->usImageName, pMyData);
RtlInitEmptyAnsiString(&asData, tmpData, sizeof(tmpData)); //初始化一个空的AnsiString
RtlUnicodeStringToAnsiString(&asData, &pMyData->usImageName, TRUE); //将UnicodeString转化成AnsiString
outData = (PCHAR)asData.Buffer; //输出的信息
outDataLen = asData.Length + 1; //输出的长度
RtlCopyBytes(outBuf, outData, outBufLength); //复制我们要传入的内容到输出缓冲区
DbgPrint("[Aliwy] asData: %Z(%d) outData: %s(%d) outBuf: %s(%d)/n", &asData, asData.Length,outData, outDataLen, outBuf, outBufLength);
Irp->IoStatus.Information = (outBufLength < outDataLen ? outBufLength : outDataLen);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT); //结束IRP请求
ExFreePool(pMyData); //释放为pMyData申请的内存,此处pMyData的内存指针与申请时的是对应的,故无需再用变量保存原始指针
}
else
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
DbgPrint("[Aliwy] MyDeviceIoControl Over/n");
return Irp->IoStatus.Status;
}
//------------------------------
//----------打开关闭------------
NTSTATUS MyCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
DbgPrint("[Aliwy] MyCreateClose/n");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}
//------------------------------
//----------驱动卸载------------
VOID MyDriverOnUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING DeviceLink; //符号链接名
DbgPrint("[Aliwy] MyDriverOnUnload/n");
RtlInitUnicodeString(&DeviceLink, L"//DosDevices//IamAliwy");
IoDeleteSymbolicLink(&DeviceLink); //删除符号链接
if (DriverObject->DeviceObject != NULL)
{
IoDeleteDevice(DriverObject->DeviceObject); //删除设备
}
}
//------------------------------
应用层irp3exe.cpp文件:
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
/*采用缓冲区内存模式IOCTL,MY_DVC_IN_CODE是自定义的控制码*/
#define MY_DVC_BUFFERED_CODE /
(ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, /
0x900, /
METHOD_BUFFERED, /
FILE_ANY_ACCESS)
void main()
{
ULONG bytesReturned;
char outBuf[50]; //用于接收驱动传出内容的缓冲区
/*打开设备,用我们自定的符号链接,响应驱动IRP_MJ_CREATE*/
HANDLE hDevice = CreateFile("////.//IamAliwy",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
printf("设备打开失败 %d %.8x/n", GetLastError(), hDevice);
return;
}
memset(outBuf, 0, sizeof(outBuf));
while (true)
{
/*控制设备,响应驱动IRP_MJ_DEVICE_CONTROL*/
BOOL ret = DeviceIoControl(hDevice,
MY_DVC_BUFFERED_CODE, //我们自定义的功能号
NULL, //传入驱动的内容
0, //传入内容长度
&outBuf, //驱动输出的缓冲区
sizeof(outBuf), //驱动输出缓冲区大小
&bytesReturned, //返回的长度
NULL);
if (!ret)
{
printf("Error in DeviceIoControl: %d", GetLastError());
break;
}
else
{
printf("%s(%d)/n", outBuf, bytesReturned); //打印驱动传给我们的内容
if (strstr(outBuf, "Over"))
{
break;
}
}
}
/*关闭设备,对应驱动IRP_MJ_CLOSE*/
CloseHandle(hDevice);
}
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
/*采用缓冲区内存模式IOCTL,MY_DVC_IN_CODE是自定义的控制码*/
#define MY_DVC_BUFFERED_CODE /
(ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, /
0x900, /
METHOD_BUFFERED, /
FILE_ANY_ACCESS)
void main()
{
ULONG bytesReturned;
char outBuf[50]; //用于接收驱动传出内容的缓冲区
/*打开设备,用我们自定的符号链接,响应驱动IRP_MJ_CREATE*/
HANDLE hDevice = CreateFile("////.//IamAliwy",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
printf("设备打开失败 %d %.8x/n", GetLastError(), hDevice);
return;
}
memset(outBuf, 0, sizeof(outBuf));
while (true)
{
/*控制设备,响应驱动IRP_MJ_DEVICE_CONTROL*/
BOOL ret = DeviceIoControl(hDevice,
MY_DVC_BUFFERED_CODE, //我们自定义的功能号
NULL, //传入驱动的内容
0, //传入内容长度
&outBuf, //驱动输出的缓冲区
sizeof(outBuf), //驱动输出缓冲区大小
&bytesReturned, //返回的长度
NULL);
if (!ret)
{
printf("Error in DeviceIoControl: %d", GetLastError());
break;
}
else
{
printf("%s(%d)/n", outBuf, bytesReturned); //打印驱动传给我们的内容
if (strstr(outBuf, "Over"))
{
break;
}
}
}
/*关闭设备,对应驱动IRP_MJ_CLOSE*/
CloseHandle(hDevice);
}