From f01a81ffe8c12a3009b4ba81dd08921c97f1a1f5 Mon Sep 17 00:00:00 2001 From: Adhityaa C Date: Fri, 16 Dec 2016 13:14:50 +0530 Subject: [PATCH] Release v0.0.0.1 Can't stress enough that this isn't ready for production. --- Makefile | 16 ++++ arguments.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++++ arguments.h | 47 ++++++++++++ fssb.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++ proxyfile.c | 86 +++++++++++++++++++++ proxyfile.h | 45 +++++++++++ syscalls.h | 6 ++ utils.c | 215 ++++++++++++++++++++++++++++++++++++++++++++++++++++ utils.h | 63 +++++++++++++++ 9 files changed, 891 insertions(+) create mode 100644 Makefile create mode 100644 arguments.c create mode 100644 arguments.h create mode 100644 fssb.c create mode 100644 proxyfile.c create mode 100644 proxyfile.h create mode 100644 syscalls.h create mode 100644 utils.c create mode 100644 utils.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4a7ec61 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +components = fssb.o \ + arguments.o \ + utils.o \ + proxyfile.o + +all: $(components) + cc -o fssb $(components) -lcrypto + +fssb.o: fssb.c +arguments.o: arguments.c +utils.o: utils.c +proxyfile.o: proxyfile.c + +clean: + rm -rf *.o + rm -rf fssb diff --git a/arguments.c b/arguments.c new file mode 100644 index 0000000..ba7047b --- /dev/null +++ b/arguments.c @@ -0,0 +1,214 @@ +/** + * arguments.h - Argument handling. Part of the FSSB project. + * + * Copyright (C) 2016 Adhityaa Chandrasekar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include "arguments.h" + +#define INIT_HELP_ALLOC 8 + +/** + * insert_help - inserts a line of help into the list + * @arg: the argument + * @desc: help text that's supposed to accompany the argument + */ +void insert_help(char *arg, char *desc, int num_vals) { + if(help_list_count >= help_list_allocated) { + help_list_allocated *= 2; + help_list = (help *)realloc(help_list, help_list_allocated); + } + strcpy(help_list[help_list_count].arg, arg); + strcpy(help_list[help_list_count].desc, desc); + help_list[help_list_count].num_vals = num_vals; + help_list_count++; +} + +/** + * build_help - builds the list of arguments and descriptions. + */ +void build_help() { + help_list_count = 0; + + help_list = (help *)malloc(sizeof(help)*INIT_HELP_ALLOC); + help_list_allocated = INIT_HELP_ALLOC; + + insert_help("-h", "show this help and exit", 0); + insert_help("-r", "remove all temporary files at the end", 0); + insert_help("-o", "logging output file", 1); + insert_help("-m", "print file to proxyfile map at the end", 0); +} + +/** + * check_args_validity - ensure all args are recognized + * @argc: number of args given to the tracer + * @argv: argument list + * + * Exits with 1 if there is/are unrecognized argument(s). + */ +void check_args_validity(int argc, char **argv) +{ + int i, j; + + for(i = 1; i < argc; i++) { + /* it's the child's arguments from here on */ + if(strcmp(argv[i], "--") == 0) + break; + + int recognized = 0; + for(j = 0; j < help_list_count; j++) { + if(strcmp(argv[i], help_list[j].arg) == 0) { + recognized = 1; + i += help_list[j].num_vals; + } + } + if(!recognized) { + fprintf(stderr, "fssb: error: invalid option '%s'\n\n", argv[i]); + print_help(); + exit(1); + } + } +} + +/** + * help_requested - determine if the help text is requested by the user + * @argc: number of args given to the tracer + * @argv: argument list + * + * Returns 1 if help is requested, 0 otherwise. + */ +int help_requested(int argc, char **argv) +{ + int i, other_args = 0, show_help = 0; + + for(i = 1; i < argc; i++) { + if(strcmp(argv[i], "-h") == 0) + show_help = 1; + else + other_args = 1; + } + + if(!show_help) + return 0; + + if(other_args) + fprintf(stderr, "`-h` must be the only argument if it is used.\n\n"); + + return 1; +} + +/** + * print_help - print the help manual + */ +void print_help() { + fprintf(stdout, "Usage: fssb [OPTIONS] -- COMMAND\n"); + fprintf(stdout, "\n\ +FSSB is a filesystem sandbox for Linux. It's useful if you want to run a\n\ +program but also protect your files and directories from modification.\n\n"); + + int i; + for(i = 0; i < help_list_count; i++) { + fprintf(stdout, " %s", help_list[i].arg); + for(int j = 0; j < help_list[i].num_vals; j++) + fprintf(stdout, " ARG"); + for(int j = 0; j < 15 - 4*help_list[i].num_vals; j++) + fprintf(stdout, " "); + fprintf(stdout, "%s\n", help_list[i].desc); + } + + fprintf(stdout, "\n\ +You can find a more complete at https://github.com/adtac/fssb\n"); +} + +/** + * set_parameters - reads the command line arguments and sets the values + * @argc: number of args given to the tracer + * @argv: argument list + * @cleanup: whether to cleanup all temp files at exit + * @log_file: file to log all output to + */ +void set_parameters(int argc, + char **argv, + int *cleanup, + FILE **log_file, + int *print_map) +{ + /* default values */ + *cleanup = 0; + *log_file = stdout; + *print_map = 0; + + int i; + for(i = 0; i < argc; i++) { + if(strcmp(argv[i], "-r") == 0) + *cleanup = 1; + + if(strcmp(argv[i], "-m") == 0) + *print_map = 1; + + if(strcmp(argv[i], "-o") == 0) { + struct stat sb; + if(i == argc - 1) { + fprintf(stderr, "fssb: error: no logging file specified\n"); + exit(1); + } + *log_file = fopen(argv[i + 1], "w"); + if(*log_file == NULL) { + fprintf(stderr, "fssb: error: cannot create log file %s\n", + argv[i + 1]); + exit(1); + } + i++; + } + } +} + +/** + * get_child_args_start_pos - get the position where the child args start + * @argc: number of args given to the tracer + * @argv: argument list + * + * Returns the point in the array where the child arguments begin. + */ +int get_child_args_start_pos(int argc, char **argv) +{ + int pos = 0; + + while(pos < argc) { + if(strcmp(argv[pos], "--") == 0) + break; + pos++; + } + + if(pos == argc) { + fprintf(stderr, "fssb: error: no `--` found in arguments\n"); + fprintf(stderr, "usage: fssb -- \n"); + exit(1); + } + + if(pos == argc - 1) { + fprintf(stderr, "fssb: error: nothing found after `--`\n"); + fprintf(stderr, "usage: fssb -- \n"); + exit(1); + } + + return pos + 1; +} diff --git a/arguments.h b/arguments.h new file mode 100644 index 0000000..bf7e827 --- /dev/null +++ b/arguments.h @@ -0,0 +1,47 @@ +/** + * arguments.h - Argument handling. Part of the FSSB project. + * + * Copyright (C) 2016 Adhityaa Chandrasekar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _ARGUMENT_H +#define _ARGUMENT_H + +typedef struct { + char arg[3], desc[128]; + int num_vals; +} help; + +extern void build_help(); + +extern void check_args_validity(int argc, char **argv); + +extern int help_requested(int argc, char **argv); + +extern void print_help(); + +extern void set_parameters(int argc, + char **argv, + int *cleanup, + FILE **log_file, + int *print_map); + +extern int get_child_args_start_pos(int argc, char **argv); + +help *help_list; +int help_list_count, help_list_allocated; + +#endif /* _ARGUMENT_H */ diff --git a/fssb.c b/fssb.c new file mode 100644 index 0000000..71f9c7e --- /dev/null +++ b/fssb.c @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "syscalls.h" +#include "proxyfile.h" +#include "arguments.h" +#include "utils.h" + +/* Hopefully we don't need a 90-digit number. */ +char SANDBOX_DIR[100]; +int PROXY_FILE_LEN; + +proxyfile_list *list; + +FILE *log_file; + +int cleanup, print_list; + +int finish_and_return(int child, int syscall, int *retval) { + if(syscall == -1) { + char buf[2]; + fgets(buf, sizeof(buf), stdin); + } + + if(syscall_breakpoint(child) != 0) + return 0; + + *retval = get_reg(child, eax); + return 1; +} + +int handle_syscalls(pid_t child) { + if(syscall_breakpoint(child) != 0) + return 0; + + int syscall; + syscall = get_reg(child, orig_eax); + + if(syscall == SC_EXIT || syscall == SC_EXIT_GROUP) { + int exit_code = get_syscall_arg(child, 0); + fprintf(stderr, "fssb: child exited with %d\n", exit_code); + fprintf(stderr, "fssb: sandbox directory: %s\n", SANDBOX_DIR); + } + + if(syscall == SC_OPEN) { + /* get open(...) args */ + long word = get_syscall_arg(child, 0); + char *file = get_string(child, word); + int flags = get_syscall_arg(child, 1); + + /* log message */ + fprintf(log_file, "open(\"%s\", %d)\n", file, flags); + + /* name switch */ + char *new_name; + char *original_bytes; + int overwritten_size; + int switch_name = 0; + proxyfile *cur = NULL; + + if(flags & O_APPEND || flags & O_CREAT || flags & O_WRONLY) { + fprintf(log_file, "opening with write access\n"); + + /* if the file already exists, use it */ + cur = search_proxyfile(list, file); + if(cur == NULL) + cur = new_proxyfile(list, file); + + new_name = cur->proxy_path; + switch_name = 1; + } + if(flags == O_RDONLY) { + fprintf(log_file, "opening with read access\n"); + + proxyfile *cur = search_proxyfile(list, file); + if(cur != NULL) { + new_name = cur->proxy_path; + switch_name = 1; + } + } + + if(switch_name) { + original_bytes = write_string(child, + word, + new_name, + &overwritten_size); + } + + int retval; + if(finish_and_return(child, syscall, &retval) == 0) + return 0; + + if(switch_name) { + /* restore the memory */ + write_bytes(child, word, original_bytes, overwritten_size); + } + + /* + if(retval > fdlist_size) { + fdlist_size *= 2; + fdlist = realloc(fdlist, sizeof(struct proxy_file)*fdlist_size); + continue; + } + */ + + if(cur == NULL || cur->file_path != file) + free(file); + } + + return 1; +} + +void trace(pid_t child) { + int status; + waitpid(child, &status, 0); + + assert(WIFSTOPPED(status)); + ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESYSGOOD); + + while(handle_syscalls(child)); +} + +int process_child(int argc, char **argv) { + int i; + char *args[argc+1]; + for(i=0; i < argc; i++) + args[i] = argv[i]; + args[argc] = NULL; /* execvp needs NULL terminated list */ + + ptrace(PTRACE_TRACEME); + kill(getpid(), SIGSTOP); + return execvp(args[0], args); +} + +void init() { + struct stat sb; + + int i; + for(i = 1; ; i++) { + sprintf(SANDBOX_DIR, "/tmp/fssb.%d/", i); + if(stat(SANDBOX_DIR, &sb)) + break; + } + mkdir(SANDBOX_DIR, 0775); + + PROXY_FILE_LEN = strlen(SANDBOX_DIR) + 32; + + fprintf(stderr, "fssb: sandbox directory: %s\n", SANDBOX_DIR); + + list = new_proxyfile_list(); + list->SANDBOX_DIR = SANDBOX_DIR; + list->PROXY_FILE_LEN = PROXY_FILE_LEN; +} + +int main(int argc, char **argv) { + build_help(); + check_args_validity(argc, argv); + if(help_requested(argc, argv)) { + print_help(); + return 0; + } + + /* everything else must run a program */ + int pos = get_child_args_start_pos(argc, argv); + int child_argc = argc - pos; + char **child_argv = argv + pos; + + set_parameters(pos - 1, argv, &cleanup, &log_file, &print_list); + + init(); + + pid_t child = fork(); + if(child > 0) + trace(child); + else if(child == 0) + process_child(child_argc, child_argv); + else { + fprintf(stderr, "fssb: error: cannot fork\n"); + return 1; + } + + if(cleanup) + rmdir(SANDBOX_DIR); + else if(print_map) + print_map(list, log_file); + + return 0; +} diff --git a/proxyfile.c b/proxyfile.c new file mode 100644 index 0000000..5413b1d --- /dev/null +++ b/proxyfile.c @@ -0,0 +1,86 @@ +/** + * proxyfile.h - Proxy file operations. Part of the FSSB project. + * + * Copyright (C) 2016 Adhityaa Chandrasekar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "proxyfile.h" +#include "utils.h" + +#define PROXYFILE_LIST_ALLOC 128 + +proxyfile_list *new_proxyfile_list() +{ + proxyfile_list *retval = (proxyfile_list *)malloc(sizeof(proxyfile_list)); + retval->list = (proxyfile *)malloc(PROXYFILE_LIST_ALLOC*sizeof(proxyfile)); + retval->alloc = PROXYFILE_LIST_ALLOC; + retval->used = 0; + + return retval; +} + +proxyfile *new_proxyfile(proxyfile_list *list, char *file_path) +{ + if(list->used + 1 > list->alloc) { + list->alloc *= 2; + list->list = (proxyfile *)realloc(list->list, + list->alloc*sizeof(proxyfile)); + } + + proxyfile *cur = list->list + list->used; + + cur->file_path = file_path; /* no need to copy char-by-char */ + + cur->md5 = md5sum(file_path); /* just assign the already assigned addr */ + + cur->proxy_path = (char *)malloc((list->PROXY_FILE_LEN + 1)*sizeof(char)); + strcpy(cur->proxy_path, list->SANDBOX_DIR); + strcat(cur->proxy_path, cur->md5); + + list->used++; + + return cur; +} + +proxyfile *search_proxyfile(proxyfile_list *list, char *file_path) { + char *md5 = md5sum(file_path); + + int i; + for(i = 0; i < list->used; i++) { + if(strcmp((list->list + i)->md5, md5) == 0) + return list->list + i; + } + + return NULL; +} + +void print_map(proxyfile_list *list, FILE *log_file) { + fprintf(log_file, "\n"); + fprintf(log_file, "==============\n"); + fprintf(log_file, " File mapping \n"); + fprintf(log_file, "==============\n"); + fprintf(log_file, "\n"); + + int i; + for(i = 0; i < list->used; i++) { + proxyfile *cur = list->list + i; + fprintf(log_file, "%s = %s\n", cur->md5, cur->file_path); + } +} diff --git a/proxyfile.h b/proxyfile.h new file mode 100644 index 0000000..afa1e67 --- /dev/null +++ b/proxyfile.h @@ -0,0 +1,45 @@ +/** + * proxyfile.h - Proxy file operations. Part of the FSSB project. + * + * Copyright (C) 2016 Adhityaa Chandrasekar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _PROXYFILE_H +#define _PROXYFILE_H + +#include + +typedef struct { + char *file_path, *md5, *proxy_path; + int fd; +} proxyfile; + +typedef struct { + proxyfile *list; + int alloc, used; + int PROXY_FILE_LEN; + char *SANDBOX_DIR; +} proxyfile_list; + +extern proxyfile_list *new_proxyfile_list(); + +extern proxyfile *new_proxyfile(proxyfile_list *list, char *file_path); + +extern proxyfile *search_proxyfile(proxyfile_list *list, char *file_path); + +extern void print_map(proxyfile_list *list, FILE *log_file); + +#endif /* _PROXYFILE_H */ diff --git a/syscalls.h b/syscalls.h new file mode 100644 index 0000000..296e920 --- /dev/null +++ b/syscalls.h @@ -0,0 +1,6 @@ +#define SC_READ 0 +#define SC_WRITE 1 +#define SC_OPEN 2 +#define SC_CLOSE 3 +#define SC_EXIT 60 +#define SC_EXIT_GROUP 231 diff --git a/utils.c b/utils.c new file mode 100644 index 0000000..6e6950a --- /dev/null +++ b/utils.c @@ -0,0 +1,215 @@ +/** + * utils.c - Utility functions. Part of the FSSB project. + * + * Copyright (C) 2016 Adhityaa Chandrasekar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +/** + * syscall_breakpoint - break at the entry or exit of a syscall + * @child: PID of the child process + * + * This will stop the process until called again. + * + * Return 0 if the child has been stopped, 1 if it has exited. + */ +int syscall_breakpoint(pid_t child) +{ + int status; + + while(1) { + ptrace(PTRACE_SYSCALL, child, 0, 0); + waitpid(child, &status, 0); + + if (WIFSTOPPED(status) && WSTOPSIG(status) & 0x80) + return 0; + if (WIFEXITED(status)) + return 1; + } +} + +/** + * get_syscall_arg - get the nth argument of the syscall. + * @child: PID of the child process + * @n: which argument (max 6 args for any syscall) + * + * Returns the long corresponding the argument. If this is a string, a pointer + * to it is returned. If n is greater than 6, -1L is returned. + */ +long get_syscall_arg(pid_t child, int n) +{ + switch(n) { +#ifdef __amd64__ + /* x86_64 has {rdi, rsi, rdx, r10, r8, r9} */ + case 0: return get_reg(child, rdi); + case 1: return get_reg(child, rsi); + case 2: return get_reg(child, rdx); + case 3: return get_reg(child, r10); + case 4: return get_reg(child, r8); + case 5: return get_reg(child, r9); +#else + /* x86 has {ebx, ecx, edx, esi, edi, ebp} */ + case 0: return get_reg(child, ebx); + case 1: return get_reg(child, ecx); + case 2: return get_reg(child, edx); + case 3: return get_reg(child, esi); + case 4: return get_reg(child, edi); + case 5: return get_reg(child, ebp); +#endif + default: return -1L; + } +} + +/** + * get_string - returns the string at the given address of the child process + * @child: PID of the child process + * @addr: memory address location + * + * Note: the string has to be null-terminated. + * + * Returns a (char *) pointer. + */ +char *get_string(pid_t child, unsigned long addr) +{ + char *str = (char *)malloc(1024); + int alloc = 1024, copied = 0; + unsigned long word; + + while(1) { + if(copied + sizeof(word) > alloc) { /* too big (that's what she said) */ + alloc *= 2; + str = (char *)realloc(str, alloc); + } + + word = ptrace(PTRACE_PEEKDATA, child, addr + copied); + if(errno) { + str[copied] = 0; + break; + } + memcpy(str + copied, &word, sizeof(word)); + + /* If we've already encountered null, break and return */ + if(memchr(&word, 0, sizeof(word)) != NULL) + break; + + copied += sizeof(word); + } + + return str; +} + +/** + * write_string - writes a string to the given address of the child process + * @child: PID of the child process + * @addr: memory address location + * @str: string to be written + * @overwritten_size: stores the number of bytes overwritten + * + * Returns a pointer to a memory address of bytes that needs to be restored. + */ +unsigned char *write_string(pid_t child, + unsigned long addr, + char *str, + int *overwritten_size) +{ + unsigned char *original_bytes = malloc(1024); + int alloc = 1024; + *overwritten_size = 0; + + while(1) { + unsigned long word; + + word = ptrace(PTRACE_PEEKDATA, child, addr + *overwritten_size); + if(*overwritten_size + sizeof(word) > alloc) { + alloc *= 2; + original_bytes = (unsigned char *)realloc(original_bytes, alloc); + } + memcpy(original_bytes + *overwritten_size, &word, sizeof(word)); + + memcpy(&word, str + *overwritten_size, sizeof(word)); + ptrace(PTRACE_POKEDATA, child, addr + *overwritten_size, word); + + *overwritten_size += sizeof(word); + + if(memchr(&word, 0, sizeof(word)) != NULL) + break; + } + + return original_bytes; +} + +/** + * write_bytes - write n bytes to the given memory address + * @child: PID of the child process + * @addr: memory address location + * @bytes: bytes to be written + * @n: stores the number of bytes overwritten + */ +void write_bytes(pid_t child, + unsigned long addr, + unsigned char *bytes, + int n) { + int cur; + for(cur = 0; cur < n; ) { + unsigned long word; + memcpy(&word, bytes + cur, sizeof(word)); + ptrace(PTRACE_POKETEXT, child, addr + cur, word); + cur += sizeof(word); + } +} + +/** + * md5sum - return a MD5 hash of the given string + * @str: the string + * + * Returns a 32-character string containing the MD5 hash. Remember to free + * this after use. + */ +char *md5sum(char *str) +{ + char *retval = (char *)malloc(33); + + unsigned char d[17]; + MD5(str, strlen(str), d); + + for(int i = 0; i < 16; i++) { + unsigned char x = d[i] >> 4; + if(x < 10) + retval[2*i] = '0' + x; + else + retval[2*i] = 'a' + x - 10; + + x = d[i] & 0xf; + if(x < 10) + retval[2*i+1] = '0' + x; + else + retval[2*i+1] = 'a' + x - 10; + } + + retval[32] = 0; + + return retval; +} diff --git a/utils.h b/utils.h new file mode 100644 index 0000000..7ad079f --- /dev/null +++ b/utils.h @@ -0,0 +1,63 @@ +/** + * utils.c - Defines for various utlities. Part of the FSSB project. + * + * Copyright (C) 2016 Adhityaa Chandrasekar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _UTILS_H +#define _UTILS_H + +#include +#include +#include + +/* A hack for x86_64 systems. */ +#ifdef __amd64__ +#define eax rax +#define orig_eax orig_rax +#endif + +/* Get the offset of `field` in struct `str`. */ +#ifndef offsetof +#define offsetof(str, field) __builtin_offsetof(str, field) +#endif + +/* Return the register `reg` of `child`. */ +#ifndef get_reg +#define get_reg(child, reg) ptrace(PTRACE_PEEKUSER, \ + child, \ + offsetof(struct user, regs.reg)) +#endif + +extern int syscall_breakpoint(pid_t child); + +extern long get_syscall_arg(pid_t child, int n); + +extern char *get_string(pid_t child, unsigned long addr); + +extern unsigned char *write_string(pid_t child, + unsigned long addr, + char *str, + int *overwritten_bytes); + +extern void write_bytes(pid_t child, + unsigned long addr, + unsigned char *bytes, + int n); + +extern char *md5sum(char *str); + +#endif /* _UTILS_H */