본문 바로가기
정보보안/fuzzing

AFL 이해를 위한 기본 개념

by meanjung 2022. 1. 7.

일반적인 fuzzer의 architecture

  • test case generator : 입력값을 만들고
    • 새로운 test case 생성
  • worker : 주어진 입력값을 통해 프로그램 실행시키고
    • test case generator가 제공하는 테스트 케이스 실행하고 예상치 못한 동작 인식하는 역할
  • logger : 프로그램이 돌면서 버그 분석에 필요한 정보를 기록한다.
    • 발견된 모든 crash와 각각의 테스트 사례를 기록하거나 저장하는 역할
    • logging은 crash 스택 추적을 통해 crash 분석을 쉽게 할 수 있다.

 

fuzzing의 type

퍼징을 위해 입력값을 어떻게 조절하는지에 따라(테스트 케이스를 어떻게 생성하는지에 따라) 다음과 같이 두 가지 방식이 존재한다.

  • Mutation Based Fuzzing(Dumb fuzzing)
    • 새로운 테스트 케이스 생성을 위해 입력 구조의 모델이 필요하지 않은 test case generator
    • AFL 퍼저가 이에 해당한다. 
  • Generation Based Fuzzing(Smart fuzzing)
    • 입력 구조의 모델을 완전히 이해한 상태에서 수행하는 퍼징
    • 입력 구조의 모델을 분석해 포맷에 맞춰 변형한 뒤 생성해줘야하므로 구현 난이도가 높다. 

 

AFL 퍼저

  • [출처] https://rninche01.tistory.com/entry/Fuzzing-%EA%B3%B5%EB%B6%80
  • coverage 기반 mutation based fuzzing(dumb fuzzing)
    • code coverage guided fuzzing (ex. AFL, syzkaller)
      • Coverage Guided Fuzzing은 test case 생성 기술을 의미한다. 각 test case를 단순한 바이트의 나열로 읽은 후, 무작위의 byte를 무작위하게 변이시켜 새로운 test case를 생성한다.
      • AFL : 무작위로 바이트를 선택해 해당 바이트를 변이하여 새로운 test case 생성
  • test case의 code coverage를 효율적으로 늘리기 위해 유전 알고리즘을 사용하는 fuzzer
    • code coverage 개념
      • test 수행결과를 정량적으로 나타내는 방법
      • SW를 이루는 소스코드 중 테스트를 통해 실행된 코드의 비율
  • execution path 분석을 통한 넓은 code coverage와 루프 실행을 통한 빠른 속도가 특징
    • execution path ?? 
  • gray box fuzzer
    • 프로그램 내부의 일부를 아는 상황에서 퍼징
    • gray box fuzzer는 보통 test case를 evolve하기 위한 입력으로 execution feedback 정보를 사용한다.
  • open-sourced
  • in-memory fuzzing
    • 프로그램의 크기가 크면 오버헤드가 크기때문에 매번 프로세스를 respawning하지 않고 PUT의 일부만 퍼징해 오버헤드를 최소화하는 것이 좋다. 
    • GUI 프로그램들 같은 경우 initializing이 오래 걸리는데 그래서 initialization 작업이 끝난 시점의 메모리 스냅샷을 찍어놓고 복구하는 방법을 사용한다.
    • 이런 기술을 in-memory fuzzing이라고 한다. 
      • AFL은 forkserver 사용, 몇 가지 스타트업 코드 건너뛰는 방식으로.. in-memory fuzzing과 비슷하지만 snapshot대신 iteration마다 새로운 프로세스를 fork한다. 
      • PUT의 상태를 원상복구하지 않으면서 특정 함수에 대한 in-memory fuzzing을 수행하는 방법도 있다. 이를 in-memory API fuzzing이라고 하는데, AFL의 persistent mode가 이에 해당한다. 
  • 한 가지 이상의 instrumentation 방법을 사용하는 대표적인 퍼저
    • instrumentation 이란?
      • 가장 가치있는 피드백을 수집하는 방법
      • 프로그램의 행위나 특정 변수를 조사하는 기능
      • 바이너리 분석에서의 binary instrumentation은 대부분 측정이나 분석을 위해 코드를 삽입하는 동작을 포함한다. 즉, 분석을 위해 코드 등을 추가하는 것이 바이너리 계측이다.
      • static instrumentation
        • 소스코드나 중간코드(intermediate code)를 컴파일할 때 수행된다.
      • dynamic instrumentation
        • 런타임 도중에 이뤄지기 때문에 동적으로 링크되는 라이브러리를 쉽게 instrument할 수 있다.  
  • 전용 컴파일러를 이용해 코드 수준의 static instrument를 하기도 하고, QEMU의 도움으로 바이너리 수준의 dynamic instrument를 하기도 한다. 
    • QEMU 개념
      • 에뮬레이션이 가능한 hypervisor
      • 에뮬레이션 : hw를 sw적으로 구현해서 특정 실행 환경을 제공하는 것
      • +) 가상화 : 동 hw를 사용할 수 있는 os를 가상머신에서 구동하기 위해 hypervisor를 통해 커널 번역, 자원 분배 등의 기능 제공(ex. kvm)
      • hypervisor : 서로 다른 복수개의 os를 단일 물리 머신 위에서 스케줄링할 수 있는 sw
  • [출처] https://cpuu.postype.com/post/9180710
  • 바이너리 계측(instrumentation) 기법과 유전 알고리즘(genetic algorithms)를 잘 활용해서 주어진 테스트 케이스로부터 새로운 실행 경로(execution path)를 찾도록 되어있다.
    • 제공되는 컴파일러(afl-gcc)로 소스코드를 빌드하면 자동으로 바이너리 내부에 계측 정보들이 포함된다.
    • 이후 seed로 주어진 입력 파일을 해당 바이너리에 주입해 실행한다.
    • 만약 코드 커버리지를 상승하도록 하는 입력값을 찾았다면 이를 interesting input으로 간주하고, 이를 기반으로 더 다양한 변이(mutation) 작업을 수행한다.
    • 다양한 방식을 통해 입력값을 만들다가 혹시 새로운 경로를 찾는 경우가 발견하면 그 부분에 대해 집중적인 퍼징이 가해진다.
    • crash 또는 hang 발견에 대한 판단은 시그널을 통해 구분되며 이 상황에 대한 결과물은 output 디렉터리에 저장된다.
    • 대충 이해는 가는데 정확하게는 잘 모르겠다...
  • [출처] https://wogh8732.tistory.com/271
  • 입력에 대한 구조를 알 필요가 없기 때문에 dumb fuzzer라고 하지만, 해당 퍼저 내부에서 스스로 유효한 입력구조를 파악하고 생성한다

 


symbolic execution

- 프로그램 실행시 구체적인 상수값이 아니면 미지수인 변수를 사용하면, 해당 값을 기호화시켜 프로그램을 분석하는 방식이다. 기호화된 변수를 따라가면서 프로그램을 분석하는 방식이다.

 

blackbox testing

- test하려는 sw의 내부 구조나 작동 원리에 대해 무지한 상태에서 sw 동작을 검사하는 방법. 입력하는 값을 통해 올바르게 출력되는지 판별하며 검사하기 때문에 검사 대상의 코드나 내부 구조 등에 정보는 필요하지 않다.

 

whitebox testing

- 대상의 sw 내부 소스 코드를 테스트하는 기법. 반드시 소스 코드가 필요하며, 이는 개발자가 내부 소스 코드의 동작을 추적할 수 없기 때문에 실행되는 과정을 하나하나 확인하여 어떤 결로로 실행되는지, 불필요한 코드가 존재하는지, 개발자가 테스트하지 못한 부분이 있는지 등을 알아보기 위해 필요하다. 

 

coverage-guided

- greybox testing으로도 불리며 blackbox testing과 whitebox testing을 결합한 형태의 기법을 말한다. 이 기법을 사용하려면 소프트웨어나 내부 데이터 구조에 사용된 알고리즘 등의 전체적인 흐름을 부분적으로 숙지한 상태여야한다. 이런 테스트를 통해 소프트웨어 내부에서 사용되는 불필요한 코드나 부적절한 응용 프로그램으로 인해 발생하는 결함을 발견할 수 있다. 


읽어볼 것


https://rond-o.tistory.com/214

 

Fuzz with AFL & Exploit dact (1) Fuzzing

Overview AFL dact Fuzzing Build dact Use dact Build dact with scan-build build with AFL Fuzz with AFL Conclusion Overview 비오비 교육 때 박세준 멘토님께서 내주셨던 과제를 정리할 겸 AFL을 이용해 1-da..

rond-o.tistory.com

https://wogh8732.tistory.com/272

 

AFL fuzzer 설명 및 사용방법

1. AFL 퍼저 원리 afl 퍼저는 instrumentation-guided genetic algorithm 과 결합된 퍼저이다. 브푸트포스로 입력을 받지만, 거기서 끝나는게 아니라, 커버리지를 넓혀가며 프로그램 제어 흐름에 대한 변경사항

wogh8732.tistory.com

https://hackyboiz.github.io/2021/05/23/fabu1ous/winafl-1/

 

hackyboiz

hack & life

hackyboiz.github.io

 

댓글