angr 9.2.153__py3-none-manylinux2014_aarch64.whl → 9.2.154__py3-none-manylinux2014_aarch64.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/analysis.py +3 -3
- angr/analyses/calling_convention/fact_collector.py +8 -14
- angr/analyses/cfg/cfg_fast.py +2 -2
- angr/analyses/decompiler/callsite_maker.py +17 -17
- angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +210 -1
- angr/analyses/decompiler/clinic.py +6 -12
- angr/analyses/decompiler/decompilation_cache.py +1 -1
- angr/analyses/decompiler/ssailification/ssailification.py +1 -1
- angr/analyses/decompiler/structured_codegen/c.py +15 -15
- angr/analyses/decompiler/structuring/phoenix.py +28 -0
- angr/analyses/decompiler/structuring/structurer_nodes.py +11 -0
- angr/analyses/reaching_definitions/function_handler.py +13 -19
- angr/analyses/stack_pointer_tracker.py +7 -1
- angr/analyses/variable_recovery/engine_ail.py +14 -25
- angr/analyses/variable_recovery/engine_base.py +1 -1
- angr/sim_type.py +11 -70
- angr/utils/types.py +93 -1
- {angr-9.2.153.dist-info → angr-9.2.154.dist-info}/METADATA +6 -6
- {angr-9.2.153.dist-info → angr-9.2.154.dist-info}/RECORD +24 -24
- {angr-9.2.153.dist-info → angr-9.2.154.dist-info}/WHEEL +1 -1
- {angr-9.2.153.dist-info → angr-9.2.154.dist-info}/entry_points.txt +0 -0
- {angr-9.2.153.dist-info → angr-9.2.154.dist-info}/licenses/LICENSE +0 -0
- {angr-9.2.153.dist-info → angr-9.2.154.dist-info}/top_level.txt +0 -0
angr/__init__.py
CHANGED
angr/analyses/analysis.py
CHANGED
|
@@ -5,7 +5,7 @@ import sys
|
|
|
5
5
|
import contextlib
|
|
6
6
|
from collections import defaultdict
|
|
7
7
|
from inspect import Signature
|
|
8
|
-
from typing import TYPE_CHECKING, TypeVar, Generic, cast
|
|
8
|
+
from typing import TYPE_CHECKING, TypeVar, Generic, cast, Any
|
|
9
9
|
from collections.abc import Callable
|
|
10
10
|
from types import NoneType
|
|
11
11
|
from itertools import chain
|
|
@@ -111,7 +111,7 @@ class AnalysisLogEntry:
|
|
|
111
111
|
A = TypeVar("A", bound="Analysis")
|
|
112
112
|
|
|
113
113
|
|
|
114
|
-
class AnalysesHub(PluginVendor[
|
|
114
|
+
class AnalysesHub(PluginVendor[Any]):
|
|
115
115
|
"""
|
|
116
116
|
This class contains functions for all the registered and runnable analyses,
|
|
117
117
|
"""
|
|
@@ -123,7 +123,7 @@ class AnalysesHub(PluginVendor[A]):
|
|
|
123
123
|
def _init_plugin(self, plugin_cls: type[A]) -> AnalysisFactory[A]:
|
|
124
124
|
return AnalysisFactory(self.project, plugin_cls)
|
|
125
125
|
|
|
126
|
-
def __getstate__(self):
|
|
126
|
+
def __getstate__(self): # type: ignore[reportIncompatibleMethodOverride]
|
|
127
127
|
s = super().__getstate__()
|
|
128
128
|
return (s, self.project)
|
|
129
129
|
|
|
@@ -6,7 +6,6 @@ from collections import defaultdict
|
|
|
6
6
|
import pyvex
|
|
7
7
|
import claripy
|
|
8
8
|
|
|
9
|
-
from angr import SIM_LIBRARIES, SIM_TYPE_COLLECTIONS
|
|
10
9
|
from angr.utils.bits import s2u, u2s
|
|
11
10
|
from angr.block import Block
|
|
12
11
|
from angr.analyses.analysis import Analysis
|
|
@@ -15,7 +14,8 @@ from angr.knowledge_plugins.functions import Function
|
|
|
15
14
|
from angr.codenode import BlockNode, HookNode
|
|
16
15
|
from angr.engines.light import SimEngineNostmtVEX, SimEngineLight, SpOffset, RegisterOffset
|
|
17
16
|
from angr.calling_conventions import SimRegArg, SimStackArg, default_cc
|
|
18
|
-
from angr.sim_type import SimTypeBottom,
|
|
17
|
+
from angr.sim_type import SimTypeBottom, SimTypeFunction
|
|
18
|
+
from angr.utils.types import dereference_simtype_by_lib
|
|
19
19
|
from .utils import is_sane_register_variable
|
|
20
20
|
|
|
21
21
|
if TYPE_CHECKING:
|
|
@@ -121,7 +121,7 @@ class SimEngineFactCollectorVEX(
|
|
|
121
121
|
if self.block.vex.jumpkind == "Ijk_Call" and self.arch.ret_offset is not None:
|
|
122
122
|
self.state.register_written(self.arch.ret_offset, self.arch.bytes)
|
|
123
123
|
|
|
124
|
-
def _top(self, bits: int):
|
|
124
|
+
def _top(self, bits: int): # type: ignore
|
|
125
125
|
return None
|
|
126
126
|
|
|
127
127
|
def _is_top(self, expr: Any) -> bool:
|
|
@@ -190,13 +190,13 @@ class SimEngineFactCollectorVEX(
|
|
|
190
190
|
self.state.register_read(expr.offset, bits // self.arch.byte_width)
|
|
191
191
|
return RegisterOffset(bits, expr.offset, 0)
|
|
192
192
|
|
|
193
|
-
def _handle_expr_GetI(self, expr):
|
|
193
|
+
def _handle_expr_GetI(self, expr): # type: ignore
|
|
194
194
|
return None
|
|
195
195
|
|
|
196
|
-
def _handle_expr_ITE(self, expr):
|
|
196
|
+
def _handle_expr_ITE(self, expr): # type: ignore
|
|
197
197
|
return None
|
|
198
198
|
|
|
199
|
-
def _handle_expr_Load(self, expr):
|
|
199
|
+
def _handle_expr_Load(self, expr): # type: ignore
|
|
200
200
|
addr = self._expr(expr.addr)
|
|
201
201
|
if isinstance(addr, SpOffset):
|
|
202
202
|
self.state.stack_read(addr.offset, expr.result_size(self.tyenv) // self.arch.byte_width)
|
|
@@ -206,7 +206,7 @@ class SimEngineFactCollectorVEX(
|
|
|
206
206
|
def _handle_expr_RdTmp(self, expr):
|
|
207
207
|
return self.state.tmps.get(expr.tmp, None)
|
|
208
208
|
|
|
209
|
-
def _handle_expr_VECRET(self, expr):
|
|
209
|
+
def _handle_expr_VECRET(self, expr): # type: ignore
|
|
210
210
|
return None
|
|
211
211
|
|
|
212
212
|
@binop_handler
|
|
@@ -444,13 +444,7 @@ class FactCollector(Analysis):
|
|
|
444
444
|
proto = func_succ.prototype
|
|
445
445
|
if func_succ.prototype_libname is not None:
|
|
446
446
|
# we need to deref the prototype in case it uses SimTypeRef internally
|
|
447
|
-
|
|
448
|
-
for prototype_lib in SIM_LIBRARIES[func_succ.prototype_libname]:
|
|
449
|
-
if prototype_lib.type_collection_names:
|
|
450
|
-
for typelib_name in prototype_lib.type_collection_names:
|
|
451
|
-
type_collections.append(SIM_TYPE_COLLECTIONS[typelib_name])
|
|
452
|
-
if type_collections:
|
|
453
|
-
proto = dereference_simtype(proto, type_collections)
|
|
447
|
+
proto = dereference_simtype_by_lib(proto, func_succ.prototype_libname)
|
|
454
448
|
|
|
455
449
|
assert isinstance(proto, SimTypeFunction) and proto.returnty is not None
|
|
456
450
|
returnty_size = proto.returnty.with_arch(self.project.arch).size
|
angr/analyses/cfg/cfg_fast.py
CHANGED
|
@@ -1567,7 +1567,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1567
1567
|
block = func.get_block(func.addr)
|
|
1568
1568
|
except SimTranslationError:
|
|
1569
1569
|
block = None
|
|
1570
|
-
if block is not None and block.instructions == 1:
|
|
1570
|
+
if block is not None and block.instructions == 1 and len(block.capstone.insns) == 1:
|
|
1571
1571
|
insn = block.capstone.insns[0]
|
|
1572
1572
|
if block.bytes == b"\xff\xe0":
|
|
1573
1573
|
func.info["jmp_rax"] = True
|
|
@@ -1921,7 +1921,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1921
1921
|
if cfg_node is None:
|
|
1922
1922
|
continue
|
|
1923
1923
|
func_addr = cfg_node.function_address
|
|
1924
|
-
if func_addr not in tested_func_addrs:
|
|
1924
|
+
if func_addr not in tested_func_addrs and self.kb.functions.contains_addr(func_addr):
|
|
1925
1925
|
func = self.kb.functions.get_by_addr(func_addr)
|
|
1926
1926
|
if not security_check_cookie_found and is_function_security_check_cookie(
|
|
1927
1927
|
func, self.project, security_cookie_addr
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from typing import Any, TYPE_CHECKING
|
|
2
|
+
from typing import cast, Any, TYPE_CHECKING
|
|
3
3
|
import copy
|
|
4
4
|
import logging
|
|
5
5
|
|
|
@@ -14,7 +14,6 @@ from angr.sim_type import (
|
|
|
14
14
|
SimTypeChar,
|
|
15
15
|
SimTypeInt,
|
|
16
16
|
SimTypeFloat,
|
|
17
|
-
dereference_simtype,
|
|
18
17
|
SimTypeFunction,
|
|
19
18
|
SimTypeLongLong,
|
|
20
19
|
)
|
|
@@ -22,7 +21,7 @@ from angr.calling_conventions import SimReferenceArgument, SimRegArg, SimStackAr
|
|
|
22
21
|
from angr.knowledge_plugins.key_definitions.constants import OP_BEFORE
|
|
23
22
|
from angr.analyses import Analysis, register_analysis
|
|
24
23
|
from angr.analyses.s_reaching_definitions import SRDAView
|
|
25
|
-
from angr import
|
|
24
|
+
from angr.utils.types import dereference_simtype_by_lib
|
|
26
25
|
|
|
27
26
|
if TYPE_CHECKING:
|
|
28
27
|
from angr.knowledge_plugins.functions import Function
|
|
@@ -37,12 +36,14 @@ class CallSiteMaker(Analysis):
|
|
|
37
36
|
Add calling convention, declaration, and args to a call site.
|
|
38
37
|
"""
|
|
39
38
|
|
|
40
|
-
def __init__(
|
|
39
|
+
def __init__(
|
|
40
|
+
self, block, reaching_definitions=None, stack_pointer_tracker=None, ail_manager: Manager | None = None
|
|
41
|
+
):
|
|
41
42
|
self.block = block
|
|
42
43
|
|
|
43
44
|
self._reaching_definitions = reaching_definitions
|
|
44
45
|
self._stack_pointer_tracker = stack_pointer_tracker
|
|
45
|
-
self._ail_manager = ail_manager
|
|
46
|
+
self._ail_manager: Manager | None = ail_manager
|
|
46
47
|
|
|
47
48
|
self.result_block = None
|
|
48
49
|
self.stack_arg_offsets: set[tuple[int, int]] | None = None # call ins addr, stack_offset
|
|
@@ -109,16 +110,8 @@ class CallSiteMaker(Analysis):
|
|
|
109
110
|
# make sure the function prototype is resolved.
|
|
110
111
|
# TODO: Cache resolved function prototypes globally
|
|
111
112
|
prototype_libname = func.prototype_libname
|
|
112
|
-
type_collections = []
|
|
113
113
|
if prototype_libname is not None:
|
|
114
|
-
|
|
115
|
-
if prototype_lib.type_collection_names:
|
|
116
|
-
for typelib_name in prototype_lib.type_collection_names:
|
|
117
|
-
type_collections.append(SIM_TYPE_COLLECTIONS[typelib_name])
|
|
118
|
-
if type_collections:
|
|
119
|
-
prototype = dereference_simtype(prototype, type_collections).with_arch( # type: ignore
|
|
120
|
-
self.project.arch
|
|
121
|
-
)
|
|
114
|
+
prototype = cast(SimTypeFunction, dereference_simtype_by_lib(prototype, prototype_libname))
|
|
122
115
|
|
|
123
116
|
args = []
|
|
124
117
|
arg_vvars = []
|
|
@@ -151,6 +144,10 @@ class CallSiteMaker(Analysis):
|
|
|
151
144
|
# across registers). most importantly, a ComboArg represents one variable, not multiple, but we
|
|
152
145
|
# have no way to know that until later down the pipeline.
|
|
153
146
|
expanded_arg_locs += arg_loc.locations
|
|
147
|
+
elif isinstance(arg_loc, SimStructArg):
|
|
148
|
+
expanded_arg_locs += [ # type: ignore
|
|
149
|
+
arg_loc.locs[field_name] for field_name in arg_loc.struct.fields if field_name in arg_loc.locs
|
|
150
|
+
]
|
|
154
151
|
elif isinstance(arg_loc, (SimRegArg, SimStackArg, SimReferenceArgument)):
|
|
155
152
|
expanded_arg_locs.append(arg_loc)
|
|
156
153
|
else:
|
|
@@ -195,12 +192,15 @@ class CallSiteMaker(Analysis):
|
|
|
195
192
|
if vvar_def_reg_offset is not None and offset > vvar_def_reg_offset:
|
|
196
193
|
# we need to shift the value
|
|
197
194
|
vvar_use = Expr.BinaryOp(
|
|
198
|
-
self._ail_manager.next_atom(),
|
|
195
|
+
self._ail_manager.next_atom() if self._ail_manager is not None else None,
|
|
199
196
|
"Shr",
|
|
200
197
|
[
|
|
201
198
|
vvar_use,
|
|
202
199
|
Expr.Const(
|
|
203
|
-
self._ail_manager.next_atom()
|
|
200
|
+
self._ail_manager.next_atom() if self._ail_manager is not None else None,
|
|
201
|
+
None,
|
|
202
|
+
(offset - vvar_def_reg_offset) * 8,
|
|
203
|
+
8,
|
|
204
204
|
),
|
|
205
205
|
],
|
|
206
206
|
**vvar_use.tags,
|
|
@@ -208,7 +208,7 @@ class CallSiteMaker(Analysis):
|
|
|
208
208
|
if vvar_def.size > arg_loc.size:
|
|
209
209
|
# we need to narrow the value
|
|
210
210
|
vvar_use = Expr.Convert(
|
|
211
|
-
self._ail_manager.next_atom(),
|
|
211
|
+
self._ail_manager.next_atom() if self._ail_manager is not None else None,
|
|
212
212
|
vvar_use.bits,
|
|
213
213
|
arg_loc.size * self.project.arch.byte_width,
|
|
214
214
|
False,
|
|
@@ -15,6 +15,23 @@ X86_CondBitOffsets = data["X86"]["CondBitOffsets"]
|
|
|
15
15
|
class X86CCallRewriter(CCallRewriterBase):
|
|
16
16
|
"""
|
|
17
17
|
Implements VEX ccall rewriter for X86.
|
|
18
|
+
|
|
19
|
+
From libVEX:
|
|
20
|
+
|
|
21
|
+
A summary of the field usages is:
|
|
22
|
+
|
|
23
|
+
Operation DEP1 DEP2 NDEP
|
|
24
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
25
|
+
|
|
26
|
+
add/sub/mul first arg second arg unused
|
|
27
|
+
adc/sbb first arg (second arg)
|
|
28
|
+
XOR old_carry old_carry
|
|
29
|
+
and/or/xor result zero unused
|
|
30
|
+
inc/dec result zero old_carry
|
|
31
|
+
shl/shr/sar result subshifted- unused
|
|
32
|
+
result
|
|
33
|
+
rol/ror result zero old_flags
|
|
34
|
+
copy old_flags zero unused.
|
|
18
35
|
"""
|
|
19
36
|
|
|
20
37
|
__slots__ = ()
|
|
@@ -28,7 +45,7 @@ class X86CCallRewriter(CCallRewriterBase):
|
|
|
28
45
|
if isinstance(cond, Expr.Const) and isinstance(op, Expr.Const):
|
|
29
46
|
cond_v = cond.value
|
|
30
47
|
op_v = op.value
|
|
31
|
-
if cond_v == X86_CondTypes["CondLE"]:
|
|
48
|
+
if cond_v == X86_CondTypes["CondLE"]:
|
|
32
49
|
if op_v in {
|
|
33
50
|
X86_OpTypes["G_CC_OP_SUBB"],
|
|
34
51
|
X86_OpTypes["G_CC_OP_SUBW"],
|
|
@@ -52,6 +69,198 @@ class X86CCallRewriter(CCallRewriterBase):
|
|
|
52
69
|
|
|
53
70
|
r = Expr.BinaryOp(ccall.idx, "CmpLE", (dep_1, dep_2), True, **ccall.tags)
|
|
54
71
|
return Expr.Convert(None, r.bits, ccall.bits, False, r, **ccall.tags)
|
|
72
|
+
elif cond_v == X86_CondTypes["CondO"]:
|
|
73
|
+
op_v = op.value
|
|
74
|
+
ret_cond = None
|
|
75
|
+
if op_v in {
|
|
76
|
+
X86_OpTypes["G_CC_OP_UMULB"],
|
|
77
|
+
X86_OpTypes["G_CC_OP_UMULW"],
|
|
78
|
+
X86_OpTypes["G_CC_OP_UMULL"],
|
|
79
|
+
}:
|
|
80
|
+
# dep_1 * dep_2 >= max_signed_byte/word/dword
|
|
81
|
+
ret = Expr.BinaryOp(
|
|
82
|
+
None,
|
|
83
|
+
"Mul",
|
|
84
|
+
(dep_1, dep_2),
|
|
85
|
+
bits=dep_1.bits * 2,
|
|
86
|
+
**ccall.tags,
|
|
87
|
+
)
|
|
88
|
+
max_signed = Expr.Const(
|
|
89
|
+
None,
|
|
90
|
+
None,
|
|
91
|
+
(1 << (dep_1.bits - 1)),
|
|
92
|
+
bits=dep_1.bits * 2,
|
|
93
|
+
**ccall.tags,
|
|
94
|
+
)
|
|
95
|
+
ret_cond = Expr.BinaryOp(None, "CmpGE", (ret, max_signed), signed=False, **ccall.tags)
|
|
96
|
+
if op_v in {
|
|
97
|
+
X86_OpTypes["G_CC_OP_INCB"],
|
|
98
|
+
X86_OpTypes["G_CC_OP_INCW"],
|
|
99
|
+
X86_OpTypes["G_CC_OP_INCL"],
|
|
100
|
+
}:
|
|
101
|
+
# dep_1 is the result
|
|
102
|
+
overflowed = Expr.Const(
|
|
103
|
+
None,
|
|
104
|
+
None,
|
|
105
|
+
1 << (dep_1.bits - 1),
|
|
106
|
+
dep_1.bits,
|
|
107
|
+
**ccall.tags,
|
|
108
|
+
)
|
|
109
|
+
ret_cond = Expr.BinaryOp(None, "CmpEQ", (dep_1, overflowed), **ccall.tags)
|
|
110
|
+
|
|
111
|
+
if ret_cond is not None:
|
|
112
|
+
return Expr.ITE(
|
|
113
|
+
ccall.idx,
|
|
114
|
+
ret_cond,
|
|
115
|
+
Expr.Const(None, None, 0, 1, **ccall.tags),
|
|
116
|
+
Expr.Const(None, None, 1, 1, **ccall.tags),
|
|
117
|
+
**ccall.tags,
|
|
118
|
+
)
|
|
119
|
+
elif cond_v == X86_CondTypes["CondZ"]:
|
|
120
|
+
op_v = op.value
|
|
121
|
+
if op_v in {
|
|
122
|
+
X86_OpTypes["G_CC_OP_ADDB"],
|
|
123
|
+
X86_OpTypes["G_CC_OP_ADDW"],
|
|
124
|
+
X86_OpTypes["G_CC_OP_ADDL"],
|
|
125
|
+
}:
|
|
126
|
+
# dep_1 + dep_2 == 0
|
|
127
|
+
ret = Expr.BinaryOp(
|
|
128
|
+
None,
|
|
129
|
+
"Add",
|
|
130
|
+
(dep_1, dep_2),
|
|
131
|
+
bits=dep_1.bits,
|
|
132
|
+
**ccall.tags,
|
|
133
|
+
)
|
|
134
|
+
zero = Expr.Const(
|
|
135
|
+
None,
|
|
136
|
+
None,
|
|
137
|
+
0,
|
|
138
|
+
dep_1.bits,
|
|
139
|
+
**ccall.tags,
|
|
140
|
+
)
|
|
141
|
+
return Expr.BinaryOp(
|
|
142
|
+
ccall.idx,
|
|
143
|
+
"CmpEQ",
|
|
144
|
+
(ret, zero),
|
|
145
|
+
True,
|
|
146
|
+
**ccall.tags,
|
|
147
|
+
)
|
|
148
|
+
if op_v in {
|
|
149
|
+
X86_OpTypes["G_CC_OP_SUBB"],
|
|
150
|
+
X86_OpTypes["G_CC_OP_SUBW"],
|
|
151
|
+
X86_OpTypes["G_CC_OP_SUBL"],
|
|
152
|
+
}:
|
|
153
|
+
# dep_1 - dep_2 == 0
|
|
154
|
+
return Expr.BinaryOp(
|
|
155
|
+
ccall.idx,
|
|
156
|
+
"CmpEQ",
|
|
157
|
+
(dep_1, dep_2),
|
|
158
|
+
True,
|
|
159
|
+
**ccall.tags,
|
|
160
|
+
)
|
|
161
|
+
if op_v in {
|
|
162
|
+
X86_OpTypes["G_CC_OP_LOGICB"],
|
|
163
|
+
X86_OpTypes["G_CC_OP_LOGICW"],
|
|
164
|
+
X86_OpTypes["G_CC_OP_LOGICL"],
|
|
165
|
+
}:
|
|
166
|
+
# dep_1 == 0
|
|
167
|
+
return Expr.BinaryOp(
|
|
168
|
+
ccall.idx,
|
|
169
|
+
"CmpEQ",
|
|
170
|
+
(dep_1, Expr.Const(None, None, 0, dep_1.bits, **ccall.tags)),
|
|
171
|
+
True,
|
|
172
|
+
**ccall.tags,
|
|
173
|
+
)
|
|
174
|
+
elif cond_v == X86_CondTypes["CondL"]:
|
|
175
|
+
op_v = op.value
|
|
176
|
+
if op_v in {
|
|
177
|
+
X86_OpTypes["G_CC_OP_SUBB"],
|
|
178
|
+
X86_OpTypes["G_CC_OP_SUBW"],
|
|
179
|
+
X86_OpTypes["G_CC_OP_SUBL"],
|
|
180
|
+
}:
|
|
181
|
+
# dep_1 - dep_2 < 0
|
|
182
|
+
return Expr.BinaryOp(
|
|
183
|
+
ccall.idx,
|
|
184
|
+
"CmpLT",
|
|
185
|
+
(dep_1, dep_2),
|
|
186
|
+
True,
|
|
187
|
+
**ccall.tags,
|
|
188
|
+
)
|
|
189
|
+
if op_v in {
|
|
190
|
+
X86_OpTypes["G_CC_OP_LOGICB"],
|
|
191
|
+
X86_OpTypes["G_CC_OP_LOGICW"],
|
|
192
|
+
X86_OpTypes["G_CC_OP_LOGICL"],
|
|
193
|
+
}:
|
|
194
|
+
# dep_1 < 0
|
|
195
|
+
return Expr.BinaryOp(
|
|
196
|
+
ccall.idx,
|
|
197
|
+
"CmpLT",
|
|
198
|
+
(dep_1, Expr.Const(None, None, 0, dep_1.bits, **ccall.tags)),
|
|
199
|
+
True,
|
|
200
|
+
**ccall.tags,
|
|
201
|
+
)
|
|
202
|
+
elif cond_v in {
|
|
203
|
+
X86_CondTypes["CondBE"],
|
|
204
|
+
X86_CondTypes["CondB"],
|
|
205
|
+
}:
|
|
206
|
+
op_v = op.value
|
|
207
|
+
if op_v in {
|
|
208
|
+
X86_OpTypes["G_CC_OP_ADDB"],
|
|
209
|
+
X86_OpTypes["G_CC_OP_ADDW"],
|
|
210
|
+
X86_OpTypes["G_CC_OP_ADDL"],
|
|
211
|
+
}:
|
|
212
|
+
# dep_1 + dep_2 <= 0 if CondBE
|
|
213
|
+
# dep_1 + dep_2 < 0 if CondB
|
|
214
|
+
ret = Expr.BinaryOp(
|
|
215
|
+
None,
|
|
216
|
+
"Add",
|
|
217
|
+
(dep_1, dep_2),
|
|
218
|
+
signed=False,
|
|
219
|
+
bits=dep_1.bits,
|
|
220
|
+
**ccall.tags,
|
|
221
|
+
)
|
|
222
|
+
zero = Expr.Const(
|
|
223
|
+
None,
|
|
224
|
+
None,
|
|
225
|
+
0,
|
|
226
|
+
dep_1.bits,
|
|
227
|
+
**ccall.tags,
|
|
228
|
+
)
|
|
229
|
+
return Expr.BinaryOp(
|
|
230
|
+
ccall.idx,
|
|
231
|
+
"CmpLE" if cond_v == X86_CondTypes["CondBE"] else "CmpLT",
|
|
232
|
+
(ret, zero),
|
|
233
|
+
False,
|
|
234
|
+
**ccall.tags,
|
|
235
|
+
)
|
|
236
|
+
if op_v in {
|
|
237
|
+
X86_OpTypes["G_CC_OP_SUBB"],
|
|
238
|
+
X86_OpTypes["G_CC_OP_SUBW"],
|
|
239
|
+
X86_OpTypes["G_CC_OP_SUBL"],
|
|
240
|
+
}:
|
|
241
|
+
# dep_1 <= dep_2 if CondBE
|
|
242
|
+
# dep_1 < dep_2 if CondB
|
|
243
|
+
return Expr.BinaryOp(
|
|
244
|
+
ccall.idx,
|
|
245
|
+
"CmpLE" if cond_v == X86_CondTypes["CondBE"] else "CmpLT",
|
|
246
|
+
(dep_1, dep_2),
|
|
247
|
+
False,
|
|
248
|
+
**ccall.tags,
|
|
249
|
+
)
|
|
250
|
+
if op_v in {
|
|
251
|
+
X86_OpTypes["G_CC_OP_LOGICB"],
|
|
252
|
+
X86_OpTypes["G_CC_OP_LOGICW"],
|
|
253
|
+
X86_OpTypes["G_CC_OP_LOGICL"],
|
|
254
|
+
}:
|
|
255
|
+
# dep_1 <= 0 if CondBE
|
|
256
|
+
# dep_1 < 0 if CondB
|
|
257
|
+
return Expr.BinaryOp(
|
|
258
|
+
ccall.idx,
|
|
259
|
+
"CmpLE" if cond_v == X86_CondTypes["CondBE"] else "CmpLT",
|
|
260
|
+
(dep_1, Expr.Const(None, None, 0, dep_1.bits, **ccall.tags)),
|
|
261
|
+
False,
|
|
262
|
+
**ccall.tags,
|
|
263
|
+
)
|
|
55
264
|
return None
|
|
56
265
|
|
|
57
266
|
@staticmethod
|
|
@@ -12,7 +12,6 @@ import networkx
|
|
|
12
12
|
import capstone
|
|
13
13
|
|
|
14
14
|
import ailment
|
|
15
|
-
from angr import SIM_LIBRARIES, SIM_TYPE_COLLECTIONS
|
|
16
15
|
|
|
17
16
|
from angr.errors import AngrDecompilationError
|
|
18
17
|
from angr.knowledge_base import KnowledgeBase
|
|
@@ -22,9 +21,9 @@ from angr.knowledge_plugins.key_definitions import atoms
|
|
|
22
21
|
from angr.codenode import BlockNode
|
|
23
22
|
from angr.utils import timethis
|
|
24
23
|
from angr.utils.graph import GraphUtils
|
|
24
|
+
from angr.utils.types import dereference_simtype_by_lib
|
|
25
25
|
from angr.calling_conventions import SimRegArg, SimStackArg, SimFunctionArgument
|
|
26
26
|
from angr.sim_type import (
|
|
27
|
-
dereference_simtype,
|
|
28
27
|
SimTypeChar,
|
|
29
28
|
SimTypeInt,
|
|
30
29
|
SimTypeLongLong,
|
|
@@ -1240,16 +1239,8 @@ class Clinic(Analysis):
|
|
|
1240
1239
|
# make sure the function prototype is resolved.
|
|
1241
1240
|
# TODO: Cache resolved function prototypes globally
|
|
1242
1241
|
prototype_libname = func.prototype_libname
|
|
1243
|
-
type_collections = []
|
|
1244
1242
|
if prototype_libname is not None:
|
|
1245
|
-
|
|
1246
|
-
if prototype_lib.type_collection_names:
|
|
1247
|
-
for typelib_name in prototype_lib.type_collection_names:
|
|
1248
|
-
type_collections.append(SIM_TYPE_COLLECTIONS[typelib_name])
|
|
1249
|
-
if type_collections:
|
|
1250
|
-
prototype = dereference_simtype(prototype, type_collections).with_arch( # type: ignore
|
|
1251
|
-
self.project.arch
|
|
1252
|
-
)
|
|
1243
|
+
prototype = dereference_simtype_by_lib(prototype, prototype_libname)
|
|
1253
1244
|
|
|
1254
1245
|
if cc is None:
|
|
1255
1246
|
l.warning("Call site %#x (callee %s) has an unknown calling convention.", block.addr, repr(func))
|
|
@@ -1541,6 +1532,7 @@ class Clinic(Analysis):
|
|
|
1541
1532
|
vvar_id_start=self.vvar_id_start,
|
|
1542
1533
|
)
|
|
1543
1534
|
self.vvar_id_start = ssailification.max_vvar_id + 1
|
|
1535
|
+
assert ssailification.out_graph is not None
|
|
1544
1536
|
return ssailification.out_graph
|
|
1545
1537
|
|
|
1546
1538
|
@timethis
|
|
@@ -1921,6 +1913,7 @@ class Clinic(Analysis):
|
|
|
1921
1913
|
self._link_variables_on_call(variable_manager, global_variables, block, stmt_idx, stmt, is_expr=False)
|
|
1922
1914
|
|
|
1923
1915
|
elif stmt_type is ailment.Stmt.Return:
|
|
1916
|
+
assert isinstance(stmt, ailment.Stmt.Return)
|
|
1924
1917
|
self._link_variables_on_return(variable_manager, global_variables, block, stmt_idx, stmt)
|
|
1925
1918
|
|
|
1926
1919
|
def _link_variables_on_return(
|
|
@@ -2252,6 +2245,7 @@ class Clinic(Analysis):
|
|
|
2252
2245
|
def _create_triangle_for_ite_expression(self, ail_graph, block_addr: int, ite_ins_addr: int):
|
|
2253
2246
|
ite_insn_only_block = self.project.factory.block(ite_ins_addr, num_inst=1)
|
|
2254
2247
|
ite_insn_size = ite_insn_only_block.size
|
|
2248
|
+
assert ite_insn_size is not None
|
|
2255
2249
|
if ite_insn_size <= 2: # we need an address for true_block and another address for false_block
|
|
2256
2250
|
return None
|
|
2257
2251
|
if ite_insn_only_block.vex.exit_statements:
|
|
@@ -3205,7 +3199,7 @@ class Clinic(Analysis):
|
|
|
3205
3199
|
)
|
|
3206
3200
|
break
|
|
3207
3201
|
|
|
3208
|
-
if alloca_node is not None:
|
|
3202
|
+
if alloca_node is not None and sp_equal_to is not None:
|
|
3209
3203
|
stmt0 = alloca_node.statements[1]
|
|
3210
3204
|
statements = [ailment.Stmt.Call(stmt0.idx, "alloca", args=[sp_equal_to], **stmt0.tags)]
|
|
3211
3205
|
new_node = ailment.Block(alloca_node.addr, alloca_node.original_size, statements=statements)
|
|
@@ -31,7 +31,7 @@ class DecompilationCache:
|
|
|
31
31
|
self.parameters: dict[str, Any] = {}
|
|
32
32
|
self.addr = addr
|
|
33
33
|
self.type_constraints: dict[TypeVariable, set[TypeConstraint]] | None = None
|
|
34
|
-
self.func_typevar = None
|
|
34
|
+
self.func_typevar: TypeVariable | None = None
|
|
35
35
|
self.var_to_typevar: dict | None = None
|
|
36
36
|
self.codegen: BaseStructuredCodeGenerator | None = None
|
|
37
37
|
self.clinic: Clinic | None = None
|
|
@@ -107,7 +107,7 @@ class Ssailification(Analysis): # pylint:disable=abstract-method
|
|
|
107
107
|
)
|
|
108
108
|
self.secondary_stackvars = rewriter.secondary_stackvars
|
|
109
109
|
self.out_graph = rewriter.out_graph
|
|
110
|
-
self.max_vvar_id = rewriter.max_vvar_id
|
|
110
|
+
self.max_vvar_id: int = rewriter.max_vvar_id if rewriter.max_vvar_id is not None else 0
|
|
111
111
|
|
|
112
112
|
def _calculate_virtual_variables(
|
|
113
113
|
self,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pylint:disable=missing-class-docstring,too-many-boolean-expressions,unused-argument,no-self-use
|
|
2
2
|
from __future__ import annotations
|
|
3
|
-
from typing import Any, TYPE_CHECKING
|
|
3
|
+
from typing import cast, Any, TYPE_CHECKING
|
|
4
4
|
from collections.abc import Callable
|
|
5
5
|
from collections import defaultdict, Counter
|
|
6
6
|
import logging
|
|
@@ -12,7 +12,6 @@ from ailment.constant import UNDETERMINED_SIZE
|
|
|
12
12
|
from ailment.expression import StackBaseOffset, BinaryOp
|
|
13
13
|
from unique_log_filter import UniqueLogFilter
|
|
14
14
|
|
|
15
|
-
from angr.procedures import SIM_LIBRARIES, SIM_TYPE_COLLECTIONS
|
|
16
15
|
from angr.sim_type import (
|
|
17
16
|
SimTypeLongLong,
|
|
18
17
|
SimTypeInt,
|
|
@@ -32,7 +31,6 @@ from angr.sim_type import (
|
|
|
32
31
|
SimTypeFixedSizeArray,
|
|
33
32
|
SimTypeLength,
|
|
34
33
|
SimTypeReg,
|
|
35
|
-
dereference_simtype,
|
|
36
34
|
SimTypeInt128,
|
|
37
35
|
SimTypeInt256,
|
|
38
36
|
SimTypeInt512,
|
|
@@ -43,7 +41,7 @@ from angr.sim_variable import SimVariable, SimTemporaryVariable, SimStackVariabl
|
|
|
43
41
|
from angr.utils.constants import is_alignment_mask
|
|
44
42
|
from angr.utils.library import get_cpp_function_name
|
|
45
43
|
from angr.utils.loader import is_in_readonly_segment, is_in_readonly_section
|
|
46
|
-
from angr.utils.types import unpack_typeref, unpack_pointer_and_array
|
|
44
|
+
from angr.utils.types import unpack_typeref, unpack_pointer_and_array, dereference_simtype_by_lib
|
|
47
45
|
from angr.analyses.decompiler.utils import structured_node_is_simple_return
|
|
48
46
|
from angr.errors import UnsupportedNodeTypeError, AngrRuntimeError
|
|
49
47
|
from angr.knowledge_plugins.cfg.memory_data import MemoryData, MemoryDataSort
|
|
@@ -1301,12 +1299,7 @@ class CFunctionCall(CStatement, CExpression):
|
|
|
1301
1299
|
proto = self.callee_func.prototype
|
|
1302
1300
|
if self.callee_func.prototype_libname is not None:
|
|
1303
1301
|
# we need to deref the prototype in case it uses SimTypeRef internally
|
|
1304
|
-
|
|
1305
|
-
for prototype_lib in SIM_LIBRARIES[self.callee_func.prototype_libname]:
|
|
1306
|
-
if prototype_lib.type_collection_names:
|
|
1307
|
-
for typelib_name in prototype_lib.type_collection_names:
|
|
1308
|
-
type_collections.append(SIM_TYPE_COLLECTIONS[typelib_name])
|
|
1309
|
-
proto = dereference_simtype(proto, type_collections)
|
|
1302
|
+
proto = cast(SimTypeFunction, dereference_simtype_by_lib(proto, self.callee_func.prototype_libname))
|
|
1310
1303
|
return proto
|
|
1311
1304
|
returnty = SimTypeInt(signed=False)
|
|
1312
1305
|
return SimTypeFunction([arg.type for arg in self.args], returnty).with_arch(self.codegen.project.arch)
|
|
@@ -1314,7 +1307,9 @@ class CFunctionCall(CStatement, CExpression):
|
|
|
1314
1307
|
@property
|
|
1315
1308
|
def type(self):
|
|
1316
1309
|
if self.is_expr:
|
|
1317
|
-
return self.prototype.returnty or SimTypeInt(
|
|
1310
|
+
return (self.prototype.returnty if self.prototype is not None else None) or SimTypeInt(
|
|
1311
|
+
signed=False
|
|
1312
|
+
).with_arch(self.codegen.project.arch)
|
|
1318
1313
|
raise AngrRuntimeError("CFunctionCall.type should not be accessed if the function call is used as a statement.")
|
|
1319
1314
|
|
|
1320
1315
|
def _is_target_ambiguous(self, func_name: str) -> bool:
|
|
@@ -1323,6 +1318,8 @@ class CFunctionCall(CStatement, CExpression):
|
|
|
1323
1318
|
"""
|
|
1324
1319
|
caller, callee = self.codegen._func, self.callee_func
|
|
1325
1320
|
|
|
1321
|
+
assert self.codegen._variables_in_use is not None
|
|
1322
|
+
|
|
1326
1323
|
for var in self.codegen._variables_in_use.values():
|
|
1327
1324
|
if func_name == var.name:
|
|
1328
1325
|
return True
|
|
@@ -1461,7 +1458,7 @@ class CGoto(CStatement):
|
|
|
1461
1458
|
def c_repr_chunks(self, indent=0, asexpr=False):
|
|
1462
1459
|
indent_str = self.indent_str(indent=indent)
|
|
1463
1460
|
lbl = None
|
|
1464
|
-
if self.codegen is not None:
|
|
1461
|
+
if self.codegen is not None and isinstance(self.target, int):
|
|
1465
1462
|
lbl = self.codegen.map_addr_to_label.get((self.target, self.target_idx))
|
|
1466
1463
|
|
|
1467
1464
|
yield indent_str, None
|
|
@@ -1609,7 +1606,9 @@ class CVariable(CExpression):
|
|
|
1609
1606
|
|
|
1610
1607
|
self.variable: SimVariable = variable
|
|
1611
1608
|
self.unified_variable: SimVariable | None = unified_variable
|
|
1612
|
-
self.variable_type: SimType =
|
|
1609
|
+
self.variable_type: SimType | None = (
|
|
1610
|
+
variable_type.with_arch(self.codegen.project.arch) if variable_type is not None else None
|
|
1611
|
+
)
|
|
1613
1612
|
self.vvar_id = vvar_id
|
|
1614
1613
|
|
|
1615
1614
|
@property
|
|
@@ -3970,7 +3969,8 @@ class MakeTypecastsImplicit(CStructuredCodeWalker):
|
|
|
3970
3969
|
return super().handle_CAssignment(obj)
|
|
3971
3970
|
|
|
3972
3971
|
def handle_CFunctionCall(self, obj: CFunctionCall):
|
|
3973
|
-
|
|
3972
|
+
prototype_args = [] if obj.prototype is None else obj.prototype.args
|
|
3973
|
+
for i, (c_arg, arg_ty) in enumerate(zip(obj.args, prototype_args)):
|
|
3974
3974
|
obj.args[i] = self.collapse(arg_ty, c_arg)
|
|
3975
3975
|
return super().handle_CFunctionCall(obj)
|
|
3976
3976
|
|
|
@@ -4033,7 +4033,7 @@ class PointerArithmeticFixer(CStructuredCodeWalker):
|
|
|
4033
4033
|
a_ptr = a_ptr + 1.
|
|
4034
4034
|
"""
|
|
4035
4035
|
|
|
4036
|
-
def handle_CBinaryOp(self, obj):
|
|
4036
|
+
def handle_CBinaryOp(self, obj: CBinaryOp): # type: ignore
|
|
4037
4037
|
obj: CBinaryOp = super().handle_CBinaryOp(obj)
|
|
4038
4038
|
if (
|
|
4039
4039
|
obj.op in ("Add", "Sub")
|