I'm trying to get a list of the loaded modules within my application (pertaining to security/shellcode so please refrain from WINAPI calls). I'm iterating over the PEB->Ldr doubly linked list of modules, but every time I print the DLL's name, it simply prints the name and path of the currently executing application.
In others' code, I've seen that they just case the current LIST_ENTRY
pointer to be a PLDR_DATA_TABLE_ENTRY
and you can directly call FullDllName
that way. However, to actually get the base address, for example, you need to call Reserved2[0]
instead of DllBase
which is understandable due to the fact that the LIST_ENTRY
is 8 bytes into the struct, but it doesn't explain why you can call FullDllName
directly.
Here's an example. Note the return (HMODULE)pLdrDataTableEntry->Reserved2[0];
I'm using Windows 10 x64 in x86 Release Mode with Visual Studio 2015.
void ListModules(void) {
PPEB lpPeb = __readfsdword(0x30);
PPEB_LDR_DATA lpLdr = lpPeb->Ldr;
PLIST_ENTRY lpFirst, lpCurrent;
lpFirst = lpCurrent = lpLdr->InMemoryOrderModuleList.Flink;
do {
PLDR_DATA_TABLE_ENTRY lpDataTable = CONTAINING_RECORD(lpFirst, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
wprintf(L"%s ~ %d ~ 0x%08x\n", lpDataTable->FullDllName.Buffer, lpDataTable->DllBase, (DWORD)lpCurrent);
lpCurrent= lpCurrent ->Flink;
} while (lpCurrent && lpFirst != lpCurrent);
}
The output I receive is just multiple references to the current application name:
C:\Programs\Project\file.exe ~ 2818048 ~ 0x00d53a18
C:\Programs\Project\file.exe ~ 2818048 ~ 0x00d53930
C:\Programs\Project\file.exe ~ 2818048 ~ 0x00d53da8
C:\Programs\Project\file.exe ~ 2818048 ~ 0x00d54078
C:\Programs\Project\file.exe ~ 2818048 ~ 0x00d54a68
C:\Programs\Project\file.exe ~ 2818048 ~ 0x00d54910
C:\Programs\Project\file.exe ~ 2818048 ~ 0x7743fbf4
This is very likely do to MSDN's infamous undocumentation, but how can I resolve this, preferably in a 'standard' way that wouldn't require defining my own structure, although I'm certainly not against it.
Am I not iterating correctly?
look at to this line
but
lpFirst
you not changing in loop ! so and got the same records all time. you need changelpFirst
tolpCurrent
also
lpCurrent
never become the NULL - this is circle list, so condition must bewhile (lpFirst != lpCurrent)
also must be not
but
of course access to this list must be synchronized (
LdrpLoaderLock
critical section) but, if you want anyway ..!! this is not recommended to use !! only for demo/test
but even in shellcode better first got pointers to some api, and then use it. for example
LdrEnumerateLoadedModules
this is not recommendation to use. demo only for OP