angr 9.2.83__py3-none-win_amd64.whl → 9.2.85__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of angr might be problematic. Click here for more details.
- angr/__init__.py +1 -1
- angr/analyses/cfg/cfg_base.py +6 -1
- angr/analyses/cfg/cfg_fast.py +32 -10
- angr/analyses/decompiler/clinic.py +204 -4
- angr/analyses/decompiler/condition_processor.py +8 -2
- angr/analyses/decompiler/decompilation_options.py +10 -0
- angr/analyses/decompiler/decompiler.py +19 -17
- angr/analyses/decompiler/goto_manager.py +34 -51
- angr/analyses/decompiler/optimization_passes/__init__.py +5 -5
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +2 -0
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/mod_simplifier.py +2 -0
- angr/analyses/decompiler/optimization_passes/multi_simplifier.py +2 -0
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +131 -3
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +3 -3
- angr/analyses/decompiler/optimization_passes/return_duplicator.py +519 -0
- angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +14 -2
- angr/analyses/decompiler/region_identifier.py +8 -2
- angr/analyses/decompiler/region_simplifiers/goto.py +5 -4
- angr/analyses/decompiler/structured_codegen/c.py +66 -5
- angr/analyses/decompiler/structuring/phoenix.py +3 -1
- angr/analyses/decompiler/structuring/structurer_nodes.py +11 -5
- angr/analyses/decompiler/utils.py +50 -0
- angr/analyses/disassembly.py +10 -3
- angr/analyses/propagator/engine_ail.py +125 -0
- angr/analyses/reaching_definitions/engine_ail.py +36 -2
- angr/analyses/reaching_definitions/rd_initializer.py +15 -1
- angr/analyses/reaching_definitions/rd_state.py +9 -4
- angr/analyses/stack_pointer_tracker.py +10 -17
- angr/analyses/variable_recovery/engine_ail.py +27 -1
- angr/angrdb/serializers/loader.py +10 -3
- angr/calling_conventions.py +2 -0
- angr/engines/pcode/behavior.py +7 -2
- angr/engines/pcode/cc.py +1 -0
- angr/engines/pcode/emulate.py +144 -104
- angr/engines/pcode/lifter.py +135 -79
- angr/knowledge_plugins/functions/function.py +28 -0
- angr/knowledge_plugins/functions/function_manager.py +48 -5
- angr/knowledge_plugins/propagations/states.py +14 -0
- angr/lib/angr_native.dll +0 -0
- angr/procedures/cgc/deallocate.py +5 -2
- angr/procedures/posix/gethostbyname.py +23 -8
- angr/project.py +4 -0
- angr/simos/__init__.py +2 -0
- angr/simos/simos.py +1 -0
- angr/simos/snimmuc_nxp.py +152 -0
- angr/state_plugins/history.py +3 -1
- angr/utils/graph.py +20 -18
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/METADATA +9 -8
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/RECORD +61 -59
- tests/analyses/cfg/test_cfg_rust_got_resolution.py +2 -1
- tests/analyses/cfg/test_jumptables.py +2 -1
- tests/analyses/decompiler/test_decompiler.py +155 -103
- tests/engines/pcode/test_emulate.py +607 -0
- tests/engines/test_java.py +609 -663
- tests/knowledge_plugins/functions/test_function_manager.py +13 -0
- tests/serialization/test_db.py +30 -0
- angr/analyses/decompiler/optimization_passes/eager_returns.py +0 -285
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/LICENSE +0 -0
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/WHEEL +0 -0
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/entry_points.txt +0 -0
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/top_level.txt +0 -0
tests/engines/test_java.py
CHANGED
|
@@ -4,10 +4,6 @@ __package__ = __package__ or "tests.engines" # pylint:disable=redefined-builtin
|
|
|
4
4
|
import os
|
|
5
5
|
import unittest
|
|
6
6
|
|
|
7
|
-
import angr
|
|
8
|
-
from angr.storage.memory_mixins import JavaVmMemory, DefaultMemory, KeyValueMemory
|
|
9
|
-
from angr.engines.soot.values import SimSootValue_ArrayRef, SimSootValue_ThisRef
|
|
10
|
-
from angr.engines.soot.method_dispatcher import resolve_method
|
|
11
7
|
from archinfo.arch_amd64 import ArchAMD64
|
|
12
8
|
from archinfo.arch_soot import (
|
|
13
9
|
ArchSoot,
|
|
@@ -18,6 +14,11 @@ from archinfo.arch_soot import (
|
|
|
18
14
|
)
|
|
19
15
|
from claripy.backends.backend_smtlib_solvers import z3str_popen # noqa: F401
|
|
20
16
|
|
|
17
|
+
import angr
|
|
18
|
+
from angr.storage.memory_mixins import JavaVmMemory, DefaultMemory, KeyValueMemory
|
|
19
|
+
from angr.engines.soot.values import SimSootValue_ArrayRef, SimSootValue_ThisRef
|
|
20
|
+
from angr.engines.soot.method_dispatcher import resolve_method
|
|
21
|
+
|
|
21
22
|
try:
|
|
22
23
|
import pysoot
|
|
23
24
|
except ModuleNotFoundError:
|
|
@@ -26,726 +27,671 @@ except ModuleNotFoundError:
|
|
|
26
27
|
from ..common import bin_location
|
|
27
28
|
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
30
|
+
class TestJava(unittest.TestCase):
|
|
31
|
+
test_location = os.path.join(bin_location, "tests", "java")
|
|
32
|
+
sdk_path = os.path.join(os.path.expanduser("~"), "Android", "Sdk", "platforms")
|
|
33
|
+
|
|
34
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
35
|
+
def test_fauxware(self):
|
|
36
|
+
# create project
|
|
37
|
+
binary_path = os.path.join(self.test_location, "fauxware_java_jni", "fauxware.jar")
|
|
38
|
+
jni_options = {"jni_libs": ["libfauxware.so"]}
|
|
39
|
+
project = angr.Project(binary_path, main_opts=jni_options)
|
|
40
|
+
entry = project.factory.entry_state()
|
|
41
|
+
simgr = project.factory.simgr(entry)
|
|
42
|
+
|
|
43
|
+
# find path to `accepted()` method
|
|
44
|
+
accepted_method = SootMethodDescriptor.from_string("Fauxware.accepted()").address()
|
|
45
|
+
simgr.explore(find=lambda s: s.addr == accepted_method)
|
|
46
|
+
|
|
47
|
+
assert len(simgr.found) == 1
|
|
48
|
+
state = simgr.found[0]
|
|
49
|
+
|
|
50
|
+
# eval password
|
|
51
|
+
cmd_line_args = project.simos.get_cmd_line_args(state)
|
|
52
|
+
password = state.solver.eval(cmd_line_args[0])
|
|
53
|
+
assert password == "SOSNEAKY"
|
|
54
|
+
|
|
55
|
+
@unittest.skipUnless(os.path.exists(sdk_path), "Android SDK found")
|
|
56
|
+
def test_apk_loading(self):
|
|
57
|
+
loading_opts = {
|
|
58
|
+
"android_sdk": self.sdk_path,
|
|
59
|
+
"entry_point": "com.example.antoniob.android1.MainActivity.onCreate",
|
|
60
|
+
"entry_point_params": ("android.os.Bundle",),
|
|
61
|
+
}
|
|
62
|
+
project = angr.Project(
|
|
63
|
+
os.path.join(self.test_location, "android1.apk"), main_opts=loading_opts, auto_load_libs=False
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
blank_state = project.factory.blank_state()
|
|
67
|
+
a1 = SimSootValue_ThisRef.new_object(blank_state, "com.example.antoniob.android1.MainActivity")
|
|
68
|
+
a2 = SimSootValue_ThisRef.new_object(blank_state, "android.os.Bundle", symbolic=True)
|
|
69
|
+
args = [SootArgument(arg, arg.type) for arg in [a1, a2]]
|
|
70
|
+
entry = project.factory.entry_state(args=args)
|
|
71
|
+
|
|
72
|
+
simgr = project.factory.simgr(entry)
|
|
73
|
+
simgr.step()
|
|
74
|
+
simgr.step()
|
|
75
|
+
assert simgr.active[0].addr.block_idx == 0
|
|
76
|
+
assert simgr.active[0].addr.stmt_idx == 3
|
|
77
|
+
simgr.run()
|
|
78
|
+
assert len(simgr.deadended) == 1
|
|
79
|
+
assert type(simgr.deadended[0].addr) is SootAddressTerminator
|
|
51
80
|
|
|
81
|
+
#
|
|
82
|
+
# Command line arguments
|
|
83
|
+
#
|
|
52
84
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
85
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
86
|
+
def test_cmd_line_args(self):
|
|
87
|
+
project = self.create_project("cmd_line_args", load_native_libs=False)
|
|
88
|
+
entry = project.factory.entry_state()
|
|
89
|
+
simgr = project.factory.simgr(entry)
|
|
90
|
+
simgr.run()
|
|
91
|
+
assert len(simgr.deadended) == 2
|
|
92
|
+
state1, state2 = tuple(simgr.deadended)
|
|
93
|
+
|
|
94
|
+
# get symbol of args[0] from memory
|
|
95
|
+
args = state1.globals["cmd_line_args"]
|
|
96
|
+
args0_arrref = SimSootValue_ArrayRef(args, 0)
|
|
97
|
+
args0_strref = state1.memory.load(args0_arrref)
|
|
98
|
+
args0_strval = state1.memory.load(args0_strref)
|
|
99
|
+
|
|
100
|
+
# eval args[0] on both states
|
|
101
|
+
str1 = state1.solver.eval(args0_strval)
|
|
102
|
+
str2 = state2.solver.eval(args0_strval)
|
|
103
|
+
assert "secret_value" in [str1, str2]
|
|
65
104
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
args = [SootArgument(arg, arg.type) for arg in [a1, a2]]
|
|
70
|
-
entry = project.factory.entry_state(args=args)
|
|
105
|
+
#
|
|
106
|
+
# JNI Version Information
|
|
107
|
+
#
|
|
71
108
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
assert simgr.active[0].addr.block_idx == 0
|
|
76
|
-
assert simgr.active[0].addr.stmt_idx == 3
|
|
77
|
-
simgr.run()
|
|
78
|
-
assert len(simgr.deadended) == 1
|
|
79
|
-
assert type(simgr.deadended[0].addr) is SootAddressTerminator
|
|
109
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
110
|
+
def test_jni_version_information(self):
|
|
111
|
+
project = self.create_project("jni_version_information")
|
|
80
112
|
|
|
113
|
+
self.run_method(project=project, method="MixedJava.test_jni_get_version", assert_locals={"i0": 0x10008})
|
|
81
114
|
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
115
|
+
#
|
|
116
|
+
# JNI Global and Local References
|
|
117
|
+
#
|
|
85
118
|
|
|
119
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
120
|
+
def test_jni_global_and_local_refs(self):
|
|
121
|
+
project = self.create_project("jni_global_and_local_refs")
|
|
86
122
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
simgr = project.factory.simgr(entry)
|
|
92
|
-
simgr.run()
|
|
93
|
-
assert len(simgr.deadended) == 2
|
|
94
|
-
state1, state2 = tuple(simgr.deadended)
|
|
123
|
+
assertions = {"global refs dict": lambda state: (state.jni_references.global_refs == {})}
|
|
124
|
+
self.run_method(
|
|
125
|
+
project=project, method="MixedJava.test_jni_global_refs", assert_locals={"i0": 0xA}, assertions=assertions
|
|
126
|
+
)
|
|
95
127
|
|
|
96
|
-
#
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
args0_strref = state1.memory.load(args0_arrref)
|
|
100
|
-
args0_strval = state1.memory.load(args0_strref)
|
|
128
|
+
#
|
|
129
|
+
# JNI Object Operations
|
|
130
|
+
#
|
|
101
131
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
str2 = state2.solver.eval(args0_strval)
|
|
105
|
-
assert "secret_value" in [str1, str2]
|
|
132
|
+
def test_jni_object_operations(self):
|
|
133
|
+
project = self.create_project("jni_object_operations")
|
|
106
134
|
|
|
135
|
+
self.run_method(project=project, method="MixedJava.test_jni_alloc_object", assert_locals={"i0": 0})
|
|
107
136
|
|
|
108
|
-
|
|
109
|
-
# JNI Version Information
|
|
110
|
-
#
|
|
137
|
+
self.run_method(project=project, method="MixedJava.test_jni_new_object", assert_locals={"i0": 1})
|
|
111
138
|
|
|
139
|
+
self.run_method(project=project, method="MixedJava.test_jni_new_subclass_object", assert_locals={"i0": 2})
|
|
112
140
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
141
|
+
self.run_method(
|
|
142
|
+
project=project,
|
|
143
|
+
method="MixedJava.test_jni_isinstanceof",
|
|
144
|
+
assert_locals={"i0": 1, "i1": 1, "i2": 0, "i3": 1},
|
|
145
|
+
)
|
|
116
146
|
|
|
117
|
-
|
|
147
|
+
self.run_method(project=project, method="MixedJava.test_jni_issameobject", assert_locals={"i0": 0, "i1": 1})
|
|
118
148
|
|
|
149
|
+
#
|
|
150
|
+
# JNI String Operations
|
|
151
|
+
#
|
|
119
152
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
#
|
|
153
|
+
def test_jni_string_operations(self):
|
|
154
|
+
project = self.create_project("jni_string_operations")
|
|
123
155
|
|
|
156
|
+
assertions = {
|
|
157
|
+
"1st string": lambda state: (state.solver.eval_one(self.load_string(state, "r0")) == "mum"),
|
|
158
|
+
"2nd string": lambda state: (state.solver.eval_one(self.load_string(state, "r1")) == "himum!"),
|
|
159
|
+
}
|
|
160
|
+
self.run_method(
|
|
161
|
+
project=project,
|
|
162
|
+
method="MixedJava.test_jni_string_operations",
|
|
163
|
+
assert_locals={"i0": 0x3, "i1": 0x6},
|
|
164
|
+
assertions=assertions,
|
|
165
|
+
)
|
|
124
166
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
167
|
+
#
|
|
168
|
+
# JNI Field Access
|
|
169
|
+
#
|
|
128
170
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
171
|
+
def test_jni_field_access(self):
|
|
172
|
+
project = self.create_project("jni_field_access")
|
|
173
|
+
|
|
174
|
+
self.run_method(
|
|
175
|
+
project=project,
|
|
176
|
+
method="MixedJava.test_static_field_access_basic",
|
|
177
|
+
assert_locals={"i0": 0x0, "i1": 0x1, "i2": 0xA, "i3": 0xB, "i4": 0x7, "i5": 0xB, "i6": 0x0, "i7": 0x9},
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
self.run_method(
|
|
181
|
+
project=project, method="MixedJava.test_jni_static_field_access", assert_locals={"i0": 0, "i1": 5}
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
self.run_method(
|
|
185
|
+
project=project,
|
|
186
|
+
method="MixedJava.test_jni_static_field_access_subclass",
|
|
187
|
+
assert_locals={"i0": 1, "i1": 10, "i2": 30, "i3": 1},
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
self.run_method(
|
|
191
|
+
project=project,
|
|
192
|
+
method="MixedJava.test_instance_field_access_0",
|
|
193
|
+
assert_locals={"i0": 0, "i1": 10, "i2": 5, "i3": 5},
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
self.run_method(
|
|
197
|
+
project=project,
|
|
198
|
+
method="MixedJava.test_instance_field_access_1",
|
|
199
|
+
assert_locals={"i0": 0, "i1": 1, "i2": 10, "i3": 4, "i4": 4, "i5": 1},
|
|
200
|
+
)
|
|
133
201
|
|
|
202
|
+
#
|
|
203
|
+
# JNI Method Calls
|
|
204
|
+
#
|
|
134
205
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
206
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
207
|
+
def test_jni_method_calls(self):
|
|
208
|
+
project = self.create_project("jni_method_calls")
|
|
138
209
|
|
|
210
|
+
self.run_method(
|
|
211
|
+
project=project, method="MixedJava.test_jni_non_virtual_instance_method_call", assert_locals={"i0": 5}
|
|
212
|
+
)
|
|
139
213
|
|
|
140
|
-
|
|
141
|
-
|
|
214
|
+
self.run_method(
|
|
215
|
+
project=project, method="MixedJava.test_jni_instance_method_calls_basic", assert_locals={"i0": 7, "i1": 7}
|
|
216
|
+
)
|
|
142
217
|
|
|
143
|
-
|
|
218
|
+
self.run_method(
|
|
219
|
+
project=project,
|
|
220
|
+
method="MixedJava.test_jni_instance_method_calls_subclass",
|
|
221
|
+
assert_locals={"i0": 2, "i1": 2},
|
|
222
|
+
)
|
|
144
223
|
|
|
145
|
-
|
|
224
|
+
self.run_method(
|
|
225
|
+
project=project,
|
|
226
|
+
method="MixedJava.test_jni_instance_method_calls_shared_method_id",
|
|
227
|
+
assert_locals={"i0": 8, "i1": 2},
|
|
228
|
+
)
|
|
146
229
|
|
|
147
|
-
|
|
230
|
+
self.run_method(
|
|
231
|
+
project=project, method="MixedJava.test_jni_instance_method_calls_args", assert_locals={"i0": 11}
|
|
232
|
+
)
|
|
148
233
|
|
|
149
|
-
|
|
150
|
-
project=project, method="MixedJava.test_jni_isinstanceof", assert_locals={"i0": 1, "i1": 1, "i2": 0, "i3": 1}
|
|
151
|
-
)
|
|
234
|
+
self.run_method(project=project, method="MixedJava.test_jni_static_method_call", assert_locals={"i0": 10})
|
|
152
235
|
|
|
153
|
-
|
|
236
|
+
self.run_method(
|
|
237
|
+
project=project, method="MixedJava.test_jni_static_method_call_return_obj", assert_locals={"i0": 7}
|
|
238
|
+
)
|
|
154
239
|
|
|
240
|
+
#
|
|
241
|
+
# JNI Primitive Datatypes
|
|
242
|
+
#
|
|
155
243
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
244
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
245
|
+
def test_jni_primitive_datatypes(self):
|
|
246
|
+
project = self.create_project("jni_primitive_datatypes")
|
|
159
247
|
|
|
248
|
+
self.run_method(
|
|
249
|
+
project=project,
|
|
250
|
+
method="MixedJava.test_boolean",
|
|
251
|
+
assert_locals={"z0": 1, "z1": 0, "z2": 1, "z3": 0, "z4": 1},
|
|
252
|
+
)
|
|
160
253
|
|
|
161
|
-
|
|
162
|
-
|
|
254
|
+
self.run_method(
|
|
255
|
+
project=project, method="MixedJava.test_byte", assert_locals={"b5": 30, "b8": 0xFFFFFF80, "b11": 0}
|
|
256
|
+
)
|
|
163
257
|
|
|
164
|
-
|
|
165
|
-
"1st string": lambda state: (state.solver.eval_one(load_string(state, "r0")) == "mum"),
|
|
166
|
-
"2nd string": lambda state: (state.solver.eval_one(load_string(state, "r1")) == "himum!"),
|
|
167
|
-
}
|
|
168
|
-
run_method(
|
|
169
|
-
project=project,
|
|
170
|
-
method="MixedJava.test_jni_string_operations",
|
|
171
|
-
assert_locals={"i0": 0x3, "i1": 0x6},
|
|
172
|
-
assertions=assertions,
|
|
173
|
-
)
|
|
258
|
+
self.run_method(project=project, method="MixedJava.test_char", assert_locals={"c4": 21, "c6": 0, "c9": 1})
|
|
174
259
|
|
|
260
|
+
self.run_method(
|
|
261
|
+
project=project,
|
|
262
|
+
method="MixedJava.test_short",
|
|
263
|
+
assert_locals={"s3": 0x1000, "s5": 0xFFFFF000, "s0": 11, "s9": 0},
|
|
264
|
+
)
|
|
175
265
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
266
|
+
self.run_method(
|
|
267
|
+
project=project,
|
|
268
|
+
method="MixedJava.test_int",
|
|
269
|
+
assert_locals={"i1": 0xFFFFFFF6, "i3": 0, "i5": 0x80000001, "i7": 0x7FFFFFFF},
|
|
270
|
+
)
|
|
179
271
|
|
|
272
|
+
self.run_method(
|
|
273
|
+
project=project, method="MixedJava.test_long", assert_locals={"l1": 0xFFFFFFFFFFFFFFFF, "l3": 1}
|
|
274
|
+
)
|
|
180
275
|
|
|
181
|
-
|
|
182
|
-
|
|
276
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
277
|
+
def test_jni_object_arrays(self):
|
|
278
|
+
project = self.create_project("jni_object_array_operations")
|
|
183
279
|
|
|
184
|
-
|
|
185
|
-
project=project,
|
|
186
|
-
method="MixedJava.test_static_field_access_basic",
|
|
187
|
-
assert_locals={"i0": 0x0, "i1": 0x1, "i2": 0xA, "i3": 0xB, "i4": 0x7, "i5": 0xB, "i6": 0x0, "i7": 0x9},
|
|
188
|
-
)
|
|
280
|
+
self.run_method(project=project, method="MixedJava.test_jni_access_object_array", assert_locals={"i0": 7})
|
|
189
281
|
|
|
190
|
-
|
|
282
|
+
self.run_method(project=project, method="MixedJava.test_jni_new_object_array", assert_locals={"i0": 10})
|
|
191
283
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
assert_locals={"i0": 1, "i1": 10, "i2": 30, "i3": 1},
|
|
196
|
-
)
|
|
284
|
+
#
|
|
285
|
+
# JNI Array Operations
|
|
286
|
+
#
|
|
197
287
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
288
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
289
|
+
def test_jni_array_operations(self):
|
|
290
|
+
project = self.create_project("jni_array_operations")
|
|
291
|
+
|
|
292
|
+
# test_jni_newarray
|
|
293
|
+
self.run_method(
|
|
294
|
+
project=project,
|
|
295
|
+
method="MixedJava.test_jni_newarray",
|
|
296
|
+
assert_locals={"i0": 0, "i1": 1, "i2": 2, "i3": 3, "i4": 4},
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
# test_jni_getarrayregion
|
|
300
|
+
state = self.run_method(project=project, method="MixedJava.test_jni_getarrayregion")
|
|
301
|
+
a = self.load_value_from_stack(state, "i1")
|
|
302
|
+
state.solver.add(a == 15)
|
|
303
|
+
idx = state.posix.stdin.content[0][0]
|
|
304
|
+
assert state.solver.eval_one(idx) == 7
|
|
305
|
+
|
|
306
|
+
# test_jni_setarrayregion1
|
|
307
|
+
self.run_method(
|
|
308
|
+
project=project,
|
|
309
|
+
method="MixedJava.test_jni_setarrayregion1",
|
|
310
|
+
assert_locals={"i0": 0, "i1": 3, "i2": 2, "i3": 1, "i4": 4},
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
# test_jni_setarrayregion2
|
|
314
|
+
state = self.run_method(project=project, method="MixedJava.test_jni_setarrayregion2")
|
|
315
|
+
a = self.load_value_from_stack(state, "i1")
|
|
316
|
+
state.solver.add(a == 2)
|
|
317
|
+
idx = state.posix.stdin.content[0][0]
|
|
318
|
+
idx_value = state.solver.eval_one(idx)
|
|
319
|
+
assert idx_value == 0
|
|
320
|
+
|
|
321
|
+
# test_jni_setarrayregion2
|
|
322
|
+
state = self.run_method(project=project, method="MixedJava.test_jni_setarrayregion2")
|
|
323
|
+
a = self.load_value_from_stack(state, "i1")
|
|
324
|
+
state.solver.add(a == 0)
|
|
325
|
+
idx = state.posix.stdin.content[0][0]
|
|
326
|
+
idx_value = state.solver.eval_exact(idx, 2)
|
|
327
|
+
assert 1 in idx_value
|
|
328
|
+
assert 2 in idx_value
|
|
329
|
+
assert 3 not in idx_value
|
|
330
|
+
|
|
331
|
+
# test_jni_getarrayelements_symbolic
|
|
332
|
+
winning_path = self.get_winning_path(
|
|
333
|
+
project=project, method_fullname="MixedJava.test_jni_getarrayelements_symbolic"
|
|
334
|
+
)
|
|
335
|
+
stdin_packets = winning_path.posix.stdin.content
|
|
336
|
+
idx = winning_path.solver.eval_one(stdin_packets[0][0])
|
|
337
|
+
min_length = winning_path.solver.min(stdin_packets[1][0])
|
|
338
|
+
assert idx == 223
|
|
339
|
+
assert min_length == 224
|
|
340
|
+
|
|
341
|
+
# test_jni_releasearrayelements
|
|
342
|
+
self.run_method(
|
|
343
|
+
project=project,
|
|
344
|
+
method="MixedJava.test_jni_releasearrayelments",
|
|
345
|
+
assert_locals={"i0": 4, "i1": 3, "i2": 2, "i3": 1, "i4": 0},
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
# test_jni_getarrayelements_and_releasearrayelements
|
|
349
|
+
self.run_method(
|
|
350
|
+
project=project,
|
|
351
|
+
method="MixedJava.test_jni_getarrayelements_and_releasearrayelements",
|
|
352
|
+
assert_locals={
|
|
353
|
+
"c9": 0xFFFF,
|
|
354
|
+
"c14": 0x0000,
|
|
355
|
+
"b5": 0x0000007F,
|
|
356
|
+
"b10": 0xFFFFFF80,
|
|
357
|
+
"s6": 0x00007FFF,
|
|
358
|
+
"s11": 0xFFFF8000,
|
|
359
|
+
"i7": 0x7FFFFFFF,
|
|
360
|
+
"i12": 0x80000000,
|
|
361
|
+
"l8": 0x7FFFFFFFFFFFFFFF,
|
|
362
|
+
"l13": 0x8000000000000000,
|
|
363
|
+
},
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
# test_jni_getarraylength
|
|
367
|
+
state = self.run_method(project=project, method="MixedJava.test_jni_getarraylength")
|
|
368
|
+
a = state.memory.stack.load("i3")
|
|
369
|
+
assert state.solver.eval(a) == 10
|
|
370
|
+
b = state.memory.stack.load("i4")
|
|
371
|
+
assert state.solver.min(b) == 0
|
|
372
|
+
assert state.solver.max(b) == 255
|
|
203
373
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
assert_locals={"i0": 0, "i1": 1, "i2": 10, "i3": 4, "i4": 4, "i5": 1},
|
|
208
|
-
)
|
|
374
|
+
#
|
|
375
|
+
# Method Calls
|
|
376
|
+
#
|
|
209
377
|
|
|
378
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
379
|
+
def test_method_calls(self):
|
|
380
|
+
project = self.create_project("method_calls", load_native_libs=False)
|
|
210
381
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
382
|
+
self.run_method(
|
|
383
|
+
project=project,
|
|
384
|
+
method="MixedJava.test_instance_method_calls",
|
|
385
|
+
assert_locals={"i0": 0, "i1": 1, "i2": 1, "i3": 2, "i4": 2, "i5": 2},
|
|
386
|
+
)
|
|
214
387
|
|
|
388
|
+
self.run_method(
|
|
389
|
+
project=project,
|
|
390
|
+
method="MixedJava.test_static_method_calls_0",
|
|
391
|
+
assert_locals={"i0": 0, "i1": 1, "i2": 2, "i3": 2},
|
|
392
|
+
)
|
|
215
393
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
394
|
+
self.run_method(
|
|
395
|
+
project=project,
|
|
396
|
+
method="MixedJava.test_static_method_calls_1",
|
|
397
|
+
assert_locals={"i0": 0, "i1": 0, "i2": 1, "i3": 2, "i4": 2, "i5": 2},
|
|
398
|
+
)
|
|
219
399
|
|
|
220
|
-
|
|
400
|
+
self.run_method(project=project, method="MixedJava.test_special_invoke_0", assert_locals={"i0": 3})
|
|
221
401
|
|
|
222
|
-
|
|
223
|
-
project=project, method="MixedJava.test_jni_instance_method_calls_basic", assert_locals={"i0": 7, "i1": 7}
|
|
224
|
-
)
|
|
402
|
+
self.run_method(project=project, method="MixedJava.test_special_invoke_1", assert_locals={"i0": 4})
|
|
225
403
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
404
|
+
#
|
|
405
|
+
# Array Operations
|
|
406
|
+
#
|
|
229
407
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
408
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
409
|
+
def test_array_operations(self):
|
|
410
|
+
project = self.create_project("array_operations", load_native_libs=False)
|
|
411
|
+
|
|
412
|
+
# test_basic_array_operations
|
|
413
|
+
self.run_method(
|
|
414
|
+
project=project,
|
|
415
|
+
method="MixedJava.test_basic_array_operations",
|
|
416
|
+
assert_locals={"i1": 0, "i2": 1, "i3": 2, "i4": 3, "i5": 4, "i6": 5, "i7": 2, "i8": 0},
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
# test_symbolic_array_read
|
|
420
|
+
winning_path = self.get_winning_path(project=project, method_fullname="MixedJava.test_symbolic_array_read")
|
|
421
|
+
stdin_packets = winning_path.posix.stdin.content
|
|
422
|
+
input_char, _ = stdin_packets[0]
|
|
423
|
+
solutions = winning_path.solver.eval_upto(input_char, 2)
|
|
424
|
+
assert ord("A") in solutions
|
|
425
|
+
assert ord("C") in solutions
|
|
426
|
+
|
|
427
|
+
# test_symbolic_array_write
|
|
428
|
+
winning_path = self.get_winning_path(project=project, method_fullname="MixedJava.test_symbolic_array_write")
|
|
429
|
+
stdin_packets = winning_path.posix.stdin.content
|
|
430
|
+
idx_symbol, _ = stdin_packets[0]
|
|
431
|
+
val_symbol, _ = stdin_packets[1]
|
|
432
|
+
winning_path.solver.add(val_symbol != 0) # exclude trivial solution
|
|
433
|
+
idx = winning_path.solver.eval(idx_symbol)
|
|
434
|
+
val = winning_path.solver.eval(val_symbol)
|
|
435
|
+
assert idx == 73
|
|
436
|
+
assert val == 53
|
|
437
|
+
|
|
438
|
+
# test_symbolic_array_length
|
|
439
|
+
winning_path = self.get_winning_path(project=project, method_fullname="MixedJava.test_symbolic_array_length")
|
|
440
|
+
stdin_packets = winning_path.posix.stdin.content
|
|
441
|
+
input_char, _ = stdin_packets[0]
|
|
442
|
+
solution = winning_path.solver.eval(input_char)
|
|
443
|
+
assert solution == ord("F")
|
|
444
|
+
|
|
445
|
+
# test_index_of_of_bound0
|
|
446
|
+
state = self.run_method(project=project, method="MixedJava.test_index_of_of_bound0")
|
|
447
|
+
array_len = self.load_value_from_stack(state, "i1")
|
|
448
|
+
assert state.solver.min(array_len) == 0
|
|
449
|
+
assert state.solver.max(array_len) == 255
|
|
450
|
+
|
|
451
|
+
# test_index_of_of_bound1
|
|
452
|
+
state = self.run_method(project=project, method="MixedJava.test_index_of_of_bound1")
|
|
453
|
+
array_len = self.load_value_from_stack(state, "i1")
|
|
454
|
+
assert state.solver.min(array_len) == 101
|
|
455
|
+
assert state.solver.max(array_len) == 255
|
|
456
|
+
|
|
457
|
+
# test_index_of_of_bound2
|
|
458
|
+
state = self.run_method(project=project, method="MixedJava.test_index_of_of_bound2")
|
|
459
|
+
assert self.load_value_from_stack(state, "i1") is not None
|
|
460
|
+
assert self.load_value_from_stack(state, "i2") is None
|
|
461
|
+
assert self.load_value_from_stack(state, "i3") is None
|
|
462
|
+
assert self.load_value_from_stack(state, "i4") is not None
|
|
463
|
+
assert self.load_value_from_stack(state, "i5") is None
|
|
464
|
+
|
|
465
|
+
# test_index_of_of_bound3
|
|
466
|
+
state = self.run_method(project=project, method="MixedJava.test_index_of_of_bound3")
|
|
467
|
+
assert self.load_value_from_stack(state, "i1") is not None
|
|
468
|
+
assert self.load_value_from_stack(state, "i2") is not None
|
|
469
|
+
assert self.load_value_from_stack(state, "i3") is None
|
|
470
|
+
assert self.load_value_from_stack(state, "i4") is not None
|
|
471
|
+
assert self.load_value_from_stack(state, "i5") is None
|
|
472
|
+
|
|
473
|
+
# test_index_of_of_bound4
|
|
474
|
+
state = self.run_method(project=project, method="MixedJava.test_index_of_of_bound4")
|
|
475
|
+
assert self.load_value_from_stack(state, "i1") is not None
|
|
476
|
+
assert self.load_value_from_stack(state, "i2") is not None
|
|
477
|
+
assert self.load_value_from_stack(state, "i3") is None
|
|
478
|
+
|
|
479
|
+
# test_index_of_of_bound5
|
|
480
|
+
state = self.run_method(project=project, method="MixedJava.test_index_of_of_bound5")
|
|
481
|
+
assert self.load_value_from_stack(state, "i1") is not None
|
|
482
|
+
assert self.load_value_from_stack(state, "i2") is not None
|
|
483
|
+
assert self.load_value_from_stack(state, "i3") is None
|
|
235
484
|
|
|
236
|
-
|
|
485
|
+
#
|
|
486
|
+
# MultiArray Operations
|
|
487
|
+
#
|
|
237
488
|
|
|
238
|
-
|
|
489
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
490
|
+
def test_multiarray_operations(self):
|
|
491
|
+
project = self.create_project("multiarray_operations", load_native_libs=False)
|
|
239
492
|
|
|
240
|
-
|
|
493
|
+
self.run_method(project=project, method="MixedJava.basic_multiarray_ops", assert_locals={"d1": 4})
|
|
241
494
|
|
|
495
|
+
#
|
|
496
|
+
# Loading
|
|
497
|
+
#
|
|
242
498
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
#
|
|
499
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
500
|
+
def test_loading(self):
|
|
501
|
+
# Test1: test loading with load path
|
|
502
|
+
native_libs_ld_path = os.path.join(self.test_location, "misc", "loading1", "libs")
|
|
503
|
+
jar_path = os.path.join(self.test_location, "misc", "loading1", "mixedjava.jar")
|
|
504
|
+
# define which libraries to load (+ the load path)
|
|
505
|
+
jni_options = {"jni_libs": ["libmixedjava.so"], "jni_libs_ld_path": native_libs_ld_path}
|
|
506
|
+
project = angr.Project(jar_path, main_opts=jni_options, auto_load_libs=True)
|
|
507
|
+
# check if libmixedjava.so was loaded
|
|
508
|
+
loaded_libs = [lib.provides for lib in project.loader.all_elf_objects]
|
|
509
|
+
assert "libmixedjava.so" in loaded_libs
|
|
510
|
+
|
|
511
|
+
# Test 2: test loading without load path
|
|
512
|
+
# => the folder of the JAR is implicitly used as an additional load path
|
|
513
|
+
binary_dir = os.path.join(self.test_location, "misc", "loading2")
|
|
514
|
+
project = self.create_project(binary_dir)
|
|
515
|
+
# check if libmixedjava.so was loaded
|
|
516
|
+
loaded_libs = [lib.provides for lib in project.loader.all_elf_objects]
|
|
517
|
+
assert "libmixedjava.so" in loaded_libs
|
|
246
518
|
|
|
519
|
+
#
|
|
520
|
+
# SimStates
|
|
521
|
+
#
|
|
247
522
|
|
|
248
|
-
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
249
|
-
def
|
|
250
|
-
|
|
523
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
524
|
+
def test_toggling_of_simstate(self):
|
|
525
|
+
binary_dir = os.path.join(self.test_location, "misc", "simstates")
|
|
526
|
+
project = self.create_project(binary_dir)
|
|
527
|
+
|
|
528
|
+
state = project.factory.entry_state()
|
|
529
|
+
assert state.ip_is_soot_addr
|
|
530
|
+
assert isinstance(state.arch, ArchSoot)
|
|
531
|
+
assert isinstance(state.memory, JavaVmMemory)
|
|
532
|
+
assert isinstance(state.registers, KeyValueMemory)
|
|
533
|
+
|
|
534
|
+
state.regs.ip = 1
|
|
535
|
+
assert not state.ip_is_soot_addr
|
|
536
|
+
assert isinstance(state.arch, ArchAMD64)
|
|
537
|
+
assert isinstance(state.memory, DefaultMemory)
|
|
538
|
+
assert isinstance(state.registers, DefaultMemory)
|
|
539
|
+
|
|
540
|
+
state.regs._ip = project.entry
|
|
541
|
+
|
|
542
|
+
assert state.ip_is_soot_addr
|
|
543
|
+
assert isinstance(state.arch, ArchSoot)
|
|
544
|
+
assert isinstance(state.memory, JavaVmMemory)
|
|
545
|
+
assert isinstance(state.registers, KeyValueMemory)
|
|
546
|
+
|
|
547
|
+
state.ip = 1
|
|
548
|
+
assert not state.ip_is_soot_addr
|
|
549
|
+
assert isinstance(state.arch, ArchAMD64)
|
|
550
|
+
assert isinstance(state.memory, DefaultMemory)
|
|
551
|
+
assert isinstance(state.registers, DefaultMemory)
|
|
552
|
+
|
|
553
|
+
state_copy = state.copy()
|
|
554
|
+
assert not state_copy.ip_is_soot_addr
|
|
555
|
+
assert isinstance(state_copy.arch, ArchAMD64)
|
|
556
|
+
assert isinstance(state_copy.memory, DefaultMemory)
|
|
557
|
+
assert isinstance(state_copy.registers, DefaultMemory)
|
|
558
|
+
|
|
559
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
560
|
+
def test_object_tracking(self):
|
|
561
|
+
binary_dir = os.path.join(self.test_location, "object_tracking")
|
|
562
|
+
project = self.create_project(binary_dir, load_native_libs=False)
|
|
563
|
+
bootstrap_state = project.factory.blank_state(addr=SootAddressTerminator())
|
|
564
|
+
mylib_object = SimSootValue_ThisRef.new_object(bootstrap_state, "MyLib", symbolic=True, init_object=False)
|
|
565
|
+
|
|
566
|
+
soot_method = resolve_method(
|
|
567
|
+
bootstrap_state, "testGetterAndSetterConcrete", "MixedJava", ("mylib.MyLib",), init_class=False
|
|
568
|
+
).address()
|
|
569
|
+
|
|
570
|
+
call_state = project.factory.call_state(
|
|
571
|
+
soot_method,
|
|
572
|
+
SootArgument(mylib_object, mylib_object.type, is_this_ref=False),
|
|
573
|
+
base_state=bootstrap_state,
|
|
574
|
+
ret_addr=SootAddressTerminator(),
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
call_state.options.add(angr.options.JAVA_IDENTIFY_GETTER_SETTER)
|
|
578
|
+
call_state.options.add(angr.options.JAVA_TRACK_ATTRIBUTES)
|
|
579
|
+
|
|
580
|
+
simgr = project.factory.simgr(call_state)
|
|
581
|
+
simgr.run()
|
|
582
|
+
|
|
583
|
+
assert len(simgr.deadended) == 1
|
|
584
|
+
|
|
585
|
+
final_state = simgr.deadended[0]
|
|
586
|
+
|
|
587
|
+
assert final_state.solver.eval(mylib_object.get_field(final_state, "myInt", "int")) == 1
|
|
588
|
+
assert final_state.solver.eval(mylib_object.get_field(final_state, "myShort", "short")) == 1
|
|
589
|
+
assert final_state.solver.eval(mylib_object.get_field(final_state, "myChar", "char")) == ord("c")
|
|
590
|
+
assert final_state.solver.eval(mylib_object.get_field(final_state, "myLong", "long")) == 2
|
|
591
|
+
assert final_state.solver.eval(mylib_object.get_field(final_state, "myFloat", "float")) == 1.5
|
|
592
|
+
assert final_state.solver.eval(mylib_object.get_field(final_state, "myDouble", "double")) == 1.5
|
|
593
|
+
string_ref = mylib_object.get_field(final_state, "myString", "java.lang.String")
|
|
594
|
+
assert final_state.solver.eval(final_state.memory.load(string_ref)) == "Hello!"
|
|
595
|
+
array_ref = mylib_object.get_field(final_state, "myArray", "int[]")
|
|
596
|
+
assert final_state.solver.eval(array_ref.size) == 3
|
|
597
|
+
object_ref = mylib_object.get_field(final_state, "myObject", "java.lang.Object")
|
|
598
|
+
assert final_state.solver.eval(object_ref.get_field(final_state, "a", "int")) == 1
|
|
599
|
+
|
|
600
|
+
assert ("myInt", "int") in mylib_object.attributes
|
|
601
|
+
assert ("myChar", "char") in mylib_object.attributes
|
|
602
|
+
assert ("myShort", "short") in mylib_object.attributes
|
|
603
|
+
assert ("myLong", "long") in mylib_object.attributes
|
|
604
|
+
assert ("myFloat", "float") in mylib_object.attributes
|
|
605
|
+
assert ("myDouble", "double") in mylib_object.attributes
|
|
606
|
+
assert ("myString", "java.lang.String") in mylib_object.attributes
|
|
607
|
+
assert ("myArray", "int[]") in mylib_object.attributes
|
|
608
|
+
assert ("myObject", "java.lang.Object") in mylib_object.attributes
|
|
251
609
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
610
|
+
#
|
|
611
|
+
# Helper
|
|
612
|
+
#
|
|
255
613
|
|
|
256
|
-
run_method(project
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
method
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
assert state.solver.eval_one(idx) == 7
|
|
306
|
-
|
|
307
|
-
# test_jni_setarrayregion1
|
|
308
|
-
run_method(
|
|
309
|
-
project=project,
|
|
310
|
-
method="MixedJava.test_jni_setarrayregion1",
|
|
311
|
-
assert_locals={"i0": 0, "i1": 3, "i2": 2, "i3": 1, "i4": 4},
|
|
312
|
-
)
|
|
313
|
-
|
|
314
|
-
# test_jni_setarrayregion2
|
|
315
|
-
state = run_method(project=project, method="MixedJava.test_jni_setarrayregion2")
|
|
316
|
-
a = load_value_from_stack(state, "i1")
|
|
317
|
-
state.solver.add(a == 2)
|
|
318
|
-
idx = state.posix.stdin.content[0][0]
|
|
319
|
-
idx_value = state.solver.eval_one(idx)
|
|
320
|
-
assert idx_value == 0
|
|
321
|
-
|
|
322
|
-
# test_jni_setarrayregion2
|
|
323
|
-
state = run_method(project=project, method="MixedJava.test_jni_setarrayregion2")
|
|
324
|
-
a = load_value_from_stack(state, "i1")
|
|
325
|
-
state.solver.add(a == 0)
|
|
326
|
-
idx = state.posix.stdin.content[0][0]
|
|
327
|
-
idx_value = state.solver.eval_exact(idx, 2)
|
|
328
|
-
assert 1 in idx_value
|
|
329
|
-
assert 2 in idx_value
|
|
330
|
-
assert 3 not in idx_value
|
|
331
|
-
|
|
332
|
-
# test_jni_getarrayelements_symbolic
|
|
333
|
-
winning_path = get_winning_path(project=project, method_fullname="MixedJava.test_jni_getarrayelements_symbolic")
|
|
334
|
-
stdin_packets = winning_path.posix.stdin.content
|
|
335
|
-
idx = winning_path.solver.eval_one(stdin_packets[0][0])
|
|
336
|
-
min_length = winning_path.solver.min(stdin_packets[1][0])
|
|
337
|
-
assert idx == 223
|
|
338
|
-
assert min_length == 224
|
|
339
|
-
|
|
340
|
-
# test_jni_releasearrayelements
|
|
341
|
-
run_method(
|
|
342
|
-
project=project,
|
|
343
|
-
method="MixedJava.test_jni_releasearrayelments",
|
|
344
|
-
assert_locals={"i0": 4, "i1": 3, "i2": 2, "i3": 1, "i4": 0},
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
# test_jni_getarrayelements_and_releasearrayelements
|
|
348
|
-
run_method(
|
|
349
|
-
project=project,
|
|
350
|
-
method="MixedJava.test_jni_getarrayelements_and_releasearrayelements",
|
|
351
|
-
assert_locals={
|
|
352
|
-
"c9": 0xFFFF,
|
|
353
|
-
"c14": 0x0000,
|
|
354
|
-
"b5": 0x0000007F,
|
|
355
|
-
"b10": 0xFFFFFF80,
|
|
356
|
-
"s6": 0x00007FFF,
|
|
357
|
-
"s11": 0xFFFF8000,
|
|
358
|
-
"i7": 0x7FFFFFFF,
|
|
359
|
-
"i12": 0x80000000,
|
|
360
|
-
"l8": 0x7FFFFFFFFFFFFFFF,
|
|
361
|
-
"l13": 0x8000000000000000,
|
|
362
|
-
},
|
|
363
|
-
)
|
|
364
|
-
|
|
365
|
-
# test_jni_getarraylength
|
|
366
|
-
state = run_method(project=project, method="MixedJava.test_jni_getarraylength")
|
|
367
|
-
a = state.memory.stack.load("i3")
|
|
368
|
-
assert state.solver.eval(a) == 10
|
|
369
|
-
b = state.memory.stack.load("i4")
|
|
370
|
-
assert state.solver.min(b) == 0
|
|
371
|
-
assert state.solver.max(b) == 255
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
#
|
|
375
|
-
# Method Calls
|
|
376
|
-
#
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
380
|
-
def test_method_calls():
|
|
381
|
-
project = create_project("method_calls", load_native_libs=False)
|
|
382
|
-
|
|
383
|
-
run_method(
|
|
384
|
-
project=project,
|
|
385
|
-
method="MixedJava.test_instance_method_calls",
|
|
386
|
-
assert_locals={"i0": 0, "i1": 1, "i2": 1, "i3": 2, "i4": 2, "i5": 2},
|
|
387
|
-
)
|
|
388
|
-
|
|
389
|
-
run_method(
|
|
390
|
-
project=project,
|
|
391
|
-
method="MixedJava.test_static_method_calls_0",
|
|
392
|
-
assert_locals={"i0": 0, "i1": 1, "i2": 2, "i3": 2},
|
|
393
|
-
)
|
|
394
|
-
|
|
395
|
-
run_method(
|
|
396
|
-
project=project,
|
|
397
|
-
method="MixedJava.test_static_method_calls_1",
|
|
398
|
-
assert_locals={"i0": 0, "i1": 0, "i2": 1, "i3": 2, "i4": 2, "i5": 2},
|
|
399
|
-
)
|
|
400
|
-
|
|
401
|
-
run_method(project=project, method="MixedJava.test_special_invoke_0", assert_locals={"i0": 3})
|
|
402
|
-
|
|
403
|
-
run_method(project=project, method="MixedJava.test_special_invoke_1", assert_locals={"i0": 4})
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
#
|
|
407
|
-
# Array Operations
|
|
408
|
-
#
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
412
|
-
def test_array_operations():
|
|
413
|
-
project = create_project("array_operations", load_native_libs=False)
|
|
414
|
-
|
|
415
|
-
# test_basic_array_operations
|
|
416
|
-
run_method(
|
|
417
|
-
project=project,
|
|
418
|
-
method="MixedJava.test_basic_array_operations",
|
|
419
|
-
assert_locals={"i1": 0, "i2": 1, "i3": 2, "i4": 3, "i5": 4, "i6": 5, "i7": 2, "i8": 0},
|
|
420
|
-
)
|
|
421
|
-
|
|
422
|
-
# test_symbolic_array_read
|
|
423
|
-
winning_path = get_winning_path(project=project, method_fullname="MixedJava.test_symbolic_array_read")
|
|
424
|
-
stdin_packets = winning_path.posix.stdin.content
|
|
425
|
-
input_char, _ = stdin_packets[0]
|
|
426
|
-
solutions = winning_path.solver.eval_upto(input_char, 2)
|
|
427
|
-
assert ord("A") in solutions
|
|
428
|
-
assert ord("C") in solutions
|
|
429
|
-
|
|
430
|
-
# test_symbolic_array_write
|
|
431
|
-
winning_path = get_winning_path(project=project, method_fullname="MixedJava.test_symbolic_array_write")
|
|
432
|
-
stdin_packets = winning_path.posix.stdin.content
|
|
433
|
-
idx_symbol, _ = stdin_packets[0]
|
|
434
|
-
val_symbol, _ = stdin_packets[1]
|
|
435
|
-
winning_path.solver.add(val_symbol != 0) # exclude trivial solution
|
|
436
|
-
idx = winning_path.solver.eval(idx_symbol)
|
|
437
|
-
val = winning_path.solver.eval(val_symbol)
|
|
438
|
-
assert idx == 73
|
|
439
|
-
assert val == 53
|
|
440
|
-
|
|
441
|
-
# test_symbolic_array_length
|
|
442
|
-
winning_path = get_winning_path(project=project, method_fullname="MixedJava.test_symbolic_array_length")
|
|
443
|
-
stdin_packets = winning_path.posix.stdin.content
|
|
444
|
-
input_char, _ = stdin_packets[0]
|
|
445
|
-
solution = winning_path.solver.eval(input_char)
|
|
446
|
-
assert solution == ord("F")
|
|
447
|
-
|
|
448
|
-
# test_index_of_of_bound0
|
|
449
|
-
state = run_method(project=project, method="MixedJava.test_index_of_of_bound0")
|
|
450
|
-
array_len = load_value_from_stack(state, "i1")
|
|
451
|
-
assert state.solver.min(array_len) == 0
|
|
452
|
-
assert state.solver.max(array_len) == 255
|
|
453
|
-
|
|
454
|
-
# test_index_of_of_bound1
|
|
455
|
-
state = run_method(project=project, method="MixedJava.test_index_of_of_bound1")
|
|
456
|
-
array_len = load_value_from_stack(state, "i1")
|
|
457
|
-
assert state.solver.min(array_len) == 101
|
|
458
|
-
assert state.solver.max(array_len) == 255
|
|
459
|
-
|
|
460
|
-
# test_index_of_of_bound2
|
|
461
|
-
state = run_method(project=project, method="MixedJava.test_index_of_of_bound2")
|
|
462
|
-
assert load_value_from_stack(state, "i1") is not None
|
|
463
|
-
assert load_value_from_stack(state, "i2") is None
|
|
464
|
-
assert load_value_from_stack(state, "i3") is None
|
|
465
|
-
assert load_value_from_stack(state, "i4") is not None
|
|
466
|
-
assert load_value_from_stack(state, "i5") is None
|
|
467
|
-
|
|
468
|
-
# test_index_of_of_bound3
|
|
469
|
-
state = run_method(project=project, method="MixedJava.test_index_of_of_bound3")
|
|
470
|
-
assert load_value_from_stack(state, "i1") is not None
|
|
471
|
-
assert load_value_from_stack(state, "i2") is not None
|
|
472
|
-
assert load_value_from_stack(state, "i3") is None
|
|
473
|
-
assert load_value_from_stack(state, "i4") is not None
|
|
474
|
-
assert load_value_from_stack(state, "i5") is None
|
|
475
|
-
|
|
476
|
-
# test_index_of_of_bound4
|
|
477
|
-
state = run_method(project=project, method="MixedJava.test_index_of_of_bound4")
|
|
478
|
-
assert load_value_from_stack(state, "i1") is not None
|
|
479
|
-
assert load_value_from_stack(state, "i2") is not None
|
|
480
|
-
assert load_value_from_stack(state, "i3") is None
|
|
481
|
-
|
|
482
|
-
# test_index_of_of_bound5
|
|
483
|
-
state = run_method(project=project, method="MixedJava.test_index_of_of_bound5")
|
|
484
|
-
assert load_value_from_stack(state, "i1") is not None
|
|
485
|
-
assert load_value_from_stack(state, "i2") is not None
|
|
486
|
-
assert load_value_from_stack(state, "i3") is None
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
#
|
|
490
|
-
# MultiArray Operations
|
|
491
|
-
#
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
495
|
-
def test_multiarray_operations():
|
|
496
|
-
project = create_project("multiarray_operations", load_native_libs=False)
|
|
497
|
-
|
|
498
|
-
run_method(project=project, method="MixedJava.basic_multiarray_ops", assert_locals={"d1": 4})
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
#
|
|
502
|
-
# Loading
|
|
503
|
-
#
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
507
|
-
def test_loading():
|
|
508
|
-
# Test1: test loading with load path
|
|
509
|
-
native_libs_ld_path = os.path.join(test_location, "misc", "loading1", "libs")
|
|
510
|
-
jar_path = os.path.join(test_location, "misc", "loading1", "mixedjava.jar")
|
|
511
|
-
# define which libraries to load (+ the load path)
|
|
512
|
-
jni_options = {"jni_libs": ["libmixedjava.so"], "jni_libs_ld_path": native_libs_ld_path}
|
|
513
|
-
project = angr.Project(jar_path, main_opts=jni_options, auto_load_libs=True)
|
|
514
|
-
# check if libmixedjava.so was loaded
|
|
515
|
-
loaded_libs = [lib.provides for lib in project.loader.all_elf_objects]
|
|
516
|
-
assert "libmixedjava.so" in loaded_libs
|
|
517
|
-
|
|
518
|
-
# Test 2: test loading without load path
|
|
519
|
-
# => the folder of the JAR is implicitly used as an additional load path
|
|
520
|
-
binary_dir = os.path.join(test_location, "misc", "loading2")
|
|
521
|
-
project = create_project(binary_dir)
|
|
522
|
-
# check if libmixedjava.so was loaded
|
|
523
|
-
loaded_libs = [lib.provides for lib in project.loader.all_elf_objects]
|
|
524
|
-
assert "libmixedjava.so" in loaded_libs
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
#
|
|
528
|
-
# SimStates
|
|
529
|
-
#
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
533
|
-
def test_toggling_of_simstate():
|
|
534
|
-
binary_dir = os.path.join(test_location, "misc", "simstates")
|
|
535
|
-
project = create_project(binary_dir)
|
|
536
|
-
|
|
537
|
-
state = project.factory.entry_state()
|
|
538
|
-
assert state.ip_is_soot_addr
|
|
539
|
-
assert isinstance(state.arch, ArchSoot)
|
|
540
|
-
assert isinstance(state.memory, JavaVmMemory)
|
|
541
|
-
assert isinstance(state.registers, KeyValueMemory)
|
|
542
|
-
|
|
543
|
-
state.regs.ip = 1
|
|
544
|
-
assert not state.ip_is_soot_addr
|
|
545
|
-
assert isinstance(state.arch, ArchAMD64)
|
|
546
|
-
assert isinstance(state.memory, DefaultMemory)
|
|
547
|
-
assert isinstance(state.registers, DefaultMemory)
|
|
548
|
-
|
|
549
|
-
state.regs._ip = project.entry
|
|
550
|
-
|
|
551
|
-
assert state.ip_is_soot_addr
|
|
552
|
-
assert isinstance(state.arch, ArchSoot)
|
|
553
|
-
assert isinstance(state.memory, JavaVmMemory)
|
|
554
|
-
assert isinstance(state.registers, KeyValueMemory)
|
|
555
|
-
|
|
556
|
-
state.ip = 1
|
|
557
|
-
assert not state.ip_is_soot_addr
|
|
558
|
-
assert isinstance(state.arch, ArchAMD64)
|
|
559
|
-
assert isinstance(state.memory, DefaultMemory)
|
|
560
|
-
assert isinstance(state.registers, DefaultMemory)
|
|
561
|
-
|
|
562
|
-
state_copy = state.copy()
|
|
563
|
-
assert not state_copy.ip_is_soot_addr
|
|
564
|
-
assert isinstance(state_copy.arch, ArchAMD64)
|
|
565
|
-
assert isinstance(state_copy.memory, DefaultMemory)
|
|
566
|
-
assert isinstance(state_copy.registers, DefaultMemory)
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
570
|
-
def test_object_tracking():
|
|
571
|
-
binary_dir = os.path.join(test_location, "object_tracking")
|
|
572
|
-
project = create_project(binary_dir, load_native_libs=False)
|
|
573
|
-
bootstrap_state = project.factory.blank_state(addr=SootAddressTerminator())
|
|
574
|
-
mylib_object = SimSootValue_ThisRef.new_object(bootstrap_state, "MyLib", symbolic=True, init_object=False)
|
|
575
|
-
|
|
576
|
-
soot_method = resolve_method(
|
|
577
|
-
bootstrap_state, "testGetterAndSetterConcrete", "MixedJava", ("mylib.MyLib",), init_class=False
|
|
578
|
-
).address()
|
|
579
|
-
|
|
580
|
-
call_state = project.factory.call_state(
|
|
581
|
-
soot_method,
|
|
582
|
-
SootArgument(mylib_object, mylib_object.type, is_this_ref=False),
|
|
583
|
-
base_state=bootstrap_state,
|
|
584
|
-
ret_addr=SootAddressTerminator(),
|
|
585
|
-
)
|
|
586
|
-
|
|
587
|
-
call_state.options.add(angr.options.JAVA_IDENTIFY_GETTER_SETTER)
|
|
588
|
-
call_state.options.add(angr.options.JAVA_TRACK_ATTRIBUTES)
|
|
589
|
-
|
|
590
|
-
simgr = project.factory.simgr(call_state)
|
|
591
|
-
simgr.run()
|
|
592
|
-
|
|
593
|
-
assert len(simgr.deadended) == 1
|
|
594
|
-
|
|
595
|
-
final_state = simgr.deadended[0]
|
|
596
|
-
|
|
597
|
-
assert final_state.solver.eval(mylib_object.get_field(final_state, "myInt", "int")) == 1
|
|
598
|
-
assert final_state.solver.eval(mylib_object.get_field(final_state, "myShort", "short")) == 1
|
|
599
|
-
assert final_state.solver.eval(mylib_object.get_field(final_state, "myChar", "char")) == ord("c")
|
|
600
|
-
assert final_state.solver.eval(mylib_object.get_field(final_state, "myLong", "long")) == 2
|
|
601
|
-
assert final_state.solver.eval(mylib_object.get_field(final_state, "myFloat", "float")) == 1.5
|
|
602
|
-
assert final_state.solver.eval(mylib_object.get_field(final_state, "myDouble", "double")) == 1.5
|
|
603
|
-
string_ref = mylib_object.get_field(final_state, "myString", "java.lang.String")
|
|
604
|
-
assert final_state.solver.eval(final_state.memory.load(string_ref)) == "Hello!"
|
|
605
|
-
array_ref = mylib_object.get_field(final_state, "myArray", "int[]")
|
|
606
|
-
assert final_state.solver.eval(array_ref.size) == 3
|
|
607
|
-
object_ref = mylib_object.get_field(final_state, "myObject", "java.lang.Object")
|
|
608
|
-
assert final_state.solver.eval(object_ref.get_field(final_state, "a", "int")) == 1
|
|
609
|
-
|
|
610
|
-
assert ("myInt", "int") in mylib_object.attributes
|
|
611
|
-
assert ("myChar", "char") in mylib_object.attributes
|
|
612
|
-
assert ("myShort", "short") in mylib_object.attributes
|
|
613
|
-
assert ("myLong", "long") in mylib_object.attributes
|
|
614
|
-
assert ("myFloat", "float") in mylib_object.attributes
|
|
615
|
-
assert ("myDouble", "double") in mylib_object.attributes
|
|
616
|
-
assert ("myString", "java.lang.String") in mylib_object.attributes
|
|
617
|
-
assert ("myArray", "int[]") in mylib_object.attributes
|
|
618
|
-
assert ("myObject", "java.lang.Object") in mylib_object.attributes
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
#
|
|
622
|
-
# Helper
|
|
623
|
-
#
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
def run_method(project, method, assert_locals=None, assertions=None):
|
|
627
|
-
end_state = get_last_state_of_method(project, method)
|
|
628
|
-
# print_java_memory(end_state)
|
|
629
|
-
|
|
630
|
-
if assert_locals:
|
|
631
|
-
for symbol_name, assert_value in assert_locals.items():
|
|
632
|
-
symbol = load_value_from_stack(end_state, symbol_name)
|
|
633
|
-
val = end_state.solver.eval(symbol)
|
|
634
|
-
assert val == assert_value
|
|
635
|
-
|
|
636
|
-
if assertions:
|
|
637
|
-
for _, test in assertions.items():
|
|
638
|
-
assert test(end_state)
|
|
639
|
-
|
|
640
|
-
return end_state
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
# def print_java_memory(state):
|
|
644
|
-
# print "\n##### STACK ##########" + "#"*60
|
|
645
|
-
# print state.memory.stack
|
|
646
|
-
# print "\n##### HEAP ###########" + "#"*60
|
|
647
|
-
# print state.memory.heap
|
|
648
|
-
# print "\n##### VM STATIC TABLE " + "#"*60
|
|
649
|
-
# print state.memory.vm_static_table
|
|
650
|
-
# print
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
654
|
-
def create_project(binary_dir, load_native_libs=True):
|
|
655
|
-
jar_path = os.path.join(test_location, binary_dir, "mixedjava.jar")
|
|
656
|
-
if load_native_libs:
|
|
657
|
-
jni_options = {"jni_libs": ["libmixedjava.so"]}
|
|
658
|
-
project = angr.Project(jar_path, main_opts=jni_options)
|
|
659
|
-
else:
|
|
660
|
-
project = angr.Project(jar_path)
|
|
661
|
-
return project
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
def load_string(state, local_name):
|
|
665
|
-
str_ref = load_value_from_stack(state, local_name)
|
|
666
|
-
return state.memory.load(str_ref)
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
def load_value_from_stack(state, symbol_name):
|
|
670
|
-
try:
|
|
671
|
-
return state.memory.stack.load(symbol_name)
|
|
672
|
-
except KeyError:
|
|
673
|
-
return None
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
def get_entry_state_of_method(project, method_fullname):
|
|
677
|
-
# get SootAddressDescriptor of method entry
|
|
678
|
-
soot_method = project.loader.main_object.get_soot_method(method_fullname)
|
|
679
|
-
method = SootMethodDescriptor.from_soot_method(soot_method)
|
|
680
|
-
addr = SootAddressDescriptor(method, 0, 0)
|
|
681
|
-
# create call state
|
|
682
|
-
return project.factory.blank_state(addr=addr, add_options={angr.options.ZERO_FILL_UNCONSTRAINED_MEMORY})
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
def get_last_state_of_method(project, method_fullname):
|
|
686
|
-
state = get_entry_state_of_method(project, method_fullname)
|
|
687
|
-
# run until no successors exists
|
|
688
|
-
# Note: this does not work if conditional branches are present
|
|
689
|
-
states = [state]
|
|
690
|
-
succ = states[-1].step()
|
|
691
|
-
while len(succ.successors) == 1:
|
|
692
|
-
states += succ
|
|
614
|
+
def run_method(self, project, method, assert_locals=None, assertions=None):
|
|
615
|
+
end_state = self.get_last_state_of_method(project, method)
|
|
616
|
+
# print_java_memory(end_state)
|
|
617
|
+
|
|
618
|
+
if assert_locals:
|
|
619
|
+
for symbol_name, assert_value in assert_locals.items():
|
|
620
|
+
symbol = self.load_value_from_stack(end_state, symbol_name)
|
|
621
|
+
val = end_state.solver.eval(symbol)
|
|
622
|
+
assert val == assert_value
|
|
623
|
+
|
|
624
|
+
if assertions:
|
|
625
|
+
for _, test in assertions.items():
|
|
626
|
+
assert test(end_state)
|
|
627
|
+
|
|
628
|
+
return end_state
|
|
629
|
+
|
|
630
|
+
@unittest.skipUnless(pysoot, "pysoot not available")
|
|
631
|
+
def create_project(self, binary_dir, load_native_libs=True):
|
|
632
|
+
jar_path = os.path.join(self.test_location, binary_dir, "mixedjava.jar")
|
|
633
|
+
if load_native_libs:
|
|
634
|
+
jni_options = {"jni_libs": ["libmixedjava.so"]}
|
|
635
|
+
project = angr.Project(jar_path, main_opts=jni_options)
|
|
636
|
+
else:
|
|
637
|
+
project = angr.Project(jar_path)
|
|
638
|
+
return project
|
|
639
|
+
|
|
640
|
+
def load_string(self, state, local_name):
|
|
641
|
+
str_ref = self.load_value_from_stack(state, local_name)
|
|
642
|
+
return state.memory.load(str_ref)
|
|
643
|
+
|
|
644
|
+
def load_value_from_stack(self, state, symbol_name):
|
|
645
|
+
try:
|
|
646
|
+
return state.memory.stack.load(symbol_name)
|
|
647
|
+
except KeyError:
|
|
648
|
+
return None
|
|
649
|
+
|
|
650
|
+
def get_entry_state_of_method(self, project, method_fullname):
|
|
651
|
+
# get SootAddressDescriptor of method entry
|
|
652
|
+
soot_method = project.loader.main_object.get_soot_method(method_fullname)
|
|
653
|
+
method = SootMethodDescriptor.from_soot_method(soot_method)
|
|
654
|
+
addr = SootAddressDescriptor(method, 0, 0)
|
|
655
|
+
# create call state
|
|
656
|
+
return project.factory.blank_state(addr=addr, add_options={angr.options.ZERO_FILL_UNCONSTRAINED_MEMORY})
|
|
657
|
+
|
|
658
|
+
def get_last_state_of_method(self, project, method_fullname):
|
|
659
|
+
state = self.get_entry_state_of_method(project, method_fullname)
|
|
660
|
+
# run until no successors exists
|
|
661
|
+
# Note: this does not work if conditional branches are present
|
|
662
|
+
states = [state]
|
|
693
663
|
succ = states[-1].step()
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
def main():
|
|
726
|
-
for k, v in list(globals().items()):
|
|
727
|
-
if k.startswith("test_") and callable(v):
|
|
728
|
-
v()
|
|
664
|
+
while len(succ.successors) == 1:
|
|
665
|
+
states += succ
|
|
666
|
+
succ = states[-1].step()
|
|
667
|
+
# last state is the 'Terminator' state
|
|
668
|
+
# => return the state before
|
|
669
|
+
return states[-2]
|
|
670
|
+
|
|
671
|
+
def get_winning_paths(self, project, method_fullname):
|
|
672
|
+
state = self.get_entry_state_of_method(project, method_fullname)
|
|
673
|
+
simgr = project.factory.simgr(state)
|
|
674
|
+
simgr.run()
|
|
675
|
+
paths = simgr.deadended
|
|
676
|
+
|
|
677
|
+
# winning paths output a single 'W' on stdout
|
|
678
|
+
winnning_paths = []
|
|
679
|
+
for pp in paths:
|
|
680
|
+
stdout_packets = pp.posix.stdout.content
|
|
681
|
+
read_byte, _ = stdout_packets[0]
|
|
682
|
+
# a winning path is printing 'W'
|
|
683
|
+
pp.solver.add(read_byte == pp.solver.BVV(ord("W"), 8))
|
|
684
|
+
if pp.satisfiable():
|
|
685
|
+
winnning_paths.append(pp)
|
|
686
|
+
|
|
687
|
+
return winnning_paths
|
|
688
|
+
|
|
689
|
+
def get_winning_path(self, project, method_fullname):
|
|
690
|
+
winning_paths = self.get_winning_paths(project, method_fullname)
|
|
691
|
+
assert len(winning_paths) != 0
|
|
692
|
+
assert len(winning_paths) == 1
|
|
693
|
+
return winning_paths[0]
|
|
729
694
|
|
|
730
695
|
|
|
731
696
|
if __name__ == "__main__":
|
|
732
|
-
|
|
733
|
-
# logging.getLogger('cle.backends.soot').setLevel('DEBUG')
|
|
734
|
-
# logging.getLogger('cle.backends.apk').setLevel('DEBUG')
|
|
735
|
-
# logging.getLogger('cle.backends.jar').setLevel('DEBUG')
|
|
736
|
-
|
|
737
|
-
# logging.getLogger("angr").setLevel("DEBUG")
|
|
738
|
-
|
|
739
|
-
# logging.getLogger("angr.state_plugins").setLevel("INFO")
|
|
740
|
-
# logging.getLogger('angr.state_plugins.javavm_memory').setLevel("DEBUG")
|
|
741
|
-
# logging.getLogger('angr.state_plugins.jni_references').setLevel("DEBUG")
|
|
742
|
-
# logging.getLogger("angr.state_plugins.javavm_classloader").setLevel("DEBUG")
|
|
743
|
-
|
|
744
|
-
# logging.getLogger('archinfo.arch_soot').setLevel("DEBUG")
|
|
745
|
-
# logging.getLogger('angr.procedures.java_jni').setLevel("DEBUG")
|
|
746
|
-
# logging.getLogger("angr.sim_procedure").setLevel("DEBUG")
|
|
747
|
-
# logging.getLogger("angr.engines").setLevel("DEBUG")
|
|
748
|
-
# logging.getLogger('angr.simos.JavaVM').setLevel("DEBUG")
|
|
749
|
-
# logging.getLogger('angr.engines.vex').setLevel("DEBUG")
|
|
750
|
-
#
|
|
751
|
-
main()
|
|
697
|
+
unittest.main()
|