mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 13:23:51 -07:00
hf mf fchk: allow to crack a single key and show progress info
This commit is contained in:
parent
29c180285e
commit
98273d00ae
4 changed files with 95 additions and 15 deletions
|
@ -1557,10 +1557,14 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
|
||||||
uint8_t sectorcnt = arg0 & 0xFF; // 16;
|
uint8_t sectorcnt = arg0 & 0xFF; // 16;
|
||||||
uint8_t firstchunk = (arg0 >> 8) & 0xF;
|
uint8_t firstchunk = (arg0 >> 8) & 0xF;
|
||||||
uint8_t lastchunk = (arg0 >> 12) & 0xF;
|
uint8_t lastchunk = (arg0 >> 12) & 0xF;
|
||||||
|
uint16_t singleSectorParams = (arg0 >> 16) & 0xFFFF;
|
||||||
uint8_t strategy = arg1 & 0xFF;
|
uint8_t strategy = arg1 & 0xFF;
|
||||||
uint8_t use_flashmem = (arg1 >> 8) & 0xFF;
|
uint8_t use_flashmem = (arg1 >> 8) & 0xFF;
|
||||||
uint16_t keyCount = arg2 & 0xFF;
|
uint16_t keyCount = arg2 & 0xFF;
|
||||||
uint8_t status = 0;
|
uint8_t status = 0;
|
||||||
|
bool singleSectorMode = (singleSectorParams >> 15) & 1;
|
||||||
|
uint8_t keytype = (singleSectorParams >> 8) & 1;
|
||||||
|
uint8_t blockn = singleSectorParams & 0xFF;
|
||||||
|
|
||||||
struct Crypto1State mpcs = {0, 0};
|
struct Crypto1State mpcs = {0, 0};
|
||||||
struct Crypto1State *pcs;
|
struct Crypto1State *pcs;
|
||||||
|
@ -1661,6 +1665,37 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
|
||||||
chk_data.pcs = pcs;
|
chk_data.pcs = pcs;
|
||||||
chk_data.block = 0;
|
chk_data.block = 0;
|
||||||
|
|
||||||
|
if (singleSectorMode) {
|
||||||
|
chk_data.block = blockn;
|
||||||
|
chk_data.keyType = keytype;
|
||||||
|
for (uint16_t i = 0; i < keyCount; ++i) {
|
||||||
|
|
||||||
|
// Allow button press / usb cmd to interrupt device
|
||||||
|
if (BUTTON_PRESS() || data_available()) {
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
WDT_HIT();
|
||||||
|
|
||||||
|
chk_data.key = bytes_to_num(datain + i * 6, 6);
|
||||||
|
if (chkKey(&chk_data) == 0) {
|
||||||
|
reply_old(CMD_ACK, 1, 0, 0, datain + i * 6, 6);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
|
||||||
|
out:
|
||||||
|
LEDsoff();
|
||||||
|
crypto1_deinit(pcs);
|
||||||
|
set_tracing(false);
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
BigBuf_free();
|
||||||
|
BigBuf_Clear_ext(false);
|
||||||
|
g_dbglevel = oldbg;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// keychunk loop - depth first one sector.
|
// keychunk loop - depth first one sector.
|
||||||
if (strategy == 1 || use_flashmem) {
|
if (strategy == 1 || use_flashmem) {
|
||||||
|
|
||||||
|
|
|
@ -3241,6 +3241,9 @@ static int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
arg_lit0(NULL, "dump", "Dump found keys to binary file"),
|
arg_lit0(NULL, "dump", "Dump found keys to binary file"),
|
||||||
arg_lit0(NULL, "mem", "Use dictionary from flashmemory"),
|
arg_lit0(NULL, "mem", "Use dictionary from flashmemory"),
|
||||||
arg_str0("f", "file", "<fn>", "filename of dictionary"),
|
arg_str0("f", "file", "<fn>", "filename of dictionary"),
|
||||||
|
arg_int0(NULL, "blk", "<dec>", "block number (single block recovery mode)"),
|
||||||
|
arg_lit0("a", NULL, "single block recovery key A"),
|
||||||
|
arg_lit0("b", NULL, "single block recovery key B"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
@ -3262,6 +3265,16 @@ static int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
char filename[FILE_PATH_SIZE] = {0};
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
CLIParamStrToBuf(arg_get_str(ctx, 9), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
CLIParamStrToBuf(arg_get_str(ctx, 9), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||||
|
|
||||||
|
int blockn = arg_get_int_def(ctx, 10, -1);
|
||||||
|
uint8_t keytype = MF_KEY_A;
|
||||||
|
if (arg_get_lit(ctx, 11) && arg_get_lit(ctx, 12)) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
PrintAndLogEx(WARNING, "Input key type must be A or B");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
} else if (arg_get_lit(ctx, 12)) {
|
||||||
|
keytype = MF_KEY_B;
|
||||||
|
}
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
//validations
|
//validations
|
||||||
|
@ -3309,12 +3322,16 @@ static int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
// time
|
// time
|
||||||
uint64_t t1 = msclock();
|
uint64_t t1 = msclock();
|
||||||
|
|
||||||
|
uint16_t singleSectorParams = 0;
|
||||||
|
if (blockn != -1) {
|
||||||
|
singleSectorParams = (blockn & 0xFF)| keytype << 8 | 1 << 15;
|
||||||
|
}
|
||||||
if (use_flashmemory) {
|
if (use_flashmemory) {
|
||||||
PrintAndLogEx(SUCCESS, "Using dictionary in flash memory");
|
PrintAndLogEx(SUCCESS, "Using dictionary in flash memory");
|
||||||
mfCheckKeys_fast(sectorsCnt, true, true, 1, 0, keyBlock, e_sector, use_flashmemory, false);
|
mfCheckKeys_fast_ex(sectorsCnt, true, true, 1, 0, keyBlock, e_sector, use_flashmemory, false, false, singleSectorParams);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// strategys. 1= deep first on sector 0 AB, 2= width first on all sectors
|
// strategies. 1= deep first on sector 0 AB, 2= width first on all sectors
|
||||||
for (uint8_t strategy = 1; strategy < 3; strategy++) {
|
for (uint8_t strategy = 1; strategy < 3; strategy++) {
|
||||||
PrintAndLogEx(INFO, "Running strategy %u", strategy);
|
PrintAndLogEx(INFO, "Running strategy %u", strategy);
|
||||||
|
|
||||||
|
@ -3322,33 +3339,41 @@ static int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
for (i = 0; i < keycnt; i += chunksize) {
|
for (i = 0; i < keycnt; i += chunksize) {
|
||||||
|
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
|
PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
PrintAndLogEx(INPLACE, "Testing %5i/%5i %02.1f%%", i, keycnt, (float)i * 100 / keycnt);
|
||||||
uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i;
|
uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i;
|
||||||
|
|
||||||
// last chunk?
|
// last chunk?
|
||||||
if (size == keycnt - i)
|
if (size == keycnt - i)
|
||||||
lastChunk = true;
|
lastChunk = true;
|
||||||
|
|
||||||
int res = mfCheckKeys_fast(sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * MIFARE_KEY_SIZE), e_sector, false, false);
|
int res = mfCheckKeys_fast_ex(sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * MIFARE_KEY_SIZE), e_sector, false, false, true, singleSectorParams);
|
||||||
|
|
||||||
if (firstChunk)
|
if (firstChunk)
|
||||||
firstChunk = false;
|
firstChunk = false;
|
||||||
|
|
||||||
// all keys, aborted
|
// all keys, aborted
|
||||||
if (res == PM3_SUCCESS || res == 2)
|
if (res == PM3_SUCCESS || res == 2) {
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
} // end chunks of keys
|
} // end chunks of keys
|
||||||
|
PrintAndLogEx(INPLACE, "Testing %5i/%5i 100.00%%", keycnt, keycnt);
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
firstChunk = true;
|
firstChunk = true;
|
||||||
lastChunk = false;
|
lastChunk = false;
|
||||||
|
if (blockn != -1) break;
|
||||||
} // end strategy
|
} // end strategy
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
t1 = msclock() - t1;
|
t1 = msclock() - t1;
|
||||||
PrintAndLogEx(INFO, "time in checkkeys (fast) " _YELLOW_("%.1fs") "\n", (float)(t1 / 1000.0));
|
PrintAndLogEx(INFO, "Time in checkkeys (fast) " _YELLOW_("%.1fs") "\n", (float)(t1 / 1000.0));
|
||||||
|
|
||||||
|
if (blockn != -1) {
|
||||||
|
goto out2;
|
||||||
|
}
|
||||||
|
|
||||||
// check..
|
// check..
|
||||||
uint8_t found_keys = 0;
|
uint8_t found_keys = 0;
|
||||||
|
@ -3413,7 +3438,7 @@ out:
|
||||||
free(fptr);
|
free(fptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
out2:
|
||||||
free(keyBlock);
|
free(keyBlock);
|
||||||
free(e_sector);
|
free(e_sector);
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
|
@ -221,21 +221,24 @@ int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keyc
|
||||||
// 0 == ok all keys found
|
// 0 == ok all keys found
|
||||||
// 1 ==
|
// 1 ==
|
||||||
// 2 == Time-out, aborting
|
// 2 == Time-out, aborting
|
||||||
int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t strategy,
|
int mfCheckKeys_fast_ex(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) {
|
uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory,
|
||||||
|
bool verbose, bool quiet, uint16_t singleSectorParams) {
|
||||||
|
|
||||||
uint64_t t2 = msclock();
|
uint64_t t2 = msclock();
|
||||||
|
|
||||||
// send keychunk
|
// send keychunk
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandOLD(CMD_HF_MIFARE_CHKKEYS_FAST, (sectorsCnt | (firstChunk << 8) | (lastChunk << 12)), ((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, 6 * size);
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
|
||||||
uint32_t timeout = 0;
|
uint32_t timeout = 0;
|
||||||
while (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
|
while (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
|
||||||
|
|
||||||
PrintAndLogEx((timeout) ? NORMAL : INFO, "." NOLF);
|
if (! quiet) {
|
||||||
fflush(stdout);
|
PrintAndLogEx((timeout) ? NORMAL : INFO, "." NOLF);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
timeout++;
|
timeout++;
|
||||||
|
|
||||||
|
@ -249,13 +252,22 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk,
|
||||||
}
|
}
|
||||||
t2 = msclock() - t2;
|
t2 = msclock() - t2;
|
||||||
|
|
||||||
if (timeout) {
|
if (timeout && ! quiet) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// time to convert the returned data.
|
// time to convert the returned data.
|
||||||
uint8_t curr_keys = resp.oldarg[0];
|
uint8_t curr_keys = resp.oldarg[0];
|
||||||
|
|
||||||
|
if ((singleSectorParams >> 15) & 1) {
|
||||||
|
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);
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(INFO, "Chunk %.1fs | found %u/%u keys (%u)", (float)(t2 / 1000.0), curr_keys, (sectorsCnt << 1), size);
|
PrintAndLogEx(INFO, "Chunk %.1fs | found %u/%u keys (%u)", (float)(t2 / 1000.0), curr_keys, (sectorsCnt << 1), size);
|
||||||
}
|
}
|
||||||
|
@ -317,6 +329,11 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk,
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mfCheckKeys_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 mfCheckKeys_fast_ex(sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock, e_sector, use_flashmemory, verbose, false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Trigger device to use a binary file on flash mem as keylist for mfCheckKeys.
|
// Trigger device to use a binary file on flash mem as keylist for mfCheckKeys.
|
||||||
// As of now, 255 keys possible in the file
|
// As of now, 255 keys possible in the file
|
||||||
// 6 * 255 = 1500 bytes
|
// 6 * 255 = 1500 bytes
|
||||||
|
|
|
@ -76,6 +76,9 @@ int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keyc
|
||||||
int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk,
|
int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk,
|
||||||
uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector,
|
uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector,
|
||||||
bool use_flashmemory, bool verbose);
|
bool use_flashmemory, bool verbose);
|
||||||
|
int mfCheckKeys_fast_ex(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, bool quiet, uint16_t singleSectorParams);
|
||||||
|
|
||||||
int mfCheckKeys_file(uint8_t *destfn, uint64_t *key);
|
int mfCheckKeys_file(uint8_t *destfn, uint64_t *key);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue