def update_cfd(self, index, instrlist): if not self.looking_for_cfd: return tl = instrlist[index:index + 5] inv = lambda i: get_loc(i).loc_addr in self.locs if not any(map(inv, tl)): self.looking_for_cfd = False self.update_trimtbl(self.up_bound.loc_addr, get_loc(tl[0]).loc_addr)
def vinst(self, i): loc = get_loc(i) if self.skip_entry: if loc.loc_addr == self.end_loc.loc_addr: bn = 'BB_' + str(cfg.counter) cfg.counter += 1 b = Types.Bblock('', bn, loc, loc, i) self.bb_list.insert(0, b) else: self.entry_loc = loc self.entry_instr = i self.found_entry = True self.skip_entry = False self.last_loc = loc return self.help_exit( i) if Opcode_utils.is_control_transfer_op(i[0]) else i elif loc.loc_addr == self.end_loc.loc_addr: return self.help_exit(i) elif self.bb_entry(i): self.help_entry(i) return self.help_exit(i) if Opcode_utils.is_control_transfer_op( i[0]) else i elif isinstance( i, (Types.DoubleInstr, Types.SingleInstr)) and self.bb_exit(i[0]): return self.help_exit(i) self.last_loc = loc return i
def visit(self, instrlist): self.locs = filter( lambda i: self.invalid_opcode(i) or self.invalid_transfer(i), instrlist) self.locs = map(lambda i: get_loc(i).loc_addr, self.locs) if len(self.locs) != 0: self.validate(instrlist) return instrlist
def unify_loc(self, instrs): last_label = '' for i in xrange(len(instrs)): lo = get_loc(instrs[i]) if lo.loc_label != '' and lo.loc_label == last_label: instrs[i] = set_loc(instrs[i], Types.Loc('', lo.loc_addr, True)) else: last_label = lo.loc_label return instrs
def build_func_info(self): self.func_begins = unify_int_list(self.func_begins) self.func_begins = self.filter_addr_by_secs(self.func_begins) for i in range(len(self.func_begins)-1): self.baddr = self.func_begins[i] self.eaddr = self.func_begins[i+1] self.update() self.baddr = self.func_begins[-1] self.eaddr = get_loc(self.instrs[0]).loc_addr self.update()
def help_entry(self, i): if self.found_entry: bn = 'BB_' + str(cfg.counter) cfg.counter += 1 b = Types.Bblock('', bn, self.entry_loc, self.last_loc, self.entry_instr) self.bb_list.insert(0, b) self.found_entry = True self.entry_instr = i self.entry_loc = get_loc(i) self.last_loc = self.entry_loc return i
def visit(self, instrs): self.end_loc = get_loc(instrs[-1]) il1 = map(self.vinst, instrs) self.update_bl() self.fb_list(self.bl) self.bl_sort = sorted(self.bl, cmp=lambda b1, b2: b1.bblock_begin_loc.loc_addr - b2.bblock_begin_loc.loc_addr) self.bl_sort = map( lambda b: tb(b.bblock_name, b.bblock_begin_loc.loc_addr, b. bblock_end_loc.loc_addr), self.bl_sort) return il1
def visit_heuristic_analysis(self, instrs): func = lambda i: self.check_text(get_loc(i).loc_addr) self.instr_list = instrs tl = map(lambda i: self.vinst2(func, i), instrs) is_32 = 1 if ELF_utils.elf_32() else 0 def desmapper(l): try: return int(l[2:10 + is_32], 16) except: return int(l[3:11 + is_32], 16) tl1 = map(desmapper, self.deslist) self.symbol_list = tl1 + self.symbol_list return tl
def add_func_label(self, ufuncs, instrs): i = 0 j = 0 while True: if i == len(ufuncs) or j == len(instrs): break hf = ufuncs[i] hi = instrs[j] iloc = get_loc(hi) if hf.func_begin_addr == iloc.loc_addr: iloc.loc_label = '\n' + hf.func_name + ' : ' + iloc.loc_label instrs[j] = set_loc(hi, iloc) i += 1 j -= 1 elif hf.func_begin_addr < iloc.loc_addr: i += 1 j += 1 return instrs
def help_exit(self, i): loc = get_loc(i) if self.found_entry: self.last_loc = loc bn = 'BB_' + str(cfg.counter) cfg.counter += 1 b = Types.Bblock('', bn, self.entry_loc, self.last_loc, self.entry_instr) self.bb_list.insert(0, b) self.found_entry = False self.skip_entry = True elif loc.loc_addr == self.end_loc.loc_addr: bn = 'BB_' + str(cfg.counter) cfg.counter += 1 b = Types.Bblock('', bn, loc, loc, i) self.bb_list.insert(0, b) else: self.last_loc = loc return i
def add_bblock_label(self, bbl, instrs): bbl1 = sorted( bbl, lambda b1, b2: b1.bblock_begin_loc.loc_addr - b2. bblock_begin_loc.loc_addr) i = 0 j = 0 while True: if i == len(instrs) and j < len(bbl1): raise Exception('failed to add block label') if j == len(bbl1): break hi = instrs[i] hb = bbl1[j] iloc = get_loc(hi) bloc = hb.bblock_begin_loc if bloc.loc_addr == iloc.loc_addr: iloc = Types.Loc(hb.bblock_name + ': ' + iloc.loc_label, iloc.loc_addr, iloc.loc_visible) instrs[i] = set_loc(instrs[i], iloc) j += 1 i += 1 return instrs
def validate(self, instrlist): self.five_q = simple_queue() for (index, i) in enumerate(instrlist): loc = get_loc(i) if loc.loc_addr in self.locs: self.up_bound = dis_validator.icf_stack.pop() self.looking_for_cfd = True else: if len(loc.loc_label) > 1: self.update_cfd(index) self.update_cft_track(i) else: p = get_op(i) e = get_cf_des(i) if p == 'CALL': print "detected call instruction in disassembly validator" self.update_cfd(index + 1) if self.is_icf(p, e): self.update_cft_stack(i) elif self.is_icf(p, e): self.update_cft_stack(i) self.update_cft_track(i)
def aux(bnl, acc, i): if isinstance(i, Types.SingleInstr) and Opcode_utils.is_ret(i[0]): bn = self.bbn_byloc(get_loc(i).loc_addr) acc.insert(0, (bn, (Types.J(), 'RET'))) elif isinstance(i, Types.DoubleInstr): if Opcode_utils.is_indirect(i[1]): bn = self.bbn_byloc(get_loc(i).loc_addr) acc.insert(0, (bn, (Types.J(), 'T'))) elif Opcode_utils.is_call(i[0]): bn = self.bbn_byloc(get_loc(i).loc_addr) bn1 = self.next_bb(bnl, bn) acc.insert(0, (bn, (Types.J(), bn1))) acc.insert(0, (bn, (Types.J(), 'INTER'))) elif Opcode_utils.is_jmp(i[0]): bn = self.bbn_byloc(get_loc(i).loc_addr) if Opcode_utils.is_func(i[1]): acc.insert(0, (bn, (Types.J(), 'INTER'))) else: en = recover_addr_from_label(p_exp(i[1])) if en == -1: acc.insert(0, (bn, (Types.J(), 'T'))) else: dn = self.bbn_byloc(en) acc.insert(0, (bn, (Types.J(), dn))) elif Opcode_utils.is_cond_jmp(i[0]): if not Opcode_utils.is_func(i[1]): bn = self.bbn_byloc(get_loc(i).loc_addr) sn = self.next_bb(bnl, bn) acc.insert(0, (bn, (Types.F(), sn))) else: assert (False) else: bn = self.bbn_byloc(get_loc(i).loc_addr) dn = self.next_bb(bnl, bn) acc.insert(0, (bn, (Types.F(), dn))) return acc
def bb_entry(self, i): return ':' in get_loc(i).loc_label
def v_exp2(self, exp, instr, f, chk): # TODO: create subfunctions to simplify this mess # check_test_condition = lambda l,c: not (isinstance(l, Types.Normal) and c) if isinstance(exp, Types.Const): if isinstance(exp, Types.Normal) and chk: return exp l1 = self.parse_const(exp) s = self.check_sec(l1) if s is not None: s_label = self.build_symbol(exp) loc1 = get_loc(instr) if not self.has_data(l1): reassemble.data_set[l1] = '' self.label.insert(0, (s.sec_name, l1)) self.c2d_addr.insert(0, loc1.loc_addr) return Types.Label(s_label) if self.check_text(l1): s_label = self.build_symbol(exp) loc1 = get_loc(instr) if not self.has_text(l1): reassemble.text_set[l1] = '' self.deslist.insert(0, s_label) self.deslist_reloc.insert(0, loc1.loc_addr) return Types.Label(s_label) if self.check_plt(l1): 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) if not self.has_text(exp): reassemble.text_set[exp] = '' self.deslist.insert(0, s_label) return Types.Label(s_label) elif isinstance(exp, Types.StarDes): return Types.StarDes(self.v_exp2(exp.content, instr, f, chk)) elif isinstance(exp, Types.CallDes): fn = exp.func_name[2:] is_dig_loc = False try: addr = int(fn, 16) is_dig_loc = True except: self.symbol_list.insert(0, exp.func_begin_addr) if is_dig_loc: if self.check_text(addr): s_label = 'S_' + dec_hex(addr) if not self.has_text(addr): reassemble.text_set[addr] = '' self.deslist.insert(0, s_label) return Types.Label(s_label) 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) loc1 = get_loc(instr) if not self.has_data(addr): reassemble.data_set[addr] = '' self.label.insert(0, (s.sec_name, addr)) self.c2d_addr.insert(0, loc1.loc_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) loc1 = get_loc(instr) if not self.has_data(addr): reassemble.data_set[addr] = '' self.label.insert(0, (s.sec_name, addr)) self.c2d_addr.insert(0, loc1.loc_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) loc1 = get_loc(instr) if not self.has_data(addr): reassemble.data_set[addr] = '' self.label.insert(0, (s.sec_name, addr)) self.c2d_addr.insert(0, loc1.loc_addr) return Types.JmpTable_PLUS_S((s_label, r, off)) if self.check_text(addr): s_label = 'S_' + dec_hex(addr) loc1 = get_loc(instr) if not self.has_text(addr): reassemble.text_set[addr] = '' self.deslist.insert(0, s_label) self.deslist_reloc.insert(0, loc1.loc_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) loc1 = get_loc(instr) if not self.has_data(addr): reassemble.data_set[addr] = '' self.label.insert(0, (s.sec_name, addr)) self.c2d_addr.insert(0, loc1.loc_addr) return Types.JmpTable_MINUS_S((s_label, r, off)) if self.check_text(addr): s_label = '-S_' + dec_hex(addr) loc1 = get_loc(instr) if not self.has_text(addr): reassemble.text_set[addr] = '' self.deslist.insert(0, s_label) self.deslist_reloc.insert(0, loc1.loc_addr) return Types.JmpTable_MINUS_S((s_label, r, off)) return exp
def update_cft_stack(self, instr): inv = lambda i: get_loc(i).loc_addr in self.locs if not self.five_q.exists(inv): dis_validator.icf_stack.push(get_loc(instr))