Reverse engineering with AI agents introduces a subtle but critical failure mode: trusting the output of a decompiler too early. A recent deep dive into XRef 0.4.0, a native analyzer for binary analysis, illustrates how a synthetic test case with 2,000 decoy functions can produce convincing but false positives. The article emphasizes that while serialized field names can point to memory offsets, identifying the specific code that modifies those fields requires rigorous verification against machine instructions, not just pseudo-C output.
The Decoy Problem in Binary Analysis
The walkthrough utilizes a stripped Linux executable built with GCC 13.3.0 and objcopy --strip-all, containing a real writer function and 2,000 decoy functions. Each decoy writes to the same memory offsets (+8 and +16) as the real function but is never called. When querying for functions that write to specific fields (m and e), the tool initially returns candidates that look identical in terms of memory access patterns. The real function scores 50 points, while the decoys score 40, with the difference coming entirely from call graph proximity to the serializer. This highlights that offset matching alone is insufficient; without understanding the caller context, an AI agent can easily latch onto a function that writes the right bytes but belongs to a completely different logic path.
Pseudo-C Is Not the Source of Truth
A major warning in the article concerns the reliability of decompiled pseudo-C. The author recounts a historical bug in XRef 0.3.0 where a branch reconstruction after an SBB (Subtract with Borrow) instruction incorrectly used an already-modified operand for the carry flag check. In this case, the machine code returned 4 for a specific input, but the decompilerβs pseudo-C would have returned 99 if interpreted literally. This discrepancy proves that while pseudo-C is useful for reading high-level operations, it can hide semantic details about flag calculations and operand lifetimes. For AI agents, this means that a plausible-looking decompiled function might still be logically wrong, requiring a fallback to raw assembly inspection.
Verification Chains and Negative Results
The XRef 0.4.0 release addresses earlier failures where queries returned not_found_under_limits without explaining what the tool actually checked. PR 77 added diagnostics to report which keys were seen and where the analysis lost the connection to the fields. The article argues that empty results must be self-explanatory to prevent users from widening searches randomly. Furthermore, the distinction between following a pointer address (lea) and a value loaded through that pointer (mov) is critical. A search for lea might miss fields accessed via direct loads, leading to false negatives. The recommended workflow involves checking the base pointer origin (argument vs. memory load) and verifying call sites before accepting any candidate as the correct function.
Key Takeaways
- Offset matching is weak evidence: 2,000 decoy functions can mimic the memory writes of a real target, requiring call graph analysis to disambiguate.
- Pseudo-C can lie: Historical bugs show decompilers can misrepresent flag calculations and operand values, making raw assembly verification essential.
- Negative results need context: Modern tools like XRef 0.4.0 must provide diagnostics for failed searches to prevent users from guessing or widening queries blindly.
- Pointer origin matters: Distinguishing between addresses derived from arguments versus memory loads is necessary to correctly attribute writes to specific objects.
The Bottom Line
AI agents must treat decompiler output as a hypothesis, not a fact. The only reliable ground truth in reverse engineering is the machine instruction stream, and agents that skip verification against raw assembly will inevitably be misled by synthetic decoys or decompiler bugs.