mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 21:33:47 -07:00
commit
c851ac7314
12 changed files with 280 additions and 29 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 `hf mf ginfo` command for get info about Gen4 GTU configuration (@merlokk)
|
||||||
- Added support for loading Flipper PICOPASS dump files (@iceman1001)
|
- Added support for loading Flipper PICOPASS dump files (@iceman1001)
|
||||||
- Fixed unknown chip identification (@jmichelp)
|
- Fixed unknown chip identification (@jmichelp)
|
||||||
- Fixed `nfc decode` - now properly handles MFU dump files (@iceman1001)
|
- Fixed `nfc decode` - now properly handles MFU dump files (@iceman1001)
|
||||||
|
|
|
@ -1324,7 +1324,7 @@ static int CmdHFiClassESetBlk(const char *Cmd) {
|
||||||
static bool iclass_detect_new_pacs(uint8_t *d) {
|
static bool iclass_detect_new_pacs(uint8_t *d) {
|
||||||
uint8_t n = 0;
|
uint8_t n = 0;
|
||||||
while (n++ < (PICOPASS_BLOCK_SIZE / 2)) {
|
while (n++ < (PICOPASS_BLOCK_SIZE / 2)) {
|
||||||
if (d[n] &&
|
if (d[n] &&
|
||||||
d[n + 1] == 0xA6) {
|
d[n + 1] == 0xA6) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1332,7 +1332,7 @@ static bool iclass_detect_new_pacs(uint8_t *d) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// block 7 decoder for PACS
|
// block 7 decoder for PACS
|
||||||
static int iclass_decode_credentials_new_pacs(uint8_t *d) {
|
static int iclass_decode_credentials_new_pacs(uint8_t *d) {
|
||||||
|
|
||||||
uint8_t offset = 0;
|
uint8_t offset = 0;
|
||||||
|
@ -1349,7 +1349,7 @@ static int iclass_decode_credentials_new_pacs(uint8_t *d) {
|
||||||
return PM3_EMALLOC;
|
return PM3_EMALLOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t n = PICOPASS_BLOCK_SIZE - offset - 2;
|
uint8_t n = PICOPASS_BLOCK_SIZE - offset - 2;
|
||||||
byte_2_binstr(binstr, d + offset + 2, n);
|
byte_2_binstr(binstr, d + offset + 2, n);
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
|
@ -7434,6 +7434,83 @@ static int CmdHF14AMfView(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// info about Gen4 GTU card
|
||||||
|
static int CmdHF14AGen4Info(const char *cmd) {
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf mf ginfo",
|
||||||
|
"Read info about magic gen4 GTU card.",
|
||||||
|
"hf mf ginfo --> get info with default password 00000000\n"
|
||||||
|
"hf mf ginfo --pwd 01020304 --> get info with password\n"
|
||||||
|
);
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_lit0("v", "verbose", "verbose output"),
|
||||||
|
arg_str0("p", "pwd", "<hex>", "password 4bytes"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, cmd, argtable, true);
|
||||||
|
bool verbose = arg_get_lit(ctx, 1);
|
||||||
|
|
||||||
|
int pwd_len = 0;
|
||||||
|
uint8_t pwd[4] = {0};
|
||||||
|
CLIGetHexWithReturn(ctx, 3, pwd, &pwd_len);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
if (pwd_len != 0 && pwd_len != 4) {
|
||||||
|
PrintAndLogEx(FAILED, "Password must be 4 bytes length, got " _YELLOW_("%u"), pwd_len);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t resp[40] = {0};
|
||||||
|
size_t resplen = 0;
|
||||||
|
int res = mfG4GetConfig(pwd, resp, &resplen, verbose);
|
||||||
|
if (res != PM3_SUCCESS || resplen == 0) {
|
||||||
|
if (res == PM3_ETIMEOUT)
|
||||||
|
PrintAndLogEx(ERR, "No card in the field or card command timeout.");
|
||||||
|
else
|
||||||
|
PrintAndLogEx(ERR, "Error get config. Maybe not a Gen4 card?. error=%d rlen=%d", res, resplen);
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "---------- Gen4 configuration ----------");
|
||||||
|
if (resplen != 30 && resplen != 32) {
|
||||||
|
PrintAndLogEx(INFO, "Raw config [%02d] %s", resplen, sprint_hex_inrow(resp, resplen));
|
||||||
|
PrintAndLogEx(WARNING, "Unknown config format");
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
if (verbose)
|
||||||
|
PrintAndLogEx(INFO, "Raw config [%02d]..... %s", resplen, sprint_hex_inrow(resp, resplen));
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "UL protocol......... %02x", resp[0]);
|
||||||
|
PrintAndLogEx(INFO, "UID length.......... %02x", resp[1]);
|
||||||
|
PrintAndLogEx(INFO, "Password............ %s", sprint_hex_inrow(&resp[2], 4));
|
||||||
|
PrintAndLogEx(INFO, "GTU mode............ %02x", resp[6]);
|
||||||
|
PrintAndLogEx(INFO, "ATS [%02d]............ %s", resp[7], sprint_hex_inrow(&resp[8], resp[7]));
|
||||||
|
PrintAndLogEx(INFO, "ATQA................ %02x%02x", resp[24], resp[25]);
|
||||||
|
PrintAndLogEx(INFO, "SAK................. %02x", resp[26]);
|
||||||
|
PrintAndLogEx(INFO, "UL mode............. %02x", resp[27]);
|
||||||
|
PrintAndLogEx(INFO, "max rd/wr sectors... %02x", resp[28]);
|
||||||
|
PrintAndLogEx(INFO, "block0 direct wr.... %02x", resp[29]);
|
||||||
|
|
||||||
|
|
||||||
|
res = mfG4GetFactoryTest(pwd, resp, &resplen, false);
|
||||||
|
if (res == PM3_SUCCESS && resplen > 2) {
|
||||||
|
if (verbose)
|
||||||
|
PrintAndLogEx(INFO, "Raw test [%02d]....... %s", resplen, sprint_hex_inrow(resp, resplen));
|
||||||
|
|
||||||
|
if (resp[resplen - 2] == 0x66 && resp[resplen - 1] == 0x66)
|
||||||
|
PrintAndLogEx(INFO, "Card type........... generic");
|
||||||
|
else if (resp[resplen - 2] == 0x02 && resp[resplen - 1] == 0xaa)
|
||||||
|
PrintAndLogEx(INFO, "Card type........... limited functionality");
|
||||||
|
else if (resp[resplen - 2] == 0x06 && resp[resplen - 1] == 0xa0)
|
||||||
|
PrintAndLogEx(INFO, "Card type........... broken functionality");
|
||||||
|
else
|
||||||
|
PrintAndLogEx(INFO, "Card type........... unknown %02x%02x", resp[resplen - 2], resp[resplen - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// Read block from Gen4 GTU card
|
// Read block from Gen4 GTU card
|
||||||
static int CmdHF14AGen4GetBlk(const char *cmd) {
|
static int CmdHF14AGen4GetBlk(const char *cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
|
@ -8689,6 +8766,7 @@ static command_t CommandTable[] = {
|
||||||
{"gen3blk", CmdHf14AGen3Block, IfPm3Iso14443a, "Overwrite manufacturer block"},
|
{"gen3blk", CmdHf14AGen3Block, IfPm3Iso14443a, "Overwrite manufacturer block"},
|
||||||
{"gen3freeze", CmdHf14AGen3Freeze, IfPm3Iso14443a, "Perma lock UID changes. irreversible"},
|
{"gen3freeze", CmdHf14AGen3Freeze, IfPm3Iso14443a, "Perma lock UID changes. irreversible"},
|
||||||
{"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("magic gen4 GTU") " --------------------------"},
|
{"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("magic gen4 GTU") " --------------------------"},
|
||||||
|
{"ginfo", CmdHF14AGen4Info, IfPm3Iso14443a, "Info about configuration of the card"},
|
||||||
{"ggetblk", CmdHF14AGen4GetBlk, IfPm3Iso14443a, "Read block from card"},
|
{"ggetblk", CmdHF14AGen4GetBlk, IfPm3Iso14443a, "Read block from card"},
|
||||||
{"gload", CmdHF14AGen4Load, IfPm3Iso14443a, "Load dump to card"},
|
{"gload", CmdHF14AGen4Load, IfPm3Iso14443a, "Load dump to card"},
|
||||||
{"gsave", CmdHF14AGen4Save, IfPm3Iso14443a, "Save dump from card into file or emulator"},
|
{"gsave", CmdHF14AGen4Save, IfPm3Iso14443a, "Save dump from card into file or emulator"},
|
||||||
|
|
|
@ -70,7 +70,7 @@ static uint8_t default_pwd_pack[][4] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint64_t UL_TYPES_ARRAY[] = {
|
static uint64_t UL_TYPES_ARRAY[] = {
|
||||||
MFU_TT_UNKNOWN, MFU_TT_UL,
|
MFU_TT_UNKNOWN, MFU_TT_UL,
|
||||||
MFU_TT_UL_C, MFU_TT_UL_EV1_48,
|
MFU_TT_UL_C, MFU_TT_UL_EV1_48,
|
||||||
MFU_TT_UL_EV1_128, MFU_TT_NTAG,
|
MFU_TT_UL_EV1_128, MFU_TT_NTAG,
|
||||||
MFU_TT_NTAG_203, MFU_TT_NTAG_210,
|
MFU_TT_NTAG_203, MFU_TT_NTAG_210,
|
||||||
|
@ -79,7 +79,7 @@ static uint64_t UL_TYPES_ARRAY[] = {
|
||||||
MFU_TT_MY_D, MFU_TT_MY_D_NFC,
|
MFU_TT_MY_D, MFU_TT_MY_D_NFC,
|
||||||
MFU_TT_MY_D_MOVE, MFU_TT_MY_D_MOVE_NFC,
|
MFU_TT_MY_D_MOVE, MFU_TT_MY_D_MOVE_NFC,
|
||||||
MFU_TT_MY_D_MOVE_LEAN, MFU_TT_NTAG_I2C_1K,
|
MFU_TT_MY_D_MOVE_LEAN, MFU_TT_NTAG_I2C_1K,
|
||||||
MFU_TT_NTAG_I2C_2K, MFU_TT_NTAG_I2C_1K_PLUS,
|
MFU_TT_NTAG_I2C_2K, MFU_TT_NTAG_I2C_1K_PLUS,
|
||||||
MFU_TT_NTAG_I2C_2K_PLUS, MFU_TT_FUDAN_UL,
|
MFU_TT_NTAG_I2C_2K_PLUS, MFU_TT_FUDAN_UL,
|
||||||
MFU_TT_NTAG_213_F, MFU_TT_NTAG_216_F,
|
MFU_TT_NTAG_213_F, MFU_TT_NTAG_216_F,
|
||||||
MFU_TT_UL_EV1, MFU_TT_UL_NANO_40,
|
MFU_TT_UL_EV1, MFU_TT_UL_NANO_40,
|
||||||
|
@ -1891,7 +1891,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read signature
|
// Read signature
|
||||||
if ((tagtype & (MFU_TT_UL_EV1_48 | MFU_TT_UL_EV1_128 | MFU_TT_UL_EV1 | MFU_TT_UL_NANO_40 |
|
if ((tagtype & (MFU_TT_UL_EV1_48 | MFU_TT_UL_EV1_128 | MFU_TT_UL_EV1 | MFU_TT_UL_NANO_40 |
|
||||||
MFU_TT_NTAG_210u | MFU_TT_NTAG_213 | MFU_TT_NTAG_213_F | MFU_TT_NTAG_213_C |
|
MFU_TT_NTAG_210u | MFU_TT_NTAG_213 | MFU_TT_NTAG_213_F | MFU_TT_NTAG_213_C |
|
||||||
MFU_TT_NTAG_213_TT | MFU_TT_NTAG_215 | MFU_TT_NTAG_216 | MFU_TT_NTAG_216_F |
|
MFU_TT_NTAG_213_TT | MFU_TT_NTAG_215 | MFU_TT_NTAG_216 | MFU_TT_NTAG_216_F |
|
||||||
MFU_TT_NTAG_I2C_1K | MFU_TT_NTAG_I2C_2K | MFU_TT_NTAG_I2C_1K_PLUS | MFU_TT_NTAG_I2C_2K_PLUS))) {
|
MFU_TT_NTAG_I2C_1K | MFU_TT_NTAG_I2C_2K | MFU_TT_NTAG_I2C_1K_PLUS | MFU_TT_NTAG_I2C_2K_PLUS))) {
|
||||||
|
|
|
@ -113,12 +113,12 @@ static int CmdNfcDecode(const char *Cmd) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *tmp = dump;
|
uint8_t *tmp = dump;
|
||||||
|
|
||||||
// if not MIFARE Classic default sizes, assume its Ultralight/NTAG
|
// if not MIFARE Classic default sizes, assume its Ultralight/NTAG
|
||||||
if ( bytes_read != MIFARE_4K_MAX_BYTES
|
if ( bytes_read != MIFARE_4K_MAX_BYTES
|
||||||
&& bytes_read != MIFARE_2K_MAX_BYTES
|
&& bytes_read != MIFARE_2K_MAX_BYTES
|
||||||
&& bytes_read != MIFARE_1K_MAX_BYTES
|
&& bytes_read != MIFARE_1K_MAX_BYTES
|
||||||
&& bytes_read != MIFARE_MINI_MAX_BYTES) {
|
&& bytes_read != MIFARE_MINI_MAX_BYTES) {
|
||||||
|
|
||||||
uint8_t **pd = &tmp;
|
uint8_t **pd = &tmp;
|
||||||
|
|
|
@ -292,7 +292,7 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case jsfMfc_v2: {
|
case jsfMfc_v2: {
|
||||||
|
|
||||||
iso14a_mf_extdump_t xdump;
|
iso14a_mf_extdump_t xdump;
|
||||||
memcpy(&xdump, data, sizeof(iso14a_mf_extdump_t));
|
memcpy(&xdump, data, sizeof(iso14a_mf_extdump_t));
|
||||||
|
|
||||||
|
@ -1038,7 +1038,7 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s
|
||||||
// 256 + 2 newline chars + 1 null terminator
|
// 256 + 2 newline chars + 1 null terminator
|
||||||
char line[256 + 2 + 1];
|
char line[256 + 2 + 1];
|
||||||
memset(line, 0, sizeof(line));
|
memset(line, 0, sizeof(line));
|
||||||
|
|
||||||
udata_t udata = (udata_t)data;
|
udata_t udata = (udata_t)data;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
uint32_t counter = 0;
|
uint32_t counter = 0;
|
||||||
|
@ -1067,14 +1067,14 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s
|
||||||
// param_gethex_to_eol(line + 4, 0, udata.mfc->card_info.uid, sizeof(udata.mfc->card_info.uid), &n);
|
// param_gethex_to_eol(line + 4, 0, udata.mfc->card_info.uid, sizeof(udata.mfc->card_info.uid), &n);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str_startswith(line, "atqa:")) {
|
if (str_startswith(line, "atqa:")) {
|
||||||
if (ft == NFC_DF_MFC) {
|
if (ft == NFC_DF_MFC) {
|
||||||
// param_gethex_to_eol(line + 5, 0, udata.mfc->card_info.atqa, sizeof(udata.mfc->card_info.atqa), &n);
|
// param_gethex_to_eol(line + 5, 0, udata.mfc->card_info.atqa, sizeof(udata.mfc->card_info.atqa), &n);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str_startswith(line, "sak:")) {
|
if (str_startswith(line, "sak:")) {
|
||||||
if (ft == NFC_DF_MFC) {
|
if (ft == NFC_DF_MFC) {
|
||||||
|
@ -1083,7 +1083,7 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s
|
||||||
// udata.mfc->card_info.sak = sak & 0xFF;
|
// udata.mfc->card_info.sak = sak & 0xFF;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str_startswith(line, "signature:")) {
|
if (str_startswith(line, "signature:")) {
|
||||||
if (ft == NFC_DF_MFC) {
|
if (ft == NFC_DF_MFC) {
|
||||||
|
@ -1091,7 +1091,7 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s
|
||||||
param_gethex_to_eol(line + 11, 0, udata.mfu->signature, sizeof(udata.mfu->signature), &n);
|
param_gethex_to_eol(line + 11, 0, udata.mfu->signature, sizeof(udata.mfu->signature), &n);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str_startswith(line, "mifare version:")) {
|
if (str_startswith(line, "mifare version:")) {
|
||||||
if (ft == NFC_DF_MFC) {
|
if (ft == NFC_DF_MFC) {
|
||||||
|
@ -1099,7 +1099,7 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s
|
||||||
param_gethex_to_eol(line + 16, 0, udata.mfu->version, sizeof(udata.mfu->version), &n);
|
param_gethex_to_eol(line + 16, 0, udata.mfu->version, sizeof(udata.mfu->version), &n);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str_startswith(line, "counter 0:")) {
|
if (str_startswith(line, "counter 0:")) {
|
||||||
int no = 0;
|
int no = 0;
|
||||||
|
@ -1111,7 +1111,7 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s
|
||||||
udata.mfu->counter_tearing[0][2] = no & 0xFF;
|
udata.mfu->counter_tearing[0][2] = no & 0xFF;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str_startswith(line, "tearing 0:")) {
|
if (str_startswith(line, "tearing 0:")) {
|
||||||
if (ft == NFC_DF_MFC) {
|
if (ft == NFC_DF_MFC) {
|
||||||
|
@ -1121,7 +1121,7 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s
|
||||||
udata.mfu->counter_tearing[0][3] = b & 0xFF;
|
udata.mfu->counter_tearing[0][3] = b & 0xFF;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str_startswith(line, "counter 1:")) {
|
if (str_startswith(line, "counter 1:")) {
|
||||||
int no = 0;
|
int no = 0;
|
||||||
|
@ -1133,7 +1133,7 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s
|
||||||
udata.mfu->counter_tearing[1][2] = no & 0xFF;
|
udata.mfu->counter_tearing[1][2] = no & 0xFF;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str_startswith(line, "tearing 1:")) {
|
if (str_startswith(line, "tearing 1:")) {
|
||||||
if (ft == NFC_DF_MFC) {
|
if (ft == NFC_DF_MFC) {
|
||||||
|
@ -1155,7 +1155,7 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s
|
||||||
udata.mfu->counter_tearing[2][2] = no & 0xFF;
|
udata.mfu->counter_tearing[2][2] = no & 0xFF;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str_startswith(line, "tearing 2:")) {
|
if (str_startswith(line, "tearing 2:")) {
|
||||||
if (ft == NFC_DF_MFC) {
|
if (ft == NFC_DF_MFC) {
|
||||||
|
@ -1174,7 +1174,7 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s
|
||||||
udata.mfu->pages = n;
|
udata.mfu->pages = n;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Page 0: 04 10 56 CA
|
// Page 0: 04 10 56 CA
|
||||||
if (str_startswith(line, "page ")) {
|
if (str_startswith(line, "page ")) {
|
||||||
|
@ -2317,7 +2317,7 @@ nfc_df_e detect_nfc_dump_format(const char *preferredName, bool verbose) {
|
||||||
break;
|
break;
|
||||||
case NFC_DF_PICOPASS:
|
case NFC_DF_PICOPASS:
|
||||||
PrintAndLogEx(INFO, "detected PICOPASS based dump format");
|
PrintAndLogEx(INFO, "detected PICOPASS based dump format");
|
||||||
break;
|
break;
|
||||||
case NFC_DF_UNKNOWN:
|
case NFC_DF_UNKNOWN:
|
||||||
PrintAndLogEx(WARNING, "failed to detected dump format");
|
PrintAndLogEx(WARNING, "failed to detected dump format");
|
||||||
break;
|
break;
|
||||||
|
|
37
client/src/mifare/gen4.h
Normal file
37
client/src/mifare/gen4.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// See LICENSE.txt for the text of the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// High frequency ISO14443A commands
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifndef __GEN4_H
|
||||||
|
#define __GEN4_H
|
||||||
|
|
||||||
|
#define GEN4_CMD_CONFIG_GTU 0x32
|
||||||
|
#define GEN4_CMD_CONFIG_ATS 0x34
|
||||||
|
#define GEN4_CMD_CONFIG_ATQA_SAK 0x35
|
||||||
|
#define GEN4_CMD_CONFIG_UID_LEN 0x68
|
||||||
|
#define GEN4_CMD_CONFIG_UL_ENABLE 0x69
|
||||||
|
#define GEN4_CMD_CONFIG_UL_MODE 0x6A
|
||||||
|
#define GEN4_CMD_CONFIG_UL_SECTOR_COUNT 0x6A
|
||||||
|
#define GEN4_CMD_DUMP_CONFIG 0xC6
|
||||||
|
#define GEN4_CMD_FACTORY_TEST 0xCC
|
||||||
|
#define GEN4_CMD_WRITE_BLOCK 0xCD
|
||||||
|
#define GEN4_CMD_READ_BLOCK 0xCE
|
||||||
|
#define GEN4_CMD_BL0_DIRECT_WRITE_EN 0xCF
|
||||||
|
#define GEN4_CMD_SET_CONFIG 0xF0
|
||||||
|
#define GEN4_CMD_SET_CONFIG_PERMANENT 0xF1
|
||||||
|
#define GEN4_CMD_CHANGE_PASSWORD 0xFE
|
||||||
|
|
||||||
|
#endif
|
|
@ -40,6 +40,8 @@
|
||||||
#include "crypto/libpcrypto.h"
|
#include "crypto/libpcrypto.h"
|
||||||
#include "util.h" // xor
|
#include "util.h" // xor
|
||||||
#include "mbedtls/sha1.h" // SHA1
|
#include "mbedtls/sha1.h" // SHA1
|
||||||
|
#include "cmdhf14a.h"
|
||||||
|
#include "gen4.h"
|
||||||
|
|
||||||
int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
||||||
uint32_t uid = 0;
|
uint32_t uid = 0;
|
||||||
|
@ -1173,6 +1175,118 @@ int mfGen3Freeze(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mfG4ExCommand(uint8_t cmd, uint8_t *pwd, uint8_t *data, size_t datalen, uint8_t *response, size_t *responselen, bool verbose) {
|
||||||
|
struct p {
|
||||||
|
uint8_t cmdheader;
|
||||||
|
uint8_t pwd[4];
|
||||||
|
uint8_t command;
|
||||||
|
uint8_t data[32];
|
||||||
|
} PACKED payload;
|
||||||
|
memset(&payload, 0, sizeof(payload));
|
||||||
|
|
||||||
|
if (datalen > sizeof(payload.data)) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.cmdheader = 0xCF;
|
||||||
|
payload.command = cmd;
|
||||||
|
if (pwd != NULL) {
|
||||||
|
memcpy(payload.pwd, pwd, sizeof(payload.pwd));
|
||||||
|
}
|
||||||
|
if (data != NULL && datalen > 0) {
|
||||||
|
memcpy(payload.data, data, datalen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int resplen = 0;
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_RAW | ISO14A_NO_RATS | ISO14A_APPEND_CRC, 6 + datalen, 0, (uint8_t *)&payload, 6 + datalen);
|
||||||
|
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
|
if (resp.oldarg[0] != 2) {
|
||||||
|
if (verbose) PrintAndLogEx(ERR, "No card in the field.");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
iso14a_card_select_t card;
|
||||||
|
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
|
||||||
|
if (verbose) {
|
||||||
|
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
||||||
|
PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
|
||||||
|
PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (verbose) PrintAndLogEx(ERR, "No card in the field.");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
|
resplen = resp.oldarg[0];
|
||||||
|
|
||||||
|
if (!resplen) {
|
||||||
|
if (verbose) PrintAndLogEx(ERR, "No card response.");
|
||||||
|
return PM3_EFAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
resplen = resplen - 2; // 14A CRC
|
||||||
|
if (resplen < 0)
|
||||||
|
resplen = 0;
|
||||||
|
|
||||||
|
if (resplen > 40) {
|
||||||
|
if (verbose) PrintAndLogEx(ERR, "Buffer too small(%d).", resplen);
|
||||||
|
return PM3_EOVFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response != NULL)
|
||||||
|
memcpy(response, resp.data.asBytes, resplen);
|
||||||
|
|
||||||
|
if (responselen != NULL)
|
||||||
|
*responselen = resplen;
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
} else {
|
||||||
|
if (verbose) PrintAndLogEx(ERR, "Reply timeout.");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose) {
|
||||||
|
uint8_t resp[40] = {0};
|
||||||
|
size_t resplen = 0;
|
||||||
|
|
||||||
|
int res = mfG4ExCommand(GEN4_CMD_DUMP_CONFIG, pwd, NULL, 0, resp, &resplen, verbose);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data != NULL)
|
||||||
|
memcpy(data, resp, resplen);
|
||||||
|
|
||||||
|
if (datalen != NULL)
|
||||||
|
*datalen = resplen;
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose) {
|
||||||
|
uint8_t resp[40] = {0};
|
||||||
|
size_t resplen = 0;
|
||||||
|
|
||||||
|
int res = mfG4ExCommand(GEN4_CMD_FACTORY_TEST, pwd, NULL, 0, resp, &resplen, verbose);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data != NULL)
|
||||||
|
memcpy(data, resp, resplen);
|
||||||
|
|
||||||
|
if (datalen != NULL)
|
||||||
|
*datalen = resplen;
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags) {
|
int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags) {
|
||||||
struct p {
|
struct p {
|
||||||
uint8_t blockno;
|
uint8_t blockno;
|
||||||
|
|
|
@ -96,6 +96,9 @@ int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid);
|
||||||
int mfGen3Block(uint8_t *block, int blockLen, uint8_t *newBlock);
|
int mfGen3Block(uint8_t *block, int blockLen, uint8_t *newBlock);
|
||||||
int mfGen3Freeze(void);
|
int mfGen3Freeze(void);
|
||||||
|
|
||||||
|
int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose);
|
||||||
|
int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose);
|
||||||
|
|
||||||
int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags);
|
int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags);
|
||||||
int mfG4SetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags);
|
int mfG4SetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags);
|
||||||
|
|
||||||
|
|
|
@ -366,6 +366,7 @@ const static vocabulary_t vocabulary[] = {
|
||||||
{ 0, "hf mf gen3uid" },
|
{ 0, "hf mf gen3uid" },
|
||||||
{ 0, "hf mf gen3blk" },
|
{ 0, "hf mf gen3blk" },
|
||||||
{ 0, "hf mf gen3freeze" },
|
{ 0, "hf mf gen3freeze" },
|
||||||
|
{ 0, "hf mf ginfo" },
|
||||||
{ 0, "hf mf ggetblk" },
|
{ 0, "hf mf ggetblk" },
|
||||||
{ 0, "hf mf gload" },
|
{ 0, "hf mf gload" },
|
||||||
{ 0, "hf mf gsave" },
|
{ 0, "hf mf gsave" },
|
||||||
|
|
|
@ -279,6 +279,7 @@
|
||||||
"command": "data bmap",
|
"command": "data bmap",
|
||||||
"description": "Breaks down a hex value to binary according a template data bmap -d 16 -m 4,4 This will give two rows each with four bits",
|
"description": "Breaks down a hex value to binary according a template data bmap -d 16 -m 4,4 This will give two rows each with four bits",
|
||||||
"notes": [
|
"notes": [
|
||||||
|
"data bmap -d 3B",
|
||||||
"data bmap -d 3B -m 2,5,1"
|
"data bmap -d 3B -m 2,5,1"
|
||||||
],
|
],
|
||||||
"offline": true,
|
"offline": true,
|
||||||
|
@ -3026,10 +3027,10 @@
|
||||||
},
|
},
|
||||||
"hf iclass configcard": {
|
"hf iclass configcard": {
|
||||||
"command": "hf iclass configcard",
|
"command": "hf iclass configcard",
|
||||||
"description": "Manage reader configuration card via Cardhelper, The generated config card will be uploaded to device emulator memory. You can start simulating `hf iclass sim -t 3` or use the emul commands",
|
"description": "Manage reader configuration card via Cardhelper or internal database, The generated config card will be uploaded to device emulator memory. You can start simulating `hf iclass sim -t 3` or use the emul commands",
|
||||||
"notes": [
|
"notes": [
|
||||||
"hf iclass configcard -l -> download config card settings",
|
"hf iclass configcard -l -> download config card settings from cardhelper",
|
||||||
"hf iclass configcard -p -> print all config cards",
|
"hf iclass configcard -p -> print all config cards in the database",
|
||||||
"hf iclass configcard --ci 1 -> view config card setting in slot 1",
|
"hf iclass configcard --ci 1 -> view config card setting in slot 1",
|
||||||
"hf iclass configcard -g --ci 0 -> generate config file from slot 0"
|
"hf iclass configcard -g --ci 0 -> generate config file from slot 0"
|
||||||
],
|
],
|
||||||
|
@ -4553,6 +4554,21 @@
|
||||||
],
|
],
|
||||||
"usage": "hf mf ggetblk [-hv] -b <dec> [-p <hex>]"
|
"usage": "hf mf ggetblk [-hv] -b <dec> [-p <hex>]"
|
||||||
},
|
},
|
||||||
|
"hf mf ginfo": {
|
||||||
|
"command": "hf mf ginfo",
|
||||||
|
"description": "Read info about magic gen4 GTU card.",
|
||||||
|
"notes": [
|
||||||
|
"hf mf ginfo -> get info with default password 00000000",
|
||||||
|
"hf mf ginfo --pwd 01020304 -> get info with password"
|
||||||
|
],
|
||||||
|
"offline": false,
|
||||||
|
"options": [
|
||||||
|
"-h, --help This help",
|
||||||
|
"-v, --verbose verbose output",
|
||||||
|
"-p, --pwd <hex> password 4bytes"
|
||||||
|
],
|
||||||
|
"usage": "hf mf ginfo [-hv] [-p <hex>]"
|
||||||
|
},
|
||||||
"hf mf gload": {
|
"hf mf gload": {
|
||||||
"command": "hf mf gload",
|
"command": "hf mf gload",
|
||||||
"description": "Load magic gen4 gtu card with data from (bin/eml/json) dump file or from emulator memory.",
|
"description": "Load magic gen4 gtu card with data from (bin/eml/json) dump file or from emulator memory.",
|
||||||
|
@ -8939,7 +8955,7 @@
|
||||||
"-1, --ht1 Card type Hitag 1",
|
"-1, --ht1 Card type Hitag 1",
|
||||||
"-2, --ht2 Card type Hitag 2",
|
"-2, --ht2 Card type Hitag 2",
|
||||||
"-s, --hts Card type Hitag S",
|
"-s, --hts Card type Hitag S",
|
||||||
"-m, --htm Card type Hitag \u03bc"
|
"-m, --htm Card type Hitag \u041e\u0458"
|
||||||
],
|
],
|
||||||
"usage": "lf hitag eload [-h12sm] -f <fn>"
|
"usage": "lf hitag eload [-h12sm] -f <fn>"
|
||||||
},
|
},
|
||||||
|
@ -12015,8 +12031,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"commands_extracted": 696,
|
"commands_extracted": 697,
|
||||||
"extracted_by": "PM3Help2JSON v1.00",
|
"extracted_by": "PM3Help2JSON v1.00",
|
||||||
"extracted_on": "2023-10-30T12:11:34"
|
"extracted_on": "2023-11-05T22:22:55"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -529,6 +529,7 @@ Check column "offline" for their availability.
|
||||||
|`hf mf gen3uid `|N |`Set UID without changing manufacturer block`
|
|`hf mf gen3uid `|N |`Set UID without changing manufacturer block`
|
||||||
|`hf mf gen3blk `|N |`Overwrite manufacturer block`
|
|`hf mf gen3blk `|N |`Overwrite manufacturer block`
|
||||||
|`hf mf gen3freeze `|N |`Perma lock UID changes. irreversible`
|
|`hf mf gen3freeze `|N |`Perma lock UID changes. irreversible`
|
||||||
|
|`hf mf ginfo `|N |`Info about configuration of the card`
|
||||||
|`hf mf ggetblk `|N |`Read block from card`
|
|`hf mf ggetblk `|N |`Read block from card`
|
||||||
|`hf mf gload `|N |`Load dump to card`
|
|`hf mf gload `|N |`Load dump to card`
|
||||||
|`hf mf gsave `|N |`Save dump from card into file or emulator`
|
|`hf mf gsave `|N |`Save dump from card into file or emulator`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue