mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-20 23:36:31 +08:00
commit
d1a3e8bf56
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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", "<dec>", "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", "<hex>", "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, "<none>");
|
||||
|
||||
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"},
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue