add static encrypted nonce detection

This commit is contained in:
merlokk 2023-12-11 21:24:26 +02:00
commit 91892bc1bf
9 changed files with 125 additions and 10 deletions

View file

@ -1866,6 +1866,17 @@ static void PacketReceived(PacketCommandNG *packet) {
MifareHasStaticNonce(); MifareHasStaticNonce();
break; break;
} }
case CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE: {
struct p {
uint8_t block_no;
uint8_t key_type;
uint8_t key[6];
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
MifareHasStaticEncryptedNonce(payload->block_no, payload->key_type, payload->key);
break;
}
#endif #endif
#ifdef WITH_NFCBARCODE #ifdef WITH_NFCBARCODE

View file

@ -90,7 +90,7 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c
goto OUT; goto OUT;
} }
if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL)) { if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL, NULL)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
retval = PM3_ESOFT; retval = PM3_ESOFT;
goto OUT; goto OUT;
@ -158,7 +158,7 @@ int16_t mifare_cmd_writeblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t write
goto OUT; goto OUT;
}; };
if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL)) { if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL, NULL)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
retval = PM3_ESOFT; retval = PM3_ESOFT;
goto OUT; goto OUT;
@ -2681,6 +2681,73 @@ OUT:
// 2B F9 1C 1B D5 08 48 48 03 A4 B1 B1 75 FF 2D 90 // 2B F9 1C 1B D5 08 48 48 03 A4 B1 B1 75 FF 2D 90
// ^^ ^^ // ^^ ^^
void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *key) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
clear_trace();
set_tracing(true);
int retval = PM3_SUCCESS;
uint8_t *uid = BigBuf_malloc(10);
memset(uid, 0x00, 10);
uint8_t data[1] = { NONCE_FAIL };
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
uint64_t ui64key = bytes_to_num(key, 6);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
iso14a_card_select_t card_info;
uint32_t cuid = 0;
if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
retval = PM3_ESOFT;
goto OUT;
}
uint8_t key_auth_cmd = MIFARE_AUTH_KEYA + (key_type & 1);
if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL, NULL)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
retval = PM3_ESOFT;
goto OUT;
};
uint32_t nt = 0;
uint8_t enc_counter = 0;
uint32_t ntenc = 0;
uint32_t oldntenc = 0;
for (uint8_t i = 0; i < 3; i++) {
if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_NESTED, &nt, &ntenc, NULL)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
retval = PM3_ESOFT;
goto OUT;
};
if (g_dbglevel >= DBG_INFO)
Dbprintf("nt: %x, nt encoded: %x", nt, ntenc);
if (oldntenc == 0)
oldntenc = ntenc;
else if (ntenc == oldntenc)
enc_counter++;
}
if (enc_counter) {
data[0] = NONCE_STATIC_ENC;
} else {
data[0] = NONCE_NORMAL;
}
OUT:
crypto1_deinit(pcs);
reply_ng(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, retval, data, sizeof(data));
// turns off
OnSuccessMagic();
BigBuf_free();
}
void OnSuccessMagic(void) { void OnSuccessMagic(void) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();

View file

@ -49,6 +49,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work wi
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain);
void MifareCIdent(bool is_mfc); // is "magic chinese" card? void MifareCIdent(bool is_mfc); // is "magic chinese" card?
void MifareHasStaticNonce(void); // Has the tag a static nonce? void MifareHasStaticNonce(void); // Has the tag a static nonce?
void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *key); // Has the tag a static encrypted nonce?
// MFC GEN3 // MFC GEN3
int DoGen3Cmd(uint8_t *cmd, uint8_t cmd_len); int DoGen3Cmd(uint8_t *cmd, uint8_t cmd_len);

View file

@ -142,9 +142,9 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo,
return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL);
} }
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) {
return mifare_classic_authex_cmd(pcs, uid, blockNo, (keyType & 1) ? MIFARE_AUTH_KEYB : MIFARE_AUTH_KEYA, ui64Key, isNested, ntptr, timing); return mifare_classic_authex_cmd(pcs, uid, blockNo, (keyType & 1) ? MIFARE_AUTH_KEYB : MIFARE_AUTH_KEYA, ui64Key, isNested, ntptr, NULL, timing);
} }
int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *ntencptr, uint32_t *timing) {
// "random" reader nonce: // "random" reader nonce:
uint8_t nr[4]; uint8_t nr[4];
@ -159,6 +159,8 @@ int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
// Save the tag nonce (nt) // Save the tag nonce (nt)
uint32_t nt = bytes_to_num(receivedAnswer, 4); uint32_t nt = bytes_to_num(receivedAnswer, 4);
if (ntencptr)
*ntencptr = nt;
// ----------------------------- crypto1 create // ----------------------------- crypto1 create
if (isNested) if (isNested)

View file

@ -72,7 +72,7 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
// mifare classic // mifare classic
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing); int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing);
int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing); int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *ntencptr, uint32_t *timing);
int mifare_classic_readblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData); int mifare_classic_readblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData);
int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte); int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte);

View file

@ -8875,7 +8875,7 @@ static int CmdHF14AMfInfo(const char *Cmd) {
PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]); PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]); PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) if (setDeviceDebugLevel(verbose ? DBG_INFO : DBG_NONE, false) != PM3_SUCCESS)
return PM3_EFAILED; return PM3_EFAILED;
PrintAndLogEx(INFO, "--- " _CYAN_("Backdoors Information") "---------------------"); PrintAndLogEx(INFO, "--- " _CYAN_("Backdoors Information") "---------------------");
@ -8951,7 +8951,11 @@ static int CmdHF14AMfInfo(const char *Cmd) {
// detect static encrypted nonce // detect static encrypted nonce
if (keyType != 0xff) { if (keyType != 0xff) {
res = detect_classic_static_encrypted_nonce(0, keyType, key); // TODO: add block number to the config
if (res == NONCE_STATIC)
PrintAndLogEx(SUCCESS, "Static nested nonce: " _YELLOW_("yes"));
if (res == NONCE_STATIC_ENC)
PrintAndLogEx(SUCCESS, "Static encrypted nonce: " _YELLOW_("yes"));
} }
if (do_nack_test) if (do_nack_test)

View file

@ -1349,6 +1349,33 @@ int detect_classic_static_nonce(void) {
return NONCE_FAIL; return NONCE_FAIL;
} }
/* Detect Mifare Classic static encrypted nonce
detects special magic cards that has a static / fixed nonce
returns:
0 = nonce ok
1 = has static/fixed nonce
2 = cmd failed
3 = has encrypted nonce
*/
int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, uint8_t *key) {
clearCommandBuffer();
uint8_t cdata[1 + 1 + MIFARE_KEY_SIZE] = {0};
cdata[0] = block_no;
cdata[1] = key_type;
memcpy(&cdata[2], key, MIFARE_KEY_SIZE);
SendCommandNG(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, cdata, sizeof(cdata));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, &resp, 1000)) {
if (resp.status == PM3_ESOFT)
return NONCE_FAIL;
return resp.data.asBytes[0];
}
return NONCE_FAIL;
}
/* try to see if card responses to "Chinese magic backdoor" commands. */ /* try to see if card responses to "Chinese magic backdoor" commands. */
int detect_mf_magic(bool is_mfc) { int detect_mf_magic(bool is_mfc) {

View file

@ -102,6 +102,7 @@ int detect_classic_prng(void);
int detect_classic_nackbug(bool verbose); int detect_classic_nackbug(bool verbose);
int detect_mf_magic(bool is_mfc); int detect_mf_magic(bool is_mfc);
int detect_classic_static_nonce(void); int detect_classic_static_nonce(void);
int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, uint8_t *key);
bool detect_mfc_ev1_signature(void); bool detect_mfc_ev1_signature(void);
int read_mfc_ev1_signature(uint8_t *signature); int read_mfc_ev1_signature(uint8_t *signature);

View file

@ -675,6 +675,7 @@ typedef struct {
#define CMD_HF_MIFARE_NACK_DETECT 0x0730 #define CMD_HF_MIFARE_NACK_DETECT 0x0730
#define CMD_HF_MIFARE_STATIC_NONCE 0x0731 #define CMD_HF_MIFARE_STATIC_NONCE 0x0731
#define CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE 0x0732
// MFU OTP TearOff // MFU OTP TearOff
#define CMD_HF_MFU_OTP_TEAROFF 0x0740 #define CMD_HF_MFU_OTP_TEAROFF 0x0740
@ -743,6 +744,7 @@ typedef struct {
#define NONCE_FAIL 0x01 #define NONCE_FAIL 0x01
#define NONCE_NORMAL 0x02 #define NONCE_NORMAL 0x02
#define NONCE_STATIC 0x03 #define NONCE_STATIC 0x03
#define NONCE_STATIC_ENC 0x04
// Dbprintf flags // Dbprintf flags
#define FLAG_RAWPRINT 0x00 #define FLAG_RAWPRINT 0x00