Zum Inhalt

WebAssembly (WASM) Werkzeuge Cheat Sheet

generieren

Überblick

WebAssembly (WASM) ist ein binäres Befehlsformat für eine stapelbasierte virtuelle Maschine, die als tragbares Compilationsziel für Programmiersprachen konzipiert ist. Da WASM in Webanwendungen und sogar Malware immer häufiger verbreitet wird, sind spezialisierte Tools für Analyse, Dekompilation und Sicherheitsforschung unerlässlich.

RECHT *Key Tools: wasm-decompile, Binaryen, WABT (WebAssembly Binary Toolkit), wasm2c, wasm-objdump und verschiedene Browser-basierte Analysetools für umfassende WASM binäre Analyse.

Installation und Inbetriebnahme

WABT (WebAssembly Binary Toolkit)

```bash

Install via package manager (Ubuntu/Debian)

sudo apt-get update sudo apt-get install wabt

Install via Homebrew (macOS)

brew install wabt

Build from source

git clone --recursive https://github.com/WebAssembly/wabt cd wabt mkdir build && cd build cmake .. cmake --build .

Add to PATH

export PATH=$PATH:/path/to/wabt/build

Verify installation

wasm-objdump --version wasm2wat --version wat2wasm --version

Install additional tools

sudo apt-get install nodejs npm npm install -g @webassembly/wabt ```_

Binary

```bash

Install via package manager

sudo apt-get install binaryen

Install via npm

npm install -g binaryen

Build from source

git clone https://github.com/WebAssembly/binaryen.git cd binaryen cmake . && make

Verify installation

wasm-opt --version wasm-dis --version wasm-as --version

Install Python bindings

pip install binaryen

Test installation

python -c "import binaryen; print('Binaryen installed successfully')" ```_

wasm-decompile und zusätzliche Tools

```bash

Install wasm-decompile (part of WABT)

Already included with WABT installation

Install wasm2c

git clone https://github.com/WebAssembly/wasm2c cd wasm2c make

Install Wasmer (WASM runtime)

curl https://get.wasmer.io -sSfL | sh source ~/.wasmer/wasmer.sh

Install Wasmtime (another WASM runtime)

curl https://wasmtime.dev/install.sh -sSf | bash

Install wasm-pack (for Rust)

curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

Install Emscripten (for C/C++ to WASM)

git clone https://github.com/emscripten-core/emsdk.git cd emsdk ./emsdk install latest ./emsdk activate latest source ./emsdk_env.sh

Verify all tools

which wasm-objdump wasm-decompile wasm-opt wasmer wasmtime ```_

Browserbasierte Tools Setup

```bash

Install browser extensions and tools

Chrome DevTools WASM debugging (built-in)

Firefox Developer Tools WASM support (built-in)

Install wasm-pack for web development

npm install -g wasm-pack

Install wasmtime-js for Node.js

npm install @bytecodealliance/wasmtime

Set up local web server for WASM analysis

python3 -m http.server 8000

or

npx serve .

Install additional analysis tools

npm install -g wasm-strip npm install -g wasm-snip npm install -g twiggy # WASM code size profiler ```_

Grundlegende WASM Analyse

Dateiinformationen und Struktur

```bash

Get basic file information

file sample.wasm hexdump -C sample.wasm | head -20

Check WASM magic number (0x00 0x61 0x73 0x6d)

xxd sample.wasm | head -1

Get WASM module information

wasm-objdump -h sample.wasm

Display all sections

wasm-objdump -s sample.wasm

Show section details

wasm-objdump -x sample.wasm

Display imports and exports

wasm-objdump -j import sample.wasm wasm-objdump -j export sample.wasm

Show function signatures

wasm-objdump -j type sample.wasm

Display function bodies

wasm-objdump -j code sample.wasm

Show data sections

wasm-objdump -j data sample.wasm

Display custom sections

wasm-objdump -j custom sample.wasm

Get detailed disassembly

wasm-objdump -d sample.wasm

Show relocation information

wasm-objdump -r sample.wasm

Display symbol table

wasm-objdump -t sample.wasm ```_

WASM zu WAT-Umrechnung

```bash

Convert WASM binary to WAT (WebAssembly Text)

wasm2wat sample.wasm -o sample.wat

Convert with verbose output

wasm2wat sample.wasm -v -o sample.wat

Convert with function names

wasm2wat sample.wasm --generate-names -o sample.wat

Convert with inline exports

wasm2wat sample.wasm --inline-exports -o sample.wat

Convert with folded expressions

wasm2wat sample.wasm --fold-exprs -o sample.wat

Convert specific sections only

wasm2wat sample.wasm --no-debug-names -o sample.wat

Convert with custom formatting

wasm2wat sample.wasm --no-check -o sample.wat

Batch conversion

for file in *.wasm; do wasm2wat "$file" -o "${file%.wasm}.wat" done

Convert WAT back to WASM

wat2wasm sample.wat -o sample.wasm

Validate WASM file

wat2wasm sample.wat --validate ```_

WASM-Dekompilation

```bash

Decompile WASM to C-like pseudocode

wasm-decompile sample.wasm -o sample.dcmp

Decompile with function names

wasm-decompile sample.wasm --generate-names -o sample.dcmp

Decompile with inline exports

wasm-decompile sample.wasm --inline-exports -o sample.dcmp

Decompile with variable names

wasm-decompile sample.wasm --name-all -o sample.dcmp

Advanced decompilation options

wasm-decompile sample.wasm \ --generate-names \ --inline-exports \ --fold-exprs \ --name-all \ -o sample_detailed.dcmp

Decompile specific functions

wasm-decompile sample.wasm --func-index=0 -o function0.dcmp wasm-decompile sample.wasm --func-name=main -o main_function.dcmp

Batch decompilation

for file in *.wasm; do echo "Decompiling $file..." wasm-decompile "$file" --generate-names -o "${file%.wasm}.dcmp" done

Compare original and decompiled

diff -u original.c sample.dcmp ```_

Erweiterte Analysetechniken

Binary-Analyse-Tools

```bash

Optimize WASM binary

wasm-opt sample.wasm -O3 -o sample_optimized.wasm

Analyze optimization opportunities

wasm-opt sample.wasm --print-features

Remove debug information

wasm-opt sample.wasm --strip-debug -o sample_stripped.wasm

Minify WASM

wasm-opt sample.wasm -Oz --strip-debug -o sample_minified.wasm

Validate WASM module

wasm-opt sample.wasm --validate

Print module structure

wasm-opt sample.wasm --print

Print function CFG

wasm-opt sample.wasm --print-function-map

Analyze memory usage

wasm-opt sample.wasm --print-stack-ir

Dead code elimination

wasm-opt sample.wasm --dce -o sample_dce.wasm

Inline functions

wasm-opt sample.wasm --inline-functions-with-loops -o sample_inlined.wasm

Constant folding

wasm-opt sample.wasm --const-hoisting -o sample_const.wasm

Loop optimization

wasm-opt sample.wasm --optimize-level=3 --shrink-level=1 -o sample_loops.wasm ```_

Speicher- und Datenanalyse

```bash

Extract data sections

wasm-objdump -j data sample.wasm > data_sections.txt

Analyze memory layout

wasm-objdump -s sample.wasm | grep -A 10 "Contents of section data"

Extract strings from WASM

strings sample.wasm > extracted_strings.txt

Search for specific patterns

| hexdump -C sample.wasm | grep -i "password\ | secret\ | key" |

Analyze imports for API calls

| wasm-objdump -j import sample.wasm | grep -E "(func | memory | table | global)" |

Check for suspicious imports

| wasm-objdump -j import sample.wasm | grep -E "(eval | document | window | fetch | XMLHttpRequest)" |

Analyze exports

wasm-objdump -j export sample.wasm

Extract function names

| wasm-objdump -j export sample.wasm | grep "func" | awk '{print $4}' |

Analyze global variables

wasm-objdump -j global sample.wasm

Check memory configuration

wasm-objdump -j memory sample.wasm

Analyze table sections

wasm-objdump -j table sample.wasm

Extract custom sections

wasm-objdump -j custom sample.wasm ```_

Steuerungsflussanalyse

```bash

Generate control flow graph

wasm-opt sample.wasm --print-function-map > cfg.txt

Analyze function calls

wasm-objdump -d sample.wasm | grep "call"

Find indirect calls

wasm-objdump -d sample.wasm | grep "call_indirect"

Analyze branches

| wasm-objdump -d sample.wasm | grep -E "(br | br_if | br_table)" |

Find loops

| wasm-objdump -d sample.wasm | grep -E "(loop | block)" |

Analyze exception handling

| wasm-objdump -d sample.wasm | grep -E "(try | catch | throw)" |

Extract function boundaries

awk '/^[0-9a-f]+.*func/ {print $0}' sample.wat

Analyze stack operations

| wasm-objdump -d sample.wasm | grep -E "(local. | global. | i32. | i64. | f32. | f64.)" |

Find return statements

wasm-objdump -d sample.wasm | grep "return"

Analyze unreachable code

wasm-objdump -d sample.wasm | grep "unreachable" ```_

Sicherheitsanalyse

Techniken der Malware-Analyse

```bash

Check for obfuscation indicators

| wasm-objdump -h sample.wasm | grep -E "(custom | unknown)" |

Analyze suspicious function names

| wasm2wat sample.wasm --generate-names | grep -E "(eval | exec | shell | cmd)" |

Check for dynamic code generation

| wasm-objdump -d sample.wasm | grep -E "(memory.grow | table.grow)" |

Analyze memory access patterns

| wasm-objdump -d sample.wasm | grep -E "(load | store)" | head -20 |

Check for anti-analysis techniques

| wasm-objdump -d sample.wasm | grep -E "(unreachable | trap)" |

Analyze imports for suspicious APIs

| wasm-objdump -j import sample.wasm | grep -v -E "(Math | console | Date)" |

Check for encrypted/encoded data

| hexdump -C sample.wasm | grep -E "([0-9a-f]{2} ){16}" | head -10 |

Analyze function complexity

| wasm-decompile sample.wasm | grep -c "if\ | while\ | for" |

Check for self-modification

| wasm-objdump -d sample.wasm | grep -E "(memory.copy | memory.fill)" |

Analyze exception handling for evasion

| wasm-objdump -d sample.wasm | grep -E "(try | catch)" -A 5 -B 5 | ```_

Schwachstellenerkennung

```bash

Check for buffer overflow vulnerabilities

| wasm-objdump -d sample.wasm | grep -E "(memory.size | memory.grow)" -A 3 -B 3 |

Analyze bounds checking

| wasm-decompile sample.wasm | grep -E "bounds | check | limit" |

Check for integer overflow

| wasm-objdump -d sample.wasm | grep -E "(add | mul | div)" | head -10 |

Analyze memory safety

| wasm-opt sample.wasm --print-stack-ir | grep -E "load | store" |

Check for use-after-free patterns

| wasm-decompile sample.wasm | grep -E "free | malloc | realloc" -A 5 -B 5 |

Analyze type confusion

wasm-objdump -j type sample.wasm

Check for format string vulnerabilities

strings sample.wasm | grep -E "%[sdxp]"

Analyze input validation

| wasm-decompile sample.wasm | grep -E "validate | sanitize | check" |

Check for race conditions

| wasm-objdump -d sample.wasm | grep -E "(atomic | shared)" |

Analyze cryptographic usage

| strings sample.wasm | grep -E "(crypto | hash | encrypt | decrypt | key | iv)" | ```_

Sandbox Escape Analyse

```bash

Check for DOM manipulation

| wasm-objdump -j import sample.wasm | grep -E "(document | window | DOM)" |

Analyze file system access

| wasm-objdump -j import sample.wasm | grep -E "(file | read | write | open)" |

Check for network access

| wasm-objdump -j import sample.wasm | grep -E "(fetch | xhr | websocket | http)" |

Analyze process creation

| wasm-objdump -j import sample.wasm | grep -E "(exec | spawn | process)" |

Check for memory access outside sandbox

| wasm-objdump -d sample.wasm | grep -E "memory.(load | store)" -A 2 | grep -E "offset=" |

Analyze shared memory usage

wasm-objdump -j memory sample.wasm | grep "shared"

Check for worker thread creation

| wasm-objdump -j import sample.wasm | grep -E "(worker | thread)" |

Analyze timing attacks

| wasm-objdump -j import sample.wasm | grep -E "(performance | time | date)" |

Check for side-channel attacks

| wasm-decompile sample.wasm | grep -E "cache | timing | power" | ```_

Dynamische Analyse

Laufzeitanalyse mit Wasmer

```bash

Run WASM with Wasmer

wasmer run sample.wasm

Run with arguments

wasmer run sample.wasm -- arg1 arg2 arg3

Run with environment variables

ENV_VAR=value wasmer run sample.wasm

Enable debugging

wasmer run sample.wasm --debug

Run with memory limits

wasmer run sample.wasm --max-memory=1GB

Run with CPU limits

wasmer run sample.wasm --max-time=30s

Enable tracing

wasmer run sample.wasm --trace

Run with custom imports

wasmer run sample.wasm --mapdir=/host:/guest

Profile execution

time wasmer run sample.wasm

Run with different engines

wasmer run sample.wasm --backend=cranelift wasmer run sample.wasm --backend=llvm wasmer run sample.wasm --backend=singlepass ```_

Laufzeitanalyse mit Abfallzeit

```bash

Run WASM with Wasmtime

wasmtime run sample.wasm

Run with arguments

wasmtime run sample.wasm -- arg1 arg2 arg3

Enable debugging

wasmtime run --debug sample.wasm

Run with memory limits

wasmtime run --max-memory=1073741824 sample.wasm # 1GB

Enable optimization

wasmtime run --optimize sample.wasm

Run with fuel limits (instruction counting)

wasmtime run --fuel=1000000 sample.wasm

Enable epoch interruption

wasmtime run --epoch-interruption sample.wasm

Run with WASI support

wasmtime run --wasi-modules=wasi_snapshot_preview1 sample.wasm

Profile execution

wasmtime run --profile=jitdump sample.wasm

Run with custom configuration

wasmtime run --config wasmtime.toml sample.wasm

Enable memory profiling

wasmtime run --profile=perfmap sample.wasm ```_

Browserbasierte dynamische Analyse

```javascript // Load and analyze WASM in browser async function analyzeWasm(wasmUrl) { try { // Fetch WASM binary const response = await fetch(wasmUrl); const wasmBytes = await response.arrayBuffer();

    // Compile WASM module
    const wasmModule = await WebAssembly.compile(wasmBytes);

    // Get module imports
    const imports = WebAssembly.Module.imports(wasmModule);
    console.log('Imports:', imports);

    // Get module exports
    const exports = WebAssembly.Module.exports(wasmModule);
    console.log('Exports:', exports);

    // Create instance with instrumented imports
    const instrumentedImports = createInstrumentedImports();
    const wasmInstance = await WebAssembly.instantiate(wasmModule, instrumentedImports);

    // Analyze exported functions
    for (const exp of exports) {
        if (exp.kind === 'function') {
            console.log(`Function: ${exp.name}`);

            // Hook function calls
            const originalFunc = wasmInstance.exports[exp.name];
            wasmInstance.exports[exp.name] = function(...args) {
                console.log(`Calling ${exp.name} with args:`, args);
                const result = originalFunc.apply(this, args);
                console.log(`${exp.name} returned:`, result);
                return result;
            };
        }
    }

    return wasmInstance;

} catch (error) {
    console.error('WASM analysis failed:', error);
}

}

// Create instrumented imports for monitoring function createInstrumentedImports() { return { env: { // Hook memory operations memory: new WebAssembly.Memory({ initial: 256, maximum: 256 }),

        // Hook console operations
        console_log: function(ptr, len) {
            const memory = new Uint8Array(this.memory.buffer);
            const str = new TextDecoder().decode(memory.slice(ptr, ptr + len));
            console.log('WASM console.log:', str);
        },

        // Hook mathematical operations
        Math_random: function() {
            const value = Math.random();
            console.log('WASM Math.random():', value);
            return value;
        },

        // Hook date operations
        Date_now: function() {
            const value = Date.now();
            console.log('WASM Date.now():', value);
            return value;
        }
    },

    // Hook WASI operations
    wasi_snapshot_preview1: {
        fd_write: function(fd, iovs, iovs_len, nwritten) {
            console.log(`WASM fd_write: fd=${fd}, iovs_len=${iovs_len}`);
            return 0;
        },

        proc_exit: function(code) {
            console.log(`WASM proc_exit: code=${code}`);
        }
    }
};

}

// Memory analysis functions function analyzeWasmMemory(wasmInstance) { const memory = wasmInstance.exports.memory; if (!memory) return;

const buffer = new Uint8Array(memory.buffer);

// Search for strings
const strings = [];
let currentString = '';
for (let i = 0; i < buffer.length; i++) {
    if (buffer[i] >= 32 && buffer[i] <= 126) {
        currentString += String.fromCharCode(buffer[i]);
    } else {
        if (currentString.length > 4) {
            strings.push(currentString);
        }
        currentString = '';
    }
}

console.log('Found strings:', strings);

// Analyze memory patterns
const patterns = {
    nullBytes: 0,
    highEntropy: 0,
    repeatingPatterns: 0
};

for (let i = 0; i < buffer.length; i++) {
    if (buffer[i] === 0) patterns.nullBytes++;
    if (buffer[i] > 127) patterns.highEntropy++;
    if (i > 0 && buffer[i] === buffer[i-1]) patterns.repeatingPatterns++;
}

console.log('Memory patterns:', patterns);

}

// Function call tracing function traceWasmExecution(wasmInstance) { const callStack = [];

// Hook all exported functions
for (const [name, func] of Object.entries(wasmInstance.exports)) {
    if (typeof func === 'function') {
        wasmInstance.exports[name] = function(...args) {
            callStack.push({ function: name, args: args, timestamp: Date.now() });
            console.log(`→ ${name}(${args.join(', ')})`);

            try {
                const result = func.apply(this, args);
                console.log(`← ${name} returned: ${result}`);
                return result;
            } catch (error) {
                console.log(`← ${name} threw: ${error}`);
                throw error;
            } finally {
                callStack.pop();
            }
        };
    }
}

return callStack;

} ```_

Automatisierte Analyseskripte

Umfassende WASM Analyse Script

```python

!/usr/bin/env python3

""" Comprehensive WASM Analysis Tool Analyzes WebAssembly binaries for security issues and malware indicators """

import os import sys import subprocess import json import hashlib import re from pathlib import Path

class WasmAnalyzer: def init(self, wasm_file): self.wasm_file = Path(wasm_file) self.analysis_results = { 'file_info': {}, 'structure': {}, 'security': {}, 'strings': [], 'functions': [], 'imports': [], 'exports': [], 'suspicious_indicators': [] }

def analyze(self):
    """Perform comprehensive WASM analysis"""

    print(f"Analyzing WASM file: {self.wasm_file}")

    # Basic file analysis
    self.analyze_file_info()

    # Structure analysis
    self.analyze_structure()

    # Security analysis
    self.analyze_security()

    # Extract strings
    self.extract_strings()

    # Analyze functions
    self.analyze_functions()

    # Analyze imports/exports
    self.analyze_imports_exports()

    # Generate report
    self.generate_report()

    return self.analysis_results

def analyze_file_info(self):
    """Analyze basic file information"""

    stat = self.wasm_file.stat()

    with open(self.wasm_file, 'rb') as f:
        content = f.read()

    self.analysis_results['file_info'] = {
        'size': stat.st_size,
        'md5': hashlib.md5(content).hexdigest(),
        'sha1': hashlib.sha1(content).hexdigest(),
        'sha256': hashlib.sha256(content).hexdigest(),
        'magic': content[:4].hex() if len(content) >= 4 else '',
        'valid_magic': content[:4] == b'\x00asm'
    }

def analyze_structure(self):
    """Analyze WASM structure"""

    try:
        # Get section information
        result = subprocess.run(['wasm-objdump', '-h', str(self.wasm_file)], 
                              capture_output=True, text=True)

        if result.returncode == 0:
            sections = []
            for line in result.stdout.split('\n'):
                if 'Section Details:' in line or line.strip().startswith('Type'):
                    continue
                if line.strip() and not line.startswith('Sections:'):
                    sections.append(line.strip())

            self.analysis_results['structure']['sections'] = sections

        # Get detailed structure
        result = subprocess.run(['wasm-objdump', '-x', str(self.wasm_file)], 
                              capture_output=True, text=True)

        if result.returncode == 0:
            self.analysis_results['structure']['detailed'] = result.stdout

    except FileNotFoundError:
        print("Warning: wasm-objdump not found. Install WABT for detailed analysis.")

def analyze_security(self):
    """Perform security analysis"""

    security_issues = []

    # Check for suspicious imports
    try:
        result = subprocess.run(['wasm-objdump', '-j', 'import', str(self.wasm_file)], 
                              capture_output=True, text=True)

        if result.returncode == 0:
            suspicious_imports = [
                'eval', 'Function', 'document', 'window', 'XMLHttpRequest',
                'fetch', 'WebSocket', 'Worker', 'SharedArrayBuffer'
            ]

            for imp in suspicious_imports:
                if imp in result.stdout:
                    security_issues.append(f"Suspicious import: {imp}")

    except FileNotFoundError:
        pass

    # Check for obfuscation indicators
    with open(self.wasm_file, 'rb') as f:
        content = f.read()

    # High entropy check (possible encryption/obfuscation)
    entropy = self.calculate_entropy(content)
    if entropy > 7.5:
        security_issues.append(f"High entropy detected: {entropy:.2f}")

    # Check for unusual section names
    try:
        result = subprocess.run(['wasm-objdump', '-j', 'custom', str(self.wasm_file)], 
                              capture_output=True, text=True)

        if result.returncode == 0 and result.stdout.strip():
            security_issues.append("Custom sections detected (possible obfuscation)")

    except FileNotFoundError:
        pass

    self.analysis_results['security']['issues'] = security_issues

def calculate_entropy(self, data):
    """Calculate Shannon entropy of data"""

    if not data:
        return 0

    # Count byte frequencies
    frequencies = {}
    for byte in data:
        frequencies[byte] = frequencies.get(byte, 0) + 1

    # Calculate entropy
    entropy = 0
    data_len = len(data)

    for count in frequencies.values():
        probability = count / data_len
        if probability > 0:
            entropy -= probability * (probability.bit_length() - 1)

    return entropy

def extract_strings(self):
    """Extract strings from WASM binary"""

    try:
        result = subprocess.run(['strings', str(self.wasm_file)], 
                              capture_output=True, text=True)

        if result.returncode == 0:
            strings = [s.strip() for s in result.stdout.split('\n') if len(s.strip()) > 3]
            self.analysis_results['strings'] = strings[:100]  # Limit to first 100

            # Check for suspicious strings
            suspicious_patterns = [
                r'password', r'secret', r'key', r'token', r'auth',
                r'eval\(', r'document\.', r'window\.', r'\.exe',
                r'cmd\.exe', r'powershell', r'bash', r'sh\s'
            ]

            for string in strings:
                for pattern in suspicious_patterns:
                    if re.search(pattern, string, re.IGNORECASE):
                        self.analysis_results['suspicious_indicators'].append(
                            f"Suspicious string: {string}"
                        )

    except FileNotFoundError:
        print("Warning: strings command not found")

def analyze_functions(self):
    """Analyze WASM functions"""

    try:
        # Get function information
        result = subprocess.run(['wasm-objdump', '-j', 'code', str(self.wasm_file)], 
                              capture_output=True, text=True)

        if result.returncode == 0:
            functions = []
            current_function = None

            for line in result.stdout.split('\n'):
                if 'func[' in line:
                    if current_function:
                        functions.append(current_function)
                    current_function = {'name': line.strip(), 'instructions': []}
                elif current_function and line.strip():
                    current_function['instructions'].append(line.strip())

            if current_function:
                functions.append(current_function)

            self.analysis_results['functions'] = functions

    except FileNotFoundError:
        pass

def analyze_imports_exports(self):
    """Analyze imports and exports"""

    try:
        # Analyze imports
        result = subprocess.run(['wasm-objdump', '-j', 'import', str(self.wasm_file)], 
                              capture_output=True, text=True)

        if result.returncode == 0:
            imports = []
            for line in result.stdout.split('\n'):
                if 'import[' in line or 'func' in line or 'memory' in line:
                    imports.append(line.strip())

            self.analysis_results['imports'] = imports

        # Analyze exports
        result = subprocess.run(['wasm-objdump', '-j', 'export', str(self.wasm_file)], 
                              capture_output=True, text=True)

        if result.returncode == 0:
            exports = []
            for line in result.stdout.split('\n'):
                if 'export[' in line or 'func' in line:
                    exports.append(line.strip())

            self.analysis_results['exports'] = exports

    except FileNotFoundError:
        pass

def generate_report(self):
    """Generate analysis report"""

    report_file = self.wasm_file.with_suffix('.analysis.json')

    with open(report_file, 'w') as f:
        json.dump(self.analysis_results, f, indent=2)

    print(f"Analysis report saved to: {report_file}")

    # Print summary
    print("\n=== WASM Analysis Summary ===")
    print(f"File: {self.wasm_file}")
    print(f"Size: {self.analysis_results['file_info']['size']} bytes")
    print(f"SHA256: {self.analysis_results['file_info']['sha256']}")
    print(f"Valid WASM: {self.analysis_results['file_info']['valid_magic']}")

    if self.analysis_results['security']['issues']:
        print(f"\nSecurity Issues ({len(self.analysis_results['security']['issues'])}):")
        for issue in self.analysis_results['security']['issues']:
            print(f"  - {issue}")

    if self.analysis_results['suspicious_indicators']:
        print(f"\nSuspicious Indicators ({len(self.analysis_results['suspicious_indicators'])}):")
        for indicator in self.analysis_results['suspicious_indicators'][:10]:
            print(f"  - {indicator}")

    print(f"\nFunctions: {len(self.analysis_results['functions'])}")
    print(f"Imports: {len(self.analysis_results['imports'])}")
    print(f"Exports: {len(self.analysis_results['exports'])}")
    print(f"Strings: {len(self.analysis_results['strings'])}")

def main(): if len(sys.argv) != 2: print("Usage: python wasm_analyzer.py ") sys.exit(1)

wasm_file = sys.argv[1]

if not os.path.exists(wasm_file):
    print(f"Error: File {wasm_file} not found")
    sys.exit(1)

analyzer = WasmAnalyzer(wasm_file)
results = analyzer.analyze()

if name == "main": main() ```_

Batch WASM AnalyseScript

```bash

!/bin/bash

Batch WASM analysis script

WASM_DIR="$1" OUTPUT_DIR="$2"

| if [ -z "$WASM_DIR" ] | | [ -z "$OUTPUT_DIR" ]; then | echo "Usage: $0 " exit 1 fi

mkdir -p "$OUTPUT_DIR"

echo "Starting batch WASM analysis..." echo "Input directory: $WASM_DIR" echo "Output directory: $OUTPUT_DIR"

Find all WASM files

find "$WASM_DIR" -name "*.wasm" -type f | while read -r wasm_file; do echo "Processing: $wasm_file"

# Create output subdirectory
rel_path=$(realpath --relative-to="$WASM_DIR" "$wasm_file")
output_subdir="$OUTPUT_DIR/$(dirname "$rel_path")"
mkdir -p "$output_subdir"

# Base name for output files
base_name=$(basename "$wasm_file" .wasm)
output_base="$output_subdir/$base_name"

# Basic analysis
echo "  - Basic analysis..."
wasm-objdump -h "$wasm_file" > "${output_base}_headers.txt" 2>/dev/null
wasm-objdump -x "$wasm_file" > "${output_base}_details.txt" 2>/dev/null

# Disassembly
echo "  - Disassembly..."
wasm-objdump -d "$wasm_file" > "${output_base}_disasm.txt" 2>/dev/null

# Decompilation
echo "  - Decompilation..."
wasm-decompile "$wasm_file" -o "${output_base}_decompiled.c" 2>/dev/null

# WAT conversion
echo "  - WAT conversion..."
wasm2wat "$wasm_file" -o "${output_base}.wat" 2>/dev/null

# String extraction
echo "  - String extraction..."
strings "$wasm_file" > "${output_base}_strings.txt" 2>/dev/null

# Security analysis
echo "  - Security analysis..."
{
    echo "=== IMPORTS ==="
    wasm-objdump -j import "$wasm_file" 2>/dev/null
    echo -e "\n=== EXPORTS ==="
    wasm-objdump -j export "$wasm_file" 2>/dev/null
    echo -e "\n=== SUSPICIOUS STRINGS ==="

| strings "$wasm_file" | grep -E -i "(eval | document | window | fetch | xhr | websocket | crypto | password | secret | key)" 2>/dev/null | } > "${output_base}_security.txt"

# File hash
echo "  - Computing hashes..."
{
    echo "MD5: $(md5sum "$wasm_file" | cut -d' ' -f1)"
    echo "SHA1: $(sha1sum "$wasm_file" | cut -d' ' -f1)"
    echo "SHA256: $(sha256sum "$wasm_file" | cut -d' ' -f1)"
    echo "Size: $(stat -c%s "$wasm_file") bytes"
} > "${output_base}_hashes.txt"

echo "  - Complete!"

done

Generate summary report

echo "Generating summary report..." { echo "WASM Batch Analysis Summary" echo "==========================" echo "Analysis Date: $(date)" echo "Input Directory: $WASM_DIR" echo "Output Directory: $OUTPUT_DIR" echo ""

total_files=$(find "$WASM_DIR" -name "*.wasm" -type f | wc -l)
echo "Total WASM files analyzed: $total_files"

echo ""
echo "File Sizes:"

| find "$WASM_DIR" -name "*.wasm" -type f -exec stat -c"%s %n" {} \; | sort -n | tail -10 |

echo ""
echo "Most Common Imports:"

| find "$OUTPUT_DIR" -name "*_security.txt" -exec grep -h "import[" {} \; | sort | uniq -c | sort -nr | head -10 |

echo ""
echo "Most Common Exports:"

| find "$OUTPUT_DIR" -name "*_security.txt" -exec grep -h "export[" {} \; | sort | uniq -c | sort -nr | head -10 |

} > "$OUTPUT_DIR/analysis_summary.txt"

echo "Batch analysis complete!" echo "Summary report: $OUTPUT_DIR/analysis_summary.txt" ```_

Integration mit Reverse Engineering Workflows

WASM in Malware Analyse Pipeline

```python

!/usr/bin/env python3

""" WASM Malware Analysis Pipeline Integrates WASM analysis into broader malware analysis workflow """

import os import json import subprocess import tempfile from pathlib import Path

class WasmMalwareAnalyzer: def init(self, sample_path): self.sample_path = Path(sample_path) self.temp_dir = Path(tempfile.mkdtemp()) self.analysis_results = {}

def analyze_sample(self):
    """Analyze WASM sample for malware indicators"""

    # Extract WASM from various containers
    wasm_files = self.extract_wasm_files()

    if not wasm_files:
        print("No WASM files found in sample")
        return

    # Analyze each WASM file
    for wasm_file in wasm_files:
        print(f"Analyzing WASM file: {wasm_file}")

        analysis = {
            'static_analysis': self.static_analysis(wasm_file),
            'behavioral_analysis': self.behavioral_analysis(wasm_file),
            'threat_assessment': self.threat_assessment(wasm_file)
        }

        self.analysis_results[str(wasm_file)] = analysis

    # Generate IOCs
    self.generate_iocs()

    # Create YARA rules
    self.create_yara_rules()

    return self.analysis_results

def extract_wasm_files(self):
    """Extract WASM files from various containers"""

    wasm_files = []

    # Direct WASM file
    if self.sample_path.suffix == '.wasm':
        return [self.sample_path]

    # Extract from HTML/JS files
    if self.sample_path.suffix in ['.html', '.htm', '.js']:
        wasm_files.extend(self.extract_from_web_files())

    # Extract from archives
    if self.sample_path.suffix in ['.zip', '.tar', '.gz']:
        wasm_files.extend(self.extract_from_archives())

    # Search for embedded WASM
    wasm_files.extend(self.find_embedded_wasm())

    return wasm_files

def extract_from_web_files(self):
    """Extract WASM from HTML/JS files"""

    wasm_files = []

    with open(self.sample_path, 'r', encoding='utf-8', errors='ignore') as f:
        content = f.read()

    # Look for WASM loading patterns
    patterns = [
        r'fetch\(["\'](https://[^"\']*\.wasm)["\']',
        r'WebAssembly\.instantiateStreaming\([^,]*["\'](https://[^"\']*\.wasm)["\']',
        r'new\s+WebAssembly\.Module\([^)]*["\'](https://[^"\']*\.wasm)["\']'
    ]

    import re
    for pattern in patterns:
        matches = re.findall(pattern, content)
        for match in matches:
            wasm_path = self.sample_path.parent / match
            if wasm_path.exists():
                wasm_files.append(wasm_path)

    return wasm_files

def extract_from_archives(self):
    """Extract WASM from archive files"""

    wasm_files = []
    extract_dir = self.temp_dir / "extracted"
    extract_dir.mkdir(exist_ok=True)

    try:
        if self.sample_path.suffix == '.zip':
            subprocess.run(['unzip', '-q', str(self.sample_path), '-d', str(extract_dir)])
        elif self.sample_path.suffix in ['.tar', '.gz']:
            subprocess.run(['tar', '-xf', str(self.sample_path), '-C', str(extract_dir)])

        # Find WASM files in extracted content
        for wasm_file in extract_dir.rglob('*.wasm'):
            wasm_files.append(wasm_file)

    except subprocess.CalledProcessError:
        pass

    return wasm_files

def find_embedded_wasm(self):
    """Find embedded WASM in binary files"""

    wasm_files = []

    with open(self.sample_path, 'rb') as f:
        content = f.read()

    # Look for WASM magic bytes
    wasm_magic = b'\x00asm'
    offset = 0

    while True:
        pos = content.find(wasm_magic, offset)
        if pos == -1:
            break

        # Extract potential WASM module
        wasm_data = self.extract_wasm_module(content, pos)
        if wasm_data:
            wasm_file = self.temp_dir / f"embedded_{pos:08x}.wasm"
            with open(wasm_file, 'wb') as f:
                f.write(wasm_data)
            wasm_files.append(wasm_file)

        offset = pos + 4

    return wasm_files

def extract_wasm_module(self, data, start_pos):
    """Extract complete WASM module from binary data"""

    if start_pos + 8 > len(data):
        return None

    # Check magic and version
    if data[start_pos:start_pos+4] != b'\x00asm':
        return None

    version = int.from_bytes(data[start_pos+4:start_pos+8], 'little')
    if version != 1:
        return None

    # Parse sections to find module end
    pos = start_pos + 8

    while pos < len(data):
        if pos + 1 > len(data):
            break

        section_id = data[pos]
        pos += 1

        # Parse LEB128 size
        size, size_bytes = self.parse_leb128(data, pos)
        if size is None:
            break

        pos += size_bytes

        if pos + size > len(data):
            break

        pos += size

        # If we've read all standard sections, we're done
        if section_id == 0:  # Custom section at end
            break

    return data[start_pos:pos]

def parse_leb128(self, data, pos):
    """Parse LEB128 encoded integer"""

    result = 0
    shift = 0
    size = 0

    while pos + size < len(data):
        byte = data[pos + size]
        size += 1

        result |= (byte & 0x7f) << shift
        shift += 7

        if (byte & 0x80) == 0:
            break

        if size > 5:  # Prevent infinite loop
            return None, 0

    return result, size

def static_analysis(self, wasm_file):
    """Perform static analysis on WASM file"""

    analysis = {
        'file_info': {},
        'structure': {},
        'suspicious_indicators': [],
        'capabilities': []
    }

    # File information
    stat = wasm_file.stat()
    with open(wasm_file, 'rb') as f:
        content = f.read()

    analysis['file_info'] = {
        'size': stat.st_size,
        'sha256': hashlib.sha256(content).hexdigest(),
        'entropy': self.calculate_entropy(content)
    }

    # Analyze imports for capabilities
    try:
        result = subprocess.run(['wasm-objdump', '-j', 'import', str(wasm_file)], 
                              capture_output=True, text=True)

        if result.returncode == 0:
            imports = result.stdout

            # Check for suspicious capabilities
            if 'fetch' in imports or 'XMLHttpRequest' in imports:
                analysis['capabilities'].append('network_access')
                analysis['suspicious_indicators'].append('Network access capability')

            if 'document' in imports or 'window' in imports:
                analysis['capabilities'].append('dom_manipulation')
                analysis['suspicious_indicators'].append('DOM manipulation capability')

            if 'eval' in imports or 'Function' in imports:
                analysis['capabilities'].append('code_execution')
                analysis['suspicious_indicators'].append('Dynamic code execution capability')

            if 'crypto' in imports:
                analysis['capabilities'].append('cryptography')

            if 'Worker' in imports:
                analysis['capabilities'].append('worker_threads')
                analysis['suspicious_indicators'].append('Worker thread capability')

    except FileNotFoundError:
        pass

    # Check for obfuscation
    if analysis['file_info']['entropy'] > 7.5:
        analysis['suspicious_indicators'].append('High entropy (possible obfuscation)')

    return analysis

def behavioral_analysis(self, wasm_file):
    """Perform behavioral analysis using sandboxed execution"""

    analysis = {
        'execution_trace': [],
        'network_activity': [],
        'file_operations': [],
        'api_calls': []
    }

    # Create instrumented environment
    instrumented_js = self.create_instrumented_environment()

    # Run WASM in controlled environment
    try:
        with tempfile.NamedTemporaryFile(mode='w', suffix='.js', delete=False) as f:
            f.write(instrumented_js)
            js_file = f.name

        # Execute with Node.js
        result = subprocess.run(['node', js_file, str(wasm_file)], 
                              capture_output=True, text=True, timeout=30)

        if result.returncode == 0:
            # Parse execution trace
            for line in result.stdout.split('\n'):
                if line.startswith('TRACE:'):
                    analysis['execution_trace'].append(line[6:])
                elif line.startswith('NETWORK:'):
                    analysis['network_activity'].append(line[8:])
                elif line.startswith('API:'):
                    analysis['api_calls'].append(line[4:])

        os.unlink(js_file)

    except (subprocess.TimeoutExpired, FileNotFoundError):
        analysis['execution_trace'].append('Execution timeout or Node.js not available')

    return analysis

def create_instrumented_environment(self):
    """Create instrumented JavaScript environment for WASM execution"""

    return """

const fs = require('fs'); const path = require('path');

// Instrumented WebAssembly implementation const originalInstantiate = WebAssembly.instantiate; WebAssembly.instantiate = async function(source, imports) { console.log('TRACE: WebAssembly.instantiate called');

// Instrument imports
if (imports) {
    for (const [module, funcs] of Object.entries(imports)) {
        for (const [name, func] of Object.entries(funcs)) {
            if (typeof func === 'function') {
                imports[module][name] = function(...args) {
                    console.log(`API: ${module}.${name}(${args.join(', ')})`);
                    return func.apply(this, args);
                };
            }
        }
    }
}

const result = await originalInstantiate.call(this, source, imports);

// Instrument exports
if (result.instance && result.instance.exports) {
    for (const [name, func] of Object.entries(result.instance.exports)) {
        if (typeof func === 'function') {
            result.instance.exports[name] = function(...args) {
                console.log(`TRACE: Calling exported function ${name}(${args.join(', ')})`);
                return func.apply(this, args);
            };
        }
    }
}

return result;

};

// Instrument fetch for network monitoring global.fetch = function(url, options) { console.log(NETWORK: fetch(${url})); return Promise.reject(new Error('Network access blocked in sandbox')); };

// Load and run WASM file async function runWasm() { try { const wasmFile = process.argv[2]; if (!wasmFile) { console.error('Usage: node script.js '); return; }

    const wasmBuffer = fs.readFileSync(wasmFile);
    console.log(`TRACE: Loading WASM file: ${wasmFile} (${wasmBuffer.length} bytes)`);

    const wasmModule = await WebAssembly.instantiate(wasmBuffer, {
        env: {
            console_log: (ptr, len) => console.log('TRACE: console.log called'),
            memory: new WebAssembly.Memory({ initial: 256, maximum: 256 })
        }
    });

    console.log('TRACE: WASM module loaded successfully');

    // Try to call main function if it exists
    if (wasmModule.instance.exports.main) {
        console.log('TRACE: Calling main function');
        wasmModule.instance.exports.main();
    }

} catch (error) {
    console.log(`TRACE: Error: ${error.message}`);
}

}

runWasm(); """

def threat_assessment(self, wasm_file):
    """Assess threat level of WASM file"""

    threat_score = 0
    threat_indicators = []

    # Get analysis results
    static = self.analysis_results.get(str(wasm_file), {}).get('static_analysis', {})
    behavioral = self.analysis_results.get(str(wasm_file), {}).get('behavioral_analysis', {})

    # Score based on capabilities
    capabilities = static.get('capabilities', [])

    if 'network_access' in capabilities:
        threat_score += 30
        threat_indicators.append('Network access capability')

    if 'code_execution' in capabilities:
        threat_score += 40
        threat_indicators.append('Dynamic code execution')

    if 'dom_manipulation' in capabilities:
        threat_score += 20
        threat_indicators.append('DOM manipulation')

    if 'worker_threads' in capabilities:
        threat_score += 15
        threat_indicators.append('Worker thread creation')

    # Score based on suspicious indicators
    suspicious = static.get('suspicious_indicators', [])
    threat_score += len(suspicious) * 10

    # Score based on entropy
    entropy = static.get('file_info', {}).get('entropy', 0)
    if entropy > 7.5:
        threat_score += 25
        threat_indicators.append('High entropy (obfuscation)')

    # Determine threat level
    if threat_score >= 80:
        threat_level = 'HIGH'
    elif threat_score >= 50:
        threat_level = 'MEDIUM'
    elif threat_score >= 20:
        threat_level = 'LOW'
    else:
        threat_level = 'MINIMAL'

    return {
        'threat_level': threat_level,
        'threat_score': threat_score,
        'threat_indicators': threat_indicators
    }

def generate_iocs(self):
    """Generate Indicators of Compromise"""

    iocs = {
        'file_hashes': [],
        'network_indicators': [],
        'behavioral_indicators': []
    }

    for wasm_file, analysis in self.analysis_results.items():
        # File hash IOCs
        file_info = analysis.get('static_analysis', {}).get('file_info', {})
        if 'sha256' in file_info:
            iocs['file_hashes'].append(file_info['sha256'])

        # Network IOCs
        network_activity = analysis.get('behavioral_analysis', {}).get('network_activity', [])
        iocs['network_indicators'].extend(network_activity)

        # Behavioral IOCs
        capabilities = analysis.get('static_analysis', {}).get('capabilities', [])
        iocs['behavioral_indicators'].extend(capabilities)

    # Save IOCs
    ioc_file = self.temp_dir / 'iocs.json'
    with open(ioc_file, 'w') as f:
        json.dump(iocs, f, indent=2)

    print(f"IOCs saved to: {ioc_file}")
    return iocs

def create_yara_rules(self):
    """Create YARA rules for detected threats"""

    yara_rules = []

    for wasm_file, analysis in self.analysis_results.items():
        threat = analysis.get('threat_assessment', {})

        if threat.get('threat_level') in ['HIGH', 'MEDIUM']:
            rule_name = f"WASM_Malware_{Path(wasm_file).stem}"

            rule = f"""

rule {rule_name} {{ meta: description = "Suspicious WASM file detected" threat_level = "{threat.get('threat_level')}" threat_score = {threat.get('threat_score')}

strings:
    $magic = {{ 00 61 73 6D }}  // WASM magic

condition:
    $magic at 0

}} """ yara_rules.append(rule)

    # Save YARA rules
    if yara_rules:
        yara_file = self.temp_dir / 'wasm_malware.yar'
        with open(yara_file, 'w') as f:
            f.write('\n'.join(yara_rules))

        print(f"YARA rules saved to: {yara_file}")

    return yara_rules

def main(): if len(sys.argv) != 2: print("Usage: python wasm_malware_analyzer.py ") sys.exit(1)

sample_file = sys.argv[1]

if not os.path.exists(sample_file):
    print(f"Error: File {sample_file} not found")
    sys.exit(1)

analyzer = WasmMalwareAnalyzer(sample_file)
results = analyzer.analyze_sample()

# Print summary
print("\n=== WASM Malware Analysis Summary ===")
for wasm_file, analysis in results.items():
    threat = analysis.get('threat_assessment', {})
    print(f"\nFile: {wasm_file}")
    print(f"Threat Level: {threat.get('threat_level', 'UNKNOWN')}")
    print(f"Threat Score: {threat.get('threat_score', 0)}")

    indicators = threat.get('threat_indicators', [])
    if indicators:
        print("Threat Indicators:")
        for indicator in indicators:
            print(f"  - {indicator}")

if name == "main": main() ```_

Ressourcen und Dokumentation

Offizielle Mittel

Lernressourcen

Sicherheitsforschung

Werkzeuge und Anwendungen

  • Wasmer - Universal WebAssembly Laufzeit
  • Warmtime - Standalone WebAssembly Laufzeit
  • wasm-pack - Rust to WebAssembly Workflow
  • Emscripten - C/C++ zu WebAssembly Compiler