Skip to content

Commit 442f877

Browse files
iMHLv2ikelos
authored andcommitted
refs #197 initial commit of windows.dumpfiles
1 parent 20f4fbf commit 442f877

File tree

2 files changed

+31
-18
lines changed

2 files changed

+31
-18
lines changed

volatility/framework/plugins/windows/dumpfiles.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,4 +242,4 @@ def run(self):
242242

243243
return renderers.TreeGrid(
244244
[("Cache", str), ("FileObject", format_hints.Hex), ("FileName", str), ("Result", str)],
245-
self._generator(procs, offsets))
245+
self._generator(procs, offsets))

volatility/framework/symbols/windows/extensions/__init__.py

100644100755
Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
import datetime
77
import functools
88
import logging
9+
import struct
910
import math
10-
from typing import Iterable, Iterator, Optional, Union, Tuple, List
11+
from typing import Iterable, Iterator, Optional, Union, Dict, Tuple, List
1112

1213
from volatility.framework import constants, exceptions, interfaces, objects, renderers, symbols
1314
from volatility.framework.layers import intel
@@ -30,6 +31,7 @@ def get_time(self):
3031

3132
class MMVAD_SHORT(objects.StructType):
3233
"""A class that represents process virtual memory ranges.
34+
3335
Each instance is a node in a binary tree structure and is pointed to
3436
by VadRoot.
3537
"""
@@ -135,7 +137,6 @@ def get_right_child(self):
135137
return self.Core.VadNode.RightChild
136138
if self.Core.VadNode.has_member("Right"):
137139
return self.Core.VadNode.Right
138-
139140
raise AttributeError("Unable to find the right child member")
140141

141142
def get_left_child(self):
@@ -146,7 +147,6 @@ def get_left_child(self):
146147

147148
elif self.has_member("Left"):
148149
return self.Left
149-
150150
# this is for windows 8 and 10
151151
elif self.has_member("VadNode"):
152152
if self.VadNode.has_member("LeftChild"):
@@ -323,6 +323,7 @@ def get_file_name(self):
323323
class EX_FAST_REF(objects.StructType):
324324
"""This is a standard Windows structure that stores a pointer to an object
325325
but also leverages the least significant bits to encode additional details.
326+
326327
When dereferencing the pointer, we need to strip off the extra bits.
327328
"""
328329

@@ -404,7 +405,6 @@ def file_name_with_device(self) -> Union[str, interfaces.renderers.BaseAbsentVal
404405
pass
405406

406407
return name
407-
408408
def access_string(self):
409409
## Make a nicely formatted ACL string
410410
return (('R' if self.ReadAccess else '-') + ('W' if self.WriteAccess else '-') +
@@ -431,7 +431,6 @@ class ETHREAD(objects.StructType):
431431
def owning_process(self, kernel_layer: str = None) -> interfaces.objects.ObjectInterface:
432432
"""Return the EPROCESS that owns this thread."""
433433
return self.ThreadsProcess.dereference(kernel_layer)
434-
435434
def get_cross_thread_flags(self) -> str:
436435
dictCrossThreadFlags = {
437436
'PS_CROSS_THREAD_FLAGS_TERMINATED': 0,
@@ -666,7 +665,6 @@ def get_vad_root(self):
666665
else:
667666
# windows xp and 2003
668667
return self.VadRoot.dereference().cast("_MMVAD")
669-
670668
def environment_variables(self):
671669
"""Generator for environment variables.
672670
@@ -756,7 +754,6 @@ def to_list(self,
756754
def __iter__(self) -> Iterator[interfaces.objects.ObjectInterface]:
757755
return self.to_list(self.vol.parent.vol.type_name, self.vol.member_name)
758756

759-
760757
class TOKEN(objects.StructType):
761758
"""A class for process etoken object."""
762759

@@ -875,6 +872,7 @@ def get_wait_reason(self) -> str:
875872
37: 'MaximumWaitReason'
876873
}
877874
return dictWaitReason.get(self.WaitReason, renderers.NotApplicableValue())
875+
878876
class CONTROL_AREA(objects.StructType):
879877
"""A class for _CONTROL_AREA structures"""
880878

@@ -984,6 +982,24 @@ class VACB(objects.StructType):
984982

985983
FILEOFFSET_MASK = 0xFFFFFFFFFFFF0000
986984

985+
def is_valid(self, shared_cache_map: interfaces.objects.ObjectInterface) -> bool:
986+
"""Determine if the object is valid."""
987+
try:
988+
layer = self._context.layers[self.vol.layer_name]
989+
990+
# Check if the Overlay member of _VACB is resident. The Overlay member stores information
991+
# about the FileOffset and the ActiveCount. This is just another proactive sanity check.
992+
#if not self.Overlay:
993+
# return False
994+
995+
if not layer.is_valid(self.SharedCacheMap):
996+
return False
997+
998+
# Make sure that the SharedCacheMap member of the VACB points back to the parent object.
999+
return self.SharedCacheMap == shared_cache_map.vol.offset
1000+
except exceptions.InvalidAddressException:
1001+
return False
1002+
9871003
def get_file_offset(self) -> int:
9881004
# The FileOffset member of VACB is used to denote the offset within the file where the
9891005
# view begins. Since all views are 256 KB in size, the bottom 16 bits are used to
@@ -1075,19 +1091,15 @@ def get_available_pages(self) -> List:
10751091
iterval = 0
10761092
while (iterval < full_blocks) and (full_blocks <= 4):
10771093
vacb_obj = self.InitialVacbs[iterval]
1078-
try:
1079-
# Make sure that the SharedCacheMap member of the VACB points back to the parent object.
1080-
if vacb_obj.SharedCacheMap == self.vol.offset:
1081-
self.save_vacb(vacb_obj, vacb_list)
1082-
except exceptions.InvalidAddressException:
1083-
pass
1094+
if vacb_obj.is_valid(shared_cache_map=self):
1095+
self.save_vacb(vacb_obj, vacb_list)
10841096
iterval += 1
10851097

10861098
# We also have to account for the spill over data that is not found in the full blocks.
10871099
# The first case to consider is when the spill over is still in InitialVacbs.
10881100
if (left_over > 0) and (full_blocks < 4):
10891101
vacb_obj = self.InitialVacbs[iterval]
1090-
if vacb_obj.SharedCacheMap == self.vol.offset:
1102+
if vacb_obj.is_valid(shared_cache_map=self):
10911103
self.save_vacb(vacb_obj, vacb_list)
10921104

10931105
# If the file is larger than 1 MB, a seperate VACB index array needs to be allocated.
@@ -1124,7 +1136,7 @@ def get_available_pages(self) -> List:
11241136
continue
11251137

11261138
vacb = vacb_entry.dereference().cast(symbol_table_name + constants.BANG + "_VACB")
1127-
if vacb.SharedCacheMap == self.vol.offset:
1139+
if vacb.is_valid(shared_cache_map=self):
11281140
self.save_vacb(vacb, vacb_list)
11291141

11301142
if left_over > 0:
@@ -1136,7 +1148,7 @@ def get_available_pages(self) -> List:
11361148
return vacb_list
11371149

11381150
vacb = vacb_entry.dereference().cast(symbol_table_name + constants.BANG + "_VACB")
1139-
if vacb.SharedCacheMap == self.vol.offset:
1151+
if vacb.is_valid(shared_cache_map=self):
11401152
self.save_vacb(vacb, vacb_list)
11411153

11421154
# The file is less than 32 MB, so we can stop processing.
@@ -1168,7 +1180,8 @@ def get_available_pages(self) -> List:
11681180

11691181
vacb = vacb_array[counter].dereference().cast(symbol_table_name + constants.BANG + "_VACB")
11701182
if vacb.SharedCacheMap == self.vol.offset:
1171-
self.save_vacb(vacb, vacb_list)
1183+
if vacb.is_valid(shared_cache_map=self):
1184+
self.save_vacb(vacb, vacb_list)
11721185
else:
11731186
# Process the next level of the multi-level array. We set the limit_depth to be
11741187
# the depth of the tree as determined from the size and we initialize the

0 commit comments

Comments
 (0)