
Symbolic Execution Tools
Drop in angr script recipes to symbolically find flags or success paths in CTF and crackme-style binaries.
Overview
Symbolic-execution-tools is an agent skill for the Ship phase that provides drop-in angr cookbook scripts for common CTF challenge patterns.
Install
npx skills add https://github.com/yaklang/hack-skills --skill symbolic-execution-toolsWhat is this skill?
- Recipe 1: find/avoid exploration by fixed addresses
- Recipe 2: find/avoid by stdout content for PIE or indirect control flow
- Recipe 3: symbolic stdin with printable Claripy constraints for fixed flag length
- Each recipe includes scenario, full script, and adaptation notes
- Assumes main SKILL.md angr fundamentals are already loaded
- 3+ documented angr recipe patterns with scenario, script, and adaptation notes
Adoption & trust: 1.1k installs on skills.sh; 980 GitHub stars; 2/3 security scanners passed (skills.sh audits).
What problem does it solve?
You know angr in theory but stall rewriting find/avoid loops and stdin constraints for each new crackme or challenge binary.
Who is it for?
Indie CTF players and security learners who want agent help wiring angr explore() with minimal ceremony.
Skip if: Production SaaS teams needing integration tests—symbolic execution does not replace unit tests on interpreted web stacks.
When should I use this skill?
Load when you need drop-in angr script templates for common CTF challenge patterns after the main SKILL.md angr fundamentals are loaded.
What do I get? / Deliverables
You start from a matching recipe, adapt addresses or stdout hooks, and dump a satisfying input when simgr.found resolves.
- Runnable angr explore script
- Recovered flag or stdin payload from simgr.found
Recommended Skills
Journey fit
Symbolic execution cookbooks belong in Ship because they validate unknown program behavior under test-like constraints rather than shipping product features. Testing is the shelf for executable verification patterns—here, automated path exploration to stdin/stdout success conditions.
How it compares
Use as scripted angr templates instead of manual fuzzing when the success condition is a single secret input path.
Common Questions / FAQ
Who is symbolic-execution-tools for?
Solo reversers and CTF competitors who use Python and angr and want the agent to supply complete explore/find patterns.
When should I use symbolic-execution-tools?
During Ship testing when you have a challenge binary, known or stdout-detectable success strings, and need symbolic stdin or argv exploration.
Is symbolic-execution-tools safe to install?
Check the Security Audits panel on this page; only run generated scripts against binaries you trust or own, since angr executes untrusted code paths.
SKILL.md
READMESKILL.md - Symbolic Execution Tools
# angr Cookbook — Ready-to-Use Script Patterns for CTF Challenges > **AI LOAD INSTRUCTION**: Load this when you need drop-in angr script templates for common CTF challenge patterns. Each recipe includes the scenario description, complete script, and adaptation notes. Assumes the main [SKILL.md](./SKILL.md) is already loaded for angr fundamentals. --- ## Recipe 1: Basic find/avoid by Address **Scenario**: Binary prints "Correct" at 0x401234, "Wrong" at 0x401300. Input via stdin. ```python import angr proj = angr.Project('./challenge', auto_load_libs=False) state = proj.factory.entry_state() simgr = proj.factory.simulation_manager(state) simgr.explore(find=0x401234, avoid=[0x401300]) if simgr.found: print(simgr.found[0].posix.dumps(0)) # fd 0 = stdin ``` --- ## Recipe 2: Find by stdout Content **Scenario**: Success/failure messages not at fixed addresses (PIE binary or indirect calls). ```python import angr proj = angr.Project('./challenge', auto_load_libs=False) state = proj.factory.entry_state() simgr = proj.factory.simulation_manager(state) simgr.explore( find=lambda s: b"Correct" in s.posix.dumps(1), avoid=lambda s: b"Wrong" in s.posix.dumps(1) ) if simgr.found: print(simgr.found[0].posix.dumps(0)) ``` --- ## Recipe 3: Symbolic stdin with Printable Constraint **Scenario**: Flag is 32 printable characters read via scanf/fgets. ```python import angr import claripy proj = angr.Project('./challenge', auto_load_libs=False) FLAG_LEN = 32 flag = claripy.BVS("flag", 8 * FLAG_LEN) state = proj.factory.entry_state(stdin=flag) for i in range(FLAG_LEN): byte = flag.get_byte(i) state.solver.add(byte >= 0x20) state.solver.add(byte <= 0x7e) simgr = proj.factory.simulation_manager(state) simgr.explore(find=0x401234, avoid=[0x401300]) if simgr.found: solution = simgr.found[0].solver.eval(flag, cast_to=bytes) print(f"Flag: {solution}") ``` --- ## Recipe 4: Symbolic argv **Scenario**: Binary takes flag as command-line argument `./challenge FLAG`. ```python import angr import claripy proj = angr.Project('./challenge', auto_load_libs=False) flag = claripy.BVS("flag", 8 * 32) state = proj.factory.full_init_state( args=['./challenge', flag], add_options=angr.options.unicorn ) for i in range(32): b = flag.get_byte(i) state.solver.add(b >= 0x20, b <= 0x7e) simgr = proj.factory.simulation_manager(state) simgr.explore(find=0x401234, avoid=[0x401300]) if simgr.found: print(simgr.found[0].solver.eval(flag, cast_to=bytes)) ``` --- ## Recipe 5: Symbolic File Input **Scenario**: Binary reads flag from a file. ```python import angr import claripy proj = angr.Project('./challenge', auto_load_libs=False) flag = claripy.BVS("flag", 8 * 64) sim_file = angr.SimFile("flag.txt", content=flag) state = proj.factory.entry_state(fs={'/tmp/flag.txt': sim_file}) simgr = proj.factory.simulation_manager(state) simgr.explore(find=0x401234, avoid=[0x401300]) if simgr.found: print(simgr.found[0].solver.eval(flag, cast_to=bytes)) ``` --- ## Recipe 6: Hook scanf **Scenario**: Custom scanf that angr's default SimProcedure handles incorrectly. ```python import angr import claripy class MyScanf(angr.SimProcedure): def run(self, fmt, ptr): buf = claripy.BVS("scanf_input", 8 * 32) self.state.memory.store(ptr, buf) self.state.globals['scanf_buf'] = buf return 1 proj = angr.Project('./challenge', auto_load_libs=False) proj.hook_symbol('__isoc99_scanf', MyScanf()) state = proj.factory.entry_state() simgr = proj.factory.simulation_manager(state) simgr.explore(find=0x401234, avoid=[0x401300]) if simgr.found: found = simgr.found[0] buf = found.globals['scanf_buf'] print(found.solver.eval(buf, cast_to=bytes)) ``` --- ## Recipe 7: Hook strcmp to Leak Expected Value **Scenario**: Binary compares input against computed value. Hook strcmp to extract the expected string. ```python import angr import claripy class LeakStrcmp(angr.Si