Skip to content

Instantly share code, notes, and snippets.

@Spl3en
Created May 9, 2015 10:09
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save Spl3en/9c0ea329bb7878df9b9b to your computer and use it in GitHub Desktop.
Save Spl3en/9c0ea329bb7878df9b9b to your computer and use it in GitHub Desktop.
Get current process modules from PEB
#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