官方文档
Step-1. Implement 2 functions to parse the request and response sequences
You can use the available extract_requests_*
and extract_response_codes_*
functions as references. These functions should be declared and implemented in aflnet.h and aflnet.c, respectively. Note that, please use the same function parameters.
Step-2. Update main function to support a new protocol
Please update the code that handles the -P
option in the main function to support a new protocol.
aflnet.h
一共是三个结构体,两个枚举,都有注释,比较清楚
- region_t 保存了发完被测服务器的消息信息。其中,start_byte是开始的比特,end_byte是结束的比特,modifiable是可修改的flag信息, *state_sequence指向保存的从服务器反馈的状态信息,state_count是state_sequence中保存的状态数量。
- messsge_t保存了消息信息。其中,mdata指向被保存的message数据,msize是message的长度。
- state_info_t包含了协议状态的相关信息,如状态id,该状态是否被覆盖(可用于计算模糊测试的覆盖度),经过该状态的路径数量,当该状态被选中时扩展的新路径数量,该状态被选中的数量,生成的测试数量,保存到过该状态的种子以及全部种子数量。
- 两个枚举量分别定义了使用的传输层协议和种子选择算法。
aflnet.c
主要是extract_request_*和extract_response_codes_函数,以smtp协议为例分析一下:
1:region_t extract_requests_smtp
该函数提取了SMTP协议的requests,即由客户端发出的消息。返回regions,一个个消息报文
- 当一条消息包结束(遇到终止符)时创建一个新的region,并且重新定义消息的开始和结尾。
//Check if the last two bytes are 0x0D0A
if ((mem_count > 1) && (memcmp(&mem[mem_count - 1], terminator, 2) == 0)) {
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;
}
- 如果没有遇到终止符,则继续往后数,直到最后一个字节,创建新的region,同时退出while循环。
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;
break;
}
- 如果一直没有创建region,则说明缓存区的结构出问题了,为整个缓存都创建一个region。
//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;
}
2:extract_response_codes_smtp
该函数提取了SMTP协议的response_code,即由服务器端发出的消息。根据对SMTP协议的分析,确定提取响应码的位置,根据响应码确定不同的服务器状态,并加入到状态机中。
参考资料
http://e.betheme.net/article/show-1158649.aspx?action=onClick