def push_comms(): global skel_conn commBL = [ "size_t", "int", "LPSTR", "char", "char *", "lpString", "unsigned int", "void *", "indirect table for switch statement", "this", "jump table for switch statement", "switch jump" ] for i in range(idc.MinEA(), idc.MaxEA()): if idc.GetCommentEx( i, 0) is not None and not idc.GetCommentEx(i, 0) in commBL: if not skel_conn.push_comment(i, idc.GetCommentEx(i, 0)): return -1 elif idc.GetCommentEx( i, 1) is not None and not idc.GetCommentEx(i, 1) in commBL: if not skel_conn.push_comment(i, idc.GetCommentEx(i, 1)): return -1 for function_ea in idautils.Functions(idc.MinEA(), idc.MaxEA()): fName = idc.GetFunctionName(function_ea) if hasSubNoppedPrefix(fName) is False: if not skel_conn.push_name(function_ea, fName): g_logger.error("Error sending function name %s" % (fName)) # if idc.GetFunctionCmt(function_ea,0) != "": # push_change("idc.SetFunctionCmt",shex(function_ea),idc.GetFunctionCmt(i,0)) # elif idc.GetFunctionCmt(function_ea,1) != "": # push_change("idc.SetFunctionCmt",shex(function_ea),idc.GetFunctionCmt(function_ea,1)) return
def GetDyn(): phoff = idc.Dword(idc.MinEA() + 0x1c) + idc.MinEA() phnum = idc.Word(idc.MinEA() + 0x2c) phentsize = idc.Word(idc.MinEA() + 0x2a) for i in range(phnum): p_type = idc.Dword(phoff + phentsize * i) if p_type == 2: # PY_DYNAMIC dyn_addr = idc.Dword(phoff + phentsize * i + 8) return dyn_addr
def find_interesting_xors(self): next_xor = idc.FindText(idc.MinEA(), idc.SEARCH_DOWN | idc.SEARCH_NEXT, 0, 0, "xor") while next_xor != idc.BADADDR: if idc.GetOpnd(next_xor, 0) != idc.GetOpnd(next_xor, 1): entry = { "func": "", "addr": next_xor, "loop": False, "disasm": idc.GetDisasm(next_xor) } func = idaapi.get_func(next_xor) if func: entry["func"] = idaapi.get_name(idc.BADADDR, func.startEA) heads = idautils.Heads(next_xor, func.endEA) lxors = [] for head in heads: if idc.GetMnem(head).startswith('j'): jmp_addr = idc.GetOperandValue(head, 0) if jmp_addr < next_xor and jmp_addr > func.startEA: entry["loop"] = True break self._interesting_xors.append(entry) next_xor = idc.FindText(idc.NextHead(next_xor), idc.SEARCH_DOWN | idc.SEARCH_NEXT, 0, 0, "xor")
def main(): if _IN_IDA: # # get dyld_shared_cache path from IDA's openFile dialog print "[+] Please choose the original dyld_shared_cache_arm64" dsc_path = idc.AskFile(0, "*.*", "dyld shared cache file") else: dsc_path = sys.argv[1] if not dsc_path or not os.path.exists(dsc_path): raise RuntimeError("Couldn't find the dyld shared cache file..") print "[+] about to parse %s.." % (dsc_path) dsc_file = open(dsc_path, "rb") adrfind = AddrFinder(dsc_file, cache_symbols=False) map_shared_bridges(dsc_file, adrfind) if _IN_IDA: addresses = sorted(set(get_bad_addresses())) else: addresses = sorted(set(eval(open("addrs.txt", "rb").read()))) segments, exports = get_segments_and_exports_for_addresses( addresses, adrfind) # segments = join_neighbors(segments, threshold=0x1000) if _IN_IDA: map_segments(segments, dsc_file) map_exports(exports) idaapi.analyze_area(idc.MinEA(), idc.MaxEA())
def msr_parse(): start = idc.MinEA() stop = idc.MaxEA() rdmsr_addr = idaapi.find_binary(start, stop, "0F 32", 0, 0) wrmsr_addr = idaapi.find_binary(start, stop, "0F 30", 0, 0) cpuid_addr = idaapi.find_binary(start, stop, "0F A2", 0, 0) idc.MakeCode(each)
def find_function_epilogue_bxlr(self, makecode=False): ''' Find opcode bytes corresponding to BX LR. This is a common way to return from a function call. Using the IDA API, convert these opcodes to code. This kicks off IDA analysis. ''' EAstart = idc.MinEA() EAend = idc.MaxEA() ea = EAstart length = 2 # this code isn't tolerant to values other than 2 right now fmt_string = "Possible BX LR 0x%08x == " for i in range(length): fmt_string += "%02x " while ea < EAend: instructions = [] for i in range(length): instructions.append(idc.Byte(ea + i)) if not ida_bytes.isCode(ida_bytes.getFlags(ea)) and instructions[ 0] == 0x70 and instructions[1] == 0x47: if self.printflag: print fmt_string % (ea, instructions[0], instructions[1]) if makecode: idc.MakeCode(ea) ea = ea + length
def sample_dest(): global x src_hashes = {} for i in x.split("|"): z = i.split(":") if src_hashes.has_key(z): src_hashes[z] = "baadf00d" else: src_hashes[i[1]] = i[0] dst_hashes = {} for addr in idautils.Functions(idc.MinEA(), idc.MaxEA()): fname = idc.GetFunctionName(addr) if fname.startswith("sub_"): z = calc_hash(addr) if dst_hashes.has_key(z): src_hashes[z] = "baadf00d" else: src_hashes[z] = addr for x in dst_hashes: if dst_hashes[x] == "baadf00d": continue if src_hashes.has_key(x): if src_hashes[x] != "baadf00d": idc.MakeNameEx(dst_hashes[x], src_hashes[x], SN_NOWARN) print full_hash
def find_all_switch_jumps(self): self._switch_dict = defaultdict(list) next_switch = idc.FindBinary(idc.MinEA(), idc.SEARCH_DOWN|idc.SEARCH_NEXT, "ff 24") while next_switch != idc.BADADDR: sw = idaapi.get_switch_info_ex(next_switch) if idc.GetMnem(next_switch).startswith("jmp") and sw: ic = self.get_jlocs(sw) self._switch_dict[idaapi.get_func_name(next_switch)].append((next_switch, sw.ncases, ic)) next_switch = idc.FindBinary(idc.NextHead(next_switch), idc.SEARCH_DOWN|idc.SEARCH_NEXT, "ff 24")
def activate(self, ctx): arch = idc.Word(idc.MinEA() + 0x12) if arch == 0x3E: # EM_X86_64 PltResolver64() elif arch == 0x3: # EM_386 PltResolver32() else: print '[-] Only support EM_X86_64 and EM_386' return 1
def getAddressOfFirstLine(root_path): with open(root_path + 'first_address.txt', 'w') as f: try: address_of_first_line = str(hex(idc.MinEA())) except: address_of_first_line = "error" f.write(address_of_first_line)
def find_wdf_callback_through_immediate(mnemonic, operand, val): for i in range(10): addr, operand_ = idc.FindImmediate(idc.MinEA(), idc.SEARCH_DOWN|idc.SEARCH_NEXT, val) if addr != idc.BADADDR: #print hex(addr), idc.GetDisasm(addr), "Operand ", operand_ if operand_ == operand and idc.GetMnem(addr) == mnemonic: return addr else: break return None
def AnalyzeAllSections(self): BlockData = {} Map = [] CurrentAddress = idc.MinEA() i = 0 while i < idaapi.get_segm_qty(): seg = idaapi.getnseg(i) self.AnalyzeRange(seg.startEA, seg.endEA) i += 1
def save_call_graph(): cur = idc.MinEA() end = idc.MaxEA() #D:\source\test1\test_dir\p_16 #path_dir=os.path.dirname(idc.GetIdbPath()) #p_dir=path_dir.split('\\')[-1] #elf_name=os.path.basename(idc.GetIdbPath()).split('.')[-2] i64_file = idc.GetIdbPath() first_dot = i64_file.find('.') no_dot_file = i64_file[:first_dot] gdl_path = no_dot_file + '.gdl' idc.GenCallGdl(gdl_path, 'Call Gdl', idc.CHART_GEN_GDL)
def push_functions_names(): """ Push the defined function names """ global skel_conn for addr in idautils.Functions(idc.MinEA(), idc.MaxEA()): fname = GetFunctionName(addr) if fname != "" and not hasSubNoppedPrefix(fname): if skel_conn.push_name(addr, fname) == -1: return False return True
def is_valid_ea(ea): """ Description: Returns true for valid EAs, False for invalid ones. Input: ea - The EA to check Output: True if the EA is valid, False if it is not """ return ea not in [INVALID, UNUSED, idc.BADADDR] and idc.MinEA() <= ea <= idc.MaxEA()
def pushFunctionsNames(): """ update les noms de fonctions depuis l'idb actuel """ global sample_id for addr in idautils.Functions(idc.MinEA(), idc.MaxEA()): fname = GetFunctionName(addr) if fname != "" and not hasSubNoppedPrefix(fname): if skel_conn.push_name(addr, fname) == -1: return -1 return 0
def renameDword(self): proc_addr = self._import_table.item(self._import_table.currentRow(), 3).text() proc_name = str(self._import_table.item(self._import_table.currentRow(), 2).text()) renamed = 0 if proc_addr: try: proc_addr = int(proc_addr, 16) proc_bin_str = " ".join([x.encode("hex") for x in struct.pack("<I", proc_addr)]) next_dword = idc.FindBinary(idc.MinEA(), idc.SEARCH_DOWN|idc.SEARCH_NEXT, proc_bin_str) while next_dword != idc.BADADDR: log.debug("Trying to fix-up 0x{:08x}".format(next_dword)) # DWORDs can be "inaccessible" for many reasons and it requires "breaking up" the data blobs # and manually fixing them # Reason 1: In a dword array in an unknown section if idc.isUnknown(next_dword): idc.MakeUnkn(next_dword, idc.DOUNK_EXPAND) idc.MakeDword(next_dword) # Reason 2: In a dword array in a data section elif idc.isData(next_dword): hd = idc.ItemHead(next_dword) idc.MakeDword(hd) idc.MakeDword(next_dword) # Reason 3: In a dword array in a code section (validate via "dd <dword>,") elif idc.isCode(next_dword) and idc.GetDisasm(next_dword).startswith("dd "): hd = idc.ItemHead(next_dword) idc.MakeDword(hd) idc.MakeDword(next_dword) # Only perform if idc.Name(next_dword).startswith(("off_", "dword_")) or idc.Name(next_dword) == "": success = idc.MakeNameEx(next_dword, proc_name, idc.SN_NOWARN|idc.SN_NON_AUTO) i = 0 new_proc_name = proc_name while not success and i < 10: new_proc_name = "{}{}".format(proc_name, i) success = idc.MakeNameEx(next_dword, new_proc_name, idc.SN_NOWARN|idc.SN_NON_AUTO) i += 1 if success: renamed += 1 item = self._import_table.item(self._import_table.currentRow(), 5) item.setText("{}, {}".format(str(item.text()), new_proc_name)) log.debug("DWORD @ 0x{:08x} now has name {}".format(next_dword, new_proc_name)) else: log.error("Unable to auto-rename successfully, terminating search") break else: log.debug("Value at 0x{:08x} does not meet renaming requirements".format(next_dword)) next_dword = idc.FindBinary(next_dword+4, idc.SEARCH_DOWN|idc.SEARCH_NEXT, proc_bin_str) except Exception, e: log.error("Error encountered: {}".format(e)) log.debug("Renamed {:d} instances of {}".format(renamed, proc_name))
def renamed(self, *args): g_logger.debug("[IDP Hook] Something is renamed") ea, new_name, is_local_name = args if ea >= idc.MinEA() and ea <= idc.MaxEA(): if is_local_name: g_logger.warning("Local names are unimplemented") pass else: if not SkelUtils.name_blacklist(new_name): self.skel_conn.push_name(ea, new_name) else: g_logger.warning("ea outside program...") return idaapi.IDP_Hooks.renamed(self, *args)
def renamed(self, *args): g_logger.debug("[IDB Hook] Something is renamed") ea, new_name, is_local_name = args if ea > idc.MinEA() and ea < idc.MaxEA(): if is_local_name: # XXX push_new_local_name(ea, new_name) pass else: if not SkelUtils.name_blacklist(new_name): self.skel_conn.push_name(ea, new_name) else: print "ea outside program..." return idaapi.IDP_Hooks.renamed(self, *args)
def autoCode(hex_value): start = idc.MinEA(); len=idc.MaxEA()-start; addr=start; flag = False for x in range(len): addr = idc.FindBinary(addr, SEARCH_DOWN|SEARCH_CASE|SEARCH_NEXT, hex_value) if addr != idc.BADADDR: make_code(addr,addr+4) print "{:>8X} {:<32}".format(addr,idc.GetDisasm(addr)) else: flag = False #addr=idc.NextHead(addr) return 0
def find_string_table_refs(string_table_start, string_table_end, mark=False): image_start = idc.MinEA() image_end = idc.MaxEA() image_size = image_end - image_start print "Analyzing image from %.8x-%.8x of size %.8x" % ( image_start, image_end, image_size) for cur_ea in xrange(image_start, image_end, 4): cur_long = Dword(cur_ea) if cur_long >= string_table_start and cur_long < string_table_end: if mark: SetType(cur_ea, "char *ptr;") print "Found string table ref at 0x%.8x to 0x%.8x (%s)" % ( cur_ea, cur_long, GetDisasm(cur_ea))
def nonfunction_first_instruction_heuristic(self, makefunction=False): EAstart = idc.MinEA() EAend = idc.MaxEA() ea = EAstart flag_code_outside_function = False self.printflag = False while ea < EAend: # skip functions, next instruction will be the target to inspect function_name = idc.GetFunctionName(ea) if function_name != "": flag_code_outside_function = False # skip to end of function and keep going # ea = idc.FindFuncEnd(ea) #if self.printflag: # print "Skipping function %s" % (function_name) ea = ida_search.find_not_func(ea, 1) continue elif ida_bytes.isCode(ida_bytes.getFlags(ea)): # code that is not a function # get mnemonic to see if this is a push mnem = idc.GetMnem(ea) if makefunction and (mnem == "PUSH" or mnem == "PUSH.W" or mnem == "STM" or mnem == "MOV"): if self.printflag: print "nonfunction_first_instruction_heuristic() making function %08x" % ea idc.MakeFunction(ea) flag_code_outside_function = False ea = ida_search.find_not_func(ea, 1) continue else: if self.printflag: print "nonfunction_first_instruction_heuristic() other instruction %08x\t'%s'" % ( ea, mnem) ea = idc.NextFunction(ea) continue ea += 1
def pci_analisys(): # searching snippets: # ------------------- # mov eax, 8000xxxxh ; optional line # mov dx, CF8h # out dx, eax # ------------------- # mov dx, CF8h # mov eax, 8000xxxxh # out dx, eax # ------------------- position_start = idc.MinEA() position_stop = idc.MaxEA() outdxeax = position_start while outdxeax : outdxeax = idaapi.find_binary(position_start, position_stop, "66 EF", 0, 0) if outdxeax: position_start = outdxeax + 1
def make_new_functions_heuristic_push_regs(self, makefunction=False): ''' After converting bytes to instructions, Look for PUSH instructions that are likely the beginning of functions. Convert these code areas to functions. ''' EAstart = idc.MinEA() EAend = idc.MaxEA() ea = EAstart while ea < EAend: if self.printflag: print "EA %08x" % ea ea_function_start = idc.GetFunctionAttr(ea, idc.FUNCATTR_START) # If ea is inside a defined function, skip to end of function if ea_function_start != idc.BADADDR: ea = idc.FindFuncEnd(ea) continue # If current ea is code if ida_bytes.isCode(ida_bytes.getFlags(ea)): # Looking for prologues that do PUSH {register/s} mnem = idc.GetMnem(ea) # if (mnem == "PUSH"): if makefunction: if self.printflag: print "Converting code to function @ %08x" % ea idc.MakeFunction(ea) eanewfunction = idc.FindFuncEnd(ea) if eanewfunction != idc.BADADDR: ea = eanewfunction continue nextcode = ida_search.find_code(ea, idc.SEARCH_DOWN) if nextcode != idc.BADADDR: ea = nextcode else: ea += 1
def find_pushpop_registers_arm(self, makecode=False): ''' Find opcodes for PUSH/POP registers in ARM mode Using the IDA API, convert these opcodes to code. This kicks off IDA analysis. bigup jmitch ** ** 2d e9 and ** ** bd e8 ''' EAstart = idc.MinEA() EAend = idc.MaxEA() ea = EAstart length = 2 # this code isn't tolerant to values other than 2 right now fmt_string = "Possible %s {REGS} 0x%08x == " for i in range(length): fmt_string += "%02x " while ea < EAend: instructions = [] for i in range(length): instructions.append(idc.Byte(ea + i)) # print BX LR bytes if not ida_bytes.isCode(ida_bytes.getFlags(ea)) and \ (instructions[0] == 0xbd and instructions[1] == 0xe8): if self.printflag: print fmt_string % ("POP ", ea, instructions[0], instructions[1]) if makecode: idc.MakeCode(ea) if not ida_bytes.isCode(ida_bytes.getFlags(ea)) and \ (instructions[0] == 0x2d and instructions[1] == 0xe9) \ : if self.printflag: print fmt_string % ("PUSH", ea, instructions[0], instructions[1]) if makecode: idc.MakeCode(ea) ea = ea + length
def find_push_thumb(mark=False): def is_push(opcode): return (0xfffffe00 & opcode) == 0x0000b400 image_start = idc.MinEA() image_end = idc.MaxEA() image_size = image_end - image_start print "Analyzing image from %.8x-%.8x of size %.8x" % ( image_start, image_end, image_size) for cur_ea in xrange(image_start, image_end, 2): cur_word = Word(cur_ea) if is_push(cur_word) and "DCB" in GetDisasm(cur_ea): print "Found candidate at 0x%.8x -> %s" % (cur_ea, GetDisasm(cur_ea)) if mark: MakeCode(cur_ea) print "Marked candidate at 0x%.8x -> %s" % (cur_ea, GetDisasm(cur_ea))
def find_nops(mark=False): """ Look for THUMB nops (0xbf00). """ def is_nop(opcode): return opcode == 0xbf00 image_start = idc.MinEA() image_end = idc.MaxEA() image_size = image_end - image_start print "Analyzing image from %.8x-%.8x of size %.8x" % ( image_start, image_end, image_size) for cur_ea in xrange(image_start, image_end, 2): cur_word = Word(cur_ea) if is_nop(cur_word): print "Found candidate at 0x%.8x -> %s" % (cur_ea, GetDisasm(cur_ea)) if mark: MakeCode(cur_ea)
def find_prologs(): push_masks = [(0x0fff0000, 0x092d0000), (0x0fff0fff, 0x052d0004)] def is_push(opcode): for mask in push_masks: if (mask[0] & opcode) == mask[1]: return True return False image_start = idc.MinEA() image_end = idc.MaxEA() image_size = image_end - image_start print "Analyzing image from %.8x-%.8x of size %.8x" % ( image_start, image_end, image_size) for cur_ea in xrange(image_start, image_end, 4): cur_long = Dword(cur_ea) if is_push(cur_long): print "Found candidate at 0x%.8x -> %s" % (cur_ea, GetDisasm(cur_ea))
def find_pairs(): ea = idc.MinEA() movh = [None] * MAX_REGISTERS while ea < idc.MaxEA(): insn = idautils.DecodeInstruction(ea) if insn: mnem = insn.get_canon_mnem() reg1 = insn.Op1.reg reg2 = insn.Op2.reg val1 = insn.Op2.value val2 = insn.Op3.value size = insn.size if mnem == "movh" and insn.Op2.type == o_imm: movh[reg1] = (val1, insn.ea) elif movh[reg1] is not None: other = movh[reg1] if mnem == "add3" and reg1 == reg2: target = (other[0] << 16) + val2 print "Found a add3 pointer pair to ", hex(target), " at ", hex(insn.ea) idc.add_dref(insn.ea, target, dr_O) idc.add_dref(other[1], target, dr_O) idaapi.set_refinfo(insn.ea, 2, REF_LOW16, target, 0, 0) idaapi.set_refinfo(other[1], 1, REF_HIGH16, target, 0, 0) elif mnem == "or3" and reg1 == reg2: target = (other[0] << 16) | val2 print "Found a or3 pointer pair to ", hex(target), " at ", hex(insn.ea) idc.add_dref(insn.ea, target, dr_O) idc.add_dref(other[1], target, dr_O) idaapi.set_refinfo(insn.ea, 2, REF_LOW16, target, 0, 0) idaapi.set_refinfo(other[1], 1, REF_HIGH16, target, 0, 0) movh[reg1] = None if insn.get_canon_feature() & (idaapi.CF_STOP | idaapi.CF_CALL): movh = [None] * MAX_REGISTERS else: size = 2 ea += size
def find_pushpop_registers_thumb(self, makecode=False): ''' Look for opcodes that push registers onto the stack, which are indicators of function prologues. Using the IDA API, convert these opcodes to code. This kicks off IDA analysis. ''' ''' thumb register list from [email protected] ''' thumb_reg_list = [ 0x00, 0x02, 0x08, 0x0b, 0x0e, 0x10, 0x1c, 0x1f, 0x30, 0x30, 0x38, 0x3e, 0x4e, 0x55, 0x70, 0x72, 0x73, 0x7c, 0x7f, 0x80, 0x90, 0xb0, 0xf0, 0xf3, 0xf7, 0xf8, 0xfe, 0xff ] EAstart = idc.MinEA() EAend = idc.MaxEA() ea = EAstart length = 2 # this code isn't tolerant to values other than 2 right now fmt_string = "Possible Function 0x%08x == " for i in range(length): fmt_string += "%02x " while ea < EAend: instructions = [] for i in range(length): instructions.append(idc.Byte(ea + i)) if not ida_bytes.isCode(ida_bytes.getFlags( ea)) and instructions[0] in thumb_reg_list and ( instructions[1] == 0xb5 or instructions[1] == 0xbd): if self.printflag: print fmt_string % (ea, instructions[0], instructions[1]) if makecode: idc.MakeCode(ea) ea = ea + length