mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 10:37:23 -07:00
textual changes, one fix for overflows when sending OLD frames. Now inform and breaks like MIXED/NG does. Improved hf mf autopwn
to detect static encrypted nonces and inform user. Last fix is the user abort during check keys steps in autopwn. The device side now detects and cancels if no card is available and on client it also allows to user abort
This commit is contained in:
parent
c0af6cd7d2
commit
c8d46a2a7c
7 changed files with 155 additions and 116 deletions
|
@ -3,6 +3,7 @@ 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...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Changed `hf mf autopwn` - tries to detect static encrypted nonces and also user cancel during chk keys (@iceman1001)
|
||||
- Added option to `hf mf autopwn` to use SPI flash dictionary (@jmichelp)
|
||||
- Changed `trace list -t seos` - now annotate ISO7816 (@iceman1001)
|
||||
- Updated aid and mad json files (@iceman1001)
|
||||
|
|
|
@ -356,7 +356,7 @@ static void mf_print_blocks(uint16_t n, uint8_t *d, bool verbose) {
|
|||
|
||||
// MAD detection
|
||||
if (HasMADKey(d)) {
|
||||
PrintAndLogEx(HINT, "Hint: MAD key detected. Try " _YELLOW_("`hf mf mad`") " for more details");
|
||||
PrintAndLogEx(HINT, "Hint: MAD key detected. Try `" _YELLOW_("hf mf mad") "` for more details");
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
|
@ -766,7 +766,7 @@ static int mf_load_keys(uint8_t **pkeyBlock, uint32_t *pkeycnt, uint8_t *userkey
|
|||
PrintAndLogEx(DEBUG, _YELLOW_("%2d") " - %s", i, sprint_hex(*pkeyBlock + i * MIFARE_KEY_SIZE, MIFARE_KEY_SIZE));
|
||||
}
|
||||
*pkeycnt += numKeys;
|
||||
PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") " user keys", numKeys);
|
||||
PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%d") " user keys", numKeys);
|
||||
}
|
||||
|
||||
if (load_default) {
|
||||
|
@ -2555,7 +2555,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
|||
bool in = arg_get_lit(ctx, 16);
|
||||
#if defined(COMPILER_HAS_SIMD_X86)
|
||||
bool im = arg_get_lit(ctx, 17);
|
||||
bool is = arg_get_lit(ctx, 1);
|
||||
bool is = arg_get_lit(ctx, 18);
|
||||
bool ia = arg_get_lit(ctx, 19);
|
||||
bool i2 = arg_get_lit(ctx, 20);
|
||||
#endif
|
||||
|
@ -2754,6 +2754,9 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
|||
free(fptr);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
//
|
||||
has_staticnonce = detect_classic_static_encrypted_nonce(0, MF_KEY_A, g_mifare_default_key);
|
||||
}
|
||||
|
||||
// print parameters
|
||||
|
@ -2765,12 +2768,24 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
|||
PrintAndLogEx(INFO, " keytype ....... " _YELLOW_("%c"), (keytype == MF_KEY_B) ? 'B' : 'A');
|
||||
PrintAndLogEx(INFO, " known key ..... " _YELLOW_("%s"), sprint_hex_inrow(key, sizeof(key)));
|
||||
|
||||
if (has_staticnonce == NONCE_STATIC)
|
||||
switch(has_staticnonce) {
|
||||
case NONCE_STATIC: {
|
||||
PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("STATIC"));
|
||||
else if (has_staticnonce == NONCE_NORMAL)
|
||||
break;
|
||||
}
|
||||
case NONCE_STATIC_ENC: {
|
||||
PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("STATIC ENCRYPTED"));
|
||||
break;
|
||||
}
|
||||
case NONCE_NORMAL: {
|
||||
PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("%s"), prng_type ? "WEAK" : "HARD");
|
||||
else
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("Could not determine PRNG,") " " _RED_("read failed."));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, " dictionary .... " _YELLOW_("%s"), strlen(filename) ? filename : "NONE");
|
||||
PrintAndLogEx(INFO, " legacy mode ... " _YELLOW_("%s"), legacy_mfchk ? "True" : "False");
|
||||
|
@ -2826,6 +2841,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
|||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
} else {
|
||||
|
||||
if (use_flashmemory) {
|
||||
PrintAndLogEx(SUCCESS, "Using dictionary in flash memory");
|
||||
res = mf_check_keys_fast(sector_cnt, true, true, 1, key_cnt, keyBlock, e_sector, use_flashmemory, verbose);
|
||||
|
@ -2845,6 +2861,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
|||
strategy = 3;
|
||||
break; // Exit the loop
|
||||
}
|
||||
|
||||
uint32_t size = ((key_cnt - i) > chunksize) ? chunksize : key_cnt - i;
|
||||
// last chunk?
|
||||
if (size == key_cnt - i) {
|
||||
|
@ -2919,8 +2936,9 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
|||
|
||||
isOK = mf_dark_side(mfFirstBlockOfSector(sectorno), MIFARE_AUTH_KEYA + keytype, &key64);
|
||||
|
||||
if (isOK != PM3_SUCCESS)
|
||||
if (isOK != PM3_SUCCESS) {
|
||||
goto noValidKeyFound;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Found valid key [ " _GREEN_("%012" PRIx64) " ]\n", key64);
|
||||
|
||||
|
@ -2937,7 +2955,15 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
|||
|
||||
noValidKeyFound:
|
||||
PrintAndLogEx(FAILED, "No usable key was found!");
|
||||
if (use_flashmemory == false && fnlen == 0) {
|
||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf mf autopwn -f mfc_default_keys")"` i.e. the Randy special");
|
||||
}
|
||||
|
||||
if (has_staticnonce == NONCE_STATIC_ENC) {
|
||||
PrintAndLogEx(HINT, "Hint: Static encrypted nonce detected, run `" _YELLOW_("script run fm11rf08s_recovery.py") "`");
|
||||
}
|
||||
|
||||
DropField();
|
||||
free(keyBlock);
|
||||
free(e_sector);
|
||||
free(fptr);
|
||||
|
@ -3295,10 +3321,10 @@ all_found:
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
strncpy(filename, fptr, sizeof(filename) - 1);
|
||||
strncpy(outfilename, fptr, sizeof(outfilename) - 1);
|
||||
free(fptr);
|
||||
|
||||
pm3_save_mf_dump(filename, dump, bytes, jsfCardMemory);
|
||||
pm3_save_mf_dump(outfilename, dump, bytes, jsfCardMemory);
|
||||
free(dump);
|
||||
|
||||
out:
|
||||
|
@ -3306,6 +3332,7 @@ out:
|
|||
t1 = msclock() - t1;
|
||||
PrintAndLogEx(INFO, "autopwn execution time: " _YELLOW_("%.0f") " seconds", (float)t1 / 1000.0);
|
||||
|
||||
DropField();
|
||||
free(e_sector);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -3397,7 +3424,6 @@ static int CmdHF14AMfChk_fast(const char *Cmd) {
|
|||
|
||||
uint8_t *keyBlock = NULL;
|
||||
uint32_t keycnt = 0;
|
||||
|
||||
// If we use the dictionary in flash memory, we don't want to load keys
|
||||
// from hard drive dictionary as it could exceed BigBuf capacity
|
||||
if (use_flashmemory) {
|
||||
|
@ -9923,7 +9949,7 @@ static int CmdHF14AMfInfo(const char *Cmd) {
|
|||
}
|
||||
|
||||
if (res == NONCE_STATIC_ENC) {
|
||||
PrintAndLogEx(HINT, "try `" _YELLOW_("script run fm11rf08s_recovery.py") "`");
|
||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("script run fm11rf08s_recovery.py") "`");
|
||||
}
|
||||
|
||||
if (setDeviceDebugLevel(dbg_curr, false) != PM3_SUCCESS) {
|
||||
|
|
|
@ -88,7 +88,15 @@ void SendCommandBL(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, vo
|
|||
}
|
||||
|
||||
void SendCommandOLD(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, const void *data, size_t len) {
|
||||
|
||||
PacketCommandOLD c = {CMD_UNKNOWN, {0, 0, 0}, {{0}}};
|
||||
|
||||
if (len > PM3_CMD_DATA_SIZE) {
|
||||
PrintAndLogEx(WARNING, "Sending " _RED_("%zu") " bytes of payload is too much for OLD frames, abort", len);
|
||||
return;
|
||||
// return PM3_EOUTOFBOUND;
|
||||
}
|
||||
|
||||
c.cmd = cmd;
|
||||
c.arg[0] = arg0;
|
||||
c.arg[1] = arg1;
|
||||
|
@ -97,6 +105,7 @@ void SendCommandOLD(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, c
|
|||
memcpy(&c.d, data, len);
|
||||
}
|
||||
|
||||
|
||||
#ifdef COMMS_DEBUG
|
||||
PrintAndLogEx(NORMAL, "Sending %s", "OLD");
|
||||
#endif
|
||||
|
@ -142,7 +151,7 @@ static void SendCommandNG_internal(uint16_t cmd, uint8_t *data, size_t len, bool
|
|||
return;
|
||||
}
|
||||
if (len > PM3_CMD_DATA_SIZE) {
|
||||
PrintAndLogEx(WARNING, "Sending %zu bytes of payload is too much, abort", len);
|
||||
PrintAndLogEx(WARNING, "Sending " _RED_("%zu") " bytes of payload is too much, abort", len);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -203,7 +212,7 @@ void SendCommandNG(uint16_t cmd, uint8_t *data, size_t len) {
|
|||
void SendCommandMIX(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, const void *data, size_t len) {
|
||||
uint64_t arg[3] = {arg0, arg1, arg2};
|
||||
if (len > PM3_CMD_DATA_SIZE_MIX) {
|
||||
PrintAndLogEx(WARNING, "Sending %zu bytes of payload is too much for MIX frames, abort", len);
|
||||
PrintAndLogEx(WARNING, "Sending " _RED_("%zu") " bytes of payload is too much for MIX frames, abort", len);
|
||||
return;
|
||||
}
|
||||
uint8_t cmddata[PM3_CMD_DATA_SIZE];
|
||||
|
|
|
@ -209,10 +209,12 @@ int mf_dark_side(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
|||
}
|
||||
|
||||
int mf_check_keys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key) {
|
||||
|
||||
if (key) {
|
||||
*key = -1;
|
||||
}
|
||||
clearCommandBuffer();
|
||||
|
||||
|
||||
uint8_t data[PM3_CMD_DATA_SIZE] = {0};
|
||||
data[0] = keyType;
|
||||
data[1] = blockNo;
|
||||
|
@ -220,12 +222,14 @@ int mf_check_keys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t ke
|
|||
data[3] = 0;
|
||||
data[4] = keycnt;
|
||||
memcpy(data + 5, keyBlock, MIFARE_KEY_SIZE * keycnt);
|
||||
SendCommandNG(CMD_HF_MIFARE_CHKKEYS, data, (5 + MIFARE_KEY_SIZE * keycnt));
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFARE_CHKKEYS, data, (5 + MIFARE_KEY_SIZE * keycnt));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS, &resp, 2500) == false) {
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
return resp.status;
|
||||
}
|
||||
|
@ -257,12 +261,24 @@ int mf_check_keys_fast_ex(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastCh
|
|||
|
||||
// send keychunk
|
||||
clearCommandBuffer();
|
||||
SendCommandOLD(CMD_HF_MIFARE_CHKKEYS_FAST, (sectorsCnt | (firstChunk << 8) | (lastChunk << 12) | (singleSectorParams << 16)), ((use_flashmemory << 8) | strategy), size, keyBlock, 6 * size);
|
||||
SendCommandOLD(CMD_HF_MIFARE_CHKKEYS_FAST
|
||||
, (sectorsCnt | (firstChunk << 8) | (lastChunk << 12) | (singleSectorParams << 16))
|
||||
, ((use_flashmemory << 8) | strategy)
|
||||
, size
|
||||
, keyBlock
|
||||
, (MIFARE_KEY_SIZE * size)
|
||||
);
|
||||
PacketResponseNG resp;
|
||||
|
||||
uint32_t timeout = 0;
|
||||
while (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
|
||||
|
||||
while (kbd_enter_pressed()) {
|
||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_EOPABORTED;
|
||||
}
|
||||
|
||||
if (quiet == false) {
|
||||
PrintAndLogEx((timeout) ? NORMAL : INFO, "." NOLF);
|
||||
fflush(stdout);
|
||||
|
@ -285,7 +301,6 @@ int mf_check_keys_fast_ex(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastCh
|
|||
if (timeout && (quiet == false)) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
|
||||
// time to convert the returned data.
|
||||
uint8_t curr_keys = resp.oldarg[0];
|
||||
|
||||
|
@ -366,8 +381,9 @@ int mf_check_keys_fast_ex(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastCh
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
int mf_check_keys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t strategy,
|
||||
uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory, bool verbose) {
|
||||
int mf_check_keys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t strategy
|
||||
, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory
|
||||
, bool verbose) {
|
||||
return mf_check_keys_fast_ex(sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock, e_sector, use_flashmemory, verbose, false, 0);
|
||||
}
|
||||
|
||||
|
@ -375,8 +391,10 @@ int mf_check_keys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk
|
|||
// As of now, 255 keys possible in the file
|
||||
// 6 * 255 = 1500 bytes
|
||||
int mf_check_keys_file(uint8_t *destfn, uint64_t *key) {
|
||||
|
||||
if (key) {
|
||||
*key = -1;
|
||||
clearCommandBuffer();
|
||||
}
|
||||
|
||||
struct {
|
||||
uint8_t filename[32];
|
||||
|
@ -384,13 +402,14 @@ int mf_check_keys_file(uint8_t *destfn, uint64_t *key) {
|
|||
|
||||
memcpy(payload_file.filename, destfn, sizeof(payload_file.filename) - 1);
|
||||
|
||||
clearCommandBuffer();
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFARE_CHKKEYS_FILE, (uint8_t *)&payload_file, sizeof(payload_file));
|
||||
|
||||
uint8_t retry = 10;
|
||||
|
||||
while (!WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS, &resp, 2000)) {
|
||||
while (WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS, &resp, 2000) == false) {
|
||||
|
||||
//flush queue
|
||||
while (kbd_enter_pressed()) {
|
||||
|
@ -406,14 +425,19 @@ int mf_check_keys_file(uint8_t *destfn, uint64_t *key) {
|
|||
}
|
||||
}
|
||||
|
||||
if (resp.status != PM3_SUCCESS) return resp.status;
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
return resp.status;
|
||||
}
|
||||
|
||||
struct kr {
|
||||
uint8_t key[MIFARE_KEY_SIZE];
|
||||
bool found;
|
||||
} PACKED;
|
||||
struct kr *keyresult = (struct kr *)&resp.data.asBytes;
|
||||
if (!keyresult->found) return PM3_ESOFT;
|
||||
|
||||
if (keyresult->found == false) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
*key = bytes_to_num(keyresult->key, sizeof(keyresult->key));
|
||||
return PM3_SUCCESS;
|
||||
|
@ -457,9 +481,10 @@ int mf_key_brute(uint8_t blockNo, uint8_t keyType, const uint8_t *key, uint64_t
|
|||
}
|
||||
|
||||
// progress
|
||||
if (counter % 20 == 0)
|
||||
if (counter % 20 == 0) {
|
||||
PrintAndLogEx(SUCCESS, "tried %s.. \t %u keys", sprint_hex(candidates + i, 6), counter * KEYS_IN_BLOCK);
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
|
@ -494,7 +519,7 @@ __attribute__((force_align_arg_pointer))
|
|||
|
||||
int mf_nested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate) {
|
||||
|
||||
uint32_t uid;
|
||||
uint32_t uid = 0;
|
||||
StateList_t statelists[2];
|
||||
struct Crypto1State *p1, *p2, *p3, *p4;
|
||||
|
||||
|
@ -611,7 +636,9 @@ int mf_nested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo
|
|||
|
||||
//statelists[0].tail.keytail = --p7;
|
||||
uint32_t keycnt = statelists[0].len;
|
||||
if (keycnt == 0) goto out;
|
||||
if (keycnt == 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") " key candidates", keycnt);
|
||||
|
||||
|
@ -680,7 +707,7 @@ out:
|
|||
|
||||
int mf_static_nested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey) {
|
||||
|
||||
uint32_t uid;
|
||||
uint32_t uid = 0;
|
||||
StateList_t statelists[2];
|
||||
struct Crypto1State *p1, *p2, *p3, *p4;
|
||||
|
||||
|
@ -789,48 +816,6 @@ int mf_static_nested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trg
|
|||
// Create the intersection
|
||||
statelists[0].len = intersection(statelists[0].head.keyhead, statelists[1].head.keyhead);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
memcpy(&uid, package->cuid, sizeof(package->cuid));
|
||||
|
||||
statelists[0].blockNo = package->block;
|
||||
statelists[0].keyType = package->keytype;
|
||||
statelists[0].uid = uid;
|
||||
|
||||
memcpy(&statelists[0].nt_enc, package->nt, sizeof(package->nt));
|
||||
memcpy(&statelists[0].ks1, package->ks, sizeof(package->ks));
|
||||
|
||||
// calc keys
|
||||
pthread_t t;
|
||||
|
||||
// create and run worker thread
|
||||
pthread_create(&t, NULL, nested_worker_thread, &statelists[0]);
|
||||
|
||||
// wait for thread to terminate:
|
||||
pthread_join(t, (void *)&statelists[0].head.slhead);
|
||||
|
||||
// the first 16 Bits of the cryptostate already contain part of our key.
|
||||
p1 = p3 = statelists[0].head.slhead;
|
||||
|
||||
// create key candidates.
|
||||
while (p1 <= statelists[0].tail.sltail) {
|
||||
struct Crypto1State savestate;
|
||||
savestate = *p1;
|
||||
while (Compare16Bits(p1, &savestate) == 0 && p1 <= statelists[0].tail.sltail) {
|
||||
*p3 = *p1;
|
||||
lfsr_rollback_word(p3, statelists[0].nt_enc ^ statelists[0].uid, 0);
|
||||
p3++;
|
||||
p1++;
|
||||
}
|
||||
}
|
||||
|
||||
p3->odd = -1;
|
||||
p3->even = -1;
|
||||
statelists[0].len = p3 - statelists[0].head.slhead;
|
||||
statelists[0].tail.sltail = --p3;
|
||||
*/
|
||||
|
||||
uint32_t keycnt = statelists[0].len;
|
||||
if (keycnt == 0) {
|
||||
goto out;
|
||||
|
@ -1060,7 +1045,7 @@ int mf_eml_get_mem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtW
|
|||
SendCommandNG(CMD_HF_MIFARE_EML_MEMGET, (uint8_t *)&payload, sizeof(payload));
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_EML_MEMGET, &resp, 1500) == 0) {
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_EML_MEMGET, &resp, 1500) == false) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
@ -1182,13 +1167,16 @@ int mf_chinese_wipe(uint8_t *uid, const uint8_t *atqa, const uint8_t *sak, uint8
|
|||
memcpy(block0, uid, 4);
|
||||
block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3];
|
||||
}
|
||||
if (sak != NULL)
|
||||
|
||||
if (sak != NULL) {
|
||||
block0[5] = sak[0];
|
||||
}
|
||||
|
||||
if (atqa != NULL) {
|
||||
block0[6] = atqa[1];
|
||||
block0[7] = atqa[0];
|
||||
}
|
||||
|
||||
int res;
|
||||
for (int blockNo = 0; blockNo < 4 * 16; blockNo++) {
|
||||
for (int retry = 0; retry < 3; retry++) {
|
||||
|
@ -1198,14 +1186,16 @@ int mf_chinese_wipe(uint8_t *uid, const uint8_t *atqa, const uint8_t *sak, uint8
|
|||
if (blockNo == 0) {
|
||||
res = mf_chinese_set_block(blockNo, block0, NULL, params);
|
||||
} else {
|
||||
if (mfIsSectorTrailer(blockNo))
|
||||
if (mfIsSectorTrailer(blockNo)) {
|
||||
res = mf_chinese_set_block(blockNo, blockK, NULL, params);
|
||||
else
|
||||
} else {
|
||||
res = mf_chinese_set_block(blockNo, blockD, NULL, params);
|
||||
}
|
||||
}
|
||||
|
||||
if (res == PM3_SUCCESS)
|
||||
if (res == PM3_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
PrintAndLogEx(WARNING, "retry block %d ...", blockNo);
|
||||
}
|
||||
|
@ -1221,16 +1211,22 @@ int mf_chinese_wipe(uint8_t *uid, const uint8_t *atqa, const uint8_t *sak, uint8
|
|||
}
|
||||
|
||||
int mf_chinese_set_block(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) {
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_MIFARE_CSETBL, params, blockNo, 0, data, MFBLOCK_SIZE);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 3500)) {
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 3500) == false) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(WARNING, "Command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
uint8_t isOK = resp.oldarg[0] & 0xFF;
|
||||
if (uid != NULL) {
|
||||
memcpy(uid, resp.data.asBytes, 4);
|
||||
}
|
||||
|
||||
if (!isOK) {
|
||||
if (isOK == 0) {
|
||||
|
||||
uint8_t reason = (resp.oldarg[1] & 0xFF);
|
||||
if (reason == 4) {
|
||||
|
@ -1243,11 +1239,7 @@ int mf_chinese_set_block(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t p
|
|||
|
||||
return PM3_EUNDEF;
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(WARNING, "Command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1257,7 +1249,7 @@ int mf_chinese_get_block(uint8_t blockNo, uint8_t *data, uint8_t params) {
|
|||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
||||
if (!isOK) {
|
||||
if (isOK == 0) {
|
||||
return PM3_EUNDEF;
|
||||
}
|
||||
memcpy(data, resp.data.asBytes, MFBLOCK_SIZE);
|
||||
|
@ -1287,32 +1279,28 @@ int mf_chinese_gen_3_block(uint8_t *block, int blockLen, uint8_t *newBlock) {
|
|||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_MIFARE_GEN3BLK, blockLen, 0, 0, block, MFBLOCK_SIZE);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3BLK, &resp, 3500)) {
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3BLK, &resp, 3500) == false) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (resp.status == PM3_SUCCESS && newBlock) {
|
||||
memcpy(newBlock, resp.data.asBytes, MFBLOCK_SIZE);
|
||||
}
|
||||
return resp.status;
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
int mf_chinese_gen_3_freeze(void) {
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFARE_GEN3FREEZ, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3FREEZ, &resp, 3500)) {
|
||||
return resp.status;
|
||||
} else {
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3FREEZ, &resp, 3500) == false) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
return resp.status;
|
||||
}
|
||||
|
||||
// variables
|
||||
uint32_t cuid = 0; // uid part used for crypto1.
|
||||
|
||||
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted) {
|
||||
if (len != 1) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
|
@ -1357,9 +1345,8 @@ int detect_classic_prng(void) {
|
|||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443A_READER, flags, sizeof(cmd), 0, cmd, sizeof(cmd));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "PRNG UID: Reply timeout.");
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
|
@ -1369,7 +1356,7 @@ int detect_classic_prng(void) {
|
|||
return PM3_ERFTRANS;
|
||||
}
|
||||
if (WaitForResponseTimeout(CMD_ACK, &respA, 2500) == false) {
|
||||
PrintAndLogEx(WARNING, "PRNG data: Reply timeout.");
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
|
@ -1428,6 +1415,7 @@ int detect_classic_nackbug(bool verbose) {
|
|||
PrintAndLogEx(SUCCESS, "num of auth requests : %u", auths);
|
||||
PrintAndLogEx(SUCCESS, "num of received NACK : %u", nacks);
|
||||
}
|
||||
|
||||
switch (ok) {
|
||||
case 96 :
|
||||
case 98 : {
|
||||
|
@ -1443,19 +1431,23 @@ int detect_classic_nackbug(bool verbose) {
|
|||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
case 2 :
|
||||
case 2: {
|
||||
PrintAndLogEx(SUCCESS, "NACK test: " _GREEN_("always leak NACK"));
|
||||
return PM3_SUCCESS;
|
||||
case 1 :
|
||||
}
|
||||
case 1: {
|
||||
PrintAndLogEx(SUCCESS, "NACK test: " _GREEN_("detected"));
|
||||
return PM3_SUCCESS;
|
||||
case 0 :
|
||||
}
|
||||
case 0: {
|
||||
PrintAndLogEx(SUCCESS, "NACK test: " _GREEN_("no bug"));
|
||||
return PM3_SUCCESS;
|
||||
default :
|
||||
}
|
||||
default: {
|
||||
PrintAndLogEx(ERR, "errorcode from device " _RED_("[%i]"), ok);
|
||||
return PM3_EUNDEF;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1476,8 +1468,9 @@ int detect_classic_static_nonce(void) {
|
|||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_NONCE, &resp, 1000)) {
|
||||
|
||||
if (resp.status == PM3_ESOFT)
|
||||
if (resp.status == PM3_ESOFT) {
|
||||
return NONCE_FAIL;
|
||||
}
|
||||
|
||||
return resp.data.asBytes[0];
|
||||
}
|
||||
|
@ -1492,8 +1485,12 @@ returns:
|
|||
2 = cmd failed
|
||||
3 = has encrypted nonce
|
||||
*/
|
||||
int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type, uint8_t *key, uint8_t block_no_nested, uint8_t key_type_nested, uint8_t *key_nested, uint8_t nr_nested, bool reset, bool hardreset, bool addread, bool addauth, bool incblk2, bool corruptnrar, bool corruptnrarparity, bool verbose) {
|
||||
clearCommandBuffer();
|
||||
int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type, const uint8_t *key, uint8_t block_no_nested
|
||||
, uint8_t key_type_nested, const uint8_t *key_nested
|
||||
, uint8_t nr_nested, bool reset, bool hardreset
|
||||
, bool addread, bool addauth, bool incblk2
|
||||
, bool corruptnrar, bool corruptnrarparity, bool verbose) {
|
||||
|
||||
uint8_t cdata[1 + 1 + MIFARE_KEY_SIZE + 1 + 1 + MIFARE_KEY_SIZE + 1 + 1 + 1 + 1 + 1 + 1 + 1] = { 0 };
|
||||
cdata[0] = block_no;
|
||||
cdata[1] = key_type;
|
||||
|
@ -1508,6 +1505,8 @@ int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type,
|
|||
cdata[20] = incblk2;
|
||||
cdata[21] = corruptnrar;
|
||||
cdata[22] = corruptnrarparity;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, cdata, sizeof(cdata));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, &resp, 1000)) {
|
||||
|
@ -1515,6 +1514,7 @@ int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type,
|
|||
if (resp.status == PM3_ESOFT) {
|
||||
return NONCE_FAIL;
|
||||
}
|
||||
|
||||
if (verbose && (resp.data.asBytes[0] == NONCE_STATIC_ENC)) {
|
||||
|
||||
uint32_t uid = resp.data.asBytes[1] << 24 |
|
||||
|
@ -1539,7 +1539,7 @@ int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type,
|
|||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
||||
uint64_t ui64key = bytes_to_num(key_nested, 6);
|
||||
uint64_t ui64key = bytes_to_num(key_nested, MIFARE_KEY_SIZE);
|
||||
|
||||
crypto1_init(pcs, ui64key); // key_nested
|
||||
uint32_t ks = crypto1_word(pcs, ntenc ^ uid, 1);
|
||||
|
@ -1578,7 +1578,7 @@ int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type,
|
|||
return NONCE_FAIL;
|
||||
}
|
||||
|
||||
int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, uint8_t *key) {
|
||||
int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, const uint8_t *key) {
|
||||
return detect_classic_static_encrypted_nonce_ex(block_no, key_type, key, block_no, key_type, key, 3, false, false, false, false, false, false, false, false);
|
||||
}
|
||||
|
||||
|
@ -1696,8 +1696,9 @@ int read_mfc_ev1_signature(uint8_t *signature) {
|
|||
}
|
||||
|
||||
int convert_mfc_2_arr(uint8_t *in, uint16_t ilen, uint8_t *out, uint16_t *olen) {
|
||||
if (in == NULL || out == NULL)
|
||||
if (in == NULL || out == NULL) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint8_t blockno = 0;
|
||||
while (ilen) {
|
||||
|
|
|
@ -111,8 +111,11 @@ int detect_classic_prng(void);
|
|||
int detect_classic_nackbug(bool verbose);
|
||||
uint16_t detect_mf_magic(bool is_mfc, uint8_t key_type, uint64_t key);
|
||||
int detect_classic_static_nonce(void);
|
||||
int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type, uint8_t *key, uint8_t block_no_nested, uint8_t key_type_nested, uint8_t *key_nested, uint8_t nr_nested, bool reset, bool hardreset, bool addread, bool addauth, bool incblk2, bool corruptnrar, bool corruptnrarparity, bool verbose);
|
||||
int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, uint8_t *key);
|
||||
int detect_classic_static_encrypted_nonce_ex(uint8_t block_no, uint8_t key_type, const uint8_t *key
|
||||
, uint8_t block_no_nested, uint8_t key_type_nested, const uint8_t *key_nested
|
||||
, uint8_t nr_nested, bool reset, bool hardreset, bool addread, bool addauth
|
||||
, bool incblk2, bool corruptnrar, bool corruptnrarparity, bool verbose);
|
||||
int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, const uint8_t *key);
|
||||
bool detect_mfc_ev1_signature(void);
|
||||
int read_mfc_ev1_signature(uint8_t *signature);
|
||||
|
||||
|
|
|
@ -557,9 +557,8 @@ void reverse_arraybytes(uint8_t *arr, size_t len) {
|
|||
}
|
||||
}
|
||||
|
||||
void reverse_arraybytes_copy(uint8_t *arr, uint8_t *dest, size_t len) {
|
||||
size_t i;
|
||||
for (i = 0; i < len ; i++) {
|
||||
void reverse_arraybytes_copy(const uint8_t *arr, uint8_t *dest, size_t len) {
|
||||
for (size_t i = 0; i < len ; i++) {
|
||||
dest[i] = reflect8(arr[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,10 +86,10 @@ void format_version_information_short(char *dst, int len, const void *version_in
|
|||
|
||||
uint32_t reflect(uint32_t v, int b); // used in crc.c ...
|
||||
uint8_t reflect8(uint8_t b); // dedicated 8bit reversal
|
||||
uint16_t reflect16(uint16_t b); // dedicated 16bit reversal
|
||||
uint32_t reflect32(uint32_t b); // dedicated 32bit reversal
|
||||
uint64_t reflect48(uint64_t b); // dedicated 48bit reversal
|
||||
uint64_t reflect64(uint64_t b); // dedicated 64bit reversal
|
||||
uint16_t reflect16(uint16_t v); // dedicated 16bit reversal
|
||||
uint32_t reflect32(uint32_t v); // dedicated 32bit reversal
|
||||
uint64_t reflect48(uint64_t v); // dedicated 48bit reversal
|
||||
uint64_t reflect64(uint64_t v); // dedicated 64bit reversal
|
||||
|
||||
void num_to_bytes(uint64_t n, size_t len, uint8_t *dest);
|
||||
uint64_t bytes_to_num(const uint8_t *src, size_t len);
|
||||
|
@ -150,7 +150,7 @@ void reverse_array_copy(const uint8_t *src, int src_len, uint8_t *dest);
|
|||
bool hexstr_to_byte_array(const char *hexstr, uint8_t *d, size_t *n);
|
||||
|
||||
void reverse_arraybytes(uint8_t *arr, size_t len);
|
||||
void reverse_arraybytes_copy(uint8_t *arr, uint8_t *dest, size_t len);
|
||||
void reverse_arraybytes_copy(const uint8_t *arr, uint8_t *dest, size_t len);
|
||||
|
||||
size_t concatbits(uint8_t *dest, int dest_offset, const uint8_t *src, int src_offset, size_t nbits, bool src_lsb);
|
||||
int char2int(char c);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue