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

简介:

本篇算是前两篇的综合,驱动列举出进程,并将进程名加入到一个链表中,
最后应用层程序通过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
目录
相关文章
|
3天前
驱动保护 -- 通过PID保护指定进程
驱动保护 -- 通过PID保护指定进程
28 0
驱动保护 -- 通过PID保护指定进程
|
3天前
2023驱动保护学习 -- 通过驱动保护进程
2023驱动保护学习 -- 通过驱动保护进程
20 0
|
5月前
|
Windows
5.4 Windows驱动开发:内核通过PEB取进程参数
PEB结构`(Process Envirorment Block Structure)`其中文名是进程环境块信息,进程环境块内部包含了进程运行的详细参数信息,每一个进程在运行后都会存在一个特有的PEB结构,通过附加进程并遍历这段结构即可得到非常多的有用信息。在应用层下,如果想要得到PEB的基地址只需要取`fs:[0x30]`即可,TEB线程环境块则是`fs:[0x18]`,如果在内核层想要得到应用层进程的PEB信息我们需要调用特定的内核函数来获取。
53 0
5.4 Windows驱动开发:内核通过PEB取进程参数
|
5月前
|
监控 安全 API
7.1 Windows驱动开发:内核监控进程与线程回调
在前面的文章中`LyShark`一直在重复的实现对系统底层模块的枚举,今天我们将展开一个新的话题,内核监控,我们以`监控进程线程`创建为例,在`Win10`系统中监控进程与线程可以使用微软提供给我们的两个新函数来实现,此类函数的原理是创建一个回调事件,当有进程或线程被创建或者注销时,系统会通过回调机制将该进程相关信息优先返回给我们自己的函数待处理结束后再转向系统层。
64 0
7.1 Windows驱动开发:内核监控进程与线程回调
|
5月前
|
存储 Windows
4.6 Windows驱动开发:内核遍历进程VAD结构体
在上一篇文章`《内核中实现Dump进程转储》`中我们实现了ARK工具的转存功能,本篇文章继续以内存为出发点介绍`VAD`结构,该结构的全程是`Virtual Address Descriptor`即`虚拟地址描述符`,VAD是一个`AVL`自`平衡二叉树`,树的每一个节点代表一段虚拟地址空间。程序中的代码段,数据段,堆段都会各种占用一个或多个`VAD`节点,由一个`MMVAD`结构完整描述。
49 0
4.6 Windows驱动开发:内核遍历进程VAD结构体
|
5月前
|
存储 数据安全/隐私保护 Windows
4.5 Windows驱动开发:内核中实现进程数据转储
多数ARK反内核工具中都存在驱动级别的内存转存功能,该功能可以将应用层中运行进程的内存镜像转存到特定目录下,内存转存功能在应对加壳程序的分析尤为重要,当进程在内存中解码后,我们可以很容易的将内存镜像导出,从而更好的对样本进行分析,当然某些加密壳可能无效但绝大多数情况下是可以被转存的。
27 0
4.5 Windows驱动开发:内核中实现进程数据转储
|
5月前
|
监控 Windows
4.4 Windows驱动开发:内核监控进程与线程创建
当你需要在Windows操作系统中监控进程的启动和退出时,可以使用`PsSetCreateProcessNotifyRoutineEx`函数来创建一个`MyCreateProcessNotifyEx`回调函数,该回调函数将在每个进程的创建和退出时被调用。PsSetCreateProcessNotifyRoutineEx 用于在系统启动后向内核注册一个回调函数,以监视新进程的创建和退出,
42 0
4.4 Windows驱动开发:内核监控进程与线程创建
|
5月前
|
监控 安全 Windows
4.3 Windows驱动开发:监控进程与线程对象操作
在内核中,可以使用`ObRegisterCallbacks`这个内核回调函数来实现监控进程和线程对象操作。通过注册一个`OB_CALLBACK_REGISTRATION`回调结构体,可以指定所需的回调函数和回调的监控类型。这个回调结构体包含了回调函数和监控的对象类型,还有一个`Altitude`字段,用于指定回调函数的优先级。优先级越高的回调函数会先被调用,如果某个回调函数返回了一个非NULL值,后续的回调函数就不会被调用。当有进程或线程对象创建、删除、复制或重命名时,内核会调用注册的回调函数。回调函数可以访问被监控对象的信息,如句柄、进程ID等,并可以采取相应的操作,如打印日志、记录信息等。
37 0
4.3 Windows驱动开发:监控进程与线程对象操作
|
6月前
|
存储 安全 调度
4.2 Windows驱动开发:内核中进程线程与模块
内核进程线程和模块是操作系统内核中非常重要的概念。它们是操作系统的核心部分,用于管理系统资源和处理系统请求。在驱动安全开发中,理解内核进程线程和模块的概念对于编写安全的内核驱动程序至关重要。内核进程是在操作系统内核中运行的程序。每个进程都有一个唯一的进程标识符(PID),它用于在系统中唯一地标识该进程。在内核中,进程被表示为一个进程控制块(PCB),它包含有关进程的信息,如进程状态、优先级、内存使用情况等。枚举进程可以让我们获取当前系统中所有正在运行的进程的PID和其他有用的信息,以便我们可以监视和管理系统中的进程。
76 0
4.2 Windows驱动开发:内核中进程线程与模块
|
6月前
|
存储 API Windows
4.1 Windows驱动开发:内核中进程与句柄互转
在内核开发中,经常需要进行进程和句柄之间的互相转换。进程通常由一个唯一的进程标识符(PID)来标识,而句柄是指对内核对象的引用。在Windows内核中,`EProcess`结构表示一个进程,而HANDLE是一个句柄。为了实现进程与句柄之间的转换,我们需要使用一些内核函数。对于进程PID和句柄的互相转换,可以使用函数如`OpenProcess`和`GetProcessId`。OpenProcess函数接受一个PID作为参数,并返回一个句柄。GetProcessId函数接受一个句柄作为参数,并返回该进程的PID。
54 1
4.1 Windows驱动开发:内核中进程与句柄互转