def test_arithmetic_simplify(self): cs = ConstraintSet() arr = cs.new_array(name="MEM") a = cs.new_bitvec(32, name="VARA") b = cs.new_bitvec(32, name="VARB") c = a * 2 + b self.assertEqual(translate_to_smtlib(c), "(bvadd (bvmul VARA #x00000002) VARB)") self.assertEqual( translate_to_smtlib((c + 4) - 4), "(bvsub (bvadd (bvadd (bvmul VARA #x00000002) VARB) #x00000004) #x00000004)", ) d = c + 4 s = arithmetic_simplify(d - c) self.assertIsInstance(s, Constant) self.assertEqual(s.value, 4) # size = arithmetic_simplify(size cs2 = ConstraintSet() exp = cs2.new_bitvec(32) exp |= 0 exp &= 1 exp |= 0 self.assertEqual(get_depth(exp), 4) self.assertEqual( translate_to_smtlib(exp), "(bvor (bvand (bvor BIVEC #x00000000) #x00000001) #x00000000)" ) exp = arithmetic_simplify(exp) self.assertTrue(get_depth(exp) < 4) self.assertEqual(translate_to_smtlib(exp), "(bvand BIVEC #x00000001)")
def testBasicArrayProxySymbIdx2(self): cs = ConstraintSet() array = cs.new_array(index_bits=32, value_bits=32, name="array") key = cs.new_bitvec(32, name="key") index = cs.new_bitvec(32, name="index") array[0] = 1 # Write 1 to first location array[key] = 2 # Write 2 to a symbolic (potentially any (potentially 0))location solutions = self.solver.get_all_values(cs, array[0]) # get a concrete solution for index self.assertItemsEqual(solutions, (1, 2)) solutions = self.solver.get_all_values( cs, array.get(0, 100) ) # get a concrete solution for index 0 self.assertItemsEqual(solutions, (1, 2)) solutions = self.solver.get_all_values( cs, array.get(1, 100) ) # get a concrete solution for index 1 (default 100) self.assertItemsEqual(solutions, (100, 2)) self.assertTrue( self.solver.can_be_true(cs, array[1] == 12345) ) # no default so it can be anything
def testBitvector_add2(self): cs = ConstraintSet() a = cs.new_bitvec(32) b = cs.new_bitvec(32) c = cs.new_bitvec(32) cs.add(11 == a + 10) self.assertTrue(self.solver.check(cs)) self.assertEqual(self.solver.get_value(cs, a), 1)
def test_addmod(self): """ (declare-fun BV () (_ BitVec 256)) (declare-fun BV_2 () (_ BitVec 256)) (declare-fun BV_1 () (_ BitVec 256)) (declare-fun a_1 () (_ BitVec 256))(assert (= a_1 (bvmul BV BV_1))) (declare-fun a_2 () (_ BitVec 512))(assert (= a_2 ((_ zero_extend 256) BV))) (declare-fun a_3 () (_ BitVec 512))(assert (= a_3 ((_ zero_extend 256) BV_1))) (declare-fun a_4 () (_ BitVec 512))(assert (= a_4 (bvmul a_2 a_3))) (declare-fun a_5 () (_ BitVec 512))(assert (= a_5 ((_ zero_extend 256) BV_2))) (declare-fun a_6 () (_ BitVec 512))(assert (= a_6 (bvsmod a_4 a_5))) (declare-fun a_7 () (_ BitVec 256))(assert (= a_7 ((_ extract 255 0) a_6))) (declare-fun a_8 () (_ BitVec 256))(assert (= a_8 (bvsmod a_1 BV_2))) (declare-fun a_9 () Bool)(assert (= a_9 (= a_7 a_8))) (assert (not a_9)) (check-sat) """ from manticore.platforms import evm from manticore.core.smtlib import ConstraintSet, Z3Solver, Operators constraints = ConstraintSet() address = 0x41414141414141414141 data = b"" caller = 0x42424242424242424242 value = 0 bytecode = "" vm = evm.EVM(constraints, address, data, caller, value, bytecode) self.assertEqual(vm.ADDMOD(12323, 2343, 20), 6) self.assertEqual(vm.ADDMOD(12323, 2343, 0), 0) A, B, C = ( 0x780000002090309A004201626B1400041D318000000200008A0080089C042DA7, 0xF000000740403F7007C012807BED003BE2CE800000060000FFFFBFF7E4087033, 0x338000080FFFFF64AAAACFFCF7DBFA408000000000000270120000001E7C2ACF, ) self.assertEqual( vm.ADDMOD(A, B, C), 23067954172474524581131069693479689311231082562138745684554374357070230297856, ) a, b, c = ( constraints.new_bitvec(256), constraints.new_bitvec(256), constraints.new_bitvec(256), ) constraints.add(a == A) constraints.add(b == B) constraints.add(c == C) result = vm.ADDMOD(a, b, c) # 0x32ffffd700d073ae080133f517d922bd000000000007f1611e003fffc9239d00 self.assertEqual( Z3Solver.instance().get_all_values(constraints, result), [ 0x32FFFFD700D073AE080133F517D922BD000000000007F1611E003FFFC9239D00 ], )
def testBitvector_add1(self): cs = ConstraintSet() a = cs.new_bitvec(32) b = cs.new_bitvec(32) c = cs.new_bitvec(32) cs.add(c == a + 10) cs.add(a == 1) self.assertEqual(self.solver.check(cs), True) self.assertEqual(self.solver.get_value(cs, c), 11)
def test_mulmod(self): """ (declare-fun BV () (_ BitVec 256)) (declare-fun BV_2 () (_ BitVec 256)) (declare-fun BV_1 () (_ BitVec 256)) (declare-fun a_1 () (_ BitVec 256))(assert (= a_1 (bvmul BV BV_1))) (declare-fun a_2 () (_ BitVec 512))(assert (= a_2 ((_ zero_extend 256) BV))) (declare-fun a_3 () (_ BitVec 512))(assert (= a_3 ((_ zero_extend 256) BV_1))) (declare-fun a_4 () (_ BitVec 512))(assert (= a_4 (bvmul a_2 a_3))) (declare-fun a_5 () (_ BitVec 512))(assert (= a_5 ((_ zero_extend 256) BV_2))) (declare-fun a_6 () (_ BitVec 512))(assert (= a_6 (bvsmod a_4 a_5))) (declare-fun a_7 () (_ BitVec 256))(assert (= a_7 ((_ extract 255 0) a_6))) (declare-fun a_8 () (_ BitVec 256))(assert (= a_8 (bvsmod a_1 BV_2))) (declare-fun a_9 () Bool)(assert (= a_9 (= a_7 a_8))) (assert (not a_9)) (check-sat) """ from manticore.platforms import evm from manticore.core.smtlib import ConstraintSet, Z3Solver, Operators constraints = ConstraintSet() address = 0x41414141414141414141 data = b"" caller = 0x42424242424242424242 value = 0 bytecode = "" vm = evm.EVM(constraints, address, data, caller, value, bytecode, gas=23000) self.assertEqual(vm.MULMOD(12323, 2343, 20), 9) self.assertEqual(vm.MULMOD(12323, 2343, 0), 0) A, B, C = ( 110427941548649020598956093796432407239217743554726184882600387580788736, 1048576, 4194319, ) self.assertEqual(vm.MULMOD(A, B, C), 2423129) a, b, c = ( constraints.new_bitvec(256), constraints.new_bitvec(256), constraints.new_bitvec(256), ) constraints.add(a == A) constraints.add(b == B) constraints.add(c == C) result = vm.MULMOD(a, b, c) # 0x8000000000000000000000000000000000000000000000000000000082000011 self.assertEqual( Z3Solver.instance().get_all_values(constraints, result), [2423129])
def test_cs_new_bitvec_invalid_size(self): cs = ConstraintSet() with self.assertRaises(ValueError) as e: cs.new_bitvec(size=0) self.assertEqual(str(e.exception), "Bitvec size (0) can't be equal to or less than 0") with self.assertRaises(ValueError) as e: cs.new_bitvec(size=-23) self.assertEqual(str(e.exception), "Bitvec size (-23) can't be equal to or less than 0")
def test_ITEBV_2(self): cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) c = cs.new_bitvec(8) cs.add(b == 0x44) cs.add(c == 0x44) cs.add(a == Operators.ITEBV(8, b == c, b, c)) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), 0x44)
def test_CONCAT(self): solver = self.solver cs = ConstraintSet() a = cs.new_bitvec(16) b = cs.new_bitvec(8) c = cs.new_bitvec(8) cs.add(b == 0x41) cs.add(c == 0x42) cs.add(a == Operators.CONCAT(a.size, b, c)) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), Operators.CONCAT(a.size, 0x41, 0x42))
def testBasicArraySymbIdx(self): cs = ConstraintSet() array = cs.new_array(index_bits=32, value_bits=32, name="array") key = cs.new_bitvec(32, name="key") index = cs.new_bitvec(32, name="index") array[key] = 1 # Write 1 to a single location cs.add(array.get(index, default=0) != 0) # Constrain index so it selects that location cs.add(index != key) # key and index are the same there is only one slot in 1 self.assertFalse(self.solver.check(cs))
def testBasicArrayProxySymbIdx(self): cs = ConstraintSet() array = cs.new_array(index_bits=32, value_bits=32, name="array", default=0) key = cs.new_bitvec(32, name="key") index = cs.new_bitvec(32, name="index") array[key] = 1 # Write 1 to a single location cs.add(array.get(index) != 0) # Constrain index so it selects that location a_index = self.solver.get_value(cs, index) # get a concrete solution for index cs.add(array.get(a_index) != 0) # now storage must have something at that location cs.add(a_index != index) # remove it from the solutions # It should not be another solution for index self.assertFalse(self.solver.check(cs))
def test_SREM(self): cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) c = cs.new_bitvec(8) d = cs.new_bitvec(8) cs.add(b == 0x86) #-122 cs.add(c == 0x11) #17 cs.add(a == Operators.SREM(b, c)) cs.add(d == b.srem(c)) cs.add(a == d) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), -3 & 0xFF)
def test_SDIV(self): solver = self.solver cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) c = cs.new_bitvec(8) d = cs.new_bitvec(8) cs.add(b == 0x86) # -122 cs.add(c == 0x11) # 17 cs.add(a == Operators.SDIV(b, c)) cs.add(d == (b // c)) cs.add(a == d) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), -7 & 0xFF)
def test_SAR(self): solver = self.solver A = 0xBADF00D for B in range(32): cs = ConstraintSet() a = cs.new_bitvec(32) b = cs.new_bitvec(32) c = cs.new_bitvec(32) cs.add(c == Operators.SAR(32, a, b)) cs.add(a == A) cs.add(b == B) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, c), Operators.SAR(32, A, B))
def test_UDIV(self): cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) c = cs.new_bitvec(8) d = cs.new_bitvec(8) cs.add(b == 0x86) #134 cs.add(c == 0x11) #17 cs.add(a == Operators.UDIV(b, c)) cs.add(d == b.udiv(c)) cs.add(a == d) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), 7)
def test_visitors(self): solver = Z3Solver.instance() cs = ConstraintSet() arr = cs.new_array(name="MEM") a = cs.new_bitvec(32, name="VAR") self.assertEqual(get_depth(a), 1) cond = Operators.AND(a < 200, a > 100) arr[0] = ord("a") arr[1] = ord("b") self.assertEqual(get_depth(cond), 3) self.assertEqual(get_depth(arr[a + 1]), 4) self.assertEqual( translate_to_smtlib(arr[a + 1]), "(select (store (store MEM #x00000000 #x61) #x00000001 #x62) (bvadd VAR #x00000001))", ) arr[3] = arr[a + 1] aux = arr[a + Operators.ZEXTEND(arr[a], 32)] self.assertEqual(get_depth(aux), 9) self.maxDiff = 1500 self.assertEqual( translate_to_smtlib(aux), "(select (store (store (store MEM #x00000000 #x61) #x00000001 #x62) #x00000003 (select (store (store MEM #x00000000 #x61) #x00000001 #x62) (bvadd VAR #x00000001))) (bvadd VAR ((_ zero_extend 24) (select (store (store (store MEM #x00000000 #x61) #x00000001 #x62) #x00000003 (select (store (store MEM #x00000000 #x61) #x00000001 #x62) (bvadd VAR #x00000001))) VAR))))", ) values = arr[0:2] self.assertEqual(len(values), 2) self.assertItemsEqual(solver.get_all_values(cs, values[0]), [ord("a")]) self.assertItemsEqual(solver.get_all_values(cs, values[1]), [ord("b")]) arr[1:3] = "cd" values = arr[0:3] self.assertEqual(len(values), 3) self.assertItemsEqual(solver.get_all_values(cs, values[0]), [ord("a")]) self.assertItemsEqual(solver.get_all_values(cs, values[1]), [ord("c")]) self.assertItemsEqual(solver.get_all_values(cs, values[2]), [ord("d")]) self.assertEqual( pretty_print(aux, depth=2), "ArraySelect\n ArrayStore\n ...\n BitVecAdd\n ...\n") self.assertEqual(pretty_print(Operators.EXTRACT(a, 0, 8), depth=1), "BitVecExtract{0:7}\n ...\n") self.assertEqual(pretty_print(a, depth=2), "VAR\n") x = BitVecConstant(32, 100, taint=("important", )) y = BitVecConstant(32, 200, taint=("stuff", )) z = constant_folder(x + y) self.assertItemsEqual(z.taint, ("important", "stuff")) self.assertEqual(z.value, 300) self.assertRaises(Exception, translate_to_smtlib, 1) self.assertEqual( translate_to_smtlib(simplify(Operators.ZEXTEND(a, 32))), "VAR") self.assertEqual( translate_to_smtlib( simplify(Operators.EXTRACT(Operators.EXTRACT(a, 0, 8), 0, 8))), "((_ extract 7 0) VAR)", )
def testBasicArrayStore(self): name = "bitarray" cs = ConstraintSet() # make array of 32->8 bits array = cs.new_array(32, name=name) # make free 32bit bitvector key = cs.new_bitvec(32) # assert that the array is 'A' at key position array = array.store(key, ord("A")) # let's restrict key to be greater than 1000 cs.add(key.ugt(1000)) # 1001 position of array can be 'A' self.assertTrue(self.solver.can_be_true(cs, array.select(1001) == ord("A"))) # 1001 position of array can be 'B' self.assertTrue(self.solver.can_be_true(cs, array.select(1001) == ord("B"))) # name is correctly proxied self.assertEqual(array.name, name) with cs as temp_cs: # but if it is 'B' ... temp_cs.add(array.select(1001) == ord("B")) # then key can not be 1001 temp_cs.add(key == 1001) self.assertFalse(self.solver.check(temp_cs)) with cs as temp_cs: # If 1001 position is 'B' ... temp_cs.add(array.select(1001) == ord("B")) # then key can be 1002 for ex.. temp_cs.add(key != 1002) self.assertTrue(self.solver.check(temp_cs))
def testBasicArray256(self): cs = ConstraintSet() # make array of 32->8 bits array = cs.new_array(32, value_bits=256) # make free 32bit bitvector key = cs.new_bitvec(32) # assert that the array is 111...111 at key position cs.add(array[key] == 11111111111111111111111111111111111111111111) # let's restrict key to be greater than 1000 cs.add(key.ugt(1000)) with cs as temp_cs: # 1001 position of array can be 111...111 temp_cs.add(array[1001] == 11111111111111111111111111111111111111111111) self.assertTrue(self.solver.check(temp_cs)) with cs as temp_cs: # 1001 position of array can also be 222...222 temp_cs.add(array[1001] == 22222222222222222222222222222222222222222222) self.assertTrue(self.solver.check(temp_cs)) with cs as temp_cs: # but if it is 222...222 ... temp_cs.add(array[1001] == 22222222222222222222222222222222222222222222) # then key can not be 1001 temp_cs.add(key == 1001) self.assertFalse(self.solver.check(temp_cs)) with cs as temp_cs: # If 1001 position is 222...222 ... temp_cs.add(array[1001] == 22222222222222222222222222222222222222222222) # then key can be 1002 for ex.. temp_cs.add(key == 1002) self.assertTrue(self.solver.check(temp_cs))
def test_CHR(self): cs = ConstraintSet() a = cs.new_bitvec(8) cs.add(Operators.CHR(a) == Operators.CHR(0x41)) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), 0x41)
def test_UREM(self): solver = Z3Solver.instance() cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) c = cs.new_bitvec(8) d = cs.new_bitvec(8) cs.add(b == 0x86) # 134 cs.add(c == 0x11) # 17 cs.add(a == Operators.UREM(b, c)) cs.add(d == b.urem(c)) cs.add(a == d) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), 0xF)
def test_ORD(self): cs = ConstraintSet() a = cs.new_bitvec(8) cs.add(Operators.ORD(a) == Operators.ORD('Z')) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), ord('Z'))
def testBitvector_max1(self): cs = ConstraintSet() a = cs.new_bitvec(32) cs.add(a < 200) cs.add(a > 100) self.assertTrue(self.solver.check(cs)) self.assertEqual(self.solver.minmax(cs, a), (101, 199))
def test_simple_types_ints_symbolic1(self): cs = ConstraintSet() x = cs.new_bitvec(256, name="x") # Something is terribly wrong x,y = 10,20 my_ser = ABI.serialize('uint', x) self.assertTrue( solver.must_be_true(cs, my_ser[0] == operators.EXTRACT(x, 256 - 8, 8)))
def test_ORD_proper_extract(self): solver = self.solver cs = ConstraintSet() a = cs.new_bitvec(32) cs.add(Operators.ORD(a) == Operators.ORD("\xff")) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), ord("\xff"))
def testBitvector_max(self): cs = ConstraintSet() a = cs.new_bitvec(32) cs.add(a <= 200) cs.add(a >= 100) self.assertTrue(self.solver.check(cs)) self.assertEqual(self.solver.minmax(cs, a), (100, 200)) from manticore import config consts = config.get_group("smt") consts.optimize = False cs = ConstraintSet() a = cs.new_bitvec(32) cs.add(a <= 200) cs.add(a >= 100) self.assertTrue(self.solver.check(cs)) self.assertEqual(self.solver.minmax(cs, a), (100, 200)) consts.optimize = True
def test_simple_types_ints_symbolic(self): cs = ConstraintSet() x = cs.new_bitvec(256, name="x") y = cs.new_bitvec(256, name="y") # Something is terribly wrong x,y = 10,20 my_ser = ABI.serialize('(uint,uint)', x, y) x_, y_ = ABI.deserialize('(uint,uint)', my_ser) self.assertTrue(solver.must_be_true(cs, x == x_)) self.assertTrue(solver.must_be_true(cs, y == y_))
def test_arithmetic_simplify_udiv(self): cs = ConstraintSet() a = cs.new_bitvec(32, name="VARA") b = a + Operators.UDIV(BitVecConstant(size=32, value=0), BitVecConstant(size=32, value=2)) self.assertEqual(translate_to_smtlib(b), "(bvadd VARA (bvudiv #x00000000 #x00000002))") self.assertEqual(translate_to_smtlib(simplify(b)), "VARA") c = a + Operators.UDIV(BitVecConstant(size=32, value=2), BitVecConstant(size=32, value=2)) self.assertEqual(translate_to_smtlib(c), "(bvadd VARA (bvudiv #x00000002 #x00000002))") self.assertEqual(translate_to_smtlib(simplify(c)), "(bvadd VARA #x00000001)")
def test_NOT(self): solver = self.solver cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) cs.add(a == 0x1) # 1 cs.add(b == 0x86) # -122 self.assertTrue(solver.must_be_true(cs, Operators.NOT(False))) self.assertTrue(solver.must_be_true(cs, Operators.NOT(a == b)))
def testBasicMigration(self): solver = self.solver cs1 = ConstraintSet() cs2 = ConstraintSet() var1 = cs1.new_bitvec(32, "var") var2 = cs2.new_bitvec(32, "var") cs1.add(Operators.ULT(var1, 3)) # var1 can be 0, 1, 2 # make a migration map dict migration_map1 = {} # this expression is composed with variables of both cs expression = var1 > var2 migrated_expression = cs1.migrate(expression, migration_map1) cs1.add(migrated_expression) expression = var2 > 0 migrated_expression = cs1.migrate(expression, migration_map1) cs1.add(migrated_expression) self.assertItemsEqual(solver.get_all_values(cs1, var1), [2]) # should only be [2]
def test_ULT(self): solver = self.solver cs = ConstraintSet() a = cs.new_bitvec(8) b = cs.new_bitvec(8) c = cs.new_bitvec(8) cs.add(a == 0x1) # 1 cs.add(b == 0x86) # -122 cs.add(c == 0x11) # 17 self.assertTrue(solver.must_be_true(cs, Operators.ULT(a, b))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(a, c))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(c, b))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(a, 0xF2))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(b, 0x99))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(c, 0x12))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(3, 0xF2))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(3, 4))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(0, a))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(0x85, b))) self.assertTrue(solver.must_be_true(cs, Operators.ULT(0x10, c)))