Skip to content

Commit 7db6a4d

Browse files
authored
Merge pull request #2 from SQLab/Lab7
feat: add Lab7
2 parents 03afc2d + 97fb538 commit 7db6a4d

File tree

7 files changed

+425
-0
lines changed

7 files changed

+425
-0
lines changed

Lab7/Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
all:
2+
./build.sh
3+
AFL_DEMO=1 ./AFLplusplus/afl-clang-fast -O0 -w program.c -o program
4+
mkdir -p input
5+
echo -ne "\x00" > input/seed0
6+
7+
run:
8+
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFLplusplus/afl-fuzz -i input -o output -- ./program
9+
10+
clean:
11+
rm -rf AFLplusplus input output program

Lab7/README.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Lab7
2+
3+
## Introduction
4+
5+
In this lab, you will write a LLVM pass in `llvm-pass/afl-demo-pass.so.cc` and `llvm-pass/afl-demo-rt.o.c`, and enable AFL++ to detect command injection vulnerabilities.
6+
7+
## Environment (Important.)
8+
9+
1. x86_64 machine
10+
2. Ubuntu 22.04
11+
3. llvm-14
12+
13+
## Requirement
14+
15+
**(100%)** In this lab, you will write a LLVM pass in `llvm-pass/afl-demo-pass.so.cc` & `llvm-pass/afl-demo-rt.o.c` and satisfy the following requirements.
16+
1. When running afl++ to fuzz `program`, `program` can't crash by `system("echo AAA");` at line 34 in `program.c`. It's not command injection, and you will see the error message below when you try to fuzz:
17+
```
18+
[-] PROGRAM ABORT : We need at least one valid input seed that does not crash!
19+
```
20+
Of course, you can not just detect this line to avoid it. We will modify this command and add additional system functions (which won't cause command injection) in `program.c` during testing with your fuzzer.
21+
2. When running afl++ to fuzz `program`, the fuzzer needs to find the command injection `system(cmd)` at line 18 in `program.c`.
22+
3. Write a report in `{student_ID}.pdf` to explain your work.
23+
- Your report must include the following sections
24+
- Your name and student ID,
25+
- Explanation of your work
26+
- Copy the crash fuzzer report and crash input (use `xxd`) in `{student_ID}.pdf`.
27+
28+
**Template**
29+
30+
Name:
31+
student_ID:
32+
33+
```
34+
Explanation of your work
35+
```
36+
37+
Crash fuzzer report
38+
```
39+
40+
american fuzzy lop ++4.01c {default} (./program) [fast]
41+
┌─ process timing ────────────────────────────────────┬─ overall results ────┐
42+
│ run time : 0 days, 0 hrs, 0 min, 18 sec │ cycles done : 9 │
43+
│ last new find : 0 days, 0 hrs, 0 min, 8 sec │ corpus count : 7 │
44+
│last saved crash : 0 days, 0 hrs, 0 min, 3 sec │saved crashes : 1 │
45+
│ last saved hang : none seen yet │ saved hangs : 0 │
46+
├─ cycle progress ─────────────────────┬─ map coverage┴──────────────────────┤
47+
│ now processing : 5.3 (71.4%) │ map density : 30.77% / 76.92% │
48+
│ runs timed out : 0 (0.00%) │ count coverage : 39.40 bits/tuple │
49+
├─ stage progress ─────────────────────┼─ findings in depth ─────────────────┤
50+
│ now trying : havoc │ favored items : 7 (100.00%) │
51+
│ stage execs : 312/1175 (26.55%) │ new edges on : 7 (100.00%) │
52+
│ total execs : 97.2k │ total crashes : 1 (1 saved) │
53+
│ exec speed : 5329/sec │ total tmouts : 1 (0 saved) │
54+
├─ fuzzing strategy yields ────────────┴─────────────┬─ item geometry ───────┤
55+
│ bit flips : disabled (default, enable with -D) │ levels : 6 │
56+
│ byte flips : disabled (default, enable with -D) │ pending : 0 │
57+
│ arithmetics : disabled (default, enable with -D) │ pend fav : 0 │
58+
│ known ints : disabled (default, enable with -D) │ own finds : 6 │
59+
│ dictionary : n/a │ imported : 0 │
60+
│havoc/splice : 4/38.3k, 3/58.5k │ stability : 100.00% │
61+
│py/custom/rq : unused, unused, unused, unused ├───────────────────────┘
62+
│ trim/eff : 0.00%/7, disabled │ [cpu000: 12%]
63+
└────────────────────────────────────────────────────┘
64+
65+
```
66+
Crash Input:
67+
```
68+
$ xxd output/default/crashes/id\:000000\,sig\:06\,src\:000006\,time\:15137\,execs\:81803\,op\:havoc\,rep\:2
69+
00000000: 4655 5a5a 2146 ec40 FUZZ!F.@
70+
```
71+
72+
## Submission
73+
74+
1. Lab7 will not have github ci, so the grade of Lab7 will be determined with your report `{studemt_ID}.pdf`
75+
2. Submit the report `{student_ID}.pdf` to explain your work.
76+
3. You must submit these two files `llvm-pass/afl-demo-pass.so.cc` and `llvm-pass/afl-demo-rt.o.c`.
77+
4. You need to commit and push the corresponding changes to your repository, which contains the code that satisfies the aforementioned requirements.

Lab7/build.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/bash -ex
2+
3+
if [ ! -d "AFLplusplus" ]; then
4+
git clone -b 4.01c --depth 1 https://github.com/AFLplusplus/AFLplusplus.git
5+
git -C AFLplusplus apply ../integration.diff
6+
fi
7+
8+
cp llvm-pass/* AFLplusplus/instrumentation
9+
cd AFLplusplus
10+
make LLVM_CONFIG=llvm-config-14

Lab7/integration.diff

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm
2+
index 685964b7..9f309c08 100644
3+
--- a/GNUmakefile.llvm
4+
+++ b/GNUmakefile.llvm
5+
@@ -308,7 +308,7 @@ ifeq "$(TEST_MMAP)" "1"
6+
endif
7+
8+
PROGS_ALWAYS = ./afl-cc ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o
9+
-PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./cmplog-switches-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./SanitizerCoverageLTO.so
10+
+PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./cmplog-switches-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./SanitizerCoverageLTO.so ./afl-demo-pass.so ./afl-demo-rt.o
11+
12+
# If prerequisites are not given, warn, do not build anything, and exit with code 0
13+
ifeq "$(LLVMVER)" ""
14+
@@ -436,6 +436,9 @@ endif
15+
afl-llvm-dict2file.so: instrumentation/afl-llvm-dict2file.so.cc instrumentation/afl-llvm-common.o | test_deps
16+
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
17+
18+
+afl-demo-pass.so: instrumentation/afl-demo-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
19+
+ $(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL)
20+
+
21+
.PHONY: document
22+
document:
23+
$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -fPIC -c instrumentation/afl-compiler-rt.o.c -o ./afl-compiler-rt.o
24+
@@ -453,6 +456,9 @@ document:
25+
@printf "[*] Building 64-bit variant of the runtime (-m64)... "
26+
@$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
27+
28+
+./afl-demo-rt.o: instrumentation/afl-demo-rt.o.c
29+
+ $(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -fPIC -c $< -o $@
30+
+
31+
.PHONY: test_build
32+
test_build: $(PROGS)
33+
@echo "[*] Testing the CC wrapper and instrumentation output..."
34+
@@ -475,6 +481,7 @@ install: all
35+
@if [ -f ./afl-cc ]; then set -e; install -m 755 ./afl-cc $${DESTDIR}$(BIN_PATH); ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-c++; fi
36+
@rm -f $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt*.o $${DESTDIR}$(HELPER_PATH)/afl-gcc-rt*.o
37+
@if [ -f ./afl-compiler-rt.o ]; then set -e; install -m 755 ./afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH); fi
38+
+ @if [ -f ./afl-demo-rt.o ]; then set -e; install -m 755 ./afl-demo-rt.o $${DESTDIR}$(HELPER_PATH); fi
39+
@if [ -f ./afl-lto ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto++; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ./afl-llvm-rt-lto*.o ./afl-llvm-lto-instrumentlist.so $${DESTDIR}$(HELPER_PATH); fi
40+
@if [ -f ./afl-ld-lto ]; then set -e; install -m 755 ./afl-ld-lto $${DESTDIR}$(BIN_PATH); fi
41+
@if [ -f ./afl-compiler-rt-32.o ]; then set -e; install -m 755 ./afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH); fi
42+
diff --git a/include/envs.h b/include/envs.h
43+
index 25b792fa..bbe9a99e 100644
44+
--- a/include/envs.h
45+
+++ b/include/envs.h
46+
@@ -226,6 +226,7 @@ static char *afl_environment_variables[] = {
47+
"AFL_USE_QASAN",
48+
"AFL_PRINT_FILENAMES",
49+
"AFL_PIZZA_MODE",
50+
+ "AFL_DEMO",
51+
NULL
52+
53+
};
54+
diff --git a/src/afl-cc.c b/src/afl-cc.c
55+
index 2667ae28..7da0b89c 100644
56+
--- a/src/afl-cc.c
57+
+++ b/src/afl-cc.c
58+
@@ -57,6 +57,7 @@ static u8 * lto_flag = AFL_CLANG_FLTO, *argvnull;
59+
static u8 debug;
60+
static u8 cwd[4096];
61+
static u8 cmplog_mode;
62+
+static u8 demo_mode;
63+
u8 use_stdin; /* dummy */
64+
static int passthrough;
65+
// static u8 *march_opt = CFLAGS_OPT;
66+
@@ -699,6 +700,23 @@ static void edit_params(u32 argc, char **argv, char **envp) {
67+
68+
}
69+
70+
+
71+
+ if (demo_mode) {
72+
+
73+
+#if LLVM_MAJOR >= 11
74+
+ cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
75+
+ cc_params[cc_par_cnt++] = alloc_printf(
76+
+ "-fpass-plugin=%s/afl-demo-pass.so", obj_path);
77+
+#else
78+
+ cc_params[cc_par_cnt++] = "-Xclang";
79+
+ cc_params[cc_par_cnt++] = "-load";
80+
+ cc_params[cc_par_cnt++] = "-Xclang";
81+
+ cc_params[cc_par_cnt++] =
82+
+ alloc_printf("%s/afl-demo-pass.so", obj_path);
83+
+#endif
84+
+
85+
+ }
86+
+
87+
// cc_params[cc_par_cnt++] = "-Qunused-arguments";
88+
89+
if (lto_mode && argc > 1) {
90+
@@ -1100,6 +1118,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
91+
if (lto_mode)
92+
cc_params[cc_par_cnt++] =
93+
alloc_printf("%s/afl-llvm-rt-lto.o", obj_path);
94+
+ if (demo_mode)
95+
+ cc_params[cc_par_cnt++] =
96+
+ alloc_printf("%s/afl-demo-rt.o", obj_path);
97+
break;
98+
99+
case 32:
100+
@@ -2153,6 +2174,8 @@ int main(int argc, char **argv, char **envp) {
101+
if (!be_quiet && cmplog_mode)
102+
printf("CmpLog mode by <andreafioraldi@gmail.com>\n");
103+
104+
+ demo_mode = !!getenv("AFL_DEMO");
105+
+
106+
#if !defined(__ANDROID__) && !defined(ANDROID)
107+
ptr = find_object("afl-compiler-rt.o", argv[0]);
108+

Lab7/llvm-pass/afl-demo-pass.so.cc

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#define AFL_LLVM_PASS
2+
3+
#include "config.h"
4+
#include "debug.h"
5+
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
#include <unistd.h>
9+
#include <string.h>
10+
#include <sys/time.h>
11+
12+
#include <list>
13+
#include <memory>
14+
#include <string>
15+
#include <fstream>
16+
#include <set>
17+
#include <iostream>
18+
19+
#include "llvm/Config/llvm-config.h"
20+
#include "llvm/Pass.h"
21+
#include "llvm/Passes/PassPlugin.h"
22+
#include "llvm/Passes/PassBuilder.h"
23+
#include "llvm/IR/PassManager.h"
24+
#include "llvm/ADT/Statistic.h"
25+
#include "llvm/IR/IRBuilder.h"
26+
#include "llvm/IR/BasicBlock.h"
27+
#include "llvm/IR/Module.h"
28+
#include "llvm/IR/DebugInfo.h"
29+
#include "llvm/IR/CFG.h"
30+
#include "llvm/IR/Verifier.h"
31+
#include "llvm/Support/Debug.h"
32+
#include "llvm/Support/raw_ostream.h"
33+
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
34+
#include "llvm/Analysis/LoopInfo.h"
35+
#include "llvm/Analysis/MemorySSAUpdater.h"
36+
#include "llvm/Analysis/ValueTracking.h"
37+
#include "llvm/IR/Constants.h"
38+
39+
#include "llvm/Passes/OptimizationLevel.h"
40+
41+
#include "afl-llvm-common.h"
42+
43+
using namespace llvm;
44+
45+
namespace {
46+
47+
class AFLDEMOPass : public PassInfoMixin<AFLDEMOPass> {
48+
49+
public:
50+
AFLDEMOPass() {
51+
52+
}
53+
54+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
55+
llvm::StringRef GetCallInsFunctionName(CallInst *call);
56+
57+
protected:
58+
59+
};
60+
61+
} // namespace
62+
63+
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
64+
llvmGetPassPluginInfo() {
65+
66+
return {
67+
68+
LLVM_PLUGIN_API_VERSION, "AFLDEMOPass", "v0.1", [](PassBuilder &PB) {
69+
70+
PB.registerOptimizerLastEPCallback(
71+
[](ModulePassManager &MPM, OptimizationLevel OL) {
72+
73+
MPM.addPass(AFLDEMOPass());
74+
75+
});
76+
77+
}};
78+
79+
}
80+
81+
PreservedAnalyses AFLDEMOPass::run(Module &M, ModuleAnalysisManager &MAM) {
82+
83+
LLVMContext & C = M.getContext();
84+
Type * VoidTy = Type::getVoidTy(C);
85+
FunctionCallee demo_crash = M.getOrInsertFunction("__demo_crash", VoidTy);
86+
87+
for (auto &F : M) {
88+
89+
llvm::StringRef fn = F.getName();
90+
91+
if (fn.equals("_start") || fn.startswith("__libc_csu") ||
92+
fn.startswith("__afl_") || fn.startswith("__asan") ||
93+
fn.startswith("asan.") || fn.startswith("llvm."))
94+
continue;
95+
96+
for (auto &BB : F) {
97+
98+
for (auto &I : BB) {
99+
100+
if (CallInst *call = dyn_cast<CallInst>(&I)) {
101+
102+
if (GetCallInsFunctionName(call).equals("system")) {
103+
104+
IRBuilder<> IRB(&I);
105+
IRB.CreateCall(demo_crash)->setMetadata(M.getMDKindID("nosanitize"),
106+
MDNode::get(C, None));
107+
108+
}
109+
110+
}
111+
112+
}
113+
114+
}
115+
116+
}
117+
118+
return PreservedAnalyses::all();
119+
120+
}
121+
122+
llvm::StringRef AFLDEMOPass::GetCallInsFunctionName(CallInst *call) {
123+
124+
if (Function *func = call->getCalledFunction()) {
125+
126+
return func->getName();
127+
128+
} else {
129+
130+
// Indirect call
131+
return dyn_cast<Function>(call->getCalledOperand()->stripPointerCasts())
132+
->getName();
133+
134+
}
135+
136+
}
137+

Lab7/llvm-pass/afl-demo-rt.o.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#ifdef __ANDROID__
2+
#include "android-ashmem.h"
3+
#endif
4+
#include "config.h"
5+
#include "types.h"
6+
#include "cmplog.h"
7+
#include "llvm-alternative-coverage.h"
8+
9+
#include <stdio.h>
10+
#include <stdlib.h>
11+
#include <signal.h>
12+
#include <unistd.h>
13+
#include <string.h>
14+
#include <assert.h>
15+
#include <stdint.h>
16+
#include <stddef.h>
17+
#include <limits.h>
18+
#include <errno.h>
19+
20+
#include <sys/mman.h>
21+
#ifndef __HAIKU__
22+
#include <sys/syscall.h>
23+
#endif
24+
#ifndef USEMMAP
25+
#include <sys/shm.h>
26+
#endif
27+
#include <sys/wait.h>
28+
#include <sys/types.h>
29+
30+
#if !__GNUC__
31+
#include "llvm/Config/llvm-config.h"
32+
#endif
33+
34+
#ifdef __linux__
35+
#include "snapshot-inl.h"
36+
#endif
37+
38+
void __demo_crash() {
39+
40+
fprintf(stderr, "system found!\n");
41+
abort();
42+
43+
}

0 commit comments

Comments
 (0)