DISPATCH: Unraveling Security Patches from Entangled Code Changes
Shiyu Sun
34th USENIX Security Symposium (USENIX Security '25) · Day 2 · Software Security 2: Patching and Repair
Overview
This article details the research presented in the USENIX Security paper "NASS: Fuzzing All Native Android System Services with Interface Awareness and Coverage." The paper introduces NASS, a novel fuzzer designed to uncover critical vulnerabilities in proprietary native Android system services. Given the increasing sophistication of Android's security mechanisms, such as stricter app sandboxes and kernel hardening, attackers are shifting their focus to highly privileged user-space components. Native system services, often implemented in C++ and responsible for interacting with hardware, represent a significant and under-explored attack surface, especially those that are closed-source and developed by original equipment manufacturers (OEMs).
Read the paper · Download the PDF (PDF) · Slides
Paper abstract
Compromised or malicious apps remain a primary security concern for Android. As Android tightens its app sandbox and further reduces the kernel's attack surface, native Android system services emerge as a promising target for privilege escalation. Bugs in these native system services, triggerable from the app sandbox via RPC (Remote Procedure Calls), may facilitate privilege escalation. We identify the attack surface exposed by proprietary native system services and propose NASS, an approach to effectively fuzz proprietary real-world RPC servers to detect bugs triggerable via RPC. NASS addresses the challenge of extracting coverage from complex intertwined real-world RPC servers. Furthermore, NASS leverages our novel technique deserialization-guided interface extraction to recover the RPC interface definition from proprietary RPC servers. NASS' techniques all build on common RPC design principles, which broadly apply to RPC frameworks. We implement NASS for Android's Binder RPC framework. NASS outperforms prior work regarding interface extraction, target exploration and bug finding capabilities, even without access to source code. NASS has identified 12 unique bugs in up-to-date Google, Samsung, Xiaomi, and OnePlus devices, with five CVEs assigned so far.

NASS: Fuzzing All Native Android System Services with Interface Awareness and Coverage
Speakers: Philipp Mao, Marcel Busch, Mathias Payer
Conference: USENIX Security
YouTube: N/A (peer-reviewed conference paper)
Overview
This article details the research presented in the USENIX Security paper "NASS: Fuzzing All Native Android System Services with Interface Awareness and Coverage." The paper introduces NASS, a novel fuzzer designed to uncover critical vulnerabilities in proprietary native Android system services. Given the increasing sophistication of Android's security mechanisms, such as stricter app sandboxes and kernel hardening, attackers are shifting their focus to highly privileged user-space components. Native system services, often implemented in C++ and responsible for interacting with hardware, represent a significant and under-explored attack surface, especially those that are closed-source and developed by original equipment manufacturers (OEMs).
NASS addresses two fundamental challenges in fuzzing these complex targets: the lack of publicly available interface definitions for proprietary services and the difficulty in obtaining stable, relevant code coverage from multi-threaded, hardware-dependent environments. By leveraging a new technique called deserialization-guided interface extraction (DGIE) and a refined approach to coverage collection, NASS can effectively generate interface-aware inputs and monitor the execution paths within these services. This enables NASS to identify bugs that prior black-box or source-code-dependent fuzzers have missed.
The significance of NASS lies in its ability to systematically audit a critical, previously neglected attack surface within Android. The research demonstrates that even on modern, fully updated commercial off-the-shelf (COTS) devices from major vendors like Google, Samsung, Xiaomi, and OnePlus, these proprietary services harbor severe vulnerabilities. NASS has successfully identified 12 unique bugs, leading to five assigned CVEs, highlighting the immediate impact and the necessity of proactive security measures for these components.
Background
Modern Android security architecture is designed to isolate applications from sensitive system components and the kernel. Apps operate within a strict sandbox, limiting direct access to kernel APIs and hardware. To interact with underlying hardware or perform privileged operations, apps must communicate with system services via Binder Remote Procedure Calls (RPCs). These system services act as an interposition layer, enforcing Android permissions and mediating access to the kernel or other services.
Android's user-space architecture is structured into three layers: the app layer, the framework layer, and the hardware abstraction layer (HAL). Since Android 8, under Project Treble, communication between the framework and HAL layers exclusively uses Binder IPC. System services can be implemented in Java or natively in C++. While many framework services are open-source as part of the Android Open Source Project (AOSP), a substantial portion, particularly those in the HAL layer, are proprietary, developed by OEMs or original design manufacturers (ODMs). These proprietary native services often have highly privileged access to kernel drivers and hardware. For instance, on five recent devices, 528 (30%) of all system services were native, with 316 (60%) of these being entirely proprietary. An additional 44 AOSP services loaded proprietary components.
The motivation for targeting these native system services stems from the evolving threat landscape. Historically, attackers would gain initial code execution in an app (e.g., via a browser zero-day or malicious app) and then escalate privileges by exploiting kernel vulnerabilities. However, Google's continuous efforts to harden the kernel, including rewriting the Binder kernel driver in Rust, are making direct kernel exploitation from the app sandbox increasingly difficult. Compromising a system service, especially a HAL service, provides an attacker with a significantly expanded attack surface on the kernel, as these services are designed to interact with more kernel APIs and have elevated SELinux permissions. Evidence suggests malicious actors are already targeting system services; a 2024 Google Project Zero "0-day in the Wild" report described a kernel vulnerability on a Samsung S10 exploited from the cameraserver service, which was likely compromised first as a stepping stone.
Prior work on fuzzing Android system services, such as FANS [28] and BinderCracker [8], had significant limitations. FANS relied on source code analysis to infer interface definitions, rendering it ineffective for proprietary services. BinderCracker, while applicable to proprietary services, used message capturing during normal phone usage to extract partial interface information, missing out on rarely used or unused RPC functions and thus underestimating the true attack surface. Crucially, neither FANS nor BinderCracker incorporated coverage-guided fuzzing, operating largely in a black-box manner, which limits their efficiency and bug-finding capabilities for complex, real-world targets.
Key Findings
NASS has made significant contributions to the security of Android's user space, demonstrating its effectiveness in addressing previously unsolved challenges. The key findings are:
- Discovery of Critical Vulnerabilities: NASS identified 12 unique bugs in up-to-date Google, Samsung, Xiaomi, and OnePlus devices. Five of these vulnerabilities have been assigned CVEs, including high-severity Use After Free (CVE-2024-47040), Out-of-Bounds Read (CVE-2025-0085, CVE-2024-56186, CVE-2024-47039), and Stack Overflow (CVE-2025-26459) issues. These bugs include both denial-of-service (DoS) and potentially weaponizable memory corruption vulnerabilities (12 memory corruption bugs and 60 DoS bugs).
- Superior Interface Recovery (RQ1 & RQ3): The deserialization-guided interface extraction (DGIE) technique achieved remarkable accuracy. In a ground-truth study on 14 open-source services, DGIE successfully recovered 265 out of 276 exposed RPC functions (96%) and extracted the correct sequence of deserializers for 242 (88%) of them. For services with automatically generated server stubs (e.g., from AIDL), NASS achieved 100% correct deserializer sequence recovery. This significantly outperforms BinderCracker's message capturing approach, which only recovered 53% of RPC functions, highlighting that prior methods vastly underestimated the exposed attack surface.
- Enhanced Coverage and Bug Finding (RQ2 & RQ3): NASS consistently outperformed prior work and its own non-interface-aware configuration (NASS (NI)) in terms of both code coverage and bug discovery. NASS achieved higher coverage than FANS for 8 out of 14 services and parity for 4 others. While FANS found 25 bugs, NASS discovered 19, with 9 bugs being unique to NASS. NASS was the only fuzzer to discover bugs in two services. NASS (NI) found only 8 bugs, demonstrating the critical role of interface awareness.
- Adherence to RPC Design Principles (RQ5): A manual analysis of 316 proprietary native services on COTS devices revealed that 281 services (89%) adhered to all three RPC design principles (Abstraction of IPC Binding Code, Single Entrypoint, Standard Deserialization Routines). This high compliance rate validates NASS's design, which leverages these principles for interface extraction and coverage collection.
- Practicality on COTS Devices (RQ4): NASS was successfully deployed and found bugs on five recent, fully updated COTS devices (Google Pixel 9, Samsung S23, Xiaomi Redmi Note 13, OnePlus 12R, Infinix X670) running Android versions 13 to 15, demonstrating its real-world applicability and effectiveness against production-grade proprietary software.
Technical Deep Dive
NASS's design is fundamentally driven by two key challenges in fuzzing proprietary native Android system services: C1: Automated Complete Interface Definition Extraction For Proprietary RPC Servers and C2: Isolating Coverage For Proprietary HW/SW- Dependent Multithreaded RPC Servers. The solution leverages common RPC design principles to overcome these hurdles.
RPC Design Principles
The NASS approach is built upon three generic RPC design principles observed in frameworks like Android's Binder, gRPC, and Thrift:
- Abstraction of IPC Binding Code (Ab): Developers separate application-specific logic from IPC-specific code. This involves client stubs for serializing arguments and sending requests, and server stubs for deserializing arguments and invoking the target API function.
- Single Entrypoint (Si): RPC servers typically have a single entry point function, invoked by the IPC transport layer, which maps incoming requests to the correct server stub and invokes it. This centralizes request handling. In Android Binder, this is the
onTransactfunction. - Standard Deserialization Routines (St): To ensure consistency and compatibility, serialization and deserialization routines for arguments are standardized, often automatically generated or part of a runtime library. In Android, these are found in
libbinder.soandlibbinder_ndk.so(e.g.,Parcel.h,binder_parcel.h).
Deserialization-Guided Interface Extraction (DGIE)
DGIE is NASS's core contribution for addressing C1, enabling the recovery of complete RPC interface definitions from binary-only proprietary services. It builds on principles Ab and St.
- Identifying Exposed RPC Functions: NASS first identifies all exposed RPC functions. For Android's Binder, these are typically identified by an integer
code. NASS iterates through possible 3-byte integer values, sending IPC requests and monitoring coverage. New coverage indicates the discovery of a new RPC function, and its identifier is recorded. - Iterative Deserializer Observation: Once an RPC function identifier is found, NASS iteratively invokes it, initially with random bytes as arguments. Leveraging principle St, the server stub uses standard deserialization routines to process arguments. NASS hooks these routines (e.g.,
readString[],readInt32,readStringin Android'sParcelobject) and observes their execution. - Building Deserializer Sequences: If a deserializer is observed, NASS adds it to the interface definition for that RPC function. It then generates new argument bytes by serializing the previously observed deserializers with valid data and appending random bytes for the remaining arguments. This process is repeated. For complex objects (Parcelables), which are unrolled into a linear sequence of standard deserializers, NASS observes this sequence. This iterative process continues until no new deserialization routines are observed, indicating that all arguments for that RPC function have been successfully deserialized, and the target application logic has been reached.
- Refinement Phase: DGIE is split into a fuzzing phase to extract a preliminary interface and a refinement phase. The fuzzing phase mutates argument bytes (structure and values) to trigger various deserialization paths, especially important for services that violate Ab by intertwining application logic with the server stub. The refinement phase then replays these seeds, monitoring deserialization routines to build precise deserializer-level RPC function signatures. NASS iteratively performs preliminary fuzzing and refinement until no new deserializers are observed for any RPC function, signifying a complete interface extraction.
Stable Coverage Collection
To address C2, NASS implements a robust coverage collection mechanism that accounts for the complexity of multi-threaded, hardware-dependent RPC servers. This mechanism leverages principle Si.
- Hooking the Entry Point: NASS hooks the RPC server's single entry point function (e.g.,
Demo::onTransactin Listing 1). This ensures that coverage is only collected when an IPC request is specifically directed at the target interface. - Caller PID Verification: Upon triggering the hook, NASS inspects the IPC request to determine if it originated from its own client module (by checking the process ID or PID). If the request is from an unrelated system component, the hook returns, allowing normal server operation without collecting irrelevant coverage.
- Thread-Specific Tracing: If the request is from NASS, the instrumentation module starts tracing the current thread's execution using Frida Stalker. For each encountered basic block, a shared coverage bitmap is updated. Tracing continues until the entry point function returns. This method guarantees that collected coverage is stable and directly related to NASS's dispatched IPC requests, avoiding noise from other system activities or non-determinism in thread scheduling. This approach achieves 30 to 400 executions per second on COTS devices.
Fuzzing Component
With interface awareness and stable coverage, NASS employs an evolutionary, mutation-based grey-box fuzzer.
- Interface-Aware Mutators: NASS uses the extracted interface definition to generate seeds that adhere to the server's expected argument types. Its mutator is "interface-aware," meaning it only mutates the values of RPC arguments, not the overall structure of the request, ensuring successful deserialization by the server stub.
- Type-Specific Mutations: NASS supports 23 different argument types for Binder IPC (Table 2). Primitive types (Bool, Int32, String) are mutated using standard byte-level operations. Vectors of primitives are mutated by changing individual entries or adjusting vector size.
- Special Type Handling:
- File Descriptors: Mutated by writing fuzzing input to a temporary file and serializing its file descriptor.
- Binder References (StrongBinder): Used for callbacks, these are mutated by serializing a reference to a bespoke fuzzing input service. This service returns mutated fuzzing input when invoked, allowing NASS to fuzz data flows back from the server.
- Parcelables: Handled transparently as sequences of standard deserializers. Mutating Parcelable vectors involves mutating individual members or adding/removing entries corresponding to a single Parcelable.
- On-Device Implementation: NASS runs directly on rooted COTS devices, using Frida for dynamic binary instrumentation (DBI). It consists of three modules: an instrumentation module (injected into the target), a client module (sends IPC requests, runs LibFuzzer-based logic), and an orchestrator module (on host, manages setup and restarts). Crashes are detected by monitoring the target service's PID; upon a crash, Android's
initprocess restarts the service, which NASS then reinstruments.
Demo / Proof of Concept
The effectiveness of NASS is best illustrated by the critical vulnerabilities it uncovered on modern COTS devices. The paper provides three case studies demonstrating the severity and exploitability of these bugs:
- Use After Free (UAF) on Pixel 9 (CVE-2024-47040):
- Affected Service:
android.hardware.radio.sap.ISap/slot2 - Mechanism: The service handles
apdurequests, storing them in a linked list identified by a token. When a request completes, it frees the first matchingapdurequest. NASS discovered that the service did not check for duplicate tokens. By sending two requests with the same token, NASS caused the service to free anapdurequest that was still in use after the first request completed. - Impact: This UAF could have been exploited to achieve arbitrary code execution in the
rild_exynosprocess, running with the highly privilegedradiouser permissions. Google fixed this in November 2024.
- Arbitrary Write on OnePlus 12R:
- Affected Service:
vendor.oplus.hardware.engineer.IEngineer - Mechanism: A vulnerable RPC function was designed to set an integer value in a memory buffer. However, it used a user-provided index and value without performing any range checks on the index.
- Impact: This lack of bounds checking allowed NASS to trigger an arbitrary memory write (within the integer range) in the service's process, a primitive often leveraged for privilege escalation. This bug was responsibly disclosed.
- Heap Overflow on Samsung S23:
- Affected Service:
vendor.samsung.hardware.radio.network - Mechanism: An RPC function deserialized a network protocol message from the IPC request. A field within this message, intended to be the message length, was a signed integer controlled by the attacker. Later, this deserialized message was copied to an internal buffer using the attacker-controlled length. Although the service checked that the length was not larger than the maximum message size, this check was performed on the signed integer.
- Impact: By providing a negative length value, NASS bypassed the size check, leading to a heap-buffer-overflow when the
memcpyoperation was performed, potentially allowing an attacker to corrupt heap metadata or overwrite adjacent data structures. This bug was responsibly disclosed.
These case studies exemplify how NASS's interface-aware and coverage-guided fuzzing can bypass the deserialization logic and reach deep into the application-specific code of proprietary services, uncovering critical memory corruption vulnerabilities that could be weaponized for privilege escalation.
Defensive Implications
The findings presented by NASS highlight a critical and often overlooked attack surface: proprietary native Android system services. For defenders, understanding these implications is crucial for hardening mobile platforms.
- Prioritize Fuzzing of Proprietary Components: OEMs and security teams must implement robust, automated fuzzing for all proprietary native system services. Relying solely on open-source auditing or static analysis is insufficient, as demonstrated by NASS's ability to uncover bugs missed by prior methods. NASS provides a blueprint for effective fuzzing of these binary-only targets.
- Enforce RPC Design Principles: The high compliance rate (89%) of proprietary services with NASS's identified RPC design principles (Abstraction of IPC Binding Code, Single Entrypoint, Standard Deserialization Routines) validates their importance. Developers should strictly adhere to these principles, particularly Abstraction of IPC Binding Code (Ab) and Standard Deserialization Routines (St), to minimize potential vulnerabilities introduced by custom or intertwined deserialization logic. Services that violate these principles (e.g., Xiaomi's 60% compliance) are more challenging to fuzz and thus potentially more vulnerable.
- Implement Robust Input Validation: The discovered heap overflow and arbitrary write vulnerabilities underscore the critical need for comprehensive input validation, especially for length and index values, even after deserialization. Signed integer comparisons for size checks are a common pitfall that must be addressed.
- Adopt Secure Coding Practices for Memory Safety: The prevalence of Use After Free, Out-of-Bounds reads, and heap overflows points to persistent memory safety issues in C++ implementations. Developers should adopt modern C++ practices, use safer memory management techniques, and potentially explore languages like Rust for critical components, as Google is doing for the Binder kernel driver.
- Expand Fuzzing Scope with Interface Awareness: Traditional black-box fuzzing or message capturing (like BinderCracker) vastly underestimates the attack surface. NASS demonstrates that interface-aware fuzzing is essential to reach deep into the server stub and target application logic effectively, rather than wasting cycles on inputs rejected by initial deserialization.
- Consider Semantic-Aware Mutators: While NASS excels at structural interface awareness, some services impose strict semantic requirements (e.g., valid file paths, IP addresses). Defenders developing their own fuzzers should consider integrating FANS-style semantic-aware mutation heuristics, possibly through reverse engineering or by leveraging internal knowledge, to achieve even deeper code coverage for such specific cases.
- Address State Accumulation in Services: The challenge of state accumulation causing non-reproducible crashes during persistent fuzzing highlights a potential design flaw in long-running services. Mechanisms to periodically reset service state or ensure statelessness where possible can improve both security and testability.
While NASS's techniques could theoretically be leveraged by malicious actors, the authors contend that "security through obscurity is not a sustainable strategy." By openly sharing these findings and the NASS implementation, the research empowers organizations and security researchers to proactively harden native RPC servers, thereby reducing the overall attack surface available to all adversaries.
Key Takeaways
- Proprietary native Android system services are a critical, under-fuzzed attack surface for privilege escalation, especially as kernel hardening progresses.
- NASS introduces Deserialization-Guided Interface Extraction (DGIE), a novel technique that accurately recovers complete RPC interface definitions from binary-only proprietary services without source code or captured traffic.
- Interface awareness is crucial for effective fuzzing, allowing NASS to generate valid inputs that penetrate server stubs, significantly outperforming black-box and non-interface-aware fuzzers in coverage and bug discovery.
- NASS's stable coverage collection mechanism effectively isolates relevant execution paths in complex, multi-threaded, hardware-dependent environments on COTS devices.
- NASS has found 12 unique, high-severity bugs (5 CVEs) in up-to-date devices from major vendors, demonstrating its real-world impact and the prevalence of vulnerabilities in these components.
- Most proprietary services adhere to common RPC design principles, validating NASS's design, but violations can hinder fuzzing effectiveness and potentially introduce more vulnerabilities.
About the Speaker(s)
The authors of the paper "NASS: Fuzzing All Native Android System Services with Interface Awareness and Coverage" are Philipp Mao, Marcel Busch, and Mathias Payer. All three authors are affiliated with EPFL (École Polytechnique Fédérale de Lausanne), a leading research institution in Switzerland. Their work focuses on system security, particularly in the context of mobile platforms and the challenges of securing proprietary software components. Mathias Payer is a recognized expert in system security and vulnerability research. This research showcases their expertise in developing advanced fuzzing techniques and conducting in-depth security analyses of complex software systems.
Reviews
Dr. Zero (Offensive Security Researcher) — STRONG ACCEPT
This is exactly the kind of systems security research that moves the field forward. NASS solves a real problem — fuzzing closed-source Android HAL services — with a clever technique (DGIE) that actually works, validated by 12 real bugs including a UAF on Pixel 9. The 96% interface recovery rate against ground truth isn't hand-waving; it's measured.
Heather Calloway (CISO) — SOLID
Consequential offensive research that demonstrates a significant, under-audited attack surface on every Android device your executives carry. The 12 bugs found on fully-patched flagship devices from Google, Samsung, Xiaomi, and OnePlus — including weaponizable UAF and arbitrary write primitives — should inform your mobile device procurement conversations and your assumptions about vendor patch completeness.
→ Top-rated talks at 34th USENIX Security Symposium (USENIX Security '25)
All talks from 34th USENIX Security Symposium (USENIX Security '25)