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()
|