驱动列举进程输出到应用层

本篇算是前两篇的综合,驱动列举出进程,并将进程名加入到一个链表中,
最后应用层程序通过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);
}

 

posted @ 2012-06-13 16:13  einyboy  阅读(2004)  评论(0编辑  收藏  举报