-
-
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..
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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, ®s); | |
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, ®s); | |
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, ®s); | |
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, ®s); | |
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