Merge branch 'RfidResearchGroup:master' into hf_mf_gen4_rewrite

This commit is contained in:
Didier Arenzana 2022-11-13 00:46:07 +01:00 committed by GitHub
commit 2f49b2c8cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 142 additions and 43 deletions

View file

@ -3,6 +3,9 @@ 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]
- Changed `hf mf hardnested` - now can detect and use MFC EV1 signature sector key (@iceman1001)
- Changed `hf mf autopwn` - now can detect and use MFC EV1 signature sector key (@iceman1001)
- Fixed `pm3` shell script now automatically detects WSL2 with USBIPD serial ports (@iceman1001)
- Fixed `trace list -c` - annotation of CRC bytes now is colored or squared if no ansi colors is supported (@iceman1001) - Fixed `trace list -c` - annotation of CRC bytes now is colored or squared if no ansi colors is supported (@iceman1001)
- Fixed `trace list -t mf` - now also finds UID if anticollision is partial captured, to be used for mfkey (@iceman1001) - Fixed `trace list -t mf` - now also finds UID if anticollision is partial captured, to be used for mfkey (@iceman1001)
- Added `hf mf gload, ggetblk, gsetblk` for Gen4 GTU in mifare classic mode (@DidierA) - Added `hf mf gload, ggetblk, gsetblk` for Gen4 GTU in mifare classic mode (@DidierA)

View file

@ -10,7 +10,32 @@ AEA684A6DAB23278 # AA1
F0E1D2C3B4A59687 # Kd from PicoPass 2k documentation F0E1D2C3B4A59687 # Kd from PicoPass 2k documentation
5CBCF1DA45D5FB4F # PicoPass Default Exchange Key 5CBCF1DA45D5FB4F # PicoPass Default Exchange Key
31ad7ebd2f282168 # From HID multiclassSE reader 31ad7ebd2f282168 # From HID multiclassSE reader
6EFD46EFCBB3C875 # From pastebin: https://pastebin.com/uHqpjiuU #
E033CA419AEE43F9 # From pastebin: https://pastebin.com/uHqpjiuU # From pastebin: https://pastebin.com/uHqpjiuU
2020666666668888 # iCopy-X iCL tags 6EFD46EFCBB3C875
6666202066668888 # iCopy-X iCS tags reversed from the SOs E033CA419AEE43F9
#
# iCopy-x DRM keys
2020666666668888 # iCL tags
6666202066668888 # iCS tags reversed from the SOs
#
# default picopass KD / Page 0 / Book 1
FDCB5A52EA8F3090
237FF9079863DF44
5ADC25FB27181D32
83B881F2936B2E49
43644E61EE866BA5
897034143D016080
82D17B44C0122963
4895CA7DE65E2025
DADAD4C57BE271B7
E41E9EDEF5719ABF
293D275EC3AF9C7F
C3C169251B8A70FB
F41DAF58B20C8B91
28877A609EC0DD2B
66584C91EE80D5E5
C1B74D7478053AE2
#
# default iCLASS RFIDeas
6B65797374726B72

View file

@ -2318,7 +2318,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
} }
uint8_t signature[32] = {0}; uint8_t signature[32] = {0};
res = detect_mfc_ev1_signature(signature); res = read_mfc_ev1_signature(signature);
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature)); mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature));
} }

View file

@ -1607,6 +1607,7 @@ static int CmdHFiClassDump(const char *Cmd) {
arg_lit0(NULL, "raw", "raw, the key is interpreted as raw block 3/4"), arg_lit0(NULL, "raw", "raw, the key is interpreted as raw block 3/4"),
arg_lit0(NULL, "nr", "replay of NR/MAC"), arg_lit0(NULL, "nr", "replay of NR/MAC"),
arg_lit0("z", "dense", "dense dump output style"), arg_lit0("z", "dense", "dense dump output style"),
arg_lit0(NULL, "force", "force unsecure card read"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -1691,6 +1692,7 @@ static int CmdHFiClassDump(const char *Cmd) {
bool rawkey = arg_get_lit(ctx, 7); bool rawkey = arg_get_lit(ctx, 7);
bool use_replay = arg_get_lit(ctx, 8); bool use_replay = arg_get_lit(ctx, 8);
bool dense_output = g_session.dense_output || arg_get_lit(ctx, 9); bool dense_output = g_session.dense_output || arg_get_lit(ctx, 9);
bool force = arg_get_lit(ctx, 10);
CLIParserFree(ctx); CLIParserFree(ctx);
@ -1757,6 +1759,12 @@ static int CmdHFiClassDump(const char *Cmd) {
} }
} }
//
if (force) {
pagemap = PICOPASS_NON_SECURE_PAGEMODE;
PrintAndLogEx(INFO, "Forcing NON SECURE PAGE dumping");
}
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
PrintAndLogEx(INFO, "Dumping all available memory, block 3 - %u (0x%02x)", app_limit1, app_limit1); PrintAndLogEx(INFO, "Dumping all available memory, block 3 - %u (0x%02x)", app_limit1, app_limit1);
if (auth) { if (auth) {
@ -3773,7 +3781,7 @@ static int CmdHFiClassEncode(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass encode", CLIParserInit(&ctx, "hf iclass encode",
"Encode binary wiegand to block 7\n" "Encode binary wiegand to block 7,8,9\n"
"Use either --bin or --wiegand/--fc/--cn", "Use either --bin or --wiegand/--fc/--cn",
"hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337\n" "hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337\n"
"hf iclass encode --fc 31 --cn 337 --ki 0 -> FC 31 CN 337\n" "hf iclass encode --fc 31 --cn 337 --ki 0 -> FC 31 CN 337\n"
@ -3925,8 +3933,12 @@ static int CmdHFiClassEncode(const char *Cmd) {
return PM3_ESOFT; return PM3_ESOFT;
} }
// iceman: only for formats w length smaller than 37.
// Needs a check.
// increase length to allow setting bit just above real data
packed.Length++;
// Set sentinel bit // Set sentinel bit
packed.Length++;// increase length to allow setting bit just above real data
set_bit_by_position(&packed, true, 0); set_bit_by_position(&packed, true, 0);
#ifdef HOST_LITTLE_ENDIAN #ifdef HOST_LITTLE_ENDIAN
@ -3958,7 +3970,7 @@ static int CmdHFiClassEncode(const char *Cmd) {
PrintAndLogEx(SUCCESS, "Write block %d/0x0%x ( " _GREEN_("ok") " ) --> " _YELLOW_("%s"), 6 + i, 6 + i, sprint_hex_inrow(credential + (i * 8), 8)); PrintAndLogEx(SUCCESS, "Write block %d/0x0%x ( " _GREEN_("ok") " ) --> " _YELLOW_("%s"), 6 + i, 6 + i, sprint_hex_inrow(credential + (i * 8), 8));
break; break;
default: default:
PrintAndLogEx(SUCCESS, "Write block %d/0x0%x ( " _RED_("fail") " )", 6 + i, 6 + i); PrintAndLogEx(INFO, "Write block %d/0x0%x ( " _RED_("fail") " )", 6 + i, 6 + i);
break; break;
} }
} }

View file

@ -864,7 +864,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
rights[sectorNo][3] = ((data[7] & 0x80) >> 5) | ((data[8] & 0x8) >> 2) | ((data[8] & 0x80) >> 7); // C1C2C3 for sector trailer rights[sectorNo][3] = ((data[7] & 0x80) >> 5) | ((data[8] & 0x8) >> 2) | ((data[8] & 0x80) >> 7); // C1C2C3 for sector trailer
break; break;
} else if (tries == (MIFARE_SECTOR_RETRY / 2)) { // after half unsuccessful tries, give key B a go } else if (tries == (MIFARE_SECTOR_RETRY / 2)) { // after half unsuccessful tries, give key B a go
PrintAndLogEx(WARNING, "\ntrying with key B instead...", sectorNo); PrintAndLogEx(WARNING, "\ntrying with key B instead...");
current_key = MF_KEY_B; current_key = MF_KEY_B;
PrintAndLogEx(INFO, "." NOLF); PrintAndLogEx(INFO, "." NOLF);
} else if (tries == (MIFARE_SECTOR_RETRY - 1)) { // on last try set defaults } else if (tries == (MIFARE_SECTOR_RETRY - 1)) { // on last try set defaults
@ -1841,19 +1841,22 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf hardnested", CLIParserInit(&ctx, "hf mf hardnested",
"Nested attack for hardened MIFARE Classic cards.\n" "Nested attack for hardened MIFARE Classic cards.\n"
"if card is EV1, command can detect and use known key see example below\n"
"\n"
"`--i<X>` set type of SIMD instructions. Without this flag programs autodetect it.\n" "`--i<X>` set type of SIMD instructions. Without this flag programs autodetect it.\n"
" or \n" " or \n"
" hf mf hardnested -r --tk [known target key]\n" " hf mf hardnested -r --tk [known target key]\n"
"Add the known target key to check if it is present in the remaining key space\n" "Add the known target key to check if it is present in the remaining key space\n"
" hf mf hardnested --blk 0 -a -k A0A1A2A3A4A5 --tblk 4 --ta --tk FFFFFFFFFFFF\n" " hf mf hardnested --blk 0 -a -k A0A1A2A3A4A5 --tblk 4 --ta --tk FFFFFFFFFFFF\n"
, ,
"hf mf hardnested --tblk 4 --ta --> works for MFC EV1\n"
"hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta\n" "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta\n"
"hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta -w\n" "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta -w\n"
"hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta -f nonces.bin -w -s\n" "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta -f nonces.bin -w -s\n"
"hf mf hardnested -r\n" "hf mf hardnested -r\n"
"hf mf hardnested -r --tk a0a1a2a3a4a5\n" "hf mf hardnested -r --tk a0a1a2a3a4a5\n"
"hf mf hardnested -t --tk a0a1a2a3a4a5\n" "hf mf hardnested -t --tk a0a1a2a3a4a5\n"
"hf mf hardnested --blk 0 -a -k a0a1a2a3a4a5 --tblk 4 --ta --tk FFFFFFFFFFFF" "hf mf hardnested --blk 0 -a -k a0a1a2a3a4a5 --tblk 4 --ta --tk FFFFFFFFFFFF\n"
); );
void *argtable[] = { void *argtable[] = {
@ -1976,7 +1979,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
SetSIMDInstr(SIMD_NONE); SetSIMDInstr(SIMD_NONE);
bool know_target_key = (trg_keylen); bool known_target_key = (trg_keylen);
if (nonce_file_read) { if (nonce_file_read) {
char *fptr = GenerateFilename("hf-mf-", "-nonces.bin"); char *fptr = GenerateFilename("hf-mf-", "-nonces.bin");
@ -2000,7 +2003,15 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", uid); snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", uid);
} }
if (know_target_key == false && nonce_file_read == false) { // detect MFC EV1 Signature
if (detect_mfc_ev1_signature() && keylen == 0) {
PrintAndLogEx(INFO, "MIFARE Classic EV1 card detected");
blockno = 69;
keytype = MF_KEY_B;
memcpy(key, g_mifare_signature_key_b, sizeof(g_mifare_signature_key_b));
}
if (known_target_key == false && nonce_file_read == false) {
// check if tag doesn't have static nonce // check if tag doesn't have static nonce
if (detect_classic_static_nonce() == NONCE_STATIC) { if (detect_classic_static_nonce() == NONCE_STATIC) {
@ -2021,7 +2032,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
trg_blockno, trg_blockno,
(trg_keytype == MF_KEY_B) ? 'B' : 'A', (trg_keytype == MF_KEY_B) ? 'B' : 'A',
trg_key[0], trg_key[1], trg_key[2], trg_key[3], trg_key[4], trg_key[5], trg_key[0], trg_key[1], trg_key[2], trg_key[3], trg_key[4], trg_key[5],
know_target_key ? "" : " (not set)" known_target_key ? "" : " (not set)"
); );
PrintAndLogEx(INFO, "File action: " _YELLOW_("%s") ", Slow: " _YELLOW_("%s") ", Tests: " _YELLOW_("%d"), PrintAndLogEx(INFO, "File action: " _YELLOW_("%s") ", Slow: " _YELLOW_("%s") ", Tests: " _YELLOW_("%d"),
nonce_file_write ? "write" : nonce_file_read ? "read" : "none", nonce_file_write ? "write" : nonce_file_read ? "read" : "none",
@ -2029,7 +2040,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
tests); tests);
uint64_t foundkey = 0; uint64_t foundkey = 0;
int16_t isOK = mfnestedhard(blockno, keytype, key, trg_blockno, trg_keytype, know_target_key ? trg_key : NULL, nonce_file_read, nonce_file_write, slow, tests, &foundkey, filename); int16_t isOK = mfnestedhard(blockno, keytype, key, trg_blockno, trg_keytype, known_target_key ? trg_key : NULL, nonce_file_read, nonce_file_write, slow, tests, &foundkey, filename);
if ((tests == 0) && IfPm3Iso14443a()) { if ((tests == 0) && IfPm3Iso14443a()) {
DropField(); DropField();
@ -2105,7 +2116,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
return PM3_EINVARG; return PM3_EINVARG;
} }
bool know_target_key = (keylen == 6); bool known_key = (keylen == 6);
uint8_t sectorno = arg_get_u32_def(ctx, 2, 0); uint8_t sectorno = arg_get_u32_def(ctx, 2, 0);
@ -2223,7 +2234,6 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
int bytes; int bytes;
// Settings // Settings
int prng_type = PM3_EUNDEF; int prng_type = PM3_EUNDEF;
int has_staticnonce;
uint8_t num_found_keys = 0; uint8_t num_found_keys = 0;
// ------------------------------ // ------------------------------
@ -2247,6 +2257,14 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
iso14a_card_select_t card; iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
// detect MFC EV1 Signature
bool is_ev1 = detect_mfc_ev1_signature();
if (is_ev1) {
// hidden sectors on MFC EV1
sector_cnt += 2;
}
// create/initialize key storage structure // create/initialize key storage structure
uint32_t e_sector_size = sector_cnt > sectorno ? sector_cnt : sectorno + 1; uint32_t e_sector_size = sector_cnt > sectorno ? sector_cnt : sectorno + 1;
res = initSectorTable(&e_sector, e_sector_size); res = initSectorTable(&e_sector, e_sector_size);
@ -2255,11 +2273,31 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
return PM3_EMALLOC; return PM3_EMALLOC;
} }
if (is_ev1) {
PrintAndLogEx(INFO, "MIFARE Classic EV1 card detected");
// Store the keys
e_sector[16].Key[MF_KEY_A] = bytes_to_num((uint8_t *)g_mifare_signature_key_a, sizeof(g_mifare_signature_key_a));
e_sector[16].foundKey[MF_KEY_A] = 'D';
e_sector[17].Key[MF_KEY_A] = bytes_to_num((uint8_t *)g_mifare_signature_key_a, sizeof(g_mifare_signature_key_a));
e_sector[17].foundKey[MF_KEY_A] = 'D';
e_sector[17].Key[MF_KEY_B] = bytes_to_num((uint8_t *)g_mifare_signature_key_b, sizeof(g_mifare_signature_key_b));
e_sector[17].foundKey[MF_KEY_B] = 'D';
// use found key if not supplied
if (known_key == false) {
known_key = true;
sectorno = 17;
keytype = MF_KEY_B;
memcpy(key, g_mifare_signature_key_b, sizeof(g_mifare_signature_key_b));
}
}
// read uid to generate a filename for the key file // read uid to generate a filename for the key file
char *fptr = GenerateFilename("hf-mf-", "-key.bin"); char *fptr = GenerateFilename("hf-mf-", "-key.bin");
// check if tag doesn't have static nonce // check if tag doesn't have static nonce
has_staticnonce = detect_classic_static_nonce(); int has_staticnonce = detect_classic_static_nonce();
// card prng type (weak=1 / hard=0 / select/card comm error = negative value) // card prng type (weak=1 / hard=0 / select/card comm error = negative value)
if (has_staticnonce == NONCE_NORMAL) { if (has_staticnonce == NONCE_NORMAL) {
@ -2276,7 +2314,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
if (verbose) { if (verbose) {
PrintAndLogEx(INFO, "======================= " _YELLOW_("SETTINGS") " ======================="); PrintAndLogEx(INFO, "======================= " _YELLOW_("SETTINGS") " =======================");
PrintAndLogEx(INFO, " card sectors .. " _YELLOW_("%d"), sector_cnt); PrintAndLogEx(INFO, " card sectors .. " _YELLOW_("%d"), sector_cnt);
PrintAndLogEx(INFO, " key supplied .. " _YELLOW_("%s"), know_target_key ? "True" : "False"); PrintAndLogEx(INFO, " key supplied .. " _YELLOW_("%s"), known_key ? "True" : "False");
PrintAndLogEx(INFO, " known sector .. " _YELLOW_("%d"), sectorno); PrintAndLogEx(INFO, " known sector .. " _YELLOW_("%d"), sectorno);
PrintAndLogEx(INFO, " keytype ....... " _YELLOW_("%c"), (keytype == MF_KEY_B) ? 'B' : 'A'); PrintAndLogEx(INFO, " keytype ....... " _YELLOW_("%c"), (keytype == MF_KEY_B) ? 'B' : 'A');
PrintAndLogEx(INFO, " known key ..... " _YELLOW_("%s"), sprint_hex(key, sizeof(key))); PrintAndLogEx(INFO, " known key ..... " _YELLOW_("%s"), sprint_hex(key, sizeof(key)));
@ -2298,7 +2336,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
uint64_t t1 = msclock(); uint64_t t1 = msclock();
// check the user supplied key // check the user supplied key
if (know_target_key == false) { if (known_key == false) {
PrintAndLogEx(WARNING, "no known key was supplied, key recovery might fail"); PrintAndLogEx(WARNING, "no known key was supplied, key recovery might fail");
} else { } else {
if (verbose) { if (verbose) {
@ -2318,7 +2356,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
++num_found_keys; ++num_found_keys;
} else { } else {
know_target_key = false; known_key = false;
PrintAndLogEx(FAILED, "Key is wrong. Can't authenticate to sector"_RED_("%3d") " key type "_RED_("%c") " key " _RED_("%s"), PrintAndLogEx(FAILED, "Key is wrong. Can't authenticate to sector"_RED_("%3d") " key type "_RED_("%c") " key " _RED_("%s"),
sectorno, sectorno,
(keytype == MF_KEY_B) ? 'B' : 'A', (keytype == MF_KEY_B) ? 'B' : 'A',
@ -2336,9 +2374,9 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
e_sector[i].foundKey[j] = 'U'; e_sector[i].foundKey[j] = 'U';
// If the user supplied secctor / keytype was wrong --> just be nice and correct it ;) // If the user supplied secctor / keytype was wrong --> just be nice and correct it ;)
if (know_target_key == false) { if (known_key == false) {
num_to_bytes(e_sector[i].Key[j], 6, key); num_to_bytes(e_sector[i].Key[j], 6, key);
know_target_key = true; known_key = true;
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)",
@ -2461,9 +2499,9 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
num_to_bytes(e_sector[i].Key[j], 6, tmp_key); num_to_bytes(e_sector[i].Key[j], 6, tmp_key);
// Store valid credentials for the nested / hardnested attack if none exist // Store valid credentials for the nested / hardnested attack if none exist
if (know_target_key == false) { if (known_key == false) {
num_to_bytes(e_sector[i].Key[j], 6, key); num_to_bytes(e_sector[i].Key[j], 6, key);
know_target_key = true; known_key = true;
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)",
@ -2483,7 +2521,8 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
} }
// Check if at least one sector key was found // Check if at least one sector key was found
if (know_target_key == false) { if (known_key == false) {
// Check if the darkside attack can be used // Check if the darkside attack can be used
if (prng_type && has_staticnonce != NONCE_STATIC) { if (prng_type && has_staticnonce != NONCE_STATIC) {
if (verbose) { if (verbose) {
@ -2520,6 +2559,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
key64 key64
); );
} else { } else {
noValidKeyFound: noValidKeyFound:
PrintAndLogEx(FAILED, "No usable key was found!"); PrintAndLogEx(FAILED, "No usable key was found!");
free(keyBlock); free(keyBlock);
@ -6935,12 +6975,14 @@ static int CmdHF14AGen4Load(const char *cmd) {
PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
return PM3_EMALLOC; return PM3_EMALLOC;
} }
PrintAndLogEx(INFO, "downloading emulator memory"); PrintAndLogEx(INFO, "downloading emulator memory");
if (!GetFromDevice(BIG_BUF_EML, data, block_cnt * MFBLOCK_SIZE, 0, NULL, 0, NULL, 2500, false)) { if (GetFromDevice(BIG_BUF_EML, data, block_cnt * MFBLOCK_SIZE, 0, NULL, 0, NULL, 2500, false) == false) {
PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
free(data); free(data);
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
} else { } else {
// read from file // read from file
int res = pm3_load_dump(filename, (void **)&data, &bytes_read, (MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK)); int res = pm3_load_dump(filename, (void **)&data, &bytes_read, (MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK));
@ -6950,7 +6992,7 @@ static int CmdHF14AGen4Load(const char *cmd) {
// check file size corresponds to card size. // check file size corresponds to card size.
if (bytes_read != (block_cnt * MFBLOCK_SIZE)) { if (bytes_read != (block_cnt * MFBLOCK_SIZE)) {
PrintAndLogEx(ERR, "File content error. Read %zu bytes, expected %zu", bytes_read, block_cnt * MFBLOCK_SIZE); PrintAndLogEx(ERR, "File content error. Read %zu bytes, expected %i", bytes_read, block_cnt * MFBLOCK_SIZE);
if (data != NULL) free(data); if (data != NULL) free(data);
return PM3_EFILE; return PM3_EFILE;
} }
@ -6983,7 +7025,7 @@ static int CmdHF14AGen4Load(const char *cmd) {
if (mfG4SetBlock(pwd, blockno, data + (blockno * MFBLOCK_SIZE), MAGIC_INIT | MAGIC_OFF) != PM3_SUCCESS) { if (mfG4SetBlock(pwd, blockno, data + (blockno * MFBLOCK_SIZE), MAGIC_INIT | MAGIC_OFF) != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "Can't set magic card block: %d", blockno); PrintAndLogEx(WARNING, "Can't set magic card block: %d", blockno);
PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position"); PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position");
if (data != NULL) free(data); free(data);
return PM3_ESOFT; return PM3_ESOFT;
} }
} }

View file

@ -677,6 +677,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
snprintf(pos1, 9, "[%s]", cb_str); snprintf(pos1, 9, "[%s]", cb_str);
} }
} }
free(cb_str);
} }
} }
} }

View file

@ -29,6 +29,7 @@ static const uint64_t g_mifare_default_keys[] = {
0x000000000000, // Blank key 0x000000000000, // Blank key
0xa0a1a2a3a4a5, // NFCForum MAD key 0xa0a1a2a3a4a5, // NFCForum MAD key
0xd3f7d3f7d3f7, // NDEF public key 0xd3f7d3f7d3f7, // NDEF public key
0x4b791bea7bcc, // MFC EV1 Signature B
0xb0b1b2b3b4b5, 0xb0b1b2b3b4b5,
0xaabbccddeeff, 0xaabbccddeeff,
0x1a2b3c4d5e6f, 0x1a2b3c4d5e6f,
@ -75,6 +76,10 @@ static const uint8_t g_mifare_default_key[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0x
static const uint8_t g_mifare_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}; static const uint8_t g_mifare_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5};
static const uint8_t g_mifare_mad_key_b[] = {0x89, 0xEC, 0xA9, 0x7F, 0x8C, 0x2A}; static const uint8_t g_mifare_mad_key_b[] = {0x89, 0xEC, 0xA9, 0x7F, 0x8C, 0x2A};
// 16 key B D01AFEEB890A
static const uint8_t g_mifare_signature_key_a[] = {0x5C, 0x8F, 0xF9, 0x99, 0x0D, 0xA2};
static const uint8_t g_mifare_signature_key_b[] = {0x4b, 0x79, 0x1b, 0xea, 0x7b, 0xcc};
static const uint8_t g_mifare_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; static const uint8_t g_mifare_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7};
static const uint8_t g_mifarep_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7}; static const uint8_t g_mifarep_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7};
static const uint8_t g_mifarep_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; static const uint8_t g_mifarep_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7};

View file

@ -35,6 +35,8 @@
#include "util_posix.h" // msclock #include "util_posix.h" // msclock
#include "cmdparser.h" // detection of flash capabilities #include "cmdparser.h" // detection of flash capabilities
#include "cmdflashmemspiffs.h" // upload to flash mem #include "cmdflashmemspiffs.h" // upload to flash mem
#include "mifaredefault.h" // default keys
int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
uint32_t uid = 0; uint32_t uid = 0;
@ -880,7 +882,7 @@ int mfReadSector(uint8_t sectorNo, uint8_t keyType, const uint8_t *key, uint8_t
return PM3_SUCCESS; return PM3_SUCCESS;
} }
int mfReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t *data) { int mfReadBlock(uint8_t blockNo, uint8_t keyType, const uint8_t *key, uint8_t *data) {
mf_readblock_t payload = { mf_readblock_t payload = {
.blockno = blockNo, .blockno = blockNo,
.keytype = keyType .keytype = keyType
@ -1421,15 +1423,20 @@ int detect_mf_magic(bool is_mfc) {
return isGeneration; return isGeneration;
} }
int detect_mfc_ev1_signature(uint8_t *signature) { bool detect_mfc_ev1_signature(void) {
uint64_t key = 0;
int res = mfCheckKeys(69, MF_KEY_B, false, 1, (uint8_t*)g_mifare_signature_key_b, &key);
return (res == PM3_SUCCESS);
}
int read_mfc_ev1_signature(uint8_t *signature) {
if (signature == NULL) { if (signature == NULL) {
return PM3_EINVARG; return PM3_EINVARG;
} }
uint8_t sign[32] = {0}; uint8_t sign[32] = {0};
uint8_t key[] = {0x4b, 0x79, 0x1b, 0xea, 0x7b, 0xcc}; int res = mfReadBlock(69, MF_KEY_B, g_mifare_signature_key_b, sign);
int res = mfReadBlock(69, 1, key, sign);
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
res = mfReadBlock(70, 1, key, sign + 16); res = mfReadBlock(70, MF_KEY_B, g_mifare_signature_key_b, sign + 16);
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
memcpy(signature, sign, sizeof(sign)); memcpy(signature, sign, sizeof(sign));
} }

View file

@ -80,7 +80,7 @@ int mfCheckKeys_file(uint8_t *destfn, uint64_t *key);
int mfKeyBrute(uint8_t blockNo, uint8_t keyType, const uint8_t *key, uint64_t *resultkey); int mfKeyBrute(uint8_t blockNo, uint8_t keyType, const uint8_t *key, uint64_t *resultkey);
int mfReadSector(uint8_t sectorNo, uint8_t keyType, const uint8_t *key, uint8_t *data); int mfReadSector(uint8_t sectorNo, uint8_t keyType, const uint8_t *key, uint8_t *data);
int mfReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t *data); int mfReadBlock(uint8_t blockNo, uint8_t keyType, const uint8_t *key, uint8_t *data);
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount); int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);
@ -104,7 +104,9 @@ int detect_classic_prng(void);
int detect_classic_nackbug(bool verbose); int detect_classic_nackbug(bool verbose);
int detect_mf_magic(bool is_mfc); int detect_mf_magic(bool is_mfc);
int detect_classic_static_nonce(void); int detect_classic_static_nonce(void);
int detect_mfc_ev1_signature(uint8_t *signature); bool detect_mfc_ev1_signature(void);
int read_mfc_ev1_signature(uint8_t *signature);
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted); void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted);
#endif #endif

6
pm3
View file

@ -59,20 +59,22 @@ function get_pm3_list_Linux {
fi fi
for DEV in $(find /dev/ttyACM* 2>/dev/null); do for DEV in $(find /dev/ttyACM* 2>/dev/null); do
if command -v udevadm >/dev/null; then if command -v udevadm >/dev/null; then
# WSL1 detection
if udevadm info -q property -n "$DEV" | grep -q "ID_VENDOR=proxmark.org"; then if udevadm info -q property -n "$DEV" | grep -q "ID_VENDOR=proxmark.org"; then
PM3LIST+=("$DEV") PM3LIST+=("$DEV")
if [ ${#PM3LIST[*]} -ge "$N" ]; then if [ ${#PM3LIST[*]} -ge "$N" ]; then
return return
fi fi
fi fi
else fi
# WSL2 with usbipd detection - doesn't report same things as WSL1
if grep -q "proxmark.org" "/sys/class/tty/${DEV#/dev/}/../../../manufacturer" 2>/dev/null; then if grep -q "proxmark.org" "/sys/class/tty/${DEV#/dev/}/../../../manufacturer" 2>/dev/null; then
PM3LIST+=("$DEV") PM3LIST+=("$DEV")
if [ ${#PM3LIST[*]} -ge "$N" ]; then if [ ${#PM3LIST[*]} -ge "$N" ]; then
return return
fi fi
fi fi
fi
done done
if $FINDBTDONGLE; then if $FINDBTDONGLE; then
# check if the HC-06-USB white dongle is present (still, that doesn't tell us if it's paired with a Proxmark3...) # check if the HC-06-USB white dongle is present (still, that doesn't tell us if it's paired with a Proxmark3...)