angr 9.2.92__py3-none-manylinux2014_x86_64.whl → 9.2.94__py3-none-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of angr might be problematic. Click here for more details.
- angr/__init__.py +1 -1
- angr/analyses/cfg/cfg_base.py +20 -10
- angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +1 -1
- angr/analyses/cfg/indirect_jump_resolvers/arm_elf_fast.py +89 -32
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +276 -133
- angr/analyses/complete_calling_conventions.py +1 -1
- angr/analyses/decompiler/ail_simplifier.py +20 -0
- angr/analyses/decompiler/block_io_finder.py +293 -0
- angr/analyses/decompiler/block_similarity.py +190 -0
- angr/analyses/decompiler/callsite_maker.py +5 -0
- angr/analyses/decompiler/clinic.py +103 -1
- angr/analyses/decompiler/decompilation_cache.py +2 -0
- angr/analyses/decompiler/decompiler.py +21 -4
- angr/analyses/decompiler/optimization_passes/__init__.py +6 -0
- angr/analyses/decompiler/optimization_passes/code_motion.py +361 -0
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +1 -0
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +30 -18
- angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +110 -0
- angr/analyses/decompiler/peephole_optimizations/bswap.py +53 -2
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +20 -1
- angr/analyses/decompiler/structured_codegen/c.py +76 -41
- angr/analyses/decompiler/structuring/phoenix.py +41 -9
- angr/analyses/decompiler/utils.py +13 -4
- angr/analyses/propagator/engine_ail.py +3 -0
- angr/analyses/reaching_definitions/engine_ail.py +3 -0
- angr/analyses/reaching_definitions/reaching_definitions.py +7 -0
- angr/analyses/stack_pointer_tracker.py +60 -10
- angr/analyses/typehoon/simple_solver.py +95 -24
- angr/analyses/typehoon/typeconsts.py +1 -1
- angr/calling_conventions.py +0 -3
- angr/engines/pcode/cc.py +1 -1
- angr/engines/successors.py +6 -0
- angr/knowledge_plugins/propagations/states.py +2 -1
- angr/procedures/definitions/glibc.py +3 -1
- angr/procedures/definitions/parse_win32json.py +2135 -383
- angr/procedures/definitions/wdk_ntoskrnl.py +956 -0
- angr/sim_type.py +53 -13
- angr/utils/library.py +2 -2
- {angr-9.2.92.dist-info → angr-9.2.94.dist-info}/METADATA +6 -6
- {angr-9.2.92.dist-info → angr-9.2.94.dist-info}/RECORD +44 -41
- {angr-9.2.92.dist-info → angr-9.2.94.dist-info}/WHEEL +1 -1
- angr/procedures/definitions/wdk_ntdll.py +0 -994
- {angr-9.2.92.dist-info → angr-9.2.94.dist-info}/LICENSE +0 -0
- {angr-9.2.92.dist-info → angr-9.2.94.dist-info}/entry_points.txt +0 -0
- {angr-9.2.92.dist-info → angr-9.2.94.dist-info}/top_level.txt +0 -0
angr/__init__.py
CHANGED
angr/analyses/cfg/cfg_base.py
CHANGED
|
@@ -8,7 +8,7 @@ from sortedcontainers import SortedDict
|
|
|
8
8
|
|
|
9
9
|
import pyvex
|
|
10
10
|
from claripy.utils.orderedset import OrderedSet
|
|
11
|
-
from cle import ELF, PE, Blob, TLSObject, MachO, ExternObject, KernelObject, FunctionHintSource, Hex, Coff
|
|
11
|
+
from cle import ELF, PE, Blob, TLSObject, MachO, ExternObject, KernelObject, FunctionHintSource, Hex, Coff, SRec
|
|
12
12
|
from cle.backends import NamedRegion
|
|
13
13
|
import archinfo
|
|
14
14
|
from archinfo.arch_soot import SootAddressDescriptor
|
|
@@ -748,19 +748,29 @@ class CFGBase(Analysis):
|
|
|
748
748
|
for b in binaries:
|
|
749
749
|
if isinstance(b, ELF):
|
|
750
750
|
# If we have sections, we get result from sections
|
|
751
|
+
sections = []
|
|
751
752
|
if not force_segment and b.sections:
|
|
752
753
|
# Get all executable sections
|
|
753
754
|
for section in b.sections:
|
|
754
755
|
if section.is_executable:
|
|
755
756
|
tpl = (section.min_addr, section.max_addr + 1)
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
757
|
+
sections.append(tpl)
|
|
758
|
+
memory_regions += sections
|
|
759
|
+
|
|
760
|
+
segments = []
|
|
761
|
+
# Get all executable segments
|
|
762
|
+
for segment in b.segments:
|
|
763
|
+
if segment.is_executable:
|
|
764
|
+
tpl = (segment.min_addr, segment.max_addr + 1)
|
|
765
|
+
segments.append(tpl)
|
|
766
|
+
if sections and segments:
|
|
767
|
+
# are there executable segments with no sections inside?
|
|
768
|
+
for segment in segments:
|
|
769
|
+
for section in sections:
|
|
770
|
+
if segment[0] <= section[0] < segment[1]:
|
|
771
|
+
break
|
|
772
|
+
else:
|
|
773
|
+
memory_regions.append(segment)
|
|
764
774
|
|
|
765
775
|
elif isinstance(b, (Coff, PE)):
|
|
766
776
|
for section in b.sections:
|
|
@@ -778,7 +788,7 @@ class CFGBase(Analysis):
|
|
|
778
788
|
tpl = (section.min_addr, section.max_addr + 1)
|
|
779
789
|
memory_regions.append(tpl)
|
|
780
790
|
|
|
781
|
-
elif isinstance(b, Hex):
|
|
791
|
+
elif isinstance(b, (Hex, SRec)):
|
|
782
792
|
if b.regions:
|
|
783
793
|
for region_addr, region_size in b.regions:
|
|
784
794
|
memory_regions.append((region_addr, region_addr + region_size))
|
|
@@ -18,7 +18,7 @@ class AMD64ElfGotResolver(IndirectJumpResolver):
|
|
|
18
18
|
super().__init__(project, timeless=True)
|
|
19
19
|
|
|
20
20
|
def filter(self, cfg, addr, func_addr, block, jumpkind):
|
|
21
|
-
if jumpkind
|
|
21
|
+
if not (jumpkind == "Ijk_Call" or (jumpkind == "Ijk_Boring" and addr == func_addr)):
|
|
22
22
|
return False
|
|
23
23
|
return True
|
|
24
24
|
|
|
@@ -12,11 +12,7 @@ _l = logging.getLogger(name=__name__)
|
|
|
12
12
|
|
|
13
13
|
class ArmElfFastResolver(IndirectJumpResolver):
|
|
14
14
|
"""
|
|
15
|
-
Resolves
|
|
16
|
-
manner::
|
|
17
|
-
|
|
18
|
-
ldr r3, [pc+#0x124] ; load a constant from the constant_pool
|
|
19
|
-
blx r3
|
|
15
|
+
Resolves indirect jumps in ARM ELF binaries
|
|
20
16
|
"""
|
|
21
17
|
|
|
22
18
|
def __init__(self, project):
|
|
@@ -29,6 +25,89 @@ class ArmElfFastResolver(IndirectJumpResolver):
|
|
|
29
25
|
return False
|
|
30
26
|
return True
|
|
31
27
|
|
|
28
|
+
def _resolve_default(self, stmt, block, source, cfg, blade):
|
|
29
|
+
"""
|
|
30
|
+
Resolves the indirect jump in ARM ELF binaries where all internal function calls are performed in the following
|
|
31
|
+
manner::
|
|
32
|
+
|
|
33
|
+
ldr r3, [pc+#0x124] ; load a constant from the constant_pool
|
|
34
|
+
blx r3
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
if not isinstance(stmt.data, pyvex.IRExpr.Load):
|
|
38
|
+
return False, []
|
|
39
|
+
if not isinstance(stmt.data.addr, pyvex.IRExpr.Const):
|
|
40
|
+
return False, []
|
|
41
|
+
load_addr = stmt.data.addr.con.value
|
|
42
|
+
load_size = stmt.data.result_size(block.tyenv) // 8
|
|
43
|
+
endness = archinfo.Endness.BE if stmt.data.endness == "Iend_BE" else archinfo.Endness.LE
|
|
44
|
+
|
|
45
|
+
# the next statement should be the default exit
|
|
46
|
+
next_target = next(iter(blade.slice.successors(source)))
|
|
47
|
+
|
|
48
|
+
if not (next_target[0] == block.addr and next_target[1] == DEFAULT_STATEMENT):
|
|
49
|
+
return False, []
|
|
50
|
+
next_tmp = block.next
|
|
51
|
+
if next_tmp.tmp != stmt.tmp:
|
|
52
|
+
return False, []
|
|
53
|
+
|
|
54
|
+
# load the address to jump to
|
|
55
|
+
try:
|
|
56
|
+
target_addr = self.project.loader.memory.unpack_word(load_addr, size=load_size, endness=endness)
|
|
57
|
+
if cfg.tag == "CFGFast":
|
|
58
|
+
cfg._seg_list.occupy(load_addr, load_size, "pointer-array")
|
|
59
|
+
except KeyError:
|
|
60
|
+
return False, []
|
|
61
|
+
|
|
62
|
+
return True, [target_addr]
|
|
63
|
+
|
|
64
|
+
def _resolve_put(self, stmt, block, source, cfg, blade):
|
|
65
|
+
"""
|
|
66
|
+
Resolves the indirect jump in ARM ELF binaries where all internal function calls are performed in the following
|
|
67
|
+
manner::
|
|
68
|
+
|
|
69
|
+
add ip, pc, #0x100000
|
|
70
|
+
add ip, ip, #0x1e000
|
|
71
|
+
ldr pc, [ip,#0x884]!
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
# Get the value of r12 register
|
|
75
|
+
if not isinstance(stmt.data, pyvex.IRExpr.Const):
|
|
76
|
+
return False, []
|
|
77
|
+
if not self.project.arch.register_names[stmt.offset] == "r12":
|
|
78
|
+
return False, []
|
|
79
|
+
load_addr = stmt.data.con.value
|
|
80
|
+
load_size = stmt.data.result_size(block.tyenv) // 8
|
|
81
|
+
endness = self.project.arch.default_endness
|
|
82
|
+
|
|
83
|
+
count = 0
|
|
84
|
+
for next_stmt in block.statements:
|
|
85
|
+
if (
|
|
86
|
+
isinstance(next_stmt, pyvex.IRStmt.WrTmp)
|
|
87
|
+
and isinstance(next_stmt.data, pyvex.IRExpr.Binop)
|
|
88
|
+
and "Add" in next_stmt.data.op
|
|
89
|
+
):
|
|
90
|
+
load_addr += next_stmt.constants[0].value
|
|
91
|
+
count += 1
|
|
92
|
+
|
|
93
|
+
if count != 2:
|
|
94
|
+
return False, []
|
|
95
|
+
|
|
96
|
+
next_target = next(iter(blade.slice.successors(source)))
|
|
97
|
+
|
|
98
|
+
if not next_target[0] == block.addr:
|
|
99
|
+
return False, []
|
|
100
|
+
|
|
101
|
+
# load the address to jump to
|
|
102
|
+
try:
|
|
103
|
+
target_addr = self.project.loader.memory.unpack_word(load_addr, size=load_size, endness=endness)
|
|
104
|
+
if cfg.tag == "CFGFast":
|
|
105
|
+
cfg._seg_list.occupy(load_addr, load_size, "pointer-array")
|
|
106
|
+
except KeyError:
|
|
107
|
+
return False, []
|
|
108
|
+
|
|
109
|
+
return True, [target_addr]
|
|
110
|
+
|
|
32
111
|
def resolve( # pylint:disable=unused-argument
|
|
33
112
|
self, cfg, addr, func_addr, block, jumpkind, func_graph_complete: bool = True, **kwargs
|
|
34
113
|
):
|
|
@@ -64,31 +143,9 @@ class ArmElfFastResolver(IndirectJumpResolver):
|
|
|
64
143
|
return False, []
|
|
65
144
|
|
|
66
145
|
stmt = block.statements[stmt_idx]
|
|
67
|
-
if
|
|
146
|
+
if isinstance(stmt, pyvex.IRStmt.WrTmp):
|
|
147
|
+
return self._resolve_default(stmt, block, source, cfg, b)
|
|
148
|
+
elif isinstance(stmt, pyvex.IRStmt.Put):
|
|
149
|
+
return self._resolve_put(stmt, block, source, cfg, b)
|
|
150
|
+
else:
|
|
68
151
|
return False, []
|
|
69
|
-
if not isinstance(stmt.data, pyvex.IRExpr.Load):
|
|
70
|
-
return False, []
|
|
71
|
-
if not isinstance(stmt.data.addr, pyvex.IRExpr.Const):
|
|
72
|
-
return False, []
|
|
73
|
-
load_addr = stmt.data.addr.con.value
|
|
74
|
-
load_size = stmt.data.result_size(block.tyenv) // 8
|
|
75
|
-
endness = archinfo.Endness.BE if stmt.data.endness == "Iend_BE" else archinfo.Endness.LE
|
|
76
|
-
|
|
77
|
-
# the next statement should be the default exit
|
|
78
|
-
next_target = next(iter(b.slice.successors(source)))
|
|
79
|
-
|
|
80
|
-
if not (next_target[0] == block.addr and next_target[1] == DEFAULT_STATEMENT):
|
|
81
|
-
return False, []
|
|
82
|
-
next_tmp = block.next
|
|
83
|
-
if next_tmp.tmp != stmt.tmp:
|
|
84
|
-
return False, []
|
|
85
|
-
|
|
86
|
-
# load the address to jump to
|
|
87
|
-
try:
|
|
88
|
-
target_addr = self.project.loader.memory.unpack_word(load_addr, size=load_size, endness=endness)
|
|
89
|
-
if cfg.tag == "CFGFast":
|
|
90
|
-
cfg._seg_list.occupy(load_addr, load_size, "pointer-array")
|
|
91
|
-
except KeyError:
|
|
92
|
-
return False, []
|
|
93
|
-
|
|
94
|
-
return True, [target_addr]
|