Git Product home page Git Product logo

frida-fuzzer's Introduction

Frida API Fuzzer

v1.4 Copyright (C) 2020 Andrea Fioraldi [email protected]

Released under the Apache License v2.0

This experimental fuzzer is meant to be used for API in-memory fuzzing.

The design is highly inspired and based on AFL/AFL++.

ATM the mutator is quite simple, just the AFL's havoc and splice stages.

I tested only the examples under tests/, this is a WIP project but is known to works at least on GNU/Linux x86_64 and Android x86_64.

You need Frida >= 12.8.1 to run this (pip3 install -U frida) and frida-tools to compile the harness.

Usage

The fuzz library has to be imported into a custom harness and then compiled with frida-compile to generate the agent that frida-fuzzer will inject into the target app.

The majority of the logic of the fuzzer is in the agent.

A harness has the following format:

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 is mandatory. If you don't specify fuzz.target_module, all the code executed will be instrumented.

You can also set fuzz.manual_loop_start = true to tell the fuzzer that you will call fuzz.fuzzing_loop() in a callback and so it must not call it for you (e.g. to start fuzzing when a button is clicked in the Android app).

The callback fuzz.init_callback can be set to execute code when the fuzzer is ready to begin. See tests/test_java.js for an example.

fuzz.dictionary is a classic fuzzer dictionary, an array in which you can add items (accepted types are Array, ArrayBuffer, Uint8Array, String) that are used as additional values in the mutator. See tests/test_libxml2.js for an example.

frida-fuzzer accepts the following arguments:

-i FOLDER Folder with initial seeds
-o FOLDER Output folder with intermediate seeds and crashes
-U Connect to USB
-spawn Spawn and attach instead of simply attach
-script SCRIPT Script filename (default is fuzzer-agent.js)

If you don't specify the output folder, a temp folder is created under /tmp. If you don't specify the folder with the initial seed, an uninformed seed 0000 is used as starting seed.

If you are fuzzing a local application, you may want to execute system-config before frida-fuzzer to tune the parameters of your system and speed-up the things.

Running ./frida-fuzzer -spawn ./tests/test_linux64 you will see something like the following status screen on your terminal:

screen

You can also easily add a custom stage in fuzz/fuzzer.js and add it to the stages list in fuzz/index.js.

To customize the fuzzer, edit fuzz/config.js. The variables that you may want to change are MAP_SIZE (If the code that you are fuzzing is small you can reduce it and gain a bit of speed), MAX_FILE (the maximum size of generated input) and QUEUE_CACHE_MAX_SIZE (increase the queue cache size for more speed, especially on Android).

Example

Let's fuzz the native shared library in the example Android app in tests.

Make sure you have root on your virtual device:

host$ adb root

Download the Android x86_64 frida-server from the repo release page and copy it on the device under /data/local/tmp (use adb push).

Start a shell and run the frida-server:

device# cd /data/local/tmp
device# ./frida-server

Now install the test app tests/app-debug.apk using the drag & drop into the emulator window.

Then, open the app.

Compile the agent script wiht frida-compile:

host$ frida-compile -x tests/test_ndk_x64.js -o fuzzer-agent.js

Open the app in the emulator.

Fuzz the test_func function of the libnative-lib.so library shipped with the test app with the command:

host$ ./frida-fuzzer -U -o output_folder/ com.example.ndktest1

Interesting testcases and crashes are both saved into output_folder.

Enjoy.

screen1

TODO

Hey OSS community, there are a lot of TODOs if someone wants to contribute.

  • Java code fuzzing (waiting for additional exposed methods in frida-java-bridge, should be easy, almost done)
  • splice stage (merge two testcase in queue and apply havoc on it)
  • support dictionaries (and so modify also havoc)
  • seed selection
  • inlined instrumentation for arm64
  • performance scoring (explore schedule of AFL)
  • structural mutator (mutate bytes based on a grammar written in JSON)
  • CompareCoverage (sub-instruction profiling to bypass fuzzing roadblocks)
  • rewrite frida-fuzzer in C with frida-core to be able to run all stuff on the mobile device

If you have doubt on one of this featues feel free to DM me on Twitter.

For features proposals, there is the Issues section.

frida-fuzzer's People

Contributors

andreafioraldi avatar cubarco avatar vanhauser-thc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

frida-fuzzer's Issues

how to run fuzzer

in the docs, there's the line to compile the fuzzer tst_ndk_x64.js
host$ frida-compile -x tests/test_ndk_x64.js -o fuzzer-agent.js it outputs a fuzzer-agent.js

and then to run it

host$ ./frida-fuzzer -U -o output_folder/ com.example.ndktest1

we've compiled the .js file and generated the fuzzer-agent.js but when we run ./frida-fuzzer how does it know what is the right harness to run with frida-fuzzer if the fuzzer-agent was never passed in the command line?

ReferenceError: require is not defined

Heyia (posting on the right project!)

Been trying to run the demo linux one, however am getting:

python3 ../frida-fuzzer -script test_linux_x64.js -spawn ./test_linux64
 >> Temporary output folder : /tmp/frida_fuzz_out_fq7ezsj1
{'type': 'error', 'description': 'ReferenceError: require is not defined', 'stack': 'ReferenceError: require is not defined\n    at /script1.js:1:12', 'fileName': '/script1.js', 'lineNumber': 1, 'columnNumber': 12}
 ************** FUZZER ERROR! **************
  line 1: ReferenceError: require is not defined
  JS stacktrace:

ReferenceError: require is not defined
    at /script1.js:1:12

 >> Press Control-C to exit...
script is destroyed
^C

I added an extra print statement to see the whole message. Not sure where this script1.js
comes from, but include("./fuzz") has an index.js which includes all the modules.
Am I missing something here? Latest frida version, 12.8.0!

access-violation when calling native function (arm, android)

hello, I would appreciate any help on this one.

I am basically targeting a function X, in module Y (arm native library), used by an APK Z, with frida-server running in a real android device.

I want to fuzz the second argument of target function X, and only this one, leave the other arguments (1, 3) untouched. This function X take 3 arguments.

my code is as following:

var fuzz = require("../fuzz");
fuzz.target_module = Y;
fuzz.manual_loop_start = true;

var arg0 = null;
var buffer2 = null;

Interceptor.attach (X,{
            onEnter: function (args) {
              console.log("[+] X() called with  \t= " + args[0] + ", "+ args[1] + ", " + args[2]);

              arg0 = args[0];
              buffer2 = args[2];

              fuzz.fuzzing_loop();
            },

            onLeave: function (retval) {
                console.log("[+] X() called has a return value of \t= " + retval);
                return retval;
        }
});

fuzz.fuzzer_test_one_input = function (/* Uint8Array */ payload) {

            var payload_mem = payload.buffer.unwrap();
            X(arg0, payload_mem, buffer2);
}

When run, I can see the passed argument are valid, only that when X(arg0, payload_mem, buffer2); is called, I get access violation :


  ============= CRASH FOUND! =============
    type: access-violation
    read at: 0x4614ad79


not sure what that address corresponds to.

Question 1 : is this the right way use this tool, to only fuzz one of the arguments passed to a function
Question 2: confused by the access-violation, it seems if I call any function inside fuzzer_test_one_input, with arguments, I get this access-violation.

thanks for the help!

process not found error

I'm running on windows and i'm just getting this error:
frida.ProcessNotFoundError: unable to find process with name 'com.example.ndktest1'
Tested on Nox Emulator and Galaxy A12 (both are root devices) and get the same error.

arm64 fuzzer crash

Getting the following error when trying to fuzz a function on a arm64 android.

Traceback (most recent call last):
  File "./frida-fuzzer", line 447, in <module>
    script.exports.loop()
  File "/usr/local/lib/python3.7/site-packages/frida/core.py", line 401, in method
    return script._rpc_request('call', js_name, args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/frida/core.py", line 26, in wrapper
    return f(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/frida/core.py", line 333, in _rpc_request
    raise result[2]
frida.core.RPCException: TypeError: Cannot read property 'buf' of undefined
    at Object.exports.next (fuzz/queue.js:46:1)
    at Object.exports.fuzzing_loop (fuzz/index.js:112:1)
    at Object.rpc.exports.loop (fuzz/index.js:127:1)
    at handleRpcMessage (frida/runtime/message-dispatcher.js:49:1)
    at handleMessage (frida/runtime/message-dispatcher.js:29:1)

fuzzer Crash after getting a crash

I tested in android arm64. After got a crash, the fuzzer crash too.

` >> Saving at '.\output\crash_havoc_access-violation_1594018160'

Press Control-C to exit...
Error: access violation accessing 0x0
at Object.fuzz.fuzzer_test_one_input (tests/test_ndk_x64.js:23:1)
at runner (fuzz/index.js:90:1)
at common_fuzz_stuff (fuzz/stages.js:44:1)
at fuzz_havoc (fuzz/stages.js:186:1)
at exports.havoc_stage (fuzz/stages.js:194:1)
at Object.exports.fuzzing_loop (fuzz/index.js:162:1)
at Object.rpc.exports.loop (fuzz/index.js:182:1)
at frida/runtime/message-dispatcher.js:13:1
at c (frida/runtime/message-dispatcher.js:23:1)`

Testing frida-fuzzer on Windows

  • Vulnerable program (testbinary.c)
#include <stdio.h>
#include <string.h>
#include <windows.h>
__declspec( dllexport ) void lol(char* b)
{
        char buffer[1337];
        strcpy(buffer, b);
}

int main(int argc, char** argv)
{
        lol(argv[1]);
}
  • The fuzzer
var fuzz = require("./fuzz");

var TARGET_MODULE = "testbinary.exe"
var TARGET_FUNCTION = DebugSymbol.fromName("lol").address;
var RET_TYPE = "void";
var ARGS_TYPES = ['pointer', 'uint'];

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(payload) {      
        Memory.writeByteArray(payload_mem, payload, payload.length);
        func_handle(payload_mem, payload.length);
}
  • Compile to fuzzer-agent
    frida-compile myfuzz.js -o fuzzer-agent.js

  • RUN
    python frida-fuzzer -spawn testbinary.exe

  • Output

  ╔═════════════╤═════════════════════════════════════════════════════════╗
 ║ target      │ testbinary.exe                                          ║
 ║ execs       │ 11331805                                                ║
 ║ speed       │ 18909 exec/s                                            ║
 ║ uptime      │ 0h-10m-0s                                               ║
 ║ last path   │ 0h-10m-0s                                               ║
 ║ map density │ 0.05 %                                                  ║
 ║ current     │ 3                                                       ║
 ║ queue size  │ 6                                                       ║
 ║ favoreds    │ 5                                                       ║
 ║ pending fav │ 5                                                       ║
 ║ last stage  │ splice-15                                               ║
 ║ output path │ C:\Users\Hp\AppData\Local\Temp\frida_fuzz_out_7a_huk1j  ║
 ╚═════════════╧═════════════════════════════════════════════════════════╝

timeout support

Hi,
AFL programs normally read input from stdin, is it possible for the frida-fuzzer to spawn the program on host and write to the stdin on target in order the test program can continue from read(0...)?

ReferenceError: require is not defined

============= FUZZER ERROR! =============
line 1: ReferenceError: require is not defined
JS stacktrace:

ReferenceError: require is not defined
at tests/test_ndk_x64.js:1:14

Press Control-C to exit...

Fork server not enabled

Trying to spawn the fuzzer, but found that target process pid keeps the same.
Check the code, forkserver is not developed. WIP?

Call for testers: arm64 Android and iOS

I need testers for these two platforms, especially iOS cause IDK if it really runs on iOS (bu should) cause I don't have any Apple device.
You can comment here if you are interested, TY.

Adding new mutator i.e radamsa

Hi!

Can you guide, give some tips how to add a new mutator?

What files and functions need to be modified?

Here is my attempt (with debugs):

https://github.com/marcinguy/frida-fuzzer/tree/radamsa

Somehow radamsa_target is never called.

I tried to figure it out on my own, but did not succeed.

I want to add radamsa via radamsa binary and exec it. I know it will be performance hit, but still want to try it.

I still ask however, what would be the best approach to add radamsa?

Thanks,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.