22# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
33#
44
5- from typing import Iterable
5+ from typing import Iterable , Optional , Tuple
66
77from volatility3 .framework import renderers , interfaces , exceptions
88from volatility3 .framework .configuration import requirements
@@ -51,6 +51,10 @@ def scan_drivers(
5151 symbol_table , [b"Dri\xf6 " , b"Driv" ]
5252 )
5353
54+ layer = context .layers [layer_name ]
55+ module = context .module (symbol_table , layer_name , 0 )
56+ driver_start_offset = module .get_type ("_DRIVER_OBJECT" ).relative_child_offset ("DriverStart" )
57+
5458 for result in poolscanner .PoolScanner .generate_pool_scan (
5559 context , layer_name , symbol_table , constraints
5660 ):
@@ -62,15 +66,16 @@ def scan_drivers(
6266 # `DriverStart` is the first member from the beginning of the structure
6367 # of interest to plugins, so if it is not accessible then this instance
6468 # is not useful or usable during analysis
65- try :
66- mem_object .DriverStart
67- except exceptions .InvalidAddressException :
68- continue
69+ # 8 covers this value 32 and 64 bit systems
70+ if layer .is_valid (mem_object .vol .offset + driver_start_offset , 8 ):
6971
70- yield mem_object
72+ # Many/most rootkits zero out their DriverStart member for anti-forensics
73+ # so we accept a driver start that is either 0 or is mapped in kernel memory (the current layer)
74+ if mem_object .DriverStart == 0 or layer .is_valid (mem_object .DriverStart , 8 ):
75+ yield mem_object
7176
7277 @classmethod
73- def get_names_for_driver (cls , driver ):
78+ def get_names_for_driver (cls , driver ) -> Tuple [ Optional [ str ], Optional [ str ], Optional [ str ]] :
7479 """
7580 Convenience method for getting the commonly used
7681 names associated with a driver
@@ -84,17 +89,17 @@ def get_names_for_driver(cls, driver):
8489 try :
8590 driver_name = driver .get_driver_name ()
8691 except (ValueError , exceptions .InvalidAddressException ):
87- driver_name = renderers . NotApplicableValue ()
92+ driver_name = None
8893
8994 try :
9095 service_key = driver .DriverExtension .ServiceKeyName .String
9196 except exceptions .InvalidAddressException :
92- service_key = renderers . NotApplicableValue ()
97+ service_key = None
9398
9499 try :
95100 name = driver .DriverName .String
96101 except exceptions .InvalidAddressException :
97- name = renderers . NotApplicableValue ()
102+ name = None
98103
99104 return driver_name , service_key , name
100105
@@ -106,15 +111,19 @@ def _generator(self):
106111 ):
107112 driver_name , service_key , name = self .get_names_for_driver (driver )
108113
114+ # Prior to #1481, this plugin reported dozens to hundreds of junk drivers per sample
115+ if driver .DriverStart == 0 and not driver_name and not service_key and not name :
116+ continue
117+
109118 yield (
110119 0 ,
111120 (
112121 format_hints .Hex (driver .vol .offset ),
113122 format_hints .Hex (driver .DriverStart ),
114123 format_hints .Hex (driver .DriverSize ),
115- service_key ,
116- driver_name ,
117- name ,
124+ service_key or renderers . NotAvailableValue () ,
125+ driver_name or renderers . NotAvailableValue () ,
126+ name or renderers . NotAvailableValue () ,
118127 ),
119128 )
120129
0 commit comments