AFL-GCC 的编译方式与 GCC 不同
AFL-GCC compiles differently than GCC
我想详细了解 AFL 的代码检测。
编译示例程序sample.c
int main(int argc, char **argv) {
int ret = 0;
if(argc > 1) {
ret = 7;
} else {
ret = 12;
}
return ret;
}
使用 gcc -c -o obj/sample-gcc.o src/sample.c
和 afl-gcc -c -o obj/sample-afl-gcc.o src/sample.c
并使用 objdump -d
反汇编会导致不同的汇编代码:
[海湾合作委员会]
0000000000000000 <main>:
0: f3 0f 1e fa endbr64
4: 55 push %rbp
5: 48 89 e5 mov %rsp,%rbp
8: 89 7d ec mov %edi,-0x14(%rbp)
b: 48 89 75 e0 mov %rsi,-0x20(%rbp)
f: c7 45 fc 00 00 00 00 movl [=11=]x0,-0x4(%rbp)
16: 83 7d ec 01 cmpl [=11=]x1,-0x14(%rbp)
1a: 7e 09 jle 25 <main+0x25>
1c: c7 45 fc 07 00 00 00 movl [=11=]x7,-0x4(%rbp)
23: eb 07 jmp 2c <main+0x2c>
25: c7 45 fc 0c 00 00 00 movl [=11=]xc,-0x4(%rbp)
2c: 8b 45 fc mov -0x4(%rbp),%eax
2f: 5d pop %rbp
30: c3 retq
[AFL-GCC]
0000000000000000 <main>:
0: 48 8d a4 24 68 ff ff lea -0x98(%rsp),%rsp
7: ff
8: 48 89 14 24 mov %rdx,(%rsp)
c: 48 89 4c 24 08 mov %rcx,0x8(%rsp)
11: 48 89 44 24 10 mov %rax,0x10(%rsp)
16: 48 c7 c1 0e ff 00 00 mov [=12=]xff0e,%rcx
1d: e8 00 00 00 00 callq 22 <main+0x22>
22: 48 8b 44 24 10 mov 0x10(%rsp),%rax
27: 48 8b 4c 24 08 mov 0x8(%rsp),%rcx
2c: 48 8b 14 24 mov (%rsp),%rdx
30: 48 8d a4 24 98 00 00 lea 0x98(%rsp),%rsp
37: 00
38: f3 0f 1e fa endbr64
3c: 31 c0 xor %eax,%eax
3e: 83 ff 01 cmp [=12=]x1,%edi
41: 0f 9e c0 setle %al
44: 8d 44 80 07 lea 0x7(%rax,%rax,4),%eax
48: c3 retq
- AFL(通常)在每个基本块前面添加一个蹦床来跟踪执行路径[https://github.com/mirrorer/afl/blob/master/afl-as.h#L130
-> 指令 0x00
lea
直到 0x30 lea
- AFL(通常)向程序添加主要有效负载(由于简单我排除了)[https://github.com/mirrorer/afl/blob/master/afl-as.h#L381]
- AFL 声称为 GCC 使用包装器,所以我希望其他一切都一样。为什么 if-else-condition 的编译方式仍然不同?
- 奖励问题:如果不使用 AFL 的 QEMU 模式或 Unicorn 模式手动检测没有可用源代码的二进制文件,是否可以通过(天真地)将主要有效负载和每个 trampoline 手动添加到二进制文件来实现或者有更好的方法吗?
回复:为什么使用 gcc 和使用 afl-gcc 进行编译是不同的,简短地查看 afl-gcc 源代码表明默认情况下它会修改编译器参数,设置 -O3 -funroll-loops
(以及定义__AFL_COMPILER
和 FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
).
根据文档 (docs/env_variables.txt):
By default, the wrapper appends -O3 to optimize builds. Very rarely,
this will cause problems in programs built with -Werror, simply
because -O3 enables more thorough code analysis and can spew out
additional warnings. To disable optimizations, set AFL_DONT_OPTIMIZE.
我想详细了解 AFL 的代码检测。
编译示例程序sample.c
int main(int argc, char **argv) {
int ret = 0;
if(argc > 1) {
ret = 7;
} else {
ret = 12;
}
return ret;
}
使用 gcc -c -o obj/sample-gcc.o src/sample.c
和 afl-gcc -c -o obj/sample-afl-gcc.o src/sample.c
并使用 objdump -d
反汇编会导致不同的汇编代码:
[海湾合作委员会]
0000000000000000 <main>:
0: f3 0f 1e fa endbr64
4: 55 push %rbp
5: 48 89 e5 mov %rsp,%rbp
8: 89 7d ec mov %edi,-0x14(%rbp)
b: 48 89 75 e0 mov %rsi,-0x20(%rbp)
f: c7 45 fc 00 00 00 00 movl [=11=]x0,-0x4(%rbp)
16: 83 7d ec 01 cmpl [=11=]x1,-0x14(%rbp)
1a: 7e 09 jle 25 <main+0x25>
1c: c7 45 fc 07 00 00 00 movl [=11=]x7,-0x4(%rbp)
23: eb 07 jmp 2c <main+0x2c>
25: c7 45 fc 0c 00 00 00 movl [=11=]xc,-0x4(%rbp)
2c: 8b 45 fc mov -0x4(%rbp),%eax
2f: 5d pop %rbp
30: c3 retq
[AFL-GCC]
0000000000000000 <main>:
0: 48 8d a4 24 68 ff ff lea -0x98(%rsp),%rsp
7: ff
8: 48 89 14 24 mov %rdx,(%rsp)
c: 48 89 4c 24 08 mov %rcx,0x8(%rsp)
11: 48 89 44 24 10 mov %rax,0x10(%rsp)
16: 48 c7 c1 0e ff 00 00 mov [=12=]xff0e,%rcx
1d: e8 00 00 00 00 callq 22 <main+0x22>
22: 48 8b 44 24 10 mov 0x10(%rsp),%rax
27: 48 8b 4c 24 08 mov 0x8(%rsp),%rcx
2c: 48 8b 14 24 mov (%rsp),%rdx
30: 48 8d a4 24 98 00 00 lea 0x98(%rsp),%rsp
37: 00
38: f3 0f 1e fa endbr64
3c: 31 c0 xor %eax,%eax
3e: 83 ff 01 cmp [=12=]x1,%edi
41: 0f 9e c0 setle %al
44: 8d 44 80 07 lea 0x7(%rax,%rax,4),%eax
48: c3 retq
- AFL(通常)在每个基本块前面添加一个蹦床来跟踪执行路径[https://github.com/mirrorer/afl/blob/master/afl-as.h#L130
-> 指令 0x00
lea
直到 0x30lea
- AFL(通常)向程序添加主要有效负载(由于简单我排除了)[https://github.com/mirrorer/afl/blob/master/afl-as.h#L381]
- AFL 声称为 GCC 使用包装器,所以我希望其他一切都一样。为什么 if-else-condition 的编译方式仍然不同?
- 奖励问题:如果不使用 AFL 的 QEMU 模式或 Unicorn 模式手动检测没有可用源代码的二进制文件,是否可以通过(天真地)将主要有效负载和每个 trampoline 手动添加到二进制文件来实现或者有更好的方法吗?
回复:为什么使用 gcc 和使用 afl-gcc 进行编译是不同的,简短地查看 afl-gcc 源代码表明默认情况下它会修改编译器参数,设置 -O3 -funroll-loops
(以及定义__AFL_COMPILER
和 FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
).
根据文档 (docs/env_variables.txt):
By default, the wrapper appends -O3 to optimize builds. Very rarely, this will cause problems in programs built with -Werror, simply because -O3 enables more thorough code analysis and can spew out additional warnings. To disable optimizations, set AFL_DONT_OPTIMIZE.