unify text, improving mfu info output, and fixed some bugs with card uid not used in the fingerprinting

This commit is contained in:
iceman1001 2024-02-04 23:19:43 +01:00
parent c3f2162aff
commit 6b5d5951bb
12 changed files with 117 additions and 84 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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")
);
}

View file

@ -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));

View file

@ -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;

View file

@ -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) ]"

View file

@ -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) {

View file

@ -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) {

View file

@ -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

View file

@ -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",