1import nose
2import angr
3import claripy
4import archinfo
5from angr.sim_type import SimTypePointer, SimTypeFunction, SimTypeChar, SimTypeInt, parse_defns
6from angr.errors import AngrCallableMultistateError
7
8import logging
9l = logging.getLogger("angr_tests")
10
11import os
12from common import slow_test, bin_location as location
13
14addresses_fauxware = {
15    'armel': 0x8524,
16    'armhf': 0x104c9,    # addr+1 to force thumb
17    'i386': 0x8048524,
18    'mips': 0x400710,
19    'mipsel': 0x4006d0,
20    'ppc': 0x1000054c,
21    'ppc64': 0x10000698,
22    'x86_64': 0x400664
23}
24
25addresses_manysum = {
26    'armel': 0x1041c,
27    'armhf': 0x103bd,
28    'i386': 0x80483d8,
29    'mips': 0x400704,
30    'mipsel': 0x400704,
31    'ppc': 0x10000418,
32    'ppc64': 0x10000500,
33    'x86_64': 0x4004ca
34}
35
36def run_fauxware(arch):
37    addr = addresses_fauxware[arch]
38    p = angr.Project(os.path.join(location, 'tests', arch, 'fauxware'))
39    charstar = SimTypePointer(SimTypeChar())
40    prototype = SimTypeFunction((charstar, charstar), SimTypeInt(False))
41    cc = p.factory.cc(func_ty=prototype)
42    authenticate = p.factory.callable(addr, toc=0x10018E80 if arch == 'ppc64' else None, concrete_only=True, cc=cc)
43    nose.tools.assert_equal(authenticate("asdf", "SOSNEAKY")._model_concrete.value, 1)
44    nose.tools.assert_raises(AngrCallableMultistateError, authenticate, "asdf", "NOSNEAKY")
45
46
47def run_callable_c_fauxware(arch):
48    addr = addresses_fauxware[arch]
49    p = angr.Project(os.path.join(location, 'tests', arch, 'fauxware'))
50    cc = p.factory.cc(func_ty="int f(char*, char*)")
51    authenticate = p.factory.callable(addr, toc=0x10018E80 if arch == 'ppc64' else None, concrete_only=True, cc=cc)
52    retval = authenticate.call_c('("asdf", "SOSNEAKY")')
53    nose.tools.assert_equal(retval._model_concrete.value, 1)
54    nose.tools.assert_raises(AngrCallableMultistateError, authenticate, "asdf", "NOSNEAKY")
55
56
57def run_manysum(arch):
58    addr = addresses_manysum[arch]
59    p = angr.Project(os.path.join(location, 'tests', arch, 'manysum'))
60    inttype = SimTypeInt()
61    prototype = SimTypeFunction([inttype]*11, inttype)
62    cc = p.factory.cc(func_ty=prototype)
63    sumlots = p.factory.callable(addr, cc=cc)
64    result = sumlots(1,2,3,4,5,6,7,8,9,10,11)
65    nose.tools.assert_false(result.symbolic)
66    nose.tools.assert_equal(result._model_concrete.value, sum(range(12)))
67
68
69def run_callable_c_manysum(arch):
70    addr = addresses_manysum[arch]
71    p = angr.Project(os.path.join(location, 'tests', arch, 'manysum'))
72    cc = p.factory.cc(func_ty="int f(int, int, int, int, int, int, int, int, int, int, int)")
73    sumlots = p.factory.callable(addr, cc=cc)
74    result = sumlots.call_c("(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)")
75    nose.tools.assert_false(result.symbolic)
76    nose.tools.assert_equal(result._model_concrete.value, sum(range(12)))
77
78type_cache = None
79
80def run_manyfloatsum(arch):
81    global type_cache
82    if type_cache is None:
83        with open(os.path.join(location, 'tests_src', 'manyfloatsum.c')) as fp:
84            type_cache = parse_defns(fp.read())
85
86    p = angr.Project(os.path.join(location, 'tests', arch, 'manyfloatsum'))
87    for function in ('sum_floats', 'sum_combo', 'sum_segregated', 'sum_doubles', 'sum_combo_doubles', 'sum_segregated_doubles'):
88        cc = p.factory.cc(func_ty=type_cache[function])
89        args = list(range(len(cc.func_ty.args)))
90        answer = float(sum(args))
91        addr = p.loader.main_object.get_symbol(function).rebased_addr
92        my_callable = p.factory.callable(addr, cc=cc)
93        result = my_callable(*args)
94        nose.tools.assert_false(result.symbolic)
95        result_concrete = result.args[0]
96        nose.tools.assert_equal(answer, result_concrete)
97
98@slow_test
99def run_manyfloatsum_symbolic(arch):
100    global type_cache
101    if type_cache is None:
102        with open(os.path.join(location, 'tests_src', 'manyfloatsum.c')) as fp:
103            type_cache = parse_defns(fp.read())
104
105    p = angr.Project(os.path.join(location, 'tests', arch, 'manyfloatsum'))
106    function = 'sum_doubles'
107    cc = p.factory.cc(func_ty=type_cache[function])
108    args = [claripy.FPS('arg_%d' % i, claripy.FSORT_DOUBLE) for i in range(len(type_cache[function].args))]
109    addr = p.loader.main_object.get_symbol(function).rebased_addr
110    my_callable = p.factory.callable(addr, cc=cc)
111    result = my_callable(*args)
112    nose.tools.assert_true(result.symbolic)
113
114    s = claripy.Solver(timeout=15*60*1000)
115    for arg in args:
116        s.add(arg > claripy.FPV(1.0, claripy.FSORT_DOUBLE))
117    s.add(result == claripy.FPV(27.7, claripy.FSORT_DOUBLE))
118
119    args_conc = s.batch_eval(args, 1)[0]
120    nose.tools.assert_equal(s.eval(result, 1)[0], 27.7)
121    # not almost equal!! totally equal!!! z3 is magic, if kinda slow!!!!!
122    for arg_conc in args_conc:
123        nose.tools.assert_greater(arg_conc, 1.0)
124    nose.tools.assert_equal(sum(args_conc), 27.7)
125
126
127def test_fauxware():
128    for arch in addresses_fauxware:
129        yield run_fauxware, arch
130
131def test_manysum():
132    for arch in addresses_manysum:
133        yield run_manysum, arch
134
135def test_manyfloatsum():
136    for arch in ('i386', 'x86_64'):
137        yield run_manyfloatsum, arch
138
139@slow_test
140def test_manyfloatsum_symbolic():
141    # doesn't have to be slow but it might be
142    # https://github.com/Z3Prover/z3/issues/2584
143    for arch in ('i386', 'x86_64'):
144        yield run_manyfloatsum_symbolic, arch
145
146
147def test_callable_c_fauxware():
148    for arch in addresses_fauxware:
149        yield run_callable_c_fauxware, arch
150
151
152def test_callable_c_manyfloatsum():
153    for arch in addresses_manysum:
154        yield run_callable_c_manysum, arch
155
156def test_setup_callsite():
157    p = angr.load_shellcode(b'b', arch=archinfo.ArchX86())
158
159    s = p.factory.call_state(0, "hello", stack_base=0x1234, alloc_base=0x5678, grow_like_stack=False)
160    assert (s.regs.sp == 0x1234).is_true()
161    assert (s.mem[0x1234 + 4].long.resolved == 0x5678).is_true()
162    assert (s.memory.load(0x5678, 5) == b'hello').is_true()
163
164    s = p.factory.call_state(0, "hello", stack_base=0x1234)
165    assert (s.regs.sp == 0x1234).is_true()
166    assert (s.mem[0x1234 + 4].long.resolved == 0x1234 + 8).is_true()
167    assert (s.memory.load(0x1234 + 8, 5) == b'hello').is_true()
168
169
170
171if __name__ == "__main__":
172    print('testing manyfloatsum with symbolic arguments')
173    for func, march in test_manyfloatsum_symbolic():
174        print('* testing ' + march)
175        func(march)
176    print('testing manyfloatsum')
177    for func, march in test_manyfloatsum():
178        print('* testing ' + march)
179        func(march)
180    print('testing fauxware')
181    for func, march in test_fauxware():
182        print('* testing ' + march)
183        func(march)
184    print('testing fauxware with c-style strings')
185    for func, march in test_callable_c_fauxware():
186        func(march)
187    print('testing manysum')
188    for func, march in test_manysum():
189        print('* testing ' + march)
190        func(march)
191    print('testing manyfloatsum with c_style strings')
192    for func, march in test_callable_c_manyfloatsum():
193        print('* testing ' + march)
194        func(march)
195