skeletton untested project
This commit is contained in:
commit
6fc620e8f4
187 changed files with 6584 additions and 0 deletions
110
srcs/main.c
Normal file
110
srcs/main.c
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* main.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: thrieg <thrieg@student.42mulhouse.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/12/11 04:07:30 by thrieg #+# #+# */
|
||||
/* Updated: 2025/12/11 04:59:32 by thrieg ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "../includes/ft_strace.h"
|
||||
|
||||
int main_loop(size_t binary_type)
|
||||
{
|
||||
int in_syscall = 0;
|
||||
while (1) {
|
||||
// Ask kernel to run until next syscall or signal
|
||||
if (ptrace(PTRACE_SYSCALL, pid, 0, 0) == -1) break;
|
||||
|
||||
int status;
|
||||
if (waitpid(pid, &status, 0) == -1) break;
|
||||
|
||||
if (WIFEXITED(status)) {
|
||||
// child exited normally
|
||||
printf("+++ exited with %d +++\n", WEXITSTATUS(status));
|
||||
break;
|
||||
}
|
||||
if (WIFSIGNALED(status)) {
|
||||
// killed by a signal
|
||||
printf("+++ killed by %s +++\n", strsignal(WTERMSIG(status)));
|
||||
break;
|
||||
}
|
||||
if (!WIFSTOPPED(status))
|
||||
continue;
|
||||
|
||||
int sig = WSTOPSIG(status);
|
||||
|
||||
if (sig == (SIGTRAP | 0x80)) {
|
||||
// syscall-enter or syscall-exit
|
||||
if (!in_syscall) {
|
||||
// ENTRY
|
||||
read_regs_and_print_entry(pid);
|
||||
in_syscall = 1;
|
||||
} else {
|
||||
// EXIT
|
||||
read_regs_and_print_exit(pid);
|
||||
in_syscall = 0;
|
||||
}
|
||||
} else {
|
||||
// A real signal: print it, then let it continue
|
||||
print_signal(pid, sig);
|
||||
// pass down the signal to the actual program
|
||||
if (ptrace(PTRACE_SYSCALL, pid, 0, sig) == -1) break;
|
||||
waitpid(pid, &status, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
dprintf(2, "usage: %s <path/to/program> <arg1> <arg2> ...\n", argv[0]);
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
//determine if this file is an executable, and if so, 64 or 32 bits
|
||||
ssize_t binary_bits = binary_type(argv[1]);
|
||||
if (binary_bits < 0)
|
||||
{
|
||||
if (binary_bits == -1)
|
||||
{
|
||||
dprintf(2, "couldn't read that file, make sure you have the read and execute permissions on %s\n", argv[1]);
|
||||
}
|
||||
else if (binary_bits == -2)
|
||||
{
|
||||
dprintf(2, "%s is not a supported binary\n", argv[1]);
|
||||
}
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
|
||||
if (pid == 0) {
|
||||
execvp(argv[1], argv + 1);
|
||||
perror("execvp");
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
else {
|
||||
// 1) Seize the child
|
||||
if (ptrace(PTRACE_SEIZE, pid, 0, 0) == -1) perror("PTRACE_SEIZE");
|
||||
|
||||
// 2) Interrupt it to force a stop
|
||||
if (ptrace(PTRACE_INTERRUPT, pid, 0, 0) == -1) perror("PTRACE_INTERRUPT");
|
||||
|
||||
// 3) Wait for it to stop
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
// 4) Set options
|
||||
long opts = PTRACE_O_TRACESYSGOOD;
|
||||
ptrace(PTRACE_SETOPTIONS, pid, 0, opts);
|
||||
|
||||
// 5) Enter main trace loop
|
||||
return (main_loop((size_t)binary_bits));
|
||||
}
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
121
srcs/utils.c
Normal file
121
srcs/utils.c
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* utils.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: thrieg <thrieg@student.42mulhouse.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/12/11 04:31:15 by thrieg #+# #+# */
|
||||
/* Updated: 2025/12/11 06:14:12 by thrieg ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "../includes/ft_strace.h"
|
||||
#include "../includes/syscalls_x86.h"
|
||||
#include "../includes/syscalls_x64.h"
|
||||
#include <elf.h> // for EI_NIDENT, EI_CLASS, ELFCLASS32, ELFCLASS64
|
||||
#include <fcntl.h> // for open
|
||||
#include <sys/uio.h>
|
||||
#include <sys/user.h> // for user_regs_struct
|
||||
|
||||
//returns 64 for x86_64, or 32 for 32 bits, -1 for open/read error, -2 for unrecognised file type
|
||||
ssize_t binary_type(char *path_to_binary)
|
||||
{
|
||||
int fd;
|
||||
unsigned char ident[EI_NIDENT];
|
||||
ssize_t ret;
|
||||
|
||||
fd = open(path_to_binary, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return (-1);
|
||||
ret = read(fd, ident, EI_NIDENT);
|
||||
close(fd);
|
||||
if (ret == -1)
|
||||
return (-1);
|
||||
if (ret != EI_NIDENT)
|
||||
return (-2);
|
||||
|
||||
/* Check this is an ELF file (binary) */
|
||||
if (ident[0] != 0x7f || ident[1] != 'E'
|
||||
|| ident[2] != 'L' || ident[3] != 'F')
|
||||
return (-2);
|
||||
|
||||
if (ident[EI_CLASS] == ELFCLASS64)
|
||||
return (64);
|
||||
if (ident[EI_CLASS] == ELFCLASS32)
|
||||
return (32);
|
||||
return (-2); //don't know wtf this file is at this point
|
||||
}
|
||||
|
||||
static void read_regs(pid_t pid, struct user_regs_struct *regs)
|
||||
{
|
||||
struct iovec io;
|
||||
io.iov_base = regs;
|
||||
io.iov_len = sizeof(*regs);
|
||||
|
||||
if (ptrace(PTRACE_GETREGSET, pid, (void*)NT_PRSTATUS, &io) == -1)
|
||||
{
|
||||
fprintf(stderr, "PTRACE_GETREGSET failed: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void read_regs_and_print_entry(pid_t pid, size_t binary_type)
|
||||
{
|
||||
struct user_regs_struct regs;
|
||||
read_regs(pid, ®s);
|
||||
if (binary_type == 64)
|
||||
{
|
||||
if (regs.orig_rax >= g_syscalls_64_len)
|
||||
{
|
||||
printf("unknown syscall(%ld, %lld, %lld, %lld, %lld, %lld, %lld)\n",
|
||||
(long long)regs.orig_rax,
|
||||
(long long)regs.rdi,
|
||||
(long long)regs.rsi,
|
||||
(long long)regs.rdx,
|
||||
(long long)regs.r10,
|
||||
(long long)regs.r8,
|
||||
(long long)regs.r9);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *syscall_name = g_syscalls_64[regs.orig_rax]->name;
|
||||
int argc = g_syscalls_64[regs.orig_rax]->argc;
|
||||
printf("%s(%ld, %lld, %lld, %lld, %lld, %lld, %lld)\n",
|
||||
syscall,
|
||||
(long long)regs.rdi,
|
||||
(long long)regs.rsi,
|
||||
(long long)regs.rdx,
|
||||
(long long)regs.r10,
|
||||
(long long)regs.r8,
|
||||
(long long)regs.r9);
|
||||
}
|
||||
}
|
||||
else if (binary_type == 32)
|
||||
{
|
||||
if (regs.orig_eax >= g_syscalls_86_len)
|
||||
{
|
||||
printf("unknown syscall(%ld, %lld, %lld, %lld, %lld, %lld, %lld)\n",
|
||||
(long)regs.orig_eax,
|
||||
(long)regs.ebx,
|
||||
(long)regs.ecx,
|
||||
(long)regs.edx,
|
||||
(long)regs.esi,
|
||||
(long)regs.edi,
|
||||
(long)regs.ebp);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *syscall_name = g_syscalls_86[regs.orig_eax]->name;
|
||||
int argc = g_syscalls_64[regs.orig_eax]->argc;
|
||||
printf("%s(%lld, %lld, %lld, %lld, %lld, %lld)\n",
|
||||
syscall_name,
|
||||
(long)regs.ebx,
|
||||
(long)regs.ecx,
|
||||
(long)regs.edx,
|
||||
(long)regs.esi,
|
||||
(long)regs.edi,
|
||||
(long)regs.ebp);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue