Example #1
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))
Example #2
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
Example #3
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))
Example #4
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))
Example #5
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)
Example #6
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
Example #7
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))
Example #8
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))
Example #9
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))
Example #10
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))
Example #11
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)))
Example #12
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))
Example #13
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))
Example #14
0
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)
Example #15
0
def test_aarch64_32bit_ccalls():

    # GitHub issue #1238
    s = SimState(arch="AArch64")

    x = s.solver.BVS("x", 32)
    # A normal operation
    flag_z, _ = s_ccall.arm64g_calculate_flag_z(s, s_ccall.ARM64G_CC_OP_ADD32, x, s.solver.BVV(1, 32), 0)
    nose.tools.assert_true(s.satisfiable(extra_constraints=(flag_z == 0,)))
    nose.tools.assert_true(s.satisfiable(extra_constraints=(flag_z == 1,)))
    # What VEX does
    flag_z, _ = s_ccall.arm64g_calculate_flag_z(s, s_ccall.ARM64G_CC_OP_ADD32, x.zero_extend(32), s.solver.BVV(1, 64), 0)
    nose.tools.assert_true(s.satisfiable(extra_constraints=(flag_z == 0,)))
    nose.tools.assert_true(s.satisfiable(extra_constraints=(flag_z == 1,)))
Example #16
0
def test_global_condition():
    s = SimState(arch="AMD64")

    s.regs.rax = 10
    old_rax = s.regs.rax
    with s.with_condition(False):
        nose.tools.assert_false(s.se.satisfiable())
        s.regs.rax = 20
    nose.tools.assert_is(s._global_condition, None)
    nose.tools.assert_is(old_rax, s.regs.rax)

    with s.with_condition(True):
        s.regs.rax = 20
    nose.tools.assert_is(s._global_condition, None)
    nose.tools.assert_is_not(old_rax, s.regs.rax)
    nose.tools.assert_is(s.se.BVV(20, s.arch.bits), s.regs.rax)

    with s.with_condition(s.regs.rbx != 0):
        s.regs.rax = 25
    nose.tools.assert_is(s._global_condition, None)
    nose.tools.assert_is_not(s.se.BVV(25, s.arch.bits), s.regs.rax)

    with s.with_condition(s.regs.rbx != 1):
        s.regs.rax = 30
    nose.tools.assert_is(s._global_condition, None)
    nose.tools.assert_is_not(s.se.BVV(30, s.arch.bits), s.regs.rax)

    with s.with_condition(s.regs.rbx == 0):
        nose.tools.assert_equals(s.se.eval_upto(s.regs.rbx, 10), [ 0 ])
        nose.tools.assert_items_equal(s.se.eval_upto(s.regs.rax, 10), [ 30 ])
    with s.with_condition(s.regs.rbx == 1):
        nose.tools.assert_equals(s.se.eval_upto(s.regs.rbx, 10), [ 1 ])
        nose.tools.assert_items_equal(s.se.eval_upto(s.regs.rax, 10), [ 25 ])
Example #17
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
Example #18
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,))
Example #19
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))
Example #20
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])
Example #21
0
def test_state():
    s = SimState(arch='AMD64')
    s.registers.store('sp', 0x7ffffffffff0000)
    nose.tools.assert_equals(s.se.eval(s.registers.load('sp')), 0x7ffffffffff0000)

    s.stack_push(s.se.BVV("ABCDEFGH"))
    nose.tools.assert_equals(s.se.eval(s.registers.load('sp')), 0x7fffffffffefff8)
    s.stack_push(s.se.BVV("IJKLMNOP"))
    nose.tools.assert_equals(s.se.eval(s.registers.load('sp')), 0x7fffffffffefff0)

    a = s.stack_pop()
    nose.tools.assert_equals(s.se.eval(s.registers.load('sp')), 0x7fffffffffefff8)
    nose.tools.assert_equals(s.se.eval(a, cast_to=str), "IJKLMNOP")

    b = s.stack_pop()
    nose.tools.assert_equals(s.se.eval(s.registers.load('sp')), 0x7ffffffffff0000)
    nose.tools.assert_equals(s.se.eval(b, cast_to=str), "ABCDEFGH")
Example #22
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
Example #23
0
def test_light_memory():
    s = SimState(arch='AMD64', plugins={'registers': SimLightRegisters()})
    assert type(s.registers) is SimLightRegisters

    assert s.regs.rax.symbolic
    s.regs.rax = 0x4142434445464748
    assert (s.regs.rax == 0x4142434445464748).is_true()

    assert s.regs.rbx.symbolic
    s.regs.rbx = 0x5555555544444444
    assert (s.regs.rbx == 0x5555555544444444).is_true()

    assert s.regs.rcx.symbolic

    s.regs.ah = 0
    assert (s.regs.rax == 0x4142434445460048).is_true()

    s.regs.cl = 0
    assert s.regs.rcx.symbolic
Example #24
0
def test_wcscmp():
    # concrete cases for the wide char version sufficiently overlap with strcmp and friends
    l.info("concrete a, symbolic b")
    s = SimState(arch="AMD64", mode="symbolic")
    heck = 'heck\x00'.encode('utf-16')[2:]  # remove encoding prefix
    a_addr = s.solver.BVV(0x10, 64)
    b_addr = s.solver.BVV(0xb0, 64)
    b_bvs = s.solver.BVS('b', len(heck) * 8)

    s.memory.store(a_addr, heck)
    s.memory.store(b_addr, b_bvs)

    r = wcscmp(s, arguments=[a_addr, b_addr])

    solutions = s.solver.eval_upto(b_bvs,
                                   2,
                                   cast_to=bytes,
                                   extra_constraints=(r == 0, ))
    nose.tools.assert_equal(solutions, [heck])
Example #25
0
def test_getchar():
    s = SimState(arch='AMD64', mode='symbolic')
    stdin = s.posix.files[0]
    stdin.content.store(0, "1234")
    nose.tools.assert_items_equal(s.se.any_n_int(stdin.pos, 300), [0])
    c = getchar(s, arguments=[]).ret_expr
    nose.tools.assert_items_equal(s.se.any_n_int(c, 300), [0x31])
    nose.tools.assert_items_equal(s.se.any_n_int(stdin.pos, 300), [1])

    c = getchar(s, arguments=[]).ret_expr
    nose.tools.assert_items_equal(s.se.any_n_int(c, 300), [0x32])
    nose.tools.assert_items_equal(s.se.any_n_int(stdin.pos, 300), [2])

    c = getchar(s, arguments=[]).ret_expr
    nose.tools.assert_items_equal(s.se.any_n_int(c, 300), [0x33])
    nose.tools.assert_items_equal(s.se.any_n_int(stdin.pos, 300), [3])

    c = getchar(s, arguments=[]).ret_expr
    nose.tools.assert_items_equal(s.se.any_n_int(c, 300), [0x34])
    nose.tools.assert_items_equal(s.se.any_n_int(stdin.pos, 300), [4])
Example #26
0
def test_struct_bitfield_complex():
    bitfield_struct2 = angr.types.parse_type("""struct bitfield_struct2
    {
        uint64_t    target    : 36,    
                    high8     :  8,   
                    reserved  :  7,
                    next      : 12,
                    bind      :  1;
    }""")

    angr.types.register_types(bitfield_struct2)
    state = SimState(arch="AMD64")
    state.memory.store(0x1000,
                       b"\xb3\xc7\xe9|\xad\xd7\xee$")  # store some random data
    struct = state.mem[0x1000].struct.bitfield_struct2.concrete
    assert struct.target == 0xD7CE9C7B3
    assert struct.high8 == 0x7A
    assert struct.next == 0x49D
    assert struct.bind == 0
    pass
Example #27
0
def test_alignment():
    for arch in all_arches:
        if arch.name in DEFAULT_CC:
            # There is nothing to test for soot about stack alignment
            if isinstance(arch, ArchSoot):
                continue
            l.info("Testing stack alignment for %s", arch.name)
            st = SimState(arch=arch)
            cc = DEFAULT_CC[arch.name](arch=arch)

            st.regs.sp = -1

            # setup callsite with one argument (0x1337), "returning" to 0
            cc.setup_callsite(st, 0, [0x1337])

            # ensure stack alignment is correct
            nose.tools.assert_true(
                st.solver.is_true(((st.regs.sp + cc.STACKARG_SP_DIFF) %
                                   cc.STACK_ALIGNMENT == 0)),
                'non-zero stack alignment after setup_callsite for %s' % cc)
Example #28
0
def test_state():
    s = SimState(arch='AMD64')
    s.registers.store('sp', 0x7ffffffffff0000)
    nose.tools.assert_equals(s.se.eval(s.registers.load('sp')),
                             0x7ffffffffff0000)

    s.stack_push(s.se.BVV("ABCDEFGH"))
    nose.tools.assert_equals(s.se.eval(s.registers.load('sp')),
                             0x7fffffffffefff8)
    s.stack_push(s.se.BVV("IJKLMNOP"))
    nose.tools.assert_equals(s.se.eval(s.registers.load('sp')),
                             0x7fffffffffefff0)

    a = s.stack_pop()
    nose.tools.assert_equals(s.se.eval(s.registers.load('sp')),
                             0x7fffffffffefff8)
    nose.tools.assert_equals(s.se.eval(a, cast_to=str), "IJKLMNOP")

    b = s.stack_pop()
    nose.tools.assert_equals(s.se.eval(s.registers.load('sp')),
                             0x7ffffffffff0000)
    nose.tools.assert_equals(s.se.eval(b, cast_to=str), "ABCDEFGH")
Example #29
0
def test_struct_bitfield_complex():
    bitfield_struct2 = angr.types.parse_type("""struct bitfield_struct2
    {
        uint64_t    target    : 36,    
                    high8     :  8,   
                    reserved  :  7,
                    next      : 12,
                    bind      :  1;
    }""")

    angr.types.register_types(bitfield_struct2)
    state = SimState(arch='AMD64')
    state.memory.store(0x1000,
                       b'\xb3\xc7\xe9|\xad\xd7\xee$')  # store some random data
    struct = state.mem[0x1000].struct.bitfield_struct2.concrete
    nose.tools.assert_equal(struct.target, 0xD7CE9C7B3)
    nose.tools.assert_equal(struct.high8, 0x7A)
    nose.tools.assert_equal(struct.next, 0x49D)
    nose.tools.assert_equal(struct.bind, 0)
    pass
Example #30
0
def excption_0():
    import claripy

    ins_code = "mov eax,-1 ; test eax,eax"
    address = 0x76fcbcfe

    encoding = pwn.asm(ins_code)
    count = len(encoding)
    print((str(encoding)))
    print(count)

    add_options = {angr.options.NO_SYMBOLIC_SYSCALL_RESOLUTION,
                   angr.options.LAZY_SOLVES,
                   angr.options.INITIALIZE_ZERO_REGISTERS,
                   angr.options.SIMPLIFY_REGISTER_WRITES,
                   angr.options.SIMPLIFY_MEMORY_WRITES,
                   # angr.options.CONCRETIZE,
                   # angr.options.FAST_MEMORY
                   }

    bc_arr = ""
    bc_arr = encoding

    irsb = pyvex.IRSB(bc_arr, 0x76fcbcfe, archinfo.ArchX86(), len(bc_arr))

    state = SimState(arch='X86', add_options=add_options)
    state.regs.eax = 0x5a4d
    state.regs.esi = 0x753e0001
    state.regs.esp = 0x12f8c0
    state.regs.eip = 0x76fcbcfe

    taint_len = 0x8000
    # taint_len = 0xd4000

    state.memory.store(0x753e0000, claripy.BVS(
        "TAINT_MapView", taint_len * 8), endness="Iend_LE")

    engine = angr.SimEngineVEX()

    irsb.pp()
    engine.process(state, irsb, inline=True)
Example #31
0
def test_calling_conventions():

    #
    # SimProcedures
    #

    from angr.calling_conventions import SimCCCdecl, SimCCMicrosoftFastcall

    args = [
        1, 2, 3, 4, 5, 6, 7, 8, 9, 1000, 100000, 1000000, 2000000, 14, 15, 16
    ]
    arches = [
        ('X86', SimCCCdecl),
        ('X86', SimCCMicrosoftFastcall),
        ('AMD64', None),
        ('ARMEL', None),
        ('MIPS32', None),
        ('PPC32', None),
        ('PPC64', None),
    ]

    # x86, cdecl
    for arch, cc in arches:
        s = SimState(arch=arch)
        for reg, val, _, _ in s.arch.default_register_values:
            s.registers.store(reg, val)

        if cc is not None:
            manyargs = SIM_PROCEDURES['testing']['manyargs'](
                cc=cc(s.arch)).execute(s)
        else:
            manyargs = SIM_PROCEDURES['testing']['manyargs']().execute(s)

        # Simulate a call
        if s.arch.call_pushes_ret:
            s.regs.sp = s.regs.sp + s.arch.stack_change
        manyargs.set_args(args)

        for index, arg in enumerate(args):
            nose.tools.assert_true(
                s.solver.is_true(manyargs.arg(index) == arg))
Example #32
0
def test_pwrite():
    pwrite = SIM_PROCEDURES['posix']['pwrite64']()

    state = SimState(arch="AMD64", mode='symbolic')
    simfile = SimFile('concrete_file', content='hello world!\n')
    state.fs.insert('test', simfile)
    fd = state.posix.open(b"test", 1)

    buf_addr = 0xd0000000
    state.memory.store(buf_addr, b'test!')
    pwrite.execute(state, arguments=[fd, buf_addr, 5, 6])

    simfd = state.posix.get_fd(fd)
    simfd.seek(0)
    res = 0xc0000000
    simfd.read(res, 13)
    data = state.solver.eval(state.mem[res].string.resolved, cast_to=bytes)

    nose.tools.assert_true(data == b'hello test!!\n')

    state.posix.close(fd)
Example #33
0
    def simprocedure(self, state: angr.SimState):
        proc = state.inspect.simprocedure
        if proc is None:
            # Handle syscall SimProcedures
            log.debug("Reached a syscall SimProcedure")
            return
        proc_name = proc.display_name

        if proc_name not in self.functions_monitored:
            return

        if "external_c&c" not in state.globals:
            state.globals["external_c&c"] = {}

        if proc_name == "InternetOpenUrlA":
            handle = proc.handle
            url_ptr = proc.arg(1)
            try:
                url = get_string_a(state, url_ptr)
            except SimUnsatError:
                url = None
            if "open_url" not in state.globals["external_c&c"]:
                state.globals["external_c&c"]["open_url"] = {}
            state.globals["external_c&c"]["open_url"][handle] = (url, url_ptr)

        elif proc_name == "InternetOpenUrlW":
            handle = proc.handle
            url_ptr = proc.arg(1)
            try:
                url = get_string_w(state, url_ptr)
            except SimUnsatError:
                url = None
            if "open_url" not in state.globals["external_c&c"]:
                state.globals["external_c&c"]["open_url"] = {}
            state.globals["external_c&c"]["open_url"][handle] = (url, url_ptr)

        elif proc_name == "InternetReadFile":
            handle = proc.arg(0)
            try:
                handle = state.solver.eval(handle, cast_to=int, exact=True)
            except SimUnsatError:
                handle = None
            # bufptr = proc.arg(1)
            # bufsz = proc.arg(2)
            if "read_file" not in state.globals["external_c&c"]:
                state.globals["external_c&c"]["read_file"] = []
            state.globals["external_c&c"]["read_file"].append(handle)
            self._analyze(state)
Example #34
0
def test_getc():
    s = SimState(arch='AMD64', mode='symbolic')
    stdin = s.posix.files[0]
    stdin.content.store(0, "1234")
    nose.tools.assert_items_equal(s.se.eval_upto(stdin.pos, 300), [0])
    # The argument of getc should be a FILE *
    c = getc(s, arguments=[0]).ret_expr
    nose.tools.assert_items_equal(s.se.eval_upto(c, 300), [0x31])
    nose.tools.assert_items_equal(s.se.eval_upto(stdin.pos, 300), [1])

    c = getc(s, arguments=[0]).ret_expr
    nose.tools.assert_items_equal(s.se.eval_upto(c, 300), [0x32])
    nose.tools.assert_items_equal(s.se.eval_upto(stdin.pos, 300), [2])

    c = getc(s, arguments=[0]).ret_expr
    nose.tools.assert_items_equal(s.se.eval_upto(c, 300), [0x33])
    nose.tools.assert_items_equal(s.se.eval_upto(stdin.pos, 300), [3])

    c = getc(s, arguments=[0]).ret_expr
    nose.tools.assert_items_equal(s.se.eval_upto(c, 300), [0x34])
    nose.tools.assert_items_equal(s.se.eval_upto(stdin.pos, 300), [4])
Example #35
0
def test_strchr():
    l.info("concrete haystack and needle")
    s = SimState(arch="AMD64", mode="symbolic")
    str_haystack = s.se.BVV(0x41424300, 32)
    str_needle = s.se.BVV(0x42, 64)
    addr_haystack = s.se.BVV(0x10, 64)
    s.memory.store(addr_haystack, str_haystack, endness="Iend_BE")

    ss_res = strchr(s, 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.BVV(0x41424300, 32)
    str_needle = s.se.BVS("wtf", 64)
    chr_needle = str_needle[7:0]
    addr_haystack = s.se.BVV(0x10, 64)
    s.memory.store(addr_haystack, str_haystack, endness="Iend_BE")

    ss_res = strchr(s, 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.se.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
Example #36
0
def test_pread():
    pwrite = SIM_PROCEDURES['posix']['pread64']()

    state = SimState(arch="AMD64", mode='symbolic')
    simfile = SimFile('concrete_file', content='hello world!\n')
    state.fs.insert('test', simfile)
    fd = state.posix.open(b"test", 1)

    buf1_addr = 0xd0000000
    buf2_addr = 0xd0001000
    pwrite.execute(state, arguments=[fd, buf1_addr, 6, 6])
    pwrite.execute(state, arguments=[fd, buf2_addr, 5, 0])

    data1 = state.solver.eval(state.mem[buf1_addr].string.resolved,
                              cast_to=bytes)
    data2 = state.solver.eval(state.mem[buf2_addr].string.resolved,
                              cast_to=bytes)

    nose.tools.assert_true(data1 == b'world!')
    nose.tools.assert_true(data2 == b'hello')

    state.posix.close(fd)
Example #37
0
    def simprocedure(self, state: angr.SimState):
        # Init globals
        if "key_spying" not in state.globals:
            state.globals["key_spying"] = defaultdict(list)

        # Handle procedure
        proc = state.inspect.simprocedure
        if proc is None:
            # Handle syscall SimProcedures
            log.debug("Reached a syscall SimProcedure")
            return
        proc_name = proc.display_name

        if proc_name == "RegisterHotKey":
            state.globals["key_spying"]["RegisterHotKey"].append(proc.arg(0))

        elif proc_name == "SetWindowsHookExA" or proc_name == "SetWindowsHookExW":
            state.globals["key_spying"]["SetWindowsHookEx"].append(proc.arg(0))

        elif proc_name == "GetMessageA" or proc_name == "GetMessageW":
            # Final function in sequence
            self._analyze(state, proc.arg(1))
Example #38
0
def test_hex_dump():
    s = SimState(arch='AMD64')
    addr = s.heap.allocate(0x20)
    s.memory.store(
        addr,
        claripy.Concat(
            claripy.BVV('ABCDEFGH'),
            claripy.BVS('symbolic_part', 24 * s.arch.bits)
        )
    )
    dump = s.memory.hex_dump(addr, 0x20)
    assert dump == 'c0000000: 41424344 45464748 ???????? ???????? ABCDEFGH????????\n'\
                   'c0000010: ???????? ???????? ???????? ???????? ????????????????\n'

    dump = s.memory.hex_dump(
        addr,
        0x20,
        extra_constraints=(s.memory.load(addr+0x10, 4) == 0xdeadbeef,),
        solve=True,
        endianness='Iend_LE'
    )
    assert dump == 'c0000000: 44434241 48474645 ???????? ???????? ABCDEFGH????????\n'         'c0000010: efbeadde ???????? ???????? ???????? ....????????????\n'
Example #39
0
    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
Example #40
0
def test_strcpy():
    l.info("concrete src, concrete dst")

    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)
    strcpy(s, arguments=[dst_addr, src_addr])
    new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE')
    assert s.solver.eval(new_dst, cast_to=bytes) == b"BB\x00\x00"



    l.info("symbolic src, concrete dst")
    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 = SimState(arch="AMD64", mode="symbolic")
    s.memory.store(dst_addr, dst)
    s.memory.store(src_addr, src)

    ln = strlen(s, arguments=[src_addr])

    strcpy(s, arguments=[dst_addr, src_addr])

    cm = strcmp(s, arguments=[dst_addr, src_addr])

    s.add_constraints(cm == 0)

    s.add_constraints(ln == 15)
Example #41
0
    def simprocedure(self, state: angr.SimState):
        """
        Tracks all SimProcedure calls and checks if it is calling a monitored function
        """

        proc = state.inspect.simprocedure
        if proc is None:
            # Handle syscall SimProcedures
            log.debug("Reached a syscall SimProcedure")
            return
        proc_name = proc.display_name

        if proc_name not in self.functions_monitored:
            return

        if "file_exfiltration" not in state.globals:
            state.globals["file_exfiltration"] = defaultdict(list)

        if proc_name == "OpenFile":
            data = {"return": state.inspect.simprocedure_result}
            state.globals["file_exfiltration"]["OpenFile"].append(data)
        elif proc_name == "ReadFile":
            data = {
                "lpBytesRead":
                state.memory.load(proc.arg(3),
                                  disable_actions=True,
                                  inspect=False)
            }
            state.globals["file_exfiltration"]["ReadFile"].append(data)
        elif proc_name == "Send":
            data = {
                "buf":
                state.memory.load(proc.arg(1),
                                  disable_actions=True,
                                  inspect=False)
            }
            state.globals["file_exfiltration"]["Send"].append(data)
            self._analyze(state)
def test_lseek_unseekable():
    state = SimState(arch="AMD64", mode="symbolic")

    # Illegal seek
    current_pos = lseek(state, [0, 0, SEEK_SET]).ret_expr
    current_pos = state.se.eval(current_pos)

    # Assert we have a negative return value
    nose.tools.assert_true(current_pos & (1 << 63) != 0)

    # Illegal seek
    current_pos = lseek(state, [1, 0, SEEK_SET]).ret_expr
    current_pos = state.se.eval(current_pos)

    # Assert we have a negative return value
    nose.tools.assert_true(current_pos & (1 << 63) != 0)

    # Illegal seek
    current_pos = lseek(state, [2, 0, SEEK_SET]).ret_expr
    current_pos = state.se.eval(current_pos)

    # Assert we have a negative return value
    nose.tools.assert_true(current_pos & (1 << 63) != 0)
Example #43
0
def test_loadg_no_constraint_creation():

    state = SimState(arch='armel', mode='symbolic')

    from angr.engines.vex.statements.loadg import SimIRStmt_LoadG

    state.scratch.temps[1] = state.solver.BVS('tmp_1', 32)
    stmt = pyvex.IRStmt.LoadG('Iend_LE', 'ILGop_16Uto32',
                              pyvex.IRExpr.Const(pyvex.const.U32(0x1000)),
                              pyvex.IRExpr.Const(pyvex.const.U32(0x2000)),
                              pyvex.IRExpr.Const(pyvex.const.U32(0x1337)),
                              pyvex.IRExpr.RdTmp(1)  # guard
                              )
    tyenv = pyvex.IRTypeEnv(state.arch)
    tyenv.types = [ None, 'Ity_I32' ]
    state.scratch.tyenv = tyenv
    loadg = SimIRStmt_LoadG(stmt, state)

    loadg._execute()

    # LOADG should not create new constraints - it is a simple conditional memory read. The conditions should only be
    # used inside the value AST to guard the memory read.
    assert not state.solver.constraints
Example #44
0
    def test_lseek_unseekable(self):
        state = SimState(arch="AMD64", mode="symbolic")

        # Illegal seek
        current_pos = lseek(state,[0,0,SEEK_SET]).ret_expr
        current_pos = state.solver.eval(current_pos)

        # Assert we have a negative return value
        assert current_pos & (1 << 63) != 0

        # Illegal seek
        current_pos = lseek(state,[1,0,SEEK_SET]).ret_expr
        current_pos = state.solver.eval(current_pos)

        # Assert we have a negative return value
        assert current_pos & (1 << 63) != 0

        # Illegal seek
        current_pos = lseek(state,[2,0,SEEK_SET]).ret_expr
        current_pos = state.solver.eval(current_pos)

        # Assert we have a negative return value
        assert current_pos & (1 << 63) != 0
Example #45
0
def test_multivalued_list_page():
    state = SimState(arch='AMD64', mode='symbolic', plugins={'memory': MultiValuedMemory()})

    # strong update
    state.memory.store(0x100, claripy.BVV(0x40, 64))
    state.memory.store(0x100, claripy.BVV(0x80818283, 64))
    a = state.memory.load(0x100, size=8).one_value()
    assert a is not None
    assert a is claripy.BVV(0x80818283, 64)

    # strong update with partial overwrites
    state.memory.store(0x100, claripy.BVV(0x0, 64))
    state.memory.store(0x104, claripy.BVV(0x1337, 32))
    a = state.memory.load(0x100, size=8).one_value()
    assert a is not None
    assert a is claripy.BVV(0x1337, 64)

    # weak updates
    state.memory.store(0x120, claripy.BVV(0x40, 64))
    state.memory.store(0x120, claripy.BVV(0x85868788, 64), weak=True)
    a = state.memory.load(0x120, size=8)
    assert len(a.values) == 1
    assert 0 in a.values
    assert len(a.values[0]) == 2
    assert set(state.solver.eval_exact(item, 1)[0] for item in a.values[0]) == { 0x40, 0x85868788 }

    # weak updates with symbolic values
    A = claripy.BVS("a", 64)
    state.memory.store(0x140, A, endness=state.arch.memory_endness)
    state.memory.store(0x141, claripy.BVS("b", 64), endness=state.arch.memory_endness, weak=True)
    a = state.memory.load(0x140, size=8)
    assert len(a.values) == 2
    assert 0 in a.values
    assert 1 in a.values
    assert len(a.values[0]) == 1
    assert next(iter(a.values[0])) is A[7:0]
    assert len(a.values[1]) == 2
Example #46
0
def test_strstr_inconsistency():
    l.info("symbolic haystack, symbolic needle")
    s = SimState(arch="AMD64", mode="symbolic")
    s.libc.buf_symbolic_bytes = 2
    addr_haystack = s.solver.BVV(0x10, 64)
    addr_needle = s.solver.BVV(0xb0, 64)
    #len_needle = strlen(s, inline=True, arguments=[addr_needle])

    ss_res = strstr(s, arguments=[addr_haystack, addr_needle])

    #slh_res = strlen(s, inline=True, arguments=[addr_haystack])
    #sln_res = strlen(s, inline=True, arguments=[addr_needle])
    #print "LENH:", s.solver.eval_upto(slh_res, 100)
    #print "LENN:", s.solver.eval_upto(sln_res, 100)

    assert not s.solver.unique(ss_res)
    assert sorted(s.solver.eval_upto(ss_res, 100)) == [0] + list(range(0x10, 0x10 + s.libc.buf_symbolic_bytes - 1))

    s.add_constraints(ss_res != 0)
    ss2 = strstr(s, arguments=[addr_haystack, addr_needle])
    s.add_constraints(ss2 == 0)
    assert not s.satisfiable()
Example #47
0
    def test_lseek_set(self):
        state = SimState(arch="AMD64", mode="symbolic")

        # This could be any number above 2 really
        fd = 3

        # Create a file
        state.fs.insert('/tmp/qwer', SimFile(name='qwer', size=100))
        assert fd == state.posix.open(b'/tmp/qwer', 2)

        # Part 1

        # Seek to the top of the file
        current_pos = lseek(state,[fd,0,SEEK_SET]).ret_expr
        current_pos = state.solver.eval(current_pos)

        # We should be at the start
        assert current_pos == 0

        # Part 2

        # Seek to the top of the file
        current_pos = lseek(state,[fd,8,SEEK_SET]).ret_expr
        current_pos = state.solver.eval(current_pos)

        # We should be at the start
        assert current_pos == 8

        # Part 3

        # Seek to the top of the file
        current_pos = lseek(state,[fd,3,SEEK_SET]).ret_expr
        current_pos = state.solver.eval(current_pos)

        # We should be at the start
        assert current_pos == 3
Example #48
0
def checkUAF(cur_state: angr.SimState):
    # has not FREE yet
    if "FREE_LIST" not in cur_state.globals:
        cur_state.globals["ACTS_BEFORE_FREE"] = [
            act for act in reversed(cur_state.history.actions.hardcopy)
        ]
    # after FREE occured
    else:
        new_actions = [
            act for act in reversed(cur_state.history.actions.hardcopy)
            if act not in cur_state.globals["ACTS_BEFORE_FREE"]
        ]
        for act in new_actions:
            if (act.type == 'mem') \
            and (act.action == 'read' or act.action == 'write') \
            and (act.actual_addrs[0] in cur_state.globals["FREE_LIST"]) \
            and not isSimilarPath([bbl_addr for bbl_addr in cur_state.history.bbl_addrs], paths_with_bug, ratio=0.95):
                log("USE AFTER FREE detected! IO dump :", RED)
                print("{}< stdin >{}\n".format(DRED, RST),
                      cur_state.posix.dumps(0))
                print("{}< stdout >{}\n".format(DRED, RST),
                      cur_state.posix.dumps(1).decode())
                paths_with_bug.append(
                    [bbl_addr for bbl_addr in cur_state.history.bbl_addrs])
Example #49
0
def test_crosspage_store():
    for memcls in [UltraPageMemory, ListPageMemory]:
        state = SimState(arch='x86',
                         mode='symbolic',
                         plugins={'memory': memcls()})

        state.regs.sp = 0xbaaafffc
        state.memory.store(state.regs.sp,
                           b"\x01\x02\x03\x04" + b"\x05\x06\x07\x08")
        assert state.solver.eval(state.memory.load(state.regs.sp,
                                                   8)) == 0x0102030405060708

        state.memory.store(state.regs.sp,
                           b"\x01\x02\x03\x04" + b"\x05\x06\x07\x08",
                           endness='Iend_LE')
        assert state.solver.eval(state.memory.load(state.regs.sp,
                                                   8)) == 0x0807060504030201

        symbol = claripy.BVS('symbol', 64)
        state.memory.store(state.regs.sp, symbol)
        assert state.memory.load(state.regs.sp, 8) is symbol

        state.memory.store(state.regs.sp, symbol, endness='Iend_LE')
        assert state.memory.load(state.regs.sp, 8) is symbol.reversed
Example #50
0
def test_loadg_no_constraint_creation():

    state = SimState(arch='armel', mode='symbolic')
    engine = HeavyVEXMixin(None)

    stmt = pyvex.IRStmt.LoadG('Iend_LE', 'ILGop_16Uto32',
                              0, # dst
                              pyvex.IRExpr.Const(pyvex.const.U32(0x2000)), # addr (src)
                              pyvex.IRExpr.Const(pyvex.const.U32(0x1337)), # alt
                              pyvex.IRExpr.RdTmp(1)  # guard
                              )
    tyenv = pyvex.IRTypeEnv(state.arch)
    tyenv.types = [ 'Ity_I32', 'Ity_I32' ]
    state.scratch.set_tyenv(tyenv)
    state.scratch.temps[1] = state.solver.BVS('tmp_1', 32)
    engine.state = state
    engine._handle_vex_stmt(stmt)

    # LOADG should not create new constraints - it is a simple conditional memory read. The conditions should only be
    # used inside the value AST to guard the memory read.
    assert not state.solver.constraints
    assert state.scratch.temps[0] is not None
    assert state.scratch.temps[0].variables.issuperset(state.scratch.temps[1].variables)
    assert state.scratch.temps[0].op == 'If'
Example #51
0
    def simprocedure(self, state: angr.SimState):
        # Init globals
        if "screen_spying" not in state.globals:
            state.globals["screen_spying"] = defaultdict(list)

        # Handle procedure
        proc = state.inspect.simprocedure
        if proc is None:
            # Handle syscall SimProcedures
            log.debug("Reached a syscall SimProcedure")
            return
        proc_name = proc.display_name

        if proc_name == "GetDC":
            return_value = state.inspect.simprocedure_result
            state.globals["screen_spying"]["GetDC"].append(return_value)

        elif proc_name == "GetWindowDC":
            return_value = state.inspect.simprocedure_result
            state.globals["screen_spying"]["GetWindowDC"].append(return_value)

        elif proc_name == "CreateCompatibleBitmap":
            # Final function in sequence
            self._analyze(state, proc.arg(0))
Example #52
0
def test_strstr_inconsistency(n=2):
    l.info("symbolic haystack, symbolic needle")
    s = SimState(arch="AMD64", mode="symbolic")
    s.libc.buf_symbolic_bytes = n
    addr_haystack = s.se.BVV(0x10, 64)
    addr_needle = s.se.BVV(0xb0, 64)
    #len_needle = strlen(s, inline=True, arguments=[addr_needle])

    ss_res = strstr(s, arguments=[addr_haystack, addr_needle]).ret_expr

    #slh_res = strlen(s, inline=True, arguments=[addr_haystack]).ret_expr
    #sln_res = strlen(s, inline=True, arguments=[addr_needle]).ret_expr
    #print "LENH:", s.se.any_n_int(slh_res, 100)
    #print "LENN:", s.se.any_n_int(sln_res, 100)

    nose.tools.assert_false(s.se.unique(ss_res))
    nose.tools.assert_items_equal(s.se.any_n_int(
        ss_res, 100), [0] + range(0x10, 0x10 + s.libc.buf_symbolic_bytes - 1))

    s.add_constraints(ss_res != 0)
    ss2 = strstr(s, arguments=[addr_haystack, addr_needle]).ret_expr
    s.add_constraints(ss2 == 0)
    nose.tools.assert_false(s.satisfiable())
Example #53
0
def test_strstr_inconsistency():
    l.info("symbolic haystack, symbolic needle")
    s = SimState(arch="AMD64", mode="symbolic")
    s.libc.buf_symbolic_bytes = 2
    addr_haystack = s.solver.BVV(0x10, 64)
    addr_needle = s.solver.BVV(0xb0, 64)
    #len_needle = strlen(s, inline=True, arguments=[addr_needle])

    ss_res = strstr(s, arguments=[addr_haystack, addr_needle])

    #slh_res = strlen(s, inline=True, arguments=[addr_haystack])
    #sln_res = strlen(s, inline=True, arguments=[addr_needle])
    #print "LENH:", s.solver.eval_upto(slh_res, 100)
    #print "LENN:", s.solver.eval_upto(sln_res, 100)

    nose.tools.assert_false(s.solver.unique(ss_res))
    nose.tools.assert_sequence_equal(sorted(s.solver.eval_upto(ss_res, 100)), [0] + list(range(0x10, 0x10 + s.libc.buf_symbolic_bytes - 1)))

    s.add_constraints(ss_res != 0)
    ss2 = strstr(s, arguments=[addr_haystack, addr_needle])
    s.add_constraints(ss2 == 0)
    nose.tools.assert_false(s.satisfiable())
Example #54
0
def test_strcpy():
    l.info("concrete src, concrete dst")

    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)
    strcpy(s, arguments=[dst_addr, src_addr])
    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.info("symbolic src, concrete dst")
    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 = SimState(arch="AMD64", mode="symbolic")
    s.memory.store(dst_addr, dst)
    s.memory.store(src_addr, src)

    ln = strlen(s, arguments=[src_addr])

    strcpy(s, arguments=[dst_addr, src_addr])

    cm = strcmp(s, arguments=[dst_addr, src_addr])

    s.add_constraints(cm == 0)

    s.add_constraints(ln == 15)
Example #55
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)
Example #56
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())
Example #57
0
def test_inspect_concretization():
    # some values for the test
    x = claripy.BVS('x', 64)
    y = claripy.BVS('y', 64)

    #
    # This tests concretization-time address redirection.
    #

    def change_symbolic_target(state):
        if state.inspect.address_concretization_action == 'store':
            state.inspect.address_concretization_expr = claripy.BVV(0x1000, state.arch.bits)

    s = SimState(arch='AMD64')
    s.inspect.b('address_concretization', BP_BEFORE, action=change_symbolic_target)
    s.memory.store(x, 'A')
    assert list(s.se.eval_upto(x, 10)) == [ 0x1000 ]
    assert list(s.se.eval_upto(s.memory.load(0x1000, 1), 10)) == [ 0x41 ]

    #
    # This tests disabling constraint adding through siminspect -- the write still happens
    #

    def dont_add_constraints(state):
        state.inspect.address_concretization_add_constraints = False

    s = SimState(arch='AMD64')
    s.inspect.b('address_concretization', BP_BEFORE, action=dont_add_constraints)
    s.memory.store(x, 'A')
    assert len(s.se.eval_upto(x, 10)) == 10

    #
    # This tests raising an exception if symbolic concretization fails (i.e., if the address
    # is too unconstrained). The write aborts.
    #

    class UnconstrainedAbort(Exception):
        def __init__(self, message, state):
            Exception.__init__(self, message)
            self.state = state

    def abort_unconstrained(state):
        print state.inspect.address_concretization_strategy, state.inspect.address_concretization_result
        if (
            isinstance(
                state.inspect.address_concretization_strategy,
                concretization_strategies.SimConcretizationStrategyRange
            ) and state.inspect.address_concretization_result is None
        ):
            raise UnconstrainedAbort("uh oh", state)

    s = SimState(arch='AMD64')
    s.memory.write_strategies.insert(
        0, concretization_strategies.SimConcretizationStrategyRange(128)
    )
    s.memory._write_address_range = 1
    s.memory._write_address_range_approx = 1
    s.add_constraints(y == 10)
    s.inspect.b('address_concretization', BP_AFTER, action=abort_unconstrained)
    s.memory.store(y, 'A')
    assert list(s.se.eval_upto(s.memory.load(y, 1), 10)) == [ 0x41 ]

    try:
        s.memory.store(x, 'A')
        print "THIS SHOULD NOT BE REACHED"
        assert False
    except UnconstrainedAbort as e:
        assert e.state.memory is s.memory
Example #58
0
def broken_strtok_r():
    l.debug("CONCRETE MODE")
    s = SimState(arch='AMD64', mode='symbolic')
    s.memory.store(100, s.solver.BVV(0x4141414241414241424300, 88), endness='Iend_BE')
    s.memory.store(200, s.solver.BVV(0x4200, 16), endness='Iend_BE')
    str_ptr = s.solver.BVV(100, s.arch.bits)
    delim_ptr = s.solver.BVV(200, s.arch.bits)
    state_ptr = s.solver.BVV(300, s.arch.bits)

    st1 = strtok_r(s, arguments=[str_ptr, delim_ptr, state_ptr])
    nose.tools.assert_equal(s.solver.eval_upto(st1, 10), [104])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st1-1, 1), 10), [0])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(200, 2), 10), [0x4200])

    st2 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr])
    nose.tools.assert_equal(s.solver.eval_upto(st2, 10), [107])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st2-1, 1), 10), [0])

    st3 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr])
    nose.tools.assert_equal(s.solver.eval_upto(st3, 10), [109])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st3-1, 1), 10), [0])

    st4 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr])
    nose.tools.assert_equal(s.solver.eval_upto(st4, 10), [0])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(300, s.arch.bytes, endness=s.arch.memory_endness), 10), [109])

    st5 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr])
    nose.tools.assert_equal(s.solver.eval_upto(st5, 10), [0])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(300, s.arch.bytes, endness=s.arch.memory_endness), 10), [109])

    s.memory.store(1000, s.solver.BVV(0x4141414241414241424300, 88), endness='Iend_BE')
    s.memory.store(2000, s.solver.BVV(0x4200, 16), endness='Iend_BE')
    str_ptr = s.solver.BVV(1000, s.arch.bits)
    delim_ptr = s.solver.BVV(2000, s.arch.bits)
    state_ptr = s.solver.BVV(3000, s.arch.bits)

    st1 = strtok_r(s, arguments=[str_ptr, delim_ptr, state_ptr])
    nose.tools.assert_equal(s.solver.eval_upto(st1, 10), [1004])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st1-1, 1), 10), [0])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(2000, 2), 10), [0x4200])

    st2 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr])
    nose.tools.assert_equal(s.solver.eval_upto(st2, 10), [1007])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st2-1, 1), 10), [0])

    st3 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr])
    nose.tools.assert_equal(s.solver.eval_upto(st3, 10), [1009])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st3-1, 1), 10), [0])

    st4 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr])
    nose.tools.assert_equal(s.solver.eval_upto(st4, 10), [0])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(3000, s.arch.bytes, endness=s.arch.memory_endness), 10), [1009])

    st5 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr])
    nose.tools.assert_equal(s.solver.eval_upto(st5, 10), [0])
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(3000, s.arch.bytes, endness=s.arch.memory_endness), 10), [1009])

    s = SimState(arch='AMD64', mode='symbolic')
    str_ptr = s.solver.BVV(100, s.arch.bits)
    delim_ptr = s.solver.BVV(200, s.arch.bits)
    state_ptr = s.solver.BVV(300, s.arch.bits)

    s.add_constraints(s.memory.load(delim_ptr, 1) != 0)

    st1 = strtok_r(s, arguments=[str_ptr, delim_ptr, state_ptr])
    s.add_constraints(st1 != 0)
    nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st1-1, 1), 10), [0])
Example #59
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)