A forum for reverse engineering, OS internals and malware analysis 

Ask your beginner questions here.
 #27158  by kerpow1
 Thu Nov 05, 2015 9:49 am
Hi, I am trying to list all ways a driver could be located on the system, so far;

ZwQuerySystemInformation
EnumDeviceDrivers
QueryDosDevice
GetDeviceDriverFileName

Discuss
 #27161  by EP_X0FF
 Thu Nov 05, 2015 4:56 pm
kerpow1 wrote:Hi, I am trying to list all ways a driver could be located on the system, so far;

ZwQuerySystemInformation
EnumDeviceDrivers
QueryDosDevice
GetDeviceDriverFileName

Discuss
If you mean loaded drivers then it is NtQuerySystemInformation. PSAPI uses it. QueryDosDevice is used for symbolic links that driver may not have. SCM maintain it own database in the user mode. Driver and device object names can be quered through NtQueryDirectoryObject.

If your plan is hiding your driver then look on Sirefef 2010 edition which uses ObMakeTemporaryObject on it device object to hide presence from object directory and look on TDL3 which utilises more advanced hiding. Best approach - do not use a driver loaded list, symbolic links and device/driver objects. Load your driver, allocate memory and copy payload executive part on it, call it and after this unload your driver. To exchange data and commands between user mode and your piece of kernel code - use section with on the fly session generated name. If your driver uses hooking (splice or simple address change in some kernel structures) - use a small callgates inside available loaded drivers (see Rustock.B as example) to fool simple dump/compare scan. I would also suggest a dynamic relocation of your piece of code -> for example your rootkit worked for a few minutes and then it relocated itself to a new memory address, removing footprints. To survive reboot/reset - install yourself in registry under randomly named entry. Your software should handle the situation when your rootkit is already loaded -> for example check presence of communication channel. Rootkit should be able to unload itself by request. Unloading drivers is unsafe, unloading rootkits is x2 unsafe. Remember that everything this is a perversion and BSOD-generation friendly.
 #27172  by Brock
 Fri Nov 06, 2015 11:50 pm
@Kerpow1,

The most common ways from a driver to detect "loaded" drivers are to enumerate PsLoadedModuleList, query object directory (device and driver), scanning pool memory for signatures of the object etc. You can also do something like this, but if the ObjectType field is modified it's pretty easy to fool such detection schemes. A lot more validation would be required to prevent BSODs and false positives
Code: Select all
ZwQuerySystemInformation(SYSTEM_BASIC_INFORMATION)
Iterate MmSystemRangeStart -> NumberOfPhysicalPages * PhysicalPageSize
MmGetPhysicalAddress() -> MmGetVirtualForPhysical()
hdr = OBJECT_TO_OBJECT_HEADER(validAddress);
if (hdr->ObjectType == *IoDeviceObjectType) 
 {
   pDrvObj = ((PDEVICE_OBJECT)validAddress)->DriverObject;
 }
else
 if (hdr->ObjectType == *IoDriverObjectType)
 {
   pDrvObj = (PDRIVER_OBJECT)validAddress;
 }
 #27185  by Carlbyte
 Sat Nov 07, 2015 2:10 pm
FLink = PLIST_ENTRY(DRIVER_SECTION)->FLink
BLink = PLIST_ENTRY(DRIVER_SECTION)->BLink
PKERNEL_LDR_DATA_TABLE_ENTRY(FLink)->FullDllName
...

I think that uses some kind of callback or hook and generate your own list starting from the Windows boot.
 #27189  by Brock
 Sat Nov 07, 2015 6:09 pm
Another method is to enable the FLG_MAINTAIN_OBJECT_TYPELIST flag in NtGlobalFlags (requires reboot IIRC) and scan IoDriverObjectType->TypeList and IoDeviceObjectType->TypeList directly
 #27608  by Brock
 Sun Jan 10, 2016 9:37 pm
driverquery.exe command line which seems to rely on something else not listed here - to be confirmed
driverquery just uses WMI and inside WMI provider host (wmiprvse.exe) a call to advapi32.dll!EnumServiceStatus() is made. There's no magic to it. Since driverquery only lists services through SCM driverquery will not show driver loaded by other means such as ZwLoadDriver. driverquery should be renamed to servicequery :lol:

Image