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

简介:

本篇算是前两篇的综合,驱动列举出进程,并将进程名加入到一个链表中,
最后应用层程序通过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
目录
相关文章
|
网络协议 API
让每个进程不同外网 IP,实现局部单窗口单 IP,驱动级网络加速器原理!
为解决游戏多开IP限制问题,可采用API HOOK、LSP劫持或驱动层拦截(WFP/TDI)结合SOCKS5转发数据,实现每个进程独立的外网IP。LSP方法需HOOK多个网络函数,如WSPCONNECT等。驱动层中,WFP适用于Win7以上系统,全面拦截,TDI兼容所有系统但拦截不全。提供了一个自编写的驱动层代理示例,支持全局和局部IP设置,适用于每个进程不同IP,长期维护,欢迎使用。下载链接:http://down.8u18.com/down/jsq.rar。附图片展示。
9284 0
|
6月前
驱动保护 -- 通过PID保护指定进程
驱动保护 -- 通过PID保护指定进程
64 0
驱动保护 -- 通过PID保护指定进程
|
6月前
2023驱动保护学习 -- 通过驱动保护进程
2023驱动保护学习 -- 通过驱动保护进程
41 0
驱动保护 -- 通过PID保护指定进程
驱动保护 -- 通过PID保护指定进程
97 0
|
安全
驱动开发:取进程模块的函数地址
在笔者上一篇文章`《驱动开发:内核取应用层模块基地址》`中简单为大家介绍了如何通过遍历`PLIST_ENTRY32`链表的方式获取到`32位`应用程序中特定模块的基地址,由于是入门系列所以并没有封装实现太过于通用的获取函数,本章将继续延申这个话题,并依次实现通用版`GetUserModuleBaseAddress()`取远程进程中指定模块的基址和`GetModuleExportAddress()`取远程进程中特定模块中的函数地址,此类功能也是各类安全工具中常用的代码片段。
230 0
|
存储 API Windows
驱动开发:内核中进程与句柄互转
在内核开发中,经常需要进行进程和句柄之间的互相转换。进程通常由一个唯一的进程标识符(PID)来标识,而句柄是指对内核对象的引用。在Windows内核中,`EProcess`结构表示一个进程,而HANDLE是一个句柄。为了实现进程与句柄之间的转换,我们需要使用一些内核函数。对于进程PID和句柄的互相转换,可以使用函数如`OpenProcess`和`GetProcessId`。OpenProcess函数接受一个PID作为参数,并返回一个句柄。GetProcessId函数接受一个句柄作为参数,并返回该进程的PID。
369 0
|
安全 开发工具 Windows
驱动开发:内核实现进程汇编与反汇编
在笔者上一篇文章`《驱动开发:内核MDL读写进程内存》`简单介绍了如何通过MDL映射的方式实现进程读写操作,本章将通过如上案例实现远程进程反汇编功能,此类功能也是ARK工具中最常见的功能之一,通常此类功能的实现分为两部分,内核部分只负责读写字节集,应用层部分则配合反汇编引擎对字节集进行解码,此处我们将运用`capstone`引擎实现这个功能。
270 0
龙芯2K驱动开发——使用中断触发读取GPIO电平值上传给读取进程
龙芯2K驱动开发——使用中断触发读取GPIO电平值上传给读取进程
476 0
龙芯2K驱动开发——使用中断触发读取GPIO电平值上传给读取进程
|
Shell 索引 Windows
模拟windows任务管理器列举系统进程,并关闭进程......
其实对于 windows进程的操作很简单,只要理解了 进程线程的概念 对于 进程的操作 那么就只是 几个函数的 问题了  。 下面是 对于进程操作要用到的几个函数 。 进程的概念:我们运行了一个程序,那个这个独立的程序就是一个进程。
917 0
|
4月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能

热门文章

最新文章