def __init__(self, proj, name, target, cond, addr): super(CallInstruction, self).__init__(name, addr) # XXX: IDIOM [CALL HL] if hasattr(target, 'value') and target.value == 0x00A0: target = placeholders.HL # XXX: IDIOM [CALL BC] if hasattr(target, 'value') and target.value == 0x0CDA: target = placeholders.BC # XXX: IDIOM [CALL LONG E:HL] if hasattr(target, 'value') and target.value == 0x008A: target = ComputedProcAddress(placeholders.E, placeholders.HL) self.cond = cond if hasattr(target, 'getAddress'): self.targetAddr = target.getAddress() self.target = ProcAddress(self.targetAddr) elif hasattr(target, 'value') and target.value is not None: self.targetAddr = address.fromVirtualAndCurrent(target.value, addr) self.target = ProcAddress(self.targetAddr) else: self.targetAddr = address.fromVirtual(0x4000) # XXX: ambiguous address self.target = target self.target_depset = proj.database.procInfo(self.targetAddr).depset self.returns_used = ALL_REGS self.constant_params = dict()
def render(self, r): """ Writes the procedure info, name, the callers, callees etc :param r: """ with r.lineAddress(self.addr), r.comment(): r.write("Menu: /home | /data | /jump | /proc | /bank") r.hline() r.startNewLine() r.write("Procedure flow ") r.writeSymbol(self.addr, 'procedure') r.startNewLine() r.write(" This procedure is called by: ") r.writeList(ProcAddress(x) for x in sorted(self.info.callers)) r.startNewLine() r.write(" This procedure calls: ") r.writeList(ProcAddress(x) for x in sorted(self.proc.calls())) r.hline() with r.indent(): self.proc.render(r)
def render(self, renderer): c = self.proj.database.connection.cursor() c.execute('select addr from procs where has_ambig_calls=1') renderer.startNewLine() renderer.add('ambig calls:') with renderer.indent(): for addr, in c.fetchall(): renderer.startNewLine() ProcAddress(addr).render(renderer) c.execute('select addr from procs where suspicious_switch=1') renderer.startNewLine() renderer.add('suspicious switch:') with renderer.indent(): for addr, in c.fetchall(): renderer.startNewLine() ProcAddress(addr).render(renderer) c.execute('select addr from procs where has_suspicious_instr=1') renderer.startNewLine() renderer.add('suspicious instr:') with renderer.indent(): for addr, in c.fetchall(): renderer.startNewLine() ProcAddress(addr).render(renderer) c.close()
def optimizedWithContext(self, ctx): self.target = self.target.optimizedWithContext(ctx) if hasattr(self.target, 'getAddress'): self.targetAddr = self.target.getAddress() elif hasattr(self.target, 'value') and self.target.value is not None: self.targetAddr = address.fromVirtualAndCurrent(self.target.value, self.addr) self.target = ProcAddress(self.targetAddr) else: pass # XXX deps = self.getDependencySet() ins = joinRegisters(deps.reads - set(['mem'])) for param in ins: if ctx.hasConstantValue(param): self.constant_params[param] = ctx.getValue(param) for w in deps.writes: ctx.setValueComplex(w) # TODO: XXX if self.targetAddr.virtual() == 0x07B9: if 'A' in self.constant_params: ctx.setValue('ROMBANK', self.constant_params['A']) return self
def render(self, renderer): bank_name = "{:04X}".format(self.bank) c = self.proj.database.connection.cursor() renderer.startNewLine() renderer.add('public interface:') c.execute( 'select destination from calls where substr(source, 0, 5)<>? and substr(destination, 0, 5)=? group by destination order by destination', (bank_name, bank_name)) with renderer.indent(): for addr, in c.fetchall(): renderer.startNewLine() ProcAddress(addr).render(renderer) renderer.startNewLine() renderer.add('dependencies:') c.execute( 'select destination from calls where substr(source, 0, 5)=? and substr(destination, 0, 5)<>? group by source order by source', (bank_name, bank_name)) with renderer.indent(): for addr, in c.fetchall(): renderer.startNewLine() ProcAddress(addr).render(renderer) renderer.startNewLine() renderer.add('reads:') c.execute( 'select addr from memref where substr(proc, 0, 5)=? and type=? group by addr order by addr', (bank_name, 'read')) with renderer.indent(): for addr, in c.fetchall(): renderer.startNewLine() DataAddress(addr).render(renderer) renderer.startNewLine() renderer.add('writes:') c.execute( 'select addr from memref where substr(proc, 0, 5)=? and type=? group by addr order by addr', (bank_name, 'write')) with renderer.indent(): for addr, in c.fetchall(): renderer.startNewLine() DataAddress(addr).render(renderer) c.close()
def render(self, r): with r.lineAddress(self.addr), r.comment(): r.hline() r.startNewLine() r.write("data ") r.writeSymbol(self.addr, 'data') r.startNewLine() r.write(" reads: ") r.writeList(ProcAddress(x) for x in sorted(self.reads)) r.startNewLine() r.write(" writes: ") r.writeList(ProcAddress(x) for x in sorted(self.writes)) r.hline()
def addFakeBlock(self, proj, addr): pos = len(self.blocks) self.block_id_at_addr[addr] = pos instr = TailCall(proj, ProcAddress(addr)) from .flowcontrol import Block self.blocks.append(Block([instr])) self.block_starts.append(addr) self._childs[pos] = [None]
def render(self, r): with r.lineAddress(self.addr), r.comment(): r.hline() r.startNewLine() r.write("procedure ") r.writeSymbol(self.addr, 'procedure') r.startNewLine() r.write(" callers: ") r.writeList(ProcAddress(x) for x in sorted(self.info.callers)) r.startNewLine() r.write(" calls: ") r.writeList(ProcAddress(x) for x in sorted(self.info.calls)) r.hline() with r.indent(): self.proc.render(r)
class JumpInstruction(Instruction): def __init__(self, name, target, cond, addr, reads, writes): super(JumpInstruction, self).__init__(name, addr) self._reads = reads self._writes = writes self.cond = cond if hasattr(target, 'getAddress'): self.targetAddr = target.getAddress() self.target = target elif target.value is not None: self.targetAddr = address.fromVirtualAndCurrent(target.value, addr) self.target = ProcAddress(self.targetAddr) else: self.targetAddr = None self.target = target def optimizedWithContext(self, ctx): return JumpInstruction(self.name, self.target.optimizedWithContext(ctx), self.cond, self.addr, self._reads, self._writes) def getDependencies(self, needed): return (needed - self._writes) | self._reads def getDependencySet(self): return DependencySet(self._reads, self._writes) def hasContinue(self): try: return not self.cond.alwaysTrue() except AttributeError: return True def jumps(self): if self.targetAddr and not self.targetAddr.isAmbiguous(): return set([self.targetAddr]) else: return set() def allJumps(self): if self.targetAddr: return [self.targetAddr] else: return [] def operands(self): if not self.cond.alwaysTrue(): return [self.target, self.cond] else: return [self.target]
def __init__(self, proj, addr): self.addr = addr self.targets = [] for i in range(256): a = addr.offset(i * 2) lo = proj.rom.get(a) hi = proj.rom.get(a.offset(1)) value = address.fromVirtualAndCurrent((hi << 8) | lo, addr) if not value.inPhysicalMem(): break self.targets.append(ProcAddress(value))
def __init__(self, name, target, cond, addr, reads, writes): super(JumpInstruction, self).__init__(name, addr) self._reads = reads self._writes = writes self.cond = cond if hasattr(target, 'getAddress'): self.targetAddr = target.getAddress() self.target = target elif target.value is not None: self.targetAddr = address.fromVirtualAndCurrent(target.value, addr) self.target = ProcAddress(self.targetAddr) else: self.targetAddr = None self.target = target
def __init__(self, proj, addr): self.addr = addr self.targets = [] romconfig = Config(proj.filename, rom=True) jumptables = romconfig.get(["Analysis", "Jumptable-List"]) try: size = jumptables[str(addr)] except KeyError: size = 256 for i in range(size): a = addr.offset(i * 2) lo = proj.rom.get(a) hi = proj.rom.get(a.offset(1)) value = address.fromVirtualAndCurrent((hi << 8) | lo, addr) if not value.inPhysicalMem(): print "breaking" break self.targets.append(ProcAddress(value))
class CallInstruction(Instruction): def __init__(self, proj, name, target, cond, addr): super(CallInstruction, self).__init__(name, addr) # XXX: IDIOM [CALL HL] if hasattr(target, 'value') and target.value == 0x00A0: target = placeholders.HL # XXX: IDIOM [CALL BC] if hasattr(target, 'value') and target.value == 0x0CDA: target = placeholders.BC # XXX: IDIOM [CALL LONG E:HL] if hasattr(target, 'value') and target.value == 0x008A: target = ComputedProcAddress(placeholders.E, placeholders.HL) self.cond = cond if hasattr(target, 'getAddress'): self.targetAddr = target.getAddress() self.target = ProcAddress(self.targetAddr) elif hasattr(target, 'value') and target.value is not None: self.targetAddr = address.fromVirtualAndCurrent(target.value, addr) self.target = ProcAddress(self.targetAddr) else: self.targetAddr = address.fromVirtual(0x4000) # XXX: ambiguous address self.target = target self.target_depset = proj.database.procInfo(self.targetAddr).depset self.returns_used = ALL_REGS self.constant_params = dict() def getDependencies(self, needed): #return flow.getProcDeps(self.targetAddr, needed) deps = self.getDependencySet() return (needed - deps.writes) | deps.reads def getDependencySet(self): reads = set(self.target_depset.reads) for r in joinRegisters(reads): if r in self.constant_params: reads -= splitRegister(r) return DependencySet(reads, self.target_depset.writes) def optimizeDependencies(self, needed): self.returns_used = needed & self.getDependencySet().writes return self def optimizedWithContext(self, ctx): self.target = self.target.optimizedWithContext(ctx) if hasattr(self.target, 'getAddress'): self.targetAddr = self.target.getAddress() elif hasattr(self.target, 'value') and self.target.value is not None: self.targetAddr = address.fromVirtualAndCurrent(self.target.value, self.addr) self.target = ProcAddress(self.targetAddr) else: pass # XXX deps = self.getDependencySet() ins = joinRegisters(deps.reads - set(['mem'])) for param in ins: if ctx.hasConstantValue(param): self.constant_params[param] = ctx.getValue(param) for w in deps.writes: ctx.setValueComplex(w) # TODO: XXX if self.targetAddr.virtual() == 0x07B9: if 'A' in self.constant_params: ctx.setValue('ROMBANK', self.constant_params['A']) return self def calls(self): if self.targetAddr.inPhysicalMem() and not self.targetAddr.isAmbiguous(): return set([self.targetAddr]) else: return set([]) def operands(self): if not self.cond.alwaysTrue(): return [self.target, self.cond] else: return [self.target] def fillParamIfKnown(self, param): if param in self.constant_params: return param + '=' + str(self.constant_params[param]) else: return param def signature(self): x = '' if not self.cond.alwaysTrue(): x = 'CONDITIONAL' depset = self.getDependencySet().onlyRegisters() ins = joinRegisters(depset.reads - set(['mem'])) outs = joinRegisters(self.returns_used - set(['mem'])) ins |= set(param+'='+str(self.constant_params[param]) for param in self.constant_params) ins = ', '.join(sorted(ins)) outs = ', '.join(sorted(outs)) if ins: ins = ' @ (' + ins + ')' if not outs: outs = 'void' return x + ins + ' -> ' + outs