def simulate(self, simstate, processed=[]): self._get_blocks() blockaddr = self.faddr while True: try: (baddr, processed) = self.simulate_block(simstate, blockaddr, processed) bsuccessors = self.cfg.get_successors(baddr) except SU.SimFallthroughException as e: baddr = e.blockaddr processed = e.processed bsuccessors = self.cfg.get_successors(baddr) bsuccessors = [x for x in bsuccessors if not x == e.tgtaddr] if len(bsuccessors) == 1: blockaddr = bsuccessors[0] if not (blockaddr in self.blocks): raise SU.CHBSimError( simstate, baddr, 'Block successor not found: ' + str(blockaddr)) elif len(bsuccessors) == 0: raise SU.CHBSimError( simstate, baddr, 'No block successors found' + str(self.cfg)) else: e = SU.CHBSimError( simstate, baddr, 'Multiple block successors found: ' + ','.join([str(x) for x in bsuccessors])) e.set_instructions_processed(processed) raise e
def set_register(self, iaddr, reg, srcval): if SU.is_full_reg(reg): if srcval.is_doubleword(): self.registers[reg] = srcval else: raise SU.CHBSimError( self, iaddr, 'Cannot assign byte/word value to full register: ' + str(srcval) + ' (width: ' + str(srcval.get_width()) + ')') elif SU.is_half_reg(reg): fullreg = SU.fullregmap[reg] fullregval = self.get_regval(iaddr, fullreg) newval = fullregval.set_word(srcval) self.set_register(iaddr, fullreg, newval) elif SU.is_qlow_reg(reg): fullreg = SU.fullregmap[reg] fullregval = self.get_regval(iaddr, fullreg) newval = fullregval.set_low_byte(srcval) self.set_register(iaddr, fullreg, newval) elif is_qhigh_reg(reg): fullreg = fullregmap(reg) fullregval = self.get_regval(iaddr, fullreg) newval = fullregval.set_snd_byte(srcval) self.set_register(iaddr, fullreg, newval) else: self.registers[reg] = srcval
def set_memval(self, iaddr, address, srcval): try: if address.is_address(): if address.is_global_address( ) and self.libapp and self.instaticlib: return self.libglobalmem.set(iaddr, address, srcval) if address.is_global_address(): self.globalmem.set(iaddr, address, srcval) elif address.is_stack_address(): self.stackmem.set(iaddr, address, srcval) elif address.is_base_address(): base = address.get_base() if not base in self.basemem: self.basemem[base] = MM.MIPSimBaseMemory( self, base, buffersize=address.get_buffer_size()) self.basemem[base].set(iaddr, address, srcval) else: raise SU.CHBSimError( self, iaddr, 'set-memval: ' + str(address) + ' not recognized') else: self.add_logmsg( iaddr, 'attempt to address memory with absolute value: ' + str(address)) except SU.CHBSimError as e: self.add_logmsg(iaddr, 'error in set-memval: ' + str(e)) raise SU.CHBSimError(self, iaddr, 'set-memval: ' + str(address) + ': ' + str(e))
def get_lhs(self, iaddr, op): opkind = op.get_mips_opkind() if opkind.is_mips_register() or opkind.is_mips_special_register(): return MSL.MIPSimRegister(opkind.get_mips_register()) elif opkind.is_mips_indirect_register(): reg = opkind.get_mips_register() offset = opkind.get_offset() regval = self.get_regval(iaddr, reg) if self.instaticlib: if regval.is_literal( ) and regval.value > self.libimagebase.get_offset_value(): address = SSV.SimGlobalAddress(regval).add_offset(offset) return MSL.MIPSimMemoryLocation(address) if regval.is_literal( ) and regval.value > self.imagebase.get_offset_value(): address = SSV.SimGlobalAddress(regval).add_offset(offset) return MSL.MIPSimMemoryLocation(address) elif regval.is_address(): address = regval.add_offset(offset) return MSL.MIPSimMemoryLocation(address) else: raise SU.CHBSimError( self, iaddr, 'get-lhs: operand not recognized: ' + str(op) + ' (regval: ' + str(regval) + ')') else: raise SU.CHBSimError(self, iaddr, 'get-lhs: ' + str(op))
def simulate_block(self, simstate, blockaddr, processed): if not blockaddr in self.blocks: raise SU.CHBSimError(simstate, blockaddr, 'Block address not found: ' + str(blockaddr)) block = self.blocks[blockaddr] def f(_, i): i.simulate(simstate) processed.append(i) try: block.iter_instructions(f) return (block.baddr, processed) except SU.CHBSimError as e: e.set_instructions_processed(processed) raise except SU.SimFallthroughException as e: e.set_instructions_processed(processed) e.set_block_address(block.baddr) raise except SU.SimJumpException as e: processed.append(self.get_instruction(e.iaddr)) tgtaddr = str(e.tgtaddr) if tgtaddr in self.blocks: return self.simulate_block(simstate, tgtaddr, processed) else: targets = ','.join([str(t) for t in self.blocks]) eerror = SU.CHBSimError( simstate, e.iaddr, 'Target block address not found: ' + str(e.tgtaddr) + ' (targets: ' + targets + ')') raise eerror
def simulate(self, iaddr, simstate): ecxval = simstate.get_regval(iaddr, 'ecx') newval = ecxval.sub(SV.simone) simstate.set_register(iaddr, 'ecx', newval) tgtaddr = str(self.get_target_address()) if newval.value != 0: raise SU.KTSimJumpException(iaddr, tgtaddr) raise SU.KTSimFallthroughException(iaddr, tgtaddr)
def get_lhs(self, iaddr, op): opkind = op.get_opkind() if opkind.is_register(): return SL.SimRegister(opkind.get_register()) elif opkind.is_double_register(): return SL.SimDoubleRegister(opkind.get_reg_low(), opkind.get_reg_high()) elif opkind.is_indirect_register(): reg = opkind.get_register() offset = opkind.get_offset() regval = self.get_regval(iaddr, reg) if regval.is_address(): return SL.SimMemoryLocation(regval.add_offset(offset)) elif regval.value > self.imagebase.value: address = SSV.SimGlobalAddress(regval.value + offset) return SL.SimMemoryLocation(address) else: raise SU.CHBSimError( self, iaddr, 'get-lhs: operand not recognized: ' + str(op) + ' (regval: ' + str(regval) + ')') 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(): return SL.SimMemoryLocation(regval.add_offset(offset)) else: raise SU.CHBSimError( self, iaddr, 'get-lhs: operand not recognized: ' + str(op) + ' produces: ' + str(regval)) elif (not basereg is None) and ( not indexreg is None) and scale == 1: baseregval = self.get_regval(iaddr, basereg) indexval = self.get_regval(iaddr, indexreg) if indexval.is_address(): memaddress = indexval.add_offset( baseregval.to_signed_int()) memaddress = memaddress.add_offset(offset) return SL.SimMemoryLocation(memaddress) else: raise SU.CHBSimError( self, iaddr, 'get-lhs: operand not recognized(A): ' + str(op)) else: raise SU.CHBSimError( self, iaddr, 'get-lhs: operand not recognized(B): ' + str(op) + ' (scaled indirect)') else: raise SU.CHBSimError( self, iaddr, 'get-lhs: operand not recognized(C): ' + str(op))
def get_regval(self, iaddr, reg): if SU.is_half_reg(reg): fullreg = SU.get_full_reg(reg) if fullreg in self.registers: return self.registers[fullreg].get_low_word() raise SU.CHBSimError( self, iaddr, 'get_regval: no value found for ' + reg + ' (' + fullreg + ')') elif SU.is_qlow_reg(reg): fullreg = SU.get_full_reg(reg) if fullreg in self.registers: return self.registers[fullreg].get_low_byte() raise SU.CHBSimError( self, iaddr, 'get_regval: no value found for ' + reg + ' (' + fullreg + ')') elif SU.is_qhigh_reg(reg): fullreg = SU.get_full_reg(reg) if fullreg in self.registers: return self.registers[fullreg].get_snd_byte() raise SU.CHBSimError( self, iaddr, 'get_regval: no value found for ' + reg + ' (' + fullreg + ')') elif reg in self.registers: return self.registers[reg] else: self.add_logmsg(iaddr, 'no value for register ' + reg) return SV.simundefined
def set_byte3(self, b3): if b3.is_byte(): newval = SU.compute_dw_value(self.byte1, self.byte2, b3.value, self.byte4) newdefined = self.b1defined and self.b2defined and b3.is_defined( ) and self.b4defined return SimDoubleWordValue(newval, defined=newdefined, b1defined=self.b1defined, b2defined=self.b2defined, b3defined=b3.is_defined(), b4defined=self.b4defined) raise SU.CHBSimOpError('set byte3', [self, b3])
def set_byte1(self, b1): if b1.is_byte(): newval = SU.compute_dw_value(b1.value, self.byte2, self.byte3, self.byte4) newdefined = b1.is_defined( ) and self.b2defined and self.b3defined and self.b4defined return SimDoubleWordValue(newval, defined=newdefined, b1defined=not b1.is_defined(), b2defined=self.b2defined, b3defined=self.b3defined, b4defined=self.b4defined) raise SU.CHBSimOpError('set byte1', [self, b1])
def set_byte4(self, b4): if b4.is_byte(): newval = SU.compute_dw_value(self.byte1, self.byte2, self.byte3, b4.value) newdefined = self.b1defined and self.b2defined and self.b3defined and b4.is_defined( ) return SimDoubleWordValue(newval, defined=newdefined, b1defined=self.b1defined, b2defined=self.b2defined, b3defined=self.b3defined, b4defined=b4.is_defined()) raise SU.CHBSimOpError('set byte4', [self, b4])
def compose_simvalue(bytes): for b in bytes: if not check_byte(b): raise UF.CHBError('One of the bytes is not a literal value: ' + ','.join(str(b) for b in bytes)) if len(bytes) == 1: return bytes[0] elif len(bytes) == 2: b1 = bytes[0] b2 = bytes[1] if b1.is_defined() and b2.is_defined(): return SimWordValue((b2.value << 8) + b1.value) else: return SimWordValue(0, defined=False) elif len(bytes) == 4: b1 = bytes[0] b2 = bytes[1] b3 = bytes[2] b4 = bytes[3] if b1.is_defined() and b2.is_defined() and b3.is_defined( ) and b4.is_defined(): bval = SU.compute_dw_value(b1.value, b2.value, b3.value, b4.value) return SimDoubleWordValue(bval) else: return SimDoubleWordValue(0, defined=False) else: raise UF.CHBError('Number of bytes not supported: ' + str(len(bytes)))
def add(self, other): if other.is_defined() and other.is_literal(): return mk_libc_table_value(self.name, self.offset + other.value) else: raise SU.CHBError( 'Argument to libc-table-value.add not recognized: ' + str(other))
def simulate(self, iaddr, simstate): tag = self.tags[0] tgt = str(self.get_target_address()) def jump(): raise SU.KTSimJumpException(iaddr, tgt) def fallthrough(): raise SU.KTSimFallthroughException(iaddr, tgt) def undefined(flag): raise SU.KTCHBError('Flag value ' + flag + ' is undefined') if tag == 'jc': cf = simstate.get_flag_value('CF') if cf == 1: jump() elif cf == 0: fallthrough() else: undefined('CF') elif tag == 'jnz': zf = simstate.get_flag_value('ZF') if zf == 0: jump() elif zf == 1: fallthrough() else: undefined('ZF') else: raise SU.KTCHBError('Conditional jump tag not yet supported: ' + tag)
def set_lib_memval(self, iaddr, address, srcval): if address.is_address(): if address.is_global_address() and self.libapp: self.libglobalmem.set(iaddr, address, srcval) return raise SU.CHBSimError( self, iaddr, 'set-lib-memval: ' + str(address) + ' not supported')
def zero_extend(self, size): if self.is_defined(): if size == 2: return self if size == 4: return self.to_doubleword(signextend=False) raise UF.CHBError('Size for zero-extension not supported: ' + str(size)) raise SU.CHBSimValueUndefinedError('SimWordValue:zero_extend')
def to_doubleword(self, signextend=True): if self.is_defined(): if signextend: return SimDoubleWordValue(self.to_signed_int()) else: return SimDoubleWordValue(self.value) raise SU.CHBSimValueUndefinedError('SimWordValue.to_doubleword')
def get_arg_string(self, iaddr, reg): saddr = self.registers[reg] result = '' offset = 0 if saddr.is_literal(): if saddr.value > self.imagebase.get_offset_value(): saddr = SSV.SimGlobalAddress(saddr) else: raise SU.CHBSimError( self, iaddr, 'String argument is not a valid address: ' + str(saddr)) elif saddr.is_string_address(): return saddr.get_string() elif saddr.is_symbol(): return 'symbol:' + saddr.get_name() while True: srcaddr = saddr.add_offset(offset) srcval = self.get_memval(iaddr, srcaddr, 1) if srcval.is_defined(): if srcval.value == 0: break else: result += chr(srcval.value) offset += 1 else: break return result
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 is_not_equal(self, other): if other.is_literal(): result = 1 if self.value != other.value else 0 return SimBoolValue(result, self.is_defined() and other.is_defined()) raise SU.CHBSimValueUndefinedError('SimDoubleWordValue:is_not_equal ' + str(other))
def sign_extend(self, size): if self.is_defined(): if size == 2: return self if size == 4: return self.to_doubleword(signextend=True) raise UF.CHBError('Size of sign extension not supported: ' + str(size)) raise SU.CHBSimValueUndefinedError('SimWordValue.sign_extend')
def bitwise_xor(self, other): if other.is_literal(): newval = self.value ^ other.value return SimDoubleWordValue(newval, defined=self.is_defined() and other.is_defined()) raise SU.CHBSimValueUndefinedError('SimDoubleWordValue:bitwise_xor ' + str(other))
def modu(self, other): if other.is_literal() and other.value > 0: newval = self.value % other.value return SimDoubleWordValue(newval, defined=self.is_defined() and other.is_defined()) raise SU.CHBSimValueUndefinedError('SimDoubleWordValue:mod ' + str(other))
def mul(self, other): if other.is_literal(): newval = self.value * other.value return SimQuadWordValue(newval, defined=self.is_defined() and other.is_defined()) raise SU.CHBSimValueUndefinedError('SimDoubleWordValue:mul ' + str(other))
def sub(self, other): if other.is_literal(): newval = (self.value - other.value) % (SU.max32 + 1) return SimDoubleWordValue(newval, defined=self.is_defined() and other.is_defined()) raise SU.CHBSimValueUndefinedError('SimDoubleWordValue:sub ' + str(other))
def get_flag_value(self, flag): if flag in self.flags: if self.flags[flag].undefined: return None else: return self.flags[flag].value else: raise SU.CHBSimError(self, iaddr, 'flag not recognized: ' + flag)
def to_signed_int(self): if self.is_defined(): if self.is_negative(): return self.value - 256 else: return self.value else: raise SU.SimValueUndefinedError('SimByteValue: to_signed_int')
def set_low_word(self, w): if w.is_defined(): if w.is_word(): newval = w.value + ((self.value >> 16) << 16) return SimDoubleWordValue(newval, self.is_defined()) raise SU.CHBSimOpError('set word', [self, w]) else: return simundefinedDW
def to_signed_int(self): if self.is_defined(): if self.is_negative(): return self.value - (SU.max32 + 1) else: return self.value else: raise SU.CHBSimValueUndefinedError( 'SimDoubleWordValue:to_signed_int')
def bitwise_nor(self, other): if other.is_literal(): try: orvalue = self.bitwise_or(other) return orvalue.bitwise_not() except SU.CHBSimValueUndefinedError as e: raise SU.CHBSimValueUndefinedError( 'SimDoubleWordValue:bitwise_nor ' + str(other) + ': ' + str(e))