AFL源码分析之afl-as.c

昨天阅读了afl-gcc的源码,可以看出来afl-gcc主要用途是搜索as所在的位置,然后加上必要的参数参数,在调用gcc进行实际的编译

今天又继续阅读了afl-as.c的源码,这部分主要是对于fuzz插桩的编写,阅读完后不清楚可以看一下sakura师傅的博客,有着对源码的理解,也非常感谢hollk师傅的源码注解,降低了阅读的难度

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

sakuraのAFL源码全注释 | Sakuraのblog (eternalsakura13.com)

复制代码
  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 GNU as
 19    ---------------------------------------
 20 
 21    Written and maintained by Michal Zalewski <lcamtuf@google.com>
 22 
 23    The sole purpose of this wrapper is to preprocess assembly files generated
 24    by GCC / clang and inject the instrumentation bits included from afl-as.h. It
 25    is automatically invoked by the toolchain when compiling programs using
 26    afl-gcc / afl-clang.
 27 
 28    Note that it's an explicit non-goal to instrument hand-written assembly,
 29    be it in separate .s files or in __asm__ blocks. The only aspiration this
 30    utility has right now is to be able to skip them gracefully and allow the
 31    compilation process to continue.
 32 
 33    That said, see experimental/clang_asm_normalize/ for a solution that may
 34    allow clang users to make things work even with hand-crafted assembly. Just
 35    note that there is no equivalent for GCC.
 36 
 37 */
 38 
 39 #define AFL_MAIN
 40 
 41 #include "config.h"
 42 #include "types.h"
 43 #include "debug.h"
 44 #include "alloc-inl.h"
 45 
 46 #include "afl-as.h"
 47 
 48 #include <stdio.h>
 49 #include <unistd.h>
 50 #include <stdlib.h>
 51 #include <string.h>
 52 #include <time.h>
 53 #include <ctype.h>
 54 #include <fcntl.h>
 55 
 56 #include <sys/wait.h>
 57 #include <sys/time.h>
 58 
 59 static u8** as_params;          /* Parameters passed to the real 'as' 传递给“as”的参数  */
 60 
 61 static u8*  input_file;         /* Originally specified input file  输入文件     */
 62 static u8*  modified_file;      /* Instrumented file for the real 'as' “as”进行插桩处理的文件 */
 63 
 64 static u8   be_quiet,           /* Quiet mode (no stderr output)    静默模式(没有标准输出)    */
 65             clang_mode,         /* Running in clang mode?     是否运行在clang模式           */
 66             pass_thru,          /* Just pass data through?   只通过数据            */
 67             just_version,       /* Just show version?       只显示版本            */
 68             sanitizer;          /* Using ASAN / MSAN     是否使用ASAN/MSAN                  */
 69 
 70 static u32  inst_ratio = 100,   /* Instrumentation probability (%) 插桩覆盖率      */
 71             as_par_cnt = 1;     /* Number of params to 'as' 传递给“as”的参数数量初始值             */
 72 
 73 /* If we don't find --32 or --64 in the command line, default to 
 74    instrumentation for whichever mode we were compiled with. This is not
 75    perfect, but should do the trick for almost all use cases.如果输入命令中没有“--32”或“--64”,则默认检测编译时使用的模式 */
 76 
 77 #ifdef WORD_SIZE_64
 78 
 79 static u8   use_64bit = 1; //64位的标志
 80 
 81 #else
 82 
 83 static u8   use_64bit = 0; //32位的标志
 84 
 85 #ifdef __APPLE__  //如果是苹国平台
 86 #  error "Sorry, 32-bit Apple platforms are not supported."  //提示苹果不支持32位
 87 #endif /* __APPLE__ */
 88 
 89 #endif /* ^WORD_SIZE_64 */
 90 
 91 
 92 /* Examine and modify parameters to pass to 'as'. Note that the file name
 93    is always the last parameter passed by GCC, so we exploit this property
 94    to keep the code simple. 检查并修改要传递给'as'的参数。注意,文件名总是GCC传递的最后一个参数,因此我们利用这个属性来保持代码简单*/
 95 
 96 static void edit_params(int argc, char** argv) {
 97 
 98   u8 *tmp_dir = getenv("TMPDIR"), *afl_as = getenv("AFL_AS"); //获取环境变量TMPDIR和AFL_AS
 99   u32 i;
100 
101 #ifdef __APPLE__  // 如果
102 
103   u8 use_clang_as = 0;
104 
105   /* On MacOS X, the Xcode cctool 'as' driver is a bit stale and does not work
106      with the code generated by newer versions of clang that are hand-built
107      by the user. See the thread here: http://goo.gl/HBWDtn.
108 
109      To work around this, when using clang and running without AFL_AS
110      specified, we will actually call 'clang -c' instead of 'as -q' to
111      compile the assembly file.
112 
113      The tools aren't cmdline-compatible, but at least for now, we can
114      seemingly get away with this by making only very minor tweaks. Thanks
115      to Nico Weber for the idea. */
116 
117   if (clang_mode && !afl_as) { //如果使用clang模式且没有获取到afl_as变量就进入该分支
118 
119     use_clang_as = 1;
120 
121     afl_as = getenv("AFL_CC");  //获取环境变量AFL_CC
122     if (!afl_as) afl_as = getenv("AFL_CXX");  //如果没有获取到上面的变量就获取AFL_CXX或者赋值clang字符串
123     if (!afl_as) afl_as = "clang";
124 
125   }
126 
127 #endif /* __APPLE__ */
128 
129   /* Although this is not documented, GCC also uses TEMP and TMP when TMPDIR
130      is not set. We need to check these non-standard variables to properly
131      handle the pass_thru logic later on. */
132 
133   if (!tmp_dir) tmp_dir = getenv("TEMP");  //如果没有获取到TMPDIR就赋值下面三个中的一种
134   if (!tmp_dir) tmp_dir = getenv("TMP");
135   if (!tmp_dir) tmp_dir = "/tmp";
136 
137   as_params = ck_alloc((argc + 32) * sizeof(u8*));  为as_oarams开辟一段空间
138 
139   as_params[0] = afl_as ? afl_as : (u8*)"as";  //将上面的afl_as赋值给as_params,如果没有获取到就将字符串as赋值给as_params
140 
141   as_params[argc] = 0; //设置最后一个参数为0
142 
143   for (i = 1; i < argc - 1; i++) { //从第一个参数便利到最后一个参数
144 
145     if (!strcmp(argv[i], "--64")) use_64bit = 1; //如果遍历到--64字符串就将use_64bit设置为1
146     else if (!strcmp(argv[i], "--32")) use_64bit = 0; //如果便利到--32字符串就将use_64bit设置为零
147 
148 #ifdef __APPLE__ //如果是苹果平台
149 
150     /* The Apple case is a bit different... */
151 
152     if (!strcmp(argv[i], "-arch") && i + 1 < argc) {  //如果遍历到了-arch参数
153 
154       if (!strcmp(argv[i + 1], "x86_64")) use_64bit = 1; //如果是arch x86_64  则设置use_64bint为1
155       else if (!strcmp(argv[i + 1], "i386"))  //如果是-arch i386 则报错
156         FATAL("Sorry, 32-bit Apple platforms are not supported.");
157 
158     }
159 
160     /* Strip options that set the preference for a particular upstream
161        assembler in Xcode. */
162 
163     if (clang_mode && (!strcmp(argv[i], "-q") || !strcmp(argv[i], "-Q"))) //如果是clang模式并且参数是-q或者-Q则跳出循环
164       continue;
165 
166 #endif /* __APPLE__ */
167 
168     as_params[as_par_cnt++] = argv[i];
169 
170   }
171 
172 #ifdef __APPLE__
173 
174   /* When calling clang as the upstream assembler, append -c -x assembler
175      and hope for the best. */
176 
177   if (use_clang_as) {
178 
179     as_params[as_par_cnt++] = "-c";
180     as_params[as_par_cnt++] = "-x";
181     as_params[as_par_cnt++] = "assembler"; //如果使用的是clang模式则在as_params追加上述三个参数
182 
183   }
184 
185 #endif /* __APPLE__ */
186 
187   input_file = argv[argc - 1];  //将argv最后一个参数赋值给input_file
188 
189   if (input_file[0] == '-') {  //如果input_file 的参数是-
190 
191     if (!strcmp(input_file + 1, "-version")) { //如果是-version
192       just_version = 1;
193       modified_file = input_file;  //则将just_version设置为1然后modified_file设置为-version
194       goto wrap_things_up; //跳转到参数组合尾部尾部
195     }
196 
197     if (input_file[1]) FATAL("Incorrect use (not called through afl-gcc?)");  //如果不是-version则抛出异常
198       else input_file = NULL;
199 
200   } else {
201 
202     /* Check if this looks like a standard invocation as a part of an attempt
203        to compile a program, rather than using gcc on an ad-hoc .s file in
204        a format we may not understand. This works around an issue compiling
205        NSS. */
206 
207     if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) &&  //如果首字母不是- 判断第9个和第五个字节分把是不是/var/tmp和/tmp 如果都不是则设置pass_thru为1
208         strncmp(input_file, "/var/tmp/", 9) &&
209         strncmp(input_file, "/tmp/", 5)) pass_thru = 1;
210 
211   }
212 
213   modified_file = alloc_printf("%s/.afl-%u-%u.s", tmp_dir, getpid(),  //设置modified_file为类似tmp_dir/.afl-pid-time.s这样的字符串
214                                (u32)time(NULL));
215 
216 wrap_things_up:
217 
218   as_params[as_par_cnt++] = modified_file;//接收参数为modified最后一个参数
219   as_params[as_par_cnt]   = NULL;//参数接收结束
220 
221 }
222 
223 
224 /* Process input file, generate modified_file. Insert instrumentation in all
225    the appropriate places. */
226 
227 static void add_instrumentation(void) {//处理输入文件,生成modified_file,将桩插入所有释放的位置
228 
229   static u8 line[MAX_LINE];
230 
231   FILE* inf;
232   FILE* outf;
233   s32 outfd;
234   u32 ins_lines = 0; //插桩计数器
235 
236   u8  instr_ok = 0, skip_csect = 0, skip_next_label = 0,
237       skip_intel = 0, skip_app = 0, instrument_next = 0;
238 
239 #ifdef __APPLE__
240 
241   u8* colon_pos;
242 
243 #endif /* __APPLE__ */
244 
245   if (input_file) { //如果存在输入文件名称
246 
247     inf = fopen(input_file, "r"); //尝试获取input_file句柄,将fd赋值给inf
248     if (!inf) PFATAL("Unable to read '%s'", input_file); //如果获取不到则,抛出异常
249 
250   } else inf = stdin; //如果不存在文件名则赋值标准输入
251 
252   outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600); //以写的方式打开modified_file,如果文件已存在就直接打开,如果没有就创建一个
253 
254   if (outfd < 0) PFATAL("Unable to write to '%s'", modified_file); //如果文件没有写权限,就抛出异常
255 
256   outf = fdopen(outfd, "w"); //尝试打开
257 
258   if (!outf) PFATAL("fdopen() failed");   //打不开就抛出异常
259 
260   while (fgets(line, MAX_LINE, inf)) {  //循环读取inf指向的文件的每一行到line数组,每行最多MAX_LINE(8192)个字节,含末尾“\0”
261 
262     /* In some cases, we want to defer writing the instrumentation trampoline
263        until after all the labels, macros, comments, etc. If we're in this
264        mode, and if the line starts with a tab followed by a character, dump
265        the trampoline now. */
266 
267     if (!pass_thru && !skip_intel && !skip_app && !skip_csect && instr_ok &&
268         instrument_next && line[0] == '\t' && isalpha(line[1])) { //446行判断是否为defered mode模式(判断instrument_next和instr_ok是否都为1,以及line是否以\t开始,且line[1]是否是字母)
269 
270       fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,
271               R(MAP_SIZE)); //插桩
272 
273       instrument_next = 0; //instrument_next设置为0
274       ins_lines++; //插桩计数器加1
275 
276     }
277 
278     /* Output the actual line, call it a day in pass-thru mode. */
279 
280     fputs(line, outf);
281 
282     if (pass_thru) continue;
283 
284     /* All right, this is where the actual fun begins. For one, we only want to
285        instrument the .text section. So, let's keep track of that in processed
286        files - and let's set instr_ok accordingly.首先,我们只想检测.text部分。让我们在已处理的文件中跟踪它,并相应地设置instr_ok */
287 
288     if (line[0] == '\t' && line[1] == '.') { //判断读入的行是否以\t开头,以及line[1]是否为.
289 
290       /* OpenBSD puts jump tables directly inline with the code, which is
291          a bit annoying. They use a specific format of p2align directives
292          around them, so we use that as a signal. OpenBSD将跳转表直接内联到代码中,这有点烦人。它们使用特定格式的p2align指令,所以我们将其用作信号 */
293 
294       if (!clang_mode && instr_ok && !strncmp(line + 2, "p2align ", 8) && //检查是否为p2align指令,如果是则设置skip_next_label为1
295           isdigit(line[10]) && line[11] == '\n') skip_next_label = 1;//instr_ok变量是一个flag,如果为1表示位于.text段,如果为0表示不再.text段
296 
297       if (!strncmp(line + 2, "text\n", 5) ||
298           !strncmp(line + 2, "section\t.text", 13) ||
299           !strncmp(line + 2, "section\t__TEXT,__text", 21) ||
300           !strncmp(line + 2, "section __TEXT,__text", 21)) {
301         instr_ok = 1; //匹配"text\n"、"section\t.text"、"section\t__TEXT,__text"、"section __TEXT,__text",如果匹配成功则设置instr_ok为1。跳出本次循环
302         continue; 
303       }
304 
305       if (!strncmp(line + 2, "section\t", 8) ||
306           !strncmp(line + 2, "section ", 8) ||
307           !strncmp(line + 2, "bss\n", 4) ||
308           !strncmp(line + 2, "data\n", 5)) {
309         instr_ok = 0;//匹配"section\t"、"section "、"bss\n"、"data\n",如果匹配成功说明不是在.text段,设置instr_ok变量为0
310         continue;
311       }
312 
313     }
314 
315     /* Detect off-flavor assembly (rare, happens in gdb). When this is
316        encountered, we set skip_csect until the opposite directive is
317        seen, and we do not instrument. */
318 
319     if (strstr(line, ".code")) { //判断架构
320 
321       if (strstr(line, ".code32")) skip_csect = use_64bit;
322       if (strstr(line, ".code64")) skip_csect = !use_64bit;
323 
324     }
325 
326     /* Detect syntax changes, as could happen with hand-written assembly.
327        Skip Intel blocks, resume instrumentation when back to AT&T. */
328 
329     if (strstr(line, ".intel_syntax")) skip_intel = 1;//判断是否为Intel汇编语法
330     if (strstr(line, ".att_syntax")) skip_intel = 0;//判断是否为att汇编语法
331 
332     /* Detect and skip ad-hoc __asm__ blocks, likewise skipping them. */
333 
334     if (line[0] == '#' || line[1] == '#') {//ad-hoc __asm__块是否跳过
335 
336       if (strstr(line, "#APP")) skip_app = 1;
337       if (strstr(line, "#NO_APP")) skip_app = 0;
338 
339     }
340 
341     /* If we're in the right mood for instrumenting, check for function
342        names or conditional labels. This is a bit messy, but in essence,
343        we want to catch:插桩时终端关注对象
344 
345          ^main:      - function entry point (always instrumented)
346          ^.L0:       - GCC branch labelgcc下的分支标记
347          ^.LBB0_0:   - clang branch label (but only in clang mode)clang下的分支标记(仅仅只是在clang模式中)
348          ^\tjnz foo  - conditional branches条件跳转分支标记
349 
350        ...but not:
351 
352          ^# BB#0:    - clang comments
353          ^ # BB#0:   - ditto
354          ^.Ltmp0:    - clang non-branch labels
355          ^.LC0       - GCC non-branch labels
356          ^.LBB0_0:   - ditto (when in GCC mode)
357          ^\tjmp foo  - non-conditional jumps
358 
359        Additionally, clang and GCC on MacOS X follow a different convention
360        with no leading dots on labels, hence the weird maze of #ifdefs
361        later on.
362 
363      */
364 
365     if (skip_intel || skip_app || skip_csect || !instr_ok ||
366         line[0] == '#' || line[0] == ' ') continue;
367 
368     /* Conditional branch instruction (jnz, etc). We append the instrumentation
369        right after the branch (to instrument the not-taken path) and at the
370        branch destination label (handled later on). */
371 
372     if (line[0] == '\t') {
373 
374       if (line[1] == 'j' && line[2] != 'm' && R(100) < inst_ratio) {  //对于形如\tj[^m].格式的指令,即条件跳转指令,且R()函数创建的随机数小于插桩密度inst_ratio
375 
376         fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,
377                 R(MAP_SIZE)); // 判断是否为64位程序,使用fprintf函数将桩插在outf只想的文件的\tj[^ m].跳转指令位置,插入长度为R函数创建的小于MAP_SIZE的随机数
378 
379         ins_lines++; //插桩计数器+1,跳出循环进行下一次遍历
380 
381       }
382 
383       continue;
384 
385     }
386 
387     /* Label of some sort. This may be a branch destination, but we need to
388        tread carefully and account for several different formatting
389        conventions. */
390 
391 #ifdef __APPLE__
392 
393     /* Apple: L<whatever><digit>: */
394 
395     if ((colon_pos = strstr(line, ":"))) {
396 
397       if (line[0] == 'L' && isdigit(*(colon_pos - 1))) {
398 
399 #else
400 
401     /* Everybody else: .L<whatever>: */
402 
403     if (strstr(line, ":")) {  //检查line中是否存在“:”
404 
405       if (line[0] == '.') {  //检查是否以“.”开始
406 
407 #endif /* __APPLE__ */
408 
409         /* .L0: or LBB0_0: style jump destination */
410 
411 #ifdef __APPLE__
412 
413         /* Apple: L<num> / LBB<num> */
414 
415         if ((isdigit(line[1]) || (clang_mode && !strncmp(line, "LBB", 3)))//检查line[1]是否为数字,或者在clang模式下从line开始的三个字节是否为LBB,并且随机数小于插桩密度
416             && R(100) < )inst_ratio {
417 
418 #else
419 
420         /* Apple: .L<num> / .LBB<num> */
421 
422         if ((isdigit(line[2]) || (clang_mode && !strncmp(line + 1, "LBB", 3)))
423             && R(100) < inst_ratio) { //检查line[2]是否为数字,或者在clang模式下从line[1]开始的三个字节是否为LBB,并且随机数小于插桩密度
424 
425 #endif /* __APPLE__ */
426 
427           /* An optimization is possible here by adding the code only if the
428              label is mentioned in the code in contexts other than call / jmp.
429              That said, this complicates the code by requiring two-pass
430              processing (messy with stdin), and results in a speed gain
431              typically under 10%, because compilers are generally pretty good
432              about not generating spurious intra-function jumps.
433 
434              We use deferred output chiefly to avoid disrupting
435              .Lfunc_begin0-style exception handling calculations (a problem on
436              MacOS X). */
437 
438           if (!skip_next_label) instrument_next = 1; else skip_next_label = 0;   //检查skip_next_label是否设置,是就将instrument_next设置为1 否就将skip_next_label设置为0
439 
440         }
441 
442       } else {
443 
444         /* Function label (always instrumented, deferred mode). */
445 
446         instrument_next = 1;  //否则代表这是一个function label,插桩^func,设置instrument_next为1(defered mode)
447     
448       }
449 
450     }
451 
452   }
453 
454   if (ins_lines)//如果插桩计数器不为0
455     fputs(use_64bit ? main_payload_64 : main_payload_32, outf); //向outf中写入main_payload_64或main_payload_32
456 
457   if (input_file) fclose(inf);  //关闭文件
458   fclose(outf); //关闭文件
459 
460   if (!be_quiet) { //如果使用的不是静默模式
461 
462     if (!ins_lines) WARNF("No instrumentation targets found%s.", //如果插桩计数器为空,抛异常
463                           pass_thru ? " (pass-thru mode)" : "");
464     else OKF("Instrumented %u locations (%s-bit, %s mode, ratio %u%%).", //插桩成功输出
465              ins_lines, use_64bit ? "64" : "32",
466              getenv("AFL_HARDEN") ? "hardened" : 
467              (sanitizer ? "ASAN/MSAN" : "non-hardened"),
468              inst_ratio);
469  
470   }
471 
472 }
473 
474 
475 /* Main entry point 主函数*/
476 
477 int main(int argc, char** argv) {
478 
479   s32 pid;
480   u32 rand_seed;
481   int status;
482   u8* inst_ratio_str = getenv("AFL_INST_RATIO");//获取环境变量AFL_INST_RATIO(该环境变量主要控制检测每个分支的概率,取值为0到100%,设置为0时值检测函数入口的跳转,而不会检测函数分支的跳转)
483 
484   struct timeval tv;
485   struct timezone tz;
486 
487   clang_mode = !!getenv(CLANG_ENV_VAR);
488 
489   if (isatty(2) && !getenv("AFL_QUIET")) {
490 
491     SAYF(cCYA "afl-as " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
492  
493   } else be_quiet = 1;
494 
495   if (argc < 2) {
496 
497     SAYF("\n"
498          "This is a helper application for afl-fuzz. It is a wrapper around GNU 'as',\n"
499          "executed by the toolchain whenever using afl-gcc or afl-clang. You probably\n"
500          "don't want to run this program directly.\n\n"
501 
502          "Rarely, when dealing with extremely complex projects, it may be advisable to\n"
503          "set AFL_INST_RATIO to a value less than 100 in order to reduce the odds of\n"
504          "instrumenting every discovered branch.\n\n");
505 
506     exit(1);
507 
508   }
509 
510   gettimeofday(&tv, &tz);//获取当前精确时间
511 
512   rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); //通过当前时间与进程pid进行亦或处理
513 
514   srandom(rand_seed);//获得随机化种子
515 
516   edit_params(argc, argv);//检查并修改参数以传递给“as”。文件名是以GCC传递的最后一个参数决定的。此函数主要设置变量as_params的值,以及use_64bit/modified_file的值
517 
518   if (inst_ratio_str) {//如果获取到"AFL_INST_RATIO"环境变量则进入分支
519 
520     if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || inst_ratio > 100) // 如果没有将覆盖率写入inst_ratio变量或者inst_ratio中的值超过100的话,则进入分支抛出异常
521       FATAL("Bad value of AFL_INST_RATIO (must be between 0 and 100)");
522 
523   }
524 
525   if (getenv(AS_LOOP_ENV_VAR))//如果获取到"__AFL_AS_LOOPCHECK"环境变量值,则进入分支
526     FATAL("Endless loop when calling 'as' (remove '.' from your PATH)");//抛出异常
527 
528   setenv(AS_LOOP_ENV_VAR, "1", 1);//设置"__AFL_AS_LOOPCHECK"环境变量为1
529 
530   /* When compiling with ASAN, we don't have a particularly elegant way to skip
531      ASAN-specific branches. But we can probabilistically compensate for
532      that... */
533 
534   if (getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN")) { //获取"AFL_USE_ASAN"或"AFL_USE_MSAN"环境变量,如果其中有一个值为1则进入分支
535     sanitizer = 1;//sanitizer设置为1
536     inst_ratio /= 3;//inst_ratio除以3
537   }
538 
539   if (!just_version) add_instrumentation();//如果不是只查询version,那么就会进入add_instrumentastion()函数,该函数主要处理输入文件,生成modified_file,将桩插入释放的位置
540 
541   if (!(pid = fork())) { //调用fork函数创建一个子进程。在执行execvp函数执行是
542 
543     execvp(as_params[0], (char**)as_params);//执行命令和参数
544     FATAL("Oops, failed to execute '%s' - check your PATH", as_params[0]);//失败了就抛出异常
545 
546   }
547 
548   if (pid < 0) PFATAL("fork() failed");//等待子进程结束
549 
550   if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed"); //读取环境变量"AFL_KEEP_ASSEMBLY"失败,则unlink掉modified_file
551 
552   if (!getenv("AFL_KEEP_ASSEMBLY")) unlink(modified_file);
553   //设置该环境变量主要是为了防止afl-as删掉插桩后的汇编文件,设置为1会保留插桩后的汇编文件
554   exit(WEXITSTATUS(status));
555 
556 }
复制代码

 

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