Created
October 15, 2024 13:58
-
-
Save theevilbit/f84f4721acf83b80ef65f1d4e87ce1a8 to your computer and use it in GitHub Desktop.
rc.trampoline research
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 <objc/runtime.h> | |
#include <Foundation/Foundation.h> | |
#include <IOKit/IOKitLib.h> | |
#include <spawn.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <err.h> | |
#include <sys/wait.h> | |
#include <sys/stat.h> | |
typedef uint32_t csr_config_t; | |
#define CSR_ALLOW_UNRESTRICTED_FS (1 << 1) | |
extern int csr_check(csr_config_t); | |
extern int csops(pid_t pid, unsigned int ops, void * useraddr, size_t usersize); | |
void handle_error() { | |
printf("Something went wrong, I'm lazy to implement an error for each case now...\n"); | |
exit(1); | |
} | |
int main() { | |
io_registry_entry_t ioEntry; | |
io_object_t ioObject; | |
CFMutableDictionaryRef ioProperties = NULL; | |
mach_port_t mainPort = 0; | |
if (IOMasterPort(bootstrap_port, &mainPort) != KERN_SUCCESS) { | |
handle_error(); | |
} | |
ioEntry = IORegistryEntryFromPath(mainPort, "IODeviceTree:/options"); | |
if (!ioEntry) { | |
handle_error(); | |
} | |
ioObject = ioEntry; | |
if (IORegistryEntryCreateCFProperties(ioEntry, &ioProperties, NULL, 0) != KERN_SUCCESS) { | |
handle_error(); | |
} | |
IOObjectRelease(ioObject); | |
if (!ioProperties) { | |
handle_error(); | |
} | |
// Retrieve "apple-trusted-trampoline" property | |
CFStringRef trampolineKey = CFSTR("apple-trusted-trampoline"); | |
NSString *trampolineValue = CFDictionaryGetValue(ioProperties, trampolineKey); | |
if (!trampolineValue || ![trampolineValue length]) { | |
handle_error(); | |
} | |
// Generate file path in temporary directory | |
NSString *tempDir = NSTemporaryDirectory(); | |
NSURL *fileURL = [NSURL fileURLWithPath:tempDir]; | |
NSURL *finalURL = [fileURL URLByAppendingPathComponent:@"apple-trusted-trampoline.bin"]; | |
NSString *filePath = [finalURL path]; | |
// Write trampoline to file | |
BOOL writeSuccess = [trampolineValue writeToFile:filePath atomically:NO]; | |
if (!writeSuccess) { | |
const char *filePathCStr = [filePath UTF8String]; | |
errx(1, "Failed to write binary file to %s, it must be writable.", filePathCStr); | |
} | |
chmod([filePath UTF8String], 0700); | |
// Prepare to spawn a new process | |
pid_t childPid = 0; | |
posix_spawn_file_actions_t fileActions; | |
posix_spawnattr_t spawnAttr; | |
posix_spawn_file_actions_init(&fileActions); | |
posix_spawnattr_init(&spawnAttr); | |
posix_spawnattr_setflags(&spawnAttr, POSIX_SPAWN_START_SUSPENDED); | |
const char *argv[] = {"apple-trusted-trampoline.bin", NULL}; | |
int spawnResult = posix_spawn(&childPid, [filePath UTF8String], &fileActions, &spawnAttr, (char *const *)argv, NULL); | |
if (spawnResult != 0) { | |
handle_error(); | |
} | |
// Perform checks on the spawned process | |
int csopsFlags = 0; | |
int checkResult = csops(childPid, 0, &csopsFlags, sizeof(csopsFlags)); | |
int csrCheckResult = csr_check(CSR_ALLOW_UNRESTRICTED_FS); | |
// Clean up and terminate child process if necessary | |
NSString *unlinkPath = [finalURL path]; | |
unlink([unlinkPath UTF8String]); | |
if (csrCheckResult != 0 && (checkResult != 0 || (csopsFlags & 0x4000000) == 0)) { | |
fprintf(stderr, "Killing child, it did not pass the platform check.\n"); | |
kill(childPid, SIGKILL); | |
exit(0); | |
} | |
// Resume child process and wait for it to finish | |
kill(childPid, SIGCONT); | |
int status = 0; | |
waitpid(childPid, &status, 0); | |
return 0; | |
} |
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 <IOKit/IOKitLib.h> | |
#include <CoreFoundation/CoreFoundation.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
// Function to read the file data into a CFData object | |
CFDataRef readFileData(const char *filePath) { | |
FILE *file = fopen(filePath, "rb"); // Open the file in binary mode | |
if (!file) { | |
printf("Unable to open file: %s\n", filePath); | |
return NULL; | |
} | |
// Get file size | |
fseek(file, 0, SEEK_END); | |
long fileSize = ftell(file); | |
fseek(file, 0, SEEK_SET); | |
// Allocate memory to store the file contents | |
unsigned char *buffer = (unsigned char *)malloc(fileSize); | |
if (!buffer) { | |
printf("Failed to allocate memory for file data.\n"); | |
fclose(file); | |
return NULL; | |
} | |
// Read the file contents into the buffer | |
fread(buffer, 1, fileSize, file); | |
fclose(file); | |
// Create CFData from the buffer | |
CFDataRef data = CFDataCreate(kCFAllocatorDefault, buffer, fileSize); | |
// Free the buffer since CFData now holds the file data | |
free(buffer); | |
return data; | |
} | |
int main() { | |
io_registry_entry_t service; | |
kern_return_t result; | |
mach_port_t mainPort; | |
// Step 1: Get the main port to communicate with the IOKit | |
IOMainPort(kIOMasterPortDefault, &mainPort); | |
// Step 2: Get the I/O registry entry from the path "IODeviceTree:/options" | |
service = IORegistryEntryFromPath(mainPort, "IODeviceTree:/options"); | |
if (!service) { | |
printf("Unable to find IORegistry entry at IODeviceTree:/options.\n"); | |
return -1; | |
} | |
// Step 3: Read the binary data from the file | |
CFDataRef fileData = readFileData("/usr/bin/perl"); | |
if (!fileData) { | |
IOObjectRelease(service); | |
return -1; | |
} | |
// Step 4: Create the key for the new property | |
CFStringRef key = CFStringCreateWithCString(kCFAllocatorDefault, "apple-trusted-trampoline", kCFStringEncodingUTF8); | |
// Step 5: Set the new binary property (CFData) in the registry at IODeviceTree:/options | |
result = IORegistryEntrySetCFProperty(service, key, fileData); | |
if (result == KERN_SUCCESS) { | |
printf("Successfully set 'apple-trusted-trampoline' with the binary data\n"); | |
} else { | |
printf("Failed to set property: %d\n", result); | |
} | |
// Step 6: Clean up and release resources | |
CFRelease(key); | |
CFRelease(fileData); | |
IOObjectRelease(service); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment