diff options
| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | README.md | 11 | ||||
| -rw-r--r-- | collect.c | 34 | ||||
| -rw-r--r-- | synth.zig | 49 |
4 files changed, 80 insertions, 20 deletions
diff --git a/Makefile b/Makefile index a9994cf..3b1e5f5 100644 --- a/Makefile +++ b/Makefile @@ -25,12 +25,12 @@ measure-stack: measure-stack.o helpers.o scout: scout.o helpers.o $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ -synth: synth.py - link $< $@ - trace-call: trace-call.o helpers.o $(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ +%: %.zig + zig build-exe -O ReleaseSafe $< + %: %.c e9compile $< diff --git a/README.md b/README.md index 260cad8..b1d40e9 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,8 @@ Taosc is an automated makeshift patcher for binary programs. ## Installation -Taosc depends on [AFL++], [AFL Dyninst], [Dyninst], [E9Patch], [PatchELF] -[pacfix-python], and [GNU Parallel]. To build taosc, you need -`make(1p)`, a compiler for C and C++, [GNU M4], and `link(1p)`: +Taosc depends on GDB, [Dyninst] and [E9Patch] and POSIX utilities. +To build taosc, you need [GNU M4] and a compiler for C++23 and [Zig] 0.15: make -j$(nproc) @@ -25,11 +24,7 @@ under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -[AFL++]: https://aflplus.plus -[AFL Dyninst]: https://trong.loang.net/~cnx/afl-dyninst [Dyninst]: https://github.com/dyninst/dyninst [E9Patch]: https://github.com/gjduck/e9patch -[PatchELF]: https://github.com/NixOS/patchelf -[pacfix-python]: https://github.com/hsh814/pacfix-python -[GNU Parallel]: https://www.gnu.org/software/parallel [GNU M4]: https://www.gnu.org/software/m4 +[Zig]: https://ziglang.org diff --git a/collect.c b/collect.c index cf32283..a092555 100644 --- a/collect.c +++ b/collect.c @@ -20,39 +20,55 @@ #include "stdlib.c" -static uint64_t stack_size; +static uint32_t stack_size; static int output_file = -1; /* * Get an environment variable and parse as a number. * Return 0 on error. */ -uint64_t getenvull(const char *name) +uint32_t getenvul(const char *name) { - const char *const s = getenv(name); - if (s == NULL) + const char *const str = getenv(name); + if (str == NULL) return 0ULL; errno = 0; - const uint64_t u = strtoull(s, NULL, 0); + const uint32_t ul = strtoul(str, NULL, 0); if (errno) return 0ULL; - return u; + return ul; } void init(int argc, const char *const *argv, char **envp) { environ = envp; - stack_size = getenvull("TAOSC_STACK_SIZE"); + stack_size = getenvul("TAOSC_STACK_SIZE"); const char *const path = getenv("TAOSC_OUTPUT"); if (path != NULL) output_file = open(path, O_WRONLY | O_CREAT, 0644); - if (output_file == -1) - output_file = 2; /* stderr */ + if (output_file == -1) { + const char *msg = "cannot open $TAOSC_OUTPUT for writing\n"; + write(2, msg, strlen(msg)); + fsync(2); + exit(128); + } } void log(const struct STATE *state) { + + static mutex_t mutex = MUTEX_INITIALIZER; + while (mutex_lock(&mutex) < 0); write(output_file, (const char *)state, sizeof(struct STATE)); + /* + * struct STATE starts with a 16-bit member flags, + * followed by 64-bit registers, leaving 6 bytes in between. + */ + const int offset = (int) sizeof(uint32_t) - (int) sizeof(struct STATE); + lseek(output_file, offset, SEEK_END); + write(output_file, (const char *)&stack_size, sizeof(uint32_t)); + lseek(output_file, 0, SEEK_END); write(output_file, (const char *)state->rsp, stack_size); fsync(output_file); + mutex_unlock(&mutex); } diff --git a/synth.zig b/synth.zig new file mode 100644 index 0000000..2914b6c --- /dev/null +++ b/synth.zig @@ -0,0 +1,49 @@ +//! Patch's predicate synthesizer +// Copyright (C) 2025 Nguyễn Gia Phong +// +// This file is part of taosc. +// +// Taosc is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Taosc is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with taosc. If not, see <https://www.gnu.org/licenses/>. + +const assert = std.debug.assert; +const std = @import("std"); + +const State = extern struct { + flags: u16, + stack_size: u32, + r15: i64, + r14: i64, + r13: i64, + r12: i64, + r11: i64, + r10: i64, + r9: i64, + r8: i64, + rdi: i64, + rsi: i64, + rbp: i64, + rbx: i64, + rdx: i64, + rcx: i64, + rax: i64, + rsp: i64, + rip: i64, +}; + +pub fn main() !void { + var reader = std.fs.File.stdin().reader(&.{}); + var state: State = undefined; + assert(try reader.read(@ptrCast(&state)) == @sizeOf(State)); + std.debug.print("{}\n", .{ state }); +} |
