- WinAFL Fuzzing - Target OFFSET을 구해보자2025년 01월 22일 18시 44분 15초에 업로드 된 글입니다.작성자: 방세연
공식 홈페이지에 공개된 C++ 소스코드 분석을 통해 XPDF 타겟 함수가 xpdf 모듈의 PDFDoc.cc 파일과 관련되어있다는 점을 알게 되었고, 해당 소스파일의 여러 함수에 breakpoint를 걸고 xpdf에서 계속 pdf를 여는 과정을 반복하여 다음과 같이 후보가 추려졌다.
🎯 PDFDoc.cc 후보군
PDF 파일을 로드하는 생성자 내부에 진입하는 것에 성공했다.
PDFDoc.cc 소스코드 분석하는 과정file = fopen(fileName1->getCString(), fopenReadMode); file = _wfopen(fileNameU, wfopenReadMode);
이 부분은 PDF 파일을 여는 함수였는데, 실제로 타겟으로는 적합하지 않았다.
그 이유 ⇒ XPDF 프로그램 내에서는 PDF 데이터를 분석하거나 렌더링하는 역할을 하지 않는다. 혹은 간접적인 영향만을 미치는 함수일 가능성이 있다.
str = new FileStream(file, 0, gFalse, 0, &obj);
Stream 생성 함수 (FileStream)
checkHeader();
checkHeader 함수
optContent = new OptionalContent(this); outline = new Outline(catalog->getOutline(), xref);
Optional Content 및 Outline 처리
그리고 타겟으로 가장 적합했던 후보ok = setup(ownerPassword, userPassword);
PDFDoc::setup2(ownerPassword, userPassword, gFalse);
setup 함수였다
그 이유 ⇒- PDF 파일 초기화/ 데이터 분석하는 첫 번째 주요 루틴 담당
- xref(교차 참조 테이블), catalog(카탈로그)를 읽는 행동 함
- PDF 구조를 심층 분석하는 행동 함, 가장 유력한 타겟 함수로 좁혀짐
(참고로 한 프로그램 내에서 target offset은 여러 개가 될 수 있다.)
점점 후보를 좁혀나가다 보니 PDFDOC::setup 또는 PDFDoc::setup2가 타겟 함수로 가장 적합함이 예상되었고, 이들의 디스어셈블리를 분석해 다시 중요한 동작과 그 중에서도 타겟 오프셋과 가장 적절한 함수값을 찾을 수 있었다.0:004> uf xpdf!PDFDoc::setup xpdf!PDFDoc::setup [C:\\Program Files\\xpdf-4.05\\xpdf\\PDFDoc.cc @ 261]: 261 00007ff78f42fa80 48895c2410 mov qword ptr [rsp+10h],rbx 261 00007ff78f42fa85 4889742418 mov qword ptr [rsp+18h],rsi 261 00007ff78f42fa8a 57 push rdi 261 00007ff78f42fa8b 4883ec20 sub rsp,20h 261 00007ff78f42fa8f 498bf8 mov rdi,r8 261 00007ff78f42fa92 488bf2 mov rsi,rdx 261 00007ff78f42fa95 488bd9 mov rbx,rcx 263 00007ff78f42fa98 488b4918 mov rcx,qword ptr [rcx+18h] 263 00007ff78f42fa9c 488b01 mov rax,qword ptr [rcx] 263 00007ff78f42fa9f ff5028 call qword ptr [rax+28h] 266 00007ff78f42faa2 488bcb mov rcx,rbx 266 00007ff78f42faa5 e85340efff call xpdf!ILT+11000(?checkHeaderPDFDocAEAAXXZ) (00007ff78f323afd) 269 00007ff78f42faaa 4533c9 xor r9d,r9d 269 00007ff78f42faad 4c8bc7 mov r8,rdi 269 00007ff78f42fab0 488bd6 mov rdx,rsi 269 00007ff78f42fab3 488bcb mov rcx,rbx 269 00007ff78f42fab6 e84f97efff call xpdf!ILT+33285(?setup2PDFDocAEAAHPEAVGString (00007ff78f32920a) 269 00007ff78f42fabb 85c0 test eax,eax 269 00007ff78f42fabd 754a jne xpdf!PDFDoc::setup+0x89 (00007ff78f42fb09) Branch xpdf!PDFDoc::setup+0x3f [C:\\Program Files\\xpdf-4.05\\xpdf\\PDFDoc.cc @ 270]: 270 00007ff78f42fabf 8b435c mov eax,dword ptr [rbx+5Ch] 270 00007ff78f42fac2 83e802 sub eax,2 270 00007ff78f42fac5 83f801 cmp eax,1 270 00007ff78f42fac8 772d ja xpdf!PDFDoc::setup+0x77 (00007ff78f42faf7) Branch xpdf!PDFDoc::setup+0x4a [C:\\Program Files\\xpdf-4.05\\xpdf\\PDFDoc.cc @ 272]: 272 00007ff78f42faca 4c8d0587e01500 lea r8,[xpdf!string' (00007ff78f58db58)] 272 00007ff78f42fad1 48c7c2ffffffff mov rdx,0FFFFFFFFFFFFFFFFh 272 00007ff78f42fad8 33c9 xor ecx,ecx 272 00007ff78f42fada e87c55efff call xpdf!ILT+16470(?errorYAXW4ErrorCategory_JPEBDZZ) (00007ff78f32505b) 274 00007ff78f42fadf 41b901000000 mov r9d,1 274 00007ff78f42fae5 4c8bc7 mov r8,rdi 274 00007ff78f42fae8 488bd6 mov rdx,rsi 274 00007ff78f42faeb 488bcb mov rcx,rbx 274 00007ff78f42faee e81797efff call xpdf!ILT+33285(?setup2PDFDocAEAAHPEAVGString (00007ff78f32920a) 274 00007ff78f42faf3 85c0 test eax,eax 274 00007ff78f42faf5 7512 jne xpdf!PDFDoc::setup+0x89 (00007ff78f42fb09) Branch xpdf!PDFDoc::setup+0x77 [C:\\Program Files\\xpdf-4.05\\xpdf\\PDFDoc.cc @ 275]: 275 00007ff78f42faf7 33c0 xor eax,eax 293 00007ff78f42faf9 488b5c2438 mov rbx,qword ptr [rsp+38h] 293 00007ff78f42fafe 488b742440 mov rsi,qword ptr [rsp+40h] 293 00007ff78f42fb03 4883c420 add rsp,20h 293 00007ff78f42fb07 5f pop rdi 293 00007ff78f42fb08 c3 ret xpdf!PDFDoc::setup+0x89 [C:\\Program Files\\xpdf-4.05\\xpdf\\PDFDoc.cc @ 284]: 284 00007ff78f42fb09 b908000000 mov ecx,8 284 00007ff78f42fb0e e8f719efff call xpdf!ILT+1285(??2YAPEAX_KZ) (00007ff78f32150a) 284 00007ff78f42fb13 4889442430 mov qword ptr [rsp+30h],rax 284 00007ff78f42fb18 33ff xor edi,edi 284 00007ff78f42fb1a 4885c0 test rax,rax 284 00007ff78f42fb1d 7419 je xpdf!PDFDoc::setup+0xb8 (00007ff78f42fb38) Branch xpdf!PDFDoc::setup+0x9f [C:\\Program Files\\xpdf-4.05\\xpdf\\PDFDoc.cc @ 284]: 284 00007ff78f42fb1f 488b5338 mov rdx,qword ptr [rbx+38h] 284 00007ff78f42fb23 4881c2a0000000 add rdx,0A0h 284 00007ff78f42fb2a 4c8b4330 mov r8,qword ptr [rbx+30h] 284 00007ff78f42fb2e 488bc8 mov rcx,rax 284 00007ff78f42fb31 e86592efff call xpdf!ILT+32150(??0OutlineQEAAPEAVObjectPEAVXRefZ) (00007ff78f328d9b) 284 00007ff78f42fb36 eb03 jmp xpdf!PDFDoc::setup+0xbb (00007ff78f42fb3b) Branch xpdf!PDFDoc::setup+0xb8 [C:\\Program Files\\xpdf-4.05\\xpdf\\PDFDoc.cc @ 284]: 284 00007ff78f42fb38 488bc7 mov rax,rdi xpdf!PDFDoc::setup+0xbb [C:\\Program Files\\xpdf-4.05\\xpdf\\PDFDoc.cc @ 284]: 284 00007ff78f42fb3b 48894348 mov qword ptr [rbx+48h],rax 288 00007ff78f42fb3f b918000000 mov ecx,18h 288 00007ff78f42fb44 e8c119efff call xpdf!ILT+1285(??2YAPEAX_KZ) (00007ff78f32150a) 288 00007ff78f42fb49 4889442430 mov qword ptr [rsp+30h],rax 288 00007ff78f42fb4e 4885c0 test rax,rax 288 00007ff78f42fb51 740e je xpdf!PDFDoc::setup+0xe1 (00007ff78f42fb61) Branch xpdf!PDFDoc::setup+0xd3 [C:\\Program Files\\xpdf-4.05\\xpdf\\PDFDoc.cc @ 288]: 288 00007ff78f42fb53 488bd3 mov rdx,rbx 288 00007ff78f42fb56 488bc8 mov rcx,rax 288 00007ff78f42fb59 e8494aefff call xpdf!ILT+13730(??0OptionalContentQEAAPEAVPDFDocZ) (00007ff78f3245a7) 288 00007ff78f42fb5e 488bf8 mov rdi,rax xpdf!PDFDoc::setup+0xe1 [C:\\Program Files\\xpdf-4.05\\xpdf\\PDFDoc.cc @ 288]: 288 00007ff78f42fb61 48897b50 mov qword ptr [rbx+50h],rdi 292 00007ff78f42fb65 b801000000 mov eax,1 293 00007ff78f42fb6a 488b5c2438 mov rbx,qword ptr [rsp+38h] 293 00007ff78f42fb6f 488b742440 mov rsi,qword ptr [rsp+40h] 293 00007ff78f42fb74 4883c420 add rsp,20h 293 00007ff78f42fb78 5f pop rdi 293 00007ff78f42fb79 c3 ret
PDFDoc::setup 함수의 디스어셈블리 코드 흐름을 확인했는데, 여기서 더 정확하게 타겟 함수로 적합한지 확인했다. 각각의 디스어셈블리를 확인해보면 다음과 같은 항목을 찾아볼 수 있다.
1. 초기화 작업00007ff7`8f42fa80 48895c2410 mov qword ptr [rsp+10h],rbx 00007ff7`8f42fa85 4889742418 mov qword ptr [rsp+18h],rsi
2. PDF 헤더 확인 (checkHeader)00007ff7`8f42faa5 e85340efff call xpdf!ILT+11000(?checkHeaderPDFDocAEAAXXZ)
3. PDF 데이터 분석 및 구조 설정 (setup2)00007ff7`8f42fab6 e84f97efff call xpdf!ILT+33285(?setup2PDFDocAEAAHPEAVGString)
⇒ 이 지점이 바로 가장 적합한 타겟 오프셋의 후보였다.
pdf 파일 구조를 분석하고 복구하는 과정이 포함되어 있고, winafl을 돌릴 때 데이터분석, 취약점 탐지에 가장 적합하다.
1. Optional Content 및 Outline 초기화00007ff7`8f42fb59 e8494aefff call xpdf!ILT+13730(??0OptionalContentQEAAPEAVPDFDocZ)
2. 정상 종료00007ff7`8f42fb79 c3 ret
이런 흐름이 나타난다.
0:000> bp 0x7ff7`8f42fab6 0:000> g
PDF 데이터 분석 및 구조 설정 (setup2)
이 부분에 bp를 걸어서 bp가 걸리는지도 확인했다. 프로그램 내에서 파일을 열고 닫는 행위를 수행했을 때 bp에 이 지점이 걸린다면, 타겟 오프셋의 후보임이 명확해질 것이다.
⚠️ Breakpoint 걸리는지 확인
Breakpoint 0 hit xpdf!PDFDoc::setup+0x36: 00007ff7`8f42fab6 e84f97efff call xpdf!ILT+33285(?setup2PDFDocAEAAHPEAVGString (00007ff7`8f32920a)
xpdf에서 임의의 pdf를 open했을 때 마찬가지로 breakpoint가 걸렸다.
breakpoint가 걸린 지점의 PDFDoc.cc 코드를 확인해보았을 때, 해당 소스코드 내의 setup2 함수에서 bp가 걸린 점을 Windbg에서 확인할 수 있었다.
최종적인 target_offset 값 구해내기
XPDF 모듈의 로드 주소 (xpdf.exe 메모리에 로드된 시작 주소)
lm m xpdf 00007ff78f320000 00007ff78f696000 xpdf xpdf.exe
0x7ff78f320000`
찾아낸 setup2의 호출 지점 주소00007ff7`8f42fab6 e84f97efff call xpdf!ILT+33285(?setup2PDFDocAEAAHPEAVGString) (00007ff7`8f32920a)
00007ff78f32920a
타겟 오프셋 계산 공식타겟 오프셋 = 타겟 함수 주소 - 모듈 로드 주소
즉, 타겟 오프셋은0x7ff7`8f32920a - 0x7ff7`8f320000 = 0x920a
(직접 빌드한 소스코드를 통해 target offset을 구했기 때문에 아마 원본 프로그램에서는 타겟 함수 계산 값이 다르게 나타날 것이다.)
🕷️ WinAFL 퍼징 실행
위에서 구했던 target offset으로 fuzzing이 돌아가는 모습이다.
올바른 경로와 인자 값과 함께 명령어 값을 작성해줬는데 일단 이 타겟 오프셋은 성공했고, 만약 퍼징이 너무 느리게 되거나 하는 등의 문제가 발생할 경우에는 추후 퍼징 옵션을 조금 변경해도 좋을 것 같다.
디버깅 정보가 없는 프로그램의 경우 Windbg, IDA 분석에 필요한 정보가 부족해지기 때문에 fuzzing target offset 값을 찾는 것에 제약이 생긴다. 따라서 추후 이때의 해결 방안에 대해 디버깅 정보 없이 타겟 오프셋을 구할 수 있도록 리버싱 기술을 더 많이 공부해보고 싶고, ASLR 문제에 대해서도 더 나은 해결책을 찾아보고 싶다.
그간의 퍼징 실패 원인 분석
퍼징에 실패했을 때 남겨진 .proc 파일인데, 타임아웃 오류가 발생하면서
WARNING: Target function was never called. Incorrect target_offset?
이라는 문구가 올 확률이 높다. 그 이유는 타겟 오프셋을 잘못 설정했거나, 커버리지 모듈을 잘못 설정했거나, 타겟 모듈을 잘못 설정했거나 하는 이유일 가능성이 크다.
아직 다른 target_offset이 존재하는지에 대해서는 더 알아보아야 할 것 같다. 이전의 실패가 주소값 계산을 잘못 하거나 하는 등의 문제일 수도 있기 때문이다.
또한 PDFDoc.cc 파일 내의 setup2라는 함수에 대해서는 퍼징이 되었지만, PDFDoc 함수 자체의 주소를 target_offset으로 사용했을 때도 timeout과 Incorrect target_offset 문제가 발생했다.
만약 해당 함수나 파일이 PDF 파싱에 관련된 것이 유력하다고 생각할 수 있다면 디스어셈블링을 통해 그 안에 있는 하위 함수나 생성자들, 어떤 함수로 연결이 되는지를 추가로 더 찾아보아야 할 수도 있다.
🔩procmon.exe
추가로 해외 글을 찾아보다가 procmon을 통해 WinAFL의 타겟에 대해 도움을 받은 정보 글이 있어 사용해보았는데, 해당 프로그램은 실시간으로 시스템에서 발생하는 파일, 레지스트리, 프로세스와 같은 활동을 추적한다. 프로그램 필터링 값에 퍼징을 원하는 프로그램을 지정해주고 PDF 파싱과 관련된 함수를 찾을 수 있도록 파일을 열고 닫는 행동을 수행하고 그 주위의 지점을 분석해보았다. 필자는 ReadFile, CreateFile과 같은 동작들의 오프셋 값을 확인할 수 있었다.
해당 프로그램은 Windbg, IDA처럼 디버깅 정보에 의해 제약을 받지 않았다. 따라서 제약이 있는 상황에서 AFL Fuzzing을 돌리고 싶을 때 많은 도움을 받을 수 있는 윈도우 프로그램이 될 수 있을 것으로 보여진다.
해맸던 부분
Breakpoint 0 hit xpdf!PDFDoc::setup: 00007ff78f42fa80 48895c2410 mov qword ptr [rsp+10h],rbx ss:000000aebb9aa978=0000000000000025
Breakpoint 0 hit xpdf!PDFDoc::setup+0x36: 00007ff7`8f42fab6 e84f97efff call xpdf!ILT+33285(?setup2PDFDocAEAAHPEAVGString (00007ff7`8f32920a)
이 두 개는 비슷해보이지만 첫 번째 코드 00007ff78f42fa80 이 값으로는 퍼징이 되지 않는다.
이럴 경우에 함수 내부를 더 분석해보아야 한다. 0x7ff78f42fa80은 xpdf!PDFDoc::setup: 함수의 시작점이지만,
00007ff7`8f42fa95 488bd9 mov rbx,rcx ; 초기화 작업 00007ff7`8f42fa98 488b4918 mov rcx,qword ptr [rcx+18h] ; 특정 메모리 접근 ... 00007ff7`8f42fab6 e84f97efff call xpdf!ILT+33285(?setup2PDFDocAEAAHPEAVGString) ; setup2 호출
이처럼 핵심 로직 setup2는 xpdf!ILT+33285(?setup2PDFDocAEAAHPEAVGString) 부분을 통해 시작된다.
call xpdf!ILT+33285 이후에 PDF 파싱 및 분석과 같은 주요 동작이 실행되기 때문에, 해당 주소 값이 타겟 오프셋 값으로 선정할 수 있는 지점이 된다.
다음글이 없습니다.이전글이 없습니다.댓글