Skip to content

knowonething/wasm_analyzer_exploit

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WebAssembly Runtime Analyzer & Exploit

A research tool for analyzing WebAssembly runtimes and evaluating exploit feasibility.


Artifact Version Notice

The complete version of the artifact, including all data and supplementary materials, is available for download on Zenodo. This GitHub repository contains a simplified version with only the essential code to keep the size manageable. Please note that the artifact is currently under review. We may update it based on reviewer feedback. Once the review process is complete, we will update this repository accordingly. If you do not want to download the full artifact, below are some additional instructions and information to help you use the code effectively.

Decompiler

Our analysis method uses a decompiler tool. We recommend retdec. You can download the precompiled retdec binary (note that it is quite large) and then create a decompiler directory where you place retdec. Additionally, modify the retdec variable in start.sh to point to retdec-decompiler. If you do not need this functionality, simply remove the --retdec "$retdec" parameter.

Runtimes

To analyze WebAssembly runtimes (such as Wasmtime and Wasmer), you first need to obtain their source code. You can create a wasm_runtimes directory and clone the target runtime repositories into it. For example, clone Wasmtime and checkout branch 24.0.0, or clone Wasmer and checkout branch v4.3.2. Additionally, the INPUT_DIR variable in the start.sh script defaults to wasm_runtimes/wasmtime. You may need to modify it accordingly.

LLVM

Our analysis method relies on the LLVM API, so you may need to first build and install LLVM (which is quite large), and then use CMake to build our analyzer.

WebAssembly Module

To test the exploit strategy, you will need to build a WebAssembly module. The latest official documentation of Wasmtime and Wasmer both explain how to compile Rust code into modules runnable by Wasmtime/Wasmer. Here, we briefly introduce the relevant commands:

# for Wasmtime
rustup target add wasm32-wasip1-threads
cargo build --target wasm32-wasip1-threads
# for Wasmer
cargo install cargo-wasix
cargo wasix build

Artifacts Structure

Please download the compressed package we provided, which consists of 13 volumes (wasm_artifacts.7z.*). After extraction, you will get the wasm_artifacts directory with the following structure:

wasm_artifacts/
├── analyzer             # Includes our analysis tool, which is organized as a CMake-based project.
├── decompiler           # Includes the dependent decompilation tool.
├── docker
│   └── Dockerfile       # Dockerfile for the provided Docker image.
├── exploit              # Includes the exploit implementation.
├── result               # If you run start.sh locally, the output will be in this directory.
├── result_backup        # Backup of previous analysis output results.
├── start.sh             # The startup script builds the project, extracts the IR, analyzes the IR, and outputs the results.
├── wcargo_build         # start.sh builds the project and extracts IR based on wcargo_build.
└── wasm_runtimes        # Wasmtime and Wasmer prepared and ready for analysis。

This artifact consists of two main components:

  • Part 1: WebAssembly Runtime Analyzer
  • Part 2: Exploit

How to Evaluate

  • ✅ For Part 1: You can evaluate the output results produced by our analysis tool to verify its accuracy and completeness.
  • ✅ For Part 2: You can assess the effectiveness of the proposed exploit through practical testing and validation.

🧠 Part 1: WebAssembly Runtime Analyzer

We assume you are using a fresh Ubuntu system without the dependencies required by our artifact. We provide two methods to run the analyzer demo, and we strongly recommend using the Docker-based approach, as it won't pollute your host environment. The Docker image we prepared contains all the necessary data and configuration files for running, so it is quite large—about 10 GB. To enable faster uploading to Zenodo, we compressed it using 7z and split it into 25 volumes named artifact.image.7z.*. Please download them all and place them together.

Start With Docker (Recommended 🚀)

  1. Install Docker: Please refer to the Docker documentation to install Docker. Here, we briefly explain how to install Docker on a fresh Ubuntu system based on the official documentation.
# Uninstall all conflicting packages
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

# Install the latest version
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  1. Load our Artifacts Docker image: Please download our 25 volumes named artifact.image.7z.* and place them together.
# in the folder which contains 25 volumes named artifact.image.7z.*
sudo apt update
sudo apt install p7zip-full
7z x artifact.image.7z.001
# load
sudo docker load -i artifact.image
# check, artifacts:latest
sudo docker images
  1. Run our Artifacts: Our Docker image will automatically run a demo upon execution. It will build Wasmtime, extract the LLVM IR, analyze the IR, and output the analysis results. You don't need to provide any input or configuration for the Demo—everything required is already included in the image. As a result, the image is quite large.
sudo docker run -it --rm artifacts:latest

You are expected to see the following process. (Note: the video is sped up.)

Build And Analyze

⬆️: Build Rust project, extract intermediate representation (IR), analyze it, and display the results. (Video speed increased for brevity.)

Our image’s Dockerfile is located at wasm_artifacts/docker/Dockerfile. Since the required files(e.g., LLVM) are very large and take a long time to upload, we did not include them.

Start Without Docker

Without Docker, you would need to install many dependencies, such as LLVM and a specific nightly version of Rust. We do not recommend this approach, as differences in environments can easily lead to errors.

  1. Install required dependencies: We need to install LLVM and a specific nightly version of Rust.
# for LLVM
sudo apt --yes update && sudo apt install --yes cmake gcc g++ \
                python3 python3-dev zlib1g make binutils bzip2 \
                zip xz-utils git
git clone https://github.com/llvm/llvm-project.git
mkdir ./build && cd ./build/
cmake -S ../llvm-project/llvm/ -B ./ -G "Unix Makefiles" \
                -DCMAKE_BUILD_TYPE=Release \
                -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lldb;lld" \
                -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;compiler-rt" \
make -j 8
sudo make install
# check
clang --version

# for Rust
sudo apt install --yes curl
# install rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# install nightly version
~/.cargo/bin/rustup toolchain install nightly-2024-02-01
# setup nightly version
~/.cargo/bin/rustup default nightly-2024-02-01-x86_64-unknown-linux-gnu
# download the rust std source code
~/.cargo/bin/rustup component add rust-src --toolchain nightly-2024-02-01-x86_64-unknown-linux-gnu
  1. Prepare & run: After downloading the compressed package we provided (consisting of 13 volumes, wasm_artifacts.7z.*), extract it and run the script inside.
# extract
sudo apt update
sudo apt install p7zip-full
7z x wasm_artifacts.7z.001
# run
cd wasm_artifacts
./start.sh
# After the demo finishes running, check wasm_artifacts/result/API2PotentialAPIs_Syscalls.json.

After running, you should see the same output as in the Docker container, such as:

Build And Analyze

📦 Output Structure

The output will be saved in wasm_artifacts/result.

  • API2PotentialAPIs_Syscalls.json: Contains the analysis results, i.e., the APIs/syscalls involved in the interfaces.

  • bc/: Contains the complete LLVM IR extracted from the project.

  • module_asm*: There may also be some module_asm* files. This is because the analyzer needs to convert assembly code blocks in the LLVM bitcode file into LLVM IR and merge them with the main LLVM IR in the LLVM bitcode.

Backup Data

In the wasm_artifacts/result_backup/ directory, we have saved our previous analysis results: API2PotentialAPIs_Syscalls_wasmer.json and API2PotentialAPIs_Syscalls_wasmtime.json. These are JSON-format files, and their contents are as follows:

{
  "API2PotentialArgValues": {    // External APIs that may be involved in runtime interfaces
    "fsync": {                   // Name of the API
      "0": []                    // Possible values for the the argument are unknown
    }
  },
  "syscall2PotentialValues": {   // Syscalls that may be involved in runtime interfaces
    "332": {                     // Syscall number
      "0": [0],                  // The first argument may be 0
      "1": [],                   // No known possible values for the second argument
      "2": [ 0, 256, 4096],      // The third argument may be 0, 256, or 4096
      "3": [4095],               // The fourth argument may be 4095
      "4": []                    // No known possible values for the fifth argument
    }
  }
}

💣 Part 2: Exploit

  1. Install required dependencies:
# for python
sudo apt install python3
# for Wasmtime
curl https://wasmtime.dev/install.sh -sSf | bash
# for Wasmer
curl https://get.wasmer.io -sSfL | sh
# and others
sudo apt install dstat ent fio iperf3 sysstat
  1. Generate commands: The compressed archive we provide includes 13 volumes (wasm_artifacts.7z.*), which contain pre-built WebAssembly modules for exploitation demonstration. First, extract the archive. Then, run the script on your machine to generate the command for launching the exploitation. And check wasm_artifacts/exploit/data/config, where you'll find the set of commands we just generated—prepared separately for Wasmtime and Wasmer.
# extract
sudo apt update
sudo apt install p7zip-full
7z x wasm_artifacts.7z.001
# generate commands
cd wasm_artifacts/exploit/test_tool
python tester.py
  1. Prepare the fio configuration file: To evaluate the impact of exploitation on file I/O performance, we use fio for testing. Therefore, you need to prepare the fio configuration files. Modify read.fio and write.fio located in wasm_artifacts/exploit/data/fio/. Specifically, create two large files (e.g., 10 GB each), and in the last line of both read.fio and write.fio (i.e., filename=<path/to/a/big/file>), replace the placeholder with the absolute path to each large file, respectively. Since uploading large files is time-consuming, we did not include them in the artifact. You can quickly generate large files like this.
dd if=/dev/urandom of=for_read_fio bs=1M count=10240 status=progress
dd if=/dev/urandom of=for_write_fio bs=1M count=10240 status=progress
  1. Start testing: Now that we have installed wasmtime and wasmer, and generated the exploitation commands, we can proceed with testing. You can open two shells: one for testing system performance and the other for launching the exploitation. However, first you should collect baseline data—that is, the system performance when it is idle (without running the exploitation).
# in the wasm_artifacts/exploit/
# test file I/O performance
fio data/fio/read.fio
fio data/fio/write.fio
# view overall system resource usage (e.g., CPU)
dstat

After confirming the baseline, run the exploitation, then run fio and dstat again, focusing on the resource usage shown in dstat's output. Once fio completes, kill the exploitation process and check the output of fio. You can select a exploit command to execute from wasm_artifacts/exploit/data/config/wasmtime.json, for example:

# Note: You should copy a command from your own wasmtime.json file, not from this example.
wasmtime  -S threads=y --dir /dev --dir /home/user/wasm_artifacts/exploit/test_tool/../data/test /home/user/wasm_artifacts/exploit/test_tool/../target/wasm32-wasip1-threads/debug/wasmtime_api_tester.wasm fs sync multi /home/user/wasm_artifacts/exploit/test_tool/../data/test/newfile 100 true false",

The gif below shows the test results on my machine. First, we run fio to obtain the baseline. Then, we execute the exploit command. After that, we run fio again to test the IO performance. As you can see, performance dropped from 410.0MiB/s to 22.2MiB/s—a decrease of over 94.6%—which demonstrates the effectiveness of our attack.

sync attack result

To test the impact on the network, you need to use iperf3. The gif below shows the network-related results of the exploitation. We used two machines, A and B, both have iperf3 installed, and B additionally has ncat installed. Machine A sends traffic, while B listens. iperf3 measures network bandwidth, and our exploitation commands consume bandwidth. As you can see, the sending and receiving bandwidth decreased by 22.0% and 18.1%, respectively.

net attack result

  1. Use our script: If you want to simplify the testing process, wasm_artifacts/exploit/test_tool/tester.py is the tool we provide for automated testing. It is currently used to generate exploitation commands, as shown below:
if __name__ == "__main__":
    # baseline()
    # show_baseline()
    wasm.wasmer_param_generator(DATA_DIR / "config" / "wasmer.json")
    wasm.wasmtime_param_generator(DATA_DIR / "config" / "wasmtime.json")
    # run_wasm_config_task()
    # run_wasm_config_task(cgroup="/sys/fs/cgroup/test_cgroup/cgroup.procs")

The function run_wasm_config_task performs automated testing. It reads exploitation commands from the JSON files in the wasm_artifacts/exploit/data/config directory and runs the tests. During the exploitation, it uses tools like dstat, pidstat, fio, iperf, and ent to monitor system performance, then saves the results in the wasm_artifacts/exploit/data/result directory.

This function tests only one command at a time because we found that running commands consecutively leads to inaccurate results. Therefore, we test commands one by one. You can modify tester.py to first collect baseline data using the baseline() function, and then collect exploitation data by running run_wasm_config_task().

Backup Data

In the wasm_artifacts/exploit/data/result_backup directory, we have saved the system performance data recorded during previous exploit testing, including baseline data.

Within this directory, there are three JSON files, all of which are configuration files containing the commands required to launch the exploitations, similar to those we generated earlier.

All other subdirectories are named using the format "configFileName_commandIndex", corresponding one-to-one with the commands in the configuration files. These subdirectories may contain:

  • dstat.csv: Overall system CPU usage data.
  • ent.txt: Random number generation rate.
  • fio_read.jsonfio_write.json: File I/O performance data.
  • ipert3.txt: Network bandwidth data.
  • pidstat.txt: CPU usage data of the exploit process.

By comparing these data with those in the baseline, we can assess the performance degradation caused by the exploit.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • C++ 93.9%
  • Rust 2.6%
  • Python 2.0%
  • C 1.0%
  • Shell 0.3%
  • Dockerfile 0.1%
  • CMake 0.1%