驱动列举进程输出到应用层
本篇算是前两篇的综合,驱动列举出进程,并将进程名加入到一个链表中,
最后应用层程序通过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);
}
驱动列举进程输出到应用层相关推荐
- 使用 C# 捕获进程输出
在 .net 中捕获进程输出 Intro 很多时候我们可能会需要执行一段命令获取一个输出,遇到的比较典型的就是之前我们需要用 FFMpeg 实现视频的编码压缩水印等一系列操作,当时使用的是 FFMpe ...
- 驱动保护进程 句柄降权 杀软自保 游戏破图标技术原理和实现
文章目录 实现效果 实现原理 代码实现 实现效果 句柄降权对抗(实现破游戏图标和关闭杀软自保) 降权对抗延伸 游戏降权对抗 杀软自保对抗 隐藏Object钩子回调 完整代码 实现效果 效果如图所示: ...
- [论文]基于模型的细长体欠驱动水下机器人输出反馈控制:理论与实验
[论文]基于模型的细长体欠驱动水下机器人输出反馈控制:理论与实验 摘要 本文介绍了一种新型细长体水下机器人输出反馈控制器的设计和实验结果.控制器是使用基于模型的设计技术得到的.采用了两个独立的控制设备 ...
- MSP432驱动舵机串口输出角度
MSP432驱动舵机串口输出角度 备注:我用的TI官方launchpad的MSP432P401R开发板 1.舵机需要50Hz基准的PWM,占空比是0.025~0.125.如何产生PWM,当然是定时器了 ...
- Linux驱动获取进程PID和进程名字
Linux驱动打印进程PID和进程名字 在内核中, 进程用task_struct结构表示, 其中有char comm[TASK_COMM_LEN]成员, 其含义是 executable name ex ...
- 【吐血推荐】领域驱动设计学习输出
一.Hello DDD 刚开始接触学习「DDD - 领域驱动」的时候,我被各种新颖的概念所吸引:「领域」.「领域驱动」.「子域」.「聚合」.「聚合根」.「值对象」.「通用语言」.....总之一大堆有关 ...
- linux重定向进程输出到文件删除,Linux文件编辑器vim输出输入重定向、管道以及进程(示例代码)...
合抱之木,生于毫末:九层之台,起于累土:千里之行,始于足下.正因基础的重要性,才又撸起了linux. linux编辑工具: VI VIM EMACS vim 是vi的升级版本,它不仅兼容vi的所有指令 ...
- s5p4418 Android 4.4.2 驱动层 HAL层 服务层 应用层 开发流程记录(一 硬件驱动层)
欢迎转载,务必注明出处:http://blog.csdn.net/wang_shuai_ww/article/details/44303069 本文章是记录Android开发中驱动层.HAL层.应用层 ...
- NdisFilter驱动数据全部转发到应用层的性能之优化(使用共享环形队列方式)
by fanxiushu 2019-01-22 转载或引用请注明原始作者. 在上一篇文章中, https://blog.csdn.net/fanxiushu/article/details/8651 ...
最新文章
- abb变频器acs800功率_ABB变频器如何选型(1)
- Latex之WinEdt编辑界面的自动换行
- 设计模式系列(一)单例模式
- 在C#中选择“.NET研究”正确的集合进行编码
- python模块matplotlib.pyplot用法_python – 虽然使用pyplot.show(),但如何使用matplotlib保持图形大小不变?...
- OpenSceneGraph学习笔记
- 广度优先遍历算法-03树的右侧问题
- 【最新合集】编译原理习题(含答案)_1 绪论_MOOC慕课 哈工大陈鄞
- 【jzoj】2018.2.5NOIP普及组——C组模拟赛
- 以Linux系统(Ubuntu)开发生活(一)
- 「PKUWC2018」Slay the Spire
- 【JavaScript】在JavaScript中使用JSON进行序列化/反序列化操作
- LINUX下,ffmpeg增加NVIDIA硬件编解码的步骤及解决办法
- 软件测试 — 面试题
- 在Excel中批量生成二维码标签,标签中可添加二维码或者条形码
- 今天,腾讯云总裁邱跃鹏表示,云计算发展要迈过三道关……
- 【简单记】用友NC6.5_RCE
- 3D 专业词汇 (转)
- HTML5系列代码:使用自定义图像来作为空距
- 分享一个宝藏级 Java 插件
热门文章
- 电脑不能打字_宝妈、学生、上班族手机兼职——打字录入
- java 工程ssl配置_JAVA_SSL配置
- between and 效率_香港城市大学吕坚教授Adv. Funct. Mater.: 铁基金属玻璃在工业废水处理上再次突破,实现催化效率与稳定性双提升...
- java字符串操作_Java的字符串操作
- 笔记-知识产权与标准化知识-GB/T9385-2006计算机软件文档编制规范
- Vue中使用v-for实现一对多数据的2层和3层嵌套循环
- Electron中实现通过webview实现内嵌网页并嵌入css样式和js脚本等
- C#中在窗体应用中使用StringBuilder拼接显示网页
- Java中使用递归算法实现子级架构的查询
- SSM+KindEditor实现富文本编辑器图片上传