Find Kernel Module Address
Last updated
Last updated
Sometimes we need to get the base address of some kernel modules, such as ntoskrnl, win32k and other device driver modules. So far as I know there are three methods we can use to make it
MS has an undocumented function named ZwQuerySystemInformation
which can obtain many information about the system. Its declaration is as below( ):
The first parameter SystemInformationClass
indicates what information the function should query. Here we pass SystemModuleInformation
as argument to get information about all kernel modules.
First we pass 0 to SystemInformation
buffer to get accurate size of this information, allocate memory respectively and query system information.
there are two structure we need to use to extract the specific information:
as you can see, Module
field in _SYSTEM_MODULE_INFORMATION
is a list of _SYSTEM_MODULE_ENTRY
in which each element represents a information block of corresponding module.
Generally the ntoskrnl module is always the first entry whose base address is pMods->Module[0].ImageBase
. For other modules we can loop through the list and compare each entry's FullPathName, with our target module's path to get target module's base address.
( Note that the path is "\Systemroot\system32\module-name ").
Alternatively, if you have some data or function address belonging to a certain module, we can use it to get the module base address.
To use this function, we must call function AuxKlibInitialize
first (which is needed in any function call in Aux_Klib )
Then just like ZwQuerySystemInformation
, we need to get specific size of the information buffer.
Allocate memory for buffer
Finally query modules information
After that we get a list of AUX_MODULE_EXTENDED_INFO
structures, declared as:
So we can use these information to find any specified system module.
There is a LIST_ENTRY
data structure in kernel named PsLoadedModuleList
, which is the head of a list of information blocks about all kernel modules. Each block has a structure defined as below:
The first field InLoadOrderLinks
of every block is linked to the list, so we can traverse the list and for a block retrieve some information like FullDllName
or BaseDllName
, then compare them with our target module and get its base address.
This structure is the head of the system module list, and the ntoskrnl module is always the first entry in the list, so we can find ntoskrnl in the list first and trace back to find PsLoadedModuleList.
First we need to find ntoskrnl 's base address ( well we can use method 1 showed above, and something else will be added here in future)
Then we need to find a breakthrough point into the system modules list. Actually we can use our own driver module to do this ( because it's in the list too).
So the basic idea is to start from the list block of our driver, then traverse the list to find ntoskrnl module and get the list head PsLoadedMouldList at last.
After we find the PsLoadedModuleList, To find any given kernel module we just need to traverse the list at the beginning. Like method 1, we can use either the module name or a address within the module.
Every driver has a name like \Driver\driver-name
, and we can get it's driver object pointer with its name by an undocumented function ObReferenceObjectByName
, declared below:
Well, the parameter ObjectPath
is the driver name we need to specify, AccessMode
needs to be KernelMode
, and ObjectPtr
is used to receive the pointer to _DRIVER_OBJECT
structure of specified driver module. Moreover the parameter ObjectType
indicates which type the object belongs to, here the driver is IoDriverObjectType
( Note this type is undocumented so we need declare it explicitly as below).
Here we use keyboard class driver ( kbdclass.sys) as a example:
After we get the driver object pointer of specified driver, we can retrieve the KLDR_LOAD_TABLE_ENTRY
structure through the DriverSection
field and get some useful information including its base address.
Just like method 1 MS has provided another query function named AuxKlibQueryModuleInformation
which belongs to the lib Aux_Klib
( Note you have to add it to link manually) to query ONLY system module information. This function is declared as below ( ):
In every driver's entry function DriverEntry
, there is a parameter named DriverObject
which has type of PDRIVER_OBJECT
( ). The field DriverSection
with PVOID
type is actually a pointer to the KLDR_LOAD_TABLE_ENTRY
structure stored information of the driver module, which is exactly the block inserted into the system modules list.