Skip to content

Commit ebf2d6f

Browse files
committed
Windows: Fix devicetree traversal
Previously, the attached devices were being traversed once depth-wise, but the horizontal levels of the device tree were not being properly traversed, leading to tons of missing device entries. This fixes the issue by implementing a recursive staticmethod for properly descending + enumerating devices on each level of the tree.
1 parent 701ad1a commit ebf2d6f

File tree

1 file changed

+60
-57
lines changed

1 file changed

+60
-57
lines changed

volatility3/framework/plugins/windows/devicetree.py

+60-57
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
#
44

55
import logging
6+
from typing import Iterator, List, Set, Tuple
67

7-
from typing import Iterator, List, Tuple
8-
9-
from volatility3.framework import constants, renderers, exceptions, interfaces
8+
from volatility3.framework import constants, exceptions, interfaces, renderers
109
from volatility3.framework.configuration import requirements
1110
from volatility3.framework.renderers import format_hints
11+
from volatility3.framework.symbols.windows.extensions import DEVICE_OBJECT
1212
from volatility3.plugins.windows import driverscan
1313

1414
DEVICE_CODES = {
@@ -102,7 +102,7 @@ def _generator(self) -> Iterator[Tuple]:
102102
):
103103
try:
104104
try:
105-
driver_name = driver.get_driver_name()
105+
driver_name = driver.DriverName.get_string()
106106
except (ValueError, exceptions.InvalidAddressException):
107107
vollog.log(
108108
constants.LOGLEVEL_VVVV,
@@ -124,59 +124,20 @@ def _generator(self) -> Iterator[Tuple]:
124124

125125
# Scan to get the device information of driver.
126126
for device in driver.get_devices():
127-
try:
128-
device_name = device.get_device_name()
129-
except (ValueError, exceptions.InvalidAddressException):
130-
vollog.log(
131-
constants.LOGLEVEL_VVVV,
132-
f"Failed to get Device name : {device.vol.offset:x}",
133-
)
134-
device_name = renderers.UnparsableValue()
135-
136-
device_type = DEVICE_CODES.get(device.DeviceType, "UNKNOWN")
137-
138-
yield (
139-
1,
140-
(
141-
format_hints.Hex(device.vol.offset),
142-
"DEV",
143-
driver_name,
144-
device_name,
145-
renderers.NotApplicableValue(),
146-
device_type,
147-
),
148-
)
149-
150-
# Scan to get the attached devices information of device.
151-
for level, attached_device in enumerate(
152-
device.get_attached_devices(), start=2
153-
):
154-
try:
155-
device_name = attached_device.get_device_name()
156-
except (ValueError, exceptions.InvalidAddressException):
157-
vollog.log(
158-
constants.LOGLEVEL_VVVV,
159-
f"Failed to get Attached Device Name: {attached_device.vol.offset:x}",
160-
)
161-
device_name = renderers.UnparsableValue()
162-
163-
attached_device_driver_name = (
164-
attached_device.DriverObject.DriverName.get_string()
165-
)
166-
attached_device_type = DEVICE_CODES.get(
167-
attached_device.DeviceType, "UNKNOWN"
168-
)
169-
170-
yield (
171-
level,
172-
(
173-
format_hints.Hex(attached_device.vol.offset),
174-
"ATT",
175-
driver_name,
176-
device_name,
177-
attached_device_driver_name,
178-
attached_device_type,
179-
),
127+
for level, (
128+
offset,
129+
drv_name,
130+
dev_name,
131+
att_drv_name,
132+
dev_typ,
133+
) in self._traverse_device_stack(device, driver_name, 1):
134+
yield level, (
135+
offset,
136+
"DEV" if level == 1 else "ATT",
137+
drv_name,
138+
dev_name,
139+
att_drv_name,
140+
dev_typ,
180141
)
181142

182143
except exceptions.InvalidAddressException:
@@ -186,6 +147,48 @@ def _generator(self) -> Iterator[Tuple]:
186147
)
187148
continue
188149

150+
@staticmethod
151+
def _traverse_device_stack(
152+
device: DEVICE_OBJECT, driver_name: str, level: int, seen: Set[int] = set()
153+
) -> Iterator[Tuple]:
154+
while device and device.vol.offset not in seen:
155+
seen.add(device.vol.offset)
156+
try:
157+
device_name = device.get_device_name()
158+
except (ValueError, exceptions.InvalidAddressException):
159+
vollog.log(
160+
constants.LOGLEVEL_VVVV,
161+
f"Failed to get Device name : {device.vol.offset:x}",
162+
)
163+
device_name = renderers.UnparsableValue()
164+
165+
device_type = DEVICE_CODES.get(device.DeviceType, "UNKNOWN")
166+
167+
att_drv_name = device.DriverObject.DriverName.get_string()
168+
169+
yield (
170+
level,
171+
(
172+
format_hints.Hex(device.vol.offset),
173+
driver_name,
174+
device_name,
175+
att_drv_name,
176+
device_type,
177+
),
178+
)
179+
try:
180+
attached = device.AttachedDevice.dereference()
181+
yield from DeviceTree._traverse_device_stack(
182+
attached, driver_name, level + 1, seen
183+
)
184+
except exceptions.InvalidAddressException:
185+
pass
186+
187+
try:
188+
device = device.NextDevice.dereference()
189+
except exceptions.InvalidAddressException:
190+
pass
191+
189192
def run(self) -> renderers.TreeGrid:
190193
return renderers.TreeGrid(
191194
[

0 commit comments

Comments
 (0)