I Asked a Frontier LLM to Recover Secrets from My Decompiled Build
DEV Community

I Asked a Frontier LLM to Recover Secrets from My Decompiled Build

Protecting Application Logic: A Study on Build Hardening

The clean way to protect application logic is to keep it on a server, out of reach. When it has to live in the client, anyone can pull apart and analyze the compiled app on their device. Obfuscation cannot make recovery impossible; it can only raise its cost.

The Challenge of Recovery

Making a secret unreadable in a decompiler leaves an awkward question: how hard is it to recover? That was the question I wanted to answer about my own build hardening. I could inspect the output and confirm that configuration values no longer appeared as readable strings. But I knew how the hardening worked. I knew which data mattered, where decoding happened, and what relationships to look for.

The Experiment

Out of engineering curiosity, I gave a frontier LLM the build and had it investigate. I wanted to see whether it could work backward from the shipped artifact to the secrets the application could recover for itself. The interesting part of the experiment became the investigation around the model: how to challenge its interpretations, what evidence to demand, and how much confidence to place in a failed recovery attempt.

The Master Key

The master key ships inside the binary. The application needs to decode its values, so the artifact contains what it needs to do that. A sufficiently capable reverse engineer might find the master key, understand the derivation, and reproduce the decoding. I wrote that limitation into the threat model.

The Hardening Aims

The hardening aims to raise the cost of reverse engineering and make encoded values harder to associate with one another. I treated this as an obfuscation test. Calling it cryptographic protection would obscure the engineering question I could actually investigate: given the build, could an adversary find and use the material already inside it?

Making Relationships Harder to Discover

The configuration values are XOR-encoded. Each value uses a working key derived at runtime from a single 32-byte master key. Those working keys are never stored at rest in the binary. XOR is straightforward to reverse once the corresponding key bytes are available.

The Difficulty of Discovery

The difficulty I was trying to introduce therefore lay in discovery: recognizing which arrays held encoded values, finding the master key, and connecting it to the derivation and decoding logic. Removing readable strings eliminates an easy starting point, but those relationships are what an investigator ultimately needs to reconstruct.

Decorrelation and Shared Prefixes

I also wanted to remove similarities between related values. Shared prefixes can give an investigator a useful foothold: several values that look alike may belong together, and understanding one can guide the investigation of the others. The derivation deliberately strips shared prefixes so that similar secrets do not produce similar-looking output.

Three Implementations Must Agree Byte for Byte

There is an implementation cost to this arrangement. The derivation exists in three independent places: the application runtime, a build-time tool, and a native build script. They are written in three different languages and must agree byte for byte. Conceptual agreement is insufficient here. Each implementation has to produce exactly the bytes the others expect.

The Investigation

I used a group of LLM agents organized as an adversarial court. Three neutral researchers gathered facts from different parts of the build. One examined code, permissions, and obfuscation patterns. Another focused on network and data. The third investigated libraries and behavior. Their job was to establish what the artifact supported before turning observations into an argument.

The Process

A prosecutor then argued for findings, with a deliberate bias toward identifying problems. An advocate challenged those interpretations and supplied mitigating or benign explanations. An impartial judge weighed the record and decided which conclusions had enough support.

What the Blind Attempt Established

In this blind attempt, the model could neither identify the master key nor cluster the encoded values. It had only the build and had not been told what to look for. The hardening held against that attempt. The qualification β€œblind” is essential. Pointing an investigator at a particular array, explaining the derivation, or identifying the decoding path changes the task.

The Result

The model’s failure to discover the necessary relationships says something useful about that cost under the tested conditions, even though it does not quantify it. It does not establish that recovery is impossible. The master key remains in the binary. Another investigator, a different approach, or additional guidance could produce a different result.

Conclusion

One unsuccessful attempt cannot settle those possibilities. What I gained was a concrete observation about the shipped artifact from an adversary that lacked my implementation knowledge. That was more useful than inspecting unreadable values and deciding they looked sufficiently obscure. LLMs make this kind of artifact testing practical and inexpensive enough to be worth doing. Their usefulness extends beyond reviewing source code: they can investigate what a build reveals, particularly when their conclusions have to pass through competing interpretations and explicit evidence requirements.

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.