added: mem spiffs view - to view a file on SPIFFS\n mem spiffs dump - now uses cliparser and NG

This commit is contained in:
iceman1001
2021-03-09 14:38:31 +01:00
parent a8f74b54ea
commit ad2b0879fc
11 changed files with 263 additions and 270 deletions

View File

@@ -17,55 +17,7 @@
static int CmdHelp(const char *Cmd);
static int usage_flashmemspiffs_copy(void) {
PrintAndLogEx(NORMAL, "Copy a file to another (destructively) in spiffs filesystem\n");
PrintAndLogEx(NORMAL, "Usage: mem spiffs copy <source> <destination>");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs copy lasttag.bin lasttag_cpy.bin"));
return PM3_SUCCESS;
}
static int usage_flashmemspiffs_dump(void) {
PrintAndLogEx(NORMAL, "Dumps flash memory on device into a file or in console");
PrintAndLogEx(NORMAL, "Size is handled by first sending a STAT command against file existence\n");
PrintAndLogEx(NORMAL, "Usage: mem spiffs dump o <filename> [f <file name> [e]] [p]");
PrintAndLogEx(NORMAL, " o <filename> - filename in SPIFFS");
PrintAndLogEx(NORMAL, " f <filename> - file name to save to <w/o .bin>");
PrintAndLogEx(NORMAL, " p - print dump in console");
PrintAndLogEx(NORMAL, " e - also save in EML format (good for tags save and dictonnary files)");
PrintAndLogEx(NORMAL, " You must specify at lease option f or option p, both if you wish");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs dump o lasttag.bin f lasttag e"));
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs dump o lasttag.bin p"));
return PM3_SUCCESS;
}
static int usage_flashmemspiffs_load(void) {
PrintAndLogEx(NORMAL, "Uploads binary-wise file into device filesystem");
PrintAndLogEx(NORMAL, "Warning: mem area to be written must have been wiped first");
PrintAndLogEx(NORMAL, "(this is already taken care when loading dictionaries)\n");
PrintAndLogEx(NORMAL, "Usage: mem spiffs load o <filename> f <filename>");
PrintAndLogEx(NORMAL, " o <filename> - destination filename");
PrintAndLogEx(NORMAL, " f <filename> - local filename");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs load f myfile o myapp.conf"));
return PM3_SUCCESS;
}
static int usage_flashmemspiffs_wipe(void) {
PrintAndLogEx(NORMAL, "wipes all files on the device filesystem " _RED_("* Warning *"));
PrintAndLogEx(NORMAL, "Usage: mem spiffs wipe [h]");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs wipe"));
return PM3_SUCCESS;
}
int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) {
int flashmem_spiffs_load(char *destfn, uint8_t *data, size_t datalen) {
int ret_val = PM3_SUCCESS;
@@ -76,33 +28,35 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) {
// Send to device
uint32_t bytes_sent = 0;
uint32_t bytes_remaining = datalen;
uint32_t append = 0;
// fast push mode
conn.block_after_ACK = true;
while (bytes_remaining > 0) {
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
flashmem_write_t *payload = calloc(1, sizeof(flashmem_write_t) + bytes_in_packet);
payload->append = (bytes_sent > 0);
payload->fnlen = strlen(destfn);
memcpy(payload->fn, destfn, strlen(destfn));
payload->bytes_in_packet = bytes_in_packet;
memset(payload->data, 0, bytes_in_packet);
memcpy(payload->data, data + bytes_sent, bytes_in_packet);
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_SPIFFS_WRITE, (uint8_t *)payload, sizeof(flashmem_write_t) + bytes_in_packet);
char fdata[32 + bytes_in_packet];
memset(fdata, 0, sizeof(fdata));
memcpy(fdata, destfn, 32);
memcpy(fdata + 32, data + bytes_sent, bytes_in_packet);
if (bytes_sent > 0)
append = 1;
SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet);
free(payload);
bytes_remaining -= bytes_in_packet;
bytes_sent += bytes_in_packet;
PacketResponseNG resp;
uint8_t retry = 3;
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
while (WaitForResponseTimeout(CMD_SPIFFS_WRITE, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
retry--;
if (retry == 0) {
@@ -110,13 +64,6 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) {
goto out;
}
}
uint8_t isok = resp.oldarg[0] & 0xFF;
if (!isok) {
PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent);
ret_val = PM3_EFLASH;
break;
}
}
out:
@@ -128,7 +75,6 @@ out:
// We want to unmount after these to set things back to normal but more than this
// unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory
SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0);
return ret_val;
}
@@ -321,246 +267,273 @@ static int CmdFlashMemSpiFFSRename(const char *Cmd) {
}
static int CmdFlashMemSpiFFSCopy(const char *Cmd) {
int len = strlen(Cmd);
if (len < 1) {
return usage_flashmemspiffs_copy();
}
char ctmp = tolower(param_getchar(Cmd, 0));
if (len == 1 && ctmp == 'h') {
return usage_flashmemspiffs_copy();
}
CLIParserContext *ctx;
CLIParserInit(&ctx, "mem spiffs copy",
"Copy a file to another (destructively) in SPIFFS file system",
"mem spiffs copy -s aaa.bin -d aaa_cpy.bin"
);
void *argtable[] = {
arg_param_begin,
arg_str1("s", "src", "<fn>", "source file name"),
arg_str1("d", "dest", "<fn>", "destination file name"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
char srcfilename[32] = {0};
char destfilename[32] = {0};
bool errors = false;
int slen = 0;
char src[32] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen);
if (param_getstr(Cmd, 0, srcfilename, 32) >= 32) {
PrintAndLogEx(FAILED, "Source Filename too long");
errors = true;
}
if (srcfilename[0] == '\0') {
PrintAndLogEx(FAILED, "Source Filename missing or invalid");
errors = true;
}
int dlen = 0;
char dest[32] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, 32, &dlen);
CLIParserFree(ctx);
if (param_getstr(Cmd, 1, destfilename, 32) >= 32) {
PrintAndLogEx(FAILED, "Source Filename too long");
errors = true;
}
if (destfilename[0] == '\0') {
PrintAndLogEx(FAILED, "Source Filename missing or invalid");
errors = true;
}
struct {
uint8_t slen;
uint8_t src[32];
uint8_t dlen;
uint8_t dest[32];
} PACKED payload;
payload.slen = slen;
payload.dlen = dlen;
// check null filename ?
if (errors) {
usage_flashmemspiffs_copy();
return PM3_EINVARG;
}
memcpy(payload.src, src, slen);
memcpy(payload.dest, dest, dlen);
char data[65];
sprintf(data, "%s,%s", srcfilename, destfilename);
SendCommandMIX(CMD_SPIFFS_COPY, 0, 0, 0, (uint8_t *)data, 65);
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_SPIFFS_COPY, (uint8_t *)&payload, sizeof(payload));
WaitForResponse(CMD_SPIFFS_COPY, &resp);
if (resp.status == PM3_SUCCESS)
PrintAndLogEx(INFO, "Done!");
PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify");
return PM3_SUCCESS;
}
static int CmdFlashMemSpiFFSDump(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "mem spiffs dump",
"Dumps device SPIFFS file to a local file\n"
"Size is handled by first sending a STAT command against file to verify existence",
"mem spiffs dump -s tag.bin --> download binary file from device\n"
"mem spiffs dump -s tag.bin -d aaa -e --> download tag.bin, save as aaa.eml format"
);
char filename[FILE_PATH_SIZE] = {0};
uint8_t cmdp = 0;
bool errors = false;
bool print = false;
uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE;
char destfilename[32] = {0};
bool eml = false;
void *argtable[] = {
arg_param_begin,
arg_str1("s", "src", "<fn>", "SPIFFS file to save"),
arg_str0("d", "dest", "<fn>", "file name to save to <w/o .bin>"),
arg_lit0("e", "eml", "also save in EML format"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_flashmemspiffs_dump();
/*case 'l':
len = param_get32ex(Cmd, cmdp + 1, FLASH_MEM_MAX_SIZE, 10);
cmdp += 2;
break;*/
case 'o':
param_getstr(Cmd, cmdp + 1, destfilename, 32);
cmdp += 2;
break;
case 'p':
print = true;
cmdp += 1;
break;
case 'e':
eml = true;
cmdp += 1;
break;
case 'f':
// File handling
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
PrintAndLogEx(FAILED, "Filename too long");
errors = true;
break;
}
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
int slen = 0;
char src[32] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen);
if ((filename[0] == '\0') && (!print)) {
PrintAndLogEx(FAILED, "No print asked and local dump filename missing or invalid");
errors = true;
}
int dlen = 0;
char dest[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, FILE_PATH_SIZE, &dlen);
if (destfilename[0] == '\0') {
PrintAndLogEx(FAILED, "SPIFFS filename missing or invalid");
errors = true;
}
// Validations
if (errors || cmdp == 0) {
usage_flashmemspiffs_dump();
return PM3_EINVARG;
}
bool eml = arg_get_lit(ctx, 3);
CLIParserFree(ctx);
// get size from spiffs itself !
SendCommandMIX(CMD_SPIFFS_STAT, 0, 0, 0, (uint8_t *)destfilename, 32);
clearCommandBuffer();
SendCommandNG(CMD_SPIFFS_STAT, (uint8_t *)src, slen);
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
if (WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
len = resp.oldarg[0];
uint32_t len = resp.data.asDwords[0];
uint8_t *dump = calloc(len, sizeof(uint8_t));
if (!dump) {
PrintAndLogEx(ERR, "error, cannot allocate memory ");
return PM3_EMALLOC;
}
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from spiffs (flashmem)", len);
if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)destfilename, 32, NULL, -1, true)) {
PrintAndLogEx(FAILED, "ERROR; downloading from spiffs(flashmemory)");
// download from device
uint32_t start_index = 0;
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from `" _YELLOW_("%s") "` (spiffs)", len, src);
if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)src, slen, NULL, -1, true)) {
PrintAndLogEx(FAILED, "error, downloading from spiffs");
free(dump);
return PM3_EFLASH;
}
if (print) {
print_hex_break(dump, len, 32);
// save to file
char fn[FILE_PATH_SIZE] = {0};
if (dlen == 0) {
strncpy(fn, src, slen);
} else {
strncpy(fn, dest, dlen);
}
if (filename[0] != '\0') {
saveFile(filename, ".bin", dump, len);
if (eml) {
uint8_t eml_len = 16;
saveFile(fn, ".bin", dump, len);
if (eml) {
uint8_t eml_len = 16;
if (strstr(fn, "class") != NULL)
eml_len = 8;
else if (strstr(fn, "mfu") != NULL)
eml_len = 4;
if (strstr(filename, "class") != NULL)
eml_len = 8;
else if (strstr(filename, "mfu") != NULL)
eml_len = 4;
saveFileEML(filename, dump, len, eml_len);
}
saveFileEML(fn, dump, len, eml_len);
}
free(dump);
return PM3_SUCCESS;
}
static int CmdFlashMemSpiFFSWipe(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "mem spiffs wipe",
_RED_("* * * Warning * * *") " \n"
_CYAN_("This command wipes all files on the device SPIFFS file system"),
"mem spiffs wipe");
char ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'h') {
return usage_flashmemspiffs_wipe();
}
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
PrintAndLogEx(INFO, "Wiping all files from SPIFFS FileSystem");
PrintAndLogEx(INFO, "Wiping all files from SPIFFS file system");
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_SPIFFS_WIPE, NULL, 0);
WaitForResponse(CMD_SPIFFS_WIPE, &resp);
PrintAndLogEx(INFO, "Done!");
if (resp.status == PM3_SUCCESS)
PrintAndLogEx(INFO, "Done!");
PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify");
return PM3_SUCCESS;
}
static int CmdFlashMemSpiFFSLoad(const char *Cmd) {
static int CmdFlashMemSpiFFSUpload(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "mem spiffs upload",
"Uploads binary-wise file into device file system\n"
"Warning: mem area to be written must have been wiped first.\n"
"This is already taken care when loading dictionaries.\n"
"File names can only be 32 bytes long on device SPIFFS",
"mem spiffs upload -s local.bin -d dest.bin"
);
char filename[FILE_PATH_SIZE] = {0};
uint8_t destfilename[32] = {0};
bool errors = false;
uint8_t cmdp = 0;
void *argtable[] = {
arg_param_begin,
arg_str1("s", "src", "<fn>", "source file name"),
arg_str1("d", "dest", "<fn>", "destination file name"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_flashmemspiffs_load();
case 'f':
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
PrintAndLogEx(FAILED, "Filename too long");
errors = true;
}
cmdp += 2;
break;
case 'o':
param_getstr(Cmd, cmdp + 1, (char *)destfilename, 32);
if (strlen((char *)destfilename) == 0) {
PrintAndLogEx(FAILED, "Destination Filename missing or invalid");
errors = true;
}
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
int slen = 0;
char src[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, FILE_PATH_SIZE, &slen);
// Validations
if (errors || cmdp == 0)
return usage_flashmemspiffs_load();
int dlen = 0;
char dest[32] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, 32, &dlen);
CLIParserFree(ctx);
PrintAndLogEx(DEBUG, "Upload `" _YELLOW_("%s") "` -> `" _YELLOW_("%s") "`", src, dest);
size_t datalen = 0;
uint8_t *data = NULL;
int res = loadFile_safe(filename, "", (void **)&data, &datalen);
// int res = loadFileEML( filename, data, &datalen);
int res = loadFile_safe(src, "", (void **)&data, &datalen);
if (res != PM3_SUCCESS) {
free(data);
return PM3_EFILE;
}
res = flashmem_spiffs_load(destfilename, data, datalen);
res = flashmem_spiffs_load(dest, data, datalen);
free(data);
if (res == PM3_SUCCESS)
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") " bytes to file "_GREEN_("%s"), datalen, destfilename);
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") " bytes to file "_GREEN_("%s"), datalen, dest);
PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify");
return res;
}
static int CmdFlashMemSpiFFSView(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "mem spiffs view",
"View a file on flash memory on devicer in console",
"mem spiffs view -f tag.bin"
);
void *argtable[] = {
arg_param_begin,
arg_str1("f", "file", "<fn>", "SPIFFS file to view"),
arg_int0("c", "cols", "<dec>", "column breaks (def 32)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int slen = 0;
char src[32] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen);
int breaks = arg_get_int_def(ctx, 2, 32);
CLIParserFree(ctx);
// get size from spiffs itself !
clearCommandBuffer();
SendCommandNG(CMD_SPIFFS_STAT, (uint8_t *)src, slen);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
uint32_t len = resp.data.asDwords[0];
uint8_t *dump = calloc(len, sizeof(uint8_t));
if (!dump) {
PrintAndLogEx(ERR, "error, cannot allocate memory ");
return PM3_EMALLOC;
}
uint32_t start_index = 0;
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from `" _YELLOW_("%s") "` (spiffs)", len, src);
if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)src, slen, NULL, -1, true)) {
PrintAndLogEx(FAILED, "error, downloading from spiffs");
free(dump);
return PM3_EFLASH;
}
PrintAndLogEx(NORMAL, "");
print_hex_break(dump, len, breaks);
PrintAndLogEx(NORMAL, "");
free(dump);
return PM3_SUCCESS;
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS file system"},
{"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented file system"},
{"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS file system"},
{"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "Print file system info and usage statistics"},
{"load", CmdFlashMemSpiFFSLoad, IfPm3Flash, "Upload file into SPIFFS file system"},
{"mount", CmdFlashMemSpiFFSMount, IfPm3Flash, "Mount the SPIFFS file system if not already mounted"},
{"remove", CmdFlashMemSpiFFSRemove, IfPm3Flash, "Remove a file from SPIFFS file system"},
{"rename", CmdFlashMemSpiFFSRename, IfPm3Flash, "Rename/move a file in SPIFFS file system"},
{"test", CmdFlashMemSpiFFSTest, IfPm3Flash, "Test SPIFFS Operations"},
{"tree", CmdFlashMemSpiFFSTree, IfPm3Flash, "Print the Flash memory file system tree"},
{"unmount", CmdFlashMemSpiFFSUnmount, IfPm3Flash, "Un-mount the SPIFFS file system"},
{"wipe", CmdFlashMemSpiFFSWipe, IfPm3Flash, "Wipe all files from SPIFFS file system. * " _RED_("dangerous") " *" },
{"upload", CmdFlashMemSpiFFSUpload, IfPm3Flash, "Upload file into SPIFFS file system"},
{"view", CmdFlashMemSpiFFSView, IfPm3Flash, "View file on SPIFFS file system"},
{"wipe", CmdFlashMemSpiFFSWipe, IfPm3Flash, "Wipe all files from SPIFFS file system * " _RED_("dangerous") " *" },
{NULL, NULL, NULL, NULL}
};