ZwQuerySystemInformation 函数查看进程列表

程序主要应用函数  ZwQuerySystemInformation  实现的,这也是window内核的一个很重要,结构很复杂的函数。

函数原型 如下:

//声明ZqQueryAyatemInformation
NTSTATUS ZwQuerySystemInformation(
                                                        IN ULONG SystemInformationClass,  //处理进程信息,只需要处理类别为5的即可
                                                        OUT PVOID SystemInformation,
                                                        IN ULONG SystemInformationLength,
                                                        OUT PULONG ReturnLength
                                                                );

由函数中 IN  OUT 即可知哪些是输入参数哪些是输出参数,

第一个参数 由字面意思即 系统信息类别,我们这里只关心进程信息(其宏定义为5),
第二个参数  存储返回结果信息的缓冲区
第三个参数 是 第二个缓冲区的大小
第四个参数是 实际返回消息的大小
关于此函数的详细信息,有兴趣的童鞋可以查看相关资料

其他说明见代码:

  

#include <ntddk.h>
#define SYSTEMPROCESSINFORMATION 5
//处理进程信息,需要用到这两个结构体
typedef struct _SYSTEM_THREADS  
{  
        LARGE_INTEGER           KernelTime;  
        LARGE_INTEGER           UserTime;  
        LARGE_INTEGER           CreateTime;  
        ULONG                   WaitTime;  
        PVOID                   StartAddress;  
        CLIENT_ID               ClientIs;  
        KPRIORITY               Priority;  
        KPRIORITY               BasePriority;  
        ULONG                   ContextSwitchCount;  
        ULONG                   ThreadState;  
        KWAIT_REASON            WaitReason;  
}SYSTEM_THREADS,*PSYSTEM_THREADS;  

//进程信息结构体  
typedef struct _SYSTEM_PROCESSES  
{  
        ULONG                           NextEntryDelta;    //链表下一个结构和上一个结构的偏移
        ULONG                           ThreadCount;  
        ULONG                           Reserved[6];  
        LARGE_INTEGER                   CreateTime;  
        LARGE_INTEGER                   UserTime;  
        LARGE_INTEGER                   KernelTime;  
        UNICODE_STRING                  ProcessName;     //进程名字
        KPRIORITY                       BasePriority;  
        ULONG                           ProcessId;      //进程的pid号
        ULONG                           InheritedFromProcessId;  
        ULONG                           HandleCount;  
        ULONG                           Reserved2[2];  
        VM_COUNTERS                     VmCounters;  
        IO_COUNTERS                     IoCounters; //windows 2000 only  
        struct _SYSTEM_THREADS          Threads[1];  
}SYSTEM_PROCESSES,*PSYSTEM_PROCESSES;  

//声明ZqQueryAyatemInformation
NTSTATUS ZwQuerySystemInformation(
                                                        IN ULONG SystemInformationClass,  //处理进程信息,只需要处理类别为5的即可
                                                        OUT PVOID SystemInformation,
                                                        IN ULONG SystemInformationLength,
                                                        OUT PULONG ReturnLength
                                                                );
                                                        

NTSTATUS PsProcessList()
{
        NTSTATUS nStatus;
        ULONG retLength;  //缓冲区长度
        PVOID pProcInfo;
        PSYSTEM_PROCESSES pProcIndex;
        //调用函数,获取进程信息
        nStatus = ZwQuerySystemInformation(
                                                        SYSTEMPROCESSINFORMATION,   //获取进程信息,宏定义为5
                                                        NULL,
                                                        0,
                                                        &retLength  //返回的长度,即为我们需要申请的缓冲区的长度
                                                        );
        if(!retLength)
        {
                DbgPrint("ZwQuerySystemInformation error!\n");  
                return nStatus;
        }
        DbgPrint("retLength =  %u\n",retLength);
        //申请空间
        pProcInfo = ExAllocatePool(NonPagedPool,retLength);
        if(!pProcInfo)
        {
                DbgPrint("ExAllocatePool error!\n");  
                return STATUS_UNSUCCESSFUL; 
        }
        nStatus = ZwQuerySystemInformation(
                                                        SYSTEMPROCESSINFORMATION,   //获取进程信息,宏定义为5
                                                        pProcInfo,
                                                        retLength,
                                                        &retLength
                                                        );
        if(NT_SUCCESS(nStatus)/*STATUS_INFO_LENGTH_MISMATCH == nStatus*/)        

        {
                pProcIndex = (PSYSTEM_PROCESSES)pProcInfo;
                //第一个进程应该是 pid 为 0 的进程
                if(pProcIndex->ProcessId == 0)
                        DbgPrint("PID 0 System Idle Process\n");
                //循环打印所有进程信息,因为最后一天进程的NextEntryDelta值为0,所以先打印后判断
                do
                {
                pProcIndex = (PSYSTEM_PROCESSES)((char*)pProcIndex + pProcIndex->NextEntryDelta);
                //进程名字字符串处理,防止打印时,出错
                        if(pProcIndex->ProcessName.Buffer == NULL)
                                pProcIndex->ProcessName.Buffer = L"NULL";
                DbgPrint("ProcName:  %-20ws     pid:  %u\n",pProcIndex->ProcessName.Buffer,pProcIndex->ProcessId);        
                }while(pProcIndex->NextEntryDelta != 0);
        }                
        else 
         {
                DbgPrint("error code : %u!!!\n",nStatus);
         }
        ExFreePool(pProcInfo);  
    return nStatus;          
}
//卸载驱动
VOID OnUnload(IN PDRIVER_OBJECT driver)
{
        DbgPrint("Driver has been unloaded!!!\n");
}
//驱动入口函数
NTSTATUS DriverEntry(IN PDRIVER_OBJECT driver,IN PUNICODE_STRING reg_path)
{
        PsProcessList();
        driver->DriverUnload  = OnUnload; 
        return STATUS_SUCCESS;
}
结果如下:

 

关于上述代码 ,想说三点需要注意的

1、  pProcIndex = (PSYSTEM_PROCESSES)((char*)pProcIndex + pProcIndex->NextEntryDelta);  结构体链表的查找,需要加上上一个结构体的地址
2、注意循环结束的条件,是pProcIndex->NextEntryDelta == 0 的时候,链表中结构的指针为NULL的时候
3、循环的控制,pProcIndex->NextEntryDelta == 0的这个进程信息一样要输出来,所以控制好先后顺序以免少输出一条。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值