开发者社区> 长征2号> 正文

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

简介:
+关注继续查看

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

 


本文转自einyboy博客园博客,原文链接:http://www.cnblogs.com/einyboy/archive/2012/06/13/2548050.html

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
支持硬件输入输出的IN指令和OUT指令及测试输入和输出程序
支持硬件输入输出的IN指令和OUT指令及测试输入和输出程序
8 0
Linux驱动开发 数据的传输和辅助信息的作用
Linux驱动开发 数据的传输和辅助信息的作用
24 0
【操作系统篇】第三篇——进程(概念,组成,状态与转换,控制以及通信)
【操作系统篇】第三篇——进程(概念,组成,状态与转换,控制以及通信)
91 0
C/C++ 应用层下遍历驱动列表
实现在应用层下遍历输出驱动文件路径列表信息。
90 0
STM32:TIM输入捕获硬件部分(内含:1.输入捕获简介+2.频率测量+3.通用/高级定时器的输入捕获电路分析(重点)+4.主从触发模式+5.输入捕获基本结构(重点)+6.PWM基本结构)
STM32:TIM输入捕获硬件部分(内含:1.输入捕获简介+2.频率测量+3.通用/高级定时器的输入捕获电路分析(重点)+4.主从触发模式+5.输入捕获基本结构(重点)+6.PWM基本结构)
105 0
驱动开发:通过Async反向与内核通信
在前几篇文章中给大家具体解释了驱动与应用层之间正向通信的一些经典案例,本章将继续学习驱动通信,不过这次我们学习的是通过运用`Async`异步模式实现的反向通信,反向通信机制在开发中时常被用到,例如一个杀毒软件如果监控到有异常进程运行或有异常注册表被改写后,该驱动需要主动的通知应用层进程让其知道,这就需要用到驱动反向通信的相关知识点,如下将循序渐进的实现一个反向通信案例。
37 0
驱动开发:内核特征码搜索函数封装
在前面的系列教程如`《驱动开发:内核枚举DpcTimer定时器》`或者`《驱动开发:内核枚举IoTimer定时器》`里面`LyShark`大量使用了`特征码定位`这一方法来寻找符合条件的`汇编指令`集,总体来说这种方式只能定位特征较小的指令如果特征值扩展到5位以上那么就需要写很多无用的代码,本章内容中将重点分析,并实现一个`通用`特征定位函数。
72 0
小程序和h5之间的通讯及注意事项
起因:在小程序中嵌入已有的h5页面,用于快速开发。但是h5和小程序中的事件通讯是需要解决的问题。参照官网后实践之后得出结论。
293 0
用kithara驱动控制IS620N伺服电机简单实例
用kithara驱动控制IS620N伺服电机简单实例
120 0
+关注
长征2号
文章
问答
视频
文章排行榜
最热
最新
相关电子书
更多
内容驱动游戏分发
立即下载
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载