Store::~Store() { if (_thread_pool != NULL) { // It is only safe to destroy the store once the thread pool has been deleted // (as the pool stores a pointer to the store). Make sure this is the case. stop(); wait_stopped(); } pthread_key_delete(_thread_local); }
int inject_code(int pid, unsigned char *payload, size_t payload_len) { int ret = 0, status = 0; void *payload_addr = NULL, *stack = NULL, *code_cave = NULL, *payload_aligned = NULL; size_t payload_size; // align shellcode size to 32/64-bit boundary payload_size = payload_len + (sizeof(void*) - (payload_len % sizeof(void*))); payload_aligned = malloc(payload_size); CHECK(payload_aligned, "malloc() error"); memset(payload_aligned, 0x90, payload_size); // fill with NOPs memcpy(payload_aligned, payload, payload_len); printf("Injecting into target process %d\n", pid); // attach to process CHECK(ptrace_attach(pid), "Error attaching to target process %d", pid); dprintf("Attached to process"); // wait to make sure process is in ptrace-stop state before continuing, // otherwise we may inadvertently kill the process CHECK(wait_stopped(pid), "Failed to wait until target process in stopped state"); dprintf("Process is in stopped state"); // Wait until process has just returned from a system call before proceeding CHECK(ptrace_next_syscall(pid), "Failed to wait until after next syscall"); dprintf("Process exited from syscall"); // save state CHECK(_save_state(pid), "Failed to state target process state"); dprintf("Saved state of target process"); // allocate payload space CHECK(_mmap_data(pid, payload_size, NULL, 0, 0, &payload_addr), "Failed to allocate space for payload"); dprintf("Allocated space for payload at location %p", payload_addr); // copy payload CHECK(ptrace_writemem(pid, payload_addr, payload_aligned, payload_size), "Failed to copy payload to target process"); dprintf("Wrote payload to target process at address %p", payload_addr); // allocate new stack CHECK(_mmap_data(pid, STACK_SIZE, NULL, 0, 0, &stack), "Failed to allocate space for new stack"); stack += STACK_SIZE; // use top address as stack base, since stack grows downward dprintf("Allocated new stack at location %p", stack); // allocate space for code cave CHECK(_mmap_data(pid, MAX_CODE_SIZE, NULL, 0, 0, &code_cave), "Failed to allocate space for code cave"); dprintf("Allocated space for code cave at location %p", code_cave); // launch payload via clone(2) dprintf("Launching payload in new thread"); CHECK(_launch_payload(pid, code_cave, MAX_CODE_SIZE, stack, STACK_SIZE, payload_addr, payload_size, NULL, 0), "Failed to launch payload"); ret = 1; error: if (payload_aligned) free(payload_aligned); _restore_state(pid); ptrace_detach(pid); return ret; }
int main() { int i; pid_t pid; nprocs = 35; nsigs = 1000; if ((pids = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0)) == MAP_FAILED) err(1, "mmap"); for (i = 0; i < nprocs; i++) { switch((pid = fork())) { case 0: do_child(); _exit(0); case -1: err(1, "fork"); } pids[i] = pid; } atexit(cleanup); signal(SIGALRM, alrmhand); alarm(120); /* Die after two minutes. */ /* Step 1. Wait until all children have went to sleep */ for (i = 0; i < nprocs; i++) wait_stopped(pids[i]); /* And wake them */ for (i = 0; i < nprocs; i++) kill(pids[i], SIGCONT); /* Step 2. Repeat. */ for (i = 0; i < nprocs; i++) wait_stopped(pids[i]); for (i = 0; i < nprocs; i++) kill(pids[i], SIGCONT); /* * Now all children are ready for action. * Send the first signals and wait until they all exit. */ kill(pids[arc4random_uniform(nprocs)], SIGUSR1); kill(pids[arc4random_uniform(nprocs)], SIGUSR2); /* * The signal game is running, now insert noise in the process. */ for (i = 0; i < nprocs; i++) { pid_t pid = pids[arc4random_uniform(nprocs)]; kill(pid, SIGSTOP); wait_stopped(pid); kill(pid, SIGCONT); } /* Step 3. Repeat. */ for (i = 0; i < nprocs; i++) wait_stopped(pids[i]); for (i = 0; i < nprocs; i++) kill(pids[i], SIGCONT); /* Wait for everyone to finish. */ for (i = 0; i < nprocs; i++) { int status; if (waitpid(pids[i], &status, WUNTRACED) != pids[i]) err(1, "waitpid"); if (!WIFEXITED(status)) errx(1, "child %d not stopped (%d)", pids[i], status); if (WEXITSTATUS(status) != 0) warnx("child %d status: %d", i, status); } return (0); }