Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FRIDA mode does NOT support multithreading #1605

Open
fuboat opened this issue Dec 20, 2022 · 5 comments
Open

FRIDA mode does NOT support multithreading #1605

fuboat opened this issue Dec 20, 2022 · 5 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@fuboat
Copy link

fuboat commented Dec 20, 2022

Is your feature request related to a problem? Please describe.
It seems that current FRIDA mode cannot catch the basic block hit happening in child thread. It limits FRIDA mode's ability to collect the coverage of binaries which heavily use multithreading. Some program just do almost all the thing in child thread and do nothing in main thread; In this situation, FRIDA mode cannot collect useful coverage information.

Describe the solution you'd like
Is there some way to collect coverage in child thread with FRIDA mode? Maybe it is hard for FRIDA mode due to the limitation of frida itself.

Describe alternatives you've considered
If edge coverage is hard to implement, is there some way to implement basic block coverage and so on?

Additional context
It is easy to prove that current FRIDA mode does not consider the child thread. let's see such a simple C++ program example.cc:

#include <sstream>
#include <iostream>
#include <cstdio>
#include <unistd.h>
#include <thread>
#include <chrono>

int main(int argc, char ** argv) {
    if (argc == 1) {
        // single thread mode when no extra args.
        while (true) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    } else {
        // multi thread mode when any extra args.
        std::thread t([] {
            while (true) {
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }
        });
        t.join();
    }

    return 0;
}

Let's compile the program into a native binary with g++:

g++ example.cc -o example -pthread

Now, Let's test it with FRIDA mode, enabling AFL_FRIDA_INST_TRACE. The results of the following two will be much different: the first one will output continuously, while the second one only output a few and then nothing anymore.

# single thread mode. There will be continuous output of AFL_FRIDA_INST_TRACE.
LD_PRELOAD=/path/to/afl-frida-trace.so AFL_FRIDA_INST_TRACE=1 ./example

# multi thread mode. There will be ONLY severval lines of output of AFL_FRIDA_INST_TRACE, then nothing is printed anymore.
LD_PRELOAD=/path/to/afl-frida-trace.so AFL_FRIDA_INST_TRACE=1 ./example xxx

I think the result is abnormal. Maybe it is the limitation of frida itself. Any ideas?

@vanhauser-thc
Copy link
Member

@WorksButNotTested

@WorksButNotTested
Copy link
Contributor

AFL++ FRIDA mode does only support a single thread right now as that’s all I needed for my purposes. There are a few options though which you could pursue to add multi threading and PRs would be welcome.

If you still wish to fuzz a single thread, but it happens not to be the main thread (e.g. the one which calls main). You could modify main.c to not call the main startup code directly (

__attribute__((visibility("default"))) void afl_frida_start(void) {
), but to accept an additional environment variable to specify an alternative function called by another thread as a point to begin initialisation (and hook using interceptor) since the current implementation only instruments the thread which performs the initialisation.

Alternatively, for all threads to be instrumented, you’d need to modify the portion where stalker is initialised to stalk the other threads too, and then modify the inline instrumentation code to store the previous_pc value in thread local storage instead of a global (although that may well add some performance overhead).

Generally I have taken the approach of writing my harnesses to operate in a single threaded fashion, replacing any IPC with a simple queue and processing the messages on the originating thread.

@vanhauser-thc vanhauser-thc added enhancement New feature or request help wanted Extra attention is needed labels Feb 28, 2023
@skirge
Copy link

skirge commented Mar 15, 2024

I made an attempt to handle this and it works for me, please check if it makes any sense.

@WorksButNotTested
Copy link
Contributor

Is this not equivalent to just setting AFL_ENTRYPOINT for you target or am I missing something?

@skirge
Copy link

skirge commented Mar 18, 2024

I had a program which did the processing in second thread, setting entrypoint using setAflEntryPoint caused everything to hang and this worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants