def modify_immediate(self, inst, immediate):
     """
     Modify the immediate in an instruction
     :param inst: Instruction to modify
     :param inmediate: The new Immediate
     :return:
     """
     if inst & 0xE000000 == 0x4000000:
         return Bits.copy_bits(immediate, inst, 0, 11, 0)
     else:
         return Bits.copy_bits(immediate, inst, 0, 7, 0)
 def jumping_address(self):
     if self._jumping_address is None:
         # On the other hand, one can compute the jumping address
         address = self.encoding & Bits.set(23, 0)
         if Bits.is_on(address, 23):
             address |= Bits.set(29, 24)
         address = (address << 2)
         address += self.address + 8
         address &= 0xffffffff
         self._jumping_address = address
     return self._jumping_address
示例#3
0
class AOpType(object):
    """
    ARM Opcodes types. The cryptic AOpType name is to have short code
    """
    ALWAYS = Bits.set(31, 29)
    COND_ALWAYS = 0b1110

    LOAD_STORE_MULTIPLE = Bits.on(27)
    LOAD_STORE = Bits.on(26)
    LOAD_STORE_OFFSET = Bits.set(26, 25)
    SOFT_INTERRUPT = 0xF000000
    BRANCH = 0xA000000
    DATA_PROCESSING = 0x0
    DATA_PROCESSING_IMMEDIATE = 0x2000000
示例#4
0
 def _get_register_list(encoding, result=None):
     if not result:
         result = []
     for x in range(0, 16):
         if Bits.is_on(encoding, x) and x not in result:
             result.append(x)
     return result
示例#5
0
 def jumping_address(self):
     """
     Jumping address for branching instructions
     """
     if self.is_branch:
         if self._jumping_address is None:
             # On the other hand, one can compute the jumping address
             address = self.encoding & Bits.set(23, 0)
             if Bits.is_on(address, 23):
                 address |= Bits.set(29, 24)
             address = (address << 2)
             address += self.address + 8
             address &= 0xffffffff
             self._jumping_address = address
         return self._jumping_address
     return None
示例#6
0
def corrupt_bits(hi, lo, amount, instruction):
    """
    Corrupt the bits in an instruction by fliping bits around
    :param hi: Corruption bit start
    :param lo:  Corruption bit end
    :param amount: Number of bits to corrupt
    :param instruction: Instruction to corrupt
    :return: Returns the original instruction, as well as all the others resulting from the corruption
    """
    # Generate random positions
    result, bits = [instruction], []
    while len(bits) < amount:
        x = random.randint(lo, hi)
        if x not in bits:
            bits.append(x)

    for i in range(1, 2**amount):
        noise, j, m = 0, 1, math.log(i, 2) + 1
        while j <= m:
            noise += Bits.on(bits[j - 1]) if j & i else 0
            j <<= 1
        noised = instruction ^ noise
        if noised not in result:
            result.append(noised)
    return result
 def modify_opcode(self, inst, new_cond):
     """
     Modifies an instructions conditional
     :param inst: Instruction to modify
     :param new_cond: New conditional
     :return: The modified instruction
     """
     return Bits.copy_bits(new_cond, inst, 0, 3, 21)
 def modify_rn(self, encoding, rn):
     """
     Modifies the Rn register in an instruction
     :param encoding: Instruction to modify
     :param Rn: The new register
     :return: The modified instruction
     """
     return Bits.copy_bits(rn, encoding, 0, 3, 16)
 def modify_rm(self, inst, rs):
     """
     Modifies the Rd register in an instruction
     :param inst: Instruction to modify
     :param Rd: The new register
     :return: The modified instruction
     """
     return Bits.copy_bits(rs, inst, 0, 3, 0)
示例#10
0
 def test_copy_bits(self):
     # Some numbers with bit patterns
     a = 65295
     b = 3840
     c = 4080
     # Given these patterns, if we copy some bits from a to b, b should be equal to c
     b = Bits.copy_bits(a, b, 8, 11, 4)
     self.assertEqual(b, c)
示例#11
0
 def opcode_field(self):
     """
     Return the instruction part of the opcode for an ARM instruction (See the 'ARM ARM')
     :return: A number with the instruction part
     """
     t = self.opcode_type()
     if t in [AOpType.BRANCH, AOpType.SOFT_INTERRUPT]:
         return t
     return self.encoding & Bits.set(24, 21)
示例#12
0
 def test_corrupt_bits(self):
     # ldr	r5, [pc, #44]
     corrupted = corrupt_bits(31, 28, 2, 0xe59f502c)
     self.assertEqual(4, len(corrupted))
     mask = Bits.set(31, 28)
     self.assertTrue(corrupted[0] & mask == AOpType.ALWAYS)
     self.assertFalse(corrupted[1] & mask == AOpType.ALWAYS)
     self.assertFalse(corrupted[2] & mask == AOpType.ALWAYS)
     self.assertFalse(corrupted[3] & mask == AOpType.ALWAYS)
示例#13
0
 def test_corrupt_conditional(self):
     # ldr	r5, [pc, #44]
     corrupted = corrupt_conditional(2, 0xe59f502c)
     self.assertEqual(4, len(corrupted))
     mask = Bits.set(31, 28)
     self.assertTrue((corrupted[0] & mask) == AOpType.ALWAYS)
     self.assertFalse((corrupted[1] & mask) == AOpType.ALWAYS,
                      "{:b} - {:b}".format(corrupted[1], AOpType.ALWAYS))
     self.assertFalse((corrupted[2] & mask) == AOpType.ALWAYS,
                      "{:b} - {:b}".format(corrupted[2], AOpType.ALWAYS))
     self.assertFalse((corrupted[3] & mask) == AOpType.ALWAYS,
                      "{:b} - {:b}".format(corrupted[3], AOpType.ALWAYS))
示例#14
0
def corrupt_all_bits_tuples(tuples, instruction):
    """
    Corrupt all the bits expressed as a list of (hi, lo) tuples in a given instruction.
    Lazy me, this routine assumes that the hi and lo bits of the tuples do not intersect, i.e. having tuples
    like (0, 2) and (1, 3) which intersects in 1 and 2 produces unexpected results
    :param tuples: Bits to corrupt
    :param instruction: Instruction to corrupt
    :return: the list of corrupted instructions
    """
    size = 0
    for t in tuples:
        l, h = t
        Bits.check_range(l, h)
        size += h - l
    result = [instruction] * (2**size)
    kk = 1
    for t in tuples:
        l, h = t
        for i in range(l, h):
            for k in range(0, kk):
                result[kk + k] = result[k] ^ Bits.on(i)
            kk *= 2
    return result
示例#15
0
def corrupt_all_bits(lo, hi, instruction):
    """
    Corrupt all the bits from a given instruction from lo to hi bits
    :param hi: Hi bit to corrupt
    :param lo: Lo bit to corrupt
    :param instruction: Instruction to corrupt
    :return: the list of corrupted instructions
    """
    result = [instruction]
    for i in range(lo, hi):
        k = len(result)
        mask = Bits.on(i)
        for j in range(0, k):
            masked = result[j] ^ mask
            if masked not in result:
                result.append(masked)

    return result
示例#16
0
    def registers_used(self):
        """
        Returns the registers that this instruction is using
        :return: A list of numbers each one containing the index of the register
        """
        result = []
        t = self.opcode_type()

        # Data processing instructions
        if t <= AOpType.DATA_PROCESSING_IMMEDIATE:
            # Get the Rn register
            result.append(self._rn_field_())

            # Certain instructions address two registers:
            op = self.opcode_field()
            if op in range(AOp.EOR,
                           AOp.RSC) or op in [AOp.AND, AOp.BIC, AOp.ORR]:
                result.append(self._rd_field_())

            # And others even three or four
            if t == AOpType.DATA_PROCESSING:
                result.append(self._rm_field_())
                if Bits.is_on(self.encoding, 4):
                    result.append(self._rs_field_())

        # Load and Store
        elif t in [AOpType.LOAD_STORE, AOpType.LOAD_STORE_OFFSET]:
            result.extend([self._rn_field_(), self._rd_field_()])
            if t == AOpType.LOAD_STORE_OFFSET:
                result.append(self._rm_field_())
        # Load and Store multiple
        elif t == AOpType.LOAD_STORE_MULTIPLE:
            result.append(self._rn_field_())
            result.extend(Instruction._get_register_list(self.encoding))

        return result
示例#17
0
 def _rd_field_(self):
     """
     Returns the Rd register field
     """
     return (self.encoding & Bits.set(15, 12)) >> 12
示例#18
0
 def test_set(self):
     self.assertEqual(0xE0000000, Bits.set(31, 29))
示例#19
0
 def test_on(self):
     self.assertEqual(2**31, Bits.on(31))
     self.assertTrue(1, Bits.on(0))
示例#20
0
 def test_is_on(self):
     self.assertTrue(Bits.is_on(0xE0000000, 31))
示例#21
0
 def test_are_on(self):
     self.assertTrue(Bits.are_on(0xE0000000, 31, 29))
     self.assertTrue(Bits.are_on(0xE0000000, 30, 29))
     self.assertTrue(Bits.are_on(0x000000FF, 6, 4))
     self.assertTrue(Bits.are_on(0x000000FF, 8, 0))
示例#22
0
 def is_branch_with_link(self):
     return self.is_branch and (self.encoding & Bits.on(24))
示例#23
0
 def _rn_field_(self):
     """
     Returns the Rn register field
     """
     return (self.encoding & Bits.set(19, 16)) >> 16
示例#24
0
 def _rs_field_(self):
     """
     Returns the Rd register field
     """
     return (self.encoding & Bits.set(11, 8)) >> 8