Skip to content

Instantly share code, notes, and snippets.

@kxxt
Created October 23, 2023 07:28
Show Gist options
  • Select an option

  • Save kxxt/ee2a86351933c140a7b81cc31de7dfc5 to your computer and use it in GitHub Desktop.

Select an option

Save kxxt/ee2a86351933c140a7b81cc31de7dfc5 to your computer and use it in GitHub Desktop.
execveat quirk reproduction
#include <stdio.h>
#include <linux/fcntl.h> /* Definition of AT_* constants */
#include <unistd.h>
int main()
{
char *argv[] = {"true", "-l", NULL};
char *envp[] = {"PATH=/bin", NULL};
int dirfd = open("/bin", O_RDONLY | O_DIRECTORY);
if (!dirfd)
return 1;
if (!execveat(dirfd, "true", argv, envp, 0))
return 2;
return 0;
}
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/user.h>
#include <sys/syscall.h>
#include <linux/ptrace.h>
void die(const char *msg)
{
perror(msg);
_exit(1);
}
int main()
{
// Setup tracing
pid_t child = fork();
if (0 == child)
{
// Child
ptrace(PTRACE_TRACEME, 0, 0, 0);
if (execl("./execveat", "./execveat", NULL))
die("execl failure");
}
else
{
// Parent
int status;
if (-1 == waitpid(child, &status, 0))
die("waitpid failure");
if (!WIFSTOPPED(status))
die("child not stopped");
if (-1 == ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESYSGOOD))
die("ptrace failure");
if (-1 == ptrace(PTRACE_SYSCALL, child, 0, 0))
die("ptrace failure");
int last_syscall = -1;
while (1)
{
if (-1 == waitpid(child, &status, 0))
{
die("waitpid failure");
}
if (WIFEXITED(status))
{
printf("Child exited\n");
break;
}
if (WIFSIGNALED(status))
{
printf("Child killed\n");
break;
}
if (WIFSTOPPED(status) && (SIGTRAP | 0x80 == WSTOPSIG(status)))
{
struct ptrace_syscall_info info;
if (-1 == ptrace(PTRACE_GET_SYSCALL_INFO, child, sizeof info, &info))
die("ptrace syscall info failure");
struct user_regs_struct regs;
if (-1 == ptrace(PTRACE_GETREGS, child, 0, &regs))
die("ptrace getregs failure");
// int last_syscall = regs.orig_rax;
if (info.op == PTRACE_SYSCALL_INFO_ENTRY)
{
last_syscall = info.entry.nr;
int syscall_from_regs = regs.orig_rax;
printf("Pre syscall %lld\n", last_syscall);
if (last_syscall == SYS_execve || last_syscall == SYS_execveat)
{
printf("Syscall number: %lld\n orig_rax: %lld, rdi: 0x%x, rsi: 0x%x rdx: 0x%x\n", last_syscall, regs.orig_rax, regs.rdi, regs.rsi, regs.rdx);
}
}
else if (info.op == PTRACE_SYSCALL_INFO_EXIT)
{
printf("Post syscall %lld\n", last_syscall);
}
else if (info.op == PTRACE_SYSCALL_INFO_NONE)
{
// WTF is this?
printf("WTF is this!!! last_syscall: %lld\n orig_rax: %lld, rdi: 0x%x, rsi: 0x%x rdx: 0x%x\n", last_syscall, regs.orig_rax, regs.rdi, regs.rsi, regs.rdx);
}
else
{
printf("Unexpected syscall info op: %d\n", info.op);
}
// presyscall = !presyscall;
}
if (-1 == ptrace(PTRACE_SYSCALL, child, 0, 0))
die("ptrace syscall failure");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment