def _go_to_instruction(self, instruction_search, offset, history=[], indent=1): """ """ if offset == 0: self.next() eip = self.register.eip offset = eip for d in Decode(offset, self.data_code[offset:offset + 0x1000]): instruction = d[2] offset = d[0] history.append(offset) if instruction_search in instruction: self.backhistory = history self.set_position(offset) return True if 'RET' in instruction: return False if "CALL" in instruction: address_expression = self._get_function_name(instruction) if "0x" in address_expression: if '[' in address_expression: continue if ':' in address_expression: continue try: address = compute_operation(address_expression, self.register) if address in history: continue if address not in self.map_call: self.map_call[address] = "CALL_%x" % address self.map_call_by_name["CALL_%x" % address] = address if self._go_to_instruction(instruction_search, address, history, indent + 1): return True except Exception as e: print >> sys.stderr, "".join([ bcolors.FAIL, "\tError: Can't eval instruction'%s'" % instruction, bcolors.ENDC ]) return False
def test_compute_instructrion(self, o): """ Test """ register = Register32() value = compute_operation(o[0], register) if value != o[1]: assert False else: assert True
def test_compute_operation_register(self, o): """ Test de l'initialisation du moteur disass 32 """ register = Register32() register.eax = 5 register.edx = 1 r = compute_operation(o[0], register) if r == o[1]: assert True else: print o[0], o[1], r assert False return
def test_compute_operation_basic(self, o): """ Test de l'initialisation du moteur disass 32 """ register = Register32() r = compute_operation(o[0], register) if r == o[1]: print o[1], "=", str(r) assert True else: print "%s !!! %s != %s " % (o[0], str(r), str(o[1])) assert False return
def _make_xref(self, name, offset, depth=1): if offset in self.map_call: return self.map_call[offset] = name self.map_call_by_name[name] = offset for d in Decode(offset, self.data_code[offset:offset + 0x1000]): instruction = d[2] offset = d[0] if "CALL" in instruction: address_expression = self._get_function_name(instruction) if "0x" in address_expression: if '[' in address_expression: continue if ':' in address_expression: continue try: address = compute_operation(address_expression, self.register) except Exception as e: print >> sys.stderr, str(e), address_expression print >> sys.stderr, "".join([ bcolors.FAIL, "\tError: Can't eval CALL instruction'%s'" % instruction, bcolors.ENDC ]) continue if address not in self.map_call: self._make_xref("CALL_%x" % address, address, depth + 1) continue if self.is_register(instruction): continue if address_expression not in self.xref: self.xref[address_expression] = set() self.xref[address_expression].add(offset)
def update_stack_and_register(self, offset=None): """ Update Stack and register """ if offset is None: offset = self.register.eip bloc = '' # Am I on a function ? functionname = self.where_am_i(offset) addr = self.map_call_by_name[functionname] if addr < offset: s = addr e = offset else: s = self.where_start_my_bloc() e = offset self.stack = list() for d in Decode(addr, self.data_code[s:e]): if "PUSH" in d[2]: svalue = self._extract_value(d[2]) if svalue == '': continue if '[' in svalue: svalue = svalue[1:-1] svalue = compute_operation(svalue, self.register) svalue = "[%s]" % svalue else: svalue = compute_operation(svalue, self.register) self.stack.append(svalue) elif "POP" in d[2]: svalue = self._extract_value(d[2]) if svalue == '': continue svalue = compute_operation(svalue, self.register) self.stack.append(svalue) elif "CALL" in d[2]: continue elif "LEAVE" in d[2]: continue elif "MOVSD" in d[2]: continue elif "MOV" in d[2] or "LEA" in d[2]: bloc = d[2].split(' ') if "DWORD" in d[2]: pass elif "BYTE" in d[2]: pass else: bloc = d[2].split(' ') if 'REP' in bloc: continue if 'MOVSW' in bloc: continue if 'MOVSB' in bloc: continue if 'MOVZX' in bloc: continue if 'MOV WORD' in d[2]: continue try: dst = bloc[1][:-1].lower() src = bloc[2].lower() if '[' in dst: continue if ':' in src or ':' in dst: continue if '[' in src: value_src = compute_operation( src[1:-1], self.register) self.register.set_address(dst, value_src) else: value_src = compute_operation(src, self.register) self.register.set(dst, value_src) except Exception as e: print >> sys.stderr, "".join([ bcolors.FAIL, "\tError: '%s'" % bloc, bcolors.ENDC ]) print >> sys.stderr, "".join([ bcolors.FAIL, "\tError: Can't update stack and registry '%s' for %s" % (str(e), d[2]), bcolors.ENDC ]) pass elif "XOR" in d[2]: try: bloc = d[2].split(' ') dst = bloc[1][:-1].lower() if '[' in d[2]: continue src = bloc[2].lower() self.register.set( dst, self.register.get(dst) ^ self.register.get(src)) except Exception as e: print >> sys.stderr, "".join( [bcolors.FAIL, "\tError: '%s'" % bloc, bcolors.ENDC]) print >> sys.stderr, "".join([ bcolors.FAIL, "\tError: Can't xor '%s' for %s" % (str(e), d[2]), bcolors.ENDC ]) pass self.stack.reverse()
def _go_to_next_call(self, name, offset, history=[], indent=1): """ """ if offset == 0: self.next() eip = self.register.eip offset = eip for d in Decode(offset, self.data_code[offset:offset + 0x1000]): instruction = d[2] offset = d[0] if offset in history: return False history.append(offset) if name in self.replace_function(instruction): self.backhistory = history self.set_position(offset) return True if 'RET' in instruction: return False if 'J' == instruction[0]: address_expression = self._get_function_name(instruction) if address_expression in self.symbols_imported_by_name: #Trampoline Function name_tampoline = "__jmp__%s" % address_expression self.symbols_imported_by_name[name_tampoline] = offset self.symbols_imported[offset] = name_tampoline if name in name_tampoline: self.set_position(history[-2]) self.backhistory = history[:-2] return True return False if address_expression is None: continue if "0x" in address_expression: if '[' in address_expression: continue if ':' in address_expression: continue try: address = compute_operation(address_expression, self.register) except Exception as e: print >> sys.stderr, str(e), address_expression print >> sys.stderr, "".join([ bcolors.FAIL, "\tError: Can't eval JMP instruction'%s'" % instruction, bcolors.ENDC ]) continue if address in history: continue if self._go_to_next_call(name, address, history, indent + 1): return True if "CALL" in instruction: address_expression = self._get_function_name(instruction) if "0x" in address_expression: if '[' in address_expression: continue if ':' in address_expression: continue try: address = compute_operation(address_expression, self.register) except Exception as e: print >> sys.stderr, str(e), address_expression print >> sys.stderr, "".join([ bcolors.FAIL, "\tError: Can't eval CALL instruction'%s'" % instruction, bcolors.ENDC ]) continue if address in history: continue if address not in self.map_call: self.map_call[address] = "CALL_%x" % address self.map_call_by_name["CALL_%x" % address] = address if self._go_to_next_call(name, address, history, indent + 1): return True if self.is_register(instruction): self.backhistory = history self.update_stack_and_register(offset) value = self.register.get(address_expression.lower()) if value in self.symbols_imported: if name == self.symbols_imported[value]: self.backhistory = history self.set_position(offset) return True return False