From f4b3488a093551ef9a78ecbbe97ea79d294685b0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 13:11:20 +0100 Subject: [PATCH 1/4] 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 From fc2e11a6cdbc17dc733186ae1df291415f5c9384 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 13:12:09 +0100 Subject: [PATCH 2/4] rename function --- armsrc/hitag2.c | 32 +++++++++++++++++++++----------- armsrc/hitag2.h | 4 ++-- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 6efe5808d..3da970a24 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -35,6 +35,12 @@ #include "lfdemod.h" #include "commonutil.h" + +#define test_bit(data, i) (*(data + (i/8)) >> (7-(i % 8))) & 1 +#define set_bit(data, i) *(data + (i/8)) |= (1 << (7-(i % 8))) +#define clear_bit(data, i) *(data + (i/8)) &= ~(1 << (7-(i % 8))) +#define flip_bit(data, i) *(data + (i/8)) ^= (1 << (7-(i % 8))) + // Successful crypto auth static bool bCrypto; // Is in auth stage @@ -70,7 +76,6 @@ static enum { WRITE_STATE_PROG } writestate; - // ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces. // Historically it used to be FREE_BUFFER_SIZE, which was 2744. #define AUTH_TABLE_LENGTH 2744 @@ -87,6 +92,11 @@ uint8_t nonce[4]; bool key_no; static uint64_t cipher_state; +size_t blocknr; +size_t flipped_bit = 0; +uint32_t byte_value = 0; + + static int hitag2_reset(void) { tag.state = TAG_STATE_RESET; tag.crypto_active = 0; @@ -135,10 +145,12 @@ static int hitag2_init(void) { static void hitag_send_bit(int bit) { LED_A_ON(); + // Reset clock for the next bit AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; // Fixed modulation, earlier proxmark version used inverted signal + // check datasheet if reader uses BiPhase? if (bit == 0) { // Manchester: Unloaded, then loaded |__--| LOW(GPIO_SSC_DOUT); @@ -351,8 +363,6 @@ static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) return wait; } -size_t blocknr; - uint8_t hitag_crc(uint8_t *data, size_t length) { uint8_t crc = 0xff; unsigned int byte, bit; @@ -371,10 +381,7 @@ uint8_t hitag_crc(uint8_t *data, size_t length) { return crc; } -#define test_bit(data, i) (*(data+(i/8)) >> (7-(i%8))) & 1 -#define set_bit(data, i) *(data+(i/8)) |= (1 << (7-(i%8))) -#define clear_bit(data, i) *(data+(i/8)) &= ~(1 << (7-(i%8))) -#define flip_bit(data, i) *(data+(i/8)) ^= (1 << (7-(i%8))) +/* void fix_ac_decoding(uint8_t *input, size_t len) { // Reader routine tries to decode AC data after Manchester decoding // AC has double the bitrate, extract data from bit-pairs @@ -388,7 +395,12 @@ void fix_ac_decoding(uint8_t *input, size_t len) { } memcpy(input, temp, sizeof(temp)); } +*/ + +// looks at number of received bits. +// 0 = collision? +// 32 = good response bool hitag_plain(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool hitag_s) { uint8_t crc; *txlen = 0; @@ -457,9 +469,7 @@ bool hitag_plain(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bo return true; } -size_t flipped_bit = 0; -uint32_t byte_value = 0; bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { uint8_t crc; *txlen = 0; @@ -958,7 +968,7 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t } // Hitag2 Sniffing -void SniffHitag(void) { +void SniffHitag2(void) { LEDsoff(); StopTicks(); @@ -1037,7 +1047,7 @@ void SniffHitag(void) { } // Hitag2 simulation -void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { +void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { StopTicks(); diff --git a/armsrc/hitag2.h b/armsrc/hitag2.h index 9e0fb84e6..ec3d0d7f3 100644 --- a/armsrc/hitag2.h +++ b/armsrc/hitag2.h @@ -14,8 +14,8 @@ #include "common.h" #include "hitag.h" -void SniffHitag(void); -void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data); +void SniffHitag2(void); +void SimulateHitag2(bool tag_mem_supplied, uint8_t *data); void ReaderHitag(hitag_function htf, hitag_data *htd); void WriterHitag(hitag_function htf, hitag_data *htd, int page); From e0cd9c38da792a2c66dfc4e632e6fa7e54aa7051 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 13:13:04 +0100 Subject: [PATCH 3/4] test: hitag to use decimation on sample to save space --- armsrc/lfadc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index 3e15fdc0b..5c5b87fc0 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -188,6 +188,9 @@ void lf_init(bool reader) { if (logging) initSampleBuffer(&bufsize); + sample_config *sc = getSamplingConfig(); + sc->decimation = 2; + sc->averaging = 1; } void lf_finalize() { @@ -202,6 +205,10 @@ void lf_finalize() { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); + + sample_config *sc = getSamplingConfig(); + sc->decimation = 1; + sc->averaging = 0; } size_t lf_detect_field_drop(size_t max) { From 3fe4582e283bc8ccce70dbded28929cfa0cf6b3e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 13:13:45 +0100 Subject: [PATCH 4/4] chg: hitag dump should be in its own command --- client/cmdlfhitag.c | 58 ++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index f0a8037dc..810c0e7b3 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -563,25 +563,11 @@ static int CmdLFHitagReader(const char *Cmd) { } uint32_t id = bytes_to_num(resp.data.asBytes, 4); - + uint8_t *data = NULL; PrintAndLogEx(SUCCESS, " UID: " _YELLOW_("%08x"), id); if (htf != RHT2F_UID_ONLY) { - - PrintAndLogEx(SUCCESS, "Dumping tag memory..."); - uint8_t *data = resp.data.asBytes; - - char filename[FILE_PATH_SIZE]; - char *fnameptr = filename; - fnameptr += sprintf(fnameptr, "lf-hitag-"); - FillFileNameByUID(fnameptr, data, "-dump", 4); - - - - saveFile(filename, ".bin", data, 48); - saveFileEML(filename, data, 48, 4); - saveFileJSON(filename, jsfHitag, data, 48); - + // block3, 1 byte printHitagConfiguration(data[4 * 3]); } @@ -688,16 +674,29 @@ static int CmdLFHitagWriter(const char *Cmd) { return PM3_SUCCESS; } -/* -static int CmdLFHitagDump(const char *Cmd) { +static int CmdLFHitag2Dump(const char *Cmd) { PrintAndLogEx(INFO, "Dumping of tag memory"); - PrintAndLogEx(INFO, "To be done!"); char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hitag_dump(); + if (ctmp == 'h') return 0; // usage_hitag_dump(); + + PacketResponseNG resp; + + PrintAndLogEx(SUCCESS, "Dumping tag memory..."); + uint8_t *data = resp.data.asBytes; + + char filename[FILE_PATH_SIZE]; + char *fnameptr = filename; + fnameptr += sprintf(fnameptr, "lf-hitag-"); + FillFileNameByUID(fnameptr, data, "-dump", 4); + + saveFile(filename, ".bin", data, 48); + saveFileEML(filename, data, 48, 4); + saveFileJSON(filename, jsfHitag, data, 48); + return PM3_SUCCESS; } -*/ + // Annotate HITAG protocol void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { @@ -740,14 +739,15 @@ void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { } static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help" }, - {"list", CmdLFHitagList, IfPm3Hitag, "List Hitag trace history" }, - {"info", CmdLFHitagInfo, IfPm3Hitag, "Tag information" }, - {"reader", CmdLFHitagReader, IfPm3Hitag, "Act like a Hitag Reader" }, - {"sim", CmdLFHitagSim, IfPm3Hitag, "Simulate Hitag transponder" }, - {"sniff", CmdLFHitagSniff, IfPm3Hitag, "Eavesdrop Hitag communication" }, - {"writer", CmdLFHitagWriter, IfPm3Hitag, "Act like a Hitag Writer" }, - {"cc", CmdLFHitagCheckChallenges, IfPm3Hitag, "Test all challenges" }, + {"help", CmdHelp, AlwaysAvailable, "This help" }, + {"list", CmdLFHitagList, IfPm3Hitag, "List Hitag trace history" }, + {"info", CmdLFHitagInfo, IfPm3Hitag, "Tag information" }, + {"reader", CmdLFHitagReader, IfPm3Hitag, "Act like a Hitag Reader" }, + {"sim", CmdLFHitagSim, IfPm3Hitag, "Simulate Hitag transponder" }, + {"sniff", CmdLFHitagSniff, IfPm3Hitag, "Eavesdrop Hitag communication" }, + {"writer", CmdLFHitagWriter, IfPm3Hitag, "Act like a Hitag Writer" }, + {"dump", CmdLFHitag2Dump, IfPm3Hitag, "Dump Hitag2 tag" }, + {"cc", CmdLFHitagCheckChallenges, IfPm3Hitag, "Test all challenges" }, { NULL, NULL, 0, NULL } };