def references(function_location, decoding_str): """decodes all decoded strings by a given function by applying decoding_str to every byte. decoding_str should contain encoded_byte, for example: decode.references(0x401000, "(encoded_byte ^ 0xA2) + 0x21")""" for xref in idautils.XrefsTo(function_location): ea = xref.frm # The function needs to be defined for get_arg_addrs to work args = idaapi.get_arg_addrs(ea) encoded = idc.get_operand_value(args[0], 0) decoded = idc.get_operand_value(args[1], 0) decoded_str = "" i = 0 encoded_byte = ida_bytes.get_wide_byte(encoded) while encoded_byte != 0: decoded_byte = eval(decoding_str) decoded_str += chr(decoded_byte) ida_bytes.patch_byte(decoded + i, decoded_byte) i += 1 encoded_byte = ida_bytes.get_wide_byte(encoded + i) ida_bytes.create_strlit(decoded, i, STRTYPE_C) idc.set_cmt(ea, f"Decoded: {decoded_str}", 0) print(f"##At {hex(ea)} decoded: {decoded_str}")
def get_string_from_mem(cls, addr): """ 从addr逐字节获取字符 """ string = '' chr_t = ida_bytes.get_wide_byte(addr) i = 0 while chr_t != 0: chr_t = ida_bytes.get_wide_byte(addr+i) string += chr(chr_t) i += 1 return string[:-1]
def value(self): """ Property which return the value corresponding to the data of a numberable elements. This property works only if the :meth:`~BipData.is_numerable` and :meth:`~BipData.has_data` properties returned True. For getting value of an element which is not numerable use the :meth:`~BipElt.bytes` property. This property is link to the type defined or guessed by IDA and it is a good idea to assure you have the proper type before using it. :return: An integer representing the value of the data or ``None`` if the data element is not numerable or do not have data. """ if not self.has_data: return None elif self.is_unknown or self.is_byte: return ida_bytes.get_wide_byte(self.ea) elif self.is_word: return ida_bytes.get_wide_word(self.ea) elif self.is_dword: return ida_bytes.get_wide_dword(self.ea) elif self.is_qword: return ida_bytes.get_qword(self.ea) else: return None
def decode_str(decoding_str): """decodes the current string pointer by applying decoding_str to every byte decoding_str should contain encoded_byte, for example: decode.string("(encoded_byte ^ 0xA2) + 0x21")""" encoded = get_screen_ea() decoded_str = "" i = 0 encoded_byte = ida_bytes.get_wide_byte(encoded) while encoded_byte != 0: decoded_byte = eval(decoding_str) decoded_str += chr(decoded_byte) i += 1 encoded_byte = ida_bytes.get_wide_byte(encoded + i) idc.set_cmt(encoded, f"Decoded: {decoded_str}", 1) print(f"##At {hex(encoded)} decoded: {decoded_str}")
def bytes(self): """ Property returning the value of the bytes contain in the function. :return: A list of the bytes forming the element. :rtype: list(int) """ return [ida_bytes.get_wide_byte(i) for i in range(self.ea, self.end)]
def _obtain_bytes(start, end): """ Obtain bytes efficiently, sets non-loaded bytes to \x00 :param int start: starting address :param int end: ending address :return bytearray: bytearray containing bytes within range """ # Reconstruct the segment, account for bytes which are not loaded. bytes_range = range(start, end) # a range from start -> end return bytearray( ida_bytes.get_wide_byte(i) if idc.is_loaded(i) else 0 for i in bytes_range)
def _try_map_byte(memory, ea, seg_ref): """Try to map a byte into memory.""" seg = _find_segment_containing_ea(ea, seg_ref) if not seg: return False can_write = 0 != (seg.perm & ida_segment.SEGPERM_WRITE) can_exec = _is_executable_seg(seg) val = 0 if ida_bytes.has_value(ida_bytes.get_full_flags(ea)): val = ida_bytes.get_wide_byte(ea) & 0xFF flags = ida_bytes.get_full_flags(ea) memory.map_byte(ea, val, can_write, can_exec) return True
def _obtain_bytes(start, end): """ Obtain bytes efficiently, sets non-loaded bytes to \x00 :param int start: starting address :param int end: ending address :return bytes: bytes contained within range """ # Reconstruct the segment, account for bytes which are not loaded. # Can't use xrange() here because we can get a "Python int too large to conver to C long" error bytes_range = range(start, end) # a range from start -> end return bytes( bytearray( ida_bytes.get_wide_byte(i) if idc.is_loaded(i) else 0 for i in bytes_range))
def get_byte(ea=None, original=False): """ Static method allowing to get the value of one byte at an address. :param ea: The address at which recuperating the value. If ``None`` the screen address is used. :param original: If True the value recuperated will be the original one (before a patch). Default: False. :return: An integer corresponding to the value at the address. """ if ea is None: ea = ida_kernwin.get_screen_ea() if original: return ida_bytes.get_original_byte(ea) else: return ida_bytes.get_wide_byte(ea)
def get_bytes(ea, size, original=False): """ Static method allowing to get the value of several bytes at an address. :param ea: The address where to get the buffer. If ``None`` the screen address is used. :param size: The number of bytes to get. :param original: If True the value recuperated will be the original one (before a patch). Default: False. :return: A byte string corresponding to the bytes at the address. """ if ea is None: ea = ida_kernwin.get_screen_ea() res = b"" if original: for i in range(size): res += int2byte(ida_bytes.get_original_byte(ea + i)) else: for i in range(size): res += int2byte(ida_bytes.get_wide_byte(ea + i)) return res
def byte_patched(self, ea, old_value): self._send_packet(evt.BytePatchedEvent(ea, ida_bytes.get_wide_byte(ea))) return 0
def get_byte(self, pos=None): if pos is None: pos = self.pos self.pos += 1 return ida_bytes.get_wide_byte(self.addr + pos)
def byte_patched(self, ea, old_value): bytes = ida_bytes.get_wide_byte(ea) print("Detected a byte patched: at 0x%x" % (ea)) return 0