DLL Enumeration

Enumerating Loaded DLLs from PEB Structure

A processes PEB structure contains a linked list of all loaded DLL's. This struct is called: PEB_LDR_DATA

typedef struct _PEB_LDR_DATA {
  BYTE       Reserved1[8];
  PVOID      Reserved2[3];
  LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

The LIST_ENTRY: NOTE: Each item in the list is a pointer to an LDR_DATA_TABLE_ENTRY structure.

typedef struct _LIST_ENTRY {
   struct _LIST_ENTRY *Flink;
   struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;
  • Flink: Pointer to the first entry in the list. (The first entry is the running process example.exe)

  • Blink: Pointer to the last entry in the list.

The LDR_DATA_TABLE_ENTRY structure is defined as follows:

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;

Example:

PPEB pPeb = (PPEB)__readgsqword(0x60);

PLDR_DATA_TABLE_ENTRY pFirst = (PLDR_DATA_TABLE_ENTRY )pPeb->Ldr->InMemoryOrderModuleList.Flink;
PLDR_DATA_TABLE_ENTRY pSecond = (PLDR_DATA_TABLE_ENTRY )pPeb->Ldr->InMemoryOrderModuleList.Flink->Flink;

wprintf(L"First Entry %ls\nSecond Entry: %ls", pFirst->FullDllName.Buffer, pSecond->FullDllName.Buffer);

NOTE: The second entry will always be ntdll.dll since it's the first DLL that is loaded into a process.

Last updated