diff --git a/CHANGELOG.md b/CHANGELOG.md index fb9f99414..d7d336192 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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] +- Added support for quick dump via backdoor auth to `hf mf ecfill` (@doegox) - Fixed `hf mf restore` - really skip strict ACLs unless --force (@doegox) - Added `hf 14b setuid` - set uid on magic 14b tag (@iceman1001) - Changed `hf 14b info` - now detect Tiananxin (@iceman1001) diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index b03051ca3..c899aefe2 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -520,11 +520,11 @@ void RunMod(void) { int filled; partialEmulation = false; DbpString("[=] Filling emulator memory using key A"); - filled = MifareECardLoad(sectorsCnt, MF_KEY_A); + filled = MifareECardLoad(sectorsCnt, MF_KEY_A, NULL); if (filled != PM3_SUCCESS) { DbpString("[" _YELLOW_("-") "] " _YELLOW_("Only partially filled using key A, retry with key B!")); DbpString("[=] Filling emulator memory using key B"); - filled = MifareECardLoad(sectorsCnt, MF_KEY_B); + filled = MifareECardLoad(sectorsCnt, MF_KEY_B, NULL); if (filled != PM3_SUCCESS) { DbpString("[" _YELLOW_("-") "] " _YELLOW_("Only partially filled using key B!")); } diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 14a74fe6c..823968ba2 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1869,7 +1869,7 @@ static void PacketReceived(PacketCommandNG *packet) { } case CMD_HF_MIFARE_EML_LOAD: { mfc_eload_t *payload = (mfc_eload_t *) packet->data.asBytes; - MifareECardLoadExt(payload->sectorcnt, payload->keytype); + MifareECardLoadExt(payload->sectorcnt, payload->keytype, payload->key); break; } // Gen1a / 1b - "magic Chinese" card diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 0b6c2544b..5dd2b2420 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2078,8 +2078,8 @@ OUT: emlSetMem_xt(block, blockno, 1, sizeof(block)); } - MifareECardLoad(sectorcnt, MF_KEY_A); - MifareECardLoad(sectorcnt, MF_KEY_B); + MifareECardLoad(sectorcnt, MF_KEY_A, NULL); + MifareECardLoad(sectorcnt, MF_KEY_B, NULL); } } else { // partial/none keys found @@ -2311,14 +2311,19 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) { // Load a card into the emulator memory // //----------------------------------------------------------------------------- -int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype) { - int retval = MifareECardLoad(sectorcnt, keytype); +int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) { + int retval = MifareECardLoad(sectorcnt, keytype, key); reply_ng(CMD_HF_MIFARE_EML_LOAD, retval, NULL, 0); return retval; } -int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { - +int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) { + if ((keytype > MF_KEY_B) && (key == NULL)) { + if (g_dbglevel >= DBG_ERROR) { + Dbprintf("Error, missing key"); + } + return PM3_EINVARG; + } LED_A_ON(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); @@ -2327,6 +2332,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { // variables bool have_uid = false; + bool bd_authenticated = false; uint8_t cascade_levels = 0; uint32_t cuid = 0; uint8_t uid[10] = {0x00}; @@ -2389,13 +2395,27 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { } have_uid = true; } else { // no need for anticollision. We can directly select the card - if (iso14443a_fast_select_card(uid, cascade_levels) == 0) { - continue; + if (!bd_authenticated) { // no need to select if bd_authenticated with backdoor + if (iso14443a_fast_select_card(uid, cascade_levels) == 0) { + continue; + } } } // Auth - if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(s), keytype, ui64Key, AUTH_FIRST)) { + if (keytype > MF_KEY_B) { + if (! bd_authenticated) { + ui64Key = bytes_to_num(key, 6); + if (mifare_classic_auth(pcs, cuid, 0, keytype, ui64Key, AUTH_FIRST)) { + retval = PM3_EFAILED; + if (g_dbglevel >= DBG_ERROR) { + Dbprintf("Auth error"); + } + goto out; + } + bd_authenticated = true; + } + } else if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(s), keytype, ui64Key, AUTH_FIRST)) { ui64Key = emlGetKey(s, MF_KEY_B); @@ -2455,8 +2475,9 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { } } } - - int res = mifare_classic_halt(pcs); + int res; +out: + res = mifare_classic_halt(pcs); (void)res; iso14a_set_timeout(timeout); @@ -2468,6 +2489,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { } + //----------------------------------------------------------------------------- // Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn) // diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 86e0afd8f..a46982a55 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -45,8 +45,8 @@ void MifareChkKeys_file(uint8_t *fn); void MifareEMemClr(void); void MifareEMemGet(uint8_t blockno, uint8_t blockcnt); -int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype); -int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype); +int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key); +int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype, uint8_t *key); // MFC GEN1a /1b void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 8d5b7b074..5b12be941 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -4926,6 +4926,8 @@ static int CmdHF14AMfECFill(const char *Cmd) { arg_param_begin, arg_lit0("a", NULL, "input key type is key A(def)"), arg_lit0("b", NULL, "input key type is key B"), + arg_int0("c", NULL, "", "input key type is key A + offset"), + arg_str0("k", "key", "", "key, 6 hex bytes, only for option -c"), arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"), arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), @@ -4941,11 +4943,28 @@ static int CmdHF14AMfECFill(const char *Cmd) { } else if (arg_get_lit(ctx, 2)) { keytype = MF_KEY_B; } + uint8_t prev_keytype = keytype; + keytype = arg_get_int_def(ctx, 3, keytype); + if ((arg_get_lit(ctx, 1) || arg_get_lit(ctx, 2)) && (keytype != prev_keytype)) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "Choose one single input key type"); + return PM3_EINVARG; + } + int keylen = 0; + uint8_t key[6] = {0}; + CLIGetHexWithReturn(ctx, 4, key, &keylen); + if ((keytype > MF_KEY_B) && (keylen != 6)) { + PrintAndLogEx(WARNING, "Missing key"); + return PM3_EINVARG; + } + if ((keytype <= MF_KEY_B) && (keylen > 0)) { + PrintAndLogEx(WARNING, "Ignoring provided key"); + } - bool m0 = arg_get_lit(ctx, 3); - bool m1 = arg_get_lit(ctx, 4); - bool m2 = arg_get_lit(ctx, 5); - bool m4 = arg_get_lit(ctx, 6); + bool m0 = arg_get_lit(ctx, 5); + bool m1 = arg_get_lit(ctx, 6); + bool m2 = arg_get_lit(ctx, 7); + bool m4 = arg_get_lit(ctx, 8); CLIParserFree(ctx); // validations @@ -4975,6 +4994,7 @@ static int CmdHF14AMfECFill(const char *Cmd) { .sectorcnt = sectors_cnt, .keytype = keytype }; + memcpy(payload.key, key, sizeof(payload.key)); clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload)); diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 87d0d2c66..9e7d45bc7 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -323,6 +323,7 @@ typedef struct { typedef struct { uint8_t sectorcnt; uint8_t keytype; + uint8_t key[6]; } PACKED mfc_eload_t; typedef struct {