Using AFL's persistent mode to fuzz large amount of repetitive data

530 Views Asked by At

I have a program that processes packets of certain size but require a large amount of them for any meaningful output.

I currently fuzz my program with AFL by receiving a packet from AFL and running it through the system the necessary amount of times.

This is not ideal, since I reuse the same deformed packet multiple times, so I switched to using AFL's persistent mode, wherein it sends me data through a pipe continuously.

The problem is that, AFAICT, this mode assumes that each input is run in isolation, and I want to create a crash that is dependent on a series of inputs.

What is the correct way to fuzz my program?

1

There are 1 best solutions below

0
On

You should handle the data received from AFL as a sequence of packets. This is AFL persistent mode example (comments are stripped):

int main(int argc, char** argv) {
  char buf[100];
  while (__AFL_LOOP(1000)) {
    memset(buf, 0, 100);
    read(0, buf, 100);

    if (buf[0] == 'f') {
      printf("one\n");
      if (buf[1] == 'o') {
        printf("two\n");
        if (buf[2] == 'o') {
          printf("three\n");
          if (buf[3] == '!') {
            printf("four\n");
            abort();
          }
        }
      }
    }
  }
  return 0;
}

Modified example for your case would be:

//#define FIXED_PACKET_SIZE       set to your packet size, assuming all packets have same size
//#define NUM_PACKETS_TO_RECEIVE  set to number of packets you want to receive to get meaningfull output

int main(int argc, char** argv) {
  char buf[FIXED_PACKET_SIZE*NUM_PACKETS_TO_RECEIVE];
  while (__AFL_LOOP(1000)) {
    memset(buf, 0, FIXED_PACKET_SIZE*NUM_PACKETS_TO_RECEIVE);
    read(0, buf, FIXED_PACKET_SIZE*NUM_PACKETS_TO_RECEIVE);

    unsigned curPacket = 0;
    while (curPacket < NUM_PACKETS_TO_RECEIVE) {
      if (buf[curPacket*FIXED_PACKET_SIZE] == 'f') {
        printf("one\n");
        if (buf[curPacket*FIXED_PACKET_SIZE+1] == 'o') {
          printf("two\n");
          if (buf[curPacket*FIXED_PACKET_SIZE+2] == 'o') {
            printf("three\n");
            if (buf[curPacket*FIXED_PACKET_SIZE+3] == '!') {
              printf("four\n");
              abort();
            }
          }
        }
      }
      curPacket ++;
    }
  }
  return 0;
}

AFL works bad for big input sizes - trying to modify all bits takes enormous time. When FIXED_PACKET_SIZE*NUM_PACKETS_TO_RECEIVE is big, you should try not to use fuzzed data for packet parts, that will unlikely result in errors.

Another problem can arise when AFL modifies your test data size - it can do so for some input mutations. Your read call should handle these cases.