def broken_sprintf(): l.info("concrete src, concrete dst, concrete len") s = SimState(mode="symbolic", arch="PPC32") format_str = s.se.BitVecVal(0x25640000, 32) format_addr = s.se.BitVecVal(0x2000, 32) #dst = s.se.BitVecVal("destination", 128) dst_addr = s.se.BitVecVal(0x1000, 32) arg = s.BV("some_number", 32) s.memory.store(format_addr, format_str) sprintf(s, inline=True, arguments=[dst_addr, format_addr, arg]) for i in range(9): j = random.randint(10**i, 10**(i + 1)) s2 = s.copy() s2.add_constraints(arg == j) #print s2.se.any_n_str(s2.memory.load(dst_addr, i+2), 2), repr("%d\x00" % j) nose.tools.assert_equal( s2.se.any_n_str(s2.memory.load(dst_addr, i + 2), 2), ["%d\x00" % j]) s2 = s.copy() s2.add_constraints(arg == 0) #print s2.se.any_n_str(s2.memory.load(dst_addr, 2), 2), repr("%d\x00" % 0) nose.tools.assert_equal(s2.se.any_n_str(s2.memory.load(dst_addr, 2), 2), ["%d\x00" % 0])
def test_strcpy(): l.info("concrete src, concrete dst") l.debug("... full copy") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.se.BitVecVal(0x42420000, 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) strcpy(s, inline=True, arguments=[dst_addr, src_addr]) new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE') nose.tools.assert_equal(s.se.any_str(new_dst), "BB\x00\x00") l.info("symbolic src, concrete dst") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) ln = strlen(s, inline=True, arguments=[src_addr]).ret_expr strcpy(s, inline=True, arguments=[dst_addr, src_addr]) cm = strcmp(s, inline=True, arguments=[dst_addr, src_addr]).ret_expr s.add_constraints(cm == 0) s.add_constraints(ln == 15)
def test_memset(): l.info("concrete src, concrete dst, concrete len") s = SimState(arch="PPC32", mode="symbolic") dst = s.se.BitVecVal(0, 128) dst_addr = s.se.BitVecVal(0x1000, 32) char = s.se.BitVecVal(0x00000041, 32) char2 = s.se.BitVecVal(0x50505050, 32) length = s.BV("some_length", 32) s.memory.store(dst_addr, dst) memset(s, inline=True, arguments=[dst_addr, char, s.se.BitVecVal(3, 32)]) nose.tools.assert_equals(s.se.any_int(s.memory.load(dst_addr, 4)), 0x41414100) l.debug("Symbolic length") s = SimState(arch="PPC32", mode="symbolic") s.memory.store(dst_addr, dst) length = s.BV("some_length", 32) memset(s, inline=True, arguments=[dst_addr, char2, length]) l.debug("Trying 2") s_two = s.copy() s_two.add_constraints(length == 2) nose.tools.assert_equals(s_two.se.any_int(s_two.memory.load(dst_addr, 4)), 0x50500000) l.debug("Trying 0") s_zero = s.copy() s_zero.add_constraints(length == 0) nose.tools.assert_equals( s_zero.se.any_int(s_zero.memory.load(dst_addr, 4)), 0x00000000) l.debug("Trying 5") s_five = s.copy() s_five.add_constraints(length == 5) nose.tools.assert_equals( s_five.se.any_int(s_five.memory.load(dst_addr, 6)), 0x505050505000)
def test_strchr(): l.info("concrete haystack and needle") s = SimState(arch="AMD64", mode="symbolic") str_haystack = s.se.BitVecVal(0x41424300, 32) str_needle = s.se.BitVecVal(0x42, 64) addr_haystack = s.se.BitVecVal(0x10, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") ss_res = strchr(s, inline=True, arguments=[addr_haystack, str_needle]).ret_expr nose.tools.assert_true(s.se.unique(ss_res)) nose.tools.assert_equal(s.se.any_int(ss_res), 0x11) l.info("concrete haystack, symbolic needle") s = SimState(arch="AMD64", mode="symbolic") str_haystack = s.se.BitVecVal(0x41424300, 32) str_needle = s.BV("wtf", 64) chr_needle = str_needle[7:0] addr_haystack = s.se.BitVecVal(0x10, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") ss_res = strchr(s, inline=True, arguments=[addr_haystack, str_needle]).ret_expr nose.tools.assert_false(s.se.unique(ss_res)) nose.tools.assert_equal(len(s.se.any_n_int(ss_res, 10)), 4) s_match = s.copy() s_nomatch = s.copy() s_match.add_constraints(ss_res != 0) s_nomatch.add_constraints(ss_res == 0) nose.tools.assert_true(s_match.satisfiable()) nose.tools.assert_true(s_nomatch.satisfiable()) nose.tools.assert_equal(len(s_match.se.any_n_int(chr_needle, 300)), 3) nose.tools.assert_equal(len(s_nomatch.se.any_n_int(chr_needle, 300)), 253) nose.tools.assert_items_equal(s_match.se.any_n_int(ss_res, 300), [0x10, 0x11, 0x12]) nose.tools.assert_items_equal(s_match.se.any_n_int(chr_needle, 300), [0x41, 0x42, 0x43]) s_match.memory.store(ss_res, s_match.BVV(0x44, 8)) nose.tools.assert_items_equal( s_match.se.any_n_int(s_match.memory.load(0x10, 1), 300), [0x41, 0x44]) nose.tools.assert_items_equal( s_match.se.any_n_int(s_match.memory.load(0x11, 1), 300), [0x42, 0x44]) nose.tools.assert_items_equal( s_match.se.any_n_int(s_match.memory.load(0x12, 1), 300), [0x43, 0x44]) return
def test_inline_strncmp(): l.info("symbolic left, symbolic right, symbolic len") s = SimState(arch="AMD64", mode="symbolic") left = s.BV("left", 32) left_addr = s.se.BitVecVal(0x1000, 64) right = s.BV("right", 32) right_addr = s.se.BitVecVal(0x2000, 64) maxlen = s.BV("len", 64) s.memory.store(left_addr, left) s.memory.store(right_addr, right) s.add_constraints( strlen(s, inline=True, arguments=[left_addr]).ret_expr == 3) s.add_constraints( strlen(s, inline=True, arguments=[right_addr]).ret_expr == 0) s.add_constraints(maxlen != 0) c = strncmp(s, inline=True, arguments=[left_addr, right_addr, maxlen]).ret_expr s_match = s.copy() s_match.add_constraints(c == 0) nose.tools.assert_false(s_match.satisfiable()) #nose.tools.assert_equals(s_match.se.min_int(maxlen), 3) s_nomatch = s.copy() s_nomatch.add_constraints(c != 0) nose.tools.assert_true(s_nomatch.satisfiable()) #nose.tools.assert_equals(s_nomatch.se.max_int(maxlen), 2) l.info("zero-length") s = SimState(arch="AMD64", mode="symbolic") left = s.BV("left", 32) left_addr = s.se.BitVecVal(0x1000, 64) right = s.BV("right", 32) right_addr = s.se.BitVecVal(0x2000, 64) maxlen = s.BV("len", 64) left_len = strlen(s, inline=True, arguments=[left_addr]).ret_expr right_len = strlen(s, inline=True, arguments=[right_addr]).ret_expr c = strncmp(s, inline=True, arguments=[left_addr, right_addr, maxlen]).ret_expr s.add_constraints(right_len == 0) s.add_constraints(left_len == 0) #s.add_constraints(c == 0) s.add_constraints(maxlen == 0) nose.tools.assert_true(s.satisfiable())
def broken_symbolic_write(): s = SimState(arch='AMD64', mode='symbolic') addr = s.BV('addr', 64) s.add_constraints(s.se.Or(addr == 10, addr == 20, addr == 30)) nose.tools.assert_equals(len(s.se.any_n_int(addr, 10)), 3) s.memory.store(10, s.se.BitVecVal(1, 8)) s.memory.store(20, s.se.BitVecVal(2, 8)) s.memory.store(30, s.se.BitVecVal(3, 8)) nose.tools.assert_true(s.se.unique(s.memory.load(10, 1))) nose.tools.assert_true(s.se.unique(s.memory.load(20, 1))) nose.tools.assert_true(s.se.unique(s.memory.load(30, 1))) #print "CONSTRAINTS BEFORE:", s.constraints._solver.constraints #s.memory.store(addr, s.se.BitVecVal(255, 8), strategy=['symbolic','any'], limit=100) s.memory.store(addr, s.se.BitVecVal(255, 8)) nose.tools.assert_true(s.satisfiable()) print "GO TIME" nose.tools.assert_equals(len(s.se.any_n_int(addr, 10)), 3) nose.tools.assert_items_equal(s.se.any_n_int(s.memory.load(10, 1), 3), [1, 255]) nose.tools.assert_items_equal(s.se.any_n_int(s.memory.load(20, 1), 3), [2, 255]) nose.tools.assert_items_equal(s.se.any_n_int(s.memory.load(30, 1), 3), [3, 255]) nose.tools.assert_equals(len(s.se.any_n_int(addr, 10)), 3) # see if it works when constraining the write address sa = s.copy() sa.add_constraints(addr == 20) nose.tools.assert_true(sa.satisfiable()) nose.tools.assert_items_equal(sa.se.any_n_int(sa.memory.load(10, 1), 3), [1]) nose.tools.assert_items_equal(sa.se.any_n_int(sa.memory.load(20, 1), 3), [255]) nose.tools.assert_items_equal(sa.se.any_n_int(sa.memory.load(30, 1), 3), [3]) nose.tools.assert_items_equal(sa.se.any_n_int(addr, 10), [20]) # see if it works when constraining a value to the written one sv = s.copy() sv.add_constraints(sv.memory.load(30, 1) == 255) nose.tools.assert_true(sv.satisfiable()) nose.tools.assert_items_equal(sv.se.any_n_int(sv.memory.load(10, 1), 3), [1]) nose.tools.assert_items_equal(sv.se.any_n_int(sv.memory.load(20, 1), 3), [2]) nose.tools.assert_items_equal(sv.se.any_n_int(sv.memory.load(30, 1), 3), [255]) nose.tools.assert_items_equal(sv.se.any_n_int(addr, 10), [30]) # see if it works when constraining a value to the unwritten one sv = s.copy() sv.add_constraints(sv.memory.load(30, 1) == 3) nose.tools.assert_true(sv.satisfiable()) nose.tools.assert_items_equal(sv.se.any_n_int(sv.memory.load(10, 1), 3), [1, 255]) nose.tools.assert_items_equal(sv.se.any_n_int(sv.memory.load(20, 1), 3), [2, 255]) nose.tools.assert_items_equal(sv.se.any_n_int(sv.memory.load(30, 1), 3), [3]) nose.tools.assert_items_equal(sv.se.any_n_int(addr, 10), [10, 20]) s = SimState(arch='AMD64', mode='symbolic') s.memory.store(0, s.se.BitVecVal(0x4141414141414141, 64)) length = s.BV("length", 32) #s.memory.store(0, s.se.BitVecVal(0x4242424242424242, 64), symbolic_length=length) s.memory.store(0, s.se.BitVecVal(0x4242424242424242, 64)) for i in range(8): ss = s.copy() ss.add_constraints(length == i) nose.tools.assert_equal(ss.se.any_str(s.memory.load(0, 8)), "B" * i + "A" * (8 - i)) print "GROOVY"
def test_memory(): initial_memory = {0: 'A', 1: 'A', 2: 'A', 3: 'A', 10: 'B'} s = SimState(arch="AMD64", memory_backer=initial_memory, add_options={ simuvex.o.REVERSE_MEMORY_NAME_MAP, simuvex.o.REVERSE_MEMORY_HASH_MAP }) # Store a 4-byte variable to memory directly... s.memory.store(100, s.se.BitVecVal(0x1337, 32)) # ... then load it expr = s.memory.load(100, 4) nose.tools.assert_equal(expr.model, s.se.BitVecVal(0x1337, 32).model) expr = s.memory.load(100, 2) nose.tools.assert_equal(expr.model, s.se.BitVecVal(0, 16).model) expr = s.memory.load(102, 2) nose.tools.assert_equal(expr.model, s.se.BitVecVal(0x1337, 16).model) # concrete address and partially symbolic result expr = s.memory.load(2, 4) expr = s.memory.load(2, 4) expr = s.memory.load(2, 4) expr = s.memory.load(2, 4) nose.tools.assert_true(s.se.symbolic(expr)) nose.tools.assert_false(s.se.unique(expr)) nose.tools.assert_greater_equal(s.se.any_int(expr), 0x41410000) nose.tools.assert_less_equal(s.se.any_int(expr), 0x41420000) nose.tools.assert_equal(s.se.min_int(expr), 0x41410000) nose.tools.assert_equal(s.se.max_int(expr), 0x4141ffff) # concrete address and concrete result expr = s.memory.load(0, 4) # Returns: a z3 BitVec representing 0x41414141 nose.tools.assert_false(s.se.symbolic(expr)) nose.tools.assert_equal(s.se.any_int(expr), 0x41414141) # symbolicize v = s.memory.make_symbolic("asdf", 0, length=4) nose.tools.assert_equal(v.size(), 32) nose.tools.assert_true(s.se.unique(v)) nose.tools.assert_equal(s.se.any_int(v), 0x41414141) expr = s.memory.load(0, 4) # Returns: a z3 BitVec representing 0x41414141 nose.tools.assert_true(s.se.symbolic(expr)) nose.tools.assert_equal(s.se.any_int(expr), 0x41414141) nose.tools.assert_true(s.se.unique(expr)) c = s.BV('condition', 8) expr = s.memory.load(10, 1, condition=c == 1, fallback=s.BVV('X')) nose.tools.assert_equal( s.se.any_n_str(expr, 10, extra_constraints=[c == 1]), ['B']) nose.tools.assert_equal( s.se.any_n_str(expr, 10, extra_constraints=[c != 1]), ['X']) x = s.BV('ref_test', 16, explicit_name=True) s.memory.store(0x1000, x) s.memory.store(0x2000, x) nose.tools.assert_equal(set(s.memory.addrs_for_name('ref_test')), set((0x1000, 0x1001, 0x2000, 0x2001))) nose.tools.assert_equal(set(s.memory.addrs_for_hash(hash(x))), set((0x1000, 0x1001, 0x2000, 0x2001))) s2 = s.copy() y = s2.BV('ref_test2', 16, explicit_name=True) s2.memory.store(0x2000, y) nose.tools.assert_equal(set(s.memory.addrs_for_name('ref_test')), set((0x1000, 0x1001, 0x2000, 0x2001))) nose.tools.assert_equal(set(s.memory.addrs_for_hash(hash(x))), set((0x1000, 0x1001, 0x2000, 0x2001))) nose.tools.assert_equal(set(s2.memory.addrs_for_name('ref_test')), set((0x1000, 0x1001))) nose.tools.assert_equal(set(s2.memory.addrs_for_hash(hash(x))), set((0x1000, 0x1001))) nose.tools.assert_equal(set(s2.memory.addrs_for_name('ref_test2')), set((0x2000, 0x2001))) nose.tools.assert_equal(set(s2.memory.addrs_for_hash(hash(y))), set((0x2000, 0x2001))) s.memory.store(0x3000, s.BV('replace_old', 32, explicit_name=True)) s.memory.store(0x3001, s.BVV('AB')) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_old')), set((0x3000, 0x3003))) nose.tools.assert_equal(s.se.any_n_str(s.memory.load(0x3001, 2), 10), ["AB"]) n = s.BV('replace_new', 32, explicit_name=True) c = s.BV('replace_cool', 32, explicit_name=True) mo = s.memory.memory_objects_for_name('replace_old') nose.tools.assert_equal(len(mo), 1) s.memory.replace_memory_object(next(iter(mo)), n) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_old')), set()) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_new')), set((0x3000, 0x3003))) nose.tools.assert_equal(s.se.any_n_str(s.memory.load(0x3001, 2), 10), ["AB"]) s.memory.store(0x4000, s.se.If(n == 0, n + 10, n + 20)) nose.tools.assert_equal( set(s.memory.addrs_for_name('replace_new')), set((0x3000, 0x3003, 0x4000, 0x4001, 0x4002, 0x4003))) s.memory.replace_all(n, c) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_old')), set()) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_new')), set()) nose.tools.assert_equal( set(s.memory.addrs_for_name('replace_cool')), set((0x3000, 0x3003, 0x4000, 0x4001, 0x4002, 0x4003))) nose.tools.assert_equal(s.se.any_n_str(s.memory.load(0x3001, 2), 10), ["AB"]) z = s.BVV(0, 32) s.memory.replace_all(c, z) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_old')), set()) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_new')), set()) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_cool')), set()) nose.tools.assert_equal(s.se.any_n_str(s.memory.load(0x3001, 2), 10), ["AB"]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(0x3000, 4), 10), [0x00414200]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(0x4000, 4), 10), [0x0000000a]) # symbolic length x = s.BVV(0x11223344, 32) y = s.BVV(0xAABBCCDD, 32) n = s.BV('size', 32) s.memory.store(0x5000, x) s.memory.store(0x5000, y, size=n) nose.tools.assert_equal( set(s.se.any_n_int(s.memory.load(0x5000, 4), 10)), {0x11223344, 0xAA223344, 0xAABB3344, 0xAABBCC44, 0xAABBCCDD}) s1 = s.copy() s1.add_constraints(n == 1) nose.tools.assert_equal( set(s1.se.any_n_int(s1.memory.load(0x5000, 4), 10)), {0xAA223344}) s4 = s.copy() s4.add_constraints(n == 4) nose.tools.assert_equal( set(s4.se.any_n_int(s4.memory.load(0x5000, 4), 10)), {0xAABBCCDD}) # condition without fallback x = s.BVV(0x11223344, 32) y = s.BVV(0xAABBCCDD, 32) c = s.BV('condition', 32) s.memory.store(0x6000, x) s.memory.store(0x6000, y, condition=c == 1) nose.tools.assert_equal(set(s.se.any_n_int(s.memory.load(0x6000, 4), 10)), {0x11223344, 0xAABBCCDD}) s0 = s.copy() s0.add_constraints(c == 0) nose.tools.assert_equal( set(s0.se.any_n_int(s0.memory.load(0x6000, 4), 10)), {0x11223344}) s1 = s.copy() s1.add_constraints(c == 1) nose.tools.assert_equal( set(s1.se.any_n_int(s1.memory.load(0x6000, 4), 10)), {0xAABBCCDD}) # condition with symbolic size x = s.BVV(0x11223344, 32) y = s.BVV(0xAABBCCDD, 32) c = s.BV('condition', 32) n = s.BV('size', 32) s.memory.store(0x8000, x) s.memory.store(0x8000, y, condition=c == 1, size=n) s0 = s.copy() s0.add_constraints(c == 0) nose.tools.assert_equal( set(s0.se.any_n_int(s0.memory.load(0x8000, 4), 10)), {0x11223344}) s1 = s.copy() s1.add_constraints(c == 1) nose.tools.assert_equal( set(s1.se.any_n_int(s1.memory.load(0x8000, 4), 10)), {0x11223344, 0xAA223344, 0xAABB3344, 0xAABBCC44, 0xAABBCCDD})
def test_inline_strcmp(): s = SimState(arch="AMD64", mode="symbolic") str_a = s.se.BitVecVal(0x41414100, 32) str_b = s.BV("mystring", 32) a_addr = s.se.BitVecVal(0x10, 64) b_addr = s.se.BitVecVal(0xb0, 64) s.memory.store(a_addr, str_a, endness="Iend_BE") s.memory.store(b_addr, str_b, endness="Iend_BE") s_cmp = s.copy() cmpres = SimProcedures['libc.so.6']['strcmp'](s_cmp, inline=True, arguments=[a_addr, b_addr]).ret_expr s_match = s_cmp.copy() s_nomatch = s_cmp.copy() s_match.add_constraints(cmpres == 0) s_nomatch.add_constraints(cmpres != 0) nose.tools.assert_true(s_match.se.unique(str_b)) nose.tools.assert_false(s_nomatch.se.unique(str_b)) nose.tools.assert_equal(s_match.se.any_str(str_b), "AAA\x00") s_ncmp = s.copy() ncmpres = SimProcedures['libc.so.6']['strncmp']( s_ncmp, inline=True, arguments=[a_addr, b_addr, s.se.BitVecVal(2, s.arch.bits)]).ret_expr s_match = s_ncmp.copy() s_nomatch = s_ncmp.copy() s_match.add_constraints(ncmpres == 0) s_nomatch.add_constraints(ncmpres != 0) nose.tools.assert_false(s_match.se.unique(str_b)) nose.tools.assert_true(s_match.se.unique(s_match.memory.load(b_addr, 2))) nose.tools.assert_equal( len(s_match.se.any_n_int(s_match.memory.load(b_addr, 3), 300)), 256) nose.tools.assert_false(s_nomatch.se.unique(str_b)) l.info("concrete a, symbolic b") s = SimState(arch="AMD64", mode="symbolic") str_a = s.se.BitVecVal(0x41424300, 32) str_b = s.BV("mystring", 32) a_addr = s.se.BitVecVal(0x10, 64) b_addr = s.se.BitVecVal(0xb0, 64) s.memory.store(a_addr, str_a, endness="Iend_BE") s.memory.store(b_addr, str_b, endness="Iend_BE") s_cmp = s.copy() cmpres = strncmp( s_cmp, inline=True, arguments=[a_addr, b_addr, s.se.BitVecVal(2, s_cmp.arch.bits)]).ret_expr s_match = s_cmp.copy() s_nomatch = s_cmp.copy() s_match.add_constraints(cmpres == 0) s_nomatch.add_constraints(cmpres != 0) nose.tools.assert_true(s_match.se.solution(str_b, 0x41420000)) nose.tools.assert_true(s_match.se.solution(str_b, 0x41421234)) nose.tools.assert_true(s_match.se.solution(str_b, 0x41424300)) nose.tools.assert_false(s_nomatch.se.solution(str_b, 0x41420000)) nose.tools.assert_false(s_nomatch.se.solution(str_b, 0x41421234)) nose.tools.assert_false(s_nomatch.se.solution(str_b, 0x41424300)) l.info("symbolic a, symbolic b") s = SimState(arch="AMD64", mode="symbolic") a_addr = s.se.BitVecVal(0x10, 64) b_addr = s.se.BitVecVal(0xb0, 64) s_cmp = s.copy() cmpres = strcmp(s_cmp, inline=True, arguments=[a_addr, b_addr]).ret_expr s_match = s_cmp.copy() s_nomatch = s_cmp.copy() s_match.add_constraints(cmpres == 0) s_nomatch.add_constraints(cmpres != 0) m_res = strcmp(s_match, inline=True, arguments=[a_addr, b_addr]).ret_expr s_match.add_constraints(m_res != 0) nm_res = strcmp(s_nomatch, inline=True, arguments=[a_addr, b_addr]).ret_expr s_nomatch.add_constraints(nm_res == 0) nose.tools.assert_false(s_match.satisfiable()) nose.tools.assert_false(s_match.satisfiable())
def test_strncpy(): l.info("concrete src, concrete dst, concrete len") l.debug("... full copy") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.se.BitVecVal(0x42420000, 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) strncpy(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(3, 64)]) new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE') nose.tools.assert_equal(s.se.any_str(new_dst), "BB\x00\x00") l.debug("... partial copy") s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) strncpy(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(2, 64)]) new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE') nose.tools.assert_equal(s.se.any_n_str(new_dst, 2), ["BBA\x00"]) l.info("symbolic src, concrete dst, concrete len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) # make sure it copies it all s.add_constraints( strlen(s, inline=True, arguments=[src_addr]).ret_expr == 2) # sanity check s_false = s.copy() s_false.add_constraints( strlen(s_false, inline=True, arguments=[src_addr]).ret_expr == 3) nose.tools.assert_false(s_false.satisfiable()) strncpy(s, inline=True, arguments=[dst_addr, src_addr, 3]) nose.tools.assert_true(s.satisfiable()) c = strcmp(s, inline=True, arguments=[dst_addr, src_addr]).ret_expr nose.tools.assert_items_equal(s.se.any_n_int(c, 10), [0]) l.info("symbolic src, concrete dst, symbolic len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) maxlen = s.BV("len", 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) # make sure it copies it all s.add_constraints( strlen(s, inline=True, arguments=[src_addr]).ret_expr == 2) strncpy(s, inline=True, arguments=[dst_addr, src_addr, maxlen]) c = strcmp(s, inline=True, arguments=[dst_addr, src_addr]).ret_expr s_match = s.copy() s_match.add_constraints(c == 0) nose.tools.assert_equals(s_match.se.min_int(maxlen), 3) s_nomatch = s.copy() s_nomatch.add_constraints(c != 0) nose.tools.assert_equals(s_nomatch.se.max_int(maxlen), 2) l.info("concrete src, concrete dst, symbolic len") l.debug("... full copy") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.se.BitVecVal(0x42420000, 32) src_addr = s.se.BitVecVal(0x2000, 64) maxlen = s.BV("len", 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) strncpy(s, inline=True, arguments=[dst_addr, src_addr, maxlen]) r = s.memory.load(dst_addr, 4, endness='Iend_BE') #print repr(r.se.any_n_str(10)) nose.tools.assert_items_equal(s.se.any_n_str( r, 10), ["AAA\x00", 'BAA\x00', 'BBA\x00', 'BB\x00\x00'])
def test_memcmp(): l.info("concrete src, concrete dst, concrete len") l.debug("... full cmp") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414141, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.se.BitVecVal(0x42424242, 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) r = memcmp(s, inline=True, arguments=[dst_addr, src_addr, s.BVV(4, 64)]).ret_expr nose.tools.assert_true(s.satisfiable()) s_pos = s.copy() s_pos.add_constraints(r.SGE(0)) nose.tools.assert_false(s_pos.satisfiable()) s_neg = s.copy() s_neg.add_constraints(r.SLT(0)) nose.tools.assert_true(s_neg.satisfiable()) l.debug("... zero cmp") s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) r = memcmp(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(0, 64)]).ret_expr nose.tools.assert_equals(s.se.any_n_int(r, 2), [0]) l.info("symbolic src, concrete dst, concrete len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414141, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) # make sure it copies it all r = memcmp(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(4, 64)]).ret_expr s_match = s.copy() s_match.add_constraints(r == 0) m = s_match.memory.load(src_addr, 4) nose.tools.assert_equal(s_match.se.any_n_int(m, 2), [0x41414141]) s_nomatch = s.copy() s_nomatch.add_constraints(r != 0) m = s_nomatch.memory.load(src_addr, 4) nose.tools.assert_false(s_nomatch.se.solution(m, 0x41414141)) l.info("symbolic src, concrete dst, symbolic len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414141, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) cmplen = s.BV("len", 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) r = memcmp(s, inline=True, arguments=[dst_addr, src_addr, cmplen]).ret_expr # look at effects of different lengths s1 = s.copy() s1.add_constraints(cmplen == 1) s1.add_constraints(r == 0) l.debug("... simplifying") s1.se._solver.simplify() l.debug("... solving") nose.tools.assert_equals(s1.se.any_n_int(src[31:24], 2), [0x41]) nose.tools.assert_false(s1.se.unique(src[31:16])) l.debug("... solved") s2 = s.copy() s2.add_constraints(cmplen == 2) s2.add_constraints(r == 0) nose.tools.assert_equals(s2.se.any_n_int(s2.memory.load(src_addr, 2), 2), [0x4141]) nose.tools.assert_false(s2.se.unique(s2.memory.load(src_addr, 3))) s2u = s.copy() s2u.add_constraints(cmplen == 2) s2u.add_constraints(r == 1) nose.tools.assert_false( s2u.se.solution(s2u.memory.load(src_addr, 2), 0x4141))
def test_memcpy(): l.info("concrete src, concrete dst, concrete len") l.debug("... full copy") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414141, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.se.BitVecVal(0x42424242, 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) memcpy(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(4, 64)]) new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE') nose.tools.assert_equal(s.se.any_n_str(new_dst, 2), ["BBBB"]) l.debug("... partial copy") s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) memcpy(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(2, 64)]) new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE') nose.tools.assert_equal(s.se.any_n_str(new_dst, 2), ["BBAA"]) l.info("symbolic src, concrete dst, concrete len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414141, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) # make sure it copies it all memcpy(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(4, 64)]) nose.tools.assert_true(s.satisfiable()) s.add_constraints(src != s.memory.load(dst_addr, 4)) nose.tools.assert_false(s.satisfiable()) l.info("symbolic src, concrete dst, symbolic len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414141, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) cpylen = s.BV("len", 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) memcpy(s, inline=True, arguments=[dst_addr, src_addr, cpylen]) result = s.memory.load(dst_addr, 4, endness='Iend_BE') # make sure it copies it all s1 = s.copy() s1.add_constraints(cpylen == 1) nose.tools.assert_true(s1.se.unique(s1.memory.load(dst_addr + 1, 3))) nose.tools.assert_equals( len(s1.se.any_n_int(s1.memory.load(dst_addr, 1), 300)), 256) s2 = s.copy() s2.add_constraints(cpylen == 2) nose.tools.assert_equals(len(s2.se.any_n_int(result[31:24], 300)), 256) nose.tools.assert_equals(len(s2.se.any_n_int(result[23:16], 300)), 256) nose.tools.assert_equals(s2.se.any_n_str(result[15:0], 300), ['AA']) l.info("concrete src, concrete dst, symbolic len") dst = s2.se.BitVecVal(0x41414141, 32) dst_addr = s2.se.BitVecVal(0x1000, 64) src = s2.se.BitVecVal(0x42424242, 32) src_addr = s2.se.BitVecVal(0x2000, 64) s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) cpylen = s.BV("len", 64) s.add_constraints(s.se.ULE(cpylen, 4)) memcpy(s, inline=True, arguments=[dst_addr, src_addr, cpylen]) new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE') nose.tools.assert_items_equal(s.se.any_n_str(new_dst, 300), ['AAAA', 'BAAA', 'BBAA', 'BBBA', 'BBBB'])
def test_inline_strlen(): s = SimState(arch="AMD64", mode="symbolic") l.info("fully concrete string") a_str = s.se.BitVecVal(0x41414100, 32) a_addr = s.se.BitVecVal(0x10, 64) s.memory.store(a_addr, a_str, endness="Iend_BE") a_len = SimProcedures['libc.so.6']['strlen'](s, inline=True, arguments=[a_addr]).ret_expr nose.tools.assert_true(s.se.unique(a_len)) nose.tools.assert_equal(s.se.any_int(a_len), 3) l.info("concrete-terminated string") b_str = s.se.Concat(s.BV("mystring", 24), s.se.BitVecVal(0, 8)) b_addr = s.se.BitVecVal(0x20, 64) s.memory.store(b_addr, b_str, endness="Iend_BE") b_len = SimProcedures['libc.so.6']['strlen'](s, inline=True, arguments=[b_addr]).ret_expr nose.tools.assert_equal(s.se.max_int(b_len), 3) nose.tools.assert_items_equal(s.se.any_n_int(b_len, 10), (0, 1, 2, 3)) l.info("fully unconstrained") u_addr = s.se.BitVecVal(0x50, 64) u_len_sp = SimProcedures['libc.so.6']['strlen'](s, inline=True, arguments=[u_addr]) u_len = u_len_sp.ret_expr nose.tools.assert_equal(len(s.se.any_n_int(u_len, 100)), s.libc.buf_symbolic_bytes) nose.tools.assert_equal(s.se.max_int(u_len), s.libc.buf_symbolic_bytes - 1) #print u_len_sp.se.maximum_null #s.add_constraints(u_len < 16) nose.tools.assert_equal( s.se.any_n_int(s.memory.load(0x50 + u_len, 1), 300), [0]) # # This tests if a strlen can influence a symbolic str. # l.info("Trying to influence length.") s = SimState(arch="AMD64", mode="symbolic") str_c = s.BV("some_string", 8 * 16) c_addr = s.se.BitVecVal(0x10, 64) s.memory.store(c_addr, str_c, endness='Iend_BE') c_len = SimProcedures['libc.so.6']['strlen'](s, inline=True, arguments=[c_addr]).ret_expr nose.tools.assert_equal(len(s.se.any_n_int(c_len, 100)), s.libc.buf_symbolic_bytes) nose.tools.assert_equal(s.se.max_int(c_len), s.libc.buf_symbolic_bytes - 1) one_s = s.copy() one_s.add_constraints(c_len == 1) nose.tools.assert_equal(one_s.se.any_str(str_c).index('\x00'), 1) str_test = one_s.memory.load(c_addr, 2, endness='Iend_BE') nose.tools.assert_equal(len(one_s.se.any_n_str(str_test, 300)), 255) for i in range(16): test_s = s.copy() test_s.add_constraints(c_len == i) str_test = test_s.memory.load(c_addr, i + 1, endness='Iend_BE') nose.tools.assert_equal(test_s.se.any_str(str_test).index('\x00'), i) for j in range(i): nose.tools.assert_false( test_s.se.unique(test_s.memory.load(c_addr + j, 1)))
def broken_inline_strstr(): l.info("concrete haystack and needle") s = SimState(arch="AMD64", mode="symbolic") str_haystack = s.se.BitVecVal(0x41424300, 32) str_needle = s.se.BitVecVal(0x42430000, 32) addr_haystack = s.se.BitVecVal(0x10, 64) addr_needle = s.se.BitVecVal(0xb0, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") s.memory.store(addr_needle, str_needle, endness="Iend_BE") ss_res = strstr(s, inline=True, arguments=[addr_haystack, addr_needle]).ret_expr nose.tools.assert_true(s.se.unique(ss_res)) nose.tools.assert_equal(s.se.any_int(ss_res), 0x11) l.info("concrete haystack, symbolic needle") s = SimState(arch="AMD64", mode="symbolic") str_haystack = s.se.BitVecVal(0x41424300, 32) str_needle = s.BV("wtf", 32) addr_haystack = s.se.BitVecVal(0x10, 64) addr_needle = s.se.BitVecVal(0xb0, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") s.memory.store(addr_needle, str_needle, endness="Iend_BE") ss_res = strstr(s, inline=True, arguments=[addr_haystack, addr_needle]).ret_expr nose.tools.assert_false(s.se.unique(ss_res)) nose.tools.assert_equal(len(s.se.any_n_int(ss_res, 10)), 4) s_match = s.copy() s_nomatch = s.copy() s_match.add_constraints(ss_res != 0) s_nomatch.add_constraints(ss_res == 0) match_needle = str_needle[31:16] nose.tools.assert_equal(len(s_match.se.any_n_int(match_needle, 300)), 259) nose.tools.assert_equal(len(s_match.se.any_n_int(str_needle, 10)), 10) l.info("symbolic haystack, symbolic needle") s = SimState(arch="AMD64", mode="symbolic") s.libc.buf_symbolic_bytes = 5 addr_haystack = s.se.BitVecVal(0x10, 64) addr_needle = s.se.BitVecVal(0xb0, 64) len_needle = strlen(s, inline=True, arguments=[addr_needle]) ss_res = strstr(s, inline=True, arguments=[addr_haystack, addr_needle]).ret_expr nose.tools.assert_false(s.se.unique(ss_res)) nose.tools.assert_equal(len(s.se.any_n_int(ss_res, 100)), s.libc.buf_symbolic_bytes) s_match = s.copy() s_nomatch = s.copy() s_match.add_constraints(ss_res != 0) s_nomatch.add_constraints(ss_res == 0) match_cmp = strncmp(s_match, inline=True, arguments=[ss_res, addr_needle, len_needle.ret_expr]).ret_expr nose.tools.assert_items_equal(s_match.se.any_n_int(match_cmp, 10), [0]) r_mm = strstr(s_match, inline=True, arguments=[addr_haystack, addr_needle]).ret_expr s_match.add_constraints(r_mm == 0) nose.tools.assert_false(s_match.satisfiable()) nose.tools.assert_true(s_nomatch.satisfiable()) s_nss = s_nomatch.copy() nomatch_ss = strstr(s_nss, inline=True, arguments=[addr_haystack, addr_needle]).ret_expr s_nss.add_constraints(nomatch_ss != 0) nose.tools.assert_false(s_nss.satisfiable())