Back to blog

GOTROOT / Research

How 0-days Are Found: Patch Diffing, Coverage-Guided Fuzzing, and Static Analysis in Practice | GOTROOT

A researcher-level walkthrough of finding new vulnerabilities: reversing fresh patches (N-day diffing), discovering unknown memory corruption with coverage-guided fuzzing harnesses, and tracing source-to-sink paths with static/taint analysis.

GOTROOT Research Team Jun 5, 2026

How 0-days Are Found: Patch Diffing, Coverage-Guided Fuzzing, and Static Analysis in Practice

Behind “we found a zero-day” lies a long, iterative process: patch diffing, harness design, crash triage, root-cause analysis, and exploitability assessment. This is the workflow GOTROOT’s research team uses to discover and register high-impact CVEs (RCE, buffer overflow), stripped of marketing language. One question drives it: can we find the flaw an attacker doesn’t know yet, before they do?

Definitions: 0-day, N-day, and the patch gap

0-day 발굴 파이프라인 — 패치 디핑, 커버리지 퍼징, 크래시 트리아지, 루트코즈 분석, 익스플로잇 평가, 책임 있는 공개
GOTROOT 연구팀의 0-day 발굴 워크플로 — 패치 디핑부터 책임 있는 공개까지
  • 0-day — unknown to vendor and public; no signature exists, hardest to defend.

  • N-day (1-day) — disclosed/patched but unapplied; attackers reuse public PoCs during the “patch gap.”

  • Real-world risk comes more from the ubiquity of N-days than the rarity of 0-days — but 0-day skill sharpens N-day intuition.

1) Patch diffing — reading a fresh patch in reverse

When a vendor ships a security patch, the diff between pre/post binaries (or source) is a map of what was vulnerable. Binary diffing isolates changed functions so an exploit path can be reconstructed before a public PoC exists.

  • Binary compare: BinDiff, Diaphora to spot changed functions

  • Added bounds/sign/integer-overflow checks are the key tells

  • For source, follow the security commit diff and message ("fix bounds check")

A patch is the answer key. Reading it backwards is your N-day response speed.

2) Coverage-guided fuzzing — driving crashes with unknown input

Many 0-days come from inputs nobody expected. Coverage-guided fuzzers (AFL++, libFuzzer) evolve inputs that reach new code paths, surfacing memory corruption in parsers, decoders, and protocol handlers. The craft is in the harness that calls the target directly.

// libFuzzer 하네스 골격 — 대상 파서를 직접 호출
#include <stddef.h>
#include <stdint.h>
extern int parse_packet(const uint8_t *buf, size_t len);

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    if (size == 0) return 0;
    parse_packet(data, size);   // ASAN으로 빌드 → OOB/UAF 즉시 검출
    return 0;
}
// clang -g -O1 -fsanitize=fuzzer,address harness.c target.c -o fuzz
  • Seed corpus: start from valid samples to reach deep paths fast

  • Sanitizers: build with ASAN/UBSAN/MSAN to turn silent corruption into crashes

  • Coverage: if stuck, move to dictionary/grammar-aware fuzzing

3) Crash triage and root-cause analysis

Hundreds of crashes are mostly duplicates or unexploitable NULL derefs. Triage minimizes each crash, classifies the corruption type (OOB write, UAF, type confusion), and traces whether it reaches attacker-controllable memory.

Corruption type

Exploitation view

NULL deref / DoS

Usually availability (DoS) only

Stack/heap OOB write

High control-flow potential → RCE candidate

Use-after-free / type confusion

Weaponizable via heap grooming

4) Static and taint analysis — source to sink

Where fuzzing is dynamic, static/taint analysis traces, in code, how external input (source) reaches a dangerous function (sink) without validation — efficient for narrowing injection, authz-bypass, and memory-flaw candidates in large codebases.

  • Sources: network/file/IPC input points

  • Sinks: memcpy, system, deserialization, query builders

  • Write dataflow queries in CodeQL/Semgrep to auto-extract candidates

5) Exploitability assessment and responsible disclosure

A bug becomes a vulnerability only when impact and controllability are proven. We assess realistic difficulty against modern mitigations (ASLR, DEP/NX, CFI, stack canaries), and once weaponizability is confirmed, coordinate responsible disclosure and CVE assignment with the vendor. Client findings stay confidential.

6) Minimization, dedup, and automated triage

A fuzzer produces dozens to hundreds of crashes for the same bug. To make them analyzable we minimize each input, deduplicate by stack hash, and rank by likely exploitability.

# 1) 입력 최소화 (libFuzzer)
./fuzz -minimize_crash=1 -runs=100000 crash-abcd

# 2) 스택 해시로 중복 제거
for c in crash-*; do
  ./fuzz -runs=1 "$c" 2>&1 | grep -m1 "#0" | md5sum
done | sort | uniq -c

# 3) ASAN 리포트에서 손상 유형 분류 (heap-buffer-overflow / use-after-free ...)

Wired into CI with a growing corpus, fuzzing becomes a continuous asset that keeps surfacing new bugs rather than a one-off event.

7) Modern mitigations and bypass trends

Between “a bug exists” and “it is exploited” stand ASLR, DEP/NX, stack canaries, CFI/CET, and memory-safe languages. Realistic assessment asks whether primitives can be chained — e.g., an infoleak to defeat ASLR plus an arbitrary write to seize control flow.

  • Infoleak to recover base addresses → defeat ASLR

  • Heap grooming to align UAF/overflow with controllable objects

  • Under CFI, consider data-oriented programming and existing call gates

Why this changes pentest outcomes

A team that finds its own 0-days sees unknown flaws and chaining where scanners report “clean.” Weaponizing N-days in days via patch diffing, catching unknown 0-days via fuzzing, and narrowing risky paths in large code via static analysis all translate directly into depth on client engagements. That is why GOTROOT has registered multiple CVEs — and the essential gap between a scanner report and real penetration testing.

FAQ

Isn’t 0-day research separate from pentesting?

They connect — discovery builds the root-cause and exploitation intuition that finds deeper, chained flaws in client environments.

Do you publish findings?

We follow responsible disclosure with vendors; client findings remain confidential.

Conclusion

A team that has built exploits delivers deeper results. Experience research-driven validation via penetration testing or red teaming.