Skip to content

Commit

Permalink
hf mf csetuid - now supports cliparser. Also experimental 7byte suppo…
Browse files Browse the repository at this point in the history
…rt. Not seen one in the wild. untested
  • Loading branch information
iceman1001 committed Apr 11, 2021
1 parent 3c2b04a commit e448d58
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 103 deletions.
164 changes: 83 additions & 81 deletions client/src/cmdhfmf.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,21 +188,6 @@ static int usage_hf14_decryptbytes(void) {
return PM3_SUCCESS;
}

static int usage_hf14_csetuid(void) {
PrintAndLogEx(NORMAL, "Set UID, ATQA, and SAK for magic Chinese card. Only works with magic cards");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: hf mf csetuid [h] <UID 8 hex symbols> [ATQA 4 hex symbols] [SAK 2 hex symbols] [w]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, " w wipe card before writing");
PrintAndLogEx(NORMAL, " <uid> UID 8 hex symbols");
PrintAndLogEx(NORMAL, " <atqa> ATQA 4 hex symbols");
PrintAndLogEx(NORMAL, " <sak> SAK 2 hex symbols");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf csetuid 01020304"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf csetuid 01020304 0004 08 w"));
return PM3_SUCCESS;
}
static int usage_hf14_csetblk(void) {
PrintAndLogEx(NORMAL, "Set block data for magic Chinese card. Only works with magic cards");
PrintAndLogEx(NORMAL, "");
Expand Down Expand Up @@ -4313,109 +4298,126 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) {

// CHINESE MAGIC COMMANDS
static int CmdHF14AMfCSetUID(const char *Cmd) {
uint8_t wipeCard = 0;
uint8_t uid[8] = {0x00};
uint8_t oldUid[8] = {0x00};
uint8_t atqa[2] = {0x00};
uint8_t sak[1] = {0x00};
uint8_t atqaPresent = 1;
int res, argi = 0;
char ctmp;

if (strlen(Cmd) < 1 || param_getchar(Cmd, argi) == 'h')
return usage_hf14_csetuid();
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf csetuid",
"Set UID, ATQA, and SAK for magic gen1a card",
"hf mf csetuid -u 01020304\n"
"hf mf csetuid -w -u 01020304 --atqa 0004 --sak 08"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("w", "wipe", "wipes card with backdoor 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_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);

if (param_getchar(Cmd, argi) && param_gethex(Cmd, argi, uid, 8))
return usage_hf14_csetuid();
uint8_t wipe_card = arg_get_lit(ctx, 1);

argi++;
int uidlen = 0;
uint8_t uid[7] = {0x00};
CLIGetHexWithReturn(ctx, 2, uid, &uidlen);

ctmp = tolower(param_getchar(Cmd, argi));
if (ctmp == 'w') {
wipeCard = 1;
atqaPresent = 0;
}
int alen = 0;
uint8_t atqa[2] = {0x00};
CLIGetHexWithReturn(ctx, 3, atqa, &alen);

if (atqaPresent) {
if (param_getchar(Cmd, argi)) {
if (param_gethex(Cmd, argi, atqa, 4)) {
PrintAndLogEx(WARNING, "ATQA must include 4 HEX symbols");
return PM3_ESOFT;
}
argi++;
if (!param_getchar(Cmd, argi) || param_gethex(Cmd, argi, sak, 2)) {
PrintAndLogEx(WARNING, "SAK must include 2 HEX symbols");
return PM3_ESOFT;
}
argi++;
} else
atqaPresent = 0;
}
int slen = 0;
uint8_t sak[1] = {0x00};
CLIGetHexWithReturn(ctx, 4, sak, &slen);
CLIParserFree(ctx);

if (!wipeCard) {
ctmp = tolower(param_getchar(Cmd, argi));
if (ctmp == 'w') {
wipeCard = 1;
}
// sanity checks
if (uidlen != 4 && uidlen != 7) {
PrintAndLogEx(FAILED, "UID must be 4 or 7 hex bytes. Got %d", uidlen);
return PM3_EINVARG;
}
if (alen && alen != 2) {
PrintAndLogEx(FAILED, "ATQA must be 2 hex bytes. Got %d", alen);
return PM3_EINVARG;
}
if (slen && slen != 1) {
PrintAndLogEx(FAILED, "SAK must be 1 hex byte. Got %d", slen);
return PM3_EINVARG;
}

uint8_t old_uid[7] = {0};
uint8_t verify_uid[7] = {0};

PrintAndLogEx(NORMAL, "--wipe card:%s uid:%s", (wipeCard) ? "YES" : "NO", sprint_hex(uid, 4));
int res = mfCSetUID(
uid,
uidlen,
(alen) ? atqa : NULL,
(slen) ? sak : NULL,
old_uid,
verify_uid,
wipe_card
);

res = mfCSetUID(uid, (atqaPresent) ? atqa : NULL, (atqaPresent) ? sak : NULL, oldUid, wipeCard);
if (res) {
PrintAndLogEx(ERR, "Can't set UID. error=%d", res);
PrintAndLogEx(ERR, "Can't set UID. error %d", res);
return PM3_ESOFT;
}

PrintAndLogEx(SUCCESS, "Old UID : %s", sprint_hex(oldUid, 4));
PrintAndLogEx(SUCCESS, "New UID : %s", sprint_hex(uid, 4));
res = memcmp(uid, verify_uid, uidlen);

PrintAndLogEx(SUCCESS, "Old UID... %s", sprint_hex(old_uid, uidlen));
PrintAndLogEx(SUCCESS, "New UID... %s ( %s )",
sprint_hex(verify_uid, uidlen),
(res == 0) ? _GREEN_("verified") : _RED_("fail")
);
return PM3_SUCCESS;
}

static int CmdHF14AMfCWipe(const char *cmd) {
uint8_t uid[8] = {0x00};
int uidLen = 0;
uint8_t atqa[2] = {0x00};
int atqaLen = 0;
uint8_t sak[1] = {0x00};
int sakLen = 0;

CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf cwipe",
"Wipe gen1 magic chinese card. Set UID/ATQA/SAK/Data/Keys/Access to default values.",
"hf mf cwipe --> wipe card\n"
"Wipe gen1 magic chinese card.\n"
"Set UID / ATQA / SAK / Data / Keys / Access to default values",
"hf mf cwipe\n"
"hf mf cwipe -u 09080706 -a 0004 -s 18 --> set UID, ATQA and SAK and wipe card");

void *argtable[] = {
arg_param_begin,
arg_str0("u", "uid", "<UID (hex 4b)>", "UID for card"),
arg_str0("a", "atqa", "<ATQA (hex 2b)>", "ATQA for card"),
arg_str0("s", "sak", "<SAK (hex 1b)>", "SAK for card"),
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_param_end
};
CLIExecWithReturn(ctx, cmd, argtable, true);

CLIGetHexWithReturn(ctx, 1, uid, &uidLen);
CLIGetHexWithReturn(ctx, 2, atqa, &atqaLen);
CLIGetHexWithReturn(ctx, 3, sak, &sakLen);
int uidlen = 0;
uint8_t uid[8] = {0x00};
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);

int alen = 0;
uint8_t atqa[2] = {0x00};
CLIGetHexWithReturn(ctx, 2, atqa, &alen);

int slen = 0;
uint8_t sak[1] = {0x00};
CLIGetHexWithReturn(ctx, 3, sak, &slen);
CLIParserFree(ctx);

if (uidLen && uidLen != 4) {
PrintAndLogEx(ERR, "UID length must be 4 bytes instead of: %d", uidLen);
if (uidlen && uidlen != 4) {
PrintAndLogEx(ERR, "UID length must be 4 bytes, got %d", uidlen);
return PM3_EINVARG;
}
if (atqaLen && atqaLen != 2) {
PrintAndLogEx(ERR, "ATQA length must be 2 bytes instead of: %d", atqaLen);
if (alen && alen != 2) {
PrintAndLogEx(ERR, "ATQA length must be 2 bytes, got %d", alen);
return PM3_EINVARG;
}
if (sakLen && sakLen != 1) {
PrintAndLogEx(ERR, "SAK length must be 1 byte instead of: %d", sakLen);
if (slen && slen != 1) {
PrintAndLogEx(ERR, "SAK length must be 1 byte, got %d", slen);
return PM3_EINVARG;
}

int res = mfCWipe((uidLen) ? uid : NULL, (atqaLen) ? atqa : NULL, (sakLen) ? sak : NULL);
int res = mfCWipe((uidlen) ? uid : NULL, (alen) ? atqa : NULL, (slen) ? sak : NULL);
if (res) {
PrintAndLogEx(ERR, "Can't wipe card. error=%d", res);
PrintAndLogEx(ERR, "Can't wipe card. error %d", res);
return PM3_ESOFT;
}

Expand Down
68 changes: 50 additions & 18 deletions client/src/mifare/mifarehost.c
Original file line number Diff line number Diff line change
Expand Up @@ -853,37 +853,69 @@ int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidt
}

// "MAGIC" CARD
int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_t wipecard) {
int mfCSetUID(uint8_t *uid, uint8_t uidlen, uint8_t *atqa, uint8_t *sak, uint8_t *old_uid, uint8_t *verifed_uid, uint8_t wipecard) {

uint8_t params = MAGIC_SINGLE;
uint8_t block0[16];
memset(block0, 0x00, sizeof(block0));

int old = mfCGetBlock(0, block0, params);
if (old == 0)
PrintAndLogEx(SUCCESS, "old block 0: %s", sprint_hex(block0, sizeof(block0)));
else
PrintAndLogEx(FAILED, "couldn't get old data. Will write over the last bytes of Block 0.");
int res = mfCGetBlock(0, block0, params);
if (res == 0) {
PrintAndLogEx(SUCCESS, "old block 0... %s", sprint_hex_inrow(block0, sizeof(block0)));
if (old_uid) {
memcpy(old_uid, block0, uidlen);
}
} else {
PrintAndLogEx(INFO, "couldn't get old data. Will write over the last bytes of block 0");
}

// fill in the new values
// UID
memcpy(block0, uid, 4);
memcpy(block0, uid, uidlen);
// Mifare UID BCC
block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3];
// mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed)
if (sak != NULL)
block0[5] = sak[0];
if (uidlen == 4) {
block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3];

if (atqa != NULL) {
block0[6] = atqa[1];
block0[7] = atqa[0];
// mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed)
if (sak)
block0[5] = sak[0];

if (atqa) {
block0[6] = atqa[1];
block0[7] = atqa[0];
}

} else if (uidlen == 7) {
block0[7] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3] ^ block0[4] ^ block0[5] ^ block0[6];

// mifare classic SAK(byte 8) and ATQA(byte 9 and 10, reversed)
if (sak)
block0[8] = sak[0];

if (atqa) {
block0[9] = atqa[1];
block0[10] = atqa[0];
}
}
PrintAndLogEx(SUCCESS, "new block 0: %s", sprint_hex(block0, 16));

if (wipecard) params |= MAGIC_WIPE;
if (oldUID != NULL) params |= MAGIC_UID;
PrintAndLogEx(SUCCESS, "new block 0... %s", sprint_hex_inrow(block0, 16));

if (wipecard) {
params |= MAGIC_WIPE;
}

return mfCSetBlock(0, block0, oldUID, params);
res = mfCSetBlock(0, block0, NULL, params);
if (res == PM3_SUCCESS) {
params = MAGIC_SINGLE;
memset(block0, 0, sizeof(block0));
res = mfCGetBlock(0, block0, params);
if (res == 0) {
if (verifed_uid) {
memcpy(verifed_uid, block0, uidlen);
}
}
}
return res;
}

int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) {
Expand Down
2 changes: 1 addition & 1 deletion client/src/mifare/mifarehost.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ 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 *atqa, uint8_t *sak, uint8_t *oldUID, uint8_t wipecard);
int mfCSetUID(uint8_t *uid, uint8_t uidlen, uint8_t *atqa, uint8_t *sak, uint8_t *old_uid, uint8_t *verifed_uid, uint8_t wipecard);
int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak);
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
1 change: 0 additions & 1 deletion doc/cliparser_todo.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ hf mf restore
hf mf setmod
hf mf wrbl
hf mf csetblk
hf mf csetuid
hf mf gen3uid
hf mf gen3blk
hf mf gen3freeze
Expand Down
4 changes: 2 additions & 2 deletions doc/magic_cards_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,9 @@ hf mf cwipe -u 11223344 -a 0044 -s 18
or just fixing block0:
```
# MFC Gen1A 1k:
hf mf csetuid 11223344 0004 08
hf mf csetuid -u 11223344 -a 0004 -s 08
# MFC Gen1A 4k:
hf mf csetuid 11223344 0044 18
hf mf csetuid -u 11223344 -a 0044 -s 18
```

```
Expand Down

0 comments on commit e448d58

Please sign in to comment.