diff --git a/CHANGELOG.md b/CHANGELOG.md index e7940e2c5..11fc87a5c 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 info` command and static encrypted nonce detection (@merlokk) - Added Saflok KDF - generate MFC keys (@h1kari) - Changed `lf fdx demod` - now raw bytes shows all data (@iceman1001) - Changed `data num` - now can print reversed and inverse (@iceman1001) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index fc07d66f8..849bfcb2b 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -799,7 +799,8 @@ static void PacketReceived(PacketCommandNG *packet) { // emulator case CMD_SET_DBGMODE: { g_dbglevel = packet->data.asBytes[0]; - print_debug_level(); + if (packet->length == 1 || packet->data.asBytes[1] != 0) + print_debug_level(); reply_ng(CMD_SET_DBGMODE, PM3_SUCCESS, NULL, 0); break; } @@ -1865,6 +1866,17 @@ static void PacketReceived(PacketCommandNG *packet) { MifareHasStaticNonce(); break; } + case CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE: { + struct p { + uint8_t block_no; + uint8_t key_type; + uint8_t key[6]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + + MifareHasStaticEncryptedNonce(payload->block_no, payload->key_type, payload->key); + break; + } #endif #ifdef WITH_NFCBARCODE diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 32e90d56a..1f0683599 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -90,7 +90,7 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c goto OUT; } - if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL)) { + if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL, NULL)) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); retval = PM3_ESOFT; goto OUT; @@ -158,7 +158,7 @@ int16_t mifare_cmd_writeblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t write goto OUT; }; - if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL)) { + if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL, NULL)) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); retval = PM3_ESOFT; goto OUT; @@ -2681,6 +2681,73 @@ OUT: // 2B F9 1C 1B D5 08 48 48 03 A4 B1 B1 75 FF 2D 90 // ^^ ^^ +void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *key) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + clear_trace(); + set_tracing(true); + + int retval = PM3_SUCCESS; + uint8_t *uid = BigBuf_malloc(10); + memset(uid, 0x00, 10); + + uint8_t data[1] = { NONCE_FAIL }; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + uint64_t ui64key = bytes_to_num(key, 6); + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + iso14a_card_select_t card_info; + uint32_t cuid = 0; + if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { + retval = PM3_ESOFT; + goto OUT; + } + + uint8_t key_auth_cmd = MIFARE_AUTH_KEYA + (key_type & 1); + if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL, NULL)) { + if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); + retval = PM3_ESOFT; + goto OUT; + }; + + uint32_t nt = 0; + uint8_t enc_counter = 0; + uint32_t ntenc = 0; + uint32_t oldntenc = 0; + for (uint8_t i = 0; i < 3; i++) { + if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_NESTED, &nt, &ntenc, NULL)) { + if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); + retval = PM3_ESOFT; + goto OUT; + }; + + if (g_dbglevel >= DBG_INFO) + Dbprintf("nt: %x, nt encoded: %x", nt, ntenc); + + if (oldntenc == 0) + oldntenc = ntenc; + else if (ntenc == oldntenc) + enc_counter++; + } + + if (enc_counter) { + data[0] = NONCE_STATIC_ENC; + } else { + data[0] = NONCE_NORMAL; + } + +OUT: + crypto1_deinit(pcs); + + reply_ng(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, retval, data, sizeof(data)); + // turns off + OnSuccessMagic(); + BigBuf_free(); +} + void OnSuccessMagic(void) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 52bc37f35..64df74f97 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -49,6 +49,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work wi void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); void MifareCIdent(bool is_mfc); // is "magic chinese" card? void MifareHasStaticNonce(void); // Has the tag a static nonce? +void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *key); // Has the tag a static encrypted nonce? // MFC GEN3 int DoGen3Cmd(uint8_t *cmd, uint8_t cmd_len); diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 581efda8f..3258007e3 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -142,9 +142,9 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); } 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) { - return mifare_classic_authex_cmd(pcs, uid, blockNo, (keyType & 1) ? MIFARE_AUTH_KEYB : MIFARE_AUTH_KEYA, ui64Key, isNested, ntptr, timing); + return mifare_classic_authex_cmd(pcs, uid, blockNo, (keyType & 1) ? MIFARE_AUTH_KEYB : MIFARE_AUTH_KEYA, ui64Key, isNested, ntptr, NULL, timing); } -int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { +int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *ntencptr, uint32_t *timing) { // "random" reader nonce: uint8_t nr[4]; @@ -159,6 +159,8 @@ int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t bl // Save the tag nonce (nt) uint32_t nt = bytes_to_num(receivedAnswer, 4); + if (ntencptr) + *ntencptr = nt; // ----------------------------- crypto1 create if (isNested) diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 1e45d50be..e7ee0f7f9 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -72,7 +72,7 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t // mifare classic 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_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing); +int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *ntencptr, uint32_t *timing); int mifare_classic_readblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData); int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 85ecd8033..d65e48040 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -39,6 +39,7 @@ #include "cmdhw.h" // set_fpga_mode #include "loclass/cipherutils.h" // BitstreamOut_t #include "proxendian.h" +#include "preferences.h" #include "mifare/gen4.h" static int CmdHelp(const char *Cmd); @@ -8795,10 +8796,209 @@ static int CmdHFMFHidEncode(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14AMfInfo(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf info", + "Information and check vulnerabilities in the mfc card\n" + "To check some of them need to specify key and/or specific keys in the copmmand line", + "hf mf info -k ffffffff -nv\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_int0(NULL, "blk", "", "block number"), + arg_lit0("a", NULL, "input key type is key A (def)"), + arg_lit0("b", NULL, "input key type is key B"), + arg_str0("k", "key", "", "key, 6 hex bytes"), + arg_lit0("n", "nack", "do nack test"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int blockn = arg_get_int_def(ctx, 1, 0); + + uint8_t keytype = MF_KEY_A; + if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "Input key type must be A or B"); + return PM3_EINVARG; + } else if (arg_get_lit(ctx, 3)) { + keytype = MF_KEY_B; + } + + int keylen = 0; + uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + CLIGetHexWithReturn(ctx, 4, key, &keylen); + + bool do_nack_test = arg_get_lit(ctx, 5); + bool verbose = arg_get_lit(ctx, 6); + CLIParserFree(ctx); + + uint8_t dbg_curr = DBG_NONE; + if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) + return PM3_EFAILED; + + if (keylen != 0 && keylen != 6) { + PrintAndLogEx(ERR, "Key length must be 6 bytes"); + return PM3_EINVARG; + } + + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) { + PrintAndLogEx(DEBUG, "iso14443a card select timeout"); + return 0; + } + + iso14a_card_select_t card; + memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); + + /* + 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(DEBUG, "iso14443a card select failed"); + return select_status; + } + + if (select_status == 3) { + PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision"); + + if (verbose) { + PrintAndLogEx(SUCCESS, "ATQA: %02X %02X", card.atqa[1], card.atqa[0]); + } + + return select_status; + } + + PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") "---------------------"); + 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]); + + if (setDeviceDebugLevel(verbose ? DBG_INFO : DBG_NONE, false) != PM3_SUCCESS) + return PM3_EFAILED; + + PrintAndLogEx(INFO, "--- " _CYAN_("Backdoors Information") "---------------------"); + if (detect_mf_magic(true) == 0) + PrintAndLogEx(INFO, ""); + + PrintAndLogEx(INFO, "--- " _CYAN_("Keys Information") "---------------------"); + uint8_t fkey[MIFARE_KEY_SIZE] = {0}; + uint8_t fKeyType = 0xff; + + int sectorsCnt = 1; + uint8_t *keyBlock = NULL; + uint32_t keycnt = 0; + int res = mfLoadKeys(&keyBlock, &keycnt, NULL, 0, NULL, 0); + if (res != PM3_SUCCESS) { + return res; + } + + // create/initialize key storage structure + sector_t *e_sector = NULL; + if (initSectorTable(&e_sector, sectorsCnt) != PM3_SUCCESS) { + free(keyBlock); + return PM3_EMALLOC; + } + res = mfCheckKeys_fast(sectorsCnt, true, true, 1, keycnt, keyBlock, e_sector, false); + if (res == PM3_SUCCESS) { + uint8_t blockdata[MFBLOCK_SIZE] = {0}; + + if (e_sector[0].foundKey[0]) { + PrintAndLogEx(SUCCESS, "Sector 0 key A... %12llx", e_sector[0].Key[0]); + + num_to_bytes(e_sector[0].Key[0], MIFARE_KEY_SIZE, fkey); + if (mfReadBlock(0, MF_KEY_A, key, blockdata) == PM3_SUCCESS) + fKeyType = MF_KEY_A; + } + + if (e_sector[0].foundKey[1]) { + PrintAndLogEx(SUCCESS, "Sector 0 key B... %12llx", e_sector[0].Key[1]); + + if (fKeyType == 0xff) { + num_to_bytes(e_sector[0].Key[1], MIFARE_KEY_SIZE, fkey); + if (mfReadBlock(0, MF_KEY_B, key, blockdata) == PM3_SUCCESS) + fKeyType = MF_KEY_B; + } + } + + if (fKeyType != 0xff) + PrintAndLogEx(SUCCESS, "Block 0.......... %s", sprint_hex(blockdata, MFBLOCK_SIZE)); + } + + free(keyBlock); + free(e_sector); + + PrintAndLogEx(INFO, "--- " _CYAN_("RNG Information") "---------------------"); + + res = detect_classic_static_nonce(); + if (res == NONCE_STATIC) + PrintAndLogEx(SUCCESS, "Static nonce: " _YELLOW_("yes")); + + if (res == NONCE_FAIL && verbose) + PrintAndLogEx(SUCCESS, "Static nonce: " _RED_("read failed")); + + if (res == NONCE_NORMAL) { + // not static + res = detect_classic_prng(); + if (res == 1) + PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_("weak")); + else if (res == 0) + PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_("hard")); + else + PrintAndLogEx(FAILED, "Prng detection: " _RED_("fail")); + + + // detect static encrypted nonce + if (keylen == 6) { + res = detect_classic_static_encrypted_nonce(blockn, keytype, key); + if (res == NONCE_STATIC) { + PrintAndLogEx(SUCCESS, "Static nested nonce: " _YELLOW_("yes")); + fKeyType = 0xff; // dont detect twice + } + if (res == NONCE_STATIC_ENC) { + PrintAndLogEx(SUCCESS, "Static encrypted nonce: " _YELLOW_("yes")); + fKeyType = 0xff; // dont detect twice + } + } + if (fKeyType != 0xff) { + res = detect_classic_static_encrypted_nonce(0, fKeyType, fkey); + if (res == NONCE_STATIC) + PrintAndLogEx(SUCCESS, "Static nested nonce: " _YELLOW_("yes")); + if (res == NONCE_STATIC_ENC) + PrintAndLogEx(SUCCESS, "Static encrypted nonce: " _YELLOW_("yes")); + } + + if (do_nack_test) + detect_classic_nackbug(verbose); + } + + uint8_t signature[32] = {0}; + res = read_mfc_ev1_signature(signature); + if (res == PM3_SUCCESS) { + PrintAndLogEx(INFO, "--- " _CYAN_("Signature Information") "---------------------"); + mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature)); + } + + if (setDeviceDebugLevel(dbg_curr, false) != PM3_SUCCESS) + return PM3_EFAILED; + + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("recovery") " -----------------------"}, + {"info", CmdHF14AMfInfo, IfPm3Iso14443a, "mfc card Info"}, {"darkside", CmdHF14AMfDarkside, IfPm3Iso14443a, "Darkside attack"}, {"nested", CmdHF14AMfNested, IfPm3Iso14443a, "Nested attack"}, {"hardnested", CmdHF14AMfNestedHard, AlwaysAvailable, "Nested attack for hardened MIFARE Classic cards"}, diff --git a/client/src/cmdhw.c b/client/src/cmdhw.c index b355e66cb..184aa58e8 100644 --- a/client/src/cmdhw.c +++ b/client/src/cmdhw.c @@ -31,6 +31,7 @@ #include "cmdhw.h" #include "cmddata.h" #include "commonutil.h" +#include "preferences.h" #include "pm3_cmd.h" #include "pmflash.h" // rdv40validation_t #include "cmdflashmem.h" // get_signature.. @@ -476,14 +477,9 @@ static int CmdDbg(const char *Cmd) { return PM3_EINVARG; } - clearCommandBuffer(); - SendCommandNG(CMD_GET_DBGMODE, NULL, 0); - PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_GET_DBGMODE, &resp, 2000) == false) { - PrintAndLogEx(WARNING, "Failed to get current device debug level"); - return PM3_ETIMEOUT; - } - uint8_t curr = resp.data.asBytes[0]; + uint8_t curr = DBG_NONE; + if (getDeviceDebugLevel(&curr) != PM3_SUCCESS) + return PM3_EFAILED; const char *dbglvlstr; switch (curr) { @@ -522,8 +518,8 @@ static int CmdDbg(const char *Cmd) { else if (lv4) dbg = 4; - clearCommandBuffer(); - SendCommandNG(CMD_SET_DBGMODE, &dbg, sizeof(dbg)); + if (setDeviceDebugLevel(dbg, true) != PM3_SUCCESS) + return PM3_EFAILED; } return PM3_SUCCESS; } diff --git a/client/src/mifare/mifaredefault.h b/client/src/mifare/mifaredefault.h index 0a631a765..d94aae269 100644 --- a/client/src/mifare/mifaredefault.h +++ b/client/src/mifare/mifaredefault.h @@ -55,7 +55,9 @@ static const uint64_t g_mifare_default_keys[] = { 0xffffffffffff, // Default key (first key used by program if no user defined key) - 0xa0a1a2a3a4a5, // NFCForum MAD key + 0xa0a1a2a3a4a5, // NFCForum MAD key A + 0xb0b1b2b3b4b5, // NFCForum MAD key B + 0x89ECA97F8C2A, // NFCForum MAD key B 0xd3f7d3f7d3f7, // NDEF public key 0x4b791bea7bcc, // MFC EV1 Signature 17 B 0x5C8FF9990DA2, // MFC EV1 Signature 16 A @@ -95,13 +97,12 @@ static const uint64_t g_mifare_default_keys[] = { 0x11496F97752A, // HID 0x3E65E4FB65B3, // Gym 0x000000000000, // Blank key - 0xb0b1b2b3b4b5, - 0xaabbccddeeff, + 0x010203040506, 0x1a2b3c4d5e6f, 0x123456789abc, - 0x010203040506, 0x123456abcdef, 0xabcdef123456, + 0xaabbccddeeff, 0x4d3a99c351dd, 0x1a982c7e459a, 0x714c5c886e97, diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index f28f38aaa..8c129b8d9 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -1349,6 +1349,33 @@ int detect_classic_static_nonce(void) { return NONCE_FAIL; } +/* Detect Mifare Classic static encrypted nonce +detects special magic cards that has a static / fixed nonce +returns: +0 = nonce ok +1 = has static/fixed nonce +2 = cmd failed +3 = has encrypted nonce +*/ +int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, uint8_t *key) { + + clearCommandBuffer(); + uint8_t cdata[1 + 1 + MIFARE_KEY_SIZE] = {0}; + cdata[0] = block_no; + cdata[1] = key_type; + memcpy(&cdata[2], key, MIFARE_KEY_SIZE); + SendCommandNG(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, cdata, sizeof(cdata)); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, &resp, 1000)) { + + if (resp.status == PM3_ESOFT) + return NONCE_FAIL; + + return resp.data.asBytes[0]; + } + return NONCE_FAIL; +} + /* try to see if card responses to "Chinese magic backdoor" commands. */ int detect_mf_magic(bool is_mfc) { diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index 6f131f924..5eacabda3 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -102,6 +102,7 @@ int detect_classic_prng(void); int detect_classic_nackbug(bool verbose); int detect_mf_magic(bool is_mfc); int detect_classic_static_nonce(void); +int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, uint8_t *key); bool detect_mfc_ev1_signature(void); int read_mfc_ev1_signature(uint8_t *signature); diff --git a/client/src/preferences.c b/client/src/preferences.c index dd697da74..4effb1bef 100644 --- a/client/src/preferences.c +++ b/client/src/preferences.c @@ -762,6 +762,44 @@ static int setCmdDeviceDebug (const char *Cmd) } */ +int getDeviceDebugLevel (uint8_t *debug_level) { + if (!g_session.pm3_present) + return PM3_EFAILED; + + clearCommandBuffer(); + SendCommandNG(CMD_GET_DBGMODE, NULL, 0); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_GET_DBGMODE, &resp, 2000) == false) { + PrintAndLogEx(WARNING, "Failed to get current device debug level"); + return PM3_ETIMEOUT; + } + + if (debug_level) + *debug_level = resp.data.asBytes[0]; + + return PM3_SUCCESS; +} + +int setDeviceDebugLevel (uint8_t debug_level, bool verbose) { + if (!g_session.pm3_present) + return PM3_EFAILED; + + if (verbose) + PrintAndLogEx (INFO,"setting device debug loglevel to %u", debug_level); + + uint8_t cdata[] = {debug_level, verbose}; + clearCommandBuffer(); + SendCommandNG(CMD_SET_DBGMODE, cdata, sizeof(cdata)); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_SET_DBGMODE, &resp, 2000) == false) { + PrintAndLogEx (WARNING,"failed to set device debug loglevel"); + return PM3_EFAILED; + } + + return PM3_SUCCESS; +} + + static int setCmdOutput(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "prefs set output", diff --git a/client/src/preferences.h b/client/src/preferences.h index 56ba72fa3..74e3bc2a8 100644 --- a/client/src/preferences.h +++ b/client/src/preferences.h @@ -31,4 +31,7 @@ int preferences_save(void); void preferences_save_callback(json_t *root); void preferences_load_callback(json_t *root); +int getDeviceDebugLevel (uint8_t *debug_level); +int setDeviceDebugLevel (uint8_t debug_level, bool verbose); + #endif diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 9189704e4..33803857d 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -675,6 +675,7 @@ typedef struct { #define CMD_HF_MIFARE_NACK_DETECT 0x0730 #define CMD_HF_MIFARE_STATIC_NONCE 0x0731 +#define CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE 0x0732 // MFU OTP TearOff #define CMD_HF_MFU_OTP_TEAROFF 0x0740 @@ -740,9 +741,10 @@ typedef struct { #define MODE_FULLSIM 2 // Static Nonce detection -#define NONCE_FAIL 0x01 -#define NONCE_NORMAL 0x02 -#define NONCE_STATIC 0x03 +#define NONCE_FAIL 0x01 +#define NONCE_NORMAL 0x02 +#define NONCE_STATIC 0x03 +#define NONCE_STATIC_ENC 0x04 // Dbprintf flags #define FLAG_RAWPRINT 0x00