Пример #1
0
    def djnz_helper(self, il, addr, reg):

        # decrement the register
        self.wreg_set(il, reg, il.sub(1, self.wreg_get(il, reg), il.const(1, 1)))

        # try to find a label for the branch target
        taken = il.get_label_for_address(il.arch, addr)

        # create taken target
        taken_found = True
        if taken is None:
            taken = LowLevelILLabel()
            taken_found = False

        # create untaken target
        untaken_found = True
        untaken = il.get_label_for_address(il.arch, il.current_address + 2)
        if untaken is None:
            untaken = LowLevelILLabel()
            untaken_found = False

        # generate the conditional branch LLIL
        il.append(il.if_expr(il.compare_not_equal(1, self.wreg_get(il, reg), il.const(1, 0)), taken, untaken))

        # generate a jump to the branch target if a label couldn't be found
        if not taken_found:
            il.mark_label(taken)
            il.append(il.jump(il.const(2, addr)))

        # generate a label for the untaken branch
        if not untaken_found:
            il.mark_label(untaken)
Пример #2
0
    def _lift_inc_dec(self, il, regs, df_values):
        if not isinstance(regs, tuple):
            regs = (regs, )

        if df_values is not None and df_values.type == RegisterValueType.ConstantValue:
            if df_values.value:
                for reg in regs:
                    il.append(
                        il.set_reg(2, reg,
                                   il.sub(2, il.reg(2, reg), il.const(2, 1))))
            else:
                for reg in regs:
                    il.append(
                        il.set_reg(2, reg,
                                   il.add(2, il.reg(2, reg), il.const(2, 1))))
        else:
            inc_label, dec_label = LowLevelILLabel(), LowLevelILLabel()
            post_label = LowLevelILLabel()
            il.append(il.if_expr(il.flag('d'), dec_label, inc_label))
            il.mark_label(inc_label)
            for reg in regs:
                il.append(
                    il.set_reg(2, reg, il.add(2, il.reg(2, reg),
                                              il.const(2, 1))))
            il.append(il.goto(post_label))
            il.mark_label(dec_label)
            for reg in regs:
                il.append(
                    il.set_reg(2, reg, il.sub(2, il.reg(2, reg),
                                              il.const(2, 1))))
            il.append(il.goto(post_label))
            il.mark_label(post_label)
Пример #3
0
def il_branch(il, cond, tdest, fdest):
    
    # lookup the true branch
    t_target = None
    if il[tdest].operation == LowLevelILOperation.LLIL_CONST:
        t_target = il.get_label_for_address(Architecture['s1c88:s1c88'], il[tdest].constant)

    # if the label doesn't exist, create a new one
    indirect = False
    if t_target is None:
        t_target = LowLevelILLabel()
        indirect = True

    # create the false branch
    f_target = LowLevelILLabel()

    # create the if_expr
    il.append(il.if_expr(cond, t_target, f_target))

    # handle true target if indirect
    if indirect:
        il.mark_label(t_target)
        il.append(il.jump(tdest))

    # mark false branch
    il.mark_label(f_target)
Пример #4
0
 def lift(self, il, addr):
     overflow_label = LowLevelILLabel()
     normal_label = LowLevelILLabel()
     il.append(il.if_expr(il.flag('o'), overflow_label, normal_label))
     il.mark_label(overflow_label)
     Int.lift(self, il, addr)
     il.mark_label(normal_label)
Пример #5
0
def append_conditional_instr(cond, instr, il):
    if cond == CC.ALWAYS:
        il.append(instr)
    else:
        t = LowLevelILLabel()
        f = LowLevelILLabel()
        #if cond in CC_UN_NOT:
        #    ant = jcc_to_flag_cond(CC_UN_NOT[cond], il)
        #    il.append(il.if_expr(ant, f, t))
        #else:
        ant = jcc_to_flag_cond(cond, il)
        il.append(il.if_expr(ant, t, f))
        il.mark_label(t)
        il.append(instr)
        il.mark_label(f)
Пример #6
0
def cond_branch(il, cond, dest):
    t = None
    if il[dest].operation == LowLevelILOperation.LLIL_CONST:
        t = il.get_label_for_address(Architecture['6502'], il[dest].value)
    if t is None:
        t = LowLevelILLabel()
        indirect = True
    else:
        indirect = False
    f = LowLevelILLabel()
    il.append(il.if_expr(cond, t, f))
    if indirect:
        il.mark_label(t)
        il.append(il.jump(dest))
    il.mark_label(f)
    return None
Пример #7
0
def cond_branch(il, addr, cond, arg=None):
    # try to find a label for the branch target
    taken = il.get_label_for_address(il.arch, addr)

    # build the conditional expression
    if cond == 'Z':
        expr = il.compare_equal(1, il.reg(1, 'A'), il.const(1, 0))
    elif cond == 'NZ':
        expr = il.compare_not_equal(1, il.reg(1, 'A'), il.const(1, 0))
    elif cond == 'B':
        expr = il.and_expr(1, il.reg(1, 'A'), il.const(1, 1 << arg))
    else:
        expr = il.compare_equal(1, il.flag(cond), il.const(0, arg))

    # create taken target
    taken_found = True
    if taken is None:
        taken = LowLevelILLabel()
        taken_found = False

    # create untaken target
    untaken_found = True
    untaken = il.get_label_for_address(il.arch, il.current_address + 2)
    if untaken is None:
        untaken = LowLevelILLabel()
        untaken_found = False

    # generate the conditional branch LLIL
    il.append(il.if_expr(expr, taken, untaken))

    # generate a jump to the branch target if a label couldn't be found
    if not taken_found:
        il.mark_label(taken)
        il.append(il.jump(il.const_pointer(2, addr)))

    # generate a label for the untaken branch
    if not untaken_found:
        il.mark_label(untaken)
Пример #8
0
    def lift(self, il, addr):
        untaken_label = il.get_label_for_address(il.arch, addr + self.length())
        taken_label = il.get_label_for_address(il.arch, self.ip)
        if taken_label is None:
            mark_taken = True
            taken_label = LowLevelILLabel()
        else:
            mark_taken = False

        il.append(
            il.if_expr(self._lift_loop_cond(il), taken_label, untaken_label))
        if mark_taken:
            il.mark_label(taken_label)
            il.append(il.jump(il.const(3, self.ip)))
Пример #9
0
    def lift(self, il, addr):
        if not isinstance(self.next, InstrString):
            il.append(il.undefined())
            return

        # FIXME: doesn't seem to actually work
        preheader_instr = il.append(il.nop())
        df_values = il[preheader_instr].get_possible_flag_values('d')

        header_label = LowLevelILLabel()
        exit_label = LowLevelILLabel()

        il.mark_label(header_label)
        self.next.lift(il, addr + 1, df_values)

        il.append(
            il.set_reg(2, 'cx', il.sub(2, il.reg(2, 'cx'), il.const(2, 1))))
        cond = il.compare_equal(2, il.reg(2, 'cx'), il.const(2, 0))
        if self._zf_check():
            zf_cond = il.compare_equal(2, il.flag('z'),
                                       il.const(1, self._zf_cond))
            cond = il.or_expr(1, cond, zf_cond)
        il.append(il.if_expr(cond, header_label, exit_label))
        il.mark_label(exit_label)
Пример #10
0
    def lift(self, il, addr):
        untaken_label = il.get_label_for_address(il.arch, addr + self.length())
        taken_label = il.get_label_for_address(il.arch, self.ip)
        if taken_label is None:
            mark_taken = True
            taken_label = LowLevelILLabel()
        else:
            mark_taken = False

        name = self.name()
        if name == 'jpe':
            il.append(il.if_expr(il.flag('p'), taken_label, untaken_label))
        elif name == 'jpo':
            il.append(il.if_expr(il.flag('p'), untaken_label, taken_label))
        else:
            cond = jump_cond[name]
            il.append(
                il.if_expr(il.flag_condition(cond), taken_label,
                           untaken_label))

        if mark_taken:
            il.mark_label(taken_label)
            il.append(il.jump(il.const(3, self.ip)))
Пример #11
0
def il_jump(il, dest, is_call=False):

    if is_call:
        il.append(il.call(dest))
    else:
        # lookup label 
        t = None
        if il[dest].operation == LowLevelILOperation.LLIL_CONST:
            t = il.get_label_for_address(Architecture['s1c88:s1c88'], il[dest].constant)

        # if the label doesn't exist, create a new one
        indirect = False
        if t is None:
            t = LowLevelILLabel()
            indirect = True

        # if it doesn't exist, create and jump
        if indirect:
            il.mark_label(t)
            il.append(il.jump(dest))
        else:
            # just goto label
            il.append(il.goto(t))
Пример #12
0
    def get_instruction_low_level_il(self, data, addr, il: LowLevelILFunction):
        instr = self.disassembler.instrs[addr // self.address_size]
        if instr is None:
            return None

        if isinstance(instr, Subleq):
            a, b, c = instr.a, instr.b, instr.c

            _, mem_a = self.get_addr_mem_il(a, il)
            addr_b, mem_b = self.get_addr_mem_il(b, il)
            sub_op = il.sub(self.address_size, mem_b, mem_a)
            if self.disassembler.is_register(b):
                store_b = il.set_reg(self.address_size,
                                     self.disassembler.symbol[b], sub_op)
            else:
                store_b = il.store(self.address_size, addr_b, sub_op)
            il.append(store_b)
            less_op = il.compare_signed_less_equal(
                self.address_size, mem_b, il.const(self.address_size, 0))

            t_target = il.get_label_for_address(il.arch, c * self.address_size)
            t_label_found = True
            if t_target is None:
                t_label_found = False
                t_target = LowLevelILLabel()

            f_label_found = True
            f_target = il.get_label_for_address(
                il.arch, addr + instr.width + self.address_size)
            if f_target is None:
                f_target = LowLevelILLabel()
                f_label_found = False

            il.append(il.if_expr(less_op, t_target, f_target))

            if not t_label_found:
                il.mark_label(t_target)
                il.append(
                    il.jump(il.const(self.address_size,
                                     c * self.address_size)))
            if not f_label_found:
                il.mark_label(f_target)
        elif isinstance(instr, Clear):
            b = instr.b
            c = instr.c

            addr_b, _ = self.get_addr_mem_il(b, il)
            store_b = il.store(self.address_size, addr_b,
                               il.const(self.address_size, 0))
            il.append(store_b)
            jump_c = il.jump(
                il.const(self.address_size, instr.c * self.address_size))
            il.append(jump_c)

        elif isinstance(instr, Push):
            v = instr.v

            addr_v, mem_v = self.get_addr_mem_il(v, il)
            push_v = il.push(self.address_size, mem_v)

            il.append(push_v)
        elif isinstance(instr, Mov):
            a, b = instr.a, instr.b

            addr_a, mem_a = self.get_addr_mem_il(a, il)
            addr_b, mem_b = self.get_addr_mem_il(b, il)
            if self.disassembler.is_register(b):
                mov_op = il.set_reg(self.address_size,
                                    self.disassembler.symbol[b], mem_a)
            else:
                mov_op = il.store(self.address_size, addr_b, mem_a)
            il.append(mov_op)
        elif isinstance(instr, Ret):
            il.append(
                il.ret(
                    il.load(self.address_size, il.reg(self.address_size,
                                                      "sp"))))
        elif isinstance(instr, Pop):
            v = instr.v
            addr_v, _ = self.get_addr_mem_il(v, il)
            pop_op = il.pop(self.address_size)
            if self.disassembler.is_register(v):
                store_op = il.set_reg(self.address_size,
                                      self.disassembler.symbol[v], pop_op)
            else:
                store_op = il.store(self.address_size, addr_v, pop_op)
            il.append(store_op)
        elif isinstance(instr, Call):
            il.append(
                il.call(
                    il.const(self.address_size, instr.c * self.address_size)))
        elif isinstance(instr, Inc):
            b = instr.b
            addr_b, mem_b = self.get_addr_mem_il(b, il)
            if self.disassembler.is_register(b):
                store_op = il.set_reg(
                    self.address_size,
                    self.disassembler.symbol[b],
                    il.add(self.address_size, mem_b,
                           il.const(self.address_size, 1)),
                )
            else:
                store_op = il.store(
                    self.address_size,
                    addr_b,
                    il.add(self.address_size, mem_b,
                           il.const(self.address_size, 1)),
                )
            il.append(store_op)
        elif isinstance(instr, Dec):
            b = instr.b
            addr_b, mem_b = self.get_addr_mem_il(b, il)
            if self.disassembler.is_register(b):
                store_op = il.set_reg(
                    self.address_size,
                    self.disassembler.symbol[b],
                    il.add(self.address_size, mem_b,
                           il.const(self.address_size, -1)),
                )
            else:
                store_op = il.store(
                    self.address_size,
                    addr_b,
                    il.add(self.address_size, mem_b,
                           il.const(self.address_size, -1)),
                )
            il.append(store_op)
        elif isinstance(instr, Exit):
            il.append(il.no_ret())
        elif isinstance(instr, Jmp):
            il.append(
                il.jump(
                    il.const(self.address_size, instr.c * self.address_size)))

        return instr.width * self.address_size
Пример #13
0
def gen_instr_il(addr, decoded, il):
    (oper_type, oper_val) = decoded.operands[0] if decoded.operands else (None,
                                                                          None)
    (operb_type,
     operb_val) = decoded.operands[1] if decoded.operands[1:] else (None, None)

    if decoded.op in [OP.ADD, OP.ADC]:
        assert len(decoded.operands) == 2
        if oper_type == OPER_TYPE.REG:
            size = REG_TO_SIZE[oper_val]
            rhs = operand_to_il(operb_type, operb_val, il, size)
            lhs = operand_to_il(oper_type, oper_val, il)
            if decoded.op == OP.ADD:
                tmp = il.add(size, lhs, rhs, flags='*')
            else:
                tmp = il.add_carry(size, lhs, rhs, il.flag("c"), flags='*')
            tmp = il.set_reg(size, reg2str(oper_val), tmp)
            il.append(tmp)
        else:
            il.append(il.unimplemented())

    elif decoded.op == OP.AND:
        tmp = il.reg(1, 'A')
        tmp = il.and_expr(1,
                          operand_to_il(oper_type, oper_val, il, 1),
                          tmp,
                          flags='z')
        tmp = il.set_reg(1, 'A', tmp)
        il.append(tmp)

    elif decoded.op == OP.BIT:
        assert oper_type == OPER_TYPE.IMM
        assert oper_val >= 0 and oper_val <= 7
        mask = il.const(1, 1 << oper_val)
        operand = operand_to_il(operb_type, operb_val, il, 1)
        il.append(il.and_expr(1, operand, mask, flags='*'))

    elif decoded.op == OP.CALL:
        if oper_type == OPER_TYPE.ADDR:
            il.append(il.call(il.const_pointer(2, oper_val)))
        else:
            # TODO: handle the conditional
            il.append(il.unimplemented())

    elif decoded.op == OP.CCF:
        il.append(il.set_flag('c', il.not_expr(0, il.flag('c'))))

    elif decoded.op == OP.CP:
        # sub, but do not write to register
        lhs = il.reg(1, 'A')
        rhs = operand_to_il(oper_type, oper_val, il, 1)
        sub = il.sub(1, lhs, rhs, flags='*')
        il.append(sub)

    elif decoded.op == OP.DJNZ:
        # decrement B
        tmp = il.reg(1, 'B')
        tmp = il.add(1, tmp, il.const(1, -1))
        tmp = il.set_reg(1, 'B', tmp)
        il.append(tmp)
        # if nonzero, jump! (the "go" is built into il.if_expr)
        t = il.get_label_for_address(Architecture['Z80'], oper_val)
        if not t:
            il.append(il.unimplemented())
            return
        f = il.get_label_for_address(Architecture['Z80'], addr + decoded.len)
        if not f:
            il.append(il.unimplemented())
            return
        tmp = il.compare_not_equal(1, il.reg(1, 'B'), il.const(1, 0))
        il.append(il.if_expr(tmp, t, f))

    elif decoded.op == OP.EX:
        # temp0 = lhs
        il.append(
            il.expr(LowLevelILOperation.LLIL_SET_REG,
                    LLIL_TEMP(0),
                    operand_to_il(oper_type, oper_val, il, 2),
                    size=2))

        # lhs = rhs
        rhs = operand_to_il(operb_type, operb_val, il, 2)

        if oper_type == OPER_TYPE.REG:
            il.append(il.set_reg(2, reg2str(oper_val), rhs))
        else:
            il.append(
                il.store(
                    2, operand_to_il(oper_type,
                                     oper_val,
                                     il,
                                     2,
                                     peel_load=True), rhs))

        # rhs = temp0
        il.append(
            il.set_reg(2, reg2str(operb_val),
                       il.expr(LowLevelILOperation.LLIL_REG, LLIL_TEMP(0), 2)))

    elif decoded.op == OP.INC:
        # inc reg can be 1-byte or 2-byte
        if oper_type == OPER_TYPE.REG:
            size = REG_TO_SIZE[oper_val]
            tmp = il.add(size, operand_to_il(oper_type, oper_val, il),
                         il.const(1, 1))
            tmp = il.set_reg(size, reg2str(oper_val), tmp)
        else:
            tmp = il.add(1, operand_to_il(oper_type, oper_val, il),
                         il.const(1, 1))
            tmp = il.store(
                1, operand_to_il(oper_type, oper_val, il, 1, peel_load=True),
                tmp)

        il.append(tmp)

    elif decoded.op in [OP.JP, OP.JR]:
        if oper_type == OPER_TYPE.COND:
            append_conditional_jump(oper_val, operb_type, operb_val,
                                    addr + decoded.len, il)
        else:
            il.append(goto_or_jump(oper_type, oper_val, il))

    elif decoded.op == OP.LD:
        assert len(decoded.operands) == 2

        if oper_type == OPER_TYPE.REG:
            size = REG_TO_SIZE[oper_val]
            # for two-byte nonzero loads, guess that it's an address
            if size == 2 and operb_type == OPER_TYPE.IMM and operb_val != 0:
                operb_type = OPER_TYPE.ADDR
            rhs = operand_to_il(operb_type, operb_val, il, size)
            set_reg = il.set_reg(size, reg2str(oper_val), rhs)
            il.append(set_reg)
        else:
            assert operb_type in [OPER_TYPE.REG, OPER_TYPE.IMM]

            if operb_type == OPER_TYPE.REG:
                # 1 or 2 byte stores are possible here:
                # ld (0xcdab),bc
                # ld (ix-0x55),a
                size = REG_TO_SIZE[operb_val]
            elif operb_type == OPER_TYPE.IMM:
                # only 1 byte stores are possible
                # eg: ld (ix-0x55),0xcd
                size = 1

            src = operand_to_il(operb_type, operb_val, il, size)
            dst = operand_to_il(oper_type, oper_val, il, size, peel_load=True)
            il.append(il.store(size, dst, src))

    elif decoded.op in [OP.LDI, OP.LDIR]:
        if decoded.op == OP.LDIR:
            t = LowLevelILLabel()
            f = il.get_label_for_address(Architecture['Z80'],
                                         addr + decoded.len)
            il.mark_label(t)

        il.append(il.store(1, il.reg(2, 'DE'), il.load(1, il.reg(2, 'HL'))))
        il.append(
            il.set_reg(2, 'DE', il.add(2, il.reg(2, 'DE'), il.const(2, 1))))
        il.append(
            il.set_reg(2, 'HL', il.add(2, il.reg(2, 'HL'), il.const(2, 1))))
        il.append(
            il.set_reg(2, 'BC', il.sub(2, il.reg(2, 'BC'), il.const(2, 1))))

        if decoded.op == OP.LDIR:
            do_mark = False
            if not f:
                do_mark = True
                f = LowLevelILLabel()

            il.append(
                il.if_expr(
                    il.compare_not_equal(2, il.reg(2, 'BC'), il.const(2, 0)),
                    t, f))

            if do_mark:
                il.mark_label(f)

    elif decoded.op == OP.NOP:
        il.append(il.nop())

    elif decoded.op == OP.OR:
        tmp = il.reg(1, 'A')
        tmp = il.or_expr(1,
                         operand_to_il(oper_type, oper_val, il, 1),
                         tmp,
                         flags='*')
        tmp = il.set_reg(1, 'A', tmp)
        il.append(tmp)

    elif decoded.op == OP.POP:
        # possible operands are: af bc de hl ix iy
        flag_write_type = '*' if oper_val == REG.AF else None

        size = REG_TO_SIZE[oper_val]
        tmp = il.pop(size)
        tmp = il.set_reg(size, reg2str(oper_val), tmp, flag_write_type)
        il.append(tmp)

    elif decoded.op == OP.PUSH:
        # possible operands are: af bc de hl ix iy

        # when pushing AF, actually push the flags
        if oper_val == REG.AF:
            # lo byte F first
            il.append(
                il.push(
                    2,
                    il.or_expr(
                        2,
                        il.or_expr(
                            1,
                            il.or_expr(
                                1,
                                il.shift_left(1, il.flag('s'), il.const(1, 7)),
                                il.shift_left(1, il.flag('z'), il.const(1,
                                                                        6))),
                            il.or_expr(
                                1,
                                il.or_expr(
                                    1,
                                    il.shift_left(1, il.flag('h'),
                                                  il.const(1, 4)),
                                    il.shift_left(1, il.flag('pv'),
                                                  il.const(1, 2))),
                                il.or_expr(
                                    1,
                                    il.shift_left(1, il.flag('n'),
                                                  il.const(1, 1)),
                                    il.flag('c')))),
                        il.shift_left(2, il.reg(1, 'A'), il.const(1, 8)))))
        else:
            il.append(il.push( \
                REG_TO_SIZE[oper_val], \
                operand_to_il(oper_type, oper_val, il)))

    elif decoded.op in [OP.RL, OP.RLA]:
        # rotate THROUGH carry: b0=c, c=b8
        # z80 'RL' -> llil 'RLC'
        if decoded.op == OP.RLA:
            src = il.reg(1, 'A')
        else:
            src = operand_to_il(oper_type, oper_val, il)

        rot = il.rotate_left_carry(1,
                                   src,
                                   il.const(1, 1),
                                   il.flag('c'),
                                   flags='c')

        if decoded.op == OP.RLA:
            il.append(il.set_reg(1, 'A', rot))
        elif oper_type == OPER_TYPE.REG:
            il.append(il.set_reg(1, reg2str(oper_val), rot))
        else:
            tmp = operand_to_il(oper_type, oper_val, il, 1, peel_load=True)
            il.append(il.store(1, tmp2, tmp))

    elif decoded.op in [OP.RLC, OP.RLCA]:
        # rotate and COPY to carry: b0=c, c=b8
        # z80 'RL' -> llil 'ROL'
        if decoded.op == OP.RLCA:
            src = il.reg(1, 'A')
        else:
            src = operand_to_il(oper_type, oper_val, il)

        rot = il.rotate_left(1, src, il.const(1, 1), flags='c')

        if decoded.op == OP.RLCA:
            il.append(il.set_reg(1, 'A', rot))
        elif oper_type == OPER_TYPE.REG:
            il.append(il.set_reg(1, reg2str(oper_val), rot))
        else:
            tmp = operand_to_il(oper_type, oper_val, il, 1, peel_load=True)
            il.append(il.store(1, tmp2, tmp))

    elif decoded.op == OP.RET:
        tmp = il.ret(il.pop(2))
        if decoded.operands:
            append_conditional_instr(decoded.operands[0][1], tmp, il)
        else:
            il.append(tmp)

    elif decoded.op in [OP.RR, OP.RRA]:
        # rotate THROUGH carry: b7=c, c=b0
        # z80 'RL' -> llil 'RRC'
        if decoded.op == OP.RRA:
            src = il.reg(1, 'A')
        else:
            src = operand_to_il(oper_type, oper_val, il, 1)

        rot = il.rotate_right_carry(1,
                                    src,
                                    il.const(1, 1),
                                    il.flag('c'),
                                    flags='c')

        if decoded.op == OP.RRA:
            il.append(il.set_reg(1, 'A', rot))
        elif oper_type == OPER_TYPE.REG:
            il.append(il.set_reg(1, reg2str(oper_val), rot))
        else:
            tmp2 = operand_to_il(oper_type, oper_val, il, 1, peel_load=True)
            il.append(il.store(1, tmp2, rot))

    elif decoded.op == OP.SRA:
        tmp = operand_to_il(oper_type, oper_val, il, 1)
        tmp = il.arith_shift_right(1, tmp, il.const(1, 1), flags='c')

        if oper_type == OPER_TYPE.REG:
            tmp = il.set_reg(1, reg2str(oper_val), tmp)
        else:
            tmp = il.store(
                1, operand_to_il(oper_type, oper_val, il, 1, peel_load=True),
                tmp)

        il.append(tmp)

    elif decoded.op == OP.SUB:
        tmp = operand_to_il(oper_type, oper_val, il, 1)
        tmp = il.sub(1, il.reg(1, 'A'), tmp, flags='*')
        tmp = il.set_reg(1, 'A', tmp)
        il.append(tmp)

    elif decoded.op == OP.DEC:
        if oper_type == OPER_TYPE.REG:
            size = REG_TO_SIZE[oper_val]
            reg = operand_to_il(oper_type, oper_val, il, size)
            fwt = 'not_c' if size == 1 else None
            tmp = il.sub(size, reg, il.const(1, 1), flags=fwt)
            tmp = il.set_reg(size, reg2str(oper_val), tmp)
            il.append(tmp)
        else:
            mem = operand_to_il(oper_type, oper_val, il, 1)
            tmp = il.sub(1, mem, il.const(1, 1), flags='not_c')
            tmp = il.store(1, mem, tmp)
            il.append(tmp)

    elif decoded.op == OP.SBC:
        size = REG_TO_SIZE[oper_val]
        lhs = operand_to_il(oper_type, oper_val, il, size)
        rhs = operand_to_il(operb_type, operb_val, il, size)
        tmp = il.sub_borrow(size, lhs, rhs, il.flag('c'), flags='*')
        tmp = il.set_reg(1, 'A', tmp)
        il.append(tmp)

    elif decoded.op == OP.XOR:
        tmp = il.reg(1, 'A')
        tmp = il.xor_expr(1,
                          operand_to_il(oper_type, oper_val, il, 1),
                          tmp,
                          flags='*')
        tmp = il.set_reg(1, 'A', tmp)
        il.append(tmp)

    else:
        il.append(il.unimplemented())
Пример #14
0
	def esil_to_llil(self, inst, parts, il, addr, l):
		stack = []
		label_stack = []
		skip_to_close = False
		# pop for reading - interprets the PC register as
		# the value of the next instruction
		def popr():
			r = stack.pop()
			if r == "pc":
				return il.const_pointer(4, addr + l)
			return r
		for i, token in enumerate(parts):
			# No idea why I need this
			if token == "" and i == len(parts)-1:
				break
			if skip_to_close and token != "}": continue
			if token == "$$":
				stack.append(il.const_pointer(4, addr))
				continue
			if token == "pc":
				stack.append("pc")
				continue
			if token in self.regs:
				stack.append(il.reg(4, token))
				continue
			if token in self._esil_to_llil:
				dst = popr()
				src = popr()
				stack.append(getattr(il, self._esil_to_llil[token])(4, dst, src))
				continue
			if token == "$z" or token == "!":
				stack.append(il.compare_equal(4, stack[-1], il.const(4, 0)))
				continue
			if token == "DUP":
				stack.append(stack[-1])
				continue
			if token == "=":
				dst = stack.pop()
				src = popr()
				if dst == "pc":
					srci = il[src]
					if srci.operation == LowLevelILOperation.LLIL_CONST:
						self.goto_or_jmp(il, srci.operands[0])
						continue
					il.append(il.jump(src))
					continue
				dst = il[dst]
				if dst.operation != LowLevelILOperation.LLIL_REG:
					raise ValueError("unimplemented il store to {0!r}".format(dst))
				il.append(il.set_reg(4, dst.operands[0].name, src))
				continue
			if token == "+=":
				dste = stack.pop()
				src = popr()
				if dste == "pc":
					srci = il[src]
					# Note in ESIL this is w.r.t. the *next* address
					# For narrow branch instructions, it calculates the pc relative
					# wrong in the ESIL and uses 3 bytes anyway
					# also, srci.operands[0] is 8 bytes *signed* but ESIL
					# doesn't seem to reflect this?
					# Note: except beqz, bnez, bgez, bltz which have 12 bytes *signed*
					# and beqz.n and bnez.n which are 4 bytes unsigned
					if srci.operation == LowLevelILOperation.LLIL_CONST:
						offset = srci.operands[0]
						if inst in ("beqz", "bnez", "bgez", "bltz"):
							if offset > (1 << 11) - 1:
								offset = ((1<<12)-offset) * -1
						elif inst in ("beqz.n", "bnez.n"): pass
						elif offset > 127:
							offset = (256-offset) * -1
						self.goto_or_jmp(il, offset + addr + 3)
					else:
						il.append(il.jump(il.add(4, il.const_pointer(4, addr + 3), src)))
					continue
				dst = il[dste]
				if dst.operation != LowLevelILOperation.LLIL_REG:
					raise ValueError("unimplemented il store to {0!r}".format(dst))
				il.append(il.set_reg(4, dst.operands[0].name, il.add(4, dste, src)))
				continue
			if token.startswith("=["):
				sz = int(token[2:-1])
				dst = popr()
				src = popr()
				il.append(il.store(sz, dst, src))
				continue
			if token.startswith("["):
				sz = int(token[1:-1])
				if sz == 1 or sz == 2:
					stack.append(il.zero_extend(4, il.load(sz, popr())))
				elif sz == 4:
					stack.append(il.load(4, popr()))
				else:
					raise ValueError("Invalid load size {0}".format(sz))
				continue
			# Base 16 constants
			try:
				i = int(token, 16)
			except ValueError:
				pass
			else:
				stack.append(il.const(4, i))
				continue
			# Base 10 constants
			try:
				i = int(token)
			except ValueError:
				pass
			else:
				stack.append(il.const(4, i))
				continue

			# Hack to support branch instructions
			if token == "?{":
				t = None
				set_t = False
				end = parts.index("}", i+1)

				f = None
				# Don't create useless labels if this is at the end
				# of the instruction (e.g. a branch)
				if end == len(parts)-1:
					f = self.force_label(il, addr+l)
				if f is None:
					f = LowLevelILLabel()
					label_stack.append(f)

				inner = parts[i+1:end]

				fakeil = ThreaderILDuck()
				try:
					self.esil_to_llil(inst, inner, fakeil, addr, l)
				except AttributeError as e:
					pass
				except IndexError as e: # Tried to access the stack outside! Bad!
					pass
				except Exception as e:
					log.log_error("{0} {1}".format(e, inner))
					raise e
				else:
					if fakeil.target is not None:
						t = self.force_label(il, fakeil.target)
#						log.log_info("Prediction successful at {0:X}, {1}, {2:X} {3} {4}".format(addr, inner, fakeil.target, t, parts))
#					else:
#						log.log_warn("Prediction succesful but no target {0} {1}".format(inner, parts))

				if t is None:
					set_t = True
					t = LowLevelILLabel()

				il.append(il.if_expr(stack.pop(), t, f))
				if set_t:
					il.mark_label(t)
				elif len(label_stack) == 0:
					break
				else:
					skip_to_close = True
				continue

			if token == "}":
				if len(label_stack) == 0: break
				il.mark_label(label_stack.pop())
				skip_to_close = False
				continue

			raise ValueError("Unimplemented esil {0} in {1} for {2}".format(token, esil, inst))
Пример #15
0
	def get_instruction_low_level_il(self, data, addr, il):
		locals = threading.local()
		inst,args = self._get_asm(data, addr)
		if inst == "ill":
			return None
		l = self._inst_length(inst)

		if inst in ("jx"):
			if args[0] in self.regs:
				il.append(il.jump(il.reg(4, args[0])))
			else:
				self.goto_or_jmp(il, int(args[0], 16))
			return l
		elif inst.startswith("call"):
			spilled_regs = int(inst[5 if inst.startswith("callx") else 4:])
			# Spill onto stack
			a = lambda a: "a{0}".format(a)
			r = lambda r: il.reg(4, "a{0}".format(r))
#			if spilled_regs != 0:
#				for i in range(spilled_regs):
#					il.append(il.push(4, r(i)))
#				for i in range(spilled_regs, 16):
#					il.append(il.set_reg(4, a(i-spilled_regs), r(i)))
			if spilled_regs != 0 and self.VERBOSE_IL:
				il.append(il.set_reg(1, "PS.CALLINC", il.const(1, spilled_regs)))
			# return address
#			il.append(il.set_reg(4, a(spilled_regs), il.const(4, addr + l)))
			target = il.reg(4, args[0]) if inst.startswith("callx") else il.const_pointer(4, int(args[0], 16))
			il.append(il.call(target))
			# unspill from stack
#			if spilled_regs != 0:
#				for i in range(15, spilled_regs-1, -1):
#					il.append(il.set_reg(4, a(i), r(i-spilled_regs)))
#				for i in range(spilled_regs-1, -1, -1):
#					il.append(il.set_reg(4, a(i), il.pop(4)))
			return l
		elif inst in ("ret", "retw", "ret.n", "retw.n"):
			il.append(il.ret(il.reg(4, "a0")))
			return l
		elif inst == "j":
			il.append(il.jump(il.const_pointer(4, int(args[0], 16))))
			return l
		elif inst in ("loopgtz", "loopnez", "loop"):
			lbegin = addr + l
			lend = int(args[1], 16)
			r = il.reg(4, args[0])
			lcount = il.sub(4, r, il.const(4,1))
			# lend must come before lbegin for loop detection to work lower down
			if self.VERBOSE_IL:
				il.append(il.set_reg(4, "lend", il.const_pointer(4, lend)))
				il.append(il.set_reg(4, "lbegin", il.const_pointer(4, lbegin)))
				il.append(il.set_reg(4, "lcount", lcount))
			if inst in ("loopgtz", "loopnez"):
				t = self.force_label(il, lbegin)
				f = self.force_label(il, lend)
				set_t = False
				set_f = False
				if t is None:
					set_t = True
					t = LowLevelILLabel()
				if f is None:
					set_f = True
					f = LowLevelILLabel()
				if inst == "loopnez":
					cond = il.compare_unsigned_greater_equal(4, r, il.const(4, 0))
				else:
					cond = il.compare_signed_greater_equal(4, r, il.const(4, 0))
				il.append(il.if_expr(cond, t, f))
				if set_f:
					il.mark_label(f)
					self.goto_or_jmp(il, lend)
				if set_t:
					il.mark_label(t)
					# fallthrough

			with self._looplock:
				self.loops[lend] = lbegin
			return l
		elif inst == "entry":
			# Entry doesn't *do* anything, basically
			il.append(il.intrinsic([], "entry", []))
			return l
		elif inst == "memw":
			il.append(il.intrinsic([], "memw", []))
			return l
		# override buggy l32r in radare
		elif inst == "l32r" and LITBASE & 0x1 == 1:
			a,b = self._decode_l32r(LITBASE, addr, data)
			il.append(il.set_reg(4, a, il.load(4, il.const_pointer(4, b))))
			return l

		esil = self._get_esil(data[0:l], addr)
		if esil == "":
			il.append(il.unimplemented())
			return l
		parts = esil.split(",")

		# For basic instructions, interpret the ESIL
		self.esil_to_llil(inst, parts, il, addr, l)

		# Scan the function for loop instructions pointing to here
		lbegin = None
		with self._looplock:
			n = addr + l
			if n in self.loops:
				lbegin = self.loops[n]
		if lbegin is not None:
			cond = il.compare_unsigned_greater_than(4, il.reg(4, "lcount"), il.const(4, 0))
			f = self.force_label(il, n)
			t = self.force_label(il, lbegin) #il.get_label_for_address(self, lbegin)
			set_f = False
			set_t = False
			if f is None:
				set_f = True
				f = LowLevelILLabel()
			if t is None:
				set_t = True
				t = LowLevelILLabel()

			il.append(il.if_expr(cond, t, f))
			if set_t:
				il.mark_label(t)
				self.goto_or_jmp(il, lbegin)
			if set_f:
				il.mark_label(f)
				# fallthrough
		return l