AFL源码分析之afl-gcc.c

非常感谢网上师傅队afl源码的分析理解,能使我更容易去理解这部分代码

(22条消息) afl-gcc.c源码分析 源码精注释版_学习记录-CSDN博客

(22条消息) AFL源码分析之afl-gcc.c详细注释_hollk’s blog-CSDN博客

我阅读的是2.57版本的afl,要文件可以私我,

在次记录便于以后我的复习

复制代码
  1 /*
  2   Copyright 2013 Google LLC All rights reserved.
  3 
  4   Licensed under the Apache License, Version 2.0 (the "License");
  5   you may not use this file except in compliance with the License.
  6   You may obtain a copy of the License at:
  7 
  8     http://www.apache.org/licenses/LICENSE-2.0
  9 
 10   Unless required by applicable law or agreed to in writing, software
 11   distributed under the License is distributed on an "AS IS" BASIS,
 12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13   See the License for the specific language governing permissions and
 14   limitations under the License.
 15 */
 16 
 17 /*
 18    american fuzzy lop - wrapper for GCC and clang
 19    ----------------------------------------------
 20 
 21    Written and maintained by Michal Zalewski <lcamtuf@google.com>
 22 
 23    This program is a drop-in replacement for GCC or clang. The most common way
 24    of using it is to pass the path to afl-gcc or afl-clang via CC when invoking
 25    ./configure.
 26 
 27    (Of course, use CXX and point it to afl-g++ / afl-clang++ for C++ code.)
 28 
 29    The wrapper needs to know the path to afl-as (renamed to 'as'). The default
 30    is /usr/local/lib/afl/. A convenient way to specify alternative directories
 31    would be to set AFL_PATH.
 32 
 33    If AFL_HARDEN is set, the wrapper will compile the target app with various
 34    hardening options that may help detect memory management issues more
 35    reliably. You can also specify AFL_USE_ASAN to enable ASAN.
 36 
 37    If you want to call a non-default compiler as a next step of the chain,
 38    specify its location via AFL_CC or AFL_CXX.
 39 
 40 */
 41 
 42 #define AFL_MAIN
 43 
 44 #include "config.h"
 45 #include "types.h"
 46 #include "debug.h"
 47 #include "alloc-inl.h"
 48 
 49 #include <stdio.h>
 50 #include <unistd.h>
 51 #include <stdlib.h>
 52 #include <string.h>
 53 
 54 static u8*  as_path;                /* Path to the AFL 'as' wrapper  as包装器的路径    */
 55 static u8** cc_params;              /* Parameters passed to the real CC 传递给cc的参数 */
 56 static u32  cc_par_cnt = 1;         /* Param count, including argv0      */
 57 static u8   be_quiet,               /* Quiet mode    静默模式                    */
 58             clang_mode;             /* Invoked as afl-clang*? 调用afl-clang模式?           */
 59 
 60 
 61 /* Try to find our "fake" GNU assembler in AFL_PATH or at the location derived
 62    from argv[0]. If that fails, abort. 试着在AFL_PATH或派生的位置找到我们的fake”GNU汇编器从argv[0]。如果失败,中止*/
 63 
 64 static void find_as(u8* argv0) {
 65     //通过argv[0](当前文件的路径)来寻找对应的汇编器as(linux上as是常用的一个汇编器,负责把生成的汇编代码翻译到二进制)
 66   u8 *afl_path = getenv("AFL_PATH"); //读取环境变量中的afl_path变量
 67   u8 *slash, *tmp;
 68 
 69   if (afl_path) {  //如果成功获取到了afl_path变量
 70 
 71     tmp = alloc_printf("%s/as", afl_path); //alloc_printf函数动态为afl_path分配一段空间
 72 
 73     if (!access(tmp, X_OK)) { //监测路径是否可以访问   
 74         // access函数用来判断指定的文件或目录是否存在(F_OK),已存在的文件或目录是否有可读(R_OK)、可写(W_OK)、可执行(X_OK)权限。F_OK、R_OK、W_OK、X_OK这四种方式通过access函数中的第二个参数mode指定。如果指定的方式有效,则此函数返回0,否则返回-1。
 75  
 76       as_path = afl_path;  //如果可以访问则将as_path = afl_path
 77       ck_free(tmp);   //然后free掉tmp也就是alloc_printf申请的那段空间
 78       return;  //返回
 79     }
 80 
 81     ck_free(tmp);  //如果无法访问路径,则也free掉tmp的空间大小
 82 
 83   }
 84 
 85   slash = strrchr(argv0, '/');   //如果获取afl_path变量失败 ,从argv0中查找/字符串 也就是提取当前的路径dir
 86 
 87   if (slash) {  //如果成功获取到了dir路径
 88 
 89     u8 *dir;
 90 
 91     *slash = 0;
 92     dir = ck_strdup(argv0); //将argv0路径命名
 93     *slash = '/';
 94 
 95     tmp = alloc_printf("%s/afl-as", dir);  //为dir申请一段空间
 96 
 97     if (!access(tmp, X_OK)) {  //如果路径是可以访问到的
 98       as_path = dir; //将路径赋值给as_path
 99       ck_free(tmp);  //然后将tmp空间释放掉
100       return;
101     }
102 
103     ck_free(tmp); //如果访问不到路径则释放掉tmp的空间
104     ck_free(dir);
105 
106   }
107 
108   if (!access(AFL_PATH "/as", X_OK)) {  //如果上面俩种情况都没有则寻找as抛出异常
109     as_path = AFL_PATH;  //如果找到了就赋值
110     return;
111   }
112 
113   FATAL("Unable to find AFL wrapper binary for 'as'. Please set AFL_PATH");
114  
115 }
116 
117 
118 /* Copy argv to cc_params, making the necessary edits.复制argv到cc_params,进行必要的编辑。 */
119 
120 static void edit_params(u32 argc, char** argv) {
121 
122   u8 fortify_set = 0, asan_set = 0; //设置cc的参数
123   u8 *name;
124 
125 #if defined(__FreeBSD__) && defined(__x86_64__)
126   u8 m32_set = 0;
127 #endif
128 
129   cc_params = ck_alloc((argc + 128) * sizeof(u8*));   //为cc_params开辟内存空间
130 
131   name = strrchr(argv[0], '/');   //获取/后的编译器名称
132   if (!name) name = argv[0]; else name++;
133 
134   if (!strncmp(name, "afl-clang", 9)) { //如果name是以afl-clang开头的
135 
136     clang_mode = 1; //则设置clang_mode的模式为1
137 
138     setenv(CLANG_ENV_VAR, "1", 1);
139 
140     if (!strcmp(name, "afl-clang++")) {  //如果name中的变量是afl-clang++
141       u8* alt_cxx = getenv("AFL_CXX");  //则获取环境变量 afl_cxx
142       cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++"; //如果获得获取到环境变量值,那么将环境变量值付给cc_params,如果没有获取到则直接给字符串“clang++”
143     }
144     else {
145     } else {
146       u8* alt_cc = getenv("AFL_CC"); //如果name中的变量不是afl-clang++则获取环境变量AFL_cc
147       cc_params[0] = alt_cc ? alt_cc : (u8*)"clang";//如果获取到环境变量值,那么将环境变量值赋给cc_params,如果没有则直接给字符串“clang”
148     }
149 
150   } else {
151 
152     /* With GCJ and Eclipse installed, you can actually compile Java! The
153        instrumentation will work (amazingly). Alas, unhandled exceptions do
154        not call abort(), so afl-fuzz would need to be modified to equate
155        non-zero exit codes with crash conditions when working with Java
156        binaries. Meh. */
157 
158 #ifdef __APPLE__  //如果没有afl_clang分支而且还是apple的平台,就会进入这个分支
159 
160     if (!strcmp(name, "afl-g++")) cc_params[0] = getenv("AFL_CXX");  //如果对比的值是afl-g++ 则获取环境变量afl_cxx的值并且赋值给cc_params
161     else if (!strcmp(name, "afl-gcj")) cc_params[0] = getenv("AFL_GCJ");  //如果对比的值是afl-gcj,测获取环境变量afl_gcj的值并且赋值给afl_gcj
162     else cc_params[0] = getenv("AFL_CC");  //如果都不是则获取环境变量AFL_cc的值赋值给cc_parms
163 
164     if (!cc_params[0]) { //如果cc_params没有值,则提示mac下有限使用afl-alang,如果要使用afl-gcc需要配置路径
165 
166       SAYF("\n" cLRD "[-] " cRST
167            "On Apple systems, 'gcc' is usually just a wrapper for clang. Please use the\n"
168            "    'afl-clang' utility instead of 'afl-gcc'. If you really have GCC installed,\n"
169            "    set AFL_CC or AFL_CXX to specify the correct path to that compiler.\n");
170 
171       FATAL("AFL_CC or AFL_CXX required on MacOS X");
172 
173     }
174 
175 #else
176 
177     if (!strcmp(name, "afl-g++")) {  //判断name的值是不是afl-g++
178       u8* alt_cxx = getenv("AFL_CXX"); //获取环境变量AFL_CXX的值赋值给alt_cxx
179       cc_params[0] = alt_cxx ? alt_cxx : (u8*)"g++"; //如果获取到了值则将值赋值给cc_params,如果没有获取到则直接将字符串g++给cc_params
180     } else if (!strcmp(name, "afl-gcj")) { //判断name的值是不是afl-gcj
181       u8* alt_cc = getenv("AFL_GCJ");  //获取环境变量afl_gcj的值赋值给alt_cc
182       cc_params[0] = alt_cc ? alt_cc : (u8*)"gcj"; //如果获取到了值则将值赋值给cc_params,如果没有获取到则将字符串gcj赋值给cc_params
183     } else {
184       u8* alt_cc = getenv("AFL_CC");  //如果都不是则获取环境变量afl_cc的值赋值给alt_cc
185       cc_params[0] = alt_cc ? alt_cc : (u8*)"gcc";//将alt_cc的值赋值给cc_params,如果没有获取到则将字符串gcc赋值给cc_params
186     }
187 
188 #endif /* __APPLE__ */
189 
190   }
191 
192   while (--argc) { //进入while循环扫描argv数组 给cc_params赋值(可见217行
193     u8* cur = *(++argv);//获取参数
194 
195     if (!strncmp(cur, "-B", 2)) { //如果当前的参数是-B
196 
197       if (!be_quiet) WARNF("-B is already set, overriding"); //判断静默模式是否关闭,如果关闭则提示"-B"以设置
198 
199       if (!cur[2] && argc > 1) { argc--; argv++; }//
200       continue;
201 
202     }
203 
204     if (!strcmp(cur, "-integrated-as")) continue;  //如果扫描到-integrated-as 则跳过
205 
206     if (!strcmp(cur, "-pipe")) continue; //如果扫描到-pipe 则跳过
207 
208 #if defined(__FreeBSD__) && defined(__x86_64__) //判断如果是freebsd系统或者是x86_64的系统
209     if (!strcmp(cur, "-m32")) m32_set = 1; //判断当前的参数是不是-m32,并且将m32_set的值赋值为1
210 #endif
211 
212     if (!strcmp(cur, "-fsanitize=address") ||  //如果当前的参数为-fsanitize=address或者-fsanitize=memory,则将asan_set的值赋值为1 (这俩个参数是为了告诉gcc检查内存访问错误
213         !strcmp(cur, "-fsanitize=memory")) asan_set = 1;
214 
215     if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; //如果当前的参数为"FORTIFY_SOURCE",则将fortify_set 赋值为1(这个参数是为了检查fortify保护是否开启)
216     
217     cc_params[cc_par_cnt++] = cur; //给cc_params赋值,cc_par_cnt++初值值为1
218 
219   }
220 
221   cc_params[cc_par_cnt++] = "-B";
222   cc_params[cc_par_cnt++] = as_path; //跳出循环后,向cc_params中加入"-B" 以及前面find_as函数赋值的as_path 组成"-B as_path"
223 
224   if (clang_mode) //判断clang_mode的值,在136行有分支将值设置为1
225     cc_params[cc_par_cnt++] = "-no-integrated-as"; //如果是的话则将cc_params的值追加参数为 "-no-integrated-as"
226 
227   if (getenv("AFL_HARDEN")) { //获取环境变量afl_harden的值,如果获取到进入该分支
228 
229     cc_params[cc_par_cnt++] = "-fstack-protector-all"; //cc_params追加参数"-fstack-protector-all"
230 
231     if (!fortify_set) //检查是否设置fortify_set参数是否设置 (215行)如果没有则cc_params追加参数"-D_FORTIFY_SOURCE=2"
232       cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2";
233 
234   }
235 
236   if (asan_set) { //判断是否检查内存 位置在215 
237 
238     /* Pass this on to afl-as to adjust map density.将此传递给afl-as以调整地图密度 */
239 
240     setenv("AFL_USE_ASAN", "1", 1); //如果检查内存了则将AFL_USE_ASAN环境变量设置为1
241 
242   } else if (getenv("AFL_USE_ASAN")) { //如果设置成功则进入该分支
243 
244     if (getenv("AFL_USE_MSAN")) //获取AFL_USE_MSAN是否设置成功,如果成功则提示asan和msan是互斥的
245       FATAL("ASAN and MSAN are mutually exclusive");
246 
247     if (getenv("AFL_HARDEN"))//获取"AFL_HARDEN"是否设置为1,存在则提示ASAN和AFL_HARDEN是互斥的
248       FATAL("ASAN and AFL_HARDEN are mutually exclusive");
249 
250     cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
251     cc_params[cc_par_cnt++] = "-fsanitize=address";//如果上述两个环境变量都没有设置,则再cc_params中追加"-U_FORTIFY_SOURCE"和"-fsanitize=address"两个参数
252 
253   } else if (getenv("AFL_USE_MSAN")) { //获取AFL_USE_MSAN环境变量进入该分支
254 
255     if (getenv("AFL_USE_ASAN")) //获取AFL_USE_ASAN是否设置为1,如果设置则提示ASAN和MSAN是互斥的
256       FATAL("ASAN and MSAN are mutually exclusive");
257 
258     if (getenv("AFL_HARDEN")) //获取AFL_HARDEN"是否设置为1,如果设置则提示MSAN和AFL_HARDEN"是互斥的
259       FATAL("MSAN and AFL_HARDEN are mutually exclusive");
260 
261     cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
262     cc_params[cc_par_cnt++] = "-fsanitize=memory";//如果上述两个环境变量都没有设置,则再cc_params中追加"-U_FORTIFY_SOURCE"和"-fsanitize=memory"两个参数
263 
264 
265   }
266 
267   if (!getenv("AFL_DONT_OPTIMIZE")) {  //获取AFL_DONT_OPTIMIZE环境变量,失败进入分支
268 
269 #if defined(__FreeBSD__) && defined(__x86_64__) //如果是freebsd或者x86_64的系统进入分支
270 
271     /* On 64-bit FreeBSD systems, clang -g -m32 is broken, but -m32 itself
272        works OK. This has nothing to do with us, but let's avoid triggering
273        that bug. */
274 
275     if (!clang_mode || !m32_set)//如果没有设置clang模式或者没有设置-m32参数则进入分支 (在136行)
276       cc_params[cc_par_cnt++] = "-g";//cc_params中追加“-g”参数
277 
278 #else //如果不是上述俩系统进入该分支
279 
280       cc_params[cc_par_cnt++] = "-g";//cc_params中追加“-g”参数
281 
282 #endif
283 
284     cc_params[cc_par_cnt++] = "-O3";//在cc_params中追加“-O3”参数
285     cc_params[cc_par_cnt++] = "-funroll-loops";
286 
287     /* Two indicators that you're building for fuzzing; one of them is
288        AFL-specific, the other is shared with libfuzzer.你要为模糊设计的两个指标;其中一个是afl特异性,另一个与libfuzzer共享。 */
289 
290     cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
291     cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";//cc_params中追加上述几个参数
292 
293   }
294 
295   if (getenv("AFL_NO_BUILTIN")) { //如果设置了"AFL_NO_BUILTIN"环境变量则进入该分支
296 
297     cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
298     cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
299     cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp";
300     cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp";
301     cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
302     cc_params[cc_par_cnt++] = "-fno-builtin-strstr";
303     cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr";//在cc_params中追加上述参数
304 
305   }
306 
307   cc_params[cc_par_cnt] = NULL;//cc_params最后追加NULL,表示参数数组结束
308 
309 }
310 
311 
312 /* Main entry point程序的主入口 */
313 
314 int main(int argc, char** argv) {
315 
316   if (isatty(2) && !getenv("AFL_QUIET")) {
317 
318     SAYF(cCYA "afl-cc " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
319 
320   } else be_quiet = 1;
321 
322   if (argc < 2) {
323 
324     SAYF("\n"
325          "This is a helper application for afl-fuzz. It serves as a drop-in replacement\n"
326          "for gcc or clang, letting you recompile third-party code with the required\n"
327          "runtime instrumentation. A common use pattern would be one of the following:\n\n"
328 
329          "  CC=%s/afl-gcc ./configure\n"
330          "  CXX=%s/afl-g++ ./configure\n\n"
331 
332          "You can specify custom next-stage toolchain via AFL_CC, AFL_CXX, and AFL_AS.\n"
333          "Setting AFL_HARDEN enables hardening optimizations in the compiled code.\n\n",
334          BIN_PATH, BIN_PATH);
335 
336     exit(1);
337 
338   }
339 
340   find_as(argv[0]);//主要来查找汇编器
341 
342   edit_params(argc, argv); //通过传入编译的参数来进行参数处理,将确定好的参数放入cc_params[]数组
343 
344   execvp(cc_params[0], (char**)cc_params);//调用该函数执行afl-gcc(cc_params[0]为编译器,(char**)cc_params为编译器参数)
345 
346 
347   FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]);
348 
349   return 0;
350 
351 }
复制代码

 

posted @   庄周恋蝶蝶恋花  阅读(277)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示