mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 21:33:47 -07:00
CHG: a major remake of the "hf mf c*" commands. Ie chinese magic tags. Tried to make them consistent in parameter calls and simplified. And fixed the annoying gen1 tags that answers with a ACK/NACK on HALT commands..
This commit is contained in:
parent
bb9796ba26
commit
c2731f37be
13 changed files with 344 additions and 426 deletions
|
@ -17,6 +17,7 @@
|
|||
#include "apps.h"
|
||||
#include "util.h"
|
||||
#include "crc.h"
|
||||
#include "protocols.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Select, Authenticate, Read a MIFARE tag.
|
||||
|
@ -1010,224 +1011,176 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
//-----------------------------------------------------------------------------
|
||||
// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)
|
||||
//
|
||||
// PARAMS - workFlags
|
||||
// bit 0 - need get UID
|
||||
// bit 1 - need wupC
|
||||
// bit 2 - need HALT after sequence
|
||||
// bit 3 - need turn on FPGA before sequence
|
||||
// bit 4 - need turn off FPGA
|
||||
// bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a)
|
||||
// bit 6 - wipe tag.
|
||||
//-----------------------------------------------------------------------------
|
||||
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
|
||||
|
||||
// params
|
||||
uint8_t needWipe = arg0;
|
||||
// bit 0 - need get UID
|
||||
// bit 1 - need wupC
|
||||
// bit 2 - need HALT after sequence
|
||||
// bit 3 - need init FPGA and field before sequence
|
||||
// bit 4 - need reset FPGA and LED
|
||||
uint8_t workFlags = arg1;
|
||||
uint8_t blockNo = arg2;
|
||||
// magic uid card generation 1 commands
|
||||
uint8_t wupC1[] = { MIFARE_MAGICWUPC1 };
|
||||
uint8_t wupC2[] = { MIFARE_MAGICWUPC2 };
|
||||
uint8_t wipeC[] = { MIFARE_MAGICWIPEC };
|
||||
|
||||
// card commands
|
||||
uint8_t wupC1[] = { 0x40 };
|
||||
uint8_t wupC2[] = { 0x43 };
|
||||
uint8_t wipeC[] = { 0x41 };
|
||||
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){
|
||||
|
||||
// params
|
||||
uint8_t workFlags = arg0;
|
||||
uint8_t blockNo = arg1;
|
||||
|
||||
Dbprintf("ICE :: CSetBlocks Flags %02x", workFlags);
|
||||
|
||||
// variables
|
||||
byte_t isOK = 0;
|
||||
uint8_t uid[10] = {0x00};
|
||||
uint8_t d_block[18] = {0x00};
|
||||
uint8_t data[18] = {0x00};
|
||||
uint32_t cuid;
|
||||
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
// reset FPGA and LED
|
||||
if (workFlags & 0x08) {
|
||||
if (workFlags & MAGIC_INIT) {
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
clear_trace();
|
||||
set_tracing(TRUE);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
|
||||
// get UID from chip
|
||||
if (workFlags & 0x01) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
//break;
|
||||
};
|
||||
|
||||
if(mifare_classic_halt(NULL, cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
//break;
|
||||
};
|
||||
// read UID and return to client
|
||||
if (workFlags & MAGIC_UID) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");
|
||||
OnErrorMagic(MAGIC_UID);
|
||||
};
|
||||
};
|
||||
|
||||
// reset chip
|
||||
if (needWipe){
|
||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||
break;
|
||||
};
|
||||
|
||||
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_classic_halt(NULL, cuid)) {
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("INFO - Tag answered the 'Halt' command");
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
// write block
|
||||
if (workFlags & 0x02) {
|
||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||
break;
|
||||
};
|
||||
|
||||
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");
|
||||
break;
|
||||
// wipe tag, fill it with zeros
|
||||
if (workFlags & MAGIC_WIPE){
|
||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error");
|
||||
OnErrorMagic(MAGIC_WIPE);
|
||||
};
|
||||
|
||||
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wipeC error");
|
||||
OnErrorMagic(MAGIC_WIPE);
|
||||
};
|
||||
};
|
||||
|
||||
// write block
|
||||
if (workFlags & MAGIC_WUPC) {
|
||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error");
|
||||
OnErrorMagic(MAGIC_WUPC);
|
||||
};
|
||||
|
||||
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC2 error");
|
||||
OnErrorMagic(MAGIC_WUPC);
|
||||
};
|
||||
|
||||
memcpy(d_block, datain, 16);
|
||||
AppendCrc14443a(d_block, 16);
|
||||
|
||||
ReaderTransmit(d_block, sizeof(d_block), NULL);
|
||||
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
|
||||
break;
|
||||
};
|
||||
|
||||
if (workFlags & 0x04) {
|
||||
if (mifare_classic_halt(NULL, cuid)) {
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("INFO - Tag answered the 'Halt' command");
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
isOK = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((mifare_sendcmd_short(NULL, 0, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("write block send command error");
|
||||
OnErrorMagic(4);
|
||||
};
|
||||
|
||||
memcpy(data, datain, sizeof(data));
|
||||
AppendCrc14443a(data, sizeof(data));
|
||||
|
||||
ReaderTransmit(data, sizeof(data), NULL);
|
||||
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("write block send data error");
|
||||
OnErrorMagic(0);
|
||||
};
|
||||
|
||||
if (workFlags & MAGIC_OFF)
|
||||
mifare_classic_halt_ex(NULL);
|
||||
|
||||
LED_B_ON();
|
||||
cmd_send(CMD_ACK,isOK,0,0,uid,4);
|
||||
// check if uid is cuid?
|
||||
cmd_send(CMD_ACK,1,0,0,uid,sizeof(uid));
|
||||
LED_B_OFF();
|
||||
|
||||
if ((workFlags & 0x10) || (!isOK)) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
set_tracing(FALSE);
|
||||
}
|
||||
if (workFlags & MAGIC_OFF)
|
||||
OnSuccessMagic();
|
||||
}
|
||||
|
||||
|
||||
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
|
||||
|
||||
// params
|
||||
// bit 1 - need wupC
|
||||
// bit 2 - need HALT after sequence
|
||||
// bit 3 - need init FPGA and field before sequence
|
||||
// bit 4 - need reset FPGA and LED
|
||||
// bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a)
|
||||
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){
|
||||
|
||||
uint8_t workFlags = arg0;
|
||||
uint8_t blockNo = arg2;
|
||||
|
||||
// card commands
|
||||
uint8_t wupC1[] = { 0x40 };
|
||||
uint8_t wupC2[] = { 0x43 };
|
||||
uint8_t blockNo = arg1;
|
||||
|
||||
Dbprintf("ICE :: CGetBlocks Flags %02x", workFlags);
|
||||
|
||||
// variables
|
||||
byte_t isOK = 0;
|
||||
uint8_t data[18] = {0x00};
|
||||
uint32_t cuid = 0;
|
||||
|
||||
uint8_t data[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
if (workFlags & 0x08) {
|
||||
memset(data, 0x00, sizeof(data));
|
||||
|
||||
if (workFlags & MAGIC_INIT) {
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
set_tracing(TRUE);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (workFlags & 0x02) {
|
||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||
break;
|
||||
};
|
||||
|
||||
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
// read block
|
||||
if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");
|
||||
break;
|
||||
if (workFlags & MAGIC_WUPC) {
|
||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error");
|
||||
OnErrorMagic(MAGIC_WUPC);
|
||||
};
|
||||
|
||||
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC2 error");
|
||||
OnErrorMagic(MAGIC_WUPC);
|
||||
};
|
||||
memcpy(data, receivedAnswer, 18);
|
||||
|
||||
if (workFlags & 0x04) {
|
||||
if (mifare_classic_halt(NULL, cuid)) {
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("INFO - Tag answered the 'Halt' command");
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
isOK = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// read block
|
||||
if ((mifare_sendcmd_short(NULL, 0, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("read block send command error");
|
||||
OnErrorMagic(0);
|
||||
};
|
||||
|
||||
memcpy(data, receivedAnswer, sizeof(data));
|
||||
|
||||
// send HALT
|
||||
if (workFlags & MAGIC_HALT)
|
||||
mifare_classic_halt_ex(NULL);
|
||||
|
||||
LED_B_ON();
|
||||
if (workFlags & 0x20) {
|
||||
if (isOK)
|
||||
memcpy(datain, data, 18);
|
||||
}
|
||||
|
||||
// if MAGIC_DATAIN, the data stays on device side.
|
||||
if (workFlags & MAGIC_DATAIN)
|
||||
memcpy(datain, data, sizeof(data));
|
||||
else
|
||||
cmd_send(CMD_ACK,isOK,0,0,data,18);
|
||||
cmd_send(CMD_ACK,1,0,0,data,sizeof(data));
|
||||
|
||||
LED_B_OFF();
|
||||
|
||||
if ((workFlags & 0x10) || (!isOK)) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
set_tracing(FALSE);
|
||||
}
|
||||
if (workFlags & MAGIC_OFF)
|
||||
OnSuccessMagic();
|
||||
}
|
||||
|
||||
void MifareCIdent(){
|
||||
|
||||
// card commands
|
||||
uint8_t wupC1[] = { 0x40 };
|
||||
uint8_t wupC2[] = { 0x43 };
|
||||
|
||||
// variables
|
||||
byte_t isOK = 1;
|
||||
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
byte_t isOK = 1;
|
||||
uint8_t receivedAnswer[1];
|
||||
uint8_t receivedAnswerPar[1];
|
||||
|
||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
|
@ -1241,76 +1194,21 @@ void MifareCIdent(){
|
|||
|
||||
// removed the if, since some magic tags misbehavies and send an answer to it.
|
||||
mifare_classic_halt(NULL, 0);
|
||||
|
||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
}
|
||||
|
||||
void MifareCollectNonces(uint32_t arg0, uint32_t arg1){
|
||||
|
||||
BigBuf_free();
|
||||
|
||||
uint32_t iterations = arg0;
|
||||
uint8_t uid[10] = {0x00};
|
||||
|
||||
uint8_t *response = BigBuf_malloc(MAX_MIFARE_FRAME_SIZE);
|
||||
uint8_t *responsePar = BigBuf_malloc(MAX_MIFARE_PARITY_SIZE);
|
||||
|
||||
uint8_t mf_auth[] = { 0x60,0x00,0xf5,0x7b };
|
||||
|
||||
// get memory from BigBuf.
|
||||
uint8_t *nonces = BigBuf_malloc(iterations * 4);
|
||||
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
set_tracing(TRUE);
|
||||
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// Test if the action was cancelled
|
||||
if(BUTTON_PRESS()) break;
|
||||
|
||||
// if(mifare_classic_halt(pcs, cuid)) {
|
||||
// if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
//}
|
||||
|
||||
if(!iso14443a_select_card(uid, NULL, NULL)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
continue;
|
||||
};
|
||||
|
||||
// Transmit MIFARE_CLASSIC_AUTH.
|
||||
ReaderTransmit(mf_auth, sizeof(mf_auth), NULL);
|
||||
|
||||
// Receive the (4 Byte) "random" nonce
|
||||
if (!ReaderReceive(response, responsePar)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Couldn't receive tag nonce");
|
||||
continue;
|
||||
}
|
||||
|
||||
nonces[i*4] = bytes_to_num(response, 4);
|
||||
}
|
||||
|
||||
int packLen = iterations * 4;
|
||||
int packSize = 0;
|
||||
int packNum = 0;
|
||||
while (packLen > 0) {
|
||||
packSize = MIN(USB_CMD_DATA_SIZE, packLen);
|
||||
LED_B_ON();
|
||||
cmd_send(CMD_ACK, 77, 0, packSize, nonces - packLen, packSize);
|
||||
LED_B_OFF();
|
||||
|
||||
packLen -= packSize;
|
||||
packNum++;
|
||||
}
|
||||
void OnSuccessMagic(){
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
set_tracing(FALSE);
|
||||
set_tracing(FALSE);
|
||||
}
|
||||
void OnErrorMagic(uint8_t reason){
|
||||
// ACK, ISOK, reason,0,0,0
|
||||
cmd_send(CMD_ACK,0,reason,0,0,0);
|
||||
OnSuccessMagic();
|
||||
}
|
||||
|
||||
void MifareCollectNonces(uint32_t arg0, uint32_t arg1){
|
||||
}
|
||||
|
||||
//
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue