Windows Process Internals: A few Concepts to know before jumping on Memory Forensics [Part 3] – Journey in to the PsLoadedModuleList ( Loaded Kernel Modules)
This is the Part-3 of the series of article “Windows Process Internals: A few Concepts to know before jumping on Memory Forensics”. In Part-1, we saw that how _EPROCESS stores the information about the active processes on the system and how we can traverse through all the processes using live kernel debugger. Volatility Plugins like pslist and pstree use _EPROCESS memory structures to fetch the information about the active processes on the system. In Part-2, we saw that how _PEB stores information about the loaded modules (dlls) and how to traverse through various lists that stores information about the loaded modules. Volatility Plugin like dlllist and ldrmodules use _PEB memory structures of the process to fetch the information about the loaded dlls.
In this part-3, we will see how memory stores the information about the loaded modules (kernel drivers) and how to traverse through the list of the loaded modules/drivers to fetch all the loaded drivers on the system.
To track the loaded kernel modules on the system, the first thing we need to get hold of is PsLoadedModuleList which is one of the fields of KDBG (Kernel Debugger). PsLoadedModuleList points to the doubly linked list. This doubly LinkedList points to the KLDR_DATA_TABLE_ENTRY structures that holds the metadata/information about the loaded kernel modules. The first and last node of the LinkedList points back to the PsLoadedModuleList. Please look at the following diagram to get a better understanding of the verbiage above.
Volatility plugin “modules” and any other tool that uses Windows API will traverse through this doubly LinkedList and fetch the information about the loaded kernel modules. This list arranges its nodes based on the order of module loading in to the memory. Hence, typically first 2 entries of the list would be ntoskrnl.exe and hal.dll (as shown in the diagram).
Now, let us use, kernel debugger and go through this doubly linked list.
First step is to identify the PsLoadedModuleList pointer.
Now, we have a pointer to the head of the doubly LinkedList ( _LIST_ENTRY structure) that points to the module metadata structure (_KLDR_DATA_TABLE_ENTRY). Let us enumerate the _LIST_ENTRY to see where it is pointing to.
We have got our head of the list which is seating at 0xffffdb84`c4679570. The structure at this pointer is KLDR_DATA_ENTRY_TABLE. Let us enumerate it and see which is this module.
As expected, it is ntoskrnl.exe. Please note that it shows the fullpath on the disk for the loaded module.
Let us look at the next entry (should be hal.dll) in the list. To get to the hal.dll metadata structure, we need to look at the FLINK of InLoadOrderLinks field in the first metadata entry (for ntoskrnl.exe).
As expected, it is a structure for hal.dll.
Finally, let us traverse through the entire list to fetch the all loaded kernel modules in the memory. We can pickup any reference pointer and traverse from there, we will pick up the pointer to hal.dll and traverse from there – ntoskrnl.exe should be listed last in the output. Let us see.
As you can see, we started from hal.dll and ended up at the ntoskrnl.exe and listed down all the loaded modules by traversing through the doubly LinkedList pointed by PsLoadedModuleList.
That’s it for now, folks !! happy hunting, fellas!!