Esempio n. 1
0
def test_merge_memory_object_endness():

    for memcls in [UltraPageMemory, ListPageMemory]:
        state0 = SimState(arch='AMD64',
                          mode='symbolic',
                          plugins={'memory': memcls()})
        state0.memory.store(0x20000, claripy.BVS("x", 64), endness="Iend_LE")

        state1 = SimState(arch="AMD64",
                          mode="symbolic",
                          plugins={'memory': memcls()})
        state1.memory.store(0x20000, claripy.BVS("y", 64), endness="Iend_LE")

        state, _, _ = state0.merge(state1)
        obj = state.memory.load(0x20000, size=8, endness="Iend_LE")
        assert isinstance(obj, claripy.ast.Base)
        # the original endness should be respected, and obj.op should not be Reverse
        assert obj.op == "If"
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. 3
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. 4
0
    def test_merge_seq(self):
        state1 = SimState(arch='AMD64',
                          mode='symbolic',
                          plugins={'memory': UltraPageMemory()})
        state2 = SimState(arch='AMD64',
                          mode='symbolic',
                          plugins={'memory': UltraPageMemory()})

        state1.regs.rsp = 0x80000000
        state2.regs.rsp = 0x80000000

        state1.memory.store(state1.regs.rsp, 0x11, 1)
        state1.memory.store(state1.regs.rsp + 1, 0x22, 1)
        state2.memory.store(state2.regs.rsp, 0xAA, 1)
        state2.memory.store(state2.regs.rsp + 1, 0xBB, 1)

        state3, _, __ = state1.merge(state2)
        vals = (v for v in state3.solver.eval_upto(
            state3.memory.load(state3.regs.rsp, 2), 10))
        assert set([0x1122, 0xaabb]) == set(vals)
Esempio n. 5
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. 6
0
    def test_state_merge_static(self):
        # With abstract memory
        # Aligned memory merging
        a = SimState(arch="AMD64", mode="static")

        addr = a.solver.ValueSet(32, "global", 0, 8)
        a.memory.store(addr, a.solver.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.solver.BVV(50, 32), endness="Iend_LE")
        b.memory.store(addr, a.solver.BVV(60, 32), endness="Iend_LE")
        c.memory.store(addr, a.solver.BVV(70, 32), endness="Iend_LE")

        merged, _, _ = a.merge(b, c)
        actual = claripy.backends.vsa.convert(
            merged.memory.load(addr, 4, endness="Iend_LE"))
        expected = claripy.backends.vsa.convert(
            a.solver.SI(bits=32, stride=10, lower_bound=50, upper_bound=70))
        assert actual.identical(expected)
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. 8
0
def test_abstract_memory():
    initial_memory = {0: 'A', 1: 'B', 2: 'C', 3: '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.se.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.se.any_int(expr), 0x43)
    nose.tools.assert_equal(s.se.max_int(expr), 0x43)
    nose.tools.assert_equal(s.se.min_int(expr), 0x43)

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

    # Store a single-byte StridedInterval to global region
    si_0 = s.se.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.se.min_int(expr), 10)
    nose.tools.assert_equal(s.se.max_int(expr), 20)
    nose.tools.assert_equal(s.se.any_n_int(expr, 100),
                            [10, 12, 14, 16, 18, 20])

    # Store a two-byte StridedInterval object to global region
    si_1 = s.se.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.se.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.se.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.se.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.se.BVS('unnamed', 32, 0, 0xffffffff, 1)))
    nose.tools.assert_true(
        claripy.backends.vsa.identical(
            expr, s.se.BVS('unnamed', 32, -0x80000000, 0x7fffffff, 1)))

    #
    # Merging
    #

    # Merging two one-byte values
    s.memory.store(to_vs('function_merge', 0),
                   s.se.BVS('unnamed', 8, 0x10, 0x10, 0))
    a = s.copy()
    a.memory.store(to_vs('function_merge', 0),
                   s.se.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.se.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 = 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 = set([c_mem[0x20], c_mem[0x20], c_mem[0x22], c_mem[0x23]])
    nose.tools.assert_equal(len(object_set), 1)

    #
    # Widening
    #

    a = s.se.SI(bits=32, stride=1, lower_bound=1, upper_bound=2)
    b = s.se.SI(bits=32, stride=1, lower_bound=1, upper_bound=3)
    a = a.reversed
    b = b.reversed
Esempio n. 9
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. 10
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",
                 dict_memory_backer=initial_memory,
                 add_options={o.ABSTRACT_SOLVER, o.ABSTRACT_MEMORY})
    se = s.solver

    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)
    assert s.solver.eval(expr) == 0x43
    assert s.solver.max_int(expr) == 0x43
    assert 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)
    assert 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)
    assert s.solver.min_int(expr) == 10
    assert s.solver.max_int(expr) == 20
    assert 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)
    assert 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)
    assert 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)
    assert 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)
    assert claripy.backends.vsa.identical(expr, s.solver.BVS('unnamed', 32, 0, 0xffffffff, 1))
    assert 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)
    assert 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)
    assert claripy.backends.vsa.identical(expr, se.SI(bits=32, stride=1, lower_bound=0x100000, upper_bound=0x100001))
    c_page = c.memory._regions['function_merge']._pages[0]
    object_set = {c_page._get_object(0x20, 0),
                  c_page._get_object(0x21, 0),
                  c_page._get_object(0x22, 0),
                  c_page._get_object(0x23, 0),
                  }
    assert 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)
    assert claripy.backends.vsa.identical(expr, se.SI(bits=32, stride=0x100000, lower_bound=0x100000, upper_bound=0x300000))
    object_set = {c_page._get_object(0x20, 0),
                  c_page._get_object(0x21, 0),
                  c_page._get_object(0x22, 0),
                  c_page._get_object(0x23, 0),
                  }
    assert 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. 11
0
    def test_state_merge(self):
        a = SimState(arch="AMD64", mode="symbolic")
        a.memory.store(1, a.solver.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
        assert a.solver.eval(a.memory.load(1, 1)) == 42
        assert b.solver.eval(b.memory.load(1, 1)) == 42
        assert c.solver.eval(c.memory.load(1, 1)) == 42

        # make sure the byte at 2 is right
        assert a.solver.eval(a.memory.load(2, 1)) == 43
        assert b.solver.eval(b.memory.load(2, 1)) == 84
        assert c.solver.eval(c.memory.load(2, 1)) == 21

        # the byte at 2 should be unique for all before the merge
        assert a.solver.unique(a.memory.load(2, 1))
        assert b.solver.unique(b.memory.load(2, 1))
        assert c.solver.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)

        assert merging_occurred
        # assert sorted(m.solver.eval_upto(merge_flag, 10)) == [ 0,1,2 ]
        assert len(merge_conditions) == 3

        # the byte at 2 should now *not* be unique for a
        assert not m.solver.unique(m.memory.load(2, 1))
        assert a.solver.unique(a.memory.load(2, 1))
        assert b.solver.unique(b.memory.load(2, 1))
        assert c.solver.unique(c.memory.load(2, 1))

        # the byte at 2 should have the three values
        self.assertSequenceEqual(
            sorted(m.solver.eval_upto(m.memory.load(2, 1), 10)), (21, 43, 84))

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

        a_b = m.copy()
        a_b.add_constraints(merge_conditions[1])
        assert a_b.solver.unique(a_b.memory.load(2, 1))
        assert a_b.solver.eval(a_b.memory.load(2, 1)) == 84

        a_c = m.copy()
        a_c.add_constraints(merge_conditions[2])
        assert a_c.solver.unique(a_c.memory.load(2, 1))
        assert a_c.solver.eval(a_c.memory.load(2, 1)) == 21

        # test different sets of plugins
        a = SimState(arch="AMD64", mode="symbolic")
        assert a.has_plugin("memory")
        assert a.has_plugin("registers")
        assert not a.has_plugin("libc")

        b = a.copy()
        a.get_plugin("libc")
        assert a.has_plugin("libc")
        assert not b.has_plugin("libc")
        c = a.copy().merge(b.copy())[0]
        d = b.copy().merge(a.copy())[0]
        assert c.has_plugin("libc")
        assert d.has_plugin("libc")

        # test merging posix with different open files (illegal!)
        a = SimState(arch="AMD64", mode="symbolic")
        b = a.copy()
        a.posix.open(b"/tmp/idk", 1)
        self.assertRaises(angr.errors.SimMergeError,
                          lambda: a.copy().merge(b.copy()))