Ring0中通过PEB查找指定Ring3进程的模块地址(路径/模块名等)

代码笔记 99
代码笔记 99

最近正好又想要原力游戏一下,尝试在Ring0中获取到Ring3中某个进程的特定模块地址,想到两种方法一种是利用LoadImage判断到模块路径来找到这个模块的地址,另一种是利用PEB来获取到进程的模块信息。个人觉得利用PEB应该是一个更好的方法,由于初学C++,基础不扎实代码写的不规范,文章用作记录用到的代码,便于下次继续使用。


x86/x64进程所涉及到的数据结构是不一样的,定义的数据结构当中分别有针对x86/x64的定义,使用时需要注意区分。
定义数据结构:

typedef struct _PEB_LDR_DATA {
    ULONG Length;
    UCHAR Initialized;
    PVOID SsHandle;
    LIST_ENTRY InLoadOrderModuleList;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
    PVOID EntryInProgress;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

typedef struct _PEB_LDR_DATA32 {
    ULONG Length;
    UCHAR Initialized;
    ULONG SsHandle;
    LIST_ENTRY32 InLoadOrderModuleList;
    LIST_ENTRY32 InMemoryOrderModuleList;
    LIST_ENTRY32 InInitializationOrderModuleList;
    ULONG EntryInProgress;
} PEB_LDR_DATA32, *PPEB_LDR_DATA32;

typedef struct _PEB {
    UCHAR InheritedAddressSpace;
    UCHAR ReadImageFileExecOptions;
    UCHAR BeingDebugged;
    UCHAR Spare;
    PVOID Mutant;
    PVOID ImageBaseAddress;
    PPEB_LDR_DATA Ldr;
    PVOID SubSystemData;
} PEB, *PPEB;

typedef struct _PEB32 {
    UCHAR InheritedAddressSpace;
    UCHAR ReadImageFileExecOptions;
    UCHAR BeingDebugged;
    UCHAR Spare;
    ULONG Mutant;
    ULONG ImageBaseAddress;
    ULONG Ldr;
} PEB32, *PPEB32;


typedef struct _LDR_DATA_TABLE_ENTRY {
    LIST_ENTRY InLoadOrderLinks;
    LIST_ENTRY InMemoryOrderLinks;
    LIST_ENTRY InInitializationOrderLinks;
    PVOID DllBase;
    PVOID EntryPoint;
    ULONG SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
    ULONG Flags;
    USHORT LoadCount;
    USHORT TlsIndex;
    LIST_ENTRY HashLinks;
    PVOID SectionPointer;
    ULONG CheckSum;
    ULONG TimeDateStamp;
    PVOID LoadedImports;
    PVOID EntryPointActivationContext;
    PVOID PatchInformation;
    LIST_ENTRY ForwarderLinks;
    LIST_ENTRY ServiceTagLinks;
    LIST_ENTRY StaticLinks;
    PVOID ContextInformation;
    PVOID OriginalBase;
    LARGE_INTEGER LoadTime;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

typedef struct _LDR_DATA_TABLE_ENTRY32 {
    LIST_ENTRY32 InLoadOrderLinks;
    LIST_ENTRY32 InMemoryOrderLinks;
    LIST_ENTRY32 InInitializationOrderLinks;
    ULONG DllBase;
    ULONG EntryPoint;
    ULONG SizeOfImage;
    UNICODE_STRING32 FullDllName;
    UNICODE_STRING32 BaseDllName;
    ULONG Flags;
    USHORT LoadCount;
    USHORT TlsIndex;
    LIST_ENTRY32 HashLinks;
    ULONG SectionPointer;
    ULONG CheckSum;
    ULONG TimeDateStamp;
    ULONG LoadedImports;
    ULONG EntryPointActivationContext;
    ULONG PatchInformation;
    LIST_ENTRY32 ForwarderLinks;
    LIST_ENTRY32 ServiceTagLinks;
    LIST_ENTRY32 StaticLinks;
    ULONG ContextInformation;
    ULONG OriginalBase;
    LARGE_INTEGER LoadTime;
} LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32;

代码实现:

NTSTATUS GetModulesPathByProcessID(IN HANDLE ProcessId, IN UNICODE_STRING ModuleName) {
    typedef PPEB(__stdcall * pfn_PsGetProcessPeb) (PEPROCESS pEProcess);
    typedef PPEB32(__stdcall * pfn_PsGetProcessWow64Process) (PEPROCESS Process);
    NTSTATUS nStatus;
    KAPC_STATE KAPC = { 0 };
    PEPROCESS  pEProcess = NULL;
    PPEB pPEB = NULL;
    UNICODE_STRING uniFunctionName;
    PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL;
    PLIST_ENTRY pListEntryStart = NULL;
    PLIST_ENTRY pListEntryEnd = NULL;
    
    pfn_PsGetProcessPeb  PsGetProcessPeb = NULL;
    
    nStatus = PsLookupProcessByProcessId(ProcessId, &pEProcess);
    if (!NT_SUCCESS(nStatus)) {
        return STATUS_UNSUCCESSFUL;
    }
    
    RtlInitUnicodeString(&uniFunctionName, L"PsGetProcessPeb");
    PsGetProcessPeb = (pfn_PsGetProcessPeb)(SIZE_T)MmGetSystemRoutineAddress(&uniFunctionName);
    pPEB = PsGetProcessPeb(pEProcess);
    KeStackAttachProcess(pEProcess, &KAPC);
    pListEntryStart = pPEB->Ldr->InMemoryOrderModuleList.Flink;
    pListEntryEnd = pPEB->Ldr->InMemoryOrderModuleList.Flink;
    do {
        pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
        KdPrint (("[* Enum 64-bit Module] Name:%wZ    Base-Address: %p\n", &pLdrDataEntry->BaseDllName, pLdrDataEntry->DllBase));
        if (RtlEqualUnicodeString(&pLdrDataEntry->BaseDllName, &ModuleName, TRUE)) {

            KdPrint(("[* Matched Module] Name:%wZ    Base-Address: %p\n", &pLdrDataEntry->BaseDllName, pLdrDataEntry->DllBase));
        }
        pListEntryStart = pListEntryStart->Flink;
    } while (pListEntryStart != pListEntryEnd);
#ifdef _AMD64_
    PPEB32 pPEB32 = NULL;
    PLDR_DATA_TABLE_ENTRY32 pLdrDataEntry32 = NULL;
    PLIST_ENTRY32 pListEntryStart32 = NULL;
    PLIST_ENTRY32 pListEntryEnd32 = NULL;
    
    pfn_PsGetProcessWow64Process PsGetProcessWow64Process = NULL;
    RtlInitUnicodeString(&uniFunctionName, L"PsGetProcessWow64Process");
    PsGetProcessWow64Process = (pfn_PsGetProcessWow64Process)(SIZE_T)MmGetSystemRoutineAddress(&uniFunctionName);
    
    pPEB32 = PsGetProcessWow64Process(pEProcess);
    pListEntryStart32 = (PLIST_ENTRY32)(((PEB_LDR_DATA32*)pPEB32->Ldr)->InMemoryOrderModuleList.Flink);
    pListEntryEnd32 = (PLIST_ENTRY32)(((PEB_LDR_DATA32*)pPEB32->Ldr)->InMemoryOrderModuleList.Flink);
    do {
        pLdrDataEntry32 = (PLDR_DATA_TABLE_ENTRY32)CONTAINING_RECORD(pListEntryStart32, LDR_DATA_TABLE_ENTRY32, InMemoryOrderLinks);
        UNICODE_STRING pBaseDllName;
        UStr32ToUStr(&pBaseDllName, &pLdrDataEntry32->BaseDllName);
        KdPrint (("[* Enum 32-bit Module] Name:%wZ    Base-Address: %p\n", &pBaseDllName, pLdrDataEntry32->DllBase));

        if (RtlEqualUnicodeString(&pBaseDllName, &ModuleName, TRUE)) {

            KdPrint(("[* Matched Module] Name:%wZ    Base-Address: %p\n", &pBaseDllName, pLdrDataEntry32->DllBase));
        }
        pListEntryStart32 = (PLIST_ENTRY32)pListEntryStart32->Flink;
    } while (pListEntryStart32 != pListEntryEnd32);
#endif
end:
    KeUnstackDetachProcess(&KAPC);
    ObDereferenceObject(pEProcess);
    return STATUS_SUCCESS;
}

通过KdPrint()输出x86进程模块信息的时候由于数据结构中使用的是UNICODE_STRING32,所以用到了UStr32ToUStr(&a, &b)转换。
UStr32ToUStr定义:

#define UStr32ToUStr(dst, src) { (dst)->Length = (src)->Length; \
                                 (dst)->MaximumLength = (src)->MaximumLength; \
                                 (dst)->Buffer = (PWSTR) UlongToPtr ((src)->Buffer); }

执行结果:
DebugView

  • copyright
    著作权归作者所有
  • person
  • play_arrow
    99 Views
  • create
  • autorenew
    最后修改:2019 年 04 月 13 日
  • local_offer
    代码笔记无标签
copyright info_outline

*