def slot_item_double_clicked(self, o, column): """ """ if column == CapaExplorerRulegenFeatures.get_column_address_index( ) and o.text(column): idc.jumpto(int(o.text(column), 0x10)) elif o.capa_type == CapaExplorerRulegenFeatures.get_node_type_leaf(): self.editor.update_features([o.data(0, 0x100)])
def setAddr(self, address): if self.current_focused_addr == address: return else: idc.jumpto(address) f = idaapi.get_func(address) # print(f) if f == None: print("not found function address...") return g = idaapi.FlowChart(f, flags=idaapi.FC_PREDS) target_bb_id = get_bb_id(g, address) # print(target_bb_id) if self.current_block_start_ea == f.start_ea and self.current_bb_id == target_bb_id: return else: self.recoverColor() self.current_block_start_ea = f.start_ea self.current_focused_addr = address self.current_bb_id = target_bb_id self.changeColor() ida_graph.refresh_viewer(self.widget_a)
def goto_file_ofs(): fofs = 0 txt = clip_text() if txt.isdigit(): try: fofs = int(txt, 10) except: pass elif txt.isalnum(): try: fofs = int(txt, 16) except: pass fofs = ida_kernwin.ask_addr(fofs, "Enter the file offset to jump to") if fofs is None: return 0 ea = idaapi.get_fileregion_ea(fofs) if ea != idc.BADADDR: plg_print("File offset = 0x%X -> EA = 0x%X" % (fofs, ea)) idc.jumpto(ea) return 1 else: plg_print("Invalid file offset 0x%X" % fofs) return 0
def handle_methods_interaction(self, row, column): if self.edit_class is None: return m = self.methods.item(row, 0).data(QtCore.Qt.UserRole) if type( m ) != database_entries.Method or m not in self.edit_class.methods: return elif column == 0: # Go to address idc.jumpto(m.ea) elif column == 1: # Edit signature dlg = SignatureDialog(m.return_type, m.owner.name, m.name, m.args, m.is_const, m.ctor_type, m.dtor_type, fixed_owner_type=True) if dlg.exec_() != QtWidgets.QDialog.Accepted: return m.set_signature(dlg.name, dlg.args, dlg.return_type, dlg.is_const, dlg.ctor_type, dlg.dtor_type) self.methods.setItem(row, 1, QtWidgets.QTableWidgetItem(m.get_signature())) idaapi.refresh_idaview_anyway()
def handle_vtable_interaction(self, row, column): if self.edit_class is None: return vm = self.edit_class.vmethods[row] if column == 0: # Go to vtable offset idc.jumpto(self.edit_class.vtable_start + row * 4) elif column == 1: # Go to address idc.jumpto(vm.ea) elif column == 2: # Edit signature dlg = SignatureDialog(vm.return_type, vm.owner.name, vm.name, vm.args, vm.is_const, vm.ctor_type, vm.dtor_type, fixed_owner_type=True) if dlg.exec_() != QtWidgets.QDialog.Accepted: return vm.set_signature(dlg.name, dlg.args, dlg.return_type, dlg.is_const, dlg.ctor_type, dlg.dtor_type) self.vtable.setItem(row, 2, QtWidgets.QTableWidgetItem(vm.get_signature())) idaapi.refresh_idaview_anyway()
def context_menu(self, position): sender = self.sender() menu = QtWidgets.QMenu() copy_action = menu.addAction("Copy value") copy_row = menu.addAction("Copy row") view_chunk = menu.addAction("View chunk") jump_to = menu.addAction("Jump to chunk") jump_to_u = menu.addAction("Jump to user-data") check_freaable = menu.addAction("Check freeable") chunk_addr = int(sender.item(sender.currentRow(), 0).text(), 16) action = menu.exec_(sender.mapToGlobal(position)) if action == copy_action: sender.copy_selected_value() if action == copy_row: sender.copy_selected_row() elif action == jump_to: idc.jumpto(chunk_addr) elif action == jump_to_u: idc.jumpto(chunk_addr + (config.ptr_size * 2)) elif action == view_chunk: self.view_selected_chunk() elif action == check_freaable: self.parent.check_freeable(chunk_addr)
def OnSelectLine(self, n): self.selcount += 1 ea = int(self.items[n][0], 16) idc.jumpto(ea) if DEBUG: print('[{}] jump to {addr:#010x}'.format(NAME, addr=ea)) return n
def callback(self, event, *args): if event == idaapi.hxe_populating_popup: form, phandle, vu = args if vu.item.citype == idaapi.VDI_FUNC or ( vu.item.citype == idaapi.VDI_EXPR and vu.item.e.is_expr() and vu.item.e.type.is_funcptr()): idaapi.attach_action_to_popup(form, phandle, ACTION_HX_REMOVERETTYPE, None) elif event == idaapi.hxe_double_click: vu, shift_state = args # auto jump to target if clicked item is xxx->func(); if vu.item.citype == idaapi.VDI_EXPR and vu.item.e.is_expr(): expr = idaapi.tag_remove(vu.item.e.print1(None)) if "->" in expr: # find target function name = expr.split("->")[-1] addr = idc.get_name_ea_simple(name) if addr == idaapi.BADADDR: # try class::function e = vu.item.e while e.x: e = e.x addr = idc.get_name_ea_simple( "%s::%s" % (str(e.type).split()[0], name)) if addr != idaapi.BADADDR: idc.jumpto(addr) return 1 return 0
def go_to(self): """ Transfers user to the relevant address of the update :return: None """ idc.jumpto(self.address)
def goto_clip_text(): loc = parse_location(clip_text()) if loc != idaapi.BADADDR: plg_print("Goto location 0x%X" % loc) idc.jumpto(loc) return 1 plg_print("Failed to get a valid ea") return 0
def jumpto(): model = self.ui.regsView.model() sel = self.ui.regsView.selectedIndexes() if len(sel) > 0: try: addr = int(_idangr_ctx.simregs[sel[0].row()][2], 16) idc.jumpto(addr) except: pass
def jump_addr_next_func(): import idc end = 0x0402220 ea = idc.get_screen_ea() while idc.find_func_end(ea) < end: next_func = get_next_func(ea) print(hex(next_func)) idc.jumpto(next_func) ea = idc.get_screen_ea()
def view_dblclick(self, viewer, point): widget_type = ida_kernwin.get_widget_type(viewer) if not (widget_type == 48 or widget_type == 28): return # Decompiler or Structures window place, x, y = ida_kernwin.get_custom_viewer_place(viewer, False) line = utils.get_curline_striped_from_viewer(viewer) func_cand_name = cpp_utils.find_valid_cppname_in_line(line, x) if func_cand_name is not None: func_cand_ea = ida_name.get_name_ea(BADADDR, func_cand_name) if func_cand_ea is not None and utils.is_func(func_cand_ea): idc.jumpto(func_cand_ea)
def activate(self, ctx): if self.action == ACTION_COPYEA: ea = idc.get_screen_ea() if ea != idaapi.BADADDR: copy_to_clip("0x%X" % ea) print("Address 0x%X has been copied to clipboard" % ea) elif self.action == ACTION_GOTOCLIP: loc = parse_location(clip_text()) if loc != idaapi.BADADDR: print("Goto location 0x%x" % loc) idc.jumpto(loc) return 1
def _onSignatureTreeItemDoubleClicked(self, item, column): """Action for the double clicked. Arguments: item (QTreeWidgetItem): Item that was clicked. column (int): Selected column. """ # Jump to the match address if item.data(1, 0): addr = int(item.data(2, 0), 16) idc.jumpto(addr)
def patchIDB(self,buff): for i in buff: # process file contents i=i.strip() # strip new line jumpaddr,datastr=self.extractStackData(i) # extract jump address and four double words from each line for rawbytes in datastr: # process each double word idc.jumpto(jumpaddr) # jump to segment address temp = self.convertRawHexData(rawbytes) # process word string into bytes idaapi.patch_many_bytes(jumpaddr,temp) # patch bytes at jumpaddr self.setComment("Address: 0x%x \tStack Value: %s" % (jumpaddr,rawbytes)) # create a comment at each double word in segment jumpaddr +=4 # increment jumpaddr by 4 bytes
def _onSignatureTreeItemDoubleClicked(self, item, column): """Action for the double clicked. Arguments: item (QTreeWidgetItem): Item that was clicked. column (int): Selected column. """ # Jump to the match address if item in self.qtreewidgetitems_to_addresses: try: idc.jumpto(self.qtreewidgetitems_to_addresses[item]) except: idc.Jump(self.qtreewidgetitems_to_addresses[item])
def createStackSegment(self,start_addr,end_addr): idc.AddSeg(start_addr,end_addr,0,1,0, idaapi.saRelDble) #add new segment idc.set_segm_combination(start_addr,idaapi.saRelDble) #set segm comb idc.jumpto(start_addr) #jumpt to seg start address align_start_addr=start_addr #temp align start address value #print "Making DWORDs from 0x%X - 0x%X" % (align_start_addr, end_addr) # debugging statement while align_start_addr < end_addr: # aligning into 4 byte dw MakeDword(align_start_addr) #make the double word alignment align_start_addr += 4 #inc address by four bytes #set segment combination to 'stack' MakeUnknown(align_start_addr, (end_addr-align_start_addr), DOUNK_SIMPLE)
def nextOneWordArr(): d = Data.Data(ea) while (d.ea < pointerRange[1]): content = d.getContent() # case: byte array that's 4 elements. Likely a word if type(content) == list and len(content) == 4 and (d.getSize() / len(content) == 1): break d = Data.Data(d.ea + d.getSize()) if d.ea >= pointerRange[1]: print(False) else: print('%07X' % d.ea) idc.jumpto(d.ea)
def fakered(ea, end_ea=None, ui=True, hexOut=True): """ This finds the next occurrance of a not a red code segment that has no return pattern to it, making it unlikely to belong to a function. :param ea: ea to start searching from :param ui: if True, jump to address automatically :param end_ea: the last address of the search range. If not specified, default is used. :param hexOut: output hex formatted ea range instead :return: range of ea of next fake red code segment """ # TODO: change implementation to be based on return patterns? ea = red(ea, end_ea, ui=False, hexOut=False) start_ea = ea end_red_ea = idaapi.BADADDR # flag for when the whole red segment is finished and we can go to the next red code segment finishedSegment = False # condition for if the segment has already been invalidated before reaching its end isFake = True if not end_ea: end_ea = end_ea while ea < end_ea: d = Data.Data(ea) inst = InstDecoder.Inst(ea).fields # traverse red code, and find the end of the red segment if Function.isFunction(ea) and d.isCode() or not d.isCode(): # update region end to this red code region end_red_ea = ea # confirm if the return is within range, then this isn't fake code. Find the next red! if isFake: # or start_ea <= unkret(start_ea-instLimit, end_ea, ui=False, hexOut=False) < end_ea: break # search the next red region isFake = True start_ea = ea = red(end_red_ea, end_ea, ui=False, hexOut=False) # advance through the red code else: # simple function pattern,s, if it sorta looks like it can be a function, don't count it as fake. # this includes return patterns, and push/pop. if inst and (inst['magic'] == InstDecoder.INST_MOV_PC_LR or inst['magic'] == InstDecoder.INST_BX and inst['reg'] == 14 or inst['magic'] == InstDecoder.INST_PUSHPOP and inst['lr']): isFake = False ea += d.getSize() if ui: idc.jumpto(end_red_ea - 2) if hexOut: return '(%07X, %07X)' % (start_ea, end_red_ea) return (start_ea, end_red_ea)
def OnDblClick(self, node_id): is_thread, value, label = self[node_id] if is_thread: idc.select_thread(value) self.Show() s = "SEH chain for " + hex(value) t = "-" * len(s) print t print s print t for handler in self.result[value]: print "%x: %s" % (handler, self.names[handler]) print t else: idc.jumpto(value) return True
def remake_main(): # 先新建好所有函数, 再执行 # -- 脚本将start~end所有函数 undefined, 在start处make function import ida_bytes start_addr = 0x0402126 end_addr = 0x0402220 for i in range(start_addr, end_addr): ida_bytes.del_items(i) idc.jumpto(start_addr) idc.add_func(start_addr) import ida_hexrays # open pseudocode view ida_hexrays.open_pseudocode(0x0402126, ida_hexrays.OPF_NO_WAIT)
def jumpto(self, item, offset): """Jump to offset in IDA view""" try: self.ret = idc.jumpto(offset) except: self.ret = False return self.ret
def deadfunc(ea, end_ea=None, ui=True, hexOut=True): """ This finds the next occurrance of a dead function not recognized as a function (ie, red code or data) This can only find functions ranges it can guarantee, ie, only PUSH {..., LR} POP {..., PC} patterns. :param ea: ea to start searching from :param end_ea: the last address of the search range :param ui: if True, jump to address automatically :param hexOut: output hex formatted ea range instead :return: range of ea of next dead function """ # don't count this item ea = Data.Data(ea).ea + Data.Data(ea).getSize() foundPush = False push_ea = idaapi.BADADDR pop_ea = idaapi.BADADDR push_regs = None if not end_ea: end_ea = end_ea while ea < end_ea: # the current item must not belong to a function, or have any data xrefs if not Function.isFunction(ea) and not Data.Data(ea).getXRefsTo()[1]: try: inst = InstDecoder.Inst(ea).fields except ValueError: ea += 2 continue # if PUSH {..., LR} if inst and inst['magic'] == InstDecoder.INST_PUSHPOP and not inst[ 'pop'] and inst['lr']: foundPush = True push_ea = ea push_regs = inst['Rlist'] # detected a POP {..., PC} after the PUSH {..., LR}, and the registers match if (foundPush and inst and inst['magic'] == InstDecoder.INST_PUSHPOP and inst['pop'] and inst['lr'] and inst['Rlist'] == push_regs): pop_ea = ea break else: foundPush = False ea += 2 if ui: idc.jumpto(push_ea) if hexOut: return '(%07X, %07X)' % (push_ea, pop_ea) return (push_ea, pop_ea)
def _step_into(self): # if self.data == None: self.browser.append("please load file before") return # if not self.addr_is_load: self.browser.append("please load base addr before") return # ir_list = [] mark_num = 0 min_dist = 0xffffffff for i in range(self.curr_line, len(self.data)): one_ir = self.data[i] if 'IMark' in one_ir: if mark_num >= 1: self.curr_line = i break else: ir_list.append(one_ir) cur_addr = self._get_curr_base(one_ir) - self.module_base self.or_ins = self.cur_ins self.cur_ins = cur_addr if self.or_ins != 0: idc.SetColor(self.or_ins, CIC_ITEM, 0xFFFFFFFF) mark_num = mark_num + 1 else: if 'func_' in one_ir: if min_dist == 0xffffffff: ref_addr = self.cur_ins for addr in idautils.CodeRefsTo(ref_addr, 1): if abs(addr - self.or_ins) <= min_dist: min_dist = abs(addr - self.or_ins) self.cur_ins = addr ir_list.append(one_ir) idc.jumpto(self.cur_ins) idc.SetColor(self.cur_ins, CIC_ITEM, 0x2020c0) for one_ir in ir_list: self.browser.append(one_ir)
def slot_double_click(self, model_index): """slot connected to double click event @param model_index: QModelIndex* """ if not model_index.isValid(): return item = self.map_index_to_source_item(model_index) column = model_index.column() if CapaExplorerDataModel.COLUMN_INDEX_VIRTUAL_ADDRESS == column and item.location: # user double-clicked virtual address column - navigate IDA to address idc.jumpto(item.location) if CapaExplorerDataModel.COLUMN_INDEX_RULE_INFORMATION == column: # user double-clicked information column - un/expand self.collapse(model_index) if self.isExpanded(model_index) else self.expand(model_index)
def _run(self): if self.data == None: self.browser.append("please load file before") return if not self.addr_is_load: self.browser.append("please load base addr before") return if len(self.addr_list) == 0: self.browser.append("please bp addr") return # ir_list = [] mark_num = 0 for i in range(self.curr_line, len(self.data)): one_ir = self.data[i] if 'IMark' in one_ir: if mark_num >= 1: self.curr_line = i break # cur_addr = self._get_curr_base(one_ir) - self.module_base for bp_addr in self.addr_list: if bp_addr == cur_addr: idc.jumpto(cur_addr) idc.SetColor(cur_addr, CIC_ITEM, 0x2020c0) self.or_ins = self.cur_ins self.cur_ins = cur_addr ir_list.append(one_ir) mark_num = mark_num + 1 break else: if mark_num >= 1: ir_list.append(one_ir) if mark_num == 0: self.browser.append('bp address is not taint') else: for one_ir in ir_list: self.browser.append(one_ir)
def view_dblclick(self, viewer, point): widget_type = ida_kernwin.get_widget_type(viewer) if not (widget_type == 48 or widget_type == 28): return # Decompiler or Structures window func_cand_name = None place, x, y = ida_kernwin.get_custom_viewer_place(viewer, False) if place.name() == "structplace_t": # Structure window: structplace = ida_kernwin.place_t_as_structplace_t(place) if structplace is not None: s = ida_struct.get_struc(ida_struct.get_struc_by_idx(structplace.idx)) if s: member = ida_struct.get_member(s, structplace.offset) if member: func_cand_name = ida_struct.get_member_name(member.id) if func_cand_name is None: line = utils.get_curline_striped_from_viewer(viewer) func_cand_name = cpp_utils.find_valid_cppname_in_line(line, x) if func_cand_name is not None: func_cand_ea = ida_name.get_name_ea(BADADDR, func_cand_name) if func_cand_ea is not None and utils.is_func_start(func_cand_ea): idc.jumpto(func_cand_ea)
def goto_rva(): rva = 0 txt = clip_text() if txt.isdigit(): try: rva = int(txt, 10) except: pass elif txt.isalnum(): try: rva = int(txt, 16) except: pass rva = ida_kernwin.ask_addr(rva, "Enter the RVA to jump to") if rva is None: return 0 base = ida_nalt.get_imagebase() ea = base + rva plg_print("RVA = 0x%X -> EA = 0x%X" % (rva, ea)) idc.jumpto(ea) return 1
def unkret(ea, end_ea=None, ui=True, hexOut=True): """ Thhs finds the next return based on the next.ret function, that is not already defined within a function. This counts red code, unknown bytes, and returns hidden within data. :param ea: ea to start searching from :param end_ea: the last address to look for :param ui: if True, jump to address automatically :param hexOut: output hex formatted ea instead :return: ea of next unknown return """ ea = ret(ea, end_ea, ui=False, hexOut=False) output = idaapi.BADADDR if not end_ea: end_ea = end_ea while ea < end_ea: d = Data.Data(ea) if not Function.isFunction(d.ea): output = ea break ea = ret(ea, end_ea, ui=False, hexOut=False) if ui: idc.jumpto(output) if hexOut: return '%07X' % output return output
def OnSelectLine(self, n): idc.jumpto(self.items[n][2]) return (Choose.NOTHING_CHANGED, )
def main(): eh = flare_emu.EmuHelper() # dictionary that stores data used across emulation runs, function emulation specific data is set below userData = { # found stackstrings in stack memory "stackstrings": [], # found stackstrings in global memory (globalstrings) "globalstrings": [] } cnt_functions = 0 cnt_analyzed = 0 cnt_found_ss = 0 cnt_commented_ss = 0 errors = [] start = time.time() print("Started ironstrings stackstring deobfuscation") print_header() if ANALYZE_SINGLE_FUNC: fvas = [idc.get_func_attr(idc.here(), idc.FUNCATTR_START)] else: fvas = idautils.Functions() for fva in fvas: logging.debug("running on 0x%X", fva) if JUMP_TO_FUNC: idc.jumpto(fva) if fva == idaapi.BADADDR: logging.debug("skipping invalid function address") continue if idc.get_func_flags(fva) & (idc.FUNC_LIB | idc.FUNC_THUNK): logging.debug("skipping library or thunk function 0x%X", fva) continue # function start address userData["funcStart"] = fva # list of addresses of last instruction for all basic blocks in function userData["bb_ends"] = get_bb_ends(fva) # memory writes in current function userData["mem_writes"] = {} # start and end addresses of all memory writes in function userData["writelog"] = set() # memory write count in current basic block userData["mem_write_count"] = 0 # cache previous address to count instructions that are executed multiple times, e.g. rep prefixed userData["prevAddress"] = 0 # number same instruction has been executed in a row userData["repCount"] = 0 cnt_functions += 1 try: # emulate various paths through function via flare-emu, use hooks to reconstruct strings eh.iterateAllPaths(fva, noop, hookData=userData, callHook=call_hook, instructionHook=instr_hook, memAccessHook=hook_mem_write, hookApis=False, maxPaths=MAX_CODE_PATHS) except unicorn.UcError as e: errors.append("Error analyzing function 0x{:X}: {}".format(fva, str(e))) else: cnt_analyzed += 1 # print stackstrings found in this function f_ss = filter(lambda s: s.fva == fva, userData["stackstrings"]) cnt_found_ss += len(f_ss) for ss in sorted(f_ss, key=lambda s: s.written_at): print_string(ss.fva, ss.written_at, ss.offset, ss.s) # IMPROVEMENT adjust stack frame member size in IDA view # print globalstrings found in this function f_gs = filter(lambda g: g.fva == fva, userData["globalstrings"]) cnt_found_ss += len(f_gs) for gs in sorted(f_gs, key=lambda g: g.written_at): print_string(gs.fva, gs.written_at, gs.offset, gs.s) if COMMENT_STACKSTRINGS: for ss in f_ss: if not ss.written_at: errors.append("Can't get location where '{}' was written in 0x{:X}.".format(ss.s, ss.fva)) continue ss_cmt = format_comment(ss.s) if append_comment(ss.written_at, ss_cmt): cnt_commented_ss += 1 else: errors.append("Failed to set comment at 0x{:X}: {}".format(ss.written_at, ss_cmt)) for gs in f_gs: if COMMENT_STACKSTRING_GLOBAL_REPEATABLE: repeatable = True cmt_va = gs.offset else: repeatable = False cmt_va = gs.written_at if not cmt_va: errors.append("Can't get location where '{}' was written in 0x{:X}.".format(gs.s, gs.fva)) continue gs_cmt = format_comment(gs.s) if append_comment(cmt_va, gs_cmt, repeatable): cnt_commented_ss += 1 else: errors.append("Failed to set comment at 0x{:X}: {}".format(cmt_va, gs_cmt)) # update IDA view idc.refresh_idaview_anyway() # clean up memory after each function eh.resetEmulatorHeapAndStack() print_summary(cnt_functions, cnt_analyzed, cnt_found_ss, cnt_commented_ss, errors) if PRINT_PLAIN_SUMMARY: print_plain_summary(userData["stackstrings"] + userData["globalstrings"]) print("\nFinished ironstrings stackstring deobfuscation after {:.2f} seconds".format(time.time() - start))
def jumpto(ea): if is_hexrays_v7(): idc.jumpto(ea) else: idaapi.jumpto(ea)