Sydr-Fuzz: Hybrid Fuzzing & Dynamic Analysis
- Sydr-Fuzz is a continuous hybrid fuzzing framework that combines dynamic symbolic execution with coverage-guided fuzzers to meet Security Development Lifecycle requirements.
- It integrates the Sydr DSE engine with libFuzzer and AFL++ to automate seed scheduling, corpus minimization, and security predicate checks in CI/CD environments.
- The framework enhances vulnerability detection with detailed crash triaging and coverage reporting, producing actionable insights for real-world software flaw discovery.
Searching arXiv for Sydr-Fuzz and closely related papers to ground the article in the cited literature. Sydr-Fuzz is a continuous hybrid fuzzing and dynamic analysis framework designed to meet Security Development Lifecycle (SDL) requirements by automating fuzz testing, dynamic symbolic execution (DSE), security predicate checking, crash triaging, coverage reporting, and corpus minimization. It integrates the Sydr DSE engine with libFuzzer and AFL++ and orchestrates their collaboration in a CI/CD-friendly pipeline (Vishnyakov et al., 2022). In the original formulation, the framework was motivated by a division of labor between coverage-guided fuzzers, which are fast at expanding coverage over simple constraints, and DSE, which is precise at solving complex path constraints but slower. Sydr-Fuzz combines these capabilities in a continuous testing workflow that also includes Casr for crash triage and a continuous fuzzing project, OSS-Sydr-Fuzz, which found 85 new real-world software flaws within one year (Vishnyakov et al., 2022).
1. Origin, scope, and design objectives
Sydr-Fuzz was introduced as “Continuous Hybrid Fuzzing and Dynamic Analysis for Security Development Lifecycle” and positions hybrid fuzzing as an SDL-oriented service rather than as a standalone experimental fuzzer (Vishnyakov et al., 2022). Its stated components are a hybrid fuzzing orchestrator, the Sydr DSE tool, libFuzzer and AFL++, symbolic security predicate checkers, the Casr crash triaging tool, and utilities for corpus minimization and coverage gathering (Vishnyakov et al., 2022). The framework’s key contributions include the first integration of a DSE tool, Sydr, with libFuzzer; a production-ready orchestrator that unifies hybrid fuzzing, symbolic security predicate checkers, corpus minimization, coverage gathering, and crash triaging; and practical optimizations in Sydr for hybrid fuzzing, including slicing, optimistic and strong optimistic solving, branch inversion cache, symbolic pointer handling and SMT-fuzzing of addresses, asynchronous solving, suspend-on-queue-threshold, standard-library semantics, constrained timeouts and memory limits, and flat output for seed exchange (Vishnyakov et al., 2022).
The underlying symbolic engine predates Sydr-Fuzz. Sydr itself was presented as a DSE system combining DynamoRIO dynamic binary instrumentation with the Triton symbolic engine, with path predicate slicing, branch inversion, jump-table handling, and multi-threaded symbolic state management (Vishnyakov et al., 2020). This suggests that Sydr-Fuzz should be understood not merely as a wrapper around a symbolic executor, but as an orchestration layer that operationalizes Sydr’s branch inversion capabilities in a continuous fuzzing environment.
A later extension applied the same general architecture to directed greybox fuzzing by coupling Sydr with LibAFL-DiFuzz, adding a seed scheduling algorithm based on target-related interestingness and coverage, and objective minimization and sorting according to target-related information (Parygina et al., 7 Jul 2025). A plausible implication is that “Sydr-Fuzz” names both a concrete SDL pipeline and a broader family of hybrid workflows centered on Sydr plus an orchestrator.
2. Architecture and execution pipeline
The orchestrator is the central control component. It launches and coordinates Sydr and fuzzers, manages corpus directories, prioritizes seeds for DSE, and minimizes and exchanges test cases among workers (Vishnyakov et al., 2022). Two binaries are required: an instrumented build for fuzzers, using sanitizers and coverage instrumentation, and a plain non-instrumented build for Sydr, which performs binary-level DSE (Vishnyakov et al., 2022). In the baseline workflow, fuzzers mutate inputs, Sydr explores paths and generates targeted inputs by solving path constraints, and seeds flow bidirectionally: fuzzers can consume Sydr-generated inputs, while Sydr schedules promising fuzzer-discovered seeds for symbolic exploration (Vishnyakov et al., 2022).
The integration differs by fuzzer backend. In libFuzzer mode, all workers share a corpus directory; Sydr writes generated seeds directly into that directory; a patched libFuzzer counts reloads of Sydr-generated files; and Sydr cleans un-reloaded files to avoid noise (Vishnyakov et al., 2022). Scheduling is driven by recorded coverage and features in libFuzzer logs, and the orchestrator parses a single active libFuzzer log to prioritize seeds and decide exit-on-time when coverage stagnates (Vishnyakov et al., 2022). In AFL++ mode, Sydr runs as a “fake secondary worker,” writing minimized seeds with unique coverage to a Sydr worker queue directory, while crashes are saved separately; AFL++ imports interesting files from the Sydr queue, and the orchestrator tracks imports via AFL++ statistics and filenames (Vishnyakov et al., 2022).
The end-to-end pipeline comprises input generation, instrumentation, feedback collection, DSE guidance, corpus exchange, security predicate checking, crash triaging, coverage gathering, and corpus minimization (Vishnyakov et al., 2022). Fuzzer builds use LLVM sanitizers and coverage instrumentation, whereas Sydr uses DynamoRIO for concrete execution and Triton-based symbolic execution (Vishnyakov et al., 2022). After corpus minimization, Sydr checks symbolic security predicates to generate inputs that exercise potential vulnerabilities including null dereference, division by zero, integer overflow, and out-of-bounds memory access (Vishnyakov et al., 2022). Crash handling is delegated to Casr: casr-san runs instrumented binaries on crashing seeds and generates structured reports, casr-cluster deduplicates and clusters based on stack traces, and casr-gdb produces detailed reports for non-instrumented binaries; reports are classified by exploitability (Vishnyakov et al., 2022).
For continuous operation, the pipeline exposes CLI tasks suitable for CI runners: sydr-fuzz run, cmin, security, casr, and cov-report (Vishnyakov et al., 2022). The GitLab-based OSS-Sydr-Fuzz workflow uses a Docker builder, supports extending the initial corpus with previously found seeds, and emits minimized corpus artifacts, coverage, Casr reports, and seeds (Vishnyakov et al., 2022).
3. Dynamic symbolic execution in Sydr-Fuzz
Sydr-Fuzz inherits its symbolic execution model from Sydr. Concrete execution uses DynamoRIO, symbolic execution uses Triton extended to support the Bitwuzla SMT solver, and Sydr maintains parallel processes for concrete and symbolic execution plus a separate thread pool for solving constraints asynchronously (Vishnyakov et al., 2022). In the earlier Sydr description, Conex performs dynamic binary instrumentation, intercepts input-handling system calls and libraries, and streams instruction-level execution events to Symex through shared memory; Symex tracks symbolic variables for inputs, symbolic register, memory, and file states, and path predicates (Vishnyakov et al., 2020). Sydr performs concolic execution along the concrete path defined by the current input, symbolically executing only instructions whose operands are currently symbolic (Vishnyakov et al., 2020).
Path reasoning is formalized by the conjunction of observed branch constraints,
where are branch constraints observed along the concrete path under input (Vishnyakov et al., 2022). To reach new targets, Sydr uses sliced branch negation:
where retains only constraints data-dependent on the target branch and other constraints are concretized from the original seed (Vishnyakov et al., 2022). The underlying Sydr paper presents the same idea as path predicate slicing followed by branch inversion and reports that slicing significantly increased the number of correct, branch-flipping inputs on several programs (Vishnyakov et al., 2020).
Several optimizations are specific to hybrid fuzzing. If is UNSAT, Sydr constructs an optimistic predicate with only the target branch constraint , and then attempts a strong optimistic predicate by removing constraints using call-stack and control-dependency analysis (Vishnyakov et al., 2022). Each symbolic branch is hashed in a branch inversion cache, and a per-branch counter guides repeated attempts when the counter is in powers of two until 255, while execution context is tracked to retry on changed paths (Vishnyakov et al., 2022). Sydr can process symbolic pointers in a full mode that is accurate but heavy, or use SMT-fuzzing as a lightweight mode by enumerating solver models up to defined limits; the orchestrator periodically enables full symbolic pointer processing, for example every 25th Sydr launch (Vishnyakov et al., 2022). It also supports inversion of switch statements, symbolic summaries for functions such as strto*l, *alloc, and strcmp, and bounded resource controls including single-query, total-solving, and per-run timeouts and memory caps (Vishnyakov et al., 2022).
The earlier Sydr evaluation provides context for these design choices. Skipping non-symbolic instructions made path predicate construction 1.2–3.5 times faster, and parallel solving increased the number of correct inversions in longer runs (Vishnyakov et al., 2020). This suggests that the optimizations carried into Sydr-Fuzz are not ad hoc engineering additions, but DSE cost controls aimed at maximizing coverage under bounded solver budgets.
4. Guidance, scheduling, and corpus management
Coverage guidance in Sydr-Fuzz is based on coverage instrumentation and sanitizers in fuzzer builds, which produce coverage feedback and crash reports (Vishnyakov et al., 2022). Coverage is summarized by
and coverage progress is monitored to trigger pipeline stages and to stop fuzzing after stagnation (Vishnyakov et al., 2022). Corpus minimization is defined as the optimization problem
with implementation differing by backend: AFL++ mode uses afl-showmap to gather bitmaps per seed, merge them into a global bitmap, and prune subsumed seeds, while libFuzzer mode relies on the shared corpus directory and libFuzzer’s corpus updates, with Sydr removing seeds not reloaded by libFuzzer (Vishnyakov et al., 2022).
Seed scheduling determines which corpus inputs are sent to Sydr. In libFuzzer mode, seeds are ordered by whether a new function was covered, whether new coverage was achieved, whether libFuzzer features increased, and descending t_creation/S_seed, so newer and smaller inputs are prioritized (Vishnyakov et al., 2022). In AFL++ mode, ordering is based on new coverage, initial corpus labels, smaller file size, and newer file by id-ordered filename (Vishnyakov et al., 2022). Resource allocation is typically one fuzzer instance and one Sydr instance per single-core trial, while Sydr uses asynchronous solver threads and suspends predicate building when queued branch inversions exceed a threshold (Vishnyakov et al., 2022).
A later directed-fuzzing version of Sydr-Fuzz introduces a distinct but related scheduling formulation. There, the orchestrator selects seeds from the LibAFL-DiFuzz corpus using a priority queue organized as a binary heap and lexicographically prioritizing is_interesting_ets, is_interesting_map, and file_score, where file_score is computed as file creation time divided by file size (Parygina et al., 7 Jul 2025). In that variant, synchronization from symbolic execution to the fuzzer occurs through a sync directory with a dynamic interval
where 0 is the time spent importing all seeds from the symbolic executor (Parygina et al., 7 Jul 2025). Although this formulation belongs to directed fuzzing rather than the original SDL paper, it illustrates how Sydr-Fuzz’s orchestration layer generalizes to other scheduling objectives.
The common principle across both versions is the use of seed metadata to govern DSE effort. This suggests that Sydr-Fuzz’s notion of “hybridization” includes not only seed exchange between fuzzers and symbolic execution, but also explicit prioritization policies that trade solver cost against expected utility.
5. Security predicates and crash triage
Beyond coverage expansion, Sydr-Fuzz performs targeted vulnerability-oriented input generation through symbolic security predicates (Vishnyakov et al., 2022). During symbolic execution on a non-crashing seed, at each instruction operating on symbolic data, Sydr constructs a security predicate 1 and solves
2
to generate an error-triggering seed (Vishnyakov et al., 2022). The supported bug classes are null pointer dereference, division by zero, integer overflow, and out-of-bounds memory access, and some predicates map to multiple CWEs (Vishnyakov et al., 2022).
The predicate definitions are explicit. For null pointer dereference at memory-access instructions,
3
For division by zero at div or idiv,
4
For out-of-bounds memory access at memory-access instructions,
5
with bounds tracked using a shadow heap for alloc/free and a shadow stack for function-frame boundaries, with stack bounds approximated heuristically (Vishnyakov et al., 2022). For integer overflow at arithmetic instructions,
6
for signed results or
7
for unsigned results, with signedness inferred from subsequent conditionals such as JL; the framework reports only cases in which a sink, such as a branch, dereference, or function argument, consumes the overflowed result (Vishnyakov et al., 2022).
Verification is performed automatically. The sanitizer build is run with the predicate-derived seed; if an error matches the reported source location, the result is accepted, otherwise the system re-runs the base corpus seed and checks for new sanitizer warnings (Vishnyakov et al., 2022). Verified security predicate results are deduplicated by source file, line, and column (Vishnyakov et al., 2022). Because predicate solving is heavier than branch inversion, Sydr provides a dedicated mode to separate security predicate checking from path exploration to preserve throughput (Vishnyakov et al., 2022).
Crash triage is handled by Casr. In formal terms, a crash signature is
8
where 9 is a hash over normalized stack frames and crash metadata; deduplication keeps only unique 0 (Vishnyakov et al., 2022). Casr reports include OS and package versions, command line, stack trace, registers, a disassembly snippet with crash line, open files, sockets, and a severity classification—exploitable, probably exploitable, or not exploitable—inferred from trace, signal, and code context (Vishnyakov et al., 2022). The pipeline emits clustered reports and associated triggering seeds, enabling direct reproduction from artifacts (Vishnyakov et al., 2022).
A common misconception is to view hybrid fuzzing solely as a coverage mechanism. In Sydr-Fuzz, coverage growth, predicate-based bug generation, and structured crash triage are part of one integrated SDL workflow (Vishnyakov et al., 2022).
6. Evaluation, impact, and relation to other systems
The main benchmarking campaign used FuzzBench on a server with 256 GB RAM and two AMD EPYC 7702 CPUs, with 10 trials per fuzzer-target combination, a single CPU core per trial, and 23 hours per trial (Vishnyakov et al., 2022). Sydr-Fuzz was compared against libFuzzer, AFL++, SymQEMU, and FUZZOLIC on 15 coverage-oriented targets, with fewer targets for SymQEMU and FUZZOLIC due to target constraints (Vishnyakov et al., 2022). The experimental Sydr configuration included one fuzzer and one Sydr instance per trial, direct branch inversion order, one solving thread, a 10-second per-query timeout, 60 seconds total solving time, a 2-minute per-run limit, inversion cache, strong optimistic solutions, symbolic address fuzzing with per-address model caps, periodic full symbolic pointer handling, suspension of predicate building after 300 queued inversions, and an 8 GB memory limit (Vishnyakov et al., 2022).
The reported results show higher coverage on 9 of 14 applications versus libFuzzer, with higher average normalized coverage in both target packs, approximately 98.7–99.6% versus 96.5–98.3% (Vishnyakov et al., 2022). Against AFL++, Sydr-Fuzz likewise achieved higher coverage on 9 of 14 applications and higher average normalized coverage, approximately 98.8–99.2% versus 94.9–96.7% (Vishnyakov et al., 2022). Against SymQEMU, it outperformed on 7 of 13 applications and achieved higher average normalized coverage in both packs, approximately 99.35–99.95% versus 97.03–99.67%, although SymQEMU showed instability on sqlite3 (Vishnyakov et al., 2022). Against FUZZOLIC, Sydr-Fuzz outperformed on 6 of 12 applications, showed strong advantages on libjpeg-turbo and openthread, and had similar average normalized coverage, approximately 99.1–99.84% versus 99.07–99.81%, while FUZZOLIC failed on woff2 (Vishnyakov et al., 2022). Sydr’s contribution measured by AFL++ imports was higher than SymQEMU and FUZZOLIC on 6 of 13 applications, though notably low on zlib_uncompress (Vishnyakov et al., 2022).
Real-world impact was demonstrated through OSS-Sydr-Fuzz, which found 85 previously unknown defects across 22 open-source projects over one year, including 13 found by security predicates (Vishnyakov et al., 2022). The framework’s repositories make available build scripts, Dockerfiles, fuzz targets, configuration files, initial corpora, dictionaries, and CI pipeline integration materials, while Casr is open-source as a separate crash triage tool (Vishnyakov et al., 2022).
Relative to prior and contemporaneous systems, Sydr-Fuzz adopts seed exchange and caching ideas similar to QSYM but adds slicing, strong optimistic solving, asynchronous solving, and a CI-oriented orchestrator (Vishnyakov et al., 2022). Compared with SymCC and SymQEMU, it targets binary-level execution via Triton and DynamoRIO and is characterized as the first-of-its-kind integration with libFuzzer (Vishnyakov et al., 2022). Compared with FUZZOLIC, it provides a more general SDL pipeline and security predicates (Vishnyakov et al., 2022). Compared with PASTIS, which brokers fuzzing and DSE to validate SAST alerts, Sydr-Fuzz generalizes hybrid fuzzing with corpus minimization, predicate-based bug finding, Casr triage, and continuous CI integration (Vishnyakov et al., 2022).
Known limitations remain. Tool operability varied across targets; single-core constraints and fixed timeouts affect the balance between solver and fuzzer; sqlite3 was a weak case because poor DSE performance impaired overall hybrid effectiveness; and full symbolic pointer handling is costly and therefore enabled periodically (Vishnyakov et al., 2022). Proposed future work includes AARCH64 support, Python fuzzing integration with Atheris, adjustment of AFL_SYNC_TIME, parsing debug information to refine array bounds for pointer reasoning and security predicates, a seed scheduler based on Katz graph centrality, and new security predicate checkers for integer truncation, format string, and command injection (Vishnyakov et al., 2022).
A later directed-fuzzing study showed that the Sydr-Fuzz approach also improves Time to Exposure in target-oriented settings, outperforming all tools on 3 of 7 examples with speedup up to 1.86 times over the second-best result and improving over pure LibAFL-DiFuzz on 3 of 7 examples with speedup up to 4.9 times (Parygina et al., 7 Jul 2025). This suggests that Sydr-Fuzz’s central idea—a continuously orchestrated exchange between a fuzzer and a concolic executor—extends beyond coverage maximization to target-driven testing regimes as well.