1nzag

[winAFL] winAFL DynamoRIO 관련 분석

fuzzer

*dynamoRIO

 

dynamoRIO option: 기존 인자를 파싱하는 opt_arg 함수에 -D 옵션 추가. DynamoRIO (drrun.exe)를 사용하기 위해 해당 파일의 path 지정하는 변수이다.

 

DynamoRIO option: 해당 DynamoRIO 실행파일에 넣어줄 인자를 따로 받는 구간이 존재한다.

 

 

 

해당 인자는 dynamorio_dir 전역변수에 저장되며, target 을 실행시킬 때 해당 인자를 drrun.exe에 전달해준다.

 

 

 

이때 -c option (-client) 에 winafl.dll 이 들어가는데, 이는 winafl.c 으로부터 컴파일되는 dll 파일이다.

dynamoRIO 는 사용자와 interact 하기 위해 client 를 지정할 수 있는데, 이를 지정해 주는 옵션이다.

 

 

이 클라이언트에 커스터마이징한 클라이언트 winafl.dll 을 넣음으로써 afl-fuzz 와 drrun.exe가 서로 interact 하며 작동될 수 있다.

 

이 둘은 서로 named pipe 로 통신한다.

관련된 대표적 함수는 WriteCommandFromPipe() 와 ReadCommandFromPipe() 함수임 해당 파이프라인은 Create_target_process() 함수에서 target을 실행시킬 때 생성시킨다.

 

 

다음은 run_target() 함수에서 파이프라인에 command 를 보내는 부분이다.

 

다음은 winafl.c 에서 파이프를 통해 메시지를 읽고 쓰는 함수다.

 

 

이러한 command 는 F, Q, P, K 총 4가지이다.

 

F: afl-fuzz가 winafl.dll에게 퍼징을 시작한다는 신호를 보내는 command

Q: afl-fuzz가 winafl.dll에게 process exit 하라는 신호를 보내는 command

 

P: winafl.dll 이 afl-fuzz 에게 프로그램 사이클을 끝냈다고 신호를 보내는 command

K: winafl.dll 이 afl-fuzz 에게 프로그램 사이클을 시작한다고 신호를 보내는 command

 

또하나로, drrun의 winafl.dll 이 coverage를 afl-fuzz 에게 전달할 때는 shared memory를 사용한다.

 

 

 

커버리지를 등록하는 알고리즘은 두가지가 있다. 그 두가지는 다음과 같다.

 

    1. bb coverage
    2. edge coverage

 

두 알고리즘을 설명하기 전에 먼저 dynamorio에서 어떠한 인자(변수)를 참고하는지 알 필요가 있다.

 

module_data_t : 로드한 모듈(바이너리)의 정보를 담고 있는 구조체. 그 중 module_data_t 의 start 는 해당 바이너리의 start_address 를 담고 있다. (엔트리 포인트를 담고 있다고 생각하면 된다.)

 

app_pc: 특정 pc (program counter)를 지정하는 변수명

 

dr_fragment_app_pc(): 해당 테그가 존재하는 pc 를 반환한다.

 

drmgr_register_bb_instrumentation_event:

Registers callback functions for the second and third instrumentation stages: application analysis and instrumentation insertion. drmgr will call func as the second of four instrumentation stages for each dynamic application basic block.

 

라고 적혀있는데 instrument 가 진행될때마다 call 되는 callback 함수라고 보면 될 것 같다. (정확하지 않음)

 

winafl.dll 은 로드 된 후 메인 함수에서 옵션에 따라 coverage를 등록하는 함수를 instrument가 진행될 때마다 callback 될 수 있도록 한다.

 

 

 

bb coverage:

instrument가 진행되면 그 때의 pc와 엔트리포인트의 차이를 구해 그 거리를 공유메모리 내의 테이블에 등록한다.

 

이때 start_pc는 다음으로 구한다.

 

 

edge coverage:

처음엔 bb coverage와 마찬가지로 엔트리포인트와 해당 pc 와의 거리를 구하지만 그 전의 거리값과 특정 연산을 한 후 그에 해당하는 테이블에 값을 더한다.

 

왜 이러한 차이를 두는 지는 모르겠지만 edge는 bb와 다르게 전에 있었던 pc카운터를 활용하기때문에 coverage를 더 정확히 구분할 듯 하다.

 

 

 

'fuzzer' 카테고리의 다른 글

[WinAFL] WinAFL 퍼저 요약  (1) 2020.04.20

[WinAFL] WinAFL 퍼저 요약

fuzzer
  1. WinAFL:

윈도우에서 동작할 수 있게 만든 AFL 퍼저. 기존 AFL 퍼저는 리눅스 환경에서 만들어졌으나 윈도우에서는 구조상의 차이 (instrument, forkserver 등) 에 쉽게 AFL 을 돌릴 수 없었음. 이후 윈도우에서 AFL 을 구동시킬 수 있게 하기 위해 만든 것이 WinAFL

 

WinAFL 의 특징은 크게 다음과 같이 나눌 수 있음

 - 윈도우 환경에서 AFL을 돌릴 수 있음

 - 블랙박스 퍼징이 가능함 **

 - 서버를 퍼징하는 것이 가능함(있는 기능이지만 아직 공부 안했음)

 

WinAFL 은 다음의 3가지 중 하나의 instrument 를 사용해 블랙박스 퍼징 및 경로(path) 추적을 가능하게 함

 - DynamoRIO

 - IntelPT

 - Syzygy

 

보통 WinAFL을 사용할 때는 DynamoRIO가 범용성이 높고 접근성이 높기 때문에 DynamoRIO 를 사용한다.

 

  1. DynamoRIO:

DynamoRIO 는 프로그램이 실행되는 동안 프로그램의 모든 부분에서 코드 변환을 지원하는 런타임코드 조작 시스템임. 따라서 이 특징을 이용해 AFL 에서 컴파일 할 때 추적 코드를 삽입하는 과정을 WinAFL은 블랙박스에서도 적용 할 수 있도록하게 함.

하지만 이 instrument 를 사용하면 퍼징하는 시간 전체는 느리다는 단점이 있음

 

  1. WinAFL 컴파일

WinAFL 컴파일을 위해서는 다음과 같은 컴파일 툴 및 소스가 필요하다.

 - WinAFL 코드

 - VC 컴파일러 (Visual Studio cmake)

 - DynamoRIO 코드

 

WinAFL 소스를 다운로드 한 뒤에 그 디렉토리 내부에서 다음과 같은 명령어를 VisualStudio 명령 프롬프트로 실행시켜 컴파일한다.

mkdir build32
cd build32
cmake -G"Visual Studio 15 2017" .. -DDynamoRIO_DIR=..\path\to\DynamoRIO\cmake -DINTELPT=1
cmake --build . --config Release

 

출처: <https://github.com/googleprojectzero/winafl>

 

64비트로 컴파일 하기 위해서는 -G 옵션에 Win64 아키텍쳐를 추가하고 IntelPT를 사용하지 않는다면 -DINTELPT=1 옵션을 제거한다.

 

  1. WinAFL 옵션

WInAFL 을 사용할 때는 옵션을 다음과 같이 준다.

afl-fuzz [afl 옵션] -- [DynamoRIO 옵션] -- [타겟 프로그램]

 

Afl 옵션은 다음과 같다.

 - -i : testcase 디렉토리

 - -o : output 디렉토리

 - -D : DynamoRIO bin 디렉토리

 - -t : 타임아웃

위 네 가지 옵션은 필수로 줘야 하는 옵션이다. 그 외에 옵션을 더 보고 싶으면 아래 링크를 확인하면 된다.

https://github.com/googleprojectzero/winafl

 

DynamoRIO 옵션은 다음과 같다.

 - -nargs : 프로그램을 실행시킬 때 들어가는 인자의 갯수

 - -covtype : 커버리지를 등록하는 타입

 - -dry-run :  드라이 런 모드로 돌릴 때 사용하는 옵션

 - -coverage_module : 커버리지를 등록하는 대상을 쓰는 옵션. 프로그램이 사용하는 dll

    경로를 등록하고 싶으면 dll 을 추가한다.

 - -target_module : persistant 모드를 사용하고 싶을 때 대상이 되는 코드가 들어있는

    타겟을 쓴다. target_offset 을 무조건 같이 써줘야 한다.

 - -target_offset : persistant 모드를 사용하고 싶을 때 대상이 되는 코드의 주소

 

위 옵션들은 대표적인 옵션들이고 추가 옵션은 위 링크를 통해 확인할 수 있다.

 

WinAFL을 사용하는 예시는 다음과 같다.

afl-fuzz.exe -i input_dir -o ouput_dir -t 10000 -D DynamoRIO_DIR\bin32 -- -covtype edge -coverage_module A.dll -coverage_module B.dll -nargs 2 -target_module target.exe -target_offset 0x1234566 -- target.exe @@

 

  1. Persistant mode

서버 프로그램이나 지속적으로 실행되는 프로그램의 경우 퍼징을 할때 굳이 프로그램을 새로 실행시켜가며 할 필요가 없다. 따라서 프로그램을 켜놓은 상태로 입력값만을 넣어주면서 퍼징하는 방법이 Persistant mode 이다.

Persistantmode 를 사용하기 위해서는 대상 코드에 다음과 같은 조건이 있어야 한다.

 

 - inputfile을 open 해야 한다.

 - 해당 파일의 내용을 파싱해야 한다

 - 파일을 close 해야 한다.

 - 정상적으로 리턴해야 한다.

 

해당 코드가 있으면 해당 코드의 시작지점의 주소를 target_offset 으로 설정해 Persistant mode fuzzing 을 할 수 있다.

 

Ex>

void OpenAndParse()

{

FILE *fp = fopen("input", "rb");

char c;

while(fgetc() != EOF)

{

c ^= 0x33;

}

 

fclose(fp);

return 0;

}        

다음과 같은 함수가 있을 때 target_offset 을 함수의 시작지점으로 놓으면 WinAFL 은 리턴하는 지점을 jmp target_offset 으로 패치하여 해당 부분을 무한루프로 돌며 실행하게 해준다.

따라서 프로세스는 그대로 돌아가게 유지하면서 입력값을 읽고 파싱하는 부분만 골라 퍼징할 수 있게 해준다.

 

이러한 모드는 퍼징의 속도를 늘리고 효율적인 퍼징을 할 수 있게 해준다.

 

그 외에 Custom mutate, server fuzzing (Network fuzzing)의 기능이 있다.

 

'fuzzer' 카테고리의 다른 글

[winAFL] winAFL DynamoRIO 관련 분석  (1) 2020.06.15

PDF 자바스크립트 추출

rev

pdfinfo -js 


모든 코드를 추출하고 싶다면 peepdf 이용


https://github.com/jesparza/peepdf


https://stackoverflow.com/questions/29342542/how-can-i-extract-a-javascript-from-a-pdf-file-with-a-command-line-tool

'rev' 카테고리의 다른 글

[IDA] C++ decompile failure : call analysis failed  (0) 2018.09.03
[Python] gmpy invert, divm (rctf 2018 babyre2)  (0) 2018.08.06
[IDA] 자주쓰는 IDA 단축키  (0) 2018.08.01