summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile27
-rw-r--r--collect.c23
-rw-r--r--fix.m434
-rw-r--r--synth.py (renamed from synth)50
4 files changed, 76 insertions, 58 deletions
diff --git a/Makefile b/Makefile
index 4ee0a88..92cefaf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,13 +1,15 @@
+.POSIX:
+.PHONY: all clean install uninstall
+
 CXXFLAGS += -g -std=c++23 -Wextra -Werror
-LDFLAGS += -lcommon -ldyninstAPI -linstructionAPI -lparseAPI # dyninst
-PREFIX ?= /usr/local
+LDLIBS += -lcommon -ldyninstAPI -linstructionAPI -lparseAPI # dyninst
 
-BIN := fix scout synth
-BIN_PREFIX := $(DESTDIR)$(PREFIX)/bin/taosc-
-DATA := collect patch
-DATA_DIR := $(DESTDIR)$(PREFIX)/share/taosc
+PREFIX ?= /usr/local
+BIN_PREFIX ::= $(DESTDIR)$(PREFIX)/bin/taosc-
+DATA_DIR ::= $(DESTDIR)$(PREFIX)/share/taosc
 
-.PHONY: all clean install
+BIN ::= fix scout synth
+DATA ::= collect patch
 
 all: $(BIN) $(DATA)
 
@@ -15,7 +17,10 @@ clean:
 	rm -f $(BIN) $(DATA)
 
 fix: fix.m4
-	m4 -D DATA_DIR=${DATA_DIR} $< > $@
+	m4 -D DATA_DIR=$(DATA_DIR) $< > $@
+
+synth: synth.py
+	link $< $@
 
 collect: collect.c
 	e9compile $<
@@ -23,10 +28,14 @@ collect: collect.c
 patch: patch.c
 	e9compile $<
 
-install: $(addprefix $(BIN_PREFIX),$(BIN)) $(addprefix $(DATA_DIR)/,$(DATA))
+install: $(BIN:%=$(BIN_PREFIX)%) $(DATA:%=$(DATA_DIR)/%)
 
 $(BIN_PREFIX)%: %
 	install -Dm 755 $< $@
 
 $(DATA_DIR)/%: %
 	install -Dm 644 $< $@
+
+uninstall:
+	rm -f $(BIN:%=$(BIN_PREFIX)%) $(DATA:%=$(DATA_DIR)/%)
+	rmdir $(DATA_DIR)
diff --git a/collect.c b/collect.c
index 875213a..2ae9c2e 100644
--- a/collect.c
+++ b/collect.c
@@ -21,13 +21,17 @@
 
 #include "stdlib.c"
 
-char *path;
+FILE *fout = NULL;
 
 void init(int argc, const char *const *argv, const char **envp)
 {
 	environ = envp;
-	path = getenv("TAOSC_COLLECT"); /* TODO: fopen */
-	setvbuf(stderr, NULL, _IOFBF, 0);
+	const char *const path = getenv("TAOSC_OUTPUT");
+	if (path != NULL)
+		fout = fopen(path, "w");
+	if (fout == NULL)
+		fout = stderr;
+	setvbuf(fout, NULL, _IOFBF, 0);
 }
 
 
@@ -36,12 +40,13 @@ void log(const struct STATE *state)
 	static mutex_t mutex = MUTEX_INITIALIZER;
 	if (mutex_lock(&mutex) < 0)
 		return;
-	clearerr(stderr);
-	fprintf(stderr, "[begin]\n");
+	clearerr(fout);
+	fprintf(fout, "[begin]\n");
 	const int64_t *const env = (const int64_t *) state;
-	for (unsigned char i = 1; i < sizeof(state) / sizeof(int64_t); ++i)
-		fprintf(stderr, "%hhu %lld\n", i, env[i]);
-	fprintf(stderr, "[end]\n");
-	fflush(stderr);
+	for (unsigned char i = 1; i < sizeof(*state) / sizeof(*env); ++i)
+		fprintf(fout, "%hhu %lld\n", i, env[i]);
+	fprintf(fout, "[end]\n");
+	fflush(fout);
+	fclose(fout); /* FIXME: reopen */
 	mutex_unlock(&mutex);
 }
diff --git a/fix.m4 b/fix.m4
index cbf3725..4647d00 100644
--- a/fix.m4
+++ b/fix.m4
@@ -1,6 +1,6 @@
 #!/bin/sh
 # Patcher
-# Copyright (C) 2024  Nguy?n Gia Phong
+# Copyright (C) 2024  Nguyễn Gia Phong
 #
 # This file is part of taosc.
 #
@@ -17,30 +17,32 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with taosc.  If not, see <https://www.gnu.org/licenses/>.
 
-set -e
+set -ex
 if test $# -ne 3
 then
-  echo Usage: taosc-fix binary instruction-address working-directory
+  echo Usage: taosc-fix binary address workdir
   exit 1
 fi
 binary="$(realpath $1)"
 address="$2"
 wd="$(realpath $3)"
+bin="$wd/$(basename $binary)"
 
+afl-dyninst -x "$binary" "$bin.fuzzee"
 pushd DATA_DIR > /dev/null
 trap 'popd > /dev/null' EXIT
-collect="$wd/$(basename $binary).collect"
-e9tool -M addr=$address -P 'log(state)@collect' -o "$collect.orig" "$binary"
-afl-dyninst -i "$collect.orig" -o "$collect"
-patched="$wd/$(basename $binary).patched"
-e9tool -M addr=$address -P 'if dest(state)@patch goto' -o "$patched" "$binary"
+e9tool -M addr=$address -P 'log(state)@collect'\
+  -o "$bin.collect" "$binary"
+e9tool -M addr=$address -P 'if dest(state)@patch goto'\
+  -o "$bin.patched" "$binary"
 
+# TODO: augment number of executions
+afl-dyninst-env afl-fuzz -i "$wd/fuzz/exploits" -o "$wd/fuzz/crashes"\
+  -CE 10000 -- "$bin.fuzzee" -d @@
+find "$wd/fuzz/crashes/default/crashes" -name id:* |
+  parallel TAOSC_OUTPUT="$wd/vars/neg/"'$(basename {})' "$bin.collect" -d {}
+time taosc-synth "$wd/vars" > "$wd/predicates"
 taosc-scout "$binary" "$address" > "$wd/destinations"
-#for dest in $(taosc-slice "$binary" "$address")
-#do
-#  for dest in $(taosc-slice "$binary" "$address")
-#  do
-#    TAOSC_PREDICATE="<v15p0" TAOSC_DESTINATION=$dest $patched\
-#      -d /home/cnx/Sauces/apr/vulnfix/data/binutils/cve_2017_14745/exploit
-#  done
-#done
+
+# TAOSC_PREDICATE=">=v15p0" TAOSC_DESTINATION=0x "$bin.patched" -d @@
+# vim: filetype=sh.m4
diff --git a/synth b/synth.py
index 4594d0a..c35fb84 100644
--- a/synth
+++ b/synth.py
@@ -17,39 +17,41 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with taosc.  If not, see <https://www.gnu.org/licenses/>.
 
-from contextlib import redirect_stderr
-from os import devnull
-from os.path import basename
+from argparse import ArgumentParser
+from cProfile import run
+from functools import partial
 from pathlib import Path
-from sys import argv, stdout
 
 from pacfix import learn
 from pacfix.invariant import INVARIANT_MAP, InvariantType
 from pacfix.utils import get_live_vars, get_valuations, parse_valuation
 
+write = partial(print, end='')
 
-def encode(inv, file):
+
+def write_invariant(inv):
     if inv.inv_type == InvariantType.VAR:
-        file.write(f"v{inv.data}")
+        write('v')
+        write(inv.data)
     elif inv.inv_type == InvariantType.CONST:
-        file.write(f"{'n' if inv.data < 0 else 'p'}{abs(inv.data)}")
+        write('n' if inv.data < 0 else 'p')
+        write(abs(inv.data))
     else:
-        file.write(INVARIANT_MAP[inv.inv_type])
-        encode(inv.left, file)
-        encode(inv.right, file)
-
-
-if len(argv) != 3:
-    print(f'usage: taosc-synth input-dir delta')
-    exit(1)
-input_dir = Path(argv[1])
-delta = float(argv[2])
-
-with open(input_dir / 'vars') as f: live_vars = get_live_vars(f)
-vals_neg, vals_pos = parse_valuation(get_valuations(input_dir / "neg"),
-                                     get_valuations(input_dir / "pos"))
-with open(devnull, 'w') as f, redirect_stderr(f):
-    result = learn(live_vars, vals_neg, vals_pos, delta)
+        write(INVARIANT_MAP[inv.inv_type])
+        write_invariant(inv.left)
+        write_invariant(inv.right)
+
+
+arg_parser = ArgumentParser(prog='taosc-synth')
+arg_parser.add_argument('input', help='input directory', type=Path)
+arg_parser.add_argument('delta', help='PAC delta', type=float,
+                        nargs='?', default=0.01)
+args = arg_parser.parse_args()
+
+with open(args.input / 'list') as f: live_vars = get_live_vars(f)
+vals_neg, vals_pos = parse_valuation(get_valuations(args.input / 'neg'),
+                                     get_valuations(args.input / 'pos'))
+result = learn(live_vars, vals_neg, vals_pos, args.delta)
 for i in result.inv_mgr.invs:
-    encode(i, stdout)
+    write_invariant(i)
     print()