From c522de5b79dfb6f6eb64a72054d80a05af26db93 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 24 Jun 2021 14:59:33 +0200 Subject: [PATCH] added "hf mf gview" to view contents of a magic gen3 gtu card --- CHANGELOG.md | 1 + armsrc/appmain.c | 8 +++ armsrc/mifarecmd.c | 36 +++++++++++ armsrc/mifarecmd.h | 3 + client/src/cmdhfmf.c | 107 ++++++++++++++++++++++++++++++++- client/src/mifare/mifarehost.c | 21 +++++++ client/src/mifare/mifarehost.h | 2 + include/pm3_cmd.h | 3 + 8 files changed, 180 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fddd51abe..c5cb2eba4 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 `hf mf gview` - view contents of a magic Gen3 GTU (@iceman1001) - Added Standalone mode for nexwatch ID credentials (@Guilhem7, @MaximeBosca) - Fix `lf em 4x50/4x70 *` reverted a missunderstanding in byte order macros (@iceman1001) - Added more keys (@equipter) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index af5c01c72..cfa77249f 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1568,6 +1568,14 @@ static void PacketReceived(PacketCommandNG *packet) { MifareGen3Freez(); 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: { struct p { uint8_t keytype; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 4330f2c4f..2a8642f82 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2594,6 +2594,42 @@ OUT: 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) { uint8_t mod = datain[0]; diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index baf3d9e31..bacb8405e 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -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 MifareGen3Freez(void); // Gen 3 magic card lock further UID changes +// MFC GEN3 GTU +void MifareG3ReadBlk(uint8_t blockno); + void MifareSetMod(uint8_t *datain); void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index b08de964c..bcb9c52c2 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -6007,6 +6007,110 @@ static int CmdHF14AMfView(const char *Cmd) { 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[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"}, @@ -6059,7 +6163,8 @@ static command_t CommandTable[] = { {"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without changing manufacturer block"}, {"gen3blk", CmdHf14AGen3Block, IfPm3Iso14443a, "Overwrite manufacturer block"}, {"gen3freeze", CmdHf14AGen3Freeze, IfPm3Iso14443a, "Perma lock UID changes. irreversible"}, - + {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen3 GTU") " -----------------------"}, + {"gview", CmdHF14AGen3View, IfPm3Iso14443a, "View card"}, // {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("i") " -----------------------"}, // {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"}, {NULL, NULL, NULL, NULL} diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index 9b0c20d36..cf46fc05f 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -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 uint32_t cuid = 0; // uid part used for crypto1. diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index 49adc8cbe..8f5f215fd 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -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 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 detect_classic_prng(void); diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 4e89e4f86..53343c5e1 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -740,6 +740,9 @@ typedef struct { #define CMD_HF_MIFARE_GEN3BLK 0x0851 #define CMD_HF_MIFARE_GEN3FREEZ 0x0852 +// Gen 3 GTU magic cards +#define CMD_HF_MIFARE_G3_RDBL 0x0860 + #define CMD_UNKNOWN 0xFFFF //Mifare simulation flags