commit: c3e7239fd9a12f02c1fbccf760e863f1546cf9f3
parent daacd26949b5f587c45a9784580fd44f076e402d
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Sun, 24 Nov 2024 00:39:01 +0100
handle bog standard syscalls properly
Diffstat:
M | Makefile | 6 | +++--- |
M | ministrace.c | 46 | +++++++++++----------------------------------- |
A | print_syscall.c | 220 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 234 insertions(+), 38 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,8 +1,8 @@
# SPDX-FileCopyrightText: 2024 Haelwenn (lanodan) Monnier <contact+ministrace@hacktivis.me>
# SPDX-License-Identifier: MPL-2.0
-ministrace: ministrace.c strsyscall.c
- ${CC} -std=c99 ${CFLAGS} -o ministrace ministrace.c strsyscall.c ${LDFLAGS} ${LDSTATIC}
+ministrace: ministrace.c strsyscall.c print_syscall.c
+ ${CC} -std=c99 ${CFLAGS} -o ministrace ministrace.c strsyscall.c print_syscall.c ${LDFLAGS} ${LDSTATIC}
tmp_strsyscall.h:
${CC} -undef -E -P -fdirectives-only -o tmp_strsyscall.h - <<<'#include <sys/syscall.h>'
@@ -16,4 +16,4 @@ clean:
.PHONY: format
format:
- clang-format -style=file -assume-filename=.clang-format -i ministrace.c
+ clang-format -style=file -assume-filename=.clang-format -i ministrace.c print_syscall.c
diff --git a/ministrace.c b/ministrace.c
@@ -3,22 +3,22 @@
#define _DEFAULT_SOURCE
-#include "strsyscall.h"
-
-#include <assert.h>
#include <errno.h>
#include <inttypes.h> // PRIu64
-#include <linux/ptrace.h> // ptrace_syscall_info
+#include <linux/ptrace.h> // ptrace_syscall_info, __u64
#include <stdbool.h>
-#include <stdio.h> // fprintf
-#include <string.h> // strerror
-#include <sys/ptrace.h>
-#include <sys/syscall.h> // SYS_*
+#include <stdio.h> // fprintf
+#include <string.h> // strerror
+#include <sys/ptrace.h> // ptrace()
#include <sys/wait.h>
#include <unistd.h> // getpid, fork, execvp
+extern void print_syscall(__u64 nr, __u64 args[6]);
+
+pid_t child = -1;
+
static int
-wait_for_syscall(pid_t child, int *status)
+wait_for_syscall(int *status)
{
while(1)
{
@@ -31,30 +31,6 @@ wait_for_syscall(pid_t child, int *status)
}
}
-static void
-print_syscall(__u64 nr, __u64 args[6])
-{
- assert(nr < SYSCALLS_MAX);
- if(str_syscalls[nr] != NULL)
- {
- fprintf(stderr, "%s(", str_syscalls[nr]);
- }
- else
- {
- fprintf(stderr, "syscall(%" PRIu64 ", ", (uint64_t)nr);
- }
-
- fprintf(stderr,
- "0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64
- ")",
- (uint64_t)args[0],
- (uint64_t)args[1],
- (uint64_t)args[2],
- (uint64_t)args[3],
- (uint64_t)args[4],
- (uint64_t)args[5]);
-}
-
int
main(int argc, char *argv[])
{
@@ -67,7 +43,7 @@ main(int argc, char *argv[])
return 1;
}
- pid_t child = fork();
+ child = fork();
if(child < 0)
{
fprintf(stderr, "ministrace: error: Failed creating child process: %s\n", strerror(errno));
@@ -101,7 +77,7 @@ main(int argc, char *argv[])
ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESYSGOOD);
while(1)
{
- if(wait_for_syscall(child, &status) != 0) break;
+ if(wait_for_syscall(&status) != 0) break;
struct ptrace_syscall_info syscall_info;
long ret =
diff --git a/print_syscall.c b/print_syscall.c
@@ -0,0 +1,220 @@
+// SPDX-FileCopyrightText: 2024 Haelwenn (lanodan) Monnier <contact+ministrace@hacktivis.me>
+// SPDX-License-Identifier: MPL-2.0
+
+#define _DEFAULT_SOURCE
+
+#include "strsyscall.h"
+
+#include <assert.h>
+#include <inttypes.h> // PRIu64
+#include <limits.h> // PATH_MAX
+#include <linux/ptrace.h> // __u64
+#include <stdio.h> // fprintf
+#include <string.h> // memcpy
+#include <sys/ptrace.h> // ptrace()
+#include <sys/syscall.h> // SYS_*
+#include <unistd.h> // pid_t
+
+extern pid_t child;
+
+static char *
+read_str(intptr_t addr, size_t len)
+{
+ static char str_buf[sizeof(unsigned long) * 128] = "";
+ if(len == 0 || len > sizeof(unsigned long) * 128) len = sizeof(unsigned long) * 128;
+
+ size_t i = 0;
+ while(i < len)
+ {
+ unsigned long tmp = ptrace(PTRACE_PEEKDATA, child, addr + i);
+
+ memcpy(str_buf + i, &tmp, sizeof(tmp));
+ i += sizeof(tmp);
+
+ if(memchr(&tmp, 0, sizeof(tmp)) != NULL) break;
+
+ if(i > len)
+ {
+ str_buf[len - 1] = '\0';
+ break;
+ }
+ }
+
+ return str_buf;
+}
+
+void
+print_syscall(__u64 nr, __u64 args[6])
+{
+ // Handle bog-standard syscalls, limited to ones in POSIX but exhaustivity isn't warranted
+ // Ordered by number-of-arguments/complexity
+ switch(nr)
+ {
+ // path, buf, size
+ case SYS_readlinkat:
+ fprintf(stderr,
+ "%s(%" PRIi64 ",\"%s\", 0x%" PRIx64 ", %zd)",
+ str_syscalls[nr],
+ (int64_t)args[0],
+ read_str(args[0], PATH_MAX),
+ (int64_t)args[1],
+ (size_t)args[2]);
+ return;
+ // int, path, hex, hex
+ case SYS_openat:
+ case SYS_faccessat:
+ fprintf(stderr,
+ "openat(%" PRIi64 ", \"%s\", %" PRIx64 ", %" PRIx64 ")",
+ (int64_t)args[0],
+ read_str(args[1], PATH_MAX),
+ (int64_t)args[2],
+ (int64_t)args[3]);
+ return;
+ // path, hex, hex
+ case SYS_execve:
+ fprintf(stderr,
+ "execve(\"%s\", %" PRIx64 ", %" PRIx64 ")",
+ read_str(args[0], PATH_MAX),
+ (uint64_t)args[1],
+ (uint64_t)args[2]);
+ return;
+ // int, buf, size
+ case SYS_write:
+ case SYS_read:
+ // Need handling of non-printable characters to print buf
+ fprintf(stderr,
+ "%s(%" PRIi64 ", 0x%" PRIx64 ", %zd)",
+ str_syscalls[nr],
+ (int64_t)args[0],
+ (int64_t)args[1],
+ (size_t)args[2]);
+ return;
+ // int, path, path
+ case SYS_linkat:
+ case SYS_symlinkat:
+ fprintf(stderr,
+ "%s(%" PRIi64 ", \"%s\", \"%s\")",
+ str_syscalls[nr],
+ (int64_t)args[0],
+ read_str(args[1], PATH_MAX),
+ read_str(args[2], PATH_MAX));
+ return;
+ // path, buf, size
+ case SYS_readlink:
+ fprintf(stderr,
+ "%s(\"%s\", 0x%" PRIx64 ", %zd)",
+ str_syscalls[nr],
+ read_str(args[0], PATH_MAX),
+ (int64_t)args[1],
+ (size_t)args[2]);
+ return;
+ // path, int, int
+ case SYS_open:
+ case SYS_chown:
+ case SYS_lchown:
+ fprintf(stderr,
+ "%s(\"%s\", %" PRIi64 ", %" PRIi64 ")",
+ str_syscalls[nr],
+ read_str(args[0], PATH_MAX),
+ (int64_t)args[1],
+ (int64_t)args[2]);
+ return;
+ // path, path
+ case SYS_link:
+ case SYS_symlink:
+ fprintf(stderr,
+ "%s(\"%s\", \"%s\")",
+ str_syscalls[nr],
+ read_str(args[0], PATH_MAX),
+ read_str(args[1], PATH_MAX));
+ return;
+ // path, off_t
+ case SYS_truncate:
+ fprintf(stderr,
+ "%s(\"%s\", %" PRIu64 ")",
+ str_syscalls[nr],
+ read_str(args[0], PATH_MAX),
+ (off_t)args[1]);
+ return;
+ // path, size
+ case SYS_getcwd:
+ fprintf(
+ stderr, "%s(\"%s\", %zd)", str_syscalls[nr], read_str(args[0], PATH_MAX), (size_t)args[1]);
+ return;
+ // path, int
+ case SYS_access:
+ case SYS_stat:
+ case SYS_lstat:
+ fprintf(stderr,
+ "%s(\"%s\", 0x%" PRIx64 ")",
+ str_syscalls[nr],
+ read_str(args[0], PATH_MAX),
+ (int64_t)args[1]);
+ return;
+ // int, path
+ case SYS_unlinkat:
+ fprintf(stderr, "unlinkat(%" PRIu64 "\"%s\")", (int64_t)args[0], read_str(args[1], PATH_MAX));
+ return;
+ // int, off_t
+ case SYS_ftruncate:
+ fprintf(
+ stderr, "%s(%" PRIu64 ", %" PRIu64 ")", str_syscalls[nr], (int64_t)args[0], (off_t)args[1]);
+ return;
+ // int, int
+ case SYS_kill:
+ case SYS_dup2:
+ fprintf(
+ stderr, "%s(%" PRIi64 ", %" PRIi64 ")", str_syscalls[nr], (int64_t)args[0], (int64_t)args[1]);
+ return;
+ // path
+ case SYS_unlink:
+ case SYS_rmdir:
+ case SYS_chdir:
+ fprintf(stderr, "%s(\"%s\")", str_syscalls[nr], read_str(args[0], PATH_MAX));
+ return;
+ // hex
+ case SYS_brk:
+ fprintf(stderr, "%s(%" PRIx64 ")", str_syscalls[nr], (int64_t)args[0]);
+ return;
+ // int
+ case SYS_dup:
+ case SYS_close:
+ fprintf(stderr, "%s(%" PRIi64 ")", str_syscalls[nr], (int64_t)args[0]);
+ return;
+ // uint
+ case SYS_alarm:
+ fprintf(stderr, "%s(%" PRIu64 ")", str_syscalls[nr], (uint64_t)args[0]);
+ return;
+ // syscall0
+ case SYS_getpid:
+ case SYS_getppid:
+ case SYS_munlockall:
+ case SYS_setsid:
+ case SYS_sync:
+ case SYS_fork:
+ case SYS_pause:
+ fprintf(stderr, "%s()", str_syscalls[nr]);
+ return;
+ // fallback
+ default:
+ assert(nr < SYSCALLS_MAX);
+ if(str_syscalls[nr] != NULL)
+ {
+ fprintf(stderr, "%s(", str_syscalls[nr]);
+ }
+ else
+ {
+ fprintf(stderr, "syscall(%" PRIu64 ", ", (uint64_t)nr);
+ }
+
+ fprintf(stderr,
+ "0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64
+ ")",
+ (uint64_t)args[0],
+ (uint64_t)args[1],
+ (uint64_t)args[2],
+ (uint64_t)args[3],
+ (uint64_t)args[4],
+ (uint64_t)args[5]);
+ }
+}