Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
FormatFuzzer — 템플릿 기반 바이너리 포맷 퍼저로, 고속으로 유효한 테스트 입력을 생성 및 파싱하며, AFL++와 통합되어 커버리지 기반 퍼징을 지원합니다. | Kitploit
도구/GitHubGitHub/uds-se/formatfuzzer
FuzzingBinary Analysis
GitHubuds-se/formatfuzzer

FormatFuzzer

템플릿 기반 바이너리 포맷 퍼저로, 고속으로 유효한 테스트 입력을 생성 및 파싱하며, AFL++와 통합되어 커버리지 기반 퍼징을 지원합니다.

저장소 보기웹사이트
446385개월 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

FormatFuzzer

FormatFuzzer은 고효율, 고품질의 바이너리 입력 생성 및 파싱을 위한 프레임워크입니다. 이는 바이너리 입력의 형식을 설명하는 바이너리 템플릿을 받아 해당 바이너리 형식을 생성하고 파싱하는 실행 파일을 생성합니다. 예를 들어, GIF용 바이너리 템플릿에서 FormatFuzzer는 GIF 생성기(일명 GIF 퍼저)를 생성합니다.

FormatFuzzer가 생성한 생성기는 매우 효율적이어서 초당 수천 개의 유효한 테스트 입력을 생성합니다. 이는 변이 기반 퍼저(입력의 대부분이 유효하지 않은 경우)와는 대조적입니다. FormatFuzzer가 생성한 입력은 테스트 대상 프로그램(또는 실제로는 모든 프로그램)과 독립적이므로 블랙박스 환경에서도 사용할 수 있습니다. 그러나 FormatFuzzer는 AFL++와도 통합되어 최대 커버리지를 목표로 하는 유효한 입력을 생성합니다. 실험에서 이 "두 세계의 최고" 접근 방식은 다른 모든 설정을 능가했습니다. 자세한 내용은 논문을 참조하세요.

FormatFuzzer가 사용하는 바이너리 템플릿은 010 editor에서 가져왔습니다. 170개 이상의 바이너리 템플릿이 있으며, 이들은 FormatFuzzer에 직접 사용하거나 사용에 맞게 조정할 수 있습니다. 기본적으로 FormatFuzzer는 AVI, BMP, GIF, JPG, MIDI, MP3, MP4, PCAP, PNG, WAV, ZIP과 같은 형식을 생성하며, 매주 이 목록을 확장하고 있습니다.

기여자는 환영합니다! FormatFuzzer 프로젝트 페이지를 방문하여 아이디어나 이슈를 제출하거나 풀 리퀘스트를 추가하세요. FormatFuzzer의 작동 방식과 비교 방법에 대한 자세한 내용은 논문을 참조하세요.

설치

FormatFuzzer는 FormatFuzzer 프로젝트 페이지에서 사용할 수 있습니다. 최신 릴리스를 릴리스 페이지에서 다운로드하여 압축을 풀 수 있습니다.

최신 버전의 경우, git 저장소를 클론할 수도 있습니다.

root@kitploit:~
git clone https://github.com/uds-se/FormatFuzzer.git

이후 모든 작업은 해당 메인 폴더에서 진행됩니다.

root@kitploit:~
cd FormatFuzzer

필수 조건

FormatFuzzer를 실행하려면 다음이 필요합니다.

  • Python 3
  • GNU 라이브러리(특히 getopt_long())를 지원하는 C++ 컴파일러(예: clang 또는 gcc)
  • Python 패키지 py010parser, six, intervaltree
  • zlib 라이브러리(압축 함수용)
  • boost 라이브러리(체크섬 함수용)

빌드 및 구성 스크립트(.ac 및 .am 파일)를 편집하려는 경우 다음도 필요합니다.

  • GNU autoconf
  • GNU automake

Linux에서 요구 사항 설치 (데비안 패키지, Python 가상 환경 사용)

root@kitploit:~
sudo apt install git g++ make automake python3-full zlib1g-dev libboost-dev
python3 -m venv ~/fuzz
source ~/fuzz/bin/activate
pip3 install py010parser six intervaltree

MacOS에서 요구 사항 설치 (Xcode 및 Homebrew 사용)

root@kitploit:~
xcode-select --install
brew install python3 automake boost
pip3 install py010parser six intervaltree

Python 패키지만 설치 (모든 운영 체제)

모든 시스템에서 pip 사용:

root@kitploit:~
pip install py010parser
pip install six
pip install intervaltree

빌드

참고: 모든 빌드 명령은 이 README 파일이 있는 동일한 폴더에서 실행해야 합니다. 이 폴더 외부에서 퍼저를 빌드하는 것은 아직 지원되지 않습니다.

방법 1: build.sh 스크립트 사용

모든 빌드 단계를 자동화하는 build.sh 스크립트가 있습니다. 다음과 같이 실행하세요.

root@kitploit:~
./build.sh gif

GIF 퍼저를 생성합니다.

이는 templates/에 제공된 모든 파일 형식에서 작동합니다. templates/FOO.bt 파일이 있으면 ./build.sh FOO가 퍼저를 빌드합니다.

방법 2: Make 사용

모든 빌드 단계를 자동화하는 Makefile(Makefile.am 소스)이 있습니다. (GNU make 필요.) 먼저 다음을 실행하세요.

root@kitploit:~
touch configure Makefile.in

그런 다음

root@kitploit:~
./configure

그리고 나서

root@kitploit:~
make gif-fuzzer

GIF 퍼저를 생성합니다.

이는 templates/에 제공된 모든 파일 형식에서 작동합니다. templates/FOO.bt 파일이 있으면 make FOO-fuzzer가 퍼저를 빌드합니다.

방법 3: 수동 단계

위의 make 방법이 작동하지 않거나 더 많은 제어를 원하는 경우 수동으로 진행해야 할 수 있습니다.

1단계: 바이너리 템플릿 파일을 C++ 코드로 컴파일

ffcompile 컴파일러를 실행하여 바이너리 템플릿을 C++ 코드로 컴파일합니다. 두 개의 인수를 받습니다: .bt 바이너리 템플릿과 생성될 .cpp C++ 파일.

root@kitploit:~
./ffcompile templates/gif.bt gif.cpp

2단계: C++ 코드 컴파일

다음 명령을 사용하여 퍼저 gif-fuzzer를 생성합니다. 먼저 일반적인 명령줄 드라이버를 컴파일합니다.

root@kitploit:~
g++ -c -I . -std=c++17 -g -O3 -Wall fuzzer.cpp

(-I .은 bt.h 파일의 위치를 나타냅니다. -std=c++17은 C++ 표준을 설정합니다.)

그런 다음 바이너리 파서/컴파일러를 컴파일합니다.

root@kitploit:~
g++ -c -I . -std=c++17 -g -O3 -Wall gif.cpp

마지막으로 바이너리 파서/컴파일러를 명령줄 드라이버와 링크하여 실행 파일을 얻습니다. 추가 라이브러리(예: -lz)를 사용하는 경우 여기에도 지정해야 합니다.

root@kitploit:~
g++ -O3 gif.o fuzzer.o -o gif-fuzzer -lz

퍼저 실행

FormatFuzzer는 특정 형식의 독립 실행형 파서, 생성기 또는 변이기로 실행할 수 있습니다. 또한 AFL++와 같은 범용 퍼저에서 호출하여 해당 형식별 기능을 퍼징 프로세스에 통합할 수 있습니다(AFL++ 통합에 대한 아래 섹션 참조).

생성된 퍼저는 첫 번째 인수로 _명령_을 받고, 그 뒤에 해당 명령에 대한 옵션과 인수가 옵니다.

가장 중요한 명령은 fuzz로, 출력을 생성합니다. 해당 인수는 적절한 형식으로 생성될 파일들입니다.

생성기를 다음과 같이 실행하세요.

root@kitploit:~
./gif-fuzzer fuzz output.gif

임의의 바이너리 파일 output.gif를 생성하거나,

root@kitploit:~
./gif-fuzzer fuzz out1.gif out2.gif out3.gif

세 개의 GIF 파일 out1.gif, out2.gif, out3.gif을 생성합니다.

제공된 gif.bt 템플릿에는 유효한 파일 생성을 쉽게 하기 위해 특수 함수가 추가되었습니다. 적응되지 않은 원본 .bt 템플릿 파일을 사용하면 생성 중 경고가 발생하거나 유효하지 않은 파일이 생성될 수 있습니다.

파서 실행

parse 명령을 사용하여 퍼저를 바이너리 파일의 _파서_로 실행할 수도 있습니다. 이는 바이너리 템플릿의 정확성을 테스트하거나 입력을 변이(아래 '결정 파일' 참조)하려는 경우 유용합니다.

파서를 실행하려면 다음을 사용하세요.

root@kitploit:~
./gif-fuzzer parse input.gif

input.gif를 성공적으로 파싱할 수 없으면 오류 메시지가 표시됩니다.

결정 파일

파싱하는 동안 모든 파싱 결정(즉, 어떤 파싱 대안이 선택되었는지)을 _결정 파일_에 저장할 수도 있습니다. 이는 선택된 결정을 열거하는 바이트 시퀀스입니다. 각 바이트는 단일 파싱 결정을 나타냅니다. 바이트 값 0은 첫 번째 대안이 선택되었음을 의미하고, 값 1은 두 번째 대안이 선택되었음을 의미하는 식입니다.

입력을 파싱할 때 이러한 결정 파일을 생성할 수 있습니다.

root@kitploit:~
./gif-fuzzer parse --decisions input.dec input.gif

여기서 input.dec는 input.gif를 파싱하기 위해 만들어진 결정을 저장합니다.

입력을 _생성_할 때 이러한 결정 파일을 사용할 수도 있습니다. 그러면 퍼저는 파싱 중에 발견된 것과 정확히 동일한 결정을 내립니다. 다음 명령은 input.gif를 파싱하는 동안 결정된 결정을 사용하여 새로운 GIF 파일을 생성합니다.

root@kitploit:~
./gif-fuzzer fuzz --decisions input.dec input2.gif

모든 것이 잘 작동하면 두 파일이 동일해야 합니다.

root@kitploit:~
cmp input.gif input2.gif

결정 파일을 _변이_함으로써(예: 개별 바이트 교체) 파싱된 원본 파일과 유사한 입력을 생성할 수 있습니다. 이는 AFL과 같은 특정 테스트 전략 및 퍼저와 인터페이스하는 데 유용합니다. 이 경우 gif-fuzzer 등을 결정 파일에서 바이너리 파일로 또는 그 반대로 _변환기_로 사용할 수 있습니다. AFL은 결정 파일을 변이하고, 테스트 대상 프로그램은 변환된 바이너리 파일에서 실행됩니다. AFL이 일반적으로 하는 것처럼 바이너리 파일을 직접 변이하는 것과 달리, 이는 항상 유효한 입력을 가지는 이점이 있어 커버리지 쪽으로 훨씬 빠르게 진행할 수 있습니다.

AFL++ 통합

gif-fuzzer와 같은 형식별 퍼저 외에도 FormatFuzzer는 gif.so와 같은 형식별 공유 라이브러리로 컴파일될 수 있습니다(이를 위해 ./build.sh gif 또는 make gif.so 실행). 이러한 공유 라이브러리는 AFL++와 같은 범용 퍼저에 로드될 수 있습니다.

AFL++를 FormatFuzzer와 함께 실행하려면 수정된 버전의 AFL++에 대한 지침을 따르세요. 다양한 퍼징 전략을 지원합니다. 여기에는 다음이 포함됩니다.

  • AFL+FFMut: FormatFuzzer를 사용하여 형식별 스마트 변이를 제공하면서 AFL++ 실행.

  • AFL+FFGen: FormatFuzzer를 형식별 생성기로 사용하고, AFL++는 결정 시드를 변이.

바이너리 템플릿 생성 및 사용자 정의

자체 .bt 바이너리 템플릿을 작성하고(따라서 해당 형식에 대한 고효율 퍼저/파서 생성)하려면 010 Editor 매뉴얼의 템플릿 및 스크립트 소개 섹션을 읽으세요.

많은 경우, 찾고 있는 형식(또는 유사한 형식)의 템플릿이 이미 존재할 수 있습니다. 010 editor 바이너리 템플릿 컬렉션을 확인하여 사용할 수 있거나 형식의 기반으로 삼을 수 있는 것이 있는지 확인하세요.

저장소에 제공된 .bt 파일은 일반적으로 파일 _파싱_을 대상으로 합니다. 파일 _생성_에도 사용할 수 있지만, 입력의 어느 부분이 필요한지에 대한 정확한 정보가 부족한 경우가 많습니다.

이 섹션에서는 .bt 파일을 FormatFuzzer와 잘 작동하도록 사용자 정의하는 몇 가지 방법을 논의합니다.

예를 들어, GIF 형식의 경우 templates/gif-orig.bt 파일은 원래 파싱 전용으로 설계된 원본 바이너리 템플릿을 보여주고, templates/gif.bt 파일은 유효한 GIF를 생성할 수 있는 수정된 버전입니다. 두 파일을 비교해 보면 이를 달성하기 위해 소수의 변경 사항만 필요했음을 알 수 있습니다.

make gif-fuzzer를 실행하거나 ffcompile 도구를 사용하여 gif-fuzzer를 생성했다면 이미 GIF 생성기 및 파서의 구현을 포함하는 C++ 파일 gif.cpp를 얻었을 것입니다. 이는 바이너리 템플릿에 대한 변경 사항이 실행 코드로 어떻게 변환되는지 확인하는 데 유용합니다. C++ 코드에 대한 자세한 내용은 다음 섹션에서 설명합니다.

GIF 바이너리 템플릿은 미리보기 함수 ReadUByte()와 ReadUShort()를 사용하여 실제로 struct 필드로 파싱하기 전에 파일의 다음 바이트 값을 미리 봅니다. 생성 시에는 이러한 함수가 미리 보는 바이트에 대해 선택할 좋은 알려진 값 세트를 지정하는 추가 인수를 받을 수 있습니다. 또한 특정 미리보기 함수(예: ReadUByte())를 호출할 때 항상 사용할 전역적으로 좋은 알려진 값 세트를 지정할 수도 있습니다. 이는 ReadUByteInitValues 벡터에 저장됩니다.

기본적으로 우리의 번역 절차 ffcompile은 미리보기 바이트에 대한 비교에서 사용된 흥미로운 값을 마이닝하여 전역적으로 알려진 값 세트로 사용하려고 시도합니다. ./ffcompile templates/gif.bt gif.cpp를 실행하면 식별된 미리보기 함수와 마이닝된 흥미로운 값을 보여주는 메시지가 출력됩니다.

root@kitploit:~
Finished creating cpp generator.

Lookahead functions found:

ReadUByte
ReadUShort

Mined interesting values:

GlobalColorTableFlag: ['1']
LocalColorTableFlag: ['1']
ReadUByte: ['0x3B', '0x2C']
ReadUShort: ['0xF921', '0xFE21', '0x0121', '0xFF21']
Signature: ['"GIF"']

그러나 GIF 생성을 위해서는 각 ReadUByte() 호출에서 개별적으로 좋은 알려진 값 세트를 지정하는 것이 더 좋습니다. 따라서 크기가 0인 빈 배열을 정의합니다.

root@kitploit:~
const local UBYTE ReadUByteInitValues[0];

전역 ReadUByteInitValues 세트를 덮어쓰고 각 ReadUByte() 호출에 대해 추가 인수를 사용하여 해당 특정 위치에 사용할 좋은 값 세트를 지정합니다. 바이너리 템플릿 언어는 또한 이 선택이 런타임 조건에 따라 이루어질 수 있을 만큼 강력합니다. 예를 들어, 다음 코드에서는 ReadUByte() 호출에 대한 적절한 값 선택이 현재 생성 중인 GIF 버전에 어떻게 의존할 수 있는지 보여줍니다. GIF 버전 89a는 바이트에 대해 하나의 추가 가능한 값(0x21)을 허용합니다.

root@kitploit:~
	if(GifHeader.Version == "89a")
		local UBYTE values[] = { 0x3B, 0x2C, 0x21 };
	else
		local UBYTE values[] = { 0x3B, 0x2C };

	while (ReadUByte(FTell(), values) != 0x3B) {
		...
	}

GIF 바이너리 템플릿에 필요한 나머지 편집도 유사합니다. 예를 들어, 각 struct 필드에 대해 알려진 좋은 값 세트를 지정할 수도 있습니다. 예를 들어, Version 필드에 대해 올바른 값인 87a와 89a를 지정합니다.

root@kitploit:~
	char	Version[3] = { {"87a"}, {"89a"} };

생성된 C++ 코드 이해하기

디버깅 목적과 생성기 및 파서를 개선하기 위해 적절한 변경을 수행하는 방법을 이해하기 위해 생성된 C++ 코드의 내부 작동을 이해하는 것이 유용할 수 있습니다. 이상적으로는 바이너리 템플릿 파일을 편집하여 높은 확률로 유효한 파일을 생성할 수 있을 때까지 조정해야 하므로 생성된 C++ 코드를 편집할 필요가 없어야 합니다.

C++ 코드는 바이너리 템플릿에 정의된 각 struct 및 union에 대한 클래스를 생성하며, int와 같은 네이티브 유형에 대해서도 생성합니다.

생성 시 변수를 초기화할 때 해당 변수가 취할 수 있는 좋은 알려진 값 세트를 정의할 수 있습니다. 예를 들어, 생성자 호출:

root@kitploit:~
char_array_class cname(cname_element, { "IHDR", "tEXt", "PLTE", "cHRM", "sRGB", "iEXt", "zEXt", "tIME", "pHYs", "bKGD", "sBIT", "sPLT", "acTL", "fcTL", "fdAT", "IHDR", "IEND" });

변수 cname에 대해 17개의 좋은 값을 지정합니다. 그러나 적절한 청크 유형의 선택은 문맥에 따라 달라지기 때문에 이것만으로는 충분하지 않은 경우가 많습니다. 따라서 새 청크를 생성할 때 생성 시간에 좋은 값 세트를 지정할 수도 있습니다. 예를 들어, 이 호출은 첫 번째 청크(유형이 IHDR이어야 함)의 인스턴스를 생성하는 데 사용될 수 있습니다.

root@kitploit:~
GENERATE(chunk, ::g->chunk.generate({ "IHDR" }, false));

두 번째 청크를 생성할 때는 IHDR 청크와 PLTE 청크 사이에 올 수 있는 가능한 청크들의 긴 목록을 사용할 수 있습니다.

root@kitploit:~
GENERATE(chunk, ::g->chunk.generate({ "iCCP", "sRGB", "sBIT", "gAMA", "cHRM", "pHYs", "sPLT", "tIME", "zTXt", "tEXt", "iTXt", "eXIf", "oFFs", "pCAL", "sCAL", "acTL", "fcTL", "fdAT", "fRAc", "gIFg", "gIFt", "gIFx", "sTER" }, true));

그러면 생성기는 새 인스턴스에 사용할 알려진 좋은 값 중 하나를 균일하게 선택합니다. 또한 1/128의 작은 확률로 알려진 좋은 값이 아닌 악의적인 값을 선택할 수도 있습니다. 이 기능은 set_evil_bit 메서드를 사용하여 언제든지 활성화하거나 비활성화할 수 있습니다.

생성기가 취하는 모든 무작위 선택은 rand_int() 메서드를 호출하여 이루어집니다.

root@kitploit:~
long long rand_int(unsigned long long x, std::function<long long (unsigned char*)> parse);

프로그램을 생성기로 실행할 때 이 메서드는 무작위 버퍼에서 바이트를 읽어 0에서 x-1 사이의 정수를 샘플링합니다. 프로그램을 파서로 실행할 때 이 메서드는 parse() 함수를 사용하여 대상 파일을 생성하기 위해 무작위 버퍼에 어떤 무작위 바이트가 있어야 하는지 알아낸 다음 해당 바이트를 무작위 버퍼에 씁니다. parse 함수는 인수로 파일의 현재 위치에 있는 버퍼를 받아, 이 정확한 파일 구성을 생성하기 위해 현재 rand_int() 호출이 반환해야 하는 값을 반환해야 합니다.

저자

FormatFuzzer는 Rafael Dutra <[email protected]>가 설계하고 작성했습니다.

퍼저 컴파일러의 개념은 Rahul Gopinath <[email protected]>와 Andreas Zeller <[email protected]>가 도입했습니다.

저작권 및 라이선스

FormatFuzzer는 Copyright © 2020, 2021 by CISPA Helmholtz Center for Information Security입니다. 다음 라이선스가 적용됩니다.

  • FormatFuzzer 코드(특히 모든 C++ 코드 및 해당 생성 관련 코드)는 COPYING에 명시된 GNU GENERAL PUBLIC LICENSE를 따릅니다.

  • 위의 예외로, FormatFuzzer가 생성한 C++ 코드(즉, 특정 형식에 대한 퍼저 및 파서)는 퍼블릭 도메인입니다.

  • FormatFuzzer의 기반이 되는 원본 pfp _코드_는 LICENSE-pfp에 명시된 MIT 라이선스를 따릅니다.

도구 다운로드