mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 13:23:51 -07:00
mf sim: add option to pass explicitly atqa/sak and reject explicitly unknown vals for option t
This commit is contained in:
parent
4615354864
commit
12a0540d91
5 changed files with 54 additions and 9 deletions
|
@ -1192,9 +1192,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
uint8_t exitAfter;
|
uint8_t exitAfter;
|
||||||
uint8_t uid[10];
|
uint8_t uid[10];
|
||||||
|
uint16_t atqa;
|
||||||
|
uint8_t sak;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct p *payload = (struct p *) packet->data.asBytes;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
// emulator
|
// emulator
|
||||||
|
|
|
@ -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
|
// SPEC: https://www.nxp.com/docs/en/application-note/AN10833.pdf
|
||||||
// ATQA
|
// ATQA
|
||||||
|
@ -340,8 +340,16 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
|
||||||
Dbprintf("[-] ERROR: UID size not defined");
|
Dbprintf("[-] ERROR: UID size not defined");
|
||||||
return false;
|
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) {
|
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
|
// 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 ...
|
*@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)
|
* (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;
|
tag_response_info_t *responses;
|
||||||
uint8_t cardSTATE = MFEMUL_NOFIELD;
|
uint8_t cardSTATE = MFEMUL_NOFIELD;
|
||||||
uint8_t uid_len = 0; // 4,7, 10
|
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
|
// free eventually allocated BigBuf memory but keep Emulator Memory
|
||||||
BigBuf_free_keep_EM();
|
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();
|
BigBuf_free_keep_EM();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
|
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
|
||||||
#endif
|
#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_READ 0
|
||||||
#define AC_DATA_WRITE 1
|
#define AC_DATA_WRITE 1
|
||||||
|
|
|
@ -74,6 +74,8 @@ static int usage_hf14_mfsim(void) {
|
||||||
PrintAndLogEx(NORMAL, " 1 = MIFARE Classic 1k (Default)");
|
PrintAndLogEx(NORMAL, " 1 = MIFARE Classic 1k (Default)");
|
||||||
PrintAndLogEx(NORMAL, " 2 = MIFARE Classic 2k plus in SL0 mode");
|
PrintAndLogEx(NORMAL, " 2 = MIFARE Classic 2k plus in SL0 mode");
|
||||||
PrintAndLogEx(NORMAL, " 4 = MIFARE Classic 4k");
|
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 <numreads> blocks have been read by reader. 0 = infinite");
|
PrintAndLogEx(NORMAL, " n (Optional) Automatically exit simulation after <numreads> 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, " 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");
|
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) {
|
static int CmdHF14AMfSim(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
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;
|
uint8_t exitAfterNReads = 0;
|
||||||
uint16_t flags = 0;
|
uint16_t flags = 0;
|
||||||
int uidlen = 0;
|
int uidlen = 0;
|
||||||
|
@ -2195,6 +2201,10 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
||||||
flags |= FLAG_MF_MINI;
|
flags |= FLAG_MF_MINI;
|
||||||
sprintf(csize, "MINI");
|
sprintf(csize, "MINI");
|
||||||
break;
|
break;
|
||||||
|
case 1:
|
||||||
|
flags |= FLAG_MF_1K;
|
||||||
|
sprintf(csize, "1K");
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
flags |= FLAG_MF_2K;
|
flags |= FLAG_MF_2K;
|
||||||
sprintf(csize, "2K with RATS");
|
sprintf(csize, "2K with RATS");
|
||||||
|
@ -2203,14 +2213,33 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
||||||
flags |= FLAG_MF_4K;
|
flags |= FLAG_MF_4K;
|
||||||
sprintf(csize, "4K");
|
sprintf(csize, "4K");
|
||||||
break;
|
break;
|
||||||
case 1:
|
|
||||||
default:
|
default:
|
||||||
flags |= FLAG_MF_1K;
|
PrintAndLogEx(WARNING, "Unknown parameter for option t");
|
||||||
sprintf(csize, "1K");
|
errors = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
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':
|
case 'u':
|
||||||
param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen);
|
param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen);
|
||||||
uidlen >>= 1;
|
uidlen >>= 1;
|
||||||
|
@ -2269,11 +2298,15 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
uint8_t exitAfter;
|
uint8_t exitAfter;
|
||||||
uint8_t uid[10];
|
uint8_t uid[10];
|
||||||
|
uint16_t atqa;
|
||||||
|
uint8_t sak;
|
||||||
} PACKED payload;
|
} PACKED payload;
|
||||||
|
|
||||||
payload.flags = flags;
|
payload.flags = flags;
|
||||||
payload.exitAfter = exitAfterNReads;
|
payload.exitAfter = exitAfterNReads;
|
||||||
memcpy(payload.uid, uid, uidlen);
|
memcpy(payload.uid, uid, uidlen);
|
||||||
|
payload.atqa = (atqa[1] << 8) | atqa[0];
|
||||||
|
payload.sak = sak[0];
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_MIFARE_SIMULATE, (uint8_t *)&payload, sizeof(payload));
|
SendCommandNG(CMD_HF_MIFARE_SIMULATE, (uint8_t *)&payload, sizeof(payload));
|
||||||
|
|
|
@ -495,6 +495,8 @@ typedef struct {
|
||||||
#define FLAG_MF_1K 0x100
|
#define FLAG_MF_1K 0x100
|
||||||
#define FLAG_MF_2K 0x200
|
#define FLAG_MF_2K 0x200
|
||||||
#define FLAG_MF_4K 0x400
|
#define FLAG_MF_4K 0x400
|
||||||
|
#define FLAG_FORCED_ATQA 0x800
|
||||||
|
#define FLAG_FORCED_SAK 0x1000
|
||||||
|
|
||||||
//Iclass reader flags
|
//Iclass reader flags
|
||||||
#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
|
#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue