Skip to content

Instantly share code, notes, and snippets.

@llandsmeer
Created February 16, 2020 23:26
Show Gist options
  • Save llandsmeer/77e5c20bfbfdd549d5d46120ffc11682 to your computer and use it in GitHub Desktop.
Save llandsmeer/77e5c20bfbfdd549d5d46120ffc11682 to your computer and use it in GitHub Desktop.
Execute instructions inside ptrace tracee... might be one of the ugliest hacks I made to date..
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <assert.h>
#include <errno.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <sys/user.h>
#define try_ptrace(req, pid, addr, data) err = ptrace((req), (pid), (addr), (data)); \
if (err == -1 && errno != 0) { \
perror("ptrace(" #req ", ..."); \
printf("line %d", __LINE__); \
exit(1); \
}
#define CONCAT(a, b) a ## b
#define TRACEE_BEGIN(lbl) execute(&&CONCAT(lbl_code_begin, lbl), &&CONCAT(lbl_code_end, lbl), -1); \
if (always_true) { \
goto CONCAT(lbl_code_end, lbl); \
} \
CONCAT(lbl_code_begin, lbl):
#define TRACEE_END(lbl) asm("int3"); \
CONCAT(lbl_code_end, lbl):
#define TRACEE_ASM(code) TRACEE_BEGIN(__LINE__) \
asm(code); \
TRACEE_END(__LINE__)
#define ALIGN_UP(addr, align) (((addr)+align-1) & ~(align-1))
#define ALIGN_DOWN(addr, align) ((addr) & ~(align-1))
pid_t pid;
struct user_regs_struct reset_regs;
struct user_regs_struct regs;
volatile int always_true = 1;
void execute(const char * begin, const char * end, int ninstr) {
assert((unsigned long)begin == ALIGN_DOWN((unsigned long)begin, sizeof(long)));
assert((end - begin) > 0);
long err;
long buffer[512];
const long * lbegin = (const long*)begin;
const long * lend = (const long*)ALIGN_UP((unsigned long)end, sizeof(long));
int nwords = lend - lbegin;
try_ptrace(PTRACE_GETREGS, pid, 0, &regs);
regs.rip = ALIGN_DOWN(regs.rip, sizeof(long));
const long * rip = (const long*)regs.rip;
for (int i = 0; i < nwords; i++) {
errno = 0;
try_ptrace(PTRACE_PEEKTEXT, pid, &rip[i], 0);
buffer[i] = err;
try_ptrace(PTRACE_POKETEXT, pid, &rip[i], lbegin[i]);
}
try_ptrace(PTRACE_SETREGS, pid, 0, &regs);
if (ninstr != -1) {
for (int i = 0; i < ninstr; i++) {
try_ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
waitpid(pid, 0, 0);
}
} else {
while (1) {
int status;
try_ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
waitpid(pid, &status, 0);
if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
try_ptrace(PTRACE_GETREGS, pid, 0, &regs);
errno = 0;
try_ptrace(PTRACE_PEEKTEXT, pid, regs.rip, 0);
if ((err & 0xff) == 0xcc) break;
} else if (WIFEXITED(status)) {
puts("child exit");
exit(1);
}
}
}
for (int i = 0; i < nwords; i++) {
try_ptrace(PTRACE_POKETEXT, pid, &rip[i], buffer[i]);
}
try_ptrace(PTRACE_GETREGS, pid, 0, &regs);
try_ptrace(PTRACE_SETREGS, pid, 0, &reset_regs);
}
int main(int argc, char ** argv) {
long err;
if (argc != 2) {
puts("argc != 2");
exit(1);
}
pid = atoi(argv[1]);
printf("pid tracee = %d\n", pid);
try_ptrace(PTRACE_SEIZE, pid, 0, 0);
try_ptrace(PTRACE_GETREGS, pid, 0, &reset_regs);
TRACEE_ASM(
"push 0x2048454c\n"
"mov rax, 1\n"
"mov rdi, 1\n"
"mov rsi, rsp\n"
"mov rdx, 4\n"
"syscall\n"
"pop rax\n"
)
try_ptrace(PTRACE_SETREGS, pid, 0, &reset_regs);
try_ptrace(PTRACE_CONT, pid, 0, SIGCONT);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment