NotDec: WebAssembly Decompilation With Inter-Procedural Type Recovery
Source: arXiv:2608.03286 · Published 2026-08-04 · By Jikai Wang, Ningyu He, Tianming Liu, Junhai Wang, Haoyu Wang
TL;DR
This paper addresses the challenging problem of decompiling WebAssembly (Wasm) binaries into readable, high-level C code with accurate type recovery. Due to Wasm's operand stack design, linear untyped memory, and compiler optimizations, recovering semantic types and custom data structures is difficult, limiting existing decompilers such as Ghidra with its low recompilation success and poor struct type recovery. The authors design NotDec, a new WebAssembly decompilation framework that lifts Wasm bytecode into a register-based SSA intermediate representation (leveraging an extended type-checking algorithm), applies state-of-the-art inter-procedural type recovery (Retypd) augmented with pointer-vs-numeric differentiation (PNDiff), and uses Memory SSA plus structured control flow analysis to generate readable, semantically consistent C code.
NotDec achieves a 100% recompilation success rate on large datasets including 5,241 Juliet samples and the Howard dataset, compared to 45.95% for Ghidra. It recovers 85.33% of struct member accesses versus 9.24% by Ghidra, dramatically improving readability and semantic fidelity. Though the full inter-procedural analysis can be slow on large programs, the intra-procedural variant NotDec_F trades some precision for significantly lower memory use and up to 97% faster time than Ghidra on unoptimized binaries. This work integrates compiler optimization, binary type recovery, and program analysis techniques to overcome the semantic loss challenges in Wasm decompilation, enabling practical reverse engineering and vulnerability audits.
Key findings
- NotDec achieves 100% recompilation success across all 5,241 Juliet dataset binaries and all Howard dataset programs, versus 45.95% for Ghidra.
- NotDec recovers 85.33% of struct member accesses in real-world programs on the Howard dataset, vastly outperforming Ghidra’s 9.24%.
- The intra-procedural variant NotDec_F runs up to 15.9× faster and uses 4.8× less memory than Ghidra on the Juliet dataset.
- NotDec_F consumes less than half of Ghidra’s memory and up to 97% less execution time on unoptimized binaries in the Howard dataset.
- Using the PNDiff graph to differentiate pointers from numeric values enables precise pointer constraints improving type recovery.
- Memory SSA enables insertion of temporary variables only where necessary, balancing semantic correctness with code readability.
- Stack pointer manipulations are replaced with explicit stack allocations during pre-optimization, improving type inference of local variables.
- Inter-procedural type recovery using Retypd with bottom-up summaries and top-down propagation improves cross-function custom structure recovery.
Threat model
n/a - This work focuses on static reverse engineering and code understanding of WebAssembly modules, rather than attacks or defenses against adversaries. The tool assumes availability of Wasm binaries for analysis but does not model the capabilities of attackers modifying or circumventing the decompilation process.
Methodology — deep read
Threat model & assumptions: The adversary is not explicitly modeled for attack capabilities, as this is a reverse engineering tool focused on recovering high-level code understanding from WebAssembly binaries, not an adversarial attack/defense setting. The assumption is availability of Wasm binaries for static analysis, with no ability to modify or execute the code.
Data: The evaluation uses publicly available datasets including Juliet (5,241 samples) representing a broad set of C/C++ program variants and the Howard dataset consisting of five large-scale real-world programs, covering both optimized and unoptimized Wasm binaries. The datasets come with ground truth source code to verify recompilation and type recovery accuracy.
Architecture/algorithm: NotDec consists of three modular pipeline stages mirroring classical compiler phases: (1) Front End lifts WebAssembly bytecode, which uses an operand stack, into a register-based SSA Intermediate Representation (similar to LLVM IR). This is done by extending the Wasm type checking algorithm to build use-def chains and convert stack-based instructions into SSA form. (2) Middle End performs code optimizations and state-of-the-art type recovery. This includes pattern recognition passes that detect stack allocations and common memory operations (memset/memcpy) to canonicalize the IR, followed by full-context-sensitive polymorphic type inference based on the Retypd algorithm. Retypd recovers complex struct types via a constraint graph formed from IR instructions, enhanced with a novel Pointer and Numeric Differentiation (PNDiff) step that classifies integer values as pointers or numeric scalars based on inference rules around pointer arithmetic. Inter-procedural analysis is done by bottom-up summarized constraint graphs with top-down propagation of types through call graphs, mitigating infinite recursion via collapsing strongly connected components. The final step splits large stack structures (from linear memory) into scalar local variables using Scalar Replacement of Aggregate (SROA) and applies further optimizations. (3) Back End converts the optimized IR into high-level C code. It integrates Memory SSA to track memory reads/writes and decide when temporaries must be introduced to maintain semantic consistency between loads and stores. It also applies structural control flow analysis to convert CFGs into readable structured code with loops and conditionals.
Training regime: Not applicable (not ML).
Evaluation protocol: Metrics include recompilation success rate (whether decompiled code can be rebuilt back into binaries), struct member access recovery rate (percentage of correct recovered field accesses), memory and execution time during decompilation compared to Ghidra baseline tools. Ablation studies test the effects of optimizations and PNDiff on type recovery. Both intra-procedural and full inter-procedural type recovery variants are evaluated, showing the tradeoffs in scalability and precision. Results report concrete numbers over large testbeds.
Reproducibility: NotDec’s implementation and source code are publicly available at https://github.com/NotDec/NotDec, supporting reproducibility. Datasets are publicly referenced (Juliet and Howard). Exact hyperparameters are not relevant.
Technical innovations
- Extension of WebAssembly type checking to lift operand-stack bytecode into register-based SSA intermediate representation for easier analysis and optimization.
- Integration of state-of-the-art native binary polymorphic type recovery algorithm Retypd with WebAssembly, enabling inter-procedural recovery of complex user-defined structs.
- Introduction of the PNDiff graph method to differentiate pointers from numeric integers in untyped linear memory, improving pointer constraint precision for type inference.
- Application of Memory SSA to reason about memory accesses and selectively insert temporaries, maintaining semantic correctness while improving C code readability.
- Use of Scalar Replacement of Aggregates (SROA) on stack memory modeled as large structs to recover local variables, enhancing decompilation fidelity.
Datasets
- Juliet dataset — 5,241 binaries — publicly available benchmark containing diverse C/C++ samples
- Howard dataset — 5 large-scale real-world programs — publicly referenced in prior research
Baselines vs proposed
- Ghidra: recompilation success = 45.95% vs NotDec: 100%
- Ghidra: struct member access recovery = 9.24% vs NotDec: 85.33%
- Ghidra: runtime (Juliet dataset) = baseline vs NotDec_F: 15.9× faster
- Ghidra: memory usage (Juliet dataset) = baseline vs NotDec_F: 4.8× lower
- Ghidra: memory usage (Howard dataset unoptimized binaries) = baseline vs NotDec_F: <50%
- Ghidra: execution time (Howard dataset unoptimized binaries) = baseline vs NotDec_F: up to 97% reduced
Limitations
- Full inter-procedural polymorphic type recovery can be prohibitively slow on large binaries, sometimes timing out or requiring over 24 hours.
- Inter-procedural analysis complexity can be exponential in call graph depth due to polymorphic recursion, limiting scalability.
- The method currently does not address learning-based or semantic gap limitations beyond Retypd’s type recovery capabilities.
- Evaluation focuses on C/C++-generated WebAssembly; applicability to other source languages generating Wasm (Rust, Go) not extensively tested.
- Structural control flow recovery may degrade on highly obfuscated or heavily optimized binaries beyond datasets evaluated.
- No explicit robustness evaluation against intentionally maliciously crafted Wasm designed to obfuscate or confuse type recovery.
Open questions / follow-ons
- How to improve the scalability of full inter-procedural type recovery to handle complex, large real-world binaries more efficiently?
- Can the approach be extended to support richer source languages (Rust, Go) and more diverse WebAssembly usage patterns?
- What techniques can further improve decompilation resilience to obfuscation or intentionally adversarial binaries?
- Could combining learning-based semantic inference with symbolic and type-based recovery yield better readability without hallucinations?
Why it matters for bot defense
From a bot-defense or CAPTCHA perspective, understanding WebAssembly binaries is increasingly important because Wasm is used for high-performance client-side code, including potentially malicious or automated scripts. Tools like NotDec can help security researchers reverse-engineer and audit Wasm modules embedded in browsers or third-party libraries, thereby identifying hidden vulnerabilities or suspicious behaviors.
The advanced inter-procedural polymorphic type recovery and semantics-preserving C code generation enable deeper comprehension of Wasm code beyond low-level disassemblies or less precise type inference. This can support threat hunting, vulnerability research, and forensic analysis of suspicious Wasm payloads used to bypass defenses. Though computational cost of full inter-procedural analysis is high, the intra-procedural variant offers a practical tradeoff for large-scale scanning. Overall, NotDec’s contributions enable more thorough and automated understanding of Wasm binaries, which complements CAPTCHA and bot-defense efforts that rely on behavior analysis at various software layers.
Cite
@article{arxiv2608_03286,
title={ NotDec: WebAssembly Decompilation With Inter-Procedural Type Recovery },
author={ Jikai Wang and Ningyu He and Tianming Liu and Junhai Wang and Haoyu Wang },
journal={arXiv preprint arXiv:2608.03286},
year={ 2026 },
url={https://arxiv.org/abs/2608.03286}
}