From 12a0540d91e621a4b0139e36eecf77ea826480f1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 7 Aug 2019 01:32:37 +0200 Subject: [PATCH] mf sim: add option to pass explicitly atqa/sak and reject explicitly unknown vals for option t --- armsrc/appmain.c | 4 +++- armsrc/mifaresim.c | 16 ++++++++++++---- armsrc/mifaresim.h | 2 +- client/cmdhfmf.c | 39 ++++++++++++++++++++++++++++++++++++--- include/pm3_cmd.h | 2 ++ 5 files changed, 54 insertions(+), 9 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 2529dc198..98605e481 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1192,9 +1192,11 @@ static void PacketReceived(PacketCommandNG *packet) { uint16_t flags; uint8_t exitAfter; uint8_t uid[10]; + uint16_t atqa; + uint8_t sak; } PACKED; struct p *payload = (struct p *) packet->data.asBytes; - Mifare1ksim(payload->flags, payload->exitAfter, payload->uid); + Mifare1ksim(payload->flags, payload->exitAfter, payload->uid, payload->atqa, payload->sak); break; } // emulator diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 8eb4ba973..5eadef0ea 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -163,7 +163,7 @@ static bool IsAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) { } } -static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) { +static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_t sak, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) { // SPEC: https://www.nxp.com/docs/en/application-note/AN10833.pdf // ATQA @@ -340,8 +340,16 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * Dbprintf("[-] ERROR: UID size not defined"); return false; } + if (flags & FLAG_FORCED_ATQA) { + rATQA[0] = atqa >> 8; + rATQA[1] = atqa & 0xff; + } + if (flags & FLAG_FORCED_SAK) { + rSAK[0] = sak; + } if (DBGLEVEL > DBG_NONE) { - Dbprintf("ATQA = %02X %02X and SAK = %02X)", rATQA[1], rATQA[0], rSAK[0]); + Dbprintf("ATQA : %02X %02X", rATQA[1], rATQA[0]); + Dbprintf("SAK : %02X", rSAK[0]); } // clone UIDs for byte-frame anti-collision multiple tag selection procedure @@ -435,7 +443,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * *@param exitAfterNReads, exit simulation after n blocks have been read, 0 is infinite ... * (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted) */ -void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) { +void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak) { tag_response_info_t *responses; uint8_t cardSTATE = MFEMUL_NOFIELD; uint8_t uid_len = 0; // 4,7, 10 @@ -503,7 +511,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) { // free eventually allocated BigBuf memory but keep Emulator Memory BigBuf_free_keep_EM(); - if (MifareSimInit(flags, datain, &responses, &cuid, &uid_len, &rats, &rats_len) == false) { + if (MifareSimInit(flags, datain, atqa, sak, &responses, &cuid, &uid_len, &rats, &rats_len) == false) { BigBuf_free_keep_EM(); return; } diff --git a/armsrc/mifaresim.h b/armsrc/mifaresim.h index d05b730c9..a161d2974 100644 --- a/armsrc/mifaresim.h +++ b/armsrc/mifaresim.h @@ -19,7 +19,7 @@ # define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len)) #endif -void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain); +void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak); #define AC_DATA_READ 0 #define AC_DATA_WRITE 1 diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 0fa28d5a9..16b6b9d49 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -74,6 +74,8 @@ static int usage_hf14_mfsim(void) { PrintAndLogEx(NORMAL, " 1 = MIFARE Classic 1k (Default)"); PrintAndLogEx(NORMAL, " 2 = MIFARE Classic 2k plus in SL0 mode"); PrintAndLogEx(NORMAL, " 4 = MIFARE Classic 4k"); + PrintAndLogEx(NORMAL, " a (Optional) Provide explicitly ATQA (2 bytes, override option t)"); + PrintAndLogEx(NORMAL, " s (Optional) Provide explicitly SAK (1 byte, override option t)"); PrintAndLogEx(NORMAL, " n (Optional) Automatically exit simulation after blocks have been read by reader. 0 = infinite"); PrintAndLogEx(NORMAL, " i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted"); PrintAndLogEx(NORMAL, " x (Optional) Crack, performs the 'reader attack', nr/ar attack against a reader"); @@ -2164,6 +2166,10 @@ void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose) { static int CmdHF14AMfSim(const char *Cmd) { uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint8_t atqa[2] = {0, 0}; + int atqalen = 0; + uint8_t sak[1] = {0}; + int saklen = 0; uint8_t exitAfterNReads = 0; uint16_t flags = 0; int uidlen = 0; @@ -2195,6 +2201,10 @@ static int CmdHF14AMfSim(const char *Cmd) { flags |= FLAG_MF_MINI; sprintf(csize, "MINI"); break; + case 1: + flags |= FLAG_MF_1K; + sprintf(csize, "1K"); + break; case 2: flags |= FLAG_MF_2K; sprintf(csize, "2K with RATS"); @@ -2203,14 +2213,33 @@ static int CmdHF14AMfSim(const char *Cmd) { flags |= FLAG_MF_4K; sprintf(csize, "4K"); break; - case 1: default: - flags |= FLAG_MF_1K; - sprintf(csize, "1K"); + PrintAndLogEx(WARNING, "Unknown parameter for option t"); + errors = true; break; } cmdp += 2; break; + case 'a': + param_gethex_ex(Cmd, cmdp + 1, atqa, &atqalen); + if (atqalen >> 1 != 2) { + PrintAndLogEx(WARNING, "Wrong ATQA length"); + errors = true; + break; + } + flags |= FLAG_FORCED_ATQA; + cmdp += 2; + break; + case 's': + param_gethex_ex(Cmd, cmdp + 1, sak, &saklen); + if (saklen >> 1 != 1) { + PrintAndLogEx(WARNING, "Wrong SAK length"); + errors = true; + break; + } + flags |= FLAG_FORCED_SAK; + cmdp += 2; + break; case 'u': param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen); uidlen >>= 1; @@ -2269,11 +2298,15 @@ static int CmdHF14AMfSim(const char *Cmd) { uint16_t flags; uint8_t exitAfter; uint8_t uid[10]; + uint16_t atqa; + uint8_t sak; } PACKED payload; payload.flags = flags; payload.exitAfter = exitAfterNReads; memcpy(payload.uid, uid, uidlen); + payload.atqa = (atqa[1] << 8) | atqa[0]; + payload.sak = sak[0]; clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_SIMULATE, (uint8_t *)&payload, sizeof(payload)); diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index b83cd6819..756e216e8 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -495,6 +495,8 @@ typedef struct { #define FLAG_MF_1K 0x100 #define FLAG_MF_2K 0x200 #define FLAG_MF_4K 0x400 +#define FLAG_FORCED_ATQA 0x800 +#define FLAG_FORCED_SAK 0x1000 //Iclass reader flags #define FLAG_ICLASS_READER_ONLY_ONCE 0x01