def main(argv=None): pdumps, ndump = process_command_line(argv) dtype = False pos_dumps = [reader.read_memory_dump(f) for f in pdumps] if not dtype: for md in pos_dumps: md.build_memory_graph() intersec1 = diff_memory_graphs(pos_dumps) if ndump is not None: neg_dump = reader.read_memory_dump(ndump) neg_dump.build_memory_graph() intersec2 = diff_memory_graphs([pos_dumps[-1], neg_dump]) intersec1 = substract_intersections(pos_dumps, neg_dump, intersec1, intersec2) extract_diff_graph(pos_dumps[-1], intersec1) print('Changed:', len(intersec1[0])) services.print_collection(intersec1[2]) services.print_collection(intersec1[0]) print('Removed:', len(intersec1[1])) services.print_collection(intersec1[1]) print('Added:', len(intersec1[2])) else: pass
def main(argv=None): from extras import reader dump, offset, address = process_command_line(argv) md = reader.read_memory_dump(dump) md.build_memory_graph() services.export_memory_graph(md) if offset is not None: print("offset {} corresponds to v-address 0x{:x}".format( offset, afo(md, int(offset, 0)))) if address is not None: print("address {} corresponds to offset {}".format( address, ofa(md, int(address, 16))))
def main(argv=None): from extras import reader dump, offset, address = process_command_line(argv) md = reader.read_memory_dump(dump) md.build_memory_graph() services.export_memory_graph(md) if offset is not None: print("offset {} corresponds to v-address 0x{:x}".format(offset, afo(md, int(offset, 0)))) if address is not None: print("address {} corresponds to offset {}".format(address, ofa(md, int(address, 16))))
for (md, v) in zip(pos_dumps, values): if b in KeyedSet(md.memory_graph.nodes(), key=lambda seg: seg.address): ob[b] = offsets_in_node(b, enc_type, v) break return ob if __name__ == '__main__': parser = argparse.ArgumentParser(description='Search for values in a memory\ graph or the intersection of memory graphs.') parser.add_argument('-d', required=True, dest='dumps' , nargs='+', metavar='dumps', help='memory dump files.') parser.add_argument('-v', required=True, dest='values', nargs='+', metavar='values', help='value corresponding to each memory dump.') args = parser.parse_args() pos_dumps = [reader.read_memory_dump(f) for f in args.dumps] if len(pos_dumps) == 1: offsets = number_offset(pos_dumps[0], args.values[0]) print('Number of candidate offsets:', len(offsets)) for (o, t) in offsets: print('0x{:x}'.format(services.address_from_offset(pos_dumps[0], o)), t) else: intersection = diffing.diff_memory_segments(pos_dumps) print('TODO: finish intersection by value')
@author: David I. Urbina ''' from __future__ import print_function import argparse import extras.reader as reader import finding_doi.memory_diffing as diffing import finding_doi.value_scanning as scanning if __name__ == '__main__': parser = argparse.ArgumentParser(description='Compares memory dumps data structures') parser.add_argument(dest='address' , metavar='address', help='address of the data structure to compare.') parser.add_argument(dest='dumps', nargs='+', metavar='dumps', help='memory dump files.') parser.add_argument('-r', dest='dump', metavar='dump', help='memory dump to remove.') args = parser.parse_args() memory_dumps = [reader.read_memory_dump(f) for f in args.dumps] for md in memory_dumps: md.build_memory_graph() dss = list() for md in memory_dumps: for m in md.modules: if m.address == int(args.address, 16): dss.append(m) break if len(dss) == 0: dss = [md.data_structures[int(args.address, 16)] for md in memory_dumps] offsets1 = diffing.diff_memory_segments(dss)
def main(argv=None): pdump, ndump, values, _type = process_command_line(argv) #========================================================================== # Memory Graph Generation #========================================================================== print('MEMORY GRAPH GENERATION') pos_dumps = [reader.read_memory_dump(f) for f in pdump] for md in pos_dumps: md.build_memory_graph() if ndump: neg_dump = reader.read_memory_dump(ndump) neg_dump.build_memory_graph() # If only one positive memory dump graph = pos_dumps[-1].memory_graph graph.roots = pos_dumps[-1].modules #========================================================================== # Finding Data of Interest #========================================================================== print('FINDING DATA OF INTEREST') obb = dict() # Offsets by Buffer diffing = None # (Different, Removed, Added) Buffers if len(pos_dumps) > 1: #-------------------------------------------- Memory Diffing at graph level services.start_op('\tDiffing memory graphs...') diffing = memory_diffing.diff_memory_graphs(pos_dumps) if ndump: neg_diffing = memory_diffing.diff_memory_graphs([pos_dumps[-1], neg_dump]) diffing = memory_diffing.substract_intersections(pos_dumps, [pos_dumps[-1], neg_dump], diffing, neg_diffing) services.end_op() #------------------------------------------- Memory Diffing at buffer level services.start_op('\tDiffing buffers...') for b in diffing[0].copy(): obb[b] = memory_diffing.diff_memory_segments_by_address(b.address, pos_dumps) # There is at least one common offset across dumps? if len(obb[b]) == 0: del obb[b] diffing[0].remove(b) continue if ndump: offsets = memory_diffing.diff_memory_segments_by_address( b.address, [pos_dumps[-1], neg_dump]) obb[b] = obb[b] - offsets # TODO: do we need ranges? # obb[b] = services.extract_ranges(list(obb[b])) services.end_op() if len(pos_dumps) > 1: print('Changed:', len(diffing[0])) for b in diffing[0]: print(repr(b), '#different offsets:', len(obb[b])) print('Removed:', len(diffing[1])) services.print_collection(diffing[1]) print('Added:', len(diffing[2])) services.print_collection(diffing[2]) # Adding the added buffers with offset 0 for b in diffing[2]: obb[b] = {0} # The graph resulting from the memory diffing services.start_op('Extracting diff_graph...') graph = memory_diffing.extract_diff_graph(pos_dumps[-1], diffing) services.end_op() # for (b, o) in obb.items(): # print(b, o) # TODO: remove # return 1 #----------------------------------------------------------- Value Scanning if values: services.start_op('\tValue Scanning...') obbbv = dict() # Offsets by buffer by value # Only one memory dump? if diffing == None: # Yes, use graph obbbv = value_scanning.offsets_in_graph(graph, _type, values[0]) else: # No, use diffing obbbv = value_scanning.offsets_in_diffing(pos_dumps, values, diffing, _type) # for (b, o) in obbbv.items(): # print(b, o) services.end_op() #--------------------------- Intercepting Memory Diffing and Value Scanning fcob = dict() # Final candidate offsets by buffer # Memory Diffing and Value Scanning if len(pos_dumps) > 1 and values: services.start_op('\tIntercepting Memory Diffing and Value \ Scanning...') for b in diffing[0]: # Intercept changed with values offsets = obb[b] & {o[0] for o in obbbv[b]} if len(offsets) > 0: fcob[b] = offsets for b in diffing[2]: # Intercept added with values offsets = {o[0] for o in obbbv[b]} if len(offsets) > 0: fcob[b] = offsets services.end_op() # Only Memory Diffing elif len(pos_dumps) > 1: fcob = obb # Only Value Scanning else: for (b, l) in obbbv.items(): if len(l) > 0: of = {o[0] for o in l} fcob[b] = of print('\tFinal set of candidate offsets:', len(fcob)) for (b, o) in fcob.items(): print('\t\t', b, o) #========================================================================== # Signature Generation #========================================================================== print('SIGNATURE GENERATION') #------------------------------------------------------------ Extract Paths services.start_op('\tExtracting Paths...') pb = dict() # Paths by buffer for b in fcob: pb[b] = extract_paths.by_buffer(graph, b) services.end_op() for (b, paths) in pb.items(): print('\t', b) for (index, path) in enumerate(paths): n = path.normalize() nx.write_dot(n, str(b) + '-' + str(index) + '.dot') print('\t\t', index, '-', path) # print('\t\t', index, '-', str(n)) return 0
parser = argparse.ArgumentParser(description='List the possible \ reference paths to the specified data structure in a memory \ dump. The data structure may be specified by its value or by \ its address. By default it search for shortest reference paths.') parser.add_argument(dest='dump', metavar='dump', help='memory dump file.') parser.add_argument('-a', dest='address', metavar='address', help='address of the data structure.') parser.add_argument('-s', dest='ascii', metavar='ascii', help='ASCII value to search for.') parser.add_argument('-u', dest='unicode', metavar='unicode', help='Unicode(UTF16) value to search for.') parser.add_argument('--All', dest='all', action='store_true', help='search for all simple paths. It may take a long time.') args = parser.parse_args() md = reader.read_memory_dump(args.dump) md.build_memory_graph() if args.all: search_paths = nx.all_simple_paths # Search by address if args.address != None: rps = by_address(md, int(args.address, 16)) print('{} paths to data structure 0x{:x}'.format(len(rps), int(args.address, 16))) # Search by ASCII elif args.ascii != None: rps = by_string(md, args.ascii) print('{} paths to the ASCII string {}'.format(len(rps), args.ascii)) # Search by Unicode(UTF16)
def main(argv=None): pdump, ndump, values, _type = process_command_line(argv) #========================================================================== # Memory Graph Generation #========================================================================== print('MEMORY GRAPH GENERATION') pos_dumps = [reader.read_memory_dump(f) for f in pdump] for md in pos_dumps: md.build_memory_graph() if ndump: neg_dump = reader.read_memory_dump(ndump) neg_dump.build_memory_graph() # If only one positive memory dump graph = pos_dumps[-1].memory_graph graph.roots = pos_dumps[-1].modules #========================================================================== # Finding Data of Interest #========================================================================== print('FINDING DATA OF INTEREST') obb = dict() # Offsets by Buffer diffing = None # (Different, Removed, Added) Buffers if len(pos_dumps) > 1: #-------------------------------------------- Memory Diffing at graph level services.start_op('\tDiffing memory graphs...') diffing = memory_diffing.diff_memory_graphs(pos_dumps) if ndump: neg_diffing = memory_diffing.diff_memory_graphs( [pos_dumps[-1], neg_dump]) diffing = memory_diffing.substract_intersections( pos_dumps, [pos_dumps[-1], neg_dump], diffing, neg_diffing) services.end_op() #------------------------------------------- Memory Diffing at buffer level services.start_op('\tDiffing buffers...') for b in diffing[0].copy(): obb[b] = memory_diffing.diff_memory_segments_by_address( b.address, pos_dumps) # There is at least one common offset across dumps? if len(obb[b]) == 0: del obb[b] diffing[0].remove(b) continue if ndump: offsets = memory_diffing.diff_memory_segments_by_address( b.address, [pos_dumps[-1], neg_dump]) obb[b] = obb[b] - offsets # TODO: do we need ranges? # obb[b] = services.extract_ranges(list(obb[b])) services.end_op() if len(pos_dumps) > 1: print('Changed:', len(diffing[0])) for b in diffing[0]: print(repr(b), '#different offsets:', len(obb[b])) print('Removed:', len(diffing[1])) services.print_collection(diffing[1]) print('Added:', len(diffing[2])) services.print_collection(diffing[2]) # Adding the added buffers with offset 0 for b in diffing[2]: obb[b] = {0} # The graph resulting from the memory diffing services.start_op('Extracting diff_graph...') graph = memory_diffing.extract_diff_graph(pos_dumps[-1], diffing) services.end_op() # for (b, o) in obb.items(): # print(b, o) # TODO: remove # return 1 #----------------------------------------------------------- Value Scanning if values: services.start_op('\tValue Scanning...') obbbv = dict() # Offsets by buffer by value # Only one memory dump? if diffing == None: # Yes, use graph obbbv = value_scanning.offsets_in_graph(graph, _type, values[0]) else: # No, use diffing obbbv = value_scanning.offsets_in_diffing(pos_dumps, values, diffing, _type) # for (b, o) in obbbv.items(): # print(b, o) services.end_op() #--------------------------- Intercepting Memory Diffing and Value Scanning fcob = dict() # Final candidate offsets by buffer # Memory Diffing and Value Scanning if len(pos_dumps) > 1 and values: services.start_op('\tIntercepting Memory Diffing and Value \ Scanning...') for b in diffing[0]: # Intercept changed with values offsets = obb[b] & {o[0] for o in obbbv[b]} if len(offsets) > 0: fcob[b] = offsets for b in diffing[2]: # Intercept added with values offsets = {o[0] for o in obbbv[b]} if len(offsets) > 0: fcob[b] = offsets services.end_op() # Only Memory Diffing elif len(pos_dumps) > 1: fcob = obb # Only Value Scanning else: for (b, l) in obbbv.items(): if len(l) > 0: of = {o[0] for o in l} fcob[b] = of print('\tFinal set of candidate offsets:', len(fcob)) for (b, o) in fcob.items(): print('\t\t', b, o) #========================================================================== # Signature Generation #========================================================================== print('SIGNATURE GENERATION') #------------------------------------------------------------ Extract Paths services.start_op('\tExtracting Paths...') pb = dict() # Paths by buffer for b in fcob: pb[b] = extract_paths.by_buffer(graph, b) services.end_op() for (b, paths) in pb.items(): print('\t', b) for (index, path) in enumerate(paths): n = path.normalize() nx.write_dot(n, str(b) + '-' + str(index) + '.dot') print('\t\t', index, '-', path) # print('\t\t', index, '-', str(n)) return 0
parser = argparse.ArgumentParser( description='Compares memory dumps data structures') parser.add_argument(dest='address', metavar='address', help='address of the data structure to compare.') parser.add_argument(dest='dumps', nargs='+', metavar='dumps', help='memory dump files.') parser.add_argument('-r', dest='dump', metavar='dump', help='memory dump to remove.') args = parser.parse_args() memory_dumps = [reader.read_memory_dump(f) for f in args.dumps] for md in memory_dumps: md.build_memory_graph() dss = list() for md in memory_dumps: for m in md.modules: if m.address == int(args.address, 16): dss.append(m) break if len(dss) == 0: dss = [ md.data_structures[int(args.address, 16)] for md in memory_dumps ]
parser.add_argument('-s', dest='ascii', metavar='ascii', help='ASCII value to search for.') parser.add_argument('-u', dest='unicode', metavar='unicode', help='Unicode(UTF16) value to search for.') parser.add_argument( '--All', dest='all', action='store_true', help='search for all simple paths. It may take a long time.') args = parser.parse_args() md = reader.read_memory_dump(args.dump) md.build_memory_graph() if args.all: search_paths = nx.all_simple_paths # Search by address if args.address != None: rps = by_address(md, int(args.address, 16)) print('{} paths to data structure 0x{:x}'.format( len(rps), int(args.address, 16))) # Search by ASCII elif args.ascii != None: rps = by_string(md, args.ascii) print('{} paths to the ASCII string {}'.format(len(rps), args.ascii)) # Search by Unicode(UTF16)