Skip to content

Commit

Permalink
Choose the best record type signature for the list. not just the firs…
Browse files Browse the repository at this point in the history
…t element
  • Loading branch information
trolldbois committed Oct 24, 2015
1 parent 7b8b517 commit 7d3833a
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 6 deletions.
16 changes: 13 additions & 3 deletions haystack/reverse/heuristics/reversers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from haystack.reverse.heuristics import model
from haystack.reverse.heuristics import dsa
from haystack.reverse.heuristics import pointertypes
from haystack.reverse.heuristics import signature

"""
BasicCachingReverser:
Expand Down Expand Up @@ -331,6 +332,12 @@ def iterate_list(self, _context, _address, offset, size):
#print
return current-offset, members

def find_common_type_signature(self, members):
rev = signature.CommonTypeReverser(self._memory_handler, members)
rev.reverse()
best_sig, best_addr = rev.calculate()
return best_addr

def rename_record_type(self, _members, offset):
"""
Change the type of the 2 pointers to a substructure.
Expand All @@ -343,11 +350,14 @@ def rename_record_type(self, _members, offset):
:param head_addr:
:return:
"""
# we look at each item and get the most common signature between all items
best_member = self.find_common_type_signature(_members)

# use member[1] instead of head, so that we have a better chance for field types.
# in head, back pointer is probably a zero value, not a pointer field type.
heap = self._memory_handler.get_mapping_for_address(_members[1])
heap = self._memory_handler.get_mapping_for_address(best_member)
_context = self._process_context.get_context_for_heap(heap)
_record = _context.get_record_for_address(_members[1])
_record = _context.get_record_for_address(best_member)
# we need two pointer fields to create a substructure.
## Check if field at offset is a pointer, If so change it name, otherwise split
old_next = _record.get_field_at_offset(offset)
Expand Down Expand Up @@ -391,7 +401,7 @@ def rename_record_type(self, _members, offset):
heap = self._memory_handler.get_mapping_for_address(head_addr)
_context = self._process_context.get_context_for_heap(heap)
_context.get_record_for_address(head_addr).set_name('list_head')
pass
return _record_type

def debug_lists(self):
for size, v in self.lists.items():
Expand Down
54 changes: 51 additions & 3 deletions haystack/reverse/heuristics/signature.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,55 @@ def reverse_record(self, _context, _record):
_record.set_reverse_level(self._reverse_level)
return


class CommonTypeReverser(model.AbstractReverser):
"""
From a list of records addresse, find the most common signature.
"""
REVERSE_LEVEL = 31

def __init__(self, memory_handler, members):
super(CommonTypeReverser, self).__init__(memory_handler)
self._members = members
self._members_by_context = {}
process_context = self._memory_handler.get_reverse_context()
# organise the list
for record_addr in self._members:
heap = self._memory_handler.get_mapping_for_address(record_addr)
heap_context = process_context.get_context_for_heap(heap)
if heap_context not in self._members_by_context:
self._members_by_context[heap_context] = []
self._members_by_context[heap_context].append(record_addr)
# out
self._signatures = {}
self._similarities = []

def _iterate_contexts(self):
for c in self._members_by_context.keys():
yield c

def _iterate_records(self, _context):
for item_addr in self._members_by_context[_context]:
yield _context.get_record_for_address(item_addr)

def reverse_record(self, _context, _record):
record_signature = _record.get_signature_text()
if record_signature not in self._signatures:
self._signatures[record_signature] = []
self._signatures[record_signature].append(_record.address)

def calculate(self):
#
res = [(len(v), k) for k,v in self._signatures.items()]
res.sort(reverse=True)
total = len(self._members)
best_count = res[0][0]
best_sig = res[0][1]
best_addr = self._signatures[best_sig][0]
log.debug('best match %d/%d is %s: 0x%x', best_count, total, best_sig, best_addr)
return best_sig, best_addr


# TODO a Group maker based on field pointer memorymappings and structure
# instance/sizes...

Expand Down Expand Up @@ -247,11 +296,10 @@ def __iter__(self):


class SignatureMaker(searchers.AbstractSearcher):

'''
"""
make a condensed signature of the mapping.
We could then search the signature file for a specific signature
'''
"""

NULL = 0x1
POINTER = 0x2
Expand Down
10 changes: 10 additions & 0 deletions test/haystack/reverse/heuristics/test_reversers.py
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,15 @@ def test_doublelink(self):
offset = 8
self.assertEqual(rev.lists[size_records][offset][0], expected)

# rename all lists
for size, offset_lists in rev.lists.items():
for offset, multiple_lists in offset_lists.items():
for members_list in multiple_lists:
nb = len(members_list)
rt = rev.rename_record_type(members_list, offset)
log.debug('%d members for : %s', nb, rt.to_string())


pass


Expand Down Expand Up @@ -733,6 +742,7 @@ def test_doublelink(self):
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
logging.getLogger("reversers").setLevel(logging.DEBUG)
logging.getLogger("signature").setLevel(logging.DEBUG)
logging.getLogger("test_reversers").setLevel(logging.DEBUG)
# logging.getLogger("structure").setLevel(logging.DEBUG)
# logging.getLogger("dsa").setLevel(logging.DEBUG)
Expand Down

0 comments on commit 7d3833a

Please sign in to comment.