def lines(start=None, end=None, reverse=False, selection=False): """Iterate lines in range. Args: start: Starting address, start of IDB if `None`. end: End address, end of IDB if `None`. reverse: Set to true to iterate in reverse order. selection: If set to True, replaces start and end with current selection. Returns: iterator of `Line` objects. """ if selection: start, end = get_selection() else: start, end = fix_addresses(start, end) if not reverse: item = idaapi.get_item_head(start) while item < end: yield Line(item) item += idaapi.get_item_size(item) else: # if reverse: item = idaapi.get_item_head(end - 1) while item >= start: yield Line(item) item = idaapi.get_item_head(item - 1)
def copy_bytes(): """ Copy selected bytes to clipboard """ if using_ida7api: start = idc.read_selection_start() end = idc.read_selection_end() if idaapi.BADADDR in (start, end): ea = idc.here() start = idaapi.get_item_head(ea) end = idaapi.get_item_end(ea) # # reference https://stackoverflow.com/questions/6624453/whats-the-correct-way-to-convert-bytes-to-a-hex-string-in-python-3 data = idc.get_bytes(start, end - start).hex() print("Bytes copied: %s" % data) copy_to_clip(data) else: start = idc.SelStart() end = idc.SelEnd() if idaapi.BADADDR in (start, end): ea = idc.here() start = idaapi.get_item_head(ea) end = idaapi.get_item_end(ea) # reference https://stackoverflow.com/questions/6624453/whats-the-correct-way-to-convert-bytes-to-a-hex-string-in-python-3 # not work in ida7.5 python3.7.7 # data = idc.GetManyBytes(start, end-start).encode('hex') data = idc.GetManyBytes(start, end - start).hex() print("Bytes copied: %s" % data) copy_to_clip(data) return
def is_string(ea): string_type = idc.get_str_type(idaapi.get_item_head(ea)) if string_type in (None, -1): return False return True
def convert_vtable_to_offsets(vtable, length=None): """Convert a vtable into a sequence of offsets. Arguments: vtable: The address of the virtual method table. Options: length: The length of the vtable, if known. Returns: True if the data was successfully converted into offsets. """ if length is None: length = vtable_length(vtable) if not length: _log(0, 'Address {:#x} is not a vtable', vtable) return False successful = True for address in idau.Addresses(vtable, length=length, step=idau.WORD_SIZE): # Handle addresses that are part of ALIGN directives if idaapi.is_align_insn(address) != 0: head = idaapi.get_item_head(address) idaapi.del_items(head) if not idc.op_plain_offset(address, 0, 0): _log(0, 'Could not change address {:#x} into an offset', address) successful = False return successful
def addr_switch(self, offset, msg): if (not msg) or (msg == ""): return [offset, msg] try: args = self.parser.parse_args(msg.split()) except: print "[*] failed to parse command" return [None, msg] # no address switch supplied if not args.address: return [offset, msg] try: addr = int("".join(args.address), 16) except: print "[*] failed to parse address, should be hex" return [None, msg] # make sure the address points to a valid instruction/data head = idaapi.get_item_head(addr) if head != addr: print "[*] ambiguous address, did you mean 0x%x ?" % head return [None, msg] return [addr, " ".join(args.msg)]
def addr_switch(self, offset, msg): if (not msg) or (msg == ''): return [offset, msg] try: args = self.parser.parse_args(msg.split()) except: print "[*] failed to parse command" return [None, msg] # no address switch supplied if not args.address: return [offset, msg] try: addr = int(''.join(args.address), 16) except: print "[*] failed to parse address, should be hex" return [None, msg] # make sure the address points to a valid instruction/data head = idaapi.get_item_head(addr) if head != addr: print "[*] ambiguous address, did you mean 0x%x ?" % head return [None, msg] return [addr, ' '.join(args.msg)]
def is_string(ea): string_type = idc.GetStringType(idaapi.get_item_head(ea)) if string_type is None: return False return True
def handle_dll_calls(self): dll_call_count = ida_bytes.get_dword(self.E_info_entry_ea + self.dll_call_count_offset) dll_call_lib_names_ea = ida_bytes.get_dword( self.E_info_entry_ea + self.dll_call_lib_names_offset) dll_call_func_names_ea = ida_bytes.get_dword( self.E_info_entry_ea + self.dll_call_func_names_offset) self.dll_calls = Dll_calls(dll_call_lib_names_ea, dll_call_func_names_ea, dll_call_count) ida_auto.auto_wait() ea = ida_name.get_name_ea(idaapi.BADADDR, "j__krnl_MCallDllCmd") code_fref_eas = [] fref_ea = ida_xref.get_first_fcref_to(ea) while fref_ea != idaapi.BADADDR: code_fref_eas.append(fref_ea) fref_ea = ida_xref.get_next_cref_to(ea, fref_ea) for ref_ea in code_fref_eas: #get prev mov instruction prev_ins_ea = idaapi.get_item_head(ref_ea - 1) ins = ida_lines.generate_disasm_line(prev_ins_ea, ida_lines.GENDSM_REMOVE_TAGS) if (ins.startswith("mov eax,")): index = ida_bytes.get_dword(prev_ins_ea + 1) cmt = self.dll_calls[index] ida_bytes.set_cmt(ref_ea, cmt, False)
def addr_switch(self, offset, msg): if (not msg) or (msg == ''): return [offset, msg] try: args = self.parser.parse_args(msg.split()) except argparse.ArgumentError: rs_log('failed to parse command') return [None, msg] # no address switch supplied if not args.address: return [offset, msg] try: addr = int(''.join(args.address), 16) except (TypeError, ValueError): rs_log('failed to parse address, should be hex') return [None, msg] # make sure the address points to a valid instruction/data head = idaapi.get_item_head(addr) if head != addr: rs_log("ambiguous address, did you mean 0x%x ?" % head) return [None, msg] return [addr, ' '.join(args.msg)]
def get_selection(): start = idc.SelStart() end = idc.SelEnd() if idaapi.BADADDR in (start, end): ea = idc.here() start = idaapi.get_item_head(ea) end = idaapi.get_item_end(ea) return start, end
def __head2__(cls, start, end): # Ensures that both ``start`` and ``end`` are pointing to valid addresses entryframe = cls.pframe() res_start, res_end = idaapi.get_item_head(start), idaapi.get_item_head( end) # FIXME: off-by-one here, as end can be the size of the db. if res_start != start: logging.warn( "{:s} : Starting address of {:x} not aligned to the beginning of an item. Fixing it to {:x}." .format(entryframe.f_code.co_name, start, res_start)) start = res_start if res_end != end: logging.warn( "{:s} : Ending address of {:x} not aligned to the beginning of an item. Fixing it to {:x}." .format(entryframe.f_code.co_name, end, res_end)) end = res_end return start, end
def lines(start=None, end=None, reverse=False): """Iterate lines in range. :param start: Starting address, start of IDB if `None`. :param end: End address, end of IDB if `None`. :return: iterator of `Line` objects. """ start, end = fix_addresses(start, end) if not reverse: item = idaapi.get_item_head(start) while item < end: yield Line(item) item += idaapi.get_item_size(item) else: # if reverse: item = idaapi.get_item_head(end - 1) while item > start: yield Line(item) item = idaapi.get_item_head(item - 1)
def __head1__(cls, ea): # Ensures that ``ea`` is pointing to a valid address entryframe = cls.pframe() res = idaapi.get_item_head(ea) if res != ea: logging.warn( "{:s} : Address {:x} not aligned to the beginning of an item. Fixing it to {:x}." .format(entryframe.f_code.co_name, ea, res)) ea = res return ea
def get_selection(always=True): start = idc.SelStart() end = idc.SelEnd() if idaapi.BADADDR in (start, end): if not always: raise exceptions.SarkNoSelection() ea = idc.here() start = idaapi.get_item_head(ea) end = idaapi.get_item_end(ea) return Selection(start, end)
def get_string(ea): """Read the string at the given ea. This function uses IDA's string APIs and does not implement any special logic. """ # We get the item-head because the `GetStringType` function only works on the head of an item. string_type = idc.GetStringType(idaapi.get_item_head(ea)) if string_type is None: raise exceptions.SarkNoString("No string at 0x{:08X}".format(ea)) string = idc.GetString(ea, strtype=string_type) if not string: raise exceptions.SarkNoString("No string at 0x{:08X}".format(ea)) return string
def __init__(self, ea=UseCurrentAddress, name=None): if name is not None and ea != self.UseCurrentAddress: raise ValueError(("Either supply a name or an address (ea). " "Not both. (ea={!r}, name={!r})").format(ea, name)) elif name is not None: ea = idc.LocByName(name) elif ea == self.UseCurrentAddress: ea = idc.here() elif ea is None: raise ValueError("`None` is not a valid address. To use the current screen ea, " "use `Line(ea=Line.UseCurrentAddress)` or supply no `ea`.") self._ea = idaapi.get_item_head(ea) self._comments = Comments(ea)
def visit_expr(self, expression): global Storage if expression.op == idaapi.cot_obj: for start, end, off, func in Storage: if expression.obj_ea >= start and expression.obj_ea <= end: if func and self.cfunc.entry_ea != func: return 0 parent = self.cfunc.body.find_parent_of(expression) if parent.op != idaapi.cot_idx: return 0 parent = self.cfunc.body.find_parent_of(parent) if parent.op != idaapi.cot_memref: return 0 target_ea = expression.obj_ea + off head_ea = idaapi.get_item_head(target_ea) if head_ea != target_ea and idaapi.isStruct(idaapi.getFlags(head_ea)): parent.cexpr.m = target_ea - head_ea expression.obj_ea = head_ea rc = self.recalc_parent_types() return 0 return 0
def head(cls, ea=None): ea = ui.current.address() if ea is None else ea return idaapi.get_item_head(ea)
def get_prev_insn_ea (ea, n): current_ea = ea for m in range (0, n): current_ea = idaapi.get_item_head (current_ea-1) return current_ea
def get_prev_insn_ea(ea, n): current_ea = ea for m in range(0, n): current_ea = idaapi.get_item_head(current_ea - 1) return current_ea
def visit_expr(self, expression): global Storage self.nodes.append(expression) if expression.op == idaapi.cot_obj: for start, end, off, func in Storage: if expression.obj_ea >= start and expression.obj_ea <= end: if func and self.cfunc.entry_ea != func: return 0 target_ea = expression.obj_ea + off head_ea = idaapi.get_item_head(target_ea) if head_ea != target_ea and idaapi.isStruct(idaapi.getFlags(head_ea)): ref_parent = self.cfunc.body.find_parent_of(expression) if ref_parent.op == idaapi.cot_ref: parent = self.cfunc.body.find_parent_of(ref_parent) if parent.op == idaapi.cot_add: v = target_ea - head_ea num_node = idaapi.make_num(v) num_node.thisown = False num_node.n.thisown = False parent = parent.cexpr # parent.thisown = False tif = idaapi.tinfo_t() if not idaapi.get_tinfo(tif, head_ea): idaapi.guess_tinfo(tif, head_ea) if parent.x == ref_parent.cexpr: # ref_parent.thisown = False # ref_parent.cexpr.thisown = False ref_parent = parent.x # expression = ref_parent.x ref_new = idaapi.cexpr_t(ref_parent) ref_new.thisown = False # expression.thisown = False # expression_new.type.thisown = False # tif.thisown = False element_tif = tif.get_ptrarr_object() element_tif.create_ptr(element_tif) ref_new.type = element_tif ref_new.x.type = tif ref_new.x.obj_ea = head_ea expr_add = idaapi.cexpr_t(idaapi.cot_add, ref_new, num_node) expr_add.thisown = False # expr_add.type = element_tif ref_parent.cexpr.assign(expr_add) # parent.x.thisown = False # parent.x.swap(expr_add) # ref_parent1 = idaapi.cexpr_t(ref_parent.cexpr) # parent.x.swap(ref_parent1) elif parent.y == ref_parent.cexpr: ref_parent.thisown = False ref_parent.cexpr.thisown = False ref_parent = idaapi.cexpr_t(ref_parent.cexpr) expression.thisown = False expression = idaapi.cexpr_t(expression) ref_parent.x.replace_by(expression) expr_add = idaapi.cexpr_t(idaapi.cot_add, ref_parent, num_node) parent.y.thisown = False parent.y.replace_by(expr_add) else: print "F**K!" rc = self.recalc_parent_types() # parent = self.nodes[-2] # parent = self.nodes[-3] # parent = self.nodes[-4] return 0