Merge branch 'RfidResearchGroup:master' into master

This commit is contained in:
Alex 2023-06-05 19:47:20 +02:00 committed by GitHub
commit cc6b9511d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 333 additions and 253 deletions

View file

@ -70,7 +70,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Updated documentation for installation on macOS with MacPorts (@linuxgemini) - Updated documentation for installation on macOS with MacPorts (@linuxgemini)
- Added possible Paxton id to hitag2 tag info output - Added possible Paxton id to hitag2 tag info output
- Changed `hf mf sim` - reduce 50ms threshold to 6ms for reset to idle #1974 (@net147) - Changed `hf mf sim` - reduce 50ms threshold to 6ms for reset to idle #1974 (@net147)
- Updated `amiibo_tools.lua` with new identifiers and create a python script `update_amiibo_tools_lua.py` to automate the process in the future. (@CorySolovewicz) - Update `amiibo_tools.lua` with new identifiers and create a python script `update_amiibo_tools_lua.py` to automate the process in the future. (@CorySolovewicz)
- Added `lf paradox sim --fc --cn` - Simulates Paradox fob from facility code and card number (jerji)
## [Nitride.4.16191][2023-01-29] ## [Nitride.4.16191][2023-01-29]
- Changed `build_all_firmwares.sh` to fit GENERIC 256kb firmware images (@doegox) - Changed `build_all_firmwares.sh` to fit GENERIC 256kb firmware images (@doegox)

View file

@ -1189,9 +1189,9 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
// Configure the ATQA and SAK accordingly // Configure the ATQA and SAK accordingly
rATQA[0] &= 0xBF; rATQA[0] &= 0xBF;
if(tagType == 11){ if (tagType == 11) {
rSAKc1[0] = sak & 0xFC & 0X70; rSAKc1[0] = sak & 0xFC & 0X70;
}else{ } else {
rSAKc1[0] = sak & 0xFB; rSAKc1[0] = sak & 0xFB;
} }

View file

@ -349,13 +349,13 @@ static int mf_save_keys_from_arr(uint16_t n, uint8_t *d) {
uint8_t sector = 0; uint8_t sector = 0;
for (uint16_t i = 0; i < n; i++) { for (uint16_t i = 0; i < n; i++) {
if (mfIsSectorTrailer(i)) { if (mfIsSectorTrailer(i)) {
// key A offset in ST block // key A offset in ST block
memcpy(keys + (MIFARE_KEY_SIZE * sector), d + (i * MFBLOCK_SIZE), MIFARE_KEY_SIZE); memcpy(keys + (MIFARE_KEY_SIZE * sector), d + (i * MFBLOCK_SIZE), MIFARE_KEY_SIZE);
// key B offset in ST block // key B offset in ST block
memcpy(keys + (MIFARE_KEY_SIZE * sectors) + (MIFARE_KEY_SIZE * sector), d + (i * MFBLOCK_SIZE) + 10, MIFARE_KEY_SIZE); memcpy(keys + (MIFARE_KEY_SIZE * sectors) + (MIFARE_KEY_SIZE * sector), d + (i * MFBLOCK_SIZE) + 10, MIFARE_KEY_SIZE);
sector++; sector++;
} }
} }
@ -484,7 +484,7 @@ static int mf_analyse_st_block(uint8_t blockno, uint8_t *block, bool force) {
* @param numSectors: size of the card * @param numSectors: size of the card
* @param keyFileName: filename containing keys or NULL. * @param keyFileName: filename containing keys or NULL.
*/ */
static int mfc_read_tag(iso14a_card_select_t *card, uint8_t *carddata, uint8_t numSectors, char *keyfn){ static int mfc_read_tag(iso14a_card_select_t *card, uint8_t *carddata, uint8_t numSectors, char *keyfn) {
// Select card to get UID/UIDLEN/ATQA/SAK information // Select card to get UID/UIDLEN/ATQA/SAK information
clearCommandBuffer(); clearCommandBuffer();
@ -517,7 +517,7 @@ static int mfc_read_tag(iso14a_card_select_t *card, uint8_t *carddata, uint8_t n
size_t alen = 0, blen = 0; size_t alen = 0, blen = 0;
uint8_t *keyA, *keyB; uint8_t *keyA, *keyB;
if (loadFileBinaryKey(keyfn, "", (void**)&keyA, (void**)&keyB, &alen, &blen) != PM3_SUCCESS) { if (loadFileBinaryKey(keyfn, "", (void **)&keyA, (void **)&keyB, &alen, &blen) != PM3_SUCCESS) {
if (keyA) { if (keyA) {
free(keyA); free(keyA);
} }
@ -617,7 +617,7 @@ static int mfc_read_tag(iso14a_card_select_t *card, uint8_t *carddata, uint8_t n
SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
received = WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500); received = WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500);
} else { } else {
// key A would work // key A would work
payload.blockno = mfFirstBlockOfSector(sectorNo) + blockNo; payload.blockno = mfFirstBlockOfSector(sectorNo) + blockNo;
payload.keytype = current_key; payload.keytype = current_key;
memcpy(payload.key, (current_key == MF_KEY_A) ? keyA + (sectorNo * MIFARE_KEY_SIZE) : keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE); memcpy(payload.key, (current_key == MF_KEY_A) ? keyA + (sectorNo * MIFARE_KEY_SIZE) : keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
@ -651,7 +651,7 @@ static int mfc_read_tag(iso14a_card_select_t *card, uint8_t *carddata, uint8_t n
if (mfIsSectorTrailer(blockNo)) { if (mfIsSectorTrailer(blockNo)) {
// sector trailer. Fill in the keys. // sector trailer. Fill in the keys.
memcpy(data , keyA + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE); memcpy(data, keyA + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
memcpy(data + 10, keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE); memcpy(data + 10, keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
} }
@ -1259,7 +1259,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
// //
size_t alen = 0, blen = 0; size_t alen = 0, blen = 0;
uint8_t *keyA, *keyB; uint8_t *keyA, *keyB;
if (loadFileBinaryKey(keyfilename, "", (void**)&keyA, (void**)&keyB, &alen, &blen) != PM3_SUCCESS) { if (loadFileBinaryKey(keyfilename, "", (void **)&keyA, (void **)&keyB, &alen, &blen) != PM3_SUCCESS) {
if (keyA) { if (keyA) {
free(keyA); free(keyA);
} }
@ -1354,7 +1354,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
if (kt == MF_KEY_A) if (kt == MF_KEY_A)
memcpy(wdata, keyA + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE); memcpy(wdata, keyA + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
else else
memcpy(wdata, keyB+ (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE); memcpy(wdata, keyB + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
} else { } else {
// use default key to authenticate for the write command // use default key to authenticate for the write command
memcpy(wdata, default_key, MIFARE_KEY_SIZE); memcpy(wdata, default_key, MIFARE_KEY_SIZE);
@ -2518,16 +2518,16 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
sectorno = i; sectorno = i;
keytype = j; keytype = j;
PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ] (used for nested / hardnested attack)", PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ] (used for nested / hardnested attack)",
i, i,
(j == MF_KEY_B) ? 'B' : 'A', (j == MF_KEY_B) ? 'B' : 'A',
sprint_hex_inrow(key, sizeof(key)) sprint_hex_inrow(key, sizeof(key))
); );
} else { } else {
PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]", PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]",
i, i,
(j == MF_KEY_B) ? 'B' : 'A', (j == MF_KEY_B) ? 'B' : 'A',
sprint_hex_inrow(key, sizeof(key)) sprint_hex_inrow(key, sizeof(key))
); );
} }
++num_found_keys; ++num_found_keys;
} }
@ -2645,16 +2645,16 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
sectorno = i; sectorno = i;
keytype = j; keytype = j;
PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ] (used for nested / hardnested attack)", PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ] (used for nested / hardnested attack)",
i, i,
(j == MF_KEY_B) ? 'B' : 'A', (j == MF_KEY_B) ? 'B' : 'A',
sprint_hex_inrow(tmp_key, sizeof(tmp_key)) sprint_hex_inrow(tmp_key, sizeof(tmp_key))
); );
} else { } else {
PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]", PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]",
i, i,
(j == MF_KEY_B) ? 'B' : 'A', (j == MF_KEY_B) ? 'B' : 'A',
sprint_hex_inrow(tmp_key, sizeof(tmp_key)) sprint_hex_inrow(tmp_key, sizeof(tmp_key))
); );
} }
} }
} }
@ -3949,11 +3949,11 @@ void printKeyTableEx(size_t sectorscnt, sector_t *e_sector, uint8_t start_sector
} }
PrintAndLogEx(SUCCESS, " " _YELLOW_("%03d") " | %03d | %s | %s | %s | %s" PrintAndLogEx(SUCCESS, " " _YELLOW_("%03d") " | %03d | %s | %s | %s | %s"
, s , s
, mfSectorTrailerOfSector(s) , mfSectorTrailerOfSector(s)
, strA, resA , strA, resA
, strB, resB , strB, resB
); );
} }
PrintAndLogEx(SUCCESS, "-----+-----+--------------+---+--------------+----"); PrintAndLogEx(SUCCESS, "-----+-----+--------------+---+--------------+----");
@ -5901,7 +5901,7 @@ int CmdHFMFNDEFRead(const char *Cmd) {
CLIParserFree(ctx); CLIParserFree(ctx);
uint16_t ndef_aid = NDEF_MFC_AID; uint16_t ndef_aid = NDEF_MFC_AID;
if (aidlen == 2){ if (aidlen == 2) {
ndef_aid = (aid[0] << 8) + aid[1]; ndef_aid = (aid[0] << 8) + aid[1];
} }
@ -6123,7 +6123,7 @@ int CmdHFMFNDEFFormat(const char *Cmd) {
// //
size_t alen = 0, blen = 0; size_t alen = 0, blen = 0;
uint8_t *tmpA, *tmpB; uint8_t *tmpA, *tmpB;
if (loadFileBinaryKey(keyFilename, "", (void**)&tmpA, (void**)&tmpB, &alen, &blen) != PM3_SUCCESS) { if (loadFileBinaryKey(keyFilename, "", (void **)&tmpA, (void **)&tmpB, &alen, &blen) != PM3_SUCCESS) {
if (tmpA) { if (tmpA) {
free(tmpA); free(tmpA);
} }
@ -6132,9 +6132,9 @@ int CmdHFMFNDEFFormat(const char *Cmd) {
PrintAndLogEx(INFO, "Using `" _YELLOW_("%s") "`", keyFilename); PrintAndLogEx(INFO, "Using `" _YELLOW_("%s") "`", keyFilename);
for (int i=0; i < numSectors; i++) { for (int i = 0; i < numSectors; i++) {
memcpy(keyA[i], tmpA + (i *MIFARE_KEY_SIZE), MIFARE_KEY_SIZE); memcpy(keyA[i], tmpA + (i * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
memcpy(keyB[i], tmpB + (i *MIFARE_KEY_SIZE), MIFARE_KEY_SIZE); memcpy(keyB[i], tmpB + (i * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
} }
free(tmpA); free(tmpA);
free(tmpB); free(tmpB);
@ -6680,7 +6680,7 @@ static int CmdHf14AMfSuperCard(const char *Cmd) {
return PM3_EINVARG; return PM3_EINVARG;
} }
#define SUPER_MAX_TRACES 7 #define SUPER_MAX_TRACES 7
uint8_t trace = 0; uint8_t trace = 0;
uint8_t traces[SUPER_MAX_TRACES][16]; uint8_t traces[SUPER_MAX_TRACES][16];
@ -7964,24 +7964,24 @@ static int CmdHF14AMfValue(const char *Cmd) {
"hf mf value --blk 16 -k FFFFFFFFFFFF -b --get\n" "hf mf value --blk 16 -k FFFFFFFFFFFF -b --get\n"
"hf mf value --blk 16 -k FFFFFFFFFFFF --res --transfer 30 --tk FFFFFFFFFFFF --> transfer block 16 value to block 30 (even if block can't be incremented by ACL)\n" "hf mf value --blk 16 -k FFFFFFFFFFFF --res --transfer 30 --tk FFFFFFFFFFFF --> transfer block 16 value to block 30 (even if block can't be incremented by ACL)\n"
"hf mf value --get -d 87D612007829EDFF87D6120011EE11EE\n" "hf mf value --get -d 87D612007829EDFF87D6120011EE11EE\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_str0("k", "key", "<hex>", "key, 6 hex bytes"), arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
arg_lit0("a", NULL, "input key type is key A (def)"), arg_lit0("a", NULL, "input key type is key A (def)"),
arg_lit0("b", NULL, "input key type is key B"), arg_lit0("b", NULL, "input key type is key B"),
arg_u64_0(NULL, "inc", "<dec>", "Increment value by X (0 - 2147483647)"), arg_u64_0(NULL, "inc", "<dec>", "Increment value by X (0 - 2147483647)"),
arg_u64_0(NULL, "dec", "<dec>", "Decrement value by X (0 - 2147483647)"), arg_u64_0(NULL, "dec", "<dec>", "Decrement value by X (0 - 2147483647)"),
arg_u64_0(NULL, "set", "<dec>", "Set value to X (-2147483647 - 2147483647)"), arg_u64_0(NULL, "set", "<dec>", "Set value to X (-2147483647 - 2147483647)"),
arg_u64_0(NULL, "transfer", "<dec>", "Transfer value to other block (after inc/dec/restore)"), arg_u64_0(NULL, "transfer", "<dec>", "Transfer value to other block (after inc/dec/restore)"),
arg_str0(NULL, "tkey", "<hex>", "transfer key, 6 hex bytes (if transfer is preformed to other sector)"), arg_str0(NULL, "tkey", "<hex>", "transfer key, 6 hex bytes (if transfer is preformed to other sector)"),
arg_lit0(NULL, "ta", "transfer key type is key A (def)"), arg_lit0(NULL, "ta", "transfer key type is key A (def)"),
arg_lit0(NULL, "tb", "transfer key type is key B"), arg_lit0(NULL, "tb", "transfer key type is key B"),
arg_lit0(NULL, "get", "Get value from block"), arg_lit0(NULL, "get", "Get value from block"),
arg_lit0(NULL, "res", "Restore (copy value to card buffer, should be used with --transfer)"), arg_lit0(NULL, "res", "Restore (copy value to card buffer, should be used with --transfer)"),
arg_int0(NULL, "blk", "<dec>", "block number"), arg_int0(NULL, "blk", "<dec>", "block number"),
arg_str0("d", "data", "<hex>", "block data to extract values from (16 hex bytes)"), arg_str0("d", "data", "<hex>", "block data to extract values from (16 hex bytes)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -8110,9 +8110,9 @@ static int CmdHF14AMfValue(const char *Cmd) {
// don't want to write value data and break something // don't want to write value data and break something
if ((blockno == 0) || if ((blockno == 0) ||
(mfIsSectorTrailer(blockno)) || (mfIsSectorTrailer(blockno)) ||
(trnval == 0) || (trnval == 0) ||
(trnval != -1 && mfIsSectorTrailer(trnval))) { (trnval != -1 && mfIsSectorTrailer(trnval))) {
PrintAndLogEx(WARNING, "invalid block number, should be a data block"); PrintAndLogEx(WARNING, "invalid block number, should be a data block");
return PM3_EINVARG; return PM3_EINVARG;
} }

View file

@ -1680,7 +1680,7 @@ int CmdLFfind(const char *Cmd) {
goto out; goto out;
} }
} }
if (demodParadox(true) == PM3_SUCCESS) { if (demodParadox(true, false) == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!");
if (search_cont) { if (search_cont) {
found++; found++;

View file

@ -338,7 +338,7 @@ static void printHitag2PaxtonDowngrade(const uint8_t *data) {
bytes = (bytes * 0x100) + data[i]; bytes = (bytes * 0x100) + data[i];
} }
for (int j = 0; j< 8; j++) { for (int j = 0; j < 8; j++) {
num = bytes & mask; num = bytes & mask;
skip -= 5; skip -= 5;
mask = mask >> 5; mask = mask >> 5;

View file

@ -20,7 +20,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h>
#include "commonutil.h" // ARRAYLEN #include "commonutil.h" // ARRAYLEN
#include "cmdparser.h" // command_t #include "cmdparser.h" // command_t
#include "comms.h" #include "comms.h"
@ -53,7 +52,55 @@ static const uint8_t paradox_lut[] = {
// Paradox Prox demod - FSK2a RF/50 with preamble of 00001111 (then manchester encoded) // Paradox Prox demod - FSK2a RF/50 with preamble of 00001111 (then manchester encoded)
// print full Paradox Prox ID and some bit format details if found // print full Paradox Prox ID and some bit format details if found
int demodParadox(bool verbose) { // This function will calculate the bitstream for a paradox card and place the result in bs.
// It returns the calculated CRC from the fc and cn.
// CRC calculation by mwalker33
static uint8_t GetParadoxBits(const uint32_t fc, const uint32_t cn, unsigned int *bs) {
uint8_t manchester[13] = { 0x00 }; // check size needed
uint32_t t1;
manchester[0] = 0x0F; // preamble
manchester[1] = 0x05; // Leading zeros - Note: from this byte on, is part of the CRC calculation
manchester[2] = 0x55; // Leading zeros its 4 bits out for the CRC, so we need to move
manchester[3] = 0x55; // Leading zeros back 4 bits once we have the crc (done below)
// add FC
t1 = manchesterEncode2Bytes(fc);
manchester[4] = (t1 >> 8) & 0xFF;
manchester[5] = t1 & 0xFF;
// add cn
t1 = manchesterEncode2Bytes(cn);
manchester[6] = (t1 >> 24) & 0xFF;
manchester[7] = (t1 >> 16) & 0xFF;
manchester[8] = (t1 >> 8) & 0xFF;
manchester[9] = t1 & 0xFF;
uint8_t crc = (CRC8Maxim(manchester + 1, 9) ^ 0x6) & 0xFF;
// add crc
t1 = manchesterEncode2Bytes(crc);
manchester[10] = (t1 >> 8) & 0xFF;
manchester[11] = t1 & 0xFF;
// move left 4 bits left 4 bits - Now that we have the CRC we need to re-align the data.
for (int i = 1; i < 12; i++)
manchester[i] = (manchester[i] << 4) + (manchester[i + 1] >> 4);
// Add trailing 1010 (11)
manchester[11] |= (1 << 3);
manchester[11] |= (1 << 1);
// move into tag blocks
for (int i = 0; i < 12; i++)
bs[1 + (i / 4)] += (manchester[i] << (8 * (3 - i % 4)));
return crc;
}
int demodParadox(bool verbose, bool oldChksum) {
(void) verbose; // unused so far (void) verbose; // unused so far
//raw fsk demod no manchester decoding no start bit finding just get binary from wave //raw fsk demod no manchester decoding no start bit finding just get binary from wave
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0};
@ -134,34 +181,39 @@ int demodParadox(bool verbose) {
uint32_t fc = ((hi & 0x3) << 6) | (lo >> 26); uint32_t fc = ((hi & 0x3) << 6) | (lo >> 26);
uint32_t cardnum = (lo >> 10) & 0xFFFF; uint32_t cardnum = (lo >> 10) & 0xFFFF;
uint8_t chksum = (lo >> 2) & 0xFF; uint8_t chksum = (lo >> 2) & 0xFF;
if (oldChksum) {
// Calc CRC & Checksum
// 000088f0b - FC: 8 - Card: 36619 - Checksum: 05 - RAW: 0f55555559595aa559a5566a
// checksum?
uint8_t calc_chksum = 0x47;
uint8_t pos = 0;
for (uint8_t i = 0; i < 8; i++) {
uint8_t ice = rawhex[i + 1];
for (uint8_t j = 0x80; j > 0; j >>= 2) {
// Calc CRC & Checksum if (ice & j) {
// 000088f0b - FC: 8 - Card: 36619 - Checksum: 05 - RAW: 0f55555559595aa559a5566a calc_chksum ^= paradox_lut[pos];
// checksum? }
uint8_t calc_chksum = 0x47; pos++;
uint8_t pos = 0;
for (uint8_t i = 0; i < 8; i++) {
uint8_t ice = rawhex[i + 1];
for (uint8_t j = 0x80; j > 0; j >>= 2) {
if (ice & j) {
calc_chksum ^= paradox_lut[pos];
} }
pos++;
} }
uint32_t crc = CRC8Maxim(rawhex + 1, 8);
PrintAndLogEx(INFO, " FSK/MAN raw : %s", sprint_hex(rawhex, sizeof(rawhex)));
PrintAndLogEx(INFO, " raw : %s = (maxim crc8) %02x == %02x", sprint_hex(rawhex + 1, 8), crc,
calc_chksum);
// PrintAndLogEx(DEBUG, " OTHER sample CRC-8/MAXIM : 55 55 69 A5 55 6A 59 5A = FC");
} }
uint32_t crc = CRC8Maxim(rawhex + 1, 8);
PrintAndLogEx(DEBUG, " FSK/MAN raw : %s", sprint_hex(rawhex, sizeof(rawhex)));
PrintAndLogEx(DEBUG, " raw : %s = (maxim crc8) %02x == %02x", sprint_hex(rawhex + 1, 8), crc, calc_chksum);
// PrintAndLogEx(DEBUG, " OTHER sample CRC-8/MAXIM : 55 55 69 A5 55 6A 59 5A = FC");
uint32_t rawLo = bytebits_to_byte(bits + idx + 64, 32); uint32_t rawLo = bytebits_to_byte(bits + idx + 64, 32);
uint32_t rawHi = bytebits_to_byte(bits + idx + 32, 32); uint32_t rawHi = bytebits_to_byte(bits + idx + 32, 32);
uint32_t rawHi2 = bytebits_to_byte(bits + idx, 32); uint32_t rawHi2 = bytebits_to_byte(bits + idx, 32);
uint32_t blocks[4] = {0};
uint8_t crc = GetParadoxBits(fc, cardnum, blocks);
if (chksum != crc)
PrintAndLogEx(ERR, "CRC Error! Calculated CRC is " _GREEN_("%d") " but card CRC is " _RED_("%d") ".", crc, chksum);
PrintAndLogEx(INFO, "Paradox - ID: " _GREEN_("%x%08x") " FC: " _GREEN_("%d") " Card: " _GREEN_("%d") ", Checksum: %02x, Raw: %08x%08x%08x", PrintAndLogEx(INFO, "Paradox - ID: " _GREEN_("%x%08x") " FC: " _GREEN_("%d") " Card: " _GREEN_("%d") ", Checksum: %02x, Raw: %08x%08x%08x",
hi >> 10, hi >> 10,
(hi & 0x3) << 26 | (lo >> 10), (hi & 0x3) << 26 | (lo >> 10),
@ -185,32 +237,37 @@ static int CmdParadoxDemod(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "lf paradox demod", CLIParserInit(&ctx, "lf paradox demod",
"Try to find Paradox preamble, if found decode / descramble data", "Try to find Paradox preamble, if found decode / descramble data",
"lf paradox demod" "lf paradox demod --old -> Display previous checksum version"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0(NULL, "old", "optional - Display previous checksum version"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool old = arg_get_lit(ctx, 1);
CLIParserFree(ctx); CLIParserFree(ctx);
return demodParadox(true); return demodParadox(true, old);
} }
static int CmdParadoxReader(const char *Cmd) { static int CmdParadoxReader(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "lf paradox reader", CLIParserInit(&ctx, "lf paradox reader",
"read a Paradox tag", "read a Paradox tag",
"lf Paradox reader -@ -> continuous reader mode" "lf paradox reader -@ -> continuous reader mode\n"
"lf paradox reader --old -> Display previous checksum version"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"), arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_lit0(NULL, "old", "optional - Display previous checksum version"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1); bool cm = arg_get_lit(ctx, 1);
bool old = arg_get_lit(ctx, 2);
CLIParserFree(ctx); CLIParserFree(ctx);
if (cm) { if (cm) {
@ -219,7 +276,7 @@ static int CmdParadoxReader(const char *Cmd) {
do { do {
lf_read(false, 10000); lf_read(false, 10000);
demodParadox(!cm); demodParadox(!cm, old);
} while (cm && !kbd_enter_pressed()); } while (cm && !kbd_enter_pressed());
return PM3_SUCCESS; return PM3_SUCCESS;
@ -230,7 +287,7 @@ static int CmdParadoxClone(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "lf paradox clone", CLIParserInit(&ctx, "lf paradox clone",
"clone a paradox tag to a T55x7, Q5/T5555 or EM4305/4469 tag.", "clone a paradox tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
"lf paradox clone --fc 96 --cn 40426 -> encode for T55x7 tag with fc and cn\n" "lf paradox clone --fc 96 --cn 40426 -> encode for T55x7 tag with fc and cn\n"
"lf paradox clone --raw 0f55555695596a6a9999a59a -> encode for T55x7 tag\n" "lf paradox clone --raw 0f55555695596a6a9999a59a -> encode for T55x7 tag\n"
"lf paradox clone --raw 0f55555695596a6a9999a59a --q5 -> encode for Q5/T5555 tag\n" "lf paradox clone --raw 0f55555695596a6a9999a59a --q5 -> encode for Q5/T5555 tag\n"
"lf paradox clone --raw 0f55555695596a6a9999a59a --em -> encode for EM4305/4469" "lf paradox clone --raw 0f55555695596a6a9999a59a --em -> encode for EM4305/4469"
@ -263,6 +320,16 @@ static int CmdParadoxClone(const char *Cmd) {
return PM3_EINVARG; return PM3_EINVARG;
} }
if ((fc || cn) && raw_len != 0) {
PrintAndLogEx(FAILED, "Can't specify both FC/CN and RAW at the same time");
return PM3_EINVARG;
}
if (fc > 999 || cn > 99999) {
PrintAndLogEx(FAILED, "FC has a max value of 999 and CN has a max value of 99999");
return PM3_EINVARG;
}
uint32_t blocks[4] = {0}; uint32_t blocks[4] = {0};
if (raw_len != 0) { if (raw_len != 0) {
@ -275,44 +342,8 @@ static int CmdParadoxClone(const char *Cmd) {
blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t)); blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t));
} }
} else { } else {
uint8_t manchester[13] = { 0x00 }; // check size needed //This function generates the bitstream and puts it in blocks. it returns the crc, but we don't need it here
uint32_t t1; GetParadoxBits(fc, cn, blocks);
manchester[0] = 0x0F; // preamble
manchester[1] = 0x05; // Leading zeros - Note: from this byte on, is part of the CRC calculation
manchester[2] = 0x55; // Leading zeros its 4 bits out for the CRC, so we need too move
manchester[3] = 0x55; // Leading zeros back 4 bits once we have the crc (done below)
// add FC
t1 = manchesterEncode2Bytes(fc);
manchester[4] = (t1 >> 8) & 0xFF;
manchester[5] = t1 & 0xFF;
// add cn
t1 = manchesterEncode2Bytes(cn);
manchester[6] = (t1 >> 24) & 0xFF;
manchester[7] = (t1 >> 16) & 0xFF;
manchester[8] = (t1 >> 8) & 0xFF;
manchester[9] = t1 & 0xFF;
uint8_t crc = (CRC8Maxim(manchester + 1, 9) ^ 0x6) & 0xFF;
// add crc
t1 = manchesterEncode2Bytes(crc);
manchester[10] = (t1 >> 8) & 0xFF;
manchester[11] = t1 & 0xFF;
// move left 4 bits left 4 bits - Now that we have the CRC we need to re-align the data.
for (int i = 1; i < 12; i++)
manchester[i] = (manchester[i] << 4) + (manchester[i + 1] >> 4);
// Add trailing 1010 (11)
manchester[11] |= (1 << 3);
manchester[11] |= (1 << 1);
// move into tag blocks
for (int i = 0; i < 12; i++)
blocks[1 + (i / 4)] += (manchester[i] << (8 * (3 - i % 4)));
} }
// Paradox - FSK2a, data rate 50, 3 data blocks // Paradox - FSK2a, data rate 50, 3 data blocks
@ -355,12 +386,15 @@ static int CmdParadoxSim(const char *Cmd) {
CLIParserInit(&ctx, "lf paradox sim", CLIParserInit(&ctx, "lf paradox sim",
"Enables simulation of paradox card with specified card number.\n" "Enables simulation of paradox card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.", "Simulation runs until the button is pressed or another USB command is issued.",
"lf paradox sim --raw 0f55555695596a6a9999a59a" "lf paradox sim --raw 0f55555695596a6a9999a59a -> simulate tag\n"
"lf paradox sim --fc 96 --cn 40426 -> simulate tag with fc and cn\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_str0("r", "raw", "<hex>", " raw hex data. 12 bytes"), arg_str0("r", "raw", "<hex>", "raw hex data. 12 bytes"),
arg_u64_0(NULL, "fc", "<dec>", "facility code"),
arg_u64_0(NULL, "cn", "<dec>", "card number"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -369,13 +403,32 @@ static int CmdParadoxSim(const char *Cmd) {
// skip first block, 3*4 = 12 bytes left // skip first block, 3*4 = 12 bytes left
uint8_t raw[12] = {0}; uint8_t raw[12] = {0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len); CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
uint32_t fc = arg_get_u32_def(ctx, 2, 0);
uint32_t cn = arg_get_u32_def(ctx, 3, 0);
CLIParserFree(ctx); CLIParserFree(ctx);
if (raw_len != 12) { if ((fc || cn) && raw_len != 0) {
PrintAndLogEx(ERR, "Data must be 12 bytes (24 HEX characters) %d", raw_len); PrintAndLogEx(FAILED, "Can't specify both FC/CN and RAW at the same time");
return PM3_EINVARG; return PM3_EINVARG;
} }
if (fc > 999 || cn > 99999) {
PrintAndLogEx(FAILED, "FC has a max value of 999 and CN has a max value of 99999");
return PM3_EINVARG;
}
if (raw_len != 0) {
if (raw_len != 12) {
PrintAndLogEx(ERR, "Data must be 12 bytes (24 HEX characters) %d", raw_len);
return PM3_EINVARG;
}
} else {
uint32_t blocks[4] = {0};
GetParadoxBits(fc, cn, blocks);
for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) {
num_to_bytes(blocks[i], sizeof(uint32_t), raw + ((i - 1) * 4));
}
}
PrintAndLogEx(SUCCESS, "Simulating Paradox - raw " _YELLOW_("%s"), sprint_hex_inrow(raw, sizeof(raw))); PrintAndLogEx(SUCCESS, "Simulating Paradox - raw " _YELLOW_("%s"), sprint_hex_inrow(raw, sizeof(raw)));
uint8_t bs[sizeof(raw) * 8]; uint8_t bs[sizeof(raw) * 8];
@ -404,21 +457,8 @@ static int CmdParadoxSim(const char *Cmd) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
/*
if (sscanf(Cmd, "%u %u", &fc, &cn) != 2) return usage_lf_paradox_sim();
facilitycode = (fc & 0x000000FF);
cardnumber = (cn & 0x0000FFFF);
// if ( GetParadoxBits(facilitycode, cardnumber, bs) != PM3_SUCCESS) {
// PrintAndLogEx(ERR, "Error with tag bitstream generation.");
// return 1;
// }
PrintAndLogEx(NORMAL, "Simulating Paradox - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber);
*/
static command_t CommandTable[] = { static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"}, {"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdParadoxDemod, AlwaysAvailable, "demodulate a Paradox FSK tag from the GraphBuffer"}, {"demod", CmdParadoxDemod, AlwaysAvailable, "demodulate a Paradox FSK tag from the GraphBuffer"},

View file

@ -22,6 +22,6 @@
int CmdLFParadox(const char *Cmd); int CmdLFParadox(const char *Cmd);
int demodParadox(bool verbose); int demodParadox(bool verbose, bool oldChksum);
int detectParadox(uint8_t *dest, size_t *size, int *wave_start_idx); int detectParadox(uint8_t *dest, size_t *size, int *wave_start_idx);
#endif #endif

View file

@ -316,9 +316,9 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s
int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data, size_t datalen, bool verbose, void (*callback)(json_t *), savePaths_t e_save_path) { int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data, size_t datalen, bool verbose, void (*callback)(json_t *), savePaths_t e_save_path) {
if (ftype != jsfCustom) { if (ftype != jsfCustom) {
if (data == NULL || datalen == 0) { if (data == NULL || datalen == 0) {
return PM3_EINVARG; return PM3_EINVARG;
} }
} }
char *fileName = newfilenamemcopyEx(preferredName, ".json", e_save_path); char *fileName = newfilenamemcopyEx(preferredName, ".json", e_save_path);
@ -2032,8 +2032,8 @@ int searchFile(char **foundpath, const char *pm3dir, const char *searchname, con
PrintAndLogEx(FAILED, "Error - can't find `" _YELLOW_("%s") "`", filename); PrintAndLogEx(FAILED, "Error - can't find `" _YELLOW_("%s") "`", filename);
} }
} }
free(filename); free(filename);
return res; return res;
} }
int pm3_load_dump(const char *fn, void **pdump, size_t *dumplen, size_t maxdumplen) { int pm3_load_dump(const char *fn, void **pdump, size_t *dumplen, size_t maxdumplen) {

View file

@ -424,7 +424,7 @@ int DetectHID(uint8_t *d, uint16_t manufacture) {
int convert_mad_to_arr(uint8_t *in, uint16_t ilen, uint8_t *out, uint16_t *olen) { int convert_mad_to_arr(uint8_t *in, uint16_t ilen, uint8_t *out, uint16_t *olen) {
if (in == NULL || out == NULL || ilen == 0 ) { if (in == NULL || out == NULL || ilen == 0) {
return PM3_EINVARG; return PM3_EINVARG;
} }
@ -464,7 +464,7 @@ int convert_mad_to_arr(uint8_t *in, uint16_t ilen, uint8_t *out, uint16_t *olen)
// copy to out (skip ST) // copy to out (skip ST)
memcpy(out, tmp, sizeof(tmp) - MFBLOCK_SIZE); memcpy(out, tmp, sizeof(tmp) - MFBLOCK_SIZE);
out += sizeof(tmp) - MFBLOCK_SIZE; out += sizeof(tmp) - MFBLOCK_SIZE;
*olen += sizeof(tmp) -MFBLOCK_SIZE; *olen += sizeof(tmp) - MFBLOCK_SIZE;
} }
} }
return PM3_SUCCESS; return PM3_SUCCESS;

View file

@ -917,10 +917,10 @@ static int ndefDecodeExternal_record(NDEFHeader_t *ndef) {
} }
PrintAndLogEx(INFO PrintAndLogEx(INFO
, " URN... " _GREEN_("urn:nfc:ext:%.*s") , " URN... " _GREEN_("urn:nfc:ext:%.*s")
, (int)ndef->TypeLen , (int)ndef->TypeLen
, ndef->Type , ndef->Type
); );
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Payload [%zu]...", ndef->PayloadLen); PrintAndLogEx(INFO, "Payload [%zu]...", ndef->PayloadLen);

View file

@ -360,7 +360,8 @@ const static vocabulory_t vocabulory[] = {
{ 0, "hf mf gsave" }, { 0, "hf mf gsave" },
{ 0, "hf mf gsetblk" }, { 0, "hf mf gsetblk" },
{ 0, "hf mf gview" }, { 0, "hf mf gview" },
{ 0, "hf mf gdmconfig" }, { 0, "hf mf gdmcfg" },
{ 0, "hf mf gdmsetcfg" },
{ 0, "hf mf gdmsetblk" }, { 0, "hf mf gdmsetblk" },
{ 0, "hf mf ndefformat" }, { 0, "hf mf ndefformat" },
{ 0, "hf mf ndefread" }, { 0, "hf mf ndefread" },

View file

@ -1354,9 +1354,10 @@
"offline": false, "offline": false,
"options": [ "options": [
"-h, --help This help", "-h, --help This help",
"-f, --file <fn> (optional) filename, if no <name> UID will be used as filename" "-f, --file <fn> (optional) filename, if no <name> UID will be used as filename",
"--ns no save to file"
], ],
"usage": "hf 14b dump [-h] [-f <fn>]" "usage": "hf 14b dump [-h] [-f <fn>] [--ns]"
}, },
"hf 14b help": { "hf 14b help": {
"command": "hf 14b help", "command": "hf 14b help",
@ -4218,9 +4219,10 @@
"--mini MIFARE Classic Mini / S20", "--mini MIFARE Classic Mini / S20",
"--1k MIFARE Classic 1k / S50 (def)", "--1k MIFARE Classic 1k / S50 (def)",
"--2k MIFARE Classic/Plus 2k", "--2k MIFARE Classic/Plus 2k",
"--4k MIFARE Classic 4k / S70" "--4k MIFARE Classic 4k / S70",
"--ns no save to file"
], ],
"usage": "hf mf dump [-h] [-f <fn>] [-k <fn>] [--mini] [--1k] [--2k] [--4k]" "usage": "hf mf dump [-h] [-f <fn>] [-k <fn>] [--mini] [--1k] [--2k] [--4k] [--ns]"
}, },
"hf mf ecfill": { "hf mf ecfill": {
"command": "hf mf ecfill", "command": "hf mf ecfill",
@ -4368,9 +4370,10 @@
"--1k MIFARE Classic 1k / S50 (def)", "--1k MIFARE Classic 1k / S50 (def)",
"--2k MIFARE Classic/Plus 2k", "--2k MIFARE Classic/Plus 2k",
"--4k MIFARE Classic 4k / S70", "--4k MIFARE Classic 4k / S70",
"-v, --verbose verbose output" "-v, --verbose verbose output",
"--sk Save extracted keys to file"
], ],
"usage": "hf mf eview [-hv] [--mini] [--1k] [--2k] [--4k]" "usage": "hf mf eview [-hv] [--mini] [--1k] [--2k] [--4k] [--sk]"
}, },
"hf mf fchk": { "hf mf fchk": {
"command": "hf mf fchk", "command": "hf mf fchk",
@ -4400,18 +4403,18 @@
], ],
"usage": "hf mf fchk [-h] [-k <hex>]... [--mini] [--1k] [--2k] [--4k] [--emu] [--dump] [--mem] [-f <fn>]" "usage": "hf mf fchk [-h] [-k <hex>]... [--mini] [--1k] [--2k] [--4k] [--emu] [--dump] [--mem] [-f <fn>]"
}, },
"hf mf gdmconfig": { "hf mf gdmcfg": {
"command": "hf mf gdmconfig", "command": "hf mf gdmcfg",
"description": "Get configuration data from magic gen4 GDM card.", "description": "Get configuration data from magic gen4 GDM card.",
"notes": [ "notes": [
"hf mf gdmconfig" "hf mf gdmcfg"
], ],
"offline": false, "offline": false,
"options": [ "options": [
"-h, --help This help", "-h, --help This help",
"-k, --key <hex> key 6 bytes" "-k, --key <hex> key 6 bytes"
], ],
"usage": "hf mf gdmconfig [-h] [-k <hex>]" "usage": "hf mf gdmcfg [-h] [-k <hex>]"
}, },
"hf mf gdmsetblk": { "hf mf gdmsetblk": {
"command": "hf mf gdmsetblk", "command": "hf mf gdmsetblk",
@ -4431,6 +4434,19 @@
], ],
"usage": "hf mf gdmsetblk [-hab] --blk <dec> [-d <hex>] [-k <hex>] [--force]" "usage": "hf mf gdmsetblk [-hab] --blk <dec> [-d <hex>] [-k <hex>] [--force]"
}, },
"hf mf gdmsetcfg": {
"command": "hf mf gdmsetcfg",
"description": "Set configuration data on a magic gen4 GDM card",
"notes": [
"hf mf gdmsetcfg -d 850000000000000000005A5A00000008"
],
"offline": false,
"options": [
"-h, --help This help",
"-d, --data <hex> bytes to write, 16 hex bytes"
],
"usage": "hf mf gdmsetcfg [-h] -d <hex>"
},
"hf mf gen3blk": { "hf mf gen3blk": {
"command": "hf mf gen3blk", "command": "hf mf gen3blk",
"description": "Overwrite full manufacturer block for magic Gen3 card - You can specify part of manufacturer block as 4/7-bytes for UID change only", "description": "Overwrite full manufacturer block for magic Gen3 card - You can specify part of manufacturer block as 4/7-bytes for UID change only",
@ -4902,6 +4918,7 @@
"hf mf value --blk 16 -k FFFFFFFFFFFF --inc 10", "hf mf value --blk 16 -k FFFFFFFFFFFF --inc 10",
"hf mf value --blk 16 -k FFFFFFFFFFFF -b --dec 10", "hf mf value --blk 16 -k FFFFFFFFFFFF -b --dec 10",
"hf mf value --blk 16 -k FFFFFFFFFFFF -b --get", "hf mf value --blk 16 -k FFFFFFFFFFFF -b --get",
"hf mf value --blk 16 -k FFFFFFFFFFFF --res --transfer 30 --tk FFFFFFFFFFFF -> transfer block 16 value to block 30 (even if block can't be incremented by ACL)",
"hf mf value --get -d 87D612007829EDFF87D6120011EE11EE" "hf mf value --get -d 87D612007829EDFF87D6120011EE11EE"
], ],
"offline": true, "offline": true,
@ -4910,14 +4927,19 @@
"-k, --key <hex> key, 6 hex bytes", "-k, --key <hex> key, 6 hex bytes",
"-a input key type is key A (def)", "-a input key type is key A (def)",
"-b input key type is key B", "-b input key type is key B",
"--inc <dec> Incremenet value by X (0 - 2147483647)", "--inc <dec> Increment value by X (0 - 2147483647)",
"--dec <dec> Dcrement value by X (0 - 2147483647)", "--dec <dec> Decrement value by X (0 - 2147483647)",
"--set <dec> Set value to X (-2147483647 - 2147483647)", "--set <dec> Set value to X (-2147483647 - 2147483647)",
"--transfer <dec> Transfer value to other block (after inc/dec/restore)",
"--tkey <hex> transfer key, 6 hex bytes (if transfer is preformed to other sector)",
"--ta transfer key type is key A (def)",
"--tb transfer key type is key B",
"--get Get value from block", "--get Get value from block",
"--res Restore (copy value to card buffer, should be used with --transfer)",
"--blk <dec> block number", "--blk <dec> block number",
"-d, --data <hex> block data to extract values from (16 hex bytes)" "-d, --data <hex> block data to extract values from (16 hex bytes)"
], ],
"usage": "hf mf value [-hab] [-k <hex>] [--inc <dec>] [--dec <dec>] [--set <dec>] [--get] [--blk <dec>] [-d <hex>]" "usage": "hf mf value [-hab] [-k <hex>] [--inc <dec>] [--dec <dec>] [--set <dec>] [--transfer <dec>] [--tkey <hex>] [--ta] [--tb] [--get] [--res] [--blk <dec>] [-d <hex>]"
}, },
"hf mf view": { "hf mf view": {
"command": "hf mf view", "command": "hf mf view",
@ -4929,9 +4951,10 @@
"options": [ "options": [
"-h, --help This help", "-h, --help This help",
"-f, --file <fn> filename of dump", "-f, --file <fn> filename of dump",
"-v, --verbose verbose output" "-v, --verbose verbose output",
"--sk Save extracted keys to file"
], ],
"usage": "hf mf view [-hv] -f <fn>" "usage": "hf mf view [-hv] -f <fn> [--sk]"
}, },
"hf mf wipe": { "hf mf wipe": {
"command": "hf mf wipe", "command": "hf mf wipe",
@ -6146,7 +6169,7 @@
}, },
"hf mfp commitp": { "hf mfp commitp": {
"command": "hf mfp commitp", "command": "hf mfp commitp",
"description": "Executes Commit Perso command. Can be used in SL0 mode only.", "description": "Executes Commit Perso command. Can be used in SL0 mode only. OBS! This command will not be executed if CardConfigKey, CardMasterKey and L3SwitchKey AES keys are not written.",
"notes": [ "notes": [
"hf mfp commitp" "hf mfp commitp"
], ],
@ -6246,9 +6269,9 @@
"-b, --keyb Use key B (def: keyA)", "-b, --keyb Use key B (def: keyA)",
"-p, --plain Plain communication mode between reader and card", "-p, --plain Plain communication mode between reader and card",
"--blk <0..255> Block number", "--blk <0..255> Block number",
"--key <hex> Key, 16 hex bytes" "-k, --key <hex> Key, 16 hex bytes"
], ],
"usage": "hf mfp rdbl [-hvbp] [-n <dec>] --blk <0..255> [--key <hex>]" "usage": "hf mfp rdbl [-hvbp] [-n <dec>] --blk <0..255> [-k <hex>]"
}, },
"hf mfp rdsc": { "hf mfp rdsc": {
"command": "hf mfp rdsc", "command": "hf mfp rdsc",
@ -6335,9 +6358,10 @@
"-k, --key <hex> Key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)", "-k, --key <hex> Key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)",
"-l Swap entered key's endianness", "-l Swap entered key's endianness",
"-p, --page <dec> Manually set start page number to start from", "-p, --page <dec> Manually set start page number to start from",
"-q, --qty <dec> Manually set number of pages to dump" "-q, --qty <dec> Manually set number of pages to dump",
"--ns no save to file"
], ],
"usage": "hf mfu dump [-hl] [-f <fn>] [-k <hex>] [-p <dec>] [-q <dec>]" "usage": "hf mfu dump [-hl] [-f <fn>] [-k <hex>] [-p <dec>] [-q <dec>] [--ns]"
}, },
"hf mfu eload": { "hf mfu eload": {
"command": "hf mfu eload", "command": "hf mfu eload",
@ -6565,7 +6589,7 @@
}, },
"hf mfu tamper": { "hf mfu tamper": {
"command": "hf mfu tamper", "command": "hf mfu tamper",
"description": "Set the congiguration of the NTAG 213TT tamper feature Supports: NTAG 213TT", "description": "Set the configuration of the NTAG 213TT tamper feature Supports: NTAG 213TT",
"notes": [ "notes": [
"hf mfu tamper -e -> enable tamper feature", "hf mfu tamper -e -> enable tamper feature",
"hf mfu tamper -d -> disable tamper feature", "hf mfu tamper -d -> disable tamper feature",
@ -8039,15 +8063,19 @@
"command": "lf em 4x50 brute", "command": "lf em 4x50 brute",
"description": "Tries to bruteforce the password of a EM4x50 card. Function can be stopped by pressing pm3 button.", "description": "Tries to bruteforce the password of a EM4x50 card. Function can be stopped by pressing pm3 button.",
"notes": [ "notes": [
"lf em 4x50 brute --first 12330000 --last 12340000 -> tries pwds from 0x12330000 to 0x1234000000" "lf em 4x50 brute --mode range --begin 12330000 --end 12340000 -> tries pwds from 0x12330000 to 0x12340000",
"lf em 4x50 brute --mode charset --digits --uppercase -> tries all combinations of ASCII codes for digits and uppercase letters"
], ],
"offline": false, "offline": false,
"options": [ "options": [
"-h, --help This help", "-h, --help This help",
"--first <hex> first password (start), 4 bytes, lsb", "--mode <str> Bruteforce mode (range|charset)",
"--last <hex> last password (stop), 4 bytes, lsb" "--begin <hex> Range mode - start of the key range",
"--end <hex> Range mode - end of the key range",
"--digits Charset mode - include ASCII codes for digits",
"--uppercase Charset mode - include ASCII codes for uppercase letters"
], ],
"usage": "lf em 4x50 brute [-h] --first <hex> --last <hex>" "usage": "lf em 4x50 brute [-h] --mode <str> [--begin <hex>] [--end <hex>] [--digits] [--uppercase]"
}, },
"lf em 4x50 chk": { "lf em 4x50 chk": {
"command": "lf em 4x50 chk", "command": "lf em 4x50 chk",
@ -9630,13 +9658,14 @@
"command": "lf paradox demod", "command": "lf paradox demod",
"description": "Try to find Paradox preamble, if found decode / descramble data", "description": "Try to find Paradox preamble, if found decode / descramble data",
"notes": [ "notes": [
"lf paradox demod" "lf paradox demod --old -> Display previous checksum version"
], ],
"offline": true, "offline": true,
"options": [ "options": [
"-h, --help This help" "-h, --help This help",
"--old optional - Display previous checksum version"
], ],
"usage": "lf paradox demod [-h]" "usage": "lf paradox demod [-h] [--old]"
}, },
"lf paradox help": { "lf paradox help": {
"command": "lf paradox help", "command": "lf paradox help",
@ -9650,27 +9679,32 @@
"command": "lf paradox reader", "command": "lf paradox reader",
"description": "read a Paradox tag", "description": "read a Paradox tag",
"notes": [ "notes": [
"lf Paradox reader -@ -> continuous reader mode" "lf paradox reader -@ -> continuous reader mode",
"lf paradox reader --old -> Display previous checksum version"
], ],
"offline": false, "offline": false,
"options": [ "options": [
"-h, --help This help", "-h, --help This help",
"-@ optional - continuous reader mode" "-@ optional - continuous reader mode",
"--old optional - Display previous checksum version"
], ],
"usage": "lf paradox reader [-h@]" "usage": "lf paradox reader [-h@] [--old]"
}, },
"lf paradox sim": { "lf paradox sim": {
"command": "lf paradox sim", "command": "lf paradox sim",
"description": "Enables simulation of paradox card with specified card number. Simulation runs until the button is pressed or another USB command is issued.", "description": "Enables simulation of paradox card with specified card number. Simulation runs until the button is pressed or another USB command is issued.",
"notes": [ "notes": [
"lf paradox sim --raw 0f55555695596a6a9999a59a" "lf paradox sim --raw 0f55555695596a6a9999a59a -> simulate tag",
"lf paradox sim --fc 96 --cn 40426 -> simulate tag with fc and cn"
], ],
"offline": false, "offline": false,
"options": [ "options": [
"-h, --help This help", "-h, --help This help",
"-r, --raw <hex> raw hex data. 12 bytes" "-r, --raw <hex> raw hex data. 12 bytes",
"--fc <dec> facility code",
"--cn <dec> card number"
], ],
"usage": "lf paradox sim [-h] [-r <hex>]" "usage": "lf paradox sim [-h] [-r <hex>] [--fc <dec>] [--cn <dec>]"
}, },
"lf pcf7931 config": { "lf pcf7931 config": {
"command": "lf pcf7931 config", "command": "lf pcf7931 config",
@ -10199,12 +10233,13 @@
"-f, --file <fn> filename (default is generated on blk 0)", "-f, --file <fn> filename (default is generated on blk 0)",
"-o, --override override, force pwd read despite danger to card", "-o, --override override, force pwd read despite danger to card",
"-p, --pwd <hex> password (4 hex bytes)", "-p, --pwd <hex> password (4 hex bytes)",
"--ns no save",
"--r0 downlink - fixed bit length", "--r0 downlink - fixed bit length",
"--r1 downlink - long leading reference", "--r1 downlink - long leading reference",
"--r2 downlink - leading zero", "--r2 downlink - leading zero",
"--r3 downlink - 1 of 4 coding reference" "--r3 downlink - 1 of 4 coding reference"
], ],
"usage": "lf t55xx dump [-ho] [-f <fn>] [-p <hex>] [--r0] [--r1] [--r2] [--r3]" "usage": "lf t55xx dump [-ho] [-f <fn>] [-p <hex>] [--ns] [--r0] [--r1] [--r2] [--r3]"
}, },
"lf t55xx help": { "lf t55xx help": {
"command": "lf t55xx help", "command": "lf t55xx help",
@ -10867,7 +10902,7 @@
"options": [ "options": [
"-h, --help This help", "-h, --help This help",
"-f, --file <fn> SPIFFS file to view", "-f, --file <fn> SPIFFS file to view",
"-c, --cols <dec> column breaks (def 32)" "-c, --cols <dec> column breaks (def 16)"
], ],
"usage": "mem spiffs view [-h] -f <fn> [-c <dec>]" "usage": "mem spiffs view [-h] -f <fn> [-c <dec>]"
}, },
@ -11592,7 +11627,7 @@
}, },
"script help": { "script help": {
"command": "script help", "command": "script help",
"description": "This is a feature to run Lua/Cmd/Python scripts. You can place scripts within the luascripts/cmdscripts/pyscripts folders. --------------------------------------------------------------------------------------- script list available offline: yes", "description": "This is a feature to run Lua/Cmd scripts. You can place scripts within the luascripts/cmdscripts folders. --------------------------------------------------------------------------------------- script list available offline: yes",
"notes": [], "notes": [],
"offline": true, "offline": true,
"options": [], "options": [],
@ -11987,8 +12022,9 @@
} }
}, },
"metadata": { "metadata": {
"commands_extracted": 754, "commands_extracted": 755,
"extracted_by": "PM3Help2JSON v1.00", "extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2023-03-26T15:04:49" "extracted_on": "2023-06-04T15:36:56"
} }
} }

View file

@ -523,7 +523,8 @@ Check column "offline" for their availability.
|`hf mf gsave `|N |`Save dump from card into file or emulator` |`hf mf gsave `|N |`Save dump from card into file or emulator`
|`hf mf gsetblk `|N |`Write block to card` |`hf mf gsetblk `|N |`Write block to card`
|`hf mf gview `|N |`View card` |`hf mf gview `|N |`View card`
|`hf mf gdmconfig `|N |`Read config block from card` |`hf mf gdmcfg `|N |`Read config block from card`
|`hf mf gdmsetcfg `|N |`Write config block to card`
|`hf mf gdmsetblk `|N |`Write block to card` |`hf mf gdmsetblk `|N |`Write block to card`
|`hf mf ndefformat `|N |`Format MIFARE Classic Tag as NFC Tag` |`hf mf ndefformat `|N |`Format MIFARE Classic Tag as NFC Tag`
|`hf mf ndefread `|N |`Read and print NDEF records from card` |`hf mf ndefread `|N |`Read and print NDEF records from card`
@ -568,7 +569,7 @@ Check column "offline" for their availability.
|`hf mfu restore `|N |`Restore a dump onto a MFU MAGIC tag` |`hf mfu restore `|N |`Restore a dump onto a MFU MAGIC tag`
|`hf mfu view `|Y |`Display content from tag dump file` |`hf mfu view `|Y |`Display content from tag dump file`
|`hf mfu wrbl `|N |`Write block` |`hf mfu wrbl `|N |`Write block`
|`hf mfu tamper `|N |`Cofigure the tamper feature on an NTAG 213TT` |`hf mfu tamper `|N |`Configure the tamper feature on an NTAG 213TT`
|`hf mfu eload `|N |`Load Ultralight dump file into emulator memory` |`hf mfu eload `|N |`Load Ultralight dump file into emulator memory`
|`hf mfu esave `|N |`Save Ultralight dump file from emulator memory` |`hf mfu esave `|N |`Save Ultralight dump file from emulator memory`
|`hf mfu eview `|N |`View emulator memory` |`hf mfu eview `|N |`View emulator memory`
@ -874,7 +875,7 @@ Check column "offline" for their availability.
|command |offline |description |command |offline |description
|------- |------- |----------- |------- |------- |-----------
|`lf em 4x50 help `|Y |`This help` |`lf em 4x50 help `|Y |`This help`
|`lf em 4x50 brute `|N |`Simple bruteforce attack to find password` |`lf em 4x50 brute `|N |`Bruteforce attack to find password`
|`lf em 4x50 chk `|N |`Check passwords from dictionary` |`lf em 4x50 chk `|N |`Check passwords from dictionary`
|`lf em 4x50 dump `|N |`Dump EM4x50 tag` |`lf em 4x50 dump `|N |`Dump EM4x50 tag`
|`lf em 4x50 info `|N |`Tag information` |`lf em 4x50 info `|N |`Tag information`