다음 문서는 철저히 https://github.com/mykter/afl-training을 토대로 작성되었습니다. AFL Fuzzer를 직접 다뤄보자.

AFL Fuzzer

image

​ AFL(American Fuzzy Lop) Fuzzer는 프로그램에 무작위의 데이터를 입력하게 하여 버그 및 취약점을 찾아주는 자동화된 툴이다. 일명 퍼징 기법을 사용하며, 가장 큰 특징이라면 소스코드가 주어질시에, 컴파일시에 AFL 툴이 입력받는 소스코드 루틴을 찾아줘서 무작위의 input data가 효율적으로 생성된다. 대신 black box 상태의 fuzzing은 어렵다고 한다.

Setup

  1. https://github.com/mykter/afl-training 다음 링크를 타고 zip 파일을 받고 Linux 환경으로 옮겨주자. 본인은 Ubuntu 18.04 LTS에서 진행하였다.

  2. Docker로 실습 환경을 구성할 것인데, Docker가 설치되어 있지 안다면, 구글링해서 설치하자.

  3. 실습 환경을 설치하자. 보통 docker에서 오류가 나면 거의 권한 문제이므로 본인은 아예 root 계정으로 진행하였다.

baek@ubuntu:~$ docker pull mykter/afl-training
Using default tag: latest
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.40/images/create?fromImage=mykter%2Fafl-training&tag=latest: dial unix /var/run/docker.sock: connect: permission denied
baek@ubuntu:~$ sudo -s
[sudo] password for baek: 
root@ubuntu:~# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
mykter/afl-training   latest              57eb66b3ae89        8 months ago        1.38GB

설치가 완료된 것을 볼 수 있다. 실제로 실행시켜 보자.

$ docker run --privileged -p 22000:22 -e PASSMETHOD=env -e PASS=<password> afltraining
  • privileged mode : "privileged"된 컨테이너들만 모든 host의 장치에 접근할 수 있다. 보통 보안상 "unprivileged"로 실행한다.
  • -p 22000:22 : 호스트의 22000번 포트를 컨테이너의 22번 포트에 연결한다.
  • -e : 환경변수 설정

비밀번호는 '1234'로 했다. 그리고 'afltraining'이 아니라 'mykter/afl-training'으로 입력해줘야 한다.

root@ubuntu:~# docker run --privileged -p 22000:22 -e PASSMETHOD=env -e PASS=1234 mykter/afl-training
Password set from environment variable
Spawning SSHd

이렇게 되었다면 열린 것이다. ssh로 접속해보자.

baek@ubuntu:~$ ssh fuzzer@localhost -p 22000
fuzzer@localhost's password: 
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 5.3.0-46-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

fuzzer@dcf3e1a8a686:~$ ls
afl-2.52b  workshop

동작중인 컨테이너를 중지시키려면 다음과 같이 한다.

root@ubuntu:~# docker ps
CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS              PORTS                   NAMES
dcf3e1a8a686        mykter/afl-training   "entrypoint.sh"     3 minutes ago       Up 3 minutes        0.0.0.0:22000->22/tcp   keen_perlman
root@ubuntu:~# docker stop dcf3e1a8a686
dcf3e1a8a686
  1. 로컬에 AFL Fuzzer를 설치하자. 여기서도 오류가 난다면 sudo !
$ sudo apt-get install clang-6.0 build-essential llvm-6.0-dev gnuplot-nox
$ sudo update-alternatives --install /usr/bin/clang clang `which clang-6.0` 1
$ sudo update-alternatives --install /usr/bin/clang++ clang++ `which clang++-6.0` 1
$ sudo update-alternatives --install /usr/bin/llvm-config llvm-config `which llvm-config-6.0` 1
$ sudo update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer `which llvm-symbolizer-6.0` 1
$ echo core | sudo tee /proc/sys/kernel/core_pattern
$ wget http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz
$ tar xvf afl-latest.tgz
$ cd afl-2.52b   # replace with whatever the current version is
$ make && make -C llvm_mode CXX=g++
$ make install

Easy Example

실습환경을 모두 구성하였으니 간단하게라도 AFL Fuzzer를 사용해보자. 간단한 프로그램이 예시로 주어져 있다. 그걸 이용해보자.

baek@ubuntu:~/fuzz/afl-training-master$ cd quickstart
baek@ubuntu:~/fuzz/afl-training-master/quickstart$ CC=afl-clang-fast AFL_HARDEN=1 make
afl-clang-fast -g -w vulnerable.c -o vulnerable
afl-clang-fast 2.52b by <lszekeres@google.com>
afl-llvm-pass 2.52b by <lszekeres@google.com>
[+] Instrumented 30 locations (hardened mode, ratio 100%).

vulnerable이라는 바이너리가 생성되었다. 실행해보자.

baek@ubuntu:~/fuzz/afl-training-master/quickstart$ ./vulnerable
hkhk
Usage: ./vulnerable
Text utility - accepts commands and data on stdin and prints results to stdout.
    Input             | Output
    ------------------+-----------------------
    u <N> <string>    | Uppercased version of the first <N> bytes of <string>.
    head <N> <string> | The first <N> bytes of <string>.
baek@ubuntu:~/fuzz/afl-training-master/quickstart$ ./vulnerable
u 10 alsdkjfalsdkjf
ALSDKJFALSdkjf
baek@ubuntu:~/fuzz/afl-training-master/quickstart$ ./vulnerable
head 10 alskdfjalksdjf
alskdfjalk

이 이외에도 여러 input을 넣어봤는데 오류를 쉽게 찾진 못했다.

Fuzzing

Fuzzer로 분석하기 위해선 testcase를 만들어주어야 하고 사실 이미 inputs이라는 디렉토리에 잘 만들어져 있다.

$afl-fuzz -i <test case dir> -o <output dir> target_app

이런식으로 white-box fuzzing이 일어난다.

baek@ubuntu:~/fuzz/afl-training-master/quickstart$ afl-fuzz -i inputs -o out ./vulnerable
afl-fuzz 2.52b by <lcamtuf@google.com>
[+] You have 1 CPU core and 7 runnable tasks (utilization: 700%).
[*] Checking core_pattern...
[*] Setting up output directories...
[+] Output directory exists but deemed OK to reuse.
[*] Deleting old session data...
[+] Output dir cleanup successful.
[*] Scanning 'inputs'...
[+] No auto-generated dictionary tokens to reuse.
[*] Creating hard links for all input files...
[*] Validating target binary...
[*] Attempting dry run with 'id:000000,orig:head'...
[*] Spinning up the fork server...
[+] All right - fork server is up.
    len = 67, map size = 8, exec speed = 391 us
[*] Attempting dry run with 'id:000001,orig:u'...
    len = 11, map size = 14, exec speed = 878 us
[+] All test cases processed.

[+] Here are some useful stats:

    Test case count : 2 favored, 0 variable, 2 total
       Bitmap range : 8 to 14 bits (average: 11.00 bits)
        Exec timing : 391 to 878 us (average: 634 us)

[*] No -t option specified, so I'll use exec timeout of 20 ms.
[+] All set and ready to roll!
image

보면 2 unique crashes가 발생한 것을 알 수 있다. 이 crash는 output 디렉토리에서 확인할 수 있다.

baek@ubuntu:~/fuzz/afl-training-master/quickstart$ ls out/crashes/
id:000000,sig:11,src:000008,op:ext_AO,pos:0  id:000001,sig:11,src:000008,op:havoc,rep:2  README.txt
baek@ubuntu:~/fuzz/afl-training-master/quickstart$ cat out/crashes/id\:000000\,sig\:11\,src\:000008\,op\:ext_AO\,pos\:0 
head 66666666N66

이 crash를 다시 바이너리에 입력해보면 Segmentation Fault 를 확인할 수 있다.

baek@ubuntu:~/fuzz/afl-training-master/quickstart$ ./vulnerable < out/crashes/id\:000000\,sig\:11\,src\:000008\,op\:ext_AO\,pos\:0 
Segmentation fault (core dumped)

'System Hacking' 카테고리의 다른 글

libFuzzer Training - (2) HeartBleed  (2) 2020.04.19
libFuzzer Training - (1) Start  (2) 2020.04.18
AFL Fuzzing Training - (2) HeartBleed  (0) 2020.04.18

+ Recent posts