afl-cc.c

中央编译器 afl-cc 包含各种不同类型的编译器目标和检测选项

对应afl中的afl-gcc.c

主要有如下三个函数的调用:

  • find_object(obj, argv[0]) 主要来查找汇编器等工具
  • edit_params(argc, argv, envp) 通过我们传入编译的参数来进行参数处理,将确定好的参数放入 cc_params[] 数组。
  • 在以上的步骤都完成之后,调用execvp(cc_params[0], (char **) cc_params) 执行gcc。

find_object()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//查找工具(如汇编器)(可能存在这个obj的目录都找一遍)
static u8 *find_object(u8 *obj, u8 *argv0) {
//获取环境变量中的AFL_PATH(/usr/local/lib/afl/)变量
u8 *afl_path = getenv("AFL_PATH");
u8 *slash = NULL, *tmp;
//如果获取AFL_PATH变量成功
if (afl_path) {
//动态分配一段空间存储对应的路径
tmp = alloc_printf("%s/%s", afl_path, obj);

if (debug) DEBUGF("Trying %s\n", tmp);
//检查这个路径是否可以访问
if (!access(tmp, R_OK)) {
//可以访问就赋值给obj_path
obj_path = afl_path;
//然后返回路径
return tmp;

}
//不可以访问就直接free掉
ck_free(tmp);

}
//如果获取AFL_PATH变量失败

if (argv0) {
slash = strrchr(argv0, '/');
//检查 argv[0] 是否有路径信息并使用它
if (slash) {

u8 *dir = ck_strdup(argv0);

slash = strrchr(dir, '/');
*slash = 0;

tmp = alloc_printf("%s/%s", dir, obj);

if (debug) DEBUGF("Trying %s\n", tmp);

if (!access(tmp, R_OK)) {

obj_path = dir;
return tmp;

}

ck_free(tmp);
//检查当前文件路径的../lib/afl是否有路径信息
tmp = alloc_printf("%s/../lib/afl/%s", dir, obj);

if (debug) DEBUGF("Trying %s\n", tmp);

if (!access(tmp, R_OK)) {

u8 *dir2 = alloc_printf("%s/../lib/afl", dir);
obj_path = dir2;
ck_free(dir);
return tmp;

}

ck_free(tmp);
ck_free(dir);

}

#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__linux__) || \
defined(__ANDROID__) || defined(__NetBSD__)
#define HAS_PROC_FS 1
#endif
#ifdef HAS_PROC_FS
// 如果argv[0] 没有路径信息,再检查/proc目录(only Linux, Android, NetBSD, DragonFly, and FreeBSD)
else {

char *procname = NULL;
#if defined(__FreeBSD__) || defined(__DragonFly__)
procname = "/proc/curproc/file";
#elif defined(__linux__) || defined(__ANDROID__)
procname = "/proc/self/exe";
#elif defined(__NetBSD__)
procname = "/proc/curproc/exe";
#endif
if (procname) {

char exepath[PATH_MAX];
ssize_t exepath_len = readlink(procname, exepath, sizeof(exepath));
if (exepath_len > 0 && exepath_len < PATH_MAX) {

exepath[exepath_len] = 0;
slash = strrchr(exepath, '/');

if (slash) {

*slash = 0;
tmp = alloc_printf("%s/%s", exepath, obj);

if (!access(tmp, R_OK)) {

u8 *dir = alloc_printf("%s", exepath);
obj_path = dir;
return tmp;

}

ck_free(tmp);
//也检查/proc的../lib/afl目录
tmp = alloc_printf("%s/../lib/afl/%s", exepath, obj);

if (debug) DEBUGF("Trying %s\n", tmp);

if (!access(tmp, R_OK)) {

u8 *dir = alloc_printf("%s/../lib/afl/", exepath);
obj_path = dir;
return tmp;

}

}

}

}

}

#endif
#undef HAS_PROC_FS

}
//直接找/usr/local/lib/afl
tmp = alloc_printf("%s/%s", AFL_PATH, obj);

if (debug) DEBUGF("Trying %s\n", tmp);

if (!access(tmp, R_OK)) {

obj_path = AFL_PATH;
return tmp;

}

ck_free(tmp);
//找当前目录
tmp = alloc_printf("./%s", obj);

if (debug) DEBUGF("Trying %s\n", tmp);

if (!access(tmp, R_OK)) {

obj_path = ".";
return tmp;

}

ck_free(tmp);

if (debug) DEBUGF("Trying ... giving up\n");

return NULL;

}

parse_fsanitize()

解析启用擦除器

edit_params()

这个函数主要是来设置 编译的参数。

gdb运行并设置args

image-20230328152947543

跳转到execvp函数

image-20230328153109911

可以看出是用的clang编译器

查看参数:

image-20230328152910456

afl-as.c