From c9a02adc70945d8879bdbfcdf800d66861360719 Mon Sep 17 00:00:00 2001 From: Matthias Konrath Date: Tue, 27 Aug 2019 19:45:37 +0200 Subject: [PATCH 1/6] Added the read B key with known A key feature, and minor changes to the UI (alignment). --- client/cmdhfmf.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 82aba722e..d122837e3 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1873,7 +1873,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { for (int j = 0; j < 2; j++) { if (e_sector[i].foundKey[j] == 1) { num_to_bytes(e_sector[i].Key[j], 6, tmp_key); - PrintAndLogEx(SUCCESS, "Found valid key: sector:%3d key type:%c key: " _YELLOW_("%s"), + PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"), i, j ? 'B' : 'A', sprint_hex(tmp_key, sizeof(tmp_key)) @@ -1983,6 +1983,43 @@ noValidKeyFound: // Clear the last found key num_to_bytes(0, 6, tmp_key); + if (current_key_type_i == 1) { + if (e_sector[current_sector_i].foundKey[0] && !e_sector[current_sector_i].foundKey[1]) { + PrintAndLogEx(INFO, "Reading B key: sector: %3d", current_sector_i); + uint8_t sectrail = (FirstBlockOfSector(current_sector_i) + NumBlocksPerSector(current_sector_i) - 1); + + mf_readblock_t payload; + payload.blockno = sectrail; + payload.keytype = 0; + + num_to_bytes(e_sector[current_sector_i].Key[0], 6, payload.key); // KEY A + + clearCommandBuffer(); + SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); + + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue; + + if (resp.status != PM3_SUCCESS) continue; + + uint8_t *data = resp.data.asBytes; + key64 = bytes_to_num(data + 10, 6); + if (verbose){ + num_to_bytes(key64, 6, tmp_key); + PrintAndLogEx(INFO, "Discovered key: sector: %3d key type: %c key: " _YELLOW_("%s"), + current_sector_i, + current_key_type_i ? 'B' : 'A', + sprint_hex(tmp_key, sizeof(tmp_key)) + ); + } + if (key64) { + e_sector[current_sector_i].foundKey[current_key_type_i] = 7; + e_sector[current_sector_i].Key[current_key_type_i] = key64; + num_to_bytes(key64, 6, tmp_key); + } + } + } + // Use the nested / hardnested attack if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) { if (prng_type && (! nested_failed)) { @@ -2082,6 +2119,7 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack PrintAndLogEx(INFO, " 4: Reused"); PrintAndLogEx(INFO, " 5: Nested"); PrintAndLogEx(INFO, " 6: Hardnested"); + PrintAndLogEx(INFO, " 7: Read B key with A key"); } PrintAndLogEx(INFO, "\nSaving keys"); From 42d58cbced52b093de0f6376e180204d3ddf0fb7 Mon Sep 17 00:00:00 2001 From: Matthias Konrath Date: Tue, 27 Aug 2019 19:55:45 +0200 Subject: [PATCH 2/6] fixed the read B key features error handling. --- client/cmdhfmf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index d122837e3..2f738af2c 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1998,9 +1998,9 @@ noValidKeyFound: SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue; + if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) goto skipReadBKey; - if (resp.status != PM3_SUCCESS) continue; + if (resp.status != PM3_SUCCESS) goto skipReadBKey; uint8_t *data = resp.data.asBytes; key64 = bytes_to_num(data + 10, 6); @@ -2021,6 +2021,7 @@ noValidKeyFound: } // Use the nested / hardnested attack +skipReadBKey: if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) { if (prng_type && (! nested_failed)) { uint8_t retries = 0; From a0c2de5602442110a73078a153280730fbc5c760 Mon Sep 17 00:00:00 2001 From: Matthias Konrath Date: Tue, 27 Aug 2019 20:28:28 +0200 Subject: [PATCH 3/6] Added an key found message to the read b key with a key feature. --- client/cmdhfmf.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 2f738af2c..99d6afd97 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2016,6 +2016,11 @@ noValidKeyFound: e_sector[current_sector_i].foundKey[current_key_type_i] = 7; e_sector[current_sector_i].Key[current_key_type_i] = key64; num_to_bytes(key64, 6, tmp_key); + PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"), + current_sector_i, + current_key_type_i ? 'B' : 'A', + sprint_hex(tmp_key, sizeof(tmp_key)) + ); } } } From a64aa99b74c78ee38aa1a7e2a8823dfc15de9fa5 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 27 Aug 2019 21:19:44 +0200 Subject: [PATCH 4/6] remove tabs --- armsrc/optimized_cipher.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/armsrc/optimized_cipher.c b/armsrc/optimized_cipher.c index a54aebc61..0f762a8d6 100644 --- a/armsrc/optimized_cipher.c +++ b/armsrc/optimized_cipher.c @@ -101,16 +101,16 @@ static const uint8_t opt_select_LUT[256] = { /********************** the table above has been generated with this code: ******** #include "util.h" static void init_opt_select_LUT(void) { - for (int r = 0; r < 256; r++) { - uint8_t r_ls2 = r << 2; - uint8_t r_and_ls2 = r & r_ls2; - uint8_t r_or_ls2 = r | r_ls2; - uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3); - uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r; - uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r; - opt_select_LUT[r] = (z0 & 4) | (z1 & 2) | (z2 & 1); - } - print_result("", opt_select_LUT, 256); + for (int r = 0; r < 256; r++) { + uint8_t r_ls2 = r << 2; + uint8_t r_and_ls2 = r & r_ls2; + uint8_t r_or_ls2 = r | r_ls2; + uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3); + uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r; + uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r; + opt_select_LUT[r] = (z0 & 4) | (z1 & 2) | (z2 & 1); + } + print_result("", opt_select_LUT, 256); } ***********************************************************************************/ From 4b8c80ec33dd48eba9e7cc8edad4f0b311332a79 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 27 Aug 2019 21:56:03 +0200 Subject: [PATCH 5/6] return values.. --- client/loclass/cipher.c | 7 +++---- client/loclass/cipher.h | 1 + client/loclass/cipherutils.c | 11 +++++++---- client/loclass/cipherutils.h | 1 + 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/client/loclass/cipher.c b/client/loclass/cipher.c index 931f0c845..13f686b51 100644 --- a/client/loclass/cipher.c +++ b/client/loclass/cipher.c @@ -226,8 +226,8 @@ void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) { reverse_arraybytes(dest, sizeof(dest)); memcpy(mac, dest, 4); //free(cc_nr); - return; } + void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4]) { uint8_t *address_data; uint8_t div_key[8]; @@ -245,7 +245,6 @@ void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_ke reverse_arraybytes(dest, sizeof(dest)); memcpy(mac, dest, 4); free(address_data); - return; } #ifndef ON_DEVICE @@ -267,8 +266,8 @@ int testMAC() { PrintAndLogEx(FAILED, "FAILED: MAC calculation failed:"); printarr(" Calculated_MAC", calculated_mac, 4); printarr(" Correct_MAC ", correct_MAC, 4); - return 1; + return PM3_ESOFT; } - return 0; + return PM3_SUCCESS; } #endif diff --git a/client/loclass/cipher.h b/client/loclass/cipher.h index b79dc47cd..7b1257aa5 100644 --- a/client/loclass/cipher.h +++ b/client/loclass/cipher.h @@ -39,6 +39,7 @@ #ifndef CIPHER_H #define CIPHER_H #include +#include "pm3_cmd.h" void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]); void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4]); diff --git a/client/loclass/cipherutils.c b/client/loclass/cipherutils.c index ee440fb73..b50268697 100644 --- a/client/loclass/cipherutils.c +++ b/client/loclass/cipherutils.c @@ -127,18 +127,21 @@ uint64_t x_bytes_to_num(uint8_t *src, size_t len) { } return num; } + uint8_t reversebytes(uint8_t b) { b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; b = (b & 0xCC) >> 2 | (b & 0x33) << 2; b = (b & 0xAA) >> 1 | (b & 0x55) << 1; return b; } + void reverse_arraybytes(uint8_t *arr, size_t len) { uint8_t i; for (i = 0; i < len ; i++) { arr[i] = reversebytes(arr[i]); } } + void reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len) { uint8_t i; for (i = 0; i < len ; i++) { @@ -202,9 +205,9 @@ static int testBitStream() { for (i = 0 ; i < ARRAYLEN(input) ; i++) { PrintAndLogEx(NORMAL, " IN %02x, OUT %02x", input[i], output[i]); } - return 1; + return PM3_ESOFT; } - return 0; + return PM3_SUCCESS; } static int testReversedBitstream() { @@ -232,9 +235,9 @@ static int testReversedBitstream() { for (i = 0 ; i < ARRAYLEN(input) ; i++) { PrintAndLogEx(NORMAL, " IN %02x, MIDDLE: %02x, OUT %02x", input[i], reverse[i], output[i]); } - return 1; + return PM3_ESOFT; } - return 0; + return PM3_SUCCESS; } diff --git a/client/loclass/cipherutils.h b/client/loclass/cipherutils.h index 70438d33b..6c90326a6 100644 --- a/client/loclass/cipherutils.h +++ b/client/loclass/cipherutils.h @@ -41,6 +41,7 @@ #include #include #include +#include "pm3_cmd.h" typedef struct { uint8_t *buffer; From 4fe7c7c9fa276120553679268db5489cb31ffb27 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 27 Aug 2019 23:17:02 +0200 Subject: [PATCH 6/6] remove utf8 dashes --- client/cmdhf14a.c | 2 +- client/emv/emv_tags.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 8aea8db6c..b21e8dbd7 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -133,7 +133,7 @@ static const manufactureName manufactureMapping[] = { { 0x61, "Wearlinks Technology Inc. China" }, { 0x62, "Userstar Information Systems Co., Ltd Taiwan" }, { 0x63, "Pragmatic Printing Ltd. UK" }, - { 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico – LSI-TEC Brazil" }, + { 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico - LSI-TEC Brazil" }, { 0x65, "Tendyron Corporation China" }, { 0x66, "MUTO Smart Co., Ltd. Korea" }, { 0x67, "ON Semiconductor USA" }, diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index 72c1fe78e..296dcdf82 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -401,11 +401,11 @@ static const struct emv_tag emv_tags[] = { { 0xdf811b, "Kernel Configuration", EMV_TAG_GENERIC, NULL }, { 0xdf811c, "Max Lifetime of Torn Transaction Log Record", EMV_TAG_GENERIC, NULL }, { 0xdf811d, "Max Number of Torn Transaction Log Records", EMV_TAG_GENERIC, NULL }, - { 0xdf811e, "Mag-stripe CVM Capability – CVM Required", EMV_TAG_GENERIC, NULL }, + { 0xdf811e, "Mag-stripe CVM Capability - CVM Required", EMV_TAG_GENERIC, NULL }, { 0xdf811f, "Security Capability", EMV_TAG_GENERIC, NULL }, - { 0xdf8120, "Terminal Action Code – Default", EMV_TAG_GENERIC, NULL }, - { 0xdf8121, "Terminal Action Code – Denial", EMV_TAG_GENERIC, NULL }, - { 0xdf8122, "Terminal Action Code – Online", EMV_TAG_GENERIC, NULL }, + { 0xdf8120, "Terminal Action Code - Default", EMV_TAG_GENERIC, NULL }, + { 0xdf8121, "Terminal Action Code - Denial", EMV_TAG_GENERIC, NULL }, + { 0xdf8122, "Terminal Action Code - Online", EMV_TAG_GENERIC, NULL }, { 0xdf8123, "Reader Contactless Floor Limit", EMV_TAG_GENERIC, NULL }, { 0xdf8124, "Reader Contactless Transaction Limit (No On-device CVM)", EMV_TAG_GENERIC, NULL }, { 0xdf8125, "Reader Contactless Transaction Limit (On-device CVM)", EMV_TAG_GENERIC, NULL }, @@ -415,7 +415,7 @@ static const struct emv_tag emv_tags[] = { { 0xdf8129, "Outcome Parameter Set", EMV_TAG_GENERIC, NULL }, { 0xdf812a, "DD Card (Track1)", EMV_TAG_GENERIC, NULL }, { 0xdf812b, "DD Card (Track2)", EMV_TAG_GENERIC, NULL }, - { 0xdf812c, "Mag-stripe CVM Capability – No CVM Required", EMV_TAG_GENERIC, NULL }, + { 0xdf812c, "Mag-stripe CVM Capability - No CVM Required", EMV_TAG_GENERIC, NULL }, { 0xdf812d, "Message Hold Time", EMV_TAG_GENERIC, NULL }, { 0xff8101, "Torn Record", EMV_TAG_GENERIC, NULL },