mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 10:37:23 -07:00
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:
parent
60c2446e27
commit
6d7fcc642a
6 changed files with 78 additions and 19 deletions
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue