Ensure scanners don't return duplicates in the overlap.

This commit is contained in:
Mike Auty
2018-05-13 20:55:54 +01:00
parent 8b5c58fee9
commit a07691b04f
6 changed files with 22 additions and 8 deletions
+6 -2
View File
@@ -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?
@@ -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):
+2 -1
View File
@@ -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)
+2 -1
View File
@@ -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):
@@ -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.
@@ -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