2
2
#
3
3
# File: afl-cov
4
4
#
5
- # Version: 0.6.3
5
+ # Version: 0.6.4
6
6
#
7
7
# Purpose: Perform lcov coverage diff's against each AFL queue file to see
8
8
# new functions and line coverage evolve from an AFL fuzzing cycle.
9
9
#
10
10
# Copyright (C) 2015-2016 Michael Rash ([email protected] )
11
+ # Copyright (C) 2018-2020 Marc "vanHauser" Heuse ([email protected] )
11
12
#
12
13
# License (GNU General Public License version 2 or any later version):
13
14
#
44
45
except ImportError :
45
46
import subprocess
46
47
47
- __version__ = '0.6.3 '
48
+ __version__ = '0.6.4 '
48
49
49
50
NO_OUTPUT = 0
50
51
WANT_OUTPUT = 1
@@ -185,10 +186,10 @@ def process_afl_test_cases(cargs):
185
186
### for the current AFL test case file
186
187
if run_once :
187
188
run_cmd (cargs .coverage_cmd .replace ('AFL_FILE' , f ),
188
- cov_paths ['log_file' ], cargs , NO_OUTPUT )
189
+ cov_paths ['log_file' ], cargs , NO_OUTPUT , True , f )
189
190
else :
190
191
out_lines = run_cmd (cargs .coverage_cmd .replace ('AFL_FILE' , f ),
191
- cov_paths ['log_file' ], cargs , WANT_OUTPUT )[1 ]
192
+ cov_paths ['log_file' ], cargs , WANT_OUTPUT , True , f )[1 ]
192
193
run_once = True
193
194
194
195
if cargs .afl_queue_id_limit \
@@ -584,29 +585,29 @@ def lcov_gen_coverage(cov_paths, cargs):
584
585
+ " --no-checksum --capture --directory " \
585
586
+ cargs .code_dir + " --output-file " \
586
587
+ cov_paths ['lcov_info' ], \
587
- cov_paths ['log_file' ], cargs , LOG_ERRORS )
588
+ cov_paths ['log_file' ], cargs , LOG_ERRORS , False , "" )
588
589
589
590
if (cargs .disable_lcov_exclude_pattern ):
590
591
out_lines = run_cmd (cargs .lcov_path \
591
592
+ lcov_opts
592
593
+ " --no-checksum -a " + cov_paths ['lcov_base' ] \
593
594
+ " -a " + cov_paths ['lcov_info' ] \
594
595
+ " --output-file " + cov_paths ['lcov_info_final' ], \
595
- cov_paths ['log_file' ], cargs , WANT_OUTPUT )[1 ]
596
+ cov_paths ['log_file' ], cargs , WANT_OUTPUT , False , "" )[1 ]
596
597
else :
597
598
tmp_file = NamedTemporaryFile (delete = False )
598
599
run_cmd (cargs .lcov_path \
599
600
+ lcov_opts
600
601
+ " --no-checksum -a " + cov_paths ['lcov_base' ] \
601
602
+ " -a " + cov_paths ['lcov_info' ] \
602
603
+ " --output-file " + tmp_file .name , \
603
- cov_paths ['log_file' ], cargs , LOG_ERRORS )
604
+ cov_paths ['log_file' ], cargs , LOG_ERRORS , False , "" )
604
605
out_lines = run_cmd (cargs .lcov_path \
605
606
+ lcov_opts
606
607
+ " --no-checksum -r " + tmp_file .name \
607
608
+ " " + cargs .lcov_exclude_pattern + " --output-file " \
608
609
+ cov_paths ['lcov_info_final' ],
609
- cov_paths ['log_file' ], cargs , WANT_OUTPUT )[1 ]
610
+ cov_paths ['log_file' ], cargs , WANT_OUTPUT , False , "" )[1 ]
610
611
if os .path .exists (tmp_file .name ):
611
612
os .unlink (tmp_file .name )
612
613
@@ -643,7 +644,7 @@ def gen_web_cov_report(fuzz_dir, cov_paths, cargs):
643
644
+ " --output-directory " \
644
645
+ cov_paths ['web_dir' ] + " " \
645
646
+ cov_paths ['lcov_info_final' ], \
646
- cov_paths ['log_file' ], cargs , LOG_ERRORS )
647
+ cov_paths ['log_file' ], cargs , LOG_ERRORS , False , "" )
647
648
648
649
logr ("[+] Final lcov web report: %s/%s" % \
649
650
(cov_paths ['web_dir' ], 'index.html' ), cov_paths ['log_file' ], cargs )
@@ -691,23 +692,26 @@ def get_running_pid(stats_file, pid_re):
691
692
break
692
693
return pid
693
694
694
- def run_cmd (cmd , log_file , cargs , collect ):
695
+ def run_cmd (cmd , log_file , cargs , collect , aflrun , fn ):
695
696
696
697
out = []
697
698
698
- if cargs .verbose :
699
- if log_file :
700
- logr (" CMD: %s" % cmd , log_file , cargs )
701
- else :
702
- print " CMD: %s" % cmd
703
-
704
699
fh = None
705
700
if cargs .disable_cmd_redirection or collect == WANT_OUTPUT \
706
701
or collect == LOG_ERRORS :
707
702
fh = NamedTemporaryFile (delete = False )
708
703
else :
709
704
fh = open (os .devnull , 'w' )
710
705
706
+ if aflrun == True and len (fn ) > 0 :
707
+ cmd = 'cat ' + fn + ' | ' + cmd
708
+
709
+ if cargs .verbose :
710
+ if log_file :
711
+ logr (" CMD: %s" % cmd , log_file , cargs )
712
+ else :
713
+ print " CMD: %s" % cmd
714
+
711
715
es = subprocess .call (cmd , stdin = None ,
712
716
stdout = fh , stderr = subprocess .STDOUT , shell = True )
713
717
@@ -809,15 +813,15 @@ def init_tracking(cov_paths, cargs):
809
813
run_cmd (cargs .lcov_path \
810
814
+ lcov_opts \
811
815
+ " --no-checksum --zerocounters --directory " \
812
- + cargs .code_dir , cov_paths ['log_file' ], cargs , LOG_ERRORS )
816
+ + cargs .code_dir , cov_paths ['log_file' ], cargs , LOG_ERRORS , False , "" )
813
817
814
818
run_cmd (cargs .lcov_path \
815
819
+ lcov_opts
816
820
+ " --no-checksum --capture --initial" \
817
821
+ " --directory " + cargs .code_dir \
818
822
+ " --output-file " \
819
823
+ cov_paths ['lcov_base' ], \
820
- cov_paths ['log_file' ], cargs , LOG_ERRORS )
824
+ cov_paths ['log_file' ], cargs , LOG_ERRORS , False , "" )
821
825
822
826
return True
823
827
@@ -832,7 +836,7 @@ def is_bin_gcov_enabled(binary, cargs):
832
836
833
837
### run readelf against the binary to see if it contains gcov support
834
838
for line in run_cmd ("%s -a %s" % (cargs .readelf_path , binary ),
835
- False , cargs , WANT_OUTPUT )[1 ]:
839
+ False , cargs , WANT_OUTPUT , False , "" )[1 ]:
836
840
if ' __gcov' in line :
837
841
if cargs .validate_args or cargs .gcov_check or cargs .gcov_check_bin :
838
842
print "[+] Binary '%s' is compiled with code coverage support via gcc." % binary
@@ -897,12 +901,9 @@ def is_gcov_enabled(cargs):
897
901
return False
898
902
899
903
if cargs .coverage_cmd :
900
- if 'AFL_FILE' not in cargs .coverage_cmd :
901
- print "[*] --coverage-cmd must contain AFL_FILE"
902
- return False
903
-
904
904
### make sure at least one component of the command is an
905
905
### executable and is compiled with code coverage support
906
+
906
907
found_exec = False
907
908
found_code_cov_binary = False
908
909
0 commit comments