Exemplo n.º 1
0
    def __cs_translate_operand(self, cs_op, cs_insn):
        if cs_op.type == ARM_OP_REG:
            reg = self.__cs_reg_idx_to_arm_op_reg(cs_op.value.reg, cs_insn)

            if cs_op.shift.type > 0:
                oprnd = self.__cs_shift_to_arm_op(cs_op, cs_insn, reg)
            else:
                oprnd = reg
        elif cs_op.type == ARM_OP_IMM:
            oprnd = ArmImmediateOperand(cs_op.value.imm,
                                        self._arch_info.operand_size)
        elif cs_op.type == ARM_OP_MEM:
            reg_base = self.__cs_reg_idx_to_arm_op_reg(cs_op.mem.base, cs_insn)

            # TODO: memory index type
            index_type = ARM_MEMORY_INDEX_OFFSET

            if cs_op.mem.index > 0:
                if cs_op.mem.disp > 0:
                    raise Exception(
                        "ARM_OP_MEM: Both index and disp > 0, only one can be."
                    )

                displacement = self.__cs_reg_idx_to_arm_op_reg(
                    cs_op.mem.index, cs_insn)

                # NOTE: In the case of a memory operand, in the second
                # position (slot [1]), the information regarding whether
                # or not the displacement of the operand has a shifted
                # register is encoded in the first operand (slot [0]),
                # that doesn't have a direct relation with the other.

                # TODO: Check if this has to be reported to CS.
                if cs_insn.operands[0].shift.type > 0:
                    # There's a shift operation, the displacement extracted
                    # earlier was just the base register of the shifted
                    # register that is generating the disaplacement.
                    displacement = self.__cs_shift_to_arm_op(
                        cs_insn.operands[0], cs_insn, displacement)
            else:
                displacement = ArmImmediateOperand(
                    cs_op.mem.disp, self._arch_info.operand_size)

            disp_minus = True if cs_op.mem.index == -1 else False

            oprnd = ArmMemoryOperand(reg_base, index_type, displacement,
                                     disp_minus, self._arch_info.operand_size)
        else:
            oprnd = None

            error_msg = "Instruction: " + cs_insn.mnemonic + " " + cs_insn.op_str + ". Unkown operand type: " + str(
                cs_op.type)

            logger.error(error_msg)

            raise CapstoneOperandNotSupported(error_msg)

        return oprnd
Exemplo n.º 2
0
def process_shifted_register(tokens):

    base = process_register(tokens["base"])
    sh_type = tokens["type"]
    amount = tokens.get("amount", None)

    if amount:
        if "imm" in amount:
            amount = ArmImmediateOperand("".join(amount["imm"]),
                                         arch_info.operand_size)
        elif "reg" in amount:
            amount = process_register(amount["reg"])
        else:
            raise Exception("Unknown amount type.")

    return ArmShiftedRegisterOperand(base, sh_type, amount, base.size)
Exemplo n.º 3
0
    def __cs_shift_to_arm_op(self, cs_op, cs_insn, arm_base):
        if cs_op.shift.type == 0:
            raise Exception("Invalid shift type.")

        cs_shift_mapper = {
            ARM_SFT_ASR: "asr",
            ARM_SFT_LSL: "lsl",
            ARM_SFT_LSR: "lsr",
            ARM_SFT_ROR: "ror",
            ARM_SFT_RRX: "rrx",
            ARM_SFT_ASR_REG: "asr",
            ARM_SFT_LSL_REG: "lsl",
            ARM_SFT_LSR_REG: "lsr",
            ARM_SFT_ROR_REG: "ror",
            ARM_SFT_RRX_REG: "rrx",
        }

        # The base register (arm_base) is not included in the shift
        # struct in Capstone, so it's provided separately.
        sh_type = cs_shift_mapper[cs_op.shift.type]

        if cs_op.shift.type <= ARM_SFT_RRX:
            amount = ArmImmediateOperand(cs_op.shift.value,
                                         self._arch_info.operand_size)

            # TODO: check if this is a valid case.
            if cs_op.shift.value == 0:
                raise Exception("Shift value is zero.")
        elif cs_op.shift.type <= ARM_SFT_RRX_REG:
            amount = self.__cs_reg_idx_to_arm_op_reg(cs_op.shift.value,
                                                     cs_insn)
        else:
            raise Exception("Unknown shift type.")

        return ArmShiftedRegisterOperand(arm_base, sh_type, amount,
                                         arm_base.size)
Exemplo n.º 4
0
def parse_operand(string, location, tokens):
    """Parse an ARM instruction operand.
    """

    if "immediate_operand" in tokens:
        size = arch_info.operand_size
        oprnd = ArmImmediateOperand("".join(tokens["immediate_operand"]), size)

    if "register_operand" in tokens:
        oprnd = process_register(tokens["register_operand"])

        # TODO: Figure out where to really store this flag, instead of in the register class
        if "wb" in tokens["register_operand"]:
            oprnd.wb = True

    if "memory_operand" in tokens:
        mem_oprnd = tokens["memory_operand"]

        if "offset" in mem_oprnd:
            index_type = ARM_MEMORY_INDEX_OFFSET
            mem_oprnd = mem_oprnd["offset"]
        elif "pre" in mem_oprnd:
            index_type = ARM_MEMORY_INDEX_PRE
            mem_oprnd = mem_oprnd["pre"]
        elif "post" in mem_oprnd:
            index_type = ARM_MEMORY_INDEX_POST
            mem_oprnd = mem_oprnd["post"]
        else:
            raise Exception("Unknown index type.")

        reg_base = process_register(mem_oprnd["base"])
        disp = mem_oprnd.get("disp", None)
        disp_minus = True if mem_oprnd.get("minus") else False

        if disp:
            if "shift" in disp:
                displ_imm = process_shifted_register(disp["shift"])
            elif "reg" in disp:
                displ_imm = process_register(disp["reg"])
            elif "imm" in disp:
                displ_imm = ArmImmediateOperand("".join(disp["imm"]),
                                                arch_info.operand_size)
            else:
                raise Exception("Unknown displacement type.")
        else:
            displ_imm = None

        size = arch_info.operand_size
        # TODO: Add sizes for LDR/STR variations (half word, byte, double word)
        oprnd = ArmMemoryOperand(reg_base, index_type, displ_imm, disp_minus,
                                 size)

    if "shifted_register" in tokens:
        oprnd = process_shifted_register(tokens["shifted_register"])

    if "register_list_operand" in tokens:
        parsed_reg_list = tokens["register_list_operand"]
        reg_list = []
        for reg_range in parsed_reg_list:
            start_reg = process_register(reg_range[0])
            if len(reg_range) > 1:
                end_reg = process_register(reg_range[1])
                reg_list.append([start_reg, end_reg])
            else:
                reg_list.append([start_reg])

        oprnd = ArmRegisterListOperand(reg_list, reg_list[0][0].size)

    return oprnd
Exemplo n.º 5
0
def parse_operand(string, location, tokens):
    """Parse an ARM instruction operand.
    """

    if "immediate_operand" in tokens:
        size = arch_info.operand_size
        oprnd = ArmImmediateOperand("".join(tokens["immediate_operand"]), size)

    if "register_operand" in tokens:
        oprnd =  process_register(tokens["register_operand"])

        # TODO: Figure out where to really store this flag, instead of in the register class
        if "wb" in tokens["register_operand"]:
            oprnd.wb = True


    if "memory_operand" in tokens:
        mem_oprnd = tokens["memory_operand"]

        if "offset" in mem_oprnd:
            index_type = ARM_MEMORY_INDEX_OFFSET
            mem_oprnd = mem_oprnd["offset"]
        elif "pre" in mem_oprnd:
            index_type = ARM_MEMORY_INDEX_PRE
            mem_oprnd = mem_oprnd["pre"]
        elif "post" in mem_oprnd:
            index_type = ARM_MEMORY_INDEX_POST
            mem_oprnd = mem_oprnd["post"]
        else:
            raise Exception("Unknown index type.")

        reg_base = process_register(mem_oprnd["base"])
        disp = mem_oprnd.get("disp", None)
        disp_minus = True if mem_oprnd.get("minus") else False

        if disp:
            if "shift" in disp:
                displacement = process_shifted_register(disp["shift"])
            elif "reg" in disp:
                displacement = process_register(disp["reg"])
            elif "imm" in disp:
                displacement = ArmImmediateOperand("".join(disp["imm"]), arch_info.operand_size)
            else:
                raise Exception("Unknown displacement type.")
        else:
            displacement = None

        size = arch_info.operand_size
        # TODO: Add sizes for LDR/STR variations (half word, byte, double word)
        oprnd = ArmMemoryOperand(reg_base, index_type, displacement, disp_minus, size)

    if "shifted_register" in tokens:
        oprnd =  process_shifted_register(tokens["shifted_register"])

    if "register_list_operand" in tokens:
        parsed_reg_list = tokens["register_list_operand"]
        reg_list = []
        for reg_range in parsed_reg_list:
            start_reg = process_register(reg_range[0])
            if len(reg_range) > 1:
                end_reg = process_register(reg_range[1])
                reg_list.append([start_reg, end_reg])
            else:
                reg_list.append([start_reg])

        oprnd = ArmRegisterListOperand(reg_list, reg_list[0][0].size)

    return oprnd