rework Mifare simulation flags

This commit is contained in:
Philippe Teuwen 2024-10-19 19:01:17 +02:00
commit 838e0adfa7
17 changed files with 185 additions and 215 deletions

View file

@ -248,7 +248,8 @@ void RunMod(void) {
state = STATE_SEARCH;
}
} else if (state == STATE_EMUL) {
uint16_t flags = FLAG_7B_UID_IN_DATA;
uint16_t flags = 0;
FLAG_SET_UID_IN_DATA(flags, 7);
Dbprintf("Starting simulation, press " _GREEN_("pm3 button") " to stop and go back to search state.");
SimulateIso14443aTag(7, flags, card.uid, 0, NULL);

View file

@ -297,7 +297,7 @@ static void prepare_emulation(uint8_t *tagType, uint16_t *flags, uint8_t *data,
}
memcpy(data, uidRx.dat, uidRx.len);
*flags = (uidRx.len == 10 ? FLAG_10B_UID_IN_DATA : (uidRx.len == 7 ? FLAG_7B_UID_IN_DATA : FLAG_4B_UID_IN_DATA));
FLAG_SET_UID_IN_DATA(*flags, uidRx.len);
DbpString(_CYAN_("[@]") " UID:");
Dbhexdump(uidRx.len, data, false);
Dbprintf(_CYAN_("[@]") " Flags: %hu", *flags);

View file

@ -717,33 +717,10 @@ readysim:
SpinOff(100);
LED_C_ON();
/*
uint16_t flags = 0;
switch (colin_p_card.uidlen) {
case 10:
flags = FLAG_10B_UID_IN_DATA;
break;
case 7:
flags = FLAG_7B_UID_IN_DATA;
break;
case 4:
flags = FLAG_4B_UID_IN_DATA;
break;
default:
flags = FLAG_UID_IN_EMUL;
break;
}
// Use UID, SAK, ATQA from EMUL, if uid not defined
if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
flags |= FLAG_UID_IN_EMUL;
}
flags |= FLAG_MF_1K;
if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
flags |= FLAG_UID_IN_EMUL;
}
flags = 0x10;
*/
uint16_t flags = FLAG_UID_IN_EMUL;
// FLAG_SET_UID_IN_DATA(flags, colin_p_card.uidlen);
FLAG_SET_UID_IN_EMUL(flags);
FLAG_SET_MF_SIZE(flags, MIFARE_1K_MAX_BYTES);
DbprintfEx(FLAG_NEWLINE, "\n\n\n\n\n\n\n\nn\n\nn\n\n\nflags: %d (0x%02x)", flags, flags);
cjSetCursLeft();
SpinOff(1000);

View file

@ -79,13 +79,8 @@ void RunMod(void) {
}
} else if (state == STATE_EMUL) {
uint16_t flags = 0;
if (card.uidlen == 4) {
flags |= FLAG_4B_UID_IN_DATA;
} else if (card.uidlen == 7) {
flags |= FLAG_7B_UID_IN_DATA;
} else if (card.uidlen == 10) {
flags |= FLAG_10B_UID_IN_DATA;
} else {
FLAG_SET_UID_IN_DATA(flags, card.uidlen);
if (IS_FLAG_UID_IN_EMUL(flags)) {
Dbprintf("Unusual UID length, something is wrong. Try again please.");
state = STATE_READ;
continue;

View file

@ -556,19 +556,7 @@ void RunMod(void) {
}
uint16_t simflags = 0;
switch (mattyrun_card.uidlen) {
case 4:
simflags |= FLAG_4B_UID_IN_DATA;
break;
case 7:
simflags |= FLAG_7B_UID_IN_DATA;
break;
case 10:
simflags |= FLAG_10B_UID_IN_DATA;
break;
default:
break;
}
FLAG_SET_UID_IN_DATA(simflags, mattyrun_card.uidlen);
uint16_t atqa = (uint16_t)bytes_to_num(mattyrun_card.atqa, 2);
SpinDelay(1000);

View file

@ -143,7 +143,9 @@ void RunMod(void) {
//Start to simulate
Dbprintf(_YELLOW_("[Slot: %d] Simulation start, Press button to change next card."), i);
uint16_t simflags = FLAG_UID_IN_EMUL | FLAG_MF_1K;
uint16_t simflags = 0;
FLAG_SET_MF_SIZE(simflags, MIFARE_1K_MAX_BYTES);
FLAG_SET_UID_IN_EMUL(simflags);
Mifare1ksim(simflags, 0, NULL, 0, 0);
Dbprintf(_YELLOW_("[Slot: %d] Simulation end, Write Back to dump file!"), i);

View file

@ -209,7 +209,8 @@ void RunMod(void) {
bool chktoken = false;
// UID 4 bytes(could be 7 bytes if needed it)
uint8_t flags = FLAG_4B_UID_IN_DATA;
uint8_t flags = 0;
FLAG_SET_UID_IN_DATA(flags, 4);
// in case there is a read command received we shouldn't break
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00};

View file

@ -81,7 +81,8 @@ void RunMod() {
// UID 4 bytes(could be 7 bytes if needed it)
uint8_t flags = FLAG_4B_UID_IN_DATA;
uint8_t flags = 0;
FLAG_SET_UID_IN_DATA(flags, 4);
// in case there is a read command received we shouldn't break
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00};

View file

@ -110,7 +110,8 @@ void RunMod(void) {
#define DYNAMIC_RESPONSE_BUFFER_SIZE 64
#define DYNAMIC_MODULATION_BUFFER_SIZE 512
uint8_t flags = FLAG_7B_UID_IN_DATA; // ST25TA have 7B UID
uint8_t flags = 0;
FLAG_SET_UID_IN_DATA(flags, 7); // ST25TA have 7B UID
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; // in case there is a read command received we shouldn't break
// to initialize the emulation

View file

@ -236,7 +236,8 @@ void RunMod(void) {
int button_pressed = BUTTON_HELD(1000);
if (button_pressed == BUTTON_NO_CLICK) { // No button action, proceed with sim
uint16_t flags = FLAG_4B_UID_IN_DATA;
uint16_t flags = 0
FLAG_SET_UID_IN_DATA(flags, 4);
uint8_t data[PM3_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break
memcpy(data, uids[selected].uid, uids[selected].uidlen);
@ -244,7 +245,7 @@ void RunMod(void) {
uint64_t tmpuid = bytes_to_num(uids[selected].uid, uids[selected].uidlen);
if (uids[selected].uidlen == 7) {
flags = FLAG_7B_UID_IN_DATA;
FLAG_SET_UID_IN_DATA(flags, 7);
Dbprintf("Simulating ISO14443a tag with uid: %014" PRIx64 " [Bank: %d]", tmpuid, selected);
} else {
Dbprintf("Simulating ISO14443a tag with uid: %08" PRIx64 " [Bank: %d]", tmpuid, selected);

View file

@ -1263,21 +1263,21 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, uint8
}
// if uid not supplied then get from emulator memory
if ((memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 10) == 0) || ((flags & FLAG_UID_IN_EMUL) == FLAG_UID_IN_EMUL)) {
if ((memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 10) == 0) || IS_FLAG_UID_IN_EMUL(flags)) {
if (tagType == 2 || tagType == 7) {
uint16_t start = MFU_DUMP_PREFIX_LENGTH;
uint8_t emdata[8];
emlGet(emdata, start, sizeof(emdata));
memcpy(data, emdata, 3); // uid bytes 0-2
memcpy(data + 3, emdata + 4, 4); // uid bytes 3-7
flags |= FLAG_7B_UID_IN_DATA;
FLAG_SET_UID_IN_DATA(flags, 7);
} else {
emlGet(data, 0, 4);
flags |= FLAG_4B_UID_IN_DATA;
FLAG_SET_UID_IN_DATA(flags, 4);
}
}
if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) {
if (IS_FLAG_UID_IN_DATA(flags, 4)) {
rUIDc1[0] = data[0];
rUIDc1[1] = data[1];
rUIDc1[2] = data[2];
@ -1296,7 +1296,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, uint8
AddCrc14A(rSAKc1, sizeof(rSAKc1) - 2);
*cuid = bytes_to_num(data, 4);
} else if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) {
} else if (IS_FLAG_UID_IN_DATA(flags, 7)) {
rUIDc1[0] = MIFARE_SELECT_CT; // Cascade Tag marker
rUIDc1[1] = data[0];
rUIDc1[2] = data[1];
@ -1319,7 +1319,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, uint8
*cuid = bytes_to_num(data + 3, 4);
} else if ((flags & FLAG_10B_UID_IN_DATA) == FLAG_10B_UID_IN_DATA) {
} else if (IS_FLAG_UID_IN_DATA(flags, 10)) {
rUIDc1[0] = MIFARE_SELECT_CT; // Cascade Tag marker
rUIDc1[1] = data[0];
@ -2560,7 +2560,7 @@ void iso14443a_antifuzz(uint32_t flags) {
resp[0] = 0x04;
resp[1] = 0x00;
if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) {
if (IS_FLAG_UID_IN_DATA(flags, 7)) {
resp[0] = 0x44;
}
@ -2578,7 +2578,7 @@ void iso14443a_antifuzz(uint32_t flags) {
resp[4] = resp[0] ^ resp[1] ^ resp[2] ^ resp[3];
colpos = 0;
if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) {
if (IS_FLAG_UID_IN_DATA(flags, 7)) {
resp[0] = MIFARE_SELECT_CT;
colpos = 8;
}

View file

@ -184,8 +184,9 @@ static bool IsAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
}
}
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) {
static bool MifareSimInit(uint16_t flags, uint8_t *uid, 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) {
uint8_t uid_tmp[10] = {0};
// SPEC: https://www.nxp.com/docs/en/application-note/AN10833.pdf
// ATQA
static uint8_t rATQA_Mini[] = {0x04, 0x00}; // indicate Mifare classic Mini 4Byte UID
@ -236,84 +237,79 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_
// Can be set from emulator memory or incoming data
// Length: 4,7,or 10 bytes
if (IS_FLAG_UID_IN_EMUL(flags)) {
if (uid == NULL) {
uid = uid_tmp;
}
// Get UID, SAK, ATQA from EMUL
if ((flags & FLAG_UID_IN_EMUL) == FLAG_UID_IN_EMUL) {
uint8_t block0[16];
emlGet(block0, 0, 16);
// If uid size defined, copy only uid from EMUL to use, backward compatibility for 'hf_colin.c', 'hf_mattyrun.c'
if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) != 0) {
memcpy(datain, block0, 10); // load 10bytes from EMUL to the datain pointer. to be used below.
} else {
// Check for 4 bytes uid: bcc corrected and single size uid bits in ATQA
if ((block0[0] ^ block0[1] ^ block0[2] ^ block0[3]) == block0[4] && (block0[6] & 0xc0) == 0) {
flags |= FLAG_4B_UID_IN_DATA;
memcpy(datain, block0, 4);
FLAG_SET_UID_IN_DATA(flags, 4);
memcpy(uid, block0, 4);
rSAK[0] = block0[5];
memcpy(rATQA, &block0[6], sizeof(rATQA));
}
// Check for 7 bytes UID: double size uid bits in ATQA
else if ((block0[8] & 0xc0) == 0x40) {
flags |= FLAG_7B_UID_IN_DATA;
memcpy(datain, block0, 7);
FLAG_SET_UID_IN_DATA(flags, 7);
memcpy(uid, block0, 7);
rSAK[0] = block0[7];
memcpy(rATQA, &block0[8], sizeof(rATQA));
} else {
Dbprintf("ERROR: " _RED_("Invalid dump. UID/SAK/ATQA not found"));
return false;
}
} else {
if (uid == NULL) {
Dbprintf("ERROR: " _RED_("Missing UID"));
return false;
}
}
// Tune tag type, if defined directly
// Otherwise use defined by default or extracted from EMUL
if ((flags & FLAG_MF_MINI) == FLAG_MF_MINI) {
if (IS_FLAG_MF_SIZE(flags, MIFARE_MINI_MAX_BYTES)) {
memcpy(rATQA, rATQA_Mini, sizeof(rATQA));
rSAK[0] = rSAK_Mini;
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare Mini ATQA/SAK");
} else if ((flags & FLAG_MF_1K) == FLAG_MF_1K) {
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_1K_MAX_BYTES)) {
memcpy(rATQA, rATQA_1k, sizeof(rATQA));
rSAK[0] = rSAK_1k;
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 1K ATQA/SAK");
} else if ((flags & FLAG_MF_2K) == FLAG_MF_2K) {
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_2K_MAX_BYTES)) {
memcpy(rATQA, rATQA_2k, sizeof(rATQA));
rSAK[0] = rSAK_2k;
*rats = rRATS;
*rats_len = sizeof(rRATS);
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 2K ATQA/SAK with RATS support");
} else if ((flags & FLAG_MF_4K) == FLAG_MF_4K) {
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_4K_MAX_BYTES)) {
memcpy(rATQA, rATQA_4k, sizeof(rATQA));
rSAK[0] = rSAK_4k;
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 4K ATQA/SAK");
}
// Prepare UID arrays
if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) { // get UID from datain
memcpy(rUIDBCC1, datain, 4);
if (IS_FLAG_UID_IN_DATA(flags, 4)) {
memcpy(rUIDBCC1, uid, 4);
*uid_len = 4;
if (g_dbglevel >= DBG_EXTENDED)
Dbprintf("MifareSimInit - FLAG_4B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_4B_UID_IN_DATA, flags, rUIDBCC1);
// save CUID
*cuid = bytes_to_num(rUIDBCC1, 4);
// BCC
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
if (g_dbglevel >= DBG_EXTENDED)
Dbprintf("MifareSimInit - Flags: %04X - BCC1: %02X", flags, rUIDBCC1[4]);
if (g_dbglevel > DBG_NONE) {
Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]);
}
// Correct uid size bits in ATQA
rATQA[0] = (rATQA[0] & 0x3f); // single size uid
} else if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) {
memcpy(&rUIDBCC1[1], datain, 3);
memcpy(rUIDBCC2, datain + 3, 4);
} else if (IS_FLAG_UID_IN_DATA(flags, 7)) {
memcpy(&rUIDBCC1[1], uid, 3);
memcpy(rUIDBCC2, uid + 3, 4);
*uid_len = 7;
if (g_dbglevel >= DBG_EXTENDED)
Dbprintf("MifareSimInit - FLAG_7B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_7B_UID_IN_DATA, flags, rUIDBCC1);
// save CUID
*cuid = bytes_to_num(rUIDBCC2, 4);
// CascadeTag, CT
@ -321,6 +317,8 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_
// BCC
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
if (g_dbglevel >= DBG_EXTENDED)
Dbprintf("MifareSimInit - Flags: %04X - BCC1: %02X - BCC2: %02X", flags, rUIDBCC1[4], rUIDBCC2[4]);
if (g_dbglevel > DBG_NONE) {
Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x",
rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3]);
@ -328,15 +326,11 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_
// Correct uid size bits in ATQA
rATQA[0] = (rATQA[0] & 0x3f) | 0x40; // double size uid
} else if ((flags & FLAG_10B_UID_IN_DATA) == FLAG_10B_UID_IN_DATA) {
memcpy(&rUIDBCC1[1], datain, 3);
memcpy(&rUIDBCC2[1], datain + 3, 3);
memcpy(rUIDBCC3, datain + 6, 4);
} else if (IS_FLAG_UID_IN_DATA(flags, 10)) {
memcpy(&rUIDBCC1[1], uid, 3);
memcpy(&rUIDBCC2[1], uid + 3, 3);
memcpy(rUIDBCC3, uid + 6, 4);
*uid_len = 10;
if (g_dbglevel >= DBG_EXTENDED)
Dbprintf("MifareSimInit - FLAG_10B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_10B_UID_IN_DATA, flags, rUIDBCC1);
// save CUID
*cuid = bytes_to_num(rUIDBCC3, 4);
// CascadeTag, CT
@ -346,7 +340,8 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3];
if (g_dbglevel >= DBG_EXTENDED)
Dbprintf("MifareSimInit - Flags: %04X - BCC1: %02X - BCC2: %02X - BCC3: %02X", flags, rUIDBCC1[4], rUIDBCC2[4], rUIDBCC3[4]);
if (g_dbglevel > DBG_NONE) {
Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3],
@ -361,11 +356,11 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_
Dbprintf("ERROR: " _RED_("UID size not defined"));
return false;
}
if (flags & FLAG_FORCED_ATQA) {
if (flags & FLAG_ATQA_IN_DATA) {
rATQA[0] = atqa >> 8;
rATQA[1] = atqa & 0xff;
}
if (flags & FLAG_FORCED_SAK) {
if (flags & FLAG_SAK_IN_DATA) {
rSAK[0] = sak;
}
if (g_dbglevel > DBG_NONE) {
@ -454,17 +449,11 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_
/**
*MIFARE 1K simulate.
*
*@param flags :
* FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK
* FLAG_4B_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that
* FLAG_7B_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that
* FLAG_10B_UID_IN_DATA - use 10-byte UID in the data-section not finished
* FLAG_NR_AR_ATTACK - means we should collect NR_AR responses for bruteforcing later
* FLAG_NESTED_AUTH_ATTACK - means that we support nested authentication attack
*@param flags: See pm3_cmd.h for the full definitions
*@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 attempted)
*/
void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak) {
void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t atqa, uint8_t sak) {
tag_response_info_t *responses;
uint8_t cardSTATE = MFEMUL_NOFIELD;
uint8_t uid_len = 0; // 4, 7, 10
@ -498,12 +487,6 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
uint8_t rats_len = 0;
// if fct is called with NULL we need to assign some memory since this pointer is passed around
uint8_t datain_tmp[10] = {0};
if (datain == NULL) {
datain = datain_tmp;
}
//Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2
// This will be used in the reader-only attack.
@ -522,7 +505,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
// free eventually allocated BigBuf memory but keep Emulator Memory
BigBuf_free_keep_EM();
if (MifareSimInit(flags, datain, atqa, sak, &responses, &cuid, &uid_len, &rats, &rats_len) == false) {
if (MifareSimInit(flags, uid, atqa, sak, &responses, &cuid, &uid_len, &rats, &rats_len) == false) {
BigBuf_free_keep_EM();
return;
}

View file

@ -41,6 +41,6 @@
#define AUTHKEYB 1
#define AUTHKEYNONE 0xff
void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak);
void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t atqa, uint8_t sak);
#endif

View file

@ -830,17 +830,8 @@ int CmdHF14ASim(const char *Cmd) {
bool useUIDfromEML = true;
if (uid_len > 0) {
switch (uid_len) {
case 10:
flags |= FLAG_10B_UID_IN_DATA;
break;
case 7:
flags |= FLAG_7B_UID_IN_DATA;
break;
case 4:
flags |= FLAG_4B_UID_IN_DATA;
break;
default:
FLAG_SET_UID_IN_DATA(flags, uid_len);
if (IS_FLAG_UID_IN_EMUL(flags)) {
PrintAndLogEx(ERR, "Please specify a 4, 7, or 10 byte UID");
CLIParserFree(ctx);
return PM3_EINVARG;
@ -866,7 +857,7 @@ int CmdHF14ASim(const char *Cmd) {
}
if (useUIDfromEML) {
flags |= FLAG_UID_IN_EMUL;
FLAG_SET_UID_IN_EMUL(flags);
}
struct {
@ -1660,12 +1651,14 @@ static int CmdHF14AAntiFuzz(const char *Cmd) {
struct {
uint8_t flag;
} PACKED param;
param.flag = FLAG_4B_UID_IN_DATA;
if (arg_get_lit(ctx, 2))
param.flag = FLAG_7B_UID_IN_DATA;
if (arg_get_lit(ctx, 3))
param.flag = FLAG_10B_UID_IN_DATA;
param.flag = 0;
FLAG_SET_UID_IN_DATA(param.flag, 4);
if (arg_get_lit(ctx, 2)) {
FLAG_SET_UID_IN_DATA(param.flag, 7);
}
if (arg_get_lit(ctx, 3)) {
FLAG_SET_UID_IN_DATA(param.flag, 10);
}
CLIParserFree(ctx);
clearCommandBuffer();
@ -3725,17 +3718,8 @@ int CmdHF14AAIDSim(const char *Cmd) {
bool useUIDfromEML = true;
if (uid_len > 0) {
switch (uid_len) {
case 10:
flags |= FLAG_10B_UID_IN_DATA;
break;
case 7:
flags |= FLAG_7B_UID_IN_DATA;
break;
case 4:
flags |= FLAG_4B_UID_IN_DATA;
break;
default:
FLAG_SET_UID_IN_DATA(flags, uid_len);
if (IS_FLAG_UID_IN_EMUL(flags)) {
PrintAndLogEx(ERR, "Please specify a 4, 7, or 10 byte UID");
CLIParserFree(ctx);
return PM3_EINVARG;
@ -3757,7 +3741,7 @@ int CmdHF14AAIDSim(const char *Cmd) {
}
if (useUIDfromEML) {
flags |= FLAG_UID_IN_EMUL;
FLAG_SET_UID_IN_EMUL(flags);
}
struct {

View file

@ -565,7 +565,8 @@ static int CmdHF14AJookiSim(const char *Cmd) {
// NTAG, 7 byte UID in eloaded data.
payload.tagtype = 7;
payload.flags = FLAG_UID_IN_EMUL;
payload.flags = 0;
FLAG_SET_UID_IN_EMUL(payload.flags);
payload.exitAfter = 0;
memcpy(payload.uid, uid, sizeof(uid));

View file

@ -4129,25 +4129,15 @@ static int CmdHF14AMfSim(const char *Cmd) {
uint8_t uid[10] = {0};
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
char uidsize[8] = {0};
char uidsize[9] = {0};
if (uidlen > 0) {
switch (uidlen) {
case 10:
flags |= FLAG_10B_UID_IN_DATA;
snprintf(uidsize, sizeof(uidsize), "10 byte");
break;
case 7:
flags |= FLAG_7B_UID_IN_DATA;
snprintf(uidsize, sizeof(uidsize), "7 byte");
break;
case 4:
flags |= FLAG_4B_UID_IN_DATA;
snprintf(uidsize, sizeof(uidsize), "4 byte");
break;
default:
FLAG_SET_UID_IN_DATA(flags, uidlen);
if (IS_FLAG_UID_IN_EMUL(flags)) {
PrintAndLogEx(WARNING, "Invalid parameter for UID");
CLIParserFree(ctx);
return PM3_EINVARG;
} else {
snprintf(uidsize, sizeof(uidsize), "%i bytes", uidlen);
}
}
@ -4193,7 +4183,7 @@ static int CmdHF14AMfSim(const char *Cmd) {
PrintAndLogEx(WARNING, "Wrong ATQA length");
return PM3_EINVARG;
}
flags |= FLAG_FORCED_ATQA;
flags |= FLAG_ATQA_IN_DATA;
}
if (saklen > 0) {
@ -4201,12 +4191,7 @@ static int CmdHF14AMfSim(const char *Cmd) {
PrintAndLogEx(WARNING, "Wrong SAK length");
return PM3_EINVARG;
}
flags |= FLAG_FORCED_SAK;
}
// Use UID, SAK, ATQA from EMUL, if uid not defined
if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
flags |= FLAG_UID_IN_EMUL;
flags |= FLAG_SAK_IN_DATA;
}
size_t k_sectors_cnt = MIFARE_4K_MAXSECTOR;
@ -4218,19 +4203,19 @@ static int CmdHF14AMfSim(const char *Cmd) {
}
if (m0) {
flags |= FLAG_MF_MINI;
FLAG_SET_MF_SIZE(flags, MIFARE_MINI_MAX_BYTES);
snprintf(csize, sizeof(csize), "MINI");
k_sectors_cnt = MIFARE_MINI_MAXSECTOR;
} else if (m1) {
flags |= FLAG_MF_1K;
FLAG_SET_MF_SIZE(flags, MIFARE_1K_MAX_BYTES);
snprintf(csize, sizeof(csize), "1K");
k_sectors_cnt = MIFARE_1K_MAXSECTOR;
} else if (m2) {
flags |= FLAG_MF_2K;
FLAG_SET_MF_SIZE(flags, MIFARE_2K_MAX_BYTES);
snprintf(csize, sizeof(csize), "2K with RATS");
k_sectors_cnt = MIFARE_2K_MAXSECTOR;
} else if (m4) {
flags |= FLAG_MF_4K;
FLAG_SET_MF_SIZE(flags, MIFARE_4K_MAX_BYTES);
snprintf(csize, sizeof(csize), "4K");
k_sectors_cnt = MIFARE_4K_MAXSECTOR;
} else {
@ -4262,9 +4247,8 @@ static int CmdHF14AMfSim(const char *Cmd) {
, (uidlen == 0) ? "n/a" : sprint_hex(uid, uidlen)
);
PrintAndLogEx(INFO, "Options [ numreads: %d, flags: %d (0x%02x) ]"
PrintAndLogEx(INFO, "Options [ numreads: %d, flags: 0x%04x ]"
, exitAfterNReads
, flags
, flags);
struct {

View file

@ -766,21 +766,72 @@ typedef struct {
#define CMD_UNKNOWN 0xFFFF
//Mifare simulation flags
#define FLAG_INTERACTIVE 0x01
#define FLAG_4B_UID_IN_DATA 0x02
#define FLAG_7B_UID_IN_DATA 0x04
#define FLAG_10B_UID_IN_DATA 0x08
#define FLAG_UID_IN_EMUL 0x10
#define FLAG_NR_AR_ATTACK 0x20
#define FLAG_MF_MINI 0x80
#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
#define FLAG_CVE21_0430 0x2000
#define FLAG_RATS_IN_DATA 0x4000
#define FLAG_NESTED_AUTH_ATTACK 0x8000
// In interactive mode, we are expected to finish the operation with an ACK
#define FLAG_INTERACTIVE 0x0001
#define FLAG_ATQA_IN_DATA 0x0002
#define FLAG_SAK_IN_DATA 0x0004
#define FLAG_RATS_IN_DATA 0x0008
// internal constants, use the function macros instead
#define FLAG_MASK_UID 0x0030
#define FLAG_UID_IN_EMUL 0x0000
#define FLAG_4B_UID_IN_DATA 0x0010
#define FLAG_7B_UID_IN_DATA 0x0020
#define FLAG_10B_UID_IN_DATA 0x0030
// if there is a UID in the data-section to be used:
// note: if UIDLEN is wrong, we default to FLAG_UID_IN_EMUL
#define FLAG_SET_UID_IN_DATA(flags, len) {\
flags = (flags & (~FLAG_MASK_UID))|\
(len == 4 ? FLAG_4B_UID_IN_DATA : \
(len == 7 ? FLAG_7B_UID_IN_DATA : \
(len == 10 ? FLAG_10B_UID_IN_DATA : \
FLAG_UID_IN_EMUL)));\
}
// else we tell to take UID from block 0:
#define FLAG_SET_UID_IN_EMUL(flags) {flags = (flags & (~FLAG_MASK_UID))|FLAG_UID_IN_EMUL;}
#define IS_FLAG_UID_IN_DATA(flags, len) (\
(flags & FLAG_MASK_UID) == \
(len == 4 ? FLAG_4B_UID_IN_DATA : \
(len == 7 ? FLAG_7B_UID_IN_DATA : \
(len == 10 ? FLAG_10B_UID_IN_DATA : \
FLAG_UID_IN_EMUL)))\
)
#define IS_FLAG_UID_IN_EMUL(flags) ((flags & FLAG_MASK_UID) == FLAG_UID_IN_EMUL)
// internal constants, use the function macros instead
#define MIFARE_4K_MAX_BYTES 4096
#define MIFARE_2K_MAX_BYTES 2048
#define MIFARE_1K_MAX_BYTES 1024
#define MIFARE_MINI_MAX_BYTES 320
#define FLAG_MASK_MF_SIZE 0x00C0
#define FLAG_MF_MINI 0x0000
#define FLAG_MF_1K 0x0040
#define FLAG_MF_2K 0x0080
#define FLAG_MF_4K 0x00C0
#define FLAG_SET_MF_SIZE(flags, size) {\
flags = (flags & (~FLAG_MASK_MF_SIZE))|\
(size == MIFARE_MINI_MAX_BYTES ? FLAG_MF_MINI : \
(size == MIFARE_1K_MAX_BYTES ? FLAG_MF_1K : \
(size == MIFARE_2K_MAX_BYTES ? FLAG_MF_2K : \
(size == MIFARE_4K_MAX_BYTES ? FLAG_MF_4K : \
0))));\
}
// else we tell to take UID from block 0:
#define IS_FLAG_MF_SIZE(flags, size) (\
(flags & FLAG_MASK_MF_SIZE) == \
(size == MIFARE_MINI_MAX_BYTES ? FLAG_MF_MINI : \
(size == MIFARE_1K_MAX_BYTES ? FLAG_MF_1K : \
(size == MIFARE_2K_MAX_BYTES ? FLAG_MF_2K : \
(size == MIFARE_4K_MAX_BYTES ? FLAG_MF_4K : \
0))))\
)
#define FLAG_MF_USE_READ_KEYB 0x0100
#define FLAG_CVE21_0430 0x0200
// collect NR_AR responses for bruteforcing later
#define FLAG_NR_AR_ATTACK 0x0400
// support nested authentication attack
#define FLAG_NESTED_AUTH_ATTACK 0x0800
#define MODE_SIM_CSN 0