Esempio n. 1
0
    def set_instruction(self, instruction):
        self.length = instruction.length
        self.type = instruction.type
        self.mode = instruction.mode
        self.opcode = instruction.opcode
        self.modrm = instruction.modrm
        self.sib = instruction.sib
        self.extindex = instruction.extindex
        self.fpuindex = instruction.fpuindex
        self.dispbytes = instruction.dispbytes
        self.immbytes = instruction.immbytes
        self.sectionbytes = instruction.sectionbytes
        self.flags = instruction.flags

        if instruction.op1.type:
            self.op1 = PyOperand(instruction.op1)

        if instruction.op2.type:
            self.op2 = PyOperand(instruction.op2)

        if instruction.op3.type:
            self.op3 = PyOperand(instruction.op3)

        # Disassembly string of instruction
        self.disasm = pydasm.get_instruction_string(instruction, pydasm.FORMAT_INTEL, 0x0).rstrip(" ")
        self.mnemonic = pydasm.get_mnemonic_string(instruction, pydasm.FORMAT_INTEL).rstrip(" ")
Esempio n. 2
0
    def set_instruction(self, instruction):
        self.length = instruction.length
        self.type = instruction.type
        self.mode = instruction.mode
        self.opcode = instruction.opcode
        self.modrm = instruction.modrm
        self.sib = instruction.sib
        self.extindex = instruction.extindex
        self.fpuindex = instruction.fpuindex
        self.dispbytes = instruction.dispbytes
        self.immbytes = instruction.immbytes
        self.sectionbytes = instruction.sectionbytes
        self.flags = instruction.flags

        #
        # In the future we'll use a PyOperand class, for now its to slow
        #        
        if instruction.op1.type:
            self.op1 = instruction.op1
        if instruction.op2.type:
            self.op2 = instruction.op2
        if instruction.op3.type:
            self.op3 = instruction.op3
        
        self.mnemonic = pydasm.get_mnemonic_string(instruction, pydasm.FORMAT_INTEL).rstrip(" ")
Esempio n. 3
0
def find_gadget_ends(start_ea, end_ea):
    gadget_end_addresses = []
    for opcode_byte in gadget_ends:
        ea = start_ea
        while True:
            ea = inp.code_search(ea, opcode_byte)
            if ea > end_ea or ea == None:
                break
            if inp.byte_at(ea) != 0xFF:
                gadget_end_addresses.append(ea)
            else:
                # An opcode starting with 0xFF is not necessarily an indirect jmp/call
                bytes_ahead = 10  # TODO should be smaller, probably 3, should check
                headroom = inp.seg_end(ea) - ea
                if 0 < headroom < 10:
                    bytes_ahead = headroom
                ibuf = inp.bytes_at(ea, bytes_ahead)
                if not ibuf:
                    print "WARNING: GetManyBytes(%.08X, %d) failed " % (
                        ea, bytes_ahead)
                instr = pydasm.get_instruction(ibuf, pydasm.MODE_32)
                if (instr and pydasm.get_mnemonic_string(
                        instr, pydasm.FORMAT_INTEL) in ("call", "jmp")
                        and (instr.op1.reg != 8 or instr.op1.basereg != 8
                             or instr.op1.indexreg != 8)):
                    gadget_end_addresses.append(ea)
            ea += 1
    return gadget_end_addresses
Esempio n. 4
0
 def set_instruction(self, instruction):
     self.length = instruction.length
     self.type = instruction.type
     self.mode = instruction.mode
     self.opcode = instruction.opcode
     self.modrm = instruction.modrm
     self.sib = instruction.sib
     self.extindex = instruction.extindex
     self.fpuindex = instruction.fpuindex
     self.dispbytes = instruction.dispbytes
     self.immbytes = instruction.immbytes
     self.sectionbytes = instruction.sectionbytes
     self.flags = instruction.flags
     
     if instruction.op1.type:
         self.op1 = PyOperand(instruction.op1)
         
     if instruction.op2.type:
         self.op2 = PyOperand(instruction.op2)
         
     if instruction.op3.type:
         self.op3 = PyOperand(instruction.op3)
     
     # Disassembly string of instruction
     self.disasm = pydasm.get_instruction_string(instruction, pydasm.FORMAT_INTEL, 0x0).rstrip(" ")
     self.mnemonic = pydasm.get_mnemonic_string(instruction, pydasm.FORMAT_INTEL).rstrip(" ")
Esempio n. 5
0
    def __init__(self, instruction, rawinstruction, eip):
        self.length = instruction.length
        self.type = instruction.type
        self.mode = instruction.mode
        self.opcode = instruction.opcode
        self.modrm = instruction.modrm
        self.sib = instruction.sib
        self.extindex = instruction.extindex
        self.fpuindex = instruction.fpuindex
        self.dispbytes = instruction.dispbytes
        self.immbytes = instruction.immbytes
        self.sectionbytes = instruction.sectionbytes
        self.flags = instruction.flags

        self.eip = eip
        self.raw = rawinstruction[0:self.length]
        self.mnemonic = pydasm.get_mnemonic_string(
            instruction, pydasm.FORMAT_INTEL).rstrip(" ")
        self.disasm = pydasm.get_instruction_string(instruction,
                                                    pydasm.FORMAT_INTEL,
                                                    self.eip).rstrip(" ")
        self.description = ''

        self.op1 = ''
        self.op2 = ''
        self.op3 = ''
        #
        # In the future we'll use a PyOperand class, for now its to slow
        #
        if instruction.op1.type:
            self.op1 = instruction.op1
        if instruction.op2.type:
            self.op2 = instruction.op2
        if instruction.op3.type:
            self.op3 = instruction.op3
Esempio n. 6
0
    def __init__(self, instruction, rawinstruction, eip):
        self.length = instruction.length
        self.type = instruction.type
        self.mode = instruction.mode
        self.opcode = instruction.opcode
        self.modrm = instruction.modrm
        self.sib = instruction.sib
        self.extindex = instruction.extindex
        self.fpuindex = instruction.fpuindex
        self.dispbytes = instruction.dispbytes
        self.immbytes = instruction.immbytes
        self.sectionbytes = instruction.sectionbytes
        self.flags = instruction.flags

        self.eip = eip
        self.raw = rawinstruction[0:self.length]
        self.mnemonic = pydasm.get_mnemonic_string(instruction, pydasm.FORMAT_INTEL).rstrip(" ")
        self.disasm = pydasm.get_instruction_string(instruction, pydasm.FORMAT_INTEL, self.eip).rstrip(" ")
        self.description = ''

        self.op1 = ''
        self.op2 = ''
        self.op3 = ''
        #
        # In the future we'll use a PyOperand class, for now its to slow
        #
        if instruction.op1.type:
            self.op1 = instruction.op1
        if instruction.op2.type:
            self.op2 = instruction.op2
        if instruction.op3.type:
            self.op3 = instruction.op3
Esempio n. 7
0
    def set_instruction(self, instruction):
        self.length = instruction.length
        self.type = instruction.type
        self.mode = instruction.mode
        self.opcode = instruction.opcode
        self.modrm = instruction.modrm
        self.sib = instruction.sib
        self.extindex = instruction.extindex
        self.fpuindex = instruction.fpuindex
        self.dispbytes = instruction.dispbytes
        self.immbytes = instruction.immbytes
        self.sectionbytes = instruction.sectionbytes
        self.flags = instruction.flags

        #
        # In the future we'll use a PyOperand class, for now its to slow
        #
        if instruction.op1.type:
            self.op1 = instruction.op1
        if instruction.op2.type:
            self.op2 = instruction.op2
        if instruction.op3.type:
            self.op3 = instruction.op3

        self.mnemonic = pydasm.get_mnemonic_string(
            instruction, pydasm.FORMAT_INTEL).rstrip(" ")
Esempio n. 8
0
def find_gadget_ends(start_ea, end_ea):
    gadget_end_addresses = []
    for opcode_byte in gadget_ends:
        ea = start_ea
        while True:
            ea = inp.code_search(ea, opcode_byte)
            if ea > end_ea or ea == None:
                break
            if inp.byte_at(ea) != 0xFF:
                gadget_end_addresses.append(ea)
            else:
                # An opcode starting with 0xFF is not necessarily an indirect jmp/call
                bytes_ahead = 10  # TODO should be smaller, probably 3, should check
                headroom = inp.seg_end(ea) - ea
                if 0 < headroom < 10:
                    bytes_ahead = headroom
                ibuf = inp.bytes_at(ea, bytes_ahead)
                if not ibuf:
                    print "WARNING: GetManyBytes(%.08X, %d) failed " % (ea, bytes_ahead)
                instr = pydasm.get_instruction(ibuf, pydasm.MODE_32)
                if (instr and
                            pydasm.get_mnemonic_string(instr, pydasm.FORMAT_INTEL) in ("call", "jmp") and
                        (instr.op1.reg != 8 or instr.op1.basereg != 8 or instr.op1.indexreg != 8)):
                    gadget_end_addresses.append(ea)
            ea += 1
    return gadget_end_addresses
Esempio n. 9
0
 def __init__(self, ea, bytes, spd):
     self.addr = ea
     self.bytes = bytes
     # copy whatever we need from the pydasm instruction object
     inst = pydasm.get_instruction(bytes, pydasm.MODE_32)
     if inst == None:
         print "IGNORE:", hex(ea), ''.join(
             ('\\x%02x' % ord(b) for b in bytes))
         inst = nop
     self.disas = pydasm.get_instruction_string(inst, pydasm.FORMAT_INTEL,
                                                ea)
     self.mnem = pydasm.get_mnemonic_string(inst, pydasm.FORMAT_INTEL)
     self.type = inst.type
     self.modrm_off = inst.modrm_offset
     self.opc_off = inst.opcode_offset
     self.eflags_r = inst.eflags_used
     self.eflags_w = inst.eflags_affected
     self.uses_sib = False
     self.inst_len = inst.length - inst.opcode_offset  # no prefixes!!
     self.spd = spd  # stack pointer delta
     self.pos = -1  # instruction position after ordering
     self.raddr = ea  # address after reordering (if changed)
     self.implicit = set()  # registers used implicitly by this instruction
     self.f_entry = False  # whether the instruction is a function entry point
     self.f_exit = inst.type == pydasm.INSTRUCTION_TYPE_RET
     self.regs = dict()  # holds bit positions in the instruction per reg
     self.updated = False  # for call instr, tells whether it was updated
     self.can_change = set()  # registers that can change in a indirect call
     # these copies of bytes and regs are initialized by reset_changed
     self.cregs = None
     self.cbytes = None
     self.creg_names = None
     # liveness information
     self.succ = set()  # list of successor instruction addresses
     self.USE = set()  # regs used (read) by this instruction
     self.DEF = set()  # regs defined (written) by this instruction
     self.IN = set()  # regs that are live before instruction execution
     self.OUT = set()  # regs that are live after instruction execution
     self.IN_old = None
     self.OUT_old = None
     # TODO: special case for lea optimization (3 operands)
     self._get_use_def(inst)
     self._store_operands(inst)
     self.reset_changed()
Esempio n. 10
0
 def __init__(self, ea, bytes, spd):
     self.addr = ea
     self.bytes = bytes
     # copy whatever we need from the pydasm instruction object
     inst = pydasm.get_instruction(bytes, pydasm.MODE_32)
     if inst == None:
         print "IGNORE:", hex(ea), ''.join(('\\x%02x' % ord(b) for b in bytes))
         inst = nop
     self.disas = pydasm.get_instruction_string(
         inst, pydasm.FORMAT_INTEL, ea)
     self.mnem = pydasm.get_mnemonic_string(inst, pydasm.FORMAT_INTEL)
     self.type = inst.type
     self.modrm_off = inst.modrm_offset
     self.opc_off = inst.opcode_offset
     self.eflags_r = inst.eflags_used
     self.eflags_w = inst.eflags_affected
     self.uses_sib = False
     self.inst_len = inst.length - inst.opcode_offset  # no prefixes!!
     self.spd = spd  # stack pointer delta
     self.pos = -1  # instruction position after ordering
     self.raddr = ea  # address after reordering (if changed)
     self.implicit = set()  # registers used implicitly by this instruction
     self.f_entry = False  # whether the instruction is a function entry point
     self.f_exit = inst.type == pydasm.INSTRUCTION_TYPE_RET
     self.regs = dict()  # holds bit positions in the instruction per reg
     self.updated = False  # for call instr, tells whether it was updated
     self.can_change = set()  # registers that can change in a indirect call
     # these copies of bytes and regs are initialized by reset_changed
     self.cregs = None
     self.cbytes = None
     self.creg_names = None
     # liveness information
     self.succ = set()  # list of successor instruction addresses
     self.USE = set()  # regs used (read) by this instruction
     self.DEF = set()  # regs defined (written) by this instruction
     self.IN = set()  # regs that are live before instruction execution
     self.OUT = set()  # regs that are live after instruction execution
     self.IN_old = None
     self.OUT_old = None
     # TODO: special case for lea optimization (3 operands)
     self._get_use_def(inst)
     self._store_operands(inst)
     self.reset_changed()
Esempio n. 11
0
    def swap_registers(self, r1, r2):
        """Swaps the registers of the instruction and checks if the resulting one
        is correct. Returns False if the resulting instruction is wrong or if the
        instruction was unchanged. On success, 'cregs' and 'cbytes' are updated
        accordingly."""
        def update_bits(r1, r2, bytes, cregs):
            for byte_off, bit_off in cregs[r1]:
                # print map(bin, bytes)
                clear_mask = ~(0b111 << bit_off)
                bytes[byte_off] &= clear_mask
                # print map(bin, bytes)
                set_mask = REGS.index(r2) << bit_off
                bytes[byte_off] |= set_mask
                # print map(bin, bytes)
            return

        # translate register names XXX out for now ..
        # print 'translate:', r1, r2, '->',
        # r1 = self.creg_names[r1] if r1 in self.creg_names else r1
        # r2 = self.creg_names[r2] if r2 in self.creg_names else r2
        # print r1, r2

        # check if the swap is feasible
        bytes = self.cbytes[:]
        if r1 in self.cregs:
            update_bits(r1, r2, bytes, self.cregs)
        if r2 in self.cregs:
            update_bits(r2, r1, bytes, self.cregs)

        # illegal modrm/sip states
        if self.modrm_off:
            mod = pydasm.MASK_MODRM_MOD(bytes[self.modrm_off])
            prev_rm = pydasm.MASK_MODRM_RM(self.cbytes[self.modrm_off])
            rm = pydasm.MASK_MODRM_RM(bytes[self.modrm_off])
            if mod == 0b00 and (prev_rm == 0b101
                                or rm == 0b101) and prev_rm != rm:
                # print "modrm case 1:", self.disas, "|", r1, r2
                return False
            if (0b00 <= mod <= 0b10 and (prev_rm == 0b100 or rm == 0b100)
                    and prev_rm != rm):
                # print "modrm case 2:", self.disas, "|", r1, r2
                return False
            if self.uses_sib:
                idx = pydasm.MASK_SIB_INDEX(bytes[self.modrm_off + 1])
                prev_idx = pydasm.MASK_SIB_INDEX(self.cbytes[self.modrm_off +
                                                             1])
                if (prev_idx == 0b100 or idx == 0b100) and prev_idx != idx:
                    # print "sib case 1:", self.disas, "|", r1, r2
                    return False
                base = pydasm.MASK_SIB_BASE(bytes[self.modrm_off + 1])
                prev_base = pydasm.MASK_SIB_BASE(self.cbytes[self.modrm_off +
                                                             1])
                # XXX: there is a special sub-case here.. we can swap base with index..
                if (mod == 0b00 and (prev_base == 0b101 or base == 0b101)
                        and prev_base != base):
                    # print "sib case 2:", self.disas, "|", r1, r2
                    return False

        # check if the newly created instruction can be decoded properly
        inst = pydasm.get_instruction(str(bytes), pydasm.MODE_32)
        if not inst:
            print hex(self.addr), "cant swap (", r1, r2, ")", self.disas
            return False
        # check if the mnemonic changed
        new_mnem = pydasm.get_mnemonic_string(inst, pydasm.FORMAT_INTEL)
        if self.mnem != new_mnem:
            print hex(
                self.addr), "cant swap (", r1, r2, ")", self.disas, new_mnem
            return False
        # check if the register names are the intended ones (8-bit accesses)
        # example: (esi <-> ebx) 'test bl, bl' -> 'test dh, dh' !!!!
        orig = pydasm.get_instruction(self.bytes, pydasm.MODE_32)
        for op in (orig.op1, orig.op2, orig.op3):
            if (op.type == pydasm.OPERAND_TYPE_REGISTER and  # register
                    pydasm.MASK_OT(op.flags) == pydasm.OT_b
                    and  # 8-bit (al, dl..)
                    REGS[op.reg] in (r1, r2) and  # swapped
                    set((r1, r2)) - set(
                        (REGS[op.reg], )) & set(REGS[4:])):  # with (esi..)
                return False

        # extend with NOPs
        # FIXME: manualy check if eax is dest and the instruction can be compressed
        # for i in range(inst.length, len(bytes)):
        #  bytes[i] = "\x90"
        # apply the swap!
        if r1 in self.cregs and r2 in self.cregs:
            tmp = self.cregs[r1]
            self.cregs[r1] = self.cregs[r2]
            self.cregs[r2] = tmp
        elif r1 in self.cregs:
            self.cregs[r2] = self.cregs[r1]
            del self.cregs[r1]
        elif r2 in self.cregs:
            self.cregs[r1] = self.cregs[r2]
            del self.cregs[r2]
        self.cbytes = bytes

        # update register names XXX: leave translation out for now ..
        # self.creg_names[r1] = r2
        # self.creg_names[r2] = r1
        # print 'update:', r1, r2, '->', self.creg_names[r1], self.creg_names[r2]
        # print self.disas, "->", pydasm.get_instruction_string(inst, pydasm.FORMAT_INTEL, self.addr)
        return True
Esempio n. 12
0
    def swap_registers(self, r1, r2):
        """Swaps the registers of the instruction and checks if the resulting one
        is correct. Returns False if the resulting instruction is wrong or if the
        instruction was unchanged. On success, 'cregs' and 'cbytes' are updated
        accordingly."""

        def update_bits(r1, r2, bytes, cregs):
            for byte_off, bit_off in cregs[r1]:
                # print map(bin, bytes)
                clear_mask = ~(0b111 << bit_off)
                bytes[byte_off] &= clear_mask
                # print map(bin, bytes)
                set_mask = REGS.index(r2) << bit_off
                bytes[byte_off] |= set_mask
                # print map(bin, bytes)
            return

        # translate register names XXX out for now ..
        # print 'translate:', r1, r2, '->',
        # r1 = self.creg_names[r1] if r1 in self.creg_names else r1
        # r2 = self.creg_names[r2] if r2 in self.creg_names else r2
        # print r1, r2

        # check if the swap is feasible
        bytes = self.cbytes[:]
        if r1 in self.cregs:
            update_bits(r1, r2, bytes, self.cregs)
        if r2 in self.cregs:
            update_bits(r2, r1, bytes, self.cregs)

        # illegal modrm/sip states
        if self.modrm_off:
            mod = pydasm.MASK_MODRM_MOD(bytes[self.modrm_off])
            prev_rm = pydasm.MASK_MODRM_RM(self.cbytes[self.modrm_off])
            rm = pydasm.MASK_MODRM_RM(bytes[self.modrm_off])
            if mod == 0b00 and (prev_rm == 0b101 or rm == 0b101) and prev_rm != rm:
                # print "modrm case 1:", self.disas, "|", r1, r2
                return False
            if (0b00 <= mod <= 0b10 and (prev_rm == 0b100 or rm == 0b100) and
                        prev_rm != rm):
                # print "modrm case 2:", self.disas, "|", r1, r2
                return False
            if self.uses_sib:
                idx = pydasm.MASK_SIB_INDEX(bytes[self.modrm_off + 1])
                prev_idx = pydasm.MASK_SIB_INDEX(self.cbytes[self.modrm_off + 1])
                if (prev_idx == 0b100 or idx == 0b100) and prev_idx != idx:
                    # print "sib case 1:", self.disas, "|", r1, r2
                    return False
                base = pydasm.MASK_SIB_BASE(bytes[self.modrm_off + 1])
                prev_base = pydasm.MASK_SIB_BASE(self.cbytes[self.modrm_off + 1])
                # XXX: there is a special sub-case here.. we can swap base with index..
                if (mod == 0b00 and (prev_base == 0b101 or base == 0b101) and
                            prev_base != base):
                    # print "sib case 2:", self.disas, "|", r1, r2
                    return False

        # check if the newly created instruction can be decoded properly
        inst = pydasm.get_instruction(str(bytes), pydasm.MODE_32)
        if not inst:
            print hex(self.addr), "cant swap (", r1, r2, ")", self.disas
            return False
        # check if the mnemonic changed
        new_mnem = pydasm.get_mnemonic_string(inst, pydasm.FORMAT_INTEL)
        if self.mnem != new_mnem:
            print hex(self.addr), "cant swap (", r1, r2, ")", self.disas, new_mnem
            return False
        # check if the register names are the intended ones (8-bit accesses)
        # example: (esi <-> ebx) 'test bl, bl' -> 'test dh, dh' !!!!
        orig = pydasm.get_instruction(self.bytes, pydasm.MODE_32)
        for op in (orig.op1, orig.op2, orig.op3):
            if (op.type == pydasm.OPERAND_TYPE_REGISTER and  # register
                        pydasm.MASK_OT(op.flags) == pydasm.OT_b and  # 8-bit (al, dl..)
                        REGS[op.reg] in (r1, r2) and  # swapped
                            set((r1, r2)) - set((REGS[op.reg],)) & set(REGS[4:])):  # with (esi..)
                return False

        # extend with NOPs
        # FIXME: manualy check if eax is dest and the instruction can be compressed
        # for i in range(inst.length, len(bytes)):
        #  bytes[i] = "\x90"
        # apply the swap!
        if r1 in self.cregs and r2 in self.cregs:
            tmp = self.cregs[r1]
            self.cregs[r1] = self.cregs[r2]
            self.cregs[r2] = tmp
        elif r1 in self.cregs:
            self.cregs[r2] = self.cregs[r1]
            del self.cregs[r1]
        elif r2 in self.cregs:
            self.cregs[r1] = self.cregs[r2]
            del self.cregs[r2]
        self.cbytes = bytes

        # update register names XXX: leave translation out for now ..
        # self.creg_names[r1] = r2
        # self.creg_names[r2] = r1
        # print 'update:', r1, r2, '->', self.creg_names[r1], self.creg_names[r2]
        # print self.disas, "->", pydasm.get_instruction_string(inst, pydasm.FORMAT_INTEL, self.addr)
        return True
Esempio n. 13
0
def is_branch(insn):
    # One of the branch types or an IRET
    return (insn.type in x86_branches
            or pydasm.get_mnemonic_string(insn, pydasm.FORMAT_INTEL) == 'iret'
            or pydasm.get_mnemonic_string(insn,
                                          pydasm.FORMAT_INTEL) == 'sysexit')
Esempio n. 14
0
def is_branch(insn):
    # One of the branch types or an IRET
    return (insn.type in x86_branches 
             or pydasm.get_mnemonic_string(insn, pydasm.FORMAT_INTEL) == 'iret'
             or pydasm.get_mnemonic_string(insn, pydasm.FORMAT_INTEL) == 'sysexit')