/symbolic-execution-tools
Symbolic execution and constraint solving playbook. Use when solving CTF reversing challenges, recovering keys, bypassing checks, or automating binary analysis with angr, Z3, or Unicorn Engine.
$ npx -y skills add yaklang/hack-skills --skill symbolic-execution-tools --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/symbolic-execution-tools
Context preview
The summary Claude sees to decide when to auto-load this skill.
Symbolic execution and constraint solving playbook. Use when solving CTF reversing challenges, recovering keys, bypassing checks, or automating binary analysis with angr, Z3, or Unicorn Engine.
SKILL.md
symbolic-execution-tools.SKILL.mdname: symbolic-execution-tools
description: >-
Symbolic execution and constraint solving playbook. Use when solving CTF
reversing challenges, recovering keys, bypassing checks, or automating
binary analysis with angr, Z3, or Unicorn Engine.
SKILL: Symbolic Execution Tools — Expert Analysis Playbook
> **AI LOAD INSTRUCTION**: Expert symbolic execution techniques using angr, Z3, and Unicorn Engine. Covers CTF challenge automation, constraint solving patterns, function hooking, SimProcedure replacement, and emulation-based unpacking. Base models often produce broken angr scripts due to incorrect state initialization or missing hooks for libc functions.
0. RELATED ROUTING
- [anti-debugging-techniques](../anti-debugging-techniques/SKILL.md) when anti-debug checks need to be symbolically bypassed
- [code-obfuscation-deobfuscation](../code-obfuscation-deobfuscation/SKILL.md) when using symbolic execution for deobfuscation
- [vm-and-bytecode-reverse](../vm-and-bytecode-reverse/SKILL.md) when applying angr to custom VM challenges
Advanced Reference
Also load [ANGR_COOKBOOK.md](./ANGR_COOKBOOK.md) when you need:
- 15+ ready-to-use angr script patterns for common CTF challenges
- Hook templates for scanf, printf, malloc, strcmp
- Symbolic file input, stdin, argv patterns
- Optimization tricks for path explosion management
When to use which tool
| Scenario | Best Tool | Why | |---|---|---| | Pure math / equation system | Z3 | Direct constraint solving, no binary needed | | Binary with control flow | angr | Explores paths, manages constraints automatically | | Emulate specific code region | Unicorn | Fast, no symbolic overhead, good for unpacking | | Complex binary + custom VM | angr + Unicorn (combo) | angr for control flow, Unicorn for VM handlers | | Kernel / firmware code | Qiling | Full system emulation with OS awareness |
---
1. ANGR — CORE CONCEPTS
1.1 Pipeline
Project(binary)
→ Factory.entry_state() / blank_state(addr=)
→ SimulationManager(state)
→ explore(find=target, avoid=bad)
→ found[0].solver.eval(symbolic_var)1.2 Essential Setup
import angr
import claripy
proj = angr.Project('./challenge', auto_load_libs=False)
# Entry state: start from program entry point
state = proj.factory.entry_state()
# Blank state: start from arbitrary address
state = proj.factory.blank_state(addr=0x401000)
# Full init state: with command-line args
state = proj.factory.full_init_state(args=['./challenge', arg1_sym])
simgr = proj.factory.simulation_manager(state)
simgr.explore(find=0x401234, avoid=[0x401300])
if simgr.found:
found = simgr.found[0]
solution = found.solver.eval(symbolic_input, cast_to=bytes)
print(f"Solution: {solution}")1.3 Symbolic Variables (claripy)
# Bitvector (fixed-size integer)
sym_input = claripy.BVS("input", 64) # 64-bit symbolic
sym_byte = claripy.BVS("byte", 8) # 8-bit symbolic
sym_buf = claripy.BVS("buffer", 8 * 32) # 32-byte buffer
# Concrete bitvector
concrete = claripy.BVV(0x41, 8) # concrete value 0x41
# Constraints
state.solver.add(sym_input > 0)
state.solver.add(sym_input < 100)
state.solver.add(sym_byte >= 0x20) # printable ASCII
state.solver.add(sym_byte <= 0x7e)
# Evaluate
value = state.solver.eval(sym_input)
all_values = state.solver.eval_upto(sym_input, 10) # up to 10 solutions1.4 Symbolic stdin
flag_len = 32
sym_stdin = claripy.BVS("stdin", 8 * flag_len)
state = proj.factory.entry_state(stdin=sym_stdin)
# Constrain to printable ASCII
for i in range(flag_len):
byte = sym_stdin.get_byte(i)
state.solver.add(byte >= 0x20)
state.solver.add(byte <= 0x7e)1.5 Hooking Functions
# Hook by address (skip N bytes of original code)
@proj.hook(0x401100, length=5)
def skip_check(state):
state.regs.eax = 1 # force success
# SimProcedure: replace library function
class MyStrcmp(angr.SimProcedure):
def run(self, s1, s2):
return claripy.If(
self.state.memory.load(s1, 32) == self.state.memory.load(s2, 32),
claripy.BVV(0, 32),
claripy.BVV(1, 32)
)
proj.hook_symbol('strcmp', MyStrcmp())
# Hook common problematic functions
proj.hook_symbol('printf', angr.SIM_PROCEDURES['libc']['printf']())
proj.hook_symbol('scanf', angr.SIM_PROCEDURES['libc']['scanf']())
proj.hook_symbol('puts', angr.SIM_PROCEDURES['libc']['puts']())1.6 Memory Operations
# Read memory (symbolic-aware)
data = state.memory.load(addr, size) # returns BV
data_concrete = state.solver.eval(data, cast_to=bytes)
# Write memory
state.memory.store(addr, claripy.BVV(0x41, 8))
state.memory.store(addr, sym_buf)
# Read/write registers
rax = state.regs.rax
state.regs.rdi = claripy.BVV(0x1000, 64)
---
2. Z3 CONSTRAINT SOLVING
2.1 Core API
from z3 import *
# Sorts
x = BitVec('x', 32) # 32-bit bitvector
y = Int('y') # arbitrary precision integer
b = Bool('b') # boolean
# Solver
s = Solver()
s.add(x + y == 42)
s.add(x > 0)
s.add(y > 0)
if s.check() == sat:
m = s.model()
print(f"x = {m[x]}, y = {m[y]}")2.2 Common CTF Patterns
# Serial key validation: each char satisfies constraints
key = [BitVec(f'k{i}', 8) for i in range(16)]
s = Solver()
for k in key:
s.add(k >= 0x30, k <= 0x7a) # alphanumeric-ish
# XOR key recovery
plaintext = b"known_plaintext"
ciphertext = b"\x12\x34..."
key_byte = BitVec('key', 8)
s = Solver()
for p, c in zip(plaintext, ciphertext):
s.add(p ^ key_byte == c)
# System of linear equations (modular)
a, b, c = BitVecs('a b c', 32)
s = Solver()
s.add(3*a + 5*b + 7*c == 0x12345678)
s.add(2*a + 4*b + 6*c == 0xDEADBEEF)
s.add(a ^ b ^ c == 0xCAFEBABE)2.3 Optimization
from z3 import Optimize
opt = Optimize()
x = BitVec('x', 32)
opt.add(x > 0)
opt.add(x < 1000)
opt.minimize(x) # find smallest satisfyingRead more
name: symbolic-execution-tools description: >- Symbolic execution and constraint solving playbook. Use when solving CTF reversing challenges, recovering keys, bypassing checks, or automating binary analysis with angr, Z3, or Unicorn Engine.
SKILL: Symbolic Execution Tools — Expert Analysis Playbook
> **AI LOAD INSTRUCTION**: Expert symbolic execution techniques using angr, Z3, and Unicorn Engine. Covers CTF challenge automation, constraint solving patterns, function hooking, SimProcedure replacement, and emulation-based unpacking. Base models often produce broken angr scripts due to incorrect state initialization or missing hooks for libc functions.
0. RELATED ROUTING
- [anti-debugging-techniques](../anti-debugging-techniques/SKILL.md) when anti-debug checks need to be symbolically bypassed
- [code-obfuscation-deobfuscation](../code-obfuscation-deobfuscation/SKILL.md) when using symbolic execution for deobfuscation
- [vm-and-bytecode-reverse](../vm-and-bytecode-reverse/SKILL.md) when applying angr to custom VM challenges
Advanced Reference
Also load [ANGR_COOKBOOK.md](./ANGR_COOKBOOK.md) when you need:
- 15+ ready-to-use angr script patterns for common CTF challenges
- Hook templates for scanf, printf, malloc, strcmp
- Symbolic file input, stdin, argv patterns
- Optimization tricks for path explosion management
When to use which tool
| Scenario | Best Tool | Why | |---|---|---| | Pure math / equation system | Z3 | Direct constraint solving, no binary needed | | Binary with control flow | angr | Explores paths, manages constraints automatically | | Emulate specific code region | Unicorn | Fast, no symbolic overhead, good for unpacking | | Complex binary + custom VM | angr + Unicorn (combo) | angr for control flow, Unicorn for VM handlers | | Kernel / firmware code | Qiling | Full system emulation with OS awareness |
---
1. ANGR — CORE CONCEPTS
1.1 Pipeline
Project(binary)
→ Factory.entry_state() / blank_state(addr=)
→ SimulationManager(state)
→ explore(find=target, avoid=bad)
→ found[0].solver.eval(symbolic_var)1.2 Essential Setup
import angr
import claripy
proj = angr.Project('./challenge', auto_load_libs=False)
# Entry state: start from program entry point
state = proj.factory.entry_state()
# Blank state: start from arbitrary address
state = proj.factory.blank_state(addr=0x401000)
# Full init state: with command-line args
state = proj.factory.full_init_state(args=['./challenge', arg1_sym])
simgr = proj.factory.simulation_manager(state)
simgr.explore(find=0x401234, avoid=[0x401300])
if simgr.found:
found = simgr.found[0]
solution = found.solver.eval(symbolic_input, cast_to=bytes)
print(f"Solution: {solution}")1.3 Symbolic Variables (claripy)
# Bitvector (fixed-size integer)
sym_input = claripy.BVS("input", 64) # 64-bit symbolic
sym_byte = claripy.BVS("byte", 8) # 8-bit symbolic
sym_buf = claripy.BVS("buffer", 8 * 32) # 32-byte buffer
# Concrete bitvector
concrete = claripy.BVV(0x41, 8) # concrete value 0x41
# Constraints
state.solver.add(sym_input > 0)
state.solver.add(sym_input < 100)
state.solver.add(sym_byte >= 0x20) # printable ASCII
state.solver.add(sym_byte <= 0x7e)
# Evaluate
value = state.solver.eval(sym_input)
all_values = state.solver.eval_upto(sym_input, 10) # up to 10 solutions1.4 Symbolic stdin
flag_len = 32
sym_stdin = claripy.BVS("stdin", 8 * flag_len)
state = proj.factory.entry_state(stdin=sym_stdin)
# Constrain to printable ASCII
for i in range(flag_len):
byte = sym_stdin.get_byte(i)
state.solver.add(byte >= 0x20)
state.solver.add(byte <= 0x7e)1.5 Hooking Functions
# Hook by address (skip N bytes of original code)
@proj.hook(0x401100, length=5)
def skip_check(state):
state.regs.eax = 1 # force success
# SimProcedure: replace library function
class MyStrcmp(angr.SimProcedure):
def run(self, s1, s2):
return claripy.If(
self.state.memory.load(s1, 32) == self.state.memory.load(s2, 32),
claripy.BVV(0, 32),
claripy.BVV(1, 32)
)
proj.hook_symbol('strcmp', MyStrcmp())
# Hook common problematic functions
proj.hook_symbol('printf', angr.SIM_PROCEDURES['libc']['printf']())
proj.hook_symbol('scanf', angr.SIM_PROCEDURES['libc']['scanf']())
proj.hook_symbol('puts', angr.SIM_PROCEDURES['libc']['puts']())1.6 Memory Operations
# Read memory (symbolic-aware) data = state.memory.load(addr, size) # returns BV data_concrete = state.solver.eval(data, cast_to=bytes) # Write memory state.memory.store(addr, claripy.BVV(0x41, 8)) state.memory.store(addr, sym_buf) # Read/write registers rax = state.regs.rax state.regs.rdi = claripy.BVV(0x1000, 64)
---
2. Z3 CONSTRAINT SOLVING
2.1 Core API
from z3 import *
# Sorts
x = BitVec('x', 32) # 32-bit bitvector
y = Int('y') # arbitrary precision integer
b = Bool('b') # boolean
# Solver
s = Solver()
s.add(x + y == 42)
s.add(x > 0)
s.add(y > 0)
if s.check() == sat:
m = s.model()
print(f"x = {m[x]}, y = {m[y]}")2.2 Common CTF Patterns
# Serial key validation: each char satisfies constraints
key = [BitVec(f'k{i}', 8) for i in range(16)]
s = Solver()
for k in key:
s.add(k >= 0x30, k <= 0x7a) # alphanumeric-ish
# XOR key recovery
plaintext = b"known_plaintext"
ciphertext = b"\x12\x34..."
key_byte = BitVec('key', 8)
s = Solver()
for p, c in zip(plaintext, ciphertext):
s.add(p ^ key_byte == c)
# System of linear equations (modular)
a, b, c = BitVecs('a b c', 32)
s = Solver()
s.add(3*a + 5*b + 7*c == 0x12345678)
s.add(2*a + 4*b + 6*c == 0xDEADBEEF)
s.add(a ^ b ^ c == 0xCAFEBABE)2.3 Optimization
from z3 import Optimize
opt = Optimize()
x = BitVec('x', 32)
opt.add(x > 0)
opt.add(x < 1000)
opt.minimize(x) # find smallest satisfyingMaster Entry → Category Entries → Deep Topic Skills One master entry, six category entries, and 101 deep topic skills across 14 security domains.
Repo: yaklang/hack-skills
Other skills on hack-skills.
- /401-403-bypass-techniques
401/403 bypass playbook. Use when encountering access-denied responses on admin panels, API endpoints, or restricted paths. Covers path manipulation, HTTP method tampering, header injection, protocol downgrade, and automated bypass tools.
Open skill - /active-directory-acl-abuse
Active Directory ACL abuse playbook. Use when exploiting misconfigured AD permissions including GenericAll, WriteDACL, DCSync rights, shadow credentials, LAPS reading, GPO abuse, and BloodHound-guided attack paths.
Open skill - /active-directory-certificate-services
AD Certificate Services attack playbook. Use when targeting misconfigured AD CS for privilege escalation via ESC1-ESC13 template abuse, NTLM relay to enrollment, CA officer abuse, and certificate-based persistence.
Open skill - /active-directory-kerberos-attacks
Kerberos attack playbook for Active Directory. Use when targeting AD authentication via AS-REP roasting, Kerberoasting, golden/silver/diamond tickets, delegation abuse, or pass-the-ticket attacks.
Open skill - /ai-ml-security
AI/ML security playbook. Use when assessing model supply chain attacks (pickle RCE, poisoned weights), adversarial examples, model poisoning, model stealing, data privacy attacks (membership inference, model inversion), and autonomous agent security risks.
Open skill - /android-pentesting-tricks
Android pentesting playbook. Use when testing Android applications for SSL pinning bypass, exported component abuse, WebView vulnerabilities, intent redirection, root detection bypass, tapjacking, and backup extraction during authorized mobile security assessments.
Open skill

