Add a debug command

This commit is contained in:
2019-12-11 16:19:05 -05:00
parent ebe07f5c32
commit 3c8d6c62c5
10 changed files with 240 additions and 119 deletions

View File

@@ -8,19 +8,22 @@
void dfu_send_data(struct pwned_device *dev, unsigned char *data, long data_len)
{
checkm8_debug("dfu_send_data(dev = %p, data = %p, data_len = %li)\n", dev, data, data_len);
long index = 0, amount;
int ret;
while(index < data_len)
{
if(data_len - index >= LIBUSB_MAX_PACKET_SIZE) amount = LIBUSB_MAX_PACKET_SIZE;
else amount = data_len - index;
libusb_control_transfer(dev->bundle->handle, 0x21, 1, 0, 0, &data[index], amount, 5000);
checkm8_debug("sending 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);
checkm8_debug("transferred %i bytes\n", ret);
index += amount;
}
}
static unsigned char nullbuf[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
struct command_args
{
unsigned long magic;
@@ -35,42 +38,54 @@ struct command_args
long len;
};
static unsigned char nullbuf[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int command(struct pwned_device *dev, struct command_args *args, struct command_args *resp, long response_len)
{
int ret = get_device_bundle(dev);
if(IS_CHECKM8_FAIL(ret)) return ret;
checkm8_debug("command(dev = %p, args = %p, resp = %p, response_len = %li)\n", dev, args, resp, response_len);
if(!is_device_bundle_open(dev)) return CHECKM8_FAIL_NODEV;
int ret;
dfu_send_data(dev, nullbuf, 16);
libusb_control_transfer(dev->bundle->handle, 0x21, 1, 0, 0, NULL, 0, 100);
libusb_control_transfer(dev->bundle->handle, 0xA1, 3, 0, 0, NULL, 0, 100);
libusb_control_transfer(dev->bundle->handle, 0xA1, 3, 0, 0, NULL, 6, 100);
dfu_send_data(dev, (unsigned char *) args, args->len);
ret = libusb_control_transfer(dev->bundle->handle, 0x21, 1, 0, 0, nullbuf, 0, 100);
checkm8_debug("got return code %i (%s) from control transfer\n", ret, libusb_error_name(ret));
ret = libusb_control_transfer(dev->bundle->handle, 0xA1, 3, 0, 0, nullbuf, 6, 100);
checkm8_debug("got return code %i (%s) from control transfer\n", ret, libusb_error_name(ret));
ret = libusb_control_transfer(dev->bundle->handle, 0xA1, 3, 0, 0, nullbuf, 6, 100);
checkm8_debug("got return code %i (%s) from control transfer\n", ret, libusb_error_name(ret));
dfu_send_data(dev, (unsigned char *) args, args->len);
if(response_len == 0)
{
libusb_control_transfer(dev->bundle->handle, 0xA1, 2, 0xFFFF, 0, (unsigned char *) resp, response_len + 1, 100);
ret = libusb_control_transfer(dev->bundle->handle, 0xA1, 2, 0xFFFF, 0, (unsigned char *) resp, response_len + 1, 100);
checkm8_debug("got return code %i (%s) from final response transfer\n", ret, libusb_error_name(ret));
}
else
{
libusb_control_transfer(dev->bundle->handle, 0xA1, 2, 0xFFFF, 0, (unsigned char *) resp, response_len, 100);
ret = libusb_control_transfer(dev->bundle->handle, 0xA1, 2, 0xFFFF, 0, (unsigned char *) resp, response_len, 100);
checkm8_debug("got return code %i (%s) from control transfer\n", ret, libusb_error_name(ret));
}
release_device_bundle(dev);
checkm8_debug("got response magic %X\n", resp->magic);
return CHECKM8_SUCCESS;
}
#define EXEC_MAGIC 0x6365786563657865ul
#define MEMC_MAGIC 0x636d656d636d656dul
#define MEMS_MAGIC 0x736d656d736d656dul
#define DONE_MAGIC 0x656e6f64656e6f64ul
#define EXEC_MAGIC 0x6365786563657865ul // 'execexec'[::-1]
#define MEMC_MAGIC 0x636d656d636d656dul // 'memcmemc'[::-1]
#define MEMS_MAGIC 0x736d656d736d656dul // 'memsmems'[::-1]
#define DONE_MAGIC 0x656e6f64656e6f64ul // 'donedone'[::-1]
int dev_memset(struct pwned_device *dev, long addr, char c, long len)
int dev_memset(struct pwned_device *dev, long addr, unsigned char c, long len)
{
checkm8_debug("dev_memset(dev = %p, addr = %lx, c = %x, len = %li)\n", dev, addr, c, len);
int ret;
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);
cmd_args->magic = MEMS_MAGIC;
cmd_args->arg1 = addr;
cmd_args->arg2 = (unsigned long) c;
@@ -86,11 +101,13 @@ int dev_memset(struct pwned_device *dev, long addr, char c, long len)
int dev_memcpy(struct pwned_device *dev, long dest, long src, long len)
{
checkm8_debug("dev_memset(dev = %p, dest = %lx, src = %lx, len = %li)\n", dev, dest, src, len);
int ret;
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);
cmd_args->magic = MEMC_MAGIC;
cmd_args->arg1 = dest;
cmd_args->arg2 = src;
@@ -106,7 +123,12 @@ int dev_memcpy(struct pwned_device *dev, long dest, long src, long len)
int dev_exec(struct pwned_device *dev, long response_len, int nargs, long *args)
{
if(nargs > 7) return CHECKM8_FAIL_INVARGS;
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");
return CHECKM8_FAIL_INVARGS;
}
int ret;
unsigned long *argbase;
@@ -114,14 +136,19 @@ int dev_exec(struct pwned_device *dev, long response_len, int nargs, long *args)
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: ");
cmd_args->magic = EXEC_MAGIC;
argbase = &cmd_args->arg1;
for(ret = 0; ret < nargs; ret++)
{
checkm8_debug("%lx ", args[ret]);
argbase[ret] = args[ret];
}
checkm8_debug("\n");
ret = command(dev, cmd_args, cmd_resp, 16 + response_len);
if(cmd_resp->magic != DONE_MAGIC) return CHECKM8_FAIL_NOTDONE;
if(ret == CHECKM8_SUCCESS && cmd_resp->magic != DONE_MAGIC) return CHECKM8_FAIL_NOTDONE;
else return ret;
}