From 9888eef8dc86f87c5fa9ec6038f311ff2c191bd6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 6 Jan 2023 23:53:25 +0100 Subject: [PATCH] changed hf mf wrbl and view command to look for strict readonly ACL in the data. --- CHANGELOG.md | 2 + armsrc/i2c.c | 2 +- armsrc/mifarecmd.c | 2 +- client/luascripts/hf_i2c_plus_2k_utils.lua | 20 +- client/luascripts/hf_mf_ultimatecard.lua | 6 +- client/src/cmdhficlass.c | 2 +- client/src/cmdhfmf.c | 76 +++++++- client/src/cmdhfmfu.c | 2 +- client/src/cmdlfhitag.c | 4 +- client/src/cmdscript.c | 2 +- client/src/cmdtrace.c | 16 +- client/src/mifare/mifare4.c | 39 ++-- client/src/mifare/mifare4.h | 1 + client/src/pm3line_vocabulory.h | 6 + client/src/ui.h | 2 +- doc/commands.json | 217 ++++++++++++++++----- doc/commands.md | 16 +- 17 files changed, 313 insertions(+), 102 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc54763f8..4278b6c12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ 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] + - Changed `hf mf wrbl` - now checks for strict readonly ACL's in the data to write (@iceman1001) + - Changed `hf mf view` - verbose printing if strict readonly ACL's exists in dump file (@iceman1001) - Add command `piv authsign` to get a buffer signed by the selected key (@jmichelp) - Add command `piv scan` which tries to read all known containers on PIV (@jmichelp) - Add support for PIV commands, over wired and contactless interfaces (@jmichelp) diff --git a/armsrc/i2c.c b/armsrc/i2c.c index 491e12a04..ca3cb46fd 100644 --- a/armsrc/i2c.c +++ b/armsrc/i2c.c @@ -749,7 +749,7 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose) { } } - card_ptr->atr_len = (uint8_t) (len & 0xff); + card_ptr->atr_len = (uint8_t)(len & 0xff); if (verbose) { LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false); } diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 3db9112af..74e75ddce 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2356,7 +2356,7 @@ void MifareCIdent(bool is_mfc) { uint8_t rats[4] = { ISO14443A_CMD_RATS, 0x80, 0x31, 0x73 }; uint8_t rdblf0[4] = { ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f}; uint8_t rdbl00[4] = { ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8}; - uint8_t gen4GetConf[8] = { GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_GETCNF, 0, 0}; + uint8_t gen4GetConf[8] = { GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_GETCNF, 0, 0}; uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE); uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE); uint8_t *uid = BigBuf_malloc(10); diff --git a/client/luascripts/hf_i2c_plus_2k_utils.lua b/client/luascripts/hf_i2c_plus_2k_utils.lua index 7e6b9b300..5e7652316 100644 --- a/client/luascripts/hf_i2c_plus_2k_utils.lua +++ b/client/luascripts/hf_i2c_plus_2k_utils.lua @@ -23,7 +23,7 @@ author = 'Shain Lakin' version = 'v1.0.0' desc =[[ -This script can be used to read blocks, write blocks, dump sectors, +This script can be used to read blocks, write blocks, dump sectors, or write a files hex bytes to sector 0 or 1 on the NTAG I2C PLUS 2K tag. ]] @@ -32,7 +32,7 @@ example =[[ Read block 04 from sector 1: script run hf_i2c_plus_2k_utils -m r -s 1 -b 04 - + Write FFFFFFFF to block A0 sector 1: script run hf_i2c_plus_2k_utils -m w -s 1 -b A0 -d FFFFFFFF @@ -45,15 +45,15 @@ example =[[ ]] usage = [[ - Read mode: + Read mode: script run hf_i2c_plus_2k_utils -m r -s -b - - Write mode: + + Write mode: script run hf_i2c_plus_2k_utils -m w -s -b -d - + Dump mode: script run hf_i2c_plus_2k_utils -m d -s - + File mode: script run hf_i2c_plus_2k_utils -m f -s -f @@ -124,7 +124,7 @@ end --- ---- Function to connect +--- Function to connect local function connect() core.clearCommandBuffer() @@ -189,7 +189,7 @@ local function filewriter(file,sector) end_char = 8 block_counter = 4 -- NTAG_I2C_PLUS_2K:SECTOR_0:225,SECTOR_1:255 - end_block = 225 + end_block = 225 connect() select_sector(sector) for count = 1, len do @@ -296,7 +296,7 @@ local function main(args) elseif mode == 'd' then dump(sector,uid) end - + else return print(usage) end diff --git a/client/luascripts/hf_mf_ultimatecard.lua b/client/luascripts/hf_mf_ultimatecard.lua index 4a70935bb..aec47e9d0 100644 --- a/client/luascripts/hf_mf_ultimatecard.lua +++ b/client/luascripts/hf_mf_ultimatecard.lua @@ -847,13 +847,13 @@ end -- returns true if b is the index of a sector trailer local function mfIsSectorTrailer(b) n=b+1 - if (n < 32*4 ) then - if (n % 4 == 0) then return true + if (n < 32*4 ) then + if (n % 4 == 0) then return true else return false end end - if (n % 16 == 0) then return true + if (n % 16 == 0) then return true end return false diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 4e555f909..94d710f98 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -3968,7 +3968,7 @@ static int CmdHFiClassEncode(const char *Cmd) { return PM3_ESOFT; } - // iceman: only for formats w length smaller than 37. + // iceman: only for formats w length smaller than 37. // Needs a check. // increase length to allow setting bit just above real data diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 51a9a13f0..eba190b5e 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -238,7 +238,7 @@ static bool mfc_value(const uint8_t *d, int32_t *val) { } static void mf_print_block_one(uint8_t blockno, uint8_t *d, bool verbose) { - if (blockno == 0) { + if (blockno == 0) { PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(d, MFBLOCK_SIZE)); } else if (mfIsSectorTrailer(blockno)) { PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(d, MFBLOCK_SIZE)); @@ -375,6 +375,31 @@ static bool mf_write_block(const uint8_t *key, uint8_t keytype, uint8_t blockno, return (resp.oldarg[0] & 0xff); } +static void mf_analyse_acl(uint16_t n, uint8_t *d) { + + for (uint16_t b = 3; b < n; b++) { + if (mfIsSectorTrailer(b) == false) { + continue; + } + + uint8_t block[MFBLOCK_SIZE] = {0x00}; + memcpy(block, d + (b * MFBLOCK_SIZE), MFBLOCK_SIZE); + + // ensure access right isn't messed up. + if (mfValidateAccessConditions(&block[6]) == false) { + PrintAndLogEx(WARNING, "Invalid Access Conditions on sector " _YELLOW_("%u"), mfSectorNum(b)); + } + + // Warn if ACL is strict read-only + uint8_t bar = mfNumBlocksPerSector(mfSectorNum(b)); + for (uint8_t foo = 0; foo < bar; foo++) { + if (mfReadOnlyAccessConditions(foo, &block[6])) { + PrintAndLogEx(WARNING, _YELLOW_("s%u / b%u") " - Strict ReadOnly Access Conditions detected", mfSectorNum(b), b - bar + 1 + foo); + } + } + } +} + static int CmdHF14AMfAcl(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf acl", @@ -539,6 +564,32 @@ static int CmdHF14AMfWrBl(const char *Cmd) { uint8_t blockno = (uint8_t)b; + // Warn if ACL is strict read-only + if (mfIsSectorTrailer(blockno)) { + PrintAndLogEx(INFO, "Sector trailer (ST) write detected"); + + // ensure access right isn't messed up. + if (mfValidateAccessConditions(&block[6]) == false) { + PrintAndLogEx(WARNING, "Invalid Access Conditions detected, replacing by default values"); + memcpy(block + 6, "\xFF\x07\x80\x69", 4); + } + + bool ro_detected = false; + uint8_t bar = mfNumBlocksPerSector(mfSectorNum(blockno)); + for (uint8_t foo = 0; foo < bar; foo++) { + if (mfReadOnlyAccessConditions(foo, &block[6])) { + PrintAndLogEx(WARNING, "Strict ReadOnly Access Conditions on block " _YELLOW_("%u") " detected", blockno - bar + 1 + foo); + ro_detected = true; + } + } + if (ro_detected) { + PrintAndLogEx(INFO, "Exiting, please run `" _YELLOW_("hf mf acl -d %s") "` to understand", sprint_hex_inrow(&block[6], 3)); + return PM3_EINVARG; + } else { + PrintAndLogEx(SUCCESS, "ST passed checks, continuing..."); + } + } + PrintAndLogEx(INFO, "Writing block no %d, key %c - %s", blockno, (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key))); PrintAndLogEx(INFO, "data: %s", sprint_hex(block, sizeof(block))); @@ -1172,7 +1223,7 @@ static int CmdHF14AMfRestore(const char *Cmd) { PrintAndLogEx(INFO, "Restoring " _YELLOW_("%s")" to card", datafilename); - // main loop for restoreing. + // main loop for restoring. // a bit more complicated than needed // this is because of two things. // 1. we are setting keys from a key file or using the existing ones in the dump @@ -1182,7 +1233,6 @@ static int CmdHF14AMfRestore(const char *Cmd) { for (uint8_t b = 0; b < mfNumBlocksPerSector(s); b++) { uint8_t bldata[MFBLOCK_SIZE] = {0x00}; - memcpy(bldata, dump, MFBLOCK_SIZE); // if sector trailer @@ -1209,6 +1259,13 @@ static int CmdHF14AMfRestore(const char *Cmd) { PrintAndLogEx(WARNING, "Invalid Access Conditions on sector %i, replacing by default values", s); memcpy(bldata + 6, "\xFF\x07\x80\x69", 4); } + + // Warn if ACL is strict read-only + for (uint8_t foo = 0; foo < mfNumBlocksPerSector(s); foo++) { + if (mfReadOnlyAccessConditions(foo, &bldata[6])) { + PrintAndLogEx(WARNING, "Strict ReadOnly Access Conditions on block " _YELLOW_("%u") " detected", foo); + } + } } if (bytes_read) { @@ -6818,6 +6875,7 @@ static int CmdHF14AMfView(const char *Cmd) { if (verbose) { mf_print_keys(block_cnt, dump); + mf_analyse_acl(block_cnt, dump); } int sector = DetectHID(dump, 0x4910); @@ -6836,7 +6894,7 @@ static int CmdHF14AMfView(const char *Cmd) { } // allocate memory - uint8_t* d = calloc(bytes_read, sizeof(uint8_t)); + uint8_t *d = calloc(bytes_read, sizeof(uint8_t)); if (d == NULL) { return PM3_EMALLOC; } @@ -7324,8 +7382,8 @@ static int CmdHF14AGen4Save(const char *Cmd) { int fnlen = 0; char filename[FILE_PATH_SIZE]; CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - - bool fill_emulator = arg_get_lit(ctx,7); + + bool fill_emulator = arg_get_lit(ctx, 7); CLIParserFree(ctx); // validations @@ -7420,12 +7478,12 @@ static int CmdHF14AGen4Save(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - + if (fill_emulator) { PrintAndLogEx(INFO, "uploading to emulator memory" NOLF); // fast push mode g_conn.block_after_ACK = true; - + size_t offset = 0; int cnt = 0; uint16_t bytes_left = bytes ; @@ -7454,7 +7512,7 @@ static int CmdHF14AGen4Save(const char *Cmd) { offset += MFBLOCK_SIZE; bytes_left -= MFBLOCK_SIZE; } - + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, "uploaded " _YELLOW_("%d") " bytes to emulator memory", bytes); } diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index c3701a76d..e948360e6 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -4154,7 +4154,7 @@ static int CmdHF14AMfuEView(const char *Cmd) { if (override_end) { ++end ; - } else { + } else { end = dump->pages ; } diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index ba7b72195..66fb3ea42 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -857,12 +857,12 @@ static int CmdLFHitag2Dump(const char *Cmd) { memcpy(htd.pwd.password, key, sizeof(htd.pwd.password)); PrintAndLogEx(INFO, "Authenticating in password mode"); } - + uint16_t cmd = CMD_LF_HITAG_READER; clearCommandBuffer(); SendCommandMIX(cmd, htf, 0, 0, &htd, sizeof(htd)); PacketResponseNG resp; - + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return PM3_ETIMEOUT; diff --git a/client/src/cmdscript.c b/client/src/cmdscript.c index 7a5a59130..35640922e 100644 --- a/client/src/cmdscript.c +++ b/client/src/cmdscript.c @@ -404,7 +404,7 @@ static int CmdScriptRun(const char *Cmd) { PyImport_AppendInittab("_pm3", PyInit__pm3); #endif #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 10 - Py_Initialize(); + Py_Initialize(); #else PyConfig py_conf; PyConfig_InitIsolatedConfig(&py_conf); diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 5fbf90b0d..af97e8466 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -900,16 +900,16 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr if (use_us) { PrintAndLogEx(NORMAL, " %10.1f | %10.1f | %s |fdt (Frame Delay Time): " _YELLOW_("%.1f"), - (float)time1 / 13.56, - (float)time2 / 13.56, - " ", - (float)(next_hdr->timestamp - end_of_transmission_timestamp) / 13.56); + (float)time1 / 13.56, + (float)time2 / 13.56, + " ", + (float)(next_hdr->timestamp - end_of_transmission_timestamp) / 13.56); } else { PrintAndLogEx(NORMAL, " %10u | %10u | %s |fdt (Frame Delay Time): " _YELLOW_("%d"), - time1, - time2, - " ", - (next_hdr->timestamp - end_of_transmission_timestamp)); + time1, + time2, + " ", + (next_hdr->timestamp - end_of_transmission_timestamp)); } } diff --git a/client/src/mifare/mifare4.c b/client/src/mifare/mifare4.c index a1427bc9f..1ac6b6fed 100644 --- a/client/src/mifare/mifare4.c +++ b/client/src/mifare/mifare4.c @@ -74,22 +74,37 @@ AccessConditions_t MFAccessConditionsTrailer[] = { }; bool mfValidateAccessConditions(const uint8_t *data) { - uint8_t ndata1 = (data[0]) & 0x0f; - uint8_t ndata2 = (data[0] >> 4) & 0x0f; - uint8_t ndata3 = (data[1]) & 0x0f; - uint8_t data1 = (data[1] >> 4) & 0x0f; - uint8_t data2 = (data[2]) & 0x0f; - uint8_t data3 = (data[2] >> 4) & 0x0f; + uint8_t nd1 = NIBBLE_LOW(data[0]); + uint8_t nd2 = NIBBLE_HIGH(data[0]); + uint8_t nd3 = NIBBLE_LOW(data[1]); + uint8_t d1 = NIBBLE_HIGH(data[1]); + uint8_t d2 = NIBBLE_LOW(data[2]); + uint8_t d3 = NIBBLE_HIGH(data[2]); - return ((ndata1 == (data1 ^ 0xF)) && (ndata2 == (data2 ^ 0xF)) && (ndata3 == (data3 ^ 0xF))); + return ((nd1 == (d1 ^ 0xF)) && (nd2 == (d2 ^ 0xF)) && (nd3 == (d3 ^ 0xF))); +} +bool mfReadOnlyAccessConditions(uint8_t blockn, const uint8_t *data) { + + uint8_t d1 = NIBBLE_HIGH(data[1]) >> blockn; + uint8_t d2 = NIBBLE_LOW(data[2]) >> blockn; + uint8_t d3 = NIBBLE_HIGH(data[2]) >> blockn; + uint8_t cond = (d1 & 0x01) << 2 | (d2 & 0x01) << 1 | (d3 & 0x01); + + if (blockn == 3) { + if ((cond == 0x02) || (cond == 0x06) || (cond == 0x07)) return true; + } else { + if ((cond == 0x02) || (cond == 0x05)) return true; + } + return false; } -const char *mfGetAccessConditionsDesc(uint8_t blockn, const uint8_t *data) { - uint8_t data1 = ((data[1] >> 4) & 0x0f) >> blockn; - uint8_t data2 = ((data[2]) & 0x0f) >> blockn; - uint8_t data3 = ((data[2] >> 4) & 0x0f) >> blockn; - uint8_t cond = (data1 & 0x01) << 2 | (data2 & 0x01) << 1 | (data3 & 0x01); +const char *mfGetAccessConditionsDesc(uint8_t blockn, const uint8_t *data) { + uint8_t d1 = NIBBLE_HIGH(data[1]) >> blockn; + uint8_t d2 = NIBBLE_LOW(data[2]) >> blockn; + uint8_t d3 = NIBBLE_HIGH(data[2]) >> blockn; + + uint8_t cond = (d1 & 0x01) << 2 | (d2 & 0x01) << 1 | (d3 & 0x01); if (blockn == 3) { for (int i = 0; i < ARRAYLEN(MFAccessConditionsTrailer); i++) diff --git a/client/src/mifare/mifare4.h b/client/src/mifare/mifare4.h index 7905f3ab6..489add9f3 100644 --- a/client/src/mifare/mifare4.h +++ b/client/src/mifare/mifare4.h @@ -71,6 +71,7 @@ int MFPGetSignature(bool activateField, bool leaveSignalON, uint8_t *dataout, in int MFPGetVersion(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); bool mfValidateAccessConditions(const uint8_t *data); +bool mfReadOnlyAccessConditions(uint8_t blockn, const uint8_t *data); const char *mfGetAccessConditionsDesc(uint8_t blockn, const uint8_t *data); uint8_t mfNumBlocksPerSector(uint8_t sectorNo); diff --git a/client/src/pm3line_vocabulory.h b/client/src/pm3line_vocabulory.h index 6b15007c3..de0cb6ace 100644 --- a/client/src/pm3line_vocabulory.h +++ b/client/src/pm3line_vocabulory.h @@ -349,6 +349,7 @@ const static vocabulory_t vocabulory[] = { { 0, "hf mf gen3freeze" }, { 0, "hf mf ggetblk" }, { 0, "hf mf gload" }, + { 0, "hf mf gsave" }, { 0, "hf mf gsetblk" }, { 0, "hf mf gview" }, { 0, "hf mf ndefformat" }, @@ -736,6 +737,11 @@ const static vocabulory_t vocabulory[] = { { 0, "nfc barcode read" }, { 0, "nfc barcode sim" }, { 1, "nfc barcode help" }, + { 1, "piv help" }, + { 0, "piv select" }, + { 0, "piv getdata" }, + { 0, "piv scan" }, + { 1, "piv list" }, { 1, "smart help" }, { 1, "smart list" }, { 0, "smart info" }, diff --git a/client/src/ui.h b/client/src/ui.h index 7aff98eba..4042550b3 100644 --- a/client/src/ui.h +++ b/client/src/ui.h @@ -36,7 +36,7 @@ typedef enum emojiMode {EMO_ALIAS, EMO_EMOJI, EMO_ALTTEXT, EMO_NONE} emojiMode_t typedef enum clientdebugLevel {cdbOFF, cdbSIMPLE, cdbFULL} clientdebugLevel_t; // typedef enum devicedebugLevel {ddbOFF, ddbERROR, ddbINFO, ddbDEBUG, ddbEXTENDED} devicedebugLevel_t; - // last item spItemCount used to auto map to number of files +// last item spItemCount used to auto map to number of files typedef enum savePaths {spDefault, spDump, spTrace, spItemCount} savePaths_t; typedef struct {int x; int y; int h; int w;} qtWindow_t; diff --git a/doc/commands.json b/doc/commands.json index a94e5bc6a..7546493bb 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -1030,7 +1030,7 @@ }, "help": { "command": "help", - "description": "help Use ` help` for details of a command prefs { Edit client/device preferences... } -------- ----------------------- Technology ----------------------- analyse { Analyse utils... } data { Plot window / data buffer manipulation... } emv { EMV ISO-14443 / ISO-7816... } hf { High frequency commands... } hw { Hardware commands... } lf { Low frequency commands... } nfc { NFC commands... } reveng { CRC calculations from RevEng software... } smart { Smart card ISO-7816 commands... } script { Scripting commands... } trace { Trace manipulation... } wiegand { Wiegand format manipulation... } -------- ----------------------- General ----------------------- clear Clear screen hints Turn hints on / off msleep Add a pause in milliseconds rem Add a text line in log file quit exit Exit program", + "description": "help Use ` help` for details of a command prefs { Edit client/device preferences... } -------- ----------------------- Technology ----------------------- analyse { Analyse utils... } data { Plot window / data buffer manipulation... } emv { EMV ISO-14443 / ISO-7816... } hf { High frequency commands... } hw { Hardware commands... } lf { Low frequency commands... } nfc { NFC commands... } piv { PIV commands... } reveng { CRC calculations from RevEng software... } smart { Smart card ISO-7816 commands... } script { Scripting commands... } trace { Trace manipulation... } wiegand { Wiegand format manipulation... } -------- ----------------------- General ----------------------- clear Clear screen hints Turn hints on / off msleep Add a pause in milliseconds rem Add a text line in log file quit exit Exit program", "notes": [], "offline": true, "options": [], @@ -2916,9 +2916,10 @@ "-f, --file Dictionary file with default iclass keys", "--credit key is assumed to be the credit key", "--elite elite computations applied to key", - "--raw no computations applied to key (raw)" + "--raw no computations applied to key (raw)", + "--shallow use shallow (ASK) reader modulation instead of OOK" ], - "usage": "hf iclass chk [-h] -f [--credit] [--elite] [--raw]" + "usage": "hf iclass chk [-h] -f [--credit] [--elite] [--raw] [--shallow]" }, "hf iclass configcard": { "command": "hf iclass configcard", @@ -2970,9 +2971,10 @@ "--raw raw, the key is interpreted as raw block 3/4", "--nr replay of NR/MAC", "-z, --dense dense dump output style", - "--force force unsecure card read" + "--force force unsecure card read", + "--shallow use shallow (ASK) reader modulation instead of OOK" ], - "usage": "hf iclass dump [-hz] [-f ] [-k ] [--ki ] [--credit ] [--ci ] [--elite] [--raw] [--nr] [--force]" + "usage": "hf iclass dump [-hz] [-f ] [-k ] [--ki ] [--credit ] [--ci ] [--elite] [--raw] [--nr] [--force] [--shallow]" }, "hf iclass eload": { "command": "hf iclass eload", @@ -3008,9 +3010,10 @@ "--enckey 3DES transport key, 16 hex bytes", "--fc facility code", "--cn card number", - "-w, --wiegand see `wiegand list` for available formats" + "-w, --wiegand see `wiegand list` for available formats", + "--shallow use shallow (ASK) reader modulation instead of OOK" ], - "usage": "hf iclass encode [-h] [--bin ] --ki [--credit] [--elite] [--raw] [--enckey ] [--fc ] [--cn ] [-w ]" + "usage": "hf iclass encode [-h] [--bin ] --ki [--credit] [--elite] [--raw] [--enckey ] [--fc ] [--cn ] [-w ] [--shallow]" }, "hf iclass encrypt": { "command": "hf iclass encrypt", @@ -3077,9 +3080,10 @@ ], "offline": true, "options": [ - "-h, --help This help" + "-h, --help This help", + "--shallow use shallow (ASK) reader modulation instead of OOK" ], - "usage": "hf iclass info [-h]" + "usage": "hf iclass info [-h] [--shallow]" }, "hf iclass list": { "command": "hf iclass list", @@ -3191,9 +3195,10 @@ "--elite elite computations applied to key", "--raw no computations applied to key", "--nr replay of NR/MAC", - "-v, --verbose verbose output" + "-v, --verbose verbose output", + "--shallow use shallow (ASK) reader modulation instead of OOK" ], - "usage": "hf iclass rdbl [-hv] [-k ] [--ki ] -b [--credit] [--elite] [--raw] [--nr]" + "usage": "hf iclass rdbl [-hv] [-k ] [--ki ] -b [--credit] [--elite] [--raw] [--nr] [--shallow]" }, "hf iclass reader": { "command": "hf iclass reader", @@ -3204,9 +3209,10 @@ "offline": false, "options": [ "-h, --help This help", - "-@ optional - continuous reader mode" + "-@ optional - continuous reader mode", + "--shallow use shallow (ASK) reader modulation instead of OOK" ], - "usage": "hf iclass reader [-h@]" + "usage": "hf iclass reader [-h@] [--shallow]" }, "hf iclass restore": { "command": "hf iclass restore", @@ -3227,9 +3233,10 @@ "--credit key is assumed to be the credit key", "--elite elite computations applied to key", "--raw no computations applied to key", - "-v, --verbose verbose output" + "-v, --verbose verbose output", + "--shallow use shallow (ASK) reader modulation instead of OOK" ], - "usage": "hf iclass restore [-hv] -f [-k ] [--ki ] --first --last [--credit] [--elite] [--raw]" + "usage": "hf iclass restore [-hv] -f [-k ] [--ki ] --first --last [--credit] [--elite] [--raw] [--shallow]" }, "hf iclass sim": { "command": "hf iclass sim", @@ -3301,9 +3308,10 @@ "--elite elite computations applied to key", "--raw no computations applied to key", "--nr replay of NR/MAC", - "-v, --verbose verbose output" + "-v, --verbose verbose output", + "--shallow use shallow (ASK) reader modulation instead of OOK" ], - "usage": "hf iclass wrbl [-hv] [-k ] [--ki ] -b -d [-m ] [--credit] [--elite] [--raw] [--nr]" + "usage": "hf iclass wrbl [-hv] [-k ] [--ki ] -b -d [-m ] [--credit] [--elite] [--raw] [--nr] [--shallow]" }, "hf jooki clone": { "command": "hf jooki clone", @@ -3391,6 +3399,20 @@ ], "usage": "hf jooki sim [-h] [-b ]" }, + "hf ksx6924 balance": { + "command": "hf ksx6924 balance", + "description": "Gets the current purse balance", + "notes": [ + "hf ksx6924 balance" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-k, --keep keep field ON for next command", + "-a, --apdu Show APDU requests and responses" + ], + "usage": "hf ksx6924 balance [-hka]" + }, "hf ksx6924 help": { "command": "hf ksx6924 help", "description": "help This help", @@ -3399,19 +3421,6 @@ "options": [], "usage": "" }, - "hf ksx6924 select": { - "command": "hf ksx6924 select", - "description": "Selects KS X 6924 application, and leaves field up", - "notes": [ - "hf ksx6924 select" - ], - "offline": false, - "options": [ - "-h, --help This help", - "-a, --apdu Show APDU requests and responses" - ], - "usage": "hf ksx6924 select [-ha]" - }, "hf ksx6924 info": { "command": "hf ksx6924 info", "description": "Get info about a KS X 6924 transit card. This application is used by T-Money (South Korea) and Snapper+ (Wellington, New Zealand).", @@ -3426,23 +3435,9 @@ ], "usage": "hf ksx6924 info [-hka]" }, - "hf ksx6924 balance": { - "command": "hf ksx6924 balance", - "description": "Gets the current purse balance", - "notes": [ - "hf ksx6924 balance" - ], - "offline": false, - "options": [ - "-h, --help This help", - "-k, --keep keep field ON for next command", - "-a, --apdu Show APDU requests and responses" - ], - "usage": "hf ksx6924 balance [-hka]" - }, "hf ksx6924 init": { "command": "hf ksx6924 init", - "description": "Perform transaction initialization (mpda)", + "description": "Perform transaction initialization with Mpda (Money of Purchase Transaction)", "notes": [ "hf ksx6924 init 000003e8 -> Mpda" ], @@ -3468,7 +3463,19 @@ ], "usage": "hf ksx6924 prec [-hka] " }, - + "hf ksx6924 select": { + "command": "hf ksx6924 select", + "description": "Selects KS X 6924 application, and leaves field up", + "notes": [ + "hf ksx6924 select" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-a, --apdu Show APDU requests and responses" + ], + "usage": "hf ksx6924 select [-ha]" + }, "hf legic crc": { "command": "hf legic crc", "description": "Calculates the legic crc8/crc16 on the given data", @@ -3971,7 +3978,7 @@ "--1k MIFARE Classic 1k / S50 (def)", "--2k MIFARE Classic/Plus 2k", "--4k MIFARE Classic 4k / S70", - "--emu from emulator memory" + "--emu to emulator memory" ], "usage": "hf mf csave [-h] [-f ] [--mini] [--1k] [--2k] [--4k] [--emu]" }, @@ -4348,6 +4355,27 @@ ], "usage": "hf mf gload [-hv] [--mini] [--1k] [--2k] [--4k] [-p ] [-f ] [--emu] [--start ] [--end ]" }, + "hf mf gsave": { + "command": "hf mf gsave", + "description": "Save `magic gen4 gtu` card memory into three files (BIN/EML/JSON)or into emulator memory", + "notes": [ + "hf mf gsave", + "hf mf gsave --4k", + "hf mf gsave -p DEADBEEF -f hf-mf-01020304.json" + ], + "offline": false, + "options": [ + "-h, --help This help", + "--mini MIFARE Classic Mini / S20", + "--1k MIFARE Classic 1k / S50 (def)", + "--2k MIFARE Classic/Plus 2k", + "--4k MIFARE Classic 4k / S70", + "-p, --pwd password 4bytes", + "-f, --file filename of dump", + "--emu to emulator memory" + ], + "usage": "hf mf gsave [-h] [--mini] [--1k] [--2k] [--4k] [-p ] [-f ] [--emu]" + }, "hf mf gsetblk": { "command": "hf mf gsetblk", "description": "Set block data on a magic gen4 GTU card", @@ -6176,7 +6204,7 @@ }, "hf mfu esave": { "command": "hf mfu esave", - "description": "Saves emulator memory to a MIFARE Ultralight/NTAG dump file (bin/eml/json) By default number of pages saved depends on defined tag type. You can overrife this with option --end.", + "description": "Saves emulator memory to a MIFARE Ultralight/NTAG dump file (bin/eml/json) By default number of pages saved depends on defined tag type. You can override this with option --end.", "notes": [ "hf mfu esave", "hf mfu esave --end 255 -> saves whole memory", @@ -6192,7 +6220,7 @@ }, "hf mfu eview": { "command": "hf mfu eview", - "description": "Displays emulator memory By default number of pages shown depends on defined tag type. You can overrife this with option --end.", + "description": "Displays emulator memory By default number of pages shown depends on defined tag type. You can override this with option --end.", "notes": [ "hf mfu eview", "hf mfu eview --end 255 -> dumps whole memory" @@ -10924,6 +10952,93 @@ ], "usage": "hf 14b ndefread [-hv] [-f ]" }, + "piv getdata": { + "command": "piv getdata", + "description": "Get a data container of a given tag", + "notes": [ + "piv getdata -s 5fc102 -> select card, select applet, get card holder unique identifer", + "piv getdata -st 5fc102 -> select card, select applet, get card holder unique identifer, show result in TLV" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-s, -S, --select Activate field and select applet", + "-k, -K, --keep Keep field for next command", + "-a, -A, --apdu Show APDU requests and responses", + "-t, -T, --tlv TLV decode results", + "-w, -W, --wired Send data via contact (iso7816) interface. (def: Contactless interface)", + "--aid Applet ID to select. By default A0000003080000100 will be used", + " Tag ID to read, between 1 and 3 bytes." + ], + "usage": "piv getdata [-hskatw] [--aid ] " + }, + "piv help": { + "command": "piv help", + "description": "help This help list List ISO7816 history", + "notes": [], + "offline": true, + "options": [], + "usage": "" + }, + "piv list": { + "command": "piv list", + "description": "Alias of `trace list -t 7816` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol", + "notes": [ + "piv list --frame -> show frame delay times", + "piv list -1 -> use trace buffer" + ], + "offline": true, + "options": [ + "-h, --help This help", + "-1, --buffer use data from trace buffer", + "--frame show frame delay times", + "-c mark CRC bytes", + "-r show relative times (gap and duration)", + "-u display times in microseconds instead of clock cycles", + "-x show hexdump to convert to pcap(ng)", + "or to import into Wireshark using encapsulation type \"ISO 14443\"", + "-f, --file filename of dictionary" + ], + "usage": "piv list [-h1crux] [--frame] [-f ]" + }, + "piv scan": { + "command": "piv scan", + "description": "Scan a PIV card for known containers", + "notes": [ + "piv scan -s -> select card, select applet and run scan", + "piv scan -st --aid a00000030800001000 -> select card, select applet a00000030800001000, show result of the scan in TLV" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-s, -S, --select Activate field and select applet", + "-k, -K, --keep Keep field for next command", + "-a, -A, --apdu Show APDU requests and responses", + "-t, -T, --tlv TLV decode results", + "-w, -W, --wired Send data via contact (iso7816) interface. (def: Contactless interface)", + "--aid Applet ID to select. By default A0000003080000100 will be used" + ], + "usage": "piv scan [-hskatw] [--aid ]" + }, + "piv select": { + "command": "piv select", + "description": "Executes select applet command", + "notes": [ + "piv select -s -> select card, select applet", + "piv select -st --aid a00000030800001000 -> select card, select applet a00000030800001000, show result in TLV" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-s, -S, --select Activate field and select applet", + "-k, -K, --keep Keep field for next command", + "-a, -A, --apdu Show APDU requests and responses", + "-t, -T, --tlv TLV decode results", + "-w, -W, --wired Send data via contact (iso7816) interface. (def: Contactless interface)", + "--aid Applet ID to select. By default A0000003080000100 will be used" + ], + "usage": "piv select [-hskatw] [--aid ]" + }, "prefs get barmode": { "command": "prefs get barmode", "description": "Get preference of HF/LF tune command styled output in the client", @@ -11616,8 +11731,8 @@ } }, "metadata": { - "commands_extracted": 732, + "commands_extracted": 738, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2022-11-20T20:19:15" + "extracted_on": "2023-01-06T21:37:50" } } \ No newline at end of file diff --git a/doc/commands.md b/doc/commands.md index 4b91901f4..bb4c68869 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -370,7 +370,7 @@ Check column "offline" for their availability. |`hf ksx6924 select `|N |`Select application, and leave field up` |`hf ksx6924 info `|N |`Get info about a KS X 6924 (T-Money, Snapper+) transit card` |`hf ksx6924 balance `|N |`Get current purse balance` -|`hf ksx6924 init `|N |`Perform transaction initialization with Mpda (Money of Purchase Transaction)` +|`hf ksx6924 init `|N |`Perform transaction initialization with Mpda` |`hf ksx6924 prec `|N |`Send proprietary get record command (CLA=90, INS=4C)` @@ -512,6 +512,7 @@ Check column "offline" for their availability. |`hf mf gen3freeze `|N |`Perma lock UID changes. irreversible` |`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` |`hf mf gsetblk `|N |`Write block to card` |`hf mf gview `|N |`View card` |`hf mf ndefformat `|N |`Format MIFARE Classic Tag as NFC Tag` @@ -1333,6 +1334,19 @@ Check column "offline" for their availability. |`nfc barcode help `|Y |`This help` +### piv + + { PIV commands... } + +|command |offline |description +|------- |------- |----------- +|`piv help `|Y |`This help` +|`piv select `|N |`Select the PIV applet` +|`piv getdata `|N |`Gets a container on a PIV card` +|`piv scan `|N |`Scan PIV card for known containers` +|`piv list `|Y |`List ISO7816 history` + + ### reveng { CRC calculations from RevEng software... }