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_jit_function(self): esp = idc.get_reg_value("ESP") method_name = self.get_method_name(esp) function = idc.get_wide_dword(esp + 8) method_id = idc.get_wide_dword(idc.get_wide_dword(esp + 4) + 0x20) abc_info_pos = idc.get_wide_dword(idc.get_wide_dword(esp + 4) + 0x1C) method_info = get_qword(abc_info_pos) + get_qword(abc_info_pos + 8) if (self.as3dump != []): method = next((x for x in self.as3dump if x["id"] == method_id), None) if (method is not None and method["info"] == method_info): method_name = method["name"] self.set_jit_info(method_id, function) print("Resolved jit function: 0x%x - %s" % (function, method_name)) self.rename_addr(function, method_name) if ((method_name not in self.ignore and not self.ignore_all) or (method_name in self.debug_if_equals) or (any(x for x in self.debug_if_contains if method_name is not None and x in method_name))): self.traced.append({"name": method_name, "ea": function, "type": "jit", "hit": 0}) idc.add_bpt(function)
def GetDyn(): phoff = idc.get_wide_dword(ida_ida.inf_get_min_ea() + 0x1c) + ida_ida.inf_get_min_ea() phnum = idc.get_wide_word(ida_ida.inf_get_min_ea() + 0x2c) phentsize = idc.get_wide_word(ida_ida.inf_get_min_ea() + 0x2a) for i in range(phnum): p_type = idc.get_wide_dword(phoff + phentsize * i) if p_type == 2: # PY_DYNAMIC dyn_addr = idc.get_wide_dword(phoff + phentsize * i + 8) return dyn_addr
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 ParseDyn(dyn, tag): idx = 0 while True: v1, v2 = idc.get_wide_dword(dyn + idx * 0x8), idc.get_wide_dword(dyn + idx * 0x8 + 4) if v1 == 0 and v2 == 0: return if v1 == tag: return v2 idx += 1
def resolveDispatcher(code): major = (code & 0x00ff0000) >> 0x10 minor = code & 0xff00ffff res = getMajorDispatchTableAddress() + major * 8 majorFlag = idc.get_wide_dword(res) majorAddress = idc.get_wide_dword(res + 4) if majorFlag != 0: return majorAddress + (minor * 0x10) #print "%x"% getMinorDispatchTableAddress(majorAddress) #print "resolved by 0x%x(%x)"% (majorAddress, minor) return majorAddress
def simplify_jumps(ea): # If we got long first conditional jump if idc.get_wide_byte(ea) == 0x0F: alternative_jmp_cmd = idc.get_wide_byte(ea + 1) ^ 1 interm_jmp_offt = 6 else: alternative_jmp_cmd = idc.get_wide_byte(ea) ^ 0xF1 interm_jmp_offt = 2 # Get intermediate jump's value if idc.get_wide_byte(ea + interm_jmp_offt) == 0x0F: interm_jmp_param = idc.get_wide_dword(ea + interm_jmp_offt + 2) final_jmp_addr = ea + interm_jmp_param + interm_jmp_offt + 6 else: interm_jmp_param = idc.get_wide_byte(ea + interm_jmp_offt + 1) final_jmp_addr = ea + interm_jmp_param + interm_jmp_offt + 2 # Check the last conditional jump # 75 ?? ... 0F 85 ?? ?? ?? ?? if idc.get_wide_byte(final_jmp_addr) == 0x0F and \ idc.get_wide_byte(final_jmp_addr + 1) == alternative_jmp_cmd: final_jmp_param = idc.get_wide_dword(final_jmp_addr + 2) final_jmp_target = (final_jmp_addr + final_jmp_param + 6) & 0xFFFFFFFF # 75 ?? ... 75 ?? elif idc.get_wide_byte(final_jmp_addr) ^ 0xF0 == alternative_jmp_cmd: final_jmp_param = idc.get_wide_byte(final_jmp_addr + 1) final_jmp_target = (final_jmp_addr + final_jmp_param + 2) & 0xFFFFFFFF # Make a little cleanup: remove garbage code elif interm_jmp_param < 0x10: fill_with_nops(ea + interm_jmp_offt, final_jmp_addr) return True else: return if final_jmp_target - ea < 0xFF: fill_with_nops(ea + interm_jmp_offt, final_jmp_target) else: fill_with_nops(ea + interm_jmp_offt, final_jmp_addr + 6) # Restore seconds jump idc.patch_byte(ea + interm_jmp_offt, 0x0F) idc.patch_byte(ea + interm_jmp_offt + 1, alternative_jmp_cmd) idc.patch_dword(ea + interm_jmp_offt + 2, final_jmp_target - (ea + interm_jmp_offt) - 6) idc.create_insn(ea + interm_jmp_offt) return True
def req_patch(self, hash): addr, value, length = hash['addr'], hash['value'], hash['len'] if length == 4: prev_value = idc.get_wide_dword(addr) if not ida_bytes.create_data(ea, FF_DWORD, 4, ida_idaapi.BADADDR): rs_log('[x] ida_bytes.create_data FF_DWORD failed') if not ida_bytes.patch_dword(addr, value): rs_log('[x] patch_dword failed') if not idc.op_plain_offset(addr, 0, 0): rs_log('[x] op_plain_offset failed') elif length == 8: prev_value = idc.get_qword(addr) if not ida_bytes.create_data(addr, FF_QWORD, 8, ida_idaapi.BADADDR): rs_log('[x] ida_bytes.create_data FF_QWORD failed') if not ida_bytes.patch_qword(addr, value): rs_log('[x] patch_qword failed') if not idc.op_plain_offset(addr, 0, 0): rs_log('[x] op_plain_offset failed') else: rs_log("[x] unsupported length: %d" % length) return rs_log("patched 0x%x = 0x%x (previous was 0x%x)" % (addr, value, prev_value))
def find_pointers(start, end): for va in range(start, end - 0x4): ptr = idc.get_wide_dword(va) if idc.get_segm_start(ptr) == idc.BADADDR: continue yield va, ptr
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 find_fakefast(self, target_addr): max_size = (0x80 if self.ptr_size == 8 else 0x40) ea = target_addr - max_size - self.ptr_size end_ea = target_addr - self.ptr_size results = [] while ea < end_ea: fake_size = idc.get_wide_dword(ea) idx = self.fastbin_index(fake_size & ~SIZE_BITS) if 0 <= idx <= 7: if (fake_size & 2 == 2) and ((fake_size & 4 == 4) or (fake_size & 4 == 0)): chunk_addr = ea - self.ptr_size align_size = self.tidx2size(idx) bytes_to = target_addr - ea - self.ptr_size results.append({ 'fast_id': idx, 'size': align_size, 'address': chunk_addr, 'bytes_to': bytes_to }) ea += 1 return results
def next(self): if self.pos >= self.end: raise StopIteration value = idc.get_wide_dword(self.pos) self.pos += 4 value = self.getOffset(value) return self.handle_offset(value)
def iter_vtable(self): ea = self.vtable_start end = self.vtable_end while ea <= end: yield (ea, idc.get_wide_dword(ea)) ea += 4
def get_guid(address): """get GUID located by address""" guid = list() guid.append(idc.get_wide_dword(address)) guid.append(idc.get_wide_word(address + 4)) guid.append(idc.get_wide_word(address + 6)) for addr in range(address + 8, address + 16, 1): guid.append(idc.get_wide_byte(addr)) return guid
def get_native_function(self): ecx = idc.get_reg_value("ECX") esp = idc.get_reg_value("ESP") method_name = self.get_method_name(esp) if (idc.get_wide_byte(idc.get_wide_dword(ecx + 8) + 0x38) != 0): function = idc.get_wide_dword(idc.get_wide_dword(esp + 4) + 0x28) else: function = idc.get_wide_dword(idc.get_wide_dword(esp + 4) + 0x24) print("Resolved native function: 0x%x - %s" % (function, method_name)) if ((method_name not in self.ignore and not self.ignore_all) or (method_name in self.debug_if_equals) or (any(x for x in self.debug_if_contains if method_name is not None and x in method_name))): self.traced.append({"name": method_name, "ea": function, "type": "native", "hit": 0}) idc.add_bpt(function)
def parse_vtable(ea, typename): os = get_os() if os == OS_Linux: ea += 8 funcs = [] while ea != idc.BADADDR: eatemp = ea offs = idc.get_wide_dword(ea) # if ida_bytes.is_unknown(ida_bytes.get_full_flags(ea)): # break size = idc.get_item_size( ea ) # This is bad abd abadbadbadbabdbabdad but there's no other choice here if size != 4: # This looks like it might be a bug with IDA # Random points of a vtable are getting turned into unknown data if size != 1: break s = "".join([ "%02x" % idc.get_wide_byte(ea + i) for i in range(3, -1, -1) ]) #.replace("0x", "") if not s.lower().startswith("ffff"): ea = ida_bytes.next_not_tail(ea) continue offs = int(s, 16) ea += 3 name = idc.get_name(offs, ida_name.GN_VISIBLE) if name: if os == OS_Linux: if not (name.startswith("_Z") or name.startswith("__cxa")) or name.startswith("_ZTV"): break # If we've exceeded past this vtable elif name.startswith("??"): break else: if os == OS_Win: break # dd -offsettothis # This is even worseworsoewewrosorooese s = "%02x" % offs if not s.lower().startswith("ffff"): ea = ida_bytes.next_not_tail(ea) continue name = (1 << 32) - int(offs) funcs.append(name) ea = ida_bytes.next_not_tail(ea) return funcs, eatemp
def get_data_guids(self): ''' rename GUIDs in idb ''' EFI_GUID = 'EFI_GUID *' EFI_GUID_ID = idc.get_struc_id('EFI_GUID') segments = ['.text', '.data'] for segment in segments: seg_start, seg_end = 0, 0 for seg in idautils.Segments(): if idc.get_segm_name(seg) == segment: seg_start = idc.get_segm_start(seg) seg_end = idc.get_segm_end(seg) break ea = seg_start while (ea <= seg_end - 15): prot_name = '' if idc.get_name(ea, ida_name.GN_VISIBLE).find('unk_') != -1: find = False cur_guid = [] cur_guid.append(idc.get_wide_dword(ea)) cur_guid.append(idc.get_wide_word(ea + 4)) cur_guid.append(idc.get_wide_word(ea + 6)) for addr in range(ea + 8, ea + 16, 1): cur_guid.append(idc.get_wide_byte(addr)) if cur_guid == [0] * 11: ea += 1 continue for guid_place in [ 'ami_guids', 'asrock_guids', 'dell_guids', 'edk_guids', 'edk2_guids', 'lenovo_guids' ]: for name in self.Protocols[guid_place]: if self.Protocols[guid_place][name] == cur_guid: prot_name = name + '_' + \ '{addr:#x}'.format(addr=ea) record = { 'address': ea, 'service': 'unknown', 'guid': cur_guid, 'protocol_name': name, 'protocol_place': guid_place } find = True break if find: break if find and (idc.get_name(ea, ida_name.GN_VISIBLE) != prot_name): idc.SetType(ea, EFI_GUID) self.apply_struct(ea, 16, EFI_GUID_ID) idc.set_name(ea, prot_name) self.Protocols['data'].append(record) ea += 1
def get_data_guids(self): """rename GUIDs in idb""" EFI_GUID = "EFI_GUID" EFI_GUID_ID = idc.get_struc_id("EFI_GUID") segments = [".text", ".data"] for segment in segments: seg_start, seg_end = 0, 0 for seg in idautils.Segments(): if idc.get_segm_name(seg) == segment: seg_start = idc.get_segm_start(seg) seg_end = idc.get_segm_end(seg) break ea = seg_start while ea <= seg_end - 15: prot_name = str() if "unk" in idc.get_name(ea, ida_name.GN_VISIBLE): find = False cur_guid = list() cur_guid.append(idc.get_wide_dword(ea)) cur_guid.append(idc.get_wide_word(ea + 4)) cur_guid.append(idc.get_wide_word(ea + 6)) for addr in range(ea + 8, ea + 16, 1): cur_guid.append(idc.get_wide_byte(addr)) if cur_guid == [0] * 11: ea += 1 continue for guid_place in [ "ami_guids", "asrock_guids", "dell_guids", "edk_guids", "edk2_guids", "lenovo_guids", ]: for name in self.Protocols[guid_place]: if self.Protocols[guid_place][name] == cur_guid: prot_name = f"{name}_{ea:016X}" record = { "address": ea, "service": "unknown", "guid": cur_guid, "protocol_name": name, "protocol_place": guid_place, } find = True break if find: break if find and (idc.get_name(ea, ida_name.GN_VISIBLE) != prot_name): idc.SetType(ea, EFI_GUID) self.apply_struct(ea, 16, EFI_GUID_ID) idc.set_name(ea, prot_name) self.Protocols["data"].append(record) ea += 1
def resolve_obf_calls(ea): next_instr_addr = idc.get_wide_dword(ea + 1) first_jmp_target = (ea + idc.get_wide_dword(ea + 0x7) + 0xB) & 0xFFFFFFFF second_jmp_target = (ea + idc.get_wide_dword(ea + 0xD) + 0x11) & 0xFFFFFFFF if first_jmp_target != second_jmp_target: return call_param = (first_jmp_target - ea - 5) & 0xFFFFFFFF # Now we can replace all code till next instruction's address with NOPs fill_with_nops(ea, next_instr_addr) # Insert CALL ida_bytes.patch_byte(ea, 0xE8) # CALL ida_bytes.patch_dword(ea + 1, call_param) idc.create_insn(ea) return True
def get_j_val(ea): size = 0 j_val = 0 op1 = idc.get_wide_byte(ea) if op1 == 0x0f: # jz or jnz j_val = idc.get_wide_dword(ea + 2) size = 6 else: # jz short or jnz short j_val = idc.get_wide_byte(ea + 1) size = 2 return j_val, size
def import_vtable(classname, struc): ea = get_vtable(classname) if ea == idc.BADADDR: return # Mildly adapted from Asherkin's vtable dumper ea = ea + 8 # Skip typeinfo and thisoffs funcs = [] while ea != idc.BADADDR: offs = idc.get_wide_dword(ea) if not ida_bytes.is_code(ida_bytes.get_full_flags(offs)): break name = idc.get_name(offs, ida_name.GN_VISIBLE) funcs.append(name) ea = ida_bytes.next_not_tail(ea) # print(funcs) if not len(funcs): return strucid = add_struc_ex(classname + "_vtbl") vstruc = ida_struct.get_struc(strucid) for i in funcs: # Gotta do a fancy demangle, it can't have special chars # and there can't be multiples of the same name, so let's just jazz around all of that demangled = idc.demangle_name(i, idc.get_inf_attr(idc.INF_SHORT_DN)) if demangled == None: demangled = i else: demangled = demangled[demangled.find("::") + 2:demangled.find("(")] demangled = demangled.replace("~", "_").replace("<", "_").replace(">", "_") while 1: error = ida_struct.add_struc_member(vstruc, demangled, idc.BADADDR, idc.FF_DWORD, None, 4) if error == 0: break demangled += "_{}".format( hex(ida_struct.get_struc_last_offset(vstruc) * 4 + 4)[2:]) # Now assign the vtable to the actual struct ti = idaapi.tinfo_t() idaapi.parse_decl(ti, None, classname + "_vtbl;", 0) ti.create_ptr(ti) ida_struct.set_member_tinfo(struc, ida_struct.get_member(struc, 0), 0, ti, 0)
def _prepare_guid(op, prefix): if op.type == o_mem: guid_ptr = Pointer(op.value) if guid_ptr.type != "EFI_GUID" or not is_uname( guid_ptr.name) or guid_ptr.name in ["Protocol", "HandlerType"]: guid_data1 = str("%.8x" % get_wide_dword(op.value)).upper() guid_ptr.name = "%s_PROTOCOL_%s_GUID" % (prefix, guid_data1) else: print("Do not know how to extract GUID ptr from %s at 0x%X" % (op, op.ea)) return return GUID(ptr=guid_ptr)
def find_bl_targets(text_start, text_end): targets = set() for pc in range(text_start, text_end, 4): d = idc.get_wide_dword(pc) if (d & 0xfc000000) == 0x94000000: imm = d & 0x3ffffff if imm & 0x2000000: imm |= ~0x1ffffff if 0 <= imm <= 2: continue target = pc + imm * 4 if target >= text_start and target < text_end: targets.add(target) return targets
def load(self, addr, dtyp): if addr is Unknown: return Unknown if not is_mapped_data(addr): return Unknown if dtyp == idaapi.dt_qword: return idc.get_qword(addr) elif dtyp == idaapi.dt_dword: return idc.get_wide_dword(addr) elif dtyp == idaapi.dt_word: return idc.get_wide_word(addr) elif dtyp == idaapi.dt_byte: return idc.get_wide_byte(addr) return Unknown
def cleanup_resolveapi_calls(ea): delta = 0 if idc.get_wide_byte(ea) == 0x6A else 3 intermediate_call_target = idc.get_wide_dword(ea + 8 + delta) if intermediate_call_target > 0x40: return # Check if we got library name if idc.get_wide_dword(ea + intermediate_call_target + 8 + delta) != 0x006c6c64: # "dll\x00" return # Check if we got enough space for patching if idc.get_wide_dword(ea + intermediate_call_target + 0x11 + delta) != 0x90909090 or \ idc.get_wide_byte(ea + intermediate_call_target + 0x15 + delta) != 0x90: return idc.patch_byte(ea + 7 + delta, 0xEB) idc.patch_byte(ea + 8 + delta, intermediate_call_target + 3) fill_with_nops(ea + 9 + delta, ea + 0xC + delta) idc.create_insn(ea + 7 + delta) # Now we need to pass module name parameter through stack resolve_api_call_param = idc.get_wide_dword(ea + intermediate_call_target + 0xD + delta) resolve_api_call_param = resolve_api_call_param - 5 # offset due to inserted PUSH command # Insert new PUSH command idc.patch_byte(ea + intermediate_call_target + 0xC + delta, 0x68) idc.patch_dword(ea + intermediate_call_target + 0xD + delta, ea + 0xC + delta) idc.create_insn(ea + intermediate_call_target + 0xC + delta) # Restore call ResolveApi idc.patch_byte(ea + intermediate_call_target + 0x11 + delta, 0xE8) idc.patch_dword(ea + intermediate_call_target + 0x12 + delta, resolve_api_call_param) idc.create_insn(ea + intermediate_call_target + 0x11 + delta) return True
def read_word(ea, wordsize=WORD_SIZE): """Get the word at the given address. Words are read using Byte(), Word(), Dword(), or Qword(), as appropriate. Addresses are checked using is_mapped(). If the address isn't mapped, then None is returned. """ if not is_mapped(ea, wordsize): return None if wordsize == 1: return idc.get_wide_byte(ea) if wordsize == 2: return idc.get_wide_word(ea) if wordsize == 4: return idc.get_wide_dword(ea) if wordsize == 8: return idc.get_qword(ea) raise ValueError('Invalid argument: wordsize={}'.format(wordsize))
def trace_register_family(reg, loc, func_ea, state=None): """ Trace a provided register to the location in which any member of its register family is set. If it is set using a mov operation, the value is either an o_imm type (return the immediate value) or an o_mem type, that means the referenced location MAY a pointer to the actual data, which we need to acquire. We validate this by ensuring the acquired value is within the loaded memory range of the application. Otherwise we return idc.BADADDR. If the register is set using an lea operation, it is likely done so using a stack variable (which we validate) and then trace back to determine how the stack variable is set. :param reg: The referenced register which a location is loaded into :param loc: The starting offset for tracing back from :param func_ea: Starting function offset :param state: the current TraceState (a new state will be created if one is not provided) :return: The acquired location, or idc.BADADDR """ if state is None: state = TraceState() reg_fam = unsafe_get_reg_fam(reg) if reg_fam: loc = idc.prev_head(loc) while loc != func_ea: opnd = idc.print_operand(loc, 0) op_type_1 = idc.get_operand_type(loc, 1) opval_1 = idc.get_operand_value(loc, 1) mnem = idc.print_insn_mnem(loc) if 'mov' in mnem and opnd in reg_fam: if op_type_1 == idc.o_imm: return opval_1 elif op_type_1 == idc.o_mem: poss_loc = idc.get_wide_dword(opval_1) if idaapi.cvar.inf.minEA <= poss_loc < idaapi.cvar.inf.maxEA: return poss_loc else: return opval_1 else: return idc.BADADDR elif mnem == 'lea' and op_type_1 == idc.o_displ and opnd in reg_fam: stack_var = get_operand_value_replacement(loc, 1, state) return trace_stack_var(stack_var, loc, func_ea, state) elif is_64_bit() and mnem == 'lea' and opnd in reg_fam: if op_type_1 == idc.o_mem: return opval_1 loc = idc.prev_head(loc) return idc.BADADDR
def make_date_ref(): ea = 0x9561C max_ea = ida_ida.inf_get_max_ea() min_ea = ida_ida.inf_get_min_ea() while True: ea = ida_search.find_unknown(ea, idc.SEARCH_DOWN | idc.SEARCH_NEXT) if ea > max_ea: break size = idc.get_item_size(ea) print(hex(ea)) val = idc.get_wide_dword(ea) # if 0xfff38 < val < 0x188544 or 0x1f000000 < val < 0x1ffa3fd9 or 0x20000000 < val < 0x2001ffff: # idc.OpOff(ea, 0, 0) if min_ea < val < max_ea: idc.op_plain_offset(ea, 0, 0)
def trace_register_family_x64(reg, loc, func_ea, state=None): """ Shouldn't be any different than trace_register_family except for continuing a trace if a register is loaded into the target register. However, using it in trace_register_family was not behaving properly, so keeping it separate for now. Also unsure of what the repercussions would be of adding that into the existing trace_register_family. :param reg: The referenced register which a location is loaded into :param loc: The starting offset for tracing back from :param func_ea: Starting function offset :param state: the current TraceState :return: The acquired location, or idc.BADADDR """ if state is None: state = TraceState() reg_fam = unsafe_get_reg_fam(reg) if reg_fam: loc = idc.prev_head(loc) while loc != func_ea: opnd = idc.print_operand(loc, 0) op_type_1 = idc.get_operand_type(loc, 1) opval_1 = idc.get_operand_value(loc, 1) mnem = idc.print_insn_mnem(loc) if "mov" in mnem and opnd in reg_fam: if op_type_1 == idc.o_imm: return opval_1 elif op_type_1 == idc.o_mem: poss_loc = idc.get_wide_dword(opval_1) if idaapi.cvar.inf.minEA <= poss_loc < idaapi.cvar.inf.maxEA: return poss_loc else: return opval_1 elif op_type_1 == idc.o_reg: return trace_register_family_x64(idc.print_operand(loc, 1), loc, func_ea, state) else: return idc.BADADDR elif mnem == "lea" and op_type_1 == idc.o_displ and opnd in reg_fam: stack_var = get_operand_value_replacement(loc, 1, state) return trace_stack_var(stack_var, loc, func_ea, state) elif is_64_bit() and mnem == "lea" and opnd in reg_fam: if op_type_1 == idc.o_mem: return opval_1 loc = idc.prev_head(loc) return idc.BADADDR
def read_vtable(funcname, ea): funcs = {} offset = 0 while ea != idc.BADADDR: offs = idc.get_wide_dword(ea) if not ida_bytes.is_code(ida_bytes.get_full_flags(offs)): break name = idc.get_name(offs, ida_name.GN_VISIBLE) demangled = idc.demangle_name(name, idc.get_inf_attr(idc.INF_SHORT_DN)) if demangled == None: demangled = name if "(" in demangled: demangled = demangled[:demangled.find("(")] funcs[demangled.lower()] = offset offset += 1 ea = ida_bytes.next_not_tail(ea) # We've got a list of function names, let's do this really shittily because idk any other way # This is a good programmer who makes their gamedata the proper way :) offs = funcs.get(funcname.lower(), -1) if offs != -1: return offs # Often done but sometimes there are subclass types thrown in, save those too if "::" in funcname: funcname = funcname[funcname.find("::") + 2:] # Try by exact function name funcnames = {} for key, value in get_bcompat_items(funcs): # Function overloads can f**k right off s = key[key.find("::") + 2:].lower() if "::" in key else key.lower() funcnames[s.lower()] = value offs = funcnames.get(funcname.lower(), -1) # Second best way, exact function name if offs != -1: return offs return -1
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)