From 7b93de7a81c6049eb34886abf520cbe0e38f151f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 25 Mar 2023 15:00:58 +0100 Subject: [PATCH] added GDM read configuration block --- CHANGELOG.md | 1 + armsrc/appmain.c | 11 +++++- armsrc/mifarecmd.c | 59 ++++++++++++++++++++++++++++++++ armsrc/mifarecmd.h | 1 + armsrc/mifareutil.h | 3 ++ client/src/cmdhfmf.c | 80 +++++++++++++++++++++++++++++++++++++++++++- include/protocols.h | 1 + 7 files changed, 154 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9e28fad3..f6e9c9811 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 gdmgetblk` - Support Gen4 GDM read configuration block (@iceman1001) - Changed magic note to include a section about GDM tags (@iceman1001) - Added `hf mf gdmsetblk` - Support Gen4 GDM write block (@iceman1001) - Changed `hf 14a info` - detect Gen GDM magic tags (@iceman1001) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index d435f9967..c90640828 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1735,7 +1735,16 @@ static void PacketReceived(PacketCommandNG *packet) { MifareG4WriteBlk(payload->blockno, payload->pwd, payload->data, payload->workFlags); break; } - + case CMD_HF_MIFARE_G4_GDM_RDBL: { + struct p { + uint8_t blockno; + uint8_t keytype; + uint8_t key[6]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + MifareReadBlockGDM(payload->blockno, payload->keytype, payload->key); + break; + } case CMD_HF_MIFARE_G4_GDM_WRBL: { struct p { uint8_t blockno; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index aaf1d795a..0bcb4fd74 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -214,6 +214,65 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { LEDsoff(); } +void MifareReadBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key) { + + int retval = PM3_SUCCESS; + + uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE); + if (par == NULL) { + retval = PM3_EMALLOC; + goto OUT; + } + + uint8_t *uid = BigBuf_malloc(10); + if (uid == NULL) { + retval = PM3_EMALLOC; + goto OUT; + } + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + clear_trace(); + set_tracing(true); + + // variables + uint32_t cuid = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + uint64_t ui64key = bytes_to_num(key, 6); + uint8_t outbuf[16] = {0x00}; + + if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) { + retval = PM3_ESOFT; + goto OUT; + } + + if (mifare_classic_authex_2(pcs, cuid, blockno, keytype, ui64key, AUTH_FIRST, NULL, NULL, true)) { + retval = PM3_ESOFT; + goto OUT; + }; + + if (mifare_classic_readblock_ex(pcs, cuid, blockno, outbuf, true)) { + retval = PM3_ESOFT; + goto OUT; + }; + + if (mifare_classic_halt(pcs, cuid)) { + retval = PM3_ESOFT; + goto OUT; + }; + +OUT: + crypto1_deinit(pcs); + + reply_ng(CMD_HF_MIFARE_G4_GDM_RDBL, retval, outbuf, sizeof(outbuf)); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); + BigBuf_free(); +} + //----------------------------------------------------------------------------- // Select, Authenticate, Read a MIFARE tag. // read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes) diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index f471ccecc..062c02367 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -59,6 +59,7 @@ void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overw void MifareGen3Freez(void); // Gen 3 magic card lock further UID changes // MFC GEN4 GDM +void MifareReadBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key); void MifareWriteBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key, uint8_t *datain); // MFC GEN4 GTU diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index c7c6b4a94..37b1b1294 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -73,7 +73,10 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing); int mifare_classic_authex_2(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing, bool is_gdm); + int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); +int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, bool is_gdm); + int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); int mifare_classic_halt_ex(struct Crypto1State *pcs); int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 900f201d2..a0a2c6961 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -7560,6 +7560,78 @@ static int CmdHF14AGen4Save(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14AGen4_GDM_GetBlk(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf gdmgetblk", + "Get block data from magic gen4 GDM card.", + "hf mf gdmgetblk --blk 0 --> get block 0 (manufacturer)\n" + "hf mf gdmgetblk --blk 3 -v --> get block 3, decode sector trailer\n" + ); + void *argtable[] = { + arg_param_begin, + arg_int1("b", "blk", "", "block number"), + arg_lit0("v", "verbose", "verbose output"), + arg_str0("k", "key", "", "key 6 bytes"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int b = arg_get_int_def(ctx, 1, 0); + bool verbose = arg_get_lit(ctx, 2); + + int keylen = 0; + uint8_t key[6] = {0}; + CLIGetHexWithReturn(ctx, 3, key, &keylen); + CLIParserFree(ctx); + + // validate args + if (b < 0 || b >= MIFARE_4K_MAXBLOCK) { + PrintAndLogEx(FAILED, "target block number out-of-range, got %i", b); + return PM3_EINVARG; + } + + if (keylen != 6 && keylen != 0) { + PrintAndLogEx(FAILED, "Must specify 6 bytes, got " _YELLOW_("%u"), keylen); + return PM3_EINVARG; + } + + uint8_t blockno = (uint8_t)b; + PrintAndLogEx(NORMAL, "Block: %x", blockno) ; + + struct p { + uint8_t blockno; + uint8_t keytype; + uint8_t key[6]; + } PACKED payload; + + payload.blockno = blockno; + payload.keytype = 0; + memcpy(payload.key, key, sizeof(payload.key)); + + clearCommandBuffer(); + SendCommandNG(CMD_HF_MIFARE_G4_GDM_RDBL, (uint8_t *)&payload, sizeof(payload)); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_GDM_RDBL, &resp, 1500) == false) { + PrintAndLogEx(WARNING, "command execute timeout"); + return PM3_ETIMEOUT; + } + + if (resp.status == PM3_SUCCESS) { + uint8_t sector = mfSectorNum(blockno); + mf_print_sector_hdr(sector); + + uint8_t *d = resp.data.asBytes; + mf_print_block_one(blockno, d, verbose); + + if (verbose) { + decode_print_st(blockno, d); + } else { + PrintAndLogEx(NORMAL, ""); + } + } + + return resp.status; +} + static int CmdHF14AGen4_GDM_SetBlk(const char *Cmd) { CLIParserContext *ctx; @@ -7599,7 +7671,7 @@ static int CmdHF14AGen4_GDM_SetBlk(const char *Cmd) { CLIParserFree(ctx); if (blen != MFBLOCK_SIZE) { - PrintAndLogEx(WARNING, "expected 16 HEX bytes. got %i", blen); + PrintAndLogEx(WARNING, "expected %u HEX bytes. got %i", MFBLOCK_SIZE, blen); return PM3_EINVARG; } @@ -7608,6 +7680,11 @@ static int CmdHF14AGen4_GDM_SetBlk(const char *Cmd) { return PM3_EINVARG; } + if (keylen != 6 && keylen != 0) { + PrintAndLogEx(FAILED, "Must specify 6 bytes, got " _YELLOW_("%u"), keylen); + return PM3_EINVARG; + } + uint8_t blockno = (uint8_t)b; PrintAndLogEx(INFO, "Writing block no %d, key %c - %s", blockno, (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key))); @@ -7908,6 +7985,7 @@ static command_t CommandTable[] = { {"gsetblk", CmdHF14AGen4SetBlk, IfPm3Iso14443a, "Write block to card"}, {"gview", CmdHF14AGen4View, IfPm3Iso14443a, "View card"}, {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("magic gen4 GDM") " --------------------------"}, + {"gdmgetblk", CmdHF14AGen4_GDM_GetBlk, IfPm3Iso14443a, "Read block from card"}, {"gdmsetblk", CmdHF14AGen4_GDM_SetBlk, IfPm3Iso14443a, "Write block to card"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("ndef") " -----------------------"}, // {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"}, diff --git a/include/protocols.h b/include/protocols.h index 333dcdb71..8450dc58a 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -193,6 +193,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define MIFARE_MAGIC_GDM_AUTH_KEYA 0x80 #define MIFARE_MAGIC_GDM_AUTH_KEYB 0x81 #define MIFARE_MAGIC_GDM_WRITEBLOCK 0xA8 +#define MIFARE_MAGIC_GDM_READBLOCK 0xE0 #define MIFARE_EV1_PERSONAL_UID 0x40 #define MIFARE_EV1_SETMODE 0x43