1

我有一个程序可以处理一定大小的数据包,但需要大量数据包才能进行任何有意义的输出。

我目前通过从 AFL 接收数据包并在系统中运行它必要的次数来使用 AFL 模糊我的程序。

这并不理想,因为我多次重复使用相同的变形数据包,所以我切换到使用 AFL 的持久模式,它通过管道连续向我发送数据。

问题是,AFAICT,这种模式假设每个输入都是独立运行的,我想创建一个依赖于一系列输入的崩溃。

模糊我的程序的正确方法是什么?

4

1 回答 1

0

您应该将从 AFL 接收到的数据作为数据包序列进行处理。这是 AFL 持久模式示例(已删除注释):

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;
}

您的案例的修改示例是:

//#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 不适用于大输入大小 - 尝试修改所有位需要大量时间。当FIXED_PACKET_SIZE*NUM_PACKETS_TO_RECEIVE大时,您应该尽量不要将模糊数据用于数据包部分,这不太可能导致错误。

当 AFL 修改您的测试数据大小时,可能会出现另一个问题 - 它可以针对某些输入突变这样做。您的read电话应处理这些情况。

于 2021-01-23T13:18:02.860 回答