angr 9.2.78__py3-none-win_amd64.whl → 9.2.79__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/__main__.py +34 -0
- angr/analyses/cfg/cfg_fast.py +12 -0
- angr/analyses/decompiler/block_simplifier.py +25 -5
- angr/analyses/decompiler/clinic.py +27 -17
- angr/analyses/decompiler/optimization_passes/__init__.py +2 -0
- angr/analyses/decompiler/optimization_passes/engine_base.py +2 -2
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +2 -2
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +105 -12
- angr/analyses/decompiler/peephole_optimizations/__init__.py +11 -2
- angr/analyses/decompiler/peephole_optimizations/base.py +29 -2
- angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +83 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +103 -0
- angr/analyses/decompiler/structured_codegen/c.py +20 -4
- angr/analyses/decompiler/utils.py +128 -2
- angr/analyses/proximity_graph.py +30 -0
- angr/knowledge_plugins/__init__.py +1 -0
- angr/knowledge_plugins/custom_strings.py +40 -0
- angr/knowledge_plugins/functions/function.py +29 -0
- angr/lib/angr_native.dll +0 -0
- angr/procedures/definitions/msvcr.py +0 -3
- angr/sim_type.py +3 -0
- {angr-9.2.78.dist-info → angr-9.2.79.dist-info}/METADATA +6 -6
- {angr-9.2.78.dist-info → angr-9.2.79.dist-info}/RECORD +29 -24
- {angr-9.2.78.dist-info → angr-9.2.79.dist-info}/WHEEL +1 -1
- angr-9.2.79.dist-info/entry_points.txt +2 -0
- {angr-9.2.78.dist-info → angr-9.2.79.dist-info}/LICENSE +0 -0
- {angr-9.2.78.dist-info → angr-9.2.79.dist-info}/top_level.txt +0 -0
angr/__init__.py
CHANGED
angr/__main__.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
from angr.analyses.decompiler.structuring import STRUCTURER_CLASSES
|
|
4
|
+
from angr.analyses.decompiler.utils import decompile_functions
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class COMMANDS:
|
|
8
|
+
"""
|
|
9
|
+
The commands that the angr CLI supports.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
DECOMPILE = "decompile"
|
|
13
|
+
ALL_COMMANDS = [DECOMPILE]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main():
|
|
17
|
+
parser = argparse.ArgumentParser(description="The angr CLI allows you to decompile and analyze binaries.")
|
|
18
|
+
parser.add_argument("command", help="The command to run", choices=COMMANDS.ALL_COMMANDS)
|
|
19
|
+
parser.add_argument("binary", help="The path to the binary to analyze")
|
|
20
|
+
parser.add_argument("--functions", help="The functions to analyze", nargs="+")
|
|
21
|
+
parser.add_argument(
|
|
22
|
+
"--structurer", help="The structurer to use", choices=STRUCTURER_CLASSES.keys(), default="phoenix"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
args = parser.parse_args()
|
|
26
|
+
if args.command == COMMANDS.DECOMPILE:
|
|
27
|
+
decompilation = decompile_functions(args.binary, functions=args.functions, structurer=args.structurer)
|
|
28
|
+
print(decompilation)
|
|
29
|
+
else:
|
|
30
|
+
parser.print_help()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
if __name__ == "__main__":
|
|
34
|
+
main()
|
angr/analyses/cfg/cfg_fast.py
CHANGED
|
@@ -4586,6 +4586,18 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
4586
4586
|
):
|
|
4587
4587
|
rbp_as_gpr = False
|
|
4588
4588
|
break
|
|
4589
|
+
elif (
|
|
4590
|
+
insn.mnemonic == "lea"
|
|
4591
|
+
and len(insn.operands) == 2
|
|
4592
|
+
and insn.operands[0].type == capstone.x86.X86_OP_REG
|
|
4593
|
+
and insn.operands[1].type == capstone.x86.X86_OP_MEM
|
|
4594
|
+
):
|
|
4595
|
+
if (
|
|
4596
|
+
insn.operands[0].reg == capstone.x86.X86_REG_RBP
|
|
4597
|
+
and insn.operands[1].mem.base == capstone.x86.X86_REG_RSP
|
|
4598
|
+
):
|
|
4599
|
+
rbp_as_gpr = False
|
|
4600
|
+
break
|
|
4589
4601
|
func = self.kb.functions.get_by_addr(func_addr)
|
|
4590
4602
|
func.info["bp_as_gpr"] = rbp_as_gpr
|
|
4591
4603
|
|
|
@@ -15,8 +15,15 @@ from ...analyses.propagator import PropagatorAnalysis
|
|
|
15
15
|
from ...analyses.reaching_definitions import ReachingDefinitionsAnalysis
|
|
16
16
|
from ...errors import SimMemoryMissingError
|
|
17
17
|
from .. import Analysis, register_analysis
|
|
18
|
-
from .peephole_optimizations import
|
|
19
|
-
|
|
18
|
+
from .peephole_optimizations import (
|
|
19
|
+
MULTI_STMT_OPTS,
|
|
20
|
+
STMT_OPTS,
|
|
21
|
+
EXPR_OPTS,
|
|
22
|
+
PeepholeOptimizationStmtBase,
|
|
23
|
+
PeepholeOptimizationExprBase,
|
|
24
|
+
PeepholeOptimizationMultiStmtBase,
|
|
25
|
+
)
|
|
26
|
+
from .utils import peephole_optimize_exprs, peephole_optimize_stmts, peephole_optimize_multistmts
|
|
20
27
|
|
|
21
28
|
if TYPE_CHECKING:
|
|
22
29
|
from angr.storage.memory_mixins.paged_memory.pages.multi_values import MultiValues
|
|
@@ -78,6 +85,7 @@ class BlockSimplifier(Analysis):
|
|
|
78
85
|
if peephole_optimizations is None:
|
|
79
86
|
self._expr_peephole_opts = [cls(self.project, self.kb, self.func_addr) for cls in EXPR_OPTS]
|
|
80
87
|
self._stmt_peephole_opts = [cls(self.project, self.kb, self.func_addr) for cls in STMT_OPTS]
|
|
88
|
+
self._multistmt_peephole_opts = [cls(self.project, self.kb, self.func_addr) for cls in MULTI_STMT_OPTS]
|
|
81
89
|
else:
|
|
82
90
|
self._expr_peephole_opts = [
|
|
83
91
|
cls(self.project, self.kb, self.func_addr)
|
|
@@ -89,6 +97,11 @@ class BlockSimplifier(Analysis):
|
|
|
89
97
|
for cls in peephole_optimizations
|
|
90
98
|
if issubclass(cls, PeepholeOptimizationStmtBase)
|
|
91
99
|
]
|
|
100
|
+
self._multistmt_peephole_opts = [
|
|
101
|
+
cls(self.project, self.kb, self.func_addr)
|
|
102
|
+
for cls in peephole_optimizations
|
|
103
|
+
if issubclass(cls, PeepholeOptimizationMultiStmtBase)
|
|
104
|
+
]
|
|
92
105
|
|
|
93
106
|
self.result_block = None
|
|
94
107
|
|
|
@@ -404,9 +417,16 @@ class BlockSimplifier(Analysis):
|
|
|
404
417
|
# run statement-level optimizations
|
|
405
418
|
statements, stmts_updated = peephole_optimize_stmts(block, self._stmt_peephole_opts)
|
|
406
419
|
|
|
407
|
-
if
|
|
408
|
-
|
|
409
|
-
|
|
420
|
+
if stmts_updated:
|
|
421
|
+
new_block = block.copy(statements=statements)
|
|
422
|
+
else:
|
|
423
|
+
new_block = block
|
|
424
|
+
|
|
425
|
+
statements, multi_stmts_updated = peephole_optimize_multistmts(new_block, self._multistmt_peephole_opts)
|
|
426
|
+
|
|
427
|
+
if not multi_stmts_updated:
|
|
428
|
+
return new_block
|
|
429
|
+
new_block = new_block.copy(statements=statements)
|
|
410
430
|
return new_block
|
|
411
431
|
|
|
412
432
|
|
|
@@ -20,6 +20,7 @@ from ...sim_type import (
|
|
|
20
20
|
SimTypeFunction,
|
|
21
21
|
SimTypeBottom,
|
|
22
22
|
SimTypeFloat,
|
|
23
|
+
SimTypePointer,
|
|
23
24
|
)
|
|
24
25
|
from ...sim_variable import SimVariable, SimStackVariable, SimRegisterVariable, SimMemoryVariable
|
|
25
26
|
from ...knowledge_plugins.key_definitions.constants import OP_BEFORE
|
|
@@ -1247,23 +1248,32 @@ class Clinic(Analysis):
|
|
|
1247
1248
|
expr.variable_offset = offset
|
|
1248
1249
|
|
|
1249
1250
|
elif isinstance(expr, ailment.Expr.Const):
|
|
1250
|
-
#
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1251
|
+
# custom string?
|
|
1252
|
+
if hasattr(expr, "custom_string") and expr.custom_string is True:
|
|
1253
|
+
s = self.kb.custom_strings[expr.value]
|
|
1254
|
+
expr.tags["reference_values"] = {
|
|
1255
|
+
SimTypePointer(SimTypeChar().with_arch(self.project.arch)).with_arch(self.project.arch): s.decode(
|
|
1256
|
+
"ascii"
|
|
1257
|
+
),
|
|
1258
|
+
}
|
|
1259
|
+
else:
|
|
1260
|
+
# global variable?
|
|
1261
|
+
global_vars = global_variables.get_global_variables(expr.value)
|
|
1262
|
+
if not global_vars:
|
|
1263
|
+
# detect if there is a related symbol
|
|
1264
|
+
if self.project.loader.find_object_containing(expr.value):
|
|
1265
|
+
symbol = self.project.loader.find_symbol(expr.value)
|
|
1266
|
+
if symbol is not None:
|
|
1267
|
+
# Create a new global variable if there isn't one already
|
|
1268
|
+
global_vars = global_variables.get_global_variables(symbol.rebased_addr)
|
|
1269
|
+
if not global_vars:
|
|
1270
|
+
global_var = SimMemoryVariable(symbol.rebased_addr, symbol.size, name=symbol.name)
|
|
1271
|
+
global_variables.add_variable("global", global_var.addr, global_var)
|
|
1272
|
+
global_vars = {global_var}
|
|
1273
|
+
if global_vars:
|
|
1274
|
+
global_var = next(iter(global_vars))
|
|
1275
|
+
expr.tags["reference_variable"] = global_var
|
|
1276
|
+
expr.tags["reference_variable_offset"] = 0
|
|
1267
1277
|
|
|
1268
1278
|
elif isinstance(expr, ailment.Stmt.Call):
|
|
1269
1279
|
self._link_variables_on_call(variable_manager, global_variables, block, stmt_idx, expr, is_expr=True)
|
|
@@ -89,7 +89,7 @@ class SimplifierAILEngine(
|
|
|
89
89
|
if hasattr(self, handler):
|
|
90
90
|
return getattr(self, handler)(stmt)
|
|
91
91
|
else:
|
|
92
|
-
_l.
|
|
92
|
+
_l.debug("Unsupported statement type %s.", type(stmt).__name__)
|
|
93
93
|
return stmt
|
|
94
94
|
|
|
95
95
|
def _ail_handle_Assignment(self, stmt):
|
|
@@ -176,7 +176,7 @@ class SimplifierAILEngine(
|
|
|
176
176
|
if v is None:
|
|
177
177
|
return expr
|
|
178
178
|
return v
|
|
179
|
-
_l.
|
|
179
|
+
_l.debug("Unsupported expression type %s.", type(expr).__name__)
|
|
180
180
|
return expr
|
|
181
181
|
|
|
182
182
|
def _ail_handle_StackBaseOffset(self, expr): # pylint:disable=no-self-use
|
|
@@ -84,9 +84,9 @@ class ITERegionConverter(OptimizationPass):
|
|
|
84
84
|
|
|
85
85
|
true_child, false_child = None, None
|
|
86
86
|
for child in children:
|
|
87
|
-
if child.addr == if_stmt.true_target.value:
|
|
87
|
+
if if_stmt.true_target is not None and child.addr == if_stmt.true_target.value:
|
|
88
88
|
true_child = child
|
|
89
|
-
elif child.addr == if_stmt.false_target.value:
|
|
89
|
+
elif if_stmt.false_target is not None and child.addr == if_stmt.false_target.value:
|
|
90
90
|
false_child = child
|
|
91
91
|
|
|
92
92
|
if (
|
|
@@ -3,6 +3,7 @@ from typing import Set, Dict
|
|
|
3
3
|
from collections import defaultdict
|
|
4
4
|
import logging
|
|
5
5
|
|
|
6
|
+
import capstone
|
|
6
7
|
import ailment
|
|
7
8
|
import cle
|
|
8
9
|
|
|
@@ -48,24 +49,24 @@ class WinStackCanarySimplifier(OptimizationPass):
|
|
|
48
49
|
return False, None
|
|
49
50
|
|
|
50
51
|
# Check the first block and see if there is any statement reading data from _security_cookie
|
|
51
|
-
|
|
52
|
+
init_stmts = self._find_canary_init_stmt()
|
|
52
53
|
|
|
53
|
-
return
|
|
54
|
+
return init_stmts is not None, {"init_stmts": init_stmts}
|
|
54
55
|
|
|
55
56
|
def _analyze(self, cache=None):
|
|
56
|
-
|
|
57
|
+
init_stmts = None
|
|
57
58
|
if cache is not None:
|
|
58
|
-
|
|
59
|
+
init_stmts = cache.get("init_stmts", None)
|
|
59
60
|
|
|
60
|
-
if
|
|
61
|
-
|
|
61
|
+
if init_stmts is None:
|
|
62
|
+
init_stmts = self._find_canary_init_stmt()
|
|
62
63
|
|
|
63
|
-
if
|
|
64
|
+
if init_stmts is None:
|
|
64
65
|
return
|
|
65
66
|
|
|
66
67
|
# Look for the statement that loads back canary value from the stack
|
|
67
|
-
first_block,
|
|
68
|
-
canary_init_stmt = first_block.statements[
|
|
68
|
+
first_block, canary_init_stmt_ids = init_stmts
|
|
69
|
+
canary_init_stmt = first_block.statements[canary_init_stmt_ids[-1]]
|
|
69
70
|
# where is the stack canary stored?
|
|
70
71
|
if not isinstance(canary_init_stmt.addr, ailment.Expr.StackBaseOffset):
|
|
71
72
|
_l.debug(
|
|
@@ -142,7 +143,8 @@ class WinStackCanarySimplifier(OptimizationPass):
|
|
|
142
143
|
if found_endpoints:
|
|
143
144
|
# Remove the statement that loads the stack canary from fs
|
|
144
145
|
first_block_copy = first_block.copy()
|
|
145
|
-
|
|
146
|
+
for stmt_idx in sorted(canary_init_stmt_ids, reverse=True):
|
|
147
|
+
first_block_copy.statements.pop(stmt_idx)
|
|
146
148
|
self._update_block(first_block, first_block_copy)
|
|
147
149
|
|
|
148
150
|
def _find_canary_init_stmt(self):
|
|
@@ -150,7 +152,13 @@ class WinStackCanarySimplifier(OptimizationPass):
|
|
|
150
152
|
if first_block is None:
|
|
151
153
|
return None
|
|
152
154
|
|
|
155
|
+
load_stmt_idx = None
|
|
156
|
+
load_reg = None
|
|
157
|
+
xor_stmt_idx = None
|
|
158
|
+
xored_reg = None
|
|
159
|
+
|
|
153
160
|
for idx, stmt in enumerate(first_block.statements):
|
|
161
|
+
# if we are lucky and things get folded into one statement:
|
|
154
162
|
if (
|
|
155
163
|
isinstance(stmt, ailment.Stmt.Store)
|
|
156
164
|
and isinstance(stmt.addr, ailment.Expr.StackBaseOffset)
|
|
@@ -163,13 +171,51 @@ class WinStackCanarySimplifier(OptimizationPass):
|
|
|
163
171
|
# Check addr: must be __security_cookie
|
|
164
172
|
load_addr = stmt.data.operands[0].addr.value
|
|
165
173
|
if load_addr == self._security_cookie_addr:
|
|
166
|
-
return first_block, idx
|
|
174
|
+
return first_block, [idx]
|
|
175
|
+
# or if we are unlucky and the load and the xor are two different statements
|
|
176
|
+
if (
|
|
177
|
+
isinstance(stmt, ailment.Stmt.Assignment)
|
|
178
|
+
and isinstance(stmt.dst, ailment.Expr.Register)
|
|
179
|
+
and isinstance(stmt.src, ailment.Expr.Load)
|
|
180
|
+
and isinstance(stmt.src.addr, ailment.Expr.Const)
|
|
181
|
+
):
|
|
182
|
+
load_addr = stmt.src.addr.value
|
|
183
|
+
if load_addr == self._security_cookie_addr:
|
|
184
|
+
load_stmt_idx = idx
|
|
185
|
+
load_reg = stmt.dst.reg_offset
|
|
186
|
+
if load_stmt_idx is not None and idx == load_stmt_idx + 1:
|
|
187
|
+
if (
|
|
188
|
+
isinstance(stmt, ailment.Stmt.Assignment)
|
|
189
|
+
and isinstance(stmt.dst, ailment.Expr.Register)
|
|
190
|
+
and isinstance(stmt.src, ailment.Expr.BinaryOp)
|
|
191
|
+
and stmt.src.op == "Xor"
|
|
192
|
+
and isinstance(stmt.src.operands[0], ailment.Expr.Register)
|
|
193
|
+
and stmt.src.operands[0].reg_offset == load_reg
|
|
194
|
+
and isinstance(stmt.src.operands[1], ailment.Expr.StackBaseOffset)
|
|
195
|
+
):
|
|
196
|
+
xor_stmt_idx = idx
|
|
197
|
+
xored_reg = stmt.dst.reg_offset
|
|
198
|
+
else:
|
|
199
|
+
break
|
|
200
|
+
if xor_stmt_idx is not None and idx == xor_stmt_idx + 1:
|
|
201
|
+
if (
|
|
202
|
+
isinstance(stmt, ailment.Stmt.Store)
|
|
203
|
+
and isinstance(stmt.addr, ailment.Expr.StackBaseOffset)
|
|
204
|
+
and isinstance(stmt.data, ailment.Expr.Register)
|
|
205
|
+
and stmt.data.reg_offset == xored_reg
|
|
206
|
+
):
|
|
207
|
+
return first_block, [load_stmt_idx, xor_stmt_idx, idx]
|
|
208
|
+
else:
|
|
209
|
+
break
|
|
167
210
|
|
|
168
211
|
return None
|
|
169
212
|
|
|
170
213
|
@staticmethod
|
|
171
214
|
def _find_amd64_canary_storing_stmt(block, canary_value_stack_offset):
|
|
215
|
+
load_stmt_idx = None
|
|
216
|
+
|
|
172
217
|
for idx, stmt in enumerate(block.statements):
|
|
218
|
+
# when we are lucky, we have one instruction
|
|
173
219
|
if (
|
|
174
220
|
isinstance(stmt, ailment.Stmt.Assignment)
|
|
175
221
|
and isinstance(stmt.dst, ailment.Expr.Register)
|
|
@@ -185,7 +231,29 @@ class WinStackCanarySimplifier(OptimizationPass):
|
|
|
185
231
|
if isinstance(op1, ailment.Expr.StackBaseOffset):
|
|
186
232
|
# found it
|
|
187
233
|
return idx
|
|
188
|
-
|
|
234
|
+
# or when we are unlucky, we have two instructions...
|
|
235
|
+
if (
|
|
236
|
+
isinstance(stmt, ailment.Stmt.Assignment)
|
|
237
|
+
and isinstance(stmt.dst, ailment.Expr.Register)
|
|
238
|
+
and stmt.dst.reg_name == "rcx"
|
|
239
|
+
and isinstance(stmt.src, ailment.Expr.Load)
|
|
240
|
+
and isinstance(stmt.src.addr, ailment.Expr.StackBaseOffset)
|
|
241
|
+
and stmt.src.addr.offset == canary_value_stack_offset
|
|
242
|
+
):
|
|
243
|
+
load_stmt_idx = idx
|
|
244
|
+
if load_stmt_idx is not None and idx == load_stmt_idx + 1:
|
|
245
|
+
if (
|
|
246
|
+
isinstance(stmt, ailment.Stmt.Assignment)
|
|
247
|
+
and isinstance(stmt.dst, ailment.Expr.Register)
|
|
248
|
+
and isinstance(stmt.src, ailment.Expr.BinaryOp)
|
|
249
|
+
and stmt.src.op == "Xor"
|
|
250
|
+
):
|
|
251
|
+
if (
|
|
252
|
+
isinstance(stmt.src.operands[0], ailment.Expr.Register)
|
|
253
|
+
and stmt.src.operands[0].reg_name == "rcx"
|
|
254
|
+
and isinstance(stmt.src.operands[1], ailment.Expr.StackBaseOffset)
|
|
255
|
+
):
|
|
256
|
+
return idx
|
|
189
257
|
return None
|
|
190
258
|
|
|
191
259
|
@staticmethod
|
|
@@ -200,6 +268,29 @@ class WinStackCanarySimplifier(OptimizationPass):
|
|
|
200
268
|
return idx
|
|
201
269
|
return None
|
|
202
270
|
|
|
271
|
+
def _is_function_likely_security_check_cookie(self, func) -> bool:
|
|
272
|
+
# disassemble the first instruction
|
|
273
|
+
if func.is_plt or func.is_syscall or func.is_simprocedure:
|
|
274
|
+
return False
|
|
275
|
+
block = self.project.factory.block(func.addr)
|
|
276
|
+
if block.instructions != 2:
|
|
277
|
+
return False
|
|
278
|
+
ins0 = block.capstone.insns[0]
|
|
279
|
+
if (
|
|
280
|
+
ins0.mnemonic == "cmp"
|
|
281
|
+
and len(ins0.operands) == 2
|
|
282
|
+
and ins0.operands[0].type == capstone.x86.X86_OP_REG
|
|
283
|
+
and ins0.operands[0].reg == capstone.x86.X86_REG_RCX
|
|
284
|
+
and ins0.operands[1].type == capstone.x86.X86_OP_MEM
|
|
285
|
+
and ins0.operands[1].mem.base == capstone.x86.X86_REG_RIP
|
|
286
|
+
and ins0.operands[1].mem.index == 0
|
|
287
|
+
and ins0.operands[1].mem.disp + ins0.address + ins0.size == self._security_cookie_addr
|
|
288
|
+
):
|
|
289
|
+
ins1 = block.capstone.insns[1]
|
|
290
|
+
if ins1.mnemonic == "jne":
|
|
291
|
+
return True
|
|
292
|
+
return False
|
|
293
|
+
|
|
203
294
|
def _find_stmt_calling_security_check_cookie(self, node):
|
|
204
295
|
for idx, stmt in enumerate(node.statements):
|
|
205
296
|
if isinstance(stmt, ailment.Stmt.Call) and isinstance(stmt.target, ailment.Expr.Const):
|
|
@@ -208,5 +299,7 @@ class WinStackCanarySimplifier(OptimizationPass):
|
|
|
208
299
|
func = self.kb.functions.function(addr=const_target)
|
|
209
300
|
if func.name == "_security_check_cookie":
|
|
210
301
|
return idx
|
|
302
|
+
elif self._is_function_likely_security_check_cookie(func):
|
|
303
|
+
return idx
|
|
211
304
|
|
|
212
305
|
return None
|
|
@@ -40,10 +40,12 @@ from .sar_to_signed_div import SarToSignedDiv
|
|
|
40
40
|
from .tidy_stack_addr import TidyStackAddr
|
|
41
41
|
from .invert_negated_logical_conjuction_disjunction import InvertNegatedLogicalConjunctionsAndDisjunctions
|
|
42
42
|
from .rol_ror import RolRorRewriter
|
|
43
|
+
from .inlined_strcpy import InlinedStrcpy
|
|
44
|
+
from .inlined_strcpy_consolidation import InlinedStrcpyConsolidation
|
|
43
45
|
|
|
44
|
-
from .base import PeepholeOptimizationExprBase, PeepholeOptimizationStmtBase
|
|
45
|
-
|
|
46
|
+
from .base import PeepholeOptimizationExprBase, PeepholeOptimizationStmtBase, PeepholeOptimizationMultiStmtBase
|
|
46
47
|
|
|
48
|
+
MULTI_STMT_OPTS: List[Type[PeepholeOptimizationMultiStmtBase]] = []
|
|
47
49
|
STMT_OPTS: List[Type[PeepholeOptimizationStmtBase]] = []
|
|
48
50
|
EXPR_OPTS: List[Type[PeepholeOptimizationExprBase]] = []
|
|
49
51
|
|
|
@@ -55,4 +57,11 @@ for v in _g.values():
|
|
|
55
57
|
if isinstance(v, type) and issubclass(v, PeepholeOptimizationStmtBase) and v is not PeepholeOptimizationStmtBase:
|
|
56
58
|
STMT_OPTS.append(v)
|
|
57
59
|
|
|
60
|
+
if (
|
|
61
|
+
isinstance(v, type)
|
|
62
|
+
and issubclass(v, PeepholeOptimizationMultiStmtBase)
|
|
63
|
+
and v is not PeepholeOptimizationMultiStmtBase
|
|
64
|
+
):
|
|
65
|
+
MULTI_STMT_OPTS.append(v)
|
|
66
|
+
|
|
58
67
|
_g = None
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from typing import Optional
|
|
1
|
+
from typing import List, Optional
|
|
2
2
|
|
|
3
3
|
from ailment.expression import BinaryOp, UnaryOp, Expression
|
|
4
|
-
from ailment.statement import Assignment
|
|
4
|
+
from ailment.statement import Statement, Assignment
|
|
5
5
|
from ailment import Block
|
|
6
6
|
from angr.project import Project
|
|
7
7
|
from angr.knowledge_base import KnowledgeBase
|
|
@@ -34,6 +34,33 @@ class PeepholeOptimizationStmtBase:
|
|
|
34
34
|
raise NotImplementedError("_optimize() is not implemented.")
|
|
35
35
|
|
|
36
36
|
|
|
37
|
+
class PeepholeOptimizationMultiStmtBase:
|
|
38
|
+
"""
|
|
39
|
+
The base class for all peephole optimizations that are applied on multiple AIL statements at once.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
__slots__ = (
|
|
43
|
+
"project",
|
|
44
|
+
"kb",
|
|
45
|
+
"func_addr",
|
|
46
|
+
)
|
|
47
|
+
project: Optional[Project]
|
|
48
|
+
kb: Optional[KnowledgeBase]
|
|
49
|
+
func_addr: Optional[int]
|
|
50
|
+
|
|
51
|
+
NAME = "Peephole Optimization - Multi-statement"
|
|
52
|
+
DESCRIPTION = "Peephole Optimization - Multi-statement"
|
|
53
|
+
stmt_classes = None
|
|
54
|
+
|
|
55
|
+
def __init__(self, project: Optional[Project], kb: Optional[KnowledgeBase], func_addr: Optional[int] = None):
|
|
56
|
+
self.project = project
|
|
57
|
+
self.kb = kb
|
|
58
|
+
self.func_addr = func_addr
|
|
59
|
+
|
|
60
|
+
def optimize(self, stmts: List[Statement], stmt_idx: Optional[int] = None, block=None, **kwargs):
|
|
61
|
+
raise NotImplementedError("_optimize() is not implemented.")
|
|
62
|
+
|
|
63
|
+
|
|
37
64
|
class PeepholeOptimizationExprBase:
|
|
38
65
|
"""
|
|
39
66
|
The base class for all peephole optimizations that are applied on AIL expressions.
|
|
@@ -20,7 +20,7 @@ class ConstantDereferences(PeepholeOptimizationExprBase):
|
|
|
20
20
|
if sec is not None and sec.is_readable and (not sec.is_writable or "got" in sec.name):
|
|
21
21
|
# do we know the value that it's reading?
|
|
22
22
|
try:
|
|
23
|
-
val = self.project.loader.memory.unpack_word(expr.addr.value, size=
|
|
23
|
+
val = self.project.loader.memory.unpack_word(expr.addr.value, size=expr.size)
|
|
24
24
|
except KeyError:
|
|
25
25
|
return expr
|
|
26
26
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# pylint:disable=arguments-differ
|
|
2
|
+
from typing import Tuple, Optional
|
|
3
|
+
import string
|
|
4
|
+
|
|
5
|
+
from archinfo import Endness
|
|
6
|
+
|
|
7
|
+
from ailment.expression import Const
|
|
8
|
+
from ailment.statement import Call, Store
|
|
9
|
+
|
|
10
|
+
from .base import PeepholeOptimizationStmtBase
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
ASCII_PRINTABLES = set(string.printable)
|
|
14
|
+
ASCII_DIGITS = set(string.digits)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class InlinedStrcpy(PeepholeOptimizationStmtBase):
|
|
18
|
+
"""
|
|
19
|
+
Simplifies inlined string copying logic into calls to strcpy.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
__slots__ = ()
|
|
23
|
+
|
|
24
|
+
NAME = "Simplifying inlined strcpy"
|
|
25
|
+
stmt_classes = (Store,)
|
|
26
|
+
|
|
27
|
+
def optimize(self, stmt: Store, **kwargs):
|
|
28
|
+
if isinstance(stmt.data, Const):
|
|
29
|
+
r, s = self.is_integer_likely_a_string(stmt.data.value, stmt.data.size, stmt.endness)
|
|
30
|
+
if r:
|
|
31
|
+
# replace it with a call to strncpy
|
|
32
|
+
str_id = self.kb.custom_strings.allocate(s.encode("ascii"))
|
|
33
|
+
return Call(
|
|
34
|
+
stmt.idx,
|
|
35
|
+
"strncpy",
|
|
36
|
+
args=[
|
|
37
|
+
stmt.addr,
|
|
38
|
+
Const(None, None, str_id, stmt.addr.bits, custom_string=True),
|
|
39
|
+
Const(None, None, len(s), self.project.arch.bits),
|
|
40
|
+
],
|
|
41
|
+
**stmt.tags,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
@staticmethod
|
|
47
|
+
def is_integer_likely_a_string(
|
|
48
|
+
v: int, size: int, endness: Endness, min_length: int = 4
|
|
49
|
+
) -> Tuple[bool, Optional[str]]:
|
|
50
|
+
# we need at least four bytes of printable characters
|
|
51
|
+
|
|
52
|
+
chars = []
|
|
53
|
+
if endness == Endness.LE:
|
|
54
|
+
while v != 0:
|
|
55
|
+
byt = v & 0xFF
|
|
56
|
+
if chr(byt) not in ASCII_PRINTABLES:
|
|
57
|
+
return False, None
|
|
58
|
+
chars.append(chr(byt))
|
|
59
|
+
v >>= 8
|
|
60
|
+
|
|
61
|
+
elif endness == Endness.BE:
|
|
62
|
+
first_non_zero = False
|
|
63
|
+
for _ in range(size):
|
|
64
|
+
byt = v & 0xFF
|
|
65
|
+
v >>= 8
|
|
66
|
+
if byt == 0:
|
|
67
|
+
if first_non_zero:
|
|
68
|
+
return False, None
|
|
69
|
+
continue
|
|
70
|
+
first_non_zero = True # this is the first non-zero byte
|
|
71
|
+
if chr(byt) not in ASCII_PRINTABLES:
|
|
72
|
+
return False, None
|
|
73
|
+
chars.append(chr(byt))
|
|
74
|
+
chars = chars[::-1]
|
|
75
|
+
else:
|
|
76
|
+
# unsupported endness
|
|
77
|
+
return False, None
|
|
78
|
+
|
|
79
|
+
if len(chars) >= min_length:
|
|
80
|
+
if len(chars) <= 4 and all(ch in ASCII_DIGITS for ch in chars):
|
|
81
|
+
return False, None
|
|
82
|
+
return True, "".join(chars)
|
|
83
|
+
return False, None
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# pylint:disable=arguments-differ
|
|
2
|
+
from typing import List, Tuple, Optional
|
|
3
|
+
|
|
4
|
+
from ailment.expression import Expression, BinaryOp, Const, Register, StackBaseOffset
|
|
5
|
+
from ailment.statement import Call, Store
|
|
6
|
+
|
|
7
|
+
from .base import PeepholeOptimizationMultiStmtBase
|
|
8
|
+
from .inlined_strcpy import InlinedStrcpy
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class InlinedStrcpyConsolidation(PeepholeOptimizationMultiStmtBase):
|
|
12
|
+
"""
|
|
13
|
+
Consolidate multiple inlined strcpy calls.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
__slots__ = ()
|
|
17
|
+
|
|
18
|
+
NAME = "Consolidate multiple inlined strcpy calls"
|
|
19
|
+
stmt_classes = ((Call, Call), (Call, Store))
|
|
20
|
+
|
|
21
|
+
def optimize(self, stmts: List[Call], **kwargs):
|
|
22
|
+
last_stmt, stmt = stmts
|
|
23
|
+
if InlinedStrcpyConsolidation._is_inlined_strcpy(last_stmt):
|
|
24
|
+
s_last: bytes = self.kb.custom_strings[last_stmt.args[1].value]
|
|
25
|
+
addr_last = last_stmt.args[0]
|
|
26
|
+
new_str = None # will be set if consolidation should happen
|
|
27
|
+
|
|
28
|
+
if isinstance(stmt, Call) and InlinedStrcpyConsolidation._is_inlined_strcpy(stmt):
|
|
29
|
+
# consolidating two calls
|
|
30
|
+
s_curr: bytes = self.kb.custom_strings[stmt.args[1].value]
|
|
31
|
+
addr_curr = stmt.args[0]
|
|
32
|
+
# determine if the two addresses are consecutive
|
|
33
|
+
delta = self._get_delta(addr_last, addr_curr)
|
|
34
|
+
if delta is not None and delta == len(s_last):
|
|
35
|
+
# consolidate both calls!
|
|
36
|
+
new_str = s_last + s_curr
|
|
37
|
+
elif isinstance(stmt, Store) and isinstance(stmt.data, Const):
|
|
38
|
+
# consolidating a call and a store, in case the store statement is storing the suffix of a string (but
|
|
39
|
+
# the suffix is too short to qualify an inlined strcpy optimization)
|
|
40
|
+
addr_curr = stmt.addr
|
|
41
|
+
delta = self._get_delta(addr_last, addr_curr)
|
|
42
|
+
if delta is not None and delta == len(s_last):
|
|
43
|
+
if stmt.size == 1 and stmt.data.value == 0:
|
|
44
|
+
# it's probably the terminating null byte
|
|
45
|
+
r, s = True, "\x00"
|
|
46
|
+
else:
|
|
47
|
+
r, s = InlinedStrcpy.is_integer_likely_a_string(
|
|
48
|
+
stmt.data.value, stmt.size, stmt.endness, min_length=1
|
|
49
|
+
)
|
|
50
|
+
if r:
|
|
51
|
+
new_str = s_last + s.encode("ascii")
|
|
52
|
+
|
|
53
|
+
if new_str is not None:
|
|
54
|
+
if new_str.endswith(b"\x00"):
|
|
55
|
+
call_name = "strcpy"
|
|
56
|
+
new_str_idx = self.kb.custom_strings.allocate(new_str[:-1])
|
|
57
|
+
args = [
|
|
58
|
+
last_stmt.args[0],
|
|
59
|
+
Const(None, None, new_str_idx, last_stmt.args[0].bits, custom_string=True),
|
|
60
|
+
]
|
|
61
|
+
else:
|
|
62
|
+
call_name = "strncpy"
|
|
63
|
+
new_str_idx = self.kb.custom_strings.allocate(new_str)
|
|
64
|
+
args = [
|
|
65
|
+
last_stmt.args[0],
|
|
66
|
+
Const(None, None, new_str_idx, last_stmt.args[0].bits, custom_string=True),
|
|
67
|
+
Const(None, None, len(new_str), self.project.arch.bits),
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
return [Call(stmt.idx, call_name, args=args, **stmt.tags)]
|
|
71
|
+
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
@staticmethod
|
|
75
|
+
def _is_inlined_strcpy(stmt: Call):
|
|
76
|
+
if isinstance(stmt.target, str) and stmt.target == "strncpy":
|
|
77
|
+
if len(stmt.args) == 3 and isinstance(stmt.args[1], Const) and hasattr(stmt.args[1], "custom_string"):
|
|
78
|
+
return True
|
|
79
|
+
return False
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def _parse_addr(addr: Expression) -> Tuple[Expression, int]:
|
|
83
|
+
if isinstance(addr, Register):
|
|
84
|
+
return addr, 0
|
|
85
|
+
if isinstance(addr, StackBaseOffset):
|
|
86
|
+
return StackBaseOffset(None, addr.bits, 0), addr.offset
|
|
87
|
+
if isinstance(addr, BinaryOp):
|
|
88
|
+
if addr.op == "Add" and isinstance(addr.operands[1], Const):
|
|
89
|
+
base_0, offset_0 = InlinedStrcpyConsolidation._parse_addr(addr.operands[0])
|
|
90
|
+
return base_0, offset_0 + addr.operands[1].value
|
|
91
|
+
if addr.op == "Sub" and isinstance(addr.operands[1], Const):
|
|
92
|
+
base_0, offset_0 = InlinedStrcpyConsolidation._parse_addr(addr.operands[0])
|
|
93
|
+
return base_0, offset_0 - addr.operands[1].value
|
|
94
|
+
|
|
95
|
+
return addr, 0
|
|
96
|
+
|
|
97
|
+
@staticmethod
|
|
98
|
+
def _get_delta(addr_0: Expression, addr_1: Expression) -> Optional[int]:
|
|
99
|
+
base_0, offset_0 = InlinedStrcpyConsolidation._parse_addr(addr_0)
|
|
100
|
+
base_1, offset_1 = InlinedStrcpyConsolidation._parse_addr(addr_1)
|
|
101
|
+
if base_0.likes(base_1):
|
|
102
|
+
return offset_1 - offset_0
|
|
103
|
+
return None
|
|
@@ -2037,11 +2037,22 @@ class CConstant(CExpression):
|
|
|
2037
2037
|
return
|
|
2038
2038
|
yield hex(self.reference_values[self._type]), self
|
|
2039
2039
|
elif isinstance(self._type, SimTypePointer) and isinstance(self._type.pts_to, SimTypeChar):
|
|
2040
|
-
refval = self.reference_values[self._type]
|
|
2041
|
-
|
|
2040
|
+
refval = self.reference_values[self._type]
|
|
2041
|
+
if isinstance(refval, MemoryData):
|
|
2042
|
+
v = refval.content.decode("utf-8")
|
|
2043
|
+
else:
|
|
2044
|
+
# it's a string
|
|
2045
|
+
assert isinstance(v, str)
|
|
2046
|
+
v = refval
|
|
2047
|
+
yield CConstant.str_to_c_str(v), self
|
|
2042
2048
|
elif isinstance(self._type, SimTypePointer) and isinstance(self._type.pts_to, SimTypeWideChar):
|
|
2043
|
-
refval = self.reference_values[self._type]
|
|
2044
|
-
|
|
2049
|
+
refval = self.reference_values[self._type]
|
|
2050
|
+
if isinstance(refval, MemoryData):
|
|
2051
|
+
v = refval.content.decode("utf_16_le")
|
|
2052
|
+
else:
|
|
2053
|
+
# it's a string
|
|
2054
|
+
v = refval
|
|
2055
|
+
yield CConstant.str_to_c_str(v, prefix="L"), self
|
|
2045
2056
|
else:
|
|
2046
2057
|
if isinstance(self.reference_values[self._type], int):
|
|
2047
2058
|
yield self.fmt_int(self.reference_values[self._type]), self
|
|
@@ -3199,6 +3210,11 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3199
3210
|
inline_string = False
|
|
3200
3211
|
function_pointer = False
|
|
3201
3212
|
|
|
3213
|
+
if reference_values is None and hasattr(expr, "reference_values"):
|
|
3214
|
+
reference_values = expr.reference_values.copy()
|
|
3215
|
+
if reference_values:
|
|
3216
|
+
type_ = next(iter(reference_values))
|
|
3217
|
+
|
|
3202
3218
|
if reference_values is None:
|
|
3203
3219
|
reference_values = {}
|
|
3204
3220
|
type_ = unpack_typeref(type_)
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
from typing import Optional, Tuple, Any, Union, List
|
|
1
|
+
import pathlib
|
|
2
|
+
from typing import Optional, Tuple, Any, Union, List, Iterable
|
|
3
|
+
import logging
|
|
3
4
|
|
|
4
5
|
import networkx
|
|
6
|
+
from rich.progress import track
|
|
5
7
|
|
|
6
8
|
import ailment
|
|
9
|
+
import angr
|
|
10
|
+
|
|
11
|
+
_l = logging.getLogger(__name__)
|
|
7
12
|
|
|
8
13
|
|
|
9
14
|
def remove_last_statement(node):
|
|
@@ -533,6 +538,127 @@ def peephole_optimize_stmts(block, stmt_opts):
|
|
|
533
538
|
return statements, any_update
|
|
534
539
|
|
|
535
540
|
|
|
541
|
+
def match_stmt_classes(all_stmts: List, idx: int, stmt_class_seq: Iterable[type]) -> bool:
|
|
542
|
+
for i, cls in enumerate(stmt_class_seq):
|
|
543
|
+
if idx + i >= len(all_stmts):
|
|
544
|
+
return False
|
|
545
|
+
if not isinstance(all_stmts[idx + i], cls):
|
|
546
|
+
return False
|
|
547
|
+
return True
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
def peephole_optimize_multistmts(block, stmt_opts):
|
|
551
|
+
any_update = False
|
|
552
|
+
statements = block.statements[::]
|
|
553
|
+
|
|
554
|
+
# run multi-statement optimizers
|
|
555
|
+
stmt_idx = 0
|
|
556
|
+
while stmt_idx < len(statements):
|
|
557
|
+
redo = True
|
|
558
|
+
while redo and stmt_idx < len(statements):
|
|
559
|
+
redo = False
|
|
560
|
+
for opt in stmt_opts:
|
|
561
|
+
matched = False
|
|
562
|
+
stmt_seq_len = None
|
|
563
|
+
for stmt_class_seq in opt.stmt_classes:
|
|
564
|
+
if match_stmt_classes(statements, stmt_idx, stmt_class_seq):
|
|
565
|
+
stmt_seq_len = len(stmt_class_seq)
|
|
566
|
+
matched = True
|
|
567
|
+
break
|
|
568
|
+
|
|
569
|
+
if matched:
|
|
570
|
+
matched_stmts = statements[stmt_idx : stmt_idx + stmt_seq_len]
|
|
571
|
+
r = opt.optimize(matched_stmts, stmt_idx=stmt_idx, block=block)
|
|
572
|
+
if r is not None:
|
|
573
|
+
# update statements
|
|
574
|
+
statements = statements[:stmt_idx] + r + statements[stmt_idx + stmt_seq_len :]
|
|
575
|
+
any_update = True
|
|
576
|
+
redo = True
|
|
577
|
+
break
|
|
578
|
+
|
|
579
|
+
# move on to the next statement
|
|
580
|
+
stmt_idx += 1
|
|
581
|
+
|
|
582
|
+
return statements, any_update
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
def decompile_functions(path, functions=None, structurer=None, catch_errors=True) -> Optional[str]:
|
|
586
|
+
"""
|
|
587
|
+
Decompile a binary into a set of functions.
|
|
588
|
+
|
|
589
|
+
:param path: The path to the binary to decompile.
|
|
590
|
+
:param functions: The functions to decompile. If None, all functions will be decompiled.
|
|
591
|
+
:param structurer: The structuring algorithms to use.
|
|
592
|
+
:param catch_errors: The structuring algorithms to use.
|
|
593
|
+
:return: The decompilation of all functions appended in order.
|
|
594
|
+
"""
|
|
595
|
+
# delayed imports to avoid circular imports
|
|
596
|
+
from angr.analyses.decompiler.decompilation_options import PARAM_TO_OPTION
|
|
597
|
+
|
|
598
|
+
structurer = structurer or "phoenix"
|
|
599
|
+
path = pathlib.Path(path).resolve().absolute()
|
|
600
|
+
proj = angr.Project(path, auto_load_libs=False)
|
|
601
|
+
cfg = proj.analyses.CFG(normalize=True, data_references=True)
|
|
602
|
+
proj.analyses.CompleteCallingConventions(recover_variables=True, analyze_callsites=True)
|
|
603
|
+
|
|
604
|
+
# collect all functions when None are provided
|
|
605
|
+
if functions is None:
|
|
606
|
+
functions = cfg.functions.values()
|
|
607
|
+
|
|
608
|
+
# normalize the functions that could be ints as names
|
|
609
|
+
normalized_functions = []
|
|
610
|
+
for func in functions:
|
|
611
|
+
try:
|
|
612
|
+
normalized_name = int(func, 0)
|
|
613
|
+
except ValueError:
|
|
614
|
+
normalized_name = func
|
|
615
|
+
normalized_functions.append(normalized_name)
|
|
616
|
+
functions = normalized_functions
|
|
617
|
+
|
|
618
|
+
# verify that all functions exist
|
|
619
|
+
for func in functions:
|
|
620
|
+
if func not in cfg.functions:
|
|
621
|
+
raise ValueError(f"Function {func} does not exist in the CFG.")
|
|
622
|
+
|
|
623
|
+
# decompile all functions
|
|
624
|
+
decompilation = ""
|
|
625
|
+
dec_options = [
|
|
626
|
+
(PARAM_TO_OPTION["structurer_cls"], structurer),
|
|
627
|
+
]
|
|
628
|
+
for func in track(functions, description="Decompiling functions", transient=True):
|
|
629
|
+
f = cfg.functions[func]
|
|
630
|
+
if f is None or f.is_plt:
|
|
631
|
+
continue
|
|
632
|
+
|
|
633
|
+
exception_string = ""
|
|
634
|
+
if not catch_errors:
|
|
635
|
+
dec = proj.analyses.Decompiler(f, cfg=cfg, options=dec_options)
|
|
636
|
+
else:
|
|
637
|
+
try:
|
|
638
|
+
# TODO: add a timeout
|
|
639
|
+
dec = proj.analyses.Decompiler(f, cfg=cfg, options=dec_options)
|
|
640
|
+
except Exception as e:
|
|
641
|
+
exception_string = str(e).replace("\n", " ")
|
|
642
|
+
dec = None
|
|
643
|
+
|
|
644
|
+
# do sanity checks on decompilation, skip checks if we already errored
|
|
645
|
+
if not exception_string:
|
|
646
|
+
if dec is None or not dec.codegen or not dec.codegen.text:
|
|
647
|
+
exception_string = "Decompilation had no code output (failed in Dec)"
|
|
648
|
+
elif "{\n}" in dec.codegen.text:
|
|
649
|
+
exception_string = "Decompilation outputted an empty function (failed in structuring)"
|
|
650
|
+
elif structurer in ["dream", "combing"] and "goto" in dec.codegen.text:
|
|
651
|
+
exception_string = "Decompilation outputted a goto for a Gotoless algorithm (failed in structuring)"
|
|
652
|
+
|
|
653
|
+
if exception_string:
|
|
654
|
+
_l.critical("Failed to decompile %s because %s", str(func), exception_string)
|
|
655
|
+
decompilation += f"// [error: {func} | {exception_string}]\n"
|
|
656
|
+
else:
|
|
657
|
+
decompilation += dec.codegen.text + "\n"
|
|
658
|
+
|
|
659
|
+
return decompilation
|
|
660
|
+
|
|
661
|
+
|
|
536
662
|
# delayed import
|
|
537
663
|
from .structuring.structurer_nodes import (
|
|
538
664
|
MultiNode,
|
angr/analyses/proximity_graph.py
CHANGED
|
@@ -180,6 +180,33 @@ class ProximityGraphAnalysis(Analysis):
|
|
|
180
180
|
|
|
181
181
|
self._work()
|
|
182
182
|
|
|
183
|
+
def _condense_blank_nodes(self, graph: networkx.DiGraph) -> None:
|
|
184
|
+
nodes = list(graph.nodes)
|
|
185
|
+
blank_nodes: List[BaseProxiNode] = []
|
|
186
|
+
|
|
187
|
+
for node in nodes:
|
|
188
|
+
if isinstance(node, BaseProxiNode) and node.type_ == ProxiNodeTypes.Empty:
|
|
189
|
+
blank_nodes.append(node)
|
|
190
|
+
else:
|
|
191
|
+
if blank_nodes:
|
|
192
|
+
self._merge_nodes(graph, blank_nodes)
|
|
193
|
+
blank_nodes = []
|
|
194
|
+
|
|
195
|
+
if blank_nodes:
|
|
196
|
+
self._merge_nodes(graph, blank_nodes)
|
|
197
|
+
|
|
198
|
+
def _merge_nodes(self, graph: networkx.DiGraph, nodes: List[BaseProxiNode]) -> None:
|
|
199
|
+
for node in nodes:
|
|
200
|
+
predecessors = set(graph.predecessors(node))
|
|
201
|
+
successors = set(graph.successors(node))
|
|
202
|
+
|
|
203
|
+
for pred in predecessors:
|
|
204
|
+
for succ in successors:
|
|
205
|
+
edge_data = graph.get_edge_data(pred, node) or {}
|
|
206
|
+
graph.add_edge(pred, succ, **edge_data)
|
|
207
|
+
|
|
208
|
+
graph.remove_node(node)
|
|
209
|
+
|
|
183
210
|
def _work(self):
|
|
184
211
|
self.graph = networkx.DiGraph()
|
|
185
212
|
|
|
@@ -210,6 +237,9 @@ class ProximityGraphAnalysis(Analysis):
|
|
|
210
237
|
self.graph.add_nodes_from(subgraph.nodes())
|
|
211
238
|
self.graph.add_edges_from(subgraph.edges())
|
|
212
239
|
|
|
240
|
+
# condense blank nodes after the graph has been constructed
|
|
241
|
+
self._condense_blank_nodes(self.graph)
|
|
242
|
+
|
|
213
243
|
def _endnode_connector(self, func: "Function", subgraph: networkx.DiGraph):
|
|
214
244
|
"""
|
|
215
245
|
Properly connect expanded function call's to proximity graph.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
|
|
3
|
+
from .plugin import KnowledgeBasePlugin
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class CustomStrings(KnowledgeBasePlugin):
|
|
7
|
+
"""
|
|
8
|
+
Store new strings that are recovered during various analysis. Each string has a unique ID associated.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, kb):
|
|
12
|
+
super().__init__()
|
|
13
|
+
self._kb = kb
|
|
14
|
+
|
|
15
|
+
self.string_id = 0
|
|
16
|
+
self.strings: Dict[int, bytes] = {}
|
|
17
|
+
|
|
18
|
+
def allocate(self, s: bytes) -> int:
|
|
19
|
+
# de-duplication
|
|
20
|
+
# TODO: Use a reverse map if this becomes a bottle-neck in the future
|
|
21
|
+
for idx, string in self.strings.items():
|
|
22
|
+
if string == s:
|
|
23
|
+
return idx
|
|
24
|
+
|
|
25
|
+
string_id = self.string_id
|
|
26
|
+
self.strings[string_id] = s
|
|
27
|
+
self.string_id += 1
|
|
28
|
+
return string_id
|
|
29
|
+
|
|
30
|
+
def __getitem__(self, idx):
|
|
31
|
+
return self.strings[idx]
|
|
32
|
+
|
|
33
|
+
def copy(self):
|
|
34
|
+
o = CustomStrings(self._kb)
|
|
35
|
+
o.strings = self.strings.copy()
|
|
36
|
+
o.string_id = self.string_id
|
|
37
|
+
return o
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
KnowledgeBasePlugin.register_default("custom_strings", CustomStrings)
|
|
@@ -80,6 +80,7 @@ class Function(Serializable):
|
|
|
80
80
|
"is_alignment",
|
|
81
81
|
"is_prototype_guessed",
|
|
82
82
|
"ran_cca",
|
|
83
|
+
"_cyclomatic_complexity",
|
|
83
84
|
)
|
|
84
85
|
|
|
85
86
|
def __init__(
|
|
@@ -161,6 +162,9 @@ class Function(Serializable):
|
|
|
161
162
|
self.info = {} # storing special information, like $gp values for MIPS32
|
|
162
163
|
self.tags = () # store function tags. can be set manually by performing CodeTagging analysis.
|
|
163
164
|
|
|
165
|
+
# Initialize _cyclomatic_complexity to None
|
|
166
|
+
self._cyclomatic_complexity = None
|
|
167
|
+
|
|
164
168
|
# TODO: Can we remove the following two members?
|
|
165
169
|
# Register offsets of those arguments passed in registers
|
|
166
170
|
self._argument_registers = []
|
|
@@ -302,6 +306,30 @@ class Function(Serializable):
|
|
|
302
306
|
except (SimEngineError, SimMemoryError):
|
|
303
307
|
pass
|
|
304
308
|
|
|
309
|
+
@property
|
|
310
|
+
def cyclomatic_complexity(self):
|
|
311
|
+
"""
|
|
312
|
+
The cyclomatic complexity of the function.
|
|
313
|
+
|
|
314
|
+
Cyclomatic complexity is a software metric used to indicate the complexity of a program.
|
|
315
|
+
It is a quantitative measure of the number of linearly independent paths through a program's source code.
|
|
316
|
+
It is computed using the formula: M = E - N + 2P, where
|
|
317
|
+
E = the number of edges in the graph,
|
|
318
|
+
N = the number of nodes in the graph,
|
|
319
|
+
P = the number of connected components.
|
|
320
|
+
|
|
321
|
+
The cyclomatic complexity value is lazily computed and cached for future use.
|
|
322
|
+
Initially this value is None until it is computed for the first time
|
|
323
|
+
|
|
324
|
+
:return: The cyclomatic complexity of the function.
|
|
325
|
+
:rtype: int
|
|
326
|
+
"""
|
|
327
|
+
if self._cyclomatic_complexity is None:
|
|
328
|
+
self._cyclomatic_complexity = (
|
|
329
|
+
self.transition_graph.number_of_edges() - self.transition_graph.number_of_nodes() + 2
|
|
330
|
+
)
|
|
331
|
+
return self._cyclomatic_complexity
|
|
332
|
+
|
|
305
333
|
@property
|
|
306
334
|
def xrefs(self):
|
|
307
335
|
"""
|
|
@@ -565,6 +593,7 @@ class Function(Serializable):
|
|
|
565
593
|
s += " Alignment: %s\n" % (self.alignment)
|
|
566
594
|
s += f" Arguments: reg: {self._argument_registers}, stack: {self._argument_stack_variables}\n"
|
|
567
595
|
s += " Blocks: [%s]\n" % ", ".join(["%#x" % i for i in self.block_addrs])
|
|
596
|
+
s += " Cyclomatic Complexity: %s\n" % self.cyclomatic_complexity
|
|
568
597
|
s += " Calling convention: %s" % self.calling_convention
|
|
569
598
|
return s
|
|
570
599
|
|
angr/lib/angr_native.dll
CHANGED
|
Binary file
|
|
@@ -13,6 +13,3 @@ libc.set_non_returning('_exit', 'abort', 'exit', '_invoke_watson')
|
|
|
13
13
|
libc.add_alias('_initterm', '_initterm_e')
|
|
14
14
|
|
|
15
15
|
libc.set_default_cc('AMD64', SimCCMicrosoftAMD64)
|
|
16
|
-
|
|
17
|
-
for name, procedure in libc.procedures.items():
|
|
18
|
-
libc.set_prototype(name, procedure.prototype)
|
angr/sim_type.py
CHANGED
|
@@ -908,6 +908,9 @@ class SimTypeFunction(SimType):
|
|
|
908
908
|
self.arg_names = arg_names if arg_names else ()
|
|
909
909
|
self.variadic = variadic
|
|
910
910
|
|
|
911
|
+
def __hash__(self):
|
|
912
|
+
return hash(type(self)) ^ hash(tuple(self.args)) ^ hash(self.returnty)
|
|
913
|
+
|
|
911
914
|
def __repr__(self):
|
|
912
915
|
argstrs = [str(a) for a in self.args]
|
|
913
916
|
if self.variadic:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: angr
|
|
3
|
-
Version: 9.2.
|
|
3
|
+
Version: 9.2.79
|
|
4
4
|
Summary: A multi-architecture binary analysis toolkit, with the ability to perform dynamic symbolic execution and various static analyses on binaries
|
|
5
5
|
Home-page: https://github.com/angr/angr
|
|
6
6
|
License: BSD-2-Clause
|
|
@@ -17,13 +17,13 @@ Description-Content-Type: text/markdown
|
|
|
17
17
|
License-File: LICENSE
|
|
18
18
|
Requires-Dist: CppHeaderParser
|
|
19
19
|
Requires-Dist: GitPython
|
|
20
|
-
Requires-Dist: ailment ==9.2.
|
|
21
|
-
Requires-Dist: archinfo ==9.2.
|
|
20
|
+
Requires-Dist: ailment ==9.2.79
|
|
21
|
+
Requires-Dist: archinfo ==9.2.79
|
|
22
22
|
Requires-Dist: cachetools
|
|
23
23
|
Requires-Dist: capstone ==5.0.0.post1
|
|
24
24
|
Requires-Dist: cffi >=1.14.0
|
|
25
|
-
Requires-Dist: claripy ==9.2.
|
|
26
|
-
Requires-Dist: cle ==9.2.
|
|
25
|
+
Requires-Dist: claripy ==9.2.79
|
|
26
|
+
Requires-Dist: cle ==9.2.79
|
|
27
27
|
Requires-Dist: dpkt
|
|
28
28
|
Requires-Dist: itanium-demangler
|
|
29
29
|
Requires-Dist: mulpyplexer
|
|
@@ -32,7 +32,7 @@ Requires-Dist: networkx !=2.8.1,>=2.0
|
|
|
32
32
|
Requires-Dist: protobuf >=3.19.0
|
|
33
33
|
Requires-Dist: psutil
|
|
34
34
|
Requires-Dist: pycparser >=2.18
|
|
35
|
-
Requires-Dist: pyvex ==9.2.
|
|
35
|
+
Requires-Dist: pyvex ==9.2.79
|
|
36
36
|
Requires-Dist: rich >=13.1.0
|
|
37
37
|
Requires-Dist: rpyc
|
|
38
38
|
Requires-Dist: sortedcontainers
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
angr/__init__.py,sha256=
|
|
1
|
+
angr/__init__.py,sha256=1hDKCHV5WU-92kCqJB-WuVkZO28N6APe3LTVIuMzl7g,3851
|
|
2
|
+
angr/__main__.py,sha256=kdqGysHrVO1vaW6VC6v_OTmlCO7R1-eZpiEhArmi978,1095
|
|
2
3
|
angr/annocfg.py,sha256=dK5JAdN4Ig_jgxTBZeZXwk3kAS4-IQUvE6T02GBZTDQ,10818
|
|
3
4
|
angr/blade.py,sha256=YySrLqj2Y3-td9FJnkjDqYyFvAeGhc5a5lrGoHKOT2A,15562
|
|
4
5
|
angr/block.py,sha256=FnsFukbXhLzYPW5zJRXMxNmvCRU4LFlFIaJwo5sAqkY,14468
|
|
@@ -19,7 +20,7 @@ angr/sim_options.py,sha256=OuT01xS_F3ifBD9MAfZmNCnfjtTg0HulZlrKcs1LNSY,18057
|
|
|
19
20
|
angr/sim_procedure.py,sha256=TpYn5z6YMKjugyH_Lw9XcEaQc8cpTxtyorBKrRYMewA,26073
|
|
20
21
|
angr/sim_state.py,sha256=BhAKyfvoGfqpgAPYYT4j7drrkOdPy03ucBO7LKMz0s0,37826
|
|
21
22
|
angr/sim_state_options.py,sha256=lfP7ygngjGe0AGV5rkE24tvBazJBZG-RTdrKj4rL9XE,12530
|
|
22
|
-
angr/sim_type.py,sha256=
|
|
23
|
+
angr/sim_type.py,sha256=ZU4uHgFcJyjvVMGza8_JluHKmAWbpT9S1Xb41qdydHU,117056
|
|
23
24
|
angr/sim_variable.py,sha256=VIpKm4lguu_bKokjq4UB6Q_30Ogz9J7XRBJuH62lW60,17228
|
|
24
25
|
angr/slicer.py,sha256=kbLKMAjf2kC6ov-OiGb95BqLmgV0QRl5mmEANcvzuAk,10640
|
|
25
26
|
angr/state_hierarchy.py,sha256=w_5Tl-7h9xUXBsIKZRAWw8Xh0we8GIAaN6nbKgYH_Qo,8467
|
|
@@ -48,7 +49,7 @@ angr/analyses/flirt.py,sha256=-n6GShXV6PLKDHr4nML49ZwAAlmMIP5SDeF2KmJVKOM,7847
|
|
|
48
49
|
angr/analyses/init_finder.py,sha256=hFHPsHipF4QkWzVqcDeTgL6YIaYi8bAyaURZBksS4KI,8531
|
|
49
50
|
angr/analyses/loop_analysis.py,sha256=nIbDIzvys-FRtJYnoZYNbMWH5V88qrhoMtrMRCTbkLY,9412
|
|
50
51
|
angr/analyses/loopfinder.py,sha256=X8F4Dcu2UHDXt6JifK6EfROAeeczyca6V7zxx9z7GpQ,7122
|
|
51
|
-
angr/analyses/proximity_graph.py,sha256=
|
|
52
|
+
angr/analyses/proximity_graph.py,sha256=y30caPk5N4zOzkf8TF7AEOo0AR_yDhEFJrQB89_CTnM,16323
|
|
52
53
|
angr/analyses/reassembler.py,sha256=b4EnHx36yS2DNq8nes7zr2_9SozqXbeTTx2538TCm84,100415
|
|
53
54
|
angr/analyses/soot_class_hierarchy.py,sha256=Cs_LRV1RLXH6sF_E49tJWg9Inxvv_o5mB-VaIBcbQJg,8941
|
|
54
55
|
angr/analyses/stack_pointer_tracker.py,sha256=rL8wF12Fe3P-RXAzk4caMYapB63tYX_qs-EO6E5l1n8,26228
|
|
@@ -64,7 +65,7 @@ angr/analyses/cfg/cfg.py,sha256=1JpPGlqXXRFwE0tk26xjabT_-dq-kqAxMv7o6-DUhp4,3146
|
|
|
64
65
|
angr/analyses/cfg/cfg_arch_options.py,sha256=YONHg6y-h6BCsBkJK9tuxb94DDfeOoy9CUS-LVyyDyg,3112
|
|
65
66
|
angr/analyses/cfg/cfg_base.py,sha256=o3mAO3ha5DPWFiE_TeUll38ldal-p0IUOyXY4lNnncc,121889
|
|
66
67
|
angr/analyses/cfg/cfg_emulated.py,sha256=Fi3rDN5ByxhO-H4Y7qn-3WZgBG12JGyvxcWmrD_FnFQ,152842
|
|
67
|
-
angr/analyses/cfg/cfg_fast.py,sha256=
|
|
68
|
+
angr/analyses/cfg/cfg_fast.py,sha256=jaF4UXjld_GX9JdN87noJhaD5c0vvo8lcURv3xHa2RI,210389
|
|
68
69
|
angr/analyses/cfg/cfg_fast_soot.py,sha256=eA_P-OY3gRRNj2BBgSPMsB_llGyFFCNW3VyGZ2uiMoM,26047
|
|
69
70
|
angr/analyses/cfg/cfg_job_base.py,sha256=3IQE_Iy17xtGfsIkrKc2ERIakAYiNdLtRb_jwOGQtHU,5989
|
|
70
71
|
angr/analyses/cfg/segment_list.py,sha256=XM-rcLHkl008U5xu9pkVCenhcHWAFBKwVdDLa-kGFgY,20467
|
|
@@ -91,10 +92,10 @@ angr/analyses/data_dep/sim_act_location.py,sha256=4f8jp-ahitxoHCCOSSFGJ1olvNWuHy
|
|
|
91
92
|
angr/analyses/decompiler/__init__.py,sha256=RkTvvTwAGpaLdGSTgXxVrKmGEDRxqLCNSB-b8fM6fBM,540
|
|
92
93
|
angr/analyses/decompiler/ail_simplifier.py,sha256=ZHXNxaR9yLRFbYaczolSbc1vQ1s__EhTi9fumkv8AcM,59030
|
|
93
94
|
angr/analyses/decompiler/ailgraph_walker.py,sha256=sBz9Cn0GtdpuFt7R9y3oX6NFvETQTZRh6N80eM9ZdJQ,1595
|
|
94
|
-
angr/analyses/decompiler/block_simplifier.py,sha256=
|
|
95
|
+
angr/analyses/decompiler/block_simplifier.py,sha256=X5kO97A1bEwSUfbwgj1cSO56qkhwPQZnIFi1DKMZQoo,17199
|
|
95
96
|
angr/analyses/decompiler/call_counter.py,sha256=V3TIaSvLUy9vLEWErnvlCS--_ubGWQAeU0tqq6XYeOU,1205
|
|
96
97
|
angr/analyses/decompiler/callsite_maker.py,sha256=B2lajS20_cTDWvUc-Py-2rP6UybNLd-qAjkuDJMIlX8,14938
|
|
97
|
-
angr/analyses/decompiler/clinic.py,sha256=
|
|
98
|
+
angr/analyses/decompiler/clinic.py,sha256=F2mcZKD0xuEFFXxQAlVQ8dnOTAP-YVCPW8pFeq8YwEo,72531
|
|
98
99
|
angr/analyses/decompiler/condition_processor.py,sha256=ts7-dM1ckqDRh28Vv3YhKhNYUHdsavJah4Ta3_tb-uo,48658
|
|
99
100
|
angr/analyses/decompiler/decompilation_cache.py,sha256=NveTVs6IY3TTdgsLvTb3ktftM4n0NrAJIkqjXqQ3550,1119
|
|
100
101
|
angr/analyses/decompiler/decompilation_options.py,sha256=EtLBv9XG3chXmceT3irru3K7jJhguv8JilWYCHdTWyQ,7668
|
|
@@ -110,20 +111,20 @@ angr/analyses/decompiler/redundant_label_remover.py,sha256=kDGGFWWV61I5fbASiTQTH
|
|
|
110
111
|
angr/analyses/decompiler/region_identifier.py,sha256=SQEhgXy5nHkQl6WRDTLZTtbRhxkXzT1IiBCzvP1K-p8,44389
|
|
111
112
|
angr/analyses/decompiler/region_walker.py,sha256=lTfweYbY4_a2f2yGztTKG6JtU1jXf-kaz-NHbX9nkXE,717
|
|
112
113
|
angr/analyses/decompiler/sequence_walker.py,sha256=mw4RG-Act5_no_RyQcsxWZwva-n7FdH2a7w_uItGUpI,8428
|
|
113
|
-
angr/analyses/decompiler/utils.py,sha256=
|
|
114
|
+
angr/analyses/decompiler/utils.py,sha256=jzODnWygARpEdPLBRfgcWzEjsYS6X5W-aa_-tSODj7k,24386
|
|
114
115
|
angr/analyses/decompiler/ccall_rewriters/__init__.py,sha256=wbWqZ8xG6ZvzEApkAwMsNQFC-iwF3swG1YJsaf1cIrQ,102
|
|
115
116
|
angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py,sha256=PjfduEkFVcSBKUfGouVM5dekA4kO4OBUses58ewJnCk,20488
|
|
116
117
|
angr/analyses/decompiler/ccall_rewriters/rewriter_base.py,sha256=gWezEKB7A_YnlfUDs8V8D5syoYAyIXSIme1BKQRoouM,498
|
|
117
|
-
angr/analyses/decompiler/optimization_passes/__init__.py,sha256=
|
|
118
|
+
angr/analyses/decompiler/optimization_passes/__init__.py,sha256=inyWh1QXeFfA9JBnFsK6E-3PrCBTKuNJT8O_70Pz2KE,2794
|
|
118
119
|
angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py,sha256=bjpEMW-Lqj5XW9NWUikGPcRn5scKNc8VvEjVMXxAuq8,5289
|
|
119
120
|
angr/analyses/decompiler/optimization_passes/const_derefs.py,sha256=FEoiprXxns-3S0nFaIWm2DBW_aDMq3GZ-VOG3CIqcMw,10593
|
|
120
121
|
angr/analyses/decompiler/optimization_passes/div_simplifier.py,sha256=1yTI1mmFHBMxADbrKxk9IAf3TpuNCaTLVQqWveyIx1I,17364
|
|
121
122
|
angr/analyses/decompiler/optimization_passes/eager_returns.py,sha256=rSIjiTf1IzeplmACjAH99ZqebXUeJvvP_jHHmKLoMXk,11250
|
|
122
|
-
angr/analyses/decompiler/optimization_passes/engine_base.py,sha256=
|
|
123
|
+
angr/analyses/decompiler/optimization_passes/engine_base.py,sha256=7nnNZkVMqvikHCy9X11M8KLWbL8lF0DoLYPemETWP4c,10388
|
|
123
124
|
angr/analyses/decompiler/optimization_passes/expr_op_swapper.py,sha256=vlPhWDyvuEmbGcd1ka8rS68F72Ty6Hw3J00KM3tWCus,4701
|
|
124
125
|
angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py,sha256=DjkPSAI9Z_X6YXW3Emzc1s3CzIvh45HDhBihh63UuIw,3448
|
|
125
126
|
angr/analyses/decompiler/optimization_passes/ite_expr_converter.py,sha256=-6znFCAXS7Z3cn5CTqr3mg4r1G_jJgDFJHk2PzMVwtE,7756
|
|
126
|
-
angr/analyses/decompiler/optimization_passes/ite_region_converter.py,sha256=
|
|
127
|
+
angr/analyses/decompiler/optimization_passes/ite_region_converter.py,sha256=l571GUDoCt4hZ2RHBNVUraLl-ODmP_kb11bLKwbCIB0,6762
|
|
127
128
|
angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py,sha256=MQNtGU8paXdhTcfvYvBeTplX-htqs0WI6o-72me8fmg,34328
|
|
128
129
|
angr/analyses/decompiler/optimization_passes/mod_simplifier.py,sha256=A9pPly7otXJlLkSbItU0wvjGGu6rUsNpcFw3bzy4DjY,3046
|
|
129
130
|
angr/analyses/decompiler/optimization_passes/multi_simplifier.py,sha256=Ez7ye4j2VUfELxRPkNQQIY-gF9Q9SkTZxH5jt301Rx8,10968
|
|
@@ -132,9 +133,9 @@ angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py,sh
|
|
|
132
133
|
angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py,sha256=_sTaGMQMFa5ATQIvNyL05UK8gCi_SaOckrZKyHZ2vfs,6470
|
|
133
134
|
angr/analyses/decompiler/optimization_passes/ret_deduplicator.py,sha256=CAOGRra4PB-FCjTxQs2e-lEQ6z_CMvHsrubpbyahv0M,7797
|
|
134
135
|
angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py,sha256=diqUO-k1hq9OzuC7OLMyJJODhy3i1c5Tb7d9f7lx6mU,12147
|
|
135
|
-
angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py,sha256=
|
|
136
|
+
angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py,sha256=BRl9s9DzEMSKugR7-N5OBukyNcoN2Y_vWbziXqF4nmE,13231
|
|
136
137
|
angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py,sha256=lwLc9QpOCTdSIb-0SK0hdxi2gzpABTk2kzdwBY20UOo,2980
|
|
137
|
-
angr/analyses/decompiler/peephole_optimizations/__init__.py,sha256=
|
|
138
|
+
angr/analyses/decompiler/peephole_optimizations/__init__.py,sha256=pe_zErF540hOybDNC0ij9B3ASQOck9PYNa64hzSEp3U,3208
|
|
138
139
|
angr/analyses/decompiler/peephole_optimizations/a_div_const_add_a_mul_n_div_const.py,sha256=Whptbt1qujPPRsNX8kJaobHTwgvym7SPu-tC2wBynBs,1727
|
|
139
140
|
angr/analyses/decompiler/peephole_optimizations/a_mul_const_div_shr_const.py,sha256=xuLPEVN1QdQT_5U9K4-WIdVdHTogCBOmJPWlnDW8Cz8,1365
|
|
140
141
|
angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py,sha256=tEr_XcYoOXcFm5paY_CEzgSOjrksz20utMZa6smF9TU,988
|
|
@@ -142,7 +143,7 @@ angr/analyses/decompiler/peephole_optimizations/a_sub_a_div.py,sha256=ocLn_4eLty
|
|
|
142
143
|
angr/analyses/decompiler/peephole_optimizations/a_sub_a_div_const_mul_const.py,sha256=gvPg4KkQcammW4sviu272RLf7S0ASmcYfa5GAXGQX30,2050
|
|
143
144
|
angr/analyses/decompiler/peephole_optimizations/a_sub_a_sub_n.py,sha256=KajKgL00mHXpEZewbwKgnZKLbZTnSB00-CGbed12uNU,619
|
|
144
145
|
angr/analyses/decompiler/peephole_optimizations/arm_cmpf.py,sha256=ShdDtwrhqxUzPW2MwM98xufHo7OSL8GfNYQQCGYXrVQ,9333
|
|
145
|
-
angr/analyses/decompiler/peephole_optimizations/base.py,sha256=
|
|
146
|
+
angr/analyses/decompiler/peephole_optimizations/base.py,sha256=os9bEPHDm2p5EA4h5eoA7Uso2nAjBYySwJ9gjp5p44Q,3538
|
|
146
147
|
angr/analyses/decompiler/peephole_optimizations/basepointeroffset_add_n.py,sha256=OzchLk1a0CV2ggHm6-TLpa6f_b7fj7K3Z3l6gFCUEJc,1056
|
|
147
148
|
angr/analyses/decompiler/peephole_optimizations/basepointeroffset_and_mask.py,sha256=eiUgxcBVAL6PiI3ZuR6xZMNrWGDHKXO6SZSjUbM_BVw,1065
|
|
148
149
|
angr/analyses/decompiler/peephole_optimizations/bitwise_or_to_logical_or.py,sha256=oocs8xmntUNzI7UUG8UFPCDheda3xAb99REPAkD7ins,1298
|
|
@@ -150,11 +151,13 @@ angr/analyses/decompiler/peephole_optimizations/bool_expr_xor_1.py,sha256=QANf71
|
|
|
150
151
|
angr/analyses/decompiler/peephole_optimizations/bswap.py,sha256=Nrdf5f47NduOc59CjmQbmsVmys1e79HxniPExdd3NRg,3663
|
|
151
152
|
angr/analyses/decompiler/peephole_optimizations/coalesce_same_cascading_ifs.py,sha256=9ogHTcP4vhFfwDzxccnjfhkizKGvM_7tK3y6PqyG5Hg,1020
|
|
152
153
|
angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py,sha256=KLdhgU_e1OglEeC7IHipql9UzYpatJc0LydXJJIakL4,3691
|
|
153
|
-
angr/analyses/decompiler/peephole_optimizations/constant_derefs.py,sha256=
|
|
154
|
+
angr/analyses/decompiler/peephole_optimizations/constant_derefs.py,sha256=SjSE3kTrPYPjsoY_pW3nZPk9IXrJwNR4lfQ9nV-QVKg,984
|
|
154
155
|
angr/analyses/decompiler/peephole_optimizations/conv_a_sub0_shr_and.py,sha256=vzROAUvKUrQQmwUXJ-0WyFr1v5f8EPBgjeXIpWhtDak,2578
|
|
155
156
|
angr/analyses/decompiler/peephole_optimizations/conv_shl_shr.py,sha256=0IHIk7uxIC70140k3VcXlnx4QcunAeoETXF1ZgJi2Pk,2070
|
|
156
157
|
angr/analyses/decompiler/peephole_optimizations/eager_eval.py,sha256=9FXjKuBWC2oDo3tPkNOhiSOD0C_P7vA83DAp7qJfnIU,8684
|
|
157
158
|
angr/analyses/decompiler/peephole_optimizations/extended_byte_and_mask.py,sha256=ymP9tDU4NipGOdFWsmLHrR6dKVcEFiaTgM1-L_dfmOM,2015
|
|
159
|
+
angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py,sha256=x8ZS-ThnUiJPBacRFpOZ3gBqixamrHSCCZSR-L5jyC8,2601
|
|
160
|
+
angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py,sha256=vrXAaYKT99LJK5BLKlyQ7xtzQx6hIujqTAv0-Ur1CWo,4676
|
|
158
161
|
angr/analyses/decompiler/peephole_optimizations/invert_negated_logical_conjuction_disjunction.py,sha256=a0IDp0kKBrPwhDVejPFhcNseZdprF_5EZRZs7KTR4gA,2084
|
|
159
162
|
angr/analyses/decompiler/peephole_optimizations/one_sub_bool.py,sha256=kW8AbWfMqFzI1CVFp79TFX60IZxaQhRG8XUckuc-vGI,1136
|
|
160
163
|
angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py,sha256=3a1ZoTq66HTU68y5DCC2sLvItPmqF_Kv05uvOacxsRM,591
|
|
@@ -190,7 +193,7 @@ angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py,sha256=
|
|
|
190
193
|
angr/analyses/decompiler/region_simplifiers/switch_expr_simplifier.py,sha256=HGIiC6c3C91VfcqxUHe9aTsRohwmMXOHZH_G_dbwwx4,3327
|
|
191
194
|
angr/analyses/decompiler/structured_codegen/__init__.py,sha256=Glc4jBCr7lZckltN9XZdSvMrGHf0swXFyKTr_QQKdWE,290
|
|
192
195
|
angr/analyses/decompiler/structured_codegen/base.py,sha256=nJPOoeJCbewchYdXjSE4S2b1-WN6pT3TxmCQMDO0azw,3845
|
|
193
|
-
angr/analyses/decompiler/structured_codegen/c.py,sha256=
|
|
196
|
+
angr/analyses/decompiler/structured_codegen/c.py,sha256=rJyXVUmXuzFA10jfiewfINB5WfisUIadhqje-kXTz40,128736
|
|
194
197
|
angr/analyses/decompiler/structured_codegen/dummy.py,sha256=IVfmtcWpTgNCRVsuW3GdQgDnuPmvodX85V0bBYtF_BI,535
|
|
195
198
|
angr/analyses/decompiler/structured_codegen/dwarf_import.py,sha256=TMz65TkF_ID_Ipocj0aFDb84H6slolN90wq0tzhY2Rk,6773
|
|
196
199
|
angr/analyses/decompiler/structuring/__init__.py,sha256=eSiT6xUpv9K5-enK3OZj2lNzxwowS9_5OTrjHiPgfFs,371
|
|
@@ -418,9 +421,10 @@ angr/flirt/__init__.py,sha256=UTjDOlVPnvb5u1zYOvSrI_8F-RllvA_rWCEF1XGEswk,4428
|
|
|
418
421
|
angr/flirt/build_sig.py,sha256=QnBVAjmBms6GiDK1v13dNE-YQ2i95qazDh0lYX5nKEs,10109
|
|
419
422
|
angr/knowledge_base/__init__.py,sha256=G2QiJKD3Q1dgpSjaHwZi0FMDRI8aeu2x2Lyn9FSgS54,42
|
|
420
423
|
angr/knowledge_base/knowledge_base.py,sha256=V_RDvf-VOizrB9a-FYrsuYd_bAfyPoEhxAKmZb1Z2Gc,4623
|
|
421
|
-
angr/knowledge_plugins/__init__.py,sha256=
|
|
424
|
+
angr/knowledge_plugins/__init__.py,sha256=UIjrxZHnr-EaYe5tSNQ1DVE6yRJtMlJzNXGLK6ARPhw,697
|
|
422
425
|
angr/knowledge_plugins/callsite_prototypes.py,sha256=nEJhJxuH_xivJRcRsFbeQ0KJuncHShfwk9WhChcMScA,1614
|
|
423
426
|
angr/knowledge_plugins/comments.py,sha256=Zc8_5Y7ThGsVetdfLeI7OQSrKjmu9tSkzq_qQMcDDjE,315
|
|
427
|
+
angr/knowledge_plugins/custom_strings.py,sha256=5uy6QZb40BNkLlttpgTflTQj_mPUt6v2iFSiHBns69c,1044
|
|
424
428
|
angr/knowledge_plugins/data.py,sha256=iKviVL-_lqqdw_7YECDpoSmrtUSj6oKfbCYVu40T6kE,260
|
|
425
429
|
angr/knowledge_plugins/debug_variables.py,sha256=N3vltNKykTsuQ3zVvxHz00Y_0_UvjZuIL47FhBrP0Kk,8223
|
|
426
430
|
angr/knowledge_plugins/indirect_jumps.py,sha256=puJnKhp11eRDNZ-swEXKtZk04DJ48uM1F8gBiz5xbAs,971
|
|
@@ -435,7 +439,7 @@ angr/knowledge_plugins/cfg/cfg_node.py,sha256=Q_qqQ1LisCzTWROOQAfvyaBjS86zxcMw6I
|
|
|
435
439
|
angr/knowledge_plugins/cfg/indirect_jump.py,sha256=yzPf1jjUNPgGP7D7IamqX6KF-EJX-heZjDEr4SRUWDA,2145
|
|
436
440
|
angr/knowledge_plugins/cfg/memory_data.py,sha256=FzRUFltXrN0G3OeMZEbb3xc7I-W8AaomtCTSXUQlJ0g,5040
|
|
437
441
|
angr/knowledge_plugins/functions/__init__.py,sha256=6IerJjMKKvM70mcJQhmXJYiipePOQ9ZSTmavTIUgg5Q,77
|
|
438
|
-
angr/knowledge_plugins/functions/function.py,sha256=
|
|
442
|
+
angr/knowledge_plugins/functions/function.py,sha256=NyAznn7LnJ9QIIANsEdpjJS8hwG955ve4YHtiznpK6A,65399
|
|
439
443
|
angr/knowledge_plugins/functions/function_manager.py,sha256=Nbk97zc3GCW6BzpMdZha7e8zhCOH9lD3Avw1XYZV778,17558
|
|
440
444
|
angr/knowledge_plugins/functions/function_parser.py,sha256=cb_AD5oFqoyXapDBawnJV1D9XVRMBGa9GwwDudNSc3M,11916
|
|
441
445
|
angr/knowledge_plugins/functions/soot_function.py,sha256=2zwz_tdKbEnF8eUkOEmpNr7AUeooun2-SiIoY_xIdMw,4971
|
|
@@ -469,7 +473,7 @@ angr/knowledge_plugins/xrefs/__init__.py,sha256=-5A2h048WTRu6Et7q7bqlc-AyBXNuJ9A
|
|
|
469
473
|
angr/knowledge_plugins/xrefs/xref.py,sha256=w4wjDFl4xtJYOtJplp9s1AIX3wI1RE71po3ufh1M4aY,4963
|
|
470
474
|
angr/knowledge_plugins/xrefs/xref_manager.py,sha256=GYF9N1t4JxkDNGAwrVLo4_NF51P4gqiuQ21F0IbloF0,4026
|
|
471
475
|
angr/knowledge_plugins/xrefs/xref_types.py,sha256=VR3xLQQ-gUg25oX0OL3BJHyQRlZh2A8syBac9ZMS9n4,271
|
|
472
|
-
angr/lib/angr_native.dll,sha256=
|
|
476
|
+
angr/lib/angr_native.dll,sha256=wNtDTQv01n7sYKMAYCufrdKLyTZyoryGhAPUwdKyW8Y,19209728
|
|
473
477
|
angr/misc/__init__.py,sha256=Ct-Q6-c-Frdz5Ihkqmou3j_1jyJi8WJXlQxs-gPQg0Y,237
|
|
474
478
|
angr/misc/ansi.py,sha256=TKrx7d_MViChHh5RBR2VLufNrujTUioJWsZS5ugk8k4,807
|
|
475
479
|
angr/misc/autoimport.py,sha256=6WT-Z6wf5NiacQhKZmR4d2bPOvNrokA7Wg0g2MUXSuw,2371
|
|
@@ -501,7 +505,7 @@ angr/procedures/definitions/gnulib.py,sha256=fH8KbaUj6bVOG_cv-JiaffWkVN-YHFbWwvR
|
|
|
501
505
|
angr/procedures/definitions/libstdcpp.py,sha256=lhV3EGR45spEo_vNFNw2vIdPJWdByqar_sP9dFZMvKs,700
|
|
502
506
|
angr/procedures/definitions/linux_kernel.py,sha256=uaTTlulqv2eeUmIkQ70-pvLT2-ay7rqMBjPazhh5RbQ,238887
|
|
503
507
|
angr/procedures/definitions/linux_loader.py,sha256=sW7eQ7Dk2co_9x0ql-YsWYB8JYs0YQjGz-IM_ukp5c4,219
|
|
504
|
-
angr/procedures/definitions/msvcr.py,sha256=
|
|
508
|
+
angr/procedures/definitions/msvcr.py,sha256=9Wvo9U8ARM93oYmID5pBSCAr9Yg0TxjXAj7Gi_Lks2s,601
|
|
505
509
|
angr/procedures/definitions/ntdll.py,sha256=2X_f1WvpBncRS6nN6PwatRKtgdn6cMYb4AnvLEhCYN0,404
|
|
506
510
|
angr/procedures/definitions/parse_syscalls_from_local_system.py,sha256=9OcLLDNrNb6CifvveD_yTzfhMYEN2iK46nNNjMyz3I0,1795
|
|
507
511
|
angr/procedures/definitions/parse_win32json.py,sha256=zFfq0SpBjgzIDUisbzA4zTvISGslOEPHe4V2zDbqepE,84681
|
|
@@ -1406,8 +1410,9 @@ tests/storage/test_multivalues.py,sha256=x82duiIMsU9nE-6vhm-eEsofshKfbVy5d9CNgdC
|
|
|
1406
1410
|
tests/storage/test_permissions.py,sha256=-Gsd1CUO7xZv7NTieiuikm33xfl33MyzIkembL3CuIw,883
|
|
1407
1411
|
tests/storage/test_ptmalloc.py,sha256=WwORhRoN0SYC8R9aJ_RITbVKlB6JQnLyINTWbT4PidU,10592
|
|
1408
1412
|
tests/storage/test_relro_perm.py,sha256=gqNbkYfAYr0wM-oSijS3HYi0-cbtplMDCSWQqRCqEb4,1406
|
|
1409
|
-
angr-9.2.
|
|
1410
|
-
angr-9.2.
|
|
1411
|
-
angr-9.2.
|
|
1412
|
-
angr-9.2.
|
|
1413
|
-
angr-9.2.
|
|
1413
|
+
angr-9.2.79.dist-info/LICENSE,sha256=cgL_ho5B1NH8UxwtBuqThRWdjear8b7hktycaS1sz6g,1327
|
|
1414
|
+
angr-9.2.79.dist-info/METADATA,sha256=LxvGZly4vzhzSGI_nGL-0XEZlf03uAge8ivhIgT3w4A,4856
|
|
1415
|
+
angr-9.2.79.dist-info/WHEEL,sha256=6iYPr8vTHsyDK75jr9X0V3I9wPSVmtwr_8fdATBciGk,98
|
|
1416
|
+
angr-9.2.79.dist-info/entry_points.txt,sha256=Vjh1C8PMyr5dZFMnik5WkEP01Uwr2T73I3a6N32sgQU,44
|
|
1417
|
+
angr-9.2.79.dist-info/top_level.txt,sha256=EGgw8HjaUI9JWd6w70Tzkn1AcyKTMJTVJ9OpWyaOewk,11
|
|
1418
|
+
angr-9.2.79.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|