def getConst(ea, offset): strings = [] consts = [] optype1 = idc.get_operand_type(ea, offset) if optype1 == idaapi.o_imm: imm_value = idc.get_operand_value(ea, offset) if 0<= imm_value <= 10: consts.append(imm_value) else: if idaapi.isLoaded(imm_value) and ida_segment.getseg(imm_value): str_value = idc.get_strlit_contents(imm_value) if str_value is None: str_value = idc.get_strlit_contents(imm_value+0x40000) if str_value is None: consts.append(imm_value) else: re = all(40 <= ord(c) < 128 for c in str_value) if re: strings.append(str_value) else: consts.append(imm_value) else: re = all(40 <= ord(c) < 128 for c in str_value) if re: strings.append(str_value) else: consts.append(imm_value) else: consts.append(imm_value) return strings, consts
def base64_decode(std): addr = idc.BADADDR ea = idc.get_screen_ea() flags = idaapi.get_flags(ea) if idc.is_strlit(flags): addr = ea # cursor is on the string elif idc.is_code(flags): addr = idc.get_first_dref_from(ea) # get data reference from the instruction if addr == idc.BADADDR: plg_print("No string or reference to the string found\n") return b64str_enc = None try: b64str_enc = idc.get_strlit_contents(addr, -1, idc.get_str_type(addr)) except: pass if not b64str_enc: plg_print("Could not get string at address 0x%X" % addr) return try: b64str_dec = base64.standard_b64decode(b64str_enc) if std else base64.urlsafe_b64decode(b64str_enc) except Exception as e: plg_print("Could not decode. %s" % str(e)) return if b64str_dec: plg_print("Base64 decode of string '%s':" % b64str_enc) process_data_result(ea, bytearray(b64str_dec))
def rename(beg, ptr, make_funcs=True): go_fun = Utils.load_function_comments() base = beg pos = beg + 8 #skip header size = ptr.ptr(pos) pos += ptr.size end = pos + (size * ptr.size * 2) while pos < end: offset = ptr.ptr(pos + ptr.size) ptr.maker(pos) #in order to get xrefs ptr.maker(pos + ptr.size) pos += ptr.size * 2 ptr.maker(base + offset) func_addr = ptr.ptr(base + offset) if make_funcs == True: ida_bytes.del_items(func_addr, 1, ida_bytes.DELIT_SIMPLE) ida_funcs.add_func(func_addr) name_offset = idc.get_wide_dword(base + offset + ptr.size) name = idc.get_strlit_contents(base + name_offset) comment = name if go_fun: tcomment = Utils.get_function_comment(name, go_fun) if tcomment: comment = tcomment Utils.add_function_comment(func_addr, comment) name = Utils.relaxName(name) print(name) Utils.rename(func_addr, name)
def __init__(self, objc_class_va, segment_map, arch=ARCH_X86_64): """Create a new ObjcClass instance Arguments: objc_class_va {number} -- Virtual address of the Objective-C class to parse segment_map {dictionary} -- A dictionary mapping segment names to a start/end virtual address tuple Keyword Arguments: arch {number} -- CPU architecture. Either ARCH_X86_64 or ARM64 (default: {ARCH_X86_64}) """ self.arch = arch self.segment_map = segment_map class_ro_va = get_qword(objc_class_va + self.OBJC2_CLASS_RO_OFFSET) self.name_pointer = get_qword(class_ro_va + self.OBJC2_CLASS_RO_NAME_OFFSET) self.method_list = [] if class_ro_va == BADADDR or class_ro_va == 0: self.class_ro_va = None return self.class_ro_va = class_ro_va class_methods_va = get_qword(class_ro_va + self.OBJC2_CLASS_RO_BASE_METHODS_OFFSET) if class_methods_va == BADADDR or class_methods_va == 0: self.class_methods_va = None return self.class_methods_va = class_methods_va msg("Class found at virtual address: 0x%x\n" % objc_class_va) msg("Class name: %s\n" % get_strlit_contents(self.name_pointer)) #Parse the method_list_t struct and build a list of methods self.method_list = ObjcMethodList(class_methods_va, segment_map, arch=arch)
def BL(self, bl_addr): # OSMetaClass::OSMetaClass(this, className, superclass, classSize) X0, X1, X3 = (self.regs[n] for n in ('X0', 'X1', 'X3')) if (X0 and X1 and X3 and idc.get_segm_name(X1).endswith("__cstring") and idc.get_segm_name(X0)): found_metaclass(X0, idc.get_strlit_contents(X1))
def __can_be_part_of_assert(cfunc, ctree_item): # type: (idaapi.cfunc_t, idaapi.ctree_item_t) -> bool """ Returns true if expression we clicked is an argument passed to a function and this argument is a string that can be a valid function name """ if ctree_item.citype != idaapi.VDI_EXPR: return False expression = ctree_item.it.to_specific_type if expression.op != idaapi.cot_obj: return False parent = cfunc.body.find_parent_of(expression).to_specific_type if parent.op != idaapi.cot_call or parent.x.op != idaapi.cot_obj: return False obj_ea = expression.obj_ea if not helper.is_code_ea(obj_ea) and idc.get_str_type( obj_ea) == idc.STRTYPE_C: str_potential_name = idc.get_strlit_contents(obj_ea) if type(str_potential_name) is not str: # convert bytes to str (python 3) str_potential_name = str_potential_name.decode('ascii') return idaapi.is_valid_typename(str_potential_name) return False
def get_new_func_name(log_func_addr, new_nm_index): frn_log("try get log args {:#x}".format(log_func_addr)) args_list = idaapi.get_arg_addrs(log_func_addr) if args_list == None: frn_log("func argument is none , try set argument number") return False if len(args_list) < (new_nm_index + 1): frn_log("func argument number is too small") return False if args_list[new_nm_index] > ida_ida.inf_get_max_ea(): frn_log("func argument addr is not accessible") return False name_addr = [ ref for ref in idautils.DataRefsFrom(args_list[new_nm_index]) ] if len(name_addr) < 2: frn_log("can't get name addr") return False name = idc.get_strlit_contents(name_addr[1]) if name == None: frn_log("new name is not string") return False name = 'func_' + ''.join(x for x in name.decode() if x.isalpha()) # Keep only the letters frn_log("new_func_name {}".format(name)) return name
def __PltResolver(jmprel, strtab, symtab): idx = 0 while True: r_off = idc.get_qword(jmprel + 0x18 * idx) r_info1 = idc.get_wide_dword(jmprel + 0x18 * idx + 0x8) r_info2 = idc.get_wide_dword(jmprel + 0x18 * idx + 0xc) r_addend = idc.get_qword(jmprel + 0x18 * idx + 0x10) if r_off > 0x7fffffff: return if r_info1 == 7: st_name = idc.get_wide_dword(symtab + r_info2 * 0x18) name = idc.get_strlit_contents(strtab + st_name) # rename got idc.set_name(r_off, name.decode("ascii") + '_ptr') plt_func = idc.get_qword(r_off) if debug_mode: print(hex(plt_func.start_ea), name) # rename plt idc.set_name(plt_func, 'j_' + name.decode("ascii")) SetFuncFlags(plt_func) # rename plt.sec for addr in idautils.DataRefsTo(r_off): plt_sec_func = idaapi.get_func(addr) if plt_sec_func: plt_sec_func_addr = plt_sec_func.start_ea idc.set_name(plt_sec_func_addr, '_' + name.decode("ascii")) SetFuncFlags(plt_sec_func_addr) else: print("[!] idaapi.get_func({}) failed".format( hex(addr))) idx += 1
def get_str_from_expr(expr, make_str=True): if expr is None: return None str_addr = get_obj_ea_from_expr(expr) if str_addr == BADADDR: return None return idc.get_strlit_contents(str_addr)
def get_cmmt(ea,offset): addr = idc.get_wide_word(offset)+0x400000 text = idc.get_strlit_contents(addr) if text is not None: text = str(text,encoding="utf-8") print("0x%x %s addr:0x%x "%(offset,text,addr)) set_cmmts(ea,text)
def get_typeinfo_name(self, typeinfo_ea): name_ea = utils.get_ptr(typeinfo_ea + self.CLASS_TYPE_NAME_OFFSET) if name_ea is None or name_ea == BADADDR: mangled_class_name = ida_name.get_ea_name(typeinfo_ea) else: mangled_class_name = "_Z" + idc.get_strlit_contents(name_ea).decode() class_name = ida_name.demangle_name(mangled_class_name, idc.INF_LONG_DN) return GccRTTIParser.strip_class_name(class_name)
def read_string(ea): s = idc.get_strlit_contents(ea, -1, idc.ASCSTR_C) if s: slen = len(s)+1 idc.del_items(ea, idc.DOUNK_SIMPLE, slen) idaapi.make_ascii_string(ea, slen, idc.ASCSTR_C) return s, ea + slen else: return s, ea
def read_string(ea): s = idc.get_strlit_contents(ea, -1, idc.ASCSTR_C) if s: slen = len(s) + 1 idc.del_items(ea, idc.DOUNK_SIMPLE, slen) idaapi.make_ascii_string(ea, slen, idc.ASCSTR_C) return s, ea + slen else: return s, ea
def __add_func_name(self, arg_expr): new_name = idc.get_strlit_contents(arg_expr.obj_ea) if not idaapi.is_valid_typename(new_name): logger.warn("Argument has a weird name `{}` at {}".format( new_name, helper.to_hex(helper.find_asm_address(arg_expr, self.parents)))) return self.__possible_names.add(new_name)
def get_string(ea): """ Returns a string from the given location. :param ea: starting address of string :return: A string """ stype = idc.get_str_type(ea) return idc.get_strlit_contents(ea, strtype=stype)
def getAsciiString(self, ea): """Fetch the best ascii string that starts at the given address, according to IDA. Args: ea (int): effective address of the wanted string Return Value: IDA's best ascii string that starts at the given address """ return idc.get_strlit_contents(ea, -1, -1)
def mark_string(ea, name=None): strlen = len(idc.get_strlit_contents(ea, -1) or '') ida_bytes.del_items( ea, ida_bytes.DELIT_EXPAND | ida_bytes.DELIT_DELNAMES | ida_bytes.DELIT_NOCMT, strlen + 1) ida_bytes.create_strlit(ea, strlen + 1, idc.get_inf_attr(idc.INF_STRTYPE)) if name: ida_name.set_name(ea, name, ida_name.SN_CHECK) idc.apply_type(ea, idc.parse_decl('char const a[]', 0), idc.TINFO_DEFINITE) return get_cstring(ea)
def get_str_from_expr(expr, make_str=True): if expr is None: return None str_addr = get_obj_ea_from_expr(expr) if str_addr == BADADDR: return None ret = idc.get_strlit_contents(str_addr) if ret is not None: ret = ret.decode() return ret
def __PltResolver(jmprel, strtab, symtab, pltgot): seg_sec = idc.selector_by_name('.plt.sec') sec_start = idc.get_segm_by_sel(seg_sec) sec_end = idc.get_segm_end(sec_start) if sec_start == idaapi.BADADDR: print("[-] can't find .plt.sec segment") return idx = 0 while True: r_off = idc.get_wide_dword(jmprel + 0x8 * idx) r_info1 = idc.get_wide_byte(jmprel + 0x8 * idx + 0x4) r_info2 = idc.get_wide_byte(jmprel + 0x8 * idx + 0x5) if r_off > 0x7fffffff: return if r_info1 == 7: st_name = idc.get_wide_dword(symtab + r_info2 * 0x10) name = idc.get_strlit_contents(strtab + st_name) # rename got idc.set_name(r_off, name.decode("ascii") + '_ptr') plt_func = idc.get_wide_dword(r_off) # rename plt idc.set_name(plt_func, 'j_' + name.decode("ascii")) SetFuncFlags(plt_func) # rename plt.sec for addr in idautils.DataRefsTo(r_off): plt_sec_func = idaapi.get_func(addr) if plt_sec_func: plt_sec_func_addr = plt_sec_func.start_ea idc.set_name(plt_sec_func_addr, '_' + name.decode("ascii")) SetFuncFlags(plt_sec_func_addr) else: print("[!] idaapi.get_func({}) failed".format( hex(addr))) got_off = r_off - pltgot target = '+{}h'.format( hex(got_off).lower().replace('0x', '').replace('l', '').rjust(2, '0')) for func_ea in idautils.Functions(sec_start, sec_end): func = idaapi.get_func(func_ea) cur = func.start_ea end = func.endEA find = False while cur <= end: code = idc.GetDisasm(cur).lower().replace(' ', '') if target in code: find = True break cur = idc.NextHead(cur, end) if find: idc.set_name(func_ea, '_' + name) SetFuncFlags(func_ea) idx += 1
def get_strings(start_addr, end_addr): strings = [] for h in idautils.Heads(start_addr, end_addr): refs = idautils.DataRefsFrom(h) for ref in refs: t = idc.get_str_type(ref) if isinstance(t, int) and t >= 0: s = idc.get_strlit_contents(ref) if s and isprintable(s): strings.append([h, s, t, ref]) return strings
def on_BL(addr, reg): X0, X1, X3 = reg['X0'], reg['X1'], reg['X3'] if not (X0 and X1 and X3): return _log(5, 'Have call to {:#x}({:#x}, {:#x}, ?, {:#x})', addr, X0, X1, X3) # OSMetaClass::OSMetaClass(this, className, superclass, classSize) if not idc.get_segm_name(X1).endswith( "__TEXT.__cstring") or not idc.get_segm_name(X0): return found_metaclass(X0, idc.get_strlit_contents(X1).decode(), X3, reg['X2'] or None)
def parse_function(ea): func = ida_funcs.func_t(ea) res = ida_funcs.find_func_bounds(func, ida_funcs.FIND_FUNC_DEFINE) if res == ida_funcs.FIND_FUNC_UNDEF: idc.ask_yn(1, 'can not find func bounds.') exit(0) addr = func.start_ea hit_count = 0 gnm_name = '' packet_count = 0 while addr < func.end_ea: if idc.print_insn_mnem(addr) == 'call': sub_name = idc.print_operand(addr, 0) if 'SetAllocatedNodes@SchedulerProxy' in sub_name: arg_addrs = ida_typeinf.get_arg_addrs(addr) gnm_name_arg_addr = arg_addrs[1] if idc.print_insn_mnem(gnm_name_arg_addr) != 'lea': idc.ask_yn( 1, 'gnm name not passed by lea: {:X}'.format( gnm_name_arg_addr)) exit(0) name_addr = idc.get_operand_value(gnm_name_arg_addr, 1) gnm_name = idc.get_strlit_contents(name_addr).decode('ascii') hit_count += 1 if 'set_packet_count' in sub_name: # we need to manually set set_packet_count function's type (press key Y) # or get_arg_addrs will return None arg_addrs = ida_typeinf.get_arg_addrs(addr) packet_count_arg_addr = arg_addrs[1] packet_count_inst = idc.print_insn_mnem(packet_count_arg_addr) if packet_count_inst == 'mov': op_type = idc.get_operand_type(packet_count_arg_addr, 1) if op_type == idc.o_imm: packet_count = idc.get_operand_value( packet_count_arg_addr, 1) else: packet_count = 0 elif packet_count_inst == 'lea': packet_count = 0 else: idc.ask_yn( 1, 'packet count passed by {} at {:X}'.format( packet_count_inst, packet_count_arg_addr)) exit(0) hit_count += 1 if hit_count == 2: break addr = idc.next_head(addr) return gnm_name, packet_count
def get_cstring(ea=None, size=-1): """ Static method for getting a C string from an address. :param ea: The address of the string. If ``None`` the screen address is used. :param size: The size of the string. If ``-1`` (default), until a ``\0`` is found. :return: Bytes representing the string """ if ea is None: ea = ida_kernwin.get_screen_ea() return idc.get_strlit_contents(ea, length=size)
def __add_func_name(self, arg_expr): new_name = idc.get_strlit_contents(arg_expr.obj_ea) if type(new_name) is not str: # convert bytes to str (python 3) new_name = new_name.decode('ascii') if not idaapi.is_valid_typename(new_name): logger.warn("Argument has a weird name `{}` at {}".format( new_name, helper.to_hex(helper.find_asm_address(arg_expr, self.parents)))) return self.__possible_names.add(new_name)
def stringAt(self, ea): """Return the string that was found on the given address, regardless of it's type. Args: ea (int): effective address of the wanted string Return Value: A python string that contains the found string (or None on error) """ str_type = idc.get_str_type(ea) if str_type is None: return None return idc.get_strlit_contents(ea, -1, str_type).decode("utf-8")
def rename_func_by_handle(startAddr, endAddr, offset1=8, offset2=4): # offset1 -> handle string -> get new func name # offset2 -> handle func -> get func addr for addr in range(startAddr, endAddr, offset1): for xref in idautils.XrefsFrom(addr, 0): name = idc.get_strlit_contents(xref.to) print('[INFO]{}'.format(name)) for xref in idautils.XrefsFrom(addr + offset2, 0): func_addr = xref.to # name = name.replace(b'*',b'').decode() name = 'func_' + name.decode() print(name) print(hex(func_addr)) idc.set_name(func_addr, name)
def FindEncodedStr(addrList): encodedStr = [] for addr in addrList: while True: addr = idc.prev_head(addr) disasm = idc.GetDisasm(addr) print disasm if disasm[:3] == 'lea' and 'rcx' in disasm: break strAddr = idc.get_operand_value(addr, 1) encStr = idc.get_strlit_contents(strAddr) encodedStr.append({'addr': addr, 'encStr': encStr}) return encodedStr
def defineAsciiString(self, ea): r"""Define an ascii string at the given address. Args: ea (int): effective start address of the wanted ascii string Return Value: The length of the defined string + 1 for the '\0' terminator """ content = idc.get_strlit_contents(ea, -1, -1) if not sark.Line(ea).is_string: self._analyzer.logger.debug( "Defined a unique ascii string at: 0x%x (Length of %d)", ea, len(content) + 1) ida_bytes.del_items(ea, 0, len(content) + 1) idc.create_strlit(ea, ea + len(content) + 1) return len(content) + 1
def get_string(ea): """Read the string at the given ea. This function uses IDA's string APIs and does not implement any special logic. """ # We get the item-head because the `GetStringType` function only works on the head of an item. string_type = idc.get_str_type(idaapi.get_item_head(ea)) if string_type is None: raise exceptions.SarkNoString("No string at 0x{:08X}".format(ea)) string = idc.get_strlit_contents(ea, strtype=string_type) if not string: raise exceptions.SarkNoString("No string at 0x{:08X}".format(ea)) return string
def rename(beg, ptr, make_funcs = True): base = beg pos = beg + 8 #skip header size = ptr.ptr(pos) pos += ptr.size end = pos + (size * ptr.size * 2) print("%x" % end) while pos < end: offset = ptr.ptr(pos + ptr.size) ptr.maker(pos) #in order to get xrefs ptr.maker(pos+ptr.size) pos += ptr.size * 2 ptr.maker(base+offset) func_addr = ptr.ptr(base+offset) if make_funcs == True: ida_bytes.del_items(func_addr, 1, ida_bytes.DELIT_SIMPLE) ida_funcs.add_func(func_addr) name_offset = idc.get_wide_dword(base+offset+ptr.size) name = idc.get_strlit_contents(base + name_offset) name = Utils.relaxName(name) Utils.rename(func_addr, name)
def get_method_name(self, esp): stringp = self.get_method_name_func(idc.get_wide_dword(esp + 4), 0) address = idc.get_wide_dword(stringp + 0x8) return idc.get_strlit_contents(address, -1, idc.STRTYPE_C)
def teleported(addr): import idc return idc.get_strlit_contents(addr)