From 282d22c3cc753c23fdc89393cd314aadfb5eb979 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 5 Nov 2023 21:11:55 +0200 Subject: [PATCH 01/13] add ginfo comamnd --- client/src/cmdhfmf.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index da94e1205..16d56c7dd 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -7431,6 +7431,35 @@ static int CmdHF14AMfView(const char *Cmd) { } free(dump); + 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", "", "password 4bytes"), + arg_param_end + }; + CLIExecWithReturn(ctx, cmd, argtable, false); + //bool verbose = arg_get_lit(ctx, 1); + + int pwd_len = 0; + uint8_t pwd[4] = {0}; + CLIGetHexWithReturn(ctx, 3, pwd, &pwd_len); + CLIParserFree(ctx); + + + + + return PM3_SUCCESS; } @@ -8689,6 +8718,7 @@ static command_t CommandTable[] = { {"gen3blk", CmdHf14AGen3Block, IfPm3Iso14443a, "Overwrite manufacturer block"}, {"gen3freeze", CmdHf14AGen3Freeze, IfPm3Iso14443a, "Perma lock UID changes. irreversible"}, {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("magic gen4 GTU") " --------------------------"}, + {"ginfo", CmdHF14AGen4Info, IfPm3Iso14443a, "Info about configuration of the card"}, {"ggetblk", CmdHF14AGen4GetBlk, IfPm3Iso14443a, "Read block from card"}, {"gload", CmdHF14AGen4Load, IfPm3Iso14443a, "Load dump to card"}, {"gsave", CmdHF14AGen4Save, IfPm3Iso14443a, "Save dump from card into file or emulator"}, From e6e757865e8a934a52315690ef53e87280d1f269 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 5 Nov 2023 21:58:50 +0200 Subject: [PATCH 02/13] add gen4 commands --- client/src/mifare/gen4.h | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 client/src/mifare/gen4.h diff --git a/client/src/mifare/gen4.h b/client/src/mifare/gen4.h new file mode 100644 index 000000000..bc4dcfb4f --- /dev/null +++ b/client/src/mifare/gen4.h @@ -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 \ No newline at end of file From 70eb1b13912c99f263113f997f67dc9a4265e047 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 5 Nov 2023 22:09:30 +0200 Subject: [PATCH 03/13] add low level g4 info commands --- client/src/mifare/mifarehost.c | 79 ++++++++++++++++++++++++++++++++++ client/src/mifare/mifarehost.h | 3 ++ 2 files changed, 82 insertions(+) diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index 76c392490..6666aca8a 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -40,6 +40,7 @@ #include "crypto/libpcrypto.h" #include "util.h" // xor #include "mbedtls/sha1.h" // SHA1 +#include "gen4.h" int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { uint32_t uid = 0; @@ -1173,6 +1174,84 @@ int mfGen3Freeze(void) { } } +static int mfG4ExCommand(uint8_t cmd, uint8_t *pwd, uint8_t *data, size_t datalen, uint8_t *response, size_t *responselen) { + 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); + } + + clearCommandBuffer(); + SendCommandNG(CMD_HF_MIFARE_G4_RDBL, (uint8_t *)&payload, 1 + 4 + 1 + datalen); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_RDBL, &resp, 1500)) { + if (resp.status != PM3_SUCCESS) { + return PM3_EUNDEF; + } + + if (response != NULL) + memcpy(response, resp.data.asBytes, resp.length); + + if (responselen != NULL) + *responselen = resp.length; + } else { + PrintAndLogEx(WARNING, "command execute timeout"); + return PM3_ETIMEOUT; + } + return PM3_SUCCESS; +} + +int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen) { + uint8_t resp[40] = {0}; + size_t resplen = 0; + + int res = mfG4ExCommand(GEN4_CMD_DUMP_CONFIG, pwd, NULL, 0, resp, &resplen); + if (res != PM3_SUCCESS) { + return PM3_EUNDEF; + } + + 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) { + uint8_t resp[40] = {0}; + size_t resplen = 0; + + int res = mfG4ExCommand(GEN4_CMD_FACTORY_TEST, pwd, NULL, 0, resp, &resplen); + if (res != PM3_SUCCESS) { + return PM3_EUNDEF; + } + + 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) { struct p { uint8_t blockno; diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index ccefbbd40..036770ddf 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -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 mfGen3Freeze(void); +int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen); +int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen); + 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); From 6ae1bae8c0e90cd18a5d0d880f8bc2c128e1596f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 5 Nov 2023 23:43:05 +0200 Subject: [PATCH 04/13] ginfo command works and shows raw data --- client/src/cmdhfmf.c | 27 +++++++++++++-- client/src/mifare/mifarehost.c | 61 ++++++++++++++++++++++++++-------- client/src/mifare/mifarehost.h | 4 +-- 3 files changed, 75 insertions(+), 17 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 16d56c7dd..e9507c06d 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -7448,16 +7448,39 @@ static int CmdHF14AGen4Info(const char *cmd) { arg_str0("p", "pwd", "", "password 4bytes"), arg_param_end }; - CLIExecWithReturn(ctx, cmd, argtable, false); - //bool verbose = arg_get_lit(ctx, 1); + 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) { + PrintAndLogEx(ERR, "Error get config. Maybe not a Gen4 card?. error=%d rlen=%d", res, resplen); + return PM3_ESOFT; + } + PrintAndLogEx(INFO, "---------- Gen4 configuration ----------"); + PrintAndLogEx(INFO, "Raw config [%02d]: %s", resplen, sprint_hex_inrow(resp, resplen)); + if (resplen != 32 && resplen != 34) { + PrintAndLogEx(WARNING, "Unknown config format"); + return PM3_SUCCESS; + } + + res = mfG4GetFactoryTest(pwd, resp, &resplen, verbose); + if (res == PM3_SUCCESS && resplen > 2) { + PrintAndLogEx(INFO, "Raw test [%02d]: %s", resplen, sprint_hex_inrow(resp, resplen)); + return PM3_ESOFT; + } return PM3_SUCCESS; diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index 6666aca8a..f18b103cb 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -40,6 +40,7 @@ #include "crypto/libpcrypto.h" #include "util.h" // xor #include "mbedtls/sha1.h" // SHA1 +#include "cmdhf14a.h" #include "gen4.h" int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { @@ -1174,7 +1175,7 @@ int mfGen3Freeze(void) { } } -static int mfG4ExCommand(uint8_t cmd, uint8_t *pwd, uint8_t *data, size_t datalen, uint8_t *response, size_t *responselen) { +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]; @@ -1196,31 +1197,65 @@ static int mfG4ExCommand(uint8_t cmd, uint8_t *pwd, uint8_t *data, size_t datale memcpy(payload.data, data, datalen); } + int resplen = 0; + clearCommandBuffer(); - SendCommandNG(CMD_HF_MIFARE_G4_RDBL, (uint8_t *)&payload, 1 + 4 + 1 + datalen); + 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_HF_MIFARE_G4_RDBL, &resp, 1500)) { - if (resp.status != PM3_SUCCESS) { - return PM3_EUNDEF; + 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, resp.length); + memcpy(response, resp.data.asBytes, resplen); if (responselen != NULL) - *responselen = resp.length; + *responselen = resplen; + + return PM3_SUCCESS; } else { - PrintAndLogEx(WARNING, "command execute timeout"); + if (verbose) PrintAndLogEx(ERR, "Reply timeout."); return PM3_ETIMEOUT; } - return PM3_SUCCESS; } -int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen) { +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); + int res = mfG4ExCommand(GEN4_CMD_DUMP_CONFIG, pwd, NULL, 0, resp, &resplen, verbose); if (res != PM3_SUCCESS) { return PM3_EUNDEF; } @@ -1234,11 +1269,11 @@ int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen) { return PM3_SUCCESS; } -int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen) { +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); + int res = mfG4ExCommand(GEN4_CMD_FACTORY_TEST, pwd, NULL, 0, resp, &resplen, verbose); if (res != PM3_SUCCESS) { return PM3_EUNDEF; } diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index 036770ddf..dedf7f5ea 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -96,8 +96,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 mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen); -int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen); +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 mfG4SetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags); From 89c19fce9c6a709ab00c4073287fc60b090af8aa Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 5 Nov 2023 23:51:52 +0200 Subject: [PATCH 05/13] ad test data decoding --- client/src/cmdhfmf.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index e9507c06d..35bf6e699 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -7471,15 +7471,24 @@ static int CmdHF14AGen4Info(const char *cmd) { PrintAndLogEx(INFO, "---------- Gen4 configuration ----------"); PrintAndLogEx(INFO, "Raw config [%02d]: %s", resplen, sprint_hex_inrow(resp, resplen)); - if (resplen != 32 && resplen != 34) { + if (resplen != 30 && resplen != 32) { PrintAndLogEx(WARNING, "Unknown config format"); return PM3_SUCCESS; } - res = mfG4GetFactoryTest(pwd, resp, &resplen, verbose); + res = mfG4GetFactoryTest(pwd, resp, &resplen, false); if (res == PM3_SUCCESS && resplen > 2) { - PrintAndLogEx(INFO, "Raw test [%02d]: %s", resplen, sprint_hex_inrow(resp, resplen)); - return PM3_ESOFT; + 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]); } From ac970064d31f13c474c23d9ac555521d4afee8a8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 6 Nov 2023 00:19:45 +0200 Subject: [PATCH 06/13] add timeout error --- client/src/cmdhfmf.c | 5 ++++- client/src/mifare/mifarehost.c | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 35bf6e699..47a0bdb74 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -7465,7 +7465,10 @@ static int CmdHF14AGen4Info(const char *cmd) { size_t resplen = 0; int res = mfG4GetConfig(pwd, resp, &resplen, verbose); if (res != PM3_SUCCESS || resplen == 0) { - PrintAndLogEx(ERR, "Error get config. Maybe not a Gen4 card?. error=%d rlen=%d", res, resplen); + 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; } diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index f18b103cb..b6fd7e22b 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -1257,7 +1257,7 @@ int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose) { int res = mfG4ExCommand(GEN4_CMD_DUMP_CONFIG, pwd, NULL, 0, resp, &resplen, verbose); if (res != PM3_SUCCESS) { - return PM3_EUNDEF; + return res; } if (data != NULL) @@ -1275,7 +1275,7 @@ int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbos int res = mfG4ExCommand(GEN4_CMD_FACTORY_TEST, pwd, NULL, 0, resp, &resplen, verbose); if (res != PM3_SUCCESS) { - return PM3_EUNDEF; + return res; } if (data != NULL) From 910c4d8c92b85ca0bb6ce70499b86fddba44f0c4 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 6 Nov 2023 00:29:28 +0200 Subject: [PATCH 07/13] make style --- .vscode/extensions.json | 1 - client/src/cmdhficlass.c | 6 +++--- client/src/cmdhfmfu.c | 6 +++--- client/src/cmdnfc.c | 8 ++++---- client/src/mifare/gen4.h | 2 +- client/src/mifare/mifarehost.c | 4 ++-- client/src/pm3line_vocabulary.h | 1 + doc/commands.json | 28 ++++++++++++++++++++++------ doc/commands.md | 1 + 9 files changed, 37 insertions(+), 20 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 85b3997e2..e9b75675f 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,7 +3,6 @@ // for the documentation about the extensions.json format "recommendations": [ "ms-vscode.cpptools", - "austin.code-gnu-global", "marus25.cortex-debug", "augustocdias.tasks-shell-input" ] diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index b8e80aaa4..4c60438df 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -1324,7 +1324,7 @@ static int CmdHFiClassESetBlk(const char *Cmd) { static bool iclass_detect_new_pacs(uint8_t *d) { uint8_t n = 0; while (n++ < (PICOPASS_BLOCK_SIZE / 2)) { - if (d[n] && + if (d[n] && d[n + 1] == 0xA6) { return true; } @@ -1332,7 +1332,7 @@ static bool iclass_detect_new_pacs(uint8_t *d) { return false; } -// block 7 decoder for PACS +// block 7 decoder for PACS static int iclass_decode_credentials_new_pacs(uint8_t *d) { uint8_t offset = 0; @@ -1349,7 +1349,7 @@ static int iclass_decode_credentials_new_pacs(uint8_t *d) { 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); PrintAndLogEx(NORMAL, ""); diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 860744220..6b55875f7 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -70,7 +70,7 @@ static uint8_t default_pwd_pack[][4] = { }; 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_EV1_128, MFU_TT_NTAG, 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_MOVE, MFU_TT_MY_D_MOVE_NFC, 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_213_F, MFU_TT_NTAG_216_F, MFU_TT_UL_EV1, MFU_TT_UL_NANO_40, @@ -1891,7 +1891,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { } // 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_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))) { diff --git a/client/src/cmdnfc.c b/client/src/cmdnfc.c index 4e827a32b..1096dec8f 100644 --- a/client/src/cmdnfc.c +++ b/client/src/cmdnfc.c @@ -113,12 +113,12 @@ static int CmdNfcDecode(const char *Cmd) { return res; } - uint8_t *tmp = dump; + uint8_t *tmp = dump; // if not MIFARE Classic default sizes, assume its Ultralight/NTAG - if ( bytes_read != MIFARE_4K_MAX_BYTES - && bytes_read != MIFARE_2K_MAX_BYTES - && bytes_read != MIFARE_1K_MAX_BYTES + if ( bytes_read != MIFARE_4K_MAX_BYTES + && bytes_read != MIFARE_2K_MAX_BYTES + && bytes_read != MIFARE_1K_MAX_BYTES && bytes_read != MIFARE_MINI_MAX_BYTES) { uint8_t **pd = &tmp; diff --git a/client/src/mifare/gen4.h b/client/src/mifare/gen4.h index bc4dcfb4f..3a2ab0947 100644 --- a/client/src/mifare/gen4.h +++ b/client/src/mifare/gen4.h @@ -34,4 +34,4 @@ #define GEN4_CMD_SET_CONFIG_PERMANENT 0xF1 #define GEN4_CMD_CHANGE_PASSWORD 0xFE -#endif \ No newline at end of file +#endif diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index b6fd7e22b..7ff786832 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -1208,7 +1208,7 @@ static int mfG4ExCommand(uint8_t cmd, uint8_t *pwd, uint8_t *data, size_t datale 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) { @@ -1223,7 +1223,7 @@ static int mfG4ExCommand(uint8_t cmd, uint8_t *pwd, uint8_t *data, size_t datale if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { resplen = resp.oldarg[0]; - + if (!resplen) { if (verbose) PrintAndLogEx(ERR, "No card response."); return PM3_EFAILED; diff --git a/client/src/pm3line_vocabulary.h b/client/src/pm3line_vocabulary.h index 858267278..a0fcee232 100644 --- a/client/src/pm3line_vocabulary.h +++ b/client/src/pm3line_vocabulary.h @@ -366,6 +366,7 @@ const static vocabulary_t vocabulary[] = { { 0, "hf mf gen3uid" }, { 0, "hf mf gen3blk" }, { 0, "hf mf gen3freeze" }, + { 0, "hf mf ginfo" }, { 0, "hf mf ggetblk" }, { 0, "hf mf gload" }, { 0, "hf mf gsave" }, diff --git a/doc/commands.json b/doc/commands.json index 4cb9c4623..35bb46ec4 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -279,6 +279,7 @@ "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", "notes": [ + "data bmap -d 3B", "data bmap -d 3B -m 2,5,1" ], "offline": true, @@ -3026,10 +3027,10 @@ }, "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": [ - "hf iclass configcard -l -> download config card settings", - "hf iclass configcard -p -> print all config cards", + "hf iclass configcard -l -> download config card settings from cardhelper", + "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 -g --ci 0 -> generate config file from slot 0" ], @@ -4553,6 +4554,21 @@ ], "usage": "hf mf ggetblk [-hv] -b [-p ]" }, + "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 password 4bytes" + ], + "usage": "hf mf ginfo [-hv] [-p ]" + }, "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.", @@ -8939,7 +8955,7 @@ "-1, --ht1 Card type Hitag 1", "-2, --ht2 Card type Hitag 2", "-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 " }, @@ -12015,8 +12031,8 @@ } }, "metadata": { - "commands_extracted": 696, + "commands_extracted": 697, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2023-10-30T12:11:34" + "extracted_on": "2023-11-05T22:22:55" } } \ No newline at end of file diff --git a/doc/commands.md b/doc/commands.md index 49d34875d..0ff13a82e 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -529,6 +529,7 @@ Check column "offline" for their availability. |`hf mf gen3uid `|N |`Set UID without changing manufacturer block` |`hf mf gen3blk `|N |`Overwrite manufacturer block` |`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 gload `|N |`Load dump to card` |`hf mf gsave `|N |`Save dump from card into file or emulator` From 7afaaf8535e76dce7b23fa56ee97469061c73bdf Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 6 Nov 2023 00:29:42 +0200 Subject: [PATCH 08/13] style --- client/src/fileutils.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/client/src/fileutils.c b/client/src/fileutils.c index 72850b7fe..5f923e492 100644 --- a/client/src/fileutils.c +++ b/client/src/fileutils.c @@ -292,7 +292,7 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data, break; } case jsfMfc_v2: { - + iso14a_mf_extdump_t xdump; 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 char line[256 + 2 + 1]; memset(line, 0, sizeof(line)); - + udata_t udata = (udata_t)data; int n = 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); } continue; - } + } if (str_startswith(line, "atqa:")) { if (ft == NFC_DF_MFC) { // param_gethex_to_eol(line + 5, 0, udata.mfc->card_info.atqa, sizeof(udata.mfc->card_info.atqa), &n); } continue; - } + } if (str_startswith(line, "sak:")) { 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; } continue; - } + } if (str_startswith(line, "signature:")) { 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); } continue; - } + } if (str_startswith(line, "mifare version:")) { 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); } continue; - } + } if (str_startswith(line, "counter 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; } continue; - } + } if (str_startswith(line, "tearing 0:")) { 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; } continue; - } + } if (str_startswith(line, "counter 1:")) { 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; } continue; - } + } if (str_startswith(line, "tearing 1:")) { 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; } continue; - } + } if (str_startswith(line, "tearing 2:")) { 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; } continue; - } + } // Page 0: 04 10 56 CA if (str_startswith(line, "page ")) { @@ -2317,7 +2317,7 @@ nfc_df_e detect_nfc_dump_format(const char *preferredName, bool verbose) { break; case NFC_DF_PICOPASS: PrintAndLogEx(INFO, "detected PICOPASS based dump format"); - break; + break; case NFC_DF_UNKNOWN: PrintAndLogEx(WARNING, "failed to detected dump format"); break; From 2077ea7da50c95c5a0b211ade9ea0c9e2137d7f5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 6 Nov 2023 00:30:13 +0200 Subject: [PATCH 09/13] decode config --- client/src/cmdhfmf.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 47a0bdb74..f35c0be83 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -7473,11 +7473,22 @@ static int CmdHF14AGen4Info(const char *cmd) { } PrintAndLogEx(INFO, "---------- Gen4 configuration ----------"); - PrintAndLogEx(INFO, "Raw config [%02d]: %s", resplen, sprint_hex_inrow(resp, resplen)); 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 [%d]: %s", resp[7], sprint_hex_inrow(&resp[8], resp[7])); + PrintAndLogEx(INFO, "ATQA: %02x%02x", resp[25]); + PrintAndLogEx(INFO, "SAK: %02x", resp[26]); + res = mfG4GetFactoryTest(pwd, resp, &resplen, false); if (res == PM3_SUCCESS && resplen > 2) { @@ -7494,7 +7505,6 @@ static int CmdHF14AGen4Info(const char *cmd) { PrintAndLogEx(INFO, "Card type : unknown %02x%02x", resp[resplen - 2], resp[resplen - 1]); } - return PM3_SUCCESS; } From 4c828f4424943eb0f333db5c3ff83680cece2862 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 6 Nov 2023 00:35:48 +0200 Subject: [PATCH 10/13] view format --- client/src/cmdhfmf.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index f35c0be83..adc1dd739 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -7474,35 +7474,35 @@ static int CmdHF14AGen4Info(const char *cmd) { PrintAndLogEx(INFO, "---------- Gen4 configuration ----------"); if (resplen != 30 && resplen != 32) { - PrintAndLogEx(INFO, "Raw config [%02d]: %s", resplen, sprint_hex_inrow(resp, resplen)); + 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, "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 [%d]: %s", resp[7], sprint_hex_inrow(&resp[8], resp[7])); - PrintAndLogEx(INFO, "ATQA: %02x%02x", resp[25]); - PrintAndLogEx(INFO, "SAK: %02x", resp[26]); + 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[25]); + PrintAndLogEx(INFO, "SAK............. %02x", resp[26]); 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)); + 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"); + PrintAndLogEx(INFO, "Card type....... generic"); else if (resp[resplen - 2] == 0x02 && resp[resplen - 1] == 0xaa) - PrintAndLogEx(INFO, "Card type : limited functionality"); + PrintAndLogEx(INFO, "Card type....... limited functionality"); else if (resp[resplen - 2] == 0x06 && resp[resplen - 1] == 0xa0) - PrintAndLogEx(INFO, "Card type : broken functionality"); + PrintAndLogEx(INFO, "Card type....... broken functionality"); else - PrintAndLogEx(INFO, "Card type : unknown %02x%02x", resp[resplen - 2], resp[resplen - 1]); + PrintAndLogEx(INFO, "Card type....... unknown %02x%02x", resp[resplen - 2], resp[resplen - 1]); } return PM3_SUCCESS; From c6bf1cefe32058fa221b71906c8b46c3f1d11d7a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 6 Nov 2023 00:45:14 +0200 Subject: [PATCH 11/13] fix format --- client/src/cmdhfmf.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index adc1dd739..be770be15 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -7479,30 +7479,33 @@ static int CmdHF14AGen4Info(const char *cmd) { return PM3_SUCCESS; } if (verbose) - PrintAndLogEx(INFO, "Raw config [%02d]. %s", resplen, sprint_hex_inrow(resp, resplen)); + 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[25]); - PrintAndLogEx(INFO, "SAK............. %02x", resp[26]); + 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)); + 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"); + PrintAndLogEx(INFO, "Card type........... generic"); else if (resp[resplen - 2] == 0x02 && resp[resplen - 1] == 0xaa) - PrintAndLogEx(INFO, "Card type....... limited functionality"); + PrintAndLogEx(INFO, "Card type........... limited functionality"); else if (resp[resplen - 2] == 0x06 && resp[resplen - 1] == 0xa0) - PrintAndLogEx(INFO, "Card type....... broken functionality"); + PrintAndLogEx(INFO, "Card type........... broken functionality"); else - PrintAndLogEx(INFO, "Card type....... unknown %02x%02x", resp[resplen - 2], resp[resplen - 1]); + PrintAndLogEx(INFO, "Card type........... unknown %02x%02x", resp[resplen - 2], resp[resplen - 1]); } return PM3_SUCCESS; From 69130384db6f61e9e8303d1a14249640b2bbf704 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 6 Nov 2023 00:48:18 +0200 Subject: [PATCH 12/13] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 490d96463..f73a36179 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 ginfo` command for get info about Gen4 GTU configuration (@merlokk) - Added support for loading Flipper PICOPASS dump files (@iceman1001) - Fixed unknown chip identification (@jmichelp) - Fixed `nfc decode` - now properly handles MFU dump files (@iceman1001) From 3a0002d403e11ffc0efb38fe87abc58fe1d82d76 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 6 Nov 2023 00:49:57 +0200 Subject: [PATCH 13/13] revert extensions --- .vscode/extensions.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e9b75675f..85b3997e2 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,6 +3,7 @@ // for the documentation about the extensions.json format "recommendations": [ "ms-vscode.cpptools", + "austin.code-gnu-global", "marus25.cortex-debug", "augustocdias.tasks-shell-input" ]