def apply_load_unload(ea, load=True): name = idc.GetFunctionName(ea) log('apply 0x%x %s', ea, name) decl = "{} {}(JavaVM *vm, void *reserved)".format( "jint" if load else "void", "JNI_OnLoad" if load else "JNI_OnUnload") prototype_details = idc.parse_decl(decl, idc.PT_SILENT) idc.apply_type(ea, prototype_details)
def force_variable(ea, type, name): t = ida_typeinf.tinfo_t() ida_typeinf.parse_decl(t, None, '{} a;'.format(type), 0) ida_bytes.del_items( ea, ida_bytes.DELIT_EXPAND | ida_bytes.DELIT_DELNAMES | ida_bytes.DELIT_NOCMT, t.get_size()) ida_name.set_name(ea, name, ida_name.SN_CHECK) idc.apply_type(ea, idc.parse_decl('{} a;'.format(type), 0), idc.TINFO_DEFINITE)
def assign_struct_to_address(address, struct_name): idc.apply_type(address, get_Tinfo_from_name(struct_name)) struct_id = idaapi.get_struc_id(struct_name) if struct_id != 0xffffffffffffffff: struct_size = idaapi.get_struc_size(struct_id) for i in range(struct_size): ida_bytes.del_items(address + i, 0) return idaapi.create_struct(address, struct_size, struct_id) return False
def apply_signature(ea, sig): name = idc.get_func_name(ea) ret, args = sig log('apply 0x%x %s', ea, name) decl = '{} {}({})'.format(ret, name, args) # log(decl) prototype_details = idc.parse_decl(decl, idc.PT_SILENT) # idc.set_name(ea, name) idc.apply_type(ea, prototype_details)
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 force_array(ea, type, name, count=None): t = ida_typeinf.tinfo_t() ida_typeinf.parse_decl(t, None, '{} a;'.format(type), 0) ida_bytes.del_items( ea, ida_bytes.DELIT_EXPAND | ida_bytes.DELIT_DELNAMES | ida_bytes.DELIT_NOCMT, t.get_size() * (1 if count is None else count)) ida_name.set_name(ea, name, ida_name.SN_CHECK) idc.apply_type( ea, idc.parse_decl( '{} a[{}];'.format(type, '' if count is None else str(count)), 0), idc.TINFO_DEFINITE)
def mark_string(ea, name=None): strlen = len(idc.GetString(ea, -1)) if strlen == 0: raise Exception( 'tried marking {} as string, but it isn\'t (len 0)'.format( hex(ea))) 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 idc.GetString(ea, -1)
def apply_like(path): with open('{}.log'.format(path), 'w') as log_fp: with open(path) as fp: like = json.load(fp) for item in like.values(): if item[0] != 'subprogram': continue _, return_type, name, parameters, has_varargs = item address = get_name_ea(BADADDR, str(name)) if address == BADADDR: log_fp.write('Subprogram not found: {}\n'.format(name)) log_fp.flush() continue decl = resolve_type(like, return_type, log_fp) + ' ' + name + '(' first = True for parameter_type, parameter_name in parameters: if first: first = False else: decl += ', ' if not _is_uname(str(parameter_name)): parameter_name = '_' + parameter_name decl += resolve_type(like, parameter_type, log_fp) if _is_uname(str(parameter_name)): decl += ' ' + parameter_name if has_varargs: if not first: decl += ', ' decl += '...' decl += ')' log_fp.write('{}: ...\n'.format(decl)) log_fp.flush() ret = apply_type(address, parse_decl(str(decl), 0)) log_fp.write('... ret={}\n'.format(ret)) log_fp.flush()
def apply_signature(ea, info): name = idc.GetFunctionName(ea) if info is None: log('WARN: no info found for %s', name) return log('apply 0x%x %s', ea, name) decl = '{} {}(JNIEnv* env, '.format(info['returnType'], name) if info['isStatic']: decl += 'jclass clazz' else: decl += 'jobject thiz' for idx, atype in enumerate(info['argumentTypes']): decl += ', {} arg{}'.format(atype, idx + 1) decl += ')' # log(decl) prototype_details = idc.parse_decl(decl, idc.PT_SILENT) # idc.set_name(ea, name) idc.apply_type(ea, prototype_details)
def iometa_information(): print("[-] UserClient Method construction") fd = open(iometa_path) data = fd.readlines() fd.close() # Current className = "" for line in data: t = line[:-1].strip() if "vtab" in t and "meta" in t: className = t.split(" ")[5] #print(className) continue #offset = int(t.split(" ")[0]) addr = int(t.split(" ")[1][5:], 0) sym = idc.get_func_name(addr) name = t.split(" ")[4].split("(")[0] if not idau.is_function_start(addr): print("[iometa] Current '{}'' - [{}] is not defined as function". format(name, hex(addr))) if not idau.force_function(addr): print("[iometa] Can't convert '{}' - [{}] to function".format( name, hex(addr))) if "sub_" in sym: idaapi.set_name(addr, name, idaapi.SN_FORCE) if "externalMethod" in name: sid = ida_struct.get_struc_id(className) if sid == 0xffffffffffffffff and className != "IOUserClient": print("[iometa] can't resolve class {}, create one".format( className)) construct_class(className) tu = ( '\x0c0=\tIOReturn\x07\xffA\n=\rIOUserClient=\tuint32_t\n=\x1aIOExternalMethodArguments\n=\x19IOExternalMethodDispatch\n=\tOSObject\n\x01', '\x05this\tselector\narguments\tdispatch\x07target\nreference') if not idc.apply_type(addr, tu): print( "[iometa] externalMethod type propagation failure '{}' - [{}]" .format(name, hex(addr))) print("[-] Done")
def fix_userpurge(funcea, flags=idc.TINFO_DEFINITE): """@return: True if __userpurge calling conv was found and fixed at funcea, otherwise False""" funcea = utils.get_func_start(funcea) if funcea == BADADDR: return False tif = utils.get_func_tinfo(funcea) if not tif: return False typestr = str(tif) if not typestr: return False if "__userpurge" not in typestr: return False typestr = typestr.replace("__userpurge", "(__thiscall)") typestr = re.sub(r"\@\<\w+\>", "", typestr) PT_SILENT = 1 # in IDA7.0 idc.PT_SILENT=2, which is incorrect py_type = idc.parse_decl(typestr, PT_SILENT) if not py_type: log.warn("%08X Failed to fix userpurge", funcea) return False return idc.apply_type(funcea, py_type[1:], flags)
def tinfo(self, tinfo): success = idc.apply_type(self.start_ea, tinfo) if not success: raise exceptions.SetTypeFailed(self.start_ea, tinfo)
def apply(self): """Applies the currently set signature to the IDB.""" idc.apply_type(self.start_ea, self.declaration)
def __call__(self): idc.apply_type(self.ea, self.py_type)
def resolve_type(like, die_offset, log_fp, alias=None): if die_offset is None: return 'void' type = like.get(str(die_offset)) if type is None: return DEFAULT_TYPE kind = type[0] if kind in ('struct', 'union'): if type[1] is None: if alias is None: struct_name = '{}_{}'.format(kind, hex(die_offset)) else: struct_name = alias else: struct_name = type[1] if (not _is_uname(str(struct_name)) or (get_struc_id(str(struct_name)) == BADADDR and get_name_ea(BADADDR, str(struct_name)) != BADADDR)): struct_name = '_' + struct_name struct_id = get_struc_id(str(struct_name)) if struct_id != BADADDR: if len(type) == 4: type.append(struct_id) return struct_name log_fp.write('{}: ...\n'.format(struct_name)) log_fp.flush() struct_id = add_struc(BADADDR, str(struct_name), kind == 'union') log_fp.write('... id={}\n'.format(hex(struct_id))) log_fp.flush() if struct_id == BADADDR: return DEFAULT_TYPE type.append(struct_id) if kind == 'struct' and type[2] != 0: ret = add_end_member(struct_id, struct_name, type[2], log_fp) have_end_member = ret == 0 else: have_end_member = False for member_type_die_offset, member_name, member_offset in type[3]: if member_name is None: if kind == 'struct': field_n = member_offset else: field_n = sum(1 for _ in StructMembers(struct_id)) member_name = 'field_{:X}'.format(field_n) elif not _is_uname(str(member_name)): member_name = '_' + member_name member_type_str = str(resolve_type( like, member_type_die_offset, log_fp)) member_size = get_type_size(like, member_type_die_offset) if have_end_member and member_offset + member_size == type[2]: del_struc_member(struct_id, type[2] - 1) have_end_member = False log_fp.write('{} {}.{}: ...\n'.format( member_type_str, struct_name, member_name)) log_fp.flush() ret = add_struc_member( struct_id, str(member_name), member_offset, DEFAULT_TYPE_FLAGS, DEFAULT_TYPE_ID, DEFAULT_TYPE_SIZE, ) log_fp.write('... ret={}\n'.format(ret)) log_fp.flush() if ret == 0: member_id = get_name_ea( BADADDR, '{}.{}'.format(struct_name, member_name)) apply_type(member_id, parse_decl(member_type_str, 0)) return struct_name if kind == 'typedef': return resolve_type(like, type[2], log_fp, type[1]) if kind == 'pointer': return resolve_type(like, type[1], log_fp) + '*' if kind == 'base': if type[1]: return '__int' + str(type[2] * 8) else: return 'unsigned __int' + str(type[2] * 8) if kind in ('const', 'volatile'): return resolve_type(like, type[1], log_fp) if kind == 'array': return '{}[{}]'.format(resolve_type(like, type[1], log_fp), type[2]) return DEFAULT_TYPE