diff --git a/development/nlpdtbfinder.py b/development/nlpdtbfinder.py index 0cd20f70b..844aa5906 100644 --- a/development/nlpdtbfinder.py +++ b/development/nlpdtbfinder.py @@ -24,6 +24,7 @@ PAGE_SIZE = 0x1000 PHYS_MASK = 0xfffffffffff PML4_ENTRY_SIZE = int((2 ** 64) / 512) + class PML4EScanner(interfaces.layers.ScannerInterface): overlap = 0x4000 @@ -32,7 +33,7 @@ class PML4EScanner(interfaces.layers.ScannerInterface): # go through each page in the data, look for signs of PML4 for page_offset in range(0, len(data), PAGE_SIZE): - entries = struct.unpack('<512Q', data[page_offset:page_offset+PAGE_SIZE]) + entries = struct.unpack('<512Q', data[page_offset:page_offset + PAGE_SIZE]) valid_entries = [] invalid_count = 0 user_count = 0 @@ -57,7 +58,8 @@ class PML4EScanner(interfaces.layers.ScannerInterface): # print("[%x] inv: %d val: %d" % (data_offset + page_offset, invalid_count, len(valid_entries))) if invalid_count == 0 and len(valid_entries) > 4 and user_count != 0 and supervisor_count != 0: - yield (data_offset + page_offset, valid_entries) + if page_offset < self.chunk_size: + yield (data_offset + page_offset, valid_entries) def find_pt_mapping(ctx, layer_name, entries): @@ -69,6 +71,7 @@ def find_pt_mapping(ctx, layer_name, entries): return False + def find_pd_mapping(ctx, layer_name, entries): for entry in entries: # valid entry? @@ -92,6 +95,7 @@ def find_pd_mapping(ctx, layer_name, entries): return True return False + def find_pdpt_mapping(ctx, layer_name, entries): for entry in entries: # valid entry? diff --git a/volatility/framework/automagic/nlpdtbfinder.py b/volatility/framework/automagic/nlpdtbfinder.py index 0bee5931b..649626ce7 100644 --- a/volatility/framework/automagic/nlpdtbfinder.py +++ b/volatility/framework/automagic/nlpdtbfinder.py @@ -135,7 +135,8 @@ class NlpDtbScanner(interfaces.layers.ScannerInterface): entry_num = entry_num + 1 if invalid_count == 0 and len(valid_entries) > 3 and user_count != 0 and supervisor_count != 0: - yield (data_offset + page_offset, valid_entries) + if page_offset < self.chunk_size: + yield (data_offset + page_offset, valid_entries) class NlpDtbfinder(interfaces.automagic.AutomagicInterface): diff --git a/volatility/framework/automagic/pdbscan.py b/volatility/framework/automagic/pdbscan.py index 8fac8ec82..282c015bc 100644 --- a/volatility/framework/automagic/pdbscan.py +++ b/volatility/framework/automagic/pdbscan.py @@ -59,7 +59,8 @@ class PdbSignatureScanner(interfaces.layers.ScannerInterface): self._RSDS_format.unpack(data[sig + 4:name_offset]) GUID = (16 * '{:02X}').format(g0, g1, g2, g3, g4, g5, g6, g7, g8, g9, ga, gb, gc, gd, ge, gf) - yield (GUID, a, pdb_name, data_offset + sig) + if sig < self.chunk_size: + yield (GUID, a, pdb_name, data_offset + sig) sig = data.find(b"RSDS", sig + 1) diff --git a/volatility/framework/automagic/windows.py b/volatility/framework/automagic/windows.py index df8b62825..df5402643 100644 --- a/volatility/framework/automagic/windows.py +++ b/volatility/framework/automagic/windows.py @@ -226,7 +226,8 @@ class PageMapScanner(interfaces.layers.ScannerInterface): for page_offset in range(0, len(data), 0x1000): result = test(data, data_offset, page_offset) if result is not None: - yield (test, result[0]) + if result[0] < self.chunk_size: + yield (test, result[0]) class WintelHelper(interfaces.automagic.AutomagicInterface): diff --git a/volatility/framework/interfaces/layers.py b/volatility/framework/interfaces/layers.py index 96c6caf2c..304f846ae 100644 --- a/volatility/framework/interfaces/layers.py +++ b/volatility/framework/interfaces/layers.py @@ -43,6 +43,10 @@ class ScannerInterface(validity.ValidityRoutines, metaclass = ABCMeta): scanning the chunk will take (ie, do not set an excessively large chunksize and try not to take a significant amount of time in the __call__ method). + Scanners must NOT return results found *after* self.chunk_size (ie, entirely contained + within the overlap). It is the responsibility of the scanner not to return such + duplicate results. + Scanners can mark themselves as thread_safe, if they do not require state in either their own class or the context. This will allow the scanner to be run in parallel against multiple blocks. diff --git a/volatility/framework/layers/scanners/__init__.py b/volatility/framework/layers/scanners/__init__.py index 0c204bad4..caaf362c3 100644 --- a/volatility/framework/layers/scanners/__init__.py +++ b/volatility/framework/layers/scanners/__init__.py @@ -17,7 +17,8 @@ class BytesScanner(layers.ScannerInterface): """ find_pos = data.find(self.needle) while find_pos >= 0: - yield find_pos + data_offset + if find_pos < self.chunk_size: + yield find_pos + data_offset find_pos = data.find(self.needle, find_pos + 1) @@ -35,7 +36,8 @@ class RegExScanner(layers.ScannerInterface): find_pos = self.regex.finditer(data) for match in find_pos: offset = match.start() - yield offset + data_offset + if offset < self.chunk_size: + yield offset + data_offset class MultiStringScanner(layers.ScannerInterface): @@ -54,4 +56,5 @@ class MultiStringScanner(layers.ScannerInterface): -> typing.Generator[typing.Tuple[int, typing.Union[str, bytes]], None, None]: """Runs through the data looking for the needles""" for offset, pattern in self._patterns.search(data): - yield offset + data_offset, pattern + if offset < self.chunk_size: + yield offset + data_offset, pattern