hf mf csetuid - now supports cliparser. Also experimental 7byte support. Not seen one in the wild. untested

This commit is contained in:
iceman1001 2021-04-11 12:46:45 +02:00
commit e448d58291
5 changed files with 138 additions and 105 deletions

View file

@ -188,21 +188,6 @@ static int usage_hf14_decryptbytes(void) {
return PM3_SUCCESS; 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) { static int usage_hf14_csetblk(void) {
PrintAndLogEx(NORMAL, "Set block data for magic Chinese card. Only works with magic cards"); PrintAndLogEx(NORMAL, "Set block data for magic Chinese card. Only works with magic cards");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
@ -4313,109 +4298,126 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) {
// CHINESE MAGIC COMMANDS // CHINESE MAGIC COMMANDS
static int CmdHF14AMfCSetUID(const char *Cmd) { static int CmdHF14AMfCSetUID(const char *Cmd) {
uint8_t wipeCard = 0;
uint8_t uid[8] = {0x00}; CLIParserContext *ctx;
uint8_t oldUid[8] = {0x00}; 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);
uint8_t wipe_card = arg_get_lit(ctx, 1);
int uidlen = 0;
uint8_t uid[7] = {0x00};
CLIGetHexWithReturn(ctx, 2, uid, &uidlen);
int alen = 0;
uint8_t atqa[2] = {0x00}; uint8_t atqa[2] = {0x00};
CLIGetHexWithReturn(ctx, 3, atqa, &alen);
int slen = 0;
uint8_t sak[1] = {0x00}; uint8_t sak[1] = {0x00};
uint8_t atqaPresent = 1; CLIGetHexWithReturn(ctx, 4, sak, &slen);
int res, argi = 0; CLIParserFree(ctx);
char ctmp;
if (strlen(Cmd) < 1 || param_getchar(Cmd, argi) == 'h') // sanity checks
return usage_hf14_csetuid(); if (uidlen != 4 && uidlen != 7) {
PrintAndLogEx(FAILED, "UID must be 4 or 7 hex bytes. Got %d", uidlen);
if (param_getchar(Cmd, argi) && param_gethex(Cmd, argi, uid, 8)) return PM3_EINVARG;
return usage_hf14_csetuid(); }
if (alen && alen != 2) {
argi++; PrintAndLogEx(FAILED, "ATQA must be 2 hex bytes. Got %d", alen);
return PM3_EINVARG;
ctmp = tolower(param_getchar(Cmd, argi)); }
if (ctmp == 'w') { if (slen && slen != 1) {
wipeCard = 1; PrintAndLogEx(FAILED, "SAK must be 1 hex byte. Got %d", slen);
atqaPresent = 0; return PM3_EINVARG;
} }
if (atqaPresent) { uint8_t old_uid[7] = {0};
if (param_getchar(Cmd, argi)) { uint8_t verify_uid[7] = {0};
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;
}
if (!wipeCard) { int res = mfCSetUID(
ctmp = tolower(param_getchar(Cmd, argi)); uid,
if (ctmp == 'w') { uidlen,
wipeCard = 1; (alen) ? atqa : NULL,
} (slen) ? sak : NULL,
} old_uid,
verify_uid,
wipe_card
);
PrintAndLogEx(NORMAL, "--wipe card:%s uid:%s", (wipeCard) ? "YES" : "NO", sprint_hex(uid, 4));
res = mfCSetUID(uid, (atqaPresent) ? atqa : NULL, (atqaPresent) ? sak : NULL, oldUid, wipeCard);
if (res) { if (res) {
PrintAndLogEx(ERR, "Can't set UID. error=%d", res); PrintAndLogEx(ERR, "Can't set UID. error %d", res);
return PM3_ESOFT; return PM3_ESOFT;
} }
PrintAndLogEx(SUCCESS, "Old UID : %s", sprint_hex(oldUid, 4)); res = memcmp(uid, verify_uid, uidlen);
PrintAndLogEx(SUCCESS, "New UID : %s", sprint_hex(uid, 4));
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; return PM3_SUCCESS;
} }
static int CmdHF14AMfCWipe(const char *cmd) { 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; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf cwipe", CLIParserInit(&ctx, "hf mf cwipe",
"Wipe gen1 magic chinese card. Set UID/ATQA/SAK/Data/Keys/Access to default values.", "Wipe gen1 magic chinese card.\n"
"hf mf cwipe --> wipe 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"); "hf mf cwipe -u 09080706 -a 0004 -s 18 --> set UID, ATQA and SAK and wipe card");
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_str0("u", "uid", "<UID (hex 4b)>", "UID for card"), arg_str0("u", "uid", "<hex>", "UID, 4 hex bytes"),
arg_str0("a", "atqa", "<ATQA (hex 2b)>", "ATQA for card"), arg_str0("a", "atqa", "<hex>", "ATQA, 2 hex bytes"),
arg_str0("s", "sak", "<SAK (hex 1b)>", "SAK for card"), arg_str0("s", "sak", "<hex>", "SAK, 1 hex byte"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, cmd, argtable, true); CLIExecWithReturn(ctx, cmd, argtable, true);
CLIGetHexWithReturn(ctx, 1, uid, &uidLen); int uidlen = 0;
CLIGetHexWithReturn(ctx, 2, atqa, &atqaLen); uint8_t uid[8] = {0x00};
CLIGetHexWithReturn(ctx, 3, sak, &sakLen); 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); CLIParserFree(ctx);
if (uidLen && uidLen != 4) { if (uidlen && uidlen != 4) {
PrintAndLogEx(ERR, "UID length must be 4 bytes instead of: %d", uidLen); PrintAndLogEx(ERR, "UID length must be 4 bytes, got %d", uidlen);
return PM3_EINVARG; return PM3_EINVARG;
} }
if (atqaLen && atqaLen != 2) { if (alen && alen != 2) {
PrintAndLogEx(ERR, "ATQA length must be 2 bytes instead of: %d", atqaLen); PrintAndLogEx(ERR, "ATQA length must be 2 bytes, got %d", alen);
return PM3_EINVARG; return PM3_EINVARG;
} }
if (sakLen && sakLen != 1) { if (slen && slen != 1) {
PrintAndLogEx(ERR, "SAK length must be 1 byte instead of: %d", sakLen); PrintAndLogEx(ERR, "SAK length must be 1 byte, got %d", slen);
return PM3_EINVARG; 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) { if (res) {
PrintAndLogEx(ERR, "Can't wipe card. error=%d", res); PrintAndLogEx(ERR, "Can't wipe card. error %d", res);
return PM3_ESOFT; return PM3_ESOFT;
} }

View file

@ -853,37 +853,69 @@ int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidt
} }
// "MAGIC" CARD // "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 params = MAGIC_SINGLE;
uint8_t block0[16]; uint8_t block0[16];
memset(block0, 0x00, sizeof(block0)); memset(block0, 0x00, sizeof(block0));
int old = mfCGetBlock(0, block0, params); int res = mfCGetBlock(0, block0, params);
if (old == 0) if (res == 0) {
PrintAndLogEx(SUCCESS, "old block 0: %s", sprint_hex(block0, sizeof(block0))); PrintAndLogEx(SUCCESS, "old block 0... %s", sprint_hex_inrow(block0, sizeof(block0)));
else if (old_uid) {
PrintAndLogEx(FAILED, "couldn't get old data. Will write over the last bytes of Block 0."); 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 // fill in the new values
// UID // UID
memcpy(block0, uid, 4); memcpy(block0, uid, uidlen);
// Mifare UID BCC // Mifare UID BCC
block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3]; if (uidlen == 4) {
// mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed) block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3];
if (sak != NULL)
block0[5] = sak[0];
if (atqa != NULL) { // mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed)
block0[6] = atqa[1]; if (sak)
block0[7] = atqa[0]; 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; PrintAndLogEx(SUCCESS, "new block 0... %s", sprint_hex_inrow(block0, 16));
if (oldUID != NULL) params |= MAGIC_UID;
return mfCSetBlock(0, block0, oldUID, params); if (wipecard) {
params |= MAGIC_WIPE;
}
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) { int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) {

View file

@ -76,7 +76,7 @@ int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);
int mfEmlSetMem(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 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 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 mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params);
int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params); int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params);

View file

@ -24,7 +24,6 @@ hf mf restore
hf mf setmod hf mf setmod
hf mf wrbl hf mf wrbl
hf mf csetblk hf mf csetblk
hf mf csetuid
hf mf gen3uid hf mf gen3uid
hf mf gen3blk hf mf gen3blk
hf mf gen3freeze hf mf gen3freeze

View file

@ -189,9 +189,9 @@ hf mf cwipe -u 11223344 -a 0044 -s 18
or just fixing block0: or just fixing block0:
``` ```
# MFC Gen1A 1k: # MFC Gen1A 1k:
hf mf csetuid 11223344 0004 08 hf mf csetuid -u 11223344 -a 0004 -s 08
# MFC Gen1A 4k: # MFC Gen1A 4k:
hf mf csetuid 11223344 0044 18 hf mf csetuid -u 11223344 -a 0044 -s 18
``` ```
``` ```