def lookup_rel(target, r, symtab, strtab): r_type = r.r_info & 0xff pos = r.r_info >> 8 addr = r.r_offset symbol = Elf32Sym( target.memory.getrange(symtab+pos*16 , symtab+pos*16 + 16)) if(symbol.st_name): string_ptr = symbol.st_name + strtab name = util.pull_ascii(target.memory, string_ptr) return name else: return "!unknown"
def transform(arch, callgraph, bin): sg = callgraph.keys() sg.sort() constant_regs = arch.get_analysis_constant_regs(bin) for r in arch.registers: if "stack" in r.aliases: stack_reg = r elif "pc" in r.aliases: pc_reg = r for func in sg: for block in callgraph[func]: for instr in block.code: aux_loc = block.code.index(instr) if instr.type == 'operation': #check for stack assignment operation if len(instr.ops) > 2: if instr.ops[1] == '=': reg_name = str(instr.ops[0].register_name) if reg_name in block.ssa_vals: #here we look at addr+1 because we're interested in the result after # this instruction values = block.ssa_vals[reg_name].get_states(instr.address, aux_loc+1) out = "" for value in values: if isinstance(value, int): if value in bin.memory: data = util.pull_ascii(bin.memory, value) if len(data) > 1: out += ' @@@@@ ' + `data` + '\n' else: n = [] for v in values: #dont print out if unresolved remain if isinstance(v, ssa.ssa_state): if None not in v.eval(): n += ['{'+",".join(str(x) for x in v.eval())+'}'] else: n += [str(v)] else: n += [str(v)] out += str(n) instr.annotation += " "*20 + out elif instr.type == 'load': src_addrs = block.ssa_vals[str(instr.src.register_name)].get_values(instr.address, aux_loc) if None in src_addrs: src_addrs = block.ssa_vals[str(instr.src.register_name)].get_states(instr.address, aux_loc) for src_addr in src_addrs: if isinstance(src_addr,int): addr = src_addr #update on load if addr in bin.memory and addr+instr.size in bin.memory: sizemap = {1: 'B', 2: 'H', 4: 'L', 8: 'Q'} value = struct.unpack(arch.endianness + "%s"%sizemap[instr.size], bin.memory.getrange(addr, instr.size+addr))[0] value = "%d"%value if value in bin.memory: data = util.pull_ascii(bin.memory, value) if len(data) > 1: value = data instr.annotation = "%%%% (%s) <- addr_%x"%(value,addr) else: instr.annotation = " "*10+"%s <- addr_[%s]"%(instr.dest, src_addr) elif instr.type == 'store': if instr.src.type == 'register': src_name = str(instr.src.register.register_name) src_addrs = block.ssa_vals[src_name].get_values(instr.address, aux_loc) if None in src_addrs: src_addrs = block.ssa_vals[src_name].get_states(instr.address, aux_loc) else: src_addrs = [instr.src.value] if instr.dest.type == 'register': dest_addrs = block.ssa_vals[str(instr.dest.register.register_name)].get_values(instr.address, aux_loc) if None in dest_addrs: dest_addrs = block.ssa_vals[str(instr.dest.register.register_name)].get_states(instr.address, aux_loc) else: dest_addrs = [instr.dest.value] o = "" for src_addr in src_addrs: for dest_addr in dest_addrs: o += " "*20 + " %s -> %s OR\n"%(src_addr, dest_addr) o = o[:-3] instr.annotation = o elif instr.type == 'call' or instr.type == 'jump': libcall_transform(arch, block.ssa_vals, instr, aux_loc)
def mips_resolve_external_funcs(target): #XXX this is irix specific right now funcs = {} addr = 0 for phdr in target.binformat.Phdrs: if phdr.type == PT_DYNAMIC: addr = phdr.vaddr break strsz = None strtab = None symtab = None dthash = None pltgot = None Edyn = Elf32Dyn(target.memory.getrange(addr, addr+8), target.binformat.endianness) while Edyn.d_tag != DT_NULL: #print hex(addr),'>>>>= ',hex(Edyn.d_tag), hex(Edyn.d_val) if Edyn.d_tag == DT_STRTAB: strtab = Edyn.d_val #print "STRTAB" elif Edyn.d_tag == DT_SYMTAB: symtab = Edyn.d_val #print "SYMTAB", hex(symtab) elif Edyn.d_tag == DT_HASH: dthash = Edyn.d_val #print "HASH" elif Edyn.d_tag == DT_STRSZ: strsz = Edyn.d_val #print "STRSZ" elif Edyn.d_tag == DT_PLTGOT: pltgot = Edyn.d_val elif Edyn.d_tag == 0x7000000a: localgotno = Edyn.d_val elif Edyn.d_tag == 0x70000011: symtabno = Edyn.d_val elif Edyn.d_tag == 0x70000013: gotsym = Edyn.d_val addr += 8 Edyn = Elf32Dyn(target.memory.getrange(addr, addr+8), target.binformat.endianness) #BUGCHECK this is pulled together from comparing # a bunch of different irix binaries with elfdump + elfls + objdump addr = symtab+16 Esym = Elf32Sym(target.memory.getrange(addr, addr+16), target.binformat.endianness) i = 1 while Esym.st_name != 0: if i >= gotsym: entry_addr = (localgotno+i-gotsym)*4+pltgot value = struct.unpack(">L", target.memory.getrange(entry_addr, entry_addr+4))[0] #print "=>>>>", util.pull_ascii(target.memory, strtab+Esym.st_name), hex(Esym.st_size),\ # hex(Esym.st_value), hex(Esym.st_info), hex(Esym.st_other),\ # hex(Esym.st_shndx), "%x %x"%(addr, value) funcs[value] = util.pull_ascii(target.memory, strtab+Esym.st_name) i += 1 addr += 16 Esym = Elf32Sym(target.memory.getrange(addr, addr+16), target.binformat.endianness) return funcs