def define_functions(): native_rvas = [ 0x1930, 0x3A90, 0x44b0, ] native_rvas = [(0x400000 + x) for x in native_rvas] for ea in native_rvas: if ea == 0x401930: # undefine and force convert to code as IDA doesn't analyse it at first print "Defining fcn GODDAG at 0x%x" % ea print "Making", ea, "unknown and defining it to code..." idc.MakeUnkn(ea, 1) idc.MakeCode(ea) idc.MakeUnkn(ea + 8, 1) idc.MakeCode(ea + 7) else: if ea == 0x403A90: fcn_name = "NativeGRUNDTAL_NORRVIKEN" print "Defining fcn %s at 0x%x" % (fcn_name, ea) elif ea == 0x4044B0: fcn_name = "FYRKANTIGImpl" print "Defining fcn %s at 0x%x" % (fcn_name, ea) idc.MakeFunction(ea) idc.MakeNameEx(ea, fcn_name, idc.SN_NOWARN)
def patch_32_esp(addr, sub_value, is_sub_esp): count = idc.ItemSize(addr) #get value v = idc.GetOperandValue(addr, 1) #print(hex(v)) if v == -1: print('get value error') return if count == 3: #.text:0804867C 83 EC 18 sub esp, 18h off = 0xff - v if sub_value < off: idc.PatchByte(addr + 2, v + sub_value) else: idc.PatchByte(addr + 2, 0xff) idc.MakeCode(addr) else: #.text:0804875B 81 EC 30 02 00 00 sub esp, 230h idc.PatchDword(addr + 2, v + sub_value) idc.MakeCode(addr) if is_sub_esp != 0: print('patch [sub esp, %s] ok, addr: %s' % (hex(v), hex(addr))) else: print('patch [add esp, %s] ok, addr: %s' % (hex(v), hex(addr))) return
def patch_64_rsp(addr, sub_value, is_sub_rsp): count = idc.ItemSize(addr) #get value v = idc.GetOperandValue(addr, 1) #print(hex(v)) if v == -1: print('get value error') return if count == 4: #.text:000055BBF4127FD9 48 83 EC 10 sub rsp, 10h off = 0xff - v if sub_value < off: idc.PatchByte(addr + 3, v + sub_value) else: idc.PatchByte(addr + 3, 0xff) idc.MakeCode(addr) else: #.text:00007EFEA44A5310 48 81 EC 20 01 00 00 sub rsp, 120h idc.PatchDword(addr + 3, v + sub_value) idc.MakeCode(addr) if is_sub_rsp != 0: print('patch [sub rsp, %s] ok, addr: %s' % (hex(v), hex(addr))) else: print('patch [add rsp, %s] ok, addr: %s' % (hex(v), hex(addr))) return
def patch_call(): global TOTAL_CALL global RESOLVED_CALL ea = idc.LocByName('_objc_msgSend') if ea == idc.BADADDR or ea == 0: return debug_checker = 0x7FFFFFFF debug_cur = 0 for xref in idautils.XrefsTo(ea, idaapi.XREF_ALL): TOTAL_CALL += 1 #print hex(xref.frm) ea_to = idc.GetFunctionAttr(xref.frm, idc.FUNCATTR_START) ea_cur = xref.frm if not ea_cur or ea_cur == idc.BADADDR: continue if not ea_to or ea_to == idc.BADADDR: continue _info("****** starting pos: ", hex(ea_cur)) class_name = get_name(ea_cur, ea_to, 'X0') selector_name = get_name(ea_cur, ea_to, 'X1') print "[", class_name, selector_name, "]" if selector_name == "new": # patch this inst -> mov X0, X0, TODO: point to init instead #print "new" idc.PatchDword(ea_cur, 0xAA0003E0) idc.MakeCode(ea_cur) if selector_name == "init": # patch this inst -> mov X0, X0, TODO: point to init implementation #print "new" idc.PatchDword(ea_cur, 0xAA0003E0) idc.MakeCode(ea_cur) if selector_name == "alloc": # patch this inst -> mov X0, X0, the return value is the same object #print "new" idc.PatchDword(ea_cur, 0xAA0003E0) idc.MakeCode(ea_cur) if class_name == None or selector_name == None: debug_cur += 1 if debug_cur >= debug_checker: #if selector_name == "start:": print "total call", TOTAL_CALL, "solved call", RESOLVED_CALL break else: RESOLVED_CALL += 1 # patch_msg_send(ea_cur, ea_to) '''
def ports_analisys(): ports_struc = idc.AddEnum(-1, "ports", (FF_WRD|FF_DATA)) idc.AddConstEx(ports_struc, "PCI_CONFIG_ADDRESS", PCI_CONFIG_ADDRESS, -1) idc.AddConstEx(ports_struc, "PCI_CONFIG_DATA", PCI_CONFIG_DATA, -1) for each in idaapi.find_binary(start, stop, "", 0, 0): # find_binary(ea_t startea, ea_t endea, char ubinstr, int radix, int sflag) -> ea_t idc.MakeCode(each)
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 __mark_calls(self): for thread in self["mem_areas"][0]['threads']: for call in thread['calls']: if not call['returns']: continue # generate name for the function fname = idc.GetFunctionName(call['target']) if len(fname) == 0: if len(call["name"]) > 0: fname = call["name"].encode('ascii') else: fname = "0x%x" % call["target"] # name all indirect calls for xref in call['xrefs']: idc.MakeCode(xref['addr']) op = idc.GetOpType(xref['addr'],0) if op == ida_ua.o_mem: val = idc.GetOperandValue(xref['addr'], 0) vname = idc.get_name(val) if val is not None and val > 0 and len(vname) > 0 and 'dword_' in vname: idc.MakeName(val, fname) elif op == ida_ua.o_reg or op == ida_ua.o_displ: idc.MakeComm(xref['addr'], fname)
def ida_main(): import idc filepath = idc.AskFile(0, "*.map", "Load a Dolphin emulator symbol map") if filepath is None: return symbol_map = load_dolphin_map(filepath) for symbol in symbol_map: addr = int(symbol.vaddr, 16) size = int(symbol.size, 16) idc.MakeUnknown(addr, size, 0) if symbol.section in [".init", ".text"]: idc.MakeCode(addr) success = idc.MakeFunction( addr, idc.BADADDR if not size else (addr + size)) else: success = idc.MakeData(addr, idc.FF_BYTE, size, 0) if not success: idc.Message("Can't apply properties for symbol:" " {0.vaddr} - {0.name}\n".format(symbol)) flags = idc.SN_NOCHECK | idc.SN_PUBLIC if symbol.name.startswith("zz_"): flags |= idc.SN_AUTO | idc.SN_WEAK else: flags |= idc.SN_NON_AUTO idc.MakeNameEx(addr, symbol.name, flags)
def disassemble_from_trace(self): try: index = self.traces_tab.currentIndex() trace = self.core.traces[self.id_map[index]] self.disassemble_button.setFlat(True) found_match = False for k, inst in trace.instrs.items(): if k in trace.metas: for name, arg1, arg2 in trace.metas[k]: if name == "wave": self.parent.log("LOG", "Wave n°%d encountered at (%s,%x) stop.." % (arg1, k, inst.address)) prev_inst = trace.instrs[k-1] idc.MakeComm(prev_inst.address, "Jump into Wave %d" % arg1) self.disassemble_button.setFlat(False) return # TODO: Check that the address is in the address space of the program if not idc.isCode(idc.GetFlags(inst.address)): found_match = True # TODO: Add an xref with the previous instruction self.parent.log("LOG", "Addr:%x not decoded as an instruction" % inst.address) if idc.MakeCode(inst.address) == 0: self.parent.log("ERROR", "Fail to decode at:%x" % inst.address) else: idaapi.autoWait() self.parent.log("SUCCESS", "Instruction decoded at:%x" % inst.address) if not found_match: self.parent.log("LOG", "All instruction are already decoded") self.disassemble_button.setFlat(False) except KeyError: print "No trace found to use"
def __find_entry(self, iterate_address): possible_entry_address = self.__find_entry_jump(iterate_address) if possible_entry_address == 0 or possible_entry_address == 1: return 0 elif possible_entry_address == -1: print("ERROR.FindingEntry: Issue finding entry from " + format_address(hex(iterate_address)) + \ " to " + format_address(hex(self.end_address)) + ".") return -1 else: following_landing_address = idc.FindBinary(possible_entry_address, idc.SEARCH_DOWN, LANDING_STRIP) if following_landing_address == idc.BADADDR or following_landing_address == 0: # print("ERROR.FindingEntry: Issue finding landing for " + format_address(hex(possible_entry_address)) + ".") # assume end has not yet been reached, will continue to find the correct macro entry return 0 else: # unwrap landing strip as it is usually formatted as data idc.MakeUnknown(following_landing_address, 2, idc.DOUNK_SIMPLE) idc.MakeCode(following_landing_address) # apply logging possible_jump_location_address = get_jump_destination(possible_entry_address) log_oreans_macro_information(possible_entry_address, possible_jump_location_address, following_landing_address) self.macros.append([possible_entry_address, possible_jump_location_address, following_landing_address]) if BUFFER_NOP: nop(possible_entry_address + 5, following_landing_address) if BUFFER_HIDE: hide(possible_entry_address + 5, following_landing_address, BUFFER_NAME, BUFFER_START_NAME, BUFFER_END_NAME) # change main iterator address with that pass the landing so it will step over macro range next_macro_search_range_address = following_landing_address + 5 return next_macro_search_range_address
def codeify(self, ea=idc.BADADDR): func_count = 0 code_count = 0 if ea == idc.BADADDR: ea = self.get_start_ea(self.CODE) if ea == idc.BADADDR: ea = idc.FirstSeg() self.say("\nLooking for undefined code starting at: %s:0x%X" % (idc.SegName(ea), ea)) while ea != idc.BADADDR: try: if idc.GetSegmentAttr(ea, idc.SEGATTR_TYPE) == self.CODE: if idc.GetFunctionName(ea) != '': ea = idc.FindFuncEnd(ea) continue else: if idc.MakeFunction(ea): func_count += 1 elif idc.MakeCode(ea): code_count += 1 except: pass ea = idc.NextAddr(ea) self.say("Created %d new functions and %d new code blocks\n" % (func_count, code_count))
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 markSwitchTables(self, sc, aggressive=True): """Help IDA by marking all of the needed information from the observed switch tables. Args: sc (segment): (sark) code segment in which we are interested right now aggressive (bool, optional): True iff the marking operation should be aggressive, see notes. (True by default) Notes ----- 1. Make sure the switch case jump instruction is indeed a code line 2. Make sure the jump instruction has a code reference to all of the switch cases 3. (Aggressive) Make sure each switch table entry is a proper code pointer to it's matching case 4. (Aggressive) Enforce the correct code type over the entire gap between the minimal and maximal case """ for switch_instr, table_start, table_end in filter( lambda x: sc.startEA <= x[0] and x[1] < sc.endEA, self._switch_case_entries): cases = [] if not sark.Line(switch_instr).is_code: idc.MakeUnknown(switch_instr, self._analyzer.addressSize(), 0) idc.MakeCode(switch_instr) for ea in xrange(table_start, table_end, self._analyzer.addressSize()): entry = self._analyzer.parseAdderss(ea) if aggressive: self._analyzer.markCodePtr(ea, entry) fixed_entry = self._analyzer.cleanPtr(entry) cases.append(fixed_entry) idc.add_cref(switch_instr, fixed_entry, idc.XREF_USER | idc.dr_O) if aggressive: self._analyzer.setCodeType(min(cases), max(cases), self._analyzer.ptrCodeType(entry))
def codeify(self, ea=idc.BADADDR): func_count = 0 code_count = 0 if ea == idc.BADADDR: ea = self.get_start_ea(self.CODE) if ea == idc.BADADDR: ea = idc.FirstSeg() print "\nLooking for undefined code starting at: %s:0x%X" % ( idc.SegName(ea), ea) if self.get_start_ea(self.DATA) == idc.BADADDR: print "WARNING: No data segments defined! I don't know where the code segment ends and the data segment begins." while ea != idc.BADADDR: try: if idc.GetSegmentAttr(ea, idc.SEGATTR_TYPE) == self.CODE: if idc.GetFunctionName(ea) != '': ea = idc.FindFuncEnd(ea) continue else: if idc.MakeFunction(ea): func_count += 1 elif idc.MakeCode(ea): code_count += 1 except: pass ea = idc.NextAddr(ea) print "Created %d new functions and %d new code blocks\n" % ( func_count, code_count)
def patch_to_call_puts(addr): #.text:0000114D E8 DE FE FF FF call _printf count = idc.ItemSize(addr) #get value v = idc.GetOperandValue(addr, 0) #要CALL的地址 - 下一条指令地址 = E8 后面的硬编码 plt_names = idautils.Names() for address, name in plt_names: if name == '.puts': puts_addr = address elif name == '.printf': printf_addr = address op = puts_addr - (addr + count) op = op & 0xffffffff #print('op: %s' %hex(op)) idc.PatchDword(addr + 1, op) idc.MakeCode(addr) print('patch [call _printf] ok, addr: %s' % hex(addr)) return
def make_code(start, end): for i in range((end - start) / 4): addr = start + (i * 4) if not idc.isCode(idc.GetFlags(addr)): idaapi.do_unknown_range(addr, 4, 0) idaapi.auto_make_code(addr) idc.MakeCode(addr) return
def define_functions(): # The function first searches for all user defined functions, reads # the opcodes and searches for that opcodes in the rest of the file. # # You can extend this by adding more disassembled instructions that # make you believe are function prologues. # # Obviously not any PUSH is a function start, this is only a filter # against erroneously defined functions. So if you define a function # that starts with other instruction (and you think there could be # other functions that start with that instruction), just add it here. prologues = ["STMFD", "push", "PUSH", "mov", "MOV"] print "Finding all signatures" #ea= 0 ea = 0x11800000 #ea = 0x10000000 opcodes = set() if idc.SegStart(ea) == 0xFFFFFFFF: print "Wrong segment address set!" return for funcea in idautils.Functions(idc.SegStart(ea), idc.SegEnd(ea)): # Get the opcode start_opcode = idc.Dword(funcea) # Get the disassembled text dis_text = idc.GetDisasm(funcea) we_like_it = False # Filter possible errors on manually defined functions for prologue in prologues: if prologue in dis_text: we_like_it = True # If it passes the filter, add the opcode to the search list. if we_like_it: opcodes.add(start_opcode) print "# different opcodes: %x" % (len(opcodes)) while len(opcodes) > 0: # Search for this opcode in the rest of the file opcode_bin = opcodes.pop() opcode_str = " ".join( x.encode("hex") for x in struct.pack("<L", opcode_bin)) print "Searching for " + opcode_str matches = find_all(opcode_str) for matchea in matches: # If the opcode is found in a non-function if not idc.GetFunctionName(matchea): # Try to make code and function print "Function at " + hex(matchea) idc.MakeCode(matchea) idc.MakeFunction(matchea) print "We're done!"
def parse_pclntable(module_data): pPcHeader = module_data.pPcHeader pc_header = parse_pc_header(pMem=pPcHeader) ptrSize = pc_header.ptrSize numberOfFuncs = pc_header.nFunc log._info("Number of Functions : %d" % numberOfFuncs) pclntable_start = module_data.pPclnTable cur_addr = pclntable_start for idx in range(numberOfFuncs): cur_addr = pclntable_start + (2 * ptrSize) * idx func_rva = common.mem_read_integer(addr=cur_addr, read_size=ptrSize) _func_structure_offset = common.mem_read_integer(addr=cur_addr + ptrSize, read_size=ptrSize) _func_addr = pclntable_start + _func_structure_offset if not idc.GetFunctionName(func_rva): log._info("Unk Func @0x%x" % func_rva) idc.MakeUnkn(func_rva, idc.DOUNK_EXPAND) idaapi.autoWait() idc.MakeCode(func_rva) idaapi.autoWait() if idc.MakeFunction(func_rva): idaapi.autoWait() log._info("Create Func @0x%x" % func_rva) _func = parse__func(pMem=_func_addr) #args=_func.args #func_id=_func.args func_name_addr = module_data.pFuncNameTable + _func.nameoff func_name = idc.GetString(func_name_addr) if func_name: clean_func_name = utils.clean_function_name(func_name) log._info("@0x%x Name : [%s]" % (func_rva, func_name)) idc.MakeComm(func_rva, "@0x" + str(hex(func_rva)) + " entry") idaapi.autoWait() if idc.MakeStr(func_name_addr, func_name_addr + len(func_name) + 1): idaapi.autoWait() else: log._error("@0x%x Name : [%s] Failed..." % (func_rva, func_name)) _func_addr = idaapi.get_func(func_rva) if _func_addr is not None: if idc.MakeNameEx(_func_addr.startEA, func_name, flags=idaapi.SN_FORCE): idaapi.autoWait() log._info("@0x%x Name : [%s]" % (func_rva, func_name)) else: log._error("@0x%x Name : [%s] Failed..." % (func_rva, func_name))
def do_rename(line): splitted = line.split() strname = splitted[0] straddr = splitted[1].replace("\r", "").replace("\n", "") eaaddr = int(straddr, 16) idc.MakeCode(eaaddr) idc.MakeFunction(eaaddr) idc.MakeNameEx(int(straddr, 16), strname, idc.SN_NOWARN)
def disassemble_new_targets(self, enabled): for value in self.results.values: flag = idc.GetFlags(value) if not idc.isCode(flag) and idc.isUnknown(flag): res = idc.MakeCode(value) if res == 0: print "Try disassemble at:" + hex(value) + " KO" #TODO: Rollback ? else: print "Try disassemble at:" + hex(value) + " Success !"
def resolve_loops(): PATTERNS = ["81 FB ?? ?? ?? ?? 75"] count_patched = 0 count_not_patched = 0 for pattern in PATTERNS: ea = 0 while ea != BADADDR: ''' pattern: 81 FB ?? ?? ?? ?? 75 .text:00406AA0 01 C7 add edi, eax .text:00406AA2 66 41 inc cx .text:00406AA4 43 inc ebx .text:00406AA5 81 FB A6 01 00 00 cmp ebx, 1A6h .text:00406AAB 75 F3 jnz short loc_406AA0 patched: .text:00406AA0 01 C7 add edi, eax .text:00406AA2 66 41 inc cx .text:00406AA4 43 inc ebx .text:00406AA5 90 nop .text:00406AA6 90 nop .text:00406AA7 90 nop .text:00406AA8 90 nop .text:00406AA9 90 nop .text:00406AAA 90 nop .text:00406AAB 90 nop .text:00406AAC 90 nop ''' ea = idc.FindBinary(ea, SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE, pattern) if ea_in_bounds(ea): # Patch CMP and conditional jmp instructions in order to remove the loop idc.PatchByte(ea + 0, 0x90) idc.PatchByte(ea + 1, 0x90) idc.PatchByte(ea + 2, 0x90) idc.PatchByte(ea + 3, 0x90) idc.PatchByte(ea + 4, 0x90) idc.PatchByte(ea + 5, 0x90) idc.PatchByte(ea + 6, 0x90) idc.PatchByte(ea + 7, 0x90) idc.MakeCode(ea) count_patched += 1 print "\tPatched resolve_loops: {0}".format(count_patched) print "\tNot Patched resolve_loops: {0}".format(count_not_patched)
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 mark_bbls(self, mem_area_id): if not self._from_idb: for tid in self._maze['process']['mem_areas'][mem_area_id]['tids']: for thread in self._maze['process']['threads']: if tid == thread['tid']: for bbl in thread['bbls']: ea = bbl['start'] for _ in range(bbl['inst']): inst_size = idc.MakeCode(ea) idaapi.set_item_color(ea, 0x49feaf) ea += inst_size
def load_data_section(section, p): ''' specialized handler for the DATA section to mark the offset initializer as code. ''' ppayload = p + idawasm.common.offset_of(section.data, 'payload') pentries = ppayload + idawasm.common.offset_of(section.data.payload, 'entries') pcur = pentries for i, body in enumerate(section.data.payload.entries): idc.MakeCode(pcur + idawasm.common.offset_of(body, 'offset')) pcur += idawasm.common.size_of(body)
def map_shared_bridges(dsc_file, adrfind): """ finds branch islands in a given dyld_shared_cache file, maps them to IDA's db and extract its addresses """ dsc_file.seek(0, 2) filesize = dsc_file.tell() dsc_file.seek(0) ACCESS_READ = 1 a = mmap.mmap(dsc_file.fileno(), length=filesize, access=ACCESS_READ) reexp = re.compile( "\xcf\xfa\xed\xfe.{340,360}dyld_shared_cache_branch_islands") print "[+] scanning dsc for BRANCH ISLANDS" # this list will hold all our branch_islands segments branch_islands_segments = [] jmp_to_code = collections.defaultdict(list) for ma in reexp.finditer(a): print "[+] WRITING BRANCH ISLAND: 0x%08X" % (ma.start()) fif = FileInFile(dsc_file, ma.start()) m = MachO_patched(fif) if _IN_IDA: for seg in m.segments: for sec in seg.sections: idc.AddSegEx(sec.addr, sec.addr + sec.size, 0, 0, idaapi.saRelPara, idaapi.scPub, idc.ADDSEG_FILLGAP) name = "branch_islands_%X%s%s" % (ma.start(), seg.segname, sec.sectname) idc.RenameSeg(sec.addr, name) idc.SetSegClass(sec.addr, "CODE") idc.SetSegAddressing(sec.addr, 2) dsc_file.seek(sec.offset) memcpy(sec.addr, dsc_file.read(sec.size)) branch_islands_segments.append(sec.addr) # make code codeea = sec.addr print "Going through the code!" while codeea < (sec.addr + sec.size): res = idc.MakeCode(codeea) if not res: print "[!] EA:0x%X ERR while making code" % codeea codeea += 4 continue d = idc.GetDisasm(codeea) # if it's a "B 0x4dd13550" if d.startswith("B "): addr = d.split()[1] if addr.startswith("0x"): branchaddr = int(addr, 16) jmp_to_code[branchaddr].append(codeea) # idc.MakeRptCmt(codeea, "0x%X was taken!" % branchaddr) codeea = idc.FindUnexplored(codeea, idc.SEARCH_DOWN) label_and_fix_branch_islands(dsc_file, adrfind, jmp_to_code)
def load_symbols(self, file_data, is_big_endian=True): symbol_list = [] if is_big_endian: unpack_format = '>I' else: unpack_format = '<I' symbol_count = struct.unpack(unpack_format, file_data[4:8])[0] print("symbol_count: %s" % symbol_count) symbol_offset = 8 string_table_offset = 8 + 8 * symbol_count print("string_table_offset: %s" % string_table_offset) # get symbols for i in range(symbol_count): offset = i * 8 symbol_data = file_data[symbol_offset + offset:symbol_offset + offset + 8] flag = ord(symbol_data[0]) string_offset = struct.unpack(unpack_format, '\x00' + symbol_data[1:4])[0] string_offset += string_table_offset print("string_offset: %s" % string_offset) symbol_name = "" while True: if file_data[string_offset] != '\x00': symbol_name += file_data[string_offset] string_offset += 1 else: break print("symbol_name: %s" % symbol_name) symbol_address = struct.unpack(unpack_format, symbol_data[-4:])[0] symbol_list.append([flag, symbol_name, symbol_address]) # Find TP-Link device loading address with symbols if "wrs_kernel_text_start" in symbol_name: load_address = symbol_address current_image_base = idaapi.get_imagebase() shift_address = load_address - current_image_base while shift_address >= 0x70000000: idaapi.rebase_program(0x70000000, 0x0008) shift_address -= 0x70000000 idaapi.rebase_program(shift_address, 0x0008) # load symbols for symbol_data in symbol_list: flag, symbol_name, symbol_address = symbol_data idc.MakeName(symbol_address, symbol_name) if flag == 0x54: if symbol_name: print("Start fix Function %s at %s" % (symbol_name, hex(symbol_address))) idc.MakeCode(symbol_address) # might not need idc.MakeFunction(symbol_address, idc.BADADDR)
def do_rename(l): splitted = l.split() straddr = splitted[0] strname = splitted[1].replace("\r", "").replace("\n", "") if straddr.find(":") != -1: #assuming form segment:offset #removing segment, offset should be unique, if it isn't so, we should handle it differently straddr = straddr.split(":")[1] eaaddr = int(straddr, 16) idc.MakeCode(eaaddr) idc.MakeFunction(eaaddr) idc.MakeNameEx(int(straddr, 16), strname, idc.SN_NOWARN)
def search_functions(): # For each segment for segment in idautils.Segments(): # For each byte in the address range of the segment for byte_addr in range(segment, idc.SegEnd(segment)): # Fetch byte dis_text = idc.GetDisasm(byte_addr) peekahead_dis_text = idc.GetDisasm(byte_addr + 1) if "7Ch" in dis_text and "0F2h" in peekahead_dis_text: idc.MakeCode(byte_addr) idc.MakeFunction(byte_addr) print "End of file reached"
def patch_call_free(addr): count = idc.ItemSize(addr) #.text:000011E1 E8 5A FE FF FF call _free #.text:000055BBF4127EFF E8 5C F9 FF FF call _free for i in range(count): idc.PatchByte(addr + i, 0x90) #patch to NOP instr idc.MakeCode(addr) print('patch [call _free] ok, addr: %s' % hex(addr)) return
def _convert_address_to_function(func): """Convert an address that IDA has classified incorrectly into a proper function.""" # If everything goes wrong, we'll try to restore this function. orig = idc.FirstFuncFchunk(func) # If the address is not code, let's undefine whatever it is. if not idc.isCode(idc.GetFlags(func)): if not is_mapped(func): # Well, that's awkward. return False item = idc.ItemHead(func) itemend = idc.ItemEnd(func) if item != idc.BADADDR: _log(1, 'Undefining item {:#x} - {:#x}', item, itemend) idc.MakeUnkn(item, idc.DOUNK_EXPAND) idc.MakeCode(func) # Give IDA a chance to analyze the new code or else we won't be able to create a # function. idc.Wait() idc.AnalyseArea(item, itemend) else: # Just try removing the chunk from its current function. IDA can add it to another function # automatically, so make sure it's removed from all functions by doing it in loop until it # fails. for i in range(1024): if not idc.RemoveFchunk(func, func): break # Now try making a function. if idc.MakeFunction(func) != 0: return True # This is a stubborn chunk. Try recording the list of chunks, deleting the original function, # creating the new function, then re-creating the original function. if orig != idc.BADADDR: chunks = list(idautils.Chunks(orig)) if idc.DelFunction(orig) != 0: # Ok, now let's create the new function, and recreate the original. if idc.MakeFunction(func) != 0: if idc.MakeFunction(orig) != 0: # Ok, so we created the functions! Now, if any of the original chunks are not # contained in a function, we'll abort and undo. if all(idaapi.get_func(start) for start, end in chunks): return True # Try to undo the damage. for start, _ in chunks: idc.DelFunction(start) # Everything we've tried so far has failed. If there was originally a function, try to restore # it. if orig != idc.BADADDR: _log(0, 'Trying to restore original function {:#x}', orig) idc.MakeFunction(orig) return False