zoukankan      html  css  js  c++  java
  • 通过暴力搜索PID遍历进程并获取进程信息

    背景

    通常我们在内核中使用 ZwQuerySystemInformation 函数来遍历进程模块并获取进程信息,这种是通过正常的进程遍历方式,所以,有很多 Rootkit 程序会 HOOK 这个 ZwQuerySystemInformation 函数,过滤指定进程,从而实现进程的隐藏。

    本文实现的进程遍历和获取进程信息并不打算使用 ZwQuerySystemInformation 这种方式,而是直接暴力搜索进程的 PID,根据有效的 PID 获取相应进程的信息,从而实现进程的遍历。现在,我就来讲解具体的实现过程和原理,这个程序支持 32 位和 64 位 Win 7 至 Win10 全平台。

    函数介绍

    PsLookupProcessByProcessId

        NTSTATUS PsLookupProcessByProcessId(
            _In_  HANDLE    ProcessId,		// 指定进程的进程ID。
            _Out_ PEPROCESS *Process		// 返回指向ProcessId指定的进程的EPROCESS结构的引用指针。
        );
    
    // 返回指向ProcessId指定的进程的EPROCESS结构的引用指针。
    

    如果对 PsLookupProcessByProcessId 的调用成功,PsLookupProcessByProcessId 会增加Process参数中返回的对象的引用计数。因此,当驱动程序完成使用 Process 参数时,驱动程序必须调用 ObDereferenceObject 来取消引用从 PsLookupProcessByProcessId 例程接收的Process参数。


    IoQueryFileDosDeviceName

        NTSTATUS IoQueryFileDosDeviceName(
            _In_  PFILE_OBJECT             FileObject,					// 指向文件的文件对象
            _Out_ POBJECT_NAME_INFORMATION *ObjectNameInformation		// 返回指向新分配的OBJECT_NAME_INFORMATION结构的指针。 这个结构用MS-DOS设备名称信息成功返回填写
        );
        // 成功,则返回STATUS_SUCCESS;否则错误。
    
    /*
    	typedef struct _OBJECT_NAME_INFORMATION {
         	UNICODE_STRING Name;
    	} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
    */
    

    实现原理

    暴力搜索 PID 这个不难理解,即 PID 从 4 开始,步长为 4,一直遍历到 0x1000,因为进程的 PID 总是为 4 的倍数,所以,我们设置遍历的步长为 4。

    然后,我们根据 PID,调用 PsLookupProcessByProcessId 函数获取 EPROCESS 进程结构体,因为 EPROCESS 这个结构体里存储着进程所有的信息,我们可以从这个 EPROCESS 结构体中获取我们想要的信息,例如进程的父进程、进程名、路径、进程双链表链等等。调用完 PsLookupProcessByProcessId 获取 EPROCESS 之后,记得调用 ObDereferenceObject 来释放对象。

    在不同的系统版本中,EPROCESS 这个结构体定义也不相同,所以不建议使用固定的偏移地址来获取进程信息,而应该使用提供的 API 函数从 EPROCESS 结构体中获取。例如:

    获取进程 PID,可以使用 PsGetProcessId 函数。

    获取进程的父进程 PID,可以使用PsGetProcessInheritedFromUniqueProcessId 函数。

    获取进程名称,可以使用 PsGetProcessImageFileName 函数。

    获取进程路径,可以先试用 PsReferenceProcessFilePointer 函数获取文件指针对象,然后再调用 IoQueryFileDosDeviceName 获取 Dos 路径,最后还要记得使用 ObDereferenceObject 函数来释放对象。

    编码实现

    进程遍历:

        // 遍历进程
        NTSTATUS EnumProcess()
        {
            NTSTATUS status = STATUS_SUCCESS;
            ULONG i = 0;
            PEPROCESS pEProcess = NULL;
            // 开始遍历
            for (i = 4; i < 0x10000; i = i + 4)
            {
                status = PsLookupProcessByProcessId((HANDLE)i, &pEProcess);
                if (NT_SUCCESS(status))
                {
                    // 从进程结构中获取进程信息
                    GetProcessInfo(pEProcess);
                    ObDereferenceObject(pEProcess);
                }
            }
            return status;
        }
    

    从进程结构中获取进程信息:

        // 从进程结构中获取进程信息
        VOID GetProcessInfo(PEPROCESS pEProcess)
        {
            NTSTATUS status = STATUS_SUCCESS;
            HANDLE hParentProcessId = NULL, hProcessId = NULL;
            PCHAR pszProcessName = NULL;
            PVOID pFilePoint = NULL;
            POBJECT_NAME_INFORMATION pObjectNameInfo = NULL;
            // 获取父进程 PID
            hParentProcessId = PsGetProcessInheritedFromUniqueProcessId(pEProcess);
            // 获取进程 PID
            hProcessId = PsGetProcessId(pEProcess);
            // 获取进程名称
            pszProcessName = PsGetProcessImageFileName(pEProcess);
            // 获取进程程序路径
            status = PsReferenceProcessFilePointer(pEProcess, &pFilePoint);
            if (NT_SUCCESS(status))
            {
                status = IoQueryFileDosDeviceName(pFilePoint, &pObjectNameInfo);
                if (NT_SUCCESS(status))
                {
                    // 显示
                    DbgPrint("PEPROCESS=0x%p, PPID=%d, PID=%d, NAME=%s, PATH=%ws\n",
                        pEProcess, hParentProcessId, hProcessId, pszProcessName, pObjectNameInfo->Name.Buffer);
                }
                ObDereferenceObject(pFilePoint);
            }    
        }
    
  • 相关阅读:
    ModelViewViewModel 设计模式介绍
    Sliverlight 3 3D 游戏开发学习 第一章:光照、照相机与行为
    【翻译】WF从入门到精通(第十八章):在你的工作流中调用Web服务
    一个能设置验证信息样式的WebTextBox基本验证复合控件
    一个封装了在Ajax下弹出Alert、showModelessDialog、showModalDialog窗口的类
    【翻译】WF从入门到精通(第十一章):并行活动
    测试驱动开发入门
    【翻译】WF从入门到精通(第三章):workflow实例
    【翻译】WF从入门到精通(第九章):逻辑流活动
    关系型数据库与面向对象开发之间的矛盾:学习LINQ有感
  • 原文地址:https://www.cnblogs.com/csnd/p/15613465.html
Copyright © 2011-2022 走看看