mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
Merge pull request #949 from aveao/mfucompatwrite
Introduce compatible write support to hf mfu wrbl
This commit is contained in:
commit
2990dba14f
7 changed files with 105 additions and 64 deletions
|
@ -1237,6 +1237,10 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
MifareUWriteBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
MifareUWriteBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CMD_HF_MIFAREU_WRITEBL_COMPAT: {
|
||||||
|
MifareUWriteBlockCompat(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES: {
|
case CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES: {
|
||||||
MifareAcquireEncryptedNonces(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
|
MifareAcquireEncryptedNonces(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -444,47 +444,6 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* // Command not needed but left for future testing
|
|
||||||
void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)
|
|
||||||
{
|
|
||||||
uint8_t blockNo = arg0;
|
|
||||||
uint8_t blockdata[16] = {0x00};
|
|
||||||
|
|
||||||
memcpy(blockdata, datain, 16);
|
|
||||||
|
|
||||||
uint8_t uid[10] = {0x00};
|
|
||||||
|
|
||||||
LED_A_ON(); LED_B_OFF(); LED_C_OFF();
|
|
||||||
|
|
||||||
clear_trace();
|
|
||||||
set_tracing(true);
|
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
|
||||||
|
|
||||||
if(!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) {
|
|
||||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
|
|
||||||
OnError(0);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
if(mifare_ultra_writeblock_compat(blockNo, blockdata)) {
|
|
||||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Write block error");
|
|
||||||
OnError(0);
|
|
||||||
return; };
|
|
||||||
|
|
||||||
if(mifare_ultra_halt()) {
|
|
||||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error");
|
|
||||||
OnError(0);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
|
||||||
|
|
||||||
reply_mix(CMD_ACK,1,0,0,0,0);
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
LEDsoff();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Arg0 : Block to write to.
|
// Arg0 : Block to write to.
|
||||||
// Arg1 : 0 = use no authentication.
|
// Arg1 : 0 = use no authentication.
|
||||||
// 1 = use 0x1A authentication.
|
// 1 = use 0x1A authentication.
|
||||||
|
@ -554,6 +513,75 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Arg0 : Block to write to.
|
||||||
|
// Arg1 : 0 = use no authentication.
|
||||||
|
// 1 = use 0x1A authentication.
|
||||||
|
// 2 = use 0x1B authentication.
|
||||||
|
// datain : 16 first bytes is data to be written.
|
||||||
|
// : 4/16 next bytes is authentication key.
|
||||||
|
void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
|
uint8_t blockNo = arg0;
|
||||||
|
bool useKey = (arg1 == 1); //UL_C
|
||||||
|
bool usePwd = (arg1 == 2); //UL_EV1/NTAG
|
||||||
|
uint8_t blockdata[16] = {0x00};
|
||||||
|
|
||||||
|
memcpy(blockdata, datain, 16);
|
||||||
|
|
||||||
|
LEDsoff();
|
||||||
|
LED_A_ON();
|
||||||
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
|
||||||
|
clear_trace();
|
||||||
|
set_tracing(true);
|
||||||
|
|
||||||
|
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
|
||||||
|
OnError(0);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// UL-C authentication
|
||||||
|
if (useKey) {
|
||||||
|
uint8_t key[16] = {0x00};
|
||||||
|
memcpy(key, datain + 16, sizeof(key));
|
||||||
|
|
||||||
|
if (!mifare_ultra_auth(key)) {
|
||||||
|
OnError(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UL-EV1 / NTAG authentication
|
||||||
|
if (usePwd) {
|
||||||
|
uint8_t pwd[4] = {0x00};
|
||||||
|
memcpy(pwd, datain + 16, 4);
|
||||||
|
uint8_t pack[4] = {0, 0, 0, 0};
|
||||||
|
if (!mifare_ul_ev1_auth(pwd, pack)) {
|
||||||
|
OnError(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mifare_ultra_writeblock_compat(blockNo, blockdata)) {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Write block error");
|
||||||
|
OnError(0);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (mifare_ultra_halt()) {
|
||||||
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error");
|
||||||
|
OnError(0);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||||
|
|
||||||
|
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
LEDsoff();
|
||||||
|
set_tracing(false);
|
||||||
|
}
|
||||||
|
|
||||||
void MifareUSetPwd(uint8_t arg0, uint8_t *datain) {
|
void MifareUSetPwd(uint8_t arg0, uint8_t *datain) {
|
||||||
|
|
||||||
uint8_t pwd[16] = {0x00};
|
uint8_t pwd[16] = {0x00};
|
||||||
|
|
|
@ -20,7 +20,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes);
|
||||||
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
||||||
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
//void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
|
void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
|
|
||||||
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key);
|
void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key);
|
||||||
|
|
|
@ -446,37 +446,37 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* // command not needed, but left for future testing
|
|
||||||
int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) {
|
int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) {
|
||||||
uint16_t len;
|
// variables
|
||||||
uint8_t par[3] = {0}; // enough for 18 parity bits
|
uint16_t len = 0;
|
||||||
uint8_t d_block[18] = {0x00};
|
|
||||||
uint8_t receivedAnswer[MAX_FRAME_SIZE];
|
uint8_t d_block[18];
|
||||||
uint8_t receivedAnswerPar[MAX_PARITY_SIZE];
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||||
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||||
|
|
||||||
len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
|
|
||||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
|
||||||
if (DBGLEVEL >= DBG_ERROR)
|
if (DBGLEVEL >= DBG_ERROR)
|
||||||
Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);
|
Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0], len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(d_block, blockData, 16);
|
memcpy(d_block, blockData, 16);
|
||||||
AddCrc14A(d_block, 16);
|
AddCrc14A(d_block, 16);
|
||||||
|
|
||||||
ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);
|
ReaderTransmit(d_block, sizeof(d_block), NULL);
|
||||||
|
|
||||||
|
// Receive the response
|
||||||
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||||
|
|
||||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
|
||||||
if (DBGLEVEL >= DBG_ERROR)
|
if (DBGLEVEL >= DBG_ERROR)
|
||||||
Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
|
Dbprintf("Cmd Send Data Error: %02x %d", receivedAnswer[0], len);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) {
|
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) {
|
||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
|
|
|
@ -73,7 +73,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
||||||
int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack);
|
int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack);
|
||||||
int mifare_ultra_auth(uint8_t *keybytes);
|
int mifare_ultra_auth(uint8_t *keybytes);
|
||||||
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData);
|
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData);
|
||||||
//int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData);
|
int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData);
|
||||||
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);
|
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);
|
||||||
int mifare_ultra_halt(void);
|
int mifare_ultra_halt(void);
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ static int usage_hf_mfu_wrbl(void) {
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf mfu wrbl b <block number> d <data> k <key> l\n");
|
PrintAndLogEx(NORMAL, "Usage: hf mfu wrbl b <block number> d <data> k <key> l\n");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " b <no> : block to write");
|
PrintAndLogEx(NORMAL, " b <no> : block to write");
|
||||||
PrintAndLogEx(NORMAL, " d <data> : block data - (8 hex symbols)");
|
PrintAndLogEx(NORMAL, " d <data> : block data - (8 or 32 hex symbols, 32 hex symbols will do a compatibility write)");
|
||||||
PrintAndLogEx(NORMAL, " k <key> : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
|
PrintAndLogEx(NORMAL, " k <key> : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
|
||||||
PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness");
|
PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
@ -1474,8 +1474,9 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t cmdp = 0;
|
uint8_t cmdp = 0;
|
||||||
uint8_t keylen = 0;
|
uint8_t keylen = 0;
|
||||||
uint8_t blockdata[20] = {0x00};
|
uint8_t blockdata[16] = {0x00};
|
||||||
uint8_t data[16] = {0x00};
|
uint8_t data[16] = {0x00};
|
||||||
|
uint8_t datalen = 4;
|
||||||
uint8_t authenticationkey[16] = {0x00};
|
uint8_t authenticationkey[16] = {0x00};
|
||||||
uint8_t *authKeyPtr = authenticationkey;
|
uint8_t *authKeyPtr = authenticationkey;
|
||||||
|
|
||||||
|
@ -1517,9 +1518,13 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
if (param_gethex(Cmd, cmdp + 1, blockdata, 8)) {
|
if (param_gethex(Cmd, cmdp + 1, blockdata, 8)) {
|
||||||
PrintAndLogEx(WARNING, "Block data must include 8 HEX symbols");
|
if (param_gethex(Cmd, cmdp + 1, blockdata, 32)) {
|
||||||
errors = true;
|
PrintAndLogEx(WARNING, "Block data must include 8 or 32 HEX symbols");
|
||||||
break;
|
errors = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
datalen = 16;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
|
@ -1559,9 +1564,8 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
||||||
PrintAndLogEx(NORMAL, "Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4));
|
PrintAndLogEx(NORMAL, "Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4));
|
||||||
|
|
||||||
//Send write Block
|
//Send write Block
|
||||||
uint8_t cmddata[20];
|
uint8_t cmddata[32];
|
||||||
memcpy(cmddata, blockdata, 4);
|
memcpy(cmddata, blockdata, datalen);
|
||||||
uint8_t datalen = 4;
|
|
||||||
uint8_t keytype = 0;
|
uint8_t keytype = 0;
|
||||||
if (hasAuthKey) {
|
if (hasAuthKey) {
|
||||||
keytype = 1;
|
keytype = 1;
|
||||||
|
@ -1574,7 +1578,11 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockNo, keytype, 0, cmddata, datalen);
|
if (datalen == 16) {
|
||||||
|
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL_COMPAT, blockNo, keytype, 0, cmddata, datalen);
|
||||||
|
} else {
|
||||||
|
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockNo, keytype, 0, cmddata, datalen);
|
||||||
|
}
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
uint8_t isOK = resp.oldarg[0] & 0xff;
|
||||||
|
|
|
@ -618,6 +618,7 @@ typedef struct {
|
||||||
#define CMD_HF_MIFAREU_READCARD 0x0721
|
#define CMD_HF_MIFAREU_READCARD 0x0721
|
||||||
#define CMD_HF_MIFARE_WRITEBL 0x0622
|
#define CMD_HF_MIFARE_WRITEBL 0x0622
|
||||||
#define CMD_HF_MIFAREU_WRITEBL 0x0722
|
#define CMD_HF_MIFAREU_WRITEBL 0x0722
|
||||||
|
#define CMD_HF_MIFAREU_WRITEBL_COMPAT 0x0723
|
||||||
|
|
||||||
#define CMD_HF_MIFARE_CHKKEYS 0x0623
|
#define CMD_HF_MIFARE_CHKKEYS 0x0623
|
||||||
#define CMD_HF_MIFARE_SETMOD 0x0624
|
#define CMD_HF_MIFARE_SETMOD 0x0624
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue