mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-14 02:26:59 -07:00
integrated MIFARE ultralight features, contributed by 'midnitesnake'
This commit is contained in:
parent
05f23c593c
commit
981bd4292e
10 changed files with 690 additions and 89 deletions
|
@ -782,12 +782,24 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
|||
case CMD_MIFARE_READBL:
|
||||
MifareReadBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFAREU_READBL:
|
||||
MifareUReadBlock(c->arg[0],c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFAREU_READCARD:
|
||||
MifareUReadCard(c->arg[0],c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFARE_READSC:
|
||||
MifareReadSector(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFARE_WRITEBL:
|
||||
MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFAREU_WRITEBL_COMPAT:
|
||||
MifareUWriteBlock(c->arg[0], c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFAREU_WRITEBL:
|
||||
MifareUWriteBlock_Special(c->arg[0], c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFARE_NESTED:
|
||||
MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
|
||||
break;
|
||||
|
|
|
@ -158,8 +158,12 @@ void EPA_PACE_Collect_Nonce(UsbCommand * c);
|
|||
void ReaderMifare(bool first_try);
|
||||
int32_t dist_nt(uint32_t nt1, uint32_t nt2);
|
||||
void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
|
||||
void MifareUReadBlock(uint8_t arg0,uint8_t *datain);
|
||||
void MifareUReadCard(uint8_t arg0,uint8_t *datain);
|
||||
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||
void MifareUWriteBlock(uint8_t arg0,uint8_t *datain);
|
||||
void MifareUWriteBlock_Special(uint8_t arg0,uint8_t *datain);
|
||||
void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||
void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||
|
|
|
@ -1604,7 +1604,7 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, int maxLen, int
|
|||
|
||||
void ReaderTransmitBitsPar(uint8_t* frame, int bits, uint32_t par, uint32_t *timing)
|
||||
{
|
||||
|
||||
|
||||
CodeIso14443aBitsAsReaderPar(frame,bits,par);
|
||||
|
||||
// Select the card
|
||||
|
|
|
@ -91,12 +91,66 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
// iso14a_set_tracing(TRUE);
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Select, Authenticaate, Read an MIFARE tag.
|
||||
// read sector (data = 4 x 16 bytes = 64 bytes)
|
||||
|
||||
}
|
||||
|
||||
void MifareUReadBlock(uint8_t arg0,uint8_t *datain)
|
||||
{
|
||||
// params
|
||||
uint8_t blockNo = arg0;
|
||||
|
||||
// variables
|
||||
byte_t isOK = 0;
|
||||
byte_t dataoutbuf[16];
|
||||
uint8_t uid[10];
|
||||
uint32_t cuid;
|
||||
|
||||
// clear trace
|
||||
iso14a_clear_trace();
|
||||
iso14443a_setup();
|
||||
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
while (true) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_ultra_readblock(cuid, blockNo, dataoutbuf)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Read block error");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_ultra_halt(cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
break;
|
||||
};
|
||||
|
||||
isOK = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
|
||||
|
||||
// add trace trailer
|
||||
memset(uid, 0x44, 4);
|
||||
LogTrace(uid, 4, 0, 0, TRUE);
|
||||
LED_B_ON();
|
||||
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
|
||||
LED_B_OFF();
|
||||
|
||||
|
||||
// Thats it...
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Select, Authenticaate, Read an MIFARE tag.
|
||||
// read sector (data = 4 x 16 bytes = 64 bytes)
|
||||
//-----------------------------------------------------------------------------
|
||||
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||
{
|
||||
|
@ -188,12 +242,72 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
// iso14a_set_tracing(TRUE);
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Select, Authenticaate, Read an MIFARE tag.
|
||||
// read block
|
||||
|
||||
}
|
||||
|
||||
void MifareUReadCard(uint8_t arg0, uint8_t *datain)
|
||||
{
|
||||
// params
|
||||
uint8_t sectorNo = arg0;
|
||||
|
||||
// variables
|
||||
byte_t isOK = 0;
|
||||
byte_t dataoutbuf[16 * 4];
|
||||
uint8_t uid[10];
|
||||
uint32_t cuid;
|
||||
|
||||
// clear trace
|
||||
iso14a_clear_trace();
|
||||
// iso14a_set_tracing(false);
|
||||
|
||||
iso14443a_setup();
|
||||
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
while (true) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
break;
|
||||
};
|
||||
for(int sec=0;sec<16;sec++){
|
||||
if(mifare_ultra_readblock(cuid, sectorNo * 4 + sec, dataoutbuf + 4 * sec)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Read block %d error",sec);
|
||||
break;
|
||||
};
|
||||
}
|
||||
if(mifare_ultra_halt(cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
break;
|
||||
};
|
||||
|
||||
isOK = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (MF_DBGLEVEL >= 2) DbpString("READ CARD FINISHED");
|
||||
|
||||
// add trace trailer
|
||||
memset(uid, 0x44, 4);
|
||||
LogTrace(uid, 4, 0, 0, TRUE);
|
||||
|
||||
LED_B_ON();
|
||||
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,64);
|
||||
//cmd_send(CMD_ACK,isOK,0,0,dataoutbuf+32, 32);
|
||||
LED_B_OFF();
|
||||
|
||||
// Thats it...
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
// iso14a_set_tracing(TRUE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Select, Authenticaate, Read an MIFARE tag.
|
||||
// read block
|
||||
//-----------------------------------------------------------------------------
|
||||
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||
{
|
||||
|
@ -270,12 +384,137 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
// iso14a_set_tracing(TRUE);
|
||||
|
||||
}
|
||||
|
||||
// Return 1 if the nonce is invalid else return 0
|
||||
int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, byte_t * parity) {
|
||||
return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \
|
||||
|
||||
}
|
||||
|
||||
void MifareUWriteBlock(uint8_t arg0, uint8_t *datain)
|
||||
{
|
||||
// params
|
||||
uint8_t blockNo = arg0;
|
||||
byte_t blockdata[16];
|
||||
|
||||
memset(blockdata,'\0',16);
|
||||
memcpy(blockdata, datain,16);
|
||||
|
||||
// variables
|
||||
byte_t isOK = 0;
|
||||
uint8_t uid[10];
|
||||
uint32_t cuid;
|
||||
|
||||
// clear trace
|
||||
iso14a_clear_trace();
|
||||
// iso14a_set_tracing(false);
|
||||
|
||||
iso14443a_setup();
|
||||
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
while (true) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_ultra_writeblock(cuid, blockNo, blockdata)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_ultra_halt(cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
break;
|
||||
};
|
||||
|
||||
isOK = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||
|
||||
// add trace trailer
|
||||
memset(uid, 0x44, 4);
|
||||
LogTrace(uid, 4, 0, 0, TRUE);
|
||||
|
||||
LED_B_ON();
|
||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
// UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));
|
||||
LED_B_OFF();
|
||||
|
||||
|
||||
// Thats it...
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
// iso14a_set_tracing(TRUE);
|
||||
|
||||
}
|
||||
|
||||
void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain)
|
||||
{
|
||||
// params
|
||||
uint8_t blockNo = arg0;
|
||||
byte_t blockdata[4];
|
||||
|
||||
memcpy(blockdata, datain,4);
|
||||
|
||||
// variables
|
||||
byte_t isOK = 0;
|
||||
uint8_t uid[10];
|
||||
uint32_t cuid;
|
||||
|
||||
// clear trace
|
||||
iso14a_clear_trace();
|
||||
// iso14a_set_tracing(false);
|
||||
|
||||
iso14443a_setup();
|
||||
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
while (true) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_ultra_special_writeblock(cuid, blockNo, blockdata)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_ultra_halt(cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
break;
|
||||
};
|
||||
|
||||
isOK = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||
|
||||
// add trace trailer
|
||||
memset(uid, 0x44, 4);
|
||||
LogTrace(uid, 4, 0, 0, TRUE);
|
||||
|
||||
LED_B_ON();
|
||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
// UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));
|
||||
LED_B_OFF();
|
||||
|
||||
|
||||
// Thats it...
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
// iso14a_set_tracing(TRUE);
|
||||
|
||||
}
|
||||
|
||||
// Return 1 if the nonce is invalid else return 0
|
||||
int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, byte_t * parity) {
|
||||
return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \
|
||||
(oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \
|
||||
(oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;
|
||||
}
|
||||
|
|
|
@ -79,12 +79,38 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
|
|||
// send commands
|
||||
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t *timing)
|
||||
{
|
||||
return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, NULL, timing);
|
||||
}
|
||||
|
||||
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t * parptr, uint32_t *timing)
|
||||
{
|
||||
uint8_t dcmd[4], ecmd[4];
|
||||
return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, NULL, timing);
|
||||
}
|
||||
|
||||
int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *timing)
|
||||
{
|
||||
uint8_t dcmd[8];//, ecmd[4];
|
||||
//uint32_t par=0;
|
||||
|
||||
dcmd[0] = cmd;
|
||||
dcmd[1] = data[0];
|
||||
dcmd[2] = data[1];
|
||||
dcmd[3] = data[2];
|
||||
dcmd[4] = data[3];
|
||||
dcmd[5] = data[4];
|
||||
AppendCrc14443a(dcmd, 6);
|
||||
//Dbprintf("Data command: %02x", dcmd[0]);
|
||||
//Dbprintf("Data R: %02x %02x %02x %02x %02x %02x %02x", dcmd[1],dcmd[2],dcmd[3],dcmd[4],dcmd[5],dcmd[6],dcmd[7]);
|
||||
|
||||
//memcpy(ecmd, dcmd, sizeof(dcmd));
|
||||
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
|
||||
int len = ReaderReceive(answer);
|
||||
if(!len)
|
||||
{
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
|
||||
return 2;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t * parptr, uint32_t *timing)
|
||||
{
|
||||
uint8_t dcmd[4], ecmd[4];
|
||||
uint32_t pos, par, res;
|
||||
|
||||
dcmd[0] = cmd;
|
||||
|
@ -253,12 +279,43 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
|
|||
}
|
||||
|
||||
memcpy(blockData, receivedAnswer, 16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
// variables
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
// variables
|
||||
int len;
|
||||
uint8_t bt[2];
|
||||
|
||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
||||
|
||||
// command MIFARE_CLASSIC_READBLOCK
|
||||
len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer,NULL);
|
||||
if (len == 1) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||
return 1;
|
||||
}
|
||||
if (len != 18) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: card timeout. len: %x", len);
|
||||
return 2;
|
||||
}
|
||||
|
||||
memcpy(bt, receivedAnswer + 16, 2);
|
||||
AppendCrc14443a(receivedAnswer, 16);
|
||||
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd CRC response error.");
|
||||
return 3;
|
||||
}
|
||||
|
||||
memcpy(blockData, receivedAnswer, 14);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
// variables
|
||||
int len, i;
|
||||
uint32_t pos;
|
||||
uint32_t par = 0;
|
||||
|
@ -300,12 +357,71 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
|||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
||||
{
|
||||
// variables
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
// variables
|
||||
int len;
|
||||
uint32_t par = 0;
|
||||
|
||||
uint8_t d_block[18];
|
||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
||||
|
||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||
len = mifare_sendcmd_short(NULL, 1, 0xA0, blockNo, receivedAnswer,NULL);
|
||||
|
||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(d_block,'\0',18);
|
||||
memcpy(d_block, blockData, 16);
|
||||
AppendCrc14443a(d_block, 16);
|
||||
|
||||
ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);
|
||||
|
||||
// Receive the response
|
||||
len = ReaderReceive(receivedAnswer);
|
||||
|
||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
// variables
|
||||
int len;
|
||||
//uint32_t par = 0;
|
||||
|
||||
uint8_t d_block[8];
|
||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
||||
|
||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||
memset(d_block,'\0',8);
|
||||
d_block[0]= blockNo;
|
||||
memcpy(d_block+1,blockData,4);
|
||||
AppendCrc14443a(d_block, 6);
|
||||
|
||||
//i know the data send here is correct
|
||||
len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer,NULL);
|
||||
|
||||
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
||||
{
|
||||
// variables
|
||||
int len;
|
||||
|
||||
// Mifare HALT
|
||||
|
@ -317,12 +433,29 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
|||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// work with emulator memory
|
||||
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||
uint8_t* emCARD = eml_get_bigbufptr_cardmem();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_ultra_halt(uint32_t uid)
|
||||
{
|
||||
// variables
|
||||
int len;
|
||||
|
||||
// Mifare HALT
|
||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
||||
|
||||
len = mifare_sendcmd_short(NULL, 1, 0x50, 0x00, receivedAnswer, NULL);
|
||||
if (len != 0) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("halt error. response len: %x", len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// work with emulator memory
|
||||
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||
uint8_t* emCARD = eml_get_bigbufptr_cardmem();
|
||||
|
||||
memcpy(emCARD + blockNum * 16, data, blocksCount * 16);
|
||||
}
|
||||
|
|
|
@ -52,21 +52,26 @@ extern int MF_DBGLEVEL;
|
|||
|
||||
#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();
|
||||
|
||||
//functions
|
||||
uint8_t* mifare_get_bigbufptr(void);
|
||||
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t *timing);
|
||||
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t * parptr, uint32_t *timing);
|
||||
|
||||
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, \
|
||||
//functions
|
||||
uint8_t* mifare_get_bigbufptr(void);
|
||||
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t *timing);
|
||||
int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* amswer, uint8_t *timing);
|
||||
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t * parptr, uint32_t *timing);
|
||||
|
||||
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, \
|
||||
uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested);
|
||||
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, \
|
||||
uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested, uint32_t * ntptr, uint32_t *timing);
|
||||
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
|
||||
|
||||
// crypto functions
|
||||
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len);
|
||||
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, \
|
||||
uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested, uint32_t * ntptr, uint32_t *timing);
|
||||
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||
int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||
int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
|
||||
int mifare_ultra_halt(uint32_t uid);
|
||||
|
||||
// crypto functions
|
||||
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len);
|
||||
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, int len, uint32_t *par);
|
||||
uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data);
|
||||
|
||||
|
@ -82,7 +87,7 @@ void emlGetMem(uint8_t *data, int blockNum, int blocksCount);
|
|||
void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount);
|
||||
uint64_t emlGetKey(int sectorNum, int keyType);
|
||||
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum);
|
||||
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum);
|
||||
int emlCheckValBl(int blockNum);
|
||||
|
||||
#endif
|
||||
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum);
|
||||
int emlCheckValBl(int blockNum);
|
||||
|
||||
#endif
|
||||
|
|
236
client/cmdhfmf.c
236
client/cmdhfmf.c
|
@ -137,12 +137,86 @@ int CmdHF14AMfWrBl(const char *Cmd)
|
|||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMfRdBl(const char *Cmd)
|
||||
{
|
||||
uint8_t blockNo = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMfUWrBl(const char *Cmd)
|
||||
{
|
||||
uint8_t blockNo = 0;
|
||||
uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
UsbCommand resp;
|
||||
|
||||
if (strlen(Cmd)<3) {
|
||||
PrintAndLog("Usage: hf mf uwrbl <block number> <block data (8 hex symbols)>");
|
||||
PrintAndLog(" sample: hf mf uwrbl 0 01020304");
|
||||
return 0;
|
||||
}
|
||||
|
||||
blockNo = param_get8(Cmd, 0);
|
||||
if (param_gethex(Cmd, 1, bldata, 8)) {
|
||||
PrintAndLog("Block data must include 8 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch(blockNo)
|
||||
{
|
||||
case 0:
|
||||
PrintAndLog("Access Denied");
|
||||
break;
|
||||
case 1:
|
||||
PrintAndLog("Access Denied");
|
||||
break;
|
||||
case 2:
|
||||
PrintAndLog("--specialblock no:%02x", blockNo);
|
||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
||||
UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||
memcpy(c.d.asBytes, bldata, 4);
|
||||
SendCommand(&c);
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
PrintAndLog("--specialblock no:%02x", blockNo);
|
||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
||||
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||
memcpy(d.d.asBytes,bldata, 4);
|
||||
SendCommand(&d);
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("--block no:%02x", blockNo);
|
||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
||||
//UsbCommand e = {CMD_MIFAREU_WRITEBL_COMPAT, {blockNo}};
|
||||
//memcpy(e.d.asBytes,bldata, 16);
|
||||
UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||
memcpy(e.d.asBytes,bldata, 4);
|
||||
SendCommand(&e);
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMfRdBl(const char *Cmd)
|
||||
{
|
||||
uint8_t blockNo = 0;
|
||||
uint8_t keyType = 0;
|
||||
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
|
||||
|
||||
|
@ -185,12 +259,135 @@ int CmdHF14AMfRdBl(const char *Cmd)
|
|||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMfRdSc(const char *Cmd)
|
||||
{
|
||||
int i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMfURdBl(const char *Cmd)
|
||||
{
|
||||
uint8_t blockNo = 0;
|
||||
|
||||
if (strlen(Cmd)<1) {
|
||||
PrintAndLog("Usage: hf mf urdbl <block number>");
|
||||
PrintAndLog(" sample: hf mf urdbl 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
blockNo = param_get8(Cmd, 0);
|
||||
PrintAndLog("--block no:%02x", blockNo);
|
||||
|
||||
UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
uint8_t * data = resp.d.asBytes;
|
||||
|
||||
if (isOK)
|
||||
PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
|
||||
else
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMfURdCard(const char *Cmd)
|
||||
{
|
||||
int i;
|
||||
uint8_t sectorNo = 0;
|
||||
uint8_t *lockbytes_t=NULL;
|
||||
uint8_t lockbytes[2]={0,0};
|
||||
bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
uint8_t isOK = 0;
|
||||
uint8_t * data = NULL;
|
||||
|
||||
if (sectorNo > 15) {
|
||||
PrintAndLog("Sector number must be less than 16");
|
||||
return 1;
|
||||
}
|
||||
PrintAndLog("Attempting to Read Ultralight... ");
|
||||
|
||||
UsbCommand c = {CMD_MIFAREU_READCARD, {sectorNo}};
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
isOK = resp.arg[0] & 0xff;
|
||||
data = resp.d.asBytes;
|
||||
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
if (isOK)
|
||||
for (i = 0; i < 16; i++) {
|
||||
switch(i){
|
||||
case 2:
|
||||
//process lock bytes
|
||||
lockbytes_t=data+(i*4);
|
||||
lockbytes[0]=lockbytes_t[2];
|
||||
lockbytes[1]=lockbytes_t[3];
|
||||
for(int j=0; j<16; j++){
|
||||
bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8));
|
||||
}
|
||||
//PrintAndLog("LB %02x %02x", lockbytes[0],lockbytes[1]);
|
||||
//PrintAndLog("LB2b %02x %02x %02x %02x %02x %02x %02x %02x",bit[8],bit[9],bit[10],bit[11],bit[12],bit[13],bit[14],bit[15]);
|
||||
PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
|
||||
break;
|
||||
case 3:
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[4]);
|
||||
break;
|
||||
case 4:
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[3]);
|
||||
break;
|
||||
case 5:
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[2]);
|
||||
break;
|
||||
case 6:
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[1]);
|
||||
break;
|
||||
case 7:
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[0]);
|
||||
break;
|
||||
case 8:
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[15]);
|
||||
break;
|
||||
case 9:
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[14]);
|
||||
break;
|
||||
case 10:
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[13]);
|
||||
break;
|
||||
case 11:
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[12]);
|
||||
break;
|
||||
case 12:
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[11]);
|
||||
break;
|
||||
case 13:
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[10]);
|
||||
break;
|
||||
case 14:
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[9]);
|
||||
break;
|
||||
case 15:
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[8]);
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PrintAndLog("Command1 execute timeout");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMfRdSc(const char *Cmd)
|
||||
{
|
||||
int i;
|
||||
uint8_t sectorNo = 0;
|
||||
uint8_t keyType = 0;
|
||||
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
|
||||
|
@ -1667,12 +1864,15 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
|
||||
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
|
||||
{"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},
|
||||
{"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},
|
||||
{"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
|
||||
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
|
||||
{"urdbl", CmdHF14AMfURdBl, 0, "Read MIFARE Ultralight block"},
|
||||
{"urdcard", CmdHF14AMfURdCard, 0,"Read MIFARE Ultralight Card"},
|
||||
{"uwrbl", CmdHF14AMfUWrBl, 0,"Write MIFARE Ultralight block"},
|
||||
{"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},
|
||||
{"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},
|
||||
{"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},
|
||||
{"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},
|
||||
{"chk", CmdHF14AMfChk, 0, "Test block keys"},
|
||||
{"mifare", CmdHF14AMifare, 0, "Read parity error messages. param - <used card nonce>"},
|
||||
|
|
|
@ -26,16 +26,19 @@
|
|||
#include "mifarehost.h"
|
||||
|
||||
int CmdHFMF(const char *Cmd);
|
||||
|
||||
int CmdHF14AMfDbg(const char* cmd);
|
||||
int CmdHF14AMfRdBl(const char* cmd);
|
||||
int CmdHF14AMfRdSc(const char* cmd);
|
||||
int CmdHF14AMfDump(const char* cmd);
|
||||
int CmdHF14AMfRestore(const char* cmd);
|
||||
int CmdHF14AMfWrBl(const char* cmd);
|
||||
int CmdHF14AMfChk(const char* cmd);
|
||||
int CmdHF14AMifare(const char* cmd);
|
||||
int CmdHF14AMfNested(const char* cmd);
|
||||
|
||||
int CmdHF14AMfDbg(const char* cmd);
|
||||
int CmdHF14AMfRdBl(const char* cmd);
|
||||
int CmdHF14AMfURdBl(const char* cmd);
|
||||
int CmdHF14AMfRdSc(const char* cmd);
|
||||
int CmdHF14SMfURdCard(const char* cmd);
|
||||
int CmdHF14AMfDump(const char* cmd);
|
||||
int CmdHF14AMfRestore(const char* cmd);
|
||||
int CmdHF14AMfWrBl(const char* cmd);
|
||||
int CmdHF14AMfUWrBl(const char* cmd);
|
||||
int CmdHF14AMfChk(const char* cmd);
|
||||
int CmdHF14AMifare(const char* cmd);
|
||||
int CmdHF14AMfNested(const char* cmd);
|
||||
int CmdHF14AMfSniff(const char* cmd);
|
||||
int CmdHF14AMf1kSim(const char* cmd);
|
||||
int CmdHF14AMfEClear(const char* cmd);
|
||||
|
|
|
@ -168,6 +168,7 @@ static void *main_loop(void *targ) {
|
|||
|
||||
if (cmd[0] != 0x00) {
|
||||
if (strncmp(cmd, "quit", 4) == 0) {
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -139,8 +139,12 @@ typedef struct {
|
|||
#define CMD_MIFARE_NESTED 0x0612
|
||||
|
||||
#define CMD_MIFARE_READBL 0x0620
|
||||
#define CMD_MIFAREU_READBL 0x0720
|
||||
#define CMD_MIFARE_READSC 0x0621
|
||||
#define CMD_MIFAREU_READCARD 0x0721
|
||||
#define CMD_MIFARE_WRITEBL 0x0622
|
||||
#define CMD_MIFAREU_WRITEBL_COMPAT 0x0722
|
||||
#define CMD_MIFAREU_WRITEBL 0x0723
|
||||
#define CMD_MIFARE_CHKKEYS 0x0623
|
||||
|
||||
#define CMD_MIFARE_SNIFFER 0x0630
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue