Example #1
0
 def _load_heap_constraints(self):
     """
     Init the constraints on the heap module
     :return:
     """
     parser = constraints.ConstraintsConfigHandler()
     return parser.read(self._heap_constraint_filename)
Example #2
0
def search_cmdline(args):
    """ Search for instance of a record_type in the allocated memory of a process. """
    # get the memory handler adequate for the type requested
    memory_handler = get_memory_handler(args)
    # try to load constraints
    my_constraints = None
    if args.constraints_file:
        handler = constraints.ConstraintsConfigHandler()
        my_constraints = handler.read(args.constraints_file.name)
    # get the python record type
    modulename, sep, classname = args.record_type_name.rpartition('.')
    module = None
    try:
        module = memory_handler.get_model().import_module(modulename)
    except ImportError as e:
        log.error('sys.path is %s', sys.path)
        raise e
    record_type = getattr(module, classname)
    # do the search
    results = api.search_record(memory_handler, record_type, my_constraints, extended_search=args.extended)
    # output handling
    try:
        ret = get_output(memory_handler, results, args.output)
        # print output on stdout
        print(ret)
    except Exception as e:
        log.error(e)
    finally:
        if args.interactive:
            print('results are local variable "results"')
            import code
            code.interact(local=locals())
    return
 def search_heap_direct(self, memdumpname, start_address_mapping):
     # we need a memory dump loader
     self.memory_handler = dump_loader.load(memdumpname)
     my_model = self.memory_handler.get_model()
     module_name = self._init_module_name(self.memory_handler)
     # import the module with the right arch
     heap_module = my_model.import_module(module_name)
     log.debug('the heap module loaded is %s', module_name)
     # load the constraints
     constraint_filename = self._init_constraints_filename(heap_module)
     parser = constraints.ConstraintsConfigHandler()
     my_constraints = parser.read(constraint_filename)
     m = self.memory_handler.get_mapping_for_address(start_address_mapping)
     my_searcher = searcher.AnyOffsetRecordSearcher(
         self.memory_handler,
         my_constraints, [m],
         update_cb=partial(self.print_cb, self.memory_handler))
     heap_record_name = self._init_heap_record_name()
     heap_struct = getattr(heap_module, heap_record_name)
     results = my_searcher._load_at(m,
                                    start_address_mapping,
                                    heap_struct,
                                    depth=5)
     #print haystack.output_to_python(memory_handler, [results])[0][0].toString()
     return results
Example #4
0
    def _make_dual_arch_ctypes(self):
        # dual arch
        module_name_32 = 'haystack.allocators.win32.win7_32'
        _win7_32 = target.TargetPlatform.make_target_win_32('win7')
        _model_32 = model.Model(_win7_32.get_target_ctypes())
        _win7_32_module = _model_32.import_module(module_name_32)
        # TODO make dual optional
        module_name_64 = 'haystack.allocators.win32.win7_64'
        _win7_64 = target.TargetPlatform.make_target_win_64('win7')
        _model_64 = model.Model(_win7_64.get_target_ctypes())
        _win7_64_module = _model_64.import_module(module_name_64)

        # different arch have different recors types.
        parser = constraints.ConstraintsConfigHandler()
        constraint_filename = os.path.join(os.path.dirname(sys.modules[__name__].__file__), 'win7heap32.constraints')
        _constraints_32 = parser.read(constraint_filename)
        constraint_filename = os.path.join(os.path.dirname(sys.modules[__name__].__file__), 'win7heap64.constraints')
        _constraints_64 = parser.read(constraint_filename)

        # KERNEL AS
        kas32 = (0x8000000, 0xFFFFFFFF)
        kas64 = (0xFFFF080000000000, 0xFFFFFFFFFFFFFFFF)

        _cpu = dict()
        _cpu[32] = {'model': _model_32, 'target': _win7_32, 'module': _win7_32_module,
                    'constraints': _constraints_32, 'signature_offset': 100, 'kernel_as': kas32}
        _cpu[64] = {'model': _model_64, 'target': _win7_64, 'module': _win7_64_module,
                    'constraints': _constraints_64, 'signature_offset': 160, 'kernel_as': kas64}
        return _cpu
Example #5
0
    def test_search_with_constraints(self):
        # now add some constraints to the search for struct_test3
        handler = constraints.ConstraintsConfigHandler()
        my_constraints = handler.read('test/src/ctypes3.constraints')
        results = haystack.search_record(self.memory_handler,
                                         self.ctypes3.struct_test3,
                                         my_constraints)
        # all valid record addresses are in self.offsets
        valid = self.offsets['test3']
        self.assertEqual(len(results), len(valid))
        for record, addr in results:
            self.assertIn(addr, valid)

        # search struct_Node with constraints
        results = haystack.search_record(self.memory_handler,
                                         self.ctypes3.struct_Node,
                                         my_constraints)
        # check the string output
        out = haystack.output_to_string(self.memory_handler, results)
        valid = self.offsets['test1']
        self.assertEqual(len(results), len(valid))
        for x in valid:
            self.assertIn(hex(x), out)
        # all valid record addresses are in self.offsets
        for record, addr in results:
            self.assertIn(addr, valid)
    def setUp(self):
        self.memory_handler = dump_loader.load('test/src/test-ctypes6.32.dump')
        self.memdumpname = 'test/src/test-ctypes6.32.dump'
        self._load_offsets_values(self.memdumpname)
        sys.path.append('test/src/')

        my_model = self.memory_handler.get_model()
        self.ctypes6_gen32 = my_model.import_module("ctypes6_gen32")

        handler = constraints.ConstraintsConfigHandler()
        my_constraints = handler.read('test/src/ctypes6.constraints')

        self.x32_validator = ctypes6.CTypes6Validator(self.memory_handler,
                                                      my_constraints,
                                                      self.ctypes6_gen32)
        self.offset = self.offsets['test1'][0]
        self.m = self.memory_handler.get_mapping_for_address(self.offset)
        self.usual = self.m.read_struct(self.offset,
                                        self.ctypes6_gen32.struct_usual)
        # complex
        self.o_rootA = self.offsets['rootA'][0]
        self.rootA = self.m.read_struct(self.o_rootA,
                                        self.ctypes6_gen32.struct_Node)
        self.o_rootB = self.offsets['rootB'][0]
        self.rootB = self.m.read_struct(self.o_rootB,
                                        self.ctypes6_gen32.struct_Node)
        self.o_rootC = self.offsets['rootC'][0]
        self.rootC = self.m.read_struct(self.o_rootC,
                                        self.ctypes6_gen32.struct_Node)
Example #7
0
    def test_search(self):
        handler = constraints.ConstraintsConfigHandler()
        my_constraints = handler.read('test/src/ctypes6.constraints')
        results = api.search_record(self.memory_handler, self.node,
                                    my_constraints)
        # 2 from test1
        # 3 from test_pointer_to_list
        # the rest have bad values in constrainged fields
        self.assertEqual(len(results), 2 + 3)
        # FIXME: that is a weird idea, that allocations are ordered that way
        (node1, offset1), (node2, offset2) = results[:2]
        self.assertEqual(node1.val1, 0xdeadbeef)
        self.assertEqual(node1.val2, 0xffffffff)
        self.assertEqual(node2.val1, 0xdeadbabe)
        self.assertEqual(node2.val2, 0xffffffff)

        # FIXME there is a circular reference in json.
        #with self.assertRaises(ValueError):
        #    api.output_to_json(self.memory_handler, results)
        #self.assertEqual(node2s['val1'], 0xdeadbabe)
        #self.assertEqual(node2s['val2'], 0xffffffff)
        model = self.memory_handler.get_model()
        #import code
        #code.interact(local=locals())
        x = api.output_to_pickle(self.memory_handler, results)
        rest = pickle.loads(x)
        return
Example #8
0
 def _init_haystack(self):
     self.my_name = self.config.PROFILE
     # get the structure name and type
     self.modulename, sep, self.classname = self.config.RECORD_NAME.rpartition(
         '.')
     # parse the constraint file
     if self.config.CONSTRAINT_FILE:
         handler = constraints.ConstraintsConfigHandler()
         self.my_constraints = handler.read(self.config.CONSTRAINT_FILE)
     else:
         self.my_constraints = None
     return
Example #9
0
def refresh(args):
    """
    Default function for the refresh command line option.
    Try to map a Structure from a specific offset in memory.
    Returns it in pickled or text format.

    See the command line --help .
    """
    # we need an int
    memory_address = args.addr
    # get the memory handler adequate for the type requested
    memory_handler = _get_memory_handler(args)
    # print output on stdout
    rtype = _get_output_style(args)
    # check the validity of the address
    heap = memory_handler.is_valid_address_value(memory_address)
    if not heap:
        log.error("the address is not accessible in the memoryMap")
        raise ValueError("the address is not accessible in the memoryMap")
    # get the structure name
    modulename, sep, classname = args.struct_name.rpartition('.')
    module = memory_handler.get_model().import_module(modulename)
    struct_type = getattr(module, classname)
    # load the record
    result = api.load_record(memory_handler, struct_type, memory_address)
    results = [result]
    if args.validate:
        my_constraints = None
        if args.constraints_file:
            handler = constraints.ConstraintsConfigHandler()
            my_constraints = handler.read(args.constraints_file.name)
        validation = api.validate_record(memory_handler, result[0],
                                         my_constraints)
    if args.interactive:
        import code
        code.interact(local=locals())
    # output handling
    ret = None
    if rtype == 'string':
        ret = api.output_to_string(memory_handler, results)
    elif rtype == 'python':
        ret = api.output_to_python(memory_handler, results)
    elif rtype == 'json':
        ret = api.output_to_json(memory_handler, results)
    elif rtype == 'pickled':
        ret = api.output_to_pickle(memory_handler, results)
    else:
        raise ValueError('unknown output format')
    print ret
    if args.validate:
        print 'Validated', validation
    return
Example #10
0
def show_cmdline(args):
    """Cast the bytes at this address into a record_type. """
    # we need an int
    memory_address = args.address
    # get the memory handler adequate for the type requested
    memory_handler = get_memory_handler(args)
    # check the validity of the address
    heap = memory_handler.is_valid_address_value(memory_address)
    if not heap:
        log.error("the address is not accessible in the memoryMap")
        raise ValueError("the address is not accessible in the memoryMap")
    # get the structure name
    modulename, sep, classname = args.record_type_name.rpartition('.')
    module = None
    try:
        module = memory_handler.get_model().import_module(modulename)
    except ImportError as e:
        log.error('sys.path is %s', sys.path)
        raise e
    record_type = getattr(module, classname)
    # load the record
    result = api.load_record(memory_handler, record_type, memory_address)
    results = [result]
    # validate if required
    validation = None
    if args.constraints_file:
        handler = constraints.ConstraintsConfigHandler()
        my_constraints = handler.read(args.constraints_file.name)
        validation = api.validate_record(memory_handler, result[0],
                                         my_constraints)
    # output handling
    ret = None
    try:
        ret = get_output(memory_handler, results, args.output)
        # print output on stdout
        print ret
        if args.constraints_file:
            print 'Validated', validation
    except Exception as e:
        log.error(e)
    finally:
        if args.interactive:
            print 'results are local variable "results"'
            import code
            code.interact(local=locals())
    return
Example #11
0
    def __init__(self, memory_handler):
        """
        :param memory_handler: IMemoryHandler
        :return: HeapFinder
        """
        super(LibcHeapFinder, self).__init__(memory_handler)
        heap_module_name = 'haystack.allocators.libc.ctypes_malloc'
        self._heap_module = self._memory_handler.get_model().import_module(
            heap_module_name)
        self._heap_name = 'malloc_chunk'
        self._heap_record = getattr(self._heap_module, self._heap_name)

        parser = constraints.ConstraintsConfigHandler()
        constraint_filename = os.path.join(
            os.path.dirname(sys.modules[__name__].__file__),
            'libcheap.constraints')
        log.debug('constraint_filename :%s', constraint_filename)
        self._constraints = parser.read(constraint_filename)

        return
Example #12
0
    def test_preload(self):
        sys.path.append('test/src/')

        my_model = self.memory_handler.get_model()
        ctypes6_gen64 = my_model.import_module("ctypes6_gen64")

        handler = constraints.ConstraintsConfigHandler()
        my_constraints = handler.read('test/src/ctypes6.constraints')

        x64_validator = ctypes6.CTypes6Validator(self.memory_handler,
                                                 my_constraints, ctypes6_gen64)

        record_names = ['ctypes6_gen64.%s' % n for n in ctypes6_gen64.__all__]

        krtr = reversers.KnownRecordTypeReverser(self.memory_handler,
                                                 record_names, my_constraints)
        krtr.reverse()
        ## TODO enforce better constraints, and a dynamic Contraints engine
        results = krtr.get_search_results()
        for record_name, addresses in results.items():
            print(record_name, len(addresses))
        pass
Example #13
0
def search_cmdline(args):
    """ Internal cmdline mojo. """
    # get the memory handler adequate for the type requested
    memory_handler = _get_memory_handler(args)
    # print output on stdout
    rtype = _get_output_style(args)
    # try to load constraints
    # mapper
    if args.constraints_file:
        handler = constraints.ConstraintsConfigHandler()
        my_constraints = handler.read(args.constraints_file.name)
    else:
        my_constraints = None
    # get the structure name
    modulename, sep, classname = args.struct_name.rpartition('.')
    module = memory_handler.get_model().import_module(modulename)
    struct_type = getattr(module, classname)
    # do the search
    results = api.search_record(memory_handler,
                                struct_type,
                                my_constraints,
                                extended_search=args.extended_search)
    if args.interactive:
        import code
        code.interact(local=locals())
    # output handling
    ret = None
    if rtype == 'string':
        ret = api.output_to_string(memory_handler, results)
    elif rtype == 'python':
        ret = api.output_to_python(memory_handler, results)
    elif rtype == 'json':
        ret = api.output_to_json(memory_handler, results)
    elif rtype == 'pickled':
        ret = api.output_to_pickle(memory_handler, results)
    else:
        raise ValueError('unknown output format')
    print ret
    return
Example #14
0
    def test_config_constraints(self):

        # the constraints are imposed through config file.
        parser = constraints.ConstraintsConfigHandler()
        module_constraints = parser.read('test/src/ctypes6.constraints')
        self.validator = basicmodel.CTypesRecordConstraintValidator(
            self.memory_handler, module_constraints)

        # should be valid.
        node1 = self.offsets['test2'][0]
        node2 = self.offsets['test3'][0]  # 0xdeadbabe
        for instance_addr in [node1, node2]:
            m = self.memory_handler.get_mapping_for_address(instance_addr)
            node = m.read_struct(instance_addr, self.ctypes_gen64.struct_Node)
            self.assertTrue(self.validator.is_valid(node))

        # should be invalid.
        items1 = self.offsets['mid_list'][0]
        items2 = self.offsets['end_list'][0]
        for instance_addr in [items1, items2]:
            m = self.memory_handler.get_mapping_for_address(instance_addr)
            node = m.read_struct(instance_addr, self.ctypes_gen64.struct_Node)
            self.assertFalse(self.validator.is_valid(node))
Example #15
0
    def test_search(self):
        handler = constraints.ConstraintsConfigHandler()
        my_constraints = handler.read('test/src/ctypes6.constraints')
        results = haystack.search_record(self.memory_handler, self.node,
                                         my_constraints)
        self.assertEquals(len(results), 2)
        (node1, offset1), (node2, offset2) = results
        self.assertEquals(node1.val1, 0xdeadbeef)
        self.assertEquals(node1.val2, 0xffffffff)
        self.assertEquals(node2.val1, 0xdeadbabe)
        self.assertEquals(node2.val2, 0xffffffff)

        # FIXME there is a circular reference in json.
        #with self.assertRaises(ValueError):
        #    haystack.output_to_json(self.memory_handler, results)
        #self.assertEquals(node2s['val1'], 0xdeadbabe)
        #self.assertEquals(node2s['val2'], 0xffffffff)
        model = self.memory_handler.get_model()
        #import code
        #code.interact(local=locals())
        x = api.output_to_pickle(self.memory_handler, results)
        rest = pickle.loads(x)
        return
 def search_heap(self, memdumpname):
     # we need a memory dump loader
     self.memory_handler = dump_loader.load(memdumpname)
     my_model = self.memory_handler.get_model()
     module_name = self._init_module_name(self.memory_handler)
     # import the module with the right arch
     heap_module = my_model.import_module(module_name)
     log.debug('the heap module loaded is %s', module_name)
     # load the constraints
     constraint_filename = self._init_constraints_filename(heap_module)
     parser = constraints.ConstraintsConfigHandler()
     my_constraints = parser.read(constraint_filename)
     my_searcher = searcher.AnyOffsetRecordSearcher(
         self.memory_handler,
         my_constraints,
         update_cb=partial(self.print_cb, self.memory_handler))
     ## DEBUG
     # DEBUG PEB search
     #peb = my_model.import_module('haystack.allocators.win32.winxp_32_peb')
     ##DEBUG
     heap_record_name = self._init_heap_record_name()
     heap_struct = getattr(heap_module, heap_record_name)
     # on ly return first results in each mapping
     results = []
     for mapping in self.memory_handler.get_mappings():
         log.debug("looking at %s", mapping)
         res = my_searcher._search_in(mapping,
                                      heap_struct,
                                      nb=1,
                                      align=0x1000)
         # DEBUG PEB search
         #res = my_searcher._search_in(mapping, peb.struct__PEB, nb=1, align=0x1000)
         if res:
             # FIXME output_to are stupid
             #print haystack.output_to_string(memory_handler, res)
             results.append(res)
     return results
Example #17
0
    def test_read(self):
        parser = constraints.ConstraintsConfigHandler()
        module_constraints = parser.read('test/structures/good.constraints')
        config_constraints = module_constraints.get_constraints()
        for st, stc in config_constraints.items():
            log.debug("structure: %s", st)
            for field, c in stc.items():
                log.debug("\t field: %s constraint: %s", field, c)

        self.assertIn('Struct2', config_constraints.keys())
        s2c = config_constraints['Struct2']
        self.assertNotIn('fieldC', s2c.keys())
        self.assertIn('field0', s2c.keys())
        self.assertIn('field1', s2c.keys())
        self.assertIn('field2', s2c.keys())
        self.assertIn('field3', s2c.keys())
        self.assertIn('field4', s2c.keys())
        self.assertIn('field5', s2c.keys())
        self.assertIn('field6', s2c.keys())
        self.assertIn('field7', s2c.keys())
        self.assertIn('field8', s2c.keys())
        self.assertIn('FiELD9', s2c.keys())

        # erroneous. It should be a list. Always.
        field0 = s2c['field0']
        self.assertTrue(isinstance(field0, list))
        self.assertEqual(field0, [-2, -3])

        field1 = s2c['field1']
        self.assertTrue(isinstance(field1, list))
        self.assertEqual(1, field1[0].low)
        self.assertEqual(16, field1[0].high)
        self.assertEqual('RangeValue', field1[0].__class__.__name__)

        field2 = s2c['field2']
        self.assertTrue(isinstance(field2, list))
        self.assertEqual('IgnoreMember', field2[0].__name__)

        field3 = s2c['field3']
        self.assertTrue(isinstance(field3, list))
        self.assertEqual(field3, [0, 1])

        field4 = s2c['field4']
        self.assertTrue(isinstance(field4, list))
        # no special character support
        self.assertEqual('qwklqwfnkl\\x20+++[po-09', field4[0].seq)
        self.assertEqual('BytesComparable', field4[0].__class__.__name__)

        field5 = s2c['field5']
        self.assertTrue(isinstance(field5, list))
        self.assertEqual('NotNullComparable', field5[0].__class__.__name__)

        field6 = s2c['field6']
        self.assertTrue(isinstance(field6, list))
        self.assertIn(-1, field6)
        self.assertIn(1, field6)
        self.assertIn(constraints.RangeValue(2, 3), field6)
        self.assertIn(constraints.RangeValue(4, 5), field6)
        self.assertIn(constraints.PerfectMatch(b'plop'), field6)

        field7 = s2c['field7']
        self.assertTrue(isinstance(field7, list))
        self.assertEqual(field7, [-1, 0, 0.0, 1.02])

        field8 = s2c['field8']
        self.assertTrue(isinstance(field8, list))
        self.assertEqual(field8, [0x0, 0x1, 0xff, 0xffeeffee, -0x20])