def get_from_section(self, iaddr, address, size): if address.is_defined(): if self.has_patched_global(address): return self.get_patched_global(address) elfheader = self.app.get_elf_header() sectionindex = elfheader.get_elf_section_index( address.get_offset_value()) if sectionindex is None: memval = SV.mk_simvalue(0, size=size) self.simstate.add_logmsg('global memory', str(address) + ' uninitialized') return memval offset = address.get_offset_value() for i in range(offset, offset + size): byteval = self.app.get_elf_header().get_memory_value( i, sectionindex) if byteval is not None: self.set_byte(iaddr, i, SV.SimByteValue(byteval)) else: raise UF.CHBError('No value found for ' + hex(i) + ' in section ' + str(sectionindex)) memval = M.SimMemory.get(self, iaddr, address, size) if not memval.is_defined(): memval = mk_simvalue(0, size=size) self.simstate.add_logmsg('global memory', str(address) + ' uninitialized') self.accesses.setdefault(str(address), []) chrrep = ' (' + chr( memval.value) + ')' if memval.value < 128 else '' self.accesses[str(address)].append( str(iaddr) + ':' + str(memval) + chrrep) return memval
def get_memval(self, iaddr, address, size, signextend=False): try: if address.is_address(): if address.is_global_address( ) and self.libapp and self.instaticlib: return self.libglobalmem.get(iaddr, address, size) if address.is_global_address and self.is_libc_ctype_toupper( address.get_offset_value()): return self._handle_ctype_toupper() elif address.is_global_address and self.is_libc_ctype_b( address.get_offset_value()): return self._handle_ctype_b() elif address.is_global_address(): return self.globalmem.get(iaddr, address, size) elif address.is_stack_address(): return self.stackmem.get(iaddr, address, size) elif address.is_base_address() and address.get_base( ) in self.basemem: return self.basemem[address.get_base()].get( iaddr, address, size) else: self.add_logmsg( iaddr, 'base ' + address.base + ' not yet supported') return SV.mk_undefined_simvalue(size) else: self.add_logmsg( iaddr, 'attempt to address memory with absolute value: ' + str(address)) return SV.simUndefinedDW except SU.CHBSimError as e: self.add_logmsg( iaddr, 'no value for memory address ' + str(address) + ' (' + str(e) + ')') return SV.simUndefinedDW
def get_b_result(self): if self.name == 'ctype_b': result = 0 print('ctype_b deref table value: ' + str(self.offset1) + ', ' + str(chr(self.offset1 // 2))) c = str(chr(self.offset1 // 2)) if c.isupper(): result += 1 if c.islower(): result += 2 if c.isalpha(): result += 4 if c.isnumeric(): result += 8 if c.isspace() or c == '\r' or c == '\n': result += 32 if c.isprintable(): result += 64 if c.isspace(): result += 256 if not c.isprintable(): result += 512 if c in string.punctuation: result += 1024 if c.isalnum(): result += 2048 return SV.mk_simvalue(result) else: return SV.simZero
def simulate(self, iaddr, simstate): srcop = self.get_src_operand() dstop = self.get_dst_operand() srcptrop = self.get_srcptr_operand() dstptrop = self.get_dstptr_operand() srcval = simstate.get_rhs(iaddr, srcop) srcptrval = simstate.get_rhs(iaddr, srcptrop) dstptrval = simstate.get_rhs(iaddr, dstptrop) # raise UF.KTCHBError(str(iaddr) + ': ' # + 'srcop: ' + str(srcop) # + '; srcval: ' + str(srcval) # + '; esi: ' + str(srcptrval) # + '; edi: ' + str(dstptrval) # + '\n' + str(simstate)) dflag = simstate.get_flag_value('DF') incr = SV.mk_simvalue(srcptrop.get_size(), self.get_size()) simstate.set(iaddr, dstop, srcval) if dflag == 0: simstate.set(iaddr, srcptrop, srcptrval.add(incr)) simstate.set(iaddr, dstptrop, dstptrval.add(incr)) elif dflag == 1: simstate.set(iaddr, srcptrop, srcptrval.sub(incr)) simstate.set(iaddr, dstptrop, dstptrval.sub(incr)) else: raise UF.KTCHBError('Unexpected value for direction flag: ' + str(dflag))
def simulate(self, iaddr, simstate): srcop = self.get_src_operand() dstop = self.get_dst_operand() if (srcop.is_register() and dstop.is_register() and srcop.get_register() == dstop.get_register()): zero = SV.mk_simvalue(dstop.get_size(), 0) simstate.set(iaddr, dstop, zero) simstate.set_flag('ZF') simstate.clear_flag('PF') simstate.clear_flag('CF') simstate.clear_flag('OF') simstate.clear_flag('SF') else: try: srcval = simstate.get_rhs(iaddr, srcop) dstval = simstate.get_rhs(iaddr, dstop) result = dstval.bitwise_xor(srcval) simstate.set(iaddr, dstop, result) simstate.clear_flag('OF') simstate.clear_flag('CF') simstate.update_flag('SF', result.is_negative()) simstate.update_flag('ZF', result.is_zero()) simstate.update_flag('PF', result.is_odd_parity()) except SU.KTCHBSimError as e: raise except UF.KTError as e: raise SU.KTCHBSimError(simstate, iaddr, str(e))
def subu(self, simval): if simval.is_literal() and simval.is_defined(): return self.add_offset(-simval.to_unsigned_int()) elif simval.is_stack_address(): return SV.mk_simvalue(self.get_offset_value() - simval.get_offset_value()) else: return self.add_offset(-simval.to_unsigned_int())
def subu(self, simval): if simval.is_literal() and simval.is_defined(): return self.add_offset(-simval.to_unsigned_int()) elif simval.is_base_address() and simval.get_base() == self.get_base(): return SV.mk_simvalue(self.get_offset_value() - simval.get_offset_value()) else: raise UF.CHBError('Argument ' + str(simval) + ' not recognized in SimBaseAddress.subu')
def simulate(self, iaddr, simstate): op = self.get_operand() srcval = simstate.get_rhs(iaddr, op) incval = SV.mk_simvalue(op.get_size(), 1) newval = srcval.add(incval) simstate.set(iaddr, op, newval) simstate.update_flag('OF', srcval.add_overflows(incval)) simstate.update_flag('ZF', newval.is_zero()) simstate.update_flag('SF', newval.is_negative()) simstate.update_flag('PF', newval.is_odd_parity())
def get_b_result(self): if self.name == 'ctype_b': result = 0 print('ctype_b: ' + str(self.offset) + ', ' + str(chr(self.offset // 2))) c = chr(self.offset // 2) if isspace(c): result += 32 return SV.mk_simvalue(result) else: return SV.simZero
def __init__(self, asmfn): self.asmfn = asmfn # AsmFunction self.imagebase = None self.uninitializedregion = None self.flags = {} # flagname -> SimBoolValue self.registers = {} # register name -> SimDoubleWordValue self.globalmem = M.SimGlobalMemory(self) self.stackmem = M.SimStackMemory(self) self.fnlog = {} # iaddr -> msg list self.registers['esp'] = SSV.SimStackAddress(0) self.registers['ebp'] = SV.mk_symbolic_simvalue('ebp-in') self.registers['eax'] = SV.mk_symbolic_simvalue('eax-in') self.registers['ecx'] = SV.mk_symbolic_simvalue('ecx-in') self.stackmem.set(0, 0, SSV.SimReturnAddress()) self.flags['DF'] = SV.simflagclr # direction forward self.flags['CF'] = SV.simflagclr # no carry self.flags['PF'] = SV.simflagclr # even parity self.flags['ZF'] = SV.simflagclr # no zero result self.flags['SF'] = SV.simflagclr # unsigned result self.flags['OF'] = SV.simflagclr # no overflow occurred
def simulate(self,iaddr,simstate): op = self.get_operand() srcval = simstate.get_rhs(iaddr,op) zero = SV.mk_simvalue(op.get_size(),0) result = zero.sub(srcval) simstate.set(iaddr,op,result) if srcval.is_zero(): simstate.set_flag('CF') else: simstate.clear_flag('CF') simstate.update_flag('OF',zero.sub_overflows(srcval)) simstate.update_flag('SF',result.is_negative()) simstate.update_flag('ZF',result.is_zero()) simstate.update_flag('PF',result.is_odd_parity())
def simulate(self, iaddr, simstate): dstop = self.get_dst_operand() srcop = self.get_src_operand() size = dstop.get_size() ediop = self.get_edi_operand() dfop = self.get_df_operand() srcval = simstate.get_rhs(iaddr, srcop) edival = simstate.get_rhs(iaddr, ediop) dfval = simstate.get_rhs(iaddr, dfop) ediinc = SV.mk_simvalue(4, size) if dfval.is_set(): edinewval = srcval.sub(ediinc) else: edinewval = srcval.add(ediinc) simstate.set(iaddr, dstop, srcval) simstate.set(iaddr, ediop, edinewval)
def simulate(self, iaddr, simstate): srcop = self.get_src_operand() dstop = self.get_dst_operand() size = dstop.get_size() srcval = simstate.get_rhs(iaddr, srcop) srcval = srcval.sign_extend(size) dstval = simstate.get_rhs(iaddr, dstop) cflag = simstate.get_flag_value('CF') if cflag is None: result = SV.simundefined simstate.set(iaddr, dstop, SV.simundefined) else: cflagval = SV.mk_simvalue(size, cflag) srcval = srcval.add(cflagval) result = dstval.sub(srcval) simstate.set(iaddr, dstop, result) simstate.update_flag('CF', dstval.sub_carries(srcval)) simstate.update_flag('OF', dstval.sub_overflows(srcval)) simstate.update_flag('SF', result.is_negative()) simstate.update_flag('ZF', result.is_zero()) simstate.update_flag('PF', result.is_odd_parity())
def get_rhs(self, iaddr, op): opsize = op.get_size() opkind = op.get_opkind() if opkind.is_flag(): flag = opkind.get_flag() if flag in self.flags: return self.flags[flag] else: raise SU.CHBSimError(self, iaddr, 'flag value ' + flag + ' not found') elif opkind.is_register(): reg = opkind.get_register() return self.get_regval(iaddr, reg) elif opkind.is_double_register(): lowreg = opkind.get_reg_low() highreg = opkind.get_reg_high() lowval = self.get_regval(iaddr, lowreg) highval = self.get_regval(iaddr, highreg) return lowval.to_double_size(highval) elif opkind.is_immediate(): return SV.mk_simvalue(op.get_size(), opkind.get_value()) elif opkind.is_indirect_register(): reg = opkind.get_register() offset = opkind.get_offset() regval = self.get_regval(iaddr, reg) if regval.is_address(): address = regval.add_offset(offset) return self.get_memval(iaddr, address, op.get_size()) elif regval.value > self.imagebase.value: address = SSV.SimGlobalAddress(regval.value) address = address.add_offset(offset) return self.get_memval(iaddr, address, op.get_size()) else: raise SU.CHBSimError( self, iaddr, 'register used in indirect register operand has no base: ' + str(regval) + ' (' + str(self.imagebase) + ')') elif opkind.is_scaled_indirect_register(): basereg = opkind.get_base_register() indexreg = opkind.get_ind_register() offset = opkind.get_offset() scale = opkind.get_scale() if (not basereg is None) and indexreg is None and scale == 1: regval = self.get_regval(iaddr, basereg) if regval.is_address(): address = regval.add_offset(offset) return self.get_memval(iaddr, address, op.get_size()) elif (not basereg is None) and ( not indexreg is None) and scale == 1: baseval = self.get_regval(iaddr, basereg) indexval = self.get_regval(iaddr, indexreg) if indexval.is_address(): address = indexval.add_offset(offset) address = address.add_offset(scale * baseval.to_signed_int()) return self.get_memval(iaddr, address, op.get_size()) else: raise SU.CHBSimError( self, iaddr, 'rhs-op not recognized(A): ' + str(op)) else: raise SU.CHBSimError(self, iaddr, 'rhs-op not recognized(B): ' + str(op)) else: raise SU.CHBSimError(self, iaddr, 'rhs-op not recognized(C): ' + str(op))
def mk_base_address(base, offset=0, buffersize=None, tgttype=None): """Makes a base address with offset (int) and buffer size (simvalue).""" return SimBaseAddress(base, SV.mk_simvalue(offset), buffersize=buffersize, tgttype=tgttype)
def mk_stack_address(offset): # integer return SimStackAddress(SV.mk_simvalue(offset))
def get_toupper_result(self): if self.name == 'ctype_toupper': if self.offset1 >= 97 and self.offset2 <= 122: return SV.mk_simvalue(self.offset1 // 2) else: return SV.mk_simvalue(self.offset1)
def mk_global_address(offset): # integer return SimGlobalAddress(SV.mk_simvalue(offset))
def set_uninitialized_region(self, low, high): self.uninitializedregion = (SV.mk_global_hex_address(low), SV.mk_global_hex_address(high))
def __init__( self, app, basename, # name of executable imagebase, # base address of the image (hex) startaddr, # address to start simulation (hex) bigendian=False, simsupport=BMS.BaseMIPSimSupport( '0x0'), # support class with custom initialization and stubs baseaddress=0, # load address, to be added to imagebase libapp=None, # library to statically include functions from xapp=None): # target executable for dynamic loading self.app = app self.basename = basename self.baseaddress = baseaddress self.bigendian = bigendian self.simsupport = simsupport # context self.imagebase = SSV.mk_global_address(int(imagebase, 16)) self.context = FunctionContext(self, app) self.programcounter = SSV.mk_global_address(int(startaddr, 16)) # SimAddress self.delayed_programcounter = None # SimAddress # registers and memory self.registers = {} # register name -> SimValue self.registers['zero'] = SV.SimDoubleWordValue(0) self.stackmem = MM.MIPSimStackMemory(self) self.globalmem = MM.MIPSimGlobalMemory(self, self.app) self.basemem = {} # base -> MM.MIPSimBaseMemory # static library (optional) self.libapp = libapp if self.libapp: self.libstubs = {} # int (int-address) -> (name,stub) self.libglobalmem = MM.MIPSimGlobalMemory(self, libapp) self.static_lib = { } # function-name -> function address in static lib libimgbase = self.libapp.get_elf_header().get_image_base() self.libimagebase = SSV.SimGlobalAddress( SV.SimDoubleWordValue(int(libimgbase, 16))) self.instaticlib = False # target executable for dynamic loading (optional) self.xapp = xapp if self.xapp: self.xglobalmem = MM.MIPSimGlobalMemory(self, xapp) # log self.fnlog = {} # iaddr -> msg list2 # environment self.environment = {} # string -> string self.nvram = {} # string -> string ; non-volatile ram default values self.network_input = {} # string -> f() -> string # library/application function stubs self.stubs = {} # int (int-address) -> (name,stub) self.appstubs = {} # int (int-address) -> (name,stub) self.dlstubs = {} # name -> stub ; dynamically linked symbols # libc functions implemented by tables self.ctype_toupper = None self.ctype_b = None self._initialize() self.function_start_initialization() self.push_context(startaddr)
def add_offset(self, intval): newoffset = self.offset.add(SV.SimDoubleWordValue(intval)) return SimBaseAddress(self.base, newoffset, buffersize=self.buffersize)
def set_image_base(self, value): self.imagebase = SSV.SimGlobalAddress( SV.SimDoubleWordValue(int(value, 16)))
def add_offset(self, intval): newoffset = self.offset.add(SV.SimDoubleWordValue(intval)) return SimStackAddress(newoffset)
def get_rhs(self, iaddr, op, opsize=4): opkind = op.get_mips_opkind() if opkind.is_mips_register() or opkind.is_mips_special_register(): reg = opkind.get_mips_register() return self.get_regval(iaddr, reg, opsize) elif opkind.is_mips_immediate(): return SV.mk_simvalue(opsize, opkind.get_value()) elif opkind.is_mips_indirect_register(): reg = opkind.get_mips_register() offset = opkind.get_offset() regval = self.get_regval(iaddr, reg) if not regval.is_defined(): return SV.mk_undefined_simvalue(opsize) if regval.is_string_address() and opsize == 1: regstring = regval.get_string() if offset == len(regstring): return SV.SimByteValue(0) elif offset > len(regstring): print('Accessing string value out of bounds') exit(1) else: return SV.mk_simvalue(ord(regval.get_string()[offset]), size=1) if regval.is_symbol(): base = regval.get_name() if not base in self.basemem: self.basemem[base] = MM.MIPSimBaseMemory(self, base) address = SSV.mk_base_address(base, offset=offset) return self.get_memval(iaddr, address, opsize) elif regval.is_address(): address = regval.add_offset(offset) return self.get_memval(iaddr, address, opsize) elif (regval.is_literal() and self.instaticlib and regval.value > self.libimagebase.get_offset_value()): address = SSV.mk_global_address(regval.value + offset) return self.get_memval(iaddr, address, opsize) elif (regval.is_literal() and regval.value > self.imagebase.get_offset_value()): address = SSV.mk_global_address(regval.value + offset) return self.get_memval(iaddr, address, opsize) elif regval.is_literal( ) and regval.value <= self.imagebase.get_offset_value(): print('Invalid address: ' + str(regval)) return SV.mk_undefined_simvalue(opsize) elif regval.is_string_address(): s = regval.get_string() if offset < len(s): return SV.mk_simvalue(ord(s[0]), size=opsize) elif offset == len(s): return SV.mk_simvalue(0, size=opsize) # null terminator else: raise SU.CHBSimError( self, iaddr, 'string address: ' + s.get_string() + ' with offset: ' + str(offset)) elif regval.is_libc_table_address(): return SSV.mk_libc_table_value(regval.name) elif regval.is_libc_table_value(): return SSV.mk_libc_table_value_deref(regval.name, regval.offset) else: raise SU.CHBSimError( self, iaddr, 'register used in indirect register operand has no base: ' + str(regval) + ' (' + str(self.imagebase) + ')') else: raise SU.CHBSimError(self, iaddr, 'rhs-op not recognized(C): ' + str(op))
def is_not_equal(self, other): if other.is_symbolic() and other.is_stack_address(): if self.get_offset_value() == other.get_offset_value(): return SV.SimBoolValue(0) return SV.SimBoolValue(1)
def get_patched_global(self, address): if self.has_patched_global(address): hexval = self.patched_globals[hex(address.get_offset_value())] return SV.mk_simvalue(int(hexval, 16)) raise UF.CHBError('No patched global found for ' + str(address))