From f4b3488a093551ef9a78ecbbe97ea79d294685b0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 13:11:20 +0100 Subject: [PATCH] chg: 'hf mf static' - now uses file on spiffs for key transfers. speedup on RDV4 --- armsrc/appmain.c | 14 +++- armsrc/mifarecmd.c | 29 ++++++++- armsrc/mifarecmd.h | 1 + client/cmdflashmemspiffs.c | 14 +++- client/mifare/mifarehost.c | 127 +++++++++++++++++++++++++++++-------- client/mifare/mifarehost.h | 3 + include/pm3_cmd.h | 1 + 7 files changed, 153 insertions(+), 36 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index ab0320e75..7c58fd7e6 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -930,12 +930,12 @@ static void PacketReceived(PacketCommandNG *packet) { #ifdef WITH_HITAG case CMD_LF_HITAG_SNIFF: { // Eavesdrop Hitag tag, args = type - SniffHitag(); -// SniffHitag(packet->oldarg[0]); + SniffHitag2(); +// SniffHitag2(packet->oldarg[0]); break; } case CMD_LF_HITAG_SIMULATE: { // Simulate Hitag tag, args = memory content - SimulateHitagTag((bool)packet->oldarg[0], packet->data.asBytes); + SimulateHitag2((bool)packet->oldarg[0], packet->data.asBytes); break; } case CMD_LF_HITAG_READER: { // Reader for Hitag tags, args = type and function @@ -1176,6 +1176,14 @@ static void PacketReceived(PacketCommandNG *packet) { MifareChkKeys_fast(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); break; } + case CMD_HF_MIFARE_CHKKEYS_FILE: { + struct p { + uint8_t filename[32]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + MifareChkKeys_file(payload->filename); + break; + } case CMD_HF_MIFARE_SIMULATE: { struct p { uint16_t flags; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index a0ce705be..cf1115f21 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -33,6 +33,7 @@ #include "dbprint.h" #include "ticks.h" #include "usb_cdc.h" // usb_poll_validate_length +#include "spiffs.h" // spiffs #ifndef HARDNESTED_AUTHENTICATION_TIMEOUT # define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) @@ -1701,14 +1702,15 @@ void MifareChkKeys(uint8_t *datain) { bool found; } PACKED keyresult; keyresult.found = false; - uint8_t blockNo, keyType, keyCount; + uint8_t blockNo, keyType; + uint16_t keyCount; bool clearTrace, have_uid = false; keyType = datain[0]; blockNo = datain[1]; clearTrace = datain[2]; - keyCount = datain[3]; - datain += 4; + keyCount = (datain[3] << 8) | datain[4]; + datain += 5; LEDsoff(); LED_A_ON(); @@ -1780,6 +1782,27 @@ void MifareChkKeys(uint8_t *datain) { DBGLEVEL = oldbg; } +void MifareChkKeys_file(uint8_t *fn) { + + SpinOff(0); + + int changed = rdv40_spiffs_lazy_mount(); + uint32_t size = size_in_spiffs((char *)fn); + uint8_t *mem = BigBuf_malloc(size); + + rdv40_spiffs_read_as_filetype((char *)fn, mem, size, RDV40_SPIFFS_SAFETY_SAFE); + + if (changed) { + rdv40_spiffs_lazy_unmount(); + } + + SpinOff(0); + + MifareChkKeys(mem); + + BigBuf_free(); +} + //----------------------------------------------------------------------------- // Work with emulator memory // diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index cb60ea7c5..1f5ee63a4 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -31,6 +31,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, void MifareAcquireNonces(uint32_t arg0, uint32_t flags); void MifareChkKeys(uint8_t *datain); void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +void MifareChkKeys_file(uint8_t *fn); void MifareEMemClr(void); void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain); diff --git a/client/cmdflashmemspiffs.c b/client/cmdflashmemspiffs.c index 5d003bd2c..bdc51dc5d 100644 --- a/client/cmdflashmemspiffs.c +++ b/client/cmdflashmemspiffs.c @@ -349,10 +349,15 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { bytes_sent += bytes_in_packet; PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + + uint8_t retry = 3; + while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - ret_val = PM3_ETIMEOUT; - break; + retry--; + if (retry == 0) { + ret_val = PM3_ETIMEOUT; + goto out; + } } uint8_t isok = resp.oldarg[0] & 0xFF; @@ -363,6 +368,9 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { } } +out: + clearCommandBuffer(); + // turn off fast push mode conn.block_after_ACK = false; diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index e3021c8f6..df5b2e009 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -17,12 +17,14 @@ #include "comms.h" #include "commonutil.h" #include "mifare4.h" -#include "ui.h" // PrintAndLog... +#include "ui.h" // PrintAndLog... #include "crapto1/crapto1.h" #include "crc16.h" #include "protocols.h" #include "mfkey.h" -#include "util_posix.h" // msclock +#include "util_posix.h" // msclock +#include "cmdparser.h" // detection of flash capabilities +#include "cmdflashmemspiffs.h" // upload to flash mem int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { uint32_t uid = 0; @@ -168,9 +170,10 @@ int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keyc data[0] = keyType; data[1] = blockNo; data[2] = clear_trace; - data[3] = keycnt; - memcpy(data + 4, keyBlock, 6 * keycnt); - SendCommandNG(CMD_HF_MIFARE_CHKKEYS, data, (4 + 6 * keycnt)); + data[3] = 0; + data[4] = keycnt; + memcpy(data + 5, keyBlock, 6 * keycnt); + SendCommandNG(CMD_HF_MIFARE_CHKKEYS, data, (5 + 6 * keycnt)); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS, &resp, 2500)) return PM3_ETIMEOUT; @@ -265,6 +268,45 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, return PM3_ESOFT; } +// Trigger device to use a binary file on flash mem as keylist for mfCheckKeys. +// As of now, 255 keys possible in the file +// 6 * 255 = 1500 bytes +int mfCheckKeys_file(uint8_t *destfn, uint64_t *key) { + *key = -1; + clearCommandBuffer(); + + struct { + uint8_t filename[32]; + } PACKED payload_file; + + strncpy((char*)payload_file.filename, (char*)destfn, sizeof(payload_file.filename)); + + 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)) { + retry--; + if (retry ==0) { + PrintAndLogEx(WARNING, "Chk keys file, timeouted"); + return PM3_ETIMEOUT; + } + } + + if (resp.status != PM3_SUCCESS) return resp.status; + + struct kr { + uint8_t key[6]; + bool found; + } PACKED; + struct kr *keyresult = (struct kr *)&resp.data.asBytes; + if (!keyresult->found) return PM3_ESOFT; + *key = bytes_to_num(keyresult->key, sizeof(keyresult->key)); + return PM3_SUCCESS; +} + // PM3 imp of J-Run mf_key_brute (part 2) // ref: https://github.com/J-Run/mf_key_brute int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey) { @@ -461,7 +503,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, if (keycnt == 0) goto out; PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "candidate keys", keycnt); - + memset(resultKey, 0, 6); uint64_t key64 = -1; @@ -469,10 +511,10 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint32_t max_keys = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00}; - uint64_t start_time = msclock(); - for (uint32_t i = 0; i < keycnt; i += max_keys) { + uint64_t start_time = msclock(); + uint8_t size = keycnt - i > max_keys ? max_keys : keycnt - i; register uint8_t j; @@ -498,7 +540,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, start_time = msclock(); if ( i + 1 % 10 == 0) - PrintAndLogEx(INFO, " %8d keys left | %5.1f keys/sec | worst case %6.1f seconds remaining", keycnt - i, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); + PrintAndLogEx(INFO, " %8d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt , bruteforce_per_second, (keycnt-i) / bruteforce_per_second); } @@ -601,47 +643,79 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl uint64_t key64 = -1; // The list may still contain several key candidates. Test each of them with mfCheckKeys - uint32_t max_keys_slice = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; - uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00}; + uint32_t maxkeysinblock = IfPm3Flash() ? 1600 : KEYS_IN_BLOCK; + uint32_t max_keys_slice = keycnt > maxkeysinblock ? maxkeysinblock : keycnt; + + uint8_t *mem = calloc( (maxkeysinblock * 6) + 5, sizeof(uint8_t)); + if (mem == NULL) { + free(statelists[0].head.slhead); + return PM3_EMALLOC; + } + + uint8_t *p_keyblock = mem + 5; + mem[0] = statelists[0].keyType; + mem[1] = statelists[0].blockNo; + mem[2] = 1; + mem[3] = ((maxkeysinblock >> 8) & 0xFF); + mem[4] = (maxkeysinblock & 0xFF); + + uint8_t destfn[32]; + strncpy((char*)destfn, "static_nested_000.bin", sizeof(destfn) - 1); - uint64_t start_time = msclock(); for (uint32_t i = 0; i < keycnt; i += max_keys_slice) { -// PrintAndLogEx(INFO, "Testing %u / %u ", i, keycnt); + int res = 0; + uint64_t start_time = msclock(); key64 = 0; - - uint8_t size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i; + uint32_t size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i; // copy x keys to device. - register uint8_t j; - for (j = 0; j < size; j++) { + for (uint32_t j = 0; j < size; j++) { crypto1_get_lfsr(statelists[0].head.slhead + i + j, &key64); - num_to_bytes(key64, 6, keyBlock + j * 6); + num_to_bytes(key64, 6, p_keyblock + j * 6); } // check a block of generated candidate keys. - if (mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64) == PM3_SUCCESS) { + if (IfPm3Flash()) { + // upload to flash. + res = flashmem_spiffs_load(destfn, mem, 5 + (size * 6) ); + if (res != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "SPIFFS upload failed"); + return res; + } - free(statelists[0].head.slhead); + res = mfCheckKeys_file(destfn, &key64); + } else { + res = mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, mem, &key64); + } - num_to_bytes(key64, 6, resultKey); + if (res == PM3_SUCCESS) { + p_keyblock = NULL; + free(statelists[0].head.slhead); + free(mem); - PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + num_to_bytes(key64, 6, resultKey); + + PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", package->block, package->keytype ? 'B' : 'A', sprint_hex_inrow(resultKey, 6) ); return PM3_SUCCESS; + } else if (res == PM3_ETIMEOUT) { + return res; } - float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(msclock() - start_time) * 1000.0; + + float bruteforce_per_second = (float)maxkeysinblock / (float)(msclock() - start_time) * 1000.0; start_time = msclock(); - if ( i+1 % 10 == 0) - PrintAndLogEx(INFO, " %8d keys left | %5.1f keys/sec | worst case %6.1f seconds remaining", keycnt - i, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); - + PrintAndLogEx(INFO, "Chunk %8u/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); } + p_keyblock = NULL; + free(mem); + out: PrintAndLogEx(SUCCESS, "target block:%3u key type: %c", package->block, @@ -649,7 +723,6 @@ out: ); free(statelists[0].head.slhead); - return PM3_ESOFT; } diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index 846ee4222..6f179c573 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -65,6 +65,9 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key); 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); + +int mfCheckKeys_file(uint8_t *destfn, uint64_t *key); + int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey); int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data); diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 7ae6f0779..32b2ba35c 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -500,6 +500,7 @@ typedef struct { #define CMD_HF_MIFARE_CHKKEYS 0x0623 #define CMD_HF_MIFARE_SETMOD 0x0624 #define CMD_HF_MIFARE_CHKKEYS_FAST 0x0625 +#define CMD_HF_MIFARE_CHKKEYS_FILE 0x0626 #define CMD_HF_MIFARE_SNIFF 0x0630 #define CMD_HF_MIFARE_MFKEY 0x0631