内核中提供了专用的链表结构: LIST_ENTRY,还有一些对链表的操作函数。通过枚举用户进程的功能。用户层是直接照一个进程快照,然后遍历快照的方式进行的。内核层就是去遍历LLIST_ENTRY链表达到目的。

// 遍历用户进程 - 熟悉内核链表和结构体
// 先引用ntifs,再引用ntddk
#include <ntifs.h>
#include <ntddk.h>
#include <windef.h>

// 前向声明,声明后就可以使用
extern PVOID PsGetProcessPeb(_In_ PEPROCESS Process);
extern NTKERNELAPI PVOID PsGetProcessWow64Process(_In_ PEPROCESS Process);
extern NTKERNELAPI UCHAR* PsGetProcessImageFileName(IN PEPROCESS Process);
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS* Process);
extern NTKERNELAPI HANDLE PsGetProcessInheritedFromUniqueProcessId(IN PEPROCESS Process);


// 设置结构体保存进程信息
typedef struct
{
    DWORD Pid;
    UCHAR ProcessName[2048];
    DWORD Handle;
    LIST_ENTRY ListEntry;
} ProcessList;


BOOLEAN GetAllProcess()
{
    PEPROCESS eproc = NULL;
    LIST_ENTRY linkListHead;

    // 初始化链表头部
    InitializeListHead(&linkListHead);
    ProcessList* pdata = NULL;

    // 这里步长是4,改成其他的都行,看实际情况
    for (int Pid = 0; Pid < 100000; Pid += 4)
    {
        if ( NT_SUCCESS( PsLookupProcessByProcessId((HANDLE)Pid, &eproc) ) )
        {
            if (eproc != NULL)
            {
                STRING nowProcessnameString = { 0 };
                // 初始化 8 位字符的计数字符串
                RtlInitString(&nowProcessnameString, PsGetProcessImageFileName(eproc));

                // 在内核分配堆空间
                pdata = (ProcessList*)ExAllocatePool(PagedPool, sizeof(ProcessList));
                RtlZeroMemory(pdata, sizeof(ProcessList));

                pdata->Pid = (DWORD)PsGetProcessId(eproc);
                RtlCopyMemory(pdata->ProcessName, PsGetProcessImageFileName(eproc),strlen(PsGetProcessImageFileName(eproc)) * 2);
                pdata->Handle = (DWORD)PsGetProcessInheritedFromUniqueProcessId(eproc);
                // 插入元素
                InsertTailList(&linkListHead, &pdata->ListEntry);
                ObDereferenceObject(eproc);
            }
        }
    }

    // 输出链表内的数据
    while (!IsListEmpty(&linkListHead))
    {
        LIST_ENTRY* pEntry = RemoveHeadList(&linkListHead);
        pdata = CONTAINING_RECORD(pEntry, ProcessList, ListEntry);
        DbgPrint("%d | %s | %d \n", pdata->Pid, pdata->ProcessName, pdata->Handle);
        ExFreePool(pdata);
    }
    return TRUE;
}


NTSTATUS unload(PDRIVER_OBJECT driver)
{
    DbgPrint("Driver unload success..");
    return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
    driver->DriverUnload = unload;
    DbgPrint("3 Hello World\n");
    GetAllProcess();
    return STATUS_SUCCESS;
}

从程序本身来看,和一般的程序没有啥区别,就是使用api不同了,一些关键函数名称参数不同而已。

没有版权,随便复制,免费的知识应该共享 all right reserved,powered by Gitbook该文章修订时间: 2023-08-27 22:40:29

results matching ""

    No results matching ""