This commit is contained in:
iceman1001 2022-02-12 17:46:34 +01:00
parent f1d45b491c
commit ec59acf64c
9 changed files with 961 additions and 886 deletions

View file

@ -15,7 +15,7 @@
//
//-----------------------------------------------------------------------------
// Modes of operation:
//
//
// --- Read ---
// Proxmark reads an EM4100 tag. LED A is turned on. When the tag is detected, it is saved to flash (RDV4 only) and proxmark enters the emulation mode.
// It's the default mode for non-RDV4 devices, and if no previous read is present in the flash it's the default mode for RDV4 devices.
@ -28,17 +28,17 @@
// Pressing the button enters writing mode and clones the emulated tag.
// Double pressing the button enters the validation mode.
// Holding the button enters the reading mode.
//
//
// --- Write ---
// Proxmarks writes the last read tag. LEDs A and B are turned on.
// When writing is complete LEDs A and B blink three times and proxmark enters the emulation mode.
//
//
// --- Validate ---
// Proxmark reads an EM4100 tag. LED C is turned on.
// If tag matches the last saved tag, LED C blinks three times. If it doesn't all LEDs blink three times. Proxmark enters the emulation mode afterwards.
// The result of the read is DISCARDED.
// Pressing the button enters the emulation mode.
//
//
// --- Wipe ---
// Proxmark continously wipes all approached T55xx tags. LED D is turned on, LEDs A-C are blinking.
// Pressing the button enters the default mode (reading or emulation).
@ -129,235 +129,232 @@ static void SaveIDtoFlash(uint64_t id) {
bt[4 - i] = (uint8_t)(id >> 8 * i & 0xff);
}
if (exists_in_spiffs(filename))
rdv40_spiffs_append(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL);
else
rdv40_spiffs_append(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL);
else
rdv40_spiffs_write(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL);
if (exists_in_spiffs(filenameLast))
rdv40_spiffs_remove(filenameLast, RDV40_SPIFFS_SAFETY_NORMAL);
rdv40_spiffs_write(filenameLast, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL);
if (exists_in_spiffs(filenameLast))
rdv40_spiffs_remove(filenameLast, RDV40_SPIFFS_SAFETY_NORMAL);
rdv40_spiffs_write(filenameLast, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL);
}
static bool ReadFlash(void) {
if (exists_in_spiffs(filenameLast) == false)
return false;
uint8_t bt[5];
if (rdv40_spiffs_read(filenameLast, (uint8_t *) &bt, 5, RDV40_SPIFFS_SAFETY_NORMAL) < 0)
return false;
low = bt[0];
low <<= 32;
low |= (bt[1] << 24) | (bt[2] << 16) | (bt[3] << 8) | bt[4];
low2 = low;
high = 0;
high2 = 0;
return true;
if (exists_in_spiffs(filenameLast) == false)
return false;
uint8_t bt[5];
if (rdv40_spiffs_read(filenameLast, (uint8_t *) &bt, 5, RDV40_SPIFFS_SAFETY_NORMAL) < 0)
return false;
low = bt[0];
low <<= 32;
low |= (bt[1] << 24) | (bt[2] << 16) | (bt[3] << 8) | bt[4];
low2 = low;
high = 0;
high2 = 0;
return true;
}
#endif
static void Wipe(void) {
DbpString("Wipe mode");
LEDsoff();
for (;;) {
LED_A_ON();
LED_B_ON();
LED_C_ON();
LED_D_ON();
copy_em410x_to_t55xx(LF_RWSB_T55XX_TYPE, LF_CLOCK, (uint32_t) 0, (uint32_t) 0, false);
SpinDelay(60);
LEDsoff();
LED_D_ON();
int b = BUTTON_HELD(100);
if (b != BUTTON_NO_CLICK || data_available())
return;
SpinDelay(100);
DbpString("Wipe mode");
LEDsoff();
b = BUTTON_HELD(100);
if (b != BUTTON_NO_CLICK || data_available())
return;
}
for (;;) {
LED_A_ON();
LED_B_ON();
LED_C_ON();
LED_D_ON();
copy_em410x_to_t55xx(LF_RWSB_T55XX_TYPE, LF_CLOCK, (uint32_t) 0, (uint32_t) 0, false);
SpinDelay(60);
LEDsoff();
LED_D_ON();
int b = BUTTON_HELD(100);
if (b != BUTTON_NO_CLICK || data_available())
return;
SpinDelay(100);
b = BUTTON_HELD(100);
if (b != BUTTON_NO_CLICK || data_available())
return;
}
}
static void Read(void) {
mode = 0;
while (low2 == 0 || mode == 0)
{
DbpString("Read");
LEDsoff();
LED_A_ON();
low2 = 0;
high2 = 0;
lf_em410x_watch(1, &high2, &low2, false);
if (low2 != 0) {
LED_B_ON();
low = low2;
high = high2;
mode = 1;
mode = 0;
#ifdef WITH_FLASH
SaveIDtoFlash(low2);
#endif
SpinDelay(50);
LED_C_ON();
SpinDelay(50);
LED_D_ON();
SpinDelay(50);
LEDsoff();
return;
}
if (data_available())
return;
while (low2 == 0 || mode == 0) {
DbpString("Read");
LEDsoff();
LED_A_ON();
int b = BUTTON_CLICKED(1000);
low2 = 0;
high2 = 0;
lf_em410x_watch(1, &high2, &low2, false);
if ((b == BUTTON_SINGLE_CLICK || b == BUTTON_HOLD) && low != 0) {
mode = 1;
return;
}
if (low2 != 0) {
LED_B_ON();
low = low2;
high = high2;
mode = 1;
if (b == BUTTON_DOUBLE_CLICK) {
Wipe();
#ifdef WITH_FLASH
SaveIDtoFlash(low2);
#endif
if (low != 0) {
mode = 1;
return;
}
}
}
SpinDelay(50);
LED_C_ON();
SpinDelay(50);
LED_D_ON();
SpinDelay(50);
LEDsoff();
return;
}
if (data_available())
return;
int b = BUTTON_CLICKED(1000);
if ((b == BUTTON_SINGLE_CLICK || b == BUTTON_HOLD) && low != 0) {
mode = 1;
return;
}
if (b == BUTTON_DOUBLE_CLICK) {
Wipe();
if (low != 0) {
mode = 1;
return;
}
}
}
}
static void Validate(void) {
DbpString("Validate");
LEDsoff();
LED_C_ON();
DbpString("Validate");
LEDsoff();
LED_C_ON();
for (;;) {
low2 = 0;
high2 = 0;
for (;;) {
low2 = 0;
high2 = 0;
lf_em410x_watch(1, &high2, &low2, false);
lf_em410x_watch(1, &high2, &low2, false);
if (low == low2 && high == high2) {
LED_C_OFF();
SpinDelay(150);
for (int i = 0; i < 3; i++) {
LED_C_ON();
SpinDelay(150);
LED_C_OFF();
SpinDelay(150);
}
if (low == low2 && high == high2) {
LED_C_OFF();
SpinDelay(150);
for (int i = 0; i < 3; i++) {
LED_C_ON();
SpinDelay(150);
LED_C_OFF();
SpinDelay(150);
}
return;
}
else if (low2 != 0 || high2 != 0) {
LEDsoff();
for (int i = 0; i < 3; i++) {
LED_A_ON();
LED_B_ON();
LED_C_ON();
LED_D_ON();
SpinDelay(250);
LEDsoff();
SpinDelay(150);
}
return;
} else if (low2 != 0 || high2 != 0) {
LEDsoff();
for (int i = 0; i < 3; i++) {
LED_A_ON();
LED_B_ON();
LED_C_ON();
LED_D_ON();
SpinDelay(250);
LEDsoff();
SpinDelay(150);
}
return;
}
else
SpinDelay(200);
return;
} else
SpinDelay(200);
int b = BUTTON_HELD(200);
if (b != BUTTON_NO_CLICK || data_available())
return;
}
int b = BUTTON_HELD(200);
if (b != BUTTON_NO_CLICK || data_available())
return;
}
}
static void Write(void) {
DbpString("Write");
LED_A_ON();
LED_B_ON();
copy_em410x_to_t55xx(LF_RWSB_T55XX_TYPE, LF_CLOCK, (uint32_t)(low >> 32), (uint32_t)(low & 0xffffffff), false);
SpinDelay(75);
LEDsoff();
DbpString("Write");
LED_A_ON();
LED_B_ON();
copy_em410x_to_t55xx(LF_RWSB_T55XX_TYPE, LF_CLOCK, (uint32_t)(low >> 32), (uint32_t)(low & 0xffffffff), false);
SpinDelay(75);
LEDsoff();
for (int i = 0; i < 3; i++) {
LED_A_ON();
LED_B_ON();
SpinDelay(75);
LED_A_OFF();
LED_B_OFF();
SpinDelay(75);
}
for (int i = 0; i < 3; i++) {
LED_A_ON();
LED_B_ON();
SpinDelay(75);
LED_A_OFF();
LED_B_OFF();
SpinDelay(75);
}
}
static void Emulate(void) {
DbpString("Emulate");
LEDsoff();
DbpString("Emulate");
LEDsoff();
for (;;) {
int bx = BUTTON_HELD(50);
if (bx == BUTTON_NO_CLICK)
break;
SpinDelay(50);
}
for (;;) {
int bx = BUTTON_HELD(50);
if (bx == BUTTON_NO_CLICK)
break;
SpinDelay(50);
}
LED_B_ON();
construct_EM410x_emul(rev_quads(low));
LED_B_ON();
construct_EM410x_emul(rev_quads(low));
SimulateTagLowFrequencyEx(buflen, 0, false, -1);
int b = BUTTON_CLICKED(800);
int b = BUTTON_CLICKED(800);
if (b == BUTTON_NO_CLICK)
return;
if (b == BUTTON_NO_CLICK)
return;
for (;;) {
int bx = BUTTON_HELD(50);
if (bx == BUTTON_NO_CLICK)
break;
SpinDelay(50);
}
for (;;) {
int bx = BUTTON_HELD(50);
if (bx == BUTTON_NO_CLICK)
break;
SpinDelay(50);
}
if (b == BUTTON_SINGLE_CLICK)
Write();
else if (b == BUTTON_HOLD)
mode = 0;
else if (b == BUTTON_DOUBLE_CLICK)
Validate();
if (b == BUTTON_SINGLE_CLICK)
Write();
else if (b == BUTTON_HOLD)
mode = 0;
else if (b == BUTTON_DOUBLE_CLICK)
Validate();
}
void RunMod() {
StandAloneMode();
LEDsoff();
LED_D_ON();
LEDsoff();
LED_D_ON();
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
WDT_HIT();
#ifdef WITH_FLASH
if (ReadFlash())
mode = 1;
else Read();
WDT_HIT();
#ifdef WITH_FLASH
if (ReadFlash())
mode = 1;
else Read();
#else
Read();
Read();
#endif
for (;;) {
WDT_HIT();
LEDsoff();
WDT_HIT();
LEDsoff();
if (data_available()) return;
if (mode == 0)
Read();
else Emulate();
if (mode == 0)
Read();
else Emulate();
}
}

View file

@ -233,7 +233,7 @@ static int CLIParseCommandParametersEx(CLIParserContext *ctx, size_t keyid, size
if (CLIParamHexToBuf(arg_get_str(ctx, aidid), hdata, hdatalen, &hdatalen)) {
return PM3_ESOFT;
}
if (hdatalen && (hdatalen < 1 || hdatalen > 16)) {
PrintAndLogEx(ERR, _RED_("ERROR:") " application id length must be 1-16 bytes only");
return PM3_EINVARG;
@ -1466,7 +1466,7 @@ static int CmdHFCipurseUpdateKey(const char *Cmd) {
arg_int0(NULL, "newkeyn", "<dec>", "target key ID"),
arg_str0(NULL, "newkey", "<hex 16 byte>", "new key"),
arg_str0(NULL, "newkeya", "<hex 1 byte>", "new key additional info. 0x00 by default"),
arg_int0(NULL, "enckeyn", "<dec>", "encrypt key ID (must be equal to the key on the card)"),
arg_str0(NULL, "enckey", "<hex 16 byte>", "encrypt key (must be equal to the key on the card)"),
@ -1541,7 +1541,7 @@ static int CmdHFCipurseUpdateKey(const char *Cmd) {
uint8_t encKey[CIPURSE_AES_KEY_LENGTH] = CIPURSE_DEFAULT_KEY;
if (hdatalen)
memcpy(encKey, hdata, CIPURSE_AES_KEY_LENGTH);
bool noauth = arg_get_lit(ctx, 15);
bool needCommit = arg_get_lit(ctx, 16);

View file

@ -4998,7 +4998,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
arg_lit0(NULL, "debit", "use for value file debit operation instead of credit"),
arg_lit0(NULL, "commit", "commit needs for backup file only. For the other file types and in the `auto` mode - command set it automatically"),
arg_int0(NULL, "updaterec", "<dec>", "Record number for update record command. Updates record instead of write. Lastest record - 0"),
arg_str0(NULL, "isoid" , "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
arg_str0(NULL, "fileisoid", "<hex>", "File ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO write commands"),
arg_str0(NULL, "readerid", "<hex>", "reader id for CommitReaderID command. If present - the command issued before write command"),
arg_str0(NULL, "trkey", "<hex>", "key for decode previous reader id"),

View file

@ -893,7 +893,7 @@ static int CmdHFMFPWrbl(const char *Cmd) {
void *argtable[] = {
arg_param_begin,
arg_lit0("v", "verbose", "Verbose mode"),
arg_lit0("v", "verbose", "Verbose mode"),
arg_lit0("b", "keyb", "Use key B (def: keyA)"),
arg_int1(NULL, "blk", "<0..255>", "Block number"),
arg_str1("d", "data", "<hex>", "Data, 16 hex bytes"),

View file

@ -135,22 +135,22 @@ static int ul_print_nxp_silicon_info(uint8_t *card_uid) {
uint16_t waferCoordX = ((uid[6] & 3) << 8) | uid[1];
uint16_t waferCoordY = ((uid[6] & 12) << 6) | uid[2];
uint32_t waferCounter = (
(uid[4] << 5) |
((uid[6] & 0xF0) << 17) |
(uid[5] << 13) |
(uid[3] >> 3)
);
(uid[4] << 5) |
((uid[6] & 0xF0) << 17) |
(uid[5] << 13) |
(uid[3] >> 3)
);
uint8_t testSite = uid[3] & 7;
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Silicon Information"));
PrintAndLogEx(INFO, " Wafer Counter: %" PRId32 " ( 0x%02" PRIX32 " )", waferCounter, waferCounter);
PrintAndLogEx(INFO, " Wafer Coordinates: x %" PRId16 ", y %" PRId16 " (0x%02" PRIX16 ", 0x%02" PRIX16 ")"
, waferCoordX
, waferCoordY
, waferCoordX
, waferCoordY
);
, waferCoordX
, waferCoordY
, waferCoordX
, waferCoordY
);
PrintAndLogEx(INFO, " Test Site: %u", testSite);
return PM3_SUCCESS;
}
@ -2063,7 +2063,7 @@ void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage) {
PrintAndLogEx(INFO, "Version..... " _YELLOW_("%s"), sprint_hex(card->version, sizeof(card->version)));
PrintAndLogEx(INFO, "TBD 0....... %s", sprint_hex(card->tbo, sizeof(card->tbo)));
PrintAndLogEx(INFO, "TBD 1....... %s", sprint_hex(card->tbo1, sizeof(card->tbo1)));
PrintAndLogEx(INFO, "Signature... %s", sprint_hex(card->signature, 16 ));
PrintAndLogEx(INFO, "Signature... %s", sprint_hex(card->signature, 16));
PrintAndLogEx(INFO, " %s", sprint_hex(card->signature + 16, sizeof(card->signature) - 16));
for (uint8_t i = 0; i < 3; i ++) {
PrintAndLogEx(INFO, "Counter %d... %s", i, sprint_hex(card->counter_tearing[i], 3));
@ -2535,7 +2535,7 @@ static int CmdHF14AMfURestore(const char *Cmd) {
free(fptr);
}
// reserve memory
// reserve memory
uint8_t *dump = NULL;
size_t bytes_read = 0;
int res = 0;
@ -2589,7 +2589,7 @@ static int CmdHF14AMfURestore(const char *Cmd) {
if (pages - 1 != mem->pages) {
PrintAndLogEx(ERR, "Error, invalid dump, wrong page count");
PrintAndLogEx(INFO, " %u vs mempg %u", pages -1 , mem->pages);
PrintAndLogEx(INFO, " %u vs mempg %u", pages - 1, mem->pages);
free(dump);
return PM3_ESOFT;
}
@ -4152,7 +4152,7 @@ static int CmdHF14AMfuEView(const char *Cmd) {
return PM3_ETIMEOUT;
}
printMFUdumpEx( (mfu_dump_t *)dump, blocks, 0);
printMFUdumpEx((mfu_dump_t *)dump, blocks, 0);
free(dump);
return PM3_SUCCESS;
}
@ -4225,14 +4225,14 @@ static int CmdHF14AMfuView(const char *Cmd) {
return res;
}
uint16_t block_cnt = ((bytes_read - MFU_DUMP_PREFIX_LENGTH) / MFU_BLOCK_SIZE);
uint16_t block_cnt = ((bytes_read - MFU_DUMP_PREFIX_LENGTH) / MFU_BLOCK_SIZE);
if (verbose) {
PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename);
PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt);
}
printMFUdumpEx( (mfu_dump_t *)dump, block_cnt, 0);
printMFUdumpEx((mfu_dump_t *)dump, block_cnt, 0);
free(dump);
return PM3_SUCCESS;
}

View file

@ -1112,7 +1112,7 @@ int loadFileJSONex(const char *preferredName, void *data, size_t maxdatalen, siz
if (!strcmp(ctype, "mfu")) {
mfu_dump_t* mem = (mfu_dump_t *)udata;
mfu_dump_t *mem = (mfu_dump_t *)udata;
JsonLoadBufAsHex(root, "$.Card.Version", mem->version, sizeof(mem->version), datalen);
JsonLoadBufAsHex(root, "$.Card.TBO_0", mem->tbo, sizeof(mem->tbo), datalen);
@ -1124,7 +1124,7 @@ int loadFileJSONex(const char *preferredName, void *data, size_t maxdatalen, siz
JsonLoadBufAsHex(root, "$.Card.Tearing1", &mem->counter_tearing[1][3], 1, datalen);
JsonLoadBufAsHex(root, "$.Card.Counter2", &mem->counter_tearing[2][0], 3, datalen);
JsonLoadBufAsHex(root, "$.Card.Tearing2", &mem->counter_tearing[2][3], 1, datalen);
*datalen = MFU_DUMP_PREFIX_LENGTH;
*datalen = MFU_DUMP_PREFIX_LENGTH;
size_t sptr = 0;
for (int i = 0; i < 256; i++) {
@ -1146,7 +1146,7 @@ int loadFileJSONex(const char *preferredName, void *data, size_t maxdatalen, siz
}
// remove one, since pages indicates a index rather than number of available pages
--mem->pages;
*datalen += sptr;
}

View file

@ -185,6 +185,8 @@ const static vocabulory_t vocabulory[] = {
{ 0, "hf cipurse formatall" },
{ 0, "hf cipurse create" },
{ 0, "hf cipurse delete" },
{ 0, "hf cipurse updkey" },
{ 0, "hf cipurse updakey" },
{ 0, "hf cipurse default" },
{ 1, "hf cipurse test" },
{ 1, "hf epa help" },
@ -348,6 +350,7 @@ const static vocabulory_t vocabulory[] = {
{ 0, "hf mfu ndefread" },
{ 0, "hf mfu rdbl" },
{ 0, "hf mfu restore" },
{ 1, "hf mfu view" },
{ 0, "hf mfu wrbl" },
{ 0, "hf mfu eload" },
{ 0, "hf mfu eview" },

File diff suppressed because it is too large Load diff

View file

@ -137,17 +137,17 @@ Check column "offline" for their availability.
|command |offline |description
|------- |------- |-----------
|`emv help `|Y |`This help`
|`emv exec `|N |`Executes EMV contactless transaction.`
|`emv pse `|N |`Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory.`
|`emv search `|N |`Try to select all applets from applets list and print installed applets.`
|`emv select `|N |`Select applet.`
|`emv gpo `|N |`Execute GetProcessingOptions.`
|`emv readrec `|N |`Read files from card.`
|`emv genac `|N |`Generate ApplicationCryptogram.`
|`emv challenge `|N |`Generate challenge.`
|`emv intauth `|N |`Internal authentication.`
|`emv scan `|N |`Scan EMV card and save it contents to json file for emulator.`
|`emv test `|Y |`Crypto logic test.`
|`emv exec `|N |`Executes EMV contactless transaction`
|`emv pse `|N |`Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory`
|`emv search `|N |`Try to select all applets from applets list and print installed applets`
|`emv select `|N |`Select applet`
|`emv gpo `|N |`Execute GetProcessingOptions`
|`emv readrec `|N |`Read files from card`
|`emv genac `|N |`Generate ApplicationCryptogram`
|`emv challenge `|N |`Generate challenge`
|`emv intauth `|N |`Internal authentication`
|`emv scan `|N |`Scan EMV card and save it contents to json file for emulator`
|`emv test `|Y |`Crypto logic test`
|`emv list `|Y |`List ISO7816 history`
|`emv roca `|N |`Extract public keys and run ROCA test`
@ -252,6 +252,8 @@ Check column "offline" for their availability.
|`hf cipurse formatall `|N |`Erase all the data from chip`
|`hf cipurse create `|N |`Create file, application, key via DGI record`
|`hf cipurse delete `|N |`Delete file`
|`hf cipurse updkey `|N |`Update key`
|`hf cipurse updakey `|N |`Update key attributes`
|`hf cipurse default `|N |`Set default key and file id for all the other commands`
|`hf cipurse test `|Y |`Tests`
@ -519,8 +521,9 @@ Check column "offline" for their availability.
|`hf mfu ndefread `|N |`Prints NDEF records from card`
|`hf mfu rdbl `|N |`Read block`
|`hf mfu restore `|N |`Restore a dump onto a MFU MAGIC tag`
|`hf mfu view `|Y |`Display content from tag dump file`
|`hf mfu wrbl `|N |`Write block`
|`hf mfu eload `|N |`load Ultralight .eml dump file into emulator memory`
|`hf mfu eload `|N |`Load Ultralight .eml dump file into emulator memory`
|`hf mfu eview `|N |`View emulator memory`
|`hf mfu sim `|N |`Simulate MIFARE Ultralight from emulator memory`
|`hf mfu setpwd `|N |`Set 3DES key - Ultralight-C`