Locating modules by name or hash and reading PE headers
This chapter covers finding a loaded module’s base address from the PEB module list, then parsing PE structures in memory (DOS header, NT headers, optional header, export directory).
FindSystemModule-style API
Design a function (name it as your rubric says) that accepts optional UNICODE_STRING* and/or ULONG* hash:
- If name is NULL, a hash must be supplied; otherwise return
ERROR_INVALID_PARAMETER(or equivalent). - Set an internal
bHashOnlyflag and call intoGetModuleBase.
GetModuleBase and the loader lock
GetModuleBase should:
- Resolve the PEB (e.g.
GetPebPtrusing__readgsqword/ TEB). EnterCriticalSection(PebPtr->LoaderLock)before reading loader lists.- Walk
InMemoryOrderModuleList, comparing either:BaseNameHashValueto the supplied hash (RtlCompareMemory), or_wcsicmpon wide name buffers when matching by name.
LeaveCriticalSectionon every path.
Important
Always release the loader lock on all exit paths. Early
returns during debugging must not skipLeaveCriticalSectionor you can deadlock the process.
PE parsing overview (in-memory)
After you have ModuleBase:
- Validate
IMAGE_DOS_SIGNATUREat the base (DOS header). - Use
e_lfanewto locate the NT headers. - Read the file header and optional header (32 vs 64 depends on Machine).
- Locate the export directory via
IMAGE_DIRECTORY_ENTRY_EXPORTand convert RVAs to VAs with a macro such as:
#define RVA2VA(Type, Base, Rva) ((Type)((DWORD_PTR)(Base) + (DWORD_PTR)(Rva)))
Add DumpDosHeader, DumpFileHeader, DumpExports (or similar) as separate functions that print fields you care about. Link imagehlp.lib if you use ImageHlp helpers (ImageRvaToVa, etc.).
Second pass (optional reinforcement)
If your course assigns a second milestone with the same APIs (e.g. hash-only lookup vs name lookup), treat it as practice—same lock rules, same PE steps—rather than a different codebase.
Implement
- Implement lookup by name and/or by hash per rubric.
- Parse and print DOS + file headers (and exports if required).
- Build x64, test against a known module (e.g.
KERNELBASE.dll), commit, and push.