Skip to content

Instantly share code, notes, and snippets.

@ammarfaizi2
Last active November 22, 2022 12:08
Show Gist options
  • Save ammarfaizi2/673d08a0c1a0f45a352e927fe9607528 to your computer and use it in GitHub Desktop.
Save ammarfaizi2/673d08a0c1a0f45a352e927fe9607528 to your computer and use it in GitHub Desktop.
/*
* A syscall decoder to solve a challenge from Alviro.
*
* Link: https://t.me/GNUWeebTDD/7955
*/
#include <sys/syscall.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <stdio.h>
static void dump_code(char *dst, const void *src_, const void *rip, size_t len)
{
const unsigned char *src = src_;
while (len) {
const char *fmt;
if (src == rip)
fmt = "<%02x> ";
else
fmt = "%02x ";
dst += sprintf(dst, fmt, *src);
src++;
len--;
}
}
static void exec_child_ptrace(char * const path)
{
char * const argv[] = { path, NULL };
if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0) {
perror("ptrace");
exit(1);
}
execve(path, argv, NULL);
perror("execve");
}
static pid_t start_child_ptrace(char * const path)
{
pid_t ret;
ret = fork();
if (ret < 0) {
perror("fork");
return -1;
}
if (!ret) {
exec_child_ptrace(path);
exit(1);
}
return ret;
}
static size_t copy_from_process(pid_t pid, void *_hdst, const void *_psrc,
size_t len)
{
const char *psrc = _psrc;
char *hdst = _hdst;
long ret;
while (len) {
size_t copy_size;
errno = 0;
ret = ptrace(PTRACE_PEEKDATA, pid, (void *)psrc, NULL);
if (errno)
return len;
if (len < sizeof(ret))
copy_size = len;
else
copy_size = sizeof(ret);
memcpy(hdst, &ret, copy_size);
hdst += copy_size;
psrc += copy_size;
len -= copy_size;
}
return len;
}
#if 0
static size_t copy_to_process(pid_t pid, void *pdst_, const void *hsrc_,
size_t len)
{
const char *hsrc = hsrc_;
char *pdst = pdst_;
char *src;
long ret;
while (len) {
size_t copy_size;
if (len < sizeof(ret)) {
copy_size = len;
errno = 0;
ret = ptrace(PTRACE_PEEKDATA, pid, pdst, NULL);
if (errno)
return len;
src = (char *)&ret;
memcpy(src, hsrc, copy_size);
} else {
copy_size = sizeof(ret);
src = (char *)hsrc;
}
errno = 0;
ptrace(PTRACE_POKEDATA, pid, pdst, src);
if (errno)
return len;
hsrc += copy_size;
pdst += copy_size;
len -= copy_size;
}
return len;
}
#endif
static const char *get_syscall_name(unsigned long long nr_sys)
{
switch (nr_sys) {
case __NR_mmap:
return "mmap";
case __NR_write:
return "write";
case __NR_read:
return "read";
case __NR_memfd_create:
return "memfd_create";
default:
return NULL;
}
}
static void print_syscall_arg(struct user_regs_struct *regs)
{
unsigned long long nr_sys = regs->orig_rax;
const char *name;
fprintf(stderr, "[%#llx] ", regs->rip);
name = get_syscall_name(nr_sys);
if (name) {
fprintf(stderr, "%s(%#llx, %#llx, %#llx, %#llx, %#llx, %#llx)\n",
name,
regs->rdi,
regs->rsi,
regs->rdx,
regs->r10,
regs->r8,
regs->r9);
} else {
fprintf(stderr, "syscall%llu(%#llx, %#llx, %#llx, %#llx, %#llx, %#llx)\n",
nr_sys,
regs->rdi,
regs->rsi,
regs->rdx,
regs->r10,
regs->r8,
regs->r9);
}
}
static void dump_asm_code(pid_t pid, const void *addr)
{
char code[1024];
char dump[sizeof(code) * 4];
char cmd[sizeof(dump) + 128];
const char *decoder = "/home/ammarfaizi2/work/linux.work/scripts/decodecode";
size_t rem_len, len, i;
rem_len = copy_from_process(pid, code, (void *)addr, sizeof(code));
if (rem_len == sizeof(code)) {
perror("copy_from_process");
return;
}
len = sizeof(code) - rem_len;
for (i = 0; i < (len - 8); i++) {
if (!memcmp(&code[i], "\0\0\0\0\0\0\0\0", 8)) {
len = i;
break;
}
}
for (i = 2; i < (len - 2); i++) {
if (!memcmp(&code[i], "\x0f\x05", 2)) {
len = i + 2;
break;
}
}
dump_code(dump, code, code + 2, len);
snprintf(cmd, sizeof(cmd), "echo \"Code: %s\" | %s", dump, decoder);
system(cmd);
}
static void decode_syscall_and_asm(struct user_regs_struct *regs, pid_t pid)
{
struct user_regs_struct cregs;
if (copy_from_process(pid, &cregs, (void *)regs->r10, sizeof(cregs))) {
perror("copy_from_process");
return;
}
print_syscall_arg(&cregs);
dump_asm_code(pid, (const void *)(cregs.rip - 2ull));
}
static void inspect_checkpoint(struct user_regs_struct *regs, pid_t pid)
{
if (regs->rax != (__typeof__(regs->rax))-ENOSYS)
return;
if (regs->orig_rax != __NR_ptrace)
return;
if (regs->rdi != PTRACE_SETREGS)
return;
decode_syscall_and_asm(regs, pid);
}
static int do_trace(pid_t pid)
{
struct user_regs_struct regs;
int ret;
ret = waitpid(pid, NULL, 0);
if (ret < 0)
return -1;
ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
if (ret < 0)
return -1;
ret = waitpid(pid, NULL, 0);
if (ret < 0)
return -1;
ret = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
if (ret < 0)
return -1;
inspect_checkpoint(&regs, pid);
ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
if (ret < 0)
return -1;
return 0;
}
static void trace_child(pid_t pid)
{
while (1) {
if (do_trace(pid))
return;
}
}
int main(void)
{
pid_t pid;
pid = start_child_ptrace("/home/ammarfaizi2/Downloads/Telegram Desktop/chall_expert");
if (pid < 0)
return 1;
trace_child(pid);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment