WebAssembly 동적 분석 프레임워크 (Wasabi) 설치

choehojun·2023년 6월 1일
1

WebAssembly

목록 보기
3/4

Wasabi란?

Wasabi 는 WebAssembly 파일의 동적 분석을 위한 프레임워크로, 동작 원리는 아래 그림과 같다.

이미지 출처 : http://wasabi.software-lab.org/

먼저, Wasabi의 Javascript API를 이용하여 분석을 위한 javascript 파일을 작성하고, 분석하고 싶은 .wasm 파일에 대해 Wasabi 를 실행하면, 정적으로 binary instrumentation을 해서 Wasabi의 analysis hook가 추가된 새로운 .wasm 파일과 프로그램에서 정적으로 추출된 정보와, 프로그램과 analysis 파일을 연결하기 위한 glue code가 있는 새로운 javascript 파일이 생성된다. 그리고, 기존에 .wasm 파일이 실행되던 html 파일의 script로 분석을 위해 작성한 javascript 파일과 Wasabi 를 통해 생성된 javascript 파일을 추가하면, 원하는 내용을 런타임에 동적으로 분석할 수 있게 된다. 더 자세한 내용은 Wasabi 논문Wasabi Documentation을 참고하면 알 수 있다.

Wasabi 설치 및 튜토리얼

설치 과정은 Wasabi github를 참고하였다.

Wasabi 설치에 앞서, 다음과 같은 라이브러리와 tool들이 설치되어 있어야 한다고 한다.

모두 설치하였다면, 아래의 command line을 실행하여 wasabi를 설치해본다.

$ git clone https://github.com/danleh/wasabi.git
$ cd wasabi/crates/wasabi
# Rust package manage인 cargo를 이용하여 wasabi를 설치한다.
$ cargo install --path .

그리고, wasabi 커맨드를 입력해서 다음과 같은 메시지가 뜨는지 확인한다.

$ wasabi
Error: expected at least one argument
Usage: wasabi <input_wasm_file> [<output_dir>]

만약, wasabi: Command not found의 에러가 뜬다면 아래 명령어를 통하여 ~/.bashrcwasabi 경로를 저장한 후, 적용한다.

$ echo 'export PATH=$PATH:/home/directory/.cargo/bin' >> ~/.bashrc
$ source ~/.bashrc

wasabi가 정상 동작하는지 확인하기 위해서 튜토리얼을 진행해보았는데, 직접 .wat 파일을 작성하여 .wasm 파일로 변환하는 방법도 있지만, 나는 emscripten을 이용하여 C 파일을 .wasm 파일로 컴파일하여 실행하는 방법을 사용하였다.

먼저, 아래와 같은 hello.c 파일을 작성한다.

#include <stdio.h>
int main(int argc, char const *argv[]) {
    printf("Hello, world!\n");
    return 0;
}

이후, emscripten을 이용해 hello.c.wasm 파일로 컴파일하고, 웹 서버를 8080 포트에서 실행해본다.

$ emcc hello.c -o hello.html
# wasm 파일과 함께 js파일과 html 파일이 생성되었는지 확인한다.
$ ls
hello.c  hello.html  hello.js  hello.wasm
$ emrun --no_browser --port 8080 .

이후, 브라우저에서 http://localhost:8080/hello.html 주소에 접속하여 화면에 Hello, world!가 출력되는지 확인한다. 만약 출력되고 있다면, 정상적으로 wasm 파일로 컴파일되었다는 것을 알 수 있다.

그리고, wasabi를 통한 동적 분석이 정상적으로 작동되는 지 확인해보았다.

$ wasabi hello.wasm
inserted 129 low-level hooks

# binary instrumentation 전의 hello.wasm 파일의 이름을 바꾸고, wasabi를 통해 생성된 hello.wasabi.js와 hello.wasm을 현재 디렉토리에 복사한다.
$ mv hello.wasm hello.orig.wasm
$ cp out/* .
$ ls
hello.html  hello.orig.wasm  hello.wasm hello.c  hello.js    hello.wasabi.js

# analysis 파일은 wasabi repository에 있는 example analysis 파일 중 하나를 사용하였다.
$ cp wasabi/examples/analyses/log-all.js .

# 이후, html 파일에 wasabi를 통해 생성된 js 파일과 analysis js 파일을 script 태그로 추가한다.
$ sed -i '/<script async type="text\/javascript" src="hello.js"><\/script>/a <script src="hello.wasabi.js"></script>' hello.html
$ sed -i '/<script src="hello.wasabi.js"><\/script>/a <script src="log-all.js"></script>' hello.html

# 다시 한번 웹 서버를 실행해본다.
emrun --no_browser --port 8080 .

웹 서버 실행 이후, 다시 http://localhost:8080/hello.html 주소에 접속해보고, javascript 콘솔의 출력을 확인해본다.

그러면, 다음과 같이 분석 결과가 콘솔에 정상적으로 출력되는 것을 확인할 수 있었다. 따라서, wasbi 가 정상적으로 설치되었고, 실행된다는 것을 알 수 있었다.

Wasabi 예제 파일을 통한 Taint Analysis 실행

이번에는 wasabi repository에서 제공하는 예제 analysis 파일과 C 파일을 통하여 taint analysis를 해보고자 한다.

먼저, wasabi/examples/taint/c 디렉토리를 복사한다.

$ cp -r wasabi/examples/taint/c .

그리고, wasabi/examples/analyses 디렉토리의 taint.js 파일을 c 디렉토리에 복사해준다. 이 js 파일은 taint analysis를 수행하는 내용이 담긴 analysis 파일이다.

$ cp wasabi/examples/analyses/taint.js c/

그리고, c 디렉토리의 buildBrowserTest.sh 파일의 인자로 C 파일과 analysis 파일을 넘겨주면, 튜토리얼에서의 컴파일, wasabi 실행, html 파일에 script 태그 추가 등의 과정을 모두 자동으로 처리해준다. C 파일은 디렉토리에 있는 C 파일들 중 하나를 선택하였다.

$ cd c
# buildBrowserTest.sh를 실행 가능하게 만든다.
$ chmod +x buildBrowserTest.sh
$ ./buildBrowserTest.sh test_propagate_via_call.c taint.js 

그리고, emrun --no_browser --port 8080 .을 통해 웹 서버를 실행하고, http://localhost:8080/test_propagate_via_call.html에 접속하여 콘솔의 출력을 확인해본다.

그랬더니, source function과 sink function을 찾지 못했다는 에러가 뜨는 것을 확인할 수 있다. 그 이유를 찾기 위해 taint.js 파일을 확인해보았다.

    /*
     * Taint policy: sources and sink
     */
    function findSourceSinkFcts() {
        let sourceFctIdx = -1;
        let sinkFctIdx = -1;
        for (let i = 0; i < Wasabi.module.info.functions.length; i++) {
            const fct = Wasabi.module.info.functions[i];
            if (fct.export === "taint_source" || fct.export === "_markSource") {
                sourceFctIdx = i;
            }
            if (fct.export === "taint_sink" || fct.export === "_sink") {
                sinkFctIdx = i;
            }
        }
        if (sourceFctIdx === -1) console.log("Warning: No exported source function found.");
        if (sinkFctIdx === -1) console.log("Warning: No exported sink function found.");
        return {sourceFctIdx:sourceFctIdx, sinkFctIdx:sinkFctIdx};
    }

보다시피 taint.js 파일에서는 source function과 sink function을 export된 function name을 가지고 찾는데, 현재 function name과 if문의 function name이 일치하지 않아 발생한 문제로 보였다. 이를 디버깅해보니, fct.export는 array object이고, 실제 function name은 fct.export[0]에 담겨있어 생긴 문제였다. 또, C파일에서의 sink function 이름과 source function 이름이 각각 markSourcesink로 export 되는데, 현재 taint.js에서는 다른 이름을 사용하고 있었다. 따라서, 나는 taint.js 파일의 findSourceSinkFcts()를 아래와 같이 수정하였다.

    /*
     * Taint policy: sources and sink
     */
    function findSourceSinkFcts() {
        let sourceFctIdx = -1;
        let sinkFctIdx = -1;
        for (let i = 0; i < Wasabi.module.info.functions.length; i++) {
            const fct = Wasabi.module.info.functions[i];
            if (fct.export[0] === "taint_source" || fct.export[0] === "markSource") {
                sourceFctIdx = i;
            }
            if (fct.export[0] === "taint_sink" || fct.export[0] === "sink") {
                sinkFctIdx = i;
            }
        }
        if (sourceFctIdx === -1) console.log("Warning: No exported source function found.");
        if (sinkFctIdx === -1) console.log("Warning: No exported sink function found.");
        return {sourceFctIdx:sourceFctIdx, sinkFctIdx:sinkFctIdx};
    }

그리고, 다시 buildBrowserTest.sh 파일을 실행시켜 컴파일과 wasabi 실행을 다시 진행한 이후, 웹 서버를 실행시켜 콘솔의 출력 결과를 재확인해보았다.

$ ./buildBrowserTest.sh test_propagate_via_call.c taint.js 
$ emrun --no_browser --port 8080 .

그랬더니, 위 그림과 같이 tainted된 value가 어느 위치에 도달하는지 확인할 수 있었다.

Taint analysis 수행 결과 요약

이렇듯 wasabi를 이용하면 taint analysis를 런타임에 동적으로 수행할 수 있었는데, 다만 이번에 이용한 예제 analysis 파일은 function name을 이용하여 taint analysis를 수행하여 우리가 원본 소스 파일을 알 수 없고, function name을 알 수 없는 .wasm 파일에 대해서는 taint analysis를 수행할 수 없을 것이라고 생각된다.

참고 문헌

profile
보안 전공을 희망하는 학부생

0개의 댓글