获取特定进程内特定模块的基址写法一

遍历驱动模块需要用到一些未导出的函数与结构体定义

  1. entry.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    #include <ntifs.h>
    #include <wdm.h>
    #include <intrin.h>
    #include <windef.h>
    #include <ntstrsafe.h>
    #include "ImportStruct.h"

    //https://www.bilibili.com/video/BV1bU4y1m7y9/?spm_id_from=333.999.0.0&vd_source=5777815674b3f4e5c227299a8de61c9b
    //Windows驱动开发-驱动中枚举进程信息-中文名称不乱码那种


    NTSTATUS PsReferenceProcessFilePointer(IN PEPROCESS pEprocess, OUT PVOID* pFilePointer);
    HANDLE PsGetProcessInheritedFromUniqueProcessId(IN PEPROCESS pEprocess);

    VOID DrvUnloadEnumProcess(PDRIVER_OBJECT pDriver);
    NTSTATUS DriverEntryEnumProcess(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path);
    PEPROCESS MyLookupProcess(HANDLE ProcessId);
    VOID EnumProcess();
    PVOID GetUserModuleBaseAddress(IN PEPROCESS EProcess, IN PUNICODE_STRING ModuleName, IN BOOLEAN IsWow64);
    PVOID GetModuleExportAddress(IN PVOID ModuleBase, IN PCCHAR FunctionName, IN PEPROCESS EProcess);

    // 获取进程的PEB
    NTSYSAPI PVOID NTAPI PsGetProcessWow64Process(IN PEPROCESS Process); // 获取WOW64进程的PEB
    NTKERNELAPI
    PPEB
    NTAPI
    PsGetProcessPeb(IN PEPROCESS Process);

    static VOID UnDriver(PDRIVER_OBJECT pDriverObj)
    {
    DbgPrint("[-] 驱动卸载 \n");
    }

    NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
    {
    HANDLE ProcessID = (HANDLE)7924;

    PEPROCESS EProcess = NULL;
    NTSTATUS Status = STATUS_SUCCESS;
    KAPC_STATE ApcState;

    DbgPrint("Hello \n");

    // 根据PID得到进程EProcess结构
    Status = PsLookupProcessByProcessId(ProcessID, &EProcess);
    if (Status != STATUS_SUCCESS)
    {
    DbgPrint("获取EProcessID失败 \n");
    return Status;
    }

    // 判断目标进程是32位还是64位
    BOOLEAN IsWow64 = (PsGetProcessWow64Process(EProcess) != NULL) ? TRUE : FALSE;

    // 验证地址是否可读
    if (!MmIsAddressValid(EProcess))
    {
    DbgPrint("地址不可读 \n");
    Driver->DriverUnload = UnDriver;
    return STATUS_SUCCESS;
    }

    // 将当前线程连接到目标进程的地址空间(附加进程)
    KeStackAttachProcess((PRKPROCESS)EProcess, &ApcState);

    __try
    {
    UNICODE_STRING NtdllUnicodeString = { 0 };
    PVOID NtdllAddress = NULL;

    // 得到进程内ntdll.dll模块基地址
    RtlInitUnicodeString(&NtdllUnicodeString, L"Ntdll.dll");
    NtdllAddress = GetUserModuleBaseAddress(EProcess, &NtdllUnicodeString, IsWow64);
    if (!NtdllAddress)
    {
    DbgPrint("没有找到基址 \n");
    Driver->DriverUnload = UnDriver;
    return STATUS_SUCCESS;
    }

    DbgPrint("[*] 模块ntdll.dll基址: %p \n", NtdllAddress);
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
    }

    // 取消附加
    KeUnstackDetachProcess(&ApcState);

    Driver->DriverUnload = UnDriver;
    return STATUS_SUCCESS;
    }

    // 获取特定进程内特定模块的基址
    PVOID GetUserModuleBaseAddress(IN PEPROCESS EProcess, IN PUNICODE_STRING ModuleName, IN BOOLEAN IsWow64)
    {
    if (EProcess == NULL)
    return NULL;
    __try
    {
    // 设置延迟时间为250毫秒
    LARGE_INTEGER Time = { 0 };
    Time.QuadPart = -250ll * 10 * 1000;

    // 如果是32位则执行如下代码
    if (IsWow64)
    {
    // 得到PEB进程信息
    PPEB32 Peb32 = (PPEB32)PsGetProcessWow64Process(EProcess);
    if (Peb32 == NULL)
    {
    return NULL;
    }

    // 延迟加载等待时间
    for (INT i = 0; !Peb32->Ldr && i < 10; i++)
    {
    KeDelayExecutionThread(KernelMode, TRUE, &Time);
    }

    // 没有PEB加载超时
    if (!Peb32->Ldr)
    {
    return NULL;
    }

    // 搜索模块 InLoadOrderModuleList
    for (PLIST_ENTRY32 ListEntry = (PLIST_ENTRY32)((PPEB_LDR_DATA32)Peb32->Ldr)->InLoadOrderModuleList.Flink; ListEntry != &((PPEB_LDR_DATA32)Peb32->Ldr)->InLoadOrderModuleList; ListEntry = (PLIST_ENTRY32)ListEntry->Flink)
    {
    UNICODE_STRING UnicodeString;
    PLDR_DATA_TABLE_ENTRY32 LdrDataTableEntry32 = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks);
    RtlUnicodeStringInit(&UnicodeString, (PWCH)LdrDataTableEntry32->BaseDllName.Buffer);

    // 找到了返回模块基址
    if (RtlCompareUnicodeString(&UnicodeString, ModuleName, TRUE) == 0)
    {
    return (PVOID)LdrDataTableEntry32->DllBase;
    }
    }
    }
    // 如果是64位则执行如下代码
    else
    {
    // 同理,先找64位PEB
    PPEB Peb = PsGetProcessPeb(EProcess);
    if (!Peb)
    {
    return NULL;
    }

    // 延迟加载
    for (INT i = 0; !Peb->Ldr && i < 10; i++)
    {
    KeDelayExecutionThread(KernelMode, TRUE, &Time);
    }

    // 找不到PEB直接返回
    if (!Peb->Ldr)
    {
    return NULL;
    }

    // 遍历链表
    for (PLIST_ENTRY ListEntry = Peb->Ldr->InLoadOrderModuleList.Flink; ListEntry != &Peb->Ldr->InLoadOrderModuleList; ListEntry = ListEntry->Flink)
    {
    // 将特定链表转换为PLDR_DATA_TABLE_ENTRY格式
    PLDR_DATA_TABLE_ENTRY LdrDataTableEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);

    // 找到了则返回地址
    if (RtlCompareUnicodeString(&LdrDataTableEntry->BaseDllName, ModuleName, TRUE) == 0)
    {
    return LdrDataTableEntry->DllBase;
    }
    }
    }
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
    return NULL;
    }
    return NULL;
    }


  2. ImportStruct.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    #pragma on
    #include <ntifs.h>


    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 TimeDateStamp;
    } LDR_DATA_TABLE_ENTRY32, * PLDR_DATA_TABLE_ENTRY32;
    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;
    ULONG TimeDateStamp;
    } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
    // 64位PEB相关结构体定义
    typedef struct _PEB_LDR_DATA {
    ULONG Length;
    UCHAR Initialized;
    PVOID SsHandle;
    LIST_ENTRY InLoadOrderModuleList;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
    } PEB_LDR_DATA, * PPEB_LDR_DATA;



    typedef struct _PEB {
    UCHAR InheritedAddressSpace;
    UCHAR ReadImageFileExecOptions;
    UCHAR BeingDebugged;
    UCHAR BitField;
    PVOID Mutant;
    PVOID ImageBaseAddress;
    PPEB_LDR_DATA Ldr;
    PVOID ProcessParameters;
    PVOID SubSystemData;
    PVOID ProcessHeap;
    PVOID FastPebLock;
    PVOID AtlThunkSListPtr;
    PVOID IFEOKey;
    PVOID CrossProcessFlags;
    PVOID UserSharedInfoPtr;
    ULONG SystemReserved;
    ULONG AtlThunkSListPtr32;
    PVOID ApiSetMap;
    } PEB, * PPEB;

    // 32位PEB相关结构体定义

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

    typedef struct _PEB32 {
    UCHAR InheritedAddressSpace;
    UCHAR ReadImageFileExecOptions;
    UCHAR BeingDebugged;
    UCHAR BitField;
    ULONG Mutant;
    ULONG ImageBaseAddress;
    ULONG Ldr;
    ULONG ProcessParameters;
    ULONG SubSystemData;
    ULONG ProcessHeap;
    ULONG FastPebLock;
    ULONG AtlThunkSListPtr;
    ULONG IFEOKey;
    ULONG CrossProcessFlags;
    ULONG UserSharedInfoPtr;
    ULONG SystemReserved;
    ULONG AtlThunkSListPtr32;
    ULONG ApiSetMap;
    } PEB32, * PPEB32;

获取特定进程内特定模块的基址写法二

遍历驱动模块需要用到一些未导出的函数与结构体定义

  1. entry.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #include "EnumDriver.h"

    NTSTATUS DriverUnload(PDRIVER_OBJECT pdriver)
    {
    DbgPrint("unload...\n");
    return STATUS_SUCCESS;
    }

    NTSTATUS DriverEntry(PDRIVER_OBJECT pdriver, PUNICODE_STRING path)
    {
    pdriver->DriverUnload = DriverUnload;
    DbgPrint("loading...\n");
    TestEnumModule();
    return STATUS_SUCCESS;
    }

  2. EnumDriver.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    #pragma once
    #include <ntifs.h>
    #include <wdm.h>
    #include <intrin.h>
    #include <windef.h>

    #define Log(X) DbgPrint("qi:"X##)


    //传入进程名得到PID
    ULONG GetProcessIdByName(char* name);
    VOID TestEnumModule();
    // 通过PEPROCESS获取模块基址
    PVOID GetProcessModuleBase(PEPROCESS pe, PWCHAR modname);

    // HANDLE句柄转换为PID
    ULONG HandleToPid(HANDLE handle);
    // EProcess转换为Handle句柄
    HANDLE EprocessToHandle(PEPROCESS eprocess);


    typedef NTSTATUS(*PfnZwQueryInformationProcess)(
    __in HANDLE ProcessHandle,
    __in PROCESSINFOCLASS ProcessInformationClass,
    __out_bcount(ProcessInformationLength) PVOID ProcessInformation,
    __in ULONG ProcessInformationLength,
    __out_opt PULONG ReturnLength
    );
    NTKERNELAPI
    PPEB
    NTAPI
    PsGetProcessPeb(IN PEPROCESS Process);

    NTKERNELAPI
    PVOID
    NTAPI
    PsGetProcessWow64Process(IN PEPROCESS Process);
    ////传入进程名字通过遍历进程得到PEPROCESS
    NTKERNELAPI CHAR* PsGetProcessImageFileName(PEPROCESS Process);
    // 定义函数指针
    PfnZwQueryInformationProcess ZwQueryInformationProcess;


  3. EnumDriver.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    #include "EnumDriver.h"
    #include "ImportStruct.h"

    ULONG HandleToPid(HANDLE handle)
    {
    if (!handle)return 0;
    PROCESS_BASIC_INFORMATION ProcessBasicInfor;

    // 初始化字符串,并获取动态地址
    UNICODE_STRING UtrZwQueryInformationProcessName = RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");

    ZwQueryInformationProcess = (PfnZwQueryInformationProcess)MmGetSystemRoutineAddress(&UtrZwQueryInformationProcessName);

    // 调用查询
    ZwQueryInformationProcess(
    handle,
    ProcessBasicInformation,
    (PVOID)&ProcessBasicInfor,
    sizeof(ProcessBasicInfor),
    NULL);

    // 返回进程PID
    return ProcessBasicInfor.UniqueProcessId;
    }
    PEPROCESS GetProcessObjectByName(char* name)
    {
    if (!name)return NULL;
    SIZE_T temp;
    for (temp = 100; temp < 10000; temp += 4)
    {
    NTSTATUS status;
    PEPROCESS ep;
    status = PsLookupProcessByProcessId((HANDLE)temp, &ep);
    if (NT_SUCCESS(status))
    {
    char* pn = PsGetProcessImageFileName(ep);
    if (_stricmp(pn, name) == 0)
    return ep;
    }
    }
    return NULL;
    }

    ULONG GetProcessIdByName(char* name)
    {
    if (!name)return 0;
    ////传入进程名字通过遍历进程得到PEPROCESS
    PEPROCESS eprocess = GetProcessObjectByName(name);
    if (!eprocess)
    return 0;
    // EProcess转换为Handle句柄
    HANDLE handle = EprocessToHandle(eprocess);
    if (handle == 0)return 0;
    // HANDLE句柄转换为PID
    ULONG pid = HandleToPid(handle);
    return pid;
    }


    HANDLE EprocessToHandle(PEPROCESS eprocess)
    {
    if (!eprocess)return NULL;
    HANDLE hProcessHandle = (HANDLE)-1;

    NTSTATUS status = ObOpenObjectByPointer(
    eprocess,
    OBJ_KERNEL_HANDLE,
    0,
    0,
    *PsProcessType,
    KernelMode,
    &hProcessHandle
    );

    if (status == STATUS_SUCCESS)
    {
    return hProcessHandle;
    }

    return NULL;
    }

    PVOID GetProcessModuleBase(PEPROCESS pe, PWCHAR modname)
    {
    BOOLEAN iswow64 = TRUE;
    PVOID base = PsGetProcessWow64Process(pe);

    if (!base)
    {
    iswow64 = FALSE;
    base = PsGetProcessPeb(pe);
    }
    if (!base)return NULL;

    UNICODE_STRING temp = { 0 };
    RtlInitUnicodeString(&temp, modname);
    KAPC_STATE kapc = { 0 };
    KeStackAttachProcess(pe, &kapc);

    PVOID modbase = NULL;

    if (!iswow64)
    {
    PLDR_DATA_TABLE_ENTRY entry = NULL;
    PLIST_ENTRY start = ((PPEB)base)->Ldr->InMemoryOrderModuleList.Flink;
    PLIST_ENTRY end = start;
    do {
    entry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(start, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
    if (entry->DllBase != 0)
    {
    if (RtlCompareUnicodeString(&temp, &entry->BaseDllName, TRUE) == 0)
    {
    Log("%wz,%p\n", &entry->BaseDllName, entry->DllBase);
    modbase = entry->DllBase;
    KeUnstackDetachProcess(&kapc);
    return modbase;
    }
    }
    start = start->Flink;
    } while (start != end);
    }
    else
    {
    PLDR_DATA_TABLE_ENTRY32 entry = ((PLDR_DATA_TABLE_ENTRY32)(((PPEB32)base)->Ldr))->InInitializationOrderLinks.Flink;
    PLDR_DATA_TABLE_ENTRY32 end = entry;
    do {
    if (entry->DllBase != 0)
    {
    if (wcscmp(entry->BaseDllName.Buffer, modname) == 0)
    {
    Log("%p,%ws\n", entry->DllBase, entry->BaseDllName.Buffer);
    modbase = entry->DllBase;
    KeUnstackDetachProcess(&kapc);
    return modbase;
    }
    }
    entry = (PLDR_DATA_TABLE_ENTRY32)entry->InLoadOrderLinks.Blink;
    } while (entry != end);
    }
    KeUnstackDetachProcess(&kapc);
    return NULL;
    }
    VOID TestEnumModule()
    {
    //test x86_64
    HANDLE pid = NULL;
    CHAR pname[] = "Taskmgr.exe";
    pid = GetProcessIdByName(pname);
    if (!pid)
    {
    DbgPrint("error1 pid get false\n");
    return;
    }
    PEPROCESS pe = NULL;
    PsLookupProcessByProcessId(pid, &pe);
    ObReferenceObject(pe);

    PVOID mod = GetProcessModuleBase(pe, L"ntdll.dll");
    DbgPrint("x64:%p\n", mod);
    //test x86
    ULONG pid2 = 0;
    CHAR pname2[] = "DriverMoitor.exe";
    pid2 = GetProcessIdByName(pname2);
    if (!pid)
    {
    DbgPrint("error1 pid get false\n");
    return;
    }
    PsLookupProcessByProcessId(pid2, &pe);
    ObReferenceObject(pe);
    mod = GetProcessModuleBase(pe, L"ntdll.dll");
    Log("x86:%p\n", mod);
    }
  4. ImportStruct.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    #pragma on
    #include <ntifs.h>


    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 TimeDateStamp;
    } LDR_DATA_TABLE_ENTRY32, * PLDR_DATA_TABLE_ENTRY32;
    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;
    ULONG TimeDateStamp;
    } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
    // 64位PEB相关结构体定义
    typedef struct _PEB_LDR_DATA {
    ULONG Length;
    UCHAR Initialized;
    PVOID SsHandle;
    LIST_ENTRY InLoadOrderModuleList;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
    } PEB_LDR_DATA, * PPEB_LDR_DATA;



    typedef struct _PEB {
    UCHAR InheritedAddressSpace;
    UCHAR ReadImageFileExecOptions;
    UCHAR BeingDebugged;
    UCHAR BitField;
    PVOID Mutant;
    PVOID ImageBaseAddress;
    PPEB_LDR_DATA Ldr;
    PVOID ProcessParameters;
    PVOID SubSystemData;
    PVOID ProcessHeap;
    PVOID FastPebLock;
    PVOID AtlThunkSListPtr;
    PVOID IFEOKey;
    PVOID CrossProcessFlags;
    PVOID UserSharedInfoPtr;
    ULONG SystemReserved;
    ULONG AtlThunkSListPtr32;
    PVOID ApiSetMap;
    } PEB, * PPEB;

    // 32位PEB相关结构体定义

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

    typedef struct _PEB32 {
    UCHAR InheritedAddressSpace;
    UCHAR ReadImageFileExecOptions;
    UCHAR BeingDebugged;
    UCHAR BitField;
    ULONG Mutant;
    ULONG ImageBaseAddress;
    ULONG Ldr;
    ULONG ProcessParameters;
    ULONG SubSystemData;
    ULONG ProcessHeap;
    ULONG FastPebLock;
    ULONG AtlThunkSListPtr;
    ULONG IFEOKey;
    ULONG CrossProcessFlags;
    ULONG UserSharedInfoPtr;
    ULONG SystemReserved;
    ULONG AtlThunkSListPtr32;
    ULONG ApiSetMap;
    } PEB32, * PPEB32;