
이 실험적인 퍼저는 API 인메모리 퍼징을 위해 사용됩니다.
v1.4 Copyright (C) 2020 Andrea Fioraldi [email protected]
Apache License v2.0에 따라 배포됨
이 실험적인 퍼저는 API 인메모리 퍼징을 위해 사용됩니다.
설계는 AFL/AFL++에서 크게 영감을 받았으며 이를 기반으로 합니다.
현재 뮤테이터는 매우 단순하며, AFL의 havoc 및 splice 단계만을 사용합니다.
tests/ 아래의 예제만 테스트했습니다. 이 프로젝트는 진행 중(WIP)이지만, 최소한 GNU/Linux x86_64와 Android x86_64에서 작동하는 것으로 알려져 있습니다.
이를 실행하려면 Frida >= 12.8.1이 필요합니다(pip3 install -U frida). 또한 harness를 컴파일하려면 frida-tools가 필요합니다.
fuzz 라이브러리는 사용자 지정 harness에 임포트한 후 frida-compile로 컴파일하여 frida-fuzzer가 대상 앱에 주입할 agent를 생성해야 합니다.
퍼저의 로직 대부분은 agent에 있습니다.
Harness의 형식은 다음과 같습니다:
var fuzz = require("./fuzz");
var TARGET_MODULE = "test_linux64";
var TARGET_FUNCTION = DebugSymbol.fromName("target_func").address;;
var RET_TYPE = "void";
var ARGS_TYPES = ['pointer', 'int'];
var func_handle = new NativeFunction(TARGET_FUNCTION, RET_TYPE, ARGS_TYPES, { traps: 'all' });
fuzz.target_module = TARGET_MODULE;
var payload_mem = Memory.alloc(fuzz.config.MAX_FILE);
fuzz.fuzzer_test_one_input = function (/* Uint8Array */ payload) {
Memory.writeByteArray(payload_mem, payload, payload.length);
func_handle(payload_mem, payload.length);
}
fuzz.fuzzer_test_one_input은 필수입니다. fuzz.target_module을 지정하지 않으면 실행되는 모든 코드가 계측됩니다.
또한 fuzz.manual_loop_start = true로 설정하면 콜백에서 fuzz.fuzzing_loop()를 직접 호출할 것임을 퍼저에 알릴 수 있습니다. 이 경우 퍼저가 자동으로 루프를 시작하지 않습니다(예: Android 앱에서 버튼을 클릭할 때 퍼징을 시작하려는 경우).
fuzz.init_callback 콜백을 설정하여 퍼저가 시작 준비가 되었을 때 실행할 코드를 지정할 수 있습니다. 예제는 tests/test_java.js를 참조하세요.
fuzz.dictionary는 고전적인 퍼저 사전입니다. 여기에 항목(허용되는 타입: Array, ArrayBuffer, Uint8Array, String)을 추가할 수 있으며, 뮤테이터에서 추가 값으로 사용됩니다. 예제는 tests/test_libxml2.js를 참조하세요.
frida-fuzzer는 다음 인수를 허용합니다:
출력 폴더를 지정하지 않으면 /tmp 아래에 임시 폴더가 생성됩니다.
초기 시드 폴더를 지정하지 않으면 정보가 없는 시드 0000이 시작 시드로 사용됩니다.
로컬 애플리케이션을 퍼징하는 경우, frida-fuzzer 전에 system-config를 실행하여 시스템 파라미터를 조정하고 속도를 높이는 것이 좋습니다.
./frida-fuzzer -spawn ./tests/test_linux64를 실행하면 터미널에 다음과 같은 상태 화면이 표시됩니다:

또한 fuzz/fuzzer.js에 사용자 지정 단계를 쉽게 추가하고 fuzz/index.js의 단계 목록에 추가할 수 있습니다.
퍼저를 사용자 지정하려면 fuzz/config.js를 편집하세요.
변경할 수 있는 변수로는 MAP_SIZE(퍼징하는 코드가 작으면 줄여서 약간의 속도 향상 가능), MAX_FILE(생성되는 입력의 최대 크기), QUEUE_CACHE_MAX_SIZE(큐 캐시 크기를 늘리면 특히 Android에서 속도가 향상됨) 등이 있습니다.
tests에 있는 예제 Android 앱의 네이티브 공유 라이브러리를 퍼징해 보겠습니다.
가상 디바이스에서 루트 권한이 있는지 확인하세요:
host$ adb root
릴리스 페이지에서 Android x86_64용 frida-server를 다운로드하고 adb push를 사용하여 디바이스의 /data/local/tmp 아래에 복사하세요.
셸을 열고 frida-server를 실행하세요:
device# cd /data/local/tmp
device# ./frida-server
이제 에뮬레이터 창에 드래그 앤 드롭하여 테스트 앱 tests/app-debug.apk를 설치하세요.
그런 다음 앱을 엽니다.
frida-compile로 agent 스크립트를 컴파일하세요:
host$ frida-compile -x tests/test_ndk_x64.js -o fuzzer-agent.js
에뮬레이터에서 앱을 엽니다.
다음 명령어로 테스트 앱에 포함된 libnative-lib.so 라이브러리의 test_func 함수를 퍼징하세요:
host$ ./frida-fuzzer -U -o output_folder/ com.example.ndktest1
흥미로운 테스트 케이스와 크래시는 모두 output_folder에 저장됩니다.
즐기세요.

오픈소스 커뮤니티 여러분, 기여하고 싶은 분들을 위해 많은 TODO가 있습니다.
이 기능 중 하나에 대해 궁금한 점이 있으면 Twitter로 DM을 보내주세요.
기능 제안은 Issues 섹션을 이용해 주세요.
| -i 폴더 | 초기 시드가 있는 폴더 |
| -o 폴더 | 중간 시드와 크래시를 저장할 출력 폴더 |
| -U | USB에 연결 |
| -spawn | 단순히 attach하는 대신 spawn 후 attach |
| -script 스크립트 | 스크립트 파일명 (기본값: fuzzer-agent.js) |