Created
May 9, 2015 10:09
-
-
Save Spl3en/9c0ea329bb7878df9b9b to your computer and use it in GitHub Desktop.
Get current process modules from PEB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <subauth.h> | |
#include <stdio.h> | |
/* Windows structures */ | |
typedef struct _PEB_LDR_DATA { | |
BYTE Reserved1[8]; | |
PVOID Reserved2[3]; | |
LIST_ENTRY InMemoryOrderModuleList; | |
} PEB_LDR_DATA, *PPEB_LDR_DATA; | |
typedef struct _RTL_USER_PROCESS_PARAMETERS { | |
UCHAR Reserved1[16]; | |
PVOID Reserved2[10]; | |
UNICODE_STRING ImagePathName; | |
UNICODE_STRING CommandLine; | |
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; | |
typedef struct _LDR_DATA_TABLE_ENTRY { | |
LIST_ENTRY InLoadOrderLinks; | |
LIST_ENTRY InMemoryOrderModuleList; | |
LIST_ENTRY InInitializationOrderModuleList; | |
PVOID DllBase; | |
PVOID EntryPoint; | |
ULONG SizeOfImage; | |
UNICODE_STRING FullDllName; | |
UNICODE_STRING BaseDllName; | |
ULONG Flags; | |
USHORT LoadCount; | |
USHORT TlsIndex; | |
union { | |
LIST_ENTRY HashLinks; | |
struct | |
{ | |
PVOID SectionPointer; | |
ULONG CheckSum; | |
}; | |
}; | |
union { | |
ULONG TimeDateStamp; | |
PVOID LoadedImports; | |
}; | |
PVOID EntryPointActivationContext; | |
PVOID PatchInformation; | |
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; | |
typedef struct _PEB { | |
BYTE Reserved1[2]; | |
BYTE BeingDebugged; | |
BYTE Reserved2[1]; | |
PVOID Reserved3[2]; | |
PPEB_LDR_DATA Ldr; | |
PRTL_USER_PROCESS_PARAMETERS ProcessParameters; | |
BYTE Reserved4[104]; | |
PVOID Reserved5[52]; | |
PVOID PostProcessInitRoutine; | |
BYTE Reserved6[128]; | |
PVOID Reserved7[1]; | |
ULONG SessionId; | |
} PEB, *PPEB; | |
typedef struct _PROCESS_BASIC_INFORMATION { | |
PVOID ExitStatus; | |
PPEB PebBaseAddress; | |
PVOID Reserved2[2]; | |
ULONG_PTR UniqueProcessId; | |
PVOID Reserved3; | |
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; | |
typedef enum _PROCESSINFOCLASS { | |
ProcessBasicInformation | |
// We don't need the others | |
} PROCESSINFOCLASS; | |
// MODULE_ENTRY contains basic information about a module | |
typedef struct _MODULE_ENTRY { | |
UNICODE_STRING BaseName; // BaseName of the module | |
UNICODE_STRING FullName; // FullName of the module | |
ULONG SizeOfImage; // Size in bytes of the module | |
PVOID BaseAddress; // Base address of the module | |
PVOID EntryPoint; // Entrypoint of the module | |
} MODULE_ENTRY, *PMODULE_ENTRY; | |
// MODULE_INFORMATION_TABLE contains basic information about all the modules of a given process | |
typedef struct _MODULE_INFORMATION_TABLE { | |
ULONG Pid; // PID of the process | |
ULONG ModuleCount; // Modules count for the above pointer | |
PMODULE_ENTRY Modules; // Pointer to 0...* modules | |
} MODULE_INFORMATION_TABLE, *PMODULE_INFORMATION_TABLE; | |
typedef NTSTATUS (NTAPI *pfnNtQueryInformationProcess)( | |
IN HANDLE ProcessHandle, | |
IN PROCESSINFOCLASS ProcessInformationClass, | |
OUT PVOID ProcessInformation, | |
IN ULONG ProcessInformationLength, | |
OUT PULONG ReturnLength OPTIONAL | |
); | |
PVOID | |
QueryProcessInformation ( | |
IN HANDLE Process, | |
IN PROCESSINFOCLASS ProcessInformationClass, | |
IN DWORD ProcessInformationLength | |
) { | |
PPROCESS_BASIC_INFORMATION pProcessInformation = NULL; | |
pfnNtQueryInformationProcess gNtQueryInformationProcess; | |
ULONG ReturnLength = 0; | |
NTSTATUS Status; | |
HMODULE hNtDll; | |
if (!(hNtDll = LoadLibrary ("ntdll.dll"))) { | |
printf ("Cannot load ntdll.dll.\n"); | |
return NULL; | |
} | |
if (!(gNtQueryInformationProcess = (pfnNtQueryInformationProcess) GetProcAddress (hNtDll, "NtQueryInformationProcess"))) { | |
printf ("Cannot load NtQueryInformationProcess.\n"); | |
return NULL; | |
} | |
// Allocate the memory for the requested structure | |
if ((pProcessInformation = malloc (ProcessInformationLength)) == NULL) { | |
printf ("ExAllocatePoolWithTag failed.\n"); | |
return NULL; | |
} | |
// Fill the requested structure | |
if (!NT_SUCCESS (Status = gNtQueryInformationProcess (Process, ProcessInformationClass, pProcessInformation, ProcessInformationLength, &ReturnLength))) { | |
printf ("NtQueryInformationProcess should return NT_SUCCESS (Status = %#x).\n", Status); | |
free (pProcessInformation); | |
return NULL; | |
} | |
// Check the requested structure size with the one returned by NtQueryInformationProcess | |
if (ReturnLength != ProcessInformationLength) { | |
printf ("Warning : NtQueryInformationProcess ReturnLength is different than ProcessInformationLength\n"); | |
return NULL; | |
} | |
return pProcessInformation; | |
} | |
PPEB | |
GetCurrentPebProcess ( | |
void | |
) { | |
PPROCESS_BASIC_INFORMATION pProcessInformation = NULL; | |
DWORD ProcessInformationLength = sizeof (PROCESS_BASIC_INFORMATION); | |
HANDLE Process = GetCurrentProcess(); | |
PPEB pPeb = NULL; | |
// ProcessBasicInformation returns information about the PebBaseAddress | |
if ((pProcessInformation = QueryProcessInformation (Process, ProcessBasicInformation, ProcessInformationLength)) == NULL) { | |
printf ("Handle=%x : QueryProcessInformation failed.\n", Process); | |
return NULL; | |
} | |
// Check the correctness of the value returned | |
if (pProcessInformation->PebBaseAddress == NULL) { | |
printf ("Handle=%x : PEB address cannot be found.\n", Process); | |
free (pProcessInformation); | |
return NULL; | |
} | |
pPeb = pProcessInformation->PebBaseAddress; | |
// Cleaning | |
free (pProcessInformation); | |
return pPeb; | |
} | |
PMODULE_INFORMATION_TABLE | |
CreateModuleInformation ( | |
IN PPEB pPeb | |
) { | |
ULONG Count = 0; | |
ULONG CurCount = 0; | |
PLIST_ENTRY pEntry = NULL; | |
PLIST_ENTRY pHeadEntry = NULL; | |
PPEB_LDR_DATA pLdrData = NULL; | |
PMODULE_ENTRY CurModule = NULL; | |
PLDR_DATA_TABLE_ENTRY pLdrEntry = NULL; | |
PMODULE_INFORMATION_TABLE pModuleInformationTable = NULL; | |
pLdrData = pPeb->Ldr; | |
pHeadEntry = &pLdrData->InMemoryOrderModuleList; | |
// Count user modules : iterate through the entire list | |
pEntry = pHeadEntry->Flink; | |
while (pEntry != pHeadEntry) { | |
Count++; | |
pEntry = pEntry->Flink; | |
} | |
// Allocate a MODULE_INFORMATION_TABLE | |
if ((pModuleInformationTable = malloc (sizeof (MODULE_INFORMATION_TABLE))) == NULL) { | |
printf ("Cannot allocate a MODULE_INFORMATION_TABLE.\n"); | |
return NULL; | |
} | |
// Allocate the correct amount of memory depending of the modules count | |
if ((pModuleInformationTable->Modules = malloc (Count * sizeof (MODULE_ENTRY))) == NULL) { | |
printf ("Cannot allocate a MODULE_INFORMATION_TABLE.\n"); | |
return NULL; | |
} | |
// Fill the basic information of MODULE_INFORMATION_TABLE | |
pModuleInformationTable->ModuleCount = Count; | |
// Fill all the modules information in the table | |
pEntry = pHeadEntry->Flink; | |
while (pEntry != pHeadEntry) | |
{ | |
// Retrieve the current MODULE_ENTRY | |
CurModule = &pModuleInformationTable->Modules[CurCount++]; | |
// Retrieve the current LDR_DATA_TABLE_ENTRY | |
pLdrEntry = CONTAINING_RECORD (pEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList); | |
// Fill the MODULE_ENTRY with the LDR_DATA_TABLE_ENTRY information | |
RtlCopyMemory (&CurModule->BaseName, &pLdrEntry->BaseDllName, sizeof (CurModule->BaseName)); | |
RtlCopyMemory (&CurModule->FullName, &pLdrEntry->FullDllName, sizeof (CurModule->FullName)); | |
RtlCopyMemory (&CurModule->SizeOfImage, &pLdrEntry->SizeOfImage, sizeof (CurModule->SizeOfImage)); | |
RtlCopyMemory (&CurModule->BaseAddress, &pLdrEntry->DllBase, sizeof (CurModule->BaseAddress)); | |
RtlCopyMemory (&CurModule->EntryPoint, &pLdrEntry->EntryPoint, sizeof (CurModule->EntryPoint)); | |
// Iterate to the next entry | |
pEntry = pEntry->Flink; | |
} | |
return pModuleInformationTable; | |
} | |
PMODULE_INFORMATION_TABLE | |
QueryModuleInformationProcess ( | |
void | |
) { | |
PPEB pPeb = NULL; | |
PMODULE_INFORMATION_TABLE pModuleInformationTable = NULL; | |
// Read the PEB from the current process | |
if ((pPeb = GetCurrentPebProcess ()) == NULL) { | |
printf ("GetPebCurrentProcess failed.\n"); | |
return NULL; | |
} | |
// Convert the PEB into a MODULE_INFORMATION_TABLE | |
if ((pModuleInformationTable = CreateModuleInformation (pPeb)) == NULL) { | |
printf ("CreateModuleInformation failed."); | |
return NULL; | |
} | |
return pModuleInformationTable; | |
} | |
int main (int argc, char **argv) | |
{ | |
// Retrieve modules from PEB | |
MODULE_INFORMATION_TABLE * moduleTable = QueryModuleInformationProcess (); | |
if (!moduleTable) { | |
printf ("Module table not found.\n"); | |
return -1; | |
} | |
// Iterate through modules table | |
size_t moduleIndex; | |
for (moduleIndex = 0; moduleIndex < moduleTable->ModuleCount; moduleIndex++) | |
{ | |
MODULE_ENTRY *moduleEntry = &moduleTable->Modules[moduleIndex]; | |
PVOID baseAddress = moduleEntry->BaseAddress; | |
DWORD sizeOfModule = (DWORD) moduleEntry->SizeOfImage; | |
printf ("%-15S : 0x%08x -> 0x%08x (%S)\n", moduleEntry->BaseName.Buffer, baseAddress, baseAddress + sizeOfModule, moduleEntry->FullName.Buffer); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment