STUDY.md
  • 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 파싱 및 분석과 같은 주요 동작이 실행되기 때문에, 해당 주소 값이 타겟 오프셋 값으로 선정할 수 있는 지점이 된다.
     
     
     
     


     
     
     
     

    댓글