Skip to content

Commit

Permalink
Merge pull request #2608 from nvx/hf_mf_c_gdm
Browse files Browse the repository at this point in the history
add gdm flag to hf mf c* commands
  • Loading branch information
iceman1001 authored Nov 2, 2024
2 parents 60c2446 + 1157ef0 commit e3a6ab7
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 19 deletions.
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

0 comments on commit e3a6ab7

Please sign in to comment.