def get_value_info(self, v, stack_view=False): result = "" ptr = v.value val_type = v.type level = v.level if not idaapi.is_loaded(ptr): result += self.get_printable(ptr) return result area_name = "" if config.show_area_name: area_name = self.as_area_name(v) if val_type == T_CODE: result += area_name if self.is_code(ptr): result += self.as_disasm(ptr) else: if val_type not in (T_STACK, T_HEAP): result += area_name if stack_view: if level == 0: result += self.get_ptr_value(v) else: result += self.str_or_value(v) else: result += self.str_or_value(v) return result
def value(self, value): """ Set the operand to the specified value within the cpu_context. """ # Value may be signed. if isinstance(value, int) and value < 0: value = utils.unsigned(value, bit_width=self.width * 8) # If we are writing to an immediate, I believe they want to write to the memory at the immediate. # TODO: Should we fail instead? if self.is_immediate: offset = self.value if idaapi.is_loaded(offset): self._cpu_context.mem_write(offset, value) return if self.is_register: # Convert the value from string to integer... if isinstance(value, str): value = utils.struct_unpack(value) self._cpu_context.registers[self.text] = value return if self.is_memory_reference: # FIXME: Usage of numpy is most likely symptomatic of a bug in an opcode # implementation passing in bad data. # Update this to just is "isinstance" and then fix the buggy opcode. # For data written to the frame or memory, this data MUST be a byte string. if numpy.issubdtype(type(value), numpy.integer): value = utils.struct_pack(value, width=self.width) self._cpu_context.mem_write(self.addr, value) return raise FunctionTracingError(f"Invalid operand type: {self.type}", ip=self.ip)
def get_struct(address, struct_type): assert idaapi.is_loaded( address) == True, "Can't access memory at 0x%x" % address sbytes = idaapi.get_bytes(address, sizeof(struct_type)) struct = struct_type.from_buffer_copy(sbytes) struct._addr = address return struct
def get_value_type(ea): addr_type = T_VALUE if not idaapi.is_loaded(ea): return addr_type segm_name = idc.SegName(ea) segm = idaapi.getseg(ea) flags = idc.GetFlags(ea) is_code = idc.isCode(flags) if "stack" in segm_name.lower() or \ (dbg.stack_segm and dbg.stack_segm.start_ea == segm.start_ea): addr_type = T_STACK elif "heap" in segm_name.lower(): addr_type = T_HEAP elif not is_code and segm.perm & idaapi.SEGPERM_READ and \ segm.perm & idaapi.SEGPERM_WRITE and \ segm.perm & idaapi.SEGPERM_EXEC: addr_type = T_RWX elif is_code or \ (segm.perm & idaapi.SEGPERM_READ and segm.perm & idaapi.SEGPERM_EXEC): addr_type = T_CODE elif segm.perm & idaapi.SEGPERM_READ and \ segm.perm & idaapi.SEGPERM_WRITE: addr_type = T_DATA elif segm.perm & idaapi.SEGPERM_READ: addr_type = T_RODATA return addr_type
def find_main_arena(): main_arena = idc.LocByName("main_arena") # from libc6-dbg if main_arena != idc.BADADDR: return main_arena ea = idc.SegStart(idc.LocByName("_IO_2_1_stdin_")) end_ea = idc.SegEnd(ea) # &main_arena->next offsets = { 4: [1088, 1096], # 32 bits 8: [2152, 2160] # 64 bits } if ea == idc.BADADDR or end_ea == idc.BADADDR: return None get_ptr = config.get_ptr while ea < end_ea: ptr = get_ptr(ea) # ptr to main_arena if idaapi.is_loaded(ptr) and ptr < ea and get_ptr( ptr) == 0: # flags=0x0 if (ea - ptr) in offsets[config.ptr_size]: return ptr ea += config.ptr_size return None
def OnDblClick(self, shift): symbol = self.get_current_word() if symbol is not None: ea = self.resolve_expr(symbol) if ea and idaapi.is_loaded(ea): idaapi.jumpto(ea) return True return False
def get_loaded_bytes(start_addr, size, fill_with="\x00"): data = "" cur_ea = start_addr while cur_ea < (start_addr+size): if idaapi.is_loaded(cur_ea): data += chr(idaapi.get_byte(cur_ea)) else: data += fill_with cur_ea += 1 return bytes(data, 'latin1')
def jump_in_hex(self): ea = self.get_current_expr_ea() if not ea or not idaapi.is_loaded(ea): idaapi.warning("Unable to resolve current expression\n") widget = self.find_hex_view() if not widget: idaapi.warning("Unable to find hex view") return self.jumpto_in_view(widget, ea)
def get_chain(value, limit=config.deref_limit): count = 0 stop = False result = [value] if not idaapi.is_loaded(value): return result, False next_val = dbg.get_ptr(value) while not stop and count < limit: if result.count(next_val) >= 2 or not idaapi.is_loaded(next_val): stop = True continue result.append(next_val) next_val = dbg.get_ptr(next_val) count += 1 exceeded = not stop return result, exceeded
def jump_in_new_window(self): ea = self.get_current_expr_ea() if not ea or not idaapi.is_loaded(ea): return window_name = "D-0x%x" % ea widget = idaapi.open_disasm_window(window_name) if widget: self.jumpto_in_view(widget, ea) else: idaapi.warning("Unable to create the new window")
def StartDump(self): # print self.start # print self.endorlen self.filepath = idaapi.ask_file(1, "*.dump", "save dump file") if self.dumptype == 0: ea = self.getHexNum(self.start) len = self.getHexNum(self.endorlen) if not idaapi.is_loaded(ea) or not idaapi.is_loaded(ea + len): idaapi.warning("arrary is out of bound") return -1 if len <= 0: idaapi.warning("len is <= 0") return -1 print("start read bytes") self.Close(0) idaapi.show_wait_box("read bytes") self.memdata = idaapi.get_bytes(ea, len) print("read bytes end") #idaapi.hide_wait_box("read end") idaapi.hide_wait_box() elif self.dumptype == 1: ea = self.getHexNum(self.start) len = self.getHexNum(self.endorlen) - self.getHexNum(self.start) if not idaapi.is_loaded(ea) or not idaapi.is_loaded(ea + len): idaapi.warning("arrary is out of bound") return -1 if len <= 0: idaapi.warning("len is <= 0") return -1 print("start read bytes") self.Close(0) idaapi.show_wait_box("read bytes") self.memdata = idaapi.get_bytes(ea, len) print("read bytes end") #idaapi.hide_wait_box("read end") idaapi.hide_wait_box() fp = open(self.filepath, 'wb') fp.write(self.memdata) fp.close() idaapi.msg("save:" + self.filepath) return 1
def OnDblClick(self, shift): symbol = self.get_current_word() if symbol is not None: if symbol.isupper() and symbol.replace("*", "") in dbg.registers: self.modify_value() return True else: ea = self.resolve_expr(symbol) if ea and idaapi.is_loaded(ea): idaapi.jumpto(ea) return True return False
def reload_info(self): if not dbg.is_process_suspended(): return False base_addr = None if self.base_expr is None: base_addr = idc.get_reg_value(dbg.registers.stack) else: base_addr = idaapi.str2ea(self.base_expr) if base_addr == idc.BADADDR: idaapi.warning("Invalid base expr: %s" % self.base_expr) return False if not idaapi.is_loaded(base_addr): idaapi.warning("Memory address is not loaded: $#x" % base_addr) return False self.ClearLines() dbg.set_thread_info() try: segm_end = idc.get_segm_end(base_addr) n_entries = config.n_stack_entries or ((segm_end - base_addr) // dbg.ptr_size) for i in range(n_entries): offset = i * dbg.ptr_size ptr = base_addr + offset if not idaapi.is_loaded(ptr): break value = dbg.get_ptr(ptr) self.add_line("%02d:%04X %s" % (i, offset, self.parse_value(ptr))) except Exception as e: idaapi.warning(str(e)) return False return True
def is_read_only_inited_var(self, address): s: segment_t = getseg(address) if s is None: return False if s.perm != (SEGPERM_READ | SEGPERM_WRITE): return False if is_loaded(address): return False ref_finder = xrefblk_t() is_ok = ref_finder.first_to(address, XREF_DATA) while is_ok: if ref_finder.type == dr_W: return False is_ok = ref_finder.next_to() return True
def value(self, value): """ Set the operand to the specified value within the cpu_context. """ # If we are writing to an immediate, I believe they want to write to the memory at the immediate. # TODO: Should we fail instead? if self.is_immediate: offset = self.value if idaapi.is_loaded(offset): self._cpu_context.mem_write(offset, value) return if self.is_register: # Convert the value from string to integer... if isinstance(value, str): value = utils.struct_unpack(value) # On 64-bit, the destination register must be set to 0 first (per documentation) # TODO: Check if this happens regardless of the source size if idc.__EA64__ and self.width == 4: # Only do this for 32-bit setting reg64 = utils.convert_reg(self.text, 8) self._cpu_context.registers[reg64] = 0 self._cpu_context.registers[self.text] = value return # TODO: Determine if this is still necessary. # FS, GS (at least) registers are identified as memory addresses. We need to identify them as registers # and handle them as such if self.type == idc.o_mem: if "fs" in self.text: self._cpu_context.registers.fs = value return elif "gs" in self.text: self._cpu_context.registers.gs = value return if self.is_memory_reference: # For data written to the frame or memory, this data MUST be a byte string. if numpy.issubdtype(type(value), numpy.integer): value = utils.struct_pack(value, width=self.width) self._cpu_context.mem_write(self.addr, value) return raise FunctionTracingError('Invalid operand type: {}'.format( self.type), ip=self.ip)
def next_on_click(self): chunk_addr = self.get_chunk_address() if chunk_addr is None: idaapi.warning("Invalid address / expression") return try: chunk = self.heap.get_chunk(chunk_addr) chunk_size = chunk.norm_size next_addr = chunk_addr+chunk_size if idaapi.is_loaded(next_addr): self.show_chunk("%#x" % next_addr) else: idaapi.warning("%#x: next chunk (%#x) is not loaded" % \ (chunk_addr, next_addr)) except Exception as e: idaapi.warning("ERROR: " + str(e))
def arenas(self): results = [] main_arena_addr = self.main_arena_addr arena = self.get_arena() # main_arena results.append([main_arena_addr, arena]) next_ptr = arena.next while next_ptr not in (main_arena_addr, 0): if not idaapi.is_loaded(next_ptr): break arena = self.get_arena(next_ptr) results.append([next_ptr, arena]) next_ptr = arena.next return results
def modify_value(self): ea = self.get_current_expr_ea() if not ea or not idaapi.is_loaded(ea): return stack_val = 0 if idaapi.inf_is_64bit(): stack_val = ida_bytes.get_qword(ea) else: stack_val = ida_bytes.get_dword(ea) b = idaapi.ask_str("0x%X" % stack_val, 0, "Modify value") if b is not None: try: value = int(idaapi.str2ea(b)) if idaapi.inf_is_64bit(): idc.patch_qword(ea, value) else: idc.patch_dword(ea, value) self.reload_info() except: idaapi.warning("Invalid expression")
def find_malloc_par(): mp_ = idc.get_name_ea_simple("mp_") if mp_ != idc.BADADDR: return mp_ segm = idaapi.get_segm_by_name("[heap]") if segm is None: return None offset = get_struct_offsets(malloc_par()).get('sbrk_base') sbrk_base = segm.start_ea ea = idc.get_segm_start(get_name_ea_simple("_IO_2_1_stdin_")) end_ea = idc.get_segm_end(ea) while ea < end_ea: ptr = config.get_ptr(ea) if idaapi.is_loaded(ptr) and ptr == sbrk_base: return (ea - offset) ea += config.ptr_size return None
def find_main_arena(): main_arena = idc.get_name_ea_simple("main_arena") # from libc6-dbg if main_arena != idc.BADADDR: return main_arena ea = idc.get_segm_start(idc.get_name_ea_simple("_IO_2_1_stdin_")) end_ea = idc.get_segm_end(ea) # &main_arena->next offsets = { 4: [1088, 1096], # 32 bits 8: [2152, 2160] # 64 bits }[config.ptr_size] if ea == idc.BADADDR or end_ea == idc.BADADDR: return None while ea < end_ea: ptr = config.get_ptr(ea) # ptr to main_arena if idaapi.is_loaded(ptr) and ptr < ea: if (ea - ptr) in offsets: return ptr ea += config.ptr_size return None
def view_chunk_info(self): chunk_template = ''' <style> td { padding-right: 30px; } table { font-size: 12px; white-space: nowrap; overflow: hidden; } body { width: 100%%; } #hexdump { font-family:Monaco; font-size:12px; white-space:pre; } </style> <p><b>[ %#x ]</b><br> <!-- Chunk fields --> %s <br> <p><b>[ hexdump ]</b></p> <p id="hexdump";>%s</p> ''' chunk_addr = self.get_chunk_address() if chunk_addr is None: idaapi.warning("Invalid address / expression") return try: splitted = False in_use = None chunk_data = "" chunk_hexdump = "" chunk = self.heap.get_chunk(chunk_addr) chunk_bytes = chunk.norm_size if chunk_bytes > config.hexdump_limit: chunk_bytes = config.hexdump_limit splitted = True if chunk_bytes > 0 and idaapi.is_loaded(chunk_addr + chunk_bytes): chunk_data = idaapi.get_bytes(chunk_addr, chunk_bytes) else: chunk_data = chunk.data if idaapi.is_loaded(chunk_addr + chunk.norm_size): in_use = self.heap.next_chunk(chunk_addr).prev_inuse chunk_table = self.html_chunk_table(chunk, in_use) if chunk_data: chunk_hexdump = self.html_chunk_hexdump(chunk_data, splitted) self.te_chunk_info.clear() chunk_info = chunk_template % (chunk_addr, chunk_table, chunk_hexdump) self.te_chunk_info.insertHtml(chunk_info) except Exception as e: idaapi.warning("ERROR: " + str(e))