Esempio n. 1
0
def test_memset():
    l.info("concrete src, concrete dst, concrete len")
    s = SimState(arch="PPC32", mode="symbolic")
    dst = s.solver.BVV(0, 128)
    dst_addr = s.solver.BVV(0x1000, 32)
    char = s.solver.BVV(0x00000041, 32)
    char2 = s.solver.BVV(0x50505050, 32)
    length = s.solver.BVS("some_length", 32)

    s.memory.store(dst_addr, dst)
    memset(s, arguments=[dst_addr, char, s.solver.BVV(3, 32)])
    assert s.solver.eval(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.solver.BVS("some_length", 32)
    s.add_constraints(length < 10)
    memset(s, arguments=[dst_addr, char2, length])

    l.debug("Trying 2")
    s_two = s.copy()
    s_two.add_constraints(length == 2)
    assert s_two.solver.eval(s_two.memory.load(dst_addr, 4)) == 0x50500000

    l.debug("Trying 0")
    s_zero = s.copy()
    s_zero.add_constraints(length == 0)
    assert s_zero.solver.eval(s_zero.memory.load(dst_addr, 4)) == 0x00000000

    l.debug("Trying 5")
    s_five = s.copy()
    s_five.add_constraints(length == 5)
    assert s_five.solver.eval(s_five.memory.load(dst_addr, 6)) == 0x505050505000
Esempio n. 2
0
def test_memset():
    l.info("concrete src, concrete dst, concrete len")
    s = SimState(arch="PPC32", mode="symbolic")
    dst = s.solver.BVV(0, 128)
    dst_addr = s.solver.BVV(0x1000, 32)
    char = s.solver.BVV(0x00000041, 32)
    char2 = s.solver.BVV(0x50505050, 32)
    length = s.solver.BVS("some_length", 32)

    s.memory.store(dst_addr, dst)
    memset(s, arguments=[dst_addr, char, s.solver.BVV(3, 32)])
    nose.tools.assert_equal(s.solver.eval(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.solver.BVS("some_length", 32)
    memset(s, arguments=[dst_addr, char2, length])

    l.debug("Trying 2")
    s_two = s.copy()
    s_two.add_constraints(length == 2)
    nose.tools.assert_equal(s_two.solver.eval(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_equal(s_zero.solver.eval(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_equal(s_five.solver.eval(s_five.memory.load(dst_addr, 6)), 0x505050505000)
Esempio n. 3
0
def broken_sprintf():
    l.info("concrete src, concrete dst, concrete len")
    s = SimState(mode="symbolic", arch="PPC32")
    format_str = s.solver.BVV(0x25640000, 32)
    format_addr = s.solver.BVV(0x2000, 32)
    #dst = s.solver.BVV("destination", 128)
    dst_addr = s.solver.BVV(0x1000, 32)
    arg = s.solver.BVS("some_number", 32)

    s.memory.store(format_addr, format_str)

    sprintf(s, 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.solver.eval_upto(s2.memory.load(dst_addr, i+2), 2, cast_to=bytes), repr(b"%d\x00" % j)
        nose.tools.assert_equal(
            s2.solver.eval_upto(s2.memory.load(dst_addr, i + 2),
                                2,
                                cast_to=bytes), [b"%d\x00" % j])

    s2 = s.copy()
    s2.add_constraints(arg == 0)
    #print s2.solver.eval_upto(s2.memory.load(dst_addr, 2), 2, cast_to=bytes), repr(b"%d\x00" % 0)
    nose.tools.assert_equal(
        s2.solver.eval_upto(s2.memory.load(dst_addr, 2), 2, cast_to=bytes),
        [b"%d\x00" % 0])
Esempio n. 4
0
def test_inline_strlen():
    s = SimState(arch="AMD64", mode="symbolic")

    l.info("fully concrete string")
    a_str = s.se.BVV(0x41414100, 32)
    a_addr = s.se.BVV(0x10, 64)
    s.memory.store(a_addr, a_str, endness="Iend_BE")
    a_len = strlen(s, 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.se.BVS("mystring", 24), s.se.BVV(0, 8))
    b_addr = s.se.BVV(0x20, 64)
    s.memory.store(b_addr, b_str, endness="Iend_BE")
    b_len = strlen(s, 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.BVV(0x50, 64)
    u_len_sp = strlen(s, 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.se.BVS("some_string", 8 * 16)
    c_addr = s.se.BVV(0x10, 64)
    s.memory.store(c_addr, str_c, endness='Iend_BE')
    c_len = strlen(s, 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)))
Esempio n. 5
0
def test_inline_strlen():
    s = SimState(arch="AMD64", mode="symbolic")

    l.info("fully concrete string")
    a_str = s.solver.BVV(0x41414100, 32)
    a_addr = s.solver.BVV(0x10, 64)
    s.memory.store(a_addr, a_str, endness="Iend_BE")
    a_len = strlen(s, arguments=[a_addr])
    assert s.solver.unique(a_len)
    assert s.solver.eval(a_len) == 3

    l.info("concrete-terminated string")
    b_str = s.solver.Concat(s.solver.BVS("mystring", 24), s.solver.BVV(0, 8))
    b_addr = s.solver.BVV(0x20, 64)
    s.memory.store(b_addr, b_str, endness="Iend_BE")
    b_len = strlen(s, arguments=[b_addr])
    assert s.solver.max_int(b_len) == 3
    assert tuple(sorted(s.solver.eval_upto(b_len, 10))) == (0, 1, 2, 3)

    l.info("fully unconstrained")
    u_addr = s.solver.BVV(0x50, 64)
    u_len_sp = strlen(s, arguments=[u_addr])
    u_len = u_len_sp
    assert len(s.solver.eval_upto(u_len, 100)) == s.libc.buf_symbolic_bytes
    assert s.solver.max_int(u_len) == s.libc.buf_symbolic_bytes-1
    #print u_len_sp.solver.maximum_null

    #s.add_constraints(u_len < 16)

    assert s.solver.eval_upto(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.solver.BVS("some_string", 8*16)
    c_addr = s.solver.BVV(0x10, 64)
    s.memory.store(c_addr, str_c, endness='Iend_BE')
    c_len = strlen(s, arguments=[c_addr])
    assert len(s.solver.eval_upto(c_len, 100)) == s.libc.buf_symbolic_bytes
    assert s.solver.max_int(c_len) == s.libc.buf_symbolic_bytes-1

    one_s = s.copy()
    one_s.add_constraints(c_len == 1)
    assert one_s.solver.eval(str_c, cast_to=bytes).index(b'\x00') == 1
    str_test = one_s.memory.load(c_addr, 2, endness='Iend_BE')
    assert len(one_s.solver.eval_upto(str_test, 300, cast_to=bytes)) == 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')
        assert test_s.solver.eval(str_test, cast_to=bytes).index(b'\x00') == i
        for j in range(i):
            assert not test_s.solver.unique(test_s.memory.load(c_addr+j, 1))
Esempio n. 6
0
def test_inline_strlen():
    s = SimState(arch="AMD64", mode="symbolic")

    l.info("fully concrete string")
    a_str = s.solver.BVV(0x41414100, 32)
    a_addr = s.solver.BVV(0x10, 64)
    s.memory.store(a_addr, a_str, endness="Iend_BE")
    a_len = strlen(s, arguments=[a_addr])
    nose.tools.assert_true(s.solver.unique(a_len))
    nose.tools.assert_equal(s.solver.eval(a_len), 3)

    l.info("concrete-terminated string")
    b_str = s.solver.Concat(s.solver.BVS("mystring", 24), s.solver.BVV(0, 8))
    b_addr = s.solver.BVV(0x20, 64)
    s.memory.store(b_addr, b_str, endness="Iend_BE")
    b_len = strlen(s, arguments=[b_addr])
    nose.tools.assert_equal(s.solver.max_int(b_len), 3)
    nose.tools.assert_sequence_equal(sorted(s.solver.eval_upto(b_len, 10)), (0,1,2,3))

    l.info("fully unconstrained")
    u_addr = s.solver.BVV(0x50, 64)
    u_len_sp = strlen(s, arguments=[u_addr])
    u_len = u_len_sp
    nose.tools.assert_equal(len(s.solver.eval_upto(u_len, 100)), s.libc.buf_symbolic_bytes)
    nose.tools.assert_equal(s.solver.max_int(u_len), s.libc.buf_symbolic_bytes-1)
    #print u_len_sp.solver.maximum_null

    #s.add_constraints(u_len < 16)

    nose.tools.assert_equal(s.solver.eval_upto(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.solver.BVS("some_string", 8*16)
    c_addr = s.solver.BVV(0x10, 64)
    s.memory.store(c_addr, str_c, endness='Iend_BE')
    c_len = strlen(s, arguments=[c_addr])
    nose.tools.assert_equal(len(s.solver.eval_upto(c_len, 100)), s.libc.buf_symbolic_bytes)
    nose.tools.assert_equal(s.solver.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.solver.eval(str_c, cast_to=bytes).index(b'\x00'), 1)
    str_test = one_s.memory.load(c_addr, 2, endness='Iend_BE')
    nose.tools.assert_equal(len(one_s.solver.eval_upto(str_test, 300, cast_to=bytes)), 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.solver.eval(str_test, cast_to=bytes).index(b'\x00'), i)
        for j in range(i):
            nose.tools.assert_false(test_s.solver.unique(test_s.memory.load(c_addr+j, 1)))
Esempio n. 7
0
def test_strchr():
    l.info("concrete haystack and needle")
    s = SimState(arch="AMD64", mode="symbolic")
    str_haystack = s.solver.BVV(0x41424300, 32)
    str_needle = s.solver.BVV(0x42, 64)
    addr_haystack = s.solver.BVV(0x10, 64)
    s.memory.store(addr_haystack, str_haystack, endness="Iend_BE")

    ss_res = strchr(s, arguments=[addr_haystack, str_needle])
    nose.tools.assert_true(s.solver.unique(ss_res))
    nose.tools.assert_equal(s.solver.eval(ss_res), 0x11)

    l.info("concrete haystack, symbolic needle")
    s = SimState(arch="AMD64", mode="symbolic")
    str_haystack = s.solver.BVV(0x41424300, 32)
    str_needle = s.solver.BVS("wtf", 64)
    chr_needle = str_needle[7:0]
    addr_haystack = s.solver.BVV(0x10, 64)
    s.memory.store(addr_haystack, str_haystack, endness="Iend_BE")

    ss_res = strchr(s, arguments=[addr_haystack, str_needle])
    nose.tools.assert_false(s.solver.unique(ss_res))
    nose.tools.assert_equal(len(s.solver.eval_upto(ss_res, 10)), 5)

    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.solver.eval_upto(chr_needle, 300)), 4)
    nose.tools.assert_equal(len(s_nomatch.solver.eval_upto(chr_needle, 300)),
                            252)
    nose.tools.assert_sequence_equal(
        sorted(s_match.solver.eval_upto(ss_res, 300)),
        [0x10, 0x11, 0x12, 0x13])
    nose.tools.assert_sequence_equal(
        sorted(s_match.solver.eval_upto(chr_needle, 300)),
        [0x00, 0x41, 0x42, 0x43])

    s_match.memory.store(ss_res, s_match.solver.BVV(0x44, 8))
    nose.tools.assert_sequence_equal(
        sorted(s_match.solver.eval_upto(s_match.memory.load(0x10, 1), 300)),
        [0x41, 0x44])
    nose.tools.assert_sequence_equal(
        sorted(s_match.solver.eval_upto(s_match.memory.load(0x11, 1), 300)),
        [0x42, 0x44])
    nose.tools.assert_sequence_equal(
        sorted(s_match.solver.eval_upto(s_match.memory.load(0x12, 1), 300)),
        [0x43, 0x44])
    nose.tools.assert_sequence_equal(
        sorted(s_match.solver.eval_upto(s_match.memory.load(0x13, 1), 300)),
        [0x00, 0x44])
Esempio n. 8
0
def run_calloc_multiplies(arch):
    s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
    s.heap.malloc(30)
    sc = s.copy()
    s.heap.malloc(100)
    sc.heap.calloc(4, 25)
    nose.tools.assert_true(same_heap_states(s, sc))
Esempio n. 9
0
def run_unusable_amount_returns_null(arch):
    s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
    s.heap.malloc(0x1000 - 4 * s.heap._chunk_size_t_size)
    sc = s.copy()
    p = s.heap.malloc(1)
    nose.tools.assert_equals(p, 0)
    nose.tools.assert_true(same_heap_states(s, sc))
Esempio n. 10
0
def run_realloc_no_space_returns_null(arch):
    s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
    p1 = s.heap.malloc(20)
    sc = s.copy()
    p2 = s.heap.realloc(p1, 0x2000)
    nose.tools.assert_equals(p2, 0)
    nose.tools.assert_true(same_heap_states(s, sc))
Esempio n. 11
0
 def _run_unusable_amount_returns_null(self, arch):
     s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
     s.heap.malloc(0x1000 - 4 * s.heap._chunk_size_t_size)
     sc = s.copy()
     p = s.heap.malloc(1)
     assert p == 0
     assert self.same_heap_states(s, sc)
Esempio n. 12
0
 def _run_realloc_no_space_returns_null(self, arch):
     s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
     p1 = s.heap.malloc(20)
     sc = s.copy()
     p2 = s.heap.realloc(p1, 0x2000)
     assert p2 == 0
     assert self.same_heap_states(s, sc)
Esempio n. 13
0
def test_fullpage_write():
    s = SimState(arch='AMD64')
    a = s.se.BVV('A' * 0x2000)
    s.memory.store(0, a)
    #assert len(s.memory.mem._pages) == 2
    #assert len(s.memory.mem._pages[0].keys()) == 0
    #assert len(s.memory.mem._pages[1].keys()) == 0
    assert s.memory.load(0, 0x2000) is a
    assert a.variables != s.memory.load(0x2000, 1).variables

    s = SimState(arch='AMD64')
    a = s.se.BVV('A' * 2)
    s.memory.store(0x1000, a)
    s.memory.store(0x2000, a)
    assert a.variables == s.memory.load(0x2000, 1).variables
    assert a.variables == s.memory.load(0x2001, 1).variables
    assert a.variables != s.memory.load(0x2002, 1).variables

    s = SimState(arch='AMD64')
    x = s.se.BVV('X')
    a = s.se.BVV('A' * 0x1000)
    s.memory.store(1, x)
    s2 = s.copy()
    s2.memory.store(0, a)
    assert len(s.memory.changed_bytes(s2.memory)) == 0x1000

    s = SimState(arch='AMD64')
    s.memory._maximum_symbolic_size = 0x2000000
    a = s.se.BVS('A', 0x1000000 * 8)
    s.memory.store(0, a)
    b = s.memory.load(0, 0x1000000)
    assert b is a
Esempio n. 14
0
 def _run_calloc_multiplies(self, arch):
     s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
     s.heap.malloc(30)
     sc = s.copy()
     s.heap.malloc(100)
     sc.heap.calloc(4, 25)
     assert self.same_heap_states(s, sc)
Esempio n. 15
0
def test_symbolic_write():
    s = SimState(arch='AMD64', add_options={o.SYMBOLIC_WRITE_ADDRESSES})
    x = s.solver.BVS('x', 64)
    y = s.solver.BVS('y', 64)
    a = s.solver.BVV(b'A'*0x10)
    b = s.solver.BVV(b'B')
    c = s.solver.BVV(b'C')
    d = s.solver.BVV(b'D')

    s.memory.store(0x10, a)
    s.add_constraints(x >= 0x10, x < 0x20)
    s.memory.store(x, b)

    for i in range(0x10, 0x20):
        assert len(s.solver.eval_upto(s.memory.load(i, 1), 10)) == 2

    s.memory.store(x, c)
    for i in range(0x10, 0x20):
        assert len(s.solver.eval_upto(s.memory.load(i, 1), 10)) == 2

    s2 = s.copy()
    s2.add_constraints(y >= 0x10, y < 0x20)
    s2.memory.store(y, d)
    for i in range(0x10, 0x20):
        assert len(s2.solver.eval_upto(s2.memory.load(i, 1), 10)) == 3
Esempio n. 16
0
def test_fullpage_write():
    s = SimState(arch='AMD64')
    a = s.se.BVV('A'*0x2000)
    s.memory.store(0, a)
    #assert len(s.memory.mem._pages) == 2
    #assert len(s.memory.mem._pages[0].keys()) == 0
    #assert len(s.memory.mem._pages[1].keys()) == 0
    assert s.memory.load(0, 0x2000) is a
    assert a.variables != s.memory.load(0x2000, 1).variables

    s = SimState(arch='AMD64')
    a = s.se.BVV('A'*2)
    s.memory.store(0x1000, a)
    s.memory.store(0x2000, a)
    assert a.variables == s.memory.load(0x2000, 1).variables
    assert a.variables == s.memory.load(0x2001, 1).variables
    assert a.variables != s.memory.load(0x2002, 1).variables

    s = SimState(arch='AMD64')
    x = s.se.BVV('X')
    a = s.se.BVV('A'*0x1000)
    s.memory.store(1, x)
    s2 = s.copy()
    s2.memory.store(0, a)
    assert len(s.memory.changed_bytes(s2.memory)) == 0x1000

    s = SimState(arch='AMD64')
    s.memory._maximum_symbolic_size = 0x2000000
    a = s.se.BVS('A', 0x1000000*8)
    s.memory.store(0, a)
    b = s.memory.load(0, 0x1000000)
    assert b is a
Esempio n. 17
0
def test_symbolic_write():
    s = SimState(arch='AMD64', add_options={o.SYMBOLIC_WRITE_ADDRESSES})
    x = s.se.BVS('x', 64)
    y = s.se.BVS('y', 64)
    a = s.se.BVV('A' * 0x10)
    b = s.se.BVV('B')
    c = s.se.BVV('C')
    d = s.se.BVV('D')

    s.memory.store(0x10, a)
    s.add_constraints(x >= 0x10, x < 0x20)
    s.memory.store(x, b)

    for i in range(0x10, 0x20):
        assert len(s.se.any_n_int(s.memory.load(i, 1), 10)) == 2

    s.memory.store(x, c)
    for i in range(0x10, 0x20):
        assert len(s.se.any_n_int(s.memory.load(i, 1), 10)) == 2

    s2 = s.copy()
    s2.add_constraints(y >= 0x10, y < 0x20)
    s2.memory.store(y, d)
    for i in range(0x10, 0x20):
        assert len(s2.se.any_n_int(s2.memory.load(i, 1), 10)) == 3
Esempio n. 18
0
 def _run_realloc_near_same_size(self, arch):
     s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
     s.heap.malloc(20)
     p1 = s.heap.malloc(61)
     s.heap.malloc(80)
     sc = s.copy()
     p2 = s.heap.realloc(p1, 62)
     assert p1 == p2
     assert self.same_heap_states(s, sc)
Esempio n. 19
0
def run_realloc_near_same_size(arch):
    s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
    s.heap.malloc(20)
    p1 = s.heap.malloc(61)
    s.heap.malloc(80)
    sc = s.copy()
    p2 = s.heap.realloc(p1, 62)
    nose.tools.assert_equals(p1, p2)
    nose.tools.assert_true(same_heap_states(s, sc))
Esempio n. 20
0
def run_free_null_preserves_state(arch):
    s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
    s.heap.malloc(30)
    p = s.heap.malloc(40)
    s.heap.malloc(50)
    s.heap.free(p)
    s2 = s.copy()
    s2.heap.free(0)
    nose.tools.assert_true(same_heap_states(s, s2))
Esempio n. 21
0
def run_malloc_maximizes_sym_arg(arch):
    s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
    sc = s.copy()
    x = s.solver.BVS("x", 32)
    s.solver.add(x.UGE(0))
    s.solver.add(x.ULE(max_sym_var_val(s)))
    s.heap.malloc(x)
    sc.heap.malloc(max_sym_var_val(sc))
    nose.tools.assert_true(same_heap_states(s, sc))
Esempio n. 22
0
def test_inline_strncmp():
    l.info("symbolic left, symbolic right, symbolic len")
    s = SimState(arch="AMD64", mode="symbolic")
    left = s.solver.BVS("left", 32)
    left_addr = s.solver.BVV(0x1000, 64)
    right = s.solver.BVS("right", 32)
    right_addr = s.solver.BVV(0x2000, 64)
    maxlen = s.solver.BVS("len", 64)

    s.memory.store(left_addr, left)
    s.memory.store(right_addr, right)

    s.add_constraints(strlen(s, arguments=[left_addr]) == 3)
    s.add_constraints(strlen(s, arguments=[right_addr]) == 0)

    s.add_constraints(maxlen != 0)
    c = strncmp(s, arguments=[left_addr, right_addr, maxlen])

    s_match = s.copy()
    s_match.add_constraints(c == 0)
    nose.tools.assert_false(s_match.satisfiable())
    #nose.tools.assert_equal(s_match.solver.min_int(maxlen), 3)

    s_nomatch = s.copy()
    s_nomatch.add_constraints(c != 0)
    nose.tools.assert_true(s_nomatch.satisfiable())
    #nose.tools.assert_equal(s_nomatch.solver.max_int(maxlen), 2)

    l.info("zero-length")
    s = SimState(arch="AMD64", mode="symbolic")
    left = s.solver.BVS("left", 32)
    left_addr = s.solver.BVV(0x1000, 64)
    right = s.solver.BVS("right", 32)
    right_addr = s.solver.BVV(0x2000, 64)
    maxlen = s.solver.BVS("len", 64)
    left_len = strlen(s, arguments=[left_addr])
    right_len = strlen(s, arguments=[right_addr])
    c = strncmp(s, arguments=[left_addr, right_addr, maxlen])

    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())
Esempio n. 23
0
def test_inline_strncmp():
    l.info("symbolic left, symbolic right, symbolic len")
    s = SimState(arch="AMD64", mode="symbolic")
    left = s.solver.BVS("left", 32)
    left_addr = s.solver.BVV(0x1000, 64)
    right = s.solver.BVS("right", 32)
    right_addr = s.solver.BVV(0x2000, 64)
    maxlen = s.solver.BVS("len", 64)

    s.memory.store(left_addr, left)
    s.memory.store(right_addr, right)

    s.add_constraints(strlen(s, arguments=[left_addr]) == 3)
    s.add_constraints(strlen(s, arguments=[right_addr]) == 0)

    s.add_constraints(maxlen != 0)
    c = strncmp(s, arguments=[left_addr, right_addr, maxlen])

    s_match = s.copy()
    s_match.add_constraints(c == 0)
    nose.tools.assert_false(s_match.satisfiable())
    #nose.tools.assert_equal(s_match.solver.min_int(maxlen), 3)

    s_nomatch = s.copy()
    s_nomatch.add_constraints(c != 0)
    nose.tools.assert_true(s_nomatch.satisfiable())
    #nose.tools.assert_equal(s_nomatch.solver.max_int(maxlen), 2)

    l.info("zero-length")
    s = SimState(arch="AMD64", mode="symbolic")
    left = s.solver.BVS("left", 32)
    left_addr = s.solver.BVV(0x1000, 64)
    right = s.solver.BVS("right", 32)
    right_addr = s.solver.BVV(0x2000, 64)
    maxlen = s.solver.BVS("len", 64)
    left_len = strlen(s, arguments=[left_addr])
    right_len = strlen(s, arguments=[right_addr])
    c = strncmp(s, arguments=[left_addr, right_addr, maxlen])

    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())
Esempio n. 24
0
def run_needs_space_for_metadata(arch):
    s = SimState(arch=arch,
                 plugins={
                     'heap':
                     SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)
                 })
    sc = s.copy()
    p1 = s.heap.malloc(0x1000)
    nose.tools.assert_equal(p1, 0)
    nose.tools.assert_true(same_heap_states(s, sc))
Esempio n. 25
0
def run_needs_space_for_metadata(arch):
    s = SimState(arch=arch,
                 plugins={
                     'heap':
                     SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)
                 })
    sc = s.copy()
    p1 = s.heap.malloc(0x1000)
    assert p1 == 0
    assert same_heap_states(s, sc)
Esempio n. 26
0
def run_calloc_no_space_returns_null(arch):
    s = SimState(arch=arch,
                 plugins={
                     'heap':
                     SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)
                 })
    sc = s.copy()
    p1 = s.heap.calloc(0x500, 4)
    assert p1 == 0
    assert same_heap_states(s, sc)
Esempio n. 27
0
def run_calloc_clears(arch):
    s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
    s.memory.store(0xd0000000 + 2 * s.heap._chunk_size_t_size, s.solver.BVV(-1, 100 * 8))
    sc = s.copy()
    p1 = s.heap.calloc(6, 5)
    p2 = sc.heap.malloc(30)
    v1 = s.memory.load(p1, 30)
    v2 = sc.memory.load(p2, 30)
    nose.tools.assert_true(s.solver.is_true(v1 == 0))
    nose.tools.assert_true(sc.solver.is_true(v2 == -1))
Esempio n. 28
0
 def _run_free_maximizes_sym_arg(self, arch):
     s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
     p = s.heap.malloc(50)
     sc = s.copy()
     x = s.solver.BVS("x", 32)
     s.solver.add(x.UGE(0))
     s.solver.add(x.ULE(p))
     s.heap.free(x)
     sc.heap.free(p)
     assert self.same_heap_states(s, sc)
Esempio n. 29
0
def test_strchr():
    l.info("concrete haystack and needle")
    s = SimState(arch="AMD64", mode="symbolic")
    str_haystack = s.solver.BVV(0x41424300, 32)
    str_needle = s.solver.BVV(0x42, 64)
    addr_haystack = s.solver.BVV(0x10, 64)
    s.memory.store(addr_haystack, str_haystack, endness="Iend_BE")

    ss_res = strchr(s, arguments=[addr_haystack, str_needle])
    nose.tools.assert_true(s.solver.unique(ss_res))
    nose.tools.assert_equal(s.solver.eval(ss_res), 0x11)

    l.info("concrete haystack, symbolic needle")
    s = SimState(arch="AMD64", mode="symbolic")
    str_haystack = s.solver.BVV(0x41424300, 32)
    str_needle = s.solver.BVS("wtf", 64)
    chr_needle = str_needle[7:0]
    addr_haystack = s.solver.BVV(0x10, 64)
    s.memory.store(addr_haystack, str_haystack, endness="Iend_BE")

    ss_res = strchr(s, arguments=[addr_haystack, str_needle])
    nose.tools.assert_false(s.solver.unique(ss_res))
    nose.tools.assert_equal(len(s.solver.eval_upto(ss_res, 10)), 5)

    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.solver.eval_upto(chr_needle, 300)), 4)
    nose.tools.assert_equal(len(s_nomatch.solver.eval_upto(chr_needle, 300)), 252)
    nose.tools.assert_sequence_equal(sorted(s_match.solver.eval_upto(ss_res, 300)), [ 0x10, 0x11, 0x12, 0x13 ])
    nose.tools.assert_sequence_equal(sorted(s_match.solver.eval_upto(chr_needle, 300)), [ 0x00, 0x41, 0x42, 0x43 ])

    s_match.memory.store(ss_res, s_match.solver.BVV(0x44, 8))
    nose.tools.assert_sequence_equal(sorted(s_match.solver.eval_upto(s_match.memory.load(0x10, 1), 300)), [ 0x41, 0x44 ])
    nose.tools.assert_sequence_equal(sorted(s_match.solver.eval_upto(s_match.memory.load(0x11, 1), 300)), [ 0x42, 0x44 ])
    nose.tools.assert_sequence_equal(sorted(s_match.solver.eval_upto(s_match.memory.load(0x12, 1), 300)), [ 0x43, 0x44 ])
    nose.tools.assert_sequence_equal(sorted(s_match.solver.eval_upto(s_match.memory.load(0x13, 1), 300)), [ 0x00, 0x44 ])

    return
Esempio n. 30
0
def test_store_simplification():
    state = SimState(arch='X86')
    state.regs.esp = state.se.BVS('stack_pointer', 32)
    state.regs.ebp = state.se.BVS('base_pointer', 32)
    state.regs.eax = state.se.BVS('base_eax', 32)

    irsb = pyvex.IRSB('PT]\xc2\x10\x00', 0x4000, state.arch)
    sim_successors = SimEngineVEX().process(state.copy(), irsb)
    exit_state = sim_successors.all_successors[0]

    nose.tools.assert_true(claripy.backends.z3.is_true(exit_state.regs.ebp == state.regs.esp - 4))
Esempio n. 31
0
def test_store_simplification():
    state = SimState(arch='X86')
    state.regs.esp = state.solver.BVS('stack_pointer', 32)
    state.regs.ebp = state.solver.BVS('base_pointer', 32)
    state.regs.eax = state.solver.BVS('base_eax', 32)

    irsb = pyvex.IRSB(b'PT]\xc2\x10\x00', 0x4000, state.arch)
    sim_successors = HeavyVEXMixin(None).process(state.copy(), irsb=irsb)
    exit_state = sim_successors.all_successors[0]

    nose.tools.assert_true(claripy.backends.z3.is_true(exit_state.regs.ebp == state.regs.esp - 4))
Esempio n. 32
0
def test_strchr():
    l.info("concrete haystack and needle")
    s = SimState(arch="AMD64", mode="symbolic")
    str_haystack = s.solver.BVV(0x41424300, 32)
    str_needle = s.solver.BVV(0x42, 64)
    addr_haystack = s.solver.BVV(0x10, 64)
    s.memory.store(addr_haystack, str_haystack, endness="Iend_BE")

    ss_res = strchr(s, arguments=[addr_haystack, str_needle])
    assert s.solver.unique(ss_res)
    assert s.solver.eval(ss_res) == 0x11

    l.info("concrete haystack, symbolic needle")
    s = SimState(arch="AMD64", mode="symbolic")
    str_haystack = s.solver.BVV(0x41424300, 32)
    str_needle = s.solver.BVS("wtf", 64)
    chr_needle = str_needle[7:0]
    addr_haystack = s.solver.BVV(0x10, 64)
    s.memory.store(addr_haystack, str_haystack, endness="Iend_BE")

    ss_res = strchr(s, arguments=[addr_haystack, str_needle])
    assert not s.solver.unique(ss_res)
    assert len(s.solver.eval_upto(ss_res, 10)) == 5

    s_match = s.copy()
    s_nomatch = s.copy()
    s_match.add_constraints(ss_res != 0)
    s_nomatch.add_constraints(ss_res == 0)

    assert s_match.satisfiable()
    assert s_nomatch.satisfiable()
    assert len(s_match.solver.eval_upto(chr_needle, 300)) == 4
    assert len(s_nomatch.solver.eval_upto(chr_needle, 300)) == 252
    assert sorted(s_match.solver.eval_upto(ss_res, 300)) == [ 0x10, 0x11, 0x12, 0x13 ]
    assert sorted(s_match.solver.eval_upto(chr_needle, 300)) == [ 0x00, 0x41, 0x42, 0x43 ]

    s_match.memory.store(ss_res, s_match.solver.BVV(0x44, 8))
    assert sorted(s_match.solver.eval_upto(s_match.memory.load(0x10, 1), 300)) == [ 0x41, 0x44 ]
    assert sorted(s_match.solver.eval_upto(s_match.memory.load(0x11, 1), 300)) == [ 0x42, 0x44 ]
    assert sorted(s_match.solver.eval_upto(s_match.memory.load(0x12, 1), 300)) == [ 0x43, 0x44 ]
    assert sorted(s_match.solver.eval_upto(s_match.memory.load(0x13, 1), 300)) == [ 0x00, 0x44 ]
Esempio n. 33
0
def run_calloc_maximizes_sym_arg(arch):
    s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
    sc = s.copy()
    x = s.solver.BVS("x", 32)
    s.solver.add(x.UGE(0))
    s.solver.add(x.ULE(20))
    y = s.solver.BVS("y", 32)
    s.solver.add(y.UGE(0))
    s.solver.add(y.ULE(6))
    s.heap.calloc(x, y)
    sc.heap.calloc(20, 6)
    nose.tools.assert_true(same_heap_states(s, sc))
Esempio n. 34
0
def test_store_simplification():
    state = SimState(arch="X86")
    state.regs.esp = state.solver.BVS("stack_pointer", 32)
    state.regs.ebp = state.solver.BVS("base_pointer", 32)
    state.regs.eax = state.solver.BVS("base_eax", 32)

    irsb = pyvex.IRSB(b"PT]\xc2\x10\x00", 0x4000, state.arch)
    sim_successors = HeavyVEXMixin(None).process(state.copy(), irsb=irsb)
    exit_state = sim_successors.all_successors[0]

    assert claripy.backends.z3.is_true(exit_state.regs.ebp == state.regs.esp -
                                       4)
def test_mmap_base_copy():
    state = SimState(arch="AMD64", mode="symbolic")

    mmap_base = 0x12345678

    state.libc.mmap_base = mmap_base

    # Sanity check
    nose.tools.assert_equal(state.libc.mmap_base, mmap_base)

    state_copy = state.copy()

    nose.tools.assert_equal(state_copy.libc.mmap_base, mmap_base)
Esempio n. 36
0
def test_mmap_base_copy():
    state = SimState(arch="AMD64", mode="symbolic")

    mmap_base = 0x12345678

    state.heap.mmap_base = mmap_base

    # Sanity check
    assert state.heap.mmap_base == mmap_base

    state_copy = state.copy()

    assert state_copy.heap.mmap_base == mmap_base
Esempio n. 37
0
 def _run_realloc_maximizes_sym_arg(self, arch):
     s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)})
     p = s.heap.malloc(50)
     sc = s.copy()
     x = s.solver.BVS("x", 32)
     s.solver.add(x.UGE(0))
     s.solver.add(x.ULE(p))
     y = s.solver.BVS("y", 32)
     s.solver.add(y.UGE(0))
     s.solver.add(y.ULE(self.max_sym_var_val(s)))
     s.heap.realloc(x, y)
     sc.heap.realloc(p, self.max_sym_var_val(sc))
     assert self.same_heap_states(s, sc)
Esempio n. 38
0
def broken_sprintf():
    l.info("concrete src, concrete dst, concrete len")
    s = SimState(mode="symbolic", arch="PPC32")
    format_str = s.solver.BVV(0x25640000, 32)
    format_addr = s.solver.BVV(0x2000, 32)
    #dst = s.solver.BVV("destination", 128)
    dst_addr = s.solver.BVV(0x1000, 32)
    arg = s.solver.BVS("some_number", 32)

    s.memory.store(format_addr, format_str)

    sprintf(s, 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.solver.eval_upto(s2.memory.load(dst_addr, i+2), 2, cast_to=bytes), repr(b"%d\x00" % j)
        nose.tools.assert_equal(s2.solver.eval_upto(s2.memory.load(dst_addr, i+2), 2, cast_to=bytes), [b"%d\x00" % j])

    s2 = s.copy()
    s2.add_constraints(arg == 0)
    #print s2.solver.eval_upto(s2.memory.load(dst_addr, 2), 2, cast_to=bytes), repr(b"%d\x00" % 0)
    nose.tools.assert_equal(s2.solver.eval_upto(s2.memory.load(dst_addr, 2), 2, cast_to=bytes), [b"%d\x00" % 0])
Esempio n. 39
0
def test_state_merge_3way():

    a = SimState(arch='AMD64', mode='symbolic')
    b = a.copy()
    c = a.copy()
    conds = [ a.solver.BoolS('cond_0'), a.solver.BoolS('cond_1') ]
    a.add_constraints(conds[0])
    b.add_constraints(a.solver.Not(conds[0]), conds[1])
    c.add_constraints(a.solver.Not(conds[0]), a.solver.Not(conds[1]))

    a.memory.store(0x400000, a.solver.BVV(8, 32))
    b.memory.store(0x400000, b.solver.BVV(9, 32))
    c.memory.store(0x400000, c.solver.BVV(10, 32))

    m, _, _ = a.merge(b)
    m, _, _ = m.merge(c)

    assert m.satisfiable(extra_constraints=(m.memory.load(0x400000, 4) == 8,))
    assert m.satisfiable(extra_constraints=(m.memory.load(0x400000, 4) == 9,))
    assert m.satisfiable(extra_constraints=(m.memory.load(0x400000, 4) == 10,))
Esempio n. 40
0
def test_state_merge_static():
    # With abstract memory
    # Aligned memory merging
    a = SimState(arch='AMD64', mode='static')

    addr = a.se.ValueSet(32, 'global', 0, 8)
    a.memory.store(addr, a.se.BVV(42, 32))
    # Clear a_locs, so further writes will not try to merge with value 42
    a.memory.regions['global']._alocs = { }

    b = a.copy()
    c = a.copy()
    a.memory.store(addr, a.se.BVV(50, 32), endness='Iend_LE')
    b.memory.store(addr, a.se.BVV(60, 32), endness='Iend_LE')
    c.memory.store(addr, a.se.BVV(70, 32), endness='Iend_LE')

    merged, _, _ = a.merge(b, c)
    actual = claripy.backends.vsa.convert(merged.memory.load(addr, 4))
    expected = claripy.backends.vsa.convert(a.se.SI(bits=32, stride=10, lower_bound=50, upper_bound=70))
    nose.tools.assert_true(actual.identical(expected))
Esempio n. 41
0
def test_fullpage_write():
    if os.environ.get("APPVEYOR", "false").lower() == "true":
        # Skip as AppVeyor boxes do not have enough memory to run this test
        raise nose.SkipTest()

    s = SimState(arch='AMD64')
    a = s.solver.BVV(b'A'*0x2000)
    s.memory.store(0, a)
    #assert len(s.memory.mem._pages) == 2
    #assert len(s.memory.mem._pages[0].keys()) == 0
    #assert len(s.memory.mem._pages[1].keys()) == 0
    assert s.memory.load(0, 0x2000) is a
    assert a.variables != s.memory.load(0x2000, 1).variables

    s = SimState(arch='AMD64')
    a = s.solver.BVV(b'A'*2)
    s.memory.store(0x1000, a)
    s.memory.store(0x2000, a)
    assert a.variables == s.memory.load(0x2000, 1).variables
    assert a.variables == s.memory.load(0x2001, 1).variables
    assert a.variables != s.memory.load(0x2002, 1).variables

    s = SimState(arch='AMD64')
    x = s.solver.BVV(b'X')
    a = s.solver.BVV(b'A'*0x1000)
    s.memory.store(1, x)
    s2 = s.copy()
    s2.memory.store(0, a)
    assert len(s.memory.changed_bytes(s2.memory)) == 0x1000

    s = SimState(arch='AMD64')
    s.memory._maximum_symbolic_size = 0x2000000
    a = s.solver.BVS('A', 0x1000000*8)
    s.memory.store(0, a)
    b = s.memory.load(0, 0x1000000)
    assert b is a
Esempio n. 42
0
def test_state_merge():
    a = SimState(arch='AMD64', mode='symbolic')
    a.memory.store(1, a.se.BVV(42, 8))

    b = a.copy()
    c = b.copy()
    a.memory.store(2, a.memory.load(1, 1)+1)
    b.memory.store(2, b.memory.load(1, 1)*2)
    c.memory.store(2, c.memory.load(1, 1)/2)

    # make sure the byte at 1 is right
    nose.tools.assert_equal(a.se.eval(a.memory.load(1, 1)), 42)
    nose.tools.assert_equal(b.se.eval(b.memory.load(1, 1)), 42)
    nose.tools.assert_equal(c.se.eval(c.memory.load(1, 1)), 42)

    # make sure the byte at 2 is right
    nose.tools.assert_equal(a.se.eval(a.memory.load(2, 1)), 43)
    nose.tools.assert_equal(b.se.eval(b.memory.load(2, 1)), 84)
    nose.tools.assert_equal(c.se.eval(c.memory.load(2, 1)), 21)

    # the byte at 2 should be unique for all before the merge
    nose.tools.assert_true(a.se.unique(a.memory.load(2, 1)))
    nose.tools.assert_true(b.se.unique(b.memory.load(2, 1)))
    nose.tools.assert_true(c.se.unique(c.memory.load(2, 1)))

    logging.getLogger('angr.state_plugins.symbolic_memory').setLevel(logging.DEBUG)
    m, merge_conditions, merging_occurred = a.merge(b, c)
    logging.getLogger('angr.state_plugins.symbolic_memory').setLevel(logging.WARNING)

    nose.tools.assert_true(merging_occurred)
    #nose.tools.assert_equals(sorted(m.se.eval_upto(merge_flag, 10)), [ 0,1,2 ])
    assert len(merge_conditions) == 3

    # the byte at 2 should now *not* be unique for a
    nose.tools.assert_false(m.se.unique(m.memory.load(2, 1)))
    nose.tools.assert_true(a.se.unique(a.memory.load(2, 1)))
    nose.tools.assert_true(b.se.unique(b.memory.load(2, 1)))
    nose.tools.assert_true(c.se.unique(c.memory.load(2, 1)))

    # the byte at 2 should have the three values
    nose.tools.assert_items_equal(m.se.eval_upto(m.memory.load(2, 1), 10), (43, 84, 21))

    # we should be able to select them by adding constraints
    a_a = m.copy()
    a_a.add_constraints(merge_conditions[0])
    nose.tools.assert_true(a_a.se.unique(a_a.memory.load(2, 1)))
    nose.tools.assert_equal(a_a.se.eval(a_a.memory.load(2, 1)), 43)

    a_b = m.copy()
    a_b.add_constraints(merge_conditions[1])
    nose.tools.assert_true(a_b.se.unique(a_b.memory.load(2, 1)))
    nose.tools.assert_equal(a_b.se.eval(a_b.memory.load(2, 1)), 84)

    a_c = m.copy()
    a_c.add_constraints(merge_conditions[2])
    nose.tools.assert_true(a_c.se.unique(a_c.memory.load(2, 1)))
    nose.tools.assert_equal(a_c.se.eval(a_c.memory.load(2, 1)), 21)

    # test different sets of plugins
    a = SimState(arch='AMD64', mode='symbolic')
    nose.tools.assert_true(a.has_plugin('memory'))
    nose.tools.assert_true(a.has_plugin('registers'))
    nose.tools.assert_false(a.has_plugin('libc'))

    b = a.copy()
    a.get_plugin('libc')
    nose.tools.assert_true(a.has_plugin('libc'))
    nose.tools.assert_false(b.has_plugin('libc'))
    c = a.copy().merge(b.copy())[0]
    d = b.copy().merge(a.copy())[0]
    nose.tools.assert_true(c.has_plugin('libc'))
    nose.tools.assert_true(d.has_plugin('libc'))

    # test merging posix with different open files
    a = SimState(arch='AMD64', mode='symbolic')
    b = a.copy()
    a.posix.get_file(3)
    nose.tools.assert_equal(len(a.posix.files), 4)
    nose.tools.assert_equal(len(b.posix.files), 3)
    c = a.copy().merge(b.copy())[0]
    d = b.copy().merge(a.copy())[0]
    nose.tools.assert_equal(len(c.posix.files), 4)
    nose.tools.assert_equal(len(d.posix.files), 4)
Esempio n. 43
0
def test_memory():
    initial_memory = { 0: b'A', 1: b'A', 2: b'A', 3: b'A', 10: b'B' }
    s = SimState(arch="AMD64", memory_backer=initial_memory, add_options={o.REVERSE_MEMORY_NAME_MAP, o.REVERSE_MEMORY_HASH_MAP})

    _concrete_memory_tests(s)
    # 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.solver.symbolic(expr))
    nose.tools.assert_false(s.solver.unique(expr))
    nose.tools.assert_greater_equal(s.solver.eval(expr), 0x41410000)
    nose.tools.assert_less_equal(s.solver.eval(expr), 0x41420000)
    nose.tools.assert_equal(s.solver.min_int(expr), 0x41410000)
    nose.tools.assert_equal(s.solver.max_int(expr), 0x4141ffff)

    # concrete address and concrete result
    expr = s.memory.load(0, 4) # Returns: a z3 BVS representing 0x41414141
    nose.tools.assert_false(s.solver.symbolic(expr))
    nose.tools.assert_equal(s.solver.eval(expr), 0x41414141)

    # symbolicize
    v = s.memory.make_symbolic("asdf", 0, length=4)
    nose.tools.assert_equal(v.size(), 32)
    nose.tools.assert_true(s.solver.unique(v))
    nose.tools.assert_equal(s.solver.eval(v), 0x41414141)

    expr = s.memory.load(0, 4) # Returns: a z3 BVS representing 0x41414141
    nose.tools.assert_true(s.solver.symbolic(expr))
    nose.tools.assert_equal(s.solver.eval(expr), 0x41414141)
    nose.tools.assert_true(s.solver.unique(expr))

    c = s.solver.BVS('condition', 8)
    expr = s.memory.load(10, 1, condition=c==1, fallback=s.solver.BVV(b'X'))
    nose.tools.assert_equal(s.solver.eval_upto(expr, 10, cast_to=bytes, extra_constraints=[c==1]), [ b'B' ])
    nose.tools.assert_equal(s.solver.eval_upto(expr, 10, cast_to=bytes, extra_constraints=[c!=1]), [ b'X' ])

    x = s.solver.BVS('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')), {0x1000,0x1001,0x2000,0x2001})
    nose.tools.assert_equal(set(s.memory.addrs_for_hash(hash(x))), {0x1000, 0x1001, 0x2000, 0x2001})

    s2 = s.copy()
    y = s2.solver.BVS('ref_test2', 16, explicit_name=True)
    s2.memory.store(0x2000, y)
    assert s2.memory.load(0x2000, 2) is y
    assert s.memory.load(0x2000, 2) is x
    nose.tools.assert_equal(set(s.memory.addrs_for_name('ref_test')), {0x1000,0x1001,0x2000,0x2001})
    nose.tools.assert_equal(set(s.memory.addrs_for_hash(hash(x))), {0x1000,0x1001,0x2000,0x2001})
    nose.tools.assert_equal(set(s2.memory.addrs_for_name('ref_test')), {0x1000, 0x1001})
    nose.tools.assert_equal(set(s2.memory.addrs_for_hash(hash(x))), {0x1000, 0x1001})
    nose.tools.assert_equal(set(s2.memory.addrs_for_name('ref_test2')), {0x2000, 0x2001})
    nose.tools.assert_equal(set(s2.memory.addrs_for_hash(hash(y))), {0x2000, 0x2001})

    s.memory.store(0x3000, s.solver.BVS('replace_old', 32, explicit_name=True))
    s.memory.store(0x3001, s.solver.BVV(b'AB'))
    nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_old')), {0x3000, 0x3003})
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(0x3001, 2), 10, cast_to=bytes), [b"AB"])

    n = s.solver.BVS('replace_new', 32, explicit_name=True)
    c = s.solver.BVS('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')), {0x3000, 0x3003})
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(0x3001, 2), 10, cast_to=bytes), [b"AB"])

    s.memory.store(0x4000, s.solver.If(n == 0, n+10, n+20))

    nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_new')), {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')), {0x3000, 0x3003, 0x4000, 0x4001, 0x4002, 0x4003})
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(0x3001, 2), 10, cast_to=bytes), [b"AB"])

    z = s.solver.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.solver.eval_upto(s.memory.load(0x3001, 2), 10, cast_to=bytes), [b"AB"])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(0x3000, 4), 10), [0x00414200])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(0x4000, 4), 10), [0x0000000a])

    # symbolic length
    x = s.solver.BVV(0x11223344, 32)
    y = s.solver.BVV(0xAABBCCDD, 32)
    n = s.solver.BVS('size', 32)
    s.memory.store(0x5000, x)
    s.memory.store(0x5000, y, size=n)
    nose.tools.assert_equal(set(s.solver.eval_upto(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.solver.eval_upto(s1.memory.load(0x5000, 4), 10)), { 0xAA223344 })

    s4 = s.copy()
    s4.add_constraints(n == 4)
    nose.tools.assert_equal(set(s4.solver.eval_upto(s4.memory.load(0x5000, 4), 10)), { 0xAABBCCDD })

    # condition without fallback
    x = s.solver.BVV(0x11223344, 32)
    y = s.solver.BVV(0xAABBCCDD, 32)
    c = s.solver.BVS('condition', 32)
    s.memory.store(0x6000, x)
    s.memory.store(0x6000, y, condition=c==1)
    nose.tools.assert_equal(set(s.solver.eval_upto(s.memory.load(0x6000, 4), 10)), { 0x11223344, 0xAABBCCDD })

    s0 = s.copy()
    s0.add_constraints(c == 0)
    nose.tools.assert_equal(set(s0.solver.eval_upto(s0.memory.load(0x6000, 4), 10)), { 0x11223344 })

    s1 = s.copy()
    s1.add_constraints(c == 1)
    nose.tools.assert_equal(set(s1.solver.eval_upto(s1.memory.load(0x6000, 4), 10)), { 0xAABBCCDD })

    # condition with symbolic size
    x = s.solver.BVV(0x11223344, 32)
    y = s.solver.BVV(0xAABBCCDD, 32)
    c = s.solver.BVS('condition', 32)
    n = s.solver.BVS('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.solver.eval_upto(s0.memory.load(0x8000, 4), 10)), { 0x11223344 })

    s1 = s.copy()
    s1.add_constraints(c == 1)
    nose.tools.assert_equal(set(s1.solver.eval_upto(s1.memory.load(0x8000, 4), 10)), { 0x11223344, 0xAA223344, 0xAABB3344, 0xAABBCC44, 0xAABBCCDD })
Esempio n. 44
0
def test_cased_store():
    initial_memory = { 0: b'A', 1: b'A', 2: b'A', 3: b'A' }
    so = SimState(arch="AMD64", memory_backer=initial_memory)

    # sanity check
    nose.tools.assert_equal(so.solver.eval_upto(so.memory.load(0, 4), 2, cast_to=bytes), [b'AAAA'])

    # the values
    values = [
        None,
        so.solver.BVV(b'B'),
        so.solver.BVV(b'CC'),
        so.solver.BVV(b'DDD'),
        so.solver.BVV(b'EEEE')
    ]

    # try the write
    s = so.copy()
    x = s.solver.BVS('x', 32)
    s.memory.store_cases(0, values, [ x == i for i in range(len(values)) ])
    for i,v in enumerate(values):
        v = b'' if v is None else s.solver.eval(v, cast_to=bytes)
        w = s.solver.eval_upto(s.memory.load(0, 4), 2, cast_to=bytes, extra_constraints=[x==i])
        nose.tools.assert_equal(w, [v.ljust(4, b'A')])

    # and now with a fallback
    y = s.solver.BVS('y', 32)
    s.memory.store_cases(0, values, [ y == i for i in range(len(values)) ], fallback=s.solver.BVV(b'XXXX'))
    for i,v in enumerate(values):
        v = b'' if v is None else s.solver.eval(v, cast_to=bytes)
        w = s.solver.eval_upto(s.memory.load(0, 4), 2, cast_to=bytes, extra_constraints=[y==i])
        nose.tools.assert_equal(w, [v.ljust(4, b'X')])

    # and now with endness
    y = s.solver.BVS('y', 32)
    s.memory.store_cases(0, values, [ y == i for i in range(len(values)) ], fallback=s.solver.BVV(b'XXXX'), endness="Iend_LE")
    for i,v in enumerate(values):
        v = b'' if v is None else s.solver.eval(v, cast_to=bytes)
        w = s.solver.eval_upto(s.memory.load(0, 4), 2, cast_to=bytes, extra_constraints=[y==i])
        print(w, v.rjust(4, b'X'))
        nose.tools.assert_equal(w, [v.rjust(4, b'X')])

    # and write all Nones
    s = so.copy()
    z = s.solver.BVS('z', 32)
    s.memory.store_cases(0, [ None, None, None ], [ z == 0, z == 1, z == 2])
    for i in range(len(values)):
        w = s.solver.eval_upto(s.memory.load(0, 4), 2, cast_to=bytes, extra_constraints=[z==i])
        nose.tools.assert_equal(w, [b'AAAA'])

    # and all Nones with a fallback
    u = s.solver.BVS('w', 32)
    s.memory.store_cases(0, [ None, None, None ], [ u == 0, u == 1, u == 2], fallback=s.solver.BVV(b'WWWW'))
    for i,v in enumerate(values):
        w = s.solver.eval_upto(s.memory.load(0, 4), 2, cast_to=bytes, extra_constraints=[u==i])
        nose.tools.assert_equal(w, [b'WWWW'])

    # and all identical values
    s = so.copy()
    #t = s.solver.BVS('t', 32)
    s.memory.store_cases(0, [ s.solver.BVV(b'AA'), s.solver.BVV(b'AA'), s.solver.BVV(b'AA') ], [ u == 0, u == 1, u == 2], fallback=s.solver.BVV(b'AA'))
    r = s.memory.load(0, 2)
    nose.tools.assert_equal(r.op, 'BVV')
    nose.tools.assert_equal(s.solver.eval_upto(r, 2, cast_to=bytes), [b'AA'])

    # and all identical values, with varying fallback
    s = so.copy()
    #t = s.solver.BVS('t', 32)
    s.memory.store_cases(0, [ s.solver.BVV(b'AA'), s.solver.BVV(b'AA'), s.solver.BVV(b'AA') ], [ u == 0, u == 1, u == 2], fallback=s.solver.BVV(b'XX'))
    r = s.memory.load(0, 2)
    nose.tools.assert_equal(sorted(s.solver.eval_upto(r, 3, cast_to=bytes)), [b'AA', b'XX'])

    # and some identical values
    s = so.copy()
    #q = s.solver.BVS('q', 32)
    values = [ b'AA', b'BB', b'AA' ]
    s.memory.store_cases(0, [ s.solver.BVV(v) for v in values ], [ u == i for i in range(len(values))], fallback=s.solver.BVV(b'XX'))
    r = s.memory.load(0, 2)
    for i,v in enumerate(values + [b'XX']):
        w = s.solver.eval_upto(s.memory.load(0, 2), 2, cast_to=bytes, extra_constraints=[u==i])
        nose.tools.assert_equal(w, [(values+[b'XX'])[i]])
Esempio n. 45
0
def test_abstract_memory():
    initial_memory = {0: b'A', 1: b'B', 2: b'C', 3: b'D'}

    s = SimState(mode='static',
                 arch="AMD64",
                 memory_backer=initial_memory,
                 add_options={o.ABSTRACT_SOLVER, o.ABSTRACT_MEMORY})
    se = s.se

    def to_vs(region, offset):
        return s.solver.VS(s.arch.bits, region, 0, offset)

    # Load a single-byte constant from global region
    expr = s.memory.load(to_vs('global', 2), 1)
    nose.tools.assert_equal(s.solver.eval(expr), 0x43)
    nose.tools.assert_equal(s.solver.max_int(expr), 0x43)
    nose.tools.assert_equal(s.solver.min_int(expr), 0x43)

    # Store a single-byte constant to global region
    s.memory.store(to_vs('global', 1), s.solver.BVV(b'D'), 1)
    expr = s.memory.load(to_vs('global', 1), 1)
    nose.tools.assert_equal(s.solver.eval(expr), 0x44)

    # Store a single-byte StridedInterval to global region
    si_0 = s.solver.BVS('unnamed', 8, 10, 20, 2)
    s.memory.store(to_vs('global', 4), si_0)

    # Load the single-byte StridedInterval from global region
    expr = s.memory.load(to_vs('global', 4), 1)
    nose.tools.assert_equal(s.solver.min_int(expr), 10)
    nose.tools.assert_equal(s.solver.max_int(expr), 20)
    nose.tools.assert_equal(s.solver.eval_upto(expr, 100), [10, 12, 14, 16, 18, 20])

    # Store a two-byte StridedInterval object to global region
    si_1 = s.solver.BVS('unnamed', 16, 10, 20, 2)
    s.memory.store(to_vs('global', 5), si_1)

    # Load the two-byte StridedInterval object from global region
    expr = s.memory.load(to_vs('global', 5), 2)
    nose.tools.assert_true(claripy.backends.vsa.identical(expr, si_1))

    # Store a four-byte StridedInterval object to global region
    si_2 = s.solver.BVS('unnamed', 32, 8000, 9000, 2)
    s.memory.store(to_vs('global', 7), si_2)

    # Load the four-byte StridedInterval object from global region
    expr = s.memory.load(to_vs('global', 7), 4)
    nose.tools.assert_true(claripy.backends.vsa.identical(expr, s.solver.BVS('unnamed', 32, 8000, 9000, 2)))

    # Test default values
    s.options.remove(o.SYMBOLIC_INITIAL_VALUES)
    expr = s.memory.load(to_vs('global', 100), 4)
    nose.tools.assert_true(claripy.backends.vsa.identical(expr, s.solver.BVS('unnamed', 32, 0, 0, 0)))

    # Test default values (symbolic)
    s.options.add(o.SYMBOLIC_INITIAL_VALUES)
    expr = s.memory.load(to_vs('global', 104), 4)
    nose.tools.assert_true(claripy.backends.vsa.identical(expr, s.solver.BVS('unnamed', 32, 0, 0xffffffff, 1)))
    nose.tools.assert_true(claripy.backends.vsa.identical(expr, s.solver.BVS('unnamed', 32, -0x80000000, 0x7fffffff, 1)))

    #
    # Merging
    #

    # Merging two one-byte values
    s.memory.store(to_vs('function_merge', 0), s.solver.BVS('unnamed', 8, 0x10, 0x10, 0))
    a = s.copy()
    a.memory.store(to_vs('function_merge', 0), s.solver.BVS('unnamed', 8, 0x20, 0x20, 0))

    b = s.merge(a)[0]
    expr = b.memory.load(to_vs('function_merge', 0), 1)
    nose.tools.assert_true(claripy.backends.vsa.identical(expr, s.solver.BVS('unnamed', 8, 0x10, 0x20, 0x10)))

    #  |  MO(value_0)  |
    #  |  MO(value_1)  |
    # 0x20          0x24
    # Merge one byte in value_0/1 means merging the entire MemoryObject
    a = s.copy()
    a.memory.store(to_vs('function_merge', 0x20), se.SI(bits=32, stride=0, lower_bound=0x100000, upper_bound=0x100000))
    b = s.copy()
    b.memory.store(to_vs('function_merge', 0x20), se.SI(bits=32, stride=0, lower_bound=0x100001, upper_bound=0x100001))
    c = a.merge(b)[0]
    expr = c.memory.load(to_vs('function_merge', 0x20), 4)
    nose.tools.assert_true(claripy.backends.vsa.identical(expr, se.SI(bits=32, stride=1, lower_bound=0x100000, upper_bound=0x100001)))
    c_mem = c.memory.regions['function_merge'].memory.mem
    object_set = {c_mem[0x20], c_mem[0x20], c_mem[0x22], c_mem[0x23]}
    nose.tools.assert_equal(len(object_set), 1)

    a = s.copy()
    a.memory.store(to_vs('function_merge', 0x20), se.SI(bits=32, stride=0x100000, lower_bound=0x100000, upper_bound=0x200000))
    b = s.copy()
    b.memory.store(to_vs('function_merge', 0x20), se.SI(bits=32, stride=0, lower_bound=0x300000, upper_bound=0x300000))
    c = a.merge(b)[0]
    expr = c.memory.load(to_vs('function_merge', 0x20), 4)
    nose.tools.assert_true(claripy.backends.vsa.identical(expr, se.SI(bits=32, stride=0x100000, lower_bound=0x100000, upper_bound=0x300000)))
    object_set = {c_mem[0x20], c_mem[0x20], c_mem[0x22], c_mem[0x23]}
    nose.tools.assert_equal(len(object_set), 1)

    #
    # Widening
    #

    a = s.solver.SI(bits=32, stride=1, lower_bound=1, upper_bound=2)
    b = s.solver.SI(bits=32, stride=1, lower_bound=1, upper_bound=3)
    a = a.reversed
    b = b.reversed
Esempio n. 46
0
class BlockState(object):
    def __init__(self, project, addr, state=None, taint_region=None):
        self.project = project
        self.addr = addr
        self.block_addr = addr
        self.taint_region = taint_region
        self.state = state

        self.tempstore = None
        self.tags = []
        self.write_targets = []

        if self.state is None:
            self.state = SimState(arch=project.arch,
                    mode='symbolic',
                    special_memory_filler=lambda name, bits, _state: BiHead(claripy.BVV(0, bits), claripy.BVV(0, bits)),
                    add_options={sim_options.ABSTRACT_MEMORY, sim_options.SPECIAL_MEMORY_FILL}
                )
            self.state.scratch.ins_addr = 0
            if project.arch.name.startswith('ARM'):
                it = self.state.regs.itstate
                it.taints['it'] = True
                self.state.regs.itstate = it

    def copy(self, newaddr):
        return BlockState(self.project, newaddr, state=self.state.copy(), taint_region=self.taint_region)

    def get_reg(self, offset, ty):
        if isinstance(ty, int):
            ty = 'Ity_I%d' % ty
        size = vexutils.extract_int(ty)
        val = self.state.registers.load(offset, size//8)
        if ty.startswith('Ity_F'):
            val = val.raw_to_fp()
        return val

    def put_reg(self, offset, val):
        self.state.registers.store(offset, val)

    def get_tmp(self, tmpnum):
        return self.tempstore.read(tmpnum)

    def put_tmp(self, tmpnum, val):
        self.tempstore.write(tmpnum, val)

    def get_mem(self, addr, ty):
        if isinstance(ty, int):
            ty = 'Ity_I%d' % ty
        size = vexutils.extract_int(ty)
        addr_vs = self.state.solver.VS(bits=self.state.arch.bits, region=addr.taints['pointer'] if addr.taints['pointer'] else 'global', val=addr.as_unsigned)
        val = self.state.memory.load(addr_vs, size//8, endness=self.state.arch.memory_endness)
        if ty.startswith('Ity_F'):
            val = val.raw_to_fp()
        return val

    def put_mem(self, addr, val):
        if not addr.taints['pointer']:
            return      # don't store anything to memory that's not an accounted-for region
        addr_vs = self.state.solver.VS(bits=self.state.arch.bits, region=addr.taints['pointer'], val=addr.as_unsigned)
        self.state.scratch.ins_addr += 1
        self.state.memory.store(addr_vs, val, endness=self.state.arch.memory_endness)
        self.write_targets.append((addr_vs, val.length//8))

    def access(self, addr_expression, access_type):
        if addr_expression.taints['pointer'] != self.taint_region:
            return
        self.tags.append(('ACCESS', PendingBinaryData.make_bindata(addr_expression, self.addr, access_type)))

    def alloc(self, addr_expression):
        self.tags.append(('ALLOC', PendingBinaryData.make_bindata(addr_expression, self.addr, 0)))

    def handle_irsb(self, block):
        self.tempstore = TempStore(block.tyenv)

        for stmt_idx, stmt in enumerate(block.statements):
            path = ['statements', stmt_idx]
            self.handle_statement(stmt, block.tyenv, path)

    def handle_statement(self, stmt, tyenv, path):
        if stmt.tag in ('Ist_NoOp', 'Ist_AbiHint', 'Ist_MBE'):
            pass

        elif stmt.tag == 'Ist_IMark':
            self.addr = stmt.addr + stmt.delta

        elif stmt.tag == 'Ist_Exit':
            self.handle_expression(stmt.dst, tyenv, path + ['dst'])
            # Let the cfg take care of control flow!

        elif stmt.tag == 'Ist_WrTmp':
            expression = self.handle_expression(stmt.data, tyenv, path + ['data'])
            self.put_tmp(stmt.tmp, expression)

        elif stmt.tag == 'Ist_Store':
            expression = self.handle_expression(stmt.data, tyenv, path + ['data'])
            address = self.handle_expression(stmt.addr, tyenv, path + ['addr'])
            self.put_mem(address, expression)
            self.access(address, ACCESS_WRITE)
            self.access(expression, ACCESS_POINTER)

        elif stmt.tag == 'Ist_Put':
            expression = self.handle_expression(stmt.data, tyenv, path + ['data'])
            self.put_reg(stmt.offset, expression)
            if stmt.offset == self.project.arch.sp_offset:
                if not expression.taints['concrete']:
                    l.warning("This function appears to use alloca(). Abort.")
                    raise FidgetAnalysisFailure
                self.alloc(expression)

        elif stmt.tag == 'Ist_LoadG':
            # Conditional loads. Lots of bullshit.
            addr_expression = self.handle_expression(stmt.addr, tyenv, path + ['addr'])
            self.access(addr_expression, ACCESS_READ)

            # load the actual data
            data_expression = self.get_mem(addr_expression, stmt.cvt_types[0])
            # it then needs a type conversion applied to it
            conv_diff = vexutils.extract_int(stmt.cvt_types[1]) - vexutils.extract_int(stmt.cvt_types[0])
            if conv_diff != 0:
                concrete = data_expression.taints['concrete']
                deps = data_expression.taints['deps']
                if 'S' in stmt.cvt:
                    data_expression = data_expression.sign_extend(conv_diff)
                else:
                    data_expression = data_expression.zero_extend(conv_diff)
                data_expression.taints['concrete'] = concrete
                data_expression.taints['deps'] = deps

            self.put_tmp(stmt.dst, data_expression)
            self.handle_expression(stmt.guard, tyenv, path + ['guard'])
            self.handle_expression(stmt.alt, tyenv, path + ['alt'])

        elif stmt.tag == 'Ist_StoreG':
            # Conditional store
            addr_expr = self.handle_expression(stmt.addr, tyenv, path + ['addr'])
            value_expr = self.handle_expression(stmt.data, tyenv, path + ['data'])
            self.handle_expression(stmt.guard, tyenv, path + ['guard'])
            self.put_mem(addr_expr, value_expr)
            self.access(addr_expr, ACCESS_WRITE)
            self.access(value_expr, ACCESS_POINTER)

        elif stmt.tag == 'Ist_PutI':    # haha no
            self.handle_expression(stmt.data, tyenv, path + ['data'])
        elif stmt.tag == 'Ist_CAS':     # HA ha no
            if stmt.oldLo != 4294967295:
                self.tempstore.default(stmt.oldLo)
            if stmt.oldHi != 4294967295:
                self.tempstore.default(stmt.oldHi)
        elif stmt.tag == 'Ist_Dirty':   # hahAHAHAH NO
            if stmt.tmp != 4294967295:
                self.tempstore.default(stmt.tmp)
        else:
            raise FidgetUnsupportedError("Unknown vex instruction???", stmt)

    def handle_expression(self, expr, tyenv, path):
        size = expr.result_size(tyenv) if not expr.tag.startswith('Ico_') else expr.size
        ty = expr.result_type(tyenv) if not expr.tag.startswith('Ico_') else expr.type
        addr = self.addr
        if expr.tag == 'Iex_Get':
            return self.get_reg(expr.offset, ty)
        elif expr.tag == 'Iex_RdTmp':
            return self.get_tmp(expr.tmp)
        elif expr.tag == 'Iex_Load':
            addr_expression = self.handle_expression(expr.addr, tyenv, path + ['addr'])
            self.access(addr_expression, ACCESS_READ)
            return self.get_mem(addr_expression, ty)
        elif expr.tag == 'Iex_Const' or expr.tag.startswith('Ico_'):
            if expr.tag == 'Iex_Const':
                expr = expr.con
            if 'F' in ty:
                if size == 32:
                    values = BiHead(
                            claripy.FPV(expr.value, claripy.fp.FSORT_FLOAT),
                            claripy.FPS('%x_%d' % (addr, path[1]), claripy.fp.FSORT_FLOAT)
                        )
                elif size == 64:
                    values = BiHead(
                            claripy.FPV(expr.value, claripy.fp.FSORT_DOUBLE),
                            claripy.FPS('%x_%d' % (addr, path[1]), claripy.fp.FSORT_DOUBLE)
                        )
                else:
                    raise FidgetUnsupportedError("Why is there a FP const of size %d" % size)
            else:
                values = BiHead(
                        claripy.BVV(expr.value, size),
                        claripy.BVS('%x_%d' % (addr, path[1]), size)
                    )
            values.taints['deps'].append(PendingBinaryData(self.project, self.addr, values, path))
            values.taints['concrete'] = True
            values.taints['concrete_root'] = True
            return values
        elif expr.tag == 'Iex_ITE':
            false_expr = self.handle_expression(expr.iffalse, tyenv, path + ['iffalse'])
            truth_expr = self.handle_expression(expr.iftrue, tyenv, path + ['iftrue'])
            values = truth_expr if truth_expr.taints['pointer'] else false_expr
            cond_expr = self.handle_expression(expr.cond, tyenv, path + ['cond'])
            if not cond_expr.taints['it']:
                values.taints['concrete'] = false_expr.taints['concrete'] and truth_expr.taints['concrete']
            values.taints['it'] = false_expr.taints['it'] or truth_expr.taints['it']
            return values
        elif expr.tag in ('Iex_Unop','Iex_Binop','Iex_Triop','Iex_Qop'):
            args = []
            for i, sub_expr in enumerate(expr.args):
                arg = self.handle_expression(sub_expr, tyenv, path + ['args', i])
                if expr.op.startswith('Iop_Mul') or expr.op.startswith('Iop_And') \
                        or (i == 0 and expr.op in ROUNDING_IROPS):
                    if arg.taints['concrete_root']:
                        arg = BiHead(arg.cleanval, arg.cleanval)
                        arg.taints['concrete'] = True
                args.append(arg)
            try:
                values = BiHead(
                        operations[expr.op].calculate(*(x.cleanval for x in args)),
                        operations[expr.op].calculate(*(x.dirtyval for x in args))
                    )
            except SimOperationError:
                l.exception("SimOperationError while running op '%s', returning null", expr.op)
                return BiHead.default(ty)
            except KeyError:
                l.error("Unsupported operation '%s', returning null", expr.op)
                return BiHead.default(ty)
            else:
                # propogate the taints correctly
                values.taints['concrete'] = True
                for arg in args:
                    values.taints['deps'].extend(arg.taints['deps'])
                    values.taints['concrete'] = values.taints['concrete'] and arg.taints['concrete']
                    values.taints['it'] = values.taints['it'] or arg.taints['it']
                if expr.op.startswith('Iop_Add') or expr.op.startswith('Iop_And') or \
                   expr.op.startswith('Iop_Or') or expr.op.startswith('Iop_Xor'):
                    t1 = args[0].taints['pointer']
                    t2 = args[1].taints['pointer']
                    values.taints['pointer'] = (t1 if t1 else t2) if (bool(t1) ^ bool(t2)) else False
                elif expr.op.startswith('Iop_Sub'):
                    t1 = args[0].taints['pointer']
                    t2 = args[1].taints['pointer']
                    values.taints['pointer'] = t1 if t1 and not t2 else False
                return values
        elif expr.tag == 'Iex_CCall':
            values = BiHead.default(ty)
            for i, expr in enumerate(expr.args):
                arg = self.handle_expression(expr, tyenv, path + ['args', i])
                values.taints['it'] = values.taints['it'] or arg.taints['it']
            return values
        elif expr.tag == 'Iex_GetI':
            return BiHead.default(ty)
        else:
            raise FidgetUnsupportedError('Unknown expression tag ({:#x}): {!r}'.format(addr, expr.tag))

    def end(self, clean=False):
        for name in self.project.arch.default_symbolic_registers:
            offset = self.project.arch.registers[name][0]
            if offset in (self.project.arch.sp_offset, self.project.arch.bp_offset, self.project.arch.ip_offset):
                continue
            if name == 'r7' and self.project.arch.name.startswith('ARM') and self.addr & 1 == 1:
                continue
            # values remaining in registers at end-of-block are pointers! Probably.
            value = getattr(self.state.regs, name)
            if value.taints['already_pointered']:
                continue
            self.access(value, ACCESS_POINTER)
            value.taints['already_pointered'] = True
            if value.taints['concrete'] and not value.taints['pointer']:
                # Don't let nonpointer values persist between block states
                value = BiHead(value.cleanval, value.cleanval)
            self.state.registers.store(offset, value)

        # If a call, scrub the return-value register
        if clean:
            self.state.registers.store(self.state.arch.ret_offset, BiHead(claripy.BVV(0, self.state.arch.bits), claripy.BVV(0, self.state.arch.bits)))

        # Don't let nonpointer vales persist between block state... in memory!
        for addr, size in self.write_targets:
            value = self.state.memory.load(addr, size, endness=self.state.arch.memory_endness)
            if not value.taints['pointer']:
                replacement = BiHead(value.cleanval, value.cleanval)
                self.state.scratch.ins_addr += 1
                self.state.memory.store(addr, replacement, endness=self.state.arch.memory_endness)
Esempio n. 47
0
def broken_inline_strstr():
    l.info("concrete haystack and needle")
    s = SimState(arch="AMD64", mode="symbolic")
    str_haystack = s.solver.BVV(0x41424300, 32)
    str_needle = s.solver.BVV(0x42430000, 32)
    addr_haystack = s.solver.BVV(0x10, 64)
    addr_needle = s.solver.BVV(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, arguments=[addr_haystack, addr_needle])
    nose.tools.assert_true(s.solver.unique(ss_res))
    nose.tools.assert_equal(s.solver.eval(ss_res), 0x11)

    l.info("concrete haystack, symbolic needle")
    s = SimState(arch="AMD64", mode="symbolic")
    str_haystack = s.solver.BVV(0x41424300, 32)
    str_needle = s.solver.BVS("wtf", 32)
    addr_haystack = s.solver.BVV(0x10, 64)
    addr_needle = s.solver.BVV(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, arguments=[addr_haystack, addr_needle])
    nose.tools.assert_false(s.solver.unique(ss_res))
    nose.tools.assert_equal(len(s.solver.eval_upto(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.solver.eval_upto(match_needle, 300)), 259)
    nose.tools.assert_equal(len(s_match.solver.eval_upto(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.solver.BVV(0x10, 64)
    addr_needle = s.solver.BVV(0xb0, 64)
    len_needle = strlen(s, arguments=[addr_needle])

    ss_res = strstr(s, arguments=[addr_haystack, addr_needle])
    nose.tools.assert_false(s.solver.unique(ss_res))
    nose.tools.assert_equal(len(s.solver.eval_upto(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, arguments=[ss_res, addr_needle, len_needle])
    nose.tools.assert_sequence_equal(s_match.solver.eval_upto(match_cmp, 10), [0])

    r_mm = strstr(s_match, arguments=[addr_haystack, addr_needle])
    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, arguments=[addr_haystack, addr_needle])
    s_nss.add_constraints(nomatch_ss != 0)
    nose.tools.assert_false(s_nss.satisfiable())
Esempio n. 48
0
def test_memcpy():
    l.info("concrete src, concrete dst, concrete len")
    l.debug("... full copy")
    s = SimState(arch="AMD64", mode="symbolic")
    dst = s.solver.BVV(0x41414141, 32)
    dst_addr = s.solver.BVV(0x1000, 64)
    src = s.solver.BVV(0x42424242, 32)
    src_addr = s.solver.BVV(0x2000, 64)

    s.memory.store(dst_addr, dst)
    s.memory.store(src_addr, src)
    memcpy(s, arguments=[dst_addr, src_addr, s.solver.BVV(4, 64)])
    new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE')
    nose.tools.assert_equal(s.solver.eval_upto(new_dst, 2, cast_to=bytes), [ b"BBBB" ])

    l.info("giant copy")
    s = SimState(arch="AMD64", mode="symbolic", remove_options=angr.options.simplification)
    s.memory._maximum_symbolic_size = 0x2000000
    size = s.solver.BVV(0x1000000, 64)
    dst_addr = s.solver.BVV(0x2000000, 64)
    src_addr = s.solver.BVV(0x4000000, 64)

    memcpy(s, arguments=[dst_addr, src_addr, size])
    nose.tools.assert_is(s.memory.load(dst_addr, size), s.memory.load(src_addr, size))

    l.debug("... partial copy")
    s = SimState(arch="AMD64", mode="symbolic")
    s.memory.store(dst_addr, dst)
    s.memory.store(src_addr, src)
    memcpy(s, arguments=[dst_addr, src_addr, s.solver.BVV(2, 64)])
    new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE')
    nose.tools.assert_equal(s.solver.eval_upto(new_dst, 2, cast_to=bytes), [ b"BBAA" ])

    l.info("symbolic src, concrete dst, concrete len")
    s = SimState(arch="AMD64", mode="symbolic")
    dst = s.solver.BVV(0x41414141, 32)
    dst_addr = s.solver.BVV(0x1000, 64)
    src = s.solver.BVS("src", 32)
    src_addr = s.solver.BVV(0x2000, 64)

    s.memory.store(dst_addr, dst)
    s.memory.store(src_addr, src)

    # make sure it copies it all
    memcpy(s, arguments=[dst_addr, src_addr, s.solver.BVV(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.solver.BVV(0x41414141, 32)
    dst_addr = s.solver.BVV(0x1000, 64)
    src = s.solver.BVS("src", 32)
    src_addr = s.solver.BVV(0x2000, 64)
    cpylen = s.solver.BVS("len", 64)

    s.memory.store(dst_addr, dst)
    s.memory.store(src_addr, src)
    memcpy(s, 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.solver.unique(s1.memory.load(dst_addr+1, 3)))
    nose.tools.assert_equal(len(s1.solver.eval_upto(s1.memory.load(dst_addr, 1), 300)), 256)

    s2 = s.copy()
    s2.add_constraints(cpylen == 2)
    nose.tools.assert_equal(len(s2.solver.eval_upto(result[31:24], 300)), 256)
    nose.tools.assert_equal(len(s2.solver.eval_upto(result[23:16], 300)), 256)
    nose.tools.assert_equal(s2.solver.eval_upto(result[15:0], 300, cast_to=bytes), [ b'AA' ])

    l.info("concrete src, concrete dst, symbolic len")
    dst = s2.solver.BVV(0x41414141, 32)
    dst_addr = s2.solver.BVV(0x1000, 64)
    src = s2.solver.BVV(0x42424242, 32)
    src_addr = s2.solver.BVV(0x2000, 64)

    s = SimState(arch="AMD64", mode="symbolic")
    s.memory.store(dst_addr, dst)
    s.memory.store(src_addr, src)
    cpylen = s.solver.BVS("len", 64)

    s.add_constraints(s.solver.ULE(cpylen, 4))
    memcpy(s, arguments=[dst_addr, src_addr, cpylen])
    new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE')
    nose.tools.assert_sequence_equal(sorted(s.solver.eval_upto(new_dst, 300, cast_to=bytes)), [ b'AAAA', b'BAAA', b'BBAA', b'BBBA', b'BBBB' ])
Esempio n. 49
0
def test_memcmp():
    l.info("concrete src, concrete dst, concrete len")

    l.debug("... full cmp")
    s = SimState(arch="AMD64", mode="symbolic")
    dst = s.solver.BVV(0x41414141, 32)
    dst_addr = s.solver.BVV(0x1000, 64)
    src = s.solver.BVV(0x42424242, 32)
    src_addr = s.solver.BVV(0x2000, 64)
    s.memory.store(dst_addr, dst)
    s.memory.store(src_addr, src)
    r = memcmp(s, arguments=[dst_addr, src_addr, s.solver.BVV(4, 64)])
    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, arguments=[dst_addr, src_addr, s.solver.BVV(0, 64)])
    nose.tools.assert_equal(s.solver.eval_upto(r, 2), [ 0 ])

    l.info("symbolic src, concrete dst, concrete len")
    s = SimState(arch="AMD64", mode="symbolic")
    dst = s.solver.BVV(0x41414141, 32)
    dst_addr = s.solver.BVV(0x1000, 64)
    src = s.solver.BVS("src", 32)

    src_addr = s.solver.BVV(0x2000, 64)

    s.memory.store(dst_addr, dst)
    s.memory.store(src_addr, src)

    # make sure it copies it all
    r = memcmp(s, arguments=[dst_addr, src_addr, s.solver.BVV(4, 64)])

    s_match = s.copy()
    s_match.add_constraints(r == 0)
    m = s_match.memory.load(src_addr, 4)
    nose.tools.assert_equal(s_match.solver.eval_upto(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.solver.solution(m, 0x41414141))

    l.info("symbolic src, concrete dst, symbolic len")
    s = SimState(arch="AMD64", mode="symbolic")
    dst = s.solver.BVV(0x41414141, 32)
    dst_addr = s.solver.BVV(0x1000, 64)
    src = s.solver.BVS("src", 32)
    src_addr = s.solver.BVV(0x2000, 64)
    cmplen = s.solver.BVS("len", 64)

    s.memory.store(dst_addr, dst)
    s.memory.store(src_addr, src)
    r = memcmp(s, arguments=[dst_addr, src_addr, cmplen])

    # look at effects of different lengths
    s1 = s.copy()
    s1.add_constraints(cmplen == 1)
    s1.add_constraints(r == 0)
    l.debug("... simplifying")
    s1.solver._solver.simplify()
    l.debug("... solving")
    nose.tools.assert_equal(s1.solver.eval_upto(src[31:24], 2), [ 0x41 ])
    nose.tools.assert_false(s1.solver.unique(src[31:16]))
    l.debug("... solved")

    s2 = s.copy()
    s2.add_constraints(cmplen == 2)
    s2.add_constraints(r == 0)
    nose.tools.assert_equal(s2.solver.eval_upto(s2.memory.load(src_addr, 2), 2), [ 0x4141 ])
    nose.tools.assert_false(s2.solver.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.solver.solution(s2u.memory.load(src_addr, 2), 0x4141))
Esempio n. 50
0
def test_strncpy():
    l.info("concrete src, concrete dst, concrete len")
    l.debug("... full copy")
    s = SimState(arch="AMD64", mode="symbolic")
    dst = s.solver.BVV(0x41414100, 32)
    dst_addr = s.solver.BVV(0x1000, 64)
    src = s.solver.BVV(0x42420000, 32)
    src_addr = s.solver.BVV(0x2000, 64)

    s.memory.store(dst_addr, dst)
    s.memory.store(src_addr, src)
    strncpy(s, arguments=[dst_addr, src_addr, s.solver.BVV(3, 64)])
    new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE')
    nose.tools.assert_equal(s.solver.eval(new_dst, cast_to=bytes), b"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, arguments=[dst_addr, src_addr, s.solver.BVV(2, 64)])
    new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE')
    nose.tools.assert_equal(s.solver.eval_upto(new_dst, 2, cast_to=bytes), [ b"BBA\x00" ])

    l.info("symbolic src, concrete dst, concrete len")
    s = SimState(arch="AMD64", mode="symbolic")
    dst = s.solver.BVV(0x41414100, 32)
    dst_addr = s.solver.BVV(0x1000, 64)
    src = s.solver.BVS("src", 32)
    src_addr = s.solver.BVV(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, arguments=[src_addr]) == 2)

    # sanity check
    s_false = s.copy()
    s_false.add_constraints(strlen(s_false, arguments=[src_addr]) == 3)
    nose.tools.assert_false(s_false.satisfiable())

    strncpy(s, arguments=[dst_addr, src_addr, 3])
    nose.tools.assert_true(s.satisfiable())
    c = strcmp(s, arguments=[dst_addr, src_addr])

    nose.tools.assert_sequence_equal(s.solver.eval_upto(c, 10), [0])

    l.info("symbolic src, concrete dst, symbolic len")
    s = SimState(arch="AMD64", mode="symbolic")
    dst = s.solver.BVV(0x41414100, 32)
    dst_addr = s.solver.BVV(0x1000, 64)
    src = s.solver.BVS("src", 32)
    src_addr = s.solver.BVV(0x2000, 64)
    maxlen = s.solver.BVS("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, arguments=[src_addr]) == 2)
    strncpy(s, arguments=[dst_addr, src_addr, maxlen])
    c = strcmp(s, arguments=[dst_addr, src_addr])

    s_match = s.copy()
    s_match.add_constraints(c == 0)
    nose.tools.assert_equal(s_match.solver.min_int(maxlen), 3)

    s_nomatch = s.copy()
    s_nomatch.add_constraints(c != 0)
    nose.tools.assert_equal(s_nomatch.solver.max_int(maxlen), 2)

    l.info("concrete src, concrete dst, symbolic len")
    l.debug("... full copy")
    s = SimState(arch="AMD64", mode="symbolic")

    dst = s.solver.BVV(0x41414100, 32)
    dst_addr = s.solver.BVV(0x1000, 64)
    src = s.solver.BVV(0x42420000, 32)
    src_addr = s.solver.BVV(0x2000, 64)
    maxlen = s.solver.BVS("len", 64)

    s.memory.store(dst_addr, dst)
    s.memory.store(src_addr, src)
    strncpy(s, arguments=[dst_addr, src_addr, maxlen])
    r = s.memory.load(dst_addr, 4, endness='Iend_BE')
    #print repr(r.solver.eval_upto(r, 10, cast_to=bytes))
    nose.tools.assert_sequence_equal(sorted(s.solver.eval_upto(r, 10, cast_to=bytes)), [ b"AAA\x00", b'BAA\x00', b'BB\x00\x00', b'BBA\x00' ] )
Esempio n. 51
0
def test_inline_strcmp():
    s = SimState(arch="AMD64", mode="symbolic")
    str_a = s.solver.BVV(0x41414100, 32)
    str_b = s.solver.BVS("mystring", 32)

    a_addr = s.solver.BVV(0x10, 64)
    b_addr = s.solver.BVV(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 = strcmp(s_cmp, arguments=[a_addr, b_addr])
    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.solver.unique(str_b))
    nose.tools.assert_false(s_nomatch.solver.unique(str_b))
    nose.tools.assert_equal(s_match.solver.eval(str_b, cast_to=bytes), b"AAA\x00")

    s_ncmp = s.copy()
    ncmpres = strncmp(s_ncmp, arguments=[a_addr, b_addr, s.solver.BVV(2, s.arch.bits)])
    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.solver.unique(str_b))
    nose.tools.assert_true(s_match.solver.unique(s_match.memory.load(b_addr, 2)))
    nose.tools.assert_equal(len(s_match.solver.eval_upto(s_match.memory.load(b_addr, 3), 300)), 256)
    nose.tools.assert_false(s_nomatch.solver.unique(str_b))

    l.info("concrete a, symbolic b")
    s = SimState(arch="AMD64", mode="symbolic")
    str_a = s.solver.BVV(0x41424300, 32)
    str_b = s.solver.BVS("mystring", 32)
    a_addr = s.solver.BVV(0x10, 64)
    b_addr = s.solver.BVV(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, arguments=[a_addr, b_addr, s.solver.BVV(2, s_cmp.arch.bits)])
    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.solver.solution(str_b, 0x41420000))
    nose.tools.assert_true(s_match.solver.solution(str_b, 0x41421234))
    nose.tools.assert_true(s_match.solver.solution(str_b, 0x41424300))
    nose.tools.assert_false(s_nomatch.solver.solution(str_b, 0x41420000))
    nose.tools.assert_false(s_nomatch.solver.solution(str_b, 0x41421234))
    nose.tools.assert_false(s_nomatch.solver.solution(str_b, 0x41424300))

    l.info("symbolic a, symbolic b")
    s = SimState(arch="AMD64", mode="symbolic")
    a_addr = s.solver.BVV(0x10, 64)
    b_addr = s.solver.BVV(0xb0, 64)

    s_cmp = s.copy()
    cmpres = strcmp(s_cmp, arguments=[a_addr, b_addr])
    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, arguments=[a_addr, b_addr])
    s_match.add_constraints(m_res != 0)
    nm_res = strcmp(s_nomatch, arguments=[a_addr, b_addr])
    s_nomatch.add_constraints(nm_res == 0)

    nose.tools.assert_false(s_match.satisfiable())
    nose.tools.assert_false(s_match.satisfiable())