Introduction to Wasabi

Wasabi is a dynamic analysis framework for WebAssembly. What does this mean and why is it useful?

Dynamic analysis means observing some properties of a program while it is running. Dynamic analysis is routinely used to find and fix bugs, identify performance bottlenecks, or to search for security problems.

Since dynamic analysis has access to runtime information (e.g., program inputs and its current state), it can often be more precise than static analysis, that looks at the program without executing it. Obviously, static analysis has benefits as well. In practice, they often complement each other and you need at least a little bit of both. Dynamic analysis can answer many questions in the areas of

Analysis frameworks, such as Pin, Valgrind, or Jalangi, provide generic APIs on top of which many different analyses can be implemented. They solve low-level problems, e.g., how the analysis is interleaved with the program, once and for all, and let analysis authors focus on the analysis itself.

Writing a (static or dynamic) program analysis is hard, partly because the involved algorithms are complex. But at least some part of that complexity is independent of the individual analyses, for example because it stems from the program representation that is analyzed (e.g., native code or byte code) or the execution model (e.g., a virtual machine or actual hardware). Implementing these parts over and over again for specific analyses would be repetitive and error prone. The frameworks above have been a huge success in academia and practical use by providing a reusable platform for many different dynamic analyses. We would like to follow their path with this first dynamic analysis framework for WebAssembly.

WebAssembly is a new programming language (or more precisely: byte code) for browsers. It is faster, more low-level, and a better compilation target than JavaScript, the only option on the client-side until now. We expect it to be hugely successful in the near future.

For the first time in 20 years, all major browsers support client-side execution of a different language than JavaScript, without requiring third-party plugins like Flash or Java. The official website is a great resource for more details, but in short WebAssembly offers predictable, near-native performance without garbage collection, a compact binary representation that is quick to send over the network and parse, and nice static properties with a type system and clean module interfaces. It is designed from the start as a compilation target for “systems languages”, such as C and C++. Naturally, compute-intensive applications are WebAssembly’s strong suit, e.g., game engines or machine learning, but even plain front-end work might profit off the possibility to run other languages than JavaScript in the browser.

(Click on the bullets for more information. Simplified for the sake of giving a quick intuition.)

How Does It Work?

Conceptually

The name Wasabi stands for WebAssembly analysis using binary instrumentation, which hints at the two phases Wasabi operates in:

  1. It statically instruments a WebAssembly binary (e.g., program.wasm). That is, it inserts additional instructions, such as function calls, in between the original instructions of the program. This happens before the execution. Since WebAssembly is a binary format, and to be independent of the source code (which is often not available when analyzing third-party code in websites), we directly modify the byte code.
  2. To perform the dynamic analysis, the program is then executed (by opening the website with the now instrumented program.wasm). To make the user-written analysis functions known to the WebAssembly program (and for other technical reasons), a wasabi.js script has to be added to the page alongside the analysis.js.

As an Analysis Author / In Practice

The following picture shows the main steps necessary to analyze a WebAssembly program from the view of a user of Wasabi:

Main steps for a Wasabi analysis

  1. Write an analysis (e.g., analysis.js) against our high-level API in JavaScript (example below). The analysis can do anything JavaScript can do in the browser, e.g., output analysis results to the console, send them via WebSocket, or store them in an IndexedDB.
  2. Run the Wasabi tool on the WebAssembly program that shall be analyzed (e.g., program.wasm).
    Wasabi outputs two files in the process: First, the instrumented program (now contains calls to Wasabi’s analysis hooks) and second, a JavaScript file wasabi.js that contains statically extracted information about the program and some glue code to connect the analysis with the program itself.
  3. Modify the HTML harness (e.g., website.html) of the WebAssembly program.
    Since WebAssembly cannot be directly executed in a browser, it is typically embedded in a website and loaded with JavaScript. This website needs to be made aware of Wasabi. For that, add analysis.js (written by you) and wasabi.js (generated by Wasabi) with <script ...> tags to the HTML file. Also note that the instrumented WebAssembly program replaces the original file.
  4. Finally, open the website to execute the WebAssembly program as usual. Because of Wasabi’s instrumentation and runtime library, during the execution the analysis hooks inside analysis.js are called.

Example and Demo

Typically, WebAssembly programs are compiled from C or C++ via emscripten. But for this example, assume we have a small program written manually in the WebAssembly text format, called program.wat. We can create a binary from the text format with wat2wasm from the WebAssembly Binary Toolkit (WABT).

The program below contains two functions, $main and $loop, and imports a third function $print. The $ signifies indices in WebAssembly. That is, these “names” are actually encoded as integers and thus lost in the binary format. If you are interested, you can download the (uninstrumented) binary here.

(module
    ;; import function for printing integers from host environment
    (import "env" "print" (func $print (param i32)))
    ;; make main function available to the host environment
    (export "main" (func $main))

    (func $main
        ;; print 42 via the imported function
        i32.const 42
        call $print

        ;; call the function with index $loop
        call $loop
    )

    (func $loop
        (local $counter i32)
        i32.const 5
        local.set $counter
        loop
            ;; print current loop counter
            local.get $counter
            call $print

            ;; subtract 1 from loop counter
            local.get $counter
            i32.const -1
            i32.add
            local.tee $counter

            ;; backward branch (== continue) while $loop > 0
            i32.const 0
            i32.gt_s
            br_if 0
        end
    )
)

For this demo, we have already run Wasabi on the program above, which results in an instrumented binary and a generated wasabi.js file. In the editor below, you can enter a Wasabi analysis. Once you click on “Run Program”, the WebAssembly program is run and outputs some numbers below. (Note that your browser needs to support WebAssembly, we tested it with Chrome 61+ and Firefox 58+.)

By default, there is no analysis, so the only output is from the program itself. Click on the links below the editor for small example analyses or have a look into the Wasabi repository.

Wasabi Analysis (JavaScript):

Example: All hooks Example: Calls

Program and Analysis Output (via print() function):

Getting Started

This is a quick overview, for a more extensive version, see the README in the repository (but that version might get outdated at some point).

  1. Install the requirements: Rust programming language (compiler + package manager cargo, if there are errors, please use a recent stable version) and WebAssembly Binary Toolkit.
  2. Clone, build, and install Wasabi from source.

    $ git clone https://github.com/danleh/wasabi
    $ cd wasabi
    $ cargo install --path .
    
  3. Assemble the WebAssembly example program from above.

    $ wat2wasm program.wat
    $ ls
    program.wat  program.wasm
    
  4. Instrument with Wasabi and generate wasabi.js file.

    $ wasabi program.wasm
    $ ls out/
    program.wasm  program.wasabi.js
    
  5. Replace original program.wasm with instrumented one from out/ directory and add program.wasabi.js as script to website.

  6. Write your analysis and add that analysis.js script to website.

More Details

For more details, you can: