angr 9.2.79__py3-none-win_amd64.whl → 9.2.81__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 +30 -5
- angr/analyses/cfg/cfg_fast.py +128 -3
- angr/analyses/decompiler/ail_simplifier.py +8 -0
- angr/analyses/decompiler/clinic.py +6 -2
- angr/analyses/decompiler/decompilation_options.py +9 -0
- angr/analyses/decompiler/optimization_passes/__init__.py +4 -0
- angr/analyses/decompiler/optimization_passes/multi_simplifier.py +0 -12
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +8 -5
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +2 -25
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +14 -2
- angr/analyses/decompiler/region_simplifiers/ifelse.py +19 -10
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +4 -2
- angr/analyses/decompiler/utils.py +8 -5
- angr/analyses/propagator/engine_ail.py +3 -1
- angr/analyses/propagator/engine_vex.py +61 -9
- angr/analyses/propagator/propagator.py +24 -15
- angr/analyses/reaching_definitions/engine_ail.py +1 -1
- angr/analyses/reaching_definitions/rd_state.py +4 -4
- angr/analyses/stack_pointer_tracker.py +55 -0
- angr/callable.py +4 -4
- angr/calling_conventions.py +11 -7
- angr/engines/light/engine.py +30 -18
- angr/knowledge_plugins/propagations/propagation_model.py +4 -0
- angr/knowledge_plugins/propagations/states.py +54 -4
- angr/lib/angr_native.dll +0 -0
- angr/procedures/definitions/__init__.py +2 -1
- angr/procedures/definitions/ntoskrnl.py +9 -0
- angr/procedures/win32_kernel/ExAllocatePool.py +12 -0
- angr/procedures/win32_kernel/ExFreePoolWithTag.py +7 -0
- angr/procedures/win32_kernel/__init__.py +3 -0
- angr/storage/memory_mixins/__init__.py +1 -1
- angr/utils/funcid.py +128 -0
- {angr-9.2.79.dist-info → angr-9.2.81.dist-info}/METADATA +6 -6
- {angr-9.2.79.dist-info → angr-9.2.81.dist-info}/RECORD +42 -37
- tests/analyses/cfg/test_cfgfast.py +24 -0
- tests/analyses/decompiler/test_decompiler.py +128 -0
- tests/analyses/test_constantpropagation.py +35 -0
- {angr-9.2.79.dist-info → angr-9.2.81.dist-info}/LICENSE +0 -0
- {angr-9.2.79.dist-info → angr-9.2.81.dist-info}/WHEEL +0 -0
- {angr-9.2.79.dist-info → angr-9.2.81.dist-info}/entry_points.txt +0 -0
- {angr-9.2.79.dist-info → angr-9.2.81.dist-info}/top_level.txt +0 -0
|
@@ -289,6 +289,9 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
289
289
|
if self._base_state is not None:
|
|
290
290
|
self._base_state.options.add(sim_options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS)
|
|
291
291
|
self._base_state.options.add(sim_options.SYMBOL_FILL_UNCONSTRAINED_MEMORY)
|
|
292
|
+
|
|
293
|
+
self.model.input_states[block_key] = state.copy()
|
|
294
|
+
|
|
292
295
|
state = engine.process(
|
|
293
296
|
state,
|
|
294
297
|
block=block,
|
|
@@ -305,8 +308,7 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
305
308
|
|
|
306
309
|
self.model.node_iterations[block_key] += 1
|
|
307
310
|
self.model.states[block_key] = state
|
|
308
|
-
|
|
309
|
-
self.model.block_initial_reg_values.update(state.block_initial_reg_values)
|
|
311
|
+
self.model.block_initial_reg_values.update(state.block_initial_reg_values)
|
|
310
312
|
|
|
311
313
|
if self.model.replacements is None:
|
|
312
314
|
self.model.replacements = state._replacements
|
|
@@ -325,19 +327,26 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
325
327
|
def _process_input_state_for_successor(
|
|
326
328
|
self, node, successor, input_state: Union[PropagatorAILState, PropagatorVEXState]
|
|
327
329
|
):
|
|
328
|
-
if self._only_consts
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
330
|
+
if self._only_consts:
|
|
331
|
+
if isinstance(input_state, PropagatorAILState):
|
|
332
|
+
key = node.addr, successor.addr
|
|
333
|
+
if key in self.model.block_initial_reg_values:
|
|
334
|
+
input_state: PropagatorAILState = input_state.copy()
|
|
335
|
+
for reg_atom, reg_value in self.model.block_initial_reg_values[key]:
|
|
336
|
+
input_state.store_register(
|
|
337
|
+
reg_atom,
|
|
338
|
+
PropValue(
|
|
339
|
+
claripy.BVV(reg_value.value, reg_value.bits),
|
|
340
|
+
offset_and_details={0: Detail(reg_atom.size, reg_value, self._initial_codeloc)},
|
|
341
|
+
),
|
|
342
|
+
)
|
|
343
|
+
return input_state
|
|
344
|
+
elif isinstance(input_state, PropagatorVEXState):
|
|
345
|
+
key = node.addr, successor.addr
|
|
346
|
+
if key in self.model.block_initial_reg_values:
|
|
347
|
+
input_state: PropagatorVEXState = input_state.copy()
|
|
348
|
+
for reg_offset, reg_size, value in self.model.block_initial_reg_values[key]:
|
|
349
|
+
input_state.store_register(reg_offset, reg_size, claripy.BVV(value, reg_size * 8))
|
|
341
350
|
return input_state
|
|
342
351
|
|
|
343
352
|
def _intra_analysis(self):
|
|
@@ -141,7 +141,7 @@ class SimEngineRDAIL(
|
|
|
141
141
|
return handler(expr)
|
|
142
142
|
else:
|
|
143
143
|
self.l.warning("Unsupported expression type %s.", type(expr).__name__)
|
|
144
|
-
return
|
|
144
|
+
return MultiValues(self.state.top(self.arch.bits))
|
|
145
145
|
|
|
146
146
|
def _ail_handle_Assignment(self, stmt):
|
|
147
147
|
"""
|
|
@@ -566,19 +566,19 @@ class ReachingDefinitionsState:
|
|
|
566
566
|
@overload
|
|
567
567
|
def deref(
|
|
568
568
|
self,
|
|
569
|
-
pointer: Union[
|
|
569
|
+
pointer: Union[int, claripy.ast.bv.BV, HeapAddress, SpOffset],
|
|
570
570
|
size: Union[int, DerefSize],
|
|
571
571
|
endness: str = ...,
|
|
572
|
-
) ->
|
|
572
|
+
) -> Optional[MemoryLocation]:
|
|
573
573
|
...
|
|
574
574
|
|
|
575
575
|
@overload
|
|
576
576
|
def deref(
|
|
577
577
|
self,
|
|
578
|
-
pointer: Union[
|
|
578
|
+
pointer: Union[MultiValues, Atom, Definition, Iterable[Atom], Iterable[Definition]],
|
|
579
579
|
size: Union[int, DerefSize],
|
|
580
580
|
endness: str = ...,
|
|
581
|
-
) ->
|
|
581
|
+
) -> Set[MemoryLocation]:
|
|
582
582
|
...
|
|
583
583
|
|
|
584
584
|
def deref(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# pylint:disable=abstract-method,ungrouped-imports
|
|
2
2
|
|
|
3
3
|
from typing import Set, List, Optional, TYPE_CHECKING
|
|
4
|
+
import re
|
|
4
5
|
import logging
|
|
5
6
|
|
|
6
7
|
import pyvex
|
|
@@ -286,6 +287,9 @@ class CouldNotResolveException(Exception):
|
|
|
286
287
|
"""
|
|
287
288
|
|
|
288
289
|
|
|
290
|
+
IROP_CONVERT_REGEX = re.compile(r"^Iop_(\d+)(U{0,1})to(\d+)(U{0,1})$")
|
|
291
|
+
|
|
292
|
+
|
|
289
293
|
class StackPointerTracker(Analysis, ForwardAnalysis):
|
|
290
294
|
"""
|
|
291
295
|
Track the offset of stack pointer at the end of each basic block of a function.
|
|
@@ -366,6 +370,42 @@ class StackPointerTracker(Analysis, ForwardAnalysis):
|
|
|
366
370
|
else:
|
|
367
371
|
return self.offset_before(instr_addrs[0], reg)
|
|
368
372
|
|
|
373
|
+
def _constant_for(self, addr, pre_or_post, reg):
|
|
374
|
+
try:
|
|
375
|
+
s = self._state_for(addr, pre_or_post)
|
|
376
|
+
if s is None:
|
|
377
|
+
return TOP
|
|
378
|
+
regval = dict(s.regs)[reg]
|
|
379
|
+
except KeyError:
|
|
380
|
+
return TOP
|
|
381
|
+
if type(regval) is Constant:
|
|
382
|
+
return regval.val
|
|
383
|
+
return TOP
|
|
384
|
+
|
|
385
|
+
def constant_after(self, addr, reg):
|
|
386
|
+
return self._constant_for(addr, "post", reg)
|
|
387
|
+
|
|
388
|
+
def constant_before(self, addr, reg):
|
|
389
|
+
return self._constant_for(addr, "pre", reg)
|
|
390
|
+
|
|
391
|
+
def constant_after_block(self, block_addr, reg):
|
|
392
|
+
if block_addr not in self._blocks:
|
|
393
|
+
return TOP
|
|
394
|
+
instr_addrs = self._blocks[block_addr].instruction_addrs
|
|
395
|
+
if len(instr_addrs) == 0:
|
|
396
|
+
return TOP
|
|
397
|
+
else:
|
|
398
|
+
return self.constant_after(instr_addrs[-1], reg)
|
|
399
|
+
|
|
400
|
+
def constant_before_block(self, block_addr, reg):
|
|
401
|
+
if block_addr not in self._blocks:
|
|
402
|
+
return TOP
|
|
403
|
+
instr_addrs = self._blocks[block_addr].instruction_addrs
|
|
404
|
+
if len(instr_addrs) == 0:
|
|
405
|
+
return TOP
|
|
406
|
+
else:
|
|
407
|
+
return self.constant_before(instr_addrs[0], reg)
|
|
408
|
+
|
|
369
409
|
@property
|
|
370
410
|
def inconsistent(self):
|
|
371
411
|
return any(self.inconsistent_for(r) for r in self.reg_offsets)
|
|
@@ -515,6 +555,21 @@ class StackPointerTracker(Analysis, ForwardAnalysis):
|
|
|
515
555
|
return Constant(expr.con.value)
|
|
516
556
|
elif type(expr) is pyvex.IRExpr.Get:
|
|
517
557
|
return state.get(expr.offset)
|
|
558
|
+
elif type(expr) is pyvex.IRExpr.Unop:
|
|
559
|
+
m = IROP_CONVERT_REGEX.match(expr.op)
|
|
560
|
+
if m is not None:
|
|
561
|
+
from_bits = int(m.group(1))
|
|
562
|
+
# from_unsigned = m.group(2) == "U"
|
|
563
|
+
to_bits = int(m.group(3))
|
|
564
|
+
# to_unsigned = m.group(4) == "U"
|
|
565
|
+
v = resolve_expr(expr.args[0])
|
|
566
|
+
if not isinstance(v, Constant):
|
|
567
|
+
return TOP
|
|
568
|
+
if from_bits > to_bits:
|
|
569
|
+
# truncation
|
|
570
|
+
mask = (1 << to_bits) - 1
|
|
571
|
+
return Constant(v.val & mask)
|
|
572
|
+
return v
|
|
518
573
|
elif self.track_mem and type(expr) is pyvex.IRExpr.Load:
|
|
519
574
|
return state.load(_resolve_expr(expr.addr))
|
|
520
575
|
raise CouldNotResolveException()
|
angr/callable.py
CHANGED
|
@@ -74,10 +74,10 @@ class Callable:
|
|
|
74
74
|
self.perform_call(*args, prototype=prototype)
|
|
75
75
|
if self.result_state is not None and prototype.returnty is not None:
|
|
76
76
|
loc = self._cc.return_val(prototype.returnty)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
if loc is not None:
|
|
78
|
+
val = loc.get_value(self.result_state, stack_base=self.result_state.regs.sp - self._cc.STACKARG_SP_DIFF)
|
|
79
|
+
return self.result_state.solver.simplify(val)
|
|
80
|
+
return None
|
|
81
81
|
|
|
82
82
|
def perform_call(self, *args, prototype=None):
|
|
83
83
|
prototype = SimCC.guess_prototype(args, prototype or self._func_ty).with_arch(self._project.arch)
|
angr/calling_conventions.py
CHANGED
|
@@ -1592,6 +1592,7 @@ class SimCCAMD64LinuxSyscall(SimCCSyscall):
|
|
|
1592
1592
|
RETURN_VAL = SimRegArg("rax", 8)
|
|
1593
1593
|
RETURN_ADDR = SimRegArg("ip_at_syscall", 8)
|
|
1594
1594
|
ARCH = archinfo.ArchAMD64
|
|
1595
|
+
CALLER_SAVED_REGS = ["rax", "rcx", "r11"]
|
|
1595
1596
|
|
|
1596
1597
|
@staticmethod
|
|
1597
1598
|
def _match(arch, args, sp_delta): # pylint: disable=unused-argument
|
|
@@ -2257,6 +2258,7 @@ def default_cc( # pylint:disable=unused-argument
|
|
|
2257
2258
|
arch: str,
|
|
2258
2259
|
platform: Optional[str] = "Linux",
|
|
2259
2260
|
language: Optional[str] = None,
|
|
2261
|
+
syscall: bool = False,
|
|
2260
2262
|
**kwargs,
|
|
2261
2263
|
) -> Optional[Type[SimCC]]:
|
|
2262
2264
|
"""
|
|
@@ -2265,6 +2267,7 @@ def default_cc( # pylint:disable=unused-argument
|
|
|
2265
2267
|
:param arch: The architecture name.
|
|
2266
2268
|
:param platform: The platform name (e.g., "Linux" or "Win32").
|
|
2267
2269
|
:param language: The programming language name (e.g., "go").
|
|
2270
|
+
:param syscall: Return syscall convention (True), or normal calling convention (False, default).
|
|
2268
2271
|
:return: A default calling convention class if we can find one for the architecture, platform, and
|
|
2269
2272
|
language combination, or None if nothing fits.
|
|
2270
2273
|
"""
|
|
@@ -2273,20 +2276,21 @@ def default_cc( # pylint:disable=unused-argument
|
|
|
2273
2276
|
platform = "Linux"
|
|
2274
2277
|
|
|
2275
2278
|
default = kwargs.get("default", ...)
|
|
2279
|
+
cc_map = SYSCALL_CC if syscall else DEFAULT_CC
|
|
2276
2280
|
|
|
2277
|
-
if arch in
|
|
2278
|
-
if platform not in
|
|
2281
|
+
if arch in cc_map:
|
|
2282
|
+
if platform not in cc_map[arch]:
|
|
2279
2283
|
if default is not ...:
|
|
2280
2284
|
return default
|
|
2281
|
-
if "Linux" in
|
|
2282
|
-
return
|
|
2283
|
-
return
|
|
2285
|
+
if "Linux" in cc_map[arch]:
|
|
2286
|
+
return cc_map[arch]["Linux"]
|
|
2287
|
+
return cc_map[arch][platform]
|
|
2284
2288
|
|
|
2285
2289
|
alias = unify_arch_name(arch)
|
|
2286
|
-
if alias not in
|
|
2290
|
+
if alias not in cc_map or platform not in cc_map[alias]:
|
|
2287
2291
|
if default is not ...:
|
|
2288
2292
|
return default
|
|
2289
|
-
return
|
|
2293
|
+
return cc_map[alias][platform]
|
|
2290
2294
|
|
|
2291
2295
|
|
|
2292
2296
|
def unify_arch_name(arch: str) -> str:
|
angr/engines/light/engine.py
CHANGED
|
@@ -177,12 +177,12 @@ class SimEngineLightVEXMixin(SimEngineLightMixin):
|
|
|
177
177
|
func_addr = (
|
|
178
178
|
self.block.vex.next if isinstance(self.block.vex.next, int) else self._expr(self.block.vex.next)
|
|
179
179
|
)
|
|
180
|
-
if func_addr is not None:
|
|
181
|
-
getattr(self, handler)(func_addr)
|
|
182
|
-
else:
|
|
180
|
+
if func_addr is None and self.l is not None:
|
|
183
181
|
self.l.debug("Cannot determine the callee address at %#x.", self.block.addr)
|
|
182
|
+
getattr(self, handler)(func_addr)
|
|
184
183
|
else:
|
|
185
|
-
self.l
|
|
184
|
+
if self.l is not None:
|
|
185
|
+
self.l.warning("Function handler not implemented.")
|
|
186
186
|
|
|
187
187
|
#
|
|
188
188
|
# Statement handlers
|
|
@@ -193,7 +193,8 @@ class SimEngineLightVEXMixin(SimEngineLightMixin):
|
|
|
193
193
|
if hasattr(self, handler):
|
|
194
194
|
getattr(self, handler)(stmt)
|
|
195
195
|
elif type(stmt).__name__ not in ("IMark", "AbiHint"):
|
|
196
|
-
self.l
|
|
196
|
+
if self.l is not None:
|
|
197
|
+
self.l.error("Unsupported statement type %s.", type(stmt).__name__)
|
|
197
198
|
|
|
198
199
|
# synchronize with function _handle_WrTmpData()
|
|
199
200
|
def _handle_WrTmp(self, stmt):
|
|
@@ -210,7 +211,8 @@ class SimEngineLightVEXMixin(SimEngineLightMixin):
|
|
|
210
211
|
self.tmps[tmp] = data
|
|
211
212
|
|
|
212
213
|
def _handle_Dirty(self, stmt):
|
|
213
|
-
self.l
|
|
214
|
+
if self.l is not None:
|
|
215
|
+
self.l.error("Unimplemented Dirty node for current architecture.")
|
|
214
216
|
|
|
215
217
|
def _handle_Put(self, stmt):
|
|
216
218
|
raise NotImplementedError("Please implement the Put handler with your own logic.")
|
|
@@ -232,12 +234,13 @@ class SimEngineLightVEXMixin(SimEngineLightMixin):
|
|
|
232
234
|
handler = "_handle_%s" % type(expr).__name__
|
|
233
235
|
if hasattr(self, handler):
|
|
234
236
|
return getattr(self, handler)(expr)
|
|
235
|
-
|
|
237
|
+
elif self.l is not None:
|
|
236
238
|
self.l.error("Unsupported expression type %s.", type(expr).__name__)
|
|
237
239
|
return None
|
|
238
240
|
|
|
239
241
|
def _handle_Triop(self, expr: pyvex.IRExpr.Triop): # pylint: disable=useless-return
|
|
240
|
-
self.l
|
|
242
|
+
if self.l is not None:
|
|
243
|
+
self.l.error("Unsupported Triop %s.", expr.op)
|
|
241
244
|
return None
|
|
242
245
|
|
|
243
246
|
def _handle_RdTmp(self, expr):
|
|
@@ -295,7 +298,8 @@ class SimEngineLightVEXMixin(SimEngineLightMixin):
|
|
|
295
298
|
if handler is not None and hasattr(self, handler):
|
|
296
299
|
return getattr(self, handler)(expr)
|
|
297
300
|
else:
|
|
298
|
-
self.l
|
|
301
|
+
if self.l is not None:
|
|
302
|
+
self.l.error("Unsupported Unop %s.", expr.op)
|
|
299
303
|
return None
|
|
300
304
|
|
|
301
305
|
def _handle_Binop(self, expr: pyvex.IRExpr.Binop):
|
|
@@ -372,13 +376,14 @@ class SimEngineLightVEXMixin(SimEngineLightMixin):
|
|
|
372
376
|
return getattr(self, handler)(expr, vector_size, vector_count)
|
|
373
377
|
return getattr(self, handler)(expr)
|
|
374
378
|
else:
|
|
375
|
-
if once(expr.op):
|
|
379
|
+
if once(expr.op) and self.l is not None:
|
|
376
380
|
self.l.warning("Unsupported Binop %s.", expr.op)
|
|
377
381
|
|
|
378
382
|
return None
|
|
379
383
|
|
|
380
384
|
def _handle_CCall(self, expr): # pylint:disable=useless-return
|
|
381
|
-
self.l
|
|
385
|
+
if self.l is not None:
|
|
386
|
+
self.l.warning("Unsupported expression type CCall with callee %s.", str(expr.cee))
|
|
382
387
|
return None
|
|
383
388
|
|
|
384
389
|
#
|
|
@@ -479,7 +484,8 @@ class SimEngineLightVEXMixin(SimEngineLightMixin):
|
|
|
479
484
|
try:
|
|
480
485
|
return ~expr_0 # pylint:disable=invalid-unary-operand-type
|
|
481
486
|
except TypeError as e:
|
|
482
|
-
self.l
|
|
487
|
+
if self.l is not None:
|
|
488
|
+
self.l.exception(e)
|
|
483
489
|
return None
|
|
484
490
|
|
|
485
491
|
def _handle_Clz(self, expr):
|
|
@@ -602,7 +608,8 @@ class SimEngineLightVEXMixin(SimEngineLightMixin):
|
|
|
602
608
|
try:
|
|
603
609
|
return expr_0 ^ expr_1
|
|
604
610
|
except TypeError as e:
|
|
605
|
-
self.l
|
|
611
|
+
if self.l is not None:
|
|
612
|
+
self.l.warning(e)
|
|
606
613
|
return None
|
|
607
614
|
|
|
608
615
|
def _handle_Shl(self, expr):
|
|
@@ -834,7 +841,8 @@ class SimEngineLightAILMixin(SimEngineLightMixin):
|
|
|
834
841
|
|
|
835
842
|
if h is not None:
|
|
836
843
|
return h(expr)
|
|
837
|
-
self.l
|
|
844
|
+
if self.l is not None:
|
|
845
|
+
self.l.warning("Unsupported expression type %s.", type(expr).__name__)
|
|
838
846
|
return None
|
|
839
847
|
|
|
840
848
|
#
|
|
@@ -866,7 +874,8 @@ class SimEngineLightAILMixin(SimEngineLightMixin):
|
|
|
866
874
|
getattr(self, old_handler)(stmt)
|
|
867
875
|
return
|
|
868
876
|
|
|
869
|
-
self.l
|
|
877
|
+
if self.l is not None:
|
|
878
|
+
self.l.warning("Unsupported statement type %s.", type(stmt).__name__)
|
|
870
879
|
|
|
871
880
|
def _ail_handle_Label(self, stmt):
|
|
872
881
|
pass
|
|
@@ -933,7 +942,8 @@ class SimEngineLightAILMixin(SimEngineLightMixin):
|
|
|
933
942
|
try:
|
|
934
943
|
handler = getattr(self, handler_name)
|
|
935
944
|
except AttributeError:
|
|
936
|
-
self.l
|
|
945
|
+
if self.l is not None:
|
|
946
|
+
self.l.warning("Unsupported UnaryOp %s.", expr.op)
|
|
937
947
|
return None
|
|
938
948
|
|
|
939
949
|
return handler(expr)
|
|
@@ -943,7 +953,8 @@ class SimEngineLightAILMixin(SimEngineLightMixin):
|
|
|
943
953
|
try:
|
|
944
954
|
handler = getattr(self, handler_name)
|
|
945
955
|
except AttributeError:
|
|
946
|
-
self.l
|
|
956
|
+
if self.l is not None:
|
|
957
|
+
self.l.warning("Unsupported BinaryOp %s.", expr.op)
|
|
947
958
|
return None
|
|
948
959
|
|
|
949
960
|
return handler(expr)
|
|
@@ -953,7 +964,8 @@ class SimEngineLightAILMixin(SimEngineLightMixin):
|
|
|
953
964
|
try:
|
|
954
965
|
handler = getattr(self, handler_name)
|
|
955
966
|
except AttributeError:
|
|
956
|
-
self.l
|
|
967
|
+
if self.l is not None:
|
|
968
|
+
self.l.warning("Unsupported Ternary %s.", expr.op)
|
|
957
969
|
return None
|
|
958
970
|
|
|
959
971
|
return handler(expr)
|
|
@@ -17,6 +17,7 @@ class PropagationModel(Serializable):
|
|
|
17
17
|
"key",
|
|
18
18
|
"node_iterations",
|
|
19
19
|
"states",
|
|
20
|
+
"input_states",
|
|
20
21
|
"block_initial_reg_values",
|
|
21
22
|
"replacements",
|
|
22
23
|
"equivalence",
|
|
@@ -35,9 +36,11 @@ class PropagationModel(Serializable):
|
|
|
35
36
|
replacements: Optional[DefaultDict[Any, Dict]] = None,
|
|
36
37
|
equivalence: Optional[Set] = None,
|
|
37
38
|
function: Optional[Function] = None,
|
|
39
|
+
input_states: Optional[Dict] = None,
|
|
38
40
|
):
|
|
39
41
|
self.key = prop_key
|
|
40
42
|
self.node_iterations = node_iterations if node_iterations is not None else defaultdict(int)
|
|
43
|
+
self.input_states = input_states if input_states is not None else {}
|
|
41
44
|
self.states = states if states is not None else {}
|
|
42
45
|
self.block_initial_reg_values = block_initial_reg_values if block_initial_reg_values is not None else {}
|
|
43
46
|
self.replacements = replacements
|
|
@@ -51,6 +54,7 @@ class PropagationModel(Serializable):
|
|
|
51
54
|
self.node_iterations = None
|
|
52
55
|
self.block_initial_reg_values = None
|
|
53
56
|
self.states = None
|
|
57
|
+
self.input_states = None
|
|
54
58
|
self.graph_visitor = None
|
|
55
59
|
|
|
56
60
|
def block_beginning_state(self, block_addr) -> PropagatorState:
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# pylint:disable=too-many-boolean-expressions
|
|
1
2
|
from typing import Set, Optional, Union, Tuple, DefaultDict, List, Any, Dict, TYPE_CHECKING
|
|
2
3
|
from collections import defaultdict
|
|
3
4
|
import weakref
|
|
@@ -256,7 +257,9 @@ class PropagatorState:
|
|
|
256
257
|
def init_replacements(self):
|
|
257
258
|
self._replacements = defaultdict(dict)
|
|
258
259
|
|
|
259
|
-
def add_replacement(
|
|
260
|
+
def add_replacement(
|
|
261
|
+
self, codeloc: CodeLocation, old, new, force_replace: bool = False
|
|
262
|
+
) -> bool: # pylint:disable=unused-argument
|
|
260
263
|
"""
|
|
261
264
|
Add a replacement record: Replacing expression `old` with `new` at program location `codeloc`.
|
|
262
265
|
If the self._only_consts flag is set to true, only constant values will be set.
|
|
@@ -296,6 +299,44 @@ class PropagatorState:
|
|
|
296
299
|
# VEX state
|
|
297
300
|
|
|
298
301
|
|
|
302
|
+
class RegisterAnnotation(claripy.Annotation):
|
|
303
|
+
"""
|
|
304
|
+
Annotates TOP values that are coming from registers.
|
|
305
|
+
"""
|
|
306
|
+
|
|
307
|
+
def __init__(self, offset, size):
|
|
308
|
+
self.offset = offset
|
|
309
|
+
self.size = size
|
|
310
|
+
|
|
311
|
+
@property
|
|
312
|
+
def eliminatable(self) -> bool:
|
|
313
|
+
return True
|
|
314
|
+
|
|
315
|
+
@property
|
|
316
|
+
def relocatable(self) -> bool:
|
|
317
|
+
return True
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
class RegisterComparisonAnnotation(claripy.Annotation):
|
|
321
|
+
"""
|
|
322
|
+
Annotate TOP values that are the result of register values comparing against constant values.
|
|
323
|
+
"""
|
|
324
|
+
|
|
325
|
+
def __init__(self, offset, size, cmp_op, value):
|
|
326
|
+
self.offset = offset
|
|
327
|
+
self.size = size
|
|
328
|
+
self.cmp_op = cmp_op
|
|
329
|
+
self.value = value
|
|
330
|
+
|
|
331
|
+
@property
|
|
332
|
+
def eliminatable(self) -> bool:
|
|
333
|
+
return True
|
|
334
|
+
|
|
335
|
+
@property
|
|
336
|
+
def relocatable(self) -> bool:
|
|
337
|
+
return True
|
|
338
|
+
|
|
339
|
+
|
|
299
340
|
class PropagatorVEXState(PropagatorState):
|
|
300
341
|
"""
|
|
301
342
|
Describes the state used in the VEX engine of Propagator.
|
|
@@ -305,6 +346,7 @@ class PropagatorVEXState(PropagatorState):
|
|
|
305
346
|
"_registers",
|
|
306
347
|
"_stack_variables",
|
|
307
348
|
"do_binops",
|
|
349
|
+
"block_initial_reg_values",
|
|
308
350
|
)
|
|
309
351
|
|
|
310
352
|
def __init__(
|
|
@@ -319,6 +361,7 @@ class PropagatorVEXState(PropagatorState):
|
|
|
319
361
|
expr_used_locs=None,
|
|
320
362
|
do_binops=True,
|
|
321
363
|
store_tops=True,
|
|
364
|
+
block_initial_reg_values=None,
|
|
322
365
|
gp=None,
|
|
323
366
|
max_prop_expr_occurrence: int = 1,
|
|
324
367
|
model=None,
|
|
@@ -349,6 +392,9 @@ class PropagatorVEXState(PropagatorState):
|
|
|
349
392
|
|
|
350
393
|
self._registers.set_state(self)
|
|
351
394
|
self._stack_variables.set_state(self)
|
|
395
|
+
self.block_initial_reg_values = (
|
|
396
|
+
defaultdict(list) if block_initial_reg_values is None else block_initial_reg_values
|
|
397
|
+
)
|
|
352
398
|
|
|
353
399
|
def __repr__(self):
|
|
354
400
|
return "<PropagatorVEXState>"
|
|
@@ -418,6 +464,7 @@ class PropagatorVEXState(PropagatorState):
|
|
|
418
464
|
only_consts=self._only_consts,
|
|
419
465
|
do_binops=self.do_binops,
|
|
420
466
|
store_tops=self._store_tops,
|
|
467
|
+
block_initial_reg_values=self.block_initial_reg_values.copy(),
|
|
421
468
|
gp=self._gp,
|
|
422
469
|
max_prop_expr_occurrence=self._max_prop_expr_occurrence,
|
|
423
470
|
model=self.model,
|
|
@@ -448,12 +495,15 @@ class PropagatorVEXState(PropagatorState):
|
|
|
448
495
|
def load_register(self, offset, size):
|
|
449
496
|
# TODO: Fix me
|
|
450
497
|
if size != self.gpr_size:
|
|
451
|
-
return self.top(size * self.arch.byte_width)
|
|
498
|
+
return self.top(size * self.arch.byte_width).annotate(RegisterAnnotation(offset, size))
|
|
452
499
|
|
|
453
500
|
try:
|
|
454
|
-
|
|
501
|
+
v = self._registers.load(offset, size=size)
|
|
502
|
+
if self.is_top(v):
|
|
503
|
+
v = v.annotate(RegisterAnnotation(offset, size))
|
|
504
|
+
return v
|
|
455
505
|
except SimMemoryMissingError:
|
|
456
|
-
return self.top(size * self.arch.byte_width)
|
|
506
|
+
return self.top(size * self.arch.byte_width).annotate(RegisterAnnotation(offset, size))
|
|
457
507
|
|
|
458
508
|
def register_results(self) -> Dict[str, claripy.ast.BV]:
|
|
459
509
|
result = {}
|
angr/lib/angr_native.dll
CHANGED
|
Binary file
|
|
@@ -632,7 +632,8 @@ def load_win32api_definitions():
|
|
|
632
632
|
for _ in autoimport.auto_import_modules(
|
|
633
633
|
"angr.procedures.definitions",
|
|
634
634
|
_DEFINITIONS_BASEDIR,
|
|
635
|
-
filter_func=lambda module_name: module_name.startswith("win32_")
|
|
635
|
+
filter_func=lambda module_name: module_name.startswith("win32_")
|
|
636
|
+
or module_name in {"ntoskrnl", "ntdll", "user32"},
|
|
636
637
|
):
|
|
637
638
|
pass
|
|
638
639
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from . import SimLibrary
|
|
2
|
+
from .. import SIM_PROCEDURES as P
|
|
3
|
+
from ...calling_conventions import SimCCStdcall, SimCCMicrosoftAMD64
|
|
4
|
+
|
|
5
|
+
lib = SimLibrary()
|
|
6
|
+
lib.set_library_names("ntoskrnl.exe")
|
|
7
|
+
lib.add_all_from_dict(P["win32_kernel"])
|
|
8
|
+
lib.set_default_cc("X86", SimCCStdcall)
|
|
9
|
+
lib.set_default_cc("AMD64", SimCCMicrosoftAMD64)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# pylint: disable=missing-class-docstring
|
|
2
|
+
import claripy
|
|
3
|
+
|
|
4
|
+
import angr
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ExAllocatePool(angr.SimProcedure):
|
|
8
|
+
def run(self, PoolType, NumberOfBytes): # pylint:disable=arguments-differ, unused-argument
|
|
9
|
+
addr = self.state.heap._malloc(NumberOfBytes)
|
|
10
|
+
memset = angr.SIM_PROCEDURES["libc"]["memset"]
|
|
11
|
+
self.inline_call(memset, addr, claripy.BVV(0, 8), NumberOfBytes) # zerofill
|
|
12
|
+
return addr
|