Exploiting compiler theory to automate the extraction of IOCs from JavaScript malware
Matthew Nunes (Reverse Engineer · PwC)
Virus Bulletin Conference 2025 (VB2025) · Day 2 · Green room
Overview
In this insightful talk from Virus Bulletin, Matthew Nunes, a Reverse Engineer at PwC, unveils a powerful methodology for automating the deobfuscation of JavaScript malware and the subsequent extraction of Indicators of Compromise (IOCs). The presentation, titled "Exploiting compiler theory to automate the extraction of IOCs from JavaScript malware," delves into the foundational principles of compilers and demonstrates how these concepts can be leveraged using tools like Babel to programmatically reverse highly obfuscated code. This approach significantly enhances the efficiency and scalability of threat intelligence operations, allowing analysts to quickly pivot from raw, unreadable malware samples to actionable intelligence, such as Command and Control (C2) addresses, persistence mechanisms, and file paths.

Key moments
- 0:00 Introduction to compilers and talk agenda
- 4:00 Understanding AST transformation with visitor functions
- 8:00 Context: Analyzing a Strella Stealer JavaScript loader
- 12:00 Babel implementation: Cleaning up redundant variable assignments
- 18:00 Using Babel's evaluate to concatenate obfuscated strings
- 20:00 Extracting the final deobfuscated payload from eval
- 22:00 Conclusion: Automated IOC extraction and impact
Exploiting compiler theory to automate the extraction of IOCs from JavaScript malware
Speakers: Matthew Nunes, Reverse Engineer, PwC
Conference: Virus Bulletin
YouTube: https://www.youtube.com/watch?v=gNfwEXJy8f4
Overview
In this insightful talk from Virus Bulletin, Matthew Nunes, a Reverse Engineer at PwC, unveils a powerful methodology for automating the deobfuscation of JavaScript malware and the subsequent extraction of Indicators of Compromise (IOCs). The presentation, titled "Exploiting compiler theory to automate the extraction of IOCs from JavaScript malware," delves into the foundational principles of compilers and demonstrates how these concepts can be leveraged using tools like Babel to programmatically reverse highly obfuscated code. This approach significantly enhances the efficiency and scalability of threat intelligence operations, allowing analysts to quickly pivot from raw, unreadable malware samples to actionable intelligence, such as Command and Control (C2) addresses, persistence mechanisms, and file paths.
Nunes highlights the critical need for automated solutions in an era where JavaScript loaders and droppers are prevalent and often heavily obfuscated to evade detection and hinder analysis. Traditional manual deobfuscation is time-consuming and doesn't scale to the thousands of samples encountered by modern security teams. By applying compiler theory, specifically the manipulation of Abstract Syntax Trees (ASTs), this methodology offers a robust and adaptable alternative that can handle variations in obfuscation techniques, a common pitfall for signature-based or regex-driven approaches.
The talk provides a practical, step-by-step guide, using a real-world Strella Stealer JavaScript loader as a case study. The ability to automatically process over 6,400 samples and extract critical IOCs underscores the profound impact of this technique on improving the completeness and timeliness of threat intelligence for Security Operations Center (SOC) analysts and incident responders. This presentation is invaluable for anyone involved in malware analysis, threat intelligence, or incident response seeking innovative ways to combat JavaScript-based threats.
Background
▶ Watch: Introduction to compilers and talk agenda (0:00)
To understand the core of Nunes's methodology, a basic understanding of compiler theory is essential. Compilers fundamentally translate source code from one language into another, or into a different form of the same language. This process can be broadly broken down into three stages: parsing, transformation, and code generation.
Parsing is the initial stage where the source code is converted into a structured, abstract representation. This stage itself has two sub-stages:
- Lexical analysis: The code is broken down into a stream of tokens – atomic units representing keywords, identifiers, operators, and literals. For example,
2 + 3would become tokens for2(literal),+(operator), and3(literal). - Syntactic analysis: These tokens are then organized into an Abstract Syntax Tree (AST). An AST is a tree-like representation that captures the hierarchical structure of the code, showing the relationships between tokens and expressions. For instance,
2 + 3would be represented as a binary expression node with+as the operator and2and3as its left and right children, respectively.
The transformation stage is where the compiler walks down the AST, applying changes to the nodes or restructuring the tree. This is the most critical phase for deobfuscation. Transformation functions, often called visitors, are invoked when specific node types are encountered during the tree traversal. These visitors can inspect, modify, add, or remove nodes, effectively rewriting portions of the code's structure or content.
Finally, code generation takes the modified AST and converts it back into executable code, or in this case, human-readable JavaScript code. This involves recursively traversing the tree and "stringifying" its structure back into source code.
Matthew Nunes specifically leverages Babel, a JavaScript-to-JavaScript compiler, or transpiler. Babel's original purpose, conceived by its creator, was to transform modern ECMAScript 6 (ES6) features (released in 2015) into older, backward-compatible JavaScript that could run in browsers lacking full ES6 support. This functionality makes Babel an ideal candidate for deobfuscation, as it provides a robust framework for parsing, traversing, and generating JavaScript code. Nunes also credits the work of "stake enthusiast" (not a real name) whose blog provided significant learning resources on using Babel for this purpose.
The specific malware analyzed in the talk is a JavaScript loader associated with Strella Stealer. Strella Stealer was first reported in November 2022 by DCSO Scytec. It's an information stealer with a unique focus, primarily targeting login data from only two applications: Microsoft Outlook and Mozilla Thunderbird. Its campaigns predominantly target users in specific countries, including Spain, Italy, Germany, and Ukraine. The stealer binary itself is typically a DLL, and interestingly, its core stealing functionality has remained largely unchanged since its initial discovery. The infection chain observed in this case involved an email with an SVG attachment, which, when opened, downloaded a script displaying a download button. Clicking this button led to a ZIP file containing the heavily obfuscated JavaScript loader that was the subject of Nunes's analysis.
Key Findings
▶ Watch: Context: Analyzing a Strella Stealer JavaScript loader (8:00)
The central finding of Matthew Nunes's presentation is the demonstration of a highly effective and scalable method for automating JavaScript malware deobfuscation by instrumenting a compiler. By applying principles of compiler theory and leveraging the Babel transpiler, Nunes developed a system capable of transforming incomprehensible, obfuscated JavaScript into clear, actionable code.
The primary contributions and results of this methodology include:
- Automated IOC Extraction: The system successfully automates the extraction of critical IOCs such as Command and Control (C2) addresses, registry keys used for persistence, and file paths for self-copying and execution. This transforms a laborious manual process into an efficient, programmatic one.
- Scalability and Efficiency: The technique was successfully applied to over 6,400 samples of JavaScript malware, specifically Strella Stealer loaders. This high volume processing capability allows threat intelligence teams to gain a much more comprehensive understanding of ongoing campaigns and provide timely, complete intelligence to SOC analysts and incident responders.
- Robustness Against Code Variations: Unlike many traditional deobfuscation methods that often break down when encountering even minor variations in obfuscation techniques, Nunes's AST-based approach proved to be significantly more resilient. By operating on the structural representation of the code rather than superficial patterns, it maintained its effectiveness across diverse samples, a major advantage in dynamic threat landscapes.
- Generalized Applicability: While demonstrated with Strella Stealer, the underlying principles and Babel-based techniques are generalizable. Nunes noted that the team is actively exploring and successfully applying this method to malware from other threat actors, indicating its broad utility beyond the initial use case.
- Transformation to Actionable Intelligence: The output of the deobfuscation process is not just "less obfuscated" code, but concrete data points that directly feed into defensive measures, such as network blocking, host-based detection rules, and threat hunting queries.
In essence, the key finding is that a deep understanding of how compilers process code, coupled with the programmatic manipulation capabilities of tools like Babel, provides a powerful and adaptable framework for combating sophisticated JavaScript obfuscation at scale.
Technical Deep Dive
▶ Watch: Babel implementation: Cleaning up redundant variable assignments (12:00)
The technical core of Matthew Nunes's approach revolves around systematically manipulating the Abstract Syntax Tree (AST) of obfuscated JavaScript code using Babel. The process is broken down into several stages, each targeting a specific obfuscation technique, ultimately leading to the extraction of plain-text IOCs.
The initial analysis of the Strella Stealer JavaScript loader revealed two primary obfuscation patterns:
- Repeated Variable Assignments: The same variable was initialized multiple times, with only the last assignment being relevant. For example,
let v = 'R'; v = 'B'; v = 'I'; v = 'V';– only the finalv = 'V'matters. - Concatenated Strings: Critical strings (like commands or C2s) were built by concatenating individual characters or variable references using the
+operator, often across many lines.
To begin, Nunes emphasizes the utility of aseexplorer.net, an open-source online tool that takes JavaScript code and visualizes its corresponding AST. This helps analysts understand the structure of the code and identify the types of nodes that need to be targeted for transformation.
The deobfuscation script utilizes several Babel packages:
@babel/types: Provides utilities to check node types (e.g.,t.isIdentifier(),t.isStringLiteral()) and create new AST nodes.@babel/parser: Parses the input JavaScript code into an AST.@babel/traverse: Enables walking the AST and applying visitor functions to specific node types.@babel/generator: Converts a modified AST back into JavaScript code.
Additionally, the Node.js built-in fs package is used for file system operations.
The process unfolded in distinct stages:
Stage 1: Initial Variable Mapping (First Pass Traversal)
The first step was to identify the final, effective values of repeatedly assigned variables.
- Initialization: A global JavaScript object (acting as a hashmap or dictionary) is created to store mappings from variable names to their final values.
- AST Traversal: The
babel/traversefunction is used to walk the AST. - Visitor Function: A visitor function targets
AssignmentExpressionnodes.
- When an
AssignmentExpressionis encountered (e.g.,ilco = 'f'), the script extracts the variable name from theleftproperty (anIdentifiernode, e.g.,ilco) and its assigned value from therightproperty (e.g., aStringLiteralnode with value'f'). - This mapping (e.g.,
ilco: 'f') is stored in the global hashmap. If a variable is assigned multiple times, its value in the hashmap is simply overwritten, ensuring only the last assignment is recorded.
Crucially, this first pass does not modify the AST; it only populates the variable-to-value map.
Stage 2: Variable Cleanup (Second Pass Traversal & Modification)
With the accurate mapping of variables to their final values, the next stage aims to clean up the code by removing redundant assignments.
- Second AST Traversal: The AST is traversed again, also targeting
AssignmentExpressionnodes. - Visitor Function: For each
AssignmentExpressionencountered:
- It checks if the assigned value in the current node matches the final value stored in the global hashmap for that variable.
- If the current assignment's value does not match the final value (meaning it's an overwritten, redundant assignment), the entire
AssignmentExpressionnode is removed from the AST usingpath.remove().
This stage drastically reduces the code size, transforming thousands of lines of redundant assignments into a concise set where each variable is assigned only once, often resulting in just 64 lines of meaningful assignments.
Stage 3: Replacing Variable References in Concatenated Strings
The malware often constructs commands or strings by concatenating variable names (e.g., v + o + n). This stage replaces these variable references with their actual string literal values.
- Observation: These concatenations typically form a "left-heavy tree of nested binary expressions," where each
BinaryExpressionrepresents a+operator, and the actual variable names areIdentifiernodes stored on the right-hand side. - AST Traversal: A new traversal is initiated.
- Visitor Function: This function targets
Identifiernodes.
- To ensure only relevant identifiers (those within string concatenations) are modified, a check is performed:
t.isBinaryExpression(path.parent). This verifies that the parent of theIdentifiernode is indeed aBinaryExpression(i.e., part of a+operation). - If the conditions match, the variable name (from the
Identifiernode) is used to look up its value in the global hashmap. - The
Identifiernode is then replaced with a newStringLiteralnode containing the retrieved value usingpath.replaceWith(t.stringLiteral(value)).
Stage 4: Concatenating String Literals
After replacing variable references with string literals, the next logical step is to combine these individual string literals into single, continuous strings (e.g., 'e' + 'v' + 'a' + 'l' becomes 'eval').
- AST Traversal: A traversal targets
BinaryExpressionnodes. - Visitor Function:
- Babel provides an inbuilt
evaluatefunction which can determine the value of an expression at compile time if possible. This function is called on theBinaryExpressionnode. - The
evaluatefunction returns both the computedvalueand aconfidentflag. - If
confidentis true and thevalueis a string, a newStringLiteralnode is created with the combined string. - This new
StringLiteralnode then replaces the originalBinaryExpressionnode usingpath.replaceWith(t.stringLiteral(evaluatedValue)). The use ofpath.replaceWith(instead ofpath.node.replaceWith) is crucial as it handles metadata and references safely.
Stage 5: Extracting the Final Payload String
The deobfuscated code often reveals an eval() call with a very long string argument, which contains the next stage of the malicious script.
- AST Traversal: The traversal targets
CallExpressionnodes. - Visitor Function:
- It checks if the
callee(the function being called) is anIdentifierwith the name'eval'. - It also verifies that the
CallExpressionhas exactly oneargument, and that this argument is of typeStringLiteral. - If these conditions are met, the value of the
StringLiteralargument is extracted and stored in a global variable (e.g.,newScript).
This extracted string represents the next, often still somewhat obfuscated, stage of the malware.
Stage 6: Deobfuscating the Extracted String
The extracted newScript string from Stage 5 is then treated as a new input. The entire deobfuscation process (Stages 1 through 4) is reapplied to this string. This recursive application of the deobfuscation logic eventually reveals the final, clear-text IOCs. The result for the Strella Stealer sample was a script showing the C2 address, registry keys for persistence (e.g., running on reboot), and file paths for copying itself to the AppData folder. The script essentially copies itself, contacts its C2, sets up persistence, and then enters a loop waiting for further commands.
This multi-stage, AST-driven approach, carefully leveraging Babel's programmatic capabilities, allows for a robust and automated extraction of vital threat intelligence from even highly obfuscated JavaScript malware.
Demo / Proof of Concept
▶ Watch: Extracting the final deobfuscated payload from eval (20:00)
While the talk itself did not feature a live, interactive demo in the traditional sense, Matthew Nunes's presentation served as a comprehensive, step-by-step walkthrough that effectively functioned as a proof-of-concept. He meticulously demonstrated the entire deobfuscation process using code snippets and visualizations of the Abstract Syntax Tree (AST), primarily using the aseexplorer.net tool.
Nunes walked the audience through the specific malicious JavaScript sample, highlighting the obfuscation patterns. He then showed how each stage of the deobfuscation script, written using Babel's API (@babel/parser, @babel/traverse, @babel/types, @babel/generator), progressively transformed the code. This included visual examples of:
- The initial AST structure of variable assignments and concatenated strings.
- The effect of the first traversal to map variable values.
- The resulting, cleaner code after redundant assignments were removed.
- The transformation of variable references into string literals.
- The consolidation of multiple string literals into single strings using Babel's
evaluatefunction. - The final extraction of the
evalargument and its subsequent deobfuscation.
By presenting the actual code used for each transformation alongside the "before" and "after" states of the JavaScript, Nunes provided a clear and practical demonstration of how compiler theory and Babel could be applied to achieve automated malware deobfuscation. The ultimate "proof" was the display of the final, completely deobfuscated script containing the C2 address, registry keys, and file paths, directly extracted from the original, unreadable sample. The successful application of this technique to over 6,400 real-world samples further validated its effectiveness and scalability.
Defensive Implications
▶ Watch: Conclusion: Automated IOC extraction and impact (22:00)
The automated deobfuscation methodology presented by Matthew Nunes carries significant defensive implications for organizations facing persistent threats from JavaScript-based malware. By enabling rapid and scalable extraction of Indicators of Compromise (IOCs), this approach directly enhances the capabilities of Security Operations Centers (SOCs), Incident Response (IR) teams, and Threat Intelligence (TI) analysts.
Firstly, the ability to automate IOC extraction from thousands of samples drastically improves the timeliness and completeness of threat intelligence. Instead of manually sifting through complex and time-consuming obfuscated code, security teams can now programmatically obtain critical data such as C2 server addresses, registry keys for persistence, and file paths where malware copies itself. This allows for quicker updates to firewalls, intrusion detection systems, endpoint detection and response (EDR) rules, and other security controls, effectively reducing the window of opportunity for attackers.
Secondly, the robustness against code variations is a key advantage. Traditional signature-based or regex-driven detection and deobfuscation methods are often brittle, failing when threat actors introduce even minor changes to their obfuscation techniques. By working at the AST level, this methodology operates on the underlying structure of the code, making it far more resilient to superficial changes. This translates to more consistent detection and analysis, even as malware evolves.
Thirdly, this technique empowers proactive threat hunting. With automated deobfuscation, analysts can process large volumes of suspicious JavaScript files (e.g., from email gateways or web proxies) to uncover new C2 infrastructure or previously unknown persistence mechanisms. This allows organizations to move beyond reactive defense to actively search for and neutralize threats before they cause significant damage.
Furthermore, understanding the deobfuscated logic provides deeper insights into threat actor Tactics, Techniques, and Procedures (TTPs). By seeing the actual commands, API calls, and flow of the malware (e.g., copying itself to AppData, setting registry run keys, contacting C2), defenders gain a clearer picture of how specific threat groups operate. This intelligence can inform better defensive strategies, vulnerability patching priorities, and security awareness training.
Finally, the methodology fosters efficiency and resource optimization. Manual reverse engineering of JavaScript malware is a highly specialized and time-consuming task. Automating this process frees up skilled reverse engineers to focus on more complex, novel threats, while routine deobfuscation can be handled programmatically. This maximizes the impact of limited security resources and allows for a more comprehensive coverage of the threat landscape. In essence, this technique transforms a significant analytical bottleneck into a streamlined, intelligence-generating pipeline.
Key Takeaways
- Compiler Theory for Security: Leveraging fundamental compiler concepts, specifically Abstract Syntax Trees (ASTs) and visitor functions, provides a robust and scalable method for deobfuscating complex JavaScript malware.
- Babel as a Deobfuscation Engine: The Babel transpiler, originally designed for JavaScript compatibility, offers powerful programmatic capabilities through its API (
@babel/parser,@babel/traverse,@babel/types,@babel/generator) for parsing, transforming, and generating JavaScript code, making it ideal for automated malware analysis. - Automated IOC Extraction at Scale: The demonstrated methodology successfully automates the extraction of critical Indicators of Compromise (IOCs) like C2 addresses, registry keys, and file paths from over 6,400 samples of JavaScript loaders, significantly enhancing threat intelligence production.
- Resilience to Obfuscation Variations: By operating on the structural AST rather than superficial patterns, this technique is highly robust against variations in obfuscation, overcoming a major limitation of many traditional deobfuscation tools and methods.
- Practical Application for Strella Stealer: The talk provided a concrete case study using a JavaScript loader for Strella Stealer, showcasing how to systematically clean up redundant variable assignments, substitute variables in concatenated strings, and combine string literals to reveal the final malicious logic.
- Enhanced Defensive Posture: This automation directly benefits SOC analysts and incident responders by providing timely, actionable intelligence, enabling proactive threat hunting, improving detection capabilities, and offering deeper insights into threat actor TTPs.
About the Speaker(s)
Matthew Nunes is a Reverse Engineer based in Cardiff, Wales, working for PwC's global threat intelligence team. In his current role, he primarily focuses on analyzing malware associated with crime and financially motivated threat actors. Prior to his work in threat intelligence, Matthew gained experience as a vulnerability researcher and exploit developer, and before that, he worked in software development. His diverse background in software engineering and offensive security provides him with a unique perspective on understanding and combating complex malware.
Reviews
Dr. Zero (Offensive Security Researcher) — STRONG ACCEPT
Solid, practical work demonstrating AST-based deobfuscation of JavaScript malware using Babel. Not a novel technique — this approach has been floating around for years — but Nunes executes it cleanly, shows real-world application at scale (6,400 samples), and delivers something analysts can actually replicate tomorrow.
Heather Calloway (CISO) — SOLID
Competent defender-tooling talk that demonstrates a real workflow improvement for teams processing high volumes of JavaScript malware. Useful for shops with dedicated malware analysts; limited immediate relevance for most enterprise security programs that don't maintain in-house reversing capability.
→ Top-rated talks at Virus Bulletin Conference 2025 (VB2025)