make style

This commit is contained in:
Philippe Teuwen 2024-08-03 21:21:11 +02:00
parent 44d7c54be7
commit ee8b9ca74b
14 changed files with 229 additions and 170 deletions

View file

@ -38,19 +38,19 @@
#include "ticks.h"
#include "util.h"
/*
/*
* `hf_mattyrun` tries to dump MIFARE Classic cards into emulator memory and emulates them.
*
*
* This standalone mode uses a predefined dictionary to authenticate to MIFARE Classic
* cards (cf. `hf mf chk`) and to dump the card into emulator memory (cf. `hf mf ecfill`).
* Once a card has been dumped, the card is emulated (cf. `hf mf sim`). Emulation will
* start even if only a partial dump could be retrieved from the card (e.g. due to missing
* keys).
*
*
* This standalone mode is specifically designed for devices without flash. However,
* users can pass data to/from the standalone mode through emulator memory (assuming
* continuous (battery) power supply):
*
*
* - Keys can be added to the dictionary by loading them into the emulator before
* starting the standalone mode. You can use `hf mf eload -f dump_file` to load
* any existing card dump. All keys from the key slots in the sector trailers
@ -58,14 +58,14 @@
* trailers available for a 4K card to store your user dictionary. Sector and key
* type are ignored during chk; all user keys will be tested for all sectors and
* for both key types.
*
*
* - Once a card has been cloned into emulator memory, you can extract the dump by
* ending the standalone mode and retrieving the emulator memory (`hf mf eview`
* or `hf mf esave [--mini|--1k|--2k|--4k] -f dump_file`).
*
*
* This standalone mode will log status information via USB. In addition, the LEDs
* display status information:
*
*
* - Waiting for card: LED C is on, LED D blinks.
* - Tying to authenticate: LED C and D are on; LED D will blink on errors.
* - Nested attack (NOT IMPLEMENTED!): LED B is on.
@ -73,14 +73,14 @@
* - Starting emulation: LED A, B, and C are on. LED D is on if only a partial
* dump is available.
* - Emulation started: All LEDS are off.
*
*
* You can use the user button to interact with the standalone mode. During
* emulation, (short) pressing the button ends emulation and returns to card
* discovery. Long pressing the button ends the standalone mode.
*
*
* Developers can configure the behavior of the standalone mode through the below
* constants:
*
*
* - MATTYRUN_PRINT_KEYS: Activate display of actually used key dictionary on startup.
* - MATTYRUN_NO_ECFILL: Do not load and emulate card (only discovered keys are stored).
* - MATTYRUN_MFC_DEFAULT_KEYS: Compiled-in default dictionary defined in a separate
@ -88,7 +88,7 @@
* dictionaries here.
* - MATTYRUN_MFC_ESSENTIAL_KEYS: Compiled-in dictionary of keys that should be tested
* before any user dictionary.
*
*
* This is a major rewrite of the original `hf_mattyrun` by Matías A. Medina.
* The original version is described [here](http://bit.ly/2c9nZXR) (in Spanish).
*/
@ -136,7 +136,7 @@ static bool saMifareDiscover(void) {
// Customized MifareChkKeys that operates on the already detected card in
// mattyrun_card and tests authentication with our dictionary
static int saMifareChkKeys(uint8_t const blockNo, uint8_t const keyType, bool const clearTrace,
uint16_t const keyCount, uint64_t const * const mfKeys, uint64_t * const key) {
uint16_t const keyCount, uint64_t const *const mfKeys, uint64_t *const key) {
int retval = -1;
@ -179,10 +179,17 @@ static int saMifareChkKeys(uint8_t const blockNo, uint8_t const keyType, bool co
} else {
if (cascade_levels == 0) {
switch (mattyrun_card.uidlen) {
case 4: cascade_levels = 1; break;
case 7: cascade_levels = 2; break;
case 10: cascade_levels = 3; break;
default: break;
case 4:
cascade_levels = 1;
break;
case 7:
cascade_levels = 2;
break;
case 10:
cascade_levels = 3;
break;
default:
break;
}
}
// No need for anticollision. Since we sucessfully selected the card before,
@ -239,10 +246,10 @@ void RunMod(void) {
// usb_disable();
// Allocate dictionary buffer
uint64_t * const mfcKeys = (uint64_t *)BigBuf_malloc(
sizeof(uint64_t) * (ARRAYLEN(MATTYRUN_MFC_ESSENTIAL_KEYS) +
ARRAYLEN(MATTYRUN_MFC_DEFAULT_KEYS) +
MIFARE_4K_MAXSECTOR * 2));
uint64_t *const mfcKeys = (uint64_t *)BigBuf_malloc(
sizeof(uint64_t) * (ARRAYLEN(MATTYRUN_MFC_ESSENTIAL_KEYS) +
ARRAYLEN(MATTYRUN_MFC_DEFAULT_KEYS) +
MIFARE_4K_MAXSECTOR * 2));
uint16_t mfcKeyCount = 0;
// Load essential keys to dictionary buffer
@ -542,7 +549,7 @@ void RunMod(void) {
LED_D_OFF();
DbpString("[=] Started emulation. Press button to abort at anytime.");
if (partialEmulation) {
LED_D_ON();
DbpString("[=] Partial memory dump loaded. Trying best effort emulation approach.");
@ -550,10 +557,17 @@ void RunMod(void) {
uint16_t simflags = 0;
switch (mattyrun_card.uidlen) {
case 4: simflags |= FLAG_4B_UID_IN_DATA; break;
case 7: simflags |= FLAG_7B_UID_IN_DATA; break;
case 10: simflags |= FLAG_10B_UID_IN_DATA; break;
default: break;
case 4:
simflags |= FLAG_4B_UID_IN_DATA;
break;
case 7:
simflags |= FLAG_7B_UID_IN_DATA;
break;
case 10:
simflags |= FLAG_10B_UID_IN_DATA;
break;
default:
break;
}
uint16_t atqa = (uint16_t)bytes_to_num(mattyrun_card.atqa, 2);

View file

@ -59,11 +59,11 @@ static uint64_t const MATTYRUN_MFC_DEFAULT_KEYS[] = {
0x0123456789AB,
0x123456789ABC,
// You could add more keys from, e.g, mfc_default_keys.dic here.
// However, be aware that more keys means longer brute-force times
// and too many keys will resuolt in running out of memory.
// See https://github.com/RfidResearchGroup/proxmark3/pull/2377#issuecomment-2112658439
// for a rough benchmark.
// You could add more keys from, e.g, mfc_default_keys.dic here.
// However, be aware that more keys means longer brute-force times
// and too many keys will resuolt in running out of memory.
// See https://github.com/RfidResearchGroup/proxmark3/pull/2377#issuecomment-2112658439
// for a rough benchmark.
};
#endif /* HF_MATTYRUN_H__ */

View file

@ -184,32 +184,32 @@ int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
if (g_dbglevel >= DBG_EXTENDED) {
if (!isNested) {
Dbprintf("auth cmd: %02x %02x | uid: %08x | nr: %08x %s| nt: %08x %s %5i| par: %i%i%i%i %s",
cmd, blockNo, uid,
nr32, validate_prng_nonce(nr32) ? "@" : " ",
nt, validate_prng_nonce(nt) ? "@idx" : " idx",
validate_prng_nonce(nt) ? nonce16_index(nt >> 16) : -1,
(receivedAnswerPar[0] >> 7) & 1,
(receivedAnswerPar[0] >> 6) & 1,
(receivedAnswerPar[0] >> 5) & 1,
(receivedAnswerPar[0] >> 4) & 1,
validate_parity_nonce(nt, receivedAnswerPar[0], nt) ? "ok " : "bad");
cmd, blockNo, uid,
nr32, validate_prng_nonce(nr32) ? "@" : " ",
nt, validate_prng_nonce(nt) ? "@idx" : " idx",
validate_prng_nonce(nt) ? nonce16_index(nt >> 16) : -1,
(receivedAnswerPar[0] >> 7) & 1,
(receivedAnswerPar[0] >> 6) & 1,
(receivedAnswerPar[0] >> 5) & 1,
(receivedAnswerPar[0] >> 4) & 1,
validate_parity_nonce(nt, receivedAnswerPar[0], nt) ? "ok " : "bad");
} else {
Dbprintf("auth nested cmd: %02x %02x | uid: %08x | nr: %08x %s| nt: %08x %s %5i| par: %i%i%i%i %s| ntenc: %08x %s| parerr: %i%i%i%i",
cmd, blockNo, uid,
nr32, validate_prng_nonce(nr32) ? "@" : " ",
nt, validate_prng_nonce(nt) ? "@idx" : " idx",
validate_prng_nonce(nt) ? nonce16_index(nt >> 16) : -1,
(receivedAnswerPar[0] >> 7) & 1,
(receivedAnswerPar[0] >> 6) & 1,
(receivedAnswerPar[0] >> 5) & 1,
(receivedAnswerPar[0] >> 4) & 1,
validate_parity_nonce(*ntencptr, receivedAnswerPar[0], nt) ? "ok " : "bad",
*ntencptr, validate_prng_nonce(*ntencptr) ? "@" : " ",
((receivedAnswerPar[0] >> 7) & 1) ^ oddparity8((*ntencptr >> 24) & 0xFF),
((receivedAnswerPar[0] >> 6) & 1) ^ oddparity8((*ntencptr >> 16) & 0xFF),
((receivedAnswerPar[0] >> 5) & 1) ^ oddparity8((*ntencptr >> 8) & 0xFF),
((receivedAnswerPar[0] >> 4) & 1) ^ oddparity8((*ntencptr >> 0) & 0xFF)
);
cmd, blockNo, uid,
nr32, validate_prng_nonce(nr32) ? "@" : " ",
nt, validate_prng_nonce(nt) ? "@idx" : " idx",
validate_prng_nonce(nt) ? nonce16_index(nt >> 16) : -1,
(receivedAnswerPar[0] >> 7) & 1,
(receivedAnswerPar[0] >> 6) & 1,
(receivedAnswerPar[0] >> 5) & 1,
(receivedAnswerPar[0] >> 4) & 1,
validate_parity_nonce(*ntencptr, receivedAnswerPar[0], nt) ? "ok " : "bad",
*ntencptr, validate_prng_nonce(*ntencptr) ? "@" : " ",
((receivedAnswerPar[0] >> 7) & 1) ^ oddparity8((*ntencptr >> 24) & 0xFF),
((receivedAnswerPar[0] >> 6) & 1) ^ oddparity8((*ntencptr >> 16) & 0xFF),
((receivedAnswerPar[0] >> 5) & 1) ^ oddparity8((*ntencptr >> 8) & 0xFF),
((receivedAnswerPar[0] >> 4) & 1) ^ oddparity8((*ntencptr >> 0) & 0xFF)
);
}
}
// save Nt
@ -932,7 +932,7 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData) {
bool validate_prng_nonce(uint32_t nonce) {
uint16_t x = nonce >> 16;
x = (x & 0xff) << 8 | x >> 8;
for (uint8_t i = 0; i<16; i++) {
for (uint8_t i = 0; i < 16; i++) {
x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15;
}
x = (x & 0xff) << 8 | x >> 8;
@ -942,11 +942,11 @@ bool validate_prng_nonce(uint32_t nonce) {
bool validate_parity_nonce(uint32_t ntenc, uint8_t ntparenc, uint32_t nt) {
uint32_t ks = nt ^ ntenc;
ntparenc >>= 4;
uint8_t ksp = (((ks >> 16)&1) << 3) | (((ks >> 8)&1) << 2) | (((ks >> 0)&1) << 1);
uint8_t ksp = (((ks >> 16) & 1) << 3) | (((ks >> 8) & 1) << 2) | (((ks >> 0) & 1) << 1);
uint8_t ntpar = ntparenc ^ ksp;
return (((ntpar >> 3) & 1) == oddparity8((nt>>24) & 0xFF)) &&
(((ntpar >> 2) & 1) == oddparity8((nt>>16) & 0xFF)) &&
(((ntpar >> 1) & 1) == oddparity8((nt>>8) & 0xFF));
return (((ntpar >> 3) & 1) == oddparity8((nt >> 24) & 0xFF)) &&
(((ntpar >> 2) & 1) == oddparity8((nt >> 16) & 0xFF)) &&
(((ntpar >> 1) & 1) == oddparity8((nt >> 8) & 0xFF));
}
int nonce16_distance(uint16_t x, uint16_t y) {
@ -955,9 +955,9 @@ int nonce16_distance(uint16_t x, uint16_t y) {
x = (x & 0xff) << 8 | x >> 8;
y = (y & 0xff) << 8 | y >> 8;
uint16_t i = 1;
for(;i;i++) {
for (; i; i++) {
x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15;
if (x==y)
if (x == y)
return i;
}
// never reached

View file

@ -1449,7 +1449,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
arg_lit0("v", "verbose", "verbose output"),
arg_lit0(NULL, "d6", "decode as block 6"),
arg_lit0("z", "dense", "dense dump output style"),
arg_lit0(NULL, "ns", "no save to file"),
arg_lit0(NULL, "ns", "no save to file"),
arg_param_end
};
CLIExecWithReturn(clictx, Cmd, argtable, false);
@ -1619,18 +1619,18 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
PrintAndLogEx(NORMAL, "");
} else {
// use the first block (CSN) for filename
char *fptr = calloc(50, sizeof(uint8_t));
if (fptr == false) {
PrintAndLogEx(WARNING, "Failed to allocate memory");
free(decrypted);
return PM3_EMALLOC;
}
// use the first block (CSN) for filename
char *fptr = calloc(50, sizeof(uint8_t));
if (fptr == false) {
PrintAndLogEx(WARNING, "Failed to allocate memory");
free(decrypted);
return PM3_EMALLOC;
}
strcat(fptr, "hf-iclass-");
FillFileNameByUID(fptr, hdr->csn, "-dump-decrypted", sizeof(hdr->csn));
strcat(fptr, "hf-iclass-");
FillFileNameByUID(fptr, hdr->csn, "-dump-decrypted", sizeof(hdr->csn));
pm3_save_dump(fptr, decrypted, decryptedlen, jsfIclass);
pm3_save_dump(fptr, decrypted, decryptedlen, jsfIclass);
free(fptr);
}
@ -1645,8 +1645,8 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
// decode block 6
bool has_values = (memcmp(decrypted + (8 * 6), empty, 8) != 0) && (memcmp(decrypted + (8 * 6), zeros, 8) != 0);
if (has_values && use_sc) {
DecodeBlock6(decrypted + (8 * 6));
}
DecodeBlock6(decrypted + (8 * 6));
}
// decode block 7-8-9
iclass_decode_credentials(decrypted);

View file

@ -3375,7 +3375,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) {
uint16_t singleSectorParams = 0;
if (blockn != -1) {
singleSectorParams = (blockn & 0xFF)| keytype << 8 | 1 << 15;
singleSectorParams = (blockn & 0xFF) | keytype << 8 | 1 << 15;
}
if (use_flashmemory) {
PrintAndLogEx(SUCCESS, "Using dictionary in flash memory");

View file

@ -264,7 +264,7 @@ int mfCheckKeys_fast_ex(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChun
if (curr_keys) {
uint64_t foo = bytes_to_num(resp.data.asBytes, 6);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, _GREEN_("Key %s for block %2i found: %012" PRIx64), (singleSectorParams >> 8) & 1 ? "B":"A", singleSectorParams & 0xFF, foo);
PrintAndLogEx(SUCCESS, _GREEN_("Key %s for block %2i found: %012" PRIx64), (singleSectorParams >> 8) & 1 ? "B" : "A", singleSectorParams & 0xFF, foo);
return PM3_SUCCESS;
}
}
@ -605,16 +605,16 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
if (package->keytype < 2) {
PrintAndLogEx(SUCCESS, "\nTarget block %4u key type %c -- found valid key [ " _GREEN_("%s") " ]",
package->block,
package->keytype ? 'B' : 'A',
sprint_hex_inrow(resultKey, 6)
);
package->block,
package->keytype ? 'B' : 'A',
sprint_hex_inrow(resultKey, 6)
);
} else {
PrintAndLogEx(SUCCESS, "\nTarget block %4u key type %02x -- found valid key [ " _GREEN_("%s") " ]",
package->block,
MIFARE_AUTH_KEYA + package->keytype,
sprint_hex_inrow(resultKey, 6)
);
package->block,
MIFARE_AUTH_KEYA + package->keytype,
sprint_hex_inrow(resultKey, 6)
);
}
@ -628,14 +628,14 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
out:
if (package->keytype < 2) {
PrintAndLogEx(SUCCESS, "\nTarget block %4u key type %c",
package->block,
package->keytype ? 'B' : 'A'
);
package->block,
package->keytype ? 'B' : 'A'
);
} else {
PrintAndLogEx(SUCCESS, "\nTarget block %4u key type %02x",
package->block,
MIFARE_AUTH_KEYA + package->keytype
);
package->block,
MIFARE_AUTH_KEYA + package->keytype
);
}
free(statelists[0].head.slhead);
free(statelists[1].head.slhead);
@ -1430,17 +1430,17 @@ int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type,
}
if (verbose && (resp.data.asBytes[0] == NONCE_STATIC_ENC)) {
uint32_t uid = resp.data.asBytes[1] << 24 |
resp.data.asBytes[2] << 16 |
resp.data.asBytes[3] << 8 |
resp.data.asBytes[4];
resp.data.asBytes[2] << 16 |
resp.data.asBytes[3] << 8 |
resp.data.asBytes[4];
uint32_t nt = resp.data.asBytes[5] << 24 |
resp.data.asBytes[6] << 16 |
resp.data.asBytes[7] << 8 |
resp.data.asBytes[8];
resp.data.asBytes[6] << 16 |
resp.data.asBytes[7] << 8 |
resp.data.asBytes[8];
uint32_t ntenc = resp.data.asBytes[9] << 24 |
resp.data.asBytes[10] << 16 |
resp.data.asBytes[11] << 8 |
resp.data.asBytes[12];
resp.data.asBytes[10] << 16 |
resp.data.asBytes[11] << 8 |
resp.data.asBytes[12];
uint8_t ntencparenc = resp.data.asBytes[13];
// recompute nt on client, just because
@ -1457,24 +1457,24 @@ int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type,
ntencparenc >>= 4;
// [...] Additionally, the bit of keystream used to encrypt the parity bits is reused to encrypt the next bit of plaintext.
// we can decrypt first 3 parity bits, not last one as it's using future keystream
uint8_t ksp = (((ks >> 16)&1) << 3) | (((ks >> 8)&1) << 2) | (((ks >> 0)&1) << 1);
uint8_t ksp = (((ks >> 16) & 1) << 3) | (((ks >> 8) & 1) << 2) | (((ks >> 0) & 1) << 1);
uint8_t ntencpar = ntencparenc ^ ksp;
if (validate_prng_nonce(nt)) {
PrintAndLogEx(INFO, "nTenc " _GREEN_("%08x") " par {" _YELLOW_("%i%i%i%i") "}=" _YELLOW_("%i%i%ix") " | ks " _GREEN_("%08x") " | nT " _GREEN_("%08x") " par " _YELLOW_("%i%i%i%i")" | lfsr16 index " _GREEN_("%i"),
ntenc,
(ntencparenc >> 3) & 1, (ntencparenc >> 2) & 1, (ntencparenc >> 1) & 1, ntencparenc & 1,
(ntencpar >> 3) & 1, (ntencpar >> 2) & 1, (ntencpar >> 1) & 1,
ks, nt,
oddparity8((nt>>24) & 0xFF), oddparity8((nt>>16) & 0xFF), oddparity8((nt>>8) & 0xFF), oddparity8(nt & 0xFF),
nonce_distance(0, nt));
ntenc,
(ntencparenc >> 3) & 1, (ntencparenc >> 2) & 1, (ntencparenc >> 1) & 1, ntencparenc & 1,
(ntencpar >> 3) & 1, (ntencpar >> 2) & 1, (ntencpar >> 1) & 1,
ks, nt,
oddparity8((nt >> 24) & 0xFF), oddparity8((nt >> 16) & 0xFF), oddparity8((nt >> 8) & 0xFF), oddparity8(nt & 0xFF),
nonce_distance(0, nt));
} else {
PrintAndLogEx(INFO, "nTenc " _GREEN_("%08x") " par {" _YELLOW_("%i%i%i%i") "}=" _YELLOW_("%i%i%ix") " | ks " _YELLOW_("%08x") " | nT " _YELLOW_("%08x") " par " _YELLOW_("%i%i%i%i") " | " _RED_("not lfsr16") " (wrong key)",
ntenc,
(ntencparenc >> 3) & 1, (ntencparenc >> 2) & 1, (ntencparenc >> 1) & 1, ntencparenc & 1,
(ntencpar >> 3) & 1, (ntencpar >> 2) & 1, (ntencpar >> 1) & 1,
ks, nt,
oddparity8((nt>>24) & 0xFF), oddparity8((nt>>16) & 0xFF), oddparity8((nt>>8) & 0xFF), oddparity8(nt & 0xFF)
);
ntenc,
(ntencparenc >> 3) & 1, (ntencparenc >> 2) & 1, (ntencparenc >> 1) & 1, ntencparenc & 1,
(ntencpar >> 3) & 1, (ntencpar >> 2) & 1, (ntencpar >> 1) & 1,
ks, nt,
oddparity8((nt >> 24) & 0xFF), oddparity8((nt >> 16) & 0xFF), oddparity8((nt >> 8) & 0xFF), oddparity8(nt & 0xFF)
);
}
}
return resp.data.asBytes[0];

View file

@ -337,6 +337,7 @@ const static vocabulary_t vocabulary[] = {
{ 1, "hf mf help" },
{ 1, "hf mf list" },
{ 0, "hf mf info" },
{ 0, "hf mf isen" },
{ 0, "hf mf darkside" },
{ 0, "hf mf nested" },
{ 1, "hf mf hardnested" },

View file

@ -432,7 +432,7 @@ int nonce_distance(uint32_t from, uint32_t to) {
bool validate_prng_nonce(uint32_t nonce) {
uint16_t x = nonce >> 16;
x = (x & 0xff) << 8 | x >> 8;
for (uint8_t i = 0; i<16; i++) {
for (uint8_t i = 0; i < 16; i++) {
x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15;
}
x = (x & 0xff) << 8 | x >> 8;

View file

@ -3234,9 +3234,10 @@
"-k, --key <hex> 3DES transport key",
"-v, --verbose verbose output",
"--d6 decode as block 6",
"-z, --dense dense dump output style"
"-z, --dense dense dump output style",
"--ns no save to file"
],
"usage": "hf iclass decrypt [-hvz] [-f <fn>] [-d <hex>] [-k <hex>] [--d6]"
"usage": "hf iclass decrypt [-hvz] [-f <fn>] [-d <hex>] [-k <hex>] [--d6] [--ns]"
},
"hf iclass dump": {
"command": "hf iclass dump",
@ -4699,9 +4700,12 @@
"--emu Fill simulator keys from found keys",
"--dump Dump found keys to binary file",
"--mem Use dictionary from flashmemory",
"-f, --file <fn> filename of dictionary"
"-f, --file <fn> filename of dictionary",
"--blk <dec> block number (single block recovery mode)",
"-a single block recovery key A",
"-b single block recovery key B"
],
"usage": "hf mf fchk [-h] [-k <hex>]... [--mini] [--1k] [--2k] [--4k] [--emu] [--dump] [--mem] [-f <fn>]"
"usage": "hf mf fchk [-hab] [-k <hex>]... [--mini] [--1k] [--2k] [--4k] [--emu] [--dump] [--mem] [-f <fn>] [--blk <dec>]"
},
"hf mf gchpwd": {
"command": "hf mf gchpwd",
@ -5015,6 +5019,39 @@
],
"usage": "hf mf info [-habnv] [--blk <dec>] [-k <hex>]"
},
"hf mf isen": {
"command": "hf mf isen",
"description": "Information about Static Encrypted Nonce properties in a MIFARE Classic card",
"notes": [
"hf mf isen",
"Default behavior:",
"auth(blk)-auth(blk2)-auth(blk2)-...",
"Default behavior when wrong key2:",
"auth(blk)-auth(blk2) auth(blk)-auth(blk2) ..."
],
"offline": false,
"options": [
"-h, --help This help",
"--blk <dec> block number",
"-a input key type is key A (def)",
"-b input key type is key B",
"-c <dec> input key type is key A + offset",
"-k, --key <hex> key, 6 hex bytes",
"--blk2 <dec> nested block number (default=same)",
"--a2 nested input key type is key A (default=same)",
"--b2 nested input key type is key B (default=same)",
"--c2 <dec> nested input key type is key A + offset",
"--key2 <hex> nested key, 6 hex bytes (default=same)",
"-n <dec> number of nonces (default=2)",
"--reset reset between attempts, even if auth was successful",
"--addread auth(blk)-read(blk)-auth(blk2)",
"--addauth auth(blk)-auth(blk)-auth(blk2)",
"--incblk2 auth(blk)-auth(blk2)-auth(blk2+4)-...",
"--corruptnrar corrupt {nR}{aR}, but with correct parity",
"--corruptnrarparity correct {nR}{aR}, but with corrupted parity"
],
"usage": "hf mf isen [-hab] [--blk <dec>] [-c <dec>] [-k <hex>] [--blk2 <dec>] [--a2] [--b2] [--c2 <dec>] [--key2 <hex>] [-n <dec>] [--reset] [--addread] [--addauth] [--incblk2] [--corruptnrar] [--corruptnrarparity]"
},
"hf mf mad": {
"command": "hf mf mad",
"description": "Checks and prints MIFARE Application Directory (MAD)",
@ -5131,14 +5168,17 @@
"--blk <dec> Input block number",
"-a Input key specified is A key (default)",
"-b Input key specified is B key",
"-c <dec> input key type is key A + offset",
"--tblk <dec> Target block number",
"--ta Target A key (default)",
"--tb Target B key",
"--tc <dec> Nested input key type is key A + offset (you must specify a single block as well!)",
"--emu Fill simulator keys from found keys",
"--dump Dump found keys to file",
"--mem Use dictionary from flashmemory"
"--mem Use dictionary from flashmemory",
"-i Ignore static encrypted nonces"
],
"usage": "hf mf nested [-hab] [-k <hex>] [--mini] [--1k] [--2k] [--4k] [--blk <dec>] [--tblk <dec>] [--ta] [--tb] [--emu] [--dump] [--mem]"
"usage": "hf mf nested [-habi] [-k <hex>] [--mini] [--1k] [--2k] [--4k] [--blk <dec>] [-c <dec>] [--tblk <dec>] [--ta] [--tb] [--tc <dec>] [--emu] [--dump] [--mem]"
},
"hf mf personalize": {
"command": "hf mf personalize",
@ -5177,10 +5217,11 @@
"--blk <dec> block number",
"-a input key type is key A (def)",
"-b input key type is key B",
"-c <dec> input key type is key A + offset",
"-k, --key <hex> key, 6 hex bytes",
"-v, --verbose verbose output"
],
"usage": "hf mf rdbl [-habv] --blk <dec> [-k <hex>]"
"usage": "hf mf rdbl [-habv] --blk <dec> [-c <dec>] [-k <hex>]"
},
"hf mf rdsc": {
"command": "hf mf rdsc",
@ -5194,11 +5235,12 @@
"-h, --help This help",
"-a input key specified is A key (def)",
"-b input key specified is B key",
"-c <dec> input key type is key A + offset",
"-k, --key <hex> key specified as 6 hex bytes",
"-s, --sec <dec> sector number",
"-v, --verbose verbose output"
],
"usage": "hf mf rdsc [-habv] [-k <hex>] -s <dec>"
"usage": "hf mf rdsc [-habv] [-c <dec>] [-k <hex>] -s <dec>"
},
"hf mf restore": {
"command": "hf mf restore",
@ -5387,11 +5429,12 @@
"--blk <dec> block number",
"-a input key type is key A (def)",
"-b input key type is key B",
"-c <dec> input key type is key A + offset",
"--force override warnings",
"-k, --key <hex> key, 6 hex bytes",
"-d, --data <hex> bytes to write, 16 hex bytes"
],
"usage": "hf mf wrbl [-hab] --blk <dec> [--force] [-k <hex>] [-d <hex>]"
"usage": "hf mf wrbl [-hab] --blk <dec> [-c <dec>] [--force] [-k <hex>] [-d <hex>]"
},
"hf mfdes auth": {
"command": "hf mfdes auth",
@ -12765,8 +12808,8 @@
}
},
"metadata": {
"commands_extracted": 739,
"commands_extracted": 740,
"extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2024-07-21T14:16:40"
"extracted_on": "2024-08-03T19:17:38"
}
}

View file

@ -508,6 +508,7 @@ Check column "offline" for their availability.
|`hf mf help `|Y |`This help`
|`hf mf list `|Y |`List MIFARE history`
|`hf mf info `|N |`mfc card Info`
|`hf mf isen `|N |`mfc card Info Static Encrypted Nonces`
|`hf mf darkside `|N |`Darkside attack`
|`hf mf nested `|N |`Nested attack`
|`hf mf hardnested `|Y |`Nested attack for hardened MIFARE Classic cards`

View file

@ -270,9 +270,9 @@ static uint64_t **unpredictable_nested(NtpKs1List *pNKL, uint32_t keyCounts[]) {
if (thread_status[i]) activeThreads++;
}
}
pthread_mutex_unlock(&status_mutex);
printf("\33[2K\rProgress: %02.1f%%", (double)(startPos+1)*100 /pNKL->NtDataList[0].sizeNK);
printf("\33[2K\rProgress: %02.1f%%", (double)(startPos + 1) * 100 / pNKL->NtDataList[0].sizeNK);
printf(" keys[%d]:%9i", 0, keyCounts[0]);
for (uint32_t nonce_index = 1; nonce_index < pNKL->nr_nonces; nonce_index++) {
printf(" keys[%d]:%5i", nonce_index, keyCounts[nonce_index]);
@ -309,14 +309,14 @@ static uint64_t **unpredictable_nested(NtpKs1List *pNKL, uint32_t keyCounts[]) {
// Function to compare keys and keep track of their occurrences
static void analyze_keys(uint64_t **keys, uint32_t keyCounts[MAX_NR_NONCES], uint32_t nr_nonces) {
// Assuming the maximum possible keys
#define MAX_KEYS (MAX_NR_NONCES * KEY_SPACE_SIZE_STEP2)
#define MAX_KEYS (MAX_NR_NONCES * KEY_SPACE_SIZE_STEP2)
uint64_t combined_keys[MAX_KEYS] = {0};
uint32_t combined_counts[MAX_KEYS] = {0};
uint32_t combined_length = 0;
printf("Analyzing keys...\n");
for (uint32_t i = 0; i < nr_nonces; i++) {
if (i==0) {
if (i == 0) {
printf("nT(%i): %i key candidates\n", i, keyCounts[i]);
continue;
} else {
@ -344,7 +344,7 @@ static void analyze_keys(uint64_t **keys, uint32_t keyCounts[MAX_NR_NONCES], uin
for (uint32_t i = 0; i < combined_length; i++) {
if (combined_counts[i] > 1) {
printf("Key %012" PRIx64 " found in %d arrays: 0", combined_keys[i], combined_counts[i]+1);
printf("Key %012" PRIx64 " found in %d arrays: 0", combined_keys[i], combined_counts[i] + 1);
for (uint32_t ii = 1; ii < nr_nonces; ii++) {
for (uint32_t j = 0; j < keyCounts[ii]; j++) {
if (combined_keys[i] == keys[ii][j]) {
@ -382,7 +382,7 @@ int main(int argc, char *const argv[]) {
NtpKs1List NKL = {0};
uint64_t **keys = NULL;
uint32_t keyCounts[MAX_NR_NONCES] = {0};
uint32_t authuid = hex_to_uint32(argv[1]);
// process all args.
printf("Generating nonce candidates...\n");
@ -418,9 +418,9 @@ int main(int argc, char *const argv[]) {
nttest = prng_successor(nttest, 1);
}
printf("uid=%08x nt_enc=%08x nt_par_err=%i%i%i%i nt_par_enc=%i%i%i%i %i/%i: %d\n", authuid, nt_enc,
nt_par_err_arr[0], nt_par_err_arr[1], nt_par_err_arr[2], nt_par_err_arr[3],
(nt_par_enc >> 3)&1, (nt_par_enc >> 2)&1, (nt_par_enc >> 1)&1, nt_par_enc&1,
NKL.nr_nonces + 1, (argc - 1) / 3, j);
nt_par_err_arr[0], nt_par_err_arr[1], nt_par_err_arr[2], nt_par_err_arr[3],
(nt_par_enc >> 3) & 1, (nt_par_enc >> 2) & 1, (nt_par_enc >> 1) & 1, nt_par_enc & 1,
NKL.nr_nonces + 1, (argc - 1) / 3, j);
pNtData->authuid = authuid;
pNtData->sizeNK = j;
@ -437,7 +437,7 @@ int main(int argc, char *const argv[]) {
free(NKL.NtDataList[k].pNK);
analyze_keys(keys, keyCounts, NKL.nr_nonces);
FILE* fptr;
FILE *fptr;
// opening the file in read mode
fptr = fopen("keys.dic", "w");
if (fptr != NULL) {

View file

@ -119,7 +119,7 @@ int main(int argc, char *const argv[]) {
}
uint64_t *keys = NULL;
uint32_t keyCount = 0;
uint32_t authuid = hex_to_uint32(argv[1]);
uint32_t sector = hex_to_uint32(argv[2]);
uint32_t nt = hex_to_uint32(argv[3]);
@ -129,20 +129,20 @@ int main(int argc, char *const argv[]) {
return 1;
}
uint8_t nt_par_enc = ((nt_par_err_arr[0] ^ oddparity8((nt_enc >> 24) & 0xFF)) << 3) |
((nt_par_err_arr[1] ^ oddparity8((nt_enc >> 16) & 0xFF)) << 2) |
((nt_par_err_arr[2] ^ oddparity8((nt_enc >> 8) & 0xFF)) << 1) |
((nt_par_err_arr[3] ^ oddparity8((nt_enc >> 0) & 0xFF)) << 0);
((nt_par_err_arr[1] ^ oddparity8((nt_enc >> 16) & 0xFF)) << 2) |
((nt_par_err_arr[2] ^ oddparity8((nt_enc >> 8) & 0xFF)) << 1) |
((nt_par_err_arr[3] ^ oddparity8((nt_enc >> 0) & 0xFF)) << 0);
printf("uid=%08x nt=%08x nt_enc=%08x nt_par_err=%i%i%i%i nt_par_enc=%i%i%i%i ks1=%08x\n", authuid, nt, nt_enc,
nt_par_err_arr[0], nt_par_err_arr[1], nt_par_err_arr[2], nt_par_err_arr[3],
(nt_par_enc >> 3)&1, (nt_par_enc >> 2)&1, (nt_par_enc >> 1)&1, nt_par_enc&1,
nt ^ nt_enc);
nt_par_err_arr[0], nt_par_err_arr[1], nt_par_err_arr[2], nt_par_err_arr[3],
(nt_par_enc >> 3) & 1, (nt_par_enc >> 2) & 1, (nt_par_enc >> 1) & 1, nt_par_enc & 1,
nt ^ nt_enc);
printf("Finding key candidates...\n");
keys = generate_keys(authuid, nt, nt_enc, nt_par_enc, &keyCount);
printf("Finding phase complete, found %i keys\n", keyCount);
FILE* fptr;
FILE *fptr;
char filename[30];
snprintf(filename, sizeof(filename), "keys_%08x_%02i_%08x.dic", authuid, sector, nt);

View file

@ -23,7 +23,7 @@ uint16_t s_lfsr16[1 << 16] = {0};
static void init_lfsr16_table(void) {
uint16_t x = 1;
for (uint16_t i=1; i; ++i) {
for (uint16_t i = 1; i; ++i) {
i_lfsr16[(x & 0xff) << 8 | x >> 8] = i;
s_lfsr16[i] = (x & 0xff) << 8 | x >> 8;
x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15;
@ -35,7 +35,7 @@ static void init_lfsr16_table(void) {
// }
static uint16_t prev_lfsr16(uint16_t nonce) {
return s_lfsr16[(i_lfsr16[nonce]-1) % 65535];
return s_lfsr16[(i_lfsr16[nonce] - 1) % 65535];
}
static uint16_t compute_seednt16_nt32(uint32_t nt32, uint64_t key) {
@ -43,13 +43,13 @@ static uint16_t compute_seednt16_nt32(uint32_t nt32, uint64_t key) {
uint8_t b[] = {0, 13, 1, 14, 4, 10, 15, 7, 5, 3, 8, 6, 9, 2, 12, 11};
uint16_t nt = nt32 >> 16;
uint8_t prev = 14;
for (uint8_t i=0; i<prev; i++) {
for (uint8_t i = 0; i < prev; i++) {
nt = prev_lfsr16(nt);
}
uint8_t prevoff = 8;
bool odd = 1;
for (uint8_t i=0; i<6*8; i+=8) {
for (uint8_t i = 0; i < 6 * 8; i += 8) {
if (odd) {
nt ^= (a[(key >> i) & 0xF]);
nt ^= (b[(key >> i >> 4) & 0xF]) << 4;
@ -59,7 +59,7 @@ static uint16_t compute_seednt16_nt32(uint32_t nt32, uint64_t key) {
}
odd ^= 1;
prev += prevoff;
for (uint8_t j=0; j<prevoff; j++) {
for (uint8_t j = 0; j < prevoff; j++) {
nt = prev_lfsr16(nt);
}
}
@ -75,7 +75,7 @@ int main(int argc, char *const argv[]) {
}
uint32_t uid1, sector1, nt1, uid2, sector2, nt2;
char *filename1 = argv[1], *filename2= argv[2];
char *filename1 = argv[1], *filename2 = argv[2];
int result;
result = sscanf(filename1, "keys_%8x_%2d_%8x.dic", &uid1, &sector1, &nt1);
@ -105,13 +105,13 @@ int main(int argc, char *const argv[]) {
init_lfsr16_table();
uint32_t keycount1 = 0;
uint64_t* keys1 = NULL;
uint8_t* filter_keys1 = NULL;
uint16_t* seednt1 = NULL;
uint64_t *keys1 = NULL;
uint8_t *filter_keys1 = NULL;
uint16_t *seednt1 = NULL;
uint32_t keycount2 = 0;
uint64_t* keys2 = NULL;
uint8_t* filter_keys2 = NULL;
FILE* fptr;
uint64_t *keys2 = NULL;
uint8_t *filter_keys2 = NULL;
FILE *fptr;
fptr = fopen(filename1, "r");
if (fptr != NULL) {
@ -120,9 +120,9 @@ int main(int argc, char *const argv[]) {
keycount1++;
}
keys1 = (uint64_t*)malloc(keycount1 * sizeof(uint64_t));
filter_keys1 = (uint8_t*)calloc(keycount1, sizeof(uint8_t));
if ((keys1 == NULL)||(filter_keys1 == NULL)) {
keys1 = (uint64_t *)malloc(keycount1 * sizeof(uint64_t));
filter_keys1 = (uint8_t *)calloc(keycount1, sizeof(uint8_t));
if ((keys1 == NULL) || (filter_keys1 == NULL)) {
perror("Failed to allocate memory");
fclose(fptr);
goto end;
@ -149,9 +149,9 @@ int main(int argc, char *const argv[]) {
keycount2++;
}
keys2 = (uint64_t*)malloc(keycount2 * sizeof(uint64_t));
filter_keys2 = (uint8_t*)calloc(keycount2, sizeof(uint8_t));
if ((keys2 == NULL)||(filter_keys2 == NULL)) {
keys2 = (uint64_t *)malloc(keycount2 * sizeof(uint64_t));
filter_keys2 = (uint8_t *)calloc(keycount2, sizeof(uint8_t));
if ((keys2 == NULL) || (filter_keys2 == NULL)) {
perror("Failed to allocate memory");
fclose(fptr);
goto end;
@ -174,7 +174,7 @@ int main(int argc, char *const argv[]) {
printf("%s: %i keys loaded\n", filename1, keycount1);
printf("%s: %i keys loaded\n", filename2, keycount2);
seednt1 = (uint16_t*)malloc(keycount1 * sizeof(uint16_t));
seednt1 = (uint16_t *)malloc(keycount1 * sizeof(uint16_t));
if (seednt1 == NULL) {
perror("Failed to allocate memory");
goto end;

View file

@ -25,7 +25,7 @@ uint16_t s_lfsr16[1 << 16] = {0};
static void init_lfsr16_table(void) {
uint16_t x = 1;
for (uint16_t i=1; i; ++i) {
for (uint16_t i = 1; i; ++i) {
i_lfsr16[(x & 0xff) << 8 | x >> 8] = i;
s_lfsr16[i] = (x & 0xff) << 8 | x >> 8;
x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15;
@ -37,7 +37,7 @@ static void init_lfsr16_table(void) {
// }
static uint16_t prev_lfsr16(uint16_t nonce) {
return s_lfsr16[(i_lfsr16[nonce]-1) % 65535];
return s_lfsr16[(i_lfsr16[nonce] - 1) % 65535];
}
static uint16_t compute_seednt16_nt32(uint32_t nt32, uint64_t key) {
@ -45,13 +45,13 @@ static uint16_t compute_seednt16_nt32(uint32_t nt32, uint64_t key) {
uint8_t b[] = {0, 13, 1, 14, 4, 10, 15, 7, 5, 3, 8, 6, 9, 2, 12, 11};
uint16_t nt = nt32 >> 16;
uint8_t prev = 14;
for (uint8_t i=0; i<prev; i++) {
for (uint8_t i = 0; i < prev; i++) {
nt = prev_lfsr16(nt);
}
uint8_t prevoff = 8;
bool odd = 1;
for (uint8_t i=0; i<6*8; i+=8) {
for (uint8_t i = 0; i < 6 * 8; i += 8) {
if (odd) {
nt ^= (a[(key >> i) & 0xF]);
nt ^= (b[(key >> i >> 4) & 0xF]) << 4;
@ -61,7 +61,7 @@ static uint16_t compute_seednt16_nt32(uint32_t nt32, uint64_t key) {
}
odd ^= 1;
prev += prevoff;
for (uint8_t j=0; j<prevoff; j++) {
for (uint8_t j = 0; j < prevoff; j++) {
nt = prev_lfsr16(nt);
}
}
@ -82,7 +82,7 @@ int main(int argc, char *const argv[]) {
return 1;
}
char *filename= argv[3];
char *filename = argv[3];
uint32_t uid, sector, nt2;
int result;
@ -99,16 +99,16 @@ int main(int argc, char *const argv[]) {
init_lfsr16_table();
uint32_t keycount2 = 0;
uint64_t* keys2 = NULL;
uint64_t *keys2 = NULL;
FILE* fptr = fopen(filename, "r");
FILE *fptr = fopen(filename, "r");
if (fptr != NULL) {
uint64_t buffer;
while (fscanf(fptr, "%012" PRIx64, &buffer) == 1) {
keycount2++;
}
keys2 = (uint64_t*)malloc(keycount2 * sizeof(uint64_t));
keys2 = (uint64_t *)malloc(keycount2 * sizeof(uint64_t));
if (keys2 == NULL) {
perror("Failed to allocate memory");
fclose(fptr);