Fuzzing101_exercise 1

156·2025년 3월 18일

Fuzzing101

목록 보기
2/3
post-thumbnail

Fuzzing101/Exercise 1 at main · antonio-morales/Fuzzing101

0. 문제 설명

Exercise 1
Targe : XPDF 3.02
1-day : CVE-2019-13288

학습 목표

  • Compiling a target application with instrumentation
  • Running a fuzzer (afl-fuzz)
  • Triaging crashes with a debugger (GDB)

CVE-2019-13288
Xpdf 4.01.01 버전의 Parser.cc 파일에 있는 Parser::getObj() 함수에 특정 파일을 집어넣으면 무한 재귀로 인한 DoS 발생

1. 타겟 설치

디렉토리 생성

mkdir fuzzing_xpdf && cd fuzzing_xpdf/

필수 도구 설치

sudo apt install build-essential

Xpdf 3.02 다운로드

wget https://dl.xpdfreader.com/old/xpdf-3.02.tar.gz
tar -xvzf xpdf-3.02.tar.gz

타겟 빌드

cd xpdf-3.02
sudo apt update && sudo apt install -y build-essential gcc
./configure --prefix="$HOME/fuzzing101/fuzzing_xpdf/install/"
make
make install

소프트웨어 설치 경로

./configure --prefix="~/fuzzing101/fuzzing_xpdf/install/"
  • ./configure : 디렉토리에 있는 configure 스크립트를 실행. 시스템 환경과 의존성을 확인하고 Makefile 등을 생성
  • --prefix= 옵션으로 소프트웨어 설치 경로를 지정할수 있다. 기존에는 /usr/local/ 경로에 설치되지만, --prefix 옵션을 통해 원하는 경로에 지정하여 퍼징을 편리하게 해준다.

PDF 예제파일 다운로드

mkdir pdf_examples && cd pdf_examples


sample.pdf에서 에러가 뜸 → 없어도 문제 X

테스트

$HOME/fuzzing101/fuzzing_xpdf/install/bin/pdfinfo -box -meta $HOME/fuzzing101/fuzzing_xpdf/pdf_examples/helloworld.pdf

2. AFL 설치

의존성 설치

sudo apt-get update
sudo apt-get install -y build-essential python3-dev automake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools
sudo apt-get install -y lld-14 llvm-14 llvm-14-dev clang-14 || sudo apt-get install -y lld llvm llvm-dev clang 
sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-dev

AFL build

cd $HOME
git clone https://github.com/AFLplusplus/AFLplusplus && cd AFLplusplus
export LLVM_CONFIG="llvm-config-14"
make distrib
sudo make install

afl++ 설치 확인

llvm 버전 확인

3. AFL 실행

이전 컴파일 파일 및 실행 파일 정리

rm -r $HOME/fuzzing_xpdf/install
cd $HOME/fuzzing_xpdf/xpdf-3.02/
make clean
  • 이전에는 그냥 빌드했었고
  • AFL로 빌드하기 위해 삭제
export LLVM_CONFIG="llvm-config-14"
CC=$HOME/AFLplusplus/afl-clang-fast CXX=$HOME/AFLplusplus/afl-clang-fast++ ./configure --prefix="$HOME/fuzzing101/fuzzing_xpdf/install/"
make
make install

컴파일러 변경 및 xpdf 빌드

CC=$HOME/AFLplusplus/afl-clang-fast CXX=$HOME/AFLplusplus/afl-clang-fast++ ./configure --prefix="$HOME/fuzzing101/fuzzing_xpdf/install/"
  • CC CXX : 기본 컴파일러 변경
  • ./configure로 빌드

이전에 빌드했던 xpdf를 지우고, 퍼징을 위해 afl llvm으로 xpdf를 다시 빌드

퍼저 실행

afl-fuzz -i $HOME/fuzzing101/fuzzing_xpdf/pdf_examples/ -o $HOME/fuzzing101/fuzzing_xpdf/out/ -s 123 -- $HOME/fuzzing101/fuzzing_xpdf/install/bin/pdftotext @@ $HOME/fuzzing101/fuzzing_xpdf/output

명령어 설명

afl-fuzz -i $HOME/fuzzing101/fuzzing_xpdf/pdf_examples/ \
         -o $HOME/fuzzing101/fuzzing_xpdf/out/ \
         -s 123 -- \
         $HOME/fuzzing101/fuzzing_xpdf/install/bin/pdftotext @@ $HOME/fuzzing101/fuzzing_xpdf/output
-i : 퍼징에 사용할 input 파일 경로 지정

-o : 퍼징 결과를 저장하는 디렉토리 → 크래시 파일이나 로그가 여깄음

-s 123 : 랜덤 시드를 고정하여 추후에 재현 가능을 보장

-- : 옵션과 인자 구분

$HOME/fuzzing101/fuzzing_xpdf/install/bin/pdftotext : 퍼징 대상 프로그램

@@ : 자동으로 생성한 입력 파일 → fuzzing input 파일

$HOME/fuzzing101/fuzzing_xpdf/output : 크래시 파일이나 버그 관련 정보가 저장

**trouble shooting**
야심차게 돌려볼려고했는데
![](https://velog.velcdn.com/images/156/post/6aaa6a4c-8af4-413f-bfdd-58bffddae7ea/image.png)

크래시가 발생했을 때 코어덤프를 수집못한다..?
```bash
echo core | sudo tee /proc/sys/kernel/core_pattern

이렇게 수정하는 것으로 해결 가능하다.


실제로 out에서 crashes 등을 확인할 수 있다.
아래 파일들이 크래시가 발생한 파일 자체이다.

4. 크래시 분석

크래시 재현

$HOME/fuzzing101/fuzzing_xpdf/install/bin/pdftotext id:000002,sig:11,src:000937,time:181821,execs:251850,op:havoc,rep:5 output.txt

pdftotext에 크래시 파일을 넣어서 재실행

Crash 분석

xpdf 다시 빌드

rm -r $HOME/fuzzing_xpdf/install
cd $HOME/fuzzing_xpdf/xpdf-3.02/
make clean

CC=gcc CXX=g++ ./configure --prefix="$HOME/fuzzing101/fuzzing_xpdf/install/"
make
make install

gdb attach

pdftotext를 gdb로 attach + 인자로 crash 났던 파일을 줘야함

gdb --args $HOME/fuzzing101/fuzzing_xpdf/install/bin/pdftotext $HOME/fuzzing101/fuzzing_xpdf/out/default/crashes/id:000003,sig:11,src:000001,time:241334,execs:326073,op:havoc,rep:14

r로 실행하면

똑같은 에러가 재현되고

bt를 실행해 보면

계속 동일한 부분이 반복됨을 확인할 수 있다.

**Parser::makeStream**2. **Object::dictLookup**3. **XRef::fetch**

Parser.cc getObj에서 94번째 줄

      if ((str = makeStream(obj, fileKey, encAlgorithm, keyLength,
			    objNum, objGen))) {


makeStream을 호출한다.

Parser.cc makeStream에서 156번째 줄

dict->dictLookup("Length", &obj);


dictLookup을 호출

Object.h dictLookup 에서 253번째 줄

inline Object *Object::dictLookup(char *key, Object *obj)
  { return dict->lookup(key, obj); }


lookup을 호출

XRef.cc fetch에서 823번째 줄

    parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL,
		   encAlgorithm, keyLength, num, gen);

중간에 연결이 끊기는 부분이 있지만, 코드 흐름을 따라가보면, 결국 처음으로 돌아가서

0개의 댓글