JANUS: Agentic Cross-Language Fuzzing Harness Generation for Android Native Libraries

summary

Video file (mp4)

The gist

The gist The first agentic approach to synthesizing cross-language JNI-aware fuzzing harnesses for Android native libraries, yielding more valid harnesses and uncovering previously unknown

In short

JANUS is an agentic approach that synthesizes cross-language JNI-aware fuzzing harnesses for Android native libraries. It uses Large Language Models as autonomous agents to resolve complex cross-language dependencies and recursively construct composite arguments. This method yields significantly more valid harnesses and uncovers previously unknown memory corruption vulnerabilities in closed-source Android apps.

Key concepts

JNI Awareness
This means the fuzzing harness understands how Java code calls native C/C++ code via the Java Native Interface (JNI). JANUS specifically tracks these cross-language interactions to ensure the generated test cases correctly set up both the Java objects and the necessary native state required for a successful execution.
Agentic Workflow
JANUS uses Large Language Models (LLMs) as autonomous agents that perform reasoning, planning, and tool use. Instead of just analyzing code, these agents actively work together to synthesize complex harnesses by iteratively resolving dependencies and refining the generated test cases based on feedback.
Recursive Argument Construction
Native methods often take complex objects built from multiple parts. This concept describes how JANUS breaks down these large, composite objects into smaller primitive pieces, then reassembles them bottom-up to correctly construct the exact object structure expected by the native side of the JNI call.
Structure-Aware Code Retrieval
This tool helps JANUS understand the relationship between Java declarations and native implementations. It augments language servers with JNI method tables, allowing the system to create a unified map of symbols across both languages, preventing aimless exploration during harness synthesis.

Terminology used across episodes

This episode discusses

The paper

JANUS: Agentic Cross-Language Fuzzing Harness Generation for Android Native Libraries · Read on arXiv

Nankai University · Zhongguancun Academy

Modern Android apps extensively rely on native libraries, bridging Java/Kotlin and C/C++ through the Java Native Interface (JNI). This cross-language interoperation, however, exposes the memory-safe Android Runtime to the unsafe C/C++ world, creating an attack surface that has been repeatedly exploited for full device compromise. While fuzzing is a proven technique for vetting native libraries, state-of-the-art harness generation tools struggle to faithfully capture closed-source cross-language API usage: (i) precise program analysis across the JNI boundary does not scale, whereas lightweight approximations miss critical invocation patterns; and (ii) none tackles the construction of complex composite objects consumed by JNI methods. In this paper, we propose JANUS, the first agentic approach to synthesizing cross-language JNI-aware fuzzing harnesses for Android native libraries. JANUS iteratively resolves both explicit and implicit cross-language call dependencies to recover app-specific runtime context, and recursively assembles cross-language argument objects in a bottom-up manner. JANUS leverages an autonomous agentic workflow to reduce reliance on hand-crafted heuristics, capturing the vast landscape of hidden API usage knowledge embedded in closed-source native libraries. Evaluation on 44 popular real-world apps (such as Google and YouTube Music, covering 21,386 JNI methods total) shows that JANUS produces over 5.9 times as many valid harnesses (6,094) as state-of-the-art automatic harnessing tools. On pre-installed apps from five mainstream Android vendors (e.g., Xiaomi, Vivo, Samsung), JANUS further uncovers 6 previously unknown vulnerabilities in closed-source native libraries.

Transcript

Introduction to the show: ident: Security Radio. Generated commentary on the latest security and cryptography papers.

Nadia: I'm Nadia.

Elias: And I'm Elias, here with Priya.

Nadia: We're looking at the paper: "JANUS: Agentic Cross-Language Fuzzing Harness Generation for Android Native Libraries".

Elias: Here's the gist of the paper. The gist The first agentic approach to synthesizing cross-language JNI-aware fuzzing harnesses for Android native libraries, yielding more valid harnesses and uncovering previously unknown vulnerabilities.

Nadia: Problem Statement Native libraries are pervasive in modern Android apps, invoked from Java/Kotlin through the Java Native Interface (JNI) for performance gains or to reuse battle-tested legacy code This cross-language interoperation, however, exposes the memory-safe Android Runtime to the unsafe C/C++ world, creating an attack surface that has been repeatedly exploited for full device compromise While fuzzing is a proven technique for vetting native libraries, state-of-the-art harness generation tools struggle to faithfully capture closed-source crosslanguage API usage (i) precise program analysis across the JNI boundary does not scale, whereas lightweight approximations miss critical invocation patterns; and (ii) none tackles the construction of complex composite objects consumed by JNI methods.

Elias: Root Challenges At the root of the predicament lie two fundamental challenges unique to harnessing Android native libraries.

Nadia: C1 Faithfully reconstructing cross-language invocation sequences requires intricate, app-specific runtime context (e.g., Java-side argument-object instantiation and field assignment, and native-side global state and runtime handles).

Title and authors: Nadia: So, we're looking at the paper "JANUS: Agentic Cross-Language Fuzzing Harness Generation for Android Native Libraries." This is about how to build better testing harnesses for those native libraries that live in Android apps.

Elias: Right, it’s tackling the problem where you have Java calling C++ through JNI, and the tools we have right now just don't work well because they can't figure out the full picture of what's happening across that language line.

Priya: I’m wondering what this means practically for us. We know these native libraries are a huge attack surface, and if we can generate better tests, we can find more vulnerabilities faster than before?

Nadia: Exactly. The paper suggests JANUS is the first agentic approach to synthesizing these harnesses, aiming to produce more valid ones and find bugs that were previously unknown.

Elias: The core idea is using an agentic workflow powered by Large Language Models, where these models act as autonomous agents doing code reasoning and planning instead of just being a simple helper in the fuzzing pipeline.

Priya: That sounds complicated. What exactly are these two main hurdles the paper is trying to overcome with this approach?

Nadia: The paper identifies two fundamental challenges at the root of why current tools struggle. First, reconstructing those cross-language invocation sequences requires a lot of app-specific runtime context, like knowing how a Java object gets instantiated and assigned fields to native code.

Elias: And second is the argument construction problem where JNI methods often take these complex composite objects whose construction logic you can't just guess from the JNI type signatures alone.

Priya: So, it’s not just about seeing a function signature; it’s about understanding how that object was actually built on the Java side before it even gets to native code?

Nadia: That’s right. C1 is faithfully reconstructing those invocation sequences needing that runtime context, and C2 is figuring out how to construct those complex arguments semantically.

Elias: The JANUS approach tackles this by having two main algorithms interact with the agentic workflows. One handles C1 by treating unmet dependencies as the driving force to resolve both explicit and implicit invocation contexts across Java instantiation and native state.

Priya: And for C2, how does that recursive decomposition idea actually work in practice? Can we really build complex objects from scratch using just primitive parts?

Elias: Yes, JANUS recursively decomposes those complex composite objects into synthesizable primitive objects and then reassembles them bottom-up to construct the exact objects expected by the native side.

Nadia: So, it’s not just guessing the structure; it’s building the structure from the ground up based on what the native code needs to receive.

Elias: The agentic design is where they get clever, equipping these LLM agents with a tool-augmented, structure-aware code retriever to stop them from wandering aimlessly through massive amounts of cross-language code.

Priya: That sounds like a necessary guardrail for the LLMs, because if you just throw all that cross-language code at it, it gets overwhelmed quickly.

Nadia: They also use a dedicated memory layer to keep track of verified intermediate artifacts across different methods, which helps tame context drift and reduces hallucinations during the long generation process.

The paper's summary: Nadia: So, JANUS is basically an agentic system that tries to write much better tests for those native libraries in Android apps.

Elias: Right, it uses these Large Language Models not just as a suggestion engine but as actual agents doing planning and reasoning to build the testing harness.

Priya: What I’m hearing is this agentic workflow is specifically designed to solve two major problems in cross-language fuzzing—the context of how the code runs and how complex data gets passed around.

Nadia: Exactly, it tackles reconstructing those invocation sequences, which is the hard part because you need to know what happened on the Java side and what state is active on the native side.

Elias: And then there’s this second problem where JNI methods take these complicated composite objects, and JANUS figures out how to build them correctly from scratch.

Priya: So, it’s moving beyond just looking at function signatures to actually modeling the entire application flow across the Java-native boundary.

Nadia: That's right. The paper says they treat unmet dependencies as the main driver, which helps them figure out those implicit calls you can't see just by reading the code.

Elias: And for building those complex arguments, they recursively break down those big objects into smaller pieces and put them back together piece by piece to match what the native side expects.

Priya: What’s interesting is their approach to keeping track of this long process—they use a memory layer to store verified steps so the agent doesn't completely lose track of what it's already done.

Nadia: That’s how they handle context drift, which is usually a killer when you have an agent making decisions over hundreds of steps.

Elias: The results show they produce significantly more valid harnesses and cover much more ground than the previous tools like Atlas++ or POIROT.

Priya: And the real kicker for me is that they found six previously unknown vulnerabilities in closed-source libraries from major Android vendors, which is a big deal for real-world security.

Nadia: Yeah, so this paper proposes this agentic method as a new way to approach fuzzing harnesses on the Java-native boundary.

Elias: It sets up a framework that resolves explicit and implicit calls and handles recursive argument construction using structure-aware retrieval tools.

Priya: It’s essentially saying we can build more robust tests if we let the AI agents handle the heavy lifting of figuring out those complex cross-language dependencies.

Nadia: Yeah, so this is laying some groundwork for how other auto-harnessing techniques could work across different language boundaries.

Elias: It’s definitely a step forward in how we automate testing for these kinds of security challenges.

Priya: It makes the idea that you don't need perfectly hand-crafted harnesses anymore if you have an agentic system to build them intelligently.

The paper's improvements: Tom: So, we're looking at how JANUS actually improved the original approach to building these fuzzing harnesses for Android native libraries.

Nadia: They focused on four specific enhancements to make it work better in practice and make sure the agents don't get lost.

Elias: I’m hearing they added a structure-aware code retriever, which is supposed to help the AI map Java declarations directly to the native functions so it doesn't have to guess the symbol space.

Priya: So, if you think of it as giving the AI a better map of where things are defined across both languages, making those initial mappings more reliable.

Nadia: Exactly, that retrieval layer is supposed to give the system a unified view between Java and native code definitions.

Elias: Then they have this dependency-driven call sequence extractor, which means instead of just trying random calls, it figures out what prerequisite calls are needed first before it can even try to hit the target function.

Priya: That’s a big deal for the execution validity because it ensures the harness is actually runnable and not just a collection of random function calls.

Nadia: And they have this recursive argument object construction, where they break down complex objects into simpler parts and reassemble them based on what the native side is actually reading.

Elias: That’s like taking a big LEGO structure and figuring out exactly which small blocks you need to build it correctly from the bottom up.

Priya: And they also added this validation-guided iterative refinement process, where they use compiler errors and runtime exceptions to tell the agent exactly which step went wrong so it can fix itself.

Nadia: That feedback loop closes the generation cycle, making sure every part of that massive synthesis effort is actually doing what it’s supposed to do.

Elias: The authors showed that disabling any one of these components caused a noticeable drop in quality, proving they all target different kinds of failure modes.

Priya: So, for someone just listening to the show, this means we move away from just hoping the AI writes something good and toward an AI that self-correcting based on how the code actually builds.

Nadia: It’s about making sure the synthesis isn't just syntactically correct but also semantically sound for execution.

Elias: The implication is that this agentic design could become a standard way to build complex cross-language test harnesses, not just something experimental.

Conclusion: Tom: So we’re wrapping up on JANUS, which is that agentic system for synthesizing JNI-aware fuzzing harnesses for Android native libraries.

Nadia: It's a lot of work to build those things right, and JANUS shows how an AI agent can actually handle the deep context needed for cross-language testing.

Elias: The main thing is that it takes something that used to require tons of brittle, hand-crafted heuristics and replaces it with a system that resolves call dependencies and builds complex objects recursively.

Priya: From my side, what’s compelling is the result—they found six real vulnerabilities in closed-source apps like those from Xiaomi and Samsung using this method.

Nadia: That means we're looking at a way to find holes in code that's completely inaccessible otherwise, which is a huge step for finding exploits cheaply.

Elias: It’s about moving the burden of context reconstruction from human researchers to an agentic workflow powered by LLMs that can self-reflect and iterate.

Priya: But we have to remember the paper flags its limitations—it’s still based on a linear execution model, so it might struggle with highly parallel or asynchronous native code interactions.

Nadia: True, it doesn't fully account for everything that happens in a massive Android app lifecycle, like Binder interactions or heavy concurrency issues.

Elias: So while the paper shows great promise for harness generation, we still need to figure out how to make that agentic planning robust enough for real-world asynchronous systems.

Priya: It certainly opens up a new way of thinking about automated testing, where the AI doesn't just run a script but builds the entire test environment intelligently.

Nadia: Yeah, it lays down a foundation for agentic cross-language fuzzing that we can use as a starting point for other types of security research.

Elias: It’s definitely interesting because it shows how LLMs can handle complex, multi-step reasoning tasks that are usually too tedious or impossible for a human to manage alone.

More episodes

← Home