int inject_code(const struct process_hook *ph) { char sbuf1[1024], sbuf2[1024]; struct my_user_regs regs, saved_regs, aregs; int status; size_t v = 0; assert(ph); printf("[+] 64bit mode\n"); if (ptrace(PTRACE_ATTACH, ph->pid, NULL, NULL) < 0) die("[-] ptrace"); waitpid(ph->pid, &status, 0); if (ptrace(PTRACE_GETREGS, ph->pid, NULL, ®s) < 0) die("[-] ptrace"); peek_text(ph->pid, regs.rsp + 1024, sbuf1, sizeof(sbuf1)); peek_text(ph->pid, regs.rsp, sbuf2, sizeof(sbuf2)); /* fake saved return address, triggering a SIGSEGV to catch */ v = 0; poke_text(ph->pid, regs.rsp, (char *)&v, sizeof(v)); poke_text(ph->pid, regs.rsp + 1024, ph->dso, strlen(ph->dso) + 1); memcpy(&saved_regs, ®s, sizeof(regs)); printf("[+] rdi=0x%zx rsp=0x%zx rip=0x%zx\n", regs.rdi, regs.rsp, regs.rip); /* arguments to function we call */ regs.rdi = regs.rsp + 1024; regs.rsi = RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE; regs.rip = (size_t)ph->dlopen_address; if (ptrace(PTRACE_SETREGS, ph->pid, NULL, ®s) < 0) die("[-] ptrace"); if (ptrace(PTRACE_CONT, ph->pid, NULL, NULL) < 0) die("[-] ptrace"); /* Should receive a SIGSEGV for return to 0 */ waitpid(ph->pid, &status, 0); if (ptrace(PTRACE_GETREGS, ph->pid, NULL, &aregs) < 0) die("[-] ptrace"); printf("[+] rdi=0x%zx rsp=0x%zx rip=0x%zx\n", aregs.rdi, aregs.rsp, aregs.rip); if (ptrace(PTRACE_SETREGS, ph->pid, 0, &saved_regs) < 0) die("[-] ptrace"); poke_text(ph->pid, saved_regs.rsp + 1024, sbuf1, sizeof(sbuf1)); poke_text(ph->pid, saved_regs.rsp, sbuf2, sizeof(sbuf2)); if (ptrace(PTRACE_DETACH, ph->pid, NULL, NULL) < 0) die("[-] ptrace"); if (aregs.rip != 0) printf("[-] dlopen in target may have failed (no clean NULL fault)\n"); return 0; }
int inject_code(pid_t pid, size_t libc_addr, size_t dlopen_addr, char *dso) { char sbuf1[1024], sbuf2[1024]; struct user_regs_struct regs, saved_regs; int status; if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) die("ptrace 1"); waitpid(pid, &status, 0); if (ptrace(PTRACE_GETREGS, pid, NULL, ®s) < 0) die("ptrace 2"); peek_text(pid, regs.rsp + 1024, sbuf1, sizeof(sbuf1)); peek_text(pid, regs.rsp, sbuf2, sizeof(sbuf2)); /* fake saved return address */ libc_addr = 0x0; poke_text(pid, regs.rsp, (char *)&libc_addr, sizeof(libc_addr)); poke_text(pid, regs.rsp + 1024, dso, strlen(dso) + 1); memcpy(&saved_regs, ®s, sizeof(regs)); /* pointer to &args */ printf("rdi=%zx rsp=%zx rip=%zx\n", regs.rdi, regs.rsp, regs.rip); regs.rdi = regs.rsp + 1024; regs.rsi = RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE; regs.rip = dlopen_addr + 2;// kernel bug?! always need to add 2! if (ptrace(PTRACE_SETREGS, pid, NULL, ®s) < 0) die("ptrace 3"); if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) die("ptrace 4"); /* Should receive a SIGSEGV */ waitpid(pid, &status, 0); if (ptrace(PTRACE_SETREGS, pid, 0, &saved_regs) < 0) die("ptrace 5"); poke_text(pid, saved_regs.rsp + 1024, sbuf1, sizeof(sbuf1)); poke_text(pid, saved_regs.rsp, sbuf2, sizeof(sbuf2)); if (ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0) die("ptrace 6"); return 0; }
int inject_code(pid_t pid, size_t libc_addr, size_t dlopen_addr, char *dso_file) { char sbuf1[1024], sbuf2[1024]; struct my_user_regs regs, saved_regs, aregs; int status; char *dso = NULL; size_t v = 0; printf("32bit mode\n"); dso = realpath(dso_file, NULL); if (!dso || access(dso, X_OK) < 0) die(dso ? dso : dso_file); printf("Using normalized path '%s' for injection.\n", dso); if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) die("ptrace 1"); waitpid(pid, &status, 0); if (ptrace(PTRACE_GETREGS, pid, NULL, ®s) < 0) die("ptrace 2"); peek_text(pid, regs.esp + 1024, sbuf1, sizeof(sbuf1)); peek_text(pid, regs.esp, sbuf2, sizeof(sbuf2)); /* fake saved return address, triggering a SIGSEGV to catch */ libc_addr = 0x0; poke_text(pid, regs.esp, (char *)&libc_addr, sizeof(libc_addr)); poke_text(pid, regs.esp + 1024, dso, strlen(dso) + 1); free(dso); memcpy(&saved_regs, ®s, sizeof(regs)); printf("esp=0x%zx eip=0x%zx\n", regs.esp, regs.eip); /* arguments passed on stack this time (x86) */ v = regs.esp + 1024; poke_text(pid, regs.esp + sizeof(size_t), &v, sizeof(v)); v = RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE; poke_text(pid, regs.esp + 2*sizeof(size_t), &v, sizeof(v)); /* kernel bug. always add 2; in -m32 mode on 64bit systems its * not needed!!! */ regs.eip = dlopen_addr + 2; if (ptrace(PTRACE_SETREGS, pid, NULL, ®s) < 0) die("ptrace 3"); if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) die("ptrace 4"); /* Should receive a SIGSEGV for return to 0 */ waitpid(pid, &status, 0); if (ptrace(PTRACE_GETREGS, pid, NULL, &aregs) < 0) die("ptrace 5"); printf("esp=0x%zx eip=0x%zx\n", aregs.esp, aregs.eip); if (ptrace(PTRACE_SETREGS, pid, 0, &saved_regs) < 0) die("ptrace 6"); poke_text(pid, saved_regs.esp + 1024, sbuf1, sizeof(sbuf1)); poke_text(pid, saved_regs.esp, sbuf2, sizeof(sbuf2)); if (ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0) die("ptrace 7"); if (aregs.eip != 0) printf("dlopen in target may failed (no clean NULL fault)!\n"); return 0; }
int inject_code(pid_t pid, size_t libc_addr, size_t dlopen_addr, char *dso_file) { char sbuf1[1024], sbuf2[1024]; struct my_user_regs regs, saved_regs, aregs; int status; char *dso = NULL; printf("64bit mode\n"); dso = realpath(dso_file, NULL); if (!dso || access(dso, X_OK) < 0) die(dso ? dso : dso_file); printf("Using normalized path '%s' for injection.\n", dso); if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) die("ptrace 1"); waitpid(pid, &status, 0); if (ptrace(PTRACE_GETREGS, pid, NULL, ®s) < 0) die("ptrace 2"); peek_text(pid, regs.rsp + 1024, sbuf1, sizeof(sbuf1)); peek_text(pid, regs.rsp, sbuf2, sizeof(sbuf2)); /* fake saved return address, triggering a SIGSEGV to catch */ libc_addr = 0x0; poke_text(pid, regs.rsp, (char *)&libc_addr, sizeof(libc_addr)); poke_text(pid, regs.rsp + 1024, dso, strlen(dso) + 1); free(dso); memcpy(&saved_regs, ®s, sizeof(regs)); printf("rdi=0x%zx rsp=0x%zx rip=0x%zx\n", regs.rdi, regs.rsp, regs.rip); /* arguments to function we call */ regs.rdi = regs.rsp + 1024; regs.rsi = RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE; regs.rip = dlopen_addr + 2;// kernel bug?! always need to add 2! if (ptrace(PTRACE_SETREGS, pid, NULL, ®s) < 0) die("ptrace 3"); if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) die("ptrace 4"); /* Should receive a SIGSEGV for return to 0 */ waitpid(pid, &status, 0); if (ptrace(PTRACE_GETREGS, pid, NULL, &aregs) < 0) die("ptrace 5"); printf("rdi=0x%zx rsp=0x%zx rip=0x%zx\n", aregs.rdi, aregs.rsp, aregs.rip); if (ptrace(PTRACE_SETREGS, pid, 0, &saved_regs) < 0) die("ptrace 6"); poke_text(pid, saved_regs.rsp + 1024, sbuf1, sizeof(sbuf1)); poke_text(pid, saved_regs.rsp, sbuf2, sizeof(sbuf2)); if (ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0) die("ptrace 7"); if (aregs.rip != 0) printf("dlopen in target may failed (no clean NULL fault)!\n"); return 0; }