Exemplo n.º 1
0
 def get_file_offset(self, addr: int) -> int:
     memory = self._program.getMemory()
     info = memory.getAddressSourceInfo(self._to_addr(addr))
     if not info or info.getFileOffset() == -1:
         raise NotExistError(
             f"Cannot get file offset for address: {hex(addr)}")
     return info.getFileOffset()
Exemplo n.º 2
0
 def get_virtual_address(self, file_offset: int) -> int:
     addr = self._ida_loader.get_fileregion_ea(file_offset)
     if addr == self._idc.BADADDR:
         raise NotExistError(
             f"Cannot get linear address for file offset: {hex(file_offset)}"
         )
     return addr
Exemplo n.º 3
0
    def get_string_bytes(self,
                         addr: int,
                         length: int = None,
                         bit_width: int = None) -> bytes:
        addr_obj = self._to_addr(addr)
        # First check if a string or other data type is set here.
        string_obj = self._flatapi.getDataAt(addr_obj)
        if string_obj:
            if not string_obj.hasStringValue():
                # TODO: Create a different custom exception here?
                raise NotExistError(
                    f"Data type conflict at {hex(addr)}. Expected 'string', got '{string_obj.getDataType()}'"
                )
            return bytes(string_obj.getBytes()).rstrip(b"\x00")

        from ghidra.app.util.bin import MemoryByteProvider, BinaryReader

        mem = self._program.getMemory()
        provider = MemoryByteProvider(mem, addr_obj)
        reader = BinaryReader(provider, not mem.isBigEndian())
        if bit_width is None:
            bit_width = 8  # TODO: Determine how to auto detect string type.

        try:
            if bit_width == 8:
                return reader.readNextAsciiString().encode('ascii')
            elif bit_width == 16:
                return reader.readNextUnicodeString().encode('utf-16')
            else:
                raise ValueError(f"Invalid bit width: {bit_width}")
        except Exception as e:
            raise RuntimeError(
                f"Failed to create a string at {hex(addr)} with error: {e}")
Exemplo n.º 4
0
 def get_byte(self, addr: int) -> int:
     from ghidra.program.model.mem import MemoryAccessException
     try:
         # Mask necessary because jpype bytes are signed.
         return self._flatapi.getByte(self._to_addr(addr)) & 0xff
     except MemoryAccessException:
         raise NotExistError(f"Cannot get byte at {hex(addr)}")
 def remove_parameter(self, ordinal: int):
     num_parameters = self._function.getParameterCount()
     if ordinal < 0:
         ordinal += num_parameters
     if ordinal not in range(num_parameters):
         raise NotExistError(f"Invalid ordinal for parameter deletion: {ordinal}")
     self._function.removeParameter(ordinal)
Exemplo n.º 6
0
    def get_segment(self, addr_or_name: Union[int, str]) -> IDASegment:
        if isinstance(addr_or_name, str):
            name = addr_or_name
            segment_t = self._ida_segment.get_segm_by_name(name)
            if not segment_t:
                raise NotExistError(
                    f"Could not find segment with name: {name}")
        elif isinstance(addr_or_name, int):
            addr = addr_or_name
            segment_t = self._ida_segment.getseg(addr)
            if not segment_t:
                raise NotExistError(
                    f"Could not find segment containing address: 0x{addr:08x}")
        else:
            raise ValueError(f"Invalid input: {addr_or_name!r}")

        return IDASegment(self, segment_t)
 def __init__(self, ida: IDA, addr: int):
     super().__init__(ida)
     self._ida = ida
     self._addr = addr
     insn_t = self._ida._ida_helpers.get_instruction(addr)
     if not insn_t:
         raise NotExistError(f"Instruction does not exist at: {hex(addr)}")
     self._insn_t = insn_t
Exemplo n.º 8
0
 def get_virtual_address(self, file_offset: int) -> int:
     memory = self._program.getMemory()
     addresses = memory.locateAddressesForFileOffset(file_offset)
     if not addresses:
         raise NotExistError(
             f"Cannot get virtual address for file offset: {hex(file_offset)}"
         )
     for address in addresses:
         return address.getOffset()
Exemplo n.º 9
0
 def __init__(self, ghidra: Ghidra, instruction: GhidraInstruction, index: int):
     super().__init__(instruction)
     self._ghidra = ghidra
     # Ghidra doesn't necessarily have an "Operand" type.
     # Characteristics are pulled from the originating Instruction object.
     self._instruction = instruction._instruction
     self._index = index
     # TODO: Ignore validation in interest of speed?
     if index >= self._instruction.getNumOperands():
         raise NotExistError(f"The instruction at {hex(self.address)} as no operand at {index}")
Exemplo n.º 10
0
 def get_data_type(self, name: str) -> GhidraDataType:
     from ghidra.util.data import DataTypeParser
     from ghidra.program.model.data import InvalidDataTypeException
     # Must use .valueOf() because jpype doesn't handle enums well.
     parser = DataTypeParser(None,
                             DataTypeParser.AllowedDataTypes.valueOf("ALL"))
     try:
         data_type = parser.parse(name)
     except InvalidDataTypeException as e:
         raise NotExistError(e)
     return GhidraDataType(data_type)
Exemplo n.º 11
0
 def get_export(self, name: str) -> Export:
     """
     Gets export symbol by name.
     :param name: Name of import function
     :return: Export symbol
     :raises NotExistError: If export by the given name doesn't exist.
     """
     for export in self.exports:
         if export.name == name:
             return export
     raise NotExistError(f"Export with name '{name}' doesn't exist.")
Exemplo n.º 12
0
 def _to_addr(self, addr: int) -> "Address":
     """
     Internal function used to generate Ghidra Address object from integer.
     :raises NotExistError: If overflow error occurs.
     """
     try:
         return self._flatapi.toAddr(hex(addr))
     except OverflowError:
         raise NotExistError(
             f"Invalid address {hex(addr)}. Expect 32 bit integer, got {addr.bit_length()}"
         )
    def get_block(self, addr: int) -> BasicBlock:
        """
        Gets BasicBlock containing given address.
        Defaults to iterating each block and checking if address is contained within.

        :raises NotExistError: If block doesn't exist with in the flowchart for the given address.
        """
        for block in self.blocks:
            if addr in block:
                return block
        raise NotExistError(f"Unable to find block containing address 0x{addr:08x} within flowchart.")
Exemplo n.º 14
0
 def get_import(self, name: str) -> Import:
     """
     Gets import symbol by name.
     :param name: Name of import function
     :return: Import symbol
     :raises NotExistError: If import by the given name doesn't exist.
     """
     for import_ in self.imports:
         if import_.name == name:
             return import_
     raise NotExistError(f"Import with name '{name}' doesn't exist.")
Exemplo n.º 15
0
 def __init__(self, ida: IDA, addr: int):
     super().__init__(ida)
     self._ida = ida
     # IDA has no concept of a "line", so we'll keep track of the start address,
     # which IDA refers to as the "head".
     start_addr = self._ida._ida_bytes.get_item_head(addr)
     # If ida returns the unsigned value of -1 for some bit length
     if (start_addr - (1 << start_addr.bit_length())) == -1:
         raise NotExistError(f"Line at {hex(addr)} does not exist")
     self._addr = start_addr
     self._name = None
Exemplo n.º 16
0
 def get_variable(self, addr: int) -> IDAGlobalVariable:
     start_address = self._ida_bytes.get_item_head(addr)
     # Don't count code as "variables". Otherwise we get all the
     # loop labels as variables.
     flags = self._ida_bytes.get_flags(addr)
     is_code = self._ida_bytes.is_code(flags)
     # Only count as variable if item has a name.
     if not is_code and self._ida_name.get_name(start_address):
         return IDAGlobalVariable(self, start_address)
     else:
         raise NotExistError(f"Variable doesn't exist at {hex(addr)}")
Exemplo n.º 17
0
 def get_operand(self, addr: int, index: int) -> Operand:
     """
     Returns an Operand object based on the operand at a given address.
     """
     instruction = self.get_instruction(addr)
     operands = instruction.operands
     try:
         return operands[index]
     except IndexError:
         raise NotExistError(
             f"Instruction at {hex(instruction.address)} does not have an operand at index {index}"
         )
Exemplo n.º 18
0
 def get_function_signature(self, addr: int) -> GhidraFunctionSignature:
     address = self._to_addr(addr)
     function = self._flatapi.getFunctionAt(address)
     # If we don't find a function, address might be pointing to an external function pointer. (ie. import)
     if not function:
         for ref in self._flatapi.getReferencesFrom(address):
             if ref.isExternalReference():
                 function = ref.getExternalLocation().getFunction()
                 break
     if not function:
         raise NotExistError(
             f"Function signature at {hex(addr)} does not exist.")
     return GhidraFunctionSignature(self, function)
Exemplo n.º 19
0
    def get_segment(self, addr_or_name: Union[int, str]) -> GhidraSegment:
        memory = self._program.getMemory()
        if isinstance(addr_or_name, str):
            name = addr_or_name
            memory_block = memory.getBlock(name)
            if not memory_block:
                raise NotExistError(
                    f"Could not find segment with name: {name}")
        elif isinstance(addr_or_name, int):
            addr = addr_or_name
            memory_block = memory.getBlock(self._to_addr(addr))
            if not memory_block:
                raise NotExistError(
                    f"Could not find segment containing address 0x{addr:08x}")
        else:
            raise ValueError(f"Invalid input: {addr_or_name!r}")

        if not memory_block.isInitialized():
            raise NotExistError(
                f"Memory block at {memory_block.getStart()} is not initialized."
            )

        return GhidraSegment(self, memory_block)
Exemplo n.º 20
0
    def get_block(self, addr: int) -> GhidraBasicBlock:
        """
        Gets BasicBlock containing given address.
        Defaults to iterating each block and checking if address is contained within.

        :raises NotExistError: If block doesn't exist with in the flowchart for the given address.
        """
        block = self._ghidra._basic_block_model.getFirstCodeBlockContaining(
            self._ghidra._to_addr(addr), self._ghidra._monitor)
        if block:
            return GhidraBasicBlock(self._ghidra, block)
        else:
            raise NotExistError(
                f"Unable to find block containing address 0x{addr:08x} within flowchart."
            )
Exemplo n.º 21
0
    def get_instruction(self, addr: int) -> Instruction:
        """
        Returns an Instruction object for the given any address contained within the
        instruction.

        :param int addr: Address of the instruction
        :return: Instruction object
        :raises NotExistError: If instruction isn't present at given address.
        """
        line = self.get_line(addr)
        instruction = line.instruction
        if instruction:
            return instruction
        else:
            raise NotExistError(f"Instruction not found at {hex(addr)}")
Exemplo n.º 22
0
    def get(self, address: int, size: int, fill_pattern=b"\x00") -> bytes:
        """
        Obtains bytes from given address range.
        Non-initialized bytes are filled with 0 bytes.

        :param address: Start address.
        :param size: Number of bytes to obtain.
        :param fill_pattern: byte value to fill non-initialized bytes.
            If set to None, a NotExistError will be thrown if data is not contiguous.
        """
        self._obtain_uncached_chunks(address, size)
        if fill_pattern:
            return bytes(self._memory[address:address+size:fill_pattern])
        else:
            try:
                return bytes(self._memory[address:address+size])
            except ValueError as e:
                raise NotExistError(f"Unable to obtain {size} bytes from 0x{address:08X}: {e}")
Exemplo n.º 23
0
 def get_bytes(self, addr: int, length: int, default: int = None) -> bytes:
     from ghidra.program.model.mem import MemoryAccessException
     if default is None:
         try:
             return memoryview(
                 self._flatapi.getBytes(self._to_addr(addr),
                                        length)).tobytes()
         except MemoryAccessException:
             raise NotExistError(f"Cannot get bytes at {hex(addr)}")
     else:
         data = bytearray()
         for _addr in range(addr, addr + length):
             try:
                 data.append(
                     self._flatapi.getByte(self._to_addr(_addr)) & 0xFF)
             except MemoryAccessException:
                 data.append(default)
         return bytes(data)
Exemplo n.º 24
0
    def get_data_type(self, name: str) -> IDADataType:
        is_ptr = name.endswith("*")
        name = name.strip(" *")

        # Name has to be uppercase for get_named_type() to work.
        name = name.upper()

        # Create new tinfo object of type.
        tif = self._ida_typeinf.tinfo_t()
        success = tif.get_named_type(self._ida_typeinf.get_idati(), name)
        if not success:
            raise NotExistError(f"Invalid data type: {name}")

        # If a pointer, create another tinfo object that is the pointer of the first.
        if is_ptr:
            tif2 = self._ida_typeinf.tinfo_t()
            tif2.create_ptr(tif)
            tif = tif2

        return IDADataType(self, tif)
    def lines(self, start=None, reverse=False) -> Iterable[Line]:
        """
        Iterates Lines within the block.

        :param start: Start address (defaults to start or end address)
        :param reverse: Direction to iterate

        :yields: Line objects

        :raises NotExistError: If given start address is not in block
        """
        if start is not None and start not in self:
            raise NotExistError(f"Start address {hex(start)} is not in block.")

        if reverse:
            start = start or (self.end - 1)
            end = self.start - 1
        else:
            start = start or self.start
            end = self.end

        yield from self._api.lines(start=start, end=end, reverse=reverse)
Exemplo n.º 26
0
 def get_bytes(self, addr: int, length: int, default: int = None) -> bytes:
     if default is None and not self._ida_helpers.is_loaded(addr, length):
         raise NotExistError(
             f"Unable to obtain {length} bytes from 0x{addr:08X}: "
             f"Address range not fully loaded.")
     return self._ida_helpers.get_bytes(addr, length, default=default or 0)
Exemplo n.º 27
0
 def get_register(self, name: str) -> GhidraRegister:
     reg = self._program.getRegister(name)
     if not reg:
         raise NotExistError(f"Invalid register name: {name}")
     return GhidraRegister(reg)
Exemplo n.º 28
0
 def get_function(self, addr: int) -> GhidraFunction:
     function = self._flatapi.getFunctionContaining(self._to_addr(addr))
     if not function:
         raise NotExistError(
             f"Function containing {hex(addr)} does not exist.")
     return GhidraFunction(self, function)
Exemplo n.º 29
0
 def get_variable(self, addr: int) -> GhidraGlobalVariable:
     data = self._flatapi.getDataContaining(self._to_addr(addr))
     if not data:
         raise NotExistError(f"Variable doesn't exist at {hex(addr)}")
     return GhidraGlobalVariable(self, data)
Exemplo n.º 30
0
 def get_byte(self, addr: int) -> int:
     if not self._bytes_loaded(addr, 1):
         raise NotExistError(f"Cannot get byte at {hex(addr)}")
     return self._ida_bytes.get_wide_byte(addr)