본문 바로가기

Testing Tools

klee 사용해보기

     Concolic Testing(Concrete + Symbolic : https://en.wikipedia.org/wiki/Concolic_testing)를 지원하는 오픈소스 프로젝트를 찾다 klee란 프로그램을 찾았다. (CREST란 것도 있다.) LLVM(http://llvm.org/)을 사용하여, 좀 더 정확한 분석을 수행하며, 홈페이지에서 제공하는 튜토리얼(https://klee.github.io/)을 진행해보았다.


1. klee 설치

     리눅스 머신에 klee를 직접 설치하는 방법도 있지만, 얼마 전에 docker(https://www.docker.com/)를 설치하였기에 해당 이미지가 있는지 검색해 보았다. Linux가 아니라, Mac 또는 Windows를 사용하고 있다면, Docker Toolbox(https://www.docker.com/products/docker-toolbox)를 사용할 수 있다.(현재 Windows 10을 사용하고 있다.)


docker search klee



     klee를 사용할 수 있는 docker 이미지들이 있었으며, 이 중 klee/klee 를 설치하였다.


docker pull klee/klee



     klee/klee 이미지를 다 받았다면, container를 하나 실행해 보자. 이름은 klee_test 라고 지었으며, stack=-1:-1 옵션을 주어 container에서 stack 크기를 무제한으로 설정하였다.


docker run -i -t --name klee_test --ulimit='stack=-1:-1' klee/klee /bin/bash



     container가 실행되었다. 간단한 명령을 주어 container가 실행됨을 확인한다.


     설치된, klee 와 llvm의 버전을 확인해 보자.


klee --version

clang --version



2. 예제 구동

2.1. 예제 파일

     아래의 예제(divbyzero.c)를 사용한다. 일부러 0으로 나누기 연산을 하도록 만들었다.

#include 
#include 

int divide(int a, int b)
{
        if ( b > 0 )
                return a % b;
        else
                return a % b * -1;
}

int main(int argn, char *argv[])
{
        int a;
        int b;
        int c;

        klee_make_symbolic(&a, sizeof(a), "a");
        klee_make_symbolic(&b, sizeof(b), "b");

        c = divide(a, b);

        return c;
}


     18 ~ 19 Line : Symbolic 분석을 수행할 변수를 지정해준다.

     klee_make_symbolic

        * 첫 번째 인자 : 대상 변수

        * 두 번째 인자 : 대상 변수 크기

        * 세 번째 인자 : Symbol의 이름


2.2. 컴파일


clang -I ~/klee_src/include/ -emit-llvm -c -g divbyzero.c


     컴파일이 끝나면 llvm 상에서 동작할 수 있는 divbyzero.bc 파일이 생성된다.


2.3. 분석

     klee 명령어로 분석을 수행한다.


klee --libc=uclibc --posix-runtime divbyzero.bc


     --libc 명령이 없이 libc 함수를 사용하면 제대로 인식을 못할 때가 있다.



     KLEE: ERROR: /home/klee/work/divbyzero/divbyzero.c:7: divide by zero

     0으로 나누기 오류가 발생하였음을 알 수가 있다.


2.4. 테스트 케이스 분석

     klee로 분석이 완료되면, 분석 횟수에 따라 하부에 klee-out-N 의 폴더가 생긴다. N에 수행한 횟수만큼 숫자가 증가한다. 가장 최신에 수행한 결과는 klee-last로 접근할 수 있다. 해당 폴더에는 아래와 같은 파일들이 있다.

 


     일단 test로 시작하고, 확장자가 ktest 파일들은 테스트 케이스 파일들이다. 만약 뒤에 err로 끝나는 파일이 있다면, 해당 테스트 케이스를 수행하다 오류가 발생했다는 것을 알 수 있다. 0으로 나누기 오류가 발생한 테스트 케이스가 1번임을 알 수 있다.

     테스트 케이스의 상세정보를 확인하려면, ktest-tool 명령어를 사용한다.


ktest_tool klee-last/test000001.ktest



     Symbol b의 값이 0으로 설정된 테스트 케이스임을 알 수 있다.


     다른 테스트 케이스의 내용도 확인해보자.