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 */