Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add gdm flag to hf mf c* commands #2608

Merged
merged 2 commits into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...

## [unreleased][unreleased]
- Changed `hf mf c*` - now accepts a --gdm flag to write using uscuid/gdm 20/23 alt magic wakeup (@nvx)
- Changed `pm3_console()` - Python/Lua/C: replace `passthru` by `capture` and `quiet` (@doegox)
- Fixed `hf iclass list` - annotation crc handled better (@iceman1001)
- Fixed `hf_mf_uscuid_prog.lua` - bad divisions and code style fixes (@iceman1001)
Expand Down
4 changes: 2 additions & 2 deletions armsrc/Standalone/hf_young.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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
Expand Down
33 changes: 33 additions & 0 deletions armsrc/mifarecmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2552,6 +2552,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
// 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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)) {
Expand Down
41 changes: 32 additions & 9 deletions client/src/cmdhfmf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -5209,7 +5211,8 @@ static int CmdHF14AMfCSetUID(const char *Cmd) {
(slen) ? sak : NULL,
old_uid,
verify_uid,
wipe_card
wipe_card,
gdm
);

if (res) {
Expand Down Expand Up @@ -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);
Expand All @@ -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) {
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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) {
Expand All @@ -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;
}
Expand Down Expand Up @@ -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);
Expand All @@ -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);

Expand Down Expand Up @@ -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++) {
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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) {
Expand Down
10 changes: 5 additions & 5 deletions client/src/mifare/mifarehost.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down Expand Up @@ -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) {
Expand All @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions client/src/mifare/mifarehost.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
5 changes: 4 additions & 1 deletion include/protocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,14 +250,17 @@ 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
#define MAGIC_INIT 0x08
#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
Expand Down
Loading