Working arduino control requests, still kind of clunky

This commit is contained in:
2019-12-31 00:19:06 -05:00
parent 578699bbc3
commit a215788cbc
7 changed files with 257 additions and 138 deletions

View File

@@ -14,7 +14,7 @@
#ifndef _SPI_H_INCLUDED
#define _SPI_H_INCLUDED
#include "../../../../../../../../../opt/arduino-1.8.10/hardware/arduino/avr/cores/arduino/Arduino.h"
#include "Arduino.h"
// SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(),
// usingInterrupt(), and SPISetting(clock, bitOrder, dataMode)

View File

@@ -4,10 +4,11 @@
#include "ard_protocol.h"
USB Usb;
USB_DEVICE_DESCRIPTOR desc_buf;
uint8_t state, rcode, addr = 1;
uint8_t usb_data_buf[ARD_BUF_SIZE];
uint8_t desc_buf_val = 0;
USB_DEVICE_DESCRIPTOR desc_buf;
struct serial_desc_args sd_args;
struct usb_xfer_args usb_args;
@@ -15,7 +16,7 @@ int i, chunk_i;
int size, chunk_size;
char cmd;
void recv_args(uint8_t *target, int len)
void recv_serial(uint8_t *target, int len)
{
for(i = 0; i < len; i = i + 1)
{
@@ -26,6 +27,26 @@ void recv_args(uint8_t *target, int len)
}
}
void get_dev_descriptor()
{
if(!desc_buf_val)
{
Usb.getDevDescr(addr, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t * ) & desc_buf);
desc_buf_val = 1;
}
}
uint8_t send_usb(uint8_t *buf, uint8_t len)
{
Usb.bytesWr(rSNDFIFO, len, buf);
Usb.regWr(rSNDBC, len);
Usb.regWr(rHXFR, tokOUT);
while(!(Usb.regRd(rHIRQ) & bmHXFRDNIRQ));
Usb.regWr(rHIRQ, bmHXFRDNIRQ);
return (Usb.regRd(rHRSL) & 0x0f);
}
uint8_t respond_rcode()
{
if(rcode)
@@ -37,15 +58,6 @@ uint8_t respond_rcode()
else return 0;
}
uint8_t send_data(uint8_t *buf, uint8_t len)
{
Usb.bytesWr(rSNDFIFO, len, buf);
Usb.regWr(rSNDBC, len);
Usb.regWr(rHXFR, tokOUT);
while(!(Usb.regRd(rHIRQ) & bmHXFRDNIRQ));
Usb.regWr(rHIRQ, bmHXFRDNIRQ);
return (Usb.regRd(rHRSL) & 0x0f);
}
void setup()
{
@@ -65,13 +77,18 @@ void loop()
state = Usb.getUsbTaskState();
}
if(state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE)
{
desc_buf_val = 0;
}
if(Serial.available() > 0)
{
cmd = (char) Serial.read();
switch(cmd)
{
case PROT_PARTIAL_CTRL_XFER:
recv_args((uint8_t *) &usb_args, sizeof(struct usb_xfer_args));
recv_serial((uint8_t * ) & usb_args, sizeof(struct usb_xfer_args));
Serial.write(PROT_ACK);
rcode = Usb.ctrlReq_SETUP(addr, 0,
@@ -95,7 +112,7 @@ void loop()
break;
case PROT_NO_ERROR_CTRL_XFER:
recv_args((uint8_t *) &usb_args, sizeof(struct usb_xfer_args));
recv_serial((uint8_t * ) & usb_args, sizeof(struct usb_xfer_args));
Serial.write(PROT_ACK);
rcode = Usb.ctrlReq_SETUP(addr, 0,
@@ -105,7 +122,6 @@ void loop()
(usb_args.wValue >> 8u) & 0xFFu,
usb_args.wIndex,
usb_args.data_len);
respond_rcode();
if(usb_args.bmRequestType & 0x80u)
{
@@ -114,12 +130,11 @@ void loop()
}
else rcode = Usb.dispatchPkt(tokOUTHS, 0, 0);
respond_rcode();
Serial.write(PROT_SUCCESS);
break;
case PROT_NO_ERROR_CTRL_XFER_DATA:
recv_args((uint8_t *) &usb_args, sizeof(struct usb_xfer_args));
recv_serial((uint8_t * ) & usb_args, sizeof(struct usb_xfer_args));
Serial.write(PROT_ACK);
rcode = Usb.ctrlReq_SETUP(addr, 0,
@@ -129,11 +144,8 @@ void loop()
(usb_args.wValue >> 8u) & 0xFFu,
usb_args.wIndex,
usb_args.data_len);
respond_rcode();
Usb.regWr(rHCTL, bmSNDTOG0);
rcode = send_data(usb_data_buf, 0);
respond_rcode();
rcode = send_usb(usb_data_buf, 0);
chunk_i = 0;
while(chunk_i < usb_args.data_len)
@@ -141,7 +153,7 @@ void loop()
if(usb_args.data_len - chunk_i > ARD_BUF_SIZE) chunk_size = ARD_BUF_SIZE;
else chunk_size = usb_args.data_len - chunk_i;
recv_args(usb_data_buf, chunk_size);
recv_serial(usb_data_buf, chunk_size);
Serial.write(PROT_ACK);
// i is the current data index
@@ -151,8 +163,7 @@ void loop()
if(chunk_size - i > 64) size = 64;
else size = chunk_size - i;
rcode = send_data(&usb_data_buf[i], size);
respond_rcode();
rcode = send_usb(&usb_data_buf[i], size);
i += size;
}
@@ -162,22 +173,89 @@ void loop()
Serial.write(PROT_SUCCESS);
break;
// case PROT_CTRL_XFER:
// recv_args((uint8_t *) &usb_args, sizeof(struct usb_xfer_args));
// if(receive_data_and_respond()) break;
//
// rcode = Usb.ctrlReq(addr, 0,
// usb_args.bmRequestType,
// usb_args.bRequest,
// usb_args.wValue & 0xFFu,
// (usb_args.wValue >> 8u) & 0xFFu,
// usb_args.wIndex,
// usb_args.data_len, usb_args.data_len,
// usb_data_buf, NULL);
// if(respond_rcode()) break;
//
// Serial.write(PROT_SUCCESS);
// break;
case PROT_CTRL_XFER:
recv_serial((uint8_t * ) & usb_args, sizeof(struct usb_xfer_args));
Serial.write(PROT_ACK);
get_dev_descriptor();
rcode = Usb.ctrlReq_SETUP(addr, 0,
usb_args.bmRequestType,
usb_args.bRequest,
usb_args.wValue & 0xFFu,
(usb_args.wValue >> 8u) & 0xFFu,
usb_args.wIndex,
usb_args.data_len);
if(usb_args.bmRequestType & 0x80u)
{
i = 0;
Usb.regWr(rHCTL, bmRCVTOG1);
while(i < usb_args.data_len)
{
Usb.regWr(rHXFR, tokIN);
while(!(Usb.regRd(rHIRQ) & bmHXFRDNIRQ));
Usb.regWr(rHIRQ, bmHXFRDNIRQ);
if(Usb.regRd(rHIRQ) & bmRCVDAVIRQ)
{
size = Usb.regRd(rRCVBC);
Usb.bytesRd(rRCVFIFO, size, usb_data_buf);
Usb.regWr(rHIRQ, bmRCVDAVIRQ);
Serial.write(size);
Serial.write(usb_data_buf, size);
i += size;
if(size != desc_buf.bMaxPacketSize0) break;
}
else
{
rcode = (Usb.regRd(rHRSL) & 0x0f);
if(rcode == hrNAK) continue;
Serial.write(PROT_FAIL_USB);
Serial.write(rcode);
break;
}
}
Usb.regWr(rHXFR, tokOUTHS);
Serial.write(PROT_SUCCESS);
break;
}
else
{
chunk_i = 0;
Usb.regWr(rHCTL, bmSNDTOG0);
rcode = send_usb(usb_data_buf, 0);
while(chunk_i < usb_args.data_len)
{
if(usb_args.data_len - chunk_i > ARD_BUF_SIZE) chunk_size = ARD_BUF_SIZE;
else chunk_size = usb_args.data_len - chunk_i;
recv_serial(usb_data_buf, chunk_size);
Serial.write(PROT_ACK);
i = 0;
while(i < chunk_size)
{
if(chunk_size - i > desc_buf.bMaxPacketSize0) size = desc_buf.bMaxPacketSize0;
else size = chunk_size - i;
rcode = send_usb(&usb_data_buf[i], size);
i += size;
}
chunk_i += chunk_size;
}
Usb.regWr(rHXFR, tokINHS);
Serial.write(PROT_SUCCESS);
break;
}
case PROT_RESET:
Serial.write(PROT_ACK);
@@ -189,7 +267,7 @@ void loop()
break;
case PROT_SERIAL_DESC:
recv_args((uint8_t *) &sd_args, sizeof(struct serial_desc_args));
recv_serial((uint8_t * ) & sd_args, sizeof(struct serial_desc_args));
Serial.write(PROT_ACK);
state = Usb.getUsbTaskState();
@@ -199,7 +277,7 @@ void loop()
break;
}
Usb.getDevDescr(addr, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t *) &desc_buf);
get_dev_descriptor();
if(desc_buf.idVendor != sd_args.dev_idVendor ||
desc_buf.idProduct != sd_args.dev_idProduct)
{

View File

@@ -8,7 +8,7 @@ add_executable(checkm8_remote main.c src/usb_helpers.c src/exploit.c src/payload
add_custom_command(TARGET checkm8_remote POST_BUILD
COMMAND ln
ARGS -s -f -n
${PROJECT_SOURCE_DIR}/checkm8_payloads/bin
${CMAKE_SOURCE_DIR}/checkm8_payloads/bin
${CMAKE_CURRENT_SOURCE_DIR}/bin/payloads)
target_link_libraries(checkm8_remote checkm8_libusb pthread udev)

View File

@@ -40,55 +40,55 @@ int main()
{
int ret;
struct pwned_device *dev = exploit_device();
// if(dev == NULL || dev->status == DEV_NORMAL)
// {
// printf("Failed to exploit device\n");
// return -1;
// }
//
// struct dev_cmd_resp *resp;
// ret = install_payload(dev, PAYLOAD_SYNC, DRAM);
// if(IS_CHECKM8_FAIL(ret))
// {
// printf("Failed to install sync payload\n");
// return -1;
// }
//
// ret = install_payload(dev, PAYLOAD_AES, DRAM);
// if(IS_CHECKM8_FAIL(ret))
// {
// printf("Failed to install AES payload\n");
// return -1;
// }
//
// resp = execute_payload(dev, PAYLOAD_SYNC, 0);
// if(IS_CHECKM8_FAIL(resp->ret))
// {
// printf("Failed to execute sync payload\n");
// return -1;
// }
//
// unsigned char data[16] = {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe,
// 0xef};
// unsigned char key[16] = {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe,
// 0xef};
//
// free_dev_cmd_resp(resp);
// resp = write_payload(dev, 0x180152000, data, 16);
// if(IS_CHECKM8_FAIL(resp->ret))
// {
// printf("Failed to write AES data\n");
// return -1;
// }
//
// free_dev_cmd_resp(resp);
// resp = write_payload(dev, 0x180152010, key, 16);
// if(IS_CHECKM8_FAIL(resp->ret))
// {
// printf("Failed to write AES key\n");
// return -1;
// }
//
if(dev == NULL || dev->status == DEV_NORMAL)
{
printf("Failed to exploit device\n");
return -1;
}
struct dev_cmd_resp *resp;
ret = install_payload(dev, PAYLOAD_SYNC, DRAM);
if(IS_CHECKM8_FAIL(ret))
{
printf("Failed to install sync payload\n");
return -1;
}
ret = install_payload(dev, PAYLOAD_AES, DRAM);
if(IS_CHECKM8_FAIL(ret))
{
printf("Failed to install AES payload\n");
return -1;
}
resp = execute_payload(dev, PAYLOAD_SYNC, 0);
if(IS_CHECKM8_FAIL(resp->ret))
{
printf("Failed to execute sync payload\n");
return -1;
}
unsigned char data[16] = {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe,
0xef};
unsigned char key[16] = {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe,
0xef};
free_dev_cmd_resp(resp);
resp = write_payload(dev, 0x180152000, data, 16);
if(IS_CHECKM8_FAIL(resp->ret))
{
printf("Failed to write AES data\n");
return -1;
}
free_dev_cmd_resp(resp);
resp = write_payload(dev, 0x180152010, key, 16);
if(IS_CHECKM8_FAIL(resp->ret))
{
printf("Failed to write AES key\n");
return -1;
}
// free_dev_cmd_resp(resp);
// resp = execute_payload(dev, PAYLOAD_AES, 7, 16, 0x180152000, DFU_IMAGE_BASE + 56, 128, 0, 0x180152010, 0);
//
@@ -97,7 +97,7 @@ int main()
// printf("Failed to execute AES\n");
// return -1;
// }
//
// free_dev_cmd_resp(resp);
// free_device(dev);
free_dev_cmd_resp(resp);
free_device(dev);
}

View File

@@ -29,7 +29,7 @@ int dfu_send_data(struct pwned_device *dev, unsigned char *data, long data_len)
if(ret > 0) checkm8_debug_indent("\ttransferred %i bytes\n", ret);
else
{
checkm8_debug_indent("\trequest failed with error code %i (%s)\n", ret, libusb_error_name(ret));
checkm8_debug_indent("\trequest failed with error code %i\n", ret);
return CHECKM8_FAIL_XFER;
}
index += amount;
@@ -67,7 +67,7 @@ struct dev_cmd_resp *command(struct pwned_device *dev,
if(ret >= 0) checkm8_debug_indent("\ttransferred %i bytes\n", ret);
else
{
checkm8_debug_indent("\trequest failed with error code %i (%s)\n", ret, libusb_error_name(ret));
checkm8_debug_indent("\trequest failed with error code %i\n", ret);
cmd_resp->ret = ret;
return cmd_resp;
}
@@ -76,7 +76,7 @@ struct dev_cmd_resp *command(struct pwned_device *dev,
if(ret >= 0) checkm8_debug_indent("\ttransferred %i bytes\n", ret);
else
{
checkm8_debug_indent("\trequest failed with error code %i (%s)\n", ret, libusb_error_name(ret));
checkm8_debug_indent("\trequest failed with error code %i\n", ret);
cmd_resp->ret = ret;
return cmd_resp;
}
@@ -85,7 +85,7 @@ struct dev_cmd_resp *command(struct pwned_device *dev,
if(ret >= 0) checkm8_debug_indent("\ttransferred %i bytes\n", ret);
else
{
checkm8_debug_indent("\trequest failed with error code %i (%s)\n", ret, libusb_error_name(ret));
checkm8_debug_indent("\trequest failed with error code %i\n", ret);
cmd_resp->ret = ret;
return cmd_resp;
}
@@ -106,7 +106,7 @@ struct dev_cmd_resp *command(struct pwned_device *dev,
if(ret >= 0) checkm8_debug_indent("\tfinal request transferred %i bytes\n", ret);
else
{
checkm8_debug_indent("\tfinal request failed with error code %i (%s)\n", ret, libusb_error_name(ret));
checkm8_debug_indent("\tfinal request failed with error code %i\n", ret);
cmd_resp->ret = ret;
return cmd_resp;
}
@@ -120,7 +120,7 @@ struct dev_cmd_resp *command(struct pwned_device *dev,
if(ret >= 0) checkm8_debug_indent("\tfinal request transferred %i bytes\n", ret);
else
{
checkm8_debug_indent("\tfinal request failed with error code %i (%s)\n", ret, libusb_error_name(ret));
checkm8_debug_indent("\tfinal request failed with error code %i\n", ret);
cmd_resp->ret = ret;
return cmd_resp;
}

View File

@@ -43,6 +43,7 @@ struct payload *get_payload(PAYLOAD_T p)
return NULL;
}
checkm8_debug_indent("get_payload(p = %i) -> %s\n", p, path);
res = malloc(sizeof(struct payload));
if(res == NULL) return NULL;
@@ -131,12 +132,16 @@ int *dev_unlink_payload(struct pwned_device *dev, struct payload *pl)
int install_payload(struct pwned_device *dev, PAYLOAD_T p, LOCATION_T loc)
{
checkm8_debug_indent("install_payload(dev = %p, p = %i, loc = %i)\n", dev, p, loc);
int i, ret;
int ret;
struct dev_cmd_resp *resp = NULL;
struct payload *pl = get_payload(p);
long long addr = get_address(dev, loc);
if(pl == NULL || addr == -1) return CHECKM8_FAIL_INVARGS;
if(pl == NULL || addr == -1)
{
checkm8_debug_indent("\tinvalid args (either payload or address)\n");
return CHECKM8_FAIL_INVARGS;
}
ret = open_device_session(dev);
if(IS_CHECKM8_FAIL(ret)) return ret;
@@ -161,6 +166,7 @@ int install_payload(struct pwned_device *dev, PAYLOAD_T p, LOCATION_T loc)
int uninstall_payload(struct pwned_device *dev, PAYLOAD_T p)
{
//TODO: free memory in memory allocator
return CHECKM8_SUCCESS;
}
struct dev_cmd_resp *execute_payload(struct pwned_device *dev, PAYLOAD_T p, int nargs, ...)

View File

@@ -1,7 +1,5 @@
#include "usb_helpers.h"
#include <string.h>
#ifdef WITH_ARDUINO
#include <termio.h>
@@ -12,6 +10,7 @@
#else
#include <stdlib.h>
#include <string.h>
#include "libusbi.h"
#endif
@@ -401,7 +400,8 @@ int no_error_ctrl_transfer(struct pwned_device *dev,
}
}
ret = libusb_control_transfer(dev->bundle->handle, bmRequestType, bRequest, wValue, wIndex, data, data_len, timeout);
ret = libusb_control_transfer(dev->bundle->handle, bmRequestType, bRequest, wValue, wIndex, data, data_len,
timeout);
checkm8_debug_indent("\tgot error %s but ignoring\n", libusb_error_name(ret));
return CHECKM8_SUCCESS;
#endif
@@ -434,7 +434,6 @@ int no_error_ctrl_transfer_data(struct pwned_device *dev,
if(buf == PROT_ACK)
{
checkm8_debug_indent("\treceived argument ack\n");
while(index < data_len)
{
if(data_len - index > ARD_BUF_SIZE) amount = ARD_BUF_SIZE;
@@ -442,19 +441,18 @@ int no_error_ctrl_transfer_data(struct pwned_device *dev,
checkm8_debug_indent("\twriting data chunk of size %i\n", amount);
write(dev->ard_fd, &data[index], amount);
do
while(read(dev->ard_fd, &buf, 1) == 0);
if(buf == PROT_ACK)
{
if(buf == PROT_FAIL_USB)
{
while(read(dev->ard_fd, &buf, 1) == 0);
checkm8_debug_indent("\treceived error %X but ignoring\n", buf);
}
while(read(dev->ard_fd, &buf, 1) == 0);
} while(buf != PROT_ACK);
checkm8_debug_indent("\treceived data ack\n");
index += amount;
checkm8_debug_indent("\treceived data ack\n");
index += amount;
}
else
{
checkm8_debug_indent("\treceived unexpected response %x\n", buf);
return CHECKM8_FAIL_PROT;
}
}
while(read(dev->ard_fd, &buf, 1) == 0);
@@ -463,6 +461,11 @@ int no_error_ctrl_transfer_data(struct pwned_device *dev,
checkm8_debug_indent("\tsuccess\n");
return CHECKM8_SUCCESS;
}
else
{
checkm8_debug_indent("\tunexpected response %x\n", buf);
return CHECKM8_FAIL_PROT;
}
}
else
{
@@ -481,10 +484,11 @@ int ctrl_transfer(struct pwned_device *dev,
unsigned int timeout)
{
checkm8_debug_indent(
"ctrl_transfer(dev = %p, bmRequestType = %i, bRequest = %i, wValue = %i, wIndex = %i, data = %p, data_len = %i, timeout = %i)\n",
"ctrl_transfer(dev = %p, bmRequestType = %X, bRequest = %X, wValue = %i, wIndex = %i, data = %p, data_len = %i, timeout = %i)\n",
dev, bmRequestType, bRequest, wValue, wIndex, data, data_len, timeout);
#ifdef WITH_ARDUINO
int amount, index;
char buf;
struct usb_xfer_args args;
args.bmRequestType = bmRequestType;
@@ -496,32 +500,63 @@ int ctrl_transfer(struct pwned_device *dev,
checkm8_debug_indent("\tsending data to arduino\n");
write(dev->ard_fd, &PROT_CTRL_XFER, 1);
write(dev->ard_fd, &args, sizeof(struct usb_xfer_args));
write(dev->ard_fd, data, data_len);
while(read(dev->ard_fd, &buf, 1) == 0);
if(buf == PROT_ACK)
{
checkm8_debug_indent("\treceived ack\n");
checkm8_debug_indent("\treceived argument ack\n");
if(bmRequestType & 0x80)
{
amount = 0;
while(amount < data_len)
{
// get the size of this chunk
while(read(dev->ard_fd, &buf, 1) == 0);
checkm8_debug_indent("\treceiving data chunk of size %i\n", buf);
while(read(dev->ard_fd, &buf, 1) == 0);
if(buf == PROT_FAIL_TOOBIG)
{
checkm8_debug_indent("\tdata packet is too big\n");
return CHECKM8_FAIL_INVARGS;
}
else if(buf == PROT_FAIL_USB)
{
while(read(dev->ard_fd, &buf, 1) == 0);
checkm8_debug_indent("\tUSB failed with error %x\n", buf);
}
else if(buf == PROT_SUCCESS)
{
checkm8_debug_indent("\tsuccess\n");
return CHECKM8_SUCCESS;
index = 0;
while(index < buf)
{
index += read(dev->ard_fd, &data[amount + index], buf - index);
}
amount += buf;
}
}
else
{
checkm8_debug_indent("\tunexpected response %X\n", buf);
index = 0;
while(index < data_len)
{
if(data_len - index > ARD_BUF_SIZE) amount = ARD_BUF_SIZE;
else amount = data_len - index;
checkm8_debug_indent("\twriting data chunk of size %i\n", amount);
write(dev->ard_fd, &data[index], amount);
while(read(dev->ard_fd, &buf, 1) == 0);
if(buf == PROT_ACK)
{
checkm8_debug_indent("\treceived data ack\n");
index += amount;
}
else
{
checkm8_debug_indent("\treceived unexpected response %x\n", buf);
return CHECKM8_FAIL_PROT;
}
}
}
while(read(dev->ard_fd, &buf, 1) == 0);
if(buf == PROT_SUCCESS)
{
checkm8_debug_indent("\tsuccess\n");
return data_len;
}
else
{
checkm8_debug_indent("\tunexpected response %x\n", buf);
return CHECKM8_FAIL_PROT;
}
}