The Fuzzing Book 之 样本突变Fuzzing(二)

class ProgramCoverage:
def __init__(self, source_path: str) -> None:
self._coverage = set()
self.reports = []
self.rest(source_path)
def rest(self, source_path):
self.source_path = source_path
self._sources = []
for filepath, dirnames, filenames in os.walk(source_path):
for filename in filenames:
if filename.endswith('.c'):
fullname = os.path.join(filepath, filename)
self._sources.append(fullname)
def sources(self) -> List:
return self._sources
def trace(self):
old_work_dir = os.getcwd()
os.chdir(self.source_path)
for source in self._sources:
gcov_come = subprocess.run(
["gcov", source],
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
universal_newlines=True
)
if gcov_come.stdout != '':
self.reports.append((source, gcov_come.stdout))
gcov_file = source + ".gcov"
with open(gcov_file, 'r') as f:
for line in f.readlines():
if line.startswith(' #####: '):
self._coverage.add((source, int(line.strip(' #####: ').split(':')[0])))
os.chdir(old_work_dir)
def coverage(self) -> any:
return self._coverage
def __repr__(self):
out = ""
for report in self.reports:
source, gcov_info = report
out += source + "\n"
out += gcov_info
out += '#' * 60 + '\n'
return out
class ProgramCoverageRunner(ProgramRunner):
def __init__(self, program: str, sources_path):
self.program = program
self.sources_path = sources_path
basename = "input.txt"
tmpdir = tempfile.mkdtemp()
self.input_file = os.path.join(tmpdir, basename)
def run_process(self, inp) -> subprocess.CompletedProcess:
print(inp)
with open(self.input_file, 'w') as f:
f.write(inp + '\n')
result = subprocess.run(
[self.program, self.input_file],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True
)
cov = ProgramCoverage(self.sources_path)
cov.trace()
self._coverage = cov.coverage()
return result
def coverage(self):
return self._coverage