Axeploit
Axeploit
← Back to posts

The Anatomy of a Zero-Day: How Attackers Find Bugs Before Vendors Do

By Pallavi M

A zero-day is a vulnerability that the vendor does not know about. The name comes from the patch timeline: the vendor has had zero days to address it. An attacker exploiting a zero-day is exploiting something for which no defense exists in the form of a patch because the existence of the vulnerability is not yet known to anyone who could produce one.

Zero-days occupy a specific place in the security threat model that is different from every other vulnerability class. A known vulnerability with a published CVE and an available patch is a vulnerability your organization can choose to address by patching. A zero-day is a vulnerability your organization cannot address by patching because neither you nor the vendor knows it exists. Your defense against it is not patch management. Your defense is detection, containment, and the security architecture you already had in place when the exploitation attempt began.

Understanding how zero-days are found is not primarily a theoretical exercise. It is the foundation of understanding which security investments actually matter against this threat class, why certain application architectures are more exposed than others, and what "defense in depth" means in a context where the specific vulnerability is unknown.

The Zero-Day Market: Who Finds Them and Why

Zero-days are not found exclusively by nation-state intelligence agencies. They are found by a diverse population of researchers, brokers, criminal organizations, and independent security professionals, for a range of motivations that shape both the discovery techniques and the disclosure decisions.

Independent vulnerability researchers find zero-days through systematic study of software components, motivated by intellectual challenge, professional reputation, and financial reward. Many researchers disclose their findings responsibly to vendors through bug bounty programs or coordinated disclosure processes. Some sell findings to brokers or to government agencies when the financial return significantly exceeds what a bug bounty would pay.

Bug bounty hunters operate within the authorized scope of vendor-sanctioned programs, finding vulnerabilities in products that vendors want tested. Bug bounty findings are by definition disclosed to the vendor the attacker here is operating within a legitimate framework. The techniques they use overlap substantially with those used by researchers operating outside that framework.

Commercial vulnerability research firms sell zero-days and exploit capabilities to government agencies and law enforcement organizations as legal commercial products. Companies like Crowdfense, Zerodium, and their peers publish public price lists for zero-days in specific categories iOS, Android, enterprise software, network devices. These prices which can reach millions of dollars for certain categories signal the commercial value of vulnerability discovery and fund professional, full-time research operations dedicated to finding bugs before vendors do.

Criminal organizations find and acquire zero-days primarily for financial exploitation. Ransomware operators, banking trojan developers, and large-scale fraud operations all have financial incentive to find vulnerabilities in widely-deployed software that they can exploit at scale before defenses are deployed.

Nation-state intelligence and cyber operations units find, stockpile, and deploy zero-days as instruments of espionage and offensive cyber operations. They have the largest research budgets, the longest time horizons, and the strongest incentive to keep vulnerabilities secret rather than disclosing them.

The existence of this market has a specific implication for defenders: zero-day discovery is not solely the domain of sophisticated state actors. A vulnerability in your application that can be found through systematic analysis might be found by a criminal organization as readily as by a nation-state, with different but equally significant consequences.

Technique One: Fuzzing Throwing Unexpected Input at Scale

Fuzzing is the most automated and most scalable approach to vulnerability discovery. At its core, a fuzzer generates large volumes of inputs often derived from valid inputs through mutation and submits them to a target, observing the target's behavior for signs of unexpected failure. A crash is a signal. An unexpected hang is a signal. A response that differs from expected behavior in specific ways is a signal. Each signal is a potential vulnerability.

Modern fuzzing has evolved significantly from its early form of purely random input generation. Coverage-guided fuzzing exemplified by tools like AFL, libFuzzer, and their derivatives instruments the target binary to track which code paths each input exercises. The fuzzer guides its mutation strategy toward inputs that exercise new code paths, maximizing the coverage of the target's logic rather than randomly generating inputs that exercise only the same paths repeatedly.

The result is a fuzzer that systematically exercises a larger fraction of the target's possible input space than a human tester could reach manually, at speeds measured in thousands of inputs per second, for hours or days of continuous operation.

Where fuzzing finds zero-days: The vulnerability classes most commonly found through fuzzing are memory corruption bugs buffer overflows, use-after-free, heap corruption, type confusion. These are bugs where the program's behavior on malformed input is undefined, where the undefined behavior manifests as a crash or a detectable memory safety violation. Fuzzing finds the inputs that trigger these conditions.

Fuzzing is less effective at finding logic vulnerabilities cases where the program processes a valid input incorrectly, produces wrong output, or enforces business rules incorrectly. A fuzzer that sees HTTP 200 responses has no way to know that the 200 response contains another user's data without semantic understanding of what the correct response should have been.

Differential fuzzing is a variant particularly relevant to finding semantic vulnerabilities: the same input is submitted to two different implementations of the same specification and the outputs are compared. A discrepancy between implementations is a signal that one of them is not correctly implementing the specification which may be a security vulnerability. This technique has been used to find bugs in cryptographic libraries, protocol implementations, and language parsers where two libraries that should produce identical outputs produce different ones.

Technique Two: Binary Diffing Finding Bugs in Patches

When a vendor releases a security patch, they fix a vulnerability. They also, inadvertently, publish a roadmap to the vulnerability they just fixed because the difference between the patched and unpatched binary reveals precisely where the change was made and why.

Binary diffing is the practice of comparing the binary code of a patched and unpatched version of software to identify what changed. Tools like BinDiff, Diaphora, and similar utilities automate this comparison, highlighting functions that changed between versions and showing the specific code modifications.

The attacker who performs binary diffing immediately after a security patch release has, in many cases, a shorter path to understanding the vulnerability than the team that disclosed it because they have a precise indication of where to look. The patch itself is the tip.

The n-day race: This is the mechanism behind "n-day" exploitation exploiting vulnerabilities for which a patch exists but has not yet been deployed. The vendor releases a patch. Attackers diff the binaries to understand the vulnerability. They develop an exploit. Organizations that have not yet deployed the patch are vulnerable to an attacker who now has a working exploit and a complete understanding of the vulnerability, developed from the patch itself.

The window between patch release and exploit availability has historically measured in days to weeks. As binary diffing tooling has improved and as the pool of researchers performing this analysis has grown, the window has narrowed. A critical patch released on a Tuesday has historically had working exploits in circulation by the following Monday.

Variant analysis after binary diffing: When the patched vulnerability is understood through binary diffing, an attacker may look for the same pattern elsewhere in the same codebase. If the vendor fixed a bounds check in one function, the same missing bounds check might appear in similar functions that process similar inputs. This is variant analysis finding the siblings of a known vulnerability. Variants frequently survive the patch that fixes the original finding.

Technique Three: Variant Analysis One Bug, Many Siblings

When a vulnerability class appears in software, it rarely appears exactly once. The code patterns that produce vulnerabilities missing input validation, unsafe deserialization, incorrect authorization assumptions tend to reflect design decisions and development habits that are applied consistently across a codebase.

Variant analysis is the practice of taking a confirmed vulnerability and systematically looking for the same pattern elsewhere. This can mean:

Static pattern matching. The vulnerability was in a function that performed X operation on user-controlled input Y without validation Z. Search the codebase for every other function that performs X on user-controlled input. Each one that lacks validation Z is a variant candidate.

Semantic similarity search. More sophisticated variant analysis uses semantic code analysis to find functions that are not textually similar but are logically equivalent functions that perform the same computational purpose with the same input characteristics. These may be in different files, written by different developers, but they share the root cause of the original finding.

Cross-product variant analysis. A vulnerability found in one product from a vendor may reflect a shared codebase or shared library usage across multiple products from the same vendor. The original vulnerability was in Product A; the same underlying code, with the same bug, may be in Products B, C, and D.

Project Zero, Google's zero-day research team, has published extensively on variant analysis as a research methodology. Their analysis of iOS and Android vulnerabilities frequently identifies clusters of related bugs that were introduced together, fixed partially in response to a disclosure, and required subsequent disclosure rounds to fully address. The pattern one disclosure, incomplete fix, variant in adjacent code appears with enough consistency that it is now a standard component of professional vulnerability research.

Technique Four: Logic Auditing Reading Code to Find Bugs Nobody Tested

Some of the most impactful zero-days are not found through automated means at all. They are found by a researcher who sits down with source code or a decompiled binary and reads it carefully, with the specific intent of understanding whether the security assumptions embedded in the code are correct.

This is logic auditing the practice of tracing data flows through code to find conditions under which the code's behavior diverges from the developer's intent or from the security properties the code is supposed to enforce.

Logic auditing produces vulnerability classes that fuzzing and binary diffing are poorly suited to find: authentication bypasses, authorization failures, race conditions in state management, cryptographic misuse, and business logic flaws. These are not bugs where the program crashes on bad input. They are bugs where the program produces incorrect output or incorrect behavior in response to carefully crafted valid input.

A logic audit of an authentication implementation might trace the following:

The authentication function receives credentials. It hashes the password. It compares the hash to the stored hash. It returns a session token if the comparison succeeds. It returns an error if the comparison fails.

A logic auditor asks: what happens if the stored hash is null? What happens if the supplied password is an empty string? What happens if the comparison function exhibits timing-dependent behavior that leaks information about the hash? What happens if the session token generation is deterministic rather than random? What happens if the same function is called concurrently and the state machine between hash comparison and token issuance has a race condition?

Each of these questions, if the answer is "something unexpected," is a potential vulnerability. The auditor generates the questions from reading the code and understanding its intent. The answers come from either additional code analysis or from testing.

Source-assisted auditing. Open-source software is the most accessible target for logic auditing the source code is publicly available, the history of changes is visible in version control, and the design decisions are often documented in commit messages and issue trackers. Researchers who audit open-source software can trace the history of a function to understand what assumptions were made when it was written and whether those assumptions still hold.

Decompiler-assisted auditing. For closed-source software, decompilers IDA Pro, Ghidra, Binary Ninja reconstruct pseudo-source-code from compiled binaries. The reconstruction is imperfect but sufficiently readable for logic auditing of key functions. A researcher who is interested in the authentication logic of a proprietary application can decompile the relevant binary sections and audit the reconstructed code.

Technique Five: Differential Analysis Finding Gaps Between Specification and Implementation

A protocol or API specification describes intended behavior. An implementation of that specification expresses actual behavior. The gap between the two is where a specific class of vulnerability lives: the behaviors that the specification did not anticipate or that the implementation handles differently from the specification's intent.

Differential analysis identifies these gaps by systematically comparing specification requirements against implementation behavior, looking for cases where the implementation deviates from the spec in security-relevant ways.

This technique produced several high-profile zero-days in TLS implementations (where the specification was complex enough that multiple implementations handled edge cases differently, and some edge cases had security implications), in JWT libraries (where the specification permitted algorithm flexibility that implementations handled insecurely, producing the alg:none vulnerability class discussed in a previous post), and in OAuth implementations (where the specification's optional features were implemented with security assumptions that the specification did not require).

For web application security specifically, differential analysis applies to the gap between the API's documented contract and its actual behavior. If the API documentation says that a field accepts integer values between 1 and 100, what does the implementation do with 0, -1, 101, 1.5, or null? The specification says "integer between 1 and 100." The implementation's behavior on the edges and outside that range was not specified and where behavior is unspecified, vulnerabilities tend to live.

What Organizations Can and Cannot Defend Against

Understanding how zero-days are found is necessary context for understanding what defense against them actually means.

What organizations cannot do: Prevent the discovery of zero-days in third-party software they deploy. If a vulnerability exists in a library, a framework, or a platform component that an organization uses, a researcher with sufficient time and skill can find it regardless of what the organization does. The organization has no control over the vulnerability's discovery or the vendor's awareness of it.

What organizations can do:

Reduce exposure through architecture. Software with fewer third-party dependencies has fewer potential zero-day surfaces. Software that runs with minimal privileges reduces the impact of any zero-day that is exploited the attacker reaches a process with limited access rather than one with broad access. Software that is segmented from other systems limits the lateral movement that typically follows initial zero-day exploitation.

Detect exploitation attempts. Zero-days are unknown at the vulnerability level but their exploitation typically produces observable behavior. Unusual process activity, unexpected network connections, anomalous API call patterns, and privilege escalation attempts are all detectable through behavioral monitoring even when the specific vulnerability being exploited is unknown. The SSRF-to-RCE chain described in the previous post in this series would have been detectable at the point where the SSM API calls were made from credentials that had never previously made those calls.

Apply compensating controls proactively. SSRF-safe HTTP clients protect against SSRF-to-metadata chains even when the SSRF vulnerability is unknown. IMDSv2 enforcement protects against metadata service pivots. Least-privilege IAM roles limit what can be done with stolen credentials. Consistent input validation reduces the impact of parsing vulnerabilities. These controls address vulnerability classes without requiring knowledge of specific vulnerabilities.

Patch known vulnerabilities rapidly. Zero-days become n-days when vendors patch them. The fastest reduction in zero-day exposure is aggressive patching of n-days because n-days in actively exploited software have working exploits in circulation within days of patch release. An organization that patches within 24 hours of a critical release is a narrower target than one that patches within 30 days.

The Irony of Zero-Day Research

There is an irony embedded in the zero-day research process: the techniques used to find zero-days are, in many cases, the same techniques that should be applied to software during its development and security review lifecycle.

Fuzzing should be applied to software before it ships. Logic auditing should be applied to security-critical functions during code review. Variant analysis should be applied whenever a vulnerability is found in a codebase systematically looking for similar patterns rather than fixing only the reported instance. Differential analysis between specification and implementation should be part of security testing for any system that implements a complex protocol or specification.

The attacker who finds a zero-day frequently did not discover something that was hidden. They applied techniques that would have found the vulnerability at any earlier point in the software's history if those techniques had been applied. The advantage the attacker has is not superior technique. It is that they apply the technique systematically and persistently, whereas the development process typically applies it briefly, occasionally, and under time pressure.

The asymmetry between offense and defense in zero-day research is not primarily about capability. It is about time allocation. A researcher who spends six months studying one component of one vendor's software with the intent of finding vulnerabilities will find vulnerabilities. The vendor's security review of that component, conducted as part of the development process, may have been a two-week engagement years ago that did not reach the same depth of analysis.

Closing: The Gap Between Knowing and Not Knowing

A zero-day is a knowledge asymmetry. The attacker knows the vulnerability. The vendor does not. The organization running the software does not. The gap between attacker knowledge and defender knowledge is where zero-days derive their power.

The techniques in this post fuzzing, binary diffing, variant analysis, logic auditing, differential analysis are how attackers build that knowledge. They are systematic, they scale with time and resources, and they are applied to software that is complex enough that no single development team can fully verify its security properties through the process that produced the software.

Understanding these techniques does not make organizations immune to zero-days. It makes them better equipped to reason about what zero-day exposure actually means in their specific context, which types of software carry higher zero-day risk based on their complexity and deployment prevalence, and what investments in detection and architectural resilience provide meaningful defense against exploitation attempts whose specific mechanism is unknown.

The known vulnerability has a patch. The unknown vulnerability has a security program designed for the assumption that something unknown will eventually be exploited.

Building for that assumption is what zero-day resilience actually means.

Axeploit applies several of the techniques described in this post to the applications it tests systematic fuzzing of input handling, logic auditing of authentication and authorization flows, variant analysis when a vulnerability class is found in one endpoint, and differential comparison between documented API behavior and actual implementation. It does not find zero-days in third-party libraries that requires the researcher's extended time investment that is distinct from runtime testing. What it finds are the equivalent vulnerabilities in your own application logic: the authentication bypass that a logic auditor would have found in your code, the authorization gap that variant analysis would have identified adjacent to the one that was already fixed, the input handling failure that systematic fuzzing would have surfaced. The techniques are the same. The target is your application.

Get started

Integrate Axeploit into your workflow today