보안/Fuzzing101

[Fuzzing101] exercise 2 CVE-2012-2836 실습 기록

pumisj 2026. 3. 15. 19:02

서론

최근 보안에 관심이 생겨 관련해서 공부를 하려고 노력중이다.
하지만 학교 수업만 들어서 보안에 관한 지식은 전무하다 (심지어 아직 컴퓨터구조 수업도 안들었다)

 

그래서 이번주부터 fuzzing101 실습을 좀 해보고 글로 기록하려고 한다.

빠른 학습을 위해서 Gemini를 이용해 모르는 부분을 물어보고, 다른 블로그 글을 참고하면서 문제를 해결할 예정이며, 지식 습득을 위해 따로 드림핵 강의를 수강할 생각이다.

 

해당 글에는 실습을 하면서 내가 몰랐던, 삽질했던 모든 내용을 적을 예정이라 글이 다소 감정적이고 지엽적인 내용이 있을 수 있다.

 

또 리눅스 명령어는 잘 몰라서 여기에 적으면서 기억하려고 한다. 감안하고 보면 좋겠다. 

 

그럼 시작하겠다.


테스트 환경

작년에 마련한 T9 미니PC를 서버로 사용중이다

환경은 Ubuntu 서버 OS에 afl++ 공식 도커 이미지를 이용하여 실습을 진행할 예정이다.


CVE-2012-2836

해당 취약점은 libexif라이브러리의 exif-data.c 파일에 있는 exif_data_load_data에서 발견되었는데, 해커가 out-of-bound를 일으키거나 이미지에있는 EXIF태그를 조작해 메모리에서 민감한 데이터를 빼올 수 있다고 설명이 적혀져있다.

 

이 외에도 해당 버전에서는 CVE-2009-3895라는 취약점이 있는데, 이번 실습에서는 해당 crash 파일을 찾지 못했기 때문에 넘어가겠다.

 

그러면 바로 실습을 진행하도록 하겠다.


퍼징

먼저 wget으로 libexif-0_6_14 버전을 가져온 뒤 tar로 압축을 해제한다

sudo apt install build-essential

export LLVM\_CONFIG="llvm-config-12"  
autoreconf -fvi

CC=afl-clang-lto  
./configure prefix="$HOME/fuzzing\_libexif/install/"  
make & make install  

먼저 빌드에 필요한 패키지를 설치한 뒤에 LLVM_CONFIG를 llvm-config-12로 변경해준다.


이번에 사용할 컴파일러는 성능이 좋은 afl-clang-lto인데, llvm-config-12로 명시하지 않으면 오류가 날 수 있기때문에 해당 쉘에서 임시로 사용할 수 있게 변경했다.

 

또 autoreconf라는 명령어는 이 시스템 환경에 맞춰서 configure 파일을 만들어준다. 이 파일에는 LLVM 버전이나 설치 경로같은 정보들이 저장되어있는데, 이 내용을 바탕으로 Makefile을 만들어준다.

 

Makefile에는 실질적으로 어떻게 컴파일을 할지 적혀있다. 우리가 c파일같은 수천개의 소스파일을 하나하나 빌드할 수 없으니, make로 빌드를 자동화하고 make install로 실행파일을 만든다.


이렇게 만들어진 bin은 아까 prefix로 지정한 install디렉토리에 저장된다.


다음은 해당 라이브러리를 실행할 하네스 프로그램을 설치한다.
이번 실습에서는 가장 간단한 exif-0_6_15 버전으로 진행했다.

마찬가지로 퍼징을 위해 afl로 컴파일을 진행한다.

CC=afl-clang-lto  CXX=afl-clang-lto++
./configure prefix="$HOME/fuzzing\_libexif/install/" PKG_CONFIG_PATH=$HOME/fuzzing_libexif/install/lib/pkgconfig  
make & make install  

여기서는 Makefile을 만들 때 PFG_CONFIG_PATH를 지정해줬는데, 이유는 우리가 직접 컴파일한 libexif를 사용하기 위해서다. 이를 명시하지 않으면 운영체제에 기본적으로 있는 libexif를 사용할 가능성이 있기 때문에 직접 명시해야된다.


모든 작업이 끝나면 샘플 파일을 다운받고 install 디렉토리에 있는 실행파일을 이용해 퍼징을 진행한다.

afl-fuzz -i <인풋 디렉토리> -o <아웃풋 디렉토리> -s 123 -- <실행 파일> @@

여기서 @@에는 기본 인풋에서 시드값에 따라 변형된 새로운 파일이 들어간다.

 

약 1시간 30분동안 퍼징을 진행

이제 퍼징으로 발견한 파일을 디버깅하면 된다


디버깅

여기서부터는 정확하지 않은 내용이 있을 수 있다. 틀렸으면 알려주길 바란다.

 

디버깅하기 전에 install파일을 삭제하고 make clean으로 싹 정리한 뒤에 gcc로 컴파일, 플래그로 -g -O0를 넣어주어 최적화 없이 코드 그대로 보도록 했다.

 

먼저 찾아낸 파일을 인풋으로 넣어 실행해보자.

Segmentation fault가 발생했다. GDB를 이용해서 자세히 봐보자

 

 

여기 보면 vmovdqu를 실행하다 터진거같다. 찾아보니 메모리에 있는 데이터를 레지스터로 옮기는 명령어라고 한다.

백 트레이싱으로 자세히 봐보자

 

 

보니까 libc에서 오류가 난거같은데, 이 부분은 단순히 메모리를 읽는데 문제가 생긴거같으니 그 전에 실행된 exif_data_load_data_content 함수를 보면

 

 

해당 부분에서 오류가 났다고 한다. 내부를 보면 단순히 파일 오프셋과 사이즈를 읽어 메모리를 복사하는 작업을 진행하는거같다.

 

여기서 의문이었던게 그러면 마지막으로 실행되는 부분이 exif_data_load_data_thumbnail 내부니까 #1이 exif_data_load_data_content가 아니라 exif_data_load_data_thumbnail이었어야 하지 않나? 잘 모르겠다.

 

아무튼 어떤 값이 문제였길래 터졌는지 확인하기 위해 값을 하나하나 살펴봤다.

 

 

누가봐도 thumbnail_length가 문제인거같다. offset에서 저 큰 길이 이후의 데이터를 읽으려다보니 읽을 수 있는 메모리 영역을 벗어난걸로 생각이 든다.

 

이 thumbnail_length는 다음과 같은 식으로 저장된다

 

여기 보면 d + offset + 12 * i + 8 부분의 데이터를 o에 저장하는걸로 보인다. 그러면 이 부분엔 뭐가 있는지 GHEX로 보려고 한다.

 

 

그러면 이렇게 F6 FF FF FF가 보인다. data->priv->order이 EXIF_BYTE_ORDER_INTEL인거보니 반대로 읽어서 FFFFFFF6을 읽은걸로 보인다. 이로 인해 이상한 부분의 메모리 구역을 읽어 crash가 터진것이다. 

 

그래서 메모리를 읽기 전에 o > ds 라면 바로 return을 하는 코드를 추가하면 해결이다.

 

오류가 터지지 않는다.

 

하지만 문제가 있다. 내가 찾은 부분이랑 공식 깃헙, 다른 블로그에서 해결방법과 좀 다르다는거다.

 

내가 찾은 부분은 exit_data_load_data_thumbnail에서 오류가 생긴건데, 다른걸 보면 모두 exit_data_data_thumbnail이나 exit_get_sshort에서 오류가 나는것이다.

 

그래서 내가 찾은 다른 crash 파일들중 안되는게 있는지 더 찾아봤다..

그랬더니 딱 하나 그 부분에서 터지는게 있었다.

 

 

여기 보면 exif_get_sshort에서 터진게 보인다. 코드를 확인해보자

 

 

여기를 보면 buf[1]을 볼 수 있는데, 이거 값 찍어보면 Cannot access memory at address  오류가 뜬다.

왜 이런 이상한 값이 들어왔나 봤더니 IFD 1 offset을 검증하는 부분에서 문제가 생겼다.

 

 

여기서 offset값이 fffffffc이기 때문에 정수 오버플로우가 일어나 ds보다 작게 나와 제대로 검증이 되지 않고 메모리를 읽어버린것이다.

 

해결방법은 간단하다. offset자체가 ds보다 작은지 비교하는 코드를 넣어주면 된다

 

 

제대로 오류를 잡아낸걸 확인할 수 있다.

 

후기

GDB를 이용한 디버깅은 너무 어려운거같다. 특히 rax, rsi, rdp, rip 보는게 너무 힘들어서 무슨 의미인지 계속 찾아보면서 공부했던거같다. 다음에는 좀 더 빠르게 푸는걸 목표로 해야겠다.

'보안 > Fuzzing101' 카테고리의 다른 글

[Fuzzing101] exercise 3 CVE-2017-13011 실습 기록  (0) 2026.03.19