/ Hacking

Building a Feedback Driven Fuzzer - Dev Log 3 : Radamsa Integration

Hello again, we are back with our third devlog, today we will talk about how I integrated radamsa as my mutation engine.

My first attempt at this was by forking radamsa for each iteration, meaning that I needed to fork the fuzzed program and also fork radmasa to generate the test case, I felt this is not the best way to do it, so I looked at radamsa options to see if there's something that could help.

I found that you can run radamsa as a server using the following command:
cat input.txt | radamsa --output :5000 -n inf
The above command will open a socket at port 5000, the -n inf means that it will run forever so each time you connect to port it will generate a mutated version of input.txt.

So in my code I use QProcess to fork a radamsa instance for each test case in the input directory and then use that later connect to the port and read mutated data.

The code for forking radamsa is very simple, the following is the run function responsible for forking radamsa using QProcess

void RadamsaInstance::run() {
    //Creating a QProcess, QCoreApplication is the parent.
    mProcess = new QProcess(QCoreApplication::instance());
    QObject::connect( QCoreApplication::instance(), SIGNAL(aboutToQuit()), mProcess, SLOT(kill()));
    //Reading radamsa path from settings.
    //QSettings is cross platform which is aweseme.
    QSettings settings;
    //Constructing radamsa command.
    QString radamsaPath = settings.value("radmsa_path","./Utils/radamsa").toString();
    qDebug()<<radamsaPath;
    QStringList arguments;
    //Arguments for radamsa.
    arguments<<"--output";
    arguments<<":" + QString().number(mPortNumber);
    arguments<<"-n";
    arguments<<"inf";
    qDebug()<<arguments;
    mProcess->start(radamsaPath, arguments);
    if(!mProcess->waitForStarted()) {
        return;
    }
    qDebug()<<mProcess->state();
    mProcess->write(mData);
    if(mProcess->waitForBytesWritten(-1)) {
        mProcess->closeWriteChannel();
        qDebug()<<"done writing";
    }
}

Now to read mutated data, I connect to radamsa using the readSample function, the function uses QTcpScocket.

QByteArray RadamsaInstance::readSample() {
    QTcpSocket socket;
    int iTrial=0;
    int iMaxTrials=200;
    int iTimeOut=20;
    //Retry for 200*20ms (4 seconds).
    do {
        socket.connectToHost("127.0.0.1",mPortNumber);
    } while (!socket.waitForConnected(iTimeOut) && ++iTrial < iMaxTrials);

    if(socket.waitForReadyRead(-1)) {
        return socket.readAll();
    } else {
        qDebug()<<"Fail";
        return QByteArray();
    }
}

The above code is self explanatory, the while loop is added to make sure we can connect to the socket, the need for this is because of timing issues since the code is faster than the socket opening so the first few iteration failed to connect to radamsa and read data so I had to modify the code to retry reading until the connection is successful.

for simplicity I created a class called RadamsaManager which keeps track of all radamsa instances and allows you to get a radamsa instance using the input file name, so internally it has a QMap with file name as the key and the RadamsaInstance as the value.

See you later, I am currntly finalizing the GUI, then I will test it against some applications so wish me luck.

Buy Me a Coffee at ko-fi.com
Building a Feedback Driven Fuzzer - Dev Log 3 : Radamsa Integration
Share this

Subscribe to Fady's Technical Blog