mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 13:00:42 -07:00
Merge branch 'experimental_varlen' of https://github.com/RfidResearchGroup/proxmark3 into experimental_varlen
# Conflicts: # client/scripts/ndef_dump.lua
This commit is contained in:
commit
a6ee9ef3e7
29 changed files with 332 additions and 244 deletions
24
CHANGELOG.md
24
CHANGELOG.md
|
@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file.
|
||||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||||
|
|
||||||
## [unreleased][unreleased]
|
## [unreleased][unreleased]
|
||||||
|
- Add support new frame format in all Lua scripts (@iceman)
|
||||||
|
- Add CMD_CAPABILITIES for pm3 to inform dynamically the client (@doegox)
|
||||||
|
- Change baudrate handling, make it clear it's only indicative for USB-CDC & BT (@doegox)
|
||||||
|
- Change much faster flashmem writes (@doegox)
|
||||||
|
- Change: new progressive light scheme for 'hw detectreader' (@doegox)
|
||||||
|
- Add common error definitions system for retvals (@doegox)
|
||||||
|
- Change USART RX & TX code and fix delays handling to make it more robust, especially over BT (@doegox)
|
||||||
|
- Add support for new frames format, speedup & huge changes, see doc/new_frame_format.txt (@doegox)
|
||||||
|
- Change: loadFile* & saveFile* accept filenames with (or still without) extension (@doegox)
|
||||||
|
- Fix LoadEML to accept final "\n", e.g. from pm3_mfd2eml.py (@doegox)
|
||||||
|
- Change: rework shell scripts for easy client or flasher (@doegox)
|
||||||
|
- Fix: stop poking Internet when compiling (@doegox)
|
||||||
|
- Add support for multiple commands to "-c", e.g. proxmark3 -c "hw ping;hw version" (@doegox)
|
||||||
|
- Fix external flash writing bitflips issues at 24MHz (@doegox)
|
||||||
|
- Add color support to Dbprintf & alike and rework Dbprintf flags (@doegox)
|
||||||
|
- Change: archive (and fix) hid-flasher (@doegox)
|
||||||
|
- Add standalone placeholder to simplify new standalone integration (@doegox)
|
||||||
|
- Change: refactor standalone mode info string (@iceman)
|
||||||
|
- Add iceman skeleton standalone mode for ppl to use as base for their new modes (@iceman)
|
||||||
|
- Change: move compilation options to Makefile.hal (@doegox)
|
||||||
|
- Fix compilation under OSX (@iceman)
|
||||||
|
- Add openocd config files for JLink (@doegox)
|
||||||
|
- Fix compilation dependencies for recovery (@doegox)
|
||||||
|
- Fix segfault when loading a file (@doegox)
|
||||||
- Change/Add new dump format for Ultralight/NTAG, counters support, simulation (@mceloff)
|
- Change/Add new dump format for Ultralight/NTAG, counters support, simulation (@mceloff)
|
||||||
- Add 'hf mf sim' full-byte split anticollision support (@mceloff)
|
- Add 'hf mf sim' full-byte split anticollision support (@mceloff)
|
||||||
- Fix/Add 'hf mf sim' bugs fix, RATS support, etc (@mceloff)
|
- Fix/Add 'hf mf sim' bugs fix, RATS support, etc (@mceloff)
|
||||||
|
|
|
@ -222,7 +222,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
switch (d) {
|
switch (d) {
|
||||||
case DICTIONARY_MIFARE:
|
case DICTIONARY_MIFARE:
|
||||||
start_index = DEFAULT_MF_KEYS_OFFSET;
|
start_index = DEFAULT_MF_KEYS_OFFSET;
|
||||||
res = loadFileDICTIONARY(filename, "dic", data + 2, &datalen, 6, &keycount);
|
res = loadFileDICTIONARY(filename, data + 2, &datalen, 6, &keycount);
|
||||||
if (res || !keycount) {
|
if (res || !keycount) {
|
||||||
free(data);
|
free(data);
|
||||||
return PM3_EFILE;
|
return PM3_EFILE;
|
||||||
|
@ -233,7 +233,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
case DICTIONARY_T55XX:
|
case DICTIONARY_T55XX:
|
||||||
start_index = DEFAULT_T55XX_KEYS_OFFSET;
|
start_index = DEFAULT_T55XX_KEYS_OFFSET;
|
||||||
res = loadFileDICTIONARY(filename, "dic", data + 2, &datalen, 4, &keycount);
|
res = loadFileDICTIONARY(filename, data + 2, &datalen, 4, &keycount);
|
||||||
if (res || !keycount) {
|
if (res || !keycount) {
|
||||||
free(data);
|
free(data);
|
||||||
return PM3_EFILE;
|
return PM3_EFILE;
|
||||||
|
@ -244,7 +244,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
case DICTIONARY_ICLASS:
|
case DICTIONARY_ICLASS:
|
||||||
start_index = DEFAULT_ICLASS_KEYS_OFFSET;
|
start_index = DEFAULT_ICLASS_KEYS_OFFSET;
|
||||||
res = loadFileDICTIONARY(filename, "dic", data + 2, &datalen, 8, &keycount);
|
res = loadFileDICTIONARY(filename, data + 2, &datalen, 8, &keycount);
|
||||||
if (res || !keycount) {
|
if (res || !keycount) {
|
||||||
free(data);
|
free(data);
|
||||||
return PM3_EFILE;
|
return PM3_EFILE;
|
||||||
|
@ -254,8 +254,8 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
datalen += 2;
|
datalen += 2;
|
||||||
break;
|
break;
|
||||||
case DICTIONARY_NONE:
|
case DICTIONARY_NONE:
|
||||||
res = loadFile(filename, "bin", data, FLASH_MEM_MAX_SIZE, &datalen);
|
res = loadFile(filename, ".bin", data, FLASH_MEM_MAX_SIZE, &datalen);
|
||||||
//int res = loadFileEML( filename, "eml", data, &datalen);
|
//int res = loadFileEML( filename, data, &datalen);
|
||||||
if (res) {
|
if (res) {
|
||||||
free(data);
|
free(data);
|
||||||
return PM3_EFILE;
|
return PM3_EFILE;
|
||||||
|
@ -367,8 +367,8 @@ static int CmdFlashMemSave(const char *Cmd) {
|
||||||
return PM3_EFLASH;
|
return PM3_EFLASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
saveFile(filename, "bin", dump, len);
|
saveFile(filename, ".bin", dump, len);
|
||||||
saveFileEML(filename, "eml", dump, len, 16);
|
saveFileEML(filename, dump, len, 16);
|
||||||
free(dump);
|
free(dump);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -961,8 +961,8 @@ static int CmdHF14BDump(const char *Cmd) {
|
||||||
|
|
||||||
|
|
||||||
size_t datalen = (blocks + 1) * 4;
|
size_t datalen = (blocks + 1) * 4;
|
||||||
saveFileEML(filename, "eml", data, datalen, 4);
|
saveFileEML(filename, data, datalen, 4);
|
||||||
saveFile(filename, "bin", data, datalen);
|
saveFile(filename, ".bin", data, datalen);
|
||||||
out:
|
out:
|
||||||
return switch_off_field_14b();
|
return switch_off_field_14b();
|
||||||
}
|
}
|
||||||
|
|
|
@ -833,8 +833,8 @@ static int CmdHF15Dump(const char *Cmd) {
|
||||||
PrintAndLogEx(NORMAL, "\n");
|
PrintAndLogEx(NORMAL, "\n");
|
||||||
|
|
||||||
size_t datalen = blocknum * 4;
|
size_t datalen = blocknum * 4;
|
||||||
saveFileEML(filename, "eml", data, datalen, 4);
|
saveFileEML(filename, data, datalen, 4);
|
||||||
saveFile(filename, "bin", data, datalen);
|
saveFile(filename, ".bin", data, datalen);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -422,7 +422,7 @@ static int CmdHFiClassSim(const char *Cmd) {
|
||||||
memcpy(dump + i * 24 + 16, resp.data.asBytes + i * 16 + 8, 8);
|
memcpy(dump + i * 24 + 16, resp.data.asBytes + i * 16 + 8, 8);
|
||||||
}
|
}
|
||||||
/** Now, save to dumpfile **/
|
/** Now, save to dumpfile **/
|
||||||
saveFile("iclass_mac_attack", "bin", dump, datalen);
|
saveFile("iclass_mac_attack", ".bin", dump, datalen);
|
||||||
free(dump);
|
free(dump);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -474,7 +474,7 @@ static int CmdHFiClassSim(const char *Cmd) {
|
||||||
// copy NR_MAC (eight bytes from the response) ( 8b csn + 8b epurse == 16)
|
// copy NR_MAC (eight bytes from the response) ( 8b csn + 8b epurse == 16)
|
||||||
memcpy(dump + i * MAC_ITEM_SIZE + 16, resp.data.asBytes + i * 16 + 8, 8);
|
memcpy(dump + i * MAC_ITEM_SIZE + 16, resp.data.asBytes + i * 16 + 8, 8);
|
||||||
}
|
}
|
||||||
saveFile("iclass_mac_attack_keyroll_A", "bin", dump, datalen);
|
saveFile("iclass_mac_attack_keyroll_A", ".bin", dump, datalen);
|
||||||
|
|
||||||
//KEYROLL 2
|
//KEYROLL 2
|
||||||
memset(dump, 0, datalen);
|
memset(dump, 0, datalen);
|
||||||
|
@ -489,7 +489,7 @@ static int CmdHFiClassSim(const char *Cmd) {
|
||||||
memcpy(dump + i * MAC_ITEM_SIZE + 16, resp.data.asBytes + resp_index + 8, 8);
|
memcpy(dump + i * MAC_ITEM_SIZE + 16, resp.data.asBytes + resp_index + 8, 8);
|
||||||
resp_index++;
|
resp_index++;
|
||||||
}
|
}
|
||||||
saveFile("iclass_mac_attack_keyroll_B", "bin", dump, datalen);
|
saveFile("iclass_mac_attack_keyroll_B", ".bin", dump, datalen);
|
||||||
free(dump);
|
free(dump);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -707,7 +707,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
saveFile(outfilename, "bin", decrypted, fsize);
|
saveFile(outfilename, ".bin", decrypted, fsize);
|
||||||
printIclassDumpContents(decrypted, 1, (fsize / 8), fsize);
|
printIclassDumpContents(decrypted, 1, (fsize / 8), fsize);
|
||||||
free(decrypted);
|
free(decrypted);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1067,7 +1067,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
|
|
||||||
// save the dump to .bin file
|
// save the dump to .bin file
|
||||||
PrintAndLogEx(SUCCESS, "saving dump file - %d blocks read", gotBytes / 8);
|
PrintAndLogEx(SUCCESS, "saving dump file - %d blocks read", gotBytes / 8);
|
||||||
saveFile(filename, "bin", tag_data, gotBytes);
|
saveFile(filename, ".bin", tag_data, gotBytes);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1199,8 +1199,8 @@ static int CmdLegicESave(const char *Cmd) {
|
||||||
else
|
else
|
||||||
sprintf(fnameptr + fileNlen, ".bin");
|
sprintf(fnameptr + fileNlen, ".bin");
|
||||||
|
|
||||||
saveFileEML(filename, "eml", data, numofbytes, 8);
|
saveFileEML(filename, data, numofbytes, 8);
|
||||||
saveFile(filename, "bin", data, numofbytes);
|
saveFile(filename, ".bin", data, numofbytes);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -678,7 +678,7 @@ static uint16_t NumOfBlocks(char card) {
|
||||||
case '4' :
|
case '4' :
|
||||||
return MIFARE_4K_MAXBLOCK;
|
return MIFARE_4K_MAXBLOCK;
|
||||||
default :
|
default :
|
||||||
return MIFARE_1K_MAXBLOCK;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,7 +693,7 @@ static uint8_t NumOfSectors(char card) {
|
||||||
case '4' :
|
case '4' :
|
||||||
return MIFARE_4K_MAXSECTOR;
|
return MIFARE_4K_MAXSECTOR;
|
||||||
default :
|
default :
|
||||||
return MIFARE_1K_MAXSECTOR;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -748,6 +748,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
|
||||||
default:
|
default:
|
||||||
if (cmdp == 0) {
|
if (cmdp == 0) {
|
||||||
numSectors = NumOfSectors(param_getchar(Cmd, cmdp));
|
numSectors = NumOfSectors(param_getchar(Cmd, cmdp));
|
||||||
|
if (numSectors == 0) return usage_hf14_dump();
|
||||||
cmdp++;
|
cmdp++;
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||||
|
@ -904,9 +905,9 @@ static int CmdHF14AMfDump(const char *Cmd) {
|
||||||
|
|
||||||
uint16_t bytes = 16 * (FirstBlockOfSector(numSectors - 1) + NumBlocksPerSector(numSectors - 1));
|
uint16_t bytes = 16 * (FirstBlockOfSector(numSectors - 1) + NumBlocksPerSector(numSectors - 1));
|
||||||
|
|
||||||
saveFile(dataFilename, "bin", (uint8_t *)carddata, bytes);
|
saveFile(dataFilename, ".bin", (uint8_t *)carddata, bytes);
|
||||||
saveFileEML(dataFilename, "eml", (uint8_t *)carddata, bytes, MFBLOCK_SIZE);
|
saveFileEML(dataFilename, (uint8_t *)carddata, bytes, MFBLOCK_SIZE);
|
||||||
saveFileJSON(dataFilename, "json", jsfCardMemory, (uint8_t *)carddata, bytes);
|
saveFileJSON(dataFilename, jsfCardMemory, (uint8_t *)carddata, bytes);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -948,6 +949,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
|
||||||
default:
|
default:
|
||||||
if (cmdp == 0) {
|
if (cmdp == 0) {
|
||||||
numSectors = NumOfSectors(param_getchar(Cmd, cmdp));
|
numSectors = NumOfSectors(param_getchar(Cmd, cmdp));
|
||||||
|
if (numSectors == 0) return usage_hf14_restore();
|
||||||
cmdp++;
|
cmdp++;
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||||
|
@ -1101,6 +1103,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SectorsCnt = NumOfSectors(cmdp);
|
SectorsCnt = NumOfSectors(cmdp);
|
||||||
|
if (SectorsCnt == 0) return usage_hf14_nested();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t j = 4;
|
uint8_t j = 4;
|
||||||
|
@ -1803,6 +1806,7 @@ static int CmdHF14AMfChk(const char *Cmd) {
|
||||||
if (param_getchar(Cmd, 0) == '*') {
|
if (param_getchar(Cmd, 0) == '*') {
|
||||||
blockNo = 3;
|
blockNo = 3;
|
||||||
SectorsCnt = NumOfSectors(param_getchar(Cmd + 1, 0));
|
SectorsCnt = NumOfSectors(param_getchar(Cmd + 1, 0));
|
||||||
|
if (SectorsCnt == 0) return usage_hf14_chk();
|
||||||
} else {
|
} else {
|
||||||
blockNo = param_get8(Cmd, 0);
|
blockNo = param_get8(Cmd, 0);
|
||||||
}
|
}
|
||||||
|
@ -2562,12 +2566,13 @@ int CmdHF14AMfELoad(const char *Cmd) {
|
||||||
if (numblk2 > 0)
|
if (numblk2 > 0)
|
||||||
numBlocks = numblk2;
|
numBlocks = numblk2;
|
||||||
|
|
||||||
param_getstr(Cmd, nameParamNo, filename, sizeof(filename));
|
if (0 == param_getstr(Cmd, nameParamNo, filename, sizeof(filename)))
|
||||||
|
return usage_hf14_eload();
|
||||||
|
|
||||||
uint8_t *data = calloc(4096, sizeof(uint8_t));
|
uint8_t *data = calloc(4096, sizeof(uint8_t));
|
||||||
size_t datalen = 0;
|
size_t datalen = 0;
|
||||||
//int res = loadFile(filename, "bin", data, maxdatalen, &datalen);
|
//int res = loadFile(filename, ".bin", data, maxdatalen, &datalen);
|
||||||
int res = loadFileEML(filename, "eml", data, &datalen);
|
int res = loadFileEML(filename, data, &datalen);
|
||||||
if (res) {
|
if (res) {
|
||||||
free(data);
|
free(data);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2641,7 +2646,12 @@ static int CmdHF14AMfESave(const char *Cmd) {
|
||||||
char c = tolower(param_getchar(Cmd, 0));
|
char c = tolower(param_getchar(Cmd, 0));
|
||||||
if (c == 'h') return usage_hf14_esave();
|
if (c == 'h') return usage_hf14_esave();
|
||||||
|
|
||||||
blocks = NumOfBlocks(c);
|
if (c != 0) {
|
||||||
|
blocks = NumOfBlocks(c);
|
||||||
|
if (blocks == 0) return usage_hf14_esave();
|
||||||
|
} else {
|
||||||
|
blocks = MIFARE_1K_MAXBLOCK;
|
||||||
|
}
|
||||||
bytes = blocks * MFBLOCK_SIZE;
|
bytes = blocks * MFBLOCK_SIZE;
|
||||||
|
|
||||||
dump = calloc(bytes, sizeof(uint8_t));
|
dump = calloc(bytes, sizeof(uint8_t));
|
||||||
|
@ -2667,9 +2677,9 @@ static int CmdHF14AMfESave(const char *Cmd) {
|
||||||
FillFileNameByUID(fnameptr, dump, "-dump", 4);
|
FillFileNameByUID(fnameptr, dump, "-dump", 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveFile(filename, "bin", dump, bytes);
|
saveFile(filename, ".bin", dump, bytes);
|
||||||
saveFileEML(filename, "eml", dump, bytes, MFBLOCK_SIZE);
|
saveFileEML(filename, dump, bytes, MFBLOCK_SIZE);
|
||||||
saveFileJSON(filename, "json", jsfCardMemory, dump, bytes);
|
saveFileJSON(filename, jsfCardMemory, dump, bytes);
|
||||||
free(dump);
|
free(dump);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2690,7 +2700,12 @@ static int CmdHF14AMfECFill(const char *Cmd) {
|
||||||
keyType = 1;
|
keyType = 1;
|
||||||
|
|
||||||
c = tolower(param_getchar(Cmd, 1));
|
c = tolower(param_getchar(Cmd, 1));
|
||||||
numSectors = NumOfSectors(c);
|
if (c != 0) {
|
||||||
|
numSectors = NumOfSectors(c);
|
||||||
|
if (numSectors == 0) return usage_hf14_ecfill();
|
||||||
|
} else {
|
||||||
|
numSectors = MIFARE_1K_MAXSECTOR;
|
||||||
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "--params: numSectors: %d, keyType: %c\n", numSectors, (keyType == 0) ? 'A' : 'B');
|
PrintAndLogEx(NORMAL, "--params: numSectors: %d, keyType: %c\n", numSectors, (keyType == 0) ? 'A' : 'B');
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
@ -2708,7 +2723,12 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) {
|
||||||
if (c == 'h')
|
if (c == 'h')
|
||||||
return usage_hf14_ekeyprn();
|
return usage_hf14_ekeyprn();
|
||||||
|
|
||||||
numSectors = NumOfSectors(c);
|
if (c != 0) {
|
||||||
|
numSectors = NumOfSectors(c);
|
||||||
|
if (numSectors == 0) return usage_hf14_ekeyprn();
|
||||||
|
} else {
|
||||||
|
numSectors = MIFARE_1K_MAXSECTOR;
|
||||||
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "|---|----------------|----------------|");
|
PrintAndLogEx(NORMAL, "|---|----------------|----------------|");
|
||||||
PrintAndLogEx(NORMAL, "|sec|key A |key B |");
|
PrintAndLogEx(NORMAL, "|sec|key A |key B |");
|
||||||
|
@ -2861,12 +2881,12 @@ static int CmdHF14AMfCLoad(const char *Cmd) {
|
||||||
size_t datalen = 0;
|
size_t datalen = 0;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
if (fillFromBin) {
|
if (fillFromBin) {
|
||||||
res = loadFile(fileName, "bin", data, maxdatalen, &datalen);
|
res = loadFile(fileName, ".bin", data, maxdatalen, &datalen);
|
||||||
} else {
|
} else {
|
||||||
if (fillFromJson) {
|
if (fillFromJson) {
|
||||||
res = loadFileJSON(fileName, "json", data, maxdatalen, &datalen);
|
res = loadFileJSON(fileName, data, maxdatalen, &datalen);
|
||||||
} else {
|
} else {
|
||||||
res = loadFileEML(Cmd, "eml", data, &datalen);
|
res = loadFileEML(Cmd, data, &datalen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3100,9 +3120,9 @@ static int CmdHF14AMfCSave(const char *Cmd) {
|
||||||
PrintAndLogEx(SUCCESS, "uploaded %d bytes to emulator memory", bytes);
|
PrintAndLogEx(SUCCESS, "uploaded %d bytes to emulator memory", bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveFile(filename, "bin", dump, bytes);
|
saveFile(filename, ".bin", dump, bytes);
|
||||||
saveFileEML(filename, "eml", dump, bytes, MFBLOCK_SIZE);
|
saveFileEML(filename, dump, bytes, MFBLOCK_SIZE);
|
||||||
saveFileJSON(filename, "json", jsfCardMemory, dump, bytes);
|
saveFileJSON(filename, jsfCardMemory, dump, bytes);
|
||||||
free(dump);
|
free(dump);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1969,8 +1969,8 @@ static int CmdHF14AMfUDump(const char *Cmd) {
|
||||||
FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen);
|
FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen);
|
||||||
}
|
}
|
||||||
uint16_t datalen = pages * 4 + MFU_DUMP_PREFIX_LENGTH;
|
uint16_t datalen = pages * 4 + MFU_DUMP_PREFIX_LENGTH;
|
||||||
saveFile(filename, "bin", (uint8_t *)&dump_file_data, datalen);
|
saveFile(filename, ".bin", (uint8_t *)&dump_file_data, datalen);
|
||||||
saveFileJSON(filename, "json", jsfMfuMemory, (uint8_t *)&dump_file_data, datalen);
|
saveFileJSON(filename, jsfMfuMemory, (uint8_t *)&dump_file_data, datalen);
|
||||||
|
|
||||||
if (is_partial)
|
if (is_partial)
|
||||||
PrintAndLogEx(WARNING, "Partial dump created. (%d of %d blocks)", pages, card_mem_size);
|
PrintAndLogEx(WARNING, "Partial dump created. (%d of %d blocks)", pages, card_mem_size);
|
||||||
|
|
|
@ -293,7 +293,7 @@ static int CmdLFHitagSim(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
|
param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
|
||||||
res = loadFileEML(filename, "eml", data, &datalen);
|
res = loadFileEML(filename, data, &datalen);
|
||||||
if (res > 0 || datalen != maxdatalen) {
|
if (res > 0 || datalen != maxdatalen) {
|
||||||
PrintAndLogDevice(FAILED, "error, bytes read mismatch file size");
|
PrintAndLogDevice(FAILED, "error, bytes read mismatch file size");
|
||||||
errors = true;
|
errors = true;
|
||||||
|
@ -304,7 +304,7 @@ static int CmdLFHitagSim(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
|
param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
|
||||||
res = loadFileJSON(filename, "json", data, maxdatalen, &datalen);
|
res = loadFileJSON(filename, data, maxdatalen, &datalen);
|
||||||
if (res > 0) {
|
if (res > 0) {
|
||||||
errors = true;
|
errors = true;
|
||||||
break;
|
break;
|
||||||
|
@ -314,7 +314,7 @@ static int CmdLFHitagSim(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
|
param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
|
||||||
res = loadFile(filename, "bin", data, maxdatalen, &datalen);
|
res = loadFile(filename, ".bin", data, maxdatalen, &datalen);
|
||||||
if (res > 0) {
|
if (res > 0) {
|
||||||
errors = true;
|
errors = true;
|
||||||
break;
|
break;
|
||||||
|
@ -579,9 +579,9 @@ static int CmdLFHitagReader(const char *Cmd) {
|
||||||
fnameptr += sprintf(fnameptr, "lf-hitag-");
|
fnameptr += sprintf(fnameptr, "lf-hitag-");
|
||||||
FillFileNameByUID(fnameptr, data, "-dump", 4);
|
FillFileNameByUID(fnameptr, data, "-dump", 4);
|
||||||
|
|
||||||
saveFile(filename, "bin", data, 48);
|
saveFile(filename, ".bin", data, 48);
|
||||||
saveFileEML(filename, "eml", data, 48, 4);
|
saveFileEML(filename, data, 48, 4);
|
||||||
saveFileJSON(filename, "json", jsfHitag, data, 48);
|
saveFileJSON(filename, jsfHitag, data, 48);
|
||||||
|
|
||||||
// block3, 1 byte
|
// block3, 1 byte
|
||||||
printHitagConfiguration(data[4 * 3]);
|
printHitagConfiguration(data[4 * 3]);
|
||||||
|
@ -607,7 +607,7 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) {
|
||||||
case 'f':
|
case 'f':
|
||||||
//file with all the challenges to try
|
//file with all the challenges to try
|
||||||
param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
|
param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
|
||||||
res = loadFile(filename, "cc", data, 8 * 60, &datalen);
|
res = loadFile(filename, ".cc", data, 8 * 60, &datalen);
|
||||||
if (res > 0) {
|
if (res > 0) {
|
||||||
errors = true;
|
errors = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1903,7 +1903,7 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = loadFileDICTIONARY(filename, "dic", keyBlock, &datalen, 4, &keycount);
|
int res = loadFileDICTIONARY(filename, keyBlock, &datalen, 4, &keycount);
|
||||||
if (res || keycount == 0) {
|
if (res || keycount == 0) {
|
||||||
PrintAndLogEx(WARNING, "No keys found in file");
|
PrintAndLogEx(WARNING, "No keys found in file");
|
||||||
free(keyBlock);
|
free(keyBlock);
|
||||||
|
|
|
@ -563,7 +563,7 @@ static int CmdTraceSave(const char *Cmd) {
|
||||||
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_trace_save();
|
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_trace_save();
|
||||||
|
|
||||||
param_getstr(Cmd, 0, filename, sizeof(filename));
|
param_getstr(Cmd, 0, filename, sizeof(filename));
|
||||||
saveFile(filename, "bin", trace, traceLen);
|
saveFile(filename, ".bin", trace, traceLen);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,15 +57,49 @@ int fileExists(const char *filename) {
|
||||||
return result == 0;
|
return result == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int saveFile(const char *preferredName, const char *suffix, const void *data, size_t datalen) {
|
static char *filenamemcopy(const char *preferredName, const char *suffix) {
|
||||||
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
|
if (preferredName == NULL) return NULL;
|
||||||
char *fileName = calloc(size, sizeof(char));
|
if (suffix == NULL) return NULL;
|
||||||
|
char *fileName = (char *) calloc(strlen(preferredName) + strlen(suffix) + 1, sizeof(uint8_t));
|
||||||
|
if (fileName == NULL)
|
||||||
|
return NULL;
|
||||||
|
strcpy(fileName, preferredName);
|
||||||
|
if (str_endswith(fileName, suffix))
|
||||||
|
return fileName;
|
||||||
|
strcat(fileName, suffix);
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *newfilenamemcopy(const char *preferredName, const char *suffix) {
|
||||||
|
if (preferredName == NULL) return NULL;
|
||||||
|
if (suffix == NULL) return NULL;
|
||||||
|
char *preferredNameTmp = (char *) calloc(strlen(preferredName) + 1, sizeof(uint8_t));
|
||||||
|
if (preferredNameTmp == NULL)
|
||||||
|
return NULL;
|
||||||
|
strcpy(preferredNameTmp, preferredName);
|
||||||
|
if (str_endswith(preferredNameTmp, suffix))
|
||||||
|
preferredNameTmp[strlen(preferredNameTmp) - strlen(suffix)] = '\0';
|
||||||
|
char *fileName = (char *) calloc(strlen(preferredNameTmp) + strlen(suffix) + 1 + 10, sizeof(uint8_t)); // 10: room for filenum to ensure new filename
|
||||||
|
if (fileName == NULL) {
|
||||||
|
free(preferredNameTmp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
int num = 1;
|
int num = 1;
|
||||||
sprintf(fileName, "%s.%s", preferredName, suffix);
|
sprintf(fileName, "%s%s", preferredNameTmp, suffix);
|
||||||
while (fileExists(fileName)) {
|
while (fileExists(fileName)) {
|
||||||
sprintf(fileName, "%s-%d.%s", preferredName, num, suffix);
|
sprintf(fileName, "%s-%d%s", preferredNameTmp, num, suffix);
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
|
free(preferredNameTmp);
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
int saveFile(const char *preferredName, const char *suffix, const void *data, size_t datalen) {
|
||||||
|
|
||||||
|
if (data == NULL) return 1;
|
||||||
|
char *fileName = newfilenamemcopy(preferredName, suffix);
|
||||||
|
if (fileName == NULL) return 1;
|
||||||
|
|
||||||
/* We should have a valid filename now, e.g. dumpdata-3.bin */
|
/* We should have a valid filename now, e.g. dumpdata-3.bin */
|
||||||
|
|
||||||
/*Opening file for writing in binary mode*/
|
/*Opening file for writing in binary mode*/
|
||||||
|
@ -83,23 +117,15 @@ int saveFile(const char *preferredName, const char *suffix, const void *data, si
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int saveFileEML(const char *preferredName, const char *suffix, uint8_t *data, size_t datalen, size_t blocksize) {
|
int saveFileEML(const char *preferredName, uint8_t *data, size_t datalen, size_t blocksize) {
|
||||||
|
|
||||||
if (preferredName == NULL) return 1;
|
|
||||||
if (suffix == NULL) return 1;
|
|
||||||
if (data == NULL) return 1;
|
if (data == NULL) return 1;
|
||||||
|
char *fileName = newfilenamemcopy(preferredName, ".eml");
|
||||||
|
if (fileName == NULL) return 1;
|
||||||
|
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
int blocks = datalen / blocksize;
|
int blocks = datalen / blocksize;
|
||||||
uint16_t currblock = 1;
|
uint16_t currblock = 1;
|
||||||
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
|
|
||||||
char *fileName = calloc(size, sizeof(char));
|
|
||||||
int num = 1;
|
|
||||||
sprintf(fileName, "%s.%s", preferredName, suffix);
|
|
||||||
while (fileExists(fileName)) {
|
|
||||||
sprintf(fileName, "%s-%d.%s", preferredName, num, suffix);
|
|
||||||
num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We should have a valid filename now, e.g. dumpdata-3.bin */
|
/* We should have a valid filename now, e.g. dumpdata-3.bin */
|
||||||
|
|
||||||
|
@ -136,20 +162,13 @@ out:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType ftype, uint8_t *data, size_t datalen) {
|
int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, size_t datalen) {
|
||||||
if (preferredName == NULL) return 1;
|
|
||||||
if (suffix == NULL) return 1;
|
|
||||||
if (data == NULL) return 1;
|
if (data == NULL) return 1;
|
||||||
|
char *fileName = newfilenamemcopy(preferredName, ".json");
|
||||||
|
if (fileName == NULL) return 1;
|
||||||
|
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
|
|
||||||
char *fileName = calloc(size, sizeof(char));
|
|
||||||
int num = 1;
|
|
||||||
sprintf(fileName, "%s.%s", preferredName, suffix);
|
|
||||||
while (fileExists(fileName)) {
|
|
||||||
sprintf(fileName, "%s-%d.%s", preferredName, num, suffix);
|
|
||||||
num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
json_t *root = json_object();
|
json_t *root = json_object();
|
||||||
JsonSaveStr(root, "Created", "proxmark3");
|
JsonSaveStr(root, "Created", "proxmark3");
|
||||||
|
@ -274,14 +293,11 @@ out:
|
||||||
|
|
||||||
int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen) {
|
int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen) {
|
||||||
|
|
||||||
if (preferredName == NULL) return 1;
|
|
||||||
if (suffix == NULL) return 1;
|
|
||||||
if (data == NULL) return 1;
|
if (data == NULL) return 1;
|
||||||
|
char *fileName = filenamemcopy(preferredName, suffix);
|
||||||
|
if (fileName == NULL) return 1;
|
||||||
|
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
|
|
||||||
char *fileName = calloc(size, sizeof(char));
|
|
||||||
sprintf(fileName, "%s.%s", preferredName, suffix);
|
|
||||||
|
|
||||||
FILE *f = fopen(fileName, "rb");
|
FILE *f = fopen(fileName, "rb");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
@ -336,17 +352,14 @@ out:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int loadFileEML(const char *preferredName, const char *suffix, void *data, size_t *datalen) {
|
int loadFileEML(const char *preferredName, void *data, size_t *datalen) {
|
||||||
|
|
||||||
if (preferredName == NULL) return 1;
|
|
||||||
if (suffix == NULL) return 1;
|
|
||||||
if (data == NULL) return 1;
|
if (data == NULL) return 1;
|
||||||
|
char *fileName = filenamemcopy(preferredName, ".eml");
|
||||||
|
if (fileName == NULL) return 1;
|
||||||
|
|
||||||
size_t counter = 0;
|
size_t counter = 0;
|
||||||
int retval = 0, hexlen = 0;
|
int retval = 0, hexlen = 0;
|
||||||
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
|
|
||||||
char *fileName = calloc(size, sizeof(char));
|
|
||||||
sprintf(fileName, "%s.%s", preferredName, suffix);
|
|
||||||
|
|
||||||
FILE *f = fopen(fileName, "r");
|
FILE *f = fopen(fileName, "r");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
@ -365,6 +378,8 @@ int loadFileEML(const char *preferredName, const char *suffix, void *data, size_
|
||||||
memset(line, 0, sizeof(line));
|
memset(line, 0, sizeof(line));
|
||||||
|
|
||||||
if (fgets(line, sizeof(line), f) == NULL) {
|
if (fgets(line, sizeof(line), f) == NULL) {
|
||||||
|
if (feof(f))
|
||||||
|
break;
|
||||||
fclose(f);
|
fclose(f);
|
||||||
PrintAndLogEx(FAILED, "File reading error.");
|
PrintAndLogEx(FAILED, "File reading error.");
|
||||||
retval = 2;
|
retval = 2;
|
||||||
|
@ -391,20 +406,17 @@ out:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int loadFileJSON(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen) {
|
int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen) {
|
||||||
|
|
||||||
if (preferredName == NULL) return 1;
|
|
||||||
if (suffix == NULL) return 1;
|
|
||||||
if (data == NULL) return 1;
|
if (data == NULL) return 1;
|
||||||
|
char *fileName = filenamemcopy(preferredName, ".json");
|
||||||
|
if (fileName == NULL) return 1;
|
||||||
|
|
||||||
*datalen = 0;
|
*datalen = 0;
|
||||||
json_t *root;
|
json_t *root;
|
||||||
json_error_t error;
|
json_error_t error;
|
||||||
|
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
|
|
||||||
char *fileName = calloc(size, sizeof(char));
|
|
||||||
sprintf(fileName, "%s.%s", preferredName, suffix);
|
|
||||||
|
|
||||||
root = json_load_file(fileName, 0, &error);
|
root = json_load_file(fileName, 0, &error);
|
||||||
if (!root) {
|
if (!root) {
|
||||||
|
@ -500,11 +512,12 @@ out:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt) {
|
int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt) {
|
||||||
|
|
||||||
|
|
||||||
if (preferredName == NULL) return 1;
|
|
||||||
if (suffix == NULL) return 1;
|
|
||||||
if (data == NULL) return 1;
|
if (data == NULL) return 1;
|
||||||
|
char *fileName = filenamemcopy(preferredName, ".dic");
|
||||||
|
if (fileName == NULL) return 1;
|
||||||
|
|
||||||
// t5577 == 4bytes
|
// t5577 == 4bytes
|
||||||
// mifare == 6 bytes
|
// mifare == 6 bytes
|
||||||
|
@ -521,9 +534,6 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data
|
||||||
|
|
||||||
size_t counter = 0;
|
size_t counter = 0;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
|
|
||||||
char *fileName = calloc(size, sizeof(char));
|
|
||||||
sprintf(fileName, "%s.%s", preferredName, suffix);
|
|
||||||
|
|
||||||
FILE *f = fopen(fileName, "r");
|
FILE *f = fopen(fileName, "r");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
|
|
@ -70,7 +70,7 @@ int fileExists(const char *filename);
|
||||||
* E.g. dumpdata-15.txt
|
* E.g. dumpdata-15.txt
|
||||||
*
|
*
|
||||||
* @param preferredName
|
* @param preferredName
|
||||||
* @param suffix the file suffix. Leave out the ".".
|
* @param suffix the file suffix. Including the ".".
|
||||||
* @param data The binary data to write to the file
|
* @param data The binary data to write to the file
|
||||||
* @param datalen the length of the data
|
* @param datalen the length of the data
|
||||||
* @return 0 for ok, 1 for failz
|
* @return 0 for ok, 1 for failz
|
||||||
|
@ -83,13 +83,12 @@ int saveFile(const char *preferredName, const char *suffix, const void *data, si
|
||||||
* E.g. dumpdata-15.txt
|
* E.g. dumpdata-15.txt
|
||||||
*
|
*
|
||||||
* @param preferredName
|
* @param preferredName
|
||||||
* @param suffix the file suffix. Leave out the ".".
|
|
||||||
* @param data The binary data to write to the file
|
* @param data The binary data to write to the file
|
||||||
* @param datalen the length of the data
|
* @param datalen the length of the data
|
||||||
* @param blocksize the length of one row
|
* @param blocksize the length of one row
|
||||||
* @return 0 for ok, 1 for failz
|
* @return 0 for ok, 1 for failz
|
||||||
*/
|
*/
|
||||||
int saveFileEML(const char *preferredName, const char *suffix, uint8_t *data, size_t datalen, size_t blocksize);
|
int saveFileEML(const char *preferredName, uint8_t *data, size_t datalen, size_t blocksize);
|
||||||
|
|
||||||
/** STUB
|
/** STUB
|
||||||
* @brief Utility function to save JSON data to a file. This method takes a preferred name, but if that
|
* @brief Utility function to save JSON data to a file. This method takes a preferred name, but if that
|
||||||
|
@ -97,20 +96,19 @@ int saveFileEML(const char *preferredName, const char *suffix, uint8_t *data, si
|
||||||
* E.g. dumpdata-15.json
|
* E.g. dumpdata-15.json
|
||||||
*
|
*
|
||||||
* @param preferredName
|
* @param preferredName
|
||||||
* @param suffix the file suffix. Leave out the ".".
|
|
||||||
* @param ftype type of file.
|
* @param ftype type of file.
|
||||||
* @param data The binary data to write to the file
|
* @param data The binary data to write to the file
|
||||||
* @param datalen the length of the data
|
* @param datalen the length of the data
|
||||||
* @return 0 for ok, 1 for failz
|
* @return 0 for ok, 1 for failz
|
||||||
*/
|
*/
|
||||||
int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType ftype, uint8_t *data, size_t datalen);
|
int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, size_t datalen);
|
||||||
|
|
||||||
/** STUB
|
/** STUB
|
||||||
* @brief Utility function to load data from a binary file. This method takes a preferred name.
|
* @brief Utility function to load data from a binary file. This method takes a preferred name.
|
||||||
* E.g. dumpdata-15.bin
|
* E.g. dumpdata-15.bin
|
||||||
*
|
*
|
||||||
* @param preferredName
|
* @param preferredName
|
||||||
* @param suffix the file suffix. Leave out the ".".
|
* @param suffix the file suffix. Including the ".".
|
||||||
* @param data The data array to store the loaded bytes from file
|
* @param data The data array to store the loaded bytes from file
|
||||||
* @param maxdatalen the number of bytes that your data array has
|
* @param maxdatalen the number of bytes that your data array has
|
||||||
* @param datalen the number of bytes loaded from file
|
* @param datalen the number of bytes loaded from file
|
||||||
|
@ -123,25 +121,23 @@ int loadFile(const char *preferredName, const char *suffix, void *data, size_t m
|
||||||
* E.g. dumpdata-15.txt
|
* E.g. dumpdata-15.txt
|
||||||
*
|
*
|
||||||
* @param preferredName
|
* @param preferredName
|
||||||
* @param suffix the file suffix. Leave out the ".".
|
|
||||||
* @param data The data array to store the loaded bytes from file
|
* @param data The data array to store the loaded bytes from file
|
||||||
* @param datalen the number of bytes loaded from file
|
* @param datalen the number of bytes loaded from file
|
||||||
* @return 0 for ok, 1 for failz
|
* @return 0 for ok, 1 for failz
|
||||||
*/
|
*/
|
||||||
int loadFileEML(const char *preferredName, const char *suffix, void *data, size_t *datalen);
|
int loadFileEML(const char *preferredName, void *data, size_t *datalen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Utility function to load data from a JSON textfile. This method takes a preferred name.
|
* @brief Utility function to load data from a JSON textfile. This method takes a preferred name.
|
||||||
* E.g. dumpdata-15.json
|
* E.g. dumpdata-15.json
|
||||||
*
|
*
|
||||||
* @param preferredName
|
* @param preferredName
|
||||||
* @param suffix the file suffix. Leave out the ".".
|
|
||||||
* @param data The data array to store the loaded bytes from file
|
* @param data The data array to store the loaded bytes from file
|
||||||
* @param maxdatalen maximum size of data array in bytes
|
* @param maxdatalen maximum size of data array in bytes
|
||||||
* @param datalen the number of bytes loaded from file
|
* @param datalen the number of bytes loaded from file
|
||||||
* @return 0 for ok, 1 for failz
|
* @return 0 for ok, 1 for failz
|
||||||
*/
|
*/
|
||||||
int loadFileJSON(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen);
|
int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,14 +145,13 @@ int loadFileJSON(const char *preferredName, const char *suffix, void *data, size
|
||||||
* E.g. default_keys.dic
|
* E.g. default_keys.dic
|
||||||
*
|
*
|
||||||
* @param preferredName
|
* @param preferredName
|
||||||
* @param suffix the file suffix. Leave out the ".".
|
|
||||||
* @param data The data array to store the loaded bytes from file
|
* @param data The data array to store the loaded bytes from file
|
||||||
* @param maxdatalen maximum size of data array in bytes
|
* @param maxdatalen maximum size of data array in bytes
|
||||||
* @param datalen the number of bytes loaded from file
|
* @param datalen the number of bytes loaded from file
|
||||||
* @param keylen the number of bytes a key per row is
|
* @param keylen the number of bytes a key per row is
|
||||||
* @return 0 for ok, 1 for failz
|
* @return 0 for ok, 1 for failz
|
||||||
*/
|
*/
|
||||||
int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt);
|
int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Utility function to check and convert old mfu dump format to new
|
* @brief Utility function to check and convert old mfu dump format to new
|
||||||
|
|
|
@ -92,13 +92,13 @@ Command = {
|
||||||
end
|
end
|
||||||
o.data = data
|
o.data = data
|
||||||
return o
|
return o
|
||||||
end,
|
end,
|
||||||
parse = function (packet)
|
parse = function (packet)
|
||||||
local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLLH511', packet)
|
local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLLH511', packet)
|
||||||
return Command:new{cmd = cmd, arg1 = arg1, arg2 = arg2, arg3 = arg3, data = data}
|
return Command:new{cmd = cmd, arg1 = arg1, arg2 = arg2, arg3 = arg3, data = data}
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
-- commented out, not used.
|
-- commented out, not used.
|
||||||
function Command:__tostring()
|
function Command:__tostring()
|
||||||
local output = ("%s\r\nargs : (%s, %s, %s)\r\ndata:\r\n%s\r\n"):format(
|
local output = ("%s\r\nargs : (%s, %s, %s)\r\ndata:\r\n%s\r\n"):format(
|
||||||
_commands.tostring(self.cmd),
|
_commands.tostring(self.cmd),
|
||||||
|
@ -128,7 +128,7 @@ function Command:__responsetostring()
|
||||||
tostring(self.resp_arg1),
|
tostring(self.resp_arg1),
|
||||||
tostring(self.resp_arg2),
|
tostring(self.resp_arg2),
|
||||||
tostring(self.resp_arg3)))
|
tostring(self.resp_arg3)))
|
||||||
print('NG ::', self.resp_ng)
|
print('NG ::', self.resp_ng)
|
||||||
print('package ::', self.resp_response)
|
print('package ::', self.resp_response)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -144,10 +144,10 @@ function Command:sendMIX( ignore_response, timeout )
|
||||||
local data = self.data
|
local data = self.data
|
||||||
local cmd = self.cmd
|
local cmd = self.cmd
|
||||||
local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
|
local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
|
||||||
|
|
||||||
local err, msg = core.SendCommandMIX(cmd, arg1, arg2, arg3, data)
|
local err, msg = core.SendCommandMIX(cmd, arg1, arg2, arg3, data)
|
||||||
if err == nil then return err, msg end
|
if err == nil then return err, msg end
|
||||||
|
|
||||||
if ignore_response then return true, nil end
|
if ignore_response then return true, nil end
|
||||||
|
|
||||||
if timeout == nil then timeout = TIMEOUT end
|
if timeout == nil then timeout = TIMEOUT end
|
||||||
|
@ -156,13 +156,13 @@ function Command:sendMIX( ignore_response, timeout )
|
||||||
if response == nil then
|
if response == nil then
|
||||||
return nil, 'Error, waiting for response timed out :: '..msg
|
return nil, 'Error, waiting for response timed out :: '..msg
|
||||||
end
|
end
|
||||||
|
|
||||||
-- lets digest
|
-- lets digest
|
||||||
local data
|
local data
|
||||||
local count, cmd, length, magic, status, crc, arg1, arg2, arg3 = bin.unpack('SSIsSLLL', response)
|
local count, cmd, length, magic, status, crc, arg1, arg2, arg3 = bin.unpack('SSIsSLLL', response)
|
||||||
count, data, ng = bin.unpack('H'..length..'C', response, count)
|
count, data, ng = bin.unpack('H'..length..'C', response, count)
|
||||||
|
|
||||||
--[[ uncomment if you want to debug
|
--[[ uncomment if you want to debug
|
||||||
self.resp_cmd = cmd
|
self.resp_cmd = cmd
|
||||||
self.resp_length = length
|
self.resp_length = length
|
||||||
self.resp_magic = magic
|
self.resp_magic = magic
|
||||||
|
@ -181,20 +181,20 @@ function Command:sendMIX( ignore_response, timeout )
|
||||||
end
|
end
|
||||||
function Command:sendNG( ignore_response, timeout )
|
function Command:sendNG( ignore_response, timeout )
|
||||||
local data = self.data
|
local data = self.data
|
||||||
local cmd = self.cmd
|
local cmd = self.cmd
|
||||||
local err, msg = core.SendCommandNG(cmd, data)
|
local err, msg = core.SendCommandNG(cmd, data)
|
||||||
if err == nil then return err, msg end
|
if err == nil then return err, msg end
|
||||||
|
|
||||||
if ignore_response then return true, nil end
|
if ignore_response then return true, nil end
|
||||||
|
|
||||||
if timeout == nil then timeout = TIMEOUT end
|
if timeout == nil then timeout = TIMEOUT end
|
||||||
|
|
||||||
local response, msg = core.WaitForResponseTimeout(cmd, timeout)
|
local response, msg = core.WaitForResponseTimeout(cmd, timeout)
|
||||||
if response == nil then
|
if response == nil then
|
||||||
return nil, 'Error, waiting for response timed out :: '..msg
|
return nil, 'Error, waiting for response timed out :: '..msg
|
||||||
end
|
end
|
||||||
|
|
||||||
-- lets digest
|
-- lets digest
|
||||||
local data
|
local data
|
||||||
local count, cmd, length, magic, status, crc, arg1, arg2, arg3 = bin.unpack('SSIsSLLL', response)
|
local count, cmd, length, magic, status, crc, arg1, arg2, arg3 = bin.unpack('SSIsSLLL', response)
|
||||||
count, data, ng = bin.unpack('H'..length..'C', response, count)
|
count, data, ng = bin.unpack('H'..length..'C', response, count)
|
||||||
|
|
|
@ -92,7 +92,7 @@ local function read14443a(dont_disconnect, no_rats)
|
||||||
if no_rats then
|
if no_rats then
|
||||||
command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_RATS
|
command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_RATS
|
||||||
end
|
end
|
||||||
|
|
||||||
local result,err = command:sendMIX()
|
local result,err = command:sendMIX()
|
||||||
if result then
|
if result then
|
||||||
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result)
|
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result)
|
||||||
|
|
|
@ -97,7 +97,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool pm3_present) {
|
||||||
|
|
||||||
// loops every time enter is pressed...
|
// loops every time enter is pressed...
|
||||||
while (1) {
|
while (1) {
|
||||||
|
bool printprompt = false;
|
||||||
// this should hook up the PM3 again.
|
// this should hook up the PM3 again.
|
||||||
/*
|
/*
|
||||||
if ( IsOffline() ) {
|
if ( IsOffline() ) {
|
||||||
|
@ -134,13 +134,13 @@ main_loop(char *script_cmds_file, char *script_cmd, bool pm3_present) {
|
||||||
strcleanrn(script_cmd_buf, sizeof(script_cmd_buf));
|
strcleanrn(script_cmd_buf, sizeof(script_cmd_buf));
|
||||||
|
|
||||||
if ((cmd = strmcopy(script_cmd_buf)) != NULL)
|
if ((cmd = strmcopy(script_cmd_buf)) != NULL)
|
||||||
PrintAndLogEx(NORMAL, PROXPROMPT"%s\n", cmd);
|
printprompt = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If there is a script command
|
// If there is a script command
|
||||||
if (execCommand) {
|
if (execCommand) {
|
||||||
if ((cmd = strmcopy(script_cmd)) != NULL)
|
if ((cmd = strmcopy(script_cmd)) != NULL)
|
||||||
PrintAndLogEx(NORMAL, PROXPROMPT"%s", cmd);
|
printprompt = true;
|
||||||
uint16_t len = strlen(script_cmd) + 1;
|
uint16_t len = strlen(script_cmd) + 1;
|
||||||
script_cmd += len;
|
script_cmd += len;
|
||||||
if (script_cmd_len == len - 1)
|
if (script_cmd_len == len - 1)
|
||||||
|
@ -165,7 +165,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool pm3_present) {
|
||||||
strcleanrn(script_cmd_buf, sizeof(script_cmd_buf));
|
strcleanrn(script_cmd_buf, sizeof(script_cmd_buf));
|
||||||
|
|
||||||
if ((cmd = strmcopy(script_cmd_buf)) != NULL)
|
if ((cmd = strmcopy(script_cmd_buf)) != NULL)
|
||||||
PrintAndLogEx(NORMAL, PROXPROMPT"%s", cmd);
|
printprompt = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
cmd = readline(PROXPROMPT);
|
cmd = readline(PROXPROMPT);
|
||||||
|
@ -179,10 +179,20 @@ main_loop(char *script_cmds_file, char *script_cmd, bool pm3_present) {
|
||||||
|
|
||||||
// rtrim
|
// rtrim
|
||||||
size_t l = strlen(cmd);
|
size_t l = strlen(cmd);
|
||||||
if (l > 0 && isspace(cmd[l - 1]))
|
while (l > 0 && isspace(cmd[l - 1])) {
|
||||||
cmd[l - 1] = 0x00;
|
cmd[--l] = '\0';
|
||||||
|
}
|
||||||
|
// ltrim
|
||||||
|
size_t off = 0;
|
||||||
|
while ((cmd[off] != '\0') && isspace(cmd[off]))
|
||||||
|
off++;
|
||||||
|
for (size_t i = 0; i < strlen(cmd) - off; i++)
|
||||||
|
cmd[i] = cmd[i + off];
|
||||||
|
cmd[strlen(cmd) - off] = '\0';
|
||||||
|
|
||||||
if (cmd[0] != 0x00) {
|
if (cmd[0] != '\0') {
|
||||||
|
if (printprompt)
|
||||||
|
PrintAndLogEx(NORMAL, PROXPROMPT"%s", cmd);
|
||||||
int ret = CommandReceived(cmd);
|
int ret = CommandReceived(cmd);
|
||||||
HIST_ENTRY *entry = history_get(history_length);
|
HIST_ENTRY *entry = history_get(history_length);
|
||||||
if ((!entry) || (strcmp(entry->line, cmd) != 0))
|
if ((!entry) || (strcmp(entry->line, cmd) != 0))
|
||||||
|
@ -259,7 +269,7 @@ static void show_help(bool showFullHelp, char *exec_name) {
|
||||||
PrintAndLogEx(NORMAL, " -t/--text dump all interactive command's help at once");
|
PrintAndLogEx(NORMAL, " -t/--text dump all interactive command's help at once");
|
||||||
PrintAndLogEx(NORMAL, " -m/--markdown dump all interactive help at once in markdown syntax");
|
PrintAndLogEx(NORMAL, " -m/--markdown dump all interactive help at once in markdown syntax");
|
||||||
PrintAndLogEx(NORMAL, " -p/--port serial port to connect to");
|
PrintAndLogEx(NORMAL, " -p/--port serial port to connect to");
|
||||||
PrintAndLogEx(NORMAL, " -b/--baud serial port speed");
|
PrintAndLogEx(NORMAL, " -b/--baud serial port speed (only needed for physical UART, not for USB-CDC or BT)");
|
||||||
PrintAndLogEx(NORMAL, " -w/--wait 20sec waiting the serial port to appear in the OS");
|
PrintAndLogEx(NORMAL, " -w/--wait 20sec waiting the serial port to appear in the OS");
|
||||||
PrintAndLogEx(NORMAL, " -f/--flush output will be flushed after every print");
|
PrintAndLogEx(NORMAL, " -f/--flush output will be flushed after every print");
|
||||||
PrintAndLogEx(NORMAL, " -c/--command <command> execute one proxmark3 command (or several separated by ';').");
|
PrintAndLogEx(NORMAL, " -c/--command <command> execute one proxmark3 command (or several separated by ';').");
|
||||||
|
@ -433,15 +443,9 @@ int main(int argc, char *argv[]) {
|
||||||
if (!script_cmds_file && !stdinOnPipe)
|
if (!script_cmds_file && !stdinOnPipe)
|
||||||
showBanner();
|
showBanner();
|
||||||
|
|
||||||
|
// Let's take a baudrate ok for real UART, USB-CDC & BT don't use that info anyway
|
||||||
// default speed for USB 460800, USART(FPC serial) 115200 baud
|
|
||||||
if (speed == 0)
|
if (speed == 0)
|
||||||
#ifdef WITH_FPC_HOST
|
|
||||||
// Let's assume we're talking by default to pm3 over usart in this mode
|
|
||||||
speed = USART_BAUD_RATE;
|
speed = USART_BAUD_RATE;
|
||||||
#else
|
|
||||||
speed = 460800;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (script_cmd) {
|
if (script_cmd) {
|
||||||
while (script_cmd[strlen(script_cmd) - 1] == ' ')
|
while (script_cmd[strlen(script_cmd) - 1] == ' ')
|
||||||
|
|
|
@ -73,10 +73,10 @@ static int l_SendCommandOLD(lua_State *L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse input
|
// parse input
|
||||||
cmd = luaL_checknumber(L, 1);
|
cmd = luaL_checknumber(L, 1);
|
||||||
arg0 = luaL_checknumber(L, 2);
|
arg0 = luaL_checknumber(L, 2);
|
||||||
arg1 = luaL_checknumber(L, 3);
|
arg1 = luaL_checknumber(L, 3);
|
||||||
arg2 = luaL_checknumber(L, 4);
|
arg2 = luaL_checknumber(L, 4);
|
||||||
|
|
||||||
// data
|
// data
|
||||||
const char *p_data = luaL_checklstring(L, 5, &size);
|
const char *p_data = luaL_checklstring(L, 5, &size);
|
||||||
|
@ -93,7 +93,7 @@ static int l_SendCommandOLD(lua_State *L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SendCommandOLD(cmd, arg0, arg1, arg2, data, len);
|
SendCommandOLD(cmd, arg0, arg1, arg2, data, len);
|
||||||
lua_pushboolean(L, true);
|
lua_pushboolean(L, true);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,10 +120,10 @@ static int l_SendCommandMIX(lua_State *L) {
|
||||||
return returnToLuaWithError(L, "You need to supply five parameters");
|
return returnToLuaWithError(L, "You need to supply five parameters");
|
||||||
|
|
||||||
// parse input
|
// parse input
|
||||||
cmd = luaL_checknumber(L, 1);
|
cmd = luaL_checknumber(L, 1);
|
||||||
arg0 = luaL_checknumber(L, 2);
|
arg0 = luaL_checknumber(L, 2);
|
||||||
arg1 = luaL_checknumber(L, 3);
|
arg1 = luaL_checknumber(L, 3);
|
||||||
arg2 = luaL_checknumber(L, 4);
|
arg2 = luaL_checknumber(L, 4);
|
||||||
|
|
||||||
// data
|
// data
|
||||||
const char *p_data = luaL_checklstring(L, 5, &size);
|
const char *p_data = luaL_checklstring(L, 5, &size);
|
||||||
|
@ -162,7 +162,7 @@ static int l_SendCommandNG(lua_State *L) {
|
||||||
return returnToLuaWithError(L, "You need to supply two parameters");
|
return returnToLuaWithError(L, "You need to supply two parameters");
|
||||||
|
|
||||||
// parse input
|
// parse input
|
||||||
uint64_t cmd = luaL_checknumber(L, 1);
|
uint64_t cmd = luaL_checknumber(L, 1);
|
||||||
|
|
||||||
// data
|
// data
|
||||||
const char *p_data = luaL_checklstring(L, 2, &size);
|
const char *p_data = luaL_checklstring(L, 2, &size);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
local getopt = require('getopt')
|
local getopt = require('getopt')
|
||||||
local cmds = require('commands')
|
local cmds = require('commands')
|
||||||
local lib14a = require('read14a')
|
local taglib = require('taglib')
|
||||||
local utils = require('utils')
|
local utils = require('utils')
|
||||||
|
|
||||||
copyright = ''
|
copyright = ''
|
||||||
|
@ -64,58 +64,93 @@ local function help()
|
||||||
print(example)
|
print(example)
|
||||||
print(usage)
|
print(usage)
|
||||||
end
|
end
|
||||||
--
|
|
||||||
-- Sends an instruction to do nothing, only disconnect
|
--- This function is a lua-implementation of
|
||||||
function disconnect()
|
-- cmdhf14a.c:waitCmd(uint8_t iSelect)
|
||||||
local command = Command:newMIX{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0,}
|
local function waitCmd(iSelect)
|
||||||
-- We can ignore the response here, no ACK is returned for this command
|
local response = core.WaitForResponseTimeout(cmds.CMD_ACK, 1000)
|
||||||
-- Check /armsrc/iso14443a.c, ReaderIso14443a() for details
|
if response then
|
||||||
return command:sendMIX(true)
|
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response)
|
||||||
|
|
||||||
|
local iLen = arg0
|
||||||
|
if iSelect then iLen = arg1 end
|
||||||
|
dbg(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1))
|
||||||
|
if iLen == 0 then return nil, "No response from tag" end
|
||||||
|
local recv = string.sub(response,count, iLen+count-1)
|
||||||
|
return recv
|
||||||
|
end
|
||||||
|
return nil, "No response from device"
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
--
|
--
|
||||||
local function getblockdata(response)
|
local function show(data)
|
||||||
if not response then
|
local formatString = ('H%d'):format(string.len(data))
|
||||||
return nil, 'No response from device'
|
local _,hexdata = bin.unpack(formatString, data)
|
||||||
end
|
dbg('Hexdata', hexdata)
|
||||||
|
end
|
||||||
local count, cmd, arg0 = bin.unpack('LL', response)
|
--- Fire up a connection with a tag, return uid
|
||||||
if arg0 == 1 then
|
-- @return UID if successfull
|
||||||
local count, arg1, arg2, data = bin.unpack('LLH511', response, count)
|
-- @return nil, errormessage if unsuccessfull
|
||||||
return data:sub(1, 32)
|
local function open()
|
||||||
else
|
dbg('Opening connection')
|
||||||
return nil, "Couldn't read block"
|
core.clearCommandBuffer()
|
||||||
end
|
local x = string.format('hf 14a raw -r -p -s')
|
||||||
|
dbg(x)
|
||||||
|
core.console(x)
|
||||||
|
dbg('done')
|
||||||
|
data, err = waitCmd(true)
|
||||||
|
if err then return oops(err) end
|
||||||
|
show(data)
|
||||||
|
local formatString = ('H%d'):format(string.len(data))
|
||||||
|
local _,uid = bin.unpack(formatString, data)
|
||||||
|
return uid
|
||||||
|
end
|
||||||
|
--- Shut down tag communication
|
||||||
|
-- return no return values
|
||||||
|
local function close()
|
||||||
|
dbg('Closing connection')
|
||||||
|
core.clearCommandBuffer()
|
||||||
|
local x = string.format('hf 14a raw -r')
|
||||||
|
dbg(x)
|
||||||
|
core.console(x)
|
||||||
|
dbg('done')
|
||||||
end
|
end
|
||||||
---_ Gets data from a block
|
---_ Gets data from a block
|
||||||
-- @return {block, block+1, block+2, block+3} if successfull
|
-- @return {block, block+1, block+2, block+3} if successfull
|
||||||
-- @return nil, errormessage if unsuccessfull
|
-- @return nil, errormessage if unsuccessfull
|
||||||
local function getBlock(blockno)
|
local function getBlock(block)
|
||||||
local block, err
|
local data, err
|
||||||
local cmd = Command:newMIX{cmd = cmds.CMD_MIFAREU_READBL, arg1 = blockno, data = 0}
|
|
||||||
block, err = getblockdata(cmd:sendMIX(false))
|
core.clearCommandBuffer()
|
||||||
if not block then return oops(err) end
|
|
||||||
|
local x = string.format('hf 14a raw -r -c -p 30 %02x', block)
|
||||||
if #block < 32 then
|
dbg(x)
|
||||||
return nil, ('Expected at least 16 bytes, got %d - this tag is not NDEF-compliant'):format(string.len(data))
|
core.console(x)
|
||||||
|
dbg('done')
|
||||||
|
-- By now, there should be an ACK waiting from the device, since
|
||||||
|
-- we used the -r flag (don't read response).
|
||||||
|
|
||||||
|
data, err = waitCmd(false)
|
||||||
|
if err then return oops(err) end
|
||||||
|
show(data)
|
||||||
|
|
||||||
|
if string.len(data) < 18 then
|
||||||
|
return nil, ('Expected at least 18 bytes, got %d - this tag is not NDEF-compliant'):format(string.len(data))
|
||||||
end
|
end
|
||||||
print('block', block)
|
|
||||||
-- Now, parse out the block data
|
-- Now, parse out the block data
|
||||||
-- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
|
-- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
|
||||||
-- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
|
-- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
|
||||||
b0 = string.sub(block, 1, 8)
|
b0 = string.sub(data, 1, 4)
|
||||||
b1 = string.sub(block, 9, 16)
|
b1 = string.sub(data, 5, 8)
|
||||||
b2 = string.sub(block, 17, 24)
|
b2 = string.sub(data, 9, 12)
|
||||||
b3 = string.sub(block, 25, 32)
|
b3 = string.sub(data, 13, 16)
|
||||||
return {b0, b1, b2, b3}
|
return {b0, b1, b2, b3}
|
||||||
end
|
end
|
||||||
---
|
|
||||||
--
|
|
||||||
local function main( args)
|
local function main( args)
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
dbg('script started')
|
dbg('script started')
|
||||||
local err, data, data2, k, v, i
|
local err, data, data2, k, v, i
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
|
@ -124,21 +159,6 @@ local function main( args)
|
||||||
if o == 'd' then DEBUG = true end
|
if o == 'd' then DEBUG = true end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- First of all, connect
|
|
||||||
info, err = lib14a.read(true, true)
|
|
||||||
if err then
|
|
||||||
disconnect();
|
|
||||||
return oops(err)
|
|
||||||
end
|
|
||||||
core.clearCommandBuffer()
|
|
||||||
|
|
||||||
if info.name:match("Ultralight") then
|
|
||||||
dbg('Found a tag')
|
|
||||||
else
|
|
||||||
disconnect()
|
|
||||||
return oops('Not a Ultralightbased card. This script reads NDEF formatted UL/NTAGS')
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Info contained within the tag (block 0 example)
|
-- Info contained within the tag (block 0 example)
|
||||||
-- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
|
-- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
|
||||||
-- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
|
-- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
|
||||||
|
@ -147,24 +167,31 @@ local function main( args)
|
||||||
-- N = NDEF-Structure-Compliant (if value is E1)
|
-- N = NDEF-Structure-Compliant (if value is E1)
|
||||||
-- V = NFC Forum Specification version (if 10 = v1.0)
|
-- V = NFC Forum Specification version (if 10 = v1.0)
|
||||||
|
|
||||||
|
-- First, 'connect' (fire up the field) and get the uid
|
||||||
|
local uidHexstr = open()
|
||||||
|
|
||||||
-- First, get blockt 3 byte 2
|
-- First, get blockt 3 byte 2
|
||||||
local blocks, err = getBlock(0)
|
local blocks, err = getBlock(0)
|
||||||
if err then
|
if err then
|
||||||
disconnect()
|
close()
|
||||||
return oops(err)
|
return oops(err)
|
||||||
end
|
end
|
||||||
-- Block 3 contains number of blocks
|
-- Block 3 contains number of blocks
|
||||||
local b3chars = utils.ConvertHexToBytes(blocks[4]);
|
local b3chars = {string.byte(blocks[4], 1,4)}
|
||||||
local numBlocks = b3chars[3] * 2 + 6
|
local numBlocks = b3chars[3] * 2 + 6
|
||||||
print("Number of blocks:", numBlocks)
|
print("Number of blocks:", numBlocks)
|
||||||
|
|
||||||
-- NDEF compliant?
|
-- NDEF compliant?
|
||||||
if b3chars[1] ~= 0xE1 then
|
if b3chars[1] ~= 0xE1 then
|
||||||
disconnect()
|
close()
|
||||||
return oops('This tag is not NDEF-Compliant')
|
return oops('This tag is not NDEF-Compliant')
|
||||||
end
|
end
|
||||||
|
|
||||||
local ndefversion = b3chars[2]
|
local ndefVersion = b3chars[2]
|
||||||
|
|
||||||
|
-- Block 1, byte 1 contains manufacturer info
|
||||||
|
local bl1_b1 = string.byte(blocks[1], 1)
|
||||||
|
local manufacturer = taglib.lookupManufacturer(bl1_b1)
|
||||||
|
|
||||||
-- Reuse existing info
|
-- Reuse existing info
|
||||||
local blockData = {blocks[1], blocks[2], blocks[3], blocks[4]}
|
local blockData = {blocks[1], blocks[2], blocks[3], blocks[4]}
|
||||||
|
@ -175,28 +202,22 @@ local function main( args)
|
||||||
removing bytes from 5 to 18 from each answer.
|
removing bytes from 5 to 18 from each answer.
|
||||||
--]]
|
--]]
|
||||||
print('Dumping data...please wait')
|
print('Dumping data...please wait')
|
||||||
for i = 4, numBlocks - 1, 1 do
|
for i=4,numBlocks-1,1 do
|
||||||
blocks, err = getBlock(i)
|
blocks, err = getBlock(i)
|
||||||
if err then
|
if err then close(); return oops(err) end
|
||||||
disconnect();
|
|
||||||
return oops(err)
|
|
||||||
end
|
|
||||||
table.insert(blockData, blocks[1])
|
table.insert(blockData, blocks[1])
|
||||||
end
|
end
|
||||||
-- Deactivate field
|
-- Deactivate field
|
||||||
disconnect()
|
close()
|
||||||
-- Print results
|
-- Print results
|
||||||
print('Tag info')
|
print(string.format('Tag manufacturer: %s', manufacturer))
|
||||||
print('UID ', info.uid)
|
print(string.format('Tag UID: %s', uidHexstr))
|
||||||
print('NDEF version', ('%02x'):format(ndefversion))
|
print(string.format('Tag NDEF version: 0x%02x', ndefVersion))
|
||||||
print('Manufacturer', info.manufacturer)
|
|
||||||
print('Type ', info.name)
|
|
||||||
|
|
||||||
for k,v in ipairs(blockData) do
|
for k,v in ipairs(blockData) do
|
||||||
print(string.format('Block %02x: %02x %02x %02x %02x', k-1, string.byte(v, 1,4)))
|
print(string.format('Block %02x: %02x %02x %02x %02x', k-1, string.byte(v, 1,4)))
|
||||||
end
|
end
|
||||||
|
local filename, err = utils.writeDumpFile(uidHexstr, blockData)
|
||||||
local filename, err = utils.WriteDumpFile(info.uid, blockData)
|
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
print(string.format('Dumped data into %s', filename))
|
print(string.format('Dumped data into %s', filename))
|
||||||
|
|
|
@ -80,7 +80,7 @@ local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
print(usage)
|
print(usage)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Exit message
|
-- Exit message
|
||||||
|
@ -261,7 +261,7 @@ local function test(modulation)
|
||||||
, arg2 = block
|
, arg2 = block
|
||||||
}
|
}
|
||||||
local response, err = wc:sendMIX(false)
|
local response, err = wc:sendMIX(false)
|
||||||
if not response then return oops(err) end
|
if not response then return oops(err) end
|
||||||
|
|
||||||
-- Detect
|
-- Detect
|
||||||
local res, msg = core.t55xx_detect()
|
local res, msg = core.t55xx_detect()
|
||||||
|
@ -323,7 +323,7 @@ local function main(args)
|
||||||
end
|
end
|
||||||
|
|
||||||
exitMsg('Tests finished')
|
exitMsg('Tests finished')
|
||||||
core.console(
|
core.console(
|
||||||
format('rem [SUMMARY] Success rate: %d/%d tests passed%s'
|
format('rem [SUMMARY] Success rate: %d/%d tests passed%s'
|
||||||
, total_pass
|
, total_pass
|
||||||
, total_tests
|
, total_tests
|
||||||
|
|
|
@ -63,7 +63,7 @@ local function getblockdata(response)
|
||||||
if not response then
|
if not response then
|
||||||
return nil, 'No response from device'
|
return nil, 'No response from device'
|
||||||
end
|
end
|
||||||
|
|
||||||
local count, cmd, arg0 = bin.unpack('LL', response)
|
local count, cmd, arg0 = bin.unpack('LL', response)
|
||||||
if arg0 == 1 then
|
if arg0 == 1 then
|
||||||
local count, arg1, arg2, data = bin.unpack('LLH511', response, count)
|
local count, arg1, arg2, data = bin.unpack('LLH511', response, count)
|
||||||
|
@ -81,7 +81,7 @@ local function readblock( blocknum, keyA )
|
||||||
return b
|
return b
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- decode response and get the blockdata from backdoor magic command
|
-- decode response and get the blockdata from backdoor magic command
|
||||||
local function readmagicblock( blocknum )
|
local function readmagicblock( blocknum )
|
||||||
-- Read block N
|
-- Read block N
|
||||||
local CSETBLOCK_SINGLE_OPERATION = 0x1F
|
local CSETBLOCK_SINGLE_OPERATION = 0x1F
|
||||||
|
|
|
@ -91,7 +91,7 @@ local function getblockdata(response)
|
||||||
if not response then
|
if not response then
|
||||||
return nil, 'No response from device'
|
return nil, 'No response from device'
|
||||||
end
|
end
|
||||||
|
|
||||||
local count, cmd, arg0 = bin.unpack('LL', response)
|
local count, cmd, arg0 = bin.unpack('LL', response)
|
||||||
if arg0 == 1 then
|
if arg0 == 1 then
|
||||||
local count, arg1, arg2, data = bin.unpack('LLH511', response, count)
|
local count, arg1, arg2, data = bin.unpack('LLH511', response, count)
|
||||||
|
@ -132,7 +132,7 @@ local function main(args)
|
||||||
local cmdSetDbgOff = "hf mf dbg 0"
|
local cmdSetDbgOff = "hf mf dbg 0"
|
||||||
core.console( cmdSetDbgOff)
|
core.console( cmdSetDbgOff)
|
||||||
utils.Sleep(0.5)
|
utils.Sleep(0.5)
|
||||||
|
|
||||||
result, err = lib14a.read(false, true)
|
result, err = lib14a.read(false, true)
|
||||||
if not result then return oops(err) end
|
if not result then return oops(err) end
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ local function main(args)
|
||||||
cmd = Command:newMIX{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0, data = keyA}
|
cmd = Command:newMIX{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0, data = keyA}
|
||||||
block0, err = getblockdata(cmd:sendMIX(false))
|
block0, err = getblockdata(cmd:sendMIX(false))
|
||||||
if not block0 then return oops(err) end
|
if not block0 then return oops(err) end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
-- Read block 1
|
-- Read block 1
|
||||||
|
|
|
@ -242,7 +242,7 @@ local function LoadEmulator(uid, blocks)
|
||||||
blockdata = AddKey(keys, _, blockdata)
|
blockdata = AddKey(keys, _, blockdata)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
io.write( _..',')
|
io.write( _..',')
|
||||||
io.flush()
|
io.flush()
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
|
@ -15,7 +15,7 @@ xor: the first three block (0,1,2) is not XORED. The rest seems to be xored.
|
||||||
example = [[
|
example = [[
|
||||||
-- default
|
-- default
|
||||||
script run ufodump
|
script run ufodump
|
||||||
|
|
||||||
-- stop at block 10
|
-- stop at block 10
|
||||||
script run ufodump -b 10
|
script run ufodump -b 10
|
||||||
]]
|
]]
|
||||||
|
@ -48,7 +48,7 @@ end
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR:', err)
|
print('ERROR:', err)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
|
@ -59,7 +59,7 @@ local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print('Example usage')
|
print('Example usage')
|
||||||
print(example)
|
print(example)
|
||||||
print(usage)
|
print(usage)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
--- Picks out and displays the data read from a tag
|
--- Picks out and displays the data read from a tag
|
||||||
|
@ -103,7 +103,7 @@ function sendRaw(rawdata, options)
|
||||||
-- of the ASCII-string rawdata
|
-- of the ASCII-string rawdata
|
||||||
arg2 = string.len(rawdata)/2,
|
arg2 = string.len(rawdata)/2,
|
||||||
data = rawdata}
|
data = rawdata}
|
||||||
|
|
||||||
return command:sendMIX(options.ignore_response)
|
return command:sendMIX(options.ignore_response)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
|
|
|
@ -57,7 +57,7 @@ local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print('Example usage')
|
print('Example usage')
|
||||||
print(example)
|
print(example)
|
||||||
print(usage)
|
print(usage)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
--- Set UID on magic command enabled
|
--- Set UID on magic command enabled
|
||||||
|
|
|
@ -822,10 +822,22 @@ void str_lower(char *s) {
|
||||||
for (size_t i = 0; i < strlen(s); i++)
|
for (size_t i = 0; i < strlen(s); i++)
|
||||||
s[i] = tolower(s[i]);
|
s[i] = tolower(s[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for prefix in string
|
||||||
bool str_startswith(const char *s, const char *pre) {
|
bool str_startswith(const char *s, const char *pre) {
|
||||||
return strncmp(pre, s, strlen(pre)) == 0;
|
return strncmp(pre, s, strlen(pre)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for suffix in string
|
||||||
|
bool str_endswith(const char *s, const char *suffix) {
|
||||||
|
size_t ls = strlen(s);
|
||||||
|
size_t lsuffix = strlen(suffix);
|
||||||
|
if (ls >= lsuffix) {
|
||||||
|
return strncmp(suffix, s + (ls - lsuffix), lsuffix) == 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Replace unprintable characters with a dot in char buffer
|
// Replace unprintable characters with a dot in char buffer
|
||||||
void clean_ascii(unsigned char *buf, size_t len) {
|
void clean_ascii(unsigned char *buf, size_t len) {
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
@ -848,7 +860,7 @@ void strcreplace(char *buf, size_t len, char from, char to) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strmcopy(char *buf) {
|
char *strmcopy(const char *buf) {
|
||||||
char *str = (char *) calloc(strlen(buf) + 1, sizeof(uint8_t));
|
char *str = (char *) calloc(strlen(buf) + 1, sizeof(uint8_t));
|
||||||
if (str != NULL) {
|
if (str != NULL) {
|
||||||
memset(str, 0, strlen(buf) + 1);
|
memset(str, 0, strlen(buf) + 1);
|
||||||
|
|
|
@ -231,8 +231,9 @@ int num_CPUs(void); // number of logical CPUs
|
||||||
|
|
||||||
void str_lower(char *s); // converts string to lower case
|
void str_lower(char *s); // converts string to lower case
|
||||||
bool str_startswith(const char *s, const char *pre); // check for prefix in string
|
bool str_startswith(const char *s, const char *pre); // check for prefix in string
|
||||||
|
bool str_endswith(const char *s, const char *suffix); // check for suffix in string
|
||||||
void clean_ascii(unsigned char *buf, size_t len);
|
void clean_ascii(unsigned char *buf, size_t len);
|
||||||
void strcleanrn(char *buf, size_t len);
|
void strcleanrn(char *buf, size_t len);
|
||||||
void strcreplace(char *buf, size_t len, char from, char to);
|
void strcreplace(char *buf, size_t len, char from, char to);
|
||||||
char *strmcopy(char *buf);
|
char *strmcopy(const char *buf);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -420,7 +420,7 @@ const char *getStringDescriptor(uint8_t idx) {
|
||||||
reg |= REG_NO_EFFECT_1_ALL; \
|
reg |= REG_NO_EFFECT_1_ALL; \
|
||||||
reg &= ~(flags); \
|
reg &= ~(flags); \
|
||||||
pUdp->UDP_CSR[(endpoint)] = reg; \
|
pUdp->UDP_CSR[(endpoint)] = reg; \
|
||||||
} \
|
}
|
||||||
|
|
||||||
// reset flags in the UDP_CSR register and waits for synchronization
|
// reset flags in the UDP_CSR register and waits for synchronization
|
||||||
#define UDP_SET_EP_FLAGS(endpoint, flags) { \
|
#define UDP_SET_EP_FLAGS(endpoint, flags) { \
|
||||||
|
@ -429,7 +429,7 @@ const char *getStringDescriptor(uint8_t idx) {
|
||||||
reg |= REG_NO_EFFECT_1_ALL; \
|
reg |= REG_NO_EFFECT_1_ALL; \
|
||||||
reg |= (flags); \
|
reg |= (flags); \
|
||||||
pUdp->UDP_CSR[(endpoint)] = reg; \
|
pUdp->UDP_CSR[(endpoint)] = reg; \
|
||||||
} \
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -439,12 +439,12 @@ typedef struct {
|
||||||
uint8_t DataBits;
|
uint8_t DataBits;
|
||||||
} AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;
|
} AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;
|
||||||
|
|
||||||
AT91S_CDC_LINE_CODING line = {
|
AT91S_CDC_LINE_CODING line = { // purely informative, actual values don't matter
|
||||||
115200, // baudrate
|
USART_BAUD_RATE, // baudrate
|
||||||
0, // 1 Stop Bit
|
0, // 1 Stop Bit
|
||||||
0, // None Parity
|
0, // None Parity
|
||||||
8
|
8 // 8 Data bits
|
||||||
}; // 8 Data bits
|
};
|
||||||
|
|
||||||
static void SpinDelay(int ms) {
|
static void SpinDelay(int ms) {
|
||||||
int us = ms * 1000;
|
int us = ms * 1000;
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
|
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include "at91sam7s512.h"
|
#include "at91sam7s512.h"
|
||||||
|
#include "usart.h"
|
||||||
#include "config_gpio.h"
|
#include "config_gpio.h"
|
||||||
#include "proxmark3.h" // USB_CONNECT()
|
#include "proxmark3.h" // USB_CONNECT()
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
|
@ -14,7 +14,7 @@ $ENV{'LC_ALL'} = "C";
|
||||||
$ENV{'LANG'} = "C";
|
$ENV{'LANG'} = "C";
|
||||||
|
|
||||||
# if you are making your own fork, change this line to reflect your fork-name
|
# if you are making your own fork, change this line to reflect your fork-name
|
||||||
my $fullgitinfo = 'RRG';
|
my $fullgitinfo = 'RRG/Iceman';
|
||||||
my $ctime;
|
my $ctime;
|
||||||
# GIT status 0 = dirty, 1 = clean , 2 = undecided
|
# GIT status 0 = dirty, 1 = clean , 2 = undecided
|
||||||
my $clean = 2;
|
my $clean = 2;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue