井底燕雀傥 发表于 2024-3-11 13:36:17

枚举PEB获取进程模块列表和进程路径等(不用偏移支持所...

不用系统偏移轻松搞定进程路径 和 模块 名等
typedef PPEB (__stdcall *PFNPsGetProcessPeb)(PEPROCESS pEProcess);

typedef ULONG   PPS_POST_PROCESS_INIT_ROUTINE;

typedef struct _PEB_LDR_DATA {
    BYTE       Reserved1;
    PVOID      Reserved2;
    LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

typedef struct _RTL_USER_PROCESS_PARAMETERS {
    BYTE         Reserved1;
    PVOID          Reserved2;
    UNICODE_STRING ImagePathName;
    UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;


typedef struct _PEB {
    BYTE                        Reserved1;
    BYTE                        BeingDebugged;
    BYTE                        Reserved2;
    PVOID                         Reserved3;
    PPEB_LDR_DATA               Ldr;
    PRTL_USER_PROCESS_PARAMETERSProcessParameters;
    BYTE                        Reserved4;
    PVOID                         Reserved5;
    PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
    BYTE                        Reserved6;
    PVOID                         Reserved7;
    ULONG                         SessionId;
} PEB, *PPEB;

typedef struct _LDR_DATA_TABLE_ENTRY
{
    LIST_ENTRY InLoadOrderLinks;
    LIST_ENTRY InMemoryOrderLinks;
    LIST_ENTRY InInitializationOrderLinks;
    PVOID DllBase;
    PVOID EntryPoint;
    DWORD SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
    DWORD Flags;
    WORD LoadCount;
    WORD TlsIndex;
    LIST_ENTRY HashLinks;
    PVOID SectionPointer;
    DWORD CheckSum;
    DWORD TimeDateStamp;
    PVOID LoadedImports;
    PVOID EntryPointActivationContext;
    PVOID PatchInformation;
}LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;
//结构体声明如上
//下面开始封装一个功能函数 GetProcessModules稍微修改下就 可以 获取进程的路径
NTSTATUS GetProcessModules(ULONG ulProcessId)
{
    NTSTATUS nStatus;
    //PEB结构指针
    PPEB pPEB = NULL;

    //EPROCESS结构指针
    PEPROCESSpEProcess = NULL;

    //查找的函数名称
    UNICODE_STRING uniFunctionName;

    //进程参数信息
    PRTL_USER_PROCESS_PARAMETERS pParam= NULL;

    //LDR数据结构
    PPEB_LDR_DATA pPebLdrData = NULL;

    //LDR链表入口
    PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL;

    //链表头节点、尾节点
    PLIST_ENTRY pListEntryStart = NULL;
    PLIST_ENTRY pListEntryEnd = NULL;

    //函数指针
    PFNPsGetProcessPebPsGetProcessPeb = NULL;

    //保存APC状态
    KAPC_STATE KAPC ={0};

    //是否已经附加到进程
    BOOLEAN bIsAttached = FALSE;

    //获取进程的EPROCESS结构指针
    nStatus = PsLookupProcessByProcessId((HANDLE)ulProcessId, &pEProcess);
    if (!NT_SUCCESS(nStatus))
    {
      return STATUS_UNSUCCESSFUL;
    }

    //查找函数地址
    RtlInitUnicodeString(&uniFunctionName, L"PsGetProcessPeb");
    PsGetProcessPeb = (PFNPsGetProcessPeb)MmGetSystemRoutineAddress(&uniFunctionName);
    if (PsGetProcessPeb == NULL)
    {
      KdPrint(("Get PsGetProcessPeb Failed~!\n"));
      return STATUS_UNSUCCESSFUL;
    }

    //获取PEB指针
    pPEB = PsGetProcessPeb(pEProcess);
    if (pPEB == NULL)
    {
      KdPrint(("Get pPEB Failed~!\n"));
      return STATUS_UNSUCCESSFUL;
    }

    //附加到进程
    KeStackAttachProcess(pEProcess, &KAPC);

    bIsAttached = TRUE;

    //指向LDR
    pPebLdrData = pPEB->Ldr;

    //头节点、尾节点
    pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink;


    //开始遍历_LDR_DATA_TABLE_ENTRY
    do
    {
      //通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构
      pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart,LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);

       //输出DLL全路径
      KdPrint(("%wZ \n", &pLdrDataEntry->FullDllName));

      pListEntryStart = pListEntryStart->Flink;

    }while(pListEntryStart != pListEntryEnd);


    //Detach进程
    if (bIsAttached != FALSE)
    {
      KeUnstackDetachProcess(&KAPC);
    }

    //减少引用计数
    if (pEProcess != NULL)
    {
      ObDereferenceObject(pEProcess);
      pEProcess = NULL;
    }

    return STATUS_SUCCESS;
}

页: [1]
查看完整版本: 枚举PEB获取进程模块列表和进程路径等(不用偏移支持所...