def testRelated(self): cs = ConstraintSet() aa1 = cs.new_bool(name="AA1") aa2 = cs.new_bool(name="AA2") bb1 = cs.new_bool(name="BB1") bb2 = cs.new_bool(name="BB2") cs.add(Operators.OR(aa1, aa2)) cs.add(Operators.OR(bb1, bb2)) self.assertTrue(self.solver.check(cs)) # No BB variables related to AA self.assertNotIn("BB", cs.related_to(aa1).to_string()) self.assertNotIn("BB", cs.related_to(aa2).to_string()) self.assertNotIn("BB", cs.related_to(aa1 == aa2).to_string()) self.assertNotIn("BB", cs.related_to(aa1 == False).to_string()) # No AA variables related to BB self.assertNotIn("AA", cs.related_to(bb1).to_string()) self.assertNotIn("AA", cs.related_to(bb2).to_string()) self.assertNotIn("AA", cs.related_to(bb1 == bb2).to_string()) self.assertNotIn("AA", cs.related_to(bb1 == False).to_string()) # Nothing is related to tautologies? self.assertEqual("", cs.related_to(simplify(bb1 == bb1)).to_string()) # But if the tautollogy can not get simplified we have to ask the solver # and send in all the other stuff self.assertNotIn("AA", cs.related_to(bb1 == bb1).to_string())
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 testBool4(self): cs = ConstraintSet() bf = BoolConstant(value=False) bt = BoolConstant(value=True) cs.add(Operators.OR(True, bf)) cs.add(Operators.OR(bt, bt, False)) self.assertTrue(self.solver.check(cs))
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 test_CMPXCHG8B_symbolic(self): '''CMPXCHG8B''' cs = ConstraintSet() mem = SMemory32(cs) cpu = I386Cpu(mem) #alloc/map a little mem code = mem.mmap(0x1000, 0x1000, 'rwx') data = mem.mmap(0x2000, 0x1000, 'rwx') mem[code:code+5] = '\xf0\x0f\xc7\x0f;' cpu.EIP = code cpu.EDI = cs.new_bitvec(32, 'EDI') cs.add( Operators.OR(cpu.EDI == 0x2000, cpu.EDI == 0x2100, cpu.EDI == 0x2200 ) ) self.assertEqual(sorted(solver.get_all_values(cs, cpu.EDI)),[0x2000,0x2100,0x2200]) self.assertEqual(cpu.read_int(0x2000,64), 0) self.assertEqual(cpu.read_int(0x2100,64), 0) self.assertEqual(cpu.read_int(0x2200,64), 0) self.assertItemsEqual(solver.get_all_values(cs, cpu.read_int(cpu.EDI,64)), [0]) #self.assertEqual(cpu.read_int(cpu.EDI,64), 0 ) cpu.write_int(0x2100, 0x4142434445464748, 64) cpu.EAX = cs.new_bitvec(32, 'EAX') cs.add( Operators.OR(cpu.EAX == 0x41424344, cpu.EAX == 0x0badf00d, cpu.EAX == 0xf7f7f7f7 ) ) cpu.EDX= 0x45464748 cpu.execute() self.assertTrue(solver.check(cs)) self.assertItemsEqual(solver.get_all_values(cs, cpu.read_int(cpu.EDI,64)), [0, 4702394921427289928])
def test_simplify_OR(self): cs = ConstraintSet() bf = BoolConstant(value=False) bt = BoolConstant(value=True) var = cs.new_bool() cs.add(simplify(Operators.OR(var, var)) == var) cs.add(simplify(Operators.OR(var, bt)) == bt) self.assertTrue(self.solver.check(cs))
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 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 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_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 test_SAR_2_symbolicsa(self): cs = ConstraintSet() mem = SMemory32(cs) cpu = I386Cpu(mem) mem.mmap(0x0041e000, 0x1000, 'rwx') mem[0x0041e10a] = '\xc0' mem[0x0041e10b] = '\xf8' mem[0x0041e10c] = '\xff' cpu.RIP = 0x41e10a cpu.PF = cs.new_bool() cs.add(cpu.PF == True) cpu.CF = cs.new_bool() cs.add(cpu.CF == False) cpu.SF = cs.new_bool() cs.add(cpu.SF == True) cpu.ZF = cs.new_bool() cs.add(cpu.ZF == False) cpu.AF = cs.new_bool() cs.add(cpu.AF == False) cpu.OF = cs.new_bool() cs.add(cpu.OF == False) cpu.EAX = cs.new_bitvec(32) cs.add(cpu.EAX == 0xffffffff) done = False while not done: try: cpu.execute() done = True except ConcretizeRegister as e: symbol = getattr(cpu, e.reg_name) values = solver.get_all_values(cs, symbol) self.assertEqual(len(values), 1) setattr(cpu, e.reg_name, values[0]) condition = True condition = Operators.AND(condition, cpu.EAX == 0xffffffff) condition = Operators.AND(condition, cpu.ZF == False) condition = Operators.AND(condition, cpu.PF == True) condition = Operators.AND(condition, cpu.SF == True) condition = Operators.AND(condition, cpu.CF == True) with cs as temp_cs: temp_cs.add(condition) self.assertTrue(solver.check(temp_cs)) with cs as temp_cs: temp_cs.add(condition == False) self.assertFalse(solver.check(temp_cs))
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 serialize_uint(value, size=32): '''takes an int and packs it into a 32 byte string, msb first''' assert size >= 1 bytes = [] for position in range(size): bytes.append(Operators.EXTRACT(value, position * 8, 8)) chars = map(Operators.CHR, bytes) return tuple(reversed(chars))
def compare_buffers(a, b): if len(a) != len(b): return False cond = True for i in range(len(a)): cond = Operators.AND(a[i] == b[i], cond) if cond is False: return False return cond
def testBasicITETaint(self): a = BitVecConstant(32, 100, taint=('SOURCE1', )) b = BitVecConstant(32, 200, taint=('SOURCE2', )) c = BitVecConstant(32, 300, taint=('SOURCE3', )) d = BitVecConstant(32, 400, taint=('SOURCE4', )) x = Operators.ITEBV(32, a > b, c, d) self.assertTrue('SOURCE1' in x.taint) self.assertTrue('SOURCE2' in x.taint) self.assertTrue('SOURCE3' in x.taint) self.assertTrue('SOURCE4' in x.taint)
def testBasicITETaint(self): a = BitVecConstant(size=32, value=100, taint=("SOURCE1",)) b = BitVecConstant(size=32, value=200, taint=("SOURCE2",)) c = BitVecConstant(size=32, value=300, taint=("SOURCE3",)) d = BitVecConstant(size=32, value=400, taint=("SOURCE4",)) x = Operators.ITEBV(32, a > b, c, d) self.assertTrue("SOURCE1" in x.taint) self.assertTrue("SOURCE2" in x.taint) self.assertTrue("SOURCE3" in x.taint) self.assertTrue("SOURCE4" in x.taint)
def test_related_to(self): import gzip import pickle, sys filename = os.path.abspath( os.path.join(DIRPATH, "data", "ErrRelated.pkl.gz")) # A constraint set and a contraint caught in the act of making related_to fail constraints, constraint = pickle.loads( gzip.open(filename, "rb").read()) Z3Solver.instance().can_be_true.cache_clear() ground_truth = Z3Solver.instance().can_be_true(constraints, constraint) self.assertEqual(ground_truth, False) Z3Solver.instance().can_be_true.cache_clear() self.assertEqual( ground_truth, Z3Solver.instance().can_be_true( constraints.related_to(constraints), constraint), ) # Replace new_constraint = Operators.UGE( Operators.SEXTEND(BitVecConstant(256, 0x1A), 256, 512) * BitVecConstant(512, 1), 0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000, ) self.assertEqual(translate_to_smtlib(constraint), translate_to_smtlib(new_constraint)) Z3Solver.instance().can_be_true.cache_clear() self.assertEqual( ground_truth, Z3Solver.instance().can_be_true(constraints, new_constraint)) Z3Solver.instance().can_be_true.cache_clear() self.assertEqual( ground_truth, Z3Solver.instance().can_be_true( constraints.related_to(new_constraint), new_constraint), )
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_ITE(self): cs = ConstraintSet() a = cs.new_bool() b = cs.new_bool() c = cs.new_bool() cs.add(b == True) cs.add(c == False) cs.add(a == Operators.ITE(b == c, b, c)) self.assertTrue(solver.check(cs)) self.assertEqual(solver.get_value(cs, a), False)
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 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_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_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_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_cache_003(self): cs = ConstraintSet() mem = SMemory64(cs) cpu = AMD64Cpu(mem) #alloc/map a little mem addr = mem.mmap(0x1000, 0x1000, 'rwx') self.assertEqual(addr, 0x1000) cpu.write_int(0x1000, 0x4142434445464748, 64) cpu.write_int(0x1008, 0x6162636465666768, 64) self.assertEqual(cpu.read_int(0x1000, 64), 0x4142434445464748) self.assertEqual(cpu.read_int(0x1008, 64), 0x6162636465666768) for i in range(8): self.assertEqual(cpu.read_int(0x1000 + i, 8), ord("HGFEDCBA"[i])) for i in range(8): self.assertEqual(cpu.read_int(0x1008 + i, 8), ord("hgfedcba"[i])) addr1 = cs.new_bitvec(64) cs.add(addr1 == 0x1004) cpu.write_int(addr1, 0x58, 8) # 48 47 46 45 58 43 42 41 68 67 66 65 64 63 62 61 value = cpu.read_int(0x1004, 16) self.assertItemsEqual(solver.get_all_values(cs, value), [0x4358]) addr2 = cs.new_bitvec(64) cs.add(Operators.AND(addr2 >= 0x1000, addr2 <= 0x100c)) cpu.write_int(addr2, 0x5959, 16) solutions = solver.get_all_values(cs, cpu.read_int(addr2, 32)) self.assertEqual(len(solutions), 0x100c - 0x1000 + 1) self.assertEqual( set(solutions), set([ 0x45465959, 0x41425959, 0x58455959, 0x65665959, 0x67685959, 0x43585959, 0x68415959, 0x42435959, 0x66675959, 0x62635959, 0x64655959, 0x63645959, 0x61625959 ]))
def test_arithmetic_simplify_extract(self): cs = ConstraintSet() arr = cs.new_array(name='MEM') a = cs.new_bitvec(32, name='VARA') b = Operators.CONCAT(32, Operators.EXTRACT(a, 24, 8), Operators.EXTRACT(a, 16, 8), Operators.EXTRACT(a, 8, 8), Operators.EXTRACT(a, 0, 8)) self.assertEqual( translate_to_smtlib(b), '(concat ((_ extract 31 24) VARA) ((_ extract 23 16) VARA) ((_ extract 15 8) VARA) ((_ extract 7 0) VARA))' ) self.assertEqual(translate_to_smtlib(simplify(b)), 'VARA') c = Operators.CONCAT(16, Operators.EXTRACT(a, 16, 8), Operators.EXTRACT(a, 8, 8)) self.assertEqual( translate_to_smtlib(c), '(concat ((_ extract 23 16) VARA) ((_ extract 15 8) VARA))') self.assertEqual(translate_to_smtlib(simplify(c)), '((_ extract 23 8) VARA)')
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]
from manticore.ethereum.abi import ABI ETHER = 10**18 m = ManticoreEVM() # initiate the blockchain # Generate the accounts user_account = m.create_account(balance=1000 * ETHER) with open('exercise_2.sol') as f: contract = m.solidity_create_contract(f, owner=user_account) #First add won't overflow uint256 representation value_0 = m.make_symbolic_value() contract.add(value_0, caller=user_account) #Potential overflow value_1 = m.make_symbolic_value() contract.add(value_1, caller=user_account) contract.sellerBalance(caller=user_account) for state in m.ready_states: # Check if input0 > sellerBalance # last_return is the data returned sellerBalance_tx = state.platform.transactions[-1] # retrieve last_return and input0 in a similar format seller_balance = ABI.deserialize("uint", sellerBalance_tx.return_data) condition = Operators.UGT(value_0, seller_balance) if m.generate_testcase(state, name="BugFound", only_if=condition): print(f'Bug found, results are in {m.workspace}')
contract_account = m.solidity_create_contract(source_code, owner=user_account, balance=0) contract_account.balanceOf(to_account, caller=user_account) contract_account.balanceOf(from_account, caller=user_account) contract_account.balanceOf(user_account, caller=user_account) symbolic_val1 = m.make_symbolic_value() #m.constrain(symbolic_val1 > 100) contract_account.transfer(to_account, symbolic_val1, caller=from_account) contract_account.balanceOf(user_account, caller=user_account) contract_account.balanceOf(from_account, caller=user_account) contract_account.balanceOf(to_account, caller=user_account) for state in m.ready_states: #for tx in state.platform.transactions: # print("From address: (0x%x) \n" % (tx.caller)) #print("********\n") balance_before = state.platform.transactions[1].return_data balance_before = ABI.deserialize("uint", balance_before) balance_after = state.platform.transactions[-1].return_data balance_after = ABI.deserialize("uint", balance_after) state.constrain(Operators.ULT(balance_before, balance_after)) if solver.check(state.constraints): print("Found! see {}".format(m.workspace)) m.generate_testcase(state, "Found")
def write(mem, where, val, size): mem[where:where + size / 8] = [ Operators.CHR(Operators.EXTRACT(val, offset, 8)) for offset in xrange(0, size, 8) ]