Skip to content

Commit bd678ea

Browse files
author
Dave Lassalle
committed
#816 - fix cmdscan
1 parent 9d98ab9 commit bd678ea

File tree

2 files changed

+75
-41
lines changed

2 files changed

+75
-41
lines changed

volatility3/framework/plugins/windows/cmdscan.py

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,17 @@
1414
from volatility3.framework.layers import scanners
1515
from volatility3.framework.objects import utility
1616
from volatility3.framework.renderers import format_hints
17-
from volatility3.plugins.windows import pslist, vadinfo, info, verinfo, consoles
18-
from volatility3.plugins.windows.registry import hivelist
17+
from volatility3.plugins.windows import pslist, consoles
1918

2019

21-
try:
22-
import capstone
23-
24-
has_capstone = True
25-
except ImportError:
26-
has_capstone = False
27-
2820
vollog = logging.getLogger(__name__)
2921

3022

3123
class CmdScan(interfaces.plugins.PluginInterface):
3224
"""Looks for Windows Command History lists"""
3325

3426
_required_framework_version = (2, 4, 0)
27+
_version = (1, 0, 0)
3528

3629
@classmethod
3730
def get_requirements(cls):
@@ -46,7 +39,7 @@ def get_requirements(cls):
4639
name="pslist", component=pslist.PsList, version=(2, 0, 0)
4740
),
4841
requirements.PluginRequirement(
49-
name="hivelist", plugin=hivelist.HiveList, version=(1, 0, 0)
42+
name="consoles", plugin=consoles.Consoles, version=(1, 0, 0)
5043
),
5144
requirements.BooleanRequirement(
5245
name="no_registry",
@@ -70,7 +63,7 @@ def get_filtered_vads(
7063
size_filter: Optional[int] = 0x40000000,
7164
) -> List[Tuple[int, int]]:
7265
"""
73-
Returns vads of a process with smaller than size_filter
66+
Returns vads of a process with size smaller than size_filter
7467
7568
Args:
7669
conhost_proc: the process object for conhost.exe
@@ -114,12 +107,10 @@ def get_command_history(
114107
115108
Returns:
116109
The conhost process object, the command history structure, a dictionary of properties for
117-
that command historyn structure.
110+
that command history structure.
118111
"""
119112

120-
conhost_symbol_table = consoles.Consoles.create_conhost_symbol_table(
121-
context, kernel_layer_name, kernel_table_name, config_path
122-
)
113+
conhost_symbol_table = None
123114

124115
for conhost_proc, proc_layer_name in consoles.Consoles.find_conhost_proc(procs):
125116
if not conhost_proc:
@@ -143,11 +134,22 @@ def get_command_history(
143134

144135
proc_layer = context.layers[proc_layer_name]
145136

137+
if conhost_symbol_table is None:
138+
conhost_symbol_table = consoles.Consoles.create_conhost_symbol_table(
139+
context,
140+
kernel_layer_name,
141+
kernel_table_name,
142+
config_path,
143+
proc_layer_name,
144+
conhostexe_base,
145+
)
146+
146147
conhost_module = context.module(
147148
conhost_symbol_table, proc_layer_name, offset=conhostexe_base
148149
)
149150

150151
sections = cls.get_filtered_vads(conhost_proc)
152+
found_history_for_proc = False
151153
# scan for potential _COMMAND_HISTORY structures by using the CommandHistorySize
152154
for max_history_value in max_history:
153155
max_history_bytes = struct.pack("H", max_history_value)
@@ -258,7 +260,12 @@ def get_command_history(
258260
f"reading {command_history} encountered exception {e}"
259261
)
260262

261-
yield conhost_proc, command_history, command_history_properties
263+
if command_history and command_history_properties:
264+
found_history_for_proc = True
265+
yield conhost_proc, command_history, command_history_properties
266+
267+
if not found_history_for_proc:
268+
yield conhost_proc, command_history or None, []
262269

263270
def _generator(
264271
self, procs: Generator[interfaces.objects.ObjectInterface, None, None]
@@ -276,19 +283,18 @@ def _generator(
276283
no_registry = self.config.get("no_registry")
277284

278285
if no_registry is False:
279-
max_history, _max_buffers = (
280-
consoles.Consoles.get_console_settings_from_registry(
281-
self.context,
282-
self.config_path,
283-
kernel.layer_name,
284-
kernel.symbol_table_name,
285-
max_history,
286-
[],
287-
)
286+
max_history, _ = consoles.Consoles.get_console_settings_from_registry(
287+
self.context,
288+
self.config_path,
289+
kernel.layer_name,
290+
kernel.symbol_table_name,
291+
max_history,
292+
[],
288293
)
289294

290295
vollog.debug(f"Possible CommandHistorySize values: {max_history}")
291296

297+
proc = None
292298
for (
293299
proc,
294300
command_history,
@@ -302,13 +308,14 @@ def _generator(
302308
max_history,
303309
):
304310
process_name = utility.array_to_string(proc.ImageFileName)
311+
process_pid = proc.UniqueProcessId
305312

306313
if command_history and command_history_properties:
307314
for command_history_property in command_history_properties:
308315
yield (
309316
command_history_property["level"],
310317
(
311-
proc.UniqueProcessId,
318+
process_pid,
312319
process_name,
313320
format_hints.Hex(command_history.vol.offset),
314321
command_history_property["name"],
@@ -322,6 +329,25 @@ def _generator(
322329
str(command_history_property["data"]),
323330
),
324331
)
332+
else:
333+
yield (
334+
0,
335+
(
336+
process_pid,
337+
process_name,
338+
(
339+
format_hints.Hex(command_history.vol.offset)
340+
if command_history
341+
else renderers.NotApplicableValue()
342+
),
343+
"_COMMAND_HISTORY",
344+
renderers.NotApplicableValue(),
345+
"History Not Found",
346+
),
347+
)
348+
349+
if proc is None:
350+
vollog.warn("No conhost.exe processes found.")
325351

326352
def _conhost_proc_filter(self, proc):
327353
"""

volatility3/framework/plugins/windows/consoles.py

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,19 @@
1717
from volatility3.framework.objects import utility
1818
from volatility3.framework.renderers import format_hints
1919
from volatility3.framework.symbols import intermed
20-
from volatility3.framework.symbols.windows import pdbutil
2120
from volatility3.framework.symbols.windows.extensions import pe, consoles
22-
from volatility3.plugins.windows import pslist, vadinfo, info, verinfo
21+
from volatility3.plugins.windows import pslist, info, verinfo
2322
from volatility3.plugins.windows.registry import hivelist
2423

2524

26-
try:
27-
import capstone
28-
29-
has_capstone = True
30-
except ImportError:
31-
has_capstone = False
32-
3325
vollog = logging.getLogger(__name__)
3426

3527

3628
class Consoles(interfaces.plugins.PluginInterface):
3729
"""Looks for Windows console buffers"""
3830

3931
_required_framework_version = (2, 4, 0)
32+
_version = (1, 0, 0)
4033

4134
@classmethod
4235
def get_requirements(cls):
@@ -53,9 +46,6 @@ def get_requirements(cls):
5346
requirements.VersionRequirement(
5447
name="verinfo", component=verinfo.VerInfo, version=(1, 0, 0)
5548
),
56-
requirements.VersionRequirement(
57-
name="pdbutil", component=pdbutil.PDBUtility, version=(1, 0, 0)
58-
),
5949
requirements.PluginRequirement(
6050
name="hivelist", plugin=hivelist.HiveList, version=(1, 0, 0)
6151
),
@@ -443,6 +433,7 @@ def get_console_info(
443433
conhost_symbol_table, proc_layer_name, offset=conhostexe_base
444434
)
445435

436+
found_console_info_for_proc = False
446437
# scan for potential _CONSOLE_INFORMATION structures by using the CommandHistorySize
447438
for max_history_value in max_history:
448439
max_history_bytes = struct.pack("H", max_history_value)
@@ -790,7 +781,12 @@ def get_console_info(
790781
)
791782
continue
792783

793-
yield conhost_proc, console_info, console_properties
784+
if console_info and console_properties:
785+
found_console_info_for_proc = True
786+
yield conhost_proc, console_info, console_properties
787+
788+
if not found_console_info_for_proc:
789+
yield conhost_proc, console_info or None, []
794790

795791
@classmethod
796792
def get_console_settings_from_registry(
@@ -903,8 +899,20 @@ def _generator(
903899
),
904900
)
905901
else:
906-
vollog.warn(
907-
f"_CONSOLE_INFORMATION not found for {process_name} with pid {process_pid}."
902+
yield (
903+
0,
904+
(
905+
process_pid,
906+
process_name,
907+
(
908+
format_hints.Hex(console_info.vol.offset)
909+
if console_info
910+
else renderers.NotApplicableValue()
911+
),
912+
"_CONSOLE_INFORMATION",
913+
renderers.NotApplicableValue(),
914+
"Console Information Not Found",
915+
),
908916
)
909917

910918
if proc is None:

0 commit comments

Comments
 (0)