Пример #1
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
Пример #2
0
    def _compute_register_list(self, operand):
        """Return operand register list.
        """

        ret = []
        for reg_range in operand.reg_list:
            if len(reg_range) == 1:
                ret.append(
                    ReilRegisterOperand(reg_range[0].name, reg_range[0].size))
            else:
                reg_num = int(
                    reg_range[0].name[1:]
                )  # Assuming the register is named with one letter + number
                reg_end = int(reg_range[1].name[1:])
                if reg_num > reg_end:
                    raise NotImplementedError(
                        "Instruction Not Implemented: Invalid register range.")
                while reg_num <= reg_end:
                    ret.append(
                        ReilRegisterOperand(
                            reg_range[0].name[0] + str(reg_num),
                            reg_range[0].size))
                    reg_num = reg_num + 1

        return ret
Пример #3
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')
Пример #4
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))
Пример #5
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]))
Пример #6
0
    def _classify_arithmetic(self, regs_init, regs_fini, mem_fini, written_regs, read_regs):
        """Classify binary-operation gadgets.
        """
        matches = []

        # TODO: Review these restrictions.
        op_restrictions = {
            "+": lambda x, y: False,
            "-": lambda x, y: x == y,
            "|": lambda x, y: x == y,
            "&": lambda x, y: x == y,
            "^": lambda x, y: x == y,
        }

        # Check for "dst_reg <- src1_reg OP src2_reg" pattern.
        for op_name, op_fn in self._binary_ops.items():
            for src_1_reg, src_1_val in regs_init.items():
                # Make sure the *src* register was read.
                if src_1_reg not in read_regs:
                    continue

                for src_2_reg, src_2_val in regs_init.items():
                    # Make sure the *src* register was read.
                    if src_2_reg not in read_regs:
                        continue

                    for dst_reg, dst_val in regs_fini.items():
                        # Make sure the *dst* register was written.
                        if dst_reg not in written_regs:
                            continue

                        # Check restrictions.
                        if self._arch_regs_size[src_1_reg] != self._arch_regs_size[src_2_reg] or \
                            self._arch_regs_size[src_1_reg] != self._arch_regs_size[dst_reg]:
                            continue

                        # Avoid trivial operations.
                        if op_restrictions[op_name](src_1_reg, src_2_reg):
                            continue

                        size = self._arch_regs_size[src_1_reg]

                        if dst_val == op_fn(src_1_val, src_2_val) & (2**size - 1):
                            src = sorted([src_1_reg, src_2_reg])

                            src_ir = [
                                ReilRegisterOperand(src[0], self._arch_regs_size[src[0]]),
                                ReilRegisterOperand(src[1], self._arch_regs_size[src[1]])
                            ]

                            dst_reg_ir = ReilRegisterOperand(dst_reg, self._arch_regs_size[dst_reg])

                            matches.append({
                                "src": src_ir,
                                "dst": [dst_reg_ir],
                                "op":  op_name
                            })

        return matches
Пример #7
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
Пример #8
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
Пример #9
0
def _translate_cdqe(self, tb, instruction):
    # Flags Affected
    # None.
    oprnd1 = ReilRegisterOperand("eax", 32)
    oprnd2 = ReilRegisterOperand("rax", 64)

    tmp0 = tb.temporal(oprnd1.size)

    tb.add(self._builder.gen_sext(oprnd1, tmp0))
    tb.add(self._builder.gen_sext(tmp0, oprnd2))
Пример #10
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
Пример #11
0
def _translate_movs_suffix(self, tb, instruction, suffix):
    # Flags Affected
    # None.

    # DEST <- SRC;
    # IF DF = 0
    #     THEN (E)DI <- (E)DI + sizeof(SRC);
    #     ELSE (E)DI <- (E)DI - sizeof(SRC);
    # FI;

    # Define source and destination registers.
    if self._arch_mode == ARCH_X86_MODE_32:
        src = ReilRegisterOperand("esi", 32)
        dst = ReilRegisterOperand("edi", 32)
    elif self._arch_mode == ARCH_X86_MODE_64:
        src = ReilRegisterOperand("rsi", 64)
        dst = ReilRegisterOperand("rdi", 64)
    else:
        raise Exception("Invalid architecture mode: %d", self._arch_mode)

    # Define destination register.
    if suffix == 'b':
        data_size = 8
    elif suffix == 'w':
        data_size = 16
    elif suffix == 'd':
        data_size = 32
    elif suffix == 'q':
        data_size = 64
    else:
        raise Exception("Invalid instruction suffix: %s" % suffix)

    if instruction.prefix:
        counter, loop_start_lbl = _rep_prefix_begin(self, tb, instruction)

    # Define temporal registers.
    tmp0 = tb.temporal(data_size)

    # Instruction
    # -------------------------------------------------------------------- #
    # Move data.
    tb.add(self._builder.gen_ldm(src, tmp0))
    tb.add(self._builder.gen_stm(tmp0, dst))

    # Update destination pointer.
    _update_strings_src_and_dst(self, tb, src, dst, data_size)
    # -------------------------------------------------------------------- #

    if instruction.prefix:
        _rep_prefix_end(self, tb, instruction, counter, loop_start_lbl)
Пример #12
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
Пример #13
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
Пример #14
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
Пример #15
0
    def _create_typed_gadgets(self, gadget, classified_gadgets, modified_regs, gadget_type):
        typed_gadgets = []

        # Remove register aliases
        mod_regs = []

        for r in modified_regs:
            alias, _ = self._arch_info.alias_mapper.get(r, (None, None))

            if not alias:
                mod_regs += [r]
            elif alias not in modified_regs:
                mod_regs += [r]

        modified_regs_ir = [ReilRegisterOperand(r, self._arch_regs_size[r]) for r in mod_regs]

        for candidate in classified_gadgets:
            typed_gadget = TypedGadget(gadget, gadget_type, gadget.instrs)

            if gadget_type in [GadgetType.Arithmetic, GadgetType.ArithmeticLoad, GadgetType.ArithmeticStore]:
                typed_gadget.operation = candidate["op"]

            if candidate.get("op", "") != "nop":
                typed_gadget.sources = candidate["src"]
                typed_gadget.destination = candidate["dst"]

                if gadget_type == GadgetType.StoreMemory:
                    typed_gadget.modified_registers = [r for r in modified_regs_ir]
                else:
                    typed_gadget.modified_registers = [r for r in modified_regs_ir if r not in typed_gadget.destination]

            typed_gadgets += [typed_gadget]

        return typed_gadgets
Пример #16
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)
Пример #17
0
def _translate_sahf(self, tb, instruction):
    # Flags Affected
    # The SF, ZF, AF, PF, and CF flags are loaded with values from
    # the AH register. Bits 1, 3, and 5 of the EFLAGS register are
    # unaffected, with the values remaining 1, 0, and 0,
    # respectively.

    oprnd0 = ReilRegisterOperand("ah", 8)

    tmp0 = tb.temporal(oprnd0.size)
    tmp1 = tb.temporal(oprnd0.size)
    tmp2 = tb.temporal(oprnd0.size)
    tmp3 = tb.temporal(oprnd0.size)

    shl_two = tb.immediate(-2, 8)
    shl_one = tb.immediate(-1, 8)

    tb.add(self._builder.gen_str(oprnd0, self._flags["cf"]))
    tb.add(self._builder.gen_bsh(oprnd0, shl_two, tmp0))

    tb.add(self._builder.gen_str(tmp0, self._flags["pf"]))
    tb.add(self._builder.gen_bsh(tmp0, shl_two, tmp1))

    tb.add(self._builder.gen_str(tmp1, self._flags["af"]))
    tb.add(self._builder.gen_bsh(tmp1, shl_two, tmp2))

    tb.add(self._builder.gen_str(tmp2, self._flags["zf"]))
    tb.add(self._builder.gen_bsh(tmp2, shl_one, tmp3))

    tb.add(self._builder.gen_str(tmp3, self._flags["sf"]))
Пример #18
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)
Пример #19
0
def _translate_ldrh(self, tb, instruction):
    op0_reil = ReilRegisterOperand(instruction.operands[0].name, instruction.operands[0].size)
    addr_reg = self._reg_acc_translator.compute_memory_address(tb, instruction.operands[1])
    byte_reg = tb.temporal(16)

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

    tb.add(self._builder.gen_str(byte_reg, op0_reil))
Пример #20
0
    def test_move_register_2(self):
        # testing : dst_reg <- src_reg
        binary  = b"\x00\x00\x84\xe2"                     # 0x00 : (4)  add    r0, r4, #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.MoveRegister)
        self.assertEqual(g_classified[0].sources, [ReilRegisterOperand("r4", 32)])
        self.assertEqual(g_classified[0].destination, [ReilRegisterOperand("r0", 32)])

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

        self.assertTrue(self._g_verifier.verify(g_classified[0]))
Пример #21
0
    def test_store_memory_2(self):
        # testing : dst_reg <- m[src_reg + offset]
        binary  = b"\x33\x30\x84\xe5"                     # 0x00 : (4)  str    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.StoreMemory)
        self.assertEqual(g_classified[0].sources, [ReilRegisterOperand("r3", 32)])
        self.assertEqual(g_classified[0].destination, [ReilRegisterOperand("r4", 32), ReilImmediateOperand(0x33, 32)])

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

        self.assertTrue(self._g_verifier.verify(g_classified[0]))
Пример #22
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
Пример #23
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
Пример #24
0
def _translate_strh(self, tb, instruction):
    reil_operand = ReilRegisterOperand(instruction.operands[0].name, instruction.operands[0].size)
    half_word_reg = tb.temporal(16)

    tb.add(self._builder.gen_str(reil_operand, half_word_reg))  # filter bits [15:0] part of result

    addr = self._reg_acc_translator.compute_memory_address(tb, instruction.operands[1])

    tb.add(self._builder.gen_stm(half_word_reg, addr))
Пример #25
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]))
Пример #26
0
    def test_arithmetic_sub_1(self):
        # testing : dst_reg <- src1_reg + src2_reg
        binary  = b"\x08\x00\x44\xe0"                     # 0x00 : (4)  sub    r0, r4, r8
        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.Arithmetic)
        self.assertEqual(g_classified[0].sources, [ReilRegisterOperand("r4", 32), ReilRegisterOperand("r8", 32)])
        self.assertEqual(g_classified[0].destination, [ReilRegisterOperand("r0", 32)])
        self.assertEqual(g_classified[0].operation, "-")

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

        self.assertTrue(self._g_verifier.verify(g_classified[0]))
Пример #27
0
def _translate_strb(self, tb, instruction):
    reil_operand = ReilRegisterOperand(instruction.operands[0].name, instruction.operands[0].size)
    byte_reg = tb.temporal(8)

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

    addr = tb._compute_memory_address(instruction.operands[1])

    tb.add(self._builder.gen_stm(byte_reg, addr))
Пример #28
0
    def test_move_register_1(self):
        # testing : dst_reg <- src_reg
        binary  = b"\x04\x00\xa0\xe1"                     # 0x00 : (4)  mov    r0, r4
        binary += b"\x31\xff\x2f\xe1"                     # 0x04 : (4)  blx    r1

        g_candidates, g_classified = self._find_and_classify_gadgets(binary)

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

        self.assertEqual(g_classified[0].type, GadgetType.MoveRegister)
        self.assertEqual(g_classified[0].sources, [ReilRegisterOperand("r4", 32)])
        self.assertEqual(g_classified[0].destination, [ReilRegisterOperand("r0", 32)])

        self.assertEqual(len(g_classified[0].modified_registers), 1)
        self.assertTrue(ReilRegisterOperand("r14", 32) in g_classified[0].modified_registers)

        self.assertTrue(self._g_verifier.verify(g_classified[0]))
Пример #29
0
    def __get_register(self, register):
        register = register.lower()

        if register not in self.__arch.registers_gp_all:
            raise TranslationError("Invalid register")

        if register not in self.__registers:
            self.__registers[register] = ReilRegisterOperand(
                register, self.__arch.registers_size[register])

        return self.__registers[register]
Пример #30
0
    def __get_flag(self, flag):
        flag = flag.lower()

        if flag not in self.__arch.registers_flags:
            raise TranslationError("Invalid flag")

        if flag not in self.__flags:
            self.__flags[flag] = ReilRegisterOperand(
                flag, self.__arch.registers_size[flag])

        return self.__flags[flag]