mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 13:23:51 -07:00
added "hf mf gview" to view contents of a magic gen3 gtu card
This commit is contained in:
parent
40f08108f0
commit
c522de5b79
8 changed files with 180 additions and 1 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 gview` - view contents of a magic Gen3 GTU (@iceman1001)
|
||||||
- Added Standalone mode for nexwatch ID credentials (@Guilhem7, @MaximeBosca)
|
- Added Standalone mode for nexwatch ID credentials (@Guilhem7, @MaximeBosca)
|
||||||
- Fix `lf em 4x50/4x70 *` reverted a missunderstanding in byte order macros (@iceman1001)
|
- Fix `lf em 4x50/4x70 *` reverted a missunderstanding in byte order macros (@iceman1001)
|
||||||
- Added more keys (@equipter)
|
- Added more keys (@equipter)
|
||||||
|
|
|
@ -1568,6 +1568,14 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
MifareGen3Freez();
|
MifareGen3Freez();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CMD_HF_MIFARE_G3_RDBL: {
|
||||||
|
struct p {
|
||||||
|
uint8_t blockno;
|
||||||
|
} PACKED;
|
||||||
|
struct p *payload = (struct p *) packet->data.asBytes;
|
||||||
|
MifareG3ReadBlk(payload->blockno);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CMD_HF_MIFARE_PERSONALIZE_UID: {
|
case CMD_HF_MIFARE_PERSONALIZE_UID: {
|
||||||
struct p {
|
struct p {
|
||||||
uint8_t keytype;
|
uint8_t keytype;
|
||||||
|
|
|
@ -2594,6 +2594,42 @@ OUT:
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MifareG3ReadBlk(uint8_t blockno) {
|
||||||
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
clear_trace();
|
||||||
|
set_tracing(true);
|
||||||
|
|
||||||
|
int retval = PM3_SUCCESS;
|
||||||
|
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||||
|
uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE);
|
||||||
|
uint8_t *uid = BigBuf_malloc(10);
|
||||||
|
if (iso14443a_select_card(uid, NULL, NULL, true, 0, true) == false) {
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
LED_B_ON();
|
||||||
|
uint32_t save_iso14a_timeout = iso14a_get_timeout();
|
||||||
|
iso14a_set_timeout(13560000 / 1000 / (8 * 16) * 1000); // 2 seconds timeout
|
||||||
|
|
||||||
|
uint8_t cmd[] = { 0xCF, 0x00, 0x00, 0x00, 0x00, 0xCE, blockno, 0x00, 0x00};
|
||||||
|
AddCrc14A(cmd, sizeof(cmd) - 2);
|
||||||
|
|
||||||
|
ReaderTransmit(cmd, sizeof(cmd), NULL);
|
||||||
|
int res = ReaderReceive(buf, par);
|
||||||
|
if (res != 18) {
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
}
|
||||||
|
iso14a_set_timeout(save_iso14a_timeout);
|
||||||
|
LED_B_OFF();
|
||||||
|
|
||||||
|
OUT:
|
||||||
|
reply_ng(CMD_HF_MIFARE_G3_RDBL, retval, buf, 18);
|
||||||
|
// turns off
|
||||||
|
OnSuccessMagic();
|
||||||
|
BigBuf_free();
|
||||||
|
}
|
||||||
|
|
||||||
void MifareSetMod(uint8_t *datain) {
|
void MifareSetMod(uint8_t *datain) {
|
||||||
|
|
||||||
uint8_t mod = datain[0];
|
uint8_t mod = datain[0];
|
||||||
|
|
|
@ -49,6 +49,9 @@ void MifareGen3UID(uint8_t uidlen, uint8_t *uid); // Gen 3 magic card set UID wi
|
||||||
void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overwrite manufacturer block
|
void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overwrite manufacturer block
|
||||||
void MifareGen3Freez(void); // Gen 3 magic card lock further UID changes
|
void MifareGen3Freez(void); // Gen 3 magic card lock further UID changes
|
||||||
|
|
||||||
|
// MFC GEN3 GTU
|
||||||
|
void MifareG3ReadBlk(uint8_t blockno);
|
||||||
|
|
||||||
void MifareSetMod(uint8_t *datain);
|
void MifareSetMod(uint8_t *datain);
|
||||||
void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key);
|
void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key);
|
||||||
|
|
||||||
|
|
|
@ -6007,6 +6007,110 @@ static int CmdHF14AMfView(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CmdHF14AGen3View(const char *Cmd) {
|
||||||
|
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf mf gview",
|
||||||
|
"View `magic gen3 gtu` card memory",
|
||||||
|
"hf mf gview\n"
|
||||||
|
"hf mf gview --4k"
|
||||||
|
);
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
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"),
|
||||||
|
arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
bool m0 = arg_get_lit(ctx, 1);
|
||||||
|
bool m1 = arg_get_lit(ctx, 2);
|
||||||
|
bool m2 = arg_get_lit(ctx, 3);
|
||||||
|
bool m4 = arg_get_lit(ctx, 4);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
// validations
|
||||||
|
if ((m0 + m1 + m2 + m4) > 1) {
|
||||||
|
PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
} else if ((m0 + m1 + m2 + m4) == 0) {
|
||||||
|
m1 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char s[6];
|
||||||
|
memset(s, 0, sizeof(s));
|
||||||
|
uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
|
||||||
|
if (m0) {
|
||||||
|
block_cnt = MIFARE_MINI_MAXBLOCK;
|
||||||
|
strncpy(s, "Mini", 5);
|
||||||
|
} else if (m1) {
|
||||||
|
block_cnt = MIFARE_1K_MAXBLOCK;
|
||||||
|
strncpy(s, "1K", 3);
|
||||||
|
} else if (m2) {
|
||||||
|
block_cnt = MIFARE_2K_MAXBLOCK;
|
||||||
|
strncpy(s, "2K", 3);
|
||||||
|
} else if (m4) {
|
||||||
|
block_cnt = MIFARE_4K_MAXBLOCK;
|
||||||
|
strncpy(s, "4K", 3);
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
PrintAndLogEx(SUCCESS, "View magic gen3 GTU MIFARE Classic " _GREEN_("%s"), s);
|
||||||
|
PrintAndLogEx(INFO, "." NOLF);
|
||||||
|
|
||||||
|
// Select card to get UID/UIDLEN information
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
|
||||||
|
PrintAndLogEx(WARNING, "iso14443a card select timeout");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
0: couldn't read
|
||||||
|
1: OK, with ATS
|
||||||
|
2: OK, no ATS
|
||||||
|
3: proprietary Anticollision
|
||||||
|
*/
|
||||||
|
uint64_t select_status = resp.oldarg[0];
|
||||||
|
|
||||||
|
if (select_status == 0) {
|
||||||
|
PrintAndLogEx(WARNING, "iso14443a card select failed");
|
||||||
|
return select_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
iso14a_card_select_t card;
|
||||||
|
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
|
||||||
|
|
||||||
|
// reserve memory
|
||||||
|
uint16_t bytes = block_cnt * MFBLOCK_SIZE;
|
||||||
|
uint8_t *dump = calloc(bytes, sizeof(uint8_t));
|
||||||
|
if (dump == NULL) {
|
||||||
|
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||||
|
return PM3_EMALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < block_cnt; i++) {
|
||||||
|
|
||||||
|
if (mfG3GetBlock(i, dump + (i * MFBLOCK_SIZE)) != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(WARNING, "Can't get magic card block: %u", i);
|
||||||
|
PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position");
|
||||||
|
free(dump);
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
mf_print_blocks(block_cnt, dump);
|
||||||
|
free(dump);
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"},
|
{"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"},
|
||||||
|
@ -6059,7 +6163,8 @@ static command_t CommandTable[] = {
|
||||||
{"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without changing manufacturer block"},
|
{"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without changing manufacturer block"},
|
||||||
{"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 gen3 GTU") " -----------------------"},
|
||||||
|
{"gview", CmdHF14AGen3View, IfPm3Iso14443a, "View card"},
|
||||||
// {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("i") " -----------------------"},
|
// {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("i") " -----------------------"},
|
||||||
// {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"},
|
// {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
|
|
|
@ -1050,6 +1050,27 @@ int mfGen3Freeze(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mfG3GetBlock(uint8_t blockno, uint8_t *data) {
|
||||||
|
struct p {
|
||||||
|
uint8_t blockno;
|
||||||
|
} PACKED payload;
|
||||||
|
payload.blockno = blockno;
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_HF_MIFARE_G3_RDBL, (uint8_t*)&payload, sizeof(payload));
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_MIFARE_G3_RDBL, &resp, 1500)) {
|
||||||
|
if (resp.status != PM3_SUCCESS)
|
||||||
|
return PM3_EUNDEF;
|
||||||
|
memcpy(data, resp.data.asBytes, 16);
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(WARNING, "command execute timeout");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
uint32_t cuid = 0; // uid part used for crypto1.
|
uint32_t cuid = 0; // uid part used for crypto1.
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,8 @@ 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 mfG3GetBlock(uint8_t blockno, uint8_t *data);
|
||||||
|
|
||||||
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);
|
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);
|
||||||
|
|
||||||
int detect_classic_prng(void);
|
int detect_classic_prng(void);
|
||||||
|
|
|
@ -740,6 +740,9 @@ typedef struct {
|
||||||
#define CMD_HF_MIFARE_GEN3BLK 0x0851
|
#define CMD_HF_MIFARE_GEN3BLK 0x0851
|
||||||
#define CMD_HF_MIFARE_GEN3FREEZ 0x0852
|
#define CMD_HF_MIFARE_GEN3FREEZ 0x0852
|
||||||
|
|
||||||
|
// Gen 3 GTU magic cards
|
||||||
|
#define CMD_HF_MIFARE_G3_RDBL 0x0860
|
||||||
|
|
||||||
#define CMD_UNKNOWN 0xFFFF
|
#define CMD_UNKNOWN 0xFFFF
|
||||||
|
|
||||||
//Mifare simulation flags
|
//Mifare simulation flags
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue