diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 16d56c7dd..e9507c06d 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -7448,16 +7448,39 @@ static int CmdHF14AGen4Info(const char *cmd) { arg_str0("p", "pwd", "", "password 4bytes"), arg_param_end }; - CLIExecWithReturn(ctx, cmd, argtable, false); - //bool verbose = arg_get_lit(ctx, 1); + CLIExecWithReturn(ctx, cmd, argtable, true); + bool verbose = arg_get_lit(ctx, 1); int pwd_len = 0; uint8_t pwd[4] = {0}; CLIGetHexWithReturn(ctx, 3, pwd, &pwd_len); CLIParserFree(ctx); + if (pwd_len != 0 && pwd_len != 4) { + PrintAndLogEx(FAILED, "Password must be 4 bytes length, got " _YELLOW_("%u"), pwd_len); + return PM3_EINVARG; + } + uint8_t resp[40] = {0}; + size_t resplen = 0; + int res = mfG4GetConfig(pwd, resp, &resplen, verbose); + if (res != PM3_SUCCESS || resplen == 0) { + PrintAndLogEx(ERR, "Error get config. Maybe not a Gen4 card?. error=%d rlen=%d", res, resplen); + return PM3_ESOFT; + } + PrintAndLogEx(INFO, "---------- Gen4 configuration ----------"); + PrintAndLogEx(INFO, "Raw config [%02d]: %s", resplen, sprint_hex_inrow(resp, resplen)); + if (resplen != 32 && resplen != 34) { + PrintAndLogEx(WARNING, "Unknown config format"); + return PM3_SUCCESS; + } + + res = mfG4GetFactoryTest(pwd, resp, &resplen, verbose); + if (res == PM3_SUCCESS && resplen > 2) { + PrintAndLogEx(INFO, "Raw test [%02d]: %s", resplen, sprint_hex_inrow(resp, resplen)); + return PM3_ESOFT; + } return PM3_SUCCESS; diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index 6666aca8a..f18b103cb 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -40,6 +40,7 @@ #include "crypto/libpcrypto.h" #include "util.h" // xor #include "mbedtls/sha1.h" // SHA1 +#include "cmdhf14a.h" #include "gen4.h" int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { @@ -1174,7 +1175,7 @@ int mfGen3Freeze(void) { } } -static int mfG4ExCommand(uint8_t cmd, uint8_t *pwd, uint8_t *data, size_t datalen, uint8_t *response, size_t *responselen) { +static int mfG4ExCommand(uint8_t cmd, uint8_t *pwd, uint8_t *data, size_t datalen, uint8_t *response, size_t *responselen, bool verbose) { struct p { uint8_t cmdheader; uint8_t pwd[4]; @@ -1196,31 +1197,65 @@ static int mfG4ExCommand(uint8_t cmd, uint8_t *pwd, uint8_t *data, size_t datale memcpy(payload.data, data, datalen); } + int resplen = 0; + clearCommandBuffer(); - SendCommandNG(CMD_HF_MIFARE_G4_RDBL, (uint8_t *)&payload, 1 + 4 + 1 + datalen); + SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_RAW | ISO14A_NO_RATS | ISO14A_APPEND_CRC, 6 + datalen, 0, (uint8_t *)&payload, 6 + datalen); + PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_RDBL, &resp, 1500)) { - if (resp.status != PM3_SUCCESS) { - return PM3_EUNDEF; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + if (resp.oldarg[0] != 2) { + if (verbose) PrintAndLogEx(ERR, "No card in the field."); + return PM3_ETIMEOUT; + } + + iso14a_card_select_t card; + memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); + if (verbose) { + PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]); + PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]); + } + } else { + if (verbose) PrintAndLogEx(ERR, "No card in the field."); + return PM3_ETIMEOUT; + } + + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + resplen = resp.oldarg[0]; + + if (!resplen) { + if (verbose) PrintAndLogEx(ERR, "No card response."); + return PM3_EFAILED; + } + + resplen = resplen - 2; // 14A CRC + if (resplen < 0) + resplen = 0; + + if (resplen > 40) { + if (verbose) PrintAndLogEx(ERR, "Buffer too small(%d).", resplen); + return PM3_EOVFLOW; } if (response != NULL) - memcpy(response, resp.data.asBytes, resp.length); + memcpy(response, resp.data.asBytes, resplen); if (responselen != NULL) - *responselen = resp.length; + *responselen = resplen; + + return PM3_SUCCESS; } else { - PrintAndLogEx(WARNING, "command execute timeout"); + if (verbose) PrintAndLogEx(ERR, "Reply timeout."); return PM3_ETIMEOUT; } - return PM3_SUCCESS; } -int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen) { +int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose) { uint8_t resp[40] = {0}; size_t resplen = 0; - int res = mfG4ExCommand(GEN4_CMD_DUMP_CONFIG, pwd, NULL, 0, resp, &resplen); + int res = mfG4ExCommand(GEN4_CMD_DUMP_CONFIG, pwd, NULL, 0, resp, &resplen, verbose); if (res != PM3_SUCCESS) { return PM3_EUNDEF; } @@ -1234,11 +1269,11 @@ int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen) { return PM3_SUCCESS; } -int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen) { +int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose) { uint8_t resp[40] = {0}; size_t resplen = 0; - int res = mfG4ExCommand(GEN4_CMD_FACTORY_TEST, pwd, NULL, 0, resp, &resplen); + int res = mfG4ExCommand(GEN4_CMD_FACTORY_TEST, pwd, NULL, 0, resp, &resplen, verbose); if (res != PM3_SUCCESS) { return PM3_EUNDEF; } diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index 036770ddf..dedf7f5ea 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -96,8 +96,8 @@ int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid); int mfGen3Block(uint8_t *block, int blockLen, uint8_t *newBlock); int mfGen3Freeze(void); -int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen); -int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen); +int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose); +int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose); int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags); int mfG4SetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags);