本文主要是介绍AFL run_target trace_bits,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
先简单总结下run_target中和覆盖率计算相关的代码(去除我不关注的内容,如dump,no_forkserver等):
static u8 run_target(char** argv, u32 timeout) {/* After this memset, trace_bits[] are effectively volatile, so wemust prevent any earlier operations from venturing into thatterritory. */memset(trace_bits, 0, MAP_SIZE);MEM_BARRIER();// 执行二进制程序。。。// 等待程序终止。。。/* Any subsequent operations on trace_bits must not be moved by thecompiler below this point. Past this location, trace_bits[] behavevery normally and do not have to be treated as volatile. */MEM_BARRIER();#ifdef WORD_SIZE_64classify_counts((u64*)trace_bits);
#elseclassify_counts((u32*)trace_bits);
#endif /* ^WORD_SIZE_64 */return FAULT_NONE;
把其他内容删减后,对共享内存的操作就几句话。
memset,给trace_bits全部置0。
MEM_BARRIER(),内存屏障,暂时不去了解
classify_counts((u64*)trace_bits);每次处理8个字节,一共65536个字节需要处理
classify_count函数如下:
static inline void classify_counts(u64* mem) {u32 i = MAP_SIZE >> 3;while (i--) {/* Optimize for sparse bitmaps. */if (unlikely(*mem)) {u16* mem16 = (u16*)mem;mem16[0] = count_class_lookup16[mem16[0]];mem16[1] = count_class_lookup16[mem16[1]];mem16[2] = count_class_lookup16[mem16[2]];mem16[3] = count_class_lookup16[mem16[3]];}mem++;}}
i = 65536 / 8 = 8192,while循环8192次
u16* mem16 = (u16*)mem; 把u64指针转化为u16指针
static u16 count_class_lookup16[65536];EXP_ST void init_count_class16(void) {u32 b1, b2;for (b1 = 0; b1 < 256; b1++) for (b2 = 0; b2 < 256; b2++)count_class_lookup16[(b1 << 8) + b2] = (count_class_lookup8[b1] << 8) |count_class_lookup8[b2];}static const u8 count_class_lookup8[256] = {[0] = 0,[1] = 1,[2] = 2,[3] = 4,[4 ... 7] = 8,[8 ... 15] = 16,[16 ... 31] = 32,[32 ... 127] = 64,[128 ... 255] = 128};
感觉大概意思就是,对trace_bit的数据进行一些形式化处理,但是基本上不改变值。
run_target中间没有其他地方对trace_bits的具体赋值,应该是在二进制程序插桩中直接修改了trace_bits,暂时先不去深入了解
这篇关于AFL run_target trace_bits的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!