Created
June 12, 2023 17:50
-
-
Save wh1te4ever/36ab42dd81095be4c5f42887485e93c8 to your computer and use it in GitHub Desktop.
Patch platform of build_version_command to iPhoneOS!
This file contains hidden or 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
#import <Foundation/Foundation.h> | |
#include <stdio.h> | |
#include <string> | |
#include <mach-o/loader.h> | |
#include <mach-o/fat.h> | |
#include <mach/machine.h> | |
#include <iostream> | |
#include <cstdlib> | |
#include <new> | |
#include <spawn.h> | |
//How to Compile | |
// clang++ -o patch_iphoneos patch.mm -framework Foundation | |
//How to Patch | |
// ./patch_iphoneos <binary> | |
uint32_t swap_uint32(uint32_t val) { | |
val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF); | |
return (val << 16) | (val >> 16); | |
} | |
uint64_t swap_uint64(uint64_t val) { | |
val = ((val << 8) & 0xFF00FF00FF00FF00ULL) | ((val >> 8) & 0x00FF00FF00FF00FFULL); | |
val = ((val << 16) & 0xFFFF0000FFFF0000ULL) | ((val >> 16) & 0x0000FFFF0000FFFFULL); | |
return (val << 32) | (val >> 32); | |
} | |
bool patch_build_version_command(const char* filepath) { | |
static struct { | |
build_version_command cmd; | |
build_tool_version tool_ver; | |
} buildVersionForSimulator = {LC_BUILD_VERSION, 0x20, 7, 0xE0000, 0xE0200, 1, 3, 0x2610700}; | |
FILE* file = fopen(filepath, "r+b"); | |
if (!file) { | |
printf("[-] error: failed to open file\n"); | |
return false; | |
} | |
fseek(file, 0, SEEK_END); | |
long fileSize = ftell(file); | |
fseek(file, 0, SEEK_SET); | |
char* buffer = new char[fileSize]; | |
size_t readLen = fread(buffer, 1, fileSize, file); | |
mach_header_64* header = (mach_header_64*)buffer; | |
if (header->magic == FAT_CIGAM_64 || header->magic == FAT_CIGAM) { | |
fat_header* fat = (fat_header*)buffer; | |
if (swap_uint32(fat->nfat_arch) != 1) { | |
printf("[-] error: App has fat macho with more than one architecture? (%d)\n", fat->nfat_arch); | |
delete[] buffer; | |
fclose(file); | |
return false; | |
} | |
cpu_type_t cputype; | |
uint64_t offset; | |
if (header->magic == FAT_CIGAM_64) { | |
fat_arch_64* farch64 = (fat_arch_64*)(buffer + sizeof(fat_header)); | |
cputype = swap_uint32(farch64->cputype); | |
offset = swap_uint64(farch64->offset); | |
} else { | |
fat_arch* farch = (fat_arch*)(buffer + sizeof(fat_header)); | |
cputype = swap_uint32(farch->cputype); | |
offset = swap_uint32(farch->offset); | |
} | |
if (cputype != CPU_TYPE_ARM64) { | |
printf("[-] error: iOS App has macho with wrong cputype:0x%x\n", cputype); | |
delete[] buffer; | |
fclose(file); | |
return false; | |
} | |
if (offset > fileSize) { | |
printf("[-] error: huge fat arch offset 0x%llx > 0x%lx\n", offset, fileSize); | |
delete[] buffer; | |
fclose(file); | |
return false; | |
} | |
header = (mach_header_64*)(buffer + offset); | |
} | |
if (header->magic != MH_MAGIC_64) { | |
printf("[-] error: not a valid macho file\n"); | |
delete[] buffer; | |
fclose(file); | |
return false; | |
} | |
struct load_command* lc = (load_command*)((mach_vm_address_t)header + sizeof(mach_header_64)); | |
bool found_build_version_command = false; | |
for (uint32_t i = 0; i < header->ncmds; i++) { | |
if (lc->cmd == LC_BUILD_VERSION) { | |
build_version_command* buildCmd = (build_version_command*)lc; | |
printf("[+] Platform: %u\n", buildCmd->platform); | |
found_build_version_command = true; | |
printf("[+] Found platform of build version command at offset: 0x%llx\n", (mach_vm_address_t)lc + offsetof(struct build_version_command, platform) - (mach_vm_address_t)header); | |
uint32_t platform_ios = 2; | |
memcpy((char*)lc + offsetof(struct build_version_command, platform), &platform_ios, sizeof(uint32_t)); | |
break; | |
} | |
lc = (struct load_command*)((mach_vm_address_t)lc + lc->cmdsize); | |
} | |
if (!found_build_version_command) { | |
printf("[-] error: LC_BUILD_VERSION command not found\n"); | |
delete[] buffer; | |
fclose(file); | |
return false; | |
} | |
fseek(file, 0, SEEK_SET); | |
fwrite(buffer, 1, fileSize, file); | |
delete[] buffer; | |
fclose(file); | |
return true; | |
} | |
void unzip(char* zippath, char *outputDir) { | |
pid_t pid; | |
int status; | |
const char* args[] = {"unzip", "-o", zippath, "-d", outputDir, NULL}; | |
posix_spawn(&pid, "/usr/bin/unzip", NULL, NULL, (char* const*)args, NULL); | |
waitpid(pid, &status, 0); | |
} | |
void modify_library_path(char* bin, char* from, char* to) { | |
pid_t pid; | |
int status; | |
const char* args[] = {"install_name_tool", "-change", from, to, bin, NULL}; | |
posix_spawn(&pid, "/usr/bin/install_name_tool", NULL, NULL, (char* const*)args, NULL); | |
waitpid(pid, &status, 0); | |
} | |
void sign(char* bin, char* ent) { | |
pid_t pid; | |
int status; | |
char ent_arg[16] = "-S"; | |
strcat(ent_arg, ent); | |
const char* args[] = {"ldid", ent_arg, bin, NULL}; | |
posix_spawn(&pid, "/usr/local/bin/ldid", NULL, NULL, (char* const*)args, NULL); | |
waitpid(pid, &status, 0); | |
} | |
void create_ent(char *outputPath) { | |
NSMutableDictionary *plistDict = [NSMutableDictionary dictionary]; | |
// Add the key-value pairs to the dictionary | |
[plistDict setObject:@YES forKey:@"platform-application"]; | |
[plistDict setObject:@YES forKey:@"com.apple.private.security.no-container"]; | |
[plistDict setObject:@YES forKey:@"com.apple.private.skip-library-validation"]; | |
// Create a property list object | |
NSError *error = nil; | |
NSData *plistData = [NSPropertyListSerialization dataWithPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 options:0 error:nil]; | |
[plistData writeToFile:[NSString stringWithUTF8String: outputPath] atomically:YES]; | |
} | |
void cleanup() { | |
} | |
int main(int argc, const char* argv[]) { | |
if (!patch_build_version_command(argv[1])) { | |
return 1; | |
} | |
printf("[+] Patch applied successfully!\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment