From e7f7925dec5e24bce9a5f0e0f83421e0ba3ad7fb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 11 Jul 2022 06:44:07 +0200 Subject: [PATCH] adding asn1 tvl decoding of SIO in decrypt, view, eview commands. Available when giving the `-v` verbose flag --- client/src/cmdhficlass.c | 64 +++++++++++++++++++++++++++++++++++++++- client/src/util.c | 49 ++++++++++++++++++++++++++++++ client/src/util.h | 3 ++ 3 files changed, 115 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index bc553178b..ea16de75c 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -37,6 +37,8 @@ #include "cmdsmartcard.h" // smart select fct #include "proxendian.h" #include "iclass_cmd.h" +#include "crypto/asn1utils.h" // ASN1 decoder + #define PICOPASS_BLOCK_SIZE 8 #define NUM_CSNS 9 @@ -56,6 +58,7 @@ static uint8_t empty[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; static uint8_t zeros[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static int CmdHelp(const char *Cmd); +static void printIclassSIO(uint8_t *iclass_dump); static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = { { 0xAE, 0xA6, 0x84, 0xA6, 0xDA, 0xB2, 0x32, 0x78 }, @@ -1139,6 +1142,11 @@ static int CmdHFiClassEView(const char *Cmd) { PrintAndLogEx(NORMAL, ""); printIclassDumpContents(dump, 1, blocks, bytes); + + if (verbose) { + printIclassSIO(dump); + } + free(dump); return PM3_SUCCESS; } @@ -1328,6 +1336,10 @@ static int CmdHFiClassDecrypt(const char *Cmd) { printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen); + if (verbose) { + printIclassSIO(decrypted); + } + PrintAndLogEx(NORMAL, ""); // decode block 6 @@ -2440,6 +2452,48 @@ static void detect_credential(uint8_t *data, bool *legacy, bool *se, bool *sr) { r1 = NULL, r2 = NULL; } +// print ASN1 decoded array in TLV view +static void printIclassSIO(uint8_t *iclass_dump) { + + bool isLegacy, isSE, isSR; + detect_credential(iclass_dump, &isLegacy, &isSE, &isSR); + + uint8_t pattern[] = {0x05, 0x00, 0x05, 0x00}; + if (isSE) { + + int dlen = byte_strstr(iclass_dump + (6 * 8), 8*8, pattern, sizeof(pattern)); + if (dlen) { + + dlen += sizeof(pattern); + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "---------------------------- " _CYAN_("SIO - RAW") " ----------------------------"); + print_hex_noascii_break(iclass_dump + (6*8), dlen, 32); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "------------------------- " _CYAN_("SIO - ASN1 TLV") " --------------------------"); + asn1_print(iclass_dump + (6 * 8), dlen, " "); + PrintAndLogEx(NORMAL, ""); + } + } + + if (isSR) { + + int dlen = byte_strstr(iclass_dump + (10 * 8), 8*8, pattern, sizeof(pattern)); + + if (dlen) { + dlen += sizeof(pattern); + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "---------------------------- " _CYAN_("SIO - RAW") " ----------------------------"); + print_hex_noascii_break(iclass_dump + (10*8), dlen, 32); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "------------------------- " _CYAN_("SIO - ASN1 TLV") " --------------------------"); + asn1_print(iclass_dump + (10 * 8), dlen, " "); + PrintAndLogEx(NORMAL, ""); + } + } +} + void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize) { picopass_hdr_t *hdr = (picopass_hdr_t *)iclass_dump; @@ -2599,7 +2653,10 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e if (isLegacy) PrintAndLogEx(HINT, _YELLOW_("yellow") " = legacy credential"); - if (isSE || isSR) + if (isSE) + PrintAndLogEx(HINT, _CYAN_("cyan") " = SIO / SE credential"); + + if (isSR) PrintAndLogEx(HINT, _CYAN_("cyan") " = SIO / SR credential"); PrintAndLogEx(NORMAL, ""); @@ -2650,6 +2707,11 @@ static int CmdHFiClassView(const char *Cmd) { print_picopass_header((picopass_hdr_t *) dump); print_picopass_info((picopass_hdr_t *) dump); printIclassDumpContents(dump, startblock, endblock, bytes_read); + + if (verbose) { + printIclassSIO(dump); + } + free(dump); return PM3_SUCCESS; } diff --git a/client/src/util.c b/client/src/util.c index 421cc84a3..226a813df 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -276,6 +276,31 @@ void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) { } } +void print_hex_noascii_break(const uint8_t *data, const size_t len, uint8_t breaks) { + if (data == NULL || len == 0 || breaks == 0) return; + + int i; + for (i = 0; i < len; i += breaks) { + if (len - i < breaks) { // incomplete block, will be treated out of the loop + break; + } + PrintAndLogEx(INFO, "%s", sprint_hex_inrow_spaces(data + i, breaks, 0)); + } + + // the last odd bytes + uint8_t mod = len % breaks; + + if (mod) { + char buf[UTIL_BUFFER_SIZE_SPRINT + 3]; + hex_to_buffer((uint8_t *)buf, data + i, mod, (sizeof(buf) - 1), 0, 0, true); + + // add the spaces... + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%*s", ((breaks - mod) * 3), " "); + PrintAndLogEx(INFO, "%s", buf); + } +} + + static void print_buffer_ex(const uint8_t *data, const size_t len, int level, uint8_t breaks) { if (len < 1) @@ -1209,3 +1234,27 @@ inline uint64_t leadingzeros64(uint64_t a) { return 0; #endif } + + +int byte_strstr(uint8_t* src, size_t srclen, uint8_t* pattern, size_t plen) { + + size_t max = srclen - plen + 1; + + for (size_t i = 0; i < max; i++) { + + // compare only first byte + if (src[i] != pattern[0]) + continue; + + // try to match rest of the pattern + for (int j = plen - 1; j >= 1; j--) { + + if (src[i + j] != pattern[j]) + break; + + if (j == 1) + return i; + } + } + return -1; +} \ No newline at end of file diff --git a/client/src/util.h b/client/src/util.h index 2401a95aa..064c88803 100644 --- a/client/src/util.h +++ b/client/src/util.h @@ -67,6 +67,8 @@ void hex_to_buffer(uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, void print_hex(const uint8_t *data, const size_t len); void print_hex_break(const uint8_t *data, const size_t len, const uint8_t breaks); +void print_hex_noascii_break(const uint8_t *data, const size_t len, uint8_t breaks); + char *sprint_hex(const uint8_t *data, const size_t len); char *sprint_hex_inrow(const uint8_t *data, const size_t len); char *sprint_hex_inrow_ex(const uint8_t *data, const size_t len, const size_t min_str_len); @@ -143,4 +145,5 @@ uint64_t bitcount64(uint64_t a); uint32_t leadingzeros32(uint32_t a); uint64_t leadingzeros64(uint64_t a); +int byte_strstr(uint8_t* src, size_t srclen, uint8_t* pattern, size_t plen); #endif