Skip to content

Instantly share code, notes, and snippets.

@mspi21
Last active August 9, 2025 22:29
Show Gist options
  • Save mspi21/484e3ad5cdedf9f59dd4410cfb70ece3 to your computer and use it in GitHub Desktop.
Save mspi21/484e3ad5cdedf9f59dd4410cfb70ece3 to your computer and use it in GitHub Desktop.
List loaded modules without any API calls (32-bit PEs only).
#include <cstdio>
#include <windows.h>
#if !defined(_WIN32) || defined(_WIN64)
#error This snippet is only valid for x86 executables!
#endif
typedef struct _UNICODE_STRING {
unsigned __int16 Length;
unsigned __int16 MaximumLength;
wchar_t* Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _PEB_LDR_DATA {
BYTE Reserved1[8];
PVOID Reserved2[3];
LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _LDR_DATA_TABLE_ENTRY {
PVOID Reserved1[2];
LIST_ENTRY InMemoryOrderLinks;
PVOID Reserved2[2];
PVOID DllBase;
PVOID EntryPoint;
PVOID Reserved3;
UNICODE_STRING FullDllName;
BYTE Reserved4[8];
PVOID Reserved5[3];
union {
ULONG CheckSum;
PVOID Reserved6;
};
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
typedef struct _RTL_USER_PROCESS_PARAMETERS {
BYTE Reserved1[16];
PVOID Reserved2[10];
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID Reserved4[3];
PVOID AtlThunkSListPtr;
PVOID Reserved5;
ULONG Reserved6;
PVOID Reserved7;
ULONG Reserved8;
ULONG AtlThunkSListPtr32;
PVOID Reserved9[45];
BYTE Reserved10[96];
PVOID PostProcessInitRoutine;
BYTE Reserved11[128];
PVOID Reserved12[1];
ULONG SessionId;
} PEB, *PPEB;
PPEB GetPebPointer()
{
PPEB pPeb = 0;
__asm {
mov eax, fs:[0x30]
mov pPeb, eax
}
return pPeb;
}
int main()
{
auto pPeb = GetPebPointer();
auto header = &pPeb->Ldr->InMemoryOrderModuleList;
auto entry = pPeb->Ldr->InMemoryOrderModuleList.Flink;
while (entry->Flink != header) {
auto pLdrEntry = reinterpret_cast<PLDR_DATA_TABLE_ENTRY>(entry);
wprintf(L"FullDllName: %s\n", pLdrEntry->FullDllName.Buffer);
wprintf(L"DllBase: %p\n", pLdrEntry->DllBase);
wprintf(L"\n");
entry = entry->Flink;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment