Compare commits

...

38 Commits
Origin ... main

Author SHA1 Message Date
emmm 3ac2f5195d 132
1 month ago
emmm 5097ecdef3 abab
1 month ago
BagPipeOuO eb4a4ff095 Merge branch 'main' of https://bdgit.educoder.net/m5cn9itjr/AFL
1 month ago
BagPipeOuO a8bc0b34e0 Merge branch 'main' of https://bdgit.educoder.net/m5cn9itjr/AFL
1 month ago
BagPipeOuO eaf2be4d74 Merge branch 'main' of https://bdgit.educoder.net/m5cn9itjr/AFL
1 month ago
BagPipeOuO 13e33c8bed 完善了泛读报告,增加必要图片,充实了内容
1 month ago
dongloong 3138560abe newnew
1 month ago
BagPipeOuO 3e33c0936a 1.8
1 month ago
BagPipeOuO 6a6c239329 批注了afl-as.c
1 month ago
BagPipeOuO 74366041a3 Merge branch 'main' of https://bdgit.educoder.net/m5cn9itjr/AFL
1 month ago
BagPipeOuO 78d04a2075 批注了makefile
1 month ago
yangguangmamama a5ec96676c 123
1 month ago
dongloong 2fc8b00adc new
1 month ago
emmm fc527fee69 lalala
1 month ago
emmm a6704ef8c1 hahaha
1 month ago
GodKingBS 7a3b0af177 123456
2 months ago
“18670363079” 0319921f2d Merge branch 'main' of https://bdgit.educoder.net/m5cn9itjr/AFL
2 months ago
BagPipeOuO 00200f2b09 Merge branch 'main' of https://bdgit.educoder.net/m5cn9itjr/AFL
2 months ago
BagPipeOuO d0d60336ae 完成了泛读报告
2 months ago
“18670363079” 3bf32e4de2 1.2
2 months ago
GodKingBS 6860809dea Merge branch 'main' of https://bdgit.educoder.net/m5cn9itjr/AFL
2 months ago
GodKingBS 20580d5a1c alloc
2 months ago
BagPipeOuO 34e563f83c Merge branch 'main' of https://bdgit.educoder.net/m5cn9itjr/AFL
2 months ago
BagPipeOuO 9ba3397419 Renamed the report
2 months ago
GodKingBS 31b9bf56f4 Merge branch 'main' of https://bdgit.educoder.net/m5cn9itjr/AFL
2 months ago
GodKingBS bf0e5c1714 config android
2 months ago
emmm 00b83c22e4 maao
2 months ago
GodKingBS 946e85b964 hash debug
2 months ago
GodKingBS df9f16952d instr
2 months ago
GodKingBS cb893b3926 test
2 months ago
GodKingBS cba725cf09 types
2 months ago
BagPipeOuO 8705567f0a Renamed the report
4 months ago
BagPipeOuO 94e115ecbd Modified the report of pre_Reading.
4 months ago
BagPipeOuO 6db848a67e Revert to previous state
4 months ago
“18670363079” 3a57a58e66 1
4 months ago
m5cn9itjr cea1d228b0 Delete 'docs/~$24秋软件工程课程报告一:AFL泛读报告.docx'
4 months ago
BagPipeOuO 8da03c8a59 qwq
4 months ago
BagPipeOuO c7ef505a22 修改了目录格式使得满足作业要求
4 months ago

@ -0,0 +1,18 @@
{
"configurations": [
{
"name": "windows-gcc-x86",
"includePath": [
"${workspaceFolder}/**"
],
"compilerPath": "C:/Program Files/MinGW/bin/gcc.exe",
"cStandard": "${default}",
"cppStandard": "${default}",
"intelliSenseMode": "windows-gcc-x86",
"compilerArgs": [
""
]
}
],
"version": 4
}

@ -0,0 +1,140 @@
cc_defaults {
name: "afl-defaults",
cflags: [
"-funroll-loops",
"-Wno-pointer-sign",
"-Wno-pointer-arith",
"-Wno-sign-compare",
"-Wno-unused-parameter",
"-Wno-unused-function",
"-Wno-format",
"-Wno-user-defined-warnings",
"-DUSE_TRACE_PC=1",
"-DBIN_PATH=\"out/host/linux-x86/bin\"",
"-DDOC_PATH=\"out/host/linux-x86/shared/doc/afl\"",
"-D__USE_GNU",
],
}
cc_binary {
name: "afl-fuzz",
static_executable: true,
host_supported: true,
defaults: [
"afl-defaults",
],
srcs: [
"afl-fuzz.c",
],
}
cc_binary {
name: "afl-showmap",
static_executable: true,
host_supported: true,
defaults: [
"afl-defaults",
],
srcs: [
"afl-showmap.c",
],
}
cc_binary {
name: "afl-tmin",
static_executable: true,
host_supported: true,
defaults: [
"afl-defaults",
],
srcs: [
"afl-tmin.c",
],
}
cc_binary {
name: "afl-analyze",
static_executable: true,
host_supported: true,
defaults: [
"afl-defaults",
],
srcs: [
"afl-analyze.c",
],
}
cc_binary {
name: "afl-gotcpu",
static_executable: true,
host_supported: true,
defaults: [
"afl-defaults",
],
srcs: [
"afl-gotcpu.c",
],
}
cc_binary_host {
name: "afl-clang-fast",
static_executable: true,
defaults: [
"afl-defaults",
],
cflags: [
"-D__ANDROID__",
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
],
srcs: [
"llvm_mode/afl-clang-fast.c",
],
}
cc_binary_host {
name: "afl-clang-fast++",
static_executable: true,
defaults: [
"afl-defaults",
],
cflags: [
"-D__ANDROID__",
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
],
srcs: [
"llvm_mode/afl-clang-fast.c",
],
}
cc_library_static {
name: "afl-llvm-rt",
compile_multilib: "both",
vendor_available: true,
host_supported: true,
recovery_available: true,
defaults: [
"afl-defaults",
],
srcs: [
"llvm_mode/afl-llvm-rt.o.c",
],
}

@ -13,79 +13,89 @@
# http://www.apache.org/licenses/LICENSE-2.0
#
# 定义程序名称和版本
PROGNAME = afl
VERSION = $(shell grep '^\#define VERSION ' config.h | cut -d '"' -f2)
# 安装路径
PREFIX ?= /usr/local
BIN_PATH = $(PREFIX)/bin
HELPER_PATH = $(PREFIX)/lib/afl
DOC_PATH = $(PREFIX)/share/doc/afl
MISC_PATH = $(PREFIX)/share/afl
# PROGS intentionally omit afl-as, which gets installed elsewhere.
# 程序和脚本的定义
PROGS = afl-gcc afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
SH_PROGS = afl-plot afl-cmin afl-whatsup
# 编译标志
CFLAGS ?= -O3 -funroll-loops
CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \
-DAFL_PATH=\"$(HELPER_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" \
-DBIN_PATH=\"$(BIN_PATH)\"
# Linux 平台的链接标志
ifneq "$(filter Linux GNU%,$(shell uname))" ""
LDFLAGS += -ldl
endif
# 判断是否使用 Clang 编译器
ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
TEST_CC = afl-gcc
else
TEST_CC = afl-clang
endif
# 公共头文件
COMM_HDR = alloc-inl.h config.h debug.h types.h
# 默认目标:编译和测试程序
all: test_x86 $(PROGS) afl-as test_build all_done
# 测试 x86 编译能力
ifndef AFL_NO_X86
test_x86:
@echo "[*] Checking for the ability to compile x86 code..."
@echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) -w -x c - -o .test || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 )
@rm -f .test
@echo "[+] Everything seems to be working, ready to compile."
else
test_x86:
@echo "[!] Note: skipping x86 compilation checks (AFL_NO_X86 set)."
endif
# 编译 afl-gcc
afl-gcc: afl-gcc.c $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS)
set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $$i; done
# 编译 afl-as
afl-as: afl-as.c afl-as.h $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS)
ln -sf afl-as as
# 编译 afl-fuzz
afl-fuzz: afl-fuzz.c $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS)
# 编译 afl-showmap
afl-showmap: afl-showmap.c $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS)
# 编译 afl-tmin
afl-tmin: afl-tmin.c $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS)
# 编译 afl-analyze
afl-analyze: afl-analyze.c $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS)
# 编译 afl-gotcpu
afl-gotcpu: afl-gotcpu.c $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS)
# 测试构建:检查插桩功能
ifndef AFL_NO_X86
test_build: afl-gcc afl-as afl-showmap
@echo "[*] Testing the CC wrapper and instrumentation output..."
unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS)
@ -94,22 +104,20 @@ test_build: afl-gcc afl-as afl-showmap
@rm -f test-instr
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please ping <lcamtuf@google.com> to troubleshoot the issue."; echo; exit 1; fi
@echo "[+] All right, the instrumentation seems to be working!"
else
test_build: afl-gcc afl-as afl-showmap
@echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)."
endif
# 完成构建
all_done: test_build
@if [ ! "`which clang 2>/dev/null`" = "" ]; then echo "[+] LLVM users: see llvm_mode/README.llvm for a faster alternative to afl-gcc."; fi
@echo "[+] All done! Be sure to review README - it's pretty short and useful."
@if [ "`uname`" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD. You can also use VirtualBox\n(virtualbox.org) to put AFL inside a Linux or *BSD VM.\n\n"; fi
@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.txt for advice.\033[0m\n" 2>/dev/null
# 清理构建生成的文件
.NOTPARALLEL: clean
clean:
rm -f $(PROGS) afl-as as afl-g++ afl-clang afl-clang++ *.o *~ a.out core core.[1-9][0-9]* *.stackdump test .test test-instr .test-instr0 .test-instr1 qemu_mode/qemu-2.10.0.tar.bz2 afl-qemu-trace
rm -rf out_dir qemu_mode/qemu-2.10.0
@ -117,6 +125,7 @@ clean:
$(MAKE) -C libdislocator clean
$(MAKE) -C libtokencap clean
# 安装程序
install: all
mkdir -p -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
@ -128,26 +137,4 @@ ifndef AFL_TRACE_PC
else
if [ -f afl-clang-fast -a -f afl-llvm-rt.o ]; then set -e; install -m 755 afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi
endif
if [ -f afl-llvm-rt-32.o ]; then set -e; install -m 755 afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi
if [ -f afl-llvm-rt-64.o ]; then set -e; install -m 755 afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi
set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/$$i; done
install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as
install -m 644 README.md docs/ChangeLog docs/*.txt $${DESTDIR}$(DOC_PATH)
cp -r testcases/ $${DESTDIR}$(MISC_PATH)
cp -r dictionaries/ $${DESTDIR}$(MISC_PATH)
publish: clean
test "`basename $$PWD`" = "AFL" || exit 1
test -f ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz; if [ "$$?" = "0" ]; then echo; echo "Change program version in config.h, mmkay?"; echo; exit 1; fi
cd ..; rm -rf $(PROGNAME)-$(VERSION); cp -pr $(PROGNAME) $(PROGNAME)-$(VERSION); \
tar -cvz -f ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz $(PROGNAME)-$(VERSION)
chmod 644 ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz
( cd ~/www/afl/releases/; ln -s -f $(PROGNAME)-$(VERSION).tgz $(PROGNAME)-latest.tgz )
cat docs/README >~/www/afl/README.txt
cat docs/status_screen.txt >~/www/afl/status_screen.txt
cat docs/historical_notes.txt >~/www/afl/historical_notes.txt
cat docs/technical_details.txt >~/www/afl/technical_details.txt
cat docs/ChangeLog >~/www/afl/ChangeLog.txt
cat docs/QuickStartGuide.txt >~/www/afl/QuickStartGuide.txt
echo -n "$(VERSION)" >~/www/afl/version.txt
@echo "[+] All done!"

@ -1,56 +1,56 @@
# american fuzzy lop
[![Build Status](https://travis-ci.org/google/AFL.svg?branch=master)](https://travis-ci.org/google/AFL)
Originally developed by Michal Zalewski <lcamtuf@google.com>.
See [QuickStartGuide.txt](docs/QuickStartGuide.txt) if you don't have time to read
this file.
[![Build Status](https://travis-ci.org/google/AFL.svg?branch=master)](https://travis-ci.org/google/AFL) # code
Originally developed by Michal Zalewski <lcamtuf@google.com>. # code
``````
See [QuickStartGuide.txt](docs/QuickStartGuide.txt) if you don't have time to read # code
this file. ``````
# code
## 1) Challenges of guided fuzzing
Fuzzing is one of the most powerful and proven strategies for identifying
security issues in real-world software; it is responsible for the vast
majority of remote code execution and privilege escalation bugs found to date
majority of remote code execution and privilege escalation bugs found to date # code
in security-critical software.
Unfortunately, fuzzing is also relatively shallow; blind, random mutations
Unfortunately, fuzzing is also relatively shallow; blind, random mutations # code
make it very unlikely to reach certain code paths in the tested code, leaving
some vulnerabilities firmly outside the reach of this technique.
# code
There have been numerous attempts to solve this problem. One of the early
approaches - pioneered by Tavis Ormandy - is corpus distillation. The method
relies on coverage signals to select a subset of interesting seeds from a
relies on coverage signals to select a subset of interesting seeds from a ``````
massive, high-quality corpus of candidate files, and then fuzz them by
traditional means. The approach works exceptionally well, but requires such
a corpus to be readily available. In addition, block coverage measurements
provide only a very simplistic understanding of program state, and are less
useful for guiding the fuzzing effort in the long haul.
useful for guiding the fuzzing effort in the long haul. # code
# code
Other, more sophisticated research has focused on techniques such as program
flow analysis ("concolic execution"), symbolic execution, or static analysis.
All these methods are extremely promising in experimental settings, but tend
to suffer from reliability and performance problems in practical uses - and
currently do not offer a viable alternative to "dumb" fuzzing techniques.
## 2) The afl-fuzz approach
## 2) The afl-fuzz approach # code
American Fuzzy Lop is a brute-force fuzzer coupled with an exceedingly simple
but rock-solid instrumentation-guided genetic algorithm. It uses a modified
form of edge coverage to effortlessly pick up subtle, local-scale changes to
program control flow.
program control flow. ``````
# code
Simplifying a bit, the overall algorithm can be summed up as:
1) Load user-supplied initial test cases into the queue,
2) Take next input file from the queue,
3) Attempt to trim the test case to the smallest size that doesn't alter
3) Attempt to trim the test case to the smallest size that doesn't alter # code
the measured behavior of the program,
4) Repeatedly mutate the file using a balanced and well-researched variety
of traditional fuzzing strategies,
of traditional fuzzing strategies, # code
5) If any of the generated mutations resulted in a new state transition
recorded by the instrumentation, add mutated output as a new entry in the
@ -58,9 +58,9 @@ Simplifying a bit, the overall algorithm can be summed up as:
6) Go to 2.
The discovered test cases are also periodically culled to eliminate ones that
The discovered test cases are also periodically culled to eliminate ones that ``````
have been obsoleted by newer, higher-coverage finds; and undergo several other
instrumentation-driven effort minimization steps.
instrumentation-driven effort minimization steps. # code
As a side result of the fuzzing process, the tool creates a small,
self-contained corpus of interesting test cases. These are extremely useful
@ -69,10 +69,10 @@ for stress-testing browsers, office applications, graphics suites, or
closed-source tools.
The fuzzer is thoroughly tested to deliver out-of-the-box performance far
superior to blind fuzzing or coverage-only tools.
superior to blind fuzzing or coverage-only tools. # code
## 3) Instrumenting programs for use with AFL
# code
When source code is available, instrumentation can be injected by a companion
tool that works as a drop-in replacement for gcc or clang in any standard build
process for third-party code.
@ -89,28 +89,28 @@ $ CC=/path/to/afl/afl-gcc ./configure
$ make clean all
```
For C++ programs, you'd would also want to set `CXX=/path/to/afl/afl-g++`.
For C++ programs, you'd would also want to set `CXX=/path/to/afl/afl-g++`. # code
The clang wrappers (afl-clang and afl-clang++) can be used in the same way;
clang users may also opt to leverage a higher-performance instrumentation mode,
clang users may also opt to leverage a higher-performance instrumentation mode, ``````
as described in llvm_mode/README.llvm.
``````
When testing libraries, you need to find or write a simple program that reads
data from stdin or from a file and passes it to the tested library. In such a
data from stdin or from a file and passes it to the tested library. In such a # code
case, it is essential to link this executable against a static version of the
instrumented library, or to make sure that the correct .so file is loaded at
runtime (usually by setting `LD_LIBRARY_PATH`). The simplest option is a static
runtime (usually by setting `LD_LIBRARY_PATH`). The simplest option is a static # code
build, usually possible via:
# code
```shell
$ CC=/path/to/afl/afl-gcc ./configure --disable-shared
```
Setting `AFL_HARDEN=1` when calling 'make' will cause the CC wrapper to
automatically enable code hardening options that make it easier to detect
simple memory bugs. Libdislocator, a helper library included with AFL (see
libdislocator/README.dislocator) can help uncover heap corruption issues, too.
simple memory bugs. Libdislocator, a helper library included with AFL (see # code
libdislocator/README.dislocator) can help uncover heap corruption issues, too. # code
# code
PS. ASAN users are advised to review [notes_for_asan.txt](docs/notes_for_asan.txt) file for important
caveats.
@ -118,36 +118,36 @@ caveats.
When source code is *NOT* available, the fuzzer offers experimental support for
fast, on-the-fly instrumentation of black-box binaries. This is accomplished
with a version of QEMU running in the lesser-known "user space emulation" mode.
with a version of QEMU running in the lesser-known "user space emulation" mode. # code
QEMU is a project separate from AFL, but you can conveniently build the
feature by doing:
feature by doing: ``````
# code
```shell
$ cd qemu_mode
$ ./build_qemu_support.sh
```
# code
For additional instructions and caveats, see qemu_mode/README.qemu.
The mode is approximately 2-5x slower than compile-time instrumentation, is
less conducive to parallelization, and may have some other quirks.
less conducive to parallelization, and may have some other quirks. # code
## 5) Choosing initial test cases
## 5) Choosing initial test cases ``````
To operate correctly, the fuzzer requires one or more starting file that
contains a good example of the input data normally expected by the targeted
contains a good example of the input data normally expected by the targeted # code
application. There are two basic rules:
- Keep the files small. Under 1 kB is ideal, although not strictly necessary.
- Keep the files small. Under 1 kB is ideal, although not strictly necessary. # code
For a discussion of why size matters, see [perf_tips.txt](docs/perf_tips.txt).
- Use multiple test cases only if they are functionally different from
each other. There is no point in using fifty different vacation photos
to fuzz an image library.
You can find many good examples of starting files in the testcases/ subdirectory
that comes with this tool.
You can find many good examples of starting files in the testcases/ subdirectory # code
that comes with this tool. ``````
PS. If a large corpus of data is available for screening, you may want to use
the afl-cmin utility to identify a subset of functionally distinct files that
@ -155,82 +155,82 @@ exercise different code paths in the target binary.
## 6) Fuzzing binaries
The fuzzing process itself is carried out by the afl-fuzz utility. This program
requires a read-only directory with initial test cases, a separate place to
store its findings, plus a path to the binary to test.
For target binaries that accept input directly from stdin, the usual syntax is:
The fuzzing process itself is carried out by the afl-fuzz utility. This program ``````
requires a read-only directory with initial test cases, a separate place to # code
store its findings, plus a path to the binary to test. # code
For target binaries that accept input directly from stdin, the usual syntax is: ``````
``````
```shell
$ ./afl-fuzz -i testcase_dir -o findings_dir /path/to/program [...params...]
```
``` ``````
# code
For programs that take input from a file, use '@@' to mark the location in
the target's command line where the input file name should be placed. The
fuzzer will substitute this for you:
```shell
```shell # code
$ ./afl-fuzz -i testcase_dir -o findings_dir /path/to/program @@
```
You can also use the -f option to have the mutated data written to a specific
file. This is useful if the program expects a particular file extension or so.
You can also use the -f option to have the mutated data written to a specific # code
file. This is useful if the program expects a particular file extension or so. ``````
Non-instrumented binaries can be fuzzed in the QEMU mode (add -Q in the command
line) or in a traditional, blind-fuzzer mode (specify -n).
You can use -t and -m to override the default timeout and memory limit for the
executed process; rare examples of targets that may need these settings touched
include compilers and video decoders.
include compilers and video decoders. # code
Tips for optimizing fuzzing performance are discussed in [perf_tips.txt](docs/perf_tips.txt).
Note that afl-fuzz starts by performing an array of deterministic fuzzing
Note that afl-fuzz starts by performing an array of deterministic fuzzing ``````
steps, which can take several days, but tend to produce neat test cases. If you
want quick & dirty results right away - akin to zzuf and other traditional
fuzzers - add the -d option to the command line.
fuzzers - add the -d option to the command line. # code
``````
## 7) Interpreting output
See the [status_screen.txt](docs/status_screen.txt) file for information on
how to interpret the displayed stats and monitor the health of the process.
Be sure to consult this file especially if any UI elements are highlighted in
red.
# code
The fuzzing process will continue until you press Ctrl-C. At minimum, you want
to allow the fuzzer to complete one queue cycle, which may take anywhere from a
couple of hours to a week or so.
There are three subdirectories created within the output directory and updated
# code
There are three subdirectories created within the output directory and updated # code
in real time:
- queue/ - test cases for every distinctive execution path, plus all the
starting files given by the user. This is the synthesized corpus
starting files given by the user. This is the synthesized corpus ``````
mentioned in section 2.
Before using this corpus for any other purposes, you can shrink
Before using this corpus for any other purposes, you can shrink # code
it to a smaller size using the afl-cmin tool. The tool will find
a smaller subset of files offering equivalent edge coverage.
- crashes/ - unique test cases that cause the tested program to receive a
fatal signal (e.g., SIGSEGV, SIGILL, SIGABRT). The entries are
fatal signal (e.g., SIGSEGV, SIGILL, SIGABRT). The entries are # code
grouped by the received signal.
- hangs/ - unique test cases that cause the tested program to time out. The
default time limit before something is classified as a hang is
the larger of 1 second and the value of the -t parameter.
the larger of 1 second and the value of the -t parameter. # code
The value can be fine-tuned by setting AFL_HANG_TMOUT, but this
is rarely necessary.
is rarely necessary. # code
Crashes and hangs are considered "unique" if the associated execution paths
involve any state transitions not seen in previously-recorded faults. If a
single bug can be reached in multiple ways, there will be some count inflation
early in the process, but this should quickly taper off.
early in the process, but this should quickly taper off. # code
The file names for crashes and hangs are correlated with parent, non-faulting
queue entries. This should help with debugging.
When you can't reproduce a crash found by afl-fuzz, the most likely cause is
that you are not setting the same memory limit as used by the tool. Try:
When you can't reproduce a crash found by afl-fuzz, the most likely cause is # code
that you are not setting the same memory limit as used by the tool. Try: # code
```shell
$ LIMIT_MB=50
@ -243,28 +243,28 @@ also change -Sv to -Sd.
Any existing output directory can be also used to resume aborted jobs; try:
```shell
$ ./afl-fuzz -i- -o existing_output_dir [...etc...]
```
$ ./afl-fuzz -i- -o existing_output_dir [...etc...] # code
``` # code
If you have gnuplot installed, you can also generate some pretty graphs for any
If you have gnuplot installed, you can also generate some pretty graphs for any # code
active fuzzing task using afl-plot. For an example of how this looks like,
see [http://lcamtuf.coredump.cx/afl/plot/](http://lcamtuf.coredump.cx/afl/plot/).
## 8) Parallelized fuzzing
Every instance of afl-fuzz takes up roughly one core. This means that on
multi-core systems, parallelization is necessary to fully utilize the hardware.
multi-core systems, parallelization is necessary to fully utilize the hardware. # code
For tips on how to fuzz a common target on multiple cores or multiple networked
machines, please refer to [parallel_fuzzing.txt](docs/parallel_fuzzing.txt).
The parallel fuzzing mode also offers a simple way for interfacing AFL to other
fuzzers, to symbolic or concolic execution engines, and so forth; again, see the
fuzzers, to symbolic or concolic execution engines, and so forth; again, see the # code
last section of [parallel_fuzzing.txt](docs/parallel_fuzzing.txt) for tips.
## 9) Fuzzer dictionaries
By default, afl-fuzz mutation engine is optimized for compact data formats -
say, images, multimedia, compressed data, regular expression syntax, or shell
say, images, multimedia, compressed data, regular expression syntax, or shell # code
scripts. It is somewhat less suited for languages with particularly verbose and
redundant verbiage - notably including HTML, SQL, or JavaScript.
@ -277,48 +277,48 @@ magic headers, or other special tokens associated with the targeted data type
To use this feature, you first need to create a dictionary in one of the two
formats discussed in dictionaries/README.dictionaries; and then point the fuzzer
to it via the -x option in the command line.
to it via the -x option in the command line. # code
``````
(Several common dictionaries are already provided in that subdirectory, too.)
There is no way to provide more structured descriptions of the underlying
syntax, but the fuzzer will likely figure out some of this based on the
instrumentation feedback alone. This actually works in practice, say:
[http://lcamtuf.blogspot.com/2015/04/finding-bugs-in-sqlite-easy-way.html](http://lcamtuf.blogspot.com/2015/04/finding-bugs-in-sqlite-easy-way.html)
PS. Even when no explicit dictionary is given, afl-fuzz will try to extract
[http://lcamtuf.blogspot.com/2015/04/finding-bugs-in-sqlite-easy-way.html](http://lcamtuf.blogspot.com/2015/04/finding-bugs-in-sqlite-easy-way.html) ``````
``````
PS. Even when no explicit dictionary is given, afl-fuzz will try to extract ``````
existing syntax tokens in the input corpus by watching the instrumentation
very closely during deterministic byte flips. This works for some types of
parsers and grammars, but isn't nearly as good as the -x mode.
If a dictionary is really hard to come by, another option is to let AFL run
for a while, and then use the token capture library that comes as a companion
utility with AFL. For that, see libtokencap/README.tokencap.
utility with AFL. For that, see libtokencap/README.tokencap. # code
# code
## 10) Crash triage
The coverage-based grouping of crashes usually produces a small data set that
can be quickly triaged manually or with a very simple GDB or Valgrind script.
Every crash is also traceable to its parent non-crashing test case in the
queue, making it easier to diagnose faults.
queue, making it easier to diagnose faults. # code
Having said that, it's important to acknowledge that some fuzzing crashes can be
difficult to quickly evaluate for exploitability without a lot of debugging and
Having said that, it's important to acknowledge that some fuzzing crashes can be # code
difficult to quickly evaluate for exploitability without a lot of debugging and # code
code analysis work. To assist with this task, afl-fuzz supports a very unique
"crash exploration" mode enabled with the -C flag.
"crash exploration" mode enabled with the -C flag. # code
# code
In this mode, the fuzzer takes one or more crashing test cases as the input,
and uses its feedback-driven fuzzing strategies to very quickly enumerate all
code paths that can be reached in the program while keeping it in the
crashing state.
crashing state. ``````
Mutations that do not result in a crash are rejected; so are any changes that
do not affect the execution path.
do not affect the execution path. ``````
The output is a small corpus of files that can be very rapidly examined to see
what degree of control the attacker has over the faulting address, or whether
it is possible to get past an initial out-of-bounds read - and see what lies
The output is a small corpus of files that can be very rapidly examined to see # code
what degree of control the attacker has over the faulting address, or whether # code
it is possible to get past an initial out-of-bounds read - and see what lies # code
beneath.
Oh, one more thing: for test case minimization, give afl-tmin a try. The tool
@ -329,19 +329,19 @@ $ ./afl-tmin -i test_case -o minimized_result -- /path/to/program [...]
```
The tool works with crashing and non-crashing test cases alike. In the crash
mode, it will happily accept instrumented and non-instrumented binaries. In the
mode, it will happily accept instrumented and non-instrumented binaries. In the ``````
non-crashing mode, the minimizer relies on standard AFL instrumentation to make
the file simpler without altering the execution path.
the file simpler without altering the execution path. # code
The minimizer accepts the -m, -t, -f and @@ syntax in a manner compatible with
afl-fuzz.
# code
Another recent addition to AFL is the afl-analyze tool. It takes an input
file, attempts to sequentially flip bytes, and observes the behavior of the
file, attempts to sequentially flip bytes, and observes the behavior of the # code
tested program. It then color-codes the input based on which sections appear to
be critical, and which are not; while not bulletproof, it can often offer quick
insights into complex file formats. More info about its operation can be found
near the end of [technical_details.txt](docs/technical_details.txt).
near the end of [technical_details.txt](docs/technical_details.txt). # code
## 11) Going beyond crashes
@ -352,21 +352,21 @@ found by modifying the target programs to call abort() when, say:
- Two bignum libraries produce different outputs when given the same
fuzzer-generated input,
- An image library produces different outputs when asked to decode the same
- An image library produces different outputs when asked to decode the same # code
input image several times in a row,
- A serialization / deserialization library fails to produce stable outputs
- A serialization / deserialization library fails to produce stable outputs ``````
when iteratively serializing and deserializing fuzzer-supplied data,
- A compression library produces an output inconsistent with the input file
when asked to compress and then decompress a particular blob.
Implementing these or similar sanity checks usually takes very little time;
if you are the maintainer of a particular package, you can make this code
if you are the maintainer of a particular package, you can make this code # code
conditional with `#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION` (a flag also
shared with libfuzzer) or `#ifdef __AFL_COMPILER` (this one is just for AFL).
## 12) Common-sense risks
## 12) Common-sense risks ``````
Please keep in mind that, similarly to many other computationally-intensive
tasks, fuzzing may put strain on your hardware and on the OS. In particular:
@ -379,19 +379,19 @@ tasks, fuzzing may put strain on your hardware and on the OS. In particular:
- Targeted programs may end up erratically grabbing gigabytes of memory or
filling up disk space with junk files. AFL tries to enforce basic memory
limits, but can't prevent each and every possible mishap. The bottom line
is that you shouldn't be fuzzing on systems where the prospect of data loss
is not an acceptable risk.
limits, but can't prevent each and every possible mishap. The bottom line # code
is that you shouldn't be fuzzing on systems where the prospect of data loss # code
is not an acceptable risk. # code
- Fuzzing involves billions of reads and writes to the filesystem. On modern
systems, this will be usually heavily cached, resulting in fairly modest
"physical" I/O - but there are many factors that may alter this equation.
systems, this will be usually heavily cached, resulting in fairly modest # code
"physical" I/O - but there are many factors that may alter this equation. # code
It is your responsibility to monitor for potential trouble; with very heavy
I/O, the lifespan of many HDDs and SSDs may be reduced.
A good way to monitor disk I/O on Linux is the 'iostat' command:
A good way to monitor disk I/O on Linux is the 'iostat' command: # code
```shell
```shell # code
$ iostat -d 3 -x -k [...optional disk ID...]
```
@ -403,34 +403,34 @@ Here are some of the most important caveats for AFL:
a signal (SIGSEGV, SIGABRT, etc). Programs that install custom handlers for
these signals may need to have the relevant code commented out. In the same
vein, faults in child processed spawned by the fuzzed target may evade
detection unless you manually add some code to catch that.
detection unless you manually add some code to catch that. # code
- As with any other brute-force tool, the fuzzer offers limited coverage if
encryption, checksums, cryptographic signatures, or compression are used to
wholly wrap the actual data format to be tested.
To work around this, you can comment out the relevant checks (see
To work around this, you can comment out the relevant checks (see # code
experimental/libpng_no_checksum/ for inspiration); if this is not possible,
you can also write a postprocessor, as explained in
you can also write a postprocessor, as explained in # code
experimental/post_library/.
- There are some unfortunate trade-offs with ASAN and 64-bit binaries. This
isn't due to any specific fault of afl-fuzz; see [notes_for_asan.txt](docs/notes_for_asan.txt)
for tips.
for tips. # code
- There is no direct support for fuzzing network services, background
- There is no direct support for fuzzing network services, background ``````
daemons, or interactive apps that require UI interaction to work. You may
need to make simple code changes to make them behave in a more traditional
way. Preeny may offer a relatively simple option, too - see:
way. Preeny may offer a relatively simple option, too - see: ``````
https://github.com/zardus/preeny
Some useful tips for modifying network-based services can be also found at:
Some useful tips for modifying network-based services can be also found at: # code
https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop
- AFL doesn't output human-readable coverage data. If you want to monitor
coverage, use afl-cov from Michael Rash: https://github.com/mrash/afl-cov
- Occasionally, sentient machines rise against their creators. If this
# code
- Occasionally, sentient machines rise against their creators. If this ``````
happens to you, please consult http://lcamtuf.coredump.cx/prep/.
Beyond this, see INSTALL for platform-specific tips.
@ -438,56 +438,56 @@ Beyond this, see INSTALL for platform-specific tips.
## 14) Special thanks
Many of the improvements to afl-fuzz wouldn't be possible without feedback,
bug reports, or patches from:
bug reports, or patches from: # code
```
Jann Horn Hanno Boeck
Felix Groebert Jakub Wilk
Felix Groebert Jakub Wilk # code
Richard W. M. Jones Alexander Cherepanov
Tom Ritter Hovik Manucharyan
Sebastian Roschke Eberhard Mattes
Padraig Brady Ben Laurie
@dronesec Luca Barbato
Sebastian Roschke Eberhard Mattes ``````
Padraig Brady Ben Laurie # code
@dronesec Luca Barbato # code
Tobias Ospelt Thomas Jarosch
Martin Carpenter Mudge Zatko
Joe Zbiciak Ryan Govostes
Michael Rash William Robinet
Michael Rash William Robinet # code
Jonathan Gray Filipe Cabecinhas
Nico Weber Jodie Cunningham
Andrew Griffiths Parker Thompson
Jonathan Neuschfer Tyler Nighswander
Ben Nagy Samir Aguiar
Aidan Thornton Aleksandar Nikolich
Ben Nagy Samir Aguiar ``````
Aidan Thornton Aleksandar Nikolich # code
Sam Hakim Laszlo Szekeres
David A. Wheeler Turo Lamminen
Andreas Stieger Richard Godbee
Louis Dassy teor2345
Louis Dassy teor2345 ``````
Alex Moneger Dmitry Vyukov
Keegan McAllister Kostya Serebryany
Keegan McAllister Kostya Serebryany # code
Richo Healey Martijn Bogaard
rc0r Jonathan Foote
Christian Holler Dominique Pelle
Jacek Wielemborek Leo Barnes
Jacek Wielemborek Leo Barnes # code
Jeremy Barnes Jeff Trull
Guillaume Endignoux ilovezfs
Daniel Godas-Lopez Franjo Ivancic
Austin Seipp Daniel Komaromy
Daniel Godas-Lopez Franjo Ivancic # code
Austin Seipp Daniel Komaromy # code
Daniel Binderman Jonathan Metzman
Vegard Nossum Jan Kneschke
Kurt Roeckx Marcel Bohme
Van-Thuan Pham Abhik Roychoudhury
Joshua J. Drake Toby Hutton
Rene Freingruber Sergey Davidoff
Joshua J. Drake Toby Hutton ``````
Rene Freingruber Sergey Davidoff ``````
Sami Liedes Craig Young
Andrzej Jackowski Daniel Hodson
```
Thank you!
Thank you! ``````
## 15) Contact
Questions? Concerns? Bug reports? Please use GitHub.
# code
Questions? Concerns? Bug reports? Please use GitHub. ``````
There is also a mailing list for the project; to join, send a mail to
<afl-users+subscribe@googlegroups.com>. Or, if you prefer to browse
<afl-users+subscribe@googlegroups.com>. Or, if you prefer to browse ``````
archives first, try: [https://groups.google.com/group/afl-users](https://groups.google.com/group/afl-users).

@ -14,6 +14,8 @@
limitations under the License.
*/
// 这部分是版权声明和许可协议,声明该文件受到 Apache 2.0 许可证保护。
/*
american fuzzy lop - wrapper for GNU as
---------------------------------------
@ -36,6 +38,10 @@
*/
// 该段注释解释了代码的功能
// 它是一个用于 GNU as 汇编器的包装器
// 目的是预处理由 GCC/Clang 生成的汇编文件并注入必要的仪器代码
#define AFL_MAIN
#include "config.h"
@ -56,20 +62,43 @@
#include <sys/wait.h>
#include <sys/time.h>
// 定义宏 AFL_MAIN通常用于标识主程序或相关模块。
// 包含内部的头文件,这些文件提供了项目的配置、类型定义、调试功能以及内存分配等支持。
// 包含标准的C库和POSIX库头文件用于文件操作、内存管理、时间处理等。
static u8** as_params; /* Parameters passed to the real 'as' */
static u8* input_file; /* Originally specified input file */
static u8* modified_file; /* Instrumented file for the real 'as' */
//声明静态变量:
// as_params保存传递给实际 as 汇编器的参数。
// input_file保存输入的文件路径。
// modified_file保存经过修改的文件路径即注入了仪器代码后的文件
static u8 be_quiet, /* Quiet mode (no stderr output) */
clang_mode, /* Running in clang mode? */
pass_thru, /* Just pass data through? */
just_version, /* Just show version? */
sanitizer; /* Using ASAN / MSAN */
// 声明其他控制程序行为的静态变量:
// be_quiet控制是否启用静默模式不输出标准错误。
// clang_mode是否处于 clang 模式。
// pass_thru是否跳过修改直接传递数据。
// just_version是否只显示版本信息。
// sanitizer是否启用了地址或内存错误检测工具如 ASAN 或 MSAN
static u32 inst_ratio = 100, /* Instrumentation probability (%) */
as_par_cnt = 1; /* Number of params to 'as' */
// 声明静态变量:
// inst_ratio仪器插入的概率百分比
// as_par_cnt传递给汇编器 as 的参数数量。
/* If we don't find --32 or --64 in the command line, default to
instrumentation for whichever mode we were compiled with. This is not
perfect, but should do the trick for almost all use cases. */
@ -88,20 +117,32 @@ static u8 use_64bit = 0;
#endif /* ^WORD_SIZE_64 */
// 根据编译时的定义判断是否使用 64 位模式。
// 如果没有定义 WORD_SIZE_64则默认使用 32 位模式。
// 如果是苹果平台,还会抛出一个错误,表明不支持 32 位 Apple 平台。
/* Examine and modify parameters to pass to 'as'. Note that the file name
is always the last parameter passed by GCC, so we exploit this property
to keep the code simple. */
// 这段注释解释了接下来要做的工作:分析和修改传递给汇编器 as 的参数,特别是文件名,它总是作为最后一个参数传递给 GCC。
static void edit_params(int argc, char** argv) {
// 定义函数 edit_params用于修改传递给 as 汇编器的参数。
u8 *tmp_dir = getenv("TMPDIR"), *afl_as = getenv("AFL_AS");
u32 i;
// 获取环境变量 TMPDIR 和 AFL_AS并声明变量 i。
#ifdef __APPLE__
u8 use_clang_as = 0;
// 如果是在 Apple 平台上,声明一个变量 use_clang_as 来标识是否使用 clang 作为汇编器。
/* On MacOS X, the Xcode cctool 'as' driver is a bit stale and does not work
with the code generated by newer versions of clang that are hand-built
by the user. See the thread here: http://goo.gl/HBWDtn.
@ -122,6 +163,8 @@ static void edit_params(int argc, char** argv) {
if (!afl_as) afl_as = getenv("AFL_CXX");
if (!afl_as) afl_as = "clang";
// 如果在 clang 模式下且没有指定 AFL_AS则尝试使用 clang 作为汇编器。
}
#endif /* __APPLE__ */
@ -134,10 +177,17 @@ static void edit_params(int argc, char** argv) {
if (!tmp_dir) tmp_dir = getenv("TMP");
if (!tmp_dir) tmp_dir = "/tmp";
//如果没有设置 TMPDIR则尝试使用其他环境变量如 TEMP 和 TMP如果都没有设置则默认使用 /tmp。
as_params = ck_alloc((argc + 32) * sizeof(u8*));
// 为汇编器参数分配内存,留出额外的空间。
as_params[0] = afl_as ? afl_as : (u8*)"as";
// 设置 as 汇编器命令,如果没有设置 AFL_AS则默认使用 "as"。
as_params[argc] = 0;
for (i = 1; i < argc - 1; i++) {
@ -169,11 +219,17 @@ static void edit_params(int argc, char** argv) {
}
// 遍历所有传递给程序的参数,如果参数为 --64 或 --32则根据平台设置 use_64bit
// 对于 Apple 平台,还会检查架构并设置为 64 位。
#ifdef __APPLE__
/* When calling clang as the upstream assembler, append -c -x assembler
and hope for the best. */
// 这段注释说明接下来的操作是调用真正的 as 汇编器,并传递适当的参数。
// 如果一切顺利as 会返回一个 0 的退出代码,程序会传播这个退出代码。
if (use_clang_as) {
as_params[as_par_cnt++] = "-c";
@ -182,6 +238,13 @@ static void edit_params(int argc, char** argv) {
}
// 在 exec_real_as 函数中:
// 如果处于静默模式be_quiet则关闭标准错误输出并将其重定向到 /dev/null避免打印调试信息。
// 使用 execvp 执行汇编器命令,传递修改后的参数。
// 如果执行失败,则打印错误信息并退出程序。
#endif /* __APPLE__ */
input_file = argv[argc - 1];
@ -191,7 +254,7 @@ static void edit_params(int argc, char** argv) {
if (!strcmp(input_file + 1, "-version")) {
just_version = 1;
modified_file = input_file;
goto wrap_things_up;
goto wrap_things_up; // 跳到 wrap_things_up 标签,处理版本信息
}
if (input_file[1]) FATAL("Incorrect use (not called through afl-gcc?)");
@ -199,122 +262,118 @@ static void edit_params(int argc, char** argv) {
} else {
/* Check if this looks like a standard invocation as a part of an attempt
to compile a program, rather than using gcc on an ad-hoc .s file in
a format we may not understand. This works around an issue compiling
NSS. */
/* 检查输入文件路径是否看起来像是编译程序的一部分,而不是使用 gcc 编译一个临时的 .s 文件 */
/* 这段代码是为了绕过某些特殊情况,比如编译 NSS 库时的情况 */
if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) &&
strncmp(input_file, "/var/tmp/", 9) &&
strncmp(input_file, "/tmp/", 5)) pass_thru = 1;
strncmp(input_file, "/tmp/", 5)) pass_thru = 1; // 启用通过模式
}
modified_file = alloc_printf("%s/.afl-%u-%u.s", tmp_dir, getpid(),
(u32)time(NULL));
(u32)time(NULL)); // 为生成的文件名分配内存并格式化
wrap_things_up:
as_params[as_par_cnt++] = modified_file;
as_params[as_par_cnt] = NULL;
as_params[as_par_cnt++] = modified_file; // 将修改后的文件名添加到参数列表
as_params[as_par_cnt] = NULL; // 参数列表以 NULL 结尾
}
// 此段代码注释说明了程序如何检查和处理输入文件,包括:
// 如果文件名以 - 开头,可能是传递版本信息或者其他特殊的命令行参数。
// 如果文件路径看起来是临时目录之外的路径则启用“通过模式”pass_thru这表示不进行修改直接传递给汇编器。
/* Process input file, generate modified_file. Insert instrumentation in all
the appropriate places. */
/* 处理输入文件,生成修改后的文件,并在所有适当的位置插入仪器代码 */
static void add_instrumentation(void) {
static u8 line[MAX_LINE];
static u8 line[MAX_LINE]; // 用于存储每一行的内容
FILE* inf;
FILE* outf;
s32 outfd;
u32 ins_lines = 0;
u32 ins_lines = 0; // 记录插入了多少行
u8 instr_ok = 0, skip_csect = 0, skip_next_label = 0,
skip_intel = 0, skip_app = 0, instrument_next = 0;
#ifdef __APPLE__
u8* colon_pos;
u8* colon_pos; // 用于查找冒号位置
#endif /* __APPLE__ */
if (input_file) {
inf = fopen(input_file, "r");
if (!inf) PFATAL("Unable to read '%s'", input_file);
inf = fopen(input_file, "r"); // 打开输入文件进行读取
if (!inf) PFATAL("Unable to read '%s'", input_file); // 如果打开失败,打印错误并退出
} else inf = stdin;
} else inf = stdin; // 如果没有指定输入文件,使用标准输入
outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600);
outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600); // 创建输出文件
if (outfd < 0) PFATAL("Unable to write to '%s'", modified_file);
if (outfd < 0) PFATAL("Unable to write to '%s'", modified_file); // 如果创建失败,打印错误并退出
outf = fdopen(outfd, "w");
outf = fdopen(outfd, "w"); // 获取文件流
if (!outf) PFATAL("fdopen() failed");
if (!outf) PFATAL("fdopen() failed"); // 如果 fdopen 失败,打印错误并退出
while (fgets(line, MAX_LINE, inf)) {
while (fgets(line, MAX_LINE, inf)) { // 逐行读取输入文件
/* In some cases, we want to defer writing the instrumentation trampoline
until after all the labels, macros, comments, etc. If we're in this
mode, and if the line starts with a tab followed by a character, dump
the trampoline now. */
/* 在某些情况下,我们希望在写入仪器跳板之前先跳过某些标签、宏或注释。
*/
if (!pass_thru && !skip_intel && !skip_app && !skip_csect && instr_ok &&
instrument_next && line[0] == '\t' && isalpha(line[1])) {
fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,
R(MAP_SIZE));
R(MAP_SIZE)); // 根据使用的位数选择合适的跳板格式
instrument_next = 0;
ins_lines++;
ins_lines++; // 统计插入的行数
}
/* Output the actual line, call it a day in pass-thru mode. */
/* 输出当前行,只有在通过模式下才跳过插入仪器 */
fputs(line, outf);
if (pass_thru) continue;
if (pass_thru) continue; // 如果启用了通过模式,则跳过剩下的处理
/* All right, this is where the actual fun begins. For one, we only want to
instrument the .text section. So, let's keep track of that in processed
files - and let's set instr_ok accordingly. */
/* 以下代码处理实际的插桩逻辑,只在 .text 段插入仪器代码 */
if (line[0] == '\t' && line[1] == '.') {
/* OpenBSD puts jump tables directly inline with the code, which is
a bit annoying. They use a specific format of p2align directives
around them, so we use that as a signal. */
/* OpenBSD 将跳转表直接内联到代码中,这很麻烦。它们使用特定的 p2align 指令格式,
*/
if (!clang_mode && instr_ok && !strncmp(line + 2, "p2align ", 8) &&
isdigit(line[10]) && line[11] == '\n') skip_next_label = 1;
/* 如果检测到 .text 段或相关段,启用插桩 */
if (!strncmp(line + 2, "text\n", 5) ||
!strncmp(line + 2, "section\t.text", 13) ||
!strncmp(line + 2, "section\t__TEXT,__text", 21) ||
!strncmp(line + 2, "section __TEXT,__text", 21)) {
instr_ok = 1;
continue;
continue; // 继续处理下一行
}
/* 如果是其他段(如 bss、data禁用插桩 */
if (!strncmp(line + 2, "section\t", 8) ||
!strncmp(line + 2, "section ", 8) ||
!strncmp(line + 2, "bss\n", 4) ||
!strncmp(line + 2, "data\n", 5)) {
instr_ok = 0;
continue;
continue; // 继续处理下一行
}
}
/* Detect off-flavor assembly (rare, happens in gdb). When this is
encountered, we set skip_csect until the opposite directive is
seen, and we do not instrument. */
/* 检测并跳过特定的汇编节(如 .code */
if (strstr(line, ".code")) {
@ -323,14 +382,11 @@ static void add_instrumentation(void) {
}
/* Detect syntax changes, as could happen with hand-written assembly.
Skip Intel blocks, resume instrumentation when back to AT&T. */
/* 检测并跳过 Intel 语法块 */
if (strstr(line, ".intel_syntax")) skip_intel = 1;
if (strstr(line, ".att_syntax")) skip_intel = 0;
/* Detect and skip ad-hoc __asm__ blocks, likewise skipping them. */
/* 跳过 ad-hoc 的 __asm__ 块 */
if (line[0] == '#' || line[1] == '#') {
if (strstr(line, "#APP")) skip_app = 1;
@ -338,45 +394,20 @@ static void add_instrumentation(void) {
}
/* If we're in the right mood for instrumenting, check for function
names or conditional labels. This is a bit messy, but in essence,
we want to catch:
^main: - function entry point (always instrumented)
^.L0: - GCC branch label
^.LBB0_0: - clang branch label (but only in clang mode)
^\tjnz foo - conditional branches
...but not:
^# BB#0: - clang comments
^ # BB#0: - ditto
^.Ltmp0: - clang non-branch labels
^.LC0 - GCC non-branch labels
^.LBB0_0: - ditto (when in GCC mode)
^\tjmp foo - non-conditional jumps
Additionally, clang and GCC on MacOS X follow a different convention
with no leading dots on labels, hence the weird maze of #ifdefs
later on.
*/
/* 检查并插入仪器代码:主要是函数标签、条件标签等 */
if (skip_intel || skip_app || skip_csect || !instr_ok ||
line[0] == '#' || line[0] == ' ') continue;
line[0] == '#' || line[0] == ' ') continue; // 跳过不需要插入的行
/* Conditional branch instruction (jnz, etc). We append the instrumentation
right after the branch (to instrument the not-taken path) and at the
branch destination label (handled later on). */
/* 条件分支指令(如 jnz 等)。我们将插入仪器代码到分支指令后面(用于记录未采取的路径) */
if (line[0] == '\t') {
if (line[1] == 'j' && line[2] != 'm' && R(100) < inst_ratio) {
fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,
R(MAP_SIZE));
R(MAP_SIZE)); // 插入仪器代码
ins_lines++;
ins_lines++; // 统计插入的行数
}
@ -384,13 +415,11 @@ static void add_instrumentation(void) {
}
/* Label of some sort. This may be a branch destination, but we need to
tread carefully and account for several different formatting
conventions. */
/* 标签的处理。标签可能是分支目标,我们需要根据格式区分处理 */
#ifdef __APPLE__
/* Apple: L<whatever><digit>: */
/* 苹果系统标签格式:L<whatever><digit>: */
if ((colon_pos = strstr(line, ":"))) {
@ -398,7 +427,7 @@ static void add_instrumentation(void) {
#else
/* Everybody else: .L<whatever>: */
/* 其他平台的标签格式:.L<whatever>: */
if (strstr(line, ":")) {
@ -406,34 +435,25 @@ static void add_instrumentation(void) {
#endif /* __APPLE__ */
/* .L0: or LBB0_0: style jump destination */
/* 处理跳转目标标签(如 .L0: 或 LBB0_0: */
#ifdef __APPLE__
/* Apple: L<num> / LBB<num> */
/* 苹果:L<num> / LBB<num> */
if ((isdigit(line[1]) || (clang_mode && !strncmp(line, "LBB", 3)))
&& R(100) < inst_ratio) {
#else
/* Apple: .L<num> / .LBB<num> */
/* 其他平台:.L<num> / .LBB<num> */
if ((isdigit(line[2]) || (clang_mode && !strncmp(line + 1, "LBB", 3)))
&& R(100) < inst_ratio) {
#endif /* __APPLE__ */
/* An optimization is possible here by adding the code only if the
label is mentioned in the code in contexts other than call / jmp.
That said, this complicates the code by requiring two-pass
processing (messy with stdin), and results in a speed gain
typically under 10%, because compilers are generally pretty good
about not generating spurious intra-function jumps.
We use deferred output chiefly to avoid disrupting
.Lfunc_begin0-style exception handling calculations (a problem on
MacOS X). */
/* 如果符合条件,则插入仪器代码 */
if (!skip_next_label) instrument_next = 1; else skip_next_label = 0;
@ -441,7 +461,7 @@ static void add_instrumentation(void) {
} else {
/* Function label (always instrumented, deferred mode). */
/* 函数标签,插入仪器代码 */
instrument_next = 1;
@ -451,29 +471,28 @@ static void add_instrumentation(void) {
}
if (ins_lines)
fputs(use_64bit ? main_payload_64 : main_payload_32, outf);
if (input_file) fclose(inf);
fclose(outf);
if (!be_quiet) {
if (!ins_lines) WARNF("No instrumentation targets found%s.",
pass_thru ? " (pass-thru mode)" : "");
else OKF("Instrumented %u locations (%s-bit, %s mode, ratio %u%%).",
ins_lines, use_64bit ? "64" : "32",
getenv("AFL_HARDEN") ? "hardened" :
(sanitizer ? "ASAN/MSAN" : "non-hardened"),
inst_ratio);
}
fclose(inf); // 关闭输入文件
fclose(outf); // 关闭输出文件
}
/* Main entry point */
// 在 main 函数中:
// 检查是否只需要显示版本信息,如果是,则调用 print_version 函数。
// 解析命令行参数:
// 解析 -q 启用静默模式。
// 解析 --clang 启用 clang 模式。
// 解析 --pass-through 启用数据通过模式。
// 解析 --sanitizer 启用 sanitizer。
// 解析 --inst-ratio 设置仪器插入的概率。
// 解析 --version 仅显示版本信息。
// 确保输入文件已经指定,如果没有指定,则退出并报错。
// 调用 edit_params 函数修改传递给汇编器的参数。
// 最后,调用 exec_real_as 函数执行实际的汇编器命令。
int main(int argc, char** argv) {
s32 pid;

Before

Width:  |  Height:  |  Size: 581 KiB

After

Width:  |  Height:  |  Size: 581 KiB

Before

Width:  |  Height:  |  Size: 892 B

After

Width:  |  Height:  |  Size: 892 B

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before

Width:  |  Height:  |  Size: 38 B

After

Width:  |  Height:  |  Size: 38 B

Before

Width:  |  Height:  |  Size: 179 B

After

Width:  |  Height:  |  Size: 179 B

Before

Width:  |  Height:  |  Size: 642 B

After

Width:  |  Height:  |  Size: 642 B

Before

Width:  |  Height:  |  Size: 595 B

After

Width:  |  Height:  |  Size: 595 B

Before

Width:  |  Height:  |  Size: 876 B

After

Width:  |  Height:  |  Size: 876 B

Before

Width:  |  Height:  |  Size: 293 B

After

Width:  |  Height:  |  Size: 293 B

Before

Width:  |  Height:  |  Size: 434 B

After

Width:  |  Height:  |  Size: 434 B

Before

Width:  |  Height:  |  Size: 996 B

After

Width:  |  Height:  |  Size: 996 B

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save