심볼릭 환경 사용: 테스트 대상 프로그램에 대한 심볼릭 파일 및 명령줄 인수와 같은 심볼릭 환경을 사용하는 방법에 대한 가이드 및 예제

    KLEE의 기본 명령줄 옵션 개요에서 언급한 대로, KLEE는 심볼릭 환경의 일부로 여러 옵션을 제공한다.

    그러나 이러한 옵션의 사용은 새로운 사용자에게는 종종 이해하기 어렵다.

    이 튜토리얼은 -sym-arg-sym-files 옵션 중 가장 중요한 것으로 생각되는 옵션에 대한 기본 사용 예제를 제공한다.

    -sym-arg 옵션

    우리는 -sym-arg <N> 옵션이 테스트 대상 프로그램에 길이 N의 명령줄 인수를 제공한다는 것을 알 수 있다.

    이 옵션의 변형인 -sym-args <MIN> <MAX> <N>은 적어도 MIN개의 인수와 최대 MAX개의 심볼릭 인수를 제공하며 각각의 최대 길이가 N을 의미한다.

    -sym-arg 옵션을 설명하기 위해 먼저 하드코딩된 비밀번호와 명령줄 인수를 비교하는 다음의 프로그램 소스코드인 password.c를 예로 들겠다.

    #include <stdio.h>
    
    int check_password(char *buf) {
      if (buf[0] == 'h' && buf[1] == 'e' &&
          buf[2] == 'l' && buf[3] == 'l' &&
          buf[4] == 'o')
        return 1;
      return 0;
    }
    
    int main(int argc, char **argv) {
      if (argc < 2)
         return 1;
      
      if (check_password(argv[1])) {
        printf("Password found!\\n");
        return 0;
      }
    
      return 1;
    }

    심볼릭 환경을 활성화하려면, KLEE에 -posix-runtime 옵션을 지정해야 한다.

    password.c의 bitCode를 입력으로 사용하고, -sym-arg 옵션을 다음과 같이 사용하여 KLEE를 실행한다.

    $ clang-11 -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone password.c
    $ klee -posix-runtime password.bc -sym-arg 5
    KLEE: NOTE: Using POSIX model: /snap/klee/6/usr/local/lib/klee/runtime/libkleeRuntimePOSIX64_Debug+Asserts.bca
    KLEE: output directory is "/home/ubuntu/whitehat/IOT-research/klee-study/tutorial_3/klee-out-0"
    KLEE: Using STP solver backend
    KLEE: SAT solver: MiniSat
    warning: Linking two modules of different target triples: 'password.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'klee_range64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'memcpy64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'memset64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'klee_overshift_check64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    KLEE: WARNING: undefined reference to function: printf
    KLEE: WARNING: undefined reference to function: strlen
    KLEE: WARNING: undefined reference to function: strncmp
    KLEE: WARNING ONCE: Alignment of memory from call "malloc" is not modelled. Using alignment of 8.
    KLEE: WARNING ONCE: calling external: syscall(4, 93888559554320, 93888557024960) at klee_src/runtime/POSIX/fd.c:530 12
    KLEE: WARNING ONCE: calling __klee_posix_wrapped_main with extra arguments.
    KLEE: WARNING ONCE: calling external: printf(93888562012160) at password.c:17 5
    Password found!
    
    KLEE: done: total instructions = 2028
    KLEE: done: completed paths = 6
    KLEE: done: partially completed paths = 0
    KLEE: done: generated tests = 6

    보다시피, 명령줄 인수가 심볼릭인 경우, KLEE는 하나의 경로에서 명령줄 인수가 비밀번호와 일치하는 경우를 포함하여 여섯 개의 경로를 실행했다.

    -sym-files 옵션

    옵션 -sym-files <NUM> <N>NUM개의 심볼릭 파일을 생성하며, 첫 번째 파일은 ‘A’로 이름 지어지고 두 번째 파일은 ‘B’로 이름 지어지며 이어서 진행된다.

    각 파일의 크기는 N으로 지정할 수 있다.

    이 옵션의 유사한 옵션으로 -sym-stdin-sym-stdout가 있으며, 각각 표준 입력 및 표준 출력을 심볼릭하게 만든다.

    이제 사용자가 지정한 파일에서 문자열을 읽어 하드 코딩된 비밀번호와 일치하는지 확인하는 password2.c 소스코드인 이름의 패스워드 검사기를 고려해보자.

    파일 이름이 지정되지 않거나 파일을 열 때 오류가 발생하면 표준 입력에서 문자열을 읽는다.

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <unistd.h>
    
    int check_password(int fd) {
      char buf[5];
      if (read(fd, buf, 5) != -1) {
        if (buf[0] == 'h' && buf[1] == 'e' &&
    	buf[2] == 'l' && buf[3] == 'l' &&
    	buf[4] == 'o')
          return 1;
      }
      return 0;
    }
    
    int main(int argc, char **argv) {
      int fd;
    
      if (argc >= 2) {
        if ((fd = open(argv[1], O_RDONLY)) != -1) {
          if (check_password(fd)) {
            printf("Password found in %s\\n", argv[1]);
            close(fd);
            return 0;
          }
          close(fd);
          return 1;
        }
      }
    
      if (check_password(0)) {
        printf("Password found in standard input\\n");
        return 0;
      }
    
      return 1;
    }

    이제 KLEE를 사용하여 프로그램을 실행한다.

    데이터를 읽으려고 시도하다가 프로그램이 멈추는 것을 방지하려면 입력을 제공해야 한다.

    첫 번째 실행에서는 -sym-stdin 옵션을 사용하여 심볼릭 표준 입력을 제공한다.

    심볼릭 입력을 제공함으로써 KLEE는 비밀번호 확인이 성공하는 경로를 탐색할 것이다.

    $ clang-11 -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone password2.c
    $ klee -posix-runtime password2.bc -sym-stdin 10
    KLEE: NOTE: Using POSIX model: /snap/klee/6/usr/local/lib/klee/runtime/libkleeRuntimePOSIX64_Debug+Asserts.bca
    KLEE: output directory is "/home/ubuntu/whitehat/IOT-research/klee-study/tutorial_3/klee-out-1"
    KLEE: Using STP solver backend
    KLEE: SAT solver: MiniSat
    warning: Linking two modules of different target triples: 'password2.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'klee_range64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'memcpy64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'memmove64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'memset64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'klee_overshift_check64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    KLEE: WARNING: undefined reference to function: printf
    KLEE: WARNING: undefined reference to function: strlen
    KLEE: WARNING: undefined reference to function: strncmp
    KLEE: WARNING ONCE: Alignment of memory from call "malloc" is not modelled. Using alignment of 8.
    KLEE: WARNING ONCE: calling external: syscall(4, 94631781707192, 94631778752272) at klee_src/runtime/POSIX/fd.c:530 12
    KLEE: WARNING ONCE: calling __klee_posix_wrapped_main with extra arguments.
    KLEE: WARNING ONCE: calling external: printf(94631781840032) at password2.c:35 5
    Password found in standard input
    
    KLEE: done: total instructions = 2934
    KLEE: done: completed paths = 6
    KLEE: done: partially completed paths = 0
    KLEE: done: generated tests = 6

    이제 KLEE를 사용하여 비밀번호를 발견해냈다!

    우리의 프로그램은 디스크 파일에서 비밀번호를 읽을 수도 있지만, 비밀번호 확인이 성공하는 경로를 실행하도록 KLEE가 파일의 심볼릭 내용을 읽기를 원한다.

    -sym-files 옵션은 ‘A’, ‘B’, ‘C’ 등의 이름을 가진 여러 심볼릭 파일을 제공한다.

    아래의 -sym-files 1 10 옵션을 지정함으로써, KLEE에게 크기가 10바이트인 심볼릭 파일 하나를 제공하도록 요청하고, KLEE는 이 파일을 ‘A’로 이름을 지어준다.

    그러므로 이 파일 이름을 우리의 프로그램에 인수로 제공한다.

    $ klee -posix-runtime password2.bc A -sym-files 1 10
    KLEE: NOTE: Using POSIX model: /snap/klee/6/usr/local/lib/klee/runtime/libkleeRuntimePOSIX64_Debug+Asserts.bca
    KLEE: output directory is "/home/ubuntu/whitehat/IOT-research/klee-study/tutorial_3/klee-out-2"
    KLEE: Using STP solver backend
    KLEE: SAT solver: MiniSat
    warning: Linking two modules of different target triples: 'password2.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'klee_range64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'memcpy64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'memmove64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'memset64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    warning: Linking two modules of different target triples: 'klee_overshift_check64_Debug+Asserts.bc' is 'x86_64-pc-linux-gnu' whereas 'klee_init_env64_Debug+Asserts.bc' is 'x86_64-unknown-linux-gnu'
    
    KLEE: WARNING: undefined reference to function: printf
    KLEE: WARNING: undefined reference to function: strlen
    KLEE: WARNING: undefined reference to function: strncmp
    KLEE: WARNING ONCE: Alignment of memory from call "malloc" is not modelled. Using alignment of 8.
    KLEE: WARNING ONCE: calling external: syscall(4, 94091070492128, 94091067545360) at klee_src/runtime/POSIX/fd.c:530 12
    KLEE: WARNING ONCE: calling __klee_posix_wrapped_main with extra arguments.
    KLEE: WARNING ONCE: calling external: printf(94091070597920, 94091070491088) at password2.c:25 15
    Password found in A
    
    KLEE: done: total instructions = 6351
    KLEE: done: completed paths = 6
    KLEE: done: partially completed paths = 0
    KLEE: done: generated tests = 6

    비밀번호는 실행 경로 중 하나에서 심볼릭 파일 A로부터 성공적으로 읽을 수 있었다.

    출처 및 번역

    https://klee.github.io/tutorials/using-symbolic/

    답글 남기기

    이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다