因为项目中准备使用AFL++ + Qemu下,所以研究了其中AFL++下的Qemuafl的源码,其中插桩的方式与AFL原理一样,但是代码相差很大,因此记录一下。
qemuafl中桩点基本逻辑
1) qemuafl是AFL++直接fork了一份Qemu的源码,在Qemu的源码中直接进行代码修改。
2) 其中使用每个基本块的PC来作为每个基本块的桩点信息。
3) qemuafl直接在TCG的翻译阶段,将桩点代码生成为IR指令,嵌入到每个基本块的TCG-IR开始。
4) 这样子在执行TCG-IR的时候,装点代码就被直接运行了,很巧妙。
qemuafl中将桩点代码插入TCG-IR的方式即使用了Qemu的helper机制,以下说明helper机制。
参考:[http://blog.terrynini.tw/en/2021-QEMU-AFL-and-TCG/]()
1)首先进行宏声明
DEF_HELPER_FLAGS_1(afl_maybe_log, TCG_CALL_NO_RWG, void, tl)
2)DEF_HELPER_FLAGS_1的声明在两个地方(没太明白qemuafl为啥这么做!!!)
exec/helper-proto.h
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1));
3) 但是在exec/helper-proto.h文件的末尾,又使用了#undef DEF_HELPER_FLAGS_1
4) 实际定义的地方
exec/helper-gen.h
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
dh_arg_decl(t1, 1)) \
{ \
TCGTemp *args[1] = { dh_arg(t1, 1) }; \
tcg_gen_callN(HELPER(name), dh_retvar(ret), 1, args); \
}
5) 宏定义中,调用了tcg_gen_callN函数,这个函数是作用是生成IR指令。这个函数的第一个参数HELPER(name),
其作用是生成一个helper作为前面的函数名,对于name为afl_maybe_log,则这里的HELPER(afl_maybe_log)
就是helper_afl_maybe_log,并将这个函数生成IR指令。
6) 而宏DEF_HELPER_FLAGS_1,对于name为afl_maybe_log,则声明一个名为gen_helper_afl_maybe_log的函数。
7) 总结来说,gen_helper_afl_maybe_log函数是为了生成名为helper_afl_maybe_log的函数调用的IR指令。