From e448d582918df9efc8866fc974ac8dca63e63ec6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 12:46:45 +0200 Subject: [PATCH] hf mf csetuid - now supports cliparser. Also experimental 7byte support. Not seen one in the wild. untested --- client/src/cmdhfmf.c | 168 +++++++++++++++++---------------- client/src/mifare/mifarehost.c | 68 +++++++++---- client/src/mifare/mifarehost.h | 2 +- doc/cliparser_todo.txt | 1 - doc/magic_cards_notes.md | 4 +- 5 files changed, 138 insertions(+), 105 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index f3dc00132..cf1c31478 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -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] [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 8 hex symbols"); - PrintAndLogEx(NORMAL, " ATQA 4 hex symbols"); - PrintAndLogEx(NORMAL, " 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, ""); @@ -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}; + + 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", "", "UID, 4/7 hex bytes"), + arg_str0("a", "atqa", "", "ATQA, 2 hex bytes"), + arg_str0("s", "sak", "", "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}; + CLIGetHexWithReturn(ctx, 3, atqa, &alen); + + int slen = 0; uint8_t sak[1] = {0x00}; - uint8_t atqaPresent = 1; - int res, argi = 0; - char ctmp; + CLIGetHexWithReturn(ctx, 4, sak, &slen); + CLIParserFree(ctx); - if (strlen(Cmd) < 1 || param_getchar(Cmd, argi) == 'h') - return usage_hf14_csetuid(); - - if (param_getchar(Cmd, argi) && param_gethex(Cmd, argi, uid, 8)) - return usage_hf14_csetuid(); - - argi++; - - ctmp = tolower(param_getchar(Cmd, argi)); - if (ctmp == 'w') { - wipeCard = 1; - atqaPresent = 0; + // 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; } - 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; - } + uint8_t old_uid[7] = {0}; + uint8_t verify_uid[7] = {0}; - if (!wipeCard) { - ctmp = tolower(param_getchar(Cmd, argi)); - if (ctmp == 'w') { - wipeCard = 1; - } - } + int res = mfCSetUID( + uid, + uidlen, + (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) { - 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 for card"), - arg_str0("a", "atqa", "", "ATQA for card"), - arg_str0("s", "sak", "", "SAK for card"), + arg_str0("u", "uid", "", "UID, 4 hex bytes"), + arg_str0("a", "atqa", "", "ATQA, 2 hex bytes"), + arg_str0("s", "sak", "", "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; } diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index 48ac96acd..c87e96442 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -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)); - 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) { diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index c4c65737a..49adc8cbe 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -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); diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index aa7168c26..c8e72098e 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -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 diff --git a/doc/magic_cards_notes.md b/doc/magic_cards_notes.md index d24a0b7c5..0a73a83b8 100644 --- a/doc/magic_cards_notes.md +++ b/doc/magic_cards_notes.md @@ -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 ``` ```