add gdm flag to hf mf c* commands

this enables the use of hf mf c* commands with gdm/uscuid cards when the alt wake up mode 20(7)/23 is enabled rather than gen1 wake up
This commit is contained in:
nvx 2024-11-02 22:22:13 +10:00
commit 6d7fcc642a
6 changed files with 78 additions and 19 deletions

View file

@ -55,7 +55,7 @@ void RunMod(void) {
card_clone_t uids[OPTS];
iso14a_card_select_t card[OPTS];
uint8_t params = (MAGIC_SINGLE | MAGIC_DATAIN);
uint8_t params = (MAGIC_SINGLE | MAGIC_WUPC | MAGIC_DATAIN);
LED(selected + 1, 0);
@ -184,7 +184,7 @@ void RunMod(void) {
// Mifare UID BCC
block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // BCC on byte 5
Bytes 5-7 are reserved SAK and ATQA for mifare classic
-Use mfCSetBlock(0, block0, oldUID, wantWipe, MAGIC_SINGLE) to write it
-Use mfCSetBlock(0, block0, oldUID, wantWipe, MAGIC_SINGLE | MAGIC_WUPC) to write it
*/
uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0};
// arg0 = Flags, arg1=blockNo

View file

@ -2552,6 +2552,7 @@ out:
// bit 4 - need turn off FPGA
// bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a)
// bit 6 - wipe tag.
// bit 7 - use USCUID/GDM (20/23) magic wakeup
//-----------------------------------------------------------------------------
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
@ -2620,6 +2621,22 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
mifare_classic_halt(NULL);
}
if (workFlags & MAGIC_GDM_ALT_WUPC) {
ReaderTransmitBitsPar(wupGDM1, 7, NULL, NULL);
if ((ReaderReceive(receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar) == 0) || (receivedAnswer[0] != 0x0a)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("wupGDM1 error");
errormsg = MAGIC_WUPC;
break;
}
ReaderTransmit(wupGDM2, sizeof(wupC2), NULL);
if ((ReaderReceive(receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar) == 0) || (receivedAnswer[0] != 0x0a)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("wupGDM2 error");
errormsg = MAGIC_WUPC;
break;
}
}
// write block
if (workFlags & MAGIC_WUPC) {
ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
@ -2706,6 +2723,22 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
//loop doesn't loop just breaks out if error or done
while (true) {
if (workFlags & MAGIC_GDM_ALT_WUPC) {
ReaderTransmitBitsPar(wupGDM1, 7, NULL, NULL);
if ((ReaderReceive(receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar) == 0) || (receivedAnswer[0] != 0x0a)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("wupGDM1 error");
errormsg = MAGIC_WUPC;
break;
}
ReaderTransmit(wupGDM2, sizeof(wupC2), NULL);
if ((ReaderReceive(receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar) == 0) || (receivedAnswer[0] != 0x0a)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("wupGDM2 error");
errormsg = MAGIC_WUPC;
break;
}
}
if (workFlags & MAGIC_WUPC) {
ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
if ((ReaderReceive(receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar) == 0) || (receivedAnswer[0] != 0x0a)) {

View file

@ -5166,6 +5166,7 @@ static int CmdHF14AMfCSetUID(const char *Cmd) {
arg_str0("u", "uid", "<hex>", "UID, 4/7 hex bytes"),
arg_str0("a", "atqa", "<hex>", "ATQA, 2 hex bytes"),
arg_str0("s", "sak", "<hex>", "SAK, 1 hex byte"),
arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -5183,6 +5184,7 @@ static int CmdHF14AMfCSetUID(const char *Cmd) {
int slen = 0;
uint8_t sak[1] = {0x00};
CLIGetHexWithReturn(ctx, 4, sak, &slen);
uint8_t gdm = arg_get_lit(ctx, 5);
CLIParserFree(ctx);
// sanity checks
@ -5209,7 +5211,8 @@ static int CmdHF14AMfCSetUID(const char *Cmd) {
(slen) ? sak : NULL,
old_uid,
verify_uid,
wipe_card
wipe_card,
gdm
);
if (res) {
@ -5240,6 +5243,7 @@ static int CmdHF14AMfCWipe(const char *cmd) {
arg_str0("u", "uid", "<hex>", "UID, 4 hex bytes"),
arg_str0("a", "atqa", "<hex>", "ATQA, 2 hex bytes"),
arg_str0("s", "sak", "<hex>", "SAK, 1 hex byte"),
arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
arg_param_end
};
CLIExecWithReturn(ctx, cmd, argtable, true);
@ -5255,6 +5259,7 @@ static int CmdHF14AMfCWipe(const char *cmd) {
int slen = 0;
uint8_t sak[1] = {0x00};
CLIGetHexWithReturn(ctx, 3, sak, &slen);
uint8_t gdm = arg_get_lit(ctx, 4);
CLIParserFree(ctx);
if (uidlen && uidlen != 4) {
@ -5270,7 +5275,7 @@ static int CmdHF14AMfCWipe(const char *cmd) {
return PM3_EINVARG;
}
int res = mfCWipe((uidlen) ? uid : NULL, (alen) ? atqa : NULL, (slen) ? sak : NULL);
int res = mfCWipe((uidlen) ? uid : NULL, (alen) ? atqa : NULL, (slen) ? sak : NULL, gdm);
if (res) {
PrintAndLogEx(ERR, "Can't wipe card. error %d", res);
return PM3_ESOFT;
@ -5292,6 +5297,7 @@ static int CmdHF14AMfCSetBlk(const char *Cmd) {
arg_int1("b", "blk", "<dec>", "block number"),
arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
arg_lit0("w", "wipe", "wipes card with backdoor cmd before writing"),
arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -5303,6 +5309,7 @@ static int CmdHF14AMfCSetBlk(const char *Cmd) {
CLIGetHexWithReturn(ctx, 2, data, &datalen);
uint8_t wipe_card = arg_get_lit(ctx, 3);
uint8_t gdm = arg_get_lit(ctx, 4);
CLIParserFree(ctx);
if (b < 0 || b >= MIFARE_1K_MAXBLOCK) {
@ -5316,6 +5323,12 @@ static int CmdHF14AMfCSetBlk(const char *Cmd) {
}
uint8_t params = MAGIC_SINGLE;
if (gdm) {
params |= MAGIC_GDM_ALT_WUPC;
} else {
params |= MAGIC_WUPC;
}
if (wipe_card) {
params |= MAGIC_WIPE;
}
@ -5347,6 +5360,7 @@ static int CmdHF14AMfCLoad(const char *Cmd) {
arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
arg_lit0(NULL, "emu", "from emulator memory"),
arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -5360,6 +5374,7 @@ static int CmdHF14AMfCLoad(const char *Cmd) {
bool m2 = arg_get_lit(ctx, 4);
bool m4 = arg_get_lit(ctx, 5);
bool fill_from_emulator = arg_get_lit(ctx, 6);
bool gdm = arg_get_lit(ctx, 7);
CLIParserFree(ctx);
@ -5393,7 +5408,7 @@ static int CmdHF14AMfCLoad(const char *Cmd) {
if (fill_from_emulator) {
PrintAndLogEx(INFO, "Start upload to emulator memory");
PrintAndLogEx(INFO, "Start upload from emulator memory");
PrintAndLogEx(INFO, "." NOLF);
for (int b = 0; b < block_cnt; b++) {
@ -5408,7 +5423,7 @@ static int CmdHF14AMfCLoad(const char *Cmd) {
// switch on field and send magic sequence
if (b == 0) {
flags = MAGIC_INIT + MAGIC_WUPC;
flags = MAGIC_INIT | (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC);
}
// just write
@ -5456,7 +5471,7 @@ static int CmdHF14AMfCLoad(const char *Cmd) {
// switch on field and send magic sequence
if (blockno == 0) {
flags = MAGIC_INIT + MAGIC_WUPC;
flags = MAGIC_INIT | (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC);
}
// write
@ -5511,11 +5526,13 @@ static int CmdHF14AMfCGetBlk(const char *Cmd) {
arg_param_begin,
arg_int1("b", "blk", "<dec>", "block number"),
arg_lit0("v", "verbose", "verbose output"),
arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int b = arg_get_int_def(ctx, 1, 0);
bool verbose = arg_get_lit(ctx, 2);
bool gdm = arg_get_lit(ctx, 3);
CLIParserFree(ctx);
if (b > 255) {
@ -5524,7 +5541,7 @@ static int CmdHF14AMfCGetBlk(const char *Cmd) {
uint8_t blockno = (uint8_t)b;
uint8_t data[16] = {0};
int res = mfCGetBlock(blockno, data, MAGIC_SINGLE);
int res = mfCGetBlock(blockno, data, MAGIC_SINGLE | (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC));
if (res) {
PrintAndLogEx(ERR, "Can't read block. error=%d", res);
return PM3_ESOFT;
@ -5553,11 +5570,13 @@ static int CmdHF14AMfCGetSc(const char *Cmd) {
arg_param_begin,
arg_int1("s", "sec", "<dec>", "sector number"),
arg_lit0("v", "verbose", "verbose output"),
arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int s = arg_get_int_def(ctx, 1, 0);
bool verbose = arg_get_lit(ctx, 2);
bool gdm = arg_get_lit(ctx, 3);
CLIParserFree(ctx);
if (s >= MIFARE_4K_MAXSECTOR) {
@ -5575,7 +5594,7 @@ static int CmdHF14AMfCGetSc(const char *Cmd) {
start = 128 + (sector - 32) * 16;
}
int flags = MAGIC_INIT + MAGIC_WUPC;
int flags = MAGIC_INIT + (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC);
uint8_t data[16] = {0};
for (int i = 0; i < blocks; i++) {
if (i == 1) flags = 0;
@ -5612,6 +5631,7 @@ static int CmdHF14AMfCSave(const char *Cmd) {
arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
arg_lit0(NULL, "emu", "to emulator memory"),
arg_lit0(NULL, "gdm", "to emulator memory"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -5625,6 +5645,7 @@ static int CmdHF14AMfCSave(const char *Cmd) {
bool m2 = arg_get_lit(ctx, 4);
bool m4 = arg_get_lit(ctx, 5);
bool fill_emulator = arg_get_lit(ctx, 6);
bool gdm = arg_get_lit(ctx, 7);
CLIParserFree(ctx);
// validations
@ -5692,7 +5713,7 @@ static int CmdHF14AMfCSave(const char *Cmd) {
}
// switch on field and send magic sequence
uint8_t flags = MAGIC_INIT + MAGIC_WUPC;
uint8_t flags = MAGIC_INIT + (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC);
for (uint16_t i = 0; i < block_cnt; i++) {
// read
@ -5766,6 +5787,7 @@ static int CmdHF14AMfCView(const char *Cmd) {
arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
arg_lit0("v", "verbose", "verbose output"),
arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -5774,6 +5796,7 @@ static int CmdHF14AMfCView(const char *Cmd) {
bool m2 = arg_get_lit(ctx, 3);
bool m4 = arg_get_lit(ctx, 4);
bool verbose = arg_get_lit(ctx, 5);
bool gdm = arg_get_lit(ctx, 6);
CLIParserFree(ctx);
// validations
@ -5840,7 +5863,7 @@ static int CmdHF14AMfCView(const char *Cmd) {
}
// switch on field and send magic sequence
uint8_t flags = MAGIC_INIT + MAGIC_WUPC;
uint8_t flags = MAGIC_INIT + (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC);
for (uint16_t i = 0; i < block_cnt; i++) {
// read
if (i == 1) {

View file

@ -1058,9 +1058,9 @@ int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidt
}
// "MAGIC" CARD
int mfCSetUID(uint8_t *uid, uint8_t uidlen, const uint8_t *atqa, const uint8_t *sak, uint8_t *old_uid, uint8_t *verifed_uid, uint8_t wipecard) {
int mfCSetUID(uint8_t *uid, uint8_t uidlen, const uint8_t *atqa, const uint8_t *sak, uint8_t *old_uid, uint8_t *verifed_uid, uint8_t wipecard, uint8_t gdm) {
uint8_t params = MAGIC_SINGLE;
uint8_t params = MAGIC_SINGLE | (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC);
uint8_t block0[MFBLOCK_SIZE];
memset(block0, 0x00, sizeof(block0));
@ -1111,7 +1111,7 @@ int mfCSetUID(uint8_t *uid, uint8_t uidlen, const uint8_t *atqa, const uint8_t *
res = mfCSetBlock(0, block0, NULL, params);
if (res == PM3_SUCCESS) {
params = MAGIC_SINGLE;
params = MAGIC_SINGLE | MAGIC_WUPC;
memset(block0, 0, sizeof(block0));
res = mfCGetBlock(0, block0, params);
if (res == 0) {
@ -1123,13 +1123,13 @@ int mfCSetUID(uint8_t *uid, uint8_t uidlen, const uint8_t *atqa, const uint8_t *
return res;
}
int mfCWipe(uint8_t *uid, const uint8_t *atqa, const uint8_t *sak) {
int mfCWipe(uint8_t *uid, const uint8_t *atqa, const uint8_t *sak, uint8_t gdm) {
uint8_t block0[MFBLOCK_SIZE] = {0x00, 0x56, 0x78, 0xBB, 0x95, 0x08, 0x04, 0x00, 0x02, 0xB2, 0x1E, 0x24, 0x23, 0x27, 0x1E, 0x1D};
// uint8_t block0[MFBLOCK_SIZE] = {0x04, 0x03, 0x02, 0x01, 0x04, 0x08, 0x04, 0x00, 0x64, 0xB9, 0x95, 0x11, 0x4D, 0x20, 0x42, 0x09};
uint8_t blockD[MFBLOCK_SIZE] = {0x00};
// default transport ACL
uint8_t blockK[MFBLOCK_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t params = MAGIC_SINGLE;
uint8_t params = MAGIC_SINGLE | (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC);
if (uid != NULL) {
memcpy(block0, uid, 4);

View file

@ -92,8 +92,8 @@ int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);
int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth);
int mfCSetUID(uint8_t *uid, uint8_t uidlen, const uint8_t *atqa, const uint8_t *sak, uint8_t *old_uid, uint8_t *verifed_uid, uint8_t wipecard);
int mfCWipe(uint8_t *uid, const uint8_t *atqa, const uint8_t *sak);
int mfCSetUID(uint8_t *uid, uint8_t uidlen, const uint8_t *atqa, const uint8_t *sak, uint8_t *old_uid, uint8_t *verifed_uid, uint8_t wipecard, uint8_t gdm);
int mfCWipe(uint8_t *uid, const uint8_t *atqa, const uint8_t *sak, uint8_t gdm);
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params);
int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params);

View file

@ -250,6 +250,8 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
// bit 3 - turn on FPGA
// bit 4 - turn off FPGA
// bit 5 - set datain instead of issuing USB reply (called via ARM for StandAloneMode14a)
// bit 6 - wipe tag.
// bit 7 - use USCUID/GDM (20/23) magic wakeup
#define MAGIC_UID 0x01
#define MAGIC_WUPC 0x02
#define MAGIC_HALT 0x04
@ -257,7 +259,8 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define MAGIC_OFF 0x10
#define MAGIC_DATAIN 0x20
#define MAGIC_WIPE 0x40
#define MAGIC_SINGLE (MAGIC_WUPC | MAGIC_HALT | MAGIC_INIT | MAGIC_OFF) //0x1E
#define MAGIC_GDM_ALT_WUPC 0x80
#define MAGIC_SINGLE (MAGIC_HALT | MAGIC_INIT | MAGIC_OFF) //0x1E
// by CMD_HF_MIFARE_CIDENT / Flags
#define MAGIC_FLAG_NONE 0x0000