def add_data_label(self): dataoff = self.section_addr('.data') rodataoff = self.section_addr('.rodata') for e in self.locations: n, l = e if n == '.data': self.data_list[l] = (dec_hex(l + dataoff), self.data_list[l][1]) elif n == '.rodata': self.rodata_list[l] = (dec_hex(l + rodataoff), self.rodata_list[l][1])
def doublemovARM(self, instrs): """ insert labels for double mov operations movw r0, #0x102c -> movw r0, #:lower16:S_0x2102c movt r0, #0x2 -> movt r0, #:upper16:S_0x2102c :param instrs: instruction list """ for i in self.ARMmovs: mw = list(instrs[i]) destreg = mw[1] tindex = 1 while tindex < config.ARM_maxDoublemovDist: # GCC optimizations causes movw and movt not to be close to each other currinstr = instrs[i + tindex] if currinstr[0].upper() == 'MOV' and currinstr[2] == destreg: # Sometimes GCC changes idea and picks another register to load the address destreg = instrs[i + tindex][1] elif currinstr[1] == destreg: if currinstr[0].upper().split('.')[0] == 'STR': # Some other times GCC wants to have even more fun and changes register using the stack tindex += 1 while tindex < config.ARM_maxDoublemovDist: if instrs[i + tindex][2] == currinstr[2]: destreg = instrs[tindex + i][1] break tindex += 1 else: break tindex += 1 if tindex >= config.ARM_maxDoublemovDist: continue tindex = i + tindex mt = list(instrs[tindex]) if mt[0].upper().startswith('MOVT') and mt[1] == destreg: val = (mt[2] << 16) + (mw[2] & 0xffff) s = self.check_sec(val) if s is not None: s_label = 'S_' + dec_hex(val) self.insert_data(s.sec_name, val) mw[2] = Types.Label('#:lower16:' + s_label) mt[2] = Types.Label('#:upper16:' + s_label) instrs[i] = type(instrs[i])(mw) instrs[tindex] = type(instrs[tindex])(mt) if self.check_text(val): val = val & (-2) s_label = 'S_' + dec_hex(val) self.insert_text(s_label, val) mw[2] = Types.Label('#:lower16:' + s_label) mt[2] = Types.Label('#:upper16:' + s_label) instrs[i] = type(instrs[i])(mw) instrs[tindex] = type(instrs[tindex])(mt) self.ARMmovs = []
def process(self): """ Traverse instruction list and insert generated S_ labels in the correct positions """ do_update = lambda s, n: s if n in s else s + '\n' + n des1 = self.clean_sort(self.des) i = 0 j = 0 while True: if j == len(des1) or i == len(self.locs): break # if i == len(self.locs)-1 and j == len(des1)-1: # raise Exception("undefined des list") lh = self.locs[i] dh = des1[j] if dh == lh.loc_addr: lhs = 'S_' + dec_hex(lh.loc_addr) if ELF_utils.elf_arm() and not isinstance( self.instr_list[i][0], Types.InlineData): lhs = '.thumb_func\n' + lhs label = do_update(lh.loc_label, lhs + ' : ') self.locs[i].loc_label = label j += 1 elif dh < lh.loc_addr: i -= 1 j += 1 i += 1
def update(self): func = 'S_' + dec_hex(self.baddr) if func in self.func_set: self.func_set[func].func_begin_addr = self.baddr self.func_set[func].func_end_addr = self.eaddr self.func_set[func].is_lib = False else: f1 = Func(func, self.baddr, self.eaddr, False) self.func_set[func] = f1
def data_dump(self, funcs): """ Analyze data sections and save them to file :param funcs: function list """ t = self.label + self.export_data_dump() p = datahandler(t) p.text_sec_collect() p.set_datas(funcs) self.jmpreflist = map(lambda l: 'S_' + dec_hex(l), p.get_textlabel()) p.data_output()
def v_exp(self, e): """ Check if PC relative expression and transform using labels :param e: expression :return: transformed expression if matching, original one otherwise """ if isinstance(e, (Types.BinOP_PLUS, Types.BinOP_MINUS)): r1, addr = e if r1.upper() in self.curr_regs: addr = -addr if isinstance(e, Types.BinOP_MINUS) else addr des = self.gotaddr + addr s = self.check_sec(des) if s is not None: self.label.append(des) return Types.Label('S_' + dec_hex(des)) return e
def gotexternals(self): """ Replace external symbols in .got """ with open('gotglobals.info') as f: def mapper(l): items = l.split() return (int(items[0], 16), items[1].split('@')[0]) syms = sorted(map(mapper, f), key=lambda e: e[0]) gotsec = self.sec['.got'] datatype = '.long ' if ELF_utils.elf_32() else '.quad ' skiplen = 3 if ELF_utils.elf_32() else 7 syms = filter( lambda s: gotsec.sec_begin_addr <= s[0] < gotsec.sec_begin_addr + gotsec.sec_size, syms) for s in syms: off = s[0] - gotsec.sec_begin_addr self.got_list[off] = ('S_' + dec_hex(s[0]) + ': ', datatype + s[1]) self.got_list[off + 1:off + 1 + skiplen] = [('', '')] * skiplen
def process(self, lbs, withoff=False): """ Add labels in the corresponding addresses of data sections :param lbs: list of tuples (section name, absolute address or offset) :param withoff: if True lbs contains absolute addresses """ ds = { '.data': self.data_list, '.rodata': self.rodata_list, '.got': self.got_list, '.bss': self.bss_list } for i in xrange(len(lbs)): n, l = lbs[i] if n in ds: if withoff: off = l - self.section_addr(n) else: off = l l += self.section_addr(n) ds[n][off] = ('S_' + dec_hex(l) + ': ', ds[n][off][1])
def v_exp2(self, exp, instr, f, chk): """ Analyze expression and determine if it represent an address. If so substitute if with a corresponding symbolic expression using labels :param exp: expression :param instr: instruction tuple to which the expression belongs to :param f: unused :param chk: True if instruction is TEST (x86) :return: modified expression if matching, original one otherwise """ if isinstance(exp, Types.Const): if isinstance(exp, Types.Normal) and chk: return exp s = self.check_sec(exp) if s is not None: self.insert_data(s.sec_name, exp) return Types.Label(self.build_symbol(exp)) if self.check_text(exp): if ELF_utils.elf_arm(): exp = type(exp)(exp & (-2)) s_label = self.build_symbol(exp) self.insert_text(s_label, exp) return Types.Label(s_label) if self.check_plt(exp): return Types.Label(self.build_plt_symbol(exp)) elif isinstance(exp, Types.Symbol): if isinstance(exp, Types.JumpDes): if self.check_text(exp): s_label = 'S_' + dec_hex(exp) self.insert_text(s_label, exp) return Types.Label(s_label) elif self.check_plt(exp) and exp in self.plt_hash: return Types.Label(self.plt_hash[exp]) elif isinstance(exp, Types.StarDes): return Types.StarDes(self.v_exp2(exp.content, instr, f, chk)) elif isinstance(exp, Types.CallDes): if exp.func_name.startswith('S_0'): addr = int(exp.func_name[2:], 16) if self.check_text(addr): s_label = 'S_' + dec_hex(addr) self.insert_text(s_label, addr) return Types.Label(s_label) elif self.check_plt(addr): off = 0 while not self.plt_hash.get(addr - off, None): off += 2 return Types.Label(self.plt_hash[addr - off]) else: self.symbol_list.insert(0, exp.func_begin_addr) elif isinstance(exp, Types.Ptr): if isinstance(exp, (Types.BinOP_PLUS, Types.BinOP_MINUS)): r, addr = exp s = self.check_sec(addr) if s is not None: s_label = 'S_' + dec_hex(addr) self.insert_data(s.sec_name, addr) return Types.BinOP_PLUS_S((r, s_label)) \ if isinstance(exp, Types.BinOP_PLUS) \ else Types.BinOP_MINUS_S((r, s_label)) elif isinstance(exp, (Types.FourOP_PLUS, Types.FourOP_MINUS)): r1, r2, off, addr = exp s = self.check_sec(addr) if s is not None: s_label = 'S_' + dec_hex(addr) self.insert_data(s.sec_name, addr) return Types.FourOP_PLUS_S((r1,r2,off,s_label)) \ if isinstance(exp, Types.FourOP_PLUS) \ else Types.FourOP_MINUS_S((r1,r2,off,s_label)) elif isinstance(exp, Types.JmpTable_PLUS): addr, r, off = exp s = self.check_sec(addr) if s is not None: s_label = 'S_' + dec_hex(addr) self.insert_data(s.sec_name, addr) return Types.JmpTable_PLUS_S((s_label, r, off)) if self.check_text(addr): s_label = 'S_' + dec_hex(addr) self.insert_text(s_label, addr) return Types.JmpTable_PLUS_S((s_label, r, off)) elif isinstance(exp, Types.JmpTable_MINUS): addr, r, off = exp s = self.check_sec(addr) if s is not None: s_label = '-S_' + dec_hex(addr) self.insert_data(s.sec_name, addr) return Types.JmpTable_MINUS_S((s_label, r, off)) if self.check_text(addr): s_label = '-S_' + dec_hex(addr) self.insert_text(s_label, addr) return Types.JmpTable_MINUS_S((s_label, r, off)) return exp
def build_symbol(self, c): if isinstance(c, Types.Point): return 'S_' + dec_hex(c) elif isinstance(c, Types.Normal): return reassemble.normal_char + 'S_' + dec_hex(c)
def dump_c2d_labels(self, dl): with open('final_c2d_label.txt', 'a') as f: f.write('\n'.join(map(lambda e: e[0] + ' : ' + dec_hex(e[1]), dl))) f.write('\n')
def print_cfi_specified_graph(self): self.cfi_specified_tbl() for k, v in self.cfi_tbl.iteritems(): print k for l in v: print ' ' + dec_hex(l)
def print_cg_graph(self): for k, v in self.cfi_tbl.iteritems(): sys.stdout.write(dec_hex(k)) for f in v: print ' ' + f.func_name
def func_info(self, l): for h in self.funcs: if h.func_begin_addr <= l.loc_addr < h.func_end_addr: return h raise Exception( dec_hex(l.loc_addr) + ': cannot find corresponding function')