From 6b5d5951bb1d0acc0750aed5a8f991bf75628f84 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Feb 2024 23:19:43 +0100 Subject: [PATCH] unify text, improving mfu info output, and fixed some bugs with card uid not used in the fingerprinting --- client/atr_scrap_pcsctools.py | 2 +- client/luascripts/hf_14b_calypso.lua | 40 ++++++------ client/luascripts/hf_14b_mobib.lua | 31 +++++----- client/src/atrs.h | 2 +- client/src/cmdflashmem.c | 2 +- client/src/cmdhf14a.c | 6 +- client/src/cmdhf14b.c | 13 ++-- client/src/cmdhfmf.c | 2 +- client/src/cmdhfmfu.c | 91 ++++++++++++++++++---------- client/src/cmdlffdxb.c | 2 +- client/src/iso4217.h | 2 +- client/src/preferences.c | 8 +-- 12 files changed, 117 insertions(+), 84 deletions(-) diff --git a/client/atr_scrap_pcsctools.py b/client/atr_scrap_pcsctools.py index 1f0ab3948..10471e597 100755 --- a/client/atr_scrap_pcsctools.py +++ b/client/atr_scrap_pcsctools.py @@ -62,7 +62,7 @@ const static atr_t AtrTable[] = { { "3B90969181B1FE551FC7D4", "IClass SE Processor (Other) https://www.hidglobal.com/products/embedded-modules/iclass-se/sio-processor"}, """ -C_FOOTER=""" {NULL, "N/A"} +C_FOOTER=""" {NULL, "n/a"} }; #endif diff --git a/client/luascripts/hf_14b_calypso.lua b/client/luascripts/hf_14b_calypso.lua index e9cc8c8f5..849c73657 100644 --- a/client/luascripts/hf_14b_calypso.lua +++ b/client/luascripts/hf_14b_calypso.lua @@ -31,14 +31,24 @@ device-side. local PM3_SUCCESS = 0 --- iceman, todo: return payload from ISO14b APDU is a struct now. iso14b_raw_apdu_response_t +--[[-- iceman, todo: return payload from ISO14b APDU is a struct now. iso14b_raw_apdu_response_t +typedef struct { + uint8_t response_byte; + uint16_t datalen; + uint8_t data[]; +} PACKED iso14b_raw_apdu_response_t; +--]] + local function calypso_parse(result) - if result.Oldarg0 >= 0 then - local len = result.Oldarg0 * 2 - if len > 0 then - local d = string.sub(result.Data, 0, len); - return d, nil - end + if result.Length >= 0 then + local response_byte = string.sub(result.Data, 0, 1); + local datalen = string.sub(result.Data, 2, 5); + local d = string.sub(result.Data, 6, datalen * 2); + return { + response_byte = response_byte, + datalen = datalen, + data = d + }, nil end return nil, "calypso_parse failed" end @@ -129,12 +139,8 @@ local function calypso_send_cmd_raw(data, ignoreresponse ) local senddata = ('%s%s%s%s'):format(flags_str, time_str, rawlen_str,data) local c = Command:newNG{cmd = cmds.CMD_HF_ISO14443B_COMMAND, data = senddata} local result, err = c:sendNG(ignoreresponse, 2000) - if result then - if result.status == PM3_SUCCESS then - return calypso_parse(result) - else - err = 'card response failed' - end + if result and result.status == PM3_SUCCESS then + return calypso_parse(result) else err = 'No response from card' end @@ -251,13 +257,13 @@ function main(args) for i, apdu in spairs(_calypso_cmds) do print('>> '..ansicolors.yellow..i..ansicolors.reset) apdu = apdu:gsub('%s+', '') - data, err = calypso_send_cmd_raw(apdu, false) + obj, err = calypso_send_cmd_raw(apdu, false) if err then print('<< '..err) else - if data then - local status, desc, err = calypso_apdu_status(data) - local d = data:sub(3, (#data - 8)) + if obj.data then + local status, desc, err = calypso_apdu_status(obj.data) + local d = data:sub(3, (obj.datalen - 8)) if status then print('<< '..d..' ('..ansicolors.green..'ok'..ansicolors.reset..')') else diff --git a/client/luascripts/hf_14b_mobib.lua b/client/luascripts/hf_14b_mobib.lua index e267e7412..0b9bc72cc 100644 --- a/client/luascripts/hf_14b_mobib.lua +++ b/client/luascripts/hf_14b_mobib.lua @@ -32,12 +32,15 @@ device-side. -- iceman, todo: return payload from ISO14b APDU is a struct now. iso14b_raw_apdu_response_t local function mobib_parse(result) - if result.Oldarg0 >= 0 then - local len = result.Oldarg0 * 2 - if len > 0 then - d = string.sub(result.Data, 0, len); - return d, nil - end + if result.Length >= 0 then + local response_byte = string.sub(result.Data, 0, 1); + local datalen = string.sub(result.Data, 2, 5); + local d = string.sub(result.Data, 6, datalen * 2); + return { + response_byte = response_byte, + datalen = datalen, + data = d + }, nil end return nil, "mobib_parse failed" end @@ -126,12 +129,8 @@ local function mobib_send_cmd_raw(data, ignoreresponse ) local c = Command:newNG{cmd = cmds.CMD_HF_ISO14443B_COMMAND, data = senddata} local result, err = c:sendNG(ignoreresponse, 2000) - if result then - if result.status == PM3_SUCCESS then - return mobib_parse(result) - else - err = 'card response failed' - end + if result and result.status == PM3_SUCCESS then + return mobib_parse(result) else err = 'No response from card' end @@ -240,13 +239,13 @@ function main(args) for i, apdu in spairs(_calypso_cmds) do print('>> '..ansicolors.yellow..i..ansicolors.reset) apdu = apdu:gsub('%s+', '') - data, err = mobib_send_cmd_raw(apdu , false) + obj, err = mobib_send_cmd_raw(apdu , false) if err then print('<< '..err) else - if data then - local status, desc, err = mobib_apdu_status(data) - local d = data:sub(3, (#data - 8)) + if obj.data then + local status, desc, err = mobib_apdu_status(obj.data) + local d = data:sub(3, (obj.datalen - 8)) if status then print('<< '..d..' ('..ansicolors.green..'ok'..ansicolors.reset..')') else diff --git a/client/src/atrs.h b/client/src/atrs.h index 134e74d77..eb692f6dc 100644 --- a/client/src/atrs.h +++ b/client/src/atrs.h @@ -4236,7 +4236,7 @@ const static atr_t AtrTable[] = { { "3FFF9500FF918171FF4700444E4153505330312044736836303916", "PayTV card for DishNetwork Sat receiver\nhttp://www.dishnetwork.com/\nCards were obsoleted in nationwide system update in 2009." }, { "3FFF9500FF918171FF4700444E4153505330312052657636343702", "BELL EXPRESSVU (Pay TV)" }, { "3FFF9500FF918171FF470054494745523030332052657632353064", "Tivu' Sat (Italy) CAM card www.tivu.tv" }, - {NULL, "N/A"} + {NULL, "n/a"} }; #endif diff --git a/client/src/cmdflashmem.c b/client/src/cmdflashmem.c index 9d1f5605f..34cad50d1 100644 --- a/client/src/cmdflashmem.c +++ b/client/src/cmdflashmem.c @@ -594,7 +594,7 @@ static int CmdFlashMemInfo(const char *Cmd) { PrintAndLogEx( (is_keyok) ? SUCCESS : FAILED, "RDV4 RSA private key check... ( %s )", - (is_keyok) ? _GREEN_("ok") : _YELLOW_("N/A") + (is_keyok) ? _GREEN_("ok") : _YELLOW_("n/aA") ); } diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 68e7d89c8..ab5894d88 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -1383,9 +1383,9 @@ static int CmdHF14AAPDU(const char *Cmd) { } CLIParserFree(ctx); - PrintAndLogEx(SUCCESS, "( " _YELLOW_("%s%s%s")" )", - activateField ? "select" : "", - leaveSignalON ? ", keep" : "", + PrintAndLogEx(SUCCESS, _YELLOW_("%s%s%s"), + activateField ? "select card" : "", + leaveSignalON ? ", keep field on" : "", decodeTLV ? ", TLV" : "" ); PrintAndLogEx(SUCCESS, ">>> %s", sprint_hex_inrow(data, datalen)); diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 80d475a08..5b8b1c153 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -1181,6 +1181,9 @@ static int CmdHF14Binfo(const char *Cmd) { return infoHF14B(verbose, do_aid_search); } +// #define ISO14443B_READ_BLK 0x08 +// #define ISO14443B_WRITE_BLK 0x09 + static int read_sr_block(uint8_t blockno, uint8_t *out) { struct { uint8_t blockno; @@ -2317,12 +2320,12 @@ static int CmdHF14BAPDU(const char *Cmd) { int user_timeout = arg_get_int_def(ctx, 9, -1); CLIParserFree(ctx); - PrintAndLogEx(INFO, ">>>> %s%s%s >>>> " _YELLOW_("%s"), - activate_field ? "sel" : "", - leave_signal_on ? "| keep" : "", - decode_TLV ? "| TLV" : "", - sprint_hex(data, datalen) + PrintAndLogEx(SUCCESS, _YELLOW_("%s%s%s"), + activate_field ? "select card" : "", + leave_signal_on ? ", keep field on" : "", + decode_TLV ? ", TLV" : "" ); + PrintAndLogEx(SUCCESS, ">>> %s", sprint_hex_inrow(data, datalen)); if (decode_APDU) { APDU_t apdu; diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 82dc3a207..cd1a6b0ab 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -4053,7 +4053,7 @@ static int CmdHF14AMfSim(const char *Cmd) { PrintAndLogEx(INFO, _YELLOW_("MIFARE %s") " | %s UID " _YELLOW_("%s") "" , csize , uidsize - , (uidlen == 0) ? "N/A" : sprint_hex(uid, uidlen) + , (uidlen == 0) ? "n/a" : sprint_hex(uid, uidlen) ); PrintAndLogEx(INFO, "Options [ numreads: %d, flags: %d (0x%02x) ]" diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index df080e286..60043618f 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -372,7 +372,10 @@ static int try_default_3des_keys(uint8_t **correct_key) { } int res = PM3_ESOFT; - PrintAndLogEx(INFO, "Trying some default 3des keys"); + + PrintAndLogEx(INFO, ""); + PrintAndLogEx(SUCCESS, "--- " _CYAN_("Known UL-C 3DES keys")); + for (uint8_t i = 0; i < ARRAYLEN(default_3des_keys); ++i) { uint8_t *key = default_3des_keys[i]; if (ulc_authentication(key, true)) { @@ -471,7 +474,7 @@ static int ul_fudan_check(void) { return MFU_TT_UL_ERROR; } - uint8_t cmd[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa7}; //wrong crc on purpose should be 0xa8 + uint8_t cmd[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa7}; // wrong crc on purpose, should be 0xa8 clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 4, 0, cmd, sizeof(cmd)); PacketResponseNG resp; @@ -540,11 +543,10 @@ static int ul_print_default(uint8_t *data, uint8_t *real_uid) { sprint_bin(data + 10, 2) ); - PrintAndLogEx(SUCCESS, "OneTimePad: %s - %s", + PrintAndLogEx(SUCCESS, " OTP: " _YELLOW_("%s") " - %s", sprint_hex(data + 12, 4), sprint_bin(data + 12, 4) ); - return PM3_SUCCESS; } @@ -1411,14 +1413,13 @@ typedef struct { } mfu_otp_identify_t; static mfu_otp_identify_t mfu_otp_ident_table[] = { - { "SALTO tag", 12, 4, "534C544F", ul_c_otpgenA, NULL }, -// { "SAFLOK tag", 12, 4, NULL, ul_c_otpgenB, NULL }, -// { "VINGCARD tag", 12, 4, NULL, ul_c_otpgenC, NULL }, -// { "DORMA KABA tag", 12, 4, NULL, ul_c_otpgenD, NULL }, + { "SALTO Systems card", 12, 4, "534C544F", ul_c_otpgenA, NULL }, + { "Assa Abloy Ving Card", 12, 4, NULL, ul_ev1_otpgenA, NULL }, + { "MyKey", 12, 4, NULL, ul_mykey_otpgen, NULL }, { NULL, 0, 0, NULL, NULL, NULL } }; -static mfu_otp_identify_t *mfu_match_otp_fingerprint(uint8_t *data) { +static mfu_otp_identify_t *mfu_match_otp_fingerprint(uint8_t *uid, uint8_t *data) { uint8_t i = 0; do { int ml = 0; @@ -1428,11 +1429,17 @@ static mfu_otp_identify_t *mfu_match_otp_fingerprint(uint8_t *data) { if (mfu_otp_ident_table[i].match) { param_gethex_to_eol(mfu_otp_ident_table[i].match, 0, mtmp, sizeof(mtmp), &ml); } else { - uint32_t otp = mfu_otp_ident_table[i].otp(data); + uint32_t otp = mfu_otp_ident_table[i].otp(uid); num_to_bytes(otp, 4, mtmp); } - bool m2 = (memcmp(mtmp, data + mfu_otp_ident_table[i].mpos, mfu_otp_ident_table[i].mlen) == 0); + int min = MIN(mfu_otp_ident_table[i].mlen, 4); + + PrintAndLogEx(DEBUG, "uid.... %s", sprint_hex_inrow(uid, 7)); + PrintAndLogEx(DEBUG, "calc... %s", sprint_hex_inrow(mtmp, 4)); + PrintAndLogEx(DEBUG, "dump... %s", sprint_hex_inrow(data + mfu_otp_ident_table[i].mpos, min)); + + bool m2 = (memcmp(mtmp, data + mfu_otp_ident_table[i].mpos, min) == 0); if (m2) { PrintAndLogEx(DEBUG, "(fingerprint) found %s", mfu_otp_ident_table[i].desc); return &mfu_otp_ident_table[i]; @@ -1558,26 +1565,28 @@ static uint8_t mfu_max_len(void) { static int mfu_get_version_uid(uint8_t *version, uint8_t *uid) { iso14a_card_select_t card; - if (ul_select(&card) == false) + if (ul_select(&card) == false) { return PM3_ESOFT; + } + memcpy(uid, card.uid, card.uidlen); uint8_t v[10] = {0x00}; int len = ulev1_getVersion(v, sizeof(v)); DropField(); - if (len != sizeof(v)) + if (len != sizeof(v)) { return PM3_ESOFT; + } memcpy(version, v, 8); - memcpy(uid, card.uid, 7); return PM3_SUCCESS; } static int mfu_fingerprint(uint64_t tagtype, bool hasAuthKey, uint8_t *authkey, int ak_len) { uint8_t *data = NULL; - int res = PM3_SUCCESS; + int res = PM3_ESOFT; PrintAndLogEx(INFO, ""); - PrintAndLogEx(INFO, "------------------------ " _CYAN_("Fingerprint") " -----------------------"); + PrintAndLogEx(INFO, "--- " _CYAN_("Fingerprint")); uint8_t maxbytes = mfu_max_len(); if (maxbytes == 0) { PrintAndLogEx(ERR, "fingerprint table wrong"); @@ -1594,15 +1603,26 @@ static int mfu_fingerprint(uint64_t tagtype, bool hasAuthKey, uint8_t *authkey, } uint8_t pages = (maxbytes / MFU_BLOCK_SIZE); - PrintAndLogEx(INFO, "Reading tag memory..."); - uint8_t keytype = 0; + if (hasAuthKey) { if (tagtype & MFU_TT_UL_C) - keytype = 1; //UL_C auth + keytype = 1; // UL_C auth else - keytype = 2; //UL_EV1/NTAG auth + keytype = 2; // UL_EV1/NTAG auth } + + uint8_t dbg_curr = DBG_NONE; + if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) { + res = PM3_ESOFT; + goto out; + } + + if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) { + res = PM3_ESOFT; + goto out; + } + clearCommandBuffer(); SendCommandMIX(CMD_HF_MIFAREU_READCARD, 0, pages, keytype, authkey, ak_len); @@ -1633,13 +1653,13 @@ static int mfu_fingerprint(uint64_t tagtype, bool hasAuthKey, uint8_t *authkey, goto out; } - uint8_t version[8] = {0}; uint8_t uid[7] = {0}; if (mfu_get_version_uid(version, uid) == PM3_SUCCESS) { mfu_identify_t *item = mfu_match_fingerprint(version, data); if (item) { - PrintAndLogEx(SUCCESS, "Found " _GREEN_("%s"), item->desc); + PrintAndLogEx(SUCCESS, _GREEN_("%s"), item->desc); + res = PM3_SUCCESS; if (item->hint) { if (item->Pwd) { @@ -1654,9 +1674,10 @@ static int mfu_fingerprint(uint64_t tagtype, bool hasAuthKey, uint8_t *authkey, } // OTP checks - mfu_otp_identify_t *item = mfu_match_otp_fingerprint(data); + mfu_otp_identify_t *item = mfu_match_otp_fingerprint(uid, data); if (item) { - PrintAndLogEx(SUCCESS, "Found " _GREEN_("%s"), item->desc); + PrintAndLogEx(SUCCESS, _GREEN_("%s"), item->desc); + res = PM3_SUCCESS; if (item->hint) { if (item->otp) { @@ -1668,13 +1689,15 @@ static int mfu_fingerprint(uint64_t tagtype, bool hasAuthKey, uint8_t *authkey, } } } - // - - out: + + if (res != PM3_SUCCESS) { + PrintAndLogEx(INFO, "n/a"); + } + + setDeviceDebugLevel(dbg_curr, false); free(data); - PrintAndLogEx(INFO, "------------------------------------------------------------"); return res; } @@ -1969,6 +1992,8 @@ static int CmdHF14AMfUInfo(const char *Cmd) { uint8_t keySwap[16]; memcpy(keySwap, SwapEndian64(key, 16, 8), 16); ulc_print_3deskey(keySwap); + } else { + PrintAndLogEx(INFO, "n/a"); } PrintAndLogEx(INFO, "Done!"); return PM3_SUCCESS; @@ -2082,7 +2107,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { has_auth_key = true; ak_len = 4; memcpy(authenticationkey, key, 4); - PrintAndLogEx(SUCCESS, "Found password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]); goto out; } @@ -2097,7 +2122,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { has_auth_key = true; ak_len = 4; memcpy(authenticationkey, key, 4); - PrintAndLogEx(SUCCESS, "Found password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]); goto out; } @@ -2112,7 +2137,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { has_auth_key = true; ak_len = 4; memcpy(authenticationkey, key, 4); - PrintAndLogEx(SUCCESS, "Found password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]); goto out; } @@ -2127,7 +2152,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { has_auth_key = true; ak_len = 4; memcpy(authenticationkey, key, 4); - PrintAndLogEx(SUCCESS, "Found password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]); goto out; } @@ -2142,7 +2167,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { has_auth_key = true; ak_len = 4; memcpy(authenticationkey, key, 4); - PrintAndLogEx(SUCCESS, "Found password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]); break; } else { if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) { diff --git a/client/src/cmdlffdxb.c b/client/src/cmdlffdxb.c index 88f109fdd..25b8cdfcc 100644 --- a/client/src/cmdlffdxb.c +++ b/client/src/cmdlffdxb.c @@ -471,7 +471,7 @@ static const fdxbCountryMapping_t fdxbCountryMapping[] = { { 985, "HomeAgain (Destron Fearing/Digital Angel)" }, { 991, "Peeva" }, { 999, "Test range" }, - { 0, "N/A" } // must be the last entry + { 0, "n/a" } // must be the last entry }; static const char *mapFDBX(uint16_t countryCode) { diff --git a/client/src/iso4217.h b/client/src/iso4217.h index 594a0bb38..94c0c7db6 100644 --- a/client/src/iso4217.h +++ b/client/src/iso4217.h @@ -216,7 +216,7 @@ const static iso4217_t Iso4217Table[] = { {"997", "US Dollar (Next day)", 2}, {"998", "US Dollar (Same day)", 2}, {"999", "No currency is involved", -1}, - {"NULL", "N/A", -1} + {"NULL", "n/a", -1} }; #endif diff --git a/client/src/preferences.c b/client/src/preferences.c index af0100148..a3d05b774 100644 --- a/client/src/preferences.c +++ b/client/src/preferences.c @@ -833,11 +833,13 @@ int getDeviceDebugLevel(uint8_t *debug_level) { } int setDeviceDebugLevel(uint8_t debug_level, bool verbose) { - if (!g_session.pm3_present) + if (!g_session.pm3_present) { return PM3_EFAILED; + } - if (verbose) + if (verbose) { PrintAndLogEx(INFO, "setting device debug loglevel to %u", debug_level); + } uint8_t cdata[] = {debug_level, verbose}; clearCommandBuffer(); @@ -847,11 +849,9 @@ int setDeviceDebugLevel(uint8_t debug_level, bool verbose) { PrintAndLogEx(WARNING, "failed to set device debug loglevel"); return PM3_EFAILED; } - return PM3_SUCCESS; } - static int setCmdOutput(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "prefs set output",