angr 9.2.115__py3-none-manylinux2014_aarch64.whl → 9.2.117__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/__main__.py +1 -1
- angr/analyses/cfg/cfg_emulated.py +4 -4
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +7 -7
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +3 -2
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +5 -1
- angr/analyses/decompiler/structured_codegen/c.py +10 -13
- angr/analyses/decompiler/structuring/dream.py +3 -4
- angr/analyses/decompiler/structuring/phoenix.py +4 -5
- angr/analyses/decompiler/structuring/structurer_base.py +2 -3
- angr/analyses/decompiler/structuring/structurer_nodes.py +3 -3
- angr/analyses/identifier/functions/free.py +3 -1
- angr/analyses/identifier/identify.py +13 -15
- angr/analyses/identifier/runner.py +2 -2
- angr/analyses/reaching_definitions/dep_graph.py +62 -5
- angr/analyses/reaching_definitions/function_handler_library/__init__.py +11 -0
- angr/analyses/reaching_definitions/function_handler_library/stdio.py +15 -13
- angr/analyses/reaching_definitions/function_handler_library/stdlib.py +17 -11
- angr/analyses/reaching_definitions/function_handler_library/string.py +1 -1
- angr/analyses/reaching_definitions/function_handler_library/unistd.py +2 -2
- angr/analyses/reaching_definitions/rd_state.py +26 -29
- angr/analyses/variable_recovery/engine_vex.py +0 -9
- angr/analyses/vfg.py +4 -4
- angr/calling_conventions.py +4 -2
- angr/concretization_strategies/any_named.py +3 -1
- angr/concretization_strategies/controlled_data.py +4 -2
- angr/concretization_strategies/signed_add.py +3 -1
- angr/engines/concrete.py +3 -1
- angr/engines/pcode/behavior.py +2 -0
- angr/engines/pcode/cc.py +2 -0
- angr/engines/pcode/emulate.py +4 -4
- angr/engines/pcode/engine.py +3 -7
- angr/engines/soot/engine.py +7 -6
- angr/engines/soot/expressions/constants.py +6 -5
- angr/engines/soot/expressions/newArray.py +3 -1
- angr/engines/soot/expressions/newMultiArray.py +3 -1
- angr/engines/soot/statements/goto.py +3 -1
- angr/engines/soot/statements/if_.py +3 -1
- angr/engines/soot/statements/switch.py +3 -1
- angr/engines/soot/statements/throw.py +4 -2
- angr/engines/soot/values/arrayref.py +5 -5
- angr/engines/unicorn.py +8 -7
- angr/engines/vex/heavy/concretizers.py +6 -6
- angr/engines/vex/heavy/dirty.py +20 -22
- angr/engines/vex/heavy/heavy.py +4 -8
- angr/exploration_techniques/director.py +1 -1
- angr/exploration_techniques/driller_core.py +3 -1
- angr/exploration_techniques/tracer.py +2 -1
- angr/knowledge_plugins/key_definitions/live_definitions.py +12 -13
- angr/procedures/cgc/allocate.py +8 -10
- angr/procedures/cgc/deallocate.py +10 -3
- angr/procedures/cgc/fdwait.py +15 -13
- angr/procedures/cgc/random.py +11 -5
- angr/procedures/cgc/receive.py +5 -3
- angr/procedures/cgc/transmit.py +5 -4
- angr/procedures/glibc/__libc_start_main.py +5 -4
- angr/procedures/java_jni/__init__.py +4 -4
- angr/procedures/java_jni/array_operations.py +3 -1
- angr/procedures/java_lang/string.py +1 -1
- angr/procedures/java_util/random.py +3 -1
- angr/procedures/libc/access.py +4 -2
- angr/procedures/libc/feof.py +4 -3
- angr/procedures/libc/fgetc.py +3 -1
- angr/procedures/libc/fgets.py +5 -5
- angr/procedures/libc/fopen.py +5 -4
- angr/procedures/libc/fread.py +4 -3
- angr/procedures/libc/fseek.py +4 -3
- angr/procedures/libc/getdelim.py +7 -4
- angr/procedures/libc/gets.py +4 -2
- angr/procedures/libc/memcmp.py +18 -15
- angr/procedures/libc/memset.py +9 -7
- angr/procedures/libc/puts.py +3 -1
- angr/procedures/libc/snprintf.py +4 -2
- angr/procedures/libc/sprintf.py +3 -1
- angr/procedures/libc/strchr.py +6 -3
- angr/procedures/libc/strcmp.py +5 -3
- angr/procedures/libc/strlen.py +3 -3
- angr/procedures/libc/strncmp.py +28 -28
- angr/procedures/libc/strncpy.py +5 -2
- angr/procedures/libc/strstr.py +10 -7
- angr/procedures/libc/strtol.py +32 -34
- angr/procedures/libc/tolower.py +3 -1
- angr/procedures/libc/toupper.py +3 -1
- angr/procedures/linux_kernel/fstat.py +13 -13
- angr/procedures/linux_kernel/fstat64.py +15 -15
- angr/procedures/linux_kernel/lseek.py +5 -3
- angr/procedures/linux_kernel/sigaction.py +4 -2
- angr/procedures/linux_kernel/sigprocmask.py +5 -3
- angr/procedures/linux_kernel/tgkill.py +3 -1
- angr/procedures/linux_kernel/time.py +7 -4
- angr/procedures/msvcr/fmode.py +3 -1
- angr/procedures/ntdll/exceptions.py +3 -1
- angr/procedures/posix/bzero.py +3 -1
- angr/procedures/posix/fdopen.py +6 -4
- angr/procedures/posix/fork.py +6 -4
- angr/procedures/posix/mmap.py +6 -3
- angr/procedures/posix/poll.py +6 -5
- angr/procedures/posix/readdir.py +10 -7
- angr/procedures/posix/select.py +4 -2
- angr/procedures/posix/send.py +4 -3
- angr/procedures/posix/sigaction.py +4 -2
- angr/procedures/posix/sim_time.py +3 -1
- angr/procedures/posix/strcasecmp.py +3 -1
- angr/procedures/posix/strtok_r.py +10 -7
- angr/procedures/stubs/Redirect.py +3 -1
- angr/procedures/stubs/ReturnChar.py +3 -3
- angr/procedures/stubs/UserHook.py +3 -1
- angr/procedures/stubs/b64_decode.py +3 -1
- angr/procedures/stubs/crazy_scanf.py +6 -4
- angr/procedures/stubs/format_parser.py +13 -15
- angr/procedures/tracer/receive.py +3 -1
- angr/procedures/tracer/transmit.py +3 -1
- angr/procedures/win32/GetLastInputInfo.py +4 -2
- angr/procedures/win32/GetProcessAffinityMask.py +4 -2
- angr/procedures/win32/gethostbyname.py +3 -1
- angr/procedures/win32/heap.py +3 -1
- angr/procedures/win32/local_storage.py +4 -2
- angr/procedures/win32/sim_time.py +7 -4
- angr/procedures/win_user32/chars.py +4 -2
- angr/procedures/win_user32/messagebox.py +3 -1
- angr/sim_procedure.py +7 -7
- angr/sim_state.py +10 -7
- angr/sim_type.py +3 -3
- angr/simos/cgc.py +2 -2
- angr/simos/simos.py +5 -4
- angr/simos/windows.py +5 -5
- angr/state_plugins/heap/heap_brk.py +5 -3
- angr/state_plugins/heap/heap_ptmalloc.py +5 -4
- angr/state_plugins/history.py +7 -5
- angr/state_plugins/light_registers.py +2 -2
- angr/state_plugins/plugin.py +2 -2
- angr/state_plugins/posix.py +28 -26
- angr/state_plugins/preconstrainer.py +2 -1
- angr/state_plugins/solver.py +11 -27
- angr/state_plugins/trace_additions.py +9 -13
- angr/state_plugins/uc_manager.py +4 -2
- angr/state_plugins/unicorn_engine.py +1 -1
- angr/state_plugins/view.py +1 -1
- angr/storage/file.py +21 -26
- angr/storage/memory_mixins/actions_mixin.py +4 -2
- angr/storage/memory_mixins/address_concretization_mixin.py +3 -3
- angr/storage/memory_mixins/default_filler_mixin.py +6 -4
- angr/storage/memory_mixins/javavm_memory/javavm_memory_mixin.py +7 -5
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/cooperation.py +2 -1
- angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +1 -1
- angr/storage/memory_mixins/regioned_memory/region_data.py +3 -1
- angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +1 -1
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +5 -4
- angr/storage/memory_mixins/simple_interface_mixin.py +2 -2
- angr/storage/memory_mixins/size_resolution_mixin.py +3 -1
- angr/storage/memory_mixins/slotted_memory.py +1 -1
- angr/storage/memory_mixins/smart_find_mixin.py +2 -2
- angr/storage/memory_mixins/symbolic_merger_mixin.py +5 -3
- angr/tablespecs.py +3 -3
- {angr-9.2.115.dist-info → angr-9.2.117.dist-info}/METADATA +7 -7
- {angr-9.2.115.dist-info → angr-9.2.117.dist-info}/RECORD +161 -161
- {angr-9.2.115.dist-info → angr-9.2.117.dist-info}/WHEEL +1 -1
- {angr-9.2.115.dist-info → angr-9.2.117.dist-info}/LICENSE +0 -0
- {angr-9.2.115.dist-info → angr-9.2.117.dist-info}/entry_points.txt +0 -0
- {angr-9.2.115.dist-info → angr-9.2.117.dist-info}/top_level.txt +0 -0
angr/__init__.py
CHANGED
angr/__main__.py
CHANGED
|
@@ -1016,7 +1016,7 @@ class CFGEmulated(ForwardAnalysis, CFGBase): # pylint: disable=abstract-method
|
|
|
1016
1016
|
state = self._initial_state.copy()
|
|
1017
1017
|
state.history.jumpkind = jumpkind
|
|
1018
1018
|
self._reset_state_mode(state, "fastpath")
|
|
1019
|
-
state._ip =
|
|
1019
|
+
state._ip = claripy.BVV(ip, self.project.arch.bits)
|
|
1020
1020
|
|
|
1021
1021
|
if jumpkind is not None:
|
|
1022
1022
|
state.history.jumpkind = jumpkind
|
|
@@ -1095,7 +1095,7 @@ class CFGEmulated(ForwardAnalysis, CFGBase): # pylint: disable=abstract-method
|
|
|
1095
1095
|
f = self._pending_function_hints.pop()
|
|
1096
1096
|
if f not in analyzed_addrs:
|
|
1097
1097
|
new_state = self.project.factory.entry_state(mode="fastpath")
|
|
1098
|
-
new_state.ip =
|
|
1098
|
+
new_state.ip = claripy.BVV(f, self.project.arch.bits)
|
|
1099
1099
|
|
|
1100
1100
|
# TOOD: Specially for MIPS
|
|
1101
1101
|
if new_state.arch.name in ("MIPS32", "MIPS64"):
|
|
@@ -1783,7 +1783,7 @@ class CFGEmulated(ForwardAnalysis, CFGBase): # pylint: disable=abstract-method
|
|
|
1783
1783
|
if suc_jumpkind == "Ijk_Ret":
|
|
1784
1784
|
target_addr = job.call_stack.current_return_target
|
|
1785
1785
|
if target_addr is not None:
|
|
1786
|
-
new_state.ip =
|
|
1786
|
+
new_state.ip = claripy.BVV(target_addr, new_state.arch.bits)
|
|
1787
1787
|
|
|
1788
1788
|
if target_addr is None:
|
|
1789
1789
|
# Unlucky...
|
|
@@ -2445,7 +2445,7 @@ class CFGEmulated(ForwardAnalysis, CFGBase): # pylint: disable=abstract-method
|
|
|
2445
2445
|
resolved = True
|
|
2446
2446
|
for t in targets:
|
|
2447
2447
|
new_ex = suc.copy()
|
|
2448
|
-
new_ex.ip =
|
|
2448
|
+
new_ex.ip = claripy.BVV(t, suc.ip.size())
|
|
2449
2449
|
all_successors.append(new_ex)
|
|
2450
2450
|
else:
|
|
2451
2451
|
break
|
|
@@ -634,7 +634,7 @@ class StoreHook:
|
|
|
634
634
|
write_length = len(state.inspect.mem_write_expr)
|
|
635
635
|
else:
|
|
636
636
|
write_length = write_length * state.arch.byte_width
|
|
637
|
-
state.inspect.mem_write_expr =
|
|
637
|
+
state.inspect.mem_write_expr = claripy.BVS("instrumented_store", write_length)
|
|
638
638
|
|
|
639
639
|
|
|
640
640
|
class LoadHook:
|
|
@@ -648,7 +648,7 @@ class LoadHook:
|
|
|
648
648
|
def hook_before(self, state):
|
|
649
649
|
addr = state.inspect.mem_read_address
|
|
650
650
|
size = state.solver.eval(state.inspect.mem_read_length)
|
|
651
|
-
self._var =
|
|
651
|
+
self._var = claripy.BVS("instrumented_load", size * 8)
|
|
652
652
|
state.memory.store(addr, self._var, endness=state.arch.memory_endness)
|
|
653
653
|
|
|
654
654
|
def hook_after(self, state):
|
|
@@ -662,7 +662,7 @@ class PutHook:
|
|
|
662
662
|
|
|
663
663
|
@staticmethod
|
|
664
664
|
def hook(state):
|
|
665
|
-
state.inspect.reg_write_expr =
|
|
665
|
+
state.inspect.reg_write_expr = claripy.BVS(
|
|
666
666
|
"instrumented_put", state.solver.eval(state.inspect.reg_write_length) * 8
|
|
667
667
|
)
|
|
668
668
|
|
|
@@ -678,7 +678,7 @@ class RegisterInitializerHook:
|
|
|
678
678
|
self.value = value
|
|
679
679
|
|
|
680
680
|
def hook(self, state):
|
|
681
|
-
state.registers.store(self.reg_offset,
|
|
681
|
+
state.registers.store(self.reg_offset, claripy.BVV(self.value, self.reg_bits))
|
|
682
682
|
|
|
683
683
|
|
|
684
684
|
class BSSHook:
|
|
@@ -2106,7 +2106,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
2106
2106
|
read_length = claripy.backends.vsa.convert(read_length).upper_bound
|
|
2107
2107
|
if read_length > 16:
|
|
2108
2108
|
return
|
|
2109
|
-
new_read_addr =
|
|
2109
|
+
new_read_addr = claripy.BVV(UninitReadMeta.uninit_read_base, state.arch.bits)
|
|
2110
2110
|
UninitReadMeta.uninit_read_base += read_length
|
|
2111
2111
|
|
|
2112
2112
|
# replace the expression in registers
|
|
@@ -2238,7 +2238,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
2238
2238
|
# blx r0
|
|
2239
2239
|
# It's not a jump table, but we resolve it anyway
|
|
2240
2240
|
jump_target_addr = load_stmt.data.addr.con.value
|
|
2241
|
-
return
|
|
2241
|
+
return claripy.BVV(jump_target_addr, state.arch.bits)
|
|
2242
2242
|
elif isinstance(load_stmt, pyvex.IRStmt.LoadG):
|
|
2243
2243
|
if type(load_stmt.addr) is pyvex.IRExpr.RdTmp:
|
|
2244
2244
|
load_addr_tmp = load_stmt.addr.tmp
|
|
@@ -2254,7 +2254,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
2254
2254
|
# Note that this block has two branches: One goes to 45450, the other one goes to whatever the original
|
|
2255
2255
|
# value of R3 is. Some intensive data-flow analysis is required in this case.
|
|
2256
2256
|
jump_target_addr = load_stmt.addr.con.value
|
|
2257
|
-
return
|
|
2257
|
+
return claripy.BVV(jump_target_addr, state.arch.bits)
|
|
2258
2258
|
else:
|
|
2259
2259
|
raise TypeError("Unsupported address loading statement type %s." % type(load_stmt))
|
|
2260
2260
|
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
from typing import TYPE_CHECKING
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
|
-
import pyvex
|
|
6
5
|
import archinfo
|
|
6
|
+
import claripy
|
|
7
|
+
import pyvex
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
from .... import options, BP_BEFORE
|
|
@@ -45,7 +46,7 @@ class OverwriteTmpValueCallback:
|
|
|
45
46
|
self.gp_value = gp_value
|
|
46
47
|
|
|
47
48
|
def overwrite_tmp_value(self, state):
|
|
48
|
-
state.inspect.tmp_write_expr =
|
|
49
|
+
state.inspect.tmp_write_expr = claripy.BVV(self.gp_value, state.arch.bits)
|
|
49
50
|
|
|
50
51
|
|
|
51
52
|
class MipsElfFastResolver(IndirectJumpResolver):
|
|
@@ -182,7 +182,11 @@ class StackCanarySimplifier(OptimizationPass):
|
|
|
182
182
|
|
|
183
183
|
while True:
|
|
184
184
|
traversed.add(block_addr)
|
|
185
|
-
|
|
185
|
+
try:
|
|
186
|
+
first_block = next(self._get_blocks(block_addr))
|
|
187
|
+
except StopIteration:
|
|
188
|
+
break
|
|
189
|
+
|
|
186
190
|
if first_block is None:
|
|
187
191
|
break
|
|
188
192
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# pylint:disable=missing-class-docstring,too-many-boolean-expressions,unused-argument,no-self-use
|
|
2
2
|
from typing import Optional, Any, TYPE_CHECKING
|
|
3
3
|
from collections.abc import Callable
|
|
4
|
-
from collections import defaultdict
|
|
4
|
+
from collections import defaultdict, Counter
|
|
5
5
|
import logging
|
|
6
6
|
import struct
|
|
7
7
|
|
|
@@ -491,19 +491,16 @@ class CFunction(CConstruct): # pylint:disable=abstract-method
|
|
|
491
491
|
else:
|
|
492
492
|
name = str(variable)
|
|
493
493
|
|
|
494
|
-
# sort by
|
|
494
|
+
# sort by the following:
|
|
495
|
+
# * if it's a a non-basic type
|
|
496
|
+
# * the number of occurrences
|
|
497
|
+
# * the repr of the type itself
|
|
495
498
|
# TODO: The type selection should actually happen during variable unification
|
|
496
499
|
vartypes = [x[1] for x in cvar_and_vartypes]
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
if nonprimitive_vartypes:
|
|
502
|
-
nonprimitive_vartypes = list(
|
|
503
|
-
dict.fromkeys(sorted(nonprimitive_vartypes, key=nonprimitive_vartypes.count, reverse=True))
|
|
504
|
-
)
|
|
505
|
-
vartypes.remove(nonprimitive_vartypes[0])
|
|
506
|
-
vartypes.insert(0, nonprimitive_vartypes[0])
|
|
500
|
+
count = Counter(vartypes)
|
|
501
|
+
vartypes = sorted(
|
|
502
|
+
count.copy(), key=lambda x: (isinstance(x, (SimTypeChar, SimTypeInt, SimTypeFloat)), count[x], repr(x))
|
|
503
|
+
)
|
|
507
504
|
|
|
508
505
|
for i, var_type in enumerate(vartypes):
|
|
509
506
|
if i == 0:
|
|
@@ -2177,8 +2174,8 @@ class CConstant(CExpression):
|
|
|
2177
2174
|
v = refval.content.decode("utf-8")
|
|
2178
2175
|
else:
|
|
2179
2176
|
# it's a string
|
|
2180
|
-
assert isinstance(v, str)
|
|
2181
2177
|
v = refval
|
|
2178
|
+
assert isinstance(v, str)
|
|
2182
2179
|
yield CConstant.str_to_c_str(v), self
|
|
2183
2180
|
elif isinstance(self._type, SimTypePointer) and isinstance(self._type.pts_to, SimTypeWideChar):
|
|
2184
2181
|
refval = self.reference_values[self._type]
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# pylint:disable=multiple-statements,line-too-long,consider-using-enumerate
|
|
2
2
|
from typing import Optional, Any, TYPE_CHECKING
|
|
3
|
-
from collections import OrderedDict as ODict
|
|
4
3
|
import logging
|
|
5
4
|
from collections import defaultdict, OrderedDict
|
|
6
5
|
|
|
@@ -661,7 +660,7 @@ class DreamStructurer(StructurerBase):
|
|
|
661
660
|
i,
|
|
662
661
|
node,
|
|
663
662
|
cmp_expr,
|
|
664
|
-
cases:
|
|
663
|
+
cases: OrderedDict,
|
|
665
664
|
node_default,
|
|
666
665
|
addr,
|
|
667
666
|
addr2nodes,
|
|
@@ -909,7 +908,7 @@ class DreamStructurer(StructurerBase):
|
|
|
909
908
|
head_node_idx: int,
|
|
910
909
|
node_b_addr: int,
|
|
911
910
|
addr2nodes: dict[int, set[CodeNode]],
|
|
912
|
-
) -> tuple[
|
|
911
|
+
) -> tuple[OrderedDict, Any, Any]:
|
|
913
912
|
"""
|
|
914
913
|
Discover all cases for the switch-case structure and build the switch-cases dict.
|
|
915
914
|
|
|
@@ -922,7 +921,7 @@ class DreamStructurer(StructurerBase):
|
|
|
922
921
|
:return: A tuple of (dict of cases, the default node if exists, nodes to remove).
|
|
923
922
|
"""
|
|
924
923
|
|
|
925
|
-
cases:
|
|
924
|
+
cases: OrderedDict[int | tuple[int, ...], SequenceNode] = OrderedDict()
|
|
926
925
|
to_remove = set()
|
|
927
926
|
node_default = addr2nodes.get(node_b_addr, None)
|
|
928
927
|
if node_default is not None:
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# pylint:disable=line-too-long,import-outside-toplevel,import-error,multiple-statements,too-many-boolean-expressions
|
|
2
2
|
from typing import Any, DefaultDict, Optional, TYPE_CHECKING
|
|
3
|
-
from collections import OrderedDict
|
|
4
|
-
from collections import defaultdict
|
|
3
|
+
from collections import defaultdict, OrderedDict
|
|
5
4
|
from enum import Enum
|
|
6
5
|
import logging
|
|
7
6
|
|
|
@@ -1308,8 +1307,8 @@ class PhoenixStructurer(StructurerBase):
|
|
|
1308
1307
|
node_b_addr,
|
|
1309
1308
|
graph,
|
|
1310
1309
|
full_graph,
|
|
1311
|
-
) -> tuple[
|
|
1312
|
-
cases:
|
|
1310
|
+
) -> tuple[OrderedDict, Any, set[Any]]:
|
|
1311
|
+
cases: OrderedDict[int | tuple[int], SequenceNode] = OrderedDict()
|
|
1313
1312
|
to_remove = set()
|
|
1314
1313
|
|
|
1315
1314
|
# it is possible that the default node gets duplicated by other analyses and creates a default node (addr.a)
|
|
@@ -1418,7 +1417,7 @@ class PhoenixStructurer(StructurerBase):
|
|
|
1418
1417
|
self,
|
|
1419
1418
|
head,
|
|
1420
1419
|
cmp_expr,
|
|
1421
|
-
cases:
|
|
1420
|
+
cases: OrderedDict,
|
|
1422
1421
|
node_default_addr: int,
|
|
1423
1422
|
node_default,
|
|
1424
1423
|
addr,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# pylint:disable=unused-argument
|
|
2
2
|
from typing import Optional, Any, TYPE_CHECKING
|
|
3
|
-
from collections import OrderedDict as ODict
|
|
4
3
|
from collections import defaultdict, OrderedDict
|
|
5
4
|
import logging
|
|
6
5
|
|
|
@@ -739,8 +738,8 @@ class StructurerBase(Analysis):
|
|
|
739
738
|
#
|
|
740
739
|
|
|
741
740
|
def _reorganize_switch_cases(
|
|
742
|
-
self, cases:
|
|
743
|
-
) ->
|
|
741
|
+
self, cases: OrderedDict[int | tuple[int, ...], SequenceNode]
|
|
742
|
+
) -> OrderedDict[int | tuple[int, ...], SequenceNode]:
|
|
744
743
|
new_cases = OrderedDict()
|
|
745
744
|
|
|
746
745
|
caseid2gotoaddrs = {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pylint:disable=missing-class-docstring
|
|
2
2
|
from typing import Any
|
|
3
|
-
from collections import OrderedDict
|
|
3
|
+
from collections import OrderedDict
|
|
4
4
|
|
|
5
5
|
import claripy
|
|
6
6
|
import ailment
|
|
@@ -358,9 +358,9 @@ class SwitchCaseNode(BaseNode):
|
|
|
358
358
|
"addr",
|
|
359
359
|
)
|
|
360
360
|
|
|
361
|
-
def __init__(self, switch_expr, cases:
|
|
361
|
+
def __init__(self, switch_expr, cases: OrderedDict[int | tuple[int, ...], SequenceNode], default_node, addr=None):
|
|
362
362
|
self.switch_expr = switch_expr
|
|
363
|
-
self.cases:
|
|
363
|
+
self.cases: OrderedDict[int | tuple[int, ...], SequenceNode] = cases
|
|
364
364
|
self.default_node = default_node
|
|
365
365
|
self.addr = addr
|
|
366
366
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
+
import claripy
|
|
4
|
+
|
|
3
5
|
from ..func import Func, TestData
|
|
4
6
|
from ..errors import IdentifierException
|
|
5
7
|
|
|
@@ -52,7 +54,7 @@ class free(Func):
|
|
|
52
54
|
test_input = [malloc_vals[-1]]
|
|
53
55
|
test_output = [None]
|
|
54
56
|
return_val = None
|
|
55
|
-
state.memory.store(malloc_vals[-1],
|
|
57
|
+
state.memory.store(malloc_vals[-1], claripy.BVS("some_data", 0x80 * 8))
|
|
56
58
|
free_test = TestData(test_input, test_output, return_val, max_steps)
|
|
57
59
|
state = runner.get_out_state(func, free_test, initial_state=state)
|
|
58
60
|
if state is None:
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from collections import defaultdict
|
|
2
3
|
from itertools import chain
|
|
3
|
-
import logging
|
|
4
|
-
|
|
5
|
-
from networkx import NetworkXError
|
|
6
4
|
|
|
5
|
+
import claripy
|
|
7
6
|
from cle.backends.cgc import CGC
|
|
7
|
+
from networkx import NetworkXError
|
|
8
8
|
|
|
9
9
|
from .errors import IdentifierException
|
|
10
10
|
from .functions import Functions
|
|
@@ -75,9 +75,7 @@ class Identifier(Analysis):
|
|
|
75
75
|
|
|
76
76
|
self.base_symbolic_state = self.make_symbolic_state(self.project, self._reg_list)
|
|
77
77
|
self.base_symbolic_state.options.discard(options.SUPPORT_FLOATING_POINT)
|
|
78
|
-
self.base_symbolic_state.regs.bp = self.
|
|
79
|
-
"sreg_" + "ebp" + "-", self.project.arch.bits
|
|
80
|
-
)
|
|
78
|
+
self.base_symbolic_state.regs.bp = claripy.BVS("sreg_" + "ebp" + "-", self.project.arch.bits)
|
|
81
79
|
|
|
82
80
|
for f in self._cfg.functions.values():
|
|
83
81
|
if f.is_syscall:
|
|
@@ -308,7 +306,7 @@ class Identifier(Analysis):
|
|
|
308
306
|
|
|
309
307
|
func_info = self.func_info[self.block_to_func[addr_trace[0]]]
|
|
310
308
|
for i in range(func_info.frame_size // self.project.arch.bytes + 5):
|
|
311
|
-
s.stack_push(
|
|
309
|
+
s.stack_push(claripy.BVS("var_" + hex(i), self.project.arch.bits))
|
|
312
310
|
|
|
313
311
|
if func_info.bp_based:
|
|
314
312
|
s.regs.bp = s.regs.sp + func_info.bp_sp_diff
|
|
@@ -322,7 +320,7 @@ class Identifier(Analysis):
|
|
|
322
320
|
for ss in simgr.active:
|
|
323
321
|
# todo could write symbolic data to pointers passed to functions
|
|
324
322
|
if ss.history.jumpkind == "Ijk_Call":
|
|
325
|
-
ss.regs.eax =
|
|
323
|
+
ss.regs.eax = claripy.BVS("unconstrained_ret_%#x" % ss.addr, ss.arch.bits)
|
|
326
324
|
ss.regs.ip = ss.stack_pop()
|
|
327
325
|
ss.history.jumpkind = "Ijk_Ret"
|
|
328
326
|
if ss.addr == addr_trace[0]:
|
|
@@ -333,7 +331,7 @@ class Identifier(Analysis):
|
|
|
333
331
|
if len(simgr.unconstrained) > 0:
|
|
334
332
|
s = simgr.unconstrained[0]
|
|
335
333
|
if s.history.jumpkind == "Ijk_Call":
|
|
336
|
-
s.regs.eax =
|
|
334
|
+
s.regs.eax = claripy.BVS("unconstrained_ret", s.arch.bits)
|
|
337
335
|
s.regs.ip = s.stack_pop()
|
|
338
336
|
s.history.jumpkind = "Ijk_Ret"
|
|
339
337
|
s.regs.ip = addr_trace[0]
|
|
@@ -437,7 +435,7 @@ class Identifier(Analysis):
|
|
|
437
435
|
state = input_state.copy()
|
|
438
436
|
# overwrite all registers
|
|
439
437
|
for reg in reg_list:
|
|
440
|
-
state.registers.store(reg,
|
|
438
|
+
state.registers.store(reg, claripy.BVS("sreg_" + reg + "-", project.arch.bits, explicit_name=True))
|
|
441
439
|
# restore sp
|
|
442
440
|
state.regs.sp = input_state.regs.sp
|
|
443
441
|
# restore bp
|
|
@@ -600,11 +598,11 @@ class Identifier(Analysis):
|
|
|
600
598
|
for bl_addr in func.block_addrs:
|
|
601
599
|
all_addrs.update(set(self._cfg.model.get_any_node(bl_addr).instruction_addrs))
|
|
602
600
|
|
|
603
|
-
sp =
|
|
601
|
+
sp = claripy.BVS("sym_sp", self.project.arch.bits, explicit_name=True)
|
|
604
602
|
main_state.regs.sp = sp
|
|
605
603
|
bp = None
|
|
606
604
|
if bp_based:
|
|
607
|
-
bp =
|
|
605
|
+
bp = claripy.BVS("sym_bp", self.project.arch.bits, explicit_name=True)
|
|
608
606
|
main_state.regs.bp = bp
|
|
609
607
|
|
|
610
608
|
stack_vars = set()
|
|
@@ -731,7 +729,7 @@ class Identifier(Analysis):
|
|
|
731
729
|
def _sets_ebp_from_esp(self, state, addr):
|
|
732
730
|
state = state.copy()
|
|
733
731
|
state.regs.ip = addr
|
|
734
|
-
state.regs.sp =
|
|
732
|
+
state.regs.sp = claripy.BVS("sym_sp", 32, explicit_name=True)
|
|
735
733
|
succ = self.project.factory.successors(state).all_successors[0]
|
|
736
734
|
|
|
737
735
|
diff = state.regs.sp - succ.regs.bp
|
|
@@ -818,7 +816,7 @@ class Identifier(Analysis):
|
|
|
818
816
|
options.TRACK_CONSTRAINT_ACTIONS,
|
|
819
817
|
}
|
|
820
818
|
)
|
|
821
|
-
symbolic_stack =
|
|
819
|
+
symbolic_stack = claripy.BVS("symbolic_stack", project.arch.bits * stack_length)
|
|
822
820
|
initial_state.memory.store(initial_state.regs.sp, symbolic_stack)
|
|
823
821
|
if initial_state.arch.bp_offset != initial_state.arch.sp_offset:
|
|
824
822
|
initial_state.regs.bp = initial_state.regs.sp + 20 * initial_state.arch.bytes
|
|
@@ -835,7 +833,7 @@ class Identifier(Analysis):
|
|
|
835
833
|
symbolic_state = input_state.copy()
|
|
836
834
|
# overwrite all registers
|
|
837
835
|
for reg in reg_list:
|
|
838
|
-
symbolic_state.registers.store(reg,
|
|
836
|
+
symbolic_state.registers.store(reg, claripy.BVS("sreg_" + reg + "-", project.arch.bits))
|
|
839
837
|
# restore sp
|
|
840
838
|
symbolic_state.regs.sp = input_state.regs.sp
|
|
841
839
|
# restore bp
|
|
@@ -52,7 +52,7 @@ class Runner:
|
|
|
52
52
|
entry_state = self.project.factory.entry_state(add_options=add_options, remove_options=remove_options)
|
|
53
53
|
|
|
54
54
|
# map the CGC flag page
|
|
55
|
-
fake_flag_data =
|
|
55
|
+
fake_flag_data = claripy.BVV(FLAG_DATA)
|
|
56
56
|
entry_state.memory.store(0x4347C000, fake_flag_data)
|
|
57
57
|
# map the place where I put arguments
|
|
58
58
|
entry_state.memory.map_region(0x2000, 0x10000, 7)
|
|
@@ -176,7 +176,7 @@ class Runner:
|
|
|
176
176
|
buf = state.solver.eval(state.regs.ebx)
|
|
177
177
|
for i in range(count):
|
|
178
178
|
a = random.randint(0, 255)
|
|
179
|
-
state.memory.store(buf + i,
|
|
179
|
+
state.memory.store(buf + i, claripy.BVV(a, 8))
|
|
180
180
|
|
|
181
181
|
def get_base_call_state(self, function, test_data, initial_state=None, concrete_rand=False):
|
|
182
182
|
curr_buf_loc = 0x2000
|
|
@@ -213,6 +213,68 @@ class DepGraph:
|
|
|
213
213
|
|
|
214
214
|
self.graph.add_edge(memory_location_definition, definition)
|
|
215
215
|
|
|
216
|
+
@overload
|
|
217
|
+
def find_definitions(
|
|
218
|
+
self,
|
|
219
|
+
*,
|
|
220
|
+
kind: type[A],
|
|
221
|
+
**kwargs: Any,
|
|
222
|
+
) -> list[Definition[A]]: ...
|
|
223
|
+
|
|
224
|
+
@overload
|
|
225
|
+
def find_definitions(
|
|
226
|
+
self,
|
|
227
|
+
*,
|
|
228
|
+
kind: Literal[AtomKind.REGISTER] = AtomKind.REGISTER,
|
|
229
|
+
**kwargs: Any,
|
|
230
|
+
) -> list[Definition[Register]]: ...
|
|
231
|
+
|
|
232
|
+
@overload
|
|
233
|
+
def find_definitions(
|
|
234
|
+
self,
|
|
235
|
+
*,
|
|
236
|
+
kind: Literal[AtomKind.MEMORY] = AtomKind.MEMORY,
|
|
237
|
+
**kwargs: Any,
|
|
238
|
+
) -> list[Definition[MemoryLocation]]: ...
|
|
239
|
+
|
|
240
|
+
@overload
|
|
241
|
+
def find_definitions(
|
|
242
|
+
self,
|
|
243
|
+
*,
|
|
244
|
+
kind: Literal[AtomKind.TMP] = AtomKind.TMP,
|
|
245
|
+
**kwargs: Any,
|
|
246
|
+
) -> list[Definition[Tmp]]: ...
|
|
247
|
+
|
|
248
|
+
@overload
|
|
249
|
+
def find_definitions(
|
|
250
|
+
self,
|
|
251
|
+
*,
|
|
252
|
+
kind: Literal[AtomKind.CONSTANT] = AtomKind.CONSTANT,
|
|
253
|
+
**kwargs: Any,
|
|
254
|
+
) -> list[Definition[ConstantSrc]]: ...
|
|
255
|
+
|
|
256
|
+
@overload
|
|
257
|
+
def find_definitions(
|
|
258
|
+
self,
|
|
259
|
+
*,
|
|
260
|
+
kind: Literal[AtomKind.GUARD] = AtomKind.GUARD,
|
|
261
|
+
**kwargs: Any,
|
|
262
|
+
) -> list[Definition[GuardUse]]: ...
|
|
263
|
+
|
|
264
|
+
@overload
|
|
265
|
+
def find_definitions(
|
|
266
|
+
self,
|
|
267
|
+
*,
|
|
268
|
+
reg_name: int | str = ...,
|
|
269
|
+
**kwargs: Any,
|
|
270
|
+
) -> list[Definition[Register]]: ...
|
|
271
|
+
|
|
272
|
+
@overload
|
|
273
|
+
def find_definitions(self, *, stack_offset: int = ..., **kwargs: Any) -> list[Definition[MemoryLocation]]: ...
|
|
274
|
+
|
|
275
|
+
@overload
|
|
276
|
+
def find_definitions(self, *, const_val: int = ..., **kwargs: Any) -> list[Definition[ConstantSrc]]: ...
|
|
277
|
+
|
|
216
278
|
def find_definitions(self, **kwargs) -> list[Definition]:
|
|
217
279
|
"""
|
|
218
280
|
Filter the definitions present in the graph based on various criteria.
|
|
@@ -299,11 +361,6 @@ class DepGraph:
|
|
|
299
361
|
self, starts: Definition[Atom] | Iterable[Definition[Atom]], *, const_val: int = ..., **kwargs: Any
|
|
300
362
|
) -> list[Definition[ConstantSrc]]: ...
|
|
301
363
|
|
|
302
|
-
@overload
|
|
303
|
-
def find_all_predecessors(
|
|
304
|
-
self, starts: Definition[Atom] | Iterable[Definition[Atom]], **kwargs: Any
|
|
305
|
-
) -> list[Definition[Atom]]: ...
|
|
306
|
-
|
|
307
364
|
def find_all_predecessors(self, starts, **kwargs):
|
|
308
365
|
"""
|
|
309
366
|
Filter the ancestors of the given start node or nodes that match various criteria.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from .stdlib import LibcStdlibHandlers, EnvironAtom, SystemAtom, ExecveAtom
|
|
2
|
+
from .stdio import LibcStdioHandlers, StdoutAtom, StdinAtom
|
|
3
|
+
from .unistd import LibcUnistdHandlers
|
|
4
|
+
from .string import LibcStringHandlers
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LibcHandlers(LibcStdlibHandlers, LibcStdioHandlers, LibcUnistdHandlers, LibcStringHandlers):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
__all__ = ["EnvironAtom", "SystemAtom", "ExecveAtom", "StdoutAtom", "StdinAtom", "LibcHandlers"]
|
|
@@ -19,10 +19,10 @@ _l = logging.getLogger(__name__)
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class StdoutAtom(Atom):
|
|
22
|
-
def __init__(self, sink: str):
|
|
22
|
+
def __init__(self, sink: str, size: int | None):
|
|
23
23
|
self.nonce = random.randint(0, 999999999999)
|
|
24
24
|
self.sink = sink
|
|
25
|
-
super().__init__(1)
|
|
25
|
+
super().__init__(size if size is not None else 1)
|
|
26
26
|
|
|
27
27
|
def _identity(self):
|
|
28
28
|
return (self.nonce,)
|
|
@@ -32,10 +32,10 @@ class StdoutAtom(Atom):
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
class StdinAtom(Atom):
|
|
35
|
-
def __init__(self, source: str):
|
|
35
|
+
def __init__(self, source: str, size: int | None):
|
|
36
36
|
self.nonce = random.randint(0, 999999999999)
|
|
37
37
|
self.source = source
|
|
38
|
-
super().__init__(1)
|
|
38
|
+
super().__init__(size if size is not None else 1)
|
|
39
39
|
|
|
40
40
|
def _identity(self):
|
|
41
41
|
return (self.nonce,)
|
|
@@ -83,19 +83,19 @@ class LibcStdioHandlers(FunctionHandler):
|
|
|
83
83
|
@FunctionCallDataUnwrapped.decorate
|
|
84
84
|
def handle_impl_printf(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
85
85
|
result, source_atoms = handle_printf(state, data, 0)
|
|
86
|
-
dst_atoms = StdoutAtom("printf")
|
|
86
|
+
dst_atoms = StdoutAtom("printf", len(result) if result is not None else None)
|
|
87
87
|
data.depends(dst_atoms, source_atoms, value=result)
|
|
88
88
|
|
|
89
89
|
@FunctionCallDataUnwrapped.decorate
|
|
90
90
|
def handle_impl_dprintf(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
91
91
|
result, source_atoms = handle_printf(state, data, 1)
|
|
92
|
-
dst_atoms = StdoutAtom("dprintf")
|
|
92
|
+
dst_atoms = StdoutAtom("dprintf", len(result) if result is not None else None)
|
|
93
93
|
data.depends(dst_atoms, source_atoms, value=result)
|
|
94
94
|
|
|
95
95
|
@FunctionCallDataUnwrapped.decorate
|
|
96
96
|
def handle_impl_fprintf(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
97
97
|
result, source_atoms = handle_printf(state, data, 1)
|
|
98
|
-
dst_atoms = StdoutAtom("fprintf")
|
|
98
|
+
dst_atoms = StdoutAtom("fprintf", len(result) if result is not None else None)
|
|
99
99
|
data.depends(dst_atoms, source_atoms, value=result)
|
|
100
100
|
|
|
101
101
|
@FunctionCallDataUnwrapped.decorate
|
|
@@ -108,6 +108,8 @@ class LibcStdioHandlers(FunctionHandler):
|
|
|
108
108
|
def handle_impl_snprintf(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
109
109
|
result, source_atoms = handle_printf(state, data, 2)
|
|
110
110
|
size = state.get_concrete_value(data.args_atoms[1]) or 2
|
|
111
|
+
if result is not None:
|
|
112
|
+
size = min(size, len(result) // 8)
|
|
111
113
|
dst_atoms = state.deref(data.args_atoms[0], size=size)
|
|
112
114
|
data.depends(dst_atoms, source_atoms, value=result)
|
|
113
115
|
|
|
@@ -126,7 +128,7 @@ class LibcStdioHandlers(FunctionHandler):
|
|
|
126
128
|
|
|
127
129
|
@FunctionCallDataUnwrapped.decorate
|
|
128
130
|
def handle_impl_scanf(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
129
|
-
handle_scanf(state, data, 0, {StdinAtom("scanf")})
|
|
131
|
+
handle_scanf(state, data, 0, {StdinAtom("scanf", None)})
|
|
130
132
|
|
|
131
133
|
handle_impl___isoc99_scanf = handle_impl_scanf
|
|
132
134
|
|
|
@@ -140,13 +142,13 @@ class LibcStdioHandlers(FunctionHandler):
|
|
|
140
142
|
def handle_impl_fgets(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
141
143
|
size = state.get_concrete_value(data.args_atoms[1]) or 2
|
|
142
144
|
dst_atom = state.deref(data.args_atoms[0], size)
|
|
143
|
-
input_value = claripy.BVS("weh", 8).concat(claripy.BVV(0, 8))
|
|
144
|
-
data.depends(dst_atom, StdinAtom("fgets"), value=input_value)
|
|
145
|
+
input_value = claripy.BVS("weh", (size - 1) * 8).concat(claripy.BVV(0, 8))
|
|
146
|
+
data.depends(dst_atom, StdinAtom("fgets", size), value=input_value)
|
|
145
147
|
data.depends(data.ret_atoms, data.args_atoms[0])
|
|
146
148
|
|
|
147
149
|
@FunctionCallDataUnwrapped.decorate
|
|
148
150
|
def handle_impl_fgetc(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
149
|
-
data.depends(data.ret_atoms, StdinAtom(data.function.name))
|
|
151
|
+
data.depends(data.ret_atoms, StdinAtom(data.function.name, 1))
|
|
150
152
|
|
|
151
153
|
handle_impl_getchar = handle_impl_getc = handle_impl_fgetc
|
|
152
154
|
|
|
@@ -155,14 +157,14 @@ class LibcStdioHandlers(FunctionHandler):
|
|
|
155
157
|
size = state.get_concrete_value(data.args_atoms[1]) or 1
|
|
156
158
|
nmemb = state.get_concrete_value(data.args_atoms[1]) or 2
|
|
157
159
|
dst_atom = state.deref(data.args_atoms[0], size * nmemb)
|
|
158
|
-
data.depends(dst_atom, StdinAtom("fread"))
|
|
160
|
+
data.depends(dst_atom, StdinAtom("fread", size * nmemb))
|
|
159
161
|
|
|
160
162
|
@FunctionCallDataUnwrapped.decorate
|
|
161
163
|
def handle_impl_fwrite(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
162
164
|
size = state.get_concrete_value(data.args_atoms[1]) or 1
|
|
163
165
|
nmemb = state.get_concrete_value(data.args_atoms[1]) or 2
|
|
164
166
|
src_atom = state.deref(data.args_atoms[0], size * nmemb)
|
|
165
|
-
data.depends(StdoutAtom("fwrite"), src_atom, value=state.get_values(src_atom))
|
|
167
|
+
data.depends(StdoutAtom("fwrite", size * nmemb), src_atom, value=state.get_values(src_atom))
|
|
166
168
|
|
|
167
169
|
|
|
168
170
|
def handle_printf(
|