AFLNet定制协议

AFLNet定制协议:
最近需要针对协议扩展一下AFLNet,因此我打算根据官方文档进行修改。按照官方页面的说明,如果需要扩展到其他协议,那么需要在aflnet.h和aflnet.c中定义extract_requests_*和extract_response_codes_*函数(*表示需要定制的协议名称)。
本篇来分析一下aflnet.h中的结构体。
在aflnet.h中定义了三个结构体以及两个枚举量enum,我们来挨个分析。

typedef struct {
	int start_byte;
	int end_byte;
	char modifiable;
	unsigned int *state_sequence;
	unsigned int state_count;
} region_t;

region_t *Regions保存了发完被测服务器的消息信息。其中,start_byte是开始的比特,end_byte是结束的比特,modifiable是可修改的flag信息, *state_sequence指向保存的从服务器反馈的状态信息,state_count是state_sequence中保存的状态数量。

typedef struct {
  char *mdata; /* Buffer keeping the message data */
  int msize;   /* Message size */
} message_t;

其中,mdata指向被保存的message数据,msize是message的长度。

typedef struct {
  u32 id;                     /* state id */
  u8 is_covered;              /* has this state been covered */
  u32 paths;                  /* total number of paths exercising this state */
  u32 paths_discovered;       /* total number of new paths that have been discovered when this state is targeted/selected */
  u32 selected_times;         /* total number of times this state has been targeted/selected */
  u32 fuzzs;                  /* Total number of fuzzs (i.e., inputs generated) */
  u32 score;                  /* current score of the state */
  u32 selected_seed_index;    /* the recently selected seed index */
  void **seeds;               /* keeps all seeds reaching this state -- can be casted to struct queue_entry* */
  u32 seeds_count;            /* total number of seeds, it must be equal the size of the seeds array */
} state_info_t;

该结构体主要包含了协议状态的相关信息,如状态id,该状态是否被覆盖(可用于计算模糊测试的覆盖度),经过该状态的路径数量,当该状态被选中时扩展的新路径数量,该状态被选中的数量,生成的测试数量,保存到过该状态的种子以及全部种子数量。

enum {
  /* 00 */ PRO_TCP,
  /* 01 */ PRO_UDP
};

enum {
  /* 00 */ INVALID_SELECTION,
  /* 01 */ RANDOM_SELECTION,
  /* 02 */ ROUND_ROBIN,
  /* 03 */ FAVOR
};

两个枚举量分别定义了使用的传输层协议和种子选择算法。

接下来我们分析一下aflnet.c里面的extract_request_*和extract_response_codes_*函数。

具体分析一下关于smtp协议的两个函数。

region_t* extract_requests_smtp(unsigned char* buf, unsigned int buf_size, unsigned int* region_count_ref)
{
   char *mem;
  unsigned int byte_count = 0;  //消息包中正指向的字符顺序
  unsigned int mem_count = 0;
  unsigned int mem_size = 1024;
  unsigned int region_count = 0;
  region_t *regions = NULL;
  char terminator[2] = {0x0D, 0x0A}; //终止符,分别为/r和/n,smtp通过/r/n结束。

  mem=(char *)ck_alloc(mem_size);

  unsigned int cur_start = 0;
  unsigned int cur_end = 0;
  while (byte_count < buf_size) {

    memcpy(&mem[mem_count], buf + byte_count++, 1); //从buf+byte_count++所指向的内容中取1字节复制到mem[mem_count]中

    //Check if the last two bytes are 0x0D0A
    if ((mem_count > 1) && (memcmp(&mem[mem_count - 1], terminator, 2) == 0)) {
    // 创造一个新的region
      region_count++;
      regions = (region_t *)ck_realloc(regions, region_count * sizeof(region_t));
      regions[region_count - 1].start_byte = cur_start;
      regions[region_count - 1].end_byte = cur_end;
      regions[region_count - 1].state_sequence = NULL;
      regions[region_count - 1].state_count = 0;
    // 到下一个数据包,重新定义消息的开始和结束
      mem_count = 0;
      cur_start = cur_end + 1;
      cur_end = cur_start;
    } else {
      mem_count++;
      cur_end++;

      //Check if the last byte has been reached
      if (cur_end == buf_size - 1) {
      // 创造新的区域
        region_count++;
        regions = (region_t *)ck_realloc(regions, region_count * sizeof(region_t));
        regions[region_count - 1].start_byte = cur_start;
        regions[region_count - 1].end_byte = cur_end;
        regions[region_count - 1].state_sequence = NULL;
        regions[region_count - 1].state_count = 0;
        //退出while循环
        break;
      }

      if (mem_count == mem_size) {
        //enlarge the mem buffer
        mem_size = mem_size * 2;
        mem=(char *)ck_realloc(mem, mem_size);
      }
    }
  }
  if (mem) ck_free(mem);

  //in case region_count equals zero, it means that the structure of the buffer is broken
  //hence we create one region for the whole buffer
  if ((region_count == 0) && (buf_size > 0)) {
    regions = (region_t *)ck_realloc(regions, sizeof(region_t));
    regions[0].start_byte = 0;
    regions[0].end_byte = buf_size - 1;
    regions[0].state_sequence = NULL;
    regions[0].state_count = 0;

    region_count = 1;
  }

  *region_count_ref = region_count;
  return regions;
}

该函数提取了SMTP协议的requests,即由客户端发出的消息。
当一条消息包结束(遇到终止符)时创建一个新的region,并且重新定义消息的开始和结尾。
如果没有遇到终止符,则继续往后数,直到最后一个字节,创建新的region,同时退出while循环。
如果一直没有创建region,则说明缓存区的结构出问题了,为整个缓存都创建一个region。

unsigned int* extract_response_codes_smtp(unsigned char* buf, unsigned int buf_size, unsigned int* state_count_ref)
{
  char *mem;
  unsigned int byte_count = 0;
  unsigned int mem_count = 0;
  unsigned int mem_size = 1024;
  unsigned int *state_sequence = NULL;
  unsigned int state_count = 0;
  char terminator[2] = {0x0D, 0x0A};  //终止符

  mem=(char *)ck_alloc(mem_size);
  
  //初始化状态机
  state_count++;
  state_sequence = (unsigned int *)ck_realloc(state_sequence, state_count * sizeof(unsigned int));
  state_sequence[state_count - 1] = 0;

  while (byte_count < buf_size) {
    memcpy(&mem[mem_count], buf + byte_count++, 1);

    if ((mem_count > 0) && (memcmp(&mem[mem_count - 1], terminator, 2) == 0)) {
      //Extract the response code which is the first 3 bytes
      char temp[4];
      memcpy(temp, mem, 4);
      temp[3] = 0x0;
      unsigned int message_code = (unsigned int) atoi(temp);

      if (message_code == 0) break;

      state_count++;
      state_sequence = (unsigned int *)ck_realloc(state_sequence, state_count * sizeof(unsigned int));
      state_sequence[state_count - 1] = message_code;
      mem_count = 0;
    } else {
      mem_count++;
      if (mem_count == mem_size) {
        //enlarge the mem buffer
        mem_size = mem_size * 2;
        mem=(char *)ck_realloc(mem, mem_size);
      }
    }
  }
  if (mem) ck_free(mem);
  *state_count_ref = state_count;
  return state_sequence;
}

该函数提取了SMTP协议的response_code,即由服务器端发出的消息。
根据对SMTP协议的分析,确定提取响应码的位置,根据响应码确定不同的服务器状态,并加入到状态机中。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值