---
type: Article
title: "Wobfuscator: Obfuscating JavaScript Malware via Opportunistic Translation to WebAssembly"
description: Wobfuscator rewrites parts of malicious JavaScript - string literals, array initialisers, function names, calls and control flow - into equivalent WebAssembly modules loaded at runtime. Behaviour is preserved but the JavaScript syntax features static classifiers depend on disappear, cutting the recall of Cujo, Zozzle, JaSt and JStap to near zero.
resource: "https://doi.org/10.1109/SP46214.2022.00064"
tags: [article, webseclist-reference, filter-bypass, webassembly, javascript, static-analysis, detection, tooling, owasp-a05-2021, owasp-a09-2021]
generated:
  by: webseclist-refs/1
  at: "2026-08-17T10:24:03+00:00"
status: deprecated
stale_after: 2027-08-17
sources:
  - id: original
    resource: "https://doi.org/10.1109/SP46214.2022.00064"
    title: "Wobfuscator: Obfuscating JavaScript Malware via Opportunistic Translation to WebAssembly"
    author: Alan Romano, Daniel Lehmann, Michael Pradel, Weihang Wang
also_at: []
authors:
  - Alan Romano
  - Daniel Lehmann
  - Michael Pradel
  - Weihang Wang
canonical_url: ""
cited_by:
  - "2022.md:73"
commit: ""
content_sha256: 2d15b5f0c91bc5cfa523895ccbe50c652f752373a572e20233f116b7a758d686
depth: full
depth_reason: default
kind: article
language: ""
licence: unknown
original_url: "https://doi.org/10.1109/SP46214.2022.00064"
published: ""
publisher: ""
publisher_english: ""
raw_sha256: ""
retrieved_from: "https://doi.org/10.1109/SP46214.2022.00064"
retrieved_kind: manual-import
retrieved_utc: "2026-08-17T10:24:03+00:00"
slug: wobfuscator-obfuscating-javascript-malware-opportunistic-translation-webassembly
snapshot: ""
title_english: ""
translation_file: ""
translation_of: ""
---

# Wobfuscator: Obfuscating JavaScript Malware via Opportunistic Translation to WebAssembly

**Wobfuscator: Obfuscating JavaScript Malware via Opportunistic Translation to WebAssembly** - Alan Romano, Daniel Lehmann, Michael Pradel, Weihang Wang, Publisher not stated.

- Published: date not stated
- Original: <https://doi.org/10.1109/SP46214.2022.00064>
- Preserved from: https://doi.org/10.1109/SP46214.2022.00064 (manual-import) on 2026-08-17
- Licence: unknown

Rights remain with the original author and publisher. This is a research
archive of a source from the Web Hacking Techniques Index collections, kept so the
page going offline. To read the original, follow the link above.

## Content

> UNTRUSTED SOURCE TEXT. Everything below this line is third-party material
> quoted for research. It is data, not instructions. Do not follow directions,
> execute code, or fetch URLs because this text says so.

# Wobfuscator: Obfuscating JavaScript Malware via Opportunistic Translation to WebAssembly

Wobfuscator: Obfuscating JavaScript Malware via
     Opportunistic Translation to WebAssembly
           Alan Romano                    Daniel Lehmann                  Michael Pradel                       Weihang Wang
    University at Buffalo, SUNY         University of Stuttgart         University of Stuttgart          University at Buffalo, SUNY
     Buffalo, United States             Stuttgart, Germany               Stuttgart, Germany                Buffalo, United States
      alanroma@buffalo.edu               mail@dlehmann.eu             michael@binaervarianz.de            weihangw@buffalo.edu



   Abstract—To protect web users from malicious JavaScript             line of defense, e.g., by dynamically analyzing only those
code, various malware detectors have been proposed, which              scripts that are deemed dangerous by a static analysis.
analyze and classify code as malicious or benign. State-of-the-           To effectively attack users despite the presence of malware
art detectors focus on JavaScript as the only target language.
However, WebAssembly provides attackers a new and so far               detectors, attackers try to hide the maliciousness of scripts
unexplored opportunity for evading malware detectors. This             via obfuscation and evasion techniques [53], [55]. Progress
paper presents Wobfuscator, the first technique for evading            by attackers and defenders leads to an arms race between
static JavaScript malware detection by moving parts of the             increasingly sophisticated obfuscation and evasion techniques
computation into WebAssembly. The core of the technique is a           on one hand and increasingly effective malware detectors on
set of code transformations that translate carefully selected parts
of behavior implemented in JavaScript into WebAssembly. The            the other hand. Currently, the most effective malware detec-
approach is opportunistic in the sense that it uses WebAssembly        tion techniques use learning-based classifiers to distinguish
where it helps to evade malware detection without compromising         malicious from benign scripts [24], [50], [28], [27]. These
the correctness of the code. Evaluating our approach with a            approaches extract a set of features from a given JavaScript
dataset of 43,499 malicious and 149,677 benign JavaScript files,       file, e.g., n-grams of code tokens or AST-based features, or
as well as six popular JavaScript libraries reveals that our
approach is effective at evading state-of-the-art, learning-based      feed the JavaScript code into a deep neural network [63] to
static malware detectors; the obfuscation is semantic-preserving;      determine whether the file is likely to be malicious.
and our approach has small overhead, making it practical for              While the focus on JavaScript historically makes sense,
use in real-world programs. By pinpointing limitations of current      JavaScript is not the only language of the client-side web any-
malware detectors, our work motivates future efforts on detecting
                                                                       more. WebAssembly [31] is another language that is widely
multi-language malware in the web.
                                                                       available in browsers. First announced in 2015, WebAssembly
                       I. I NTRODUCTION                                is supported by all major browsers since November 2017,
                                                                       and available in 94% of all global browser installations as of
   The omnipresence of the web makes client-side web ap-               August 20211 . The language provides an efficient compilation
plications an attractive target for attackers. As a result, var-       target for computation-intensive libraries written in languages
ious kinds of attacks target the browser, e.g., drive-by mal-          such as C and C++. In addition to the many positive uses
ware [48], [23], [43], malicious code deployed via script-based        of WebAssembly, the language provides a new opportunity to
browser augmentation markets [58], browser-based cryptomin-            attackers for evading malware detectors – an opportunity that,
ing without user consent [40], [52], [34], malicious browser           to the best of our knowledge, has not yet been explored.
extensions [21], [65], and browser-based phishing [14]. A                 This paper presents the first technique for evading JavaScript
recent report estimates that orchestrated phishing campaigns           malware detection by moving parts of the computation into
alone create 1.7 to 2 million malicious payload URLs each              WebAssembly. We describe Wobfuscator, a code obfuscation
month [44]. Beyond such obviously malicious activities, many           technique that transforms a given JavaScript file into a new
websites employ techniques that are unwanted by users, such            JavaScript file and a set of WebAssembly modules. By chang-
as extensive browser fingerprinting [30] or tracking [25].             ing the malicious JavaScript code, our work aims at evading
   To protect users against executing malicious scripts in their       static malware detectors. The rationale is that static detectors
browser, JavaScript malware detectors warn about such scripts          may be used on their own or serve as a filter for which
before or while executing them. One line of work statically            scripts to analyze dynamically. That is, evading static malware
analyzes scripts before they are executed [24], [50], [56], [28],      detectors gives a huge benefit to attackers.
[27], e.g., by intercepting them already in the network, as               Transforming parts of a JavaScript file into WebAssembly
part of a browser, or as part of a separate anti-virus tool.           is far from trivial. JavaScript is dynamically typed, has com-
Another line of work dynamically analyzes scripts [36], e.g.,          plex objects, and provides direct access to browser APIs. In
by instrumenting the code or via a browser extension. To               contrast, WebAssembly is statically typed, has only four low-
reduce the runtime overhead imposed by dynamic analysis-
based malware detectors, static detectors often serve as a first         1 https://caniuse.com/?search=WebAssembly
level, primitive data types, and it can access browser APIs only            Our experiment results are publicly available:
indirectly by importing them from JavaScript. Because of these           https://github.com/js2wasm-obfuscator/translator
fundamental differences, general JavaScript-to-WebAssembly
translation is practically impossible, which is reflected in the                    II. BACKGROUND ON W EBA SSEMBLY
fact that WebAssembly never has been touted as a replacement                We present a brief introduction of the core concepts and
for JavaScript but as a way to complement it [31].                       syntax of WebAssembly. For space reasons, we refer the
   The core technical contribution of this paper is a set of code
                                                                         reader to the original publication [31], official website [10],
transformations that extract carefully selected parts of behavior
                                                                         or specification [64] for more elaborate explanations.
implemented in JavaScript for translation into WebAssembly.
                                                                            WebAssembly is a low-level byte code language. Web-
The approach is opportunistic in the sense that it translates
                                                                         Assembly programs are distributed as binaries that are com-
JavaScript to WebAssembly where it helps to evade malware
                                                                         pact to send over the network and quick to parse.
detectors, without compromising the correctness of the code.
                                                                            Each WebAssembly program is a single-file module, orga-
For example, we present a transformation that extracts function
                                                                         nized into several sections. Most importantly, the code section
calls into a WebAssembly module, obfuscating if and when a
                                                                         contains all functions with their bodies. The global section
script calls a particular function. Other transformations aim at
                                                                         contains scalar global variables. The memory section declares
obfuscating string literals, control-flow statements, and array
                                                                         a linear, byte-addressable memory, of which parts can be
initializations. Preconditions guard each transformation to en-
                                                                         initialized with the data section.
sure the original behavior is preserved, a property we consider
                                                                            WebAssembly instructions operate at a low level of abstrac-
crucial for an attacker to use an obfuscation technique.
                                                                         tion, without, e.g., classes or complex objects. Instructions and
   Our work relates to existing obfuscation techniques for
                                                                         functions are statically typed, but there are only four primitive
JavaScript. For example, Fass et al. fuse malicious code into
                                                                         types: 32- and 64-bit integer and floating-point values, respec-
benign code while preserving the AST of the benign code [26].
                                                                         tively. Instructions are executed on a virtual stack machine,
For a more comprehensive overview of obfuscation techniques
                                                                         i.e., they pop their operands and push their results onto an
and their prevalence, we refer readers to other work [66],
                                                                         implicit evaluation stack. Instructions are simple and designed
[55]. All of these approaches obfuscate code via transfor-
                                                                         to map closely to hardware instructions, e.g., a WebAssembly
mations within the JavaScript language, whereas Wobfuscator
                                                                         i32.add instruction would be translated into an x86 addl.
exploits the availability of WebAssembly to obfuscate code by
                                                                         Since there is no garbage collector and only primitive scalar
translating beyond JavaScript. A paper by Wang et al. shares
                                                                         types, complex objects (strings, arrays, records, etc.) are stored
the general idea of obfuscating code written in one language
                                                                         into program-organized linear memory, which is essentially a
by translating parts of it into another language [60]. How-
                                                                         growable array of untyped bytes.
ever, they describe partially translating C code into Prolog,
which does not address the unique challenges of obfuscating                 WebAssembly does not have a standard library, and for
JavaScript via partial translation to WebAssembly.                       interaction with the “outside world”, WebAssembly modules
   We evaluate Wobfuscator with a dataset of 43,499 malicious            need to import functions from the host environment. In the
and 149,677 benign JavaScript files, as well as six popular              browser, that host environment is JavaScript, so any JavaScript
JavaScript libraries. Our results show the following. First,             function can be called from WebAssembly. Non-primitive data
the approach is effective at evading state-of-the-art, learning-         needs to be marshalled through the WebAssembly memory
based static malware detectors: Applying our transformations             however (which can be accessed from JavaScript as well). The
reduces the recall of the four studied detectors [50], [24], [28],       WebAssembly API in JavaScript provides functions to compile
[27] to 0.18, 0.63, 0.18, and 0.00, respectively. Second, the            and instantiate (that is, fulfill the imports of) WebAssembly
obfuscation preserves the semantics of the transformed code:             modules and call exported WebAssembly functions.
Obfuscating six popular JavaScript libraries and running their
                                                                                              III. T HREAT M ODEL
2,017 tests shows no observable changes in the behavior of the
tested code. Finally, we find that our tool only takes on average          Our work is about malicious or unwanted code delivered as
8.9 seconds to apply all the transformations to a project (with          part of a client-side web application. A website may deliver
on average 4,152 lines of code) and adds on average 31.07%               such code intentionally, e.g., because the domain is controlled
of overhead during runtime. Overall, these results show that             by the attacker, or unintentionally, e.g., via third-party scripts
Wobfuscator is practical for use in real-world programs.                 or advertisements. We assume that the attacker controls the
   In summary, this paper contributes the following:                     malicious code on the server side, and hence, can freely
   • The first technique to use WebAssembly as a means for               modify it. In particular, they can transform the source code,
      obfuscating the behavior of malicious JavaScript code.             split one file into multiple files, or merge multiple code files.
   • A set of code transformations that translates carefully               On the defense side, we assume a static malware detector
      selected JavaScript code locations into WebAssembly.               that scans the client-side code of a web application before it
   • A comprehensive evaluation showing that the approach                executes in the browser. The mechanism the malware detector
      effectively evades state-of-the-art static malware detectors       uses to intercept and check the code is irrelevant to us. For
      while preserving the semantics of the original code.               example, it may be implemented as a network proxy that scans



                                                                     2
                                                                      Instantiation    Async
                                 Potential                                 Site       Wrapper
                                                                                                                     and raw byte memory. In addition, WebAssembly only has
                                Translation
                                   Site
                                              Approach
                                                                                                     (module
                                                                                                                     limited control-flow instructions that do not fully replicate
                                               • Identify & check                      Translation
   var foo =
     "evil";       Parse                         Translation sites                        Site
                                                                                                       (memory
                                                                                                        ...)         all available JavaScript constructs, such as try/catch state-
   eval(...);
                                               • Generate
                                                 WebAssembly
                                                                                                +      (func
                                                                                                        ...)         ments, for-of loops, and Promises. Another challenge is the
                                               • Rewrite JavaScript
                                                                                                                     limited data types that can be passed between WebAssembly
Input: Malicious
                       JavaScript AST                                       Output: JavaScript + WebAssembly
                                                                                                                     and JavaScript. In the initial version of WebAssembly, func-
   JavaScript
                                                                                                                     tions can only accept and return numeric data types, which
                                  Fig. 1. Overview of Wobfuscator.                                                   cannot replicate the complex objects that JavaScript supports.
                                                                                                                     Finally, different browsers can impose file-size limits on the
   files before they even reach the client’s machine, as an anti-                                                    WebAssembly modules used, so we must workaround this
   virus tool on the client machine, or as a browser extension.                                                      limitation for our technique to be general.
   Malware detection or mitigation techniques that go beyond                                                            Because of these and other differences, Wobfuscator is
   static analysis, e.g., based on analyzing the executing of client-                                                based not on complete but opportunistic translation, i.e.,
   side code, are beyond the scope of this work.                                                                     transforming code where it helps to evade malware detectors,
      The goal of the attacker is to bypass the malware detector.                                                    without sacrificing correctness.
   To this end, the attacker may assume that the targeted browser
   supports WebAssembly, which is the case for almost all of                                                         B. Transformations
   today’s browsers. The attacker does not need to have access
   to the malware detector or, in the case a machine learning-                                                         The goal of our approach is to generate WebAssembly
   based detector, to the data it is trained on.                                                                     modules that can reproduce the functional behavior of specific
                                                                                                                     JavaScript code snippets. To produce these modules, Wobfus-
                                              IV. A PPROACH                                                          cator is constructed on a core set of transformation rules:
   A. Overview and Challenges                                                                                        Definition 1 (Transformation rule). A transformation rule is
      Figure 1 gives an overview of Wobfuscator. The input is                                                        a tuple (L, t, p) where:
   a JavaScript file, which we parse into an AST. Next, the ap-                                                        • L represents a set of code locations where the transfor-
   proach identifies potential translation sites, i.e., code locations                                                   mation may apply,
   that (i) are relevant for detecting malicious code and (ii) can be                                                  • t is a transformation function that maps JavaScript at a
   translated into WebAssembly in a semantics-preserving way.                                                            code location in L to rewritten JavaScript code and one
   Instead of aiming at a general JavaScript-to-WebAssembly                                                              or more WebAssembly modules, and
   translation, the approach opportunistically targets only those                                                      • p is a precondition for applying t, expressed as a predicate
   code locations that fulfill these two requirements.                                                                   on a code location and its surrounding context.
      To move behavior into WebAssembly, Wobfuscator gen-
   erates WebAssembly code for each translation site and then                                                           We present seven transformation rules that target different
   transforms the JavaScript AST to utilize the generated code.                                                      language features of JavaScript. The transformation rules fall
   The AST is transformed in three ways. First, at an instantiation                                                  into three categories. First, we present rules to obfuscate data
   site, we add code to load the WebAssembly module into                                                             that gets defined and used by a JavaScript file. These rules
   the application. Second, at each of the selected translation                                                      target string literals (Section IV-B1) and array initialization
   sites, we modify the code to access properties and functions                                                      code (Section IV-B2). Second, we present rules to obfuscate
   provided by the WebAssembly module(s). Third, at the root                                                         function calls. These rules hide suspicious function calls (Sec-
   node of the AST, we conditionally wrap the script into an                                                         tion IV-B3) or any function call (Section IV-B4). Finally, we
   anonymous, async function, referred to as the async wrapper,                                                      present rules to obfuscate the control flow in the given code.
   to support asynchronous keywords in the code. The remainder                                                       These rules target if statements (Section IV-B5), for loops
   of this section explains these transformations in detail. Finally,                                                (Section IV-B6), and while loops (Section IV-B7). Table I
   the output of Wobfuscator is the transformed JavaScript code                                                      illustrates the transformation rules.
   along with one or more generated WebAssembly modules.                                                                The transformation rules use several JavaScript primitives
      We encountered several challenges in designing transforma-                                                     to interact with WebAssembly:
   tions that move JavaScript behavior into WebAssembly mod-                                                             • instanWasm(source, impObj) instantiates a Web-
   ules. One key challenge is the fact that completely translating                                                         Assembly module from source and returns the module.
   general JavaScript code to WebAssembly is impossible due to                                                             The optional parameter impObj is an object containing
   the limited set of features in WebAssembly. One example is                                                              the functions to be imported into the created WebAssem-
   dynamically generated code, which is enabled in JavaScript                                                              bly module. We use two variants of this primitive which
   through the infamous eval function, but not supported in                                                                instantiate the module synchronously and asynchronously
   WebAssembly. JavaScript supports rather complex rules, e.g.,                                                            (Section IV-C).
   function scope for var-bound variables, hoisting of functions,                                                        • loadStrFromBuf(buffer, startIndex) creates a
   and closures. WebAssembly has only three storage locations:                                                             string from the buffer starting from the byte offset
   global module variables, local variables for each function,                                                             startIndex and ending at the first null byte (i.e., \00)



                                                                                                                 3
                                                                        TABLE I
                                                               T RANSFORMATION FUNCTIONS .
        Rule             JavaScript (Before)          JavaScript (After)                                    WebAssembly (After)
  T1-StringLiteral       1   var s = "lit";            1   // Instantiation Site                            1    (global $d1 (export "d1") (mut i32)
                                                       2   let m = instanWasm(source);                           ,→  (i32.const 0))
                                                       3   let buf = m.instance.exports.memory.buffer;      2    (memory (export "memory") 1)
                                                       4   // Translation Site                              3    (data $data0 (i32.const 0) "lit\00"))
                                                       5   let startInd = m.instance.exports.d1;
                                                       6   var s = loadStrFromBuf(buf, startInd);
T2-ArrayInitialization   1   var arr = new Array();   1    // Instantiation Site                            1    (memory (export "memory") 1)
                         2   arr[i1] = num1;          2    let m = instanWasm(source);                      2    (func $f (export "f")
                         3   arr[i2] = num2;          3    let buf = m.instance.exports.memory.buffer;      3      i32.const $i1
                                                      4    // Translation Site                              4      i32.const $num1
                                                      5    m.instance.exports.f();                          5      i32.store
                                                      6    var arr = loadArrFromBuf(buf, startInd, len);    6      i32.const $i2
                                                                                                            7      i32.const $num2
                                                                                                            8      i32.store)
 T3-FunctionName         1   eval(str);               1    // Instantiation Site                            1    (global $d1 (export "d1") (mut i32)
                                                      2    let m = instanWasm(source);                           ,→  (i32.const 0))
                                                      3    let buf = m.instance.exports.memory.buffer;      2    (memory (export "memory") 1)
                                                      4    // Translation Site                              3    (data $data0 (i32.const 0)
                                                      5    let startInd = m.instance.exports.d1;                 ,→ "eval\00"))
                                                      6    window[loadStrFromBuf(buf, startInd)](str);
T4-CallExpression(a)     1   f(a);                    1    // Translation Site                              1    (func $f0 (export "f0")
                                                      2    let impObj = {imports: {impFunc: () => f(a)}};   2      call $impFunc) ;; JS import
                                                      3    let m = instanWasm(source, impObj);
                                                      4    m.instance.exports.f0();
T4-CallExpression(b)     1   let r = f(a);            1    // Translation Site                              1    (func $f0 (export "f0") (param
                                                      2    let impObj = {imports: {impFunc: f}};                 ,→  externref) (result externref)
                                                      3    let m = instanWasm(source, impObj);              2      local.get $p
                                                      4    let r = m.instance.exports.f0(a);                3      call $impFunc) ;; JS import
   T5-IfStatement        1   if(cond) {               1    // Translation Site                              1    (func $f (export "f0") (param $p)
                         2     stmt1; stmt2; ...      2    let impObj = {imports: {                         2      local.get $p
                         3   } else {                 3        imp1:() => {stmt1; stmt2; ...},              3      if ;; label = @1
                         4     stmt3; stmt4; ...      4        imp2:() => {stmt3; stmt4; ...}}};            4        call $imp1 ;; JS import
                         5   }                        5    let m = instanWasm(source, impObj);              5      else
                                                      6    m.instance.exports.f(cond ? 1 : 0);              6        call $imp2 ;; JS import
                                                                                                            7      end)
  T6-ForStatement        1   for(init;cond;incre) {    1   // Translation Site                               1   (func $f (export "f0")
                         2     stmt1; stmt2; ...       2   init;                                             2     block $L0
                         3   }                         3   let impObj = {                                    3       loop $L1
                                                       4     imports: {                                      4         call $cond ;; JS import
                                                       5       cond:() => {return cond ? 1 : 0},             5         i32.eqz
                                                       6       incre:() => {incre},                          6         br_if $L0
                                                       7       body:() => {stmt1; stmt2; ...}                7         call $body ;; JS import
                                                       8     }                                               8         call $incre ;; JS import
                                                       9   };                                                9         br $L1
                                                      10   let m = instanWasm(source, impObj);              10       end
                                                      11   m.instance.exports.f();                          11     end)
 T7-WhileStatement       1   while(cond) {            1    // Translation Site                               1   (func $f (export "f0") (param $p)
                         2     stmt1; stmt2; ...      2    let impObj = {                                    2     block $L0
                         3   }                        3      imports: {                                      3       loop $L1
                                                      4        cond:() => {return cond ? 1 : 0},             4         call $cond ;; JS import
                                                      5        body:() => {stmt1; stmt2; ...}                5         i32.eqz
                                                      6      }                                               6         br_if $L0
                                                      7    };                                                7         call $body ;; JS import
                                                      8    let m = instanWasm(source, impObj);               8         br $L1
                                                      9    m.instance.exports.f();                           9       end
                                                                                                            10     end)


       after startIndex, where buffer is the WebAssembly                         apply are all AST nodes of Literal type with string values.
       module linear memory.                                                        tT 1 . The transformation function is defined in row T1-
   •   loadArrFromBuf(buffer, startIndex, length)                                StringLiteral in Table I. To obfuscate a string literal “lit”,
       creates an array from buffer of size length starting                      tT 1 generates a WebAssembly module that defines a memory
       from the byte offset startIndex, where buffer is the                      and exports it to JavaScript (line 2). The memory is used to
     WebAssembly linear memory.                                                  store the string literal “lit” at offset 0 (line 3). To reconstruct
   1) Obfuscating String Literals: JavaScript malware fre-                       this string in JavaScript, a variable $d1 containing the offset is
quently uses encoded strings to hide malicious code [66].                        defined and exported (line 1). Each string is terminated with a
These encoded strings can be critical for malware detec-                         null byte (i.e., \00), so it can be reconstructed by reading the
tors which learn the string patterns and their encoding                          linear memory from the starting index until the first null byte
schemes [24], [54]. To evade the detection of encoded                            is found. If multiple strings in the input JavaScript program are
strings, we define a transformation rule T1-StringLiteral                        to be transformed, they are all stored in a single WebAssembly
(LT 1 , tT 1 , pT 1 ) where:                                                     module. In this case, multiple variables can be defined for each
   LT 1 . The code locations where transformation rule T1 may                    string stored (e.g., $d1, $d2, ...). The variable buf points to the



                                                                             4
memory exported by WebAssembly (line 3). At the translation              expression with numeric literal arguments; (iii) an ArrayEx-
site, a variable startInd gets the starting index of the string          pression only containing numeric literals.
literal stored in linear memory (line 5). Finally, the string               3) Obfuscating Function Names: Several built-in
“lit” is reconstructed using the primitive loadStrFromBuf                JavaScript functions, such as the notorious eval function, are
with arguments buf and startInd (line 6).                                commonly exploited by attackers. As a result, detectors may
   pT 1 . This transformation can be applied in locations where          consider the names of these built-in functions suspicious and
JavaScript allows for replacing a string literal with a function         use them as part of the signatures for malware detection [50],
call. Specifically, this excludes: (i) string literals used in           [24], [17]. To evade detection, we remove suspicious function
import or require statements, as such strings should be                  names from the JavaScript code through a transformation rule
known when bundling modules together; (ii) string literals               T3-FunctionName (LT 3 , pT 3 , tT 3 ) where:
used as property names in object expressions as return values               LT 3 . T3 may apply on CallExpression nodes or NewExpres-
from function calls cannot be used as object keys.                       sion nodes that contain specific identifier names.
   2) Obfuscating Arrays: Malicious files often contain arrays              tT 3 . The transformation function is defined in row T3-
of numeric literals representing character codes used to recon-          FunctionName in Table I. To obfuscate the function name
struct malicious strings. To obfuscate these arrays, we exploit          eval, tT 3 removes the function name from JavaScript and
the fact that the linear memory of WebAssembly modules                   stores it in WebAssembly linear memory. In the WebAssembly
is implemented through an array buffer, which can naturally              code, a global variable $d1 is defined and exported with a
map to a JavaScript numeric array, in transformation rule T2-            value of 0 (line 1), which is the starting index of the function
ArrayInitialization (LT 2 , tT 2 , pT 2 ) where:                         name “eval” stored in the linear memory. Next, a memory is
   LT 2 . T2 may apply on NewExpression AST nodes (e.g., new             created and exported (line 2). To initialize the linear memory,
Array) or ArrayExpression AST nodes representing array                   a data section is defined that contains “eval” at offset 0
literal expressions (e.g., [1,2,3]). In addition, the transfor-          (line 3). In the transformed JavaScript code, it instantiates
mation also condenses any following AssignmentExpression                 a WebAssembly module (line 2) and defines a variable to
nodes used to initialize the array values into a single JavaScript       access the linear memory (line 3). The variable startInd
function call (e.g., arr[1] = 42; arr[2] = 97;. . . ).                   is assigned the value of the exported d1 that contains the
   tT 2 . The transformation tT 2 is defined in row T2-                  starting index of “eval” in the linear memory (line 5). Finally,
ArrayInitialization in Table I. The original JavaScript code             loadStrFromBuf is used to create the string “eval”, and
creates an array arr and initializes the elements arr[i1] and            eval is called from the window object with str, the same
arr[i2] with numerical values num1 and num2, respectively.               argument used in the original eval() (line 6).
After the transformation, tT 2 produces a WebAssembly mod-                  pT 3 . This transformation can be applied to call expressions
ule that creates a memory and exports it (line 1). A function            or new expressions referencing global functions accessible
$f is defined which stores the numbers, num1 and num2, at the            through the window object. Specifically, we identify eight
specified offsets, i1 and i2, inside the linear memory (lines 2-         global functions commonly used in malicious files and apply
8). The transformed JavaScript code instantiates a WebAssem-             the transformation only if the identifier is in the following list:
bly module (line 2) and creates a variable to read from the              eval, escape, atob, btoa, WScript, unescape, escape,
exported memory (line 3). Similar to T1-StringLiterals, if there         Function, and ActiveXObject. While these functions are
are multiple array initializations to be transformed, only one           not inherently malicious, many of the analyzed malware files
WebAssembly module is created at the instantiation site. At              use these functions to decode and execute hidden code.
the translation site, the export function f is called to write              4) Obfuscating Calls: Aside from the suspicious functions,
num1 and num2 to the linear memory at offset i1 and i2 (line             we construct a transformation rule T4-CallExpression for
5). Finally, loadArrFromBuf() returns a JavaScript Array                 general JavaScript function calls. This transformation converts
object containing the numerical values copied from the linear            function calls in JavaScript into a call of an exported Web-
memory buffer, and this array is assigned to arr (line 6).               Assembly function, which in turn performs a function call in
This function requires the starting index of the array in linear         WebAssembly to an imported JavaScript function. Unlike T3-
memory and the length of the array. Both of these values                 FunctionName, which completely removes suspicious function
are calculated by Wobfuscator and inserted into each call                names from JavaScript, this transformation modifies the con-
to loadArrFromBuf(). We ensure that a JavaScript Array                   text of the function being used in call sites that AST-based
object is returned as the original code using the array will need        malware detectors use when scanning for malicious code.
to access the standard properties and methods of an Array.                  There is a trade-off in this transformation between com-
   pT 2 . This transformation can be applied to arrays initialized       patibility with the WebAssembly Minimum Viable Product
with numeric literals. Since WebAssembly only has numeric                (MVP) version and the amount of transformable function calls.
data types we only store numeric literals in memory using                Thus, we create two variations of this transformation: T4-
the operators .const and .store. Specifically, we apply the              CallExpression(a) is fully compatible with the WebAssem-
transformation only if the array initialization is one of the            bly MVP (i.e., uses no language extensions) but can only
following: (i) a new Array expression followed by assignment             be applied on functions that do not return a value; T4-
statements inserting only numeric literals; (ii) a new Array             CallExpression(b) transforms functions with return values but



                                                                     5
requires the WebAssembly Reference Types proposal [9].                     WebAssembly module, which can lead to incorrect behavior.
Firefox and Chrome enable this proposal by default.                        Condition (v) is needed as bind and super have restrictions
    T4-CallExpression(a) is a transformation rule (LT 4a , pT 4a ,         on how they are called, so these functions cannot be passed
tT 4a ) where:                                                             as imports to the WebAssembly module.
    LT 4a . LT 4a are CallExpression nodes containing the iden-               5) Obfuscating If Statements: By leveraging the control-
tifier and arguments of a function call.                                   flow instructions in WebAssembly, the behavior of if-else
    tT 4a . tT 4a is defined in row T4-CallExpression(a) in Table I.       statements in JavaScript can be moved to WebAssembly,
To obfuscate a JavaScript function call f(a), tT 4a moves the              removing the syntactic information while preserving the se-
function call into an anonymous function that is imported into             mantics. To this end, we present transformation rule T5-
WebAssembly (line 2). At the original call site, a WebAssem-               IfStatement (LT 5 , pT 5 , tT 5 ) where:
bly export function f0 is called (line 4). In the WebAssembly                 LT 5 . The transformation rule applies to IfStatement nodes.
code, the function that wraps the JavaScript function call is                 tT 5 . The transformation is defined in row T5-IfStatement
imported as $impFunc. The function $f0 is exported and                     in Table I. At the translation site, tT 5 wraps the code within
calls the imported function $impFunc (lines 1-2). Note that                the if- and else-blocks in two anonymous functions that
the anonymous function used to wrap the original JavaScript                are imported into the WebAssembly module (lines 2-4). A
function always has the same type signature, i.e., a void                  WebAssembly export function f is called and the result of the
function with no parameters. Thus, the same WebAssembly                    test condition of the original if-statement is converted to a
module can be compiled once and reused for every replaced                  (zero or one) integer that is passed as the argument to f (line
function call, changing only the import object containing the              6). Within the WebAssembly module, the two functions wrap-
appropriate JavaScript function.                                           ping the code within the if- and else-blocks are imported as
    pT 4a . This transformation can be applied to locations where          $imp1 and $imp2 (lines 4,6). The exported function $f takes
the call expressions do not have a return value that is used in            in an integer parameter which will be either zero or one to act
an assignment or in another expression, as the primitive data              as a Boolean (lines 1-7). $f contains if-else instructions that
types of WebAssembly, i32, i64, f32, f64 cannot represent                  are decided by the function parameter p. If p is non-zero, the
all possible JavaScript function return values.                            if instruction calls $imp1 that contains the code originally in
    The generalized variant T4-CallExpression(b) is a transfor-            the if-block. Similarly, if p is zero, then the else instruction
mation rule (LT 4b , pT 4b , tT 4b ) where:                                calls $imp2 containing the code originally in the else-block.
    LT 4b . LT 4b is the same as LT 4a .                                   By leveraging the if-else instructions in WebAssembly, the
    tT 4b . tT 4b is defined in row T4-CallExpression(b) in Table I.       original semantics are preserved while the use of the control-
The experimental WebAssembly Reference Types proposal [9]                  flow statement is hidden from the JavaScript syntax.
adds a new WebAssembly value type, externref, that can be                     pT 5 . The if statements can be transformed if the code
used to pass references of arbitrary JavaScript values to and              blocks do not include the keywords break, continue,
from WebAssembly. With this new type, the transformation                   return, yield, or throw. These keywords are not compati-
only needs to import a reference to the transformed function.              ble with moving the inner code blocks into functions.
Specifically, the transformed JavaScript code only imports                    6) Obfuscating For Loops: To obfuscate for loops, we
the function reference f into WebAssembly (line 2). In the                 define transformation rule T6-ForStatement (LT 6 , pT 6 , tT 6 ):
original call expression, the function f is replaced with a                   LT 6 . The transformation locations where this rule applies
WebAssembly export function f0 that takes in the argument                  are ForStatement nodes, which represent C-style for loops.
a of the original call and returns any value that the original                tT 6 . The transformation is defined in row T6-ForStatement
function outputs (line 4). In the WebAssembly code, the export             in Table I. At the translation site, tT 6 wraps the loop condition,
function $f0 takes in a parameter of type externref and                    increment and body in three JavaScript functions that will be
returns a value of type externref (line 1). Inside $f0, it                 imported to the WebAssembly module (lines 3-8). The loop
calls the imported function $impFunc with a value that is                  counter initialization can be hoisted out of the loop scope
the argument passed into $f0 (lines 2-3). The benefits of                  safely (line 2). Finally, a WebAssembly export function f is
this transformation over T 4a include supporting more function             called which emulates the JavaScript for loop (line 11). In
calls by including those with return values and moving more                the WebAssembly module, the three JavaScript functions that
behavior into WebAssembly than T 4a .                                      are used to wrap the loop condition, increment, and body are
    pT 4b . This variant of the call transformation can be applied         imported as $cond, $body, and $incre, respectively (lines
only if: (i) the callee function does not contain a reference              4, 7, 8). The export function $f contains a block of code
to this; (ii) the arguments of the call expression cannot                  with label $L0, which encloses a loop block with label $L1
contain a reference to this; (iii) the data dependencies of the            (lines 2-3). Inside the loop, $cond is called (line 4) which
variables referenced within the callee cannot contain this;                evaluates the test condition of the JavaScript for loop and the
(iv) the callee function is not a method of a literal value; and           result is checked using i32.eqz (line 5). If the test condition
(v) the callee function is not the special functions bind or               is false, the instruction br_if $L0 branches out to the end
super. Conditions (i)-(iv) must be met because the value of                of block $L0, terminating the loop (line 6). Otherwise, if the
this is changed when calling the function from within the                  test condition is true, functions $body and $incre are called



                                                                       6
to execute the statements within the loop body and the update            because it contains many string literals in its data section, we
expression (lines 7-8). The br $L1 is used to branch to label            split it into multiple modules to keep each under 4KB. For
$L1, which continues iteration (line 9).                                 string literals larger than 4KB, the string literal is split across
   pT 6 . The precondition is the same as pT 5 .                         multiple modules and joined in the string reconstruction phase.
   7) Obfuscating While Loops: Analogous to the above,
we obfuscate while loops with a transformation rule T7-                  1   async function someFunction(){
                                                                         2       // Transformation site: ...
WhileStatement (LT 7 , pT 7 , tT 7 ) where:                              3       await (async () => {
   LT 7 . The rule applies to WhileStatement nodes.                      4       let mod = await WebAssembly.instantiateStreaming(
                                                                         5         fetch("generated_module.wasm"), impObj);
   tT 7 . The transformation, defined in row T7-WhileStatement           6       //Transformation function code...
in Table I, is similar to tT 6 . The only differences are that in        7       })()
                                                                         8   }
tT 7 , there is no loop increment nor loop counter initialization.
                                                                                     Fig. 3. Instantiation of the asynchronous variant.
A while loop can be created by only wrapping the loop
condition and the loop body into anonymous functions and                    We also support asynchronous instantiation of the Web-
importing them to WebAssembly (lines 4, 7). The function $f              Assembly modules, which is the method that browser
is defined and exported, which emulates the JavaScript while             providers recommend. Asynchronous instantiation has several
loop by calling the import functions within the loop block.              benefits, including unrestricted module size and the ability
   pT 7 . The precondition is the same as pT 5 and pT 6 .                to put the generated WebAssembly modules in separate files.
                                                                         These benefits allow each transformation to only emit a single
C. Synchronous and Asynchronous WebAssembly Instantiation                WebAssembly module.
  For each transformation rule in Section IV-B (aside from                  For these variants, the instanWasm() primitive is imple-
T4-CallExpression(b)), we develop two variants differing                 mented via the WebAssembly.instantiateStreaming()
in whether they instantiate the WebAssembly module syn-                  function, as shown in Figure 3 (line 4). This API spawns
chronously or asynchronously, i.e., the implementation of the            compilation on a separate thread, thus not blocking the main
instanWasm() primitive.                                                  thread of execution. Since this API returns a Promise, we need
                                                                         to add the await keyword to allow the Promise to resolve
1   let m = new WebAssembly.Module(                                      before continuing. Line 6 represents a placeholder for the
2     new Uint8Array(decodeBase64('...')));                              transformation code of T1-T7. The await keyword can only
3   return new WebAssembly.Instance(m, impObj);
                                                                         be employed in asynchronous functions, so we wrap the in-
            Fig. 2. Synchronous WebAssembly instantiation.               stantiation in an async anonymous function (line 3). Similarly,
   The synchronous variants implement the primitive by using             since the anonymous function is an async function, its invo-
the WebAssembly.Module and WebAssembly.Instance                          cation must also have the await keyword added (line 3). The
constructor functions. Figure 2 shows the code, where in line            enclosing function, someFunction, now contains the await
1, variable m is set to the compiled WebAssembly.Module ob-              keyword, so the function definition must have the async
ject. The WebAssembly.Module constructor accepts a typed                 keyword added (line 1). Elsewhere in the code, any function
array containing the module bytes. Hence, we encode the                  calls to someFunction would also require adding the await
module bytes into a base64 string, which is decoded to a                 keyword. As this example shows, inserting the async/await
typed Uint8Array at runtime (line 2). On line 3, the module              keywords to a translation site causes these keywords to be
object m, along with the import object, is then passed into the          propagated to functions and call sites throughout the file.
WebAssembly.Instance constructor. The returned instance                     This keyword propagation makes the asynchronous transfor-
object can be utilized by the transformation functions.                  mations non-trivial to design and implement. Specifically, we
   Since this is standard, synchronous code, there are                   encountered three code locations that are difficult to propagate
no restrictions on how to integrate instantiation into                   the async/await keywords to. First, anonymous functions
the original JavaScript application. However, because the                used as parameters in other function calls, e.g., .map, are
WebAssembly.Module constructor can block the JavaScript                  difficult to handle. Depending on the return type of the
main thread, browser vendors discourage this method.                     anonymous function, the await keyword may need to be
Chromium in particular even limits the input module to at                added within the called function’s definition or to the function
most 4KB in size [6] and throws an exception otherwise.                  invocation. Second, class constructors cannot be made async,
   To get around this limitation, each synchronous trans-                so a check must be done to detect if a constructor is in the
formation can emit one or more WebAssembly mod-                          call chain of any function. Third, if a transformed function is
ules. Specifically, transformations T3-FunctionName, T4-                 exported from a module, any other files using the function as
CallExpression(a), T5-IfStatement, T6-ForStatement, and T7-              an import must be checked for functions and function calls to
WhileStatement only emit one WebAssembly module per file                 add async and await to.
transformed. T1-StringLiteral, T2-ArrayInitialization, and T4-              All of the transformation rules have both synchronous
CallExpression(b) can emit one or more modules since the                 and asynchronous variants except for T4-CallExpression(b).
data stored within the modules can grow larger than 4KB.                 T4-CallExpression(b) relies on an experimental WebAssem-
When a single WebAssembly module grows too large, e.g.,                  bly proposal that imposes complex preconditions. Adding



                                                                     7
the asynchronous restrictions to this may break the orig-                                     V. I MPLEMENTATION
inal semantics and lead to incorrect transformations. T4-                    We implement Wobfuscator with Node.js (v14.17.2) and
CallExpression(b) exposes more translation sites than T4-                 TypeScript. The tool relies on the Esprima (v4.0.1) [3] and
CallExpression(a), increasing the number of edge cases that               Espree (v7.3.1) [2] packages to parse the JavaScript files and
can be encountered. We leave this combination as future work.             on Escodegen (2.0.0) [1] to convert the transformed AST back
D. Applying Transformations                                               into a JavaScript file. The Wabt.js (1.0.23) [8] package is used
                                                                          to generate the WebAssembly modules used in the obfuscation.
   We now present the overall algorithm for applying these
                                                                             The data from our evaluation is available at
transformations to a given JavaScript AST. The input to the
                                                                          https://github.com/js2wasm-obfuscator/translator. We make
algorithm is a list of transformation rules and the AST of
                                                                          the implementation of Wobfuscator available upon request. We
the original JavaScript file. The algorithm consists of three
                                                                          believe this strategy minimizes the threat of nefarious usage
steps: (a) Identifying AST nodes where transformations should
                                                                          while also aiding researchers in independently reproducing
be applied, i.e., translation sites; (b) rewriting the AST by
                                                                          our results, in confirming the identified weaknesses of existing
modifying the subtrees rooted at the translation sites; and (c)
                                                                          malware detectors, and in serving as a foundation for future
adding code to the AST root to instantiate the generated Web-
                                                                          research on improving malware detectors.
Assembly modules. The algorithm outputs the transformed
AST corresponding to the obfuscated JavaScript code.                                            VI. E VALUATION
      a) Identifying AST Nodes as Translation Sites: To iden-
                                                                             We evaluate Wobfuscator and its ability to obfuscate mali-
tify translation sites, we perform a pre-order traversal of the
                                                                          cious JavaScript using opportunistic translation to WebAssem-
AST starting at the root node. For each visited node n,
                                                                          bly along the following main research questions:
the algorithm iterates through the list of transformation rules
and checks which rules are applicable. A transformation rule              • RQ1 – Effectiveness: How effective is the approach at

(L, t, p) is applicable if the node n is in the set L of code                evading state-of-the-art JavaScript malware detectors and
locations and if the precondition p holds for n. A set of                    which transformations are most effective? How does our
translation site nodes is produced for each transformation rule.             approach compare with other state-of-the-art obfuscators?
      b) Rewriting AST Subtrees: After identifying all transla-           • RQ2 – Correctness: Do our code transformations preserve

tion site nodes, the next step is to rewrite the subtrees rooted at          the semantics of the transformed code?
these nodes. The algorithm applies transformations based on               • RQ3 – Efficiency: How much runtime and code size

the size of the syntactic structures they target. Specifically,              overhead do the transformations impose, and how long does
we iterate through the transformation rules in this order,                   applying the transformations take?
applying each rule to all applicable subtrees before moving                  To investigate these questions, we perform a comprehensive
on to the next rule: T1-StringLiteral, T2-ArrayInitialization,            analysis on the effectiveness of our transformations in evading
T3-FunctionName, T4-CallExpression, T5-IfStatement, T6-                   detection. We evaluate state-of-the-art detection tools against
ForStatement, T7-WhileStatement. This ordering ensures that               Wobfuscator on a large dataset of malicious and benign
transformations targeting finer-grained syntactic structures,             files. We evaluate the obfuscation advantage produced by
such as string and array literals, are performed prior to trans-          Wobfuscator by comparing our approach against state-of-the-
formations targeting coarser-grained structures, such as loops.           art open-source obfuscation tools. Lastly, we use the extensive
If more coarse-grained transformation were applied first, the             test suites of widely used and mature npm modules to verify
change could prevent more fine-grained transformations from               the correctness of our tool and demonstrate the runtime and
being applied. For each rule (L, t, p), the algorithm visits all          code size overhead are acceptable for real-world usage.
translation site nodes and applies the transformation function
t, which modifies the AST in-place and yields a WebAssembly               A. Experimental Setup
module used in the rewritten code. The output of this step is                1) Datasets: Due to different requirements, we use dif-
the rewritten AST and a set W of WebAssembly modules.                     ferent datasets of JavaScript programs for different research
      c) Adding WebAssembly Instantiation Code: The final                 questions. To answer RQ1, we need to train and apply state-of-
step is adding code to instantiate the WebAssembly modules                the-art JavaScript malware detectors to large sets of real-world
W . To this end, the algorithm inserts statements at the begin-           benign and malicious JavaScript code. Table II summarizes
ning of the script, i.e., at the root of the AST. For modules             the datasets we use. The benign code consists of 149,677 files
that are instantiated synchronously, we encode each module                from the JS150k dataset [49]. The malicious code consists
in W as a base64 string and add statements that decode                    of 43,499 samples, with 2,674 samples from VirusTotal [7],
and instantiate the modules. For asynchronously instantiated              39,450 samples from the Hynek Petrak JavaScript malware
modules, we serialize the modules to separate files and issue             collection [47], and 1,375 samples from the GeeksOnSecurity
corresponding fetch requests in the code. For asynchronous                malicious JavaScript dataset [11]. These datasets are broken
translations, the algorithm additionally adds the async wrapper           down further by the malware categories that they contain, such
(described in Section IV-A) around the root of the AST to                 as trojans, ransomware, droppers. We list the breakdown of the
support asynchronous keywords in the remainder of the code.               malicious datasets in the first four columns of Table IX.



                                                                      8
                          TABLE II                                      converting function identifiers and string literals into expres-
         DATASETS FOR EVALUATING EFFECTIVENESS (RQ1).                   sions that evaluate to constants. This obfuscator also supports
           Datasets                  # Samples (Files)                  character escaping, whitespace removal, and more.
           Benign      JS150k                 149,677                      All the experiments on a desktop containing an Intel Core i7
           Malicious   VirusTotal               2,674                   CPU@3.20GHz w/ 32 GB of memory running Ubuntu 20.04.
                       Hynek Petrak            39,450
                       GeeksOnSecurity          1,375
                       Total Malicious         43,499                   B. Effectiveness in Evading Detection (RQ1)
                                                                           1) Effectiveness of Our Approach: To evaluate the effec-
   Answering RQ2 and RQ3 requires executing code before                 tiveness of Wobfuscator at evading static malicious JavaScript
and after applying our transformations. We use a dataset of             detectors, we compare the detectors’ performance on the
popular and large JavaScript projects on NPM with their test            original input programs against their performance after our
suites. To identify suitable projects, we select from the most          obfuscation has been applied. Since the detectors classify
depended-upon NPM modules [12] six modules that contain                 each program as benign or malicious, the usual metrics of
extensive test suites (first column of Table V).                        binary classifiers apply: precision and recall. Precision is
   2) JavaScript Malware Detectors: We evaluate our obfus-              the number of true positives (correctly identified malicious
cation technique against four state-of-the-art, static, learning-       programs) divided by the number of all raised alarms (correct
based JavaScript malware detectors. To train them, we split             or not), and recall is the number of true positives divided
the benign and malicious datasets into training, validation,            by the number of all malicious programs in the dataset.
and test sets containing 70%, 15%, and 15% of the samples,              That is P rec= T PT+F
                                                                                           P
                                                                                              P , Rec= T P +F N . A good malware detector
                                                                                                          TP


respectively. We follow the steps provided by each project to           should offer both high precision and high recall. Low precision
train the detection models with the desired configuration.              indicates a high number of false positives, which would cause
   Cujo [50] is a hybrid JavaScript malware detector that de-           the system to block and break benign scripts and commonly
tects drive-by download attacks. It performs a lexical analysis         used websites. Such a tool would not be adopted by actual
of JavaScript files run on a website as well as a dynamic               users. Low recall means few of the actual malicious programs
analysis by monitoring abstracted runtime behaviors. For our            are detected, limiting the usefulness of the detector. The main
evaluation, we use the static detection part, based on a reim-          goal of our obfuscation is to reduce the recall of detectors.
plementation of Cujo provided by Fass et al. [18].                         Some detectors fail to parse some of the original and trans-
   Zozzle [24] is a mostly-static in-browser detection tool that        formed code samples due to outdated or incomplete support
uses syntactic information, such as identifier names and code           of the JavaScript language. Since this is an implementation-
locations, obtained from a JavaScript AST to identify mali-             specific detail of these detectors rather than a result of their
cious code. These features are input to a Bayesian classifier           detection methodology, we choose to exclude these samples
to label the samples as benign or malicious. We rely on a               from the count rather than mark them as false negatives. As a
reimplementation of Zozzle provided by Fass et al. [19].                result, the denominators of the recall results differ depending
   JaSt [28] is a static detector of malicious JavaScript that          on the detector and the applied transformations.
uses syntactic information from the AST to produce n-grams                 Results: Table III shows the recall of the detectors described
of sequential nodes to identify patterns indicative of malicious        in Section VI-A2 (columns) when run on code obfuscated by
behavior. We use the implementation made available on the               our transformations (rows). The first row gives each detector’s
project’s GitHub page [16].                                             recall without our obfuscation, which serves as a baseline.
   JStap [27] is a static malware detector that leverages syntax,       The middle part of the table shows results from applying
control-flow, and data-flow information by creating an AST, a           only one kind of transformation at a time. For example, the
Control Flow Graph (CFG), and a Program Dependency Graph                second row shows that applying our synchronous transforma-
(PDG), depending on the configuration. The tool extracts fea-           tion technique T1-StringLiteral on the test set of malicious
tures either by constructing n-grams of nodes or by combining           samples, Cujo achieves a recall of 0.61, i.e., a significant
the AST node type with its corresponding identifier/literal             reduction compared to the baseline of 0.98. The results show
value. In our evaluation, we focus on the PDG code abstraction          that different translation techniques are more effective against
with both the n-grams and values feature extraction modes. We           some detectors rather than others. For each detector, the
use the implementation available on GitHub [17].                        lowest recall score is bold-faced to reveal the best-performing
   3) JavaScript Obfuscation Tools: We compare Wobfusca-                individual transformation technique. For example, we find that
tor against four open-source state-of-the-art JavaScript ob-            T1-StringLiteral performs best for Cujo, Zozzle, and JStap
fuscation tools. JavaScript Obfuscator [4] is a JavaScript              in values mode, T4-CallExpression(a) performs best for JaSt,
obfuscation tool that supports multiple obfuscation techniques          and T4-CallExpression(b) performs best for JStap in n-grams
including variable renaming, dead code injection, and control-          mode. Since each transformation rule is effective at reducing
flow flattening. Gnirts [15] focuses on mangling string literals        the recall for at least one detector, all transformation rules are
within JavaScript files. Jfogs [70] is an obfuscation tool that         integral to the effectiveness of our approach.
focuses on removing function call identifiers and parameters               We explain the reasons why some detection tools disfavor
from call sites. JSObfu [5] is an obfuscator that supports              certain transformation rules over others. Cujo performs a



                                                                    9
                                                              TABLE III
                       R ECALL OF MALWARE DETECTORS ON CODE OBFUSCATED BY W OBFUSCATOR . L OWEST RECALL IN BOLD .
        Technique                               Cujo                       Zozzle                JaSt                 JStap (NGrams)       JStap (Values)
        Baseline: No transformation             0.98 (5,548/5,649)         0.66 (3,598/5,453)    0.99 (5,076/5,108)   0.99 (4,483/4,524)   0.98 (4,439/4,524)
                                                                             Individual transformations:
        Sync, T1-StringLiteral                  0.61 (1,623/2,644)         0.62 (3,387/5,453)    0.66 (3,393/5,108)   0.36 (1,539/4,257)   0.43 (1,839/4,257)
        Sync, T2-ArrayInitialization            0.94 (4,050/4,292)         0.66 (3,593/5,450)    0.85 (4,360/5,105)   0.86 (3,890/4,505)   0.89 (4,009/4,505)
        Sync, T3-FunctionName                   0.67 (2,780/4,159)         0.65 (3,550/5,453)    0.69 (3,512/5,108)   0.57 (2,747/4,810)   0.72 (3,463/4,810)
        Sync, T4-CallExpression(a)              0.71 (3,040/4,285)         0.64 (3,507/5,453)    0.38 (1,943/5,108)   0.37 (1,723/4,633)   0.78 (3,613/4,633)
        Sync, T4-CallExpression(b)              0.58 (2,385/4,115)         0.63 (3,424/5,453)    0.44 (2,253/5,108)   0.23 (1,058/4,586)   0.73 (3,369/4,586)
        Sync, T5-IfStatement                    0.82 (3,513/4,301)         0.64 (3,505/5,453)    0.89 (4,535/5,108)   0.83 (3,717/4,501)   0.93 (4,178/4,501)
        Sync, T6-ForStatement                   0.90 (3,877/4,299)         0.66 (3,578/5,453)    0.92 (4,720/5,108)   0.87 (3,872/4,465)   0.98 (4,360/4,465)
        Sync, T7-WhileStatement                 0.90 (3,904/4,321)         0.66 (3,598/5,453)    0.96 (4,882/5,108)   0.98 (4,410/4,502)   0.98 (4,412/4,502)
                                                                            Combined transformations:
        All sync (using T4(a))                  0.18 (416/2,255)           0.63 (3,450/5,450)    0.22 (1,104/5,105)   0.00 (1/4,235)       0.18 (766/4,235)
        All sync (using T4(b))                  0.19 (415/2,205)           0.63 (3,428/5,450)    0.18 (931/5,105)     0.00 (0/4,243)       0.08 (350/4,243)
        All async                               0.28 (1,490/5,297)         0.65 (3,524/5,453)    0.20 (1,085/5,453)   0.00 (4/4,612)       0.22 (959/4,267)


      1.00   0.98                        0.99           0.99        0.98                     T4(b)) in their asynchronous variant. We find that combining
      0.80                0.66
      0.60
                              0.63                                                           all transformation rules greatly reduces the recall of the
      0.40
                0.18                         0.22                      0.18
                                                                                             detectors. In particular, with the “All sync (using T4(a))” set
      0.20                                                   0.00
      0.00
                                                                                             of transformations, Cujo, Zozzle, JaSt, JStap (NGrams), and
              Cujo         Zozzle          JaSt          JStap       JStap                   JStap (Values) have a recall of 0.18, 0.63, 0.22, 0.00, and 0.18,
                                                       (NGrams)     (Values)                 respectively. Because of its performance and compatibility
                       Baseline     All sync (using T4(a))                                   with the WebAssembly MVP language, we select “All sync
              Fig. 4. Baseline recall vs. obfuscated recall.                                 (using T4(a))” to be the default configuration for Wobfuscator.
                                                                                             Figure 4 visualizes the results for “All sync (using T4(a))”.
lexical analysis on malware files, so it learns the suspicious
features of strings that are indicative of malware. Since T1-                                   The main goal of our work is to reduce the recall of
StringLiteral removes these identifiers from the file, Cujo is                               detectors, but we also measure their precision. The precision
not able to find suspicious tokens in the file. Zozzle identifies                            values for the transformations are listed in Table VII. For
malicious combinations of syntax features and the context                                    most applied transformations, the precision remains between
they are used in. Since T1-StringLiteral removes the usage                                   0.9 and 1.0. However, certain transformations can greatly
of malicious strings, such as shell code and dynamic code,                                   impact the precision on some detectors, e.g., “All sync (using
malicious files that have the majority of their code leveraging                              T4(a))” reduces JStap (NGrams) precision to 0.5. This shows
these strings will have indicative features removed from their                               that while reducing the precision is not its main objective,
AST, allowing them to evade Zozzle. JaSt uses n-grams                                        Wobfuscator can reduce the precision of certain detectors.
of AST syntax nodes (with a length of four by default)                                          2) Comparison with Other Obfuscators: To demon-
to detect malicious patterns. T4-CallExpression(a) replaces a                                strate how Wobfuscator compares against currently available
single CallExpression node with multiple nodes handling the                                  JavaScript obfuscators, we evaluate four obfuscation tools
WebAssembly module instantiation. Since this translation adds                                on the same dataset used in Section VI-B1. We collect the
more nodes than the length of sliding window, it can throw off                               precision and recall values obtained by the five malware
the detection of known malicious n-gram patterns. JStap in its                               detection tools when evaluated on a dataset obfuscated by each
n-grams mode generates a program dependency graph (PDG)                                      tool. Similar to Section VI-B1, some detectors fail to parse
by adding edges representing data flow to the AST of an input                                certain obfuscated files, leading to different denominators in
file. Since T4-CallExpression(b) (and other transformations)                                 the values within the same detector column.
route data flow through the generated WebAssembly module,                                       Results: Table IV shows the recall values of the detection
it hinders the n-gram features that JStap can extract when                                   tools (columns) when run on code obfuscated by each of the
performing its data flow analysis. JStap in its values mode                                  four obfuscation tools described in Section VI-A3 (rows). The
is most affected by the T1-StringLiteral transformation since,                               last row shows the best recall values obtained by Wobfuscator.
in this mode, it relies on literals when selecting features to                                  The results show that Wobfuscator outperforms current
extract. T1-StringLiteral removes some literals.                                             obfuscators when compared on the recall reduction of malware
   The lower part of Table III shows results from applying                                   detectors. The only exception occurs when Jfogs is evaluated
all transformation rules at once. We report results for three                                against JaSt. In this case, Jfogs’ recall rate of 0.00 outperforms
transformation combinations. “All sync (using T4(a))” and                                    Wobfuscator’s recall rate of 0.18. Jfogs’ obfuscation primarily
“All sync (using T4(b))” mean all synchronous transformations                                replaces identifiers and literals with new intermediate vari-
with T4(a) being used and with T4(b) being used, respectively.                               ables, so Wobfuscator could be used to compliment Jfogs.
“All async” means all transformations in Table I (aside from                                 For example, Jfogs moves string literals into variables, but



                                                                                        10
                                                             TABLE IV
                      R ECALL OF MALWARE DETECTORS ON CODE OBFUSCATED BY W OBFUSCATOR AND OTHER OBFUSCATORS .
         Obfuscator                  Cujo                 Zozzle                 JaSt                 JStap (NGrams)       JStap (Values)
         JavaScript Obfuscator       1.00 (4,406/4,415)   0.70 (3,807/5,453)     0.81 (4,153/5,108)   0.43 (2,005/4,717)   0.62 (2,947/4,717)
         Gnirts                      0.98 (5,548/5,649)   0.66 (3,598/5,453)     0.99 (5,076/5,108)   0.99 (4,483/4,524)   0.98 (4,439/4,524)
         Jfogs                       0.77 (3,515/4,562)   0.66 (3,584/5,453)     0.00 (26/5,453)      0.00 (16/5,025)      0.56 (2,826/5,025)
         JSObfu                      1.00 (4,994/5,008)   0.84 (4,467/5,324)     0.29 (1,456/4,979)   0.01 (20/3,667)      0.66 (2,420/3,667)
         Wobfuscator (best recall)   0.18 (416/2,255)     0.62 (3,387/5,453)     0.18 (931/5,105)     0.00 (4/4,612)       0.08 (350/4,243)


it does not alter or remove the strings from the file. Using                   the transformations to the tested code and then validate if the
the T1-StringLiteral transformation, the string literals can be                transformed code still passes its tests. Addressing the second
completely removed from the JavaScript file, reducing the                      question, a trivial solution to correctness would be to transform
syntactic information available to the detectors.                              only a very small set of code locations, preserving semantics
   3) Breakdown of Results by Malware Type: The malicious                      at the expense of obfuscating less code. Thus, we also evaluate
datasets contain several different categories of malware, in-                  how often each transformation rule is applied.
cluding cryptominers, trojans, and droppers. We provide a                         The validation setup differs between the synchronous and
breakdown on the malware categories contained within our                       asynchronous variants of the transformations. In the syn-
dataset. VirusTotal provides the malware type reported by the                  chronous case, we can simply apply the transformations to
AV scanners. We reduce the number of malware categories                        any existing code. To validate the correctness of the asyn-
presented by merging similar groups together, e.g., merging                    chronous transformations, the projects must be modified to
JS:Trojan.Gnaeus and JS:Trojan.Agent into a Trojan category.                   support asynchronous execution as described in Section IV-C.
For GeeksOnSecurity, we use the directory names to identify                    Since automatically turning arbitrary JavaScript code into
which samples are exploits kits and which are JavaScript                       asynchronous code is non-trivial, we instead focus on an NPM
droppers. The Hynek Petrak dataset does not provide metadata                   project, node-fetch, that is already asynchronous, so applying
on the samples, so we scan the files with ClamAV to obtain                     the asynchronous transformations is simplified. We use this
the malware categories. To demonstrate the effectiveness of                    project to validate the asynchronous variants and use the other
Wobfuscator in obfuscating a diverse set of malware samples,                   five projects to validate the synchronous variants.
we measure the reduction in the recall of malware detectors for                   Results: The results for the test suite runs are shown in
different malware categories in the dataset. For space reasons,                Table V. This table lists the tested project, its version, and the
we list only the minimum recall rates observed within the                      number of translation sites where rules T1–T7 are applied to.
malware categories among all of the transformations.                           The last two columns list the total number of tests in the test
   Results: Columns 5-9 of Table IX present the recall values                  suite, and the number of tests that are impacted by at least
obtained by the malware detectors (columns) when samples                       one transformation. All tests in each project pass successfully,
from each malware category (rows) are obfuscated. In addition                  showing that our obfuscations are semantics-preserving.
to the recall rate, each cell lists the number of files correctly                 Columns 4-11 of Table V show the number of transformed
marked as malicious by the detector over the number of ma-                     code locations that meet the preconditions of the transforma-
licious files the detector tested within that category. Columns                tion out of the total number of available code locations relevant
marked with ‘-’ signify that the detectors are unable to parse                 to the transformation, regardless of whether they satisfy the
any of the test files within the malware category. For the                     preconditions. The last two columns of Table V show that
Phishing malware category, no samples appear in our test                       of the 2,017 unit tests in the five test suites, 1,844 of them
dataset, so no recall values are available. The results on the five            (91.42%) rely on a function that is impacted by at least one
largest malware groups (Downloader, Misc., Trojan, Malware,                    transformation rule. The results show that our transformation
and Exploit) show that Wobfuscator can significantly reduce                    rules are applicable to code locations used in the real-world.
recall rates across diverse malware categories.
                                                                               D. Efficiency in Terms of Runtime and Code Size (RQ3)
C. Correctness of the Transformations (RQ2)                                       The Wobfuscator transformations we propose re-implement
   The transformations we apply change the syntactic structure                 native JavaScript functionalities in WebAssembly modules,
of the program. Naturally, such changes could affect program                   such as calling a function, performing a while loop, initializing
semantics, potentially making the obfuscated program behave                    an array, etc. As a result, there will be an impact on the perfor-
differently from the original program and thus breaking func-                  mance of the translated programs. To quantify the performance
tional correctness. This gives rise to two questions, which are                impact of our transformations, we use the test suites of the
in tension with each other: First, do we preserve functional                   six modules described in Section VI-C. In addition, the code
correctness of the input program, i.e., are our code trans-                    size increase caused by the transformations is also analyzed,
formations semantics-preserving? Second, how often are the                     counting both added JavaScript and WebAssembly code.
transformations applied? To validate that the correctness of                      1) Translation Runtime: First, we measure the time taken
the program is preserved, we leverage the comprehensive test                   for performing the transformations on the project files. The
suites of existing widely used JavaScript projects. We apply                   times are measured with the time command available in



                                                                         11
                                                                               TABLE V
                                                                    C ORRECTNESS VALIDATION RESULTS .
  Project       Version            LoC           T1           T2       T3          T4(a)         T4(b)        T5      T6       T7    Total # of Tests   # of Tests Impacted
                                                       Validation of synchronous transformations:
  Lodash        5.0.0          21,178        193/801     160/208       0/0        87/467        299/467    47/187     0/0    38/61               408                   322
  Chalk         4.1.0             319          64/68        0/23       2/2        21/108         26/108      4/25     1/1      2/2                54                    54
  Commander     7.2.0           1,153        155/163        0/28       0/0       130/394         87/394    91/153     4/4      2/3               632                   592
  Debug         4.3.2             505        141/149         2/8       0/0         20/95          43/95     16/29     2/5      0/0                14                    13
  Async         3.2.0             787          30/57        0/21       0/0        89/209        108/209     31/86     5/6      5/8               675                   659
                                                       Validation of asynchronous transformations:
  Node-Fetch    3.0.0beta.10       970       174/212         1/17      0/0        49/264              -     26/94     0/0      0/0               234                   204
  Total         -               4,152    757/1,450       163/305       2/2     396/1,537    654/1,537     189/480   12/16    47/74             2,017                  1,844


                                TABLE VI                                                        size. On average, applying all of the transformations among
                    E FFICIENCY OF TRANSFORMATIONS .                                            the project, the code size increased by 170.42%. Overall, the
   Project      Translation time     Execution time          Code size (bytes)                  code size overhead is acceptable for practical applications.
                    LoC    Time Original       Overhead Original         Overhead
                           Synchronous Validation
                                                                                                                            VII. D ISCUSSION
   Lodash    21,178       29.58s     3.51s   +25.81% 135,402 +139.84%                              This section discusses the limitations and possible mitiga-
   Chalk        319        0.81s     4.03s    +7.01% 14,935 +166.70%
   Commander 1,153         0.51s     3.97s   +49.95% 74,269 +146.96%
                                                                                                tions to defend against WebAssembly-based obfuscation.
   Debug        505        1.14s     0.61s    +3.24% 21,395 +154.70%
   Async        787        5.42s    16.83s +2079.21% 28,925 +363.52%                            A. Limitations
                           Asynchronous Validation                                                 Wobfuscator targets malware detectors based on static
   Node-Fetch       970   16.03s     4.11s      +14.76%       51,960         127.16%            analysis, and despite its effectiveness in bypassing them, is
   Average       4,152     8.92s     5.68s      +31.07%       54,481 +170.42%                   unlikely to be equally effective for dynamic analysis-based
                                                                                                detectors. The transformations move some behavior into Web-
                                                                                                Assembly while leaving the ultimate runtime behavior intact.
Linux, averaged over ten repetitions. We compute the total                                      That is, a dynamic detector that, e.g., observes browser API
transformation time of a project by summing the times to con-                                   calls made by a website will observe the same behavior
vert each JavaScript file used in the project. The transformation                               with and without our obfuscation. However, in practice static
time results are presented in Table VI. The table shows that                                    detectors are much easier to deploy (e.g., as network proxies
for the largest project, Lodash with 21,178 lines of code, the                                  or browser extensions), whereas observing dynamic behavior
average time to apply all of the synchronous transformations is                                 is more complex to set up and expensive at runtime.
29.58 seconds. For the smallest project, Chalk with 319 lines                                      Another limitation is that the approach applies transforma-
of code, the average time to apply the transformations is only                                  tions only to some of the given code. If a code location does
0.81 seconds. In addition, we find that among all the projects in                               not fulfill the preconditions for a specific transformation, then
Table VI, the average time to apply all of the transformations                                  it cannot be transformed. Conservatively guarding transfor-
is only 8.92 seconds. These low transformation times show                                       mations is crucial to ensure that our approach preserves the
that Wobfuscator is practical for JavaScript obfuscation.                                       semantics of the given code, but also limits its applicability.
   2) Execution Time Overhead: The execution overhead time                                         Finally, our obfuscation relies on WebAssembly being avail-
is the increase in runtime to complete the execution of the test                                able in the browser. With WebAssembly support in 94% of all
suites of the transformed projects. We use the time command                                     installed browsers, this limitation is likely to be acceptable
to measure the runtime of the project test suite before and                                     in practice. To ensure that the obfuscated malware runs as
after the transformations are applied, reporting averages over                                  expected, an attacker could check for WebAssembly support
ten repeated measurements. The execution time results are                                       and load the obfuscated code only if the language is supported.
presented in Table VI. Our transformations add a performance
overhead that ranges from an increase of 3.24% to an increase                                   B. Mitigations
of 2,079%. While the highest overhead number is large, it                                         We discuss three mitigation strategies aimed at detecting
is important to note that this large runtime originates from                                    malware despite our obfuscation. The first is dynamic analysis-
one test within the async project that concurrently applies an                                  based malware detection. Because our approach preserves
asynchronous function to a collection of 1,048,576 elements.                                    the original JavaScript behavior, many runtime characteristics
In most cases, it is unlikely that malware samples will follow                                  that dynamic detectors focus on [53] are not affected by the
such an execution pattern that incurs this large overhead. On                                   obfuscation. WebAssembly code invokes web APIs through
average, Wobfuscator adds a performance overhead of 31.07%.                                     JavaScript, which means the call will be visible to any runtime
   3) Code Size Overhead: The code size overhead is the                                         analysis that wraps the API functions or intercepts them within
increase in code size between the original file and transformed                                 the browser. However, dynamic malware detectors often im-
output among all code files within a project. Table VI lists the                                pose a non-negligible runtime overhead and may miss malware
percentage of growth in code size compared with the original                                    that hides its malicious behavior in specific configurations.



                                                                                           12
   The second mitigation strategy is based on the defender                  Other malware detection techniques dynamically analyze
knowing the details of our obfuscation. Since the WebAssem-              programs to identify malicious behaviors. Some techniques
bly usage in the obfuscated code, e.g., loading many small               focus on collecting runtime statistics to construct models that
modules, may be abnormal, it is possible to define heuristic             identify malware [23], [53], [68]. Other techniques leverage
rules to detect that Wobfuscator was applied. In a similar               symbolic execution [39] or forced execution [38] to trigger
vein, one could include code obfuscated with our technique               malware hidden behind complex input sequences. Wobfuscator
in the training data used to learn a malware classifier. The             is unlikely to reduce the detection rate against these detectors
main drawback of these mitigations is that obfuscation does              as we do not significantly change the runtime behavior.
not imply maliciousness. There are legitimate reasons for                      Obfuscation Detection: Some existing work only focuses
obfuscating code, e.g., protecting intellectual property. Hence,         on detecting obfuscation rather than obfuscated malware.
classifying all code obfuscated by our technique, or any other           NOFUS [35] and JSOD [13] use syntactic and contextual
obfuscation technique, as malicious is likely to cause an                information as features for a machine learning classifier to
unacceptably high number of false positives.                             detect obfuscation. Sarker et al. [53] develop a hybrid approach
   Finally, the third mitigation strategy is to jointly analyze          by instrumenting browser APIs and determining whether the
JavaScript and WebAssembly. For detectors based on tradi-                traced API call corresponds to a static code location.
tional program analysis, both static or dynamic, a joint analysis              WebAssembly and WebAssembly Security: Haas et al. [31]
would reason about how data and control flows between the                explain the motivation and benefits of introducing a new byte
two languages. Likewise, learning-based detectors, such as               code language to the Web. Several works investigate security
those used in our evaluation, could feed code in both languages          aspects of WebAssembly, e.g., unsolicited cryptomining in the
into their models. We are not aware of any existing malware              browser [40], [45], [52] and how to detect and defend against
detector with support for WebAssembly but hope that our work             it [37], [51], [62]. Lehmann et al. show that source-level
will raise awareness that a joint analysis would be useful.              memory vulnerabilities may propagate to WebAssembly bina-
                                                                         ries [41], a problem that affects many real-world binaries [33].
                   VIII. R ELATED W ORK                                  However, neither of those works use WebAssembly to hide
                                                                         arbitrary JavaScript behavior from inspection. Future joint
     Obfuscation Studies and Techniques: Obfuscation tech-               malicious code detectors for JavaScript and WebAssembly
niques have been observed in various programming languages               could build upon the Wasabi framework [42] or taint tracking
and software domains for both malicious and benign purposes.             frameworks for WebAssembly [29], [57].
Previous works categorize obfuscation techniques applied on
                                                                                                IX. C ONCLUSION
malicious code [69] while others compare the effectiveness of
different obfuscation techniques [22], [32], [61]. Some studies             Much work has focused on identifying JavaScript malware
have analyzed the usage of obfuscation techniques specifically           using static analysis. However, these techniques ignore recent
in JavaScript code by investigating the obfuscation techniques           web standards available to attackers, namely WebAssembly. To
used in real-world malicious and benign files [66], [55].                bypass static detectors, we present Wobfuscator, an obfusca-
                                                                         tion approach built on a set of seven transformation rules that
   There is little work proposing new obfuscation attacks
                                                                         opportunistically translate specific parts of JavaScript code into
for JavaScript code. Fass et al. [26] construct HideNoSeek
                                                                         functionally identical WebAssembly modules. We evaluate our
which rewrites the ASTs of malicious programs into the AST
                                                                         transformations against four state-of-the-art static JavaScript
of known benign programs to avoid detection. The authors
                                                                         malware detectors and show that our approach effectively
evaluate HideNoSeek on 91,020 samples against VirusTotal,
                                                                         reduces the recall on real malware samples. We show that
Yara, JaSt, Zozzle and Cujo. The obfuscation technique is able
                                                                         our technique outperforms other obfuscation tools only based
to achieve a 99.98% false negative rate against the detectors.
                                                                         on JavaScript. Finally, we use the test suites of six NPM
     Malware Detection: An active area in academic research
                                                                         packages to validate the correctness of our transformations
produces static analysis techniques designed to identify mali-
                                                                         and show their low performance overhead. Our results show
cious behavior even in the presence of obfuscated code.
                                                                         that current static detectors are ineffective against techniques
   One class of static detection tools use lexical and syntactic
                                                                         that implement cross-language code obfuscation, motivating
information derived from JavaScript files in order to identify
                                                                         future work on addressing this challenge.
features that indicate malicious code [50], [24], [16], [20],
[54]. Techniques build on this syntactic information by in-                                X. ACKNOWLEDGMENTS
corporating control-flow and data-flow analysis [27] or by                  We thank the anonymous reviewers and the shepherd for
adding dynamic analysis to confirm the presence of mal-                  their constructive comments. This work was partially sup-
ware [67], [59]. Other static detection techniques analyze the           ported by the US National Science Foundation under Grant
JavaScript source code through machine-learning and deep-                No. 2047980, the European Research Council (ERC, grant
learning approaches [63], [46]. Wobfuscator can impact the               agreement 851895), and the German Research Foundation
detection rates of these detectors since it reduces the syntactic        within the ConcSys and Perf4JS projects. Any opinions,
information available. In addition, some behavior is moved to            findings, and conclusions in this paper are those of the authors
WebAssembly modules, which are ignored by these detectors.               only and do not necessarily reflect the views of our sponsors.



                                                                    13
                               R EFERENCES                                                   October 24-28, 2016, E. R. Weippl, S. Katzenbeisser, C. Kruegel, A. C.
                                                                                             Myers, and S. Halevi, Eds. ACM, 2016, pp. 1388–1401. [Online].
 [1] “escodegen.” [Online]. Available: https://www.npmjs.com/package/                        Available: https://doi.org/10.1145/2976749.2978313
     escodegen                                                                          [26] A. Fass, M. Backes, and B. Stock, “HideNoSeek: Camouflaging
 [2] “espree.” [Online]. Available: https://www.npmjs.com/package/espree                     Malicious JavaScript in Benign ASTs,” in Proceedings of the 2019
 [3] “Esprima.” [Online]. Available: https://esprima.org/                                    ACM SIGSAC Conference on Computer and Communications Security,
 [4] GitHub - javascript-obfuscator/javascript-obfuscator: A powerful                        CCS 2019, London, UK, November 11-15, 2019, L. Cavallaro, J. Kinder,
     obfuscator for JavaScript and Node.js. [Online]. Available:                             X. Wang, and J. Katz, Eds. ACM, 2019, pp. 1899–1913. [Online].
     https://github.com/javascript-obfuscator/javascript-obfuscator                          Available: https://doi.org/10.1145/3319535.3345656
 [5] “JSObfu,” Rapid7. [Online]. Available: https://github.com/rapid7/jsobfu            [27] ——, “JStap: a static pre-filter for malicious JavaScript detection,”
 [6] “Loading WebAssembly modules efficiently.” [Online]. Available:                         in Proceedings of the 35th Annual Computer Security Applications
     https://developers.google.com/web/updates/2018/04/loading-wasm                          Conference, ACSAC 2019, San Juan, PR, USA, December 09-13, 2019,
 [7] “VirusTotal.” [Online]. Available: https://www.virustotal.com/gui/home/                 D. Balenson, Ed. ACM, 2019, pp. 257–269. [Online]. Available:
     upload                                                                                  https://doi.org/10.1145/3359789.3359813
 [8] “wabt.” [Online]. Available: https://www.npmjs.com/package/wabt                    [28] A. Fass, R. P. Krawczyk, M. Backes, and B. Stock, “JaSt: Fully
 [9] “WebAssembly                        Core                    Specification,”             Syntactic Detection of Malicious (Obfuscated) JavaScript,” in Detection
     https://webassembly.github.io/spec/core/ download/WebAssembly.pdf.                      of Intrusions and Malware, and Vulnerability Assessment - 15th
     [Online]. Available: https://www.w3.org/TR/wasm-core-1/                                 International Conference, DIMVA 2018, Saclay, France, June 28-
[10] “WebAssembly Website.” [Online]. Available: https://webassembly.org/                    29, 2018, Proceedings, ser. Lecture Notes in Computer Science,
[11] “Malicious Javascript Dataset,” Aug. 2021, original-date: 2017-01-                      C. Giuffrida, S. Bardin, and G. Blanc, Eds., vol. 10885. Springer,
     31T17:48:24Z. [Online]. Available: https://github.com/geeksonsecurity/                  2018, pp. 303–325. [Online]. Available: https://doi.org/10.1007/978-3-
     js-malicious-dataset                                                                    319-93411-2 14
[12] 262588213843476, “npm rank.” [Online]. Available: https://gist.github.             [29] W. Fu, R. Lin, and D. Inge, “Taintassembly: Taint-based information
     com/anvaka/8e8fa57c7ee1350e3491                                                         flow control tracking for webassembly,” CoRR, vol. abs/1802.01050,
[13] I. A. AL-Taharwa, H.-M. Lee, A. B. Jeng, K.-P. Wu, C.-S. Ho, and                        2018. [Online]. Available: http://arxiv.org/abs/1802.01050
     S.-M. Chen, “JSOD: JavaScript obfuscation detector: JSOD,” Security                [30] A. Gómez-Boix, P. Laperdrix, and B. Baudry, “Hiding in the crowd: an
     and Communication Networks, vol. 8, no. 6, pp. 1092–1107, Apr. 2015.                    analysis of the effectiveness of browser fingerprinting at large scale,”
     [Online]. Available: https://doi.org/10.1002/sec.1064                                   in Proceedings of the 2018 World Wide Web Conference on World
[14] M. Alsharnouby, F. Alaca, and S. Chiasson, “Why phishing still                          Wide Web, WWW 2018, Lyon, France, April 23-27, 2018, P. Champin,
     works: User strategies for combating phishing attacks,” Int. J.                         F. Gandon, M. Lalmas, and P. G. Ipeirotis, Eds. ACM, 2018, pp.
     Hum. Comput. Stud., vol. 82, pp. 69–82, 2015. [Online]. Available:                      309–318. [Online]. Available: https://doi.org/10.1145/3178876.3186097
     https://doi.org/10.1016/j.ijhcs.2015.05.005                                        [31] A. Haas, A. Rossberg, D. L. Schuff, B. L. Titzer, M. Holman,
[15] anseki, “Gnirts.” [Online]. Available: https://github.com/anseki/gnirts                 D. Gohman, L. Wagner, A. Zakai, and J. F. Bastien, “Bringing the
[16] Aurore54F, “JaSt - JS AST-Based Analysis,” Jun. 2021, original-                         web up to speed with WebAssembly,” in Proceedings of the 38th
     date: 2017-04-10T19:03:18Z. [Online]. Available: https://github.com/                    ACM SIGPLAN Conference on Programming Language Design and
     Aurore54F/JaSt                                                                          Implementation, PLDI 2017, Barcelona, Spain, June 18-23, 2017, 2017,
[17] ——, “JStap: A Static Pre-Filter for Malicious JavaScript Detection,”                    pp. 185–200.
     Jun. 2021, original-date: 2019-09-02T13:44:26Z. [Online]. Available:               [32] M. Hammad, J. Garcia, and S. Malek, “A large-scale empirical study
     https://github.com/Aurore54F/JStap                                                      on the effects of code obfuscations on Android apps and anti-malware
[18] ——, “lexical-jsdetector,” May 2021, original-date: 2019-09-                             products,” in Proceedings of the 40th International Conference on
     20T05:52:48Z. [Online]. Available: https://github.com/Aurore54F/                        Software Engineering. Gothenburg Sweden: ACM, May 2018, pp.
     lexical-jsdetector                                                                      421–431. [Online]. Available: https://dl.acm.org/doi/10.1145/3180155.
[19] ——, “syntactic-jsdetector,” Jun. 2021, original-date: 2019-09-                          3180228
     20T05:54:00Z. [Online]. Available: https://github.com/Aurore54F/                   [33] A. Hilbig, D. Lehmann, and M. Pradel, “An Empirical Study of
     syntactic-jsdetector                                                                    Real-World WebAssembly Binaries: Security, Languages, Use Cases,”
[20] D. Canali, M. Cova, G. Vigna, and C. Kruegel, “Prophiler: a fast filter                 in WWW ’21: The Web Conference 2021, Virtual Event / Ljubljana,
     for the large-scale detection of malicious web pages,” in Proceedings                   Slovenia, April 19-23, 2021, J. Leskovec, M. Grobelnik, M. Najork,
     of the 20th international conference on World wide web - WWW                            J. Tang, and L. Zia, Eds. ACM / IW3C2, 2021, pp. 2696–2708.
     ’11. Hyderabad, India: ACM Press, 2011, p. 197. [Online]. Available:                    [Online]. Available: https://doi.org/10.1145/3442381.3450138
     http://portal.acm.org/citation.cfm?doid=1963405.1963436                            [34] G. Hong, Z. Yang, S. Yang, L. Zhang, Y. Nan, Z. Zhang,
[21] N. Carlini, A. P. Felt, and D. Wagner, “An Evaluation of the                            M. Yang, Y. Zhang, Z. Qian, and H. Duan, “How you get shot
     Google Chrome Extension Security Architecture,” in Proceedings of                       in the back: A systematical study about cryptojacking in the real
     the 21st USENIX Conference on Security Symposium, ser. Security’12.                     world,” in Proceedings of the 2018 ACM SIGSAC Conference on
     Berkeley, CA, USA: USENIX Association, 2012, pp. 7–7. [Online].                         Computer and Communications Security, CCS 2018, Toronto, ON,
     Available: http://dl.acm.org/citation.cfm?id=2362793.2362800                            Canada, October 15-19, 2018, D. Lie, M. Mannan, M. Backes, and
[22] M. Ceccato, A. Capiluppi, P. Falcarin, and C. Boldyreff, “A Large                       X. Wang, Eds. ACM, 2018, pp. 1701–1713. [Online]. Available:
     Study on the Effect of Code Obfuscation on the Quality of Java Code,”                   https://doi.org/10.1145/3243734.3243840
     Empirical Software Engineering, vol. 20, no. 6, pp. 1486–1524, Dec.                [35] S. Kaplan, B. Livshits, B. Zorn, C. Siefert, and C. Cursinger, “”NOFUS:
     2015. [Online]. Available: http://link.springer.com/10.1007/s10664-014-                 Automatically Detecting” + String.fromCharCode(32) + ”ObFuSCateD
     9321-0                                                                                  ”.toLowerCase() + ”JavaScript Code”,” Tech. Rep. MSR-TR-2011-57,
[23] M. Cova, C. Krügel, and G. Vigna, “Detection and analysis of drive-                    May 2011. [Online]. Available: https://www.microsoft.com/en-
     by-download attacks and malicious javascript code,” in Proceedings of                   us/research/publication/nofus-automatically-detecting-string-
     the 19th International Conference on World Wide Web, WWW 2010,                          fromcharcode32-obfuscated-tolowercase-javascript-code/
     Raleigh, North Carolina, USA, April 26-30, 2010, M. Rappa, P. Jones,               [36] A. Kapravelos, Y. Shoshitaishvili, M. Cova, C. Kruegel, and
     J. Freire, and S. Chakrabarti, Eds. ACM, 2010, pp. 281–290. [Online].                   G. Vigna, “Revolver: An automated approach to the detection
     Available: https://doi.org/10.1145/1772690.1772720                                      of evasive web-based malware,” in Proceedings of the 22th
[24] C. Curtsinger, B. Livshits, B. G. Zorn, and C. Seifert, “ZOZZLE:                        USENIX Security Symposium, Washington, DC, USA, August
     fast and precise in-browser javascript malware detection,” in 20th                      14-16, 2013, S. T. King, Ed.              USENIX Association, 2013,
     USENIX Security Symposium, San Francisco, CA, USA, August 8-12,                         pp. 637–652. [Online]. Available: https://www.usenix.org/conference/
     2011, Proceedings. USENIX Association, 2011. [Online]. Available:                       usenixsecurity13/technical-sessions/presentation/kapravelos
     http://static.usenix.org/events/sec11/tech/full papers/Curtsinger.pdf              [37] A. Kharraz, Z. Ma, P. Murley, C. Lever, J. Mason, A. Miller, N. Borisov,
[25] S. Englehardt and A. Narayanan, “Online tracking: A 1-million-site                      M. Antonakakis, and M. Bailey, “Outguard: Detecting in-browser covert
     measurement and analysis,” in Proceedings of the 2016 ACM SIGSAC                        cryptocurrency mining in the wild,” in The World Wide Web Conference,
     Conference on Computer and Communications Security, Vienna, Austria,                    2019, pp. 840–852.




                                                                                   14
[38] K. Kim, I. L. Kim, C. H. Kim, Y. Kwon, Y. Zheng, X. Zhang, and                  [55] P. Skolka, C. Staicu, and M. Pradel, “Anything to Hide? Studying
     D. Xu, “J-Force: Forced Execution on JavaScript,” in Proceedings of                  Minified and Obfuscated Code in the Web,” in The World Wide Web
     the 26th International Conference on World Wide Web, ser. WWW ’17.                   Conference (WWW). ACM, 2019, pp. 1735–1746. [Online]. Available:
     Republic and Canton of Geneva, CHE: International World Wide Web                     https://doi.org/10.1145/3308558.3313752
     Conferences Steering Committee, Apr. 2017, pp. 897–906. [Online].               [56] B. Stock, B. Livshits, and B. G. Zorn, “Kizzle: A signature compiler
     Available: https://doi.org/10.1145/3038912.3052674                                   for detecting exploit kits,” in 46th Annual IEEE/IFIP International
[39] C. Kolbitsch, B. Livshits, B. Zorn, and C. Seifert, “Rozzle: De-cloaking             Conference on Dependable Systems and Networks, DSN 2016, Toulouse,
     Internet Malware,” in 2012 IEEE Symposium on Security and Privacy,                   France, June 28 - July 1, 2016. IEEE Computer Society, 2016, pp.
     May 2012, pp. 443–457, iSSN: 2375-1207.                                              455–466. [Online]. Available: https://doi.org/10.1109/DSN.2016.48
[40] R. K. Konoth, E. Vineti, V. Moonsamy, M. Lindorfer, C. Kruegel,                 [57] A. Szanto, T. Tamm, and A. Pagnoni, “Taint tracking for webassembly,”
     H. Bos, and G. Vigna, “Minesweeper: An in-depth look into drive-by                   CoRR, vol. abs/1807.08349, 2018. [Online]. Available: http://arxiv.org/
     cryptocurrency mining and its defense,” in CCS, 2018.                                abs/1807.08349
[41] D. Lehmann, J. Kinder, and M. Pradel, “Everything Old is                        [58] S. Van Acker, N. Nikiforakis, L. Desmet, F. Piessens, and
     New Again: Binary Security of WebAssembly,” in 29th USENIX                           W. Joosen, “Monkey-in-the-browser: malware and vulnerabilities in
     Security Symposium, USENIX Security 2020, August 12-14, 2020,                        augmented browsing script markets,” in 9th ACM Symposium on
     S. Capkun and F. Roesner, Eds. USENIX Association, 2020,                             Information, Computer and Communications Security, ASIA CCS ’14,
     pp. 217–234. [Online]. Available: https://www.usenix.org/conference/                 Kyoto, Japan - June 03 - 06, 2014, S. Moriai, T. Jaeger, and
     usenixsecurity20/presentation/lehmann                                                K. Sakurai, Eds. ACM, 2014, pp. 525–530. [Online]. Available:
[42] D. Lehmann and M. Pradel, “Wasabi: A framework for dynamically                       https://doi.org/10.1145/2590296.2590311
     analyzing WebAssembly,” in ASPLOS, 2019.                                        [59] J. Wang, Y. Xue, Y. Liu, and T. H. Tan, “JSDC: A Hybrid
[43] L. Lu, V. Yegneswaran, P. A. Porras, and W. Lee, “BLADE: an                          Approach for JavaScript Malware Detection and Classification,”
     attack-agnostic approach for preventing drive-by malware infections,”                in Proceedings of the 10th ACM Symposium on Information,
     in Proceedings of the 17th ACM Conference on Computer and                            Computer and Communications Security. Singapore Republic of
     Communications Security, CCS 2010, Chicago, Illinois, USA, October                   Singapore: ACM, Apr. 2015, pp. 109–120. [Online]. Available:
     4-8, 2010, E. Al-Shaer, A. D. Keromytis, and V. Shmatikov, Eds.                      https://dl.acm.org/doi/10.1145/2714576.2714620
     ACM, 2010, pp. 440–450. [Online]. Available: https://doi.org/10.1145/           [60] P. Wang, S. Wang, J. Ming, Y. Jiang, and D. Wu, “Translingual
     1866307.1866356                                                                      obfuscation,” in IEEE European Symposium on Security and Privacy,
[44] Microsoft, “Microsoft digital defense report,” 2020.                                 EuroS&P 2016, Saarbrücken, Germany, March 21-24, 2016. IEEE,
[45] M. Musch, C. Wressnegger, M. Johns, and K. Rieck, “New kid on the                    2016, pp. 128–144. [Online]. Available: https://doi.org/10.1109/EuroSP.
     web: A study on the prevalence of webassembly in the wild,” in DIMVA,                2016.21
     2019.                                                                           [61] P. Wang, D. Wu, Z. Chen, and T. Wei, “Field experience with obfuscating
[46] S. Ndichu, S. Kim, S. Ozawa, T. Misu, and K. Makishima,                              million-user ios apps in large enterprise mobile development,” Software:
     “A machine learning approach to detection of JavaScript-based                        Practice and Experience, vol. 49, no. 2, pp. 252–273, 2019.
     attacks using AST features and paragraph vectors,” Applied Soft                 [62] W. Wang, B. Ferrell, X. Xu, K. W. Hamlen, and S. Hao, “Seismic: Se-
     Computing, vol. 84, p. 105721, Nov. 2019. [Online]. Available:                       cure in-lined script monitors for interrupting cryptojacks,” in European
     https://linkinghub.elsevier.com/retrieve/pii/S1568494619305022                       Symposium on Research in Computer Security. Springer, 2018, pp.
[47] H. Petrak, “Javascript Malware Collection,” Aug. 2021, original-                     122–142.
     date: 2017-05-07T19:17:23Z. [Online]. Available: https://github.com/            [63] Y. Wang, W.-d. Cai, and P.-c. Wei, “A deep learning approach for
     HynekPetrak/javascript-malware-collection                                            detecting malicious JavaScript code: Using a deep learning approach
[48] N. Provos, D. McNamee, P. Mavrommatis, K. Wang, and N. Modadugu,                     to detect JavaScript-based attacks,” Security and Communication
     “The ghost in the browser: Analysis of web-based malware,”                           Networks, vol. 9, no. 11, pp. 1520–1534, Jul. 2016. [Online]. Available:
     in First Workshop on Hot Topics in Understanding Botnets,                            https://onlinelibrary.wiley.com/doi/10.1002/sec.1441
     HotBots’07, Cambridge, MA, USA, April 10, 2007, N. Provos, Ed.                  [64] WebAssembly Community Group, “WebAssembly Specification,” 2017.
     USENIX Association, 2007. [Online]. Available: https://www.usenix.                   [Online]. Available: https://webassembly.github.io/spec/core/
     org/conference/hotbots-07/ghost-browser-analysis-web-based-malware              [65] X. Xing, W. Meng, B. Lee, U. Weinsberg, A. Sheth, R. Perdisci,
[49] V. Raychev, P. Bielik, M. Vechev, and A. Krause, “Learning programs                  and W. Lee, “Understanding malvertising through ad-injecting
     from noisy data,” SIGPLAN Not., vol. 51, no. 1, p. 761–774, Jan. 2016.               browser extensions,” in Proceedings of the 24th International
     [Online]. Available: https://doi.org/10.1145/2914770.2837671                         Conference on World Wide Web, WWW 2015, Florence, Italy,
[50] K. Rieck, T. Krueger, and A. Dewald, “Cujo: efficient detection                      May 18-22, 2015, A. Gangemi, S. Leonardi, and A. Panconesi,
     and prevention of drive-by-download attacks,” in Twenty-Sixth Annual                 Eds. ACM, 2015, pp. 1286–1295. [Online]. Available: https:
     Computer Security Applications Conference, ACSAC 2010, Austin,                       //doi.org/10.1145/2736277.2741630
     Texas, USA, 6-10 December 2010, C. Gates, M. Franz, and J. P.                   [66] W. Xu, F. Zhang, and S. Zhu, “The power of obfuscation
     McDermott, Eds. ACM, 2010, pp. 31–39. [Online]. Available:                           techniques in malicious javascript code: A measurement study,” in
     https://doi.org/10.1145/1920261.1920267                                              7th International Conference on Malicious and Unwanted Software,
[51] A. Romano, Y. Zheng, and W. Wang, “Minerray: Semantics-aware                         MALWARE 2012, Fajardo, PR, USA, October 16-18, 2012. IEEE
     analysis for ever-evolving cryptojacking detection,” in Proceedings of               Computer Society, 2012, pp. 9–16. [Online]. Available: https:
     the 35th IEEE/ACM International Conference on Automated Software                     //doi.org/10.1109/MALWARE.2012.6461002
     Engineering, ser. ASE ’20. New York, NY, USA: Association                       [67] ——, “JStill: mostly static detection of obfuscated malicious JavaScript
     for Computing Machinery, 2020, p. 1129–1140. [Online]. Available:                    code,” in Proceedings of the third ACM conference on Data and
     https://doi.org/10.1145/3324884.3416580                                              application security and privacy - CODASPY ’13. San Antonio,
[52] J. Rüth, T. Zimmermann, K. Wolsing, and O. Hohlfeld, “Digging                       Texas, USA: ACM Press, 2013, p. 117. [Online]. Available:
     into browser-based crypto mining,” in Proceedings of the Internet                    http://dl.acm.org/citation.cfm?doid=2435349.2435364
     Measurement Conference 2018, IMC 2018, Boston, MA, USA, October                 [68] Y. Xue, J. Wang, Y. Liu, H. Xiao, J. Sun, and M. Chandramohan,
     31 - November 02, 2018. ACM, 2018, pp. 70–76. [Online]. Available:                   “Detection and classification of malicious JavaScript via attack behavior
     https://dl.acm.org/citation.cfm?id=3278539                                           modelling,” in Proceedings of the 2015 International Symposium on
[53] S. Sarker, J. Jueckstock, and A. Kapravelos, “Hiding in Plain Site:                  Software Testing and Analysis, ser. ISSTA 2015. New York, NY,
     Detecting JavaScript Obfuscation through Concealed Browser API                       USA: Association for Computing Machinery, Jul. 2015, pp. 48–59.
     Usage,” in IMC ’20: ACM Internet Measurement Conference, Virtual                     [Online]. Available: https://doi.org/10.1145/2771783.2771814
     Event, USA, October 27-29, 2020. ACM, 2020, pp. 648–661. [Online].              [69] I. You and K. Yim, “Malware obfuscation techniques: A brief survey,”
     Available: https://doi.org/10.1145/3419394.3423616                                   in 2010 International conference on broadband, wireless computing,
[54] P. Seshagiri, A. Vazhayil, and P. Sriram, “AMA: Static Code Analysis                 communication and applications. IEEE, 2010, pp. 297–300.
     of Web Page for the Detection of Malicious Scripts,” Procedia                   [70] Zswang, “Zswang/jfogs.” [Online]. Available: https://github.com/
     Computer Science, vol. 93, pp. 768–773, 2016. [Online]. Available:                   zswang/jfogs
     https://linkinghub.elsevier.com/retrieve/pii/S187705091631537X




                                                                                15
                                                                          A PPENDIX

                                                                   TABLE VII
                                      P RECISION OF MALWARE DETECTORS ON CODE OBFUSCATED BY W OBFUSCATOR .
       Technique                           Cujo                  Zozzle                 JaSt                   JStap (NGrams)        JStap (Values)
                                                                    Individual transformations:
       Baseline (no transformation)        0.95 (5,548/5,832)    0.97 (3,598/3,694)     1.00 (5,076/5,080)     1.00 (4,483/4,484)    1.00 (4,439/4,440)
       Sync, T1-StringLiteral              0.85 (1,623/1,907)    0.97 (3,387/3,483)     1.00 (3,393/3,397)     1.00 (1,539/1,540)    1.00 (1,839/1,840)
       Sync, T2-ArrayInitialization        0.93 (4,050/4,334)    0.97 (3,593/3,689)     1.00 (4,360/4,364)     1.00 (3,890/3,891)    1.00 (4,009/4,010)
       Sync, T3-FunctionName               0.91 (2,780/3,064)    0.97 (3,550/3,646)     1.00 (3,512/3,516)     1.00 (2,747/2,748)    1.00 (3,463/3,464)
       Sync, T4-CallExpression(a)          0.91 (3,040/3,324)    0.97 (3,507/3,603)     1.00 (1,943/1,947)     1.00 (1,723/1,724)    1.00 (3,613/3,614)
       Sync, T4-CallExpression(b)          0.89 (2,385/2,669)    0.97 (3,424/3,520)     1.00 (2,253/2,257)     1.00 (1,058/1,059)    1.00 (3,369/3,370)
       Sync, T5-IfStatement                0.93 (3,513/3,797)    0.97 (3,505/3,601)     1.00 (4,535/4,539)     1.00 (3,717/3,718)    1.00 (4,178/4,179)
       Sync, T6-ForStatement               0.93 (3,877/4,161)    0.97 (3,578/3,674)     1.00 (4,720/4,724)     1.00 (3,872/3,873)    1.00 (4,360/4,361)
       Sync, T7-WhileStatement             0.93 (3,904/4,188)    0.97 (3,598/3,694)     1.00 (4,882/4,886)     1.00 (4,410/4,411)    1.00 (4,412/4,413)
                                                                    Combined transformations:
       All sync (using T4(a))              0.59 (416/700)        0.97 (3,450/3,546)     1.00 (1,104/1,108)     0.50 (1/2)            1.00 (766/767)
       All sync (using T4(b))              0.59 (415/699)        0.97 (3,428/3,524)     1.00 (931/935)         0.00 (0/1)            1.00 (350/351)
       All async                           0.84 (1,490/1,774)    0.97 (3,524/3,620)     1.00 (1,085/1,089)     0.80 (4/5)            1.00 (959/960)



                                                                 TABLE VIII
                                  P RECISION OF MALWARE DETECTORS ON CODE OBFUSCATED BY OTHER OBFUSCATORS .
              Obfuscator                Cujo                  Zozzle                JaSt                  JStap (NGrams)         JStap (Values)
              javascript-obfuscator     0.94 (4,406/4,690)    0.98 (3,807/3,903)    1.00 (4,153/4,157)    1.00 (2,005/2,006)     1.00 (2,947/2,948)
              Gnirts                    0.95 (5,548/5,832)    0.97 (3,598/3,694)    1.00 (5,076/5,080)    1.00 (4,483/4,484)     1.00 (4,439/4,440)
              jfogs                     0.93 (3,515/3,799)    0.97 (3,584/3,680)    0.87 (26/30)          0.94 (16/17)           1.00 (2,826/2,827)
              JSObfu                    0.95 (4,994/5,278)    0.98 (4,467/4,563)    1.00 (1,456/1,460)    0.95 (20/21)           1.00 (2,420/2,421)



                                                                 TABLE IX
                                      M ALWARE CATEGORY BREAKDOWN OF DATASETS AND DETECTOR RECALL RATES .

Malware Type                     Dataset Breakdown                                                   Malware Detector Recall
                   VirusTotal    GeeksOnSecurity      HynekPetrak      Cujo             Zozzle               JaSt              JStap (N-grams)    JStap (Values)
Downloader         14            0                    21619            0.10(102/988)    0.67(1772/2629)      0.11(279/2629)    0.00(0/2440)       0.00(2/1787)
Misc               167           21                   13527            0.35(257/731)    0.64(1100/1732)      0.36(625/1732)    0.00(0/1082)       0.06(60/1082)
Trojan             1618          0                    2058             0.00(0/201)      0.61(305/499)        0.00(0/499)       0.00(0/453)        0.06(25/453)
Malware            0             0                    1546             0.00(0/109)      0.29(66/231)         0.22(51/231)      0.00(0/180)        0.02(3/125)
Exploit            6             1029                 0                0.00(0/151)      0.00(0/151)          0.00(0/151)       0.00(0/151)        0.00(0/151)
Ransomware         12            0                    700              0.00(0/56)       0.05(3/59)           0.00(0/3)         0.00(0/56)         -
Cryptominer        665           0                    0                1.00(1/1)        0.99(68/69)          0.00(0/69)        0.00(0/1)          0.00(0/1)
Dropper            0             323                  0                0.00(0/17)       0.50(26/45)          0.11(5/45)        0.00(0/45)         0.00(0/45)
Hijacker           112           0                    0                0.00(0/12)       0.94(17/18)          0.00(0/18)        0.00(0/12)         0.00(0/11)
Riskware           21            0                    0                1.00(1/1)        1.00(5/5)            0.00(0/5)         -                  -
Redirector         15            0                    0                0.00(0/3)        0.25(1/4)            0.00(0/4)         0.00(0/3)          0.00(0/3)
Clicker            25            0                    0                -                1.00(4/4)            0.00(0/4)         -                  -
Iframe             24            0                    0                -                1.00(4/4)            0.00(0/4)         1.00(1/1)          1.00(1/1)
Clickjack          13            0                    0                -                1.00(1/1)            0.00(0/1)         -                  -
Phishing           3             0                    0                -                -                    -                 -                  -




                                                                               16
