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 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 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 save_file(output_file): """ Save the patched file """ DIFF_RE = re.compile(r'([A-F0-9]+): ([A-F0-9]+) ([A-F0-9]+)') idc.GenerateFile(idaapi.OFILE_DIF, output_file, 0, idc.MaxEA(), 0) diff_file = open(output_file, "rb").read() orig_file = open(idc.GetInputFilePath(), "rb").read() print "OK" diff_file = diff_file.split("\n") total = 0 success = 0 for line in diff_file: match = DIFF_RE.match(line) if match: groups = match.groups() total += 1 offset = int(groups[0], 16) orig_byte = groups[1].decode('hex') new_byte = groups[2].decode('hex') if orig_file[offset] == orig_byte: orig_file = orig_file[:offset] + new_byte + orig_file[offset + 1:] success += 1 else: print "Error matching %02x at offset %x..." % (groups[1], offset) new_file = open(output_file, 'wb') new_file.write(orig_file) new_file.close() print "%i/%i patches applied" % (success, total)
def method_2(): """ Simple way to convert a table of strings into strings on IDA. """ start = AskAddr(ScreenEA(), "Where do I start looking for strings?") end = idc.MaxEA() cur_string = "" last_byte = None for cur_ea in xrange(start, end): byte_ = chr(Byte(cur_ea)) if not is_printable(byte_): # If this is a terminating byte, check if the collected bytes form a string. if byte_ == '\x00': if not len(cur_string): print "Last string at 0x%.8x" % (cur_ea) break else: print "0x%.8x : %s" % (cur_ea - len(cur_string), cur_string) MakeStr(cur_ea - len(cur_string), cur_ea + 1) cur_string = "" else: cur_string += byte_ last_byte = byte_
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 find_binary_instruction_start(search_start_location, search_direction, target, min_location=idc.MinEA(), max_location=idc.MaxEA()): """ Description: Given a starting location, target, and direction, find an instruction starting with the target bytes. Input: search_start_location - The EA to start searching at search_direction - either idc.SEARCH_UP or idc.SEARCH_DOWN target - The target as space separated bytes (i.e. '55' for 'push ebp') min_location - The minimum EA to accept results for (default: idc.MinEA()) max_location - The maximum EA to accept results for (default: idc.MaxEA()) Output: Returns the first matching location if found, otherwise idc.BADADDR """ target = target.upper() while search_start_location < max_location: ea = idc.FindBinary(search_start_location, search_direction, target) if (min_location <= ea < max_location and ea == idc.ItemHead(ea) and idaapi.get_many_bytes(ea, idc.ItemSize(ea)).encode('hex').upper().startswith(target.replace(' ', ''))): return ea else: search_start_location = ea + (1 if search_direction == idc.SEARCH_DOWN else -1) return idc.BADADDR
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 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 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 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 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 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 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 add_struc_descr(sid, structure, rep): """ Insert a (repeatable) comment descripting the structure whose id is sid. And name address in added segment annotated with structure description. Arguments: sid -- structure id which the added comment is describing structure -- structure object holding data rep -- add repeatable comment (True\False) Return: True -- if success; False otherwise """ # TODO correct or not descr = format_comment(structure.description) + '\n' if idc.SetStrucComment(sid, descr, rep): frm = [x.frm for x in idautils.XrefsTo(sid)] for ea in frm: # Added comment for global %structure.name% variable or pointer if ea > idc.MaxEA(): # getting 'member_t' using ea as 'mid' mptr = idaapi.get_member_by_id(ea) # IDA 6.8: setting member comment using 'mptr' as index idaapi.set_member_cmt(mptr, descr, rep) # IDA 6.9: mptr is type of list #idaapi.set_member_cmt(mptr[0], descr, rep) else: if not rep: idc.MakeComm(ea, descr) else: idc.MakeRptCmt(ea, descr) return True else: return False
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
def method_1(): """ This method does not work very well so far. """ dictionary = enchant.Dict("en_US") # Get the image base of the database. 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) cur_string = "" for cur_ea in xrange(image_start, image_end): byte_ = chr(Byte(cur_ea)) if not is_printable(byte_): # If this is a terminating byte, check if the collected bytes form a string. if byte_ == '\x00' and len(cur_string): cur_string = cur_string.replace("-", " ").replace("_", " ") words = cur_string.split() nwords = 0 for word in words: if len(word) > 2 and dictionary.check(word) and ( not word[0] in string.digits): nwords += 1 if nwords > 1: print "0x%.8x : %s" % (cur_ea, cur_string) break cur_string = "" else: cur_string += byte_
def fix_callgraph(msgsend, segname, class_param, sel_param): ''' fix_callgraph: msgsend, segname, class_param, sel_param Given the msgsend flavour address as a parameter, looks for the parameters (class and selector, identified by class_param and sel_param) and creates a new segment where it places a set of dummy calls named as classname_methodname (we use method instead of selector most of the time). ''' t1 = time.time() if not msgsend: print 'ERROR: msgSend not found' return total = 0 resolved = 0 call_table = dict() for xref in idautils.XrefsTo(msgsend, idaapi.XREF_ALL): total += 1 ea_call = xref.frm func_start = idc.GetFunctionAttr(ea_call, idc.FUNCATTR_START) if not func_start or func_start == idc.BADADDR: continue ea = ea_call method_name_ea = track_param(ea, func_start, idc.o_displ, sel_param) if method_name_ea: method_name = idc.GetString(method_name_ea, -1, idc.ASCSTR_C) if not method_name: method_name = '' else: method_name = '' class_name_ea = track_param(ea, func_start, idc.o_phrase, class_param) if class_name_ea: class_name = idc.GetString(class_name_ea, -1, idc.ASCSTR_C) if not class_name: class_name = '' else: class_name = '' if not method_name and not class_name: continue # Using this name convention, if the class and method # are identified by IDA, the patched call will point to # the REAL call and not one of our dummy functions # class_name = class_name.replace('_objc_class_name_', '') new_name = '_[' + class_name + '_' + method_name + ']' call_table[ea_call] = new_name resolved += 1 print '\nFinal stats:\n\t%d total calls, %d resolved' % (total, resolved) print '\tAnalysis took %.2f seconds' % (time.time() - t1) if resolved == 0: print 'Nothing to patch.' return print 'Adding new segment to store new nullsubs' # segment size = opcode ret (4 bytes) * num_calls seg_size = resolved * 4 seg_start = idc.MaxEA() + 4 idaapi.add_segm(0, seg_start, seg_start + seg_size, segname, 'CODE') print 'Patching database...' seg_ptr = seg_start for ea, new_name in call_table.items(): if idc.LocByName(new_name) != idc.BADADDR: offset = (idc.LocByName(new_name) - ea) & idc.BADADDR else: # create code and name it idc.PatchDword(seg_ptr, 0x90) # nop idc.MakeName(seg_ptr, new_name) idc.MakeCode(seg_ptr) idc.MakeFunction(seg_ptr, seg_ptr + 4) idc.MakeRptCmt(seg_ptr, new_name) offset = seg_ptr - ea seg_ptr += 4 dw = offset - 5 idc.PatchByte(ea, 0xE8) idc.PatchDword(ea + 1, dw)
idc.MakeCode(seg_ptr) idc.MakeFunction(seg_ptr, seg_ptr + 4) idc.MakeRptCmt(seg_ptr, new_name) offset = seg_ptr - ea seg_ptr += 4 dw = offset - 5 idc.PatchByte(ea, 0xE8) idc.PatchDword(ea + 1, dw) def make_offsets(segname): segea = idc.SegByBase(idc.SegByName(segname)) segend = idc.SegEnd(segea) while segea < segend: idc.OpOffset(segea, 0) ptr = idc.Dword(segea) idc.OpOffset(ptr, 0) segea += 4 if __name__ == '__main__': make_offsets('__cls_refs') make_offsets('__message_refs') idaapi.analyze_area(idc.MinEA(), idc.MaxEA()) fix_callgraph(idc.LocByName('_objc_msgSend'), 'msgSend', 4, 4) fix_callgraph(idc.LocByName('_objc_msgSendSuper'), 'msgSendSuper', 4, 4) idaapi.analyze_area(idc.MinEA(), idc.MaxEA()) print 'Done.'
def fix_names(self): """ Fix the table of imports and map enums to apis. """ start_addr = idc.AskAddr(idc.here(), "Enter table start address") ## check if address is within the base address and maximum address if (start_addr < idc.MinEA()) or (start_addr > idc.MaxEA()): idc.Warning("You have entered an invalid start address") idc.Exit self.start_addr = start_addr current_addr = self.start_addr #Current size of PoisonIvy IAT end_addr = current_addr + 568 # Walk the table 8 bytes at a time while current_addr <= end_addr: idc.MakeQword(current_addr) print "DEBUG: Current address - 0x%08x" % current_addr addr = idc.Qword(current_addr) print "DEBUG: address - 0x%08x" % addr if addr == -1: print "[!] Skipping address 0x%08x - 0x%08x" % (current_addr, addr) current_addr += 8 continue # Make the current address an offset idc.OpOff(current_addr,0,0) # We need to undefine the bytes incase IDA autoanalysis had converted an incorrect byte idc.MakeUnkn(addr, 1) # Create code at this address idc.MakeCode(addr) # Create function at the same address idc.MakeFunction(addr, addr+16) # Read the second operand at the address which should be the negative API address value imp_addr = idc.GetOperandValue(addr, 1) if imp_addr == -1: print "[!] Couldn't get operand at address - 0x%08x" % addr current_addr +=8 continue # try: # int_addr = int(imp_addr,16) # except ValueError as e: # print "[!] Failed on: %s - %s\n" % (imp_addr, e) # current_addr +=8 # continue # if we know about this value then let's do the work if imp_addr in self.enums.keys(): enum_id = self.enums[imp_addr] # Convert operand to enum idc.OpEnumEx(addr, 1, enum_id,0) const_id = idc.GetConstEx(enum_id, imp_addr, 0, -1) fn_name = "fn_"+idc.GetConstName(const_id) off_name = "ptr_"+idc.GetConstName(const_id) # Rename the function to the symbol name. # We append fn_ to the symbol for the function name # and ptr_ to the offset in the table. if not idc.MakeNameEx(addr, fn_name, idaapi.SN_NOWARN): print "[!] Failed to rename function %s at 0x%08x\n" % (fn_name, addr) if not idc.MakeNameEx(current_addr, off_name, idaapi.SN_NOWARN): print "[!] Failed to rename offset %s at 0x%08x\n" % (off_name,current_addr) current_addr += 8 return