def is_jni_header_loaded(): # not work as expected: # return idaapi.get_struc_id('JNIInvokeInterface_') != idaapi.BADADDR try: idc.parse_decl('JNIEnv *env', idc.PT_SILENT) except Exception as e: return False return True
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 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, 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 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 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 parse_type_declaration(self, new_type_declaration): result = idc.parse_decl(new_type_declaration, 0) if result is None: return False _, tp, fld = result tinfo = idaapi.tinfo_t() tinfo.deserialize(idaapi.cvar.idati, tp, fld, None) self.tinfo = tinfo self.is_array = False return True
def activate(self): new_type_declaration = idaapi.askstr(0x100, self.type_name, "Enter type:") result = idc.parse_decl(new_type_declaration, 0) if result is None: return _, tp, fld = result tinfo = idaapi.tinfo_t() tinfo.deserialize(idaapi.cvar.idati, tp, fld, None) self.tinfo = tinfo self.is_array = False
def get_type_size(type): sid = idc.get_struc_id(type) if sid != idc.BADADDR: return idc.get_struc_size(sid) try: name, tp, fld = idc.parse_decl(type, 1) if tp: return idc.SizeOf(tp) except: return 0
def get_typeinf(typestr): if not typestr: # Passing None to tinfo_t.get_named_type() can crash IDA return None tif = idaapi.tinfo_t() if tif.get_named_type(idaapi.get_idati(), typestr): return tif 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: return None return deserialize_tinfo(py_type[1:])
def DuplicateResolver(t1, t2, fToStorage=False): f = forms.DublicateResolverUI(t1.print_type(), t2.print_type(), fToStorage) while True: f.Go() if f.sel == 1: return t1 elif f.sel == 2: return t2 else: r = idc.parse_decl(f.selText, 0x008E) if r is not None: return LocalType(r[0], r[1], r[2])
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 import_structure(name, tinfo): cdecl_typedef = idaapi.print_tinfo(None, 4, 5, idaapi.PRTYPE_MULTI | idaapi.PRTYPE_TYPE | idaapi.PRTYPE_SEMI, tinfo, name, None) if idc.parse_decl(cdecl_typedef, idaapi.PT_TYP) is None: return 0 previous_ordinal = idaapi.get_type_ordinal(idaapi.cvar.idati, name) if previous_ordinal: idaapi.del_numbered_type(idaapi.cvar.idati, previous_ordinal) ordinal = idaapi.idc_set_local_type(previous_ordinal, cdecl_typedef, idaapi.PT_TYP) else: ordinal = idaapi.idc_set_local_type(-1, cdecl_typedef, idaapi.PT_TYP) return ordinal
def get_size(name, type, line): if type == "BasicType": try: return idc.SizeOf(idc.parse_decl(str(name), 0)[1]) except: try: idc.SizeOf( idc.parse_decl(str(line.get("type").get("name")), 0)[1]) except: return 1 elif type == "ArrayType": subType = line.get("type") if not subType: return line.get("size") typeSize = IDAtools.get_size(str(subType.get("name")), subType.get("table"), subType) try: return (typeSize * int(line.get("size"))) except TypeError: return 1 elif type == "PointerType" or type == "ReferenceType" or type == "QualifierType": return 4 elif type == "CFunctionType" or type == "CPPFunctionType": return 4 elif type == "PDOMCEnumeration" or type == "PDOMCPPEnumeration": return idaapi.get_enum_size(idaapi.get_enum(str(name))) elif type == "PDOMCStructure" or type == "PDOMCPPClassType": return idaapi.get_struc_size(idaapi.get_struc_id(str(name))) elif type == "PDOMCTypedef" or type == "PDOMCPPTypedef": subType = line.get("type") if not subType: return 1 return IDAtools.get_size(subType.get("name"), subType.get("table"), subType) else: raise Exception("Missing case", type)
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_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 __parse_declaration(declaration): m = re.search(r"^(\w+[ *]+)(\w+)$", declaration) if m is None: return type_name, field_name = m.groups() if field_name[0].isdigit(): print "[ERROR] Bad field name" return result = idc.parse_decl(type_name, 0) if result is None: return _, tp, fld = result tinfo = idaapi.tinfo_t() tinfo.deserialize(idaapi.cvar.idati, tp, fld, None) return tinfo, field_name
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 parse_declaration(declaration): m = re.search(r"^(\w+[ *]+)(\w+)(\[(\d+)\])?$", declaration) if m is None: logger.error("Member declaration should be like `TYPE_NAME NAME[SIZE]` (Array is optional)") return type_name, field_name, _, arr_size = m.groups() if field_name[0].isdigit(): logger.error("Bad field name") return result = idc.parse_decl(type_name, 0) if result is None: logger.error("Failed to parse member type. It should be like `TYPE_NAME NAME[SIZE]` (Array is optional)") return _, tp, fld = result tinfo = idaapi.tinfo_t() tinfo.deserialize(idaapi.cvar.idati, tp, fld, None) if arr_size: assert tinfo.create_array(tinfo, int(arr_size)) return tinfo, field_name
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
def is_jni_header_loaded(): # not work as expected: # return idaapi.get_struc_id('JNIInvokeInterface_') != idaapi.BADADDR ret = idc.parse_decl('JNIEnv *env', idc.PT_SILENT) return ret is not None