def _apply_tag_on_callee(cls, callee_ea, rv, is_call=False): name = idaapi.get_ea_name(callee_ea) name = name.replace(idaapi.FUNC_IMPORT_PREFIX, '') if '@' in name: name = name.split('@')[0] if not name: return if name in IGNORE_CALL_LIST: if is_call: rv['calls'].pop() return if name in TAGS_IGNORE_LIST: return for tag, names in TAGS.items(): for tag_api in names: if tag in STRICT_TAG_NAME_CHECKING: match = tag_api in (name, name.lstrip('_')) else: match = tag_api in name if not match or name in rv['tags'][tag]: continue # print('%#08x: %s, tag: %s' % (dis.ea, name, tag)) rv['tags'][tag].append(name) break
def _handle_calls(self, fn, fn_an): num_calls = len(fn_an['calls']) if num_calls != 1: return dis = fn_an['calls'][0] if dis.Op1.type not in (o_imm, o_far, o_near, o_mem): return ea = dis.Op1.value if not ea and dis.Op1.addr: ea = dis.Op1.addr if idaapi.has_dummy_name(idaapi.getFlags(ea)): return # TODO: check is there jmp, push+retn then don't rename the func if fn_an['strange_flow']: return possible_name = idaapi.get_ea_name(ea) if not possible_name or possible_name in blacklist: return normalized = self.normalize_name(possible_name) # if self._cfg.get('auto_rename'): if len(fn_an['math']) < self._MIN_MAX_MATH_OPS_TO_ALLOW_RENAME: idaapi.do_name_anyway(fn.startEA, normalized) # TODO: add an API to the view print 'fn: %#08x: %d calls, %d math%s possible name: %s, normalized: %s' % ( fn.startEA, len(fn_an['calls']), len(fn_an['math']), 'has bads' if fn_an['has_bads'] else '', possible_name, normalized)
def _analysis_handle_call_insn(cls, dis, rv): rv['calls'].append(dis) if dis.Op1.type != o_mem or not dis.Op1.addr: return name = idaapi.get_ea_name(dis.Op1.addr) name = name.replace(idaapi.FUNC_IMPORT_PREFIX, '') if '@' in name: name = name.split('@')[0] if not name: return if name in IGNORE_CALL_LIST: rv['calls'].pop() return for tag, names in TAGS.items(): if name in TAGS_IGNORE_LIST: continue for tag_api in names: if tag_api in name: # print '%#08x: %s, tag: %s' % (dis.ea, name, tag) rv['tags'][tag].append(name) break
def _handle_tags(self, fn, fn_an, known_refs): if known_refs: known_refs = dict(known_refs) for k, names in known_refs.items(): existing = set(fn_an['tags'][k]) new = set(names) - existing if new: fn_an['tags'][k] += list(new) tags = dict(fn_an['tags']) if not tags: return print 'fn: %#08x tags: %s' % (fn.startEA, tags) cmt = idaapi.get_func_cmt(fn, True) if cmt: cmt += '\n' s = str(tags.keys()) name = idaapi.get_ea_name(fn.startEA) item = {'ea': fn.startEA, 'name': name, 'tags': tags} if not cmt or s not in cmt: idaapi.set_func_cmt(fn, '%sTAGS: %s' % (cmt or '', s), True) # self.mark_position(fn.startEA, 'TAGS: %s' % s) for tag in tags: if tag not in self._data: self._data[tag] = list() self._data[tag].append(item)
def get_name_or_address(ea): name = idaapi.get_ea_name(ea, idaapi.GN_VISIBLE) if name: name = repr(name) else: name = "0x{:08X}".format(ea) return name
def _get_best_name(ea): try: return sark.Function(ea).demangled except exceptions.SarkNoFunction: name = idaapi.get_ea_name(ea) if name: return name return '0x{:X}'.format(ea)
def parse(self): itype_addr = common.read_mem(self.addr) & 0xFFFFFFFFFFFFFFFF self.itype = self.type_parser.parse_type(type_addr=itype_addr) rtype_addr = common.read_mem(self.addr + common.ADDR_SZ) & 0xFFFFFFFFFFFFFFFF self.rtype = self.type_parser.parse_type(type_addr=rtype_addr) self.hash = common.read_mem(self.addr + 2 * common.ADDR_SZ, forced_addr_sz=4) & 0xFFFFFFFF # methods start addr(if has method) curr_addr = self.addr + 3 * common.ADDR_SZ while True: if len(idaapi.get_ea_name(curr_addr)) > 0: # stop at next itab_elem addr # next itab elem is labeled a head name by ida pro break meth_addr = common.read_mem(curr_addr) if idaapi.get_func(meth_addr): meth_name = idaapi.get_ea_name(meth_addr) self.methods.append(meth_name) self.meth_num += 1 curr_addr += common.ADDR_SZ idc.MakeComm(self.addr, "interface: %s" % self.itype.name) idc.MakeComm(self.addr + common.ADDR_SZ, "rtype: %s" % self.rtype.name) idc.MakeComm(self.addr + 2 * common.ADDR_SZ, "rtype hash") idaapi.autoWait() itab_elem_name = "go_itab__%s_%s" % (self.rtype.name_obj.name_str, self.itype.name) idc.MakeNameEx(self.addr, itab_elem_name, flags=idaapi.SN_FORCE) common._debug("Go itab %s(@ 0x%x) parsed." % (itab_elem_name, self.addr)) idaapi.autoWait()
def _rename_ea_requested(self, addr, name_idx): old_name = name_idx.data() if idaapi.IDA_SDK_VERSION >= 700: new_name = idaapi.ask_str(str(old_name), 0, 'New name:') else: new_name = idaapi.askstr(0, str(old_name), 'New name:') if new_name is None: return self._rename(addr, new_name) renamed_name = idaapi.get_ea_name(addr) name_idx.model().setData(name_idx, renamed_name)
def _preprocess_api_wrappers(self, fnqty): rv = defaultdict(dict) for i in xrange(fnqty): fn = idaapi.getn_func(i) items = list(FuncItems(self.start_ea_of(fn))) if len(items) not in (1, 2): continue dis0 = decode_insn(items[0]) if dis0 is None: continue addr = self._check_is_jmp_wrapper(dis0) if not addr and len(items) > 1: dis1 = decode_insn(items[1]) if dis1 is not None: addr = self._check_is_push_retn_wrapper(dis0, dis1) if not addr: continue name = idaapi.get_ea_name(addr) name = name.replace(idaapi.FUNC_IMPORT_PREFIX, '') if not name: continue imp_stripped_name = name.lstrip('_') for tag, names in TAGS.items(): for tag_api in names: if tag in STRICT_TAG_NAME_CHECKING: match = tag_api in (name, imp_stripped_name) else: match = tag_api in name if not match: continue refs = list(CodeRefsTo(self.start_ea_of(fn), 1)) for ref in refs: ref_fn = idaapi.get_func(ref) if not ref_fn: # idaapi.msg('AutoRE: there is no func for ref: %08x for api: %s' % (ref, name)) continue if tag not in rv[self.start_ea_of(ref_fn)]: rv[self.start_ea_of(ref_fn)][tag] = list() if name not in rv[self.start_ea_of(ref_fn)][tag]: rv[self.start_ea_of(ref_fn)][tag].append(name) return dict(rv)
def _handle_tags(self, fn, fn_an): tags = dict(fn_an['tags']) if not tags: return print 'fn: %#08x tags: %s' % (fn.startEA, tags) cmt = idaapi.get_func_cmt(fn, True) if cmt: cmt += '\n' s = str(tags.keys()) name = idaapi.get_ea_name(fn.startEA) item = {'ea': fn.startEA, 'name': name, 'tags': tags} if not cmt or s not in cmt: idaapi.set_func_cmt(fn, '%sTAGS: %s' % (cmt or '', s), True) # self.mark_position(fn.startEA, 'TAGS: %s' % s) for tag in tags: if tag not in self._data: self._data[tag] = list() self._data[tag].append(item)
def get_offset_name(ea): # Try and get the function name try: func = get_func(ea) name = idaapi.get_ea_name(func.start_ea) name = demangle(name, 0x60) # MNG_NOTYPE | MNG_NORETTYPE if name: offset = ea - func.start_ea if offset: return '{}+{:X}'.format(name, offset) return name except exceptions.SarkNoFunction: pass # If that failed, use the segment name instead. segment = idaapi.getseg(ea) name = idaapi.get_segm_name(segment) offset_format = '{{:0{}X}}'.format(get_native_size() * 2) ea_text = offset_format.format(ea) if name: return '{}:{}'.format(name, ea_text) # Nothing found, simply return the address return ea_text
def define_vtables(): segments = util.enum_all_segments() vtables_total = 0 for segm in segments: addr = segm.start_ea while addr < segm.end_ea: funcs_counted = VirtualTable.check(addr) if funcs_counted: print 'Found possible vtable: %#x (%s) with %d functions' % ( addr, repr( idaapi.demangle_name( idaapi.get_ea_name(addr), idc.get_inf_attr( idc.INF_SHORT_DN))), funcs_counted) v = VirtualTable(addr) v.finalize() addr += funcs_counted * const.PTR_SIZE vtables_total += 1 addr += const.PTR_SIZE print '[!] Imported %d virtual tables in total!' % vtables_total
def check_member_assignment(self, expression, index): """ We are now in cexpr_t == idaapi.cot_var. This function checks if expression is part of member assignment statement. Returns None if not. :param expression: idaapi.cexpr_t :param index: int :return: Structures.AbstractField """ parents_type = map(lambda x: idaapi.get_ctype_name(x.cexpr.op), list(self.parents)[:0:-1]) parents = map(lambda x: x.cexpr, list(self.parents)[:0:-1]) for parent in parents: if parent.ea != idaapi.BADADDR: self.expression_address = parent.ea break else: self.expression_address = idaapi.BADADDR offset = 0 if parents_type[0:2] == ['asg', 'expr']: if parents[0].y == expression: # Assignment like (v1 = v2) where v2 is scanned variable if parents[0].x.op == idaapi.cot_var: self.add_variable(parents[0].x.v.idx) return else: # if expression is (var = something), we have to explore whether continue to scan this variable or not if parents[0].y.op != idaapi.cot_num: if parents[0].y.op == idaapi.cot_call: # Check if expression: var = function((TYPE) var, ...) or var = function(var, ...) args = parents[0].y.a if args and ((args[0].op == idaapi.cot_cast and args[0].x.op == idaapi.cot_var and args[0].x.v.idx == index) or (args[0].op == idaapi.cot_var and args[0].v.idx == index)): return try: self.protected_variables.remove(index) except KeyError: print "[Info] Remove variable {0} from scan list, address: 0x{1:08X}".format( index, self.expression_address) self.variables.pop(index) return # Assignment like v1 = (TYPE) v2 where TYPE is one the supported types elif parents_type[0:3] == ['cast', 'asg', 'expr']: if parents[1].x.op == idaapi.cot_var: if filter(lambda x: x.equals_to(parents[0].type), Const.LEGAL_TYPES): self.add_variable(parents[1].x.v.idx) return # Universal call with no cast conversion and offsets: call(..., this, ...) if parents_type[0] == 'call': arg_index, _ = Helper.get_func_argument_info( parents[0], expression) if SCAN_ALL_ARGUMENTS or not arg_index: self.scan_function(parents[0].x.obj_ea, 0, arg_index) return # -------------------------------------------------------------------------------------------- # When variable is DWORD, int, __int64 etc # -------------------------------------------------------------------------------------------- elif self.variables[index].equals_to(Const.X_WORD_TINFO): if parents_type[0:2] == ['add', 'cast']: if parents[0].theother(expression).op != idaapi.cot_num: return offset = parents[0].theother(expression).numval() if parents_type[2] == 'ptr': if parents_type[3] == 'asg': if parents[3].x == parents[2]: # *(TYPE *)(var + x) = ??? return self.get_member( offset, index, object=parents[3].y, default=parents[1].type.get_pointed_object()) if parents[3].x.op == idaapi.cot_var: # other_var = *(TYPE *)(var + x) return self.create_member(offset, index, parents[3].x.type) return self.create_member( offset, index, parents[1].type.get_pointed_object()) elif parents_type[2] == 'call': # call(..., (TYPE)(var + x), ...) if parents[0].theother(expression).op != idaapi.cot_num: return offset = parents[0].theother(expression).numval() return self.get_member(offset, index, call=parents[2], arg=parents[1]) elif parents_type[2] == 'asg': # other_var = (LEGAL TYPE) (var + offset) if parents[2].y == parents[1] and parents[ 2].x.op == idaapi.cot_var: if filter(lambda x: x.equals_to(parents[1].type), Const.LEGAL_TYPES): self.scan_function(self.function.entry_ea, offset, parents[2].x.v.idx) return cast_type = parents[1].type if cast_type.is_ptr(): return self.create_member(offset, index, cast_type.get_pointed_object()) elif parents_type[0:2] == ['cast', 'ptr']: if parents_type[2] == 'asg' and parents[2].x == parents[1]: # *(TYPE *)var = ??? return self.get_member( 0, index, object=parents[2].y, default=parents[0].type.get_pointed_object()) return self.create_member(0, index, parents[0].type.get_pointed_object()) elif parents_type[0:2] == ['cast', 'call']: # call(..., (TYPE)(var + x), ...) return self.get_member(0, index, call=parents[1], arg=parents[0]) elif parents_type[0] == 'add': # call(..., var + x, ...) if parents[0].theother(expression).op != idaapi.cot_num: return offset = parents[0].theother(expression).numval() if parents_type[1] == 'call': return self.get_member(offset, index, call=parents[1], arg=parents[0]) elif parents_type[1] == 'asg': if parents[1].y == parents[0] and parents[ 1].x.op == idaapi.cot_var: self.scan_function(self.function.entry_ea, offset, parents[1].x.v.idx) return elif parents_type[0] == 'asg': # var = (int)&Some_object if parents[0].y.op == idaapi.cot_cast and parents[ 0].y.x.op == idaapi.cot_ref: return self.create_member( 0, index, parents[0].y.x.type.get_pointed_object()) # -------------------------------------------------------------------------------------------- # When variable is void *, PVOID, DWORD *, QWORD * etc # -------------------------------------------------------------------------------------------- else: # print "[DEBUG] D* Parents:", parents_type offset = 0 if parents_type[0] == 'idx': if parents[0].y.op != idaapi.cot_num: # There's no way to handle with dynamic offset return None offset = parents[0].y.numval( ) * self.variables[index].get_ptrarr_objsize() if parents_type[1] == 'asg' and parents[1].x == parents[0]: # var[idx] = ??? return self.get_member( offset, index, object=parents[1].y, default=self.variables[index].get_pointed_object()) elif parents_type[1] == 'cast': # (TYPE) var[idx] return self.create_member(offset, index, parents[1].type) return self.create_member(offset, index, Const.X_WORD_TINFO) elif parents_type[0:2] == ['ptr', 'asg']: # *var = ??? return self.get_member( 0, index, object=parents[1].y, default=self.variables[index].get_pointed_object()) else: if parents_type[0:2] == ['cast', 'ptr']: if parents_type[2] == 'call': # call(..., *(TYPE *) var, ...) return self.get_member(0, index, call=parents[2], arg=parents[1]) elif parents_type[2] == 'asg' and parents[2].x == parents[ 1]: # *(TYPE *) var = ??? return self.get_member( 0, index, object=parents[2].y, default=parents[0].type.get_pointed_object()) elif parents_type[0:2] == ['cast', 'add']: if parents[1].theother(parents[0]).op != idaapi.cot_num: return None offset = parents[1].theother(parents[0]).numval() offset *= parents[0].type.get_ptrarr_objsize( ) if parents[0].type.is_ptr() else 1 if parents_type[2] == 'ptr': if parents_type[3] == 'asg' and parents[ 3].x == parents[2]: # *((TYPE *)var + x) = ??? return self.get_member( offset, index, object=parents[3].y, default=parents[0].type.get_pointed_object()) return self.create_member( offset, index, parents[0].type.get_pointed_object()) elif parents_type[2] == 'call': # call(..., (TYPE)var + offset, ...) return self.get_member(offset, index, call=parents[2], arg=parents[1]) elif parents_type[2] == 'cast' and parents[2].type.is_ptr( ): if parents_type[3] == 'call': # call(..., (TYPE *) ((TYPE *)var + x), ...) # Where argument type is not the same as cast type. Ida has a bug here choosing sometimes # wrong pointer type idx, tinfo = Helper.get_func_argument_info( parents[3], parents[2]) return self.create_member( offset, index, tinfo.get_pointed_object()) # (TYPE *) ((TYPE *)var + x) return self.create_member( offset, index, parents[2].type.get_pointed_object()) elif parents_type[0:2] == ['add', 'cast']: if parents[0].theother(expression).op != idaapi.cot_num: return None offset = parents[0].theother(expression).numval( ) * self.variables[index].get_ptrarr_objsize() if parents_type[2] == 'call': # call(..., (TYPE)(var + x), ...) return self.get_member(offset, index, call=parents[2], arg=parents[1]) elif parents_type[2] == 'asg': if parents[2].y == parents[1] and parents[ 2].x.op == idaapi.cot_var: if filter(lambda x: x.equals_to(parents[1].type), Const.LEGAL_TYPES): self.scan_function(self.function.entry_ea, offset, parents[2].x.v.idx) return else: return self.create_member( offset, index, parents[1].type.get_pointed_object()) elif parents_type[0] == 'add': # call(..., var + offset, ...) if parents[0].theother(expression).op != idaapi.cot_num: return None offset = parents[0].theother(expression).numval( ) * self.variables[index].get_ptrarr_objsize() if parents_type[1] == 'call': return self.get_member(offset, index, call=parents[1], arg=parents[0]) if parents_type[1] == 'asg': # other_var = var + offset if parents[1].y == parents[0] and parents[ 1].x.op == idaapi.cot_var: self.scan_function(self.function.entry_ea, offset, parents[1].x.v.idx) return elif parents_type[0:2] == ['cast', 'call']: # call(..., (TYPE) var, ...) return self.get_member(0, index, call=parents[1], arg=parents[0]) elif parents_type[0] == 'ptr': if parents_type[1] == 'cast': # (TYPE) *var return self.create_member(0, index, parents[0].type) # *var return self.create_member( 0, index, self.variables[index].get_pointed_object()) elif parents_type[0] == 'asg': return if 'return' not in parents_type[0:2] and parents_type[0] not in ( 'if', 'band', 'eq', 'ne', 'cast'): print "[DEBUG] Unhandled type", self.variables[index].dstr(), \ "Index:", index, \ "Offset:", offset, \ "Function:", idaapi.get_ea_name(self.function.entry_ea), \ "Address: 0x{0:08X}".format(expression.ea), \ "Parents:", parents_type
def name(self): """Function's Name""" return idaapi.get_ea_name(self.start_ea)
def name(self): """Name of the line (the label shown in IDA).""" return idaapi.get_ea_name(self.ea)
def add_record(self, ea, score): pfn = idaapi.get_func(ea) self.record[pfn.start_ea] = { 'name': idaapi.get_ea_name(pfn.start_ea), 'score': score }
def get_func_name(ea): name = idaapi.get_func_name(ea) if not name: name = idaapi.get_ea_name(ea) return idaapi.COLSTR(name, idaapi.SCOLOR_SYMBOL)
def on_get_text(self, value, attrs): name = idaapi.get_ea_name(value) demangle = getattr(idaapi, 'demangle_name2', idaapi.demangle_name) name = demangle(name, 0) or name return name or "0x{:08X}".format(value)