AFLNET源码理解(五)

这里梳理一下AFLNET对状态和消息序列的映射。
AFLNET对于状态的处理主要基于一个哈希表和一个特定的结构体。

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,是否被覆盖过,经过这个状态的路径数,测试这个状态发现的路径数,被选取的状态,被测试的次数,得分,最近选中的种子index,所有的种子和种子总数。
对于状态的管理在于名为hms的哈希表中。

k = kh_put(hms, khms_states, curStateID, &discard);
kh_value(khms_states, k) = newState_To;

对于state的id用u32* state_ids和state_ids_count进行管理。
对于消息序列,其被保存在queue_entry这个结构体中

struct queue_entry {

  u8* fname;                          /* File name for the test case      */
  u32 len;                            /* Input length                     */

  u8  cal_failed,                     /* Calibration failed?              */
      trim_done,                      /* Trimmed?                         */
      was_fuzzed,                     /* Had any fuzzing done yet?        */
      passed_det,                     /* Deterministic stages passed?     */
      has_new_cov,                    /* Triggers new coverage?           */
      var_behavior,                   /* Variable behavior?               */
      favored,                        /* Currently favored?               */
      fs_redundant;                   /* Marked as redundant in the fs?   */

  u32 bitmap_size,                    /* Number of bits set in bitmap     */
      exec_cksum;                     /* Checksum of the execution trace  */

  u64 exec_us,                        /* Execution time (us)              */
      handicap,                       /* Number of queue cycles behind    */
      depth;                          /* Path depth                       */

  u8* trace_mini;                     /* Trace bytes, if kept             */
  u32 tc_ref;                         /* Trace bytes ref count            */

  struct queue_entry *next,           /* Next element, if any             */
                     *next_100;       /* 100 elements ahead               */

  region_t *regions;                  /* Regions keeping information of message(s) sent to the server under test */
  u32 region_count;                   /* Total number of regions in this seed */
  u32 index;                          /* Index of this queue entry in the whole queue */
  u32 generating_state_id;            /* ID of the start at which the new seed was generated */
  u8 is_initial_seed;                 /* Is this an initial seed */
  u32 unique_state_count;             /* Unique number of states traversed by this queue entry */

};

static struct queue_entry *queue,     /* Fuzzing queue (linked list)      */
                          *queue_cur, /* Current offset within the queue  */
                          *queue_top, /* Top of the list                  */
                          *q_prev100; /* Previous 100 marker              */

static struct queue_entry*
  top_rated[MAP_SIZE];                /* Top entries for bitmap bytes     */

其中regions记录每一条消息的信息

typedef struct {
  int start_byte;                 /* The start byte, negative if unknown. */
  int end_byte;                   /* The last byte, negative if unknown. */
  char modifiable;                /* The modifiable flag. */
  unsigned int *state_sequence;   /* The annotation keeping the state feedback. */
  unsigned int state_count;       /* Number of states stored in state_sequence. */
} region_t;

对于指定状态选取种子时使用struct queue_entry *choose_seed(u32 target_state_id, u8 mode)函数,具体分析在之前的博客中。
当状态被指定,种子被选出后,会根据指定的状态对种子进行划分(划分M2子消息序列)
在fuzz_one()函数中

AFLNET_REGIONS_SELECTION:;

  subseq_tmouts = 0;

  cur_depth = queue_cur->depth;

  u32 M2_start_region_ID = 0, M2_region_count = 0;
  /* Identify the prefix M1, the candidate subsequence M2, and the suffix M3. See AFLNet paper */
  /* In this implementation, we only need to indentify M2_start_region_ID which is the first region of M2
  and M2_region_count which is the total number of regions in M2. How the information is identified is
  state aware dependent. However, once the information is clear, the code for fuzzing preparation is the same */

  if (state_aware_mode) {
    /* In state aware mode, select M2 based on the targeted state ID */
    u32 total_region = queue_cur->region_count;
    if (total_region == 0) PFATAL("0 region found for %s", queue_cur->fname);

    if (target_state_id == 0) {
      //No prefix subsequence (M1 is empty)
      M2_start_region_ID = 0;
      M2_region_count = 0;

      //To compute M2_region_count, we identify the first region which has a different annotation
      //Now we quickly compare the state count, we could make it more fine grained by comparing the exact response codes
      for(i = 0; i < queue_cur->region_count ; i++) {
        if (queue_cur->regions[i].state_count != queue_cur->regions[0].state_count) break;
        M2_region_count++;
      }
    } else {
      //M1 is unlikely to be empty
      M2_start_region_ID = 0;

      //Identify M2_start_region_ID first based on the target_state_id
      for(i = 0; i < queue_cur->region_count; i++) {
        u32 regionalStateCount = queue_cur->regions[i].state_count;
        if (regionalStateCount > 0) {
          //reachableStateID is the last ID in the state_sequence
          u32 reachableStateID = queue_cur->regions[i].state_sequence[regionalStateCount - 1];
          M2_start_region_ID++;
          if (reachableStateID == target_state_id) break;
        } else {
          //No annotation for this region
          return 1;
        }
      }

      //Then identify M2_region_count
      for(i = M2_start_region_ID; i < queue_cur->region_count ; i++) {
        if (queue_cur->regions[i].state_count != queue_cur->regions[M2_start_region_ID].state_count) break;
        M2_region_count++;
      }

      //Handle corner case(s) and skip the current queue entry
      if (M2_start_region_ID >= queue_cur->region_count) return 1;
    }

由于region中有记录返回的状态序列,以此进行查找筛选出M2序列。
对于regions的更新在void update_region_annotations(struct queue_entry* q)完成。

/* Update the annotations of regions (i.e., state sequence received from the server) */
void update_region_annotations(struct queue_entry* q)
{
  u32 i = 0;

  for (i = 0; i < messages_sent; i++) {
    if ((response_bytes[i] == 0) || ( i > 0 && (response_bytes[i] - response_bytes[i - 1] == 0))) {
      q->regions[i].state_sequence = NULL;
      q->regions[i].state_count = 0;
    } else {
      unsigned int state_count;
      q->regions[i].state_sequence = (*extract_response_codes)(response_buf, response_bytes[i], &state_count);
      q->regions[i].state_count = state_count;
    }
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值