mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 13:00:42 -07:00
hf mf ecfill: add support for quick dump via backdoor auth
This commit is contained in:
parent
62080b2b34
commit
a11ba61b01
7 changed files with 64 additions and 20 deletions
|
@ -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...
|
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]
|
## [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)
|
- Fixed `hf mf restore` - really skip strict ACLs unless --force (@doegox)
|
||||||
- Added `hf 14b setuid` - set uid on magic 14b tag (@iceman1001)
|
- Added `hf 14b setuid` - set uid on magic 14b tag (@iceman1001)
|
||||||
- Changed `hf 14b info` - now detect Tiananxin (@iceman1001)
|
- Changed `hf 14b info` - now detect Tiananxin (@iceman1001)
|
||||||
|
|
|
@ -520,11 +520,11 @@ void RunMod(void) {
|
||||||
int filled;
|
int filled;
|
||||||
partialEmulation = false;
|
partialEmulation = false;
|
||||||
DbpString("[=] Filling emulator memory using key A");
|
DbpString("[=] Filling emulator memory using key A");
|
||||||
filled = MifareECardLoad(sectorsCnt, MF_KEY_A);
|
filled = MifareECardLoad(sectorsCnt, MF_KEY_A, NULL);
|
||||||
if (filled != PM3_SUCCESS) {
|
if (filled != PM3_SUCCESS) {
|
||||||
DbpString("[" _YELLOW_("-") "] " _YELLOW_("Only partially filled using key A, retry with key B!"));
|
DbpString("[" _YELLOW_("-") "] " _YELLOW_("Only partially filled using key A, retry with key B!"));
|
||||||
DbpString("[=] Filling emulator memory using 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) {
|
if (filled != PM3_SUCCESS) {
|
||||||
DbpString("[" _YELLOW_("-") "] " _YELLOW_("Only partially filled using key B!"));
|
DbpString("[" _YELLOW_("-") "] " _YELLOW_("Only partially filled using key B!"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1869,7 +1869,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_EML_LOAD: {
|
case CMD_HF_MIFARE_EML_LOAD: {
|
||||||
mfc_eload_t *payload = (mfc_eload_t *) packet->data.asBytes;
|
mfc_eload_t *payload = (mfc_eload_t *) packet->data.asBytes;
|
||||||
MifareECardLoadExt(payload->sectorcnt, payload->keytype);
|
MifareECardLoadExt(payload->sectorcnt, payload->keytype, payload->key);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Gen1a / 1b - "magic Chinese" card
|
// Gen1a / 1b - "magic Chinese" card
|
||||||
|
|
|
@ -2078,8 +2078,8 @@ OUT:
|
||||||
emlSetMem_xt(block, blockno, 1, sizeof(block));
|
emlSetMem_xt(block, blockno, 1, sizeof(block));
|
||||||
}
|
}
|
||||||
|
|
||||||
MifareECardLoad(sectorcnt, MF_KEY_A);
|
MifareECardLoad(sectorcnt, MF_KEY_A, NULL);
|
||||||
MifareECardLoad(sectorcnt, MF_KEY_B);
|
MifareECardLoad(sectorcnt, MF_KEY_B, NULL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// partial/none keys found
|
// partial/none keys found
|
||||||
|
@ -2311,14 +2311,19 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) {
|
||||||
// Load a card into the emulator memory
|
// Load a card into the emulator memory
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype) {
|
int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
|
||||||
int retval = MifareECardLoad(sectorcnt, keytype);
|
int retval = MifareECardLoad(sectorcnt, keytype, key);
|
||||||
reply_ng(CMD_HF_MIFARE_EML_LOAD, retval, NULL, 0);
|
reply_ng(CMD_HF_MIFARE_EML_LOAD, retval, NULL, 0);
|
||||||
return retval;
|
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();
|
LED_A_ON();
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
|
||||||
|
@ -2327,6 +2332,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
bool have_uid = false;
|
bool have_uid = false;
|
||||||
|
bool bd_authenticated = false;
|
||||||
uint8_t cascade_levels = 0;
|
uint8_t cascade_levels = 0;
|
||||||
uint32_t cuid = 0;
|
uint32_t cuid = 0;
|
||||||
uint8_t uid[10] = {0x00};
|
uint8_t uid[10] = {0x00};
|
||||||
|
@ -2389,13 +2395,27 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
|
||||||
}
|
}
|
||||||
have_uid = true;
|
have_uid = true;
|
||||||
} else { // no need for anticollision. We can directly select the card
|
} else { // no need for anticollision. We can directly select the card
|
||||||
|
if (!bd_authenticated) { // no need to select if bd_authenticated with backdoor
|
||||||
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
|
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Auth
|
// 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);
|
ui64Key = emlGetKey(s, MF_KEY_B);
|
||||||
|
|
||||||
|
@ -2455,8 +2475,9 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int res;
|
||||||
int res = mifare_classic_halt(pcs);
|
out:
|
||||||
|
res = mifare_classic_halt(pcs);
|
||||||
(void)res;
|
(void)res;
|
||||||
|
|
||||||
iso14a_set_timeout(timeout);
|
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)
|
// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)
|
||||||
//
|
//
|
||||||
|
|
|
@ -45,8 +45,8 @@ void MifareChkKeys_file(uint8_t *fn);
|
||||||
|
|
||||||
void MifareEMemClr(void);
|
void MifareEMemClr(void);
|
||||||
void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
|
void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
|
||||||
int MifareECardLoad(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);
|
int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype, uint8_t *key);
|
||||||
|
|
||||||
// MFC GEN1a /1b
|
// MFC GEN1a /1b
|
||||||
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card
|
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card
|
||||||
|
|
|
@ -4926,6 +4926,8 @@ static int CmdHF14AMfECFill(const char *Cmd) {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_lit0("a", NULL, "input key type is key A(def)"),
|
arg_lit0("a", NULL, "input key type is key A(def)"),
|
||||||
arg_lit0("b", NULL, "input key type is key B"),
|
arg_lit0("b", NULL, "input key type is key B"),
|
||||||
|
arg_int0("c", NULL, "<dec>", "input key type is key A + offset"),
|
||||||
|
arg_str0("k", "key", "<hex>", "key, 6 hex bytes, only for option -c"),
|
||||||
arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
|
arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
|
||||||
arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
|
arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
|
||||||
arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
|
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)) {
|
} else if (arg_get_lit(ctx, 2)) {
|
||||||
keytype = MF_KEY_B;
|
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 m0 = arg_get_lit(ctx, 5);
|
||||||
bool m1 = arg_get_lit(ctx, 4);
|
bool m1 = arg_get_lit(ctx, 6);
|
||||||
bool m2 = arg_get_lit(ctx, 5);
|
bool m2 = arg_get_lit(ctx, 7);
|
||||||
bool m4 = arg_get_lit(ctx, 6);
|
bool m4 = arg_get_lit(ctx, 8);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
// validations
|
// validations
|
||||||
|
@ -4975,6 +4994,7 @@ static int CmdHF14AMfECFill(const char *Cmd) {
|
||||||
.sectorcnt = sectors_cnt,
|
.sectorcnt = sectors_cnt,
|
||||||
.keytype = keytype
|
.keytype = keytype
|
||||||
};
|
};
|
||||||
|
memcpy(payload.key, key, sizeof(payload.key));
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload));
|
SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload));
|
||||||
|
|
|
@ -323,6 +323,7 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t sectorcnt;
|
uint8_t sectorcnt;
|
||||||
uint8_t keytype;
|
uint8_t keytype;
|
||||||
|
uint8_t key[6];
|
||||||
} PACKED mfc_eload_t;
|
} PACKED mfc_eload_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue