Skip to content

Instantly share code, notes, and snippets.

@jakeajames
Last active August 4, 2022 10:16
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save jakeajames/5ee29a99107cdd2fd665b468f9f8e664 to your computer and use it in GitHub Desktop.
Save jakeajames/5ee29a99107cdd2fd665b468f9f8e664 to your computer and use it in GitHub Desktop.
"kppless" sandbox profile patch for iOS 12
addr_t Find_platform_profile() {
uint64_t string = Find_strref("\"failed to initialize platform sandbox", 1, 0, false);
if (!string) {
string = Find_strref("\"failed to initialize platform sandbox", 1, 1, false);
if (!string) {
return 0;
}
}
string -= KernDumpBase;
uint64_t adrp = Step64_back(Kernel, string, 100, INSN_ADRP);
if (!adrp) {
return 0;
}
adrp = Step64_back(Kernel, adrp - 4, 100, INSN_ADRP);
if (!adrp) {
return 0;
}
adrp = Step64_back(Kernel, adrp - 4, 100, INSN_ADRP);
if (!adrp) {
return 0;
}
uint64_t x0 = Calc64(Kernel, adrp, adrp + 8, 0);
if (!x0) {
return 0;
}
return x0 + KernDumpBase + KASLR_Slide;
}
addr_t Find_platform_data() {
uint64_t string = Find_strref("\"failed to initialize platform sandbox", 1, 0, false);
if (!string) {
string = Find_strref("\"failed to initialize platform sandbox", 1, 1, false);
if (!string) {
return 0;
}
}
string -= KernDumpBase;
uint64_t adrp = Step64_back(Kernel, string, 100, INSN_ADRP);
if (!adrp) {
return 0;
}
adrp = Step64_back(Kernel, adrp - 4, 100, INSN_ADRP);
if (!adrp) {
return 0;
}
uint64_t x1 = Calc64(Kernel, adrp, adrp + 8, 1);
if (!x1) {
return 0;
}
return x1 + KernDumpBase + KASLR_Slide;
}
addr_t Find_platform_data_size() {
uint64_t string = Find_strref("\"failed to initialize platform sandbox", 1, 0, false);
if (!string) {
string = Find_strref("\"failed to initialize platform sandbox", 1, 1, false);
if (!string) {
return 0;
}
}
string -= KernDumpBase;
uint64_t adrp = Step64_back(Kernel, string, 100, INSN_ADRP);
if (!adrp) {
return 0;
}
adrp = Step64_back(Kernel, adrp - 4, 100, INSN_ADRP);
if (!adrp) {
return 0;
}
uint64_t w3 = Calc64mov(Kernel, adrp + 8, adrp + 12, 3);
if (!w3) {
return 0;
}
return w3;
}
addr_t Find_do_profile_create() {
uint64_t string = Find_strref("\"failed to initialize platform sandbox", 1, 0, false);
if (!string) {
string = Find_strref("\"failed to initialize platform sandbox", 1, 1, false);
if (!string) {
return 0;
}
}
string -= KernDumpBase;
uint64_t bl = Step64_back(Kernel, string, 100, INSN_CALL);
if (!bl) {
return 0;
}
uint64_t call = Follow_call64(Kernel, bl);
if (!call) {
return 0;
}
return call + KernDumpBase + KASLR_Slide;
}
addr_t Find_sandbox_collection() {
uint64_t string = Find_strref("failed to initialize collection", 1, 0, false);
if (!string) {
string = Find_strref("failed to initialize collection", 1, 1, false);
if (!string) {
return 0;
}
}
string -= KernDumpBase;
uint64_t do_profile_create = Find_do_profile_create();
do_profile_create -= KernDumpBase + KASLR_Slide;
uint64_t bl = 0;
for (int i = 0; i < 10; i++) {
bl = Step64_back(Kernel, string, 100, INSN_CALL);
if (!bl) {
return 0;
}
uint64_t call = Follow_call64(Kernel, bl);
if (!call) {
return 0;
}
if (call == do_profile_create) {
break;
}
string = bl - 4;
}
uint64_t adrp = Step64_back(Kernel, bl, 100, INSN_ADRP);
if (!adrp) {
return 0;
}
adrp = Step64_back(Kernel, adrp - 4, 100, INSN_ADRP);
if (!adrp) {
return 0;
}
uint64_t page = Calc64(Kernel, adrp, adrp + 4, 22);
if (!page) {
page = Calc64(Kernel, adrp, adrp + 4, 20);
if (!page) {
return 0;
}
}
uint64_t str = adrp + 4;
uint32_t op = *(uint32_t*)(Kernel + str);
unsigned imm = ((op >> 10) & 0xFFF) << 3;
return page + imm + KernDumpBase + KASLR_Slide;
}
addr_t Find_collection_data() {
uint64_t string = Find_strref("failed to initialize collection", 1, 0, false);
if (!string) {
string = Find_strref("failed to initialize collection", 1, 1, false);
if (!string) {
return 0;
}
}
string -= KernDumpBase;
uint64_t do_profile_create = Find_do_profile_create();
do_profile_create -= KernDumpBase + KASLR_Slide;
uint64_t bl = 0;
for (int i = 0; i < 10; i++) {
bl = Step64_back(Kernel, string, 100, INSN_CALL);
if (!bl) {
return 0;
}
uint64_t call = Follow_call64(Kernel, bl);
if (!call) {
return 0;
}
if (call == do_profile_create) {
break;
}
string = bl - 4;
}
uint64_t adrp = Step64_back(Kernel, bl, 100, INSN_ADRP);
if (!adrp) {
return 0;
}
uint64_t x1 = Calc64(Kernel, adrp, adrp + 8, 1);
if (!x1) {
return 0;
}
return x1 + KernDumpBase + KASLR_Slide;
}
addr_t Find_collection_data_size() {
uint64_t string = Find_strref("failed to initialize collection", 1, 0, false);
if (!string) {
string = Find_strref("failed to initialize collection", 1, 1, false);
if (!string) {
return 0;
}
}
string -= KernDumpBase;
uint64_t do_profile_create = Find_do_profile_create();
do_profile_create -= KernDumpBase + KASLR_Slide;
uint64_t bl = 0;
for (int i = 0; i < 10; i++) {
bl = Step64_back(Kernel, string, 100, INSN_CALL);
if (!bl) {
return 0;
}
uint64_t call = Follow_call64(Kernel, bl);
if (!call) {
return 0;
}
if (call == do_profile_create) {
break;
}
string = bl - 4;
}
uint64_t adrp = Step64_back(Kernel, bl, 100, INSN_ADRP);
if (!adrp) {
return 0;
}
uint64_t w3 = Calc64mov(Kernel, adrp + 8, adrp + 16, 3);
if (!w3) {
return 0;
}
return w3;
}
addr_t Find_sandbox_operations_list() {
uint64_t platform_profile = Find_platform_profile();
if (!platform_profile) {
return 0;
}
return platform_profile + 8;
}
int Find_number_of_sb_operations() {
uint64_t list = Find_sandbox_operations_list();
if (!list) {
return 0;
}
list -= KernDumpBase + KASLR_Slide;
int num = 0;
for (int i = 0; i < 500; i++) {
uint64_t ptr = *(uint64_t*)(Kernel + list);
if (!ptr) {
return 0;
}
if ((ptr & 0xfffffff000000000) != 0xfffffff000000000) { // tagged pointers
ptr |= 0xfffffff000000000;
}
ptr -= KernDumpBase;
char *string = (char *)(Kernel + ptr);
if (!strcmp(string, "HOME")) break;
list += 8;
num++;
}
return num;
}
int Find_sandbox_operation_index(char *op) {
uint64_t list = Find_sandbox_operations_list();
if (!list) {
return 0;
}
list -= KernDumpBase + KASLR_Slide;
int count = Find_number_of_sb_operations();
for (int i = 0; i < count; i++) {
uint64_t ptr = *(uint64_t*)(Kernel + list);
if (!ptr) {
return 0;
}
if ((ptr & 0xfffffff000000000) != 0xfffffff000000000) { // tagged pointers
ptr |= 0xfffffff000000000;
}
ptr -= KernDumpBase;
char *string = (char *)(Kernel + ptr);
if (!strcmp(string, op)) {
return i;
}
list += 8;
}
return 0;
}
int patch_platform_profile() {
if (!container_sb) {
printf("[-] I need a sandbox\n");
return 1;
}
uint32_t size = (uint32_t)Find_platform_data_size();
if (!size) {
return 2;
}
int numsbops = Find_number_of_sb_operations();
if (!numsbops) {
return 3;
}
int fme_idx = Find_sandbox_operation_index("file-map-executable");
if (!fme_idx) { // only "default" should be at index 0
return 4;
}
/*int procexec_idx = Find_sandbox_operation_index("process-exec*");
if (!procexec_idx) {
return 4;
}*/
int interpreter_idx = Find_sandbox_operation_index("process-exec-interpreter");
if (!interpreter_idx) {
return 4;
}
uint64_t pprofile = Find_platform_profile();
if (!pprofile) {
return 5;
}
uint64_t platform_profile_ptr = KernelRead_64bits(pprofile);
uint64_t platform_profile = KernelRead_64bits(platform_profile_ptr);
uint64_t copy = Kernel_alloc(size);
void *ucopy = malloc(size);
KernelRead(platform_profile, ucopy, size);
KernelWrite(copy, ucopy, size);
free(ucopy);
KernelWrite_64bits(platform_profile_ptr, copy);
int idx = 0;
uint32_t val = 0;
uint16_t patch = 0;
do {
KernelRead(copy + idx * 2, &patch, sizeof(uint16_t));
val = KernelRead_32bits(copy + patch * 8);
idx++;
} while (val != 1);
KernelWrite(copy + 12 + fme_idx * 2, &patch, sizeof(uint16_t));
//KernelWrite(copy + 12 + procexec_idx * 2, &patch, sizeof(uint16_t));
KernelWrite(copy + 12 + interpreter_idx * 2, &patch, sizeof(uint16_t));
return 0;
}
uint64_t container_sb = 0;
int patch_sandbox_container() {
if (!container_sb) {
printf("[-] I need a sandbox\n");
return 1;
}
uint32_t size = (uint32_t)Find_collection_data_size();
if (!size) {
return 2;
}
int numsbops = Find_number_of_sb_operations();
if (!numsbops) {
return 3;
}
int fme_idx = Find_sandbox_operation_index("file-map-executable");
if (!fme_idx) { // only "default" should be at index 0
return 4;
}
int fread_idx = Find_sandbox_operation_index("file-read*");
if (!fread_idx) {
return 4;
}
int freaddata_idx = Find_sandbox_operation_index("file-read-data");
if (!freaddata_idx) {
return 4;
}
int freadmeta_idx = Find_sandbox_operation_index("file-read-metadata");
if (!freadmeta_idx) {
return 4;
}
int mach_lookup_idx = Find_sandbox_operation_index("mach-lookup");
if (!mach_lookup_idx) {
return 4;
}
uint64_t profile = KernelRead_64bits(container_sb);
uint64_t data = KernelRead_64bits(profile);
uint64_t copy = Kernel_alloc(size);
void *ucopy = malloc(size);
KernelRead(data, ucopy, size);
KernelWrite(copy, ucopy, size);
free(ucopy);
KernelWrite_64bits(profile, copy);
uint32_t container_off = 0;
char *found = NULL;
int idx = 0;
do {
if (found) {
free(found);
found = NULL;
}
uint16_t string_off = (uint16_t)KernelRead_32bits(copy + 14 + (numsbops + 2) * 2 * idx);
uint32_t size = KernelRead_32bits(copy + string_off * 8);
found = malloc(size);
KernelRead(copy + string_off * 8 + 4, found, size);
container_off = 14 + (numsbops + 2) * 2 * idx;
idx++;
} while (strcmp(found, "container"));
idx = 0;
uint32_t val = 0;
uint16_t patch = 0;
do {
KernelRead(copy + container_off + idx * 2, &patch, sizeof(uint16_t));
val = KernelRead_32bits(copy + patch * 8);
idx++;
} while (val != 1);
KernelWrite(copy + container_off + 4 + fme_idx * 2, &patch, sizeof(uint16_t));
KernelWrite(copy + container_off + 4 + fread_idx * 2, &patch, sizeof(uint16_t));
KernelWrite(copy + container_off + 4 + freaddata_idx * 2, &patch, sizeof(uint16_t));
KernelWrite(copy + container_off + 4 + freadmeta_idx * 2, &patch, sizeof(uint16_t));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment