Ejemplo n.º 1
0
    def _translate_cbnz(self, tb, instruction):
        oprnd0 = tb.read(instruction.operands[0])
        arm_operand = instruction.operands[1]

        if isinstance(arm_operand, ArmImmediateOperand):
            target = ReilImmediateOperand(arm_operand.immediate << 8,
                                          self._pc.size + 8)
        elif isinstance(arm_operand, ArmRegisterOperand):
            target = ReilRegisterOperand(arm_operand.name, arm_operand.size)
            target = tb._and_regs(
                target, ReilImmediateOperand(0xFFFFFFFE, target.size))

            tmp0 = tb.temporal(target.size + 8)
            tmp1 = tb.temporal(target.size + 8)

            tb.add(self._builder.gen_str(target, tmp0))
            tb.add(
                self._builder.gen_bsh(tmp0,
                                      ReilImmediateOperand(8, target.size + 8),
                                      tmp1))

            target = tmp1
        else:
            raise Exception()

        neg_oprnd = tb._negate_reg(oprnd0)

        tb._jump_if_zero(neg_oprnd, target)
Ejemplo n.º 2
0
    def _translate_branch(self, tb, instruction, link):

        arm_operand = instruction.operands[0]

        if isinstance(arm_operand, ArmImmediateOperand):
            target = ReilImmediateOperand(arm_operand.immediate << 8,
                                          self._pc.size + 8)
        elif isinstance(arm_operand, ArmRegisterOperand):
            target = ReilRegisterOperand(arm_operand.name, arm_operand.size)
            target = tb._and_regs(
                target, ReilImmediateOperand(0xFFFFFFFE, target.size))

            tmp0 = tb.temporal(target.size + 8)
            tmp1 = tb.temporal(target.size + 8)

            tb.add(self._builder.gen_str(target, tmp0))
            tb.add(
                self._builder.gen_bsh(tmp0,
                                      ReilImmediateOperand(8, target.size + 8),
                                      tmp1))

            target = tmp1
        else:
            raise NotImplementedError(
                "Instruction Not Implemented: Unknown operand for branch operation."
            )

        if (link):
            tb.add(
                self._builder.gen_str(
                    ReilImmediateOperand(
                        instruction.address + instruction.size, self._pc.size),
                    self._lr))

        tb._jump_to(target)
Ejemplo n.º 3
0
    def test_arithmetic_store_add_2(self):
        # testing : dst_reg <- dst_reg + mem[src_reg + offset]
        binary = "\x22\x30\x94\xe5"  # 0x00 : (4)  ldr    r3, [r4, 0x22]
        binary += "\x03\x30\x80\xe0"  # 0x00 : (4)  add    r3, r0, r3
        binary += "\x22\x30\x84\xe5"  # 0x00 : (4)  str    r3, [r4, 0x22]
        binary += "\x1e\xff\x2f\xe1"  # 0x04 : (4)  bx     lr

        g_candidates, g_classified = self._find_and_classify_gadgets(binary)

        self.assertEquals(len(g_candidates), 1)
        self.assertEquals(len(g_classified), 2)

        self.assertEquals(g_classified[1].type, GadgetType.ArithmeticStore)
        self.assertEquals(g_classified[1].sources, [
            ReilRegisterOperand("r4", 32),
            ReilImmediateOperand(0x22, 32),
            ReilRegisterOperand("r0", 32)
        ])
        self.assertEquals(
            g_classified[1].destination,
            [ReilRegisterOperand("r4", 32),
             ReilImmediateOperand(0x22, 32)])
        self.assertEquals(g_classified[1].operation, "+")

        self.assertEquals(len(g_classified[1].modified_registers), 1)

        self.assertFalse(
            ReilRegisterOperand("r4", 32) in
            g_classified[1].modified_registers)
        self.assertTrue(
            ReilRegisterOperand("r3", 32) in
            g_classified[1].modified_registers)

        self.assertTrue(self._g_verifier.verify(g_classified[1]))
Ejemplo n.º 4
0
    def _translate_branch(self, tb, instruction, link):
        if instruction.condition_code == ARM_COND_CODE_AL:
            cond = tb.immediate(1, 1)
        else:
            eval_cc_fn = {
                ARM_COND_CODE_EQ: self._evaluate_eq,
                ARM_COND_CODE_NE: self._evaluate_ne,
                ARM_COND_CODE_CS: self._evaluate_cs,
                ARM_COND_CODE_HS: self._evaluate_cs,
                ARM_COND_CODE_CC: self._evaluate_cc,
                ARM_COND_CODE_LO: self._evaluate_cc,
                ARM_COND_CODE_MI: self._evaluate_mi,
                ARM_COND_CODE_PL: self._evaluate_pl,
                ARM_COND_CODE_VS: self._evaluate_vs,
                ARM_COND_CODE_VC: self._evaluate_vc,
                ARM_COND_CODE_HI: self._evaluate_hi,
                ARM_COND_CODE_LS: self._evaluate_ls,
                ARM_COND_CODE_GE: self._evaluate_ge,
                ARM_COND_CODE_LT: self._evaluate_lt,
                ARM_COND_CODE_GT: self._evaluate_gt,
                ARM_COND_CODE_LE: self._evaluate_le,
            }

            cond = eval_cc_fn[instruction.condition_code](tb)

        arm_operand = instruction.operands[0]

        if isinstance(arm_operand, ArmImmediateOperand):
            target = ReilImmediateOperand(arm_operand.immediate << 8,
                                          self._pc.size + 8)
        elif isinstance(arm_operand, ArmRegisterOperand):
            target = ReilRegisterOperand(arm_operand.name, arm_operand.size)
            target = tb._and_regs(
                target, ReilImmediateOperand(0xFFFFFFFE, target.size))

            tmp0 = tb.temporal(target.size + 8)
            tmp1 = tb.temporal(target.size + 8)

            tb.add(self._builder.gen_str(target, tmp0))
            tb.add(
                self._builder.gen_bsh(tmp0,
                                      ReilImmediateOperand(8, target.size + 8),
                                      tmp1))

            target = tmp1
        else:
            raise NotImplementedError(
                "Instruction Not Implemented: Unknown operand for branch operation."
            )

        if link:
            tb.add(
                self._builder.gen_str(
                    ReilImmediateOperand(
                        instruction.address + instruction.size, self._pc.size),
                    self._lr))

        tb.add(self._builder.gen_jcc(cond, target))

        return
Ejemplo n.º 5
0
    def _classify_load_memory(self, regs_init, regs_fini, mem_fini, written_regs, read_regs):
        """Classify load-memory gadgets.
        """
        matches = []

        regs_init_inv = self._invert_dictionary(regs_init)

        # Check for "dst_reg <- mem[src_reg + offset]" pattern.
        for dst_reg, dst_val in regs_fini.items():
            # Make sure the *dst* register was written.
            if dst_reg not in written_regs:
                continue

            dst_size = self._arch_regs_size[dst_reg]

            # Look for memory addresses that contain *dst_val*.
            for src_addr in mem_fini.read_inverse(dst_val, dst_size // 8):

                # Look for registers whose values are used as memory
                # addresses.
                for src_reg, src_val in regs_init.items():
                    # Make sure the *src* register was read.
                    if src_reg not in read_regs:
                        continue

                    # Check restrictions.
                    if self._arch_regs_size[src_reg] != self._address_size:
                        continue

                    offset = (src_addr - src_val) & (2**self._address_size - 1)

                    src_reg_ir = ReilRegisterOperand(src_reg, self._arch_regs_size[src_reg])
                    src_off_ir = ReilImmediateOperand(offset, self._arch_regs_size[src_reg])
                    dst_reg_ir = ReilRegisterOperand(dst_reg, self._arch_regs_size[dst_reg])

                    matches.append({
                        "src": [src_reg_ir, src_off_ir],
                        "dst": [dst_reg_ir]
                    })

        # Check for "dst_reg <- mem[offset]" pattern.
        for dst_reg, dst_val in regs_fini.items():
            # Make sure the *dst* register was written.
            if dst_reg not in written_regs:
                continue

            dst_size = self._arch_regs_size[dst_reg]

            for src_addr in mem_fini.read_inverse(dst_val, dst_size // 8):
                src_reg_ir = ReilEmptyOperand()
                src_off_ir = ReilImmediateOperand(src_addr, self._address_size)
                dst_reg_ir = ReilRegisterOperand(dst_reg, self._arch_regs_size[dst_reg])

                matches.append({
                    "src": [src_reg_ir, src_off_ir],
                    "dst": [dst_reg_ir]
                })

        return matches
Ejemplo n.º 6
0
    def _classify_store_memory(self, regs_init, regs_fini, mem_fini, written_regs, read_regs):
        """Classify store-memory gadgets.
        """
        matches = []

        regs_init_inv = self._invert_dictionary(regs_init)

        # Check for "mem[dst_reg + offset] <- src_reg" pattern.
        for src_reg, src_val in regs_init.items():
            # Make sure the *src* register was read.
            if src_reg not in read_regs:
                continue

            src_size = self._arch_regs_size[src_reg]

            for addr in mem_fini.read_inverse(src_val, src_size // 8):
                for dst_reg, dst_val in regs_init.items():
                    # Make sure the *dst* register was written.
                    if dst_reg not in read_regs:
                        continue

                    # Check restrictions.
                    if self._arch_regs_size[dst_reg] != self._address_size:
                        continue

                    offset = (addr - dst_val) & (2**self._address_size - 1)

                    src_reg_ir = ReilRegisterOperand(src_reg, self._arch_regs_size[src_reg])
                    dst_reg_ir = ReilRegisterOperand(dst_reg, self._arch_regs_size[dst_reg])
                    dst_off_ir = ReilImmediateOperand(offset, self._arch_regs_size[dst_reg])

                    matches.append({
                        "src": [src_reg_ir],
                        "dst": [dst_reg_ir, dst_off_ir]
                    })

        # Check for "mem[offset] <- src_reg" pattern.
        for src_reg, src_val in regs_init.items():
            # Make sure the *src* register was read.
            if src_reg not in read_regs:
                continue

            src_size = self._arch_regs_size[src_reg]

            for addr in mem_fini.read_inverse(src_val, src_size // 8):
                offset = addr & (2**self._address_size - 1)

                src_reg_ir = ReilRegisterOperand(src_reg, self._arch_regs_size[src_reg])
                dst_reg_ir = ReilEmptyOperand()
                dst_off_ir = ReilImmediateOperand(offset, self._address_size)

                matches.append({
                    "src": [src_reg_ir],
                    "dst": [dst_reg_ir, dst_off_ir]
                })

        return matches
Ejemplo n.º 7
0
def _translate_address(self, tb, oprnd):
    addr_oprnd_size = oprnd.size + 8

    if isinstance(oprnd, ReilRegisterOperand):
        oprnd_tmp = tb.temporal(addr_oprnd_size)
        addr_oprnd = tb.temporal(addr_oprnd_size)
        imm = ReilImmediateOperand(8, addr_oprnd_size)

        tb.add(self._builder.gen_str(oprnd, oprnd_tmp))
        tb.add(self._builder.gen_bsh(oprnd_tmp, imm, addr_oprnd))
    elif isinstance(oprnd, ReilImmediateOperand):
        addr_oprnd = ReilImmediateOperand(oprnd.immediate << 8, addr_oprnd_size)

    return addr_oprnd
Ejemplo n.º 8
0
    def read(self, arm_operand):

        if isinstance(arm_operand, ArmImmediateOperand):

            reil_operand = ReilImmediateOperand(arm_operand.immediate,
                                                arm_operand.size)

        elif isinstance(arm_operand, ArmRegisterOperand):

            reil_operand = ReilRegisterOperand(arm_operand.name,
                                               arm_operand.size)

        elif isinstance(arm_operand, ArmShiftedRegisterOperand):

            reil_operand = self._compute_shifted_register(arm_operand)

        elif isinstance(arm_operand, ArmMemoryOperand):

            addr = self._compute_memory_address(arm_operand)

            reil_operand = self.temporal(arm_operand.size)

            self.add(self._builder.gen_ldm(addr, reil_operand))

        elif isinstance(arm_operand, ArmRegisterListOperand):

            reil_operand = self._compute_register_list(arm_operand)

        else:
            raise NotImplementedError(
                "Instruction Not Implemented: Unknown operand for read operation."
            )

        return reil_operand
Ejemplo n.º 9
0
    def __init__(self,
                 architecture_mode=ARCH_ARM_MODE_THUMB,
                 translation_mode=FULL_TRANSLATION):
        super(ArmTranslator, self).__init__()

        # Set *Architecture Mode*. The translation of each instruction
        # into the REIL language is based on this.
        self._arch_mode = architecture_mode

        # An instance of *ArchitectureInformation*.
        self._arch_info = ArmArchitectureInformation(architecture_mode)

        # Set *Translation Mode*.
        self._translation_mode = translation_mode

        # An instance of a *VariableNamer*. This is used so all the
        # temporary REIL registers are unique.
        self._ir_name_generator = VariableNamer("t", separator="")

        self._builder = ReilInstructionBuilder()

        self._flags = {
            "nf": ReilRegisterOperand("nf", 1),
            "zf": ReilRegisterOperand("zf", 1),
            "cf": ReilRegisterOperand("cf", 1),
            "vf": ReilRegisterOperand("vf", 1),
        }

        if self._arch_mode in [ARCH_ARM_MODE_ARM, ARCH_ARM_MODE_THUMB]:
            self._sp = ReilRegisterOperand("r13", 32)  # TODO: Implement alias
            self._pc = ReilRegisterOperand("r15", 32)
            self._lr = ReilRegisterOperand("r14", 32)

            self._ws = ReilImmediateOperand(4, 32)  # word size
Ejemplo n.º 10
0
    def _evaluate_condition_code(self, tb, instruction):
        if instruction.condition_code == ARM_COND_CODE_AL:
            return

        eval_cc_fn = {
            ARM_COND_CODE_EQ: self._evaluate_eq,
            ARM_COND_CODE_NE: self._evaluate_ne,
            ARM_COND_CODE_CS: self._evaluate_cs,
            ARM_COND_CODE_HS: self._evaluate_cs,
            ARM_COND_CODE_CC: self._evaluate_cc,
            ARM_COND_CODE_LO: self._evaluate_cc,
            ARM_COND_CODE_MI: self._evaluate_mi,
            ARM_COND_CODE_PL: self._evaluate_pl,
            ARM_COND_CODE_VS: self._evaluate_vs,
            ARM_COND_CODE_VC: self._evaluate_vc,
            ARM_COND_CODE_HI: self._evaluate_hi,
            ARM_COND_CODE_LS: self._evaluate_ls,
            ARM_COND_CODE_GE: self._evaluate_ge,
            ARM_COND_CODE_LT: self._evaluate_lt,
            ARM_COND_CODE_GT: self._evaluate_gt,
            ARM_COND_CODE_LE: self._evaluate_le,
        }

        neg_cond = tb._negate_reg(eval_cc_fn[instruction.condition_code](tb))

        end_addr = ReilImmediateOperand(
            (instruction.address + instruction.size) << 8,
            self._arch_info.address_size + 8)

        tb.add(self._builder.gen_jcc(neg_cond, end_addr))

        return
Ejemplo n.º 11
0
def _update_strings_dst(self, tb, dst, size, instruction):
    # Create labels.
    forward_lbl = ReilLabel('forward')
    backward_lbl = ReilLabel('backward')

    end_addr = ReilImmediateOperand((instruction.address + instruction.size) << 8, self._arch_info.address_size + 8)

    # Define immediate registers.
    imm_one = tb.immediate(1, 1)

    # Define temporary registers.
    df_zero = tb.temporal(1)
    imm_tmp = tb.immediate(size // 8, dst.size)
    dst_tmp = tb.temporal(dst.size)

    # Update destination pointer.
    tb.add(self._builder.gen_bisz(self._flags.df, df_zero))
    tb.add(self._builder.gen_jcc(df_zero, forward_lbl))

    # Update backwards.
    tb.add(backward_lbl)
    tb.add(self._builder.gen_sub(dst, imm_tmp, dst_tmp))
    tb.add(self._builder.gen_str(dst_tmp, dst))

    # Jump to next instruction.
    tb.add(self._builder.gen_jcc(imm_one, end_addr))

    # Update forwards.
    tb.add(forward_lbl)
    tb.add(self._builder.gen_add(dst, imm_tmp, dst_tmp))
    tb.add(self._builder.gen_str(dst_tmp, dst))
Ejemplo n.º 12
0
def _rep_prefix_end(self, tb, instruction, counter, loop_start_lbl):
    # Define immediate registers
    imm_one = tb.immediate(1, 1)
    counter_imm_one = tb.immediate(1, counter.size)
    end_addr = ReilImmediateOperand((instruction.address + instruction.size) << 8, self._arch_info.address_size + 8)

    # Define temporary registers.
    counter_tmp = tb.temporal(counter.size)
    counter_zero = tb.temporal(1)
    zf_zero = tb.temporal(1)

    # Termination Condition 1: RCX or (E)CX = 0.
    tb.add(self._builder.gen_sub(counter, counter_imm_one, counter_tmp))
    tb.add(self._builder.gen_str(counter_tmp, counter))
    tb.add(self._builder.gen_bisz(counter, counter_zero))
    tb.add(self._builder.gen_jcc(counter_zero, end_addr))

    prefix = instruction.prefix

    if prefix in ['rep']:
        # Termination Condition 2: None.
        pass
    elif prefix in ['repz', 'repe']:
        # Termination Condition 2: ZF = 0.
        tb.add(self._builder.gen_xor(self._flags.zf, imm_one, zf_zero))
        tb.add(self._builder.gen_jcc(zf_zero, end_addr))
    elif prefix in ['repnz', 'repne']:
        # Termination Condition 2: ZF = 1.
        tb.add(self._builder.gen_str(self._flags.zf, zf_zero))
        tb.add(self._builder.gen_jcc(zf_zero, end_addr))
    else:
        raise Exception('Invalid prefix: %s' % prefix)

    tb.add(self._builder.gen_jcc(imm_one, loop_start_lbl))
Ejemplo n.º 13
0
    def __init__(self, architecture_mode=ARCH_ARM_MODE_THUMB):
        super(ArmTranslator, self).__init__()

        # Set *Architecture Mode*. The translation of each instruction
        # into the REIL language is based on this.
        self._arch_mode = architecture_mode

        # An instance of *ArchitectureInformation*.
        self._arch_info = ArmArchitectureInformation(architecture_mode)

        self._builder = ReilBuilder()

        self._flags = {
            "nf": ReilRegisterOperand("nf", 1),
            "zf": ReilRegisterOperand("zf", 1),
            "cf": ReilRegisterOperand("cf", 1),
            "vf": ReilRegisterOperand("vf", 1),
        }

        if self._arch_mode in [ARCH_ARM_MODE_ARM, ARCH_ARM_MODE_THUMB]:
            self._sp = ReilRegisterOperand("r13", 32)  # TODO: Implement alias
            self._pc = ReilRegisterOperand("r15", 32)
            self._lr = ReilRegisterOperand("r14", 32)

            self._ws = ReilImmediateOperand(4, 32)  # word size
Ejemplo n.º 14
0
    def __resolve_loops(self, address, instrs):
        # Collect labels.
        idx_by_labels = {}
        instrs_no_labels = []
        curr = 0

        for i in instrs:
            if isinstance(i, ReilLabel):
                idx_by_labels[i.name] = curr
            else:
                instrs_no_labels.append(i)
                curr += 1

        instrs[:] = instrs_no_labels

        # Resolve instruction addresses and JCC targets.
        for index, instr in enumerate(instrs):
            instr.address = to_reil_address(address, index)

            if instr.mnemonic == ReilMnemonic.JCC:
                target = instr.operands[2]

                if isinstance(target, ReilLabel):
                    addr = to_reil_address(address, idx_by_labels[target.name])
                    size = self._arch_info.address_size + 8

                    instr.operands[2] = ReilImmediateOperand(addr, size)

        return instrs
Ejemplo n.º 15
0
    def _translate_ldrd(self, tb, instruction):

        if len(instruction.operands
               ) > 2:  # Rd2 has been specified (UAL syntax)
            addr_reg = tb._compute_memory_address(instruction.operands[2])
        else:
            addr_reg = tb._compute_memory_address(instruction.operands[1])

        reil_operand = ReilRegisterOperand(instruction.operands[0].name,
                                           instruction.operands[0].size)

        tb.add(tb._builder.gen_ldm(addr_reg, reil_operand))

        addr_reg = tb._add_to_reg(addr_reg,
                                  ReilImmediateOperand(4, reil_operand.size))

        if len(instruction.operands
               ) > 2:  # Rd2 has been specified (UAL syntax)
            reil_operand = ReilRegisterOperand(instruction.operands[1].name,
                                               instruction.operands[0].size)
        else:
            # TODO: Assuming the register is written in its number format
            # (no alias like lr or pc).
            reil_operand = ReilRegisterOperand(
                'r' + str(int(reil_operand.name[1:]) + 1), reil_operand.size)

        tb.add(tb._builder.gen_ldm(addr_reg, reil_operand))
Ejemplo n.º 16
0
    def write(self, tb, x86_operand, value):
        if isinstance(x86_operand, X86RegisterOperand):
            reil_operand = ReilRegisterOperand(x86_operand.name,
                                               x86_operand.size)

            if self._arch_info.architecture_mode == ARCH_X86_MODE_64 and x86_operand.size == 32:
                if x86_operand.name in self._regs_mapper:
                    base_reg, offset = self._regs_mapper[x86_operand.name]

                    reil_operand_base = ReilRegisterOperand(
                        base_reg, self._regs_size[base_reg])
                    reil_immediate = ReilImmediateOperand(
                        0x0, self._regs_size[base_reg])

                    tb.add(
                        tb._builder.gen_str(reil_immediate, reil_operand_base))

            tb.add(tb._builder.gen_str(value, reil_operand))
        elif isinstance(x86_operand, X86MemoryOperand):
            addr = self.resolve_memory_access(tb, x86_operand)

            if value.size != x86_operand.size:
                tmp = tb.temporal(x86_operand.size)

                tb.add(tb._builder.gen_str(value, tmp))
                tb.add(tb._builder.gen_stm(tmp, addr))
            else:
                tb.add(tb._builder.gen_stm(value, addr))
        else:
            raise Exception('Invalid operand type')
Ejemplo n.º 17
0
def _rep_prefix_begin(self, tb, instruction):
    # Define counter register.
    if self._arch_info.address_size == 16:
        counter = ReilRegisterOperand("cx", 16)
    elif self._arch_info.address_size == 32:
        counter = ReilRegisterOperand("ecx", 32)
    elif self._arch_info.address_size == 64:
        counter = ReilRegisterOperand("rcx", 64)
    else:
        raise Exception("Invalid address size: %d", self._arch_info.address_size)

    # Create labels.
    loop_start_lbl = Label('loop_start')

    # Define immediate registers.
    end_addr = ReilImmediateOperand((instruction.address + instruction.size) << 8, self._arch_info.address_size + 8)

    # Define temporary registers.
    counter_zero = tb.temporal(1)

    tb.add(loop_start_lbl)

    tb.add(self._builder.gen_bisz(counter, counter_zero))
    tb.add(self._builder.gen_jcc(counter_zero, end_addr))

    return counter, loop_start_lbl
Ejemplo n.º 18
0
    def __init__(self, architecture_mode):
        super(X86Translator, self).__init__()

        # Set *Architecture Mode*. The translation of each instruction
        # into the REIL language is based on this.
        self._arch_mode = architecture_mode

        # An instance of *ArchitectureInformation*.
        self._arch_info = X86ArchitectureInformation(architecture_mode)

        self._builder = ReilBuilder()

        self._registers = RegisterTranslator(self._arch_info)

        self._reg_acc_translator = X86OperandAccessTranslator(self._arch_info)

        self._flags = FlagTranslator(self._arch_info)

        self._flag_translator = X86FlagTranslator(self._flags)

        # Special registers.
        if self._arch_mode == ARCH_X86_MODE_32:
            self._sp = self._registers.esp
            self._bp = self._registers.ebp
            self._ip = self._registers.eip

        if self._arch_mode == ARCH_X86_MODE_64:
            self._sp = self._registers.rsp
            self._bp = self._registers.rbp
            self._ip = self._registers.rip

        # Word size.
        self._ws = ReilImmediateOperand(self._arch_info.address_size // 8,
                                        self._arch_info.address_size)
Ejemplo n.º 19
0
    def _translate_ldm_stm(self, tb, instruction, load=True):
        # LDM and STM have exactly the same logic except one loads and the
        # other stores It is assumed that the disassembler (for example
        # Capstone) writes the register list in increasing order

        base = tb.read(instruction.operands[0])
        reg_list = tb.read(instruction.operands[1])

        if instruction.ldm_stm_addr_mode is None:
            instruction.ldm_stm_addr_mode = ARM_LDM_STM_IA  # default mode for load and store

        if load:
            load_store_fn = self._load_value
            # Convert stack addressing modes to non-stack addressing modes
            if instruction.ldm_stm_addr_mode in ldm_stack_am_to_non_stack_am:
                instruction.ldm_stm_addr_mode = ldm_stack_am_to_non_stack_am[
                    instruction.ldm_stm_addr_mode]
        else:  # Store
            load_store_fn = self._store_value
            if instruction.ldm_stm_addr_mode in stm_stack_am_to_non_stack_am:
                instruction.ldm_stm_addr_mode = stm_stack_am_to_non_stack_am[
                    instruction.ldm_stm_addr_mode]

        pointer = tb.temporal(base.size)
        tb.add(self._builder.gen_str(base, pointer))
        reg_list_size_bytes = ReilImmediateOperand(
            self._ws.immediate * len(reg_list), base.size)

        if instruction.ldm_stm_addr_mode == ARM_LDM_STM_IA:
            for reg in reg_list:
                load_store_fn(tb, pointer, reg)
                pointer = tb._add_to_reg(pointer, self._ws)
        elif instruction.ldm_stm_addr_mode == ARM_LDM_STM_IB:
            for reg in reg_list:
                pointer = tb._add_to_reg(pointer, self._ws)
                load_store_fn(tb, pointer, reg)
        elif instruction.ldm_stm_addr_mode == ARM_LDM_STM_DA:
            reg_list.reverse(
            )  # Assuming the registry list was in increasing registry number
            for reg in reg_list:
                load_store_fn(tb, pointer, reg)
                pointer = tb._sub_to_reg(pointer, self._ws)
        elif instruction.ldm_stm_addr_mode == ARM_LDM_STM_DB:
            reg_list.reverse()
            for reg in reg_list:
                pointer = tb._sub_to_reg(pointer, self._ws)
                load_store_fn(tb, pointer, reg)
        else:
            raise Exception("Unknown addressing mode.")

        # Write-back
        if instruction.operands[0].wb:
            if instruction.ldm_stm_addr_mode == ARM_LDM_STM_IA or instruction.ldm_stm_addr_mode == ARM_LDM_STM_IB:
                tmp = tb._add_to_reg(base, reg_list_size_bytes)
            elif instruction.ldm_stm_addr_mode == ARM_LDM_STM_DA or instruction.ldm_stm_addr_mode == ARM_LDM_STM_DB:
                tmp = tb._sub_to_reg(base, reg_list_size_bytes)
            tb.add(self._builder.gen_str(tmp, base))
Ejemplo n.º 20
0
def _translate_cmpxchg(self, tb, instruction):
    # Flags Affected
    # The ZF flag is set if the values in the destination operand
    # and register AL, AX, or EAX are equal; otherwise it is
    # cleared. The CF, PF, AF, SF, and OF flags are set according
    # to the results of the comparison operation.

    # Accumulator = AL, AX, EAX, or RAX depending on whether a byte,
    # word, doubleword, or quadword comparison is being performed
    # IF accumulator = DEST
    # THEN
    #   ZF <- 1;
    #   DEST <- SRC;
    # ELSE
    #   ZF <- 0;
    #   accumulator <- DEST;
    # FI;

    oprnd0 = self._reg_acc_translator.read(tb, instruction.operands[0])
    oprnd1 = self._reg_acc_translator.read(tb, instruction.operands[1])

    accum_x86 = __get_cmpxchg_implicit_operand(oprnd0.size)

    accum = self._reg_acc_translator.read(tb, accum_x86)

    # Define immediate registers
    end_addr = ReilImmediateOperand(
        (instruction.address + instruction.size) << 8,
        self._arch_info.address_size + 8)

    tmp0 = tb.temporal(oprnd0.size * 2)

    one = tb.immediate(1, 1)

    change_dst_lbl = ReilLabel('change_dst')
    change_accum_lbl = ReilLabel('change_accum')

    # Compare.
    tb.add(self._builder.gen_sub(accum, oprnd0, tmp0))

    # Update flags : CF, OF, SF, ZF, AF, PF
    self._flag_translator.update_cf(tb, accum, tmp0)
    self._flag_translator.update_of(tb, accum, oprnd0, tmp0, subtraction=True)
    self._flag_translator.update_sf(tb, accum, tmp0)
    self._flag_translator.update_zf(tb, accum, tmp0)
    self._flag_translator.update_af(tb, accum, oprnd0, subtraction=True)
    self._flag_translator.update_pf(tb, tmp0)

    # Exchange
    tb.add(self._builder.gen_jcc(tmp0, change_accum_lbl))
    tb.add(change_dst_lbl)
    self._reg_acc_translator.write(tb, instruction.operands[0], oprnd1)
    tb.add(self._builder.gen_jcc(one, end_addr))
    tb.add(change_accum_lbl)
    # tb.add(self._builder.gen_str(oprnd0, accum))
    self._reg_acc_translator.write(tb, accum_x86, oprnd0)
Ejemplo n.º 21
0
    def _compute_shifted_register(self, sh_op):

        base = ReilRegisterOperand(sh_op.base_reg.name, sh_op.size)

        if sh_op.shift_amount:
            ret = self.temporal(sh_op.size)

            if isinstance(sh_op.shift_amount, ArmImmediateOperand):
                sh_am = ReilImmediateOperand(sh_op.shift_amount.immediate,
                                             sh_op.size)
            elif isinstance(sh_op.shift_amount, ArmRegisterOperand):
                sh_am = ReilRegisterOperand(sh_op.shift_amount.name,
                                            sh_op.shift_amount.size)
            else:
                raise NotImplementedError(
                    "Instruction Not Implemented: Unknown shift amount type.")

            if sh_op.shift_type == 'lsl':
                if isinstance(sh_am, ReilImmediateOperand):
                    self.add(self._builder.gen_bsh(base, sh_am, ret))
                else:
                    sh_am_greater_32_label = self.label(
                        'sh_am_greater_32_label')
                    sh_am_end_label = self.label('sh_am_end_label')

                    sh_am_7_0 = self._and_regs(
                        sh_am, self.immediate(0xFF, sh_am.size))

                    self.add(
                        self._builder.gen_jcc(
                            self._greater_than_or_equal(
                                sh_am_7_0, self.immediate(33, sh_am_7_0.size)),
                            sh_am_greater_32_label))

                    # Shift < 32 => shifted_register = base lsl sh_am
                    self.add(self._builder.gen_bsh(base, sh_am_7_0, ret))
                    self._jump_to(sh_am_end_label)

                    # Shift >= 32 => shifted_register = 0
                    self.add(sh_am_greater_32_label)
                    self.add(
                        self._builder.gen_str(self.immediate(0x0, ret.size),
                                              ret))

                    self.add(sh_am_end_label)
            else:
                # TODO: Implement other shift types
                raise NotImplementedError(
                    "Instruction Not Implemented: Shift type.")
        else:
            ret = base

        return ret
Ejemplo n.º 22
0
def _translate_movw(self, tb, instruction):
    reil_operand = ReilRegisterOperand(instruction.operands[0].name, instruction.operands[0].size)
    word_mask = ReilImmediateOperand(0x0000FFFF, reil_operand.size)
    and_temp = tb.temporal(reil_operand.size)

    oprnd1 = tb.read(instruction.operands[1])

    tb.write(instruction.operands[0], oprnd1)

    tb.add(self._builder.gen_and(reil_operand, word_mask, and_temp))  # filter bits [7:0] part of result

    tb.add(self._builder.gen_str(and_temp, reil_operand))
Ejemplo n.º 23
0
    def __init__(self, architecture_mode):

        super(X86Translator, self).__init__()

        # Set *Architecture Mode*. The translation of each instruction
        # into the REIL language is based on this.
        self._arch_mode = architecture_mode

        # An instance of *ArchitectureInformation*.
        self._arch_info = X86ArchitectureInformation(architecture_mode)

        # An instance of a *VariableNamer*. This is used so all the
        # temporary REIL registers are unique.
        self._ir_name_generator = VariableNamer("t", separator="")

        self._builder = ReilBuilder()

        self._flags = {
            "af": ReilRegisterOperand("af", 1),
            "cf": ReilRegisterOperand("cf", 1),
            "df": ReilRegisterOperand("df", 1),
            "of": ReilRegisterOperand("of", 1),
            "pf": ReilRegisterOperand("pf", 1),
            "sf": ReilRegisterOperand("sf", 1),
            "zf": ReilRegisterOperand("zf", 1),
        }

        if self._arch_mode == ARCH_X86_MODE_32:
            self._sp = ReilRegisterOperand("esp", 32)
            self._bp = ReilRegisterOperand("ebp", 32)
            self._ip = ReilRegisterOperand("eip", 32)

            self._ws = ReilImmediateOperand(4, 32)  # word size
        elif self._arch_mode == ARCH_X86_MODE_64:
            self._sp = ReilRegisterOperand("rsp", 64)
            self._bp = ReilRegisterOperand("rbp", 64)
            self._ip = ReilRegisterOperand("rip", 64)

            self._ws = ReilImmediateOperand(8, 64)  # word size
Ejemplo n.º 24
0
def _translate_branch(self, tb, instruction, link):
    oprnd_cc = ArmConditionCodeHelper.evaluate_cond_code(
        self._flags, tb, instruction.condition_code)

    arm_operand = instruction.operands[0]

    if isinstance(arm_operand, ArmImmediateOperand):
        target = ReilImmediateOperand(arm_operand.immediate << 8,
                                      self._pc.size + 8)
    elif isinstance(arm_operand, ArmRegisterOperand):
        target = ReilRegisterOperand(arm_operand.name, arm_operand.size)
        target = and_regs(tb, target,
                          ReilImmediateOperand(0xFFFFFFFE, target.size))

        tmp0 = tb.temporal(target.size + 8)
        tmp1 = tb.temporal(target.size + 8)

        tb.add(self._builder.gen_str(target, tmp0))
        tb.add(
            self._builder.gen_bsh(tmp0,
                                  ReilImmediateOperand(8,
                                                       target.size + 8), tmp1))

        target = tmp1
    else:
        raise NotImplementedError(
            "Instruction Not Implemented: Unknown operand for branch operation."
        )

    if link:
        tb.add(
            self._builder.gen_str(
                ReilImmediateOperand(instruction.address + instruction.size,
                                     self._pc.size), self._lr))

    tb.add(self._builder.gen_jcc(oprnd_cc, target))
Ejemplo n.º 25
0
    def read(self, tb, x86_operand):
        if isinstance(x86_operand, X86ImmediateOperand):
            reil_operand = ReilImmediateOperand(x86_operand.immediate,
                                                x86_operand.size)
        elif isinstance(x86_operand, X86RegisterOperand):
            reil_operand = ReilRegisterOperand(x86_operand.name,
                                               x86_operand.size)
        elif isinstance(x86_operand, X86MemoryOperand):
            reil_operand = tb.temporal(x86_operand.size)
            addr = self.resolve_memory_access(tb, x86_operand)
            tb.add(tb._builder.gen_ldm(addr, reil_operand))
        else:
            raise Exception('Invalid operand type')

        return reil_operand
Ejemplo n.º 26
0
def parse_operand(string, location, tokens):
    """Parse instruction operand.
    """
    sizes = {
        "dqword":  128,
        "pointer": 72,
        "qword":   64,
        "pointer": 40,
        "dword":   32,
        "word":    16,
        "byte":    8,
        "bit":     1,
    }

    if "immediate" in tokens:
        imm_str = "".join(tokens["immediate"])
        base = 16 if imm_str.startswith("0x") or imm_str.startswith("-0x") else 10

        imm = int(imm_str, base)

        oprnd = ReilImmediateOperand(imm)

    if "register" in tokens:
        if tokens["register"] in ["e", "empty"]:
            oprnd = ReilEmptyOperand()

            oprnd.size = 0
        else:
            name = tokens["register"]

            oprnd = ReilRegisterOperand(name)

    if "size" in tokens:
        oprnd.size = int(sizes[tokens["size"]])

    return [oprnd]
Ejemplo n.º 27
0
    def _compute_memory_address(self, mem_operand):
        """Return operand memory access translation.
        """
        base = ReilRegisterOperand(mem_operand.base_reg.name, mem_operand.size)

        if mem_operand.displacement:
            address = self.temporal(mem_operand.size)

            if isinstance(mem_operand.displacement, ArmRegisterOperand):
                disp = ReilRegisterOperand(mem_operand.displacement.name,
                                           mem_operand.size)
            elif isinstance(mem_operand.displacement, ArmImmediateOperand):
                disp = ReilImmediateOperand(mem_operand.displacement.immediate,
                                            mem_operand.size)
            elif isinstance(mem_operand.displacement,
                            ArmShiftedRegisterOperand):
                disp = self._compute_shifted_register(mem_operand.displacement)
            else:
                raise Exception(
                    "_compute_memory_address: displacement type unknown")

            if mem_operand.index_type == ARM_MEMORY_INDEX_PRE:
                if mem_operand.disp_minus:
                    self.add(self._builder.gen_sub(base, disp, address))
                else:
                    self.add(self._builder.gen_add(base, disp, address))
                self.add(self._builder.gen_str(address, base))
            elif mem_operand.index_type == ARM_MEMORY_INDEX_OFFSET:
                if mem_operand.disp_minus:
                    self.add(self._builder.gen_sub(base, disp, address))
                else:
                    self.add(self._builder.gen_add(base, disp, address))
            elif mem_operand.index_type == ARM_MEMORY_INDEX_POST:
                self.add(self._builder.gen_str(base, address))
                tmp = self.temporal(base.size)
                if mem_operand.disp_minus:
                    self.add(self._builder.gen_sub(base, disp, tmp))
                else:
                    self.add(self._builder.gen_add(base, disp, tmp))
                self.add(self._builder.gen_str(tmp, base))
            else:
                raise Exception(
                    "_compute_memory_address: indexing type unknown")

        else:
            address = base

        return address
Ejemplo n.º 28
0
    def test_load_memory_2(self):
        # testing : dst_reg <- m[src_reg + offset]
        binary  = b"\x33\x30\x94\xe5"                     # 0x00 : (4)  ldr    r3, [r4 + 0x33]
        binary += b"\x1e\xff\x2f\xe1"                     # 0x04 : (4)  bx     lr

        g_candidates, g_classified = self._find_and_classify_gadgets(binary)

        self.assertEqual(len(g_candidates), 1)
        self.assertEqual(len(g_classified), 1)

        self.assertEqual(g_classified[0].type, GadgetType.LoadMemory)
        self.assertEqual(g_classified[0].sources, [ReilRegisterOperand("r4", 32), ReilImmediateOperand(0x33, 32)])
        self.assertEqual(g_classified[0].destination, [ReilRegisterOperand("r3", 32)])

        self.assertEqual(len(g_classified[0].modified_registers), 0)

        self.assertTrue(self._g_verifier.verify(g_classified[0]))
Ejemplo n.º 29
0
    def test_load_constant_4(self):
        # testing : dst_reg <- constant
        binary  = b"\x00\x20\x02\xe2"                     # 0x00 : (4)  and    r2, r2, #0
        binary += b"\x1e\xff\x2f\xe1"                     # 0x04 : (4)  bx     lr

        g_candidates, g_classified = self._find_and_classify_gadgets(binary)

        self.assertEqual(len(g_candidates), 1)
        self.assertEqual(len(g_classified), 1)

        self.assertEqual(g_classified[0].type, GadgetType.LoadConstant)
        self.assertEqual(g_classified[0].sources, [ReilImmediateOperand(0, 32)])
        self.assertEqual(g_classified[0].destination, [ReilRegisterOperand("r2", 32)])

        self.assertEqual(len(g_classified[0].modified_registers), 0)
        self.assertFalse(ReilRegisterOperand("r2", 32) in g_classified[0].modified_registers)

        self.assertTrue(self._g_verifier.verify(g_classified[0]))
Ejemplo n.º 30
0
def _translate_call(self, tb, instruction):
    # Flags Affected
    # All flags are affected if a task switch occurs; no flags are
    # affected if a task switch does not occur.

    oprnd0 = self._reg_acc_translator.read(tb, instruction.operands[0])

    addr_oprnd = _translate_address(self, tb, oprnd0)

    imm1 = tb.immediate(1, 1)

    tmp0 = tb.temporal(self._sp.size)

    ret_addr = ReilImmediateOperand((instruction.address + instruction.size), self._arch_info.address_size)

    tb.add(self._builder.gen_sub(self._sp, self._ws, tmp0))
    tb.add(self._builder.gen_str(tmp0, self._sp))
    tb.add(self._builder.gen_stm(ret_addr, self._sp))
    tb.add(self._builder.gen_jcc(imm1, addr_oprnd))
Ejemplo n.º 31
0
    def _resolve_loops(self, instrs):
        idx_by_labels = {}

        # Collect labels.
        #         curr = 0
        #         for index, instr in enumerate(instrs):
        #             if isinstance(instr, Label):
        #                 idx_by_labels[instr.name] = curr
        #
        #                 del instrs[index]
        #             else:
        #                 curr += 1

        # TODO: Hack to avoid deleting while iterating
        instrs_no_labels = []
        curr = 0
        for i in instrs:
            if isinstance(i, Label):
                idx_by_labels[i.name] = curr
            else:
                instrs_no_labels.append(i)
                curr += 1

        instrs[:] = instrs_no_labels

        # Resolve instruction addresses and JCC targets.
        for index, instr in enumerate(instrs):
            assert isinstance(instr, ReilInstruction)

            instr.address |= index

            if instr.mnemonic == ReilMnemonic.JCC:
                target = instr.operands[2]

                if isinstance(target, Label):
                    idx = idx_by_labels[target.name]
                    address = (instr.address & ~0xff) | idx

                    instr.operands[2] = ReilImmediateOperand(
                        address, self._arch_info.address_size + 8)

        return instrs