通过PEB结构遍历进程模块
_UNICODE_STRING 结构体:
1 typedef struct _UNICODE_STRING 2 { 3 USHORT Length; 4 USHORT MaximumLength; 5 PWSTR Buffer; 6 7 } UNICODE_STRING ,*PUNICODE_STRING;
_PEB_LDR_DATA 结构体:
1 typedef struct _PEB_LDR_DATA 2 { 3 ULONG Length; 4 BOOLEAN Initialized; 5 PVOID SsHandle; 6 LIST_ENTRY InLoadOrderModuleList; 7 LIST_ENTRY InMemoryOrderModuleList; 8 LIST_ENTRY InInitializationOrderModuleList; 9 10 } PEB_LDR_DATA, *PPEB_LDR_DATA;
_LDR_DATA_TABLE_ENTRY 结构体:
1 typedef struct _LDR_DATA_TABLE_ENTRY 2 { 3 4 LIST_ENTRY InLoadOrderLinks; 5 LIST_ENTRY InMemoryOrderLinks; 6 LIST_ENTRY InInitializationOrderLinks; 7 PVOID DllBase; 8 PVOID EntryPoint; 9 ULONG SizeOfImage; 10 UNICODE_STRING FullDllName; 11 UNICODE_STRING BaseDllName; 12 ULONG Flags; 13 USHORT LoadCount; 14 USHORT TlsIndex; 15 union 16 { 17 LIST_ENTRY HashLinks; 18 struct 19 { 20 PVOID SectionPointer; 21 ULONG CheckSum; 22 }; 23 }; 24 ULONG TimeDateStamp; 25 26 } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
PEB 的0x0C偏移为 _PEB_LDR_DATA 结构体。
通过 _PEB_LDR_DATA 结构体可遍历进程加载模块,代码如下:
1 VOID GetPebModule() 2 { 3 PBYTE pPeb; 4 PPEB_LDR_DATA pLdr; 5 PLDR_DATA_TABLE_ENTRY pLdrData; 6 7 __asm 8 { 9 MOV EAX, FS:[0x18] 10 MOV EAX, [EAX + 0x30] 11 12 MOV pPeb, EAX 13 } 14 15 pLdr = (PPEB_LDR_DATA)(*(DWORD*)(pPeb + 0x0C)); 16 pLdrData = (PLDR_DATA_TABLE_ENTRY)pLdr->InLoadOrderModuleList.Flink; 17 18 for ( ; (pLdr->InLoadOrderModuleList.Flink) != (pLdrData->InLoadOrderLinks.Flink); ) 19 { 20 wprintf(L"%s\r\n", (pLdrData->FullDllName.Buffer)); 21 pLdrData = (PLDR_DATA_TABLE_ENTRY)(pLdrData->InLoadOrderLinks.Flink); 22 } 23 24 return ; 25 }
结构图: