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
commit ad2b0879fc
11 changed files with 263 additions and 270 deletions

View file

@ -39,7 +39,7 @@
* *
* To delete a dump file from flash: * To delete a dump file from flash:
* *
* 1. mem spiffs remove hf-legic-XXYYZZWW-dump.bin * 1. mem spiffs remove -f hf-legic-XXYYZZWW-dump.bin
* *
*/ */

View file

@ -48,7 +48,7 @@
* *
* To delete the log file from flash: * To delete the log file from flash:
* *
* 1. mem spiffs remove lf_hidcollect.log * 1. mem spiffs remove -f lf_hidcollect.log
*/ */
#define LF_HIDCOLLECT_LOGFILE "lf_hidcollect.log" #define LF_HIDCOLLECT_LOGFILE "lf_hidcollect.log"

View file

@ -42,7 +42,7 @@
* - LED D: unmounting/sync'ing flash (normally < 100ms) * - LED D: unmounting/sync'ing flash (normally < 100ms)
* *
* To upload input file (eml format) to flash: * To upload input file (eml format) to flash:
* - mem spiffs load f <filename> o lf_em4x50_simulate.eml * - mem spiffs upload -s <filename> -d lf_em4x50_simulate.eml
* *
* To retrieve password file from flash: * To retrieve password file from flash:
* - mem spiffs dump o lf_em4x50_passwords.log f <filename> * - mem spiffs dump o lf_em4x50_passwords.log f <filename>
@ -54,13 +54,13 @@
* the lab connected to PM3 client before taking it into the field. * the lab connected to PM3 client before taking it into the field.
* *
* To delete the input file from flash: * To delete the input file from flash:
* - mem spiffs remove lf_em4x50_simulate.eml * - mem spiffs remove -f lf_em4x50_simulate.eml
* *
* To delete the log file from flash: * To delete the log file from flash:
* - mem spiffs remove lf_em4x50_passwords.log * - mem spiffs remove -f lf_em4x50_passwords.log
* *
* To delete the log file from flash: * To delete the log file from flash:
* - mem spiffs remove lf_em4x50_collect.log * - mem spiffs remove -f lf_em4x50_collect.log
*/ */
#define STATE_SIM 0 #define STATE_SIM 0
@ -77,7 +77,7 @@ static void LoadDataInstructions(const char *inputfile) {
Dbprintf("To load datafile to flash and display it:"); Dbprintf("To load datafile to flash and display it:");
Dbprintf("1. edit input file %s", inputfile); Dbprintf("1. edit input file %s", inputfile);
Dbprintf("2. start proxmark3 client"); Dbprintf("2. start proxmark3 client");
Dbprintf("3. mem spiffs load f <filename> o %s", inputfile); Dbprintf("3. mem spiffs upload -f <filename> o %s", inputfile);
Dbprintf("4. start standalone mode"); Dbprintf("4. start standalone mode");
} }

View file

@ -2078,7 +2078,7 @@ static void PacketReceived(PacketCommandNG *packet) {
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d) | result: %d", i, i + len, len, result); Dbprintf("transfer to client failed :: | bytes between %d - %d (%d) | result: %d", i, i + len, len, result);
} }
// Trigger a finish downloading signal with an ACK frame // Trigger a finish downloading signal with an ACK frame
reply_mix(CMD_ACK, 1, 0, 0, 0, 0); reply_ng(CMD_SPIFFS_DOWNLOAD, PM3_SUCCESS, NULL, 0);
LED_B_OFF(); LED_B_OFF();
break; break;
} }
@ -2087,11 +2087,17 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t filename[32]; uint8_t filename[32];
uint8_t *pfilename = packet->data.asBytes; uint8_t *pfilename = packet->data.asBytes;
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN); memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Filename received for spiffs STAT : %s", filename); if (DBGLEVEL >= DBG_DEBUG) {
Dbprintf("Filename received for spiffs STAT : %s", filename);
}
int changed = rdv40_spiffs_lazy_mount(); int changed = rdv40_spiffs_lazy_mount();
uint32_t size = size_in_spiffs((char *)filename); uint32_t size = size_in_spiffs((char *)filename);
if (changed) rdv40_spiffs_lazy_unmount(); if (changed) {
reply_mix(CMD_ACK, size, 0, 0, 0, 0); rdv40_spiffs_lazy_unmount();
}
reply_ng(CMD_SPIFFS_STAT, PM3_SUCCESS, (uint8_t *)&size, sizeof(uint32_t));
LED_B_OFF(); LED_B_OFF();
break; break;
} }
@ -2121,12 +2127,12 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t dlen; uint8_t dlen;
uint8_t dest[32]; uint8_t dest[32];
} PACKED; } PACKED;
struct p *payload = (struct p *) packet->data.asBytes; struct p *payload = (struct p *) packet->data.asBytes;
if (DBGLEVEL >= DBG_DEBUG) { if (DBGLEVEL >= DBG_DEBUG) {
Dbprintf("Filename received as source for spiffs RENAME : %s", payload->src); Dbprintf("SPIFFS RENAME");
Dbprintf("Filename received as destination for spiffs RENAME : %s", payload->dest); Dbprintf("Source........ %s", payload->src);
Dbprintf("Destination... %s", payload->dest);
} }
rdv40_spiffs_rename((char *)payload->src, (char *)payload->dest, RDV40_SPIFFS_SAFETY_SAFE); rdv40_spiffs_rename((char *)payload->src, (char *)payload->dest, RDV40_SPIFFS_SAFETY_SAFE);
reply_ng(CMD_SPIFFS_RENAME, PM3_SUCCESS, NULL, 0); reply_ng(CMD_SPIFFS_RENAME, PM3_SUCCESS, NULL, 0);
@ -2135,40 +2141,40 @@ static void PacketReceived(PacketCommandNG *packet) {
} }
case CMD_SPIFFS_COPY: { case CMD_SPIFFS_COPY: {
LED_B_ON(); LED_B_ON();
struct p {
uint8_t slen;
uint8_t src[32]; uint8_t src[32];
uint8_t dlen;
uint8_t dest[32]; uint8_t dest[32];
uint8_t *pfilename = packet->data.asBytes; } PACKED;
char *token; struct p *payload = (struct p *) packet->data.asBytes;
token = strtok((char *)pfilename, ",");
strncpy((char *)src, token, sizeof(src) - 1);
token = strtok(NULL, ",");
strncpy((char *)dest, token, sizeof(dest) - 1);
if (DBGLEVEL >= DBG_DEBUG) { if (DBGLEVEL >= DBG_DEBUG) {
Dbprintf("Filename received as source for spiffs COPY : %s", src); Dbprintf("SPIFFS COPY");
Dbprintf("Filename received as destination for spiffs COPY : %s", dest); Dbprintf("Source........ %s", payload->src);
Dbprintf("Destination... %s", payload->dest);
} }
rdv40_spiffs_copy((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE); rdv40_spiffs_copy((char *)payload->src, (char *)payload->dest, RDV40_SPIFFS_SAFETY_SAFE);
reply_ng(CMD_SPIFFS_COPY, PM3_SUCCESS, NULL, 0);
LED_B_OFF(); LED_B_OFF();
break; break;
} }
case CMD_SPIFFS_WRITE: { case CMD_SPIFFS_WRITE: {
LED_B_ON(); LED_B_ON();
uint8_t filename[32];
uint32_t append = packet->oldarg[0];
uint32_t size = packet->oldarg[1];
uint8_t *data = packet->data.asBytes;
uint8_t *pfilename = packet->data.asBytes;
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
data += SPIFFS_OBJ_NAME_LEN;
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("> Filename received for spiffs WRITE : %s with APPEND SET TO : %d", filename, append); flashmem_write_t *payload = (flashmem_write_t *)packet->data.asBytes;
if (!append) { if (DBGLEVEL >= DBG_DEBUG) {
rdv40_spiffs_write((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE); Dbprintf("SPIFFS WRITE, dest `%s` with APPEND set to: %c", payload->fn, payload->append ? 'Y' : 'N');
} else {
rdv40_spiffs_append((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE);
} }
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
if (payload->append) {
rdv40_spiffs_append((char *) payload->fn, payload->data, payload->bytes_in_packet, RDV40_SPIFFS_SAFETY_SAFE);
} else {
rdv40_spiffs_write((char *) payload->fn, payload->data, payload->bytes_in_packet, RDV40_SPIFFS_SAFETY_SAFE);
}
reply_ng(CMD_SPIFFS_WRITE, PM3_SUCCESS, NULL, 0);
LED_B_OFF(); LED_B_OFF();
break; break;
} }

View file

@ -76,7 +76,7 @@ local function main(args)
if removeflag then if removeflag then
print('Deleting file '..filename.. ' from SPIFFS if exists') print('Deleting file '..filename.. ' from SPIFFS if exists')
core.console("mem spiffs remove " ..filename) core.console("mem spiffs remove -f " ..filename)
return return
end end

View file

@ -17,55 +17,7 @@
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static int usage_flashmemspiffs_copy(void) { int flashmem_spiffs_load(char *destfn, uint8_t *data, size_t datalen) {
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 ret_val = PM3_SUCCESS; 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 // Send to device
uint32_t bytes_sent = 0; uint32_t bytes_sent = 0;
uint32_t bytes_remaining = datalen; uint32_t bytes_remaining = datalen;
uint32_t append = 0;
// fast push mode // fast push mode
conn.block_after_ACK = true; conn.block_after_ACK = true;
while (bytes_remaining > 0) { while (bytes_remaining > 0) {
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); 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(); clearCommandBuffer();
SendCommandNG(CMD_SPIFFS_WRITE, (uint8_t *)payload, sizeof(flashmem_write_t) + bytes_in_packet);
char fdata[32 + bytes_in_packet]; free(payload);
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);
bytes_remaining -= bytes_in_packet; bytes_remaining -= bytes_in_packet;
bytes_sent += bytes_in_packet; bytes_sent += bytes_in_packet;
PacketResponseNG resp;
uint8_t retry = 3; 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."); PrintAndLogEx(WARNING, "timeout while waiting for reply.");
retry--; retry--;
if (retry == 0) { if (retry == 0) {
@ -110,13 +64,6 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) {
goto out; 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: out:
@ -128,7 +75,6 @@ out:
// We want to unmount after these to set things back to normal but more than this // 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 // unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory
SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0); SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0);
return ret_val; return ret_val;
} }
@ -321,246 +267,273 @@ static int CmdFlashMemSpiFFSRename(const char *Cmd) {
} }
static int CmdFlashMemSpiFFSCopy(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)); CLIParserContext *ctx;
if (len == 1 && ctmp == 'h') { CLIParserInit(&ctx, "mem spiffs copy",
return usage_flashmemspiffs_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}; int slen = 0;
char destfilename[32] = {0}; char src[32] = {0};
bool errors = false; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen);
if (param_getstr(Cmd, 0, srcfilename, 32) >= 32) { int dlen = 0;
PrintAndLogEx(FAILED, "Source Filename too long"); char dest[32] = {0};
errors = true; CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, 32, &dlen);
} CLIParserFree(ctx);
if (srcfilename[0] == '\0') {
PrintAndLogEx(FAILED, "Source Filename missing or invalid");
errors = true;
}
if (param_getstr(Cmd, 1, destfilename, 32) >= 32) { struct {
PrintAndLogEx(FAILED, "Source Filename too long"); uint8_t slen;
errors = true; uint8_t src[32];
} uint8_t dlen;
if (destfilename[0] == '\0') { uint8_t dest[32];
PrintAndLogEx(FAILED, "Source Filename missing or invalid"); } PACKED payload;
errors = true; payload.slen = slen;
} payload.dlen = dlen;
// check null filename ? memcpy(payload.src, src, slen);
if (errors) { memcpy(payload.dest, dest, dlen);
usage_flashmemspiffs_copy();
return PM3_EINVARG;
}
char data[65]; PacketResponseNG resp;
sprintf(data, "%s,%s", srcfilename, destfilename); clearCommandBuffer();
SendCommandMIX(CMD_SPIFFS_COPY, 0, 0, 0, (uint8_t *)data, 65); 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; return PM3_SUCCESS;
} }
static int CmdFlashMemSpiFFSDump(const char *Cmd) { 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}; void *argtable[] = {
uint8_t cmdp = 0; arg_param_begin,
bool errors = false; arg_str1("s", "src", "<fn>", "SPIFFS file to save"),
bool print = false; arg_str0("d", "dest", "<fn>", "file name to save to <w/o .bin>"),
uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE; arg_lit0("e", "eml", "also save in EML format"),
char destfilename[32] = {0}; arg_param_end
bool eml = false; };
CLIExecWithReturn(ctx, Cmd, argtable, false);
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { int slen = 0;
switch (tolower(param_getchar(Cmd, cmdp))) { char src[32] = {0};
case 'h': CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen);
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;
}
}
if ((filename[0] == '\0') && (!print)) { int dlen = 0;
PrintAndLogEx(FAILED, "No print asked and local dump filename missing or invalid"); char dest[FILE_PATH_SIZE] = {0};
errors = true; CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, FILE_PATH_SIZE, &dlen);
}
if (destfilename[0] == '\0') { bool eml = arg_get_lit(ctx, 3);
PrintAndLogEx(FAILED, "SPIFFS filename missing or invalid"); CLIParserFree(ctx);
errors = true;
}
// Validations
if (errors || cmdp == 0) {
usage_flashmemspiffs_dump();
return PM3_EINVARG;
}
// get size from spiffs itself ! // 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; PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { if (WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply."); PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
len = resp.oldarg[0]; uint32_t len = resp.data.asDwords[0];
uint8_t *dump = calloc(len, sizeof(uint8_t)); uint8_t *dump = calloc(len, sizeof(uint8_t));
if (!dump) { if (!dump) {
PrintAndLogEx(ERR, "error, cannot allocate memory "); PrintAndLogEx(ERR, "error, cannot allocate memory ");
return PM3_EMALLOC; return PM3_EMALLOC;
} }
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from spiffs (flashmem)", len); // download from device
if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)destfilename, 32, NULL, -1, true)) { uint32_t start_index = 0;
PrintAndLogEx(FAILED, "ERROR; downloading from spiffs(flashmemory)"); 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); free(dump);
return PM3_EFLASH; return PM3_EFLASH;
} }
if (print) { // save to file
print_hex_break(dump, len, 32); char fn[FILE_PATH_SIZE] = {0};
if (dlen == 0) {
strncpy(fn, src, slen);
} else {
strncpy(fn, dest, dlen);
} }
if (filename[0] != '\0') { saveFile(fn, ".bin", dump, len);
saveFile(filename, ".bin", dump, len);
if (eml) { if (eml) {
uint8_t eml_len = 16; uint8_t eml_len = 16;
if (strstr(fn, "class") != NULL)
if (strstr(filename, "class") != NULL)
eml_len = 8; eml_len = 8;
else if (strstr(filename, "mfu") != NULL) else if (strstr(fn, "mfu") != NULL)
eml_len = 4; eml_len = 4;
saveFileEML(filename, dump, len, eml_len); saveFileEML(fn, dump, len, eml_len);
} }
}
free(dump); free(dump);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int CmdFlashMemSpiFFSWipe(const char *Cmd) { 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)); void *argtable[] = {
if (ctmp == 'h') { arg_param_begin,
return usage_flashmemspiffs_wipe(); 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; PacketResponseNG resp;
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_SPIFFS_WIPE, NULL, 0); SendCommandNG(CMD_SPIFFS_WIPE, NULL, 0);
WaitForResponse(CMD_SPIFFS_WIPE, &resp); WaitForResponse(CMD_SPIFFS_WIPE, &resp);
if (resp.status == PM3_SUCCESS)
PrintAndLogEx(INFO, "Done!"); PrintAndLogEx(INFO, "Done!");
PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify"); PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify");
return PM3_SUCCESS; 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}; void *argtable[] = {
uint8_t destfilename[32] = {0}; arg_param_begin,
bool errors = false; arg_str1("s", "src", "<fn>", "source file name"),
uint8_t cmdp = 0; arg_str1("d", "dest", "<fn>", "destination file name"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { int slen = 0;
switch (tolower(param_getchar(Cmd, cmdp))) { char src[FILE_PATH_SIZE] = {0};
case 'h': CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, FILE_PATH_SIZE, &slen);
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;
}
}
// Validations int dlen = 0;
if (errors || cmdp == 0) char dest[32] = {0};
return usage_flashmemspiffs_load(); 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; size_t datalen = 0;
uint8_t *data = NULL; uint8_t *data = NULL;
int res = loadFile_safe(filename, "", (void **)&data, &datalen); int res = loadFile_safe(src, "", (void **)&data, &datalen);
// int res = loadFileEML( filename, data, &datalen);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
free(data); free(data);
return PM3_EFILE; return PM3_EFILE;
} }
res = flashmem_spiffs_load(destfilename, data, datalen); res = flashmem_spiffs_load(dest, data, datalen);
free(data); free(data);
if (res == PM3_SUCCESS) 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; 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[] = { static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"}, {"help", CmdHelp, AlwaysAvailable, "This help"},
{"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS file system"}, {"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS file system"},
{"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented file system"}, {"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented file system"},
{"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS file system"}, {"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS file system"},
{"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "Print file system info and usage statistics"}, {"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"}, {"mount", CmdFlashMemSpiFFSMount, IfPm3Flash, "Mount the SPIFFS file system if not already mounted"},
{"remove", CmdFlashMemSpiFFSRemove, IfPm3Flash, "Remove a file from SPIFFS file system"}, {"remove", CmdFlashMemSpiFFSRemove, IfPm3Flash, "Remove a file from SPIFFS file system"},
{"rename", CmdFlashMemSpiFFSRename, IfPm3Flash, "Rename/move a file in SPIFFS file system"}, {"rename", CmdFlashMemSpiFFSRename, IfPm3Flash, "Rename/move a file in SPIFFS file system"},
{"test", CmdFlashMemSpiFFSTest, IfPm3Flash, "Test SPIFFS Operations"}, {"test", CmdFlashMemSpiFFSTest, IfPm3Flash, "Test SPIFFS Operations"},
{"tree", CmdFlashMemSpiFFSTree, IfPm3Flash, "Print the Flash memory file system tree"}, {"tree", CmdFlashMemSpiFFSTree, IfPm3Flash, "Print the Flash memory file system tree"},
{"unmount", CmdFlashMemSpiFFSUnmount, IfPm3Flash, "Un-mount the SPIFFS file system"}, {"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} {NULL, NULL, NULL, NULL}
}; };

View file

@ -14,6 +14,6 @@
#include "common.h" #include "common.h"
int CmdFlashMemSpiFFS(const char *Cmd); int CmdFlashMemSpiFFS(const char *Cmd);
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);
#endif #endif

View file

@ -471,7 +471,7 @@ int CmdEM4x50Chk(const char *Cmd) {
// upload to flash. // upload to flash.
datalen = MIN(bytes_remaining, keyblock); datalen = MIN(bytes_remaining, keyblock);
res = flashmem_spiffs_load(destfn, keys, datalen); res = flashmem_spiffs_load((char*)destfn, keys, datalen);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "SPIFFS upload failed"); PrintAndLogEx(WARNING, "SPIFFS upload failed");
return res; return res;

View file

@ -839,6 +839,9 @@ static bool dl_it(uint8_t *dest, uint32_t bytes, PacketResponseNG *response, siz
if (response->cmd == CMD_ACK) if (response->cmd == CMD_ACK)
return true; return true;
// Spiffs download is converted to NG,
if (response->cmd == CMD_SPIFFS_DOWNLOAD)
return true;
// sample_buf is a array pointer, located in data.c // sample_buf is a array pointer, located in data.c
// arg0 = offset in transfer. Startindex of this chunk // arg0 = offset in transfer. Startindex of this chunk

View file

@ -695,7 +695,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
mem[4] = (chunk & 0xFF); mem[4] = (chunk & 0xFF);
// upload to flash. // upload to flash.
res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6)); res = flashmem_spiffs_load((char*)destfn, mem, 5 + (chunk * 6));
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "\nSPIFFS upload failed"); PrintAndLogEx(WARNING, "\nSPIFFS upload failed");
free(mem); free(mem);

View file

@ -384,6 +384,15 @@ typedef struct {
bool off; bool off;
} PACKED tearoff_params_t; } PACKED tearoff_params_t;
// when writing to SPIFFS
typedef struct {
bool append : 1;
uint16_t bytes_in_packet : 15;
uint8_t fnlen;
uint8_t fn[32];
uint8_t data[];
} PACKED flashmem_write_t;
// For the bootloader // For the bootloader
#define CMD_DEVICE_INFO 0x0000 #define CMD_DEVICE_INFO 0x0000
//#define CMD_SETUP_WRITE 0x0001 //#define CMD_SETUP_WRITE 0x0001
@ -565,6 +574,8 @@ typedef struct {
#define CMD_LF_HITAGS_READ 0x0373 #define CMD_LF_HITAGS_READ 0x0373
#define CMD_LF_HITAGS_WRITE 0x0375 #define CMD_LF_HITAGS_WRITE 0x0375
#define CMD_LF_HITAG_ELOAD 0x0376
#define CMD_HF_ISO14443A_ANTIFUZZ 0x0380 #define CMD_HF_ISO14443A_ANTIFUZZ 0x0380
#define CMD_HF_ISO14443B_SIMULATE 0x0381 #define CMD_HF_ISO14443B_SIMULATE 0x0381
#define CMD_HF_ISO14443B_SNIFF 0x0382 #define CMD_HF_ISO14443B_SNIFF 0x0382