コンテンツへスキップ

WebAssemblyファイルをデコンパイルする

by : 2019/04/16

WebAssemblyはあらかじめコンパイルされているのでJavaScriptのように実行時にコードをパースする必要がなく、高速に動作します。WebAssemblyのコードはバイナリデータになっているので処理を隠蔽できているように見えますが、デコンパイルを行うことで人間が読める形に変換できます。

今回はwabtを使ってWebAssemblyのデコンパイルを行ってみます。

元になるコード

今回はGoを使っています。一番簡単なコードです。

package main
func main() {
println("Hello, wasm!")
}

view raw
index.go
hosted with ❤ by GitHub

WebAssemblyにする

このコードをコンパイルしてWebAssemblyにします。

$ GOOS=js GOARCH=wasm go build -o test.wasm main.go

view raw
index.
hosted with ❤ by GitHub

そしてできあがるのが test.wasm です。このファイルは1.3MBありました。

デコンパイルする

ではここからデコンパイルします。その際に使うのがwabtです。WebAssembly用のツールが各種含まれています。ビルド時にはcmakeが必要です。

$ git clone –recursive https://github.com/WebAssembly/wabt
$ cd wabt
$ make

view raw
index.
hosted with ❤ by GitHub

そして生成されるwasm2watコマンドを使ってデコンパイルします。

bin/wasm2wat test.wasm > test.wat

view raw
index.
hosted with ❤ by GitHub

デコンパイルすると25.8MBになりました。かなり肥大化しているのが分かります。

コードを見る

デコンパイルされたコードは、WebAssemblyのテキスト版です。

(module
(type (;0;) (func (result i32)))
(type (;1;) (func (param i32)))
(type (;2;) (func (param i64 i64 i64 i64) (result i64)))
(type (;3;) (func (param i32 i32 i32) (result i32)))
(type (;4;) (func (param i64 i64 i64) (result i64)))
(type (;5;) (func (param i64 i64)))
(type (;6;) (func (param i32 i32)))
(type (;7;) (func (param i32 i32 i32)))
(type (;8;) (func (param i64 i64) (result i64)))
(type (;9;) (func (param f64) (result i64)))
(import "go" "debug" (func (;0;) (type 1)))
(import "go" "runtime.wasmExit" (func (;1;) (type 1)))
:

view raw
index.
hosted with ❤ by GitHub

その中に Hello, wasm という文字列も入っています。

byte block (GC sweep waitHello, wasm!\0abad map statefatal error:

view raw
index.
hosted with ❤ by GitHub

つまりWebAssemblyでバイナリ化していたとしても、任意の処理がどこで、どのように行われているか、探そうと思えば探し出せると言うことです。


WebAssemblyでコードをコンパイルしたとしても、100%安全という訳ではありません。Javaと同レベルくらいに考える方が良いかもしれません。隠し方は幾つかありますので、なるべく分かりづらくなる方法を選ぶべきで、安直にキーなどをコードに書かない方が良さそうです。

From → HTML5

コメントは受け付けていません。

%d人のブロガーが「いいね」をつけました。