Ejemplo n.º 1
0
    def fetch_sequence(self, address):
        base_addr, index = split_address(address)

        if base_addr not in self.__container:
            raise ReilContainerInvalidAddressError()

        return self.__container[base_addr]
Ejemplo n.º 2
0
    def __execute(self, asm_instr):
        # Process one assembler instruction. Translate it to REIL instruction and
        # process each one.
        instr_container = self.__translate(asm_instr)
        ip = to_reil_address(asm_instr.address)
        next_addr = None

        while ip:
            # Fetch instruction.
            try:
                reil_instr = instr_container.fetch(ip)
            except ReilContainerInvalidAddressError:
                next_addr, _ = split_address(ip)
                break

            if reil_instr.mnemonic == ReilMnemonic.UNKN:
                raise InstructionNotImplemented(asm_instr)

            # Execute instruction.
            next_ip = self.ir_emulator.single_step(reil_instr)

            # Update instruction pointer.
            ip = next_ip if next_ip else instr_container.get_next_address(ip)

        del instr_container

        # delete temporal registers
        regs = self.ir_emulator.registers.keys()

        for r in regs:
            if r.startswith("t"):
                del self.ir_emulator.registers[r]

        return next_addr if next_addr else asm_instr.address + asm_instr.size
Ejemplo n.º 3
0
    def fetch(self, address):
        base_addr, index = split_address(address)

        if base_addr not in self.__container:
            self.__resolve_address(base_addr)

        return self.__container[base_addr].get(index)
Ejemplo n.º 4
0
    def fetch(self, address):
        base_addr, index = split_address(address)

        if base_addr != to_asm_address(self.address):
            raise ReilSequenceInvalidAddressError()

        return self.get(index)
Ejemplo n.º 5
0
    def add(self, sequence):
        base_addr, _ = split_address(sequence.address)

        if base_addr in self.__container.keys():
            raise Exception("Invalid sequence")
        else:
            self.__container[base_addr] = sequence
Ejemplo n.º 6
0
    def fetch_sequence(self, address):
        base_addr, index = split_address(address)

        if base_addr not in self.__container.keys():
            raise ReilContainerInvalidAddressError()

        return self.__container[base_addr]
Ejemplo n.º 7
0
    def fetch(self, address):
        base_addr, index = split_address(address)

        if base_addr not in self.__container.keys():
            self.__resolve_address(base_addr)

        return self.__container[base_addr].get(index)
Ejemplo n.º 8
0
    def fetch(self, address):
        base_addr, index = split_address(address)

        if base_addr != to_asm_address(self.address):
            raise ReilSequenceInvalidAddressError()

        return self.get(index)
Ejemplo n.º 9
0
    def add(self, sequence):
        base_addr, _ = split_address(sequence.address)

        if base_addr in self.__container.keys():
            raise Exception("Invalid sequence")
        else:
            self.__container[base_addr] = sequence
Ejemplo n.º 10
0
    def fetch(self, address):
        base_addr, index = split_address(address)

        if base_addr not in self.__container:
            raise ReilContainerInvalidAddressError()

        return self.__container[base_addr].get(index)
Ejemplo n.º 11
0
    def get_next_address(self, address):
        base_addr, index = split_address(address)

        if base_addr != to_asm_address(self.address):
            raise ReilSequenceInvalidAddressError()

        addr = address

        if index < len(self.__sequence) - 1:
            addr += 1
        else:
            raise ReilSequenceInvalidAddressError()

        return addr
Ejemplo n.º 12
0
    def get_next_address(self, address):
        base_addr, index = split_address(address)

        if base_addr != to_asm_address(self.address):
            raise ReilSequenceInvalidAddressError()

        addr = address

        if index < len(self.__sequence) - 1:
            addr += 1
        else:
            raise ReilSequenceInvalidAddressError()

        return addr
Ejemplo n.º 13
0
    def get_next_address(self, address):
        base_addr, index = split_address(address)

        if base_addr not in self.__container.keys():
            raise Exception("Invalid address.")

        addr = address

        if index < len(self.__container[base_addr]) - 1:
            addr += 1
        else:
            addr = self.__container[base_addr].next_sequence_address

        return addr
Ejemplo n.º 14
0
    def get_next_address(self, address):
        base_addr, index = split_address(address)

        if base_addr not in self.__container:
            raise Exception("Invalid address.")

        addr = address

        if index < len(self.__container[base_addr]) - 1:
            addr += 1
        else:
            addr = self.__container[base_addr].next_sequence_address

        return addr
Ejemplo n.º 15
0
    def __fa_process_sequence(self, sequence, avoid, initial_state,
                              execution_state, trace_current, next_addr):
        """Process a REIL sequence.

        Args:
            sequence (ReilSequence): A REIL sequence to process.
            avoid (list): List of address to avoid.
            initial_state: Initial state.
            execution_state: Execution state queue.
            trace_current (list): Current trace.
            next_addr: Address of the next instruction following the current one.

        Returns:
            Returns the next instruction to execute in case there is one, otherwise returns None.
        """
        # TODO: Process execution intra states.

        ip = sequence.address
        next_ip = None

        while ip:
            # Fetch next instruction in the sequence.
            try:
                instr = sequence.fetch(ip)
            except ReilSequenceInvalidAddressError:
                # At this point, ip should be a native instruction address, therefore
                # the index should be zero.
                assert split_address(ip)[1] == 0x0
                next_ip = ip
                break

            try:
                target_addr = sequence.get_next_address(ip)
            except ReilSequenceInvalidAddressError:
                # We reached the end of the sequence. Execution continues on the next native instruction
                # (it's a REIL address).
                target_addr = next_addr

            next_ip = self.__process_instr(instr, avoid, target_addr,
                                           initial_state, execution_state,
                                           trace_current)

            # Update instruction pointer.
            try:
                ip = next_ip if next_ip else sequence.get_next_address(ip)
            except ReilSequenceInvalidAddressError:
                break

        return next_ip
Ejemplo n.º 16
0
    def __fa_process_sequence(self, sequence, avoid, initial_state, execution_state, trace_current, next_addr):
        """Process a REIL sequence.

        Args:
            sequence (ReilSequence): A REIL sequence to process.
            avoid (list): List of address to avoid.
            initial_state: Initial state.
            execution_state: Execution state queue.
            trace_current (list): Current trace.
            next_addr: Address of the next instruction following the current one.

        Returns:
            Returns the next instruction to execute in case there is one, otherwise returns None.
        """
        # TODO: Process execution intra states.

        ip = sequence.address
        next_ip = None

        while ip:
            # Fetch next instruction in the sequence.
            try:
                instr = sequence.fetch(ip)
            except ReilSequenceInvalidAddressError:
                # At this point, ip should be a native instruction address, therefore
                # the index should be zero.
                assert split_address(ip)[1] == 0x0
                next_ip = ip
                break

            try:
                target_addr = sequence.get_next_address(ip)
            except ReilSequenceInvalidAddressError:
                # We reached the end of the sequence. Execution continues on the next native instruction
                # (it's a REIL address).
                target_addr = next_addr

            next_ip = self.__process_instr(instr, avoid, target_addr, initial_state, execution_state, trace_current)

            # Update instruction pointer.
            try:
                ip = next_ip if next_ip else sequence.get_next_address(ip)
            except ReilSequenceInvalidAddressError:
                break

        return next_ip
Ejemplo n.º 17
0
    def __process_instr(self, instr, avoid, next_addr, initial_state,
                        execution_state, trace_current):
        """Process a REIL instruction.

        Args:
            instr (ReilInstruction): Instruction to process.
            avoid (list): List of addresses to avoid while executing the code.
            next_addr (int): Address of the following instruction.
            initial_state (State): Initial execution state.
            execution_state (Queue): Queue of execution states.
            trace_current (list): Current trace.

        Returns:
            int: Returns the next address to execute.
        """
        # Process branch (JCC oprnd0, empty, oprnd2).
        if instr.mnemonic == ReilMnemonic.JCC:
            not_taken_addr = next_addr
            address, index = split_address(instr.address)

            logger.debug("[+] Processing branch: {:#08x}:{:02x} : {:s}".format(
                address, index, instr))

            # Process conditional branch (oprnd0 is a REGISTER).
            if isinstance(instr.operands[0], ReilRegisterOperand):
                next_ip = self.__process_branch_cond(instr, avoid,
                                                     initial_state,
                                                     execution_state,
                                                     trace_current,
                                                     not_taken_addr)

            # Process unconditional branch (oprnd0 is an INTEGER).
            else:
                next_ip = self.__process_branch_uncond(instr, trace_current,
                                                       not_taken_addr)

        # Process the rest of the instructions.
        else:
            trace_current += [(instr, None)]

            self.__cpu.execute(instr)

            next_ip = next_addr

        return next_ip
Ejemplo n.º 18
0
    def __execute(self, asm_instr):
        # Process one assembler instruction. Translate it to REIL instruction and
        # process each one.
        instr_container = self.__translate(asm_instr)
        ip = to_reil_address(asm_instr.address)
        next_addr = None

        while ip:
            # Fetch instruction.
            try:
                reil_instr = instr_container.fetch(ip)
            except ReilContainerInvalidAddressError:
                next_addr, _ = split_address(ip)
                break

            if reil_instr.mnemonic == ReilMnemonic.UNKN:
                raise InstructionNotImplemented(asm_instr)

            # Execute instruction.
            next_ip = self.ir_emulator.single_step(reil_instr)

            # Update instruction pointer.
            ip = next_ip if next_ip else instr_container.get_next_address(ip)

        del instr_container

        # Execute post instruction handlers
        handler_fn_post, handler_param_post = self.__instr_handler_post
        handler_fn_post(self, asm_instr, handler_param_post)

        # delete temporal registers
        regs = self.ir_emulator.registers.keys()

        for r in regs:
            if r.startswith("t"):
                del self.ir_emulator.registers[r]

        return next_addr if next_addr else asm_instr.address + asm_instr.size
Ejemplo n.º 19
0
    def __process_instr(self, instr, avoid, next_addr, initial_state, execution_state, trace_current):
        """Process a REIL instruction.

        Args:
            instr (ReilInstruction): Instruction to process.
            avoid (list): List of addresses to avoid while executing the code.
            next_addr (int): Address of the following instruction.
            initial_state (State): Initial execution state.
            execution_state (Queue): Queue of execution states.
            trace_current (list): Current trace.

        Returns:
            int: Returns the next address to execute.
        """
        # Process branch (JCC oprnd0, empty, oprnd2).
        if instr.mnemonic == ReilMnemonic.JCC:
            not_taken_addr = next_addr
            address, index = split_address(instr.address)

            logger.debug("[+] Processing branch: {:#08x}:{:02x} : {}".format(address, index, instr))

            # Process conditional branch (oprnd0 is a REGISTER).
            if isinstance(instr.operands[0], ReilRegisterOperand):
                next_ip = self.__process_branch_cond(instr, avoid, initial_state, execution_state, trace_current, not_taken_addr)

            # Process unconditional branch (oprnd0 is an INTEGER).
            else:
                next_ip = self.__process_branch_uncond(instr, trace_current, not_taken_addr)

        # Process the rest of the instructions.
        else:
            trace_current += [(instr, None)]

            self.__cpu.execute(instr)

            next_ip = next_addr

        return next_ip
Ejemplo n.º 20
0
    def dump(self):
        for instr in self.__sequence:
            base_addr, index = split_address(instr.address)

            print("{:08x}:{:02x}\t{}".format(base_addr, index, instr))
Ejemplo n.º 21
0
    def dump(self):
        for instr in self.__sequence:
            base_addr, index = split_address(instr.address)

            print("{:08x}:{:02x}\t{}".format(base_addr, index, instr))
Ejemplo n.º 22
0
    def __fa_process_container(self, container, find, start, end, avoid, initial_state, execution_state, trace_current,
                               trace_final):
        """Process a REIL container.

        Args:
            avoid (list): List of addresses to avoid while executing the code.
            container (ReilContainer): REIL container to execute.
            end (int): End address.
            execution_state (Queue): Queue of execution states.
            find (int): Address to find.
            initial_state (State): Initial state.
            start (int): Start address.
            trace_current:
            trace_final:
        """
        ip = start

        while ip:
            # NOTE *ip* and *next_addr* variables can be, independently, either intra
            # or inter addresses.

            # Fetch next instruction.
            try:
                instr = container.fetch(ip)
            except ReilContainerInvalidAddressError:
                logger.debug("Exception @ {:#08x}".format(ip))

                raise ReilContainerInvalidAddressError

            # Compute the address of the following instruction to the fetched one.
            try:
                next_addr = container.get_next_address(ip)
            except Exception:
                logger.debug("Exception @ {:#08x}".format(ip))

                # TODO Should this be considered an error?

                raise ReilContainerInvalidAddressError

            # Process the instruction.
            next_ip = self.__process_instr(instr, avoid, next_addr, initial_state, execution_state, trace_current)

            # # ====================================================================================================== #
            # # NOTE This is an attempt to separate intra and inter instruction
            # # addresses processing. Here, *ip* and *next_addr* are always inter
            # # instruction addresses.
            #
            # assert split_address(ip)[1] == 0x0
            #
            # # Compute the address of the following instruction to the fetched one.
            # try:
            #     seq = container.fetch_sequence(ip)
            # except ReilContainerInvalidAddressError:
            #     logger.debug("Exception @ {:#08x}".format(ip))
            #
            #     raise ReilContainerInvalidAddressError
            #
            # # Fetch next instruction address.
            # try:
            #     next_addr = container.get_next_address(ip + len(seq))
            # except Exception:
            #     logger.debug("Exception @ {:#08x}".format(ip))
            #
            #     # TODO Should this be considered an error?
            #
            #     raise ReilContainerInvalidAddressError
            #
            # next_ip = self.__process_sequence(seq, avoid, initial_state, execution_state, trace_current, next_addr)
            #
            # if next_ip:
            #     assert split_address(next_ip)[1] == 0x0
            #
            # # ====================================================================================================== #

            # Check termination conditions.
            if find and next_ip and next_ip == find:
                logger.debug("[+] Find address found!")

                trace_final.append(list(trace_current))

                next_ip = None

            if end and next_ip and next_ip == end:
                logger.debug("[+] End address found!")

                next_ip = None

            # Update instruction pointer.
            ip = next_ip if next_ip else None

            while not ip:
                if not execution_state.empty():
                    # Pop next execution state.
                    ip, trace_current, registers, memory = execution_state.get()

                    if split_address(ip)[1] == 0x0:
                        logger.debug("[+] Popping execution state @ {:#x} (INTER)".format(ip))
                    else:
                        logger.debug("[+] Popping execution state @ {:#x} (INTRA)".format(ip))

                    # Setup cpu and memory.
                    self.__cpu.registers = registers
                    self.__cpu.memory = memory

                    logger.debug("[+] Next address: {:#08x}:{:02x}".format(ip >> 8, ip & 0xff))
                else:
                    logger.debug("[+] No more paths to explore! Exiting...")

                    break

                # Check termination conditions (AGAIN...).
                if find and ip == find:
                    logger.debug("[+] Find address found!")

                    trace_final.append(list(trace_current))

                    ip = None

                if end and ip == end:
                    logger.debug("[+] End address found!")

                    ip = None
Ejemplo n.º 23
0
    def __fs_process_container(self, container, final_state, start, end, avoid, initial_state, execution_state,
                               trace_current, trace_final):
        ip = start

        while ip:
            # Fetch next instruction.
            try:
                instr = container.fetch(ip)
            except ReilContainerInvalidAddressError:
                logger.debug("Exception @ {:#08x}".format(ip))

                raise ReilContainerInvalidAddressError

            # Compute the address of the following instruction to the fetched one.
            try:
                next_addr = container.get_next_address(ip)
            except Exception:
                logger.debug("Exception @ {:#08x}".format(ip))

                # TODO Should this be considered an error?

                raise ReilContainerInvalidAddressError

            # Process instruction
            next_ip = self.__process_instr(instr, avoid, next_addr, initial_state, execution_state, trace_current)

            # Check is final state holds.
            if instr.mnemonic == ReilMnemonic.JCC and isinstance(instr.operands[0], ReilRegisterOperand):
                # TODO Check only when it is necessary.
                self.__reset_solver()
                self.__set_initial_state(initial_state)
                self.__add_trace_to_solver(trace_current)
                self.__set_final_state(final_state)

                is_sat = self.__code_analyzer.check()

                if is_sat == "sat":
                    logger.debug("[+] Final state found!")

                    trace_final.append(list(trace_current))

                    next_ip = None

            # Check termination conditions.
            if end and next_ip and next_ip == end:
                logger.debug("[+] End address found!")

                next_ip = None

            # Update instruction pointer.
            ip = next_ip if next_ip else None

            while not ip:
                if not execution_state.empty():
                    # Pop next execution state.
                    ip, trace_current, registers, memory = execution_state.get()

                    if split_address(ip)[1] == 0x0:
                        logger.debug("[+] Popping execution state @ {:#x} (INTER)".format(ip))
                    else:
                        logger.debug("[+] Popping execution state @ {:#x} (INTRA)".format(ip))

                    # Setup cpu and memory.
                    self.__cpu.registers = registers
                    self.__cpu.memory = memory

                    logger.debug("[+] Next address: {:#08x}:{:02x}".format(ip >> 8, ip & 0xff))
                else:
                    logger.debug("[+] No more paths to explore! Exiting...")
                    break

                # Check termination conditions (AGAIN...).
                if end and ip == end:
                    logger.debug("[+] End address found!")

                    ip = None