Merge branch 'unisniff' of https://github.com/hazardousvoltage/proxmark3 into unisniff

This commit is contained in:
Anonymous
2023-12-03 08:46:26 -05:00
12 changed files with 568 additions and 98 deletions
+2
View File
@@ -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]
- Added encryption and other SL3 functions for Mifare Plus - more to come (@team-orangeBlue)
- Fixed the corrupted data in real-time sampling (@wh201906)
- Added a slider in the plot window for navigation (@wh201906)
- Fixed client build bug with Python 3.12 (@wh201906)
- Fixed `ExchangeAPDUSC()` in `cmdsmartcard.c` to prevent client crash (@wh201906)
-6
View File
@@ -24,12 +24,6 @@
#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
#define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
// definitions for multiple FPGA config files support
#define FPGA_BITSTREAM_LF 1
#define FPGA_BITSTREAM_HF 2
#define FPGA_BITSTREAM_HF_FELICA 3
#define FPGA_BITSTREAM_HF_15 4
/*
Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand()
Send 16 bit command / data pair to FPGA with the bit format:
+127 -5
View File
@@ -1331,8 +1331,56 @@ void annotateMfPlus(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
case MFP_AUTHENTICATEFIRST_VARIANT:
if (data_size > 1) {
// key : uint16_t uKeyNum = 0x4000 + sectorNum * 2 + (keyB ? 1 : 0);
uint16_t uKeyNum = MemLeToUint2byte(data) ;
snprintf(exp, size, "FIRST AUTH (Keynr 0x%04X: %c sector %d)", uKeyNum, uKeyNum & 0x0001 ? 'B' : 'A', (uKeyNum - 0x4000) / 2);
uint16_t uKeyNum = MemLeToUint2byte(data);
switch (uKeyNum & 0xf000){
const char* stringdata;
default:
stringdata = "FIRST AUTH (Keynr 0x%04X: Key not identified)";
snprintf(exp, strlen(stringdata)+1, stringdata, uKeyNum);
break;
case 0x4000:
snprintf(exp, size, "FIRST AUTH (Keynr 0x%04X: %c sector %d)", uKeyNum, uKeyNum & 0x0001 ? 'B' : 'A', (uKeyNum - 0x4000) / 2);
break;
case 0xA000: // There are virtual card encryption and MACing keys, but this is NOT their place!
stringdata = "FIRST AUTH(Keynr 0x%04X: Proximity Check Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uKeyNum);
break;
case 0x9000:
switch (uKeyNum & 0xf){
case 0x0:
stringdata = "FIRST AUTH (Keynr 0x%04X: Card Master Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uKeyNum);
break;
case 0x1:
stringdata = "FIRST AUTH (Keynr 0x%04X: Card Configuration Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uKeyNum);
break;
case 0x2:
stringdata = "FIRST AUTH(Keynr 0x%04X: SL2 Switch Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uKeyNum);
break;
case 0x3:
stringdata = "FIRST AUTH(Keynr 0x%04X: SL3 Switch Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uKeyNum);
break;
case 0x4:
stringdata = "FIRST AUTH(Keynr 0x%04X: SL1 Additional Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uKeyNum);
break;
case 0x6:
stringdata = "FIRST AUTH(Keynr 0x%04X: SL3 Sector Switch Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uKeyNum);
break;
case 0x7:
stringdata = "FIRST AUTH(Keynr 0x%04X: SL1SL3Mix Sector Switch Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uKeyNum);
break;
default:
stringdata = "FIRST AUTH(Keynr 0x%04X: Management Key not identified)";
snprintf(exp, strlen(stringdata)+1, stringdata, uKeyNum);
break;
}
}
} else {
snprintf(exp, size, "FIRST AUTH") ;
}
@@ -1341,7 +1389,7 @@ void annotateMfPlus(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
case MFP_WRITEPERSO:
if (data_size > 1) {
uint16_t uKeyNum = MemLeToUint2byte(data) ;
snprintf(exp, size, "WRITE PERSO (Keynr 0x%04X)", uKeyNum);
snprintf(exp, size, "WRITE PERSO (Addr 0x%04X)", uKeyNum);
} else {
snprintf(exp, size, "WRITE PERSO");
}
@@ -1381,8 +1429,82 @@ void annotateMfPlus(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
const char *responseMaced = mfpGetResponseMacedForCode(opcode) ;
if (data_size > 1) {
uint16_t uBlockNum = MemLeToUint2byte(data) ;
snprintf(exp, size, "WRITE %s(%u) %s", encrypted, uBlockNum, responseMaced);
uint16_t uBlockNum = MemLeToUint2byte(data);
switch (uBlockNum & 0xF000){
const char* stringdata;
default:
stringdata = "WRITE %s(%u) %s";
snprintf(exp, size, stringdata, encrypted, uBlockNum, responseMaced);
break;
case 0x4000:
snprintf(exp, size, "WRITE (Keynr 0x%04X: %c sector %d)", uBlockNum, uBlockNum & 0x0001 ? 'B' : 'A', (uBlockNum - 0x4000) / 2);
break;
case 0xA000: // There are virtual card encryption and MACing keys, but this is NOT their place!
stringdata = "WRITE(Keynr 0x%04X: Proximity Check Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
case 0xB000:
case 0x9000:
if ((uBlockNum & 0x2000) == 0x2000){
switch (uBlockNum & 0xf){
default:
stringdata = "WRITE(Config %04X: Unidentified)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
case 0x0:
stringdata = "WRITE(Config %04X: Config)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
case 0x1:
stringdata = "WRITE(Config %04X: Virtual Card Installation ID)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
case 0x2:
stringdata = "WRITE(Config %04X: ATS)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
case 0x3:
stringdata = "WRITE(Config %04X: Field configuration)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
}
} else {
switch (uBlockNum & 0xf){
default:
stringdata = "WRITE(Keynr 0x%04X: Management Key not identified)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
case 0x0:
stringdata = "WRITE(Keynr 0x%04X: Card Master Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
case 0x1:
stringdata = "WRITE(Keynr 0x%04X: Card Configuration Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
case 0x2:
stringdata = "WRITE(Keynr 0x%04X: SL2 Switch Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
case 0x3:
stringdata = "WRITE(Keynr 0x%04X: SL3 Switch Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
case 0x4:
stringdata = "WRITE(Keynr 0x%04X: SL1 Additional Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
case 0x6:
stringdata = "WRITE(Keynr 0x%04X: SL3 Sector Switch Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
case 0x7:
stringdata = "WRITE(Keynr 0x%04X: SL1SL3Mix Sector Switch Key)";
snprintf(exp, strlen(stringdata)+1, stringdata, uBlockNum);
break;
}
}
}
} else {
snprintf(exp, size, "WRITE %s %s ?", encrypted, responseMaced);
}
+2 -2
View File
@@ -4249,7 +4249,7 @@ int CmdHF14AMfELoad(const char *Cmd) {
// ICEMAN: bug. if device has been using ICLASS commands,
// the device needs to load the HF fpga image. It takes 1.5 second.
set_fpga_mode(2);
set_fpga_mode(FPGA_BITSTREAM_HF);
// use RDV4 spiffs
if (use_spiffs && IfPm3Flash() == false) {
@@ -8006,7 +8006,7 @@ static int CmdHF14AGen4Save(const char *Cmd) {
// ICEMAN: bug. if device has been using ICLASS commands,
// the device needs to load the HF fpga image. It takes 1.5 second.
set_fpga_mode(2);
set_fpga_mode(FPGA_BITSTREAM_HF);
// validations
if (pwd_len != 4 && pwd_len != 0) {
+316 -46
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1105,7 +1105,7 @@ static int CmdBreak(const char *Cmd) {
}
int set_fpga_mode(uint8_t mode) {
if (mode < 1 || mode > 4) {
if (mode < FPGA_BITSTREAM_LF || mode > FPGA_BITSTREAM_HF_15) {
return PM3_EINVARG;
}
uint8_t d[] = {mode};
+23 -10
View File
@@ -30,6 +30,7 @@
#include "cliparser.h" // args parsing
#include "graph.h" // for graph data
#include "cmddata.h" // for `lf search`
#include "cmdhw.h" // for setting FPGA image
#include "cmdlfawid.h" // for awid menu
#include "cmdlfem.h" // for em menu
#include "cmdlfem410x.h" // for em4x menu
@@ -725,15 +726,23 @@ static int lf_read_internal(bool realtime, bool verbose, uint64_t samples) {
size_t sample_bytes = samples * bits_per_sample;
sample_bytes = (sample_bytes / 8) + (sample_bytes % 8 != 0);
// In real-time mode, the LF bitstream should be loaded before receiving raw data.
// Otherwise, the first batch of raw data might contain the response of CMD_WTX.
int result = set_fpga_mode(FPGA_BITSTREAM_LF);
if (result != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "failed to load LF bitstream to FPGA");
return result;
}
SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
if (is_trigger_threshold_set) {
size_t first_receive_len = 32; // larger than the response of CMD_WTX
size_t first_receive_len = 32;
// Wait until a bunch of data arrives
first_receive_len = WaitForRawDataTimeout(realtimeBuf, first_receive_len, -1, false);
sample_bytes = WaitForRawDataTimeout(realtimeBuf + first_receive_len, sample_bytes - first_receive_len, 1000 + FPGA_LOAD_WAIT_TIME, true);
sample_bytes = WaitForRawDataTimeout(realtimeBuf + first_receive_len, sample_bytes - first_receive_len, 1000, true);
sample_bytes += first_receive_len;
} else {
sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000 + FPGA_LOAD_WAIT_TIME, true);
sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000, true);
}
samples = sample_bytes * 8 / bits_per_sample;
PrintAndLogEx(INFO, "Done: %" PRIu64 " samples (%zu bytes)", samples, sample_bytes);
@@ -767,8 +776,6 @@ int lf_read(bool verbose, uint64_t samples) {
}
int CmdLFRead(const char *Cmd) {
// In real-time mode, the first few bytes might be the response of CMD_WTX
// rather than the real samples if the LF FPGA image is not ready.
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf read",
"Sniff low frequency signal.\n"
@@ -837,15 +844,23 @@ int lf_sniff(bool realtime, bool verbose, uint64_t samples) {
size_t sample_bytes = samples * bits_per_sample;
sample_bytes = (sample_bytes / 8) + (sample_bytes % 8 != 0);
// In real-time mode, the LF bitstream should be loaded before receiving raw data.
// Otherwise, the first batch of raw data might contain the response of CMD_WTX.
int result = set_fpga_mode(FPGA_BITSTREAM_LF);
if (result != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "failed to load LF bitstream to FPGA");
return result;
}
SendCommandNG(CMD_LF_SNIFF_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
if (is_trigger_threshold_set) {
size_t first_receive_len = 32; // larger than the response of CMD_WTX
size_t first_receive_len = 32;
// Wait until a bunch of data arrives
first_receive_len = WaitForRawDataTimeout(realtimeBuf, first_receive_len, -1, false);
sample_bytes = WaitForRawDataTimeout(realtimeBuf + first_receive_len, sample_bytes - first_receive_len, 1000 + FPGA_LOAD_WAIT_TIME, true);
sample_bytes = WaitForRawDataTimeout(realtimeBuf + first_receive_len, sample_bytes - first_receive_len, 1000, true);
sample_bytes += first_receive_len;
} else {
sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000 + FPGA_LOAD_WAIT_TIME, true);
sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000, true);
}
samples = sample_bytes * 8 / bits_per_sample;
PrintAndLogEx(INFO, "Done: %" PRIu64 " samples (%zu bytes)", samples, sample_bytes);
@@ -875,8 +890,6 @@ int lf_sniff(bool realtime, bool verbose, uint64_t samples) {
}
int CmdLFSniff(const char *Cmd) {
// In real-time mode, the first few bytes might be the response of CMD_WTX
// rather than the real samples if the LF FPGA image is not ready.
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf sniff",
"Sniff low frequency signal. You need to configure the LF part on the Proxmark3 device manually.\n"
+23 -15
View File
@@ -258,9 +258,9 @@ int MifareAuth4(mf4Session_t *mf4session, uint8_t *keyn, uint8_t *key, bool acti
memmove(&raw[16], &RndB[1], 16);
aes_encode(NULL, key, raw, &cmd2[1], 32);
if (verbose)
if (verbose){
PrintAndLogEx(INFO, ">phase2: %s", sprint_hex(cmd2, 33));
}
res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen, silentMode);
if (res) {
if (!silentMode) PrintAndLogEx(ERR, "Exchange raw error: %d", res);
@@ -372,26 +372,34 @@ int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int
return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen);
}
int MFPReadBlock(mf4Session_t *mf4session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) {
uint8_t rcmd[4 + 8] = {(plain ? (0x37) : (0x33)), blockNum, 0x00, blockCount};
if (!plain && mf4session)
CalculateMAC(mf4session, mtypReadCmd, blockNum, blockCount, rcmd, 4, &rcmd[4], g_verbose_mode);
int res = intExchangeRAW14aPlus(rcmd, plain ? 4 : sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen);
int MFPReadBlock(mf4Session_t *mf4session, bool plain, bool nomaccmd, bool nomacres, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) {
int cmdb = 0x31;
if (nomacres){cmdb = cmdb ^ 0x01;} // If we do not want MAC in reply, remove 0x01
if (plain){cmdb = cmdb ^ 0x02;} // If we do not need an encrypted transmission, add 0x02
if (nomaccmd){cmdb = cmdb ^ 0x04;} // If we do not want to send a MAC, remove 0x04
uint8_t rcmd1[4] = {cmdb, blockNum, 0x00, blockCount};
uint8_t maccmddat[8] = {0};
uint8_t rcmd[nomaccmd ? 4 : 12];
if (!nomaccmd && mf4session)
CalculateMAC(mf4session, mtypReadCmd, blockNum, blockCount, rcmd1, 4, &maccmddat[0], g_verbose_mode);
memmove(rcmd, rcmd1, 4);
if (!nomaccmd){memmove(&rcmd[4], maccmddat, 8);}
int res = intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen);
if (res)
return res;
if (mf4session)
mf4session->R_Ctr++;
if (mf4session && mac && *dataoutlen > 11)
if (mf4session && !nomacres && *dataoutlen > 11)
CalculateMAC(mf4session, mtypReadResp, blockNum, blockCount, dataout, *dataoutlen - 8 - 2, mac, g_verbose_mode);
return 0;
}
int MFPWriteBlock(mf4Session_t *mf4session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) {
uint8_t rcmd[1 + 2 + 16 + 8] = {0xA3, blockNum, 0x00};
int MFPWriteBlock(mf4Session_t *mf4session, bool plain, bool nomacres, uint8_t blockNum, uint8_t blockHdr, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) {
int cmdb = 0xA1;
if (nomacres){cmdb = cmdb ^ 0x01;} // If we do not want MAC in reply, remove 0x01
if (plain){cmdb = cmdb ^ 0x02;} // If we do not need an encrypted transmission, add 0x02
uint8_t rcmd[1 + 2 + 16 + 8] = {cmdb, blockNum, blockHdr};
memmove(&rcmd[3], data, 16);
if (mf4session)
CalculateMAC(mf4session, mtypWriteCmd, blockNum, 1, rcmd, 19, &rcmd[19], g_verbose_mode);
@@ -403,7 +411,7 @@ int MFPWriteBlock(mf4Session_t *mf4session, uint8_t blockNum, uint8_t *data, boo
if (mf4session)
mf4session->W_Ctr++;
if (mf4session && mac && *dataoutlen > 3)
if (mf4session && mac && *dataoutlen > 3 && !nomacres)
CalculateMAC(mf4session, mtypWriteResp, blockNum, 1, dataout, *dataoutlen, mac, g_verbose_mode);
return 0;
@@ -431,7 +439,7 @@ int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data
uint8_t mac[8] = {0};
uint8_t firstBlockNo = mfFirstBlockOfSector(sectorNo);
for (int n = firstBlockNo; n < firstBlockNo + mfNumBlocksPerSector(sectorNo); n++) {
res = MFPReadBlock(&_session, plain, n & 0xff, 1, false, true, data, sizeof(data), &datalen, mac);
res = MFPReadBlock(&_session, plain, false, false, n & 0xff, 1, false, true, data, sizeof(data), &datalen, mac);
if (res) {
PrintAndLogEx(ERR, "Sector %u read error: %d", sectorNo, res);
DropField();
+2 -2
View File
@@ -63,8 +63,8 @@ int MifareAuth4(mf4Session_t *mf4session, uint8_t *keyn, uint8_t *key, bool acti
int MFPWritePerso(uint8_t *keyNum, uint8_t *key, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
int MFPReadBlock(mf4Session_t *mf4session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac);
int MFPWriteBlock(mf4Session_t *mf4session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac);
int MFPReadBlock(mf4Session_t *mf4session, bool plain, bool maccmd, bool macres, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac);
int MFPWriteBlock(mf4Session_t *mf4session, bool plain, bool nomacres, uint8_t blockNum, uint8_t blockHdr, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac);
int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *dataout, bool verbose);
int MFPGetSignature(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
+65 -11
View File
@@ -6247,6 +6247,32 @@
],
"usage": "hf mfp auth [-hv] --ki <hex> --key <hex>"
},
"hf mfp chconf": {
"command": "hf mfp chconf",
"description": "Change the configuration on a Mifare Plus tag. DANGER!",
"notes": [
"This requires Card Master Key (9000) or Card Configuration Key (9001).",
"Configuration block info can be found below.",
"* Block B000 (00; CMK): Max amount of commands without MAC (byte 0), as well as plain mode access (unknown).",
"* Block B001 (01; CCK): Installation identifier for Virtual Card. Please consult NXP for data.",
"* Block B002 (02; CCK): ATS data.",
"* Block B003 (03; CCK): Use Random ID in SL3, decide whether proximity check is mandatory.",
" * DO NOT WRITE THIS BLOCK UNDER ANY CIRCUMSTANCES! Risk of bricking.",
"More configuration tips to follow. Check JMY600 Series IC Card Module.",
"hf mfp chconf -c 00 -d 10ffffffffffffffffffffffffffffff --key A0A1A2A3A4A5A6A7A0A1A2A3A4A5A6A7 -> Allow 16 commands without MAC in a single transaction."
],
"offline": false,
"options": [
"-h, --help This help",
"-v, --verbose Verbose mode",
"--nmr Do not expect MAC in response",
"-c, --conf <hex> Config block number, 0-3",
"-k, --key <hex> Card key, 16 hex bytes",
"--cck Auth as Card Configuration key instead of Card Master Key",
"-d, --data <hex> New configuration data, 16 hex bytes"
],
"usage": "hf mfp chconf [-hv] [--nmr] -c <hex> [-k <hex>] [--cck] -d <hex>"
},
"hf mfp chk": {
"command": "hf mfp chk",
"description": "Checks keys on MIFARE Plus card",
@@ -6274,6 +6300,26 @@
],
"usage": "hf mfp chk [-habv] [-s <0..255>] [-e <0..255>] [-k <hex>] [-d <fn>] [--pattern1b] [--pattern2b] [--startp2b <pattern>] [--dump]"
},
"hf mfp chkey": {
"command": "hf mfp chkey",
"description": "Change the keys on a Mifare Plus tag",
"notes": [
"This requires the key that can update the key that you are trying to update.",
"hf mfp chkey --ki 401f -d FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF --key A0A1A2A3A4A5A6A7A0A1A2A3A4A5A6A7 -> Change key B for Sector 15 from MAD to default",
"hf mfp chkey --ki 9000 -d 32F9351A1C02B35FF97E0CA943F814F6 --key FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -> Change card master key to custom from default"
],
"offline": false,
"options": [
"-h, --help This help",
"-v, --verbose Verbose mode",
"--nmr Do not expect MAC in response",
"--ki <hex> Key Index, 2 hex bytes",
"-k, --key <hex> Current sector key, 16 hex bytes",
"-b, --typeb Sector key is key B",
"-d, --data <hex> New key, 16 hex bytes"
],
"usage": "hf mfp chkey [-hvb] [--nmr] --ki <hex> [-k <hex>] -d <hex>"
},
"hf mfp commitp": {
"command": "hf mfp commitp",
"description": "Executes Commit Perso command. Can be used in SL0 mode only. OBS! This command will not be executed if CardConfigKey, CardMasterKey and L3SwitchKey AES keys are not written.",
@@ -6436,11 +6482,13 @@
"-v, --verbose Verbose mode",
"-n, --count <dec> Blocks count (def: 1)",
"-b, --keyb Use key B (def: keyA)",
"-p, --plain Plain communication mode between reader and card",
"-p, --plain Do not use encrypted transmission between reader and card",
"--nmc Do not append MAC to command",
"--nmr Do not expect MAC in reply",
"--blk <0..255> Block number",
"-k, --key <hex> Key, 16 hex bytes"
],
"usage": "hf mfp rdbl [-hvbp] [-n <dec>] --blk <0..255> [-k <hex>]"
"usage": "hf mfp rdbl [-hvbp] [-n <dec>] [--nmc] [--nmr] --blk <0..255> [-k <hex>]"
},
"hf mfp rdsc": {
"command": "hf mfp rdsc",
@@ -6454,11 +6502,13 @@
"-h, --help This help",
"-v, --verbose Verbose mode",
"-b, --keyb Use key B (def: keyA)",
"-p, --plain Plain communication mode between reader and card",
"-p, --plain Do not use encrypted transmission between reader and card",
"--nmc Do not append MAC to command",
"--nmr Do not expect MAC in reply",
"-s, --sn <0..255> Sector number",
"-k, --key <hex> Key, 16 hex bytes"
],
"usage": "hf mfp rdsc [-hvbp] -s <0..255> [-k <hex>]"
"usage": "hf mfp rdsc [-hvbp] [--nmc] [--nmr] -s <0..255> [-k <hex>]"
},
"hf mfp wrbl": {
"command": "hf mfp wrbl",
@@ -6473,26 +6523,30 @@
"-v, --verbose Verbose mode",
"-b, --keyb Use key B (def: keyA)",
"--blk <0..255> Block number",
"-p, --plain Do not use encrypted transmission",
"--nmr Do not expect MAC in response",
"-d, --data <hex> Data, 16 hex bytes",
"-k, --key <hex> Key, 16 hex bytes"
],
"usage": "hf mfp wrbl [-hvb] --blk <0..255> -d <hex> [-k <hex>]"
"usage": "hf mfp wrbl [-hvbp] --blk <0..255> [--nmr] -d <hex> [-k <hex>]"
},
"hf mfp wrp": {
"command": "hf mfp wrp",
"description": "Executes Write Perso command. Can be used in SL0 mode only.",
"notes": [
"hf mfp wrp --ki 4000 --key 000102030405060708090a0b0c0d0e0f -> write key (00..0f) to key number 4000",
"hf mfp wrp --ki 4000 -> write default key(0xff..0xff) to key number 4000"
"hf mfp wrp --adr 4000 --data 000102030405060708090a0b0c0d0e0f -> write key (00..0f) to key number 4000",
"hf mfp wrp --adr 4000 -> write default key(0xff..0xff) to key number 4000",
"hf mfp wrp -a b000 -d 20FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -> allow 32 commands without MAC in configuration block (B000)",
"hf mfp wrp -a 0003 -d 1234561234567F078869B0B1B2B3B4B5 -> write crypto1 keys A: 123456123456 and B: B0B1B2B3B4B5 to block 3"
],
"offline": false,
"options": [
"-h, --help This help",
"-v, --verbose Verbose output",
"--ki <hex> Key number, 2 hex bytes",
"--key <hex> Key, 16 hex bytes"
"-a, --adr <hex> Address, 2 hex bytes",
"-d, --data <hex> Data, 16 hex bytes"
],
"usage": "hf mfp wrp [-hv] --ki <hex> [--key <hex>]"
"usage": "hf mfp wrp [-hv] -a <hex> [-d <hex>]"
},
"hf mfu cauth": {
"command": "hf mfu cauth",
@@ -12068,4 +12122,4 @@
"extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2023-12-01T14:06:40"
}
}
}
+2
View File
@@ -561,6 +561,8 @@ Check column "offline" for their availability.
|`hf mfp rdbl `|N |`Read blocks from card`
|`hf mfp rdsc `|N |`Read sectors from card`
|`hf mfp wrbl `|N |`Write block to card`
|`hf mfp chkey `|N |`Change key on card`
|`hf mfp chconf `|N |`Change config on card`
|`hf mfp commitp `|N |`Configure security layer (SL1/SL3 mode)`
|`hf mfp initp `|N |`Fill all the card's keys in SL0 mode`
|`hf mfp wrp `|N |`Write Perso command`
+5
View File
@@ -847,6 +847,11 @@ typedef struct {
# define UART_TCP_LOCAL_CLIENT_RX_TIMEOUT_MS 40
# define UART_UDP_LOCAL_CLIENT_RX_TIMEOUT_MS 20
// definitions for multiple FPGA config files support
#define FPGA_BITSTREAM_LF 1
#define FPGA_BITSTREAM_HF 2
#define FPGA_BITSTREAM_HF_FELICA 3
#define FPGA_BITSTREAM_HF_15 4
// CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
/* Whether a bootloader that understands the g_common_area is present */