mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-07-15 09:43:00 -07:00
Fixed bug in HID clone short format. Added EM4xxx block read/write commands
This commit is contained in:
parent
f5fca2ed62
commit
d16e0478d2
6 changed files with 343 additions and 9 deletions
|
@ -670,6 +670,12 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
||||||
ReadPCF7931();
|
ReadPCF7931();
|
||||||
UsbSendPacket((uint8_t*)&ack, sizeof(ack));
|
UsbSendPacket((uint8_t*)&ack, sizeof(ack));
|
||||||
break;
|
break;
|
||||||
|
case CMD_EM4X_READ_WORD:
|
||||||
|
EM4xReadWord(c->arg[1], c->arg[2],c->d.asBytes[0]);
|
||||||
|
break;
|
||||||
|
case CMD_EM4X_WRITE_WORD:
|
||||||
|
EM4xWriteWord(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_HITAG
|
#ifdef WITH_HITAG
|
||||||
|
|
|
@ -128,6 +128,8 @@ int DemodPCF7931(uint8_t **outBlocks);
|
||||||
int IsBlock0PCF7931(uint8_t *Block);
|
int IsBlock0PCF7931(uint8_t *Block);
|
||||||
int IsBlock1PCF7931(uint8_t *Block);
|
int IsBlock1PCF7931(uint8_t *Block);
|
||||||
void ReadPCF7931();
|
void ReadPCF7931();
|
||||||
|
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
|
||||||
|
void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
|
||||||
|
|
||||||
/// iso14443.h
|
/// iso14443.h
|
||||||
void SimulateIso14443Tag(void);
|
void SimulateIso14443Tag(void);
|
||||||
|
|
225
armsrc/lfops.c
225
armsrc/lfops.c
|
@ -1119,10 +1119,10 @@ void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT)
|
||||||
data1 = 0x1D000000; // load preamble
|
data1 = 0x1D000000; // load preamble
|
||||||
|
|
||||||
for (int i=0;i<12;i++) {
|
for (int i=0;i<12;i++) {
|
||||||
if (hi & (1<<(12-i)))
|
if (hi & (1<<(11-i)))
|
||||||
data1 |= (1<<(((12-i)*2)+1)); // 1 -> 10
|
data1 |= (1<<(((11-i)*2)+1)); // 1 -> 10
|
||||||
else
|
else
|
||||||
data1 |= (1<<((12-i)*2)); // 0 -> 01
|
data1 |= (1<<((11-i)*2)); // 0 -> 01
|
||||||
}
|
}
|
||||||
|
|
||||||
data2 = 0;
|
data2 = 0;
|
||||||
|
@ -1553,3 +1553,222 @@ void ReadPCF7931() {
|
||||||
|
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------
|
||||||
|
// EM4469 / EM4305 routines
|
||||||
|
//-----------------------------------
|
||||||
|
#define FWD_CMD_LOGIN 0xC //including the even parity, binary mirrored
|
||||||
|
#define FWD_CMD_WRITE 0xA
|
||||||
|
#define FWD_CMD_READ 0x9
|
||||||
|
#define FWD_CMD_DISABLE 0x5
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t forwardLink_data[64]; //array of forwarded bits
|
||||||
|
uint8_t * forward_ptr; //ptr for forward message preparation
|
||||||
|
uint8_t fwd_bit_sz; //forwardlink bit counter
|
||||||
|
uint8_t * fwd_write_ptr; //forwardlink bit pointer
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
// prepares command bits
|
||||||
|
// see EM4469 spec
|
||||||
|
//====================================================================
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
uint8_t Prepare_Cmd( uint8_t cmd ) {
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
*forward_ptr++ = 0; //start bit
|
||||||
|
*forward_ptr++ = 0; //second pause for 4050 code
|
||||||
|
|
||||||
|
*forward_ptr++ = cmd;
|
||||||
|
cmd >>= 1;
|
||||||
|
*forward_ptr++ = cmd;
|
||||||
|
cmd >>= 1;
|
||||||
|
*forward_ptr++ = cmd;
|
||||||
|
cmd >>= 1;
|
||||||
|
*forward_ptr++ = cmd;
|
||||||
|
|
||||||
|
return 6; //return number of emited bits
|
||||||
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
// prepares address bits
|
||||||
|
// see EM4469 spec
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
uint8_t Prepare_Addr( uint8_t addr ) {
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
register uint8_t line_parity;
|
||||||
|
|
||||||
|
uint8_t i;
|
||||||
|
line_parity = 0;
|
||||||
|
for(i=0;i<6;i++) {
|
||||||
|
*forward_ptr++ = addr;
|
||||||
|
line_parity ^= addr;
|
||||||
|
addr >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*forward_ptr++ = (line_parity & 1);
|
||||||
|
|
||||||
|
return 7; //return number of emited bits
|
||||||
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
// prepares data bits intreleaved with parity bits
|
||||||
|
// see EM4469 spec
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
uint8_t Prepare_Data( uint16_t data_low, uint16_t data_hi) {
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
register uint8_t line_parity;
|
||||||
|
register uint8_t column_parity;
|
||||||
|
register uint8_t i, j;
|
||||||
|
register uint16_t data;
|
||||||
|
|
||||||
|
data = data_low;
|
||||||
|
column_parity = 0;
|
||||||
|
|
||||||
|
for(i=0; i<4; i++) {
|
||||||
|
line_parity = 0;
|
||||||
|
for(j=0; j<8; j++) {
|
||||||
|
line_parity ^= data;
|
||||||
|
column_parity ^= (data & 1) << j;
|
||||||
|
*forward_ptr++ = data;
|
||||||
|
data >>= 1;
|
||||||
|
}
|
||||||
|
*forward_ptr++ = line_parity;
|
||||||
|
if(i == 1)
|
||||||
|
data = data_hi;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(j=0; j<8; j++) {
|
||||||
|
*forward_ptr++ = column_parity;
|
||||||
|
column_parity >>= 1;
|
||||||
|
}
|
||||||
|
*forward_ptr = 0;
|
||||||
|
|
||||||
|
return 45; //return number of emited bits
|
||||||
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
// Forward Link send function
|
||||||
|
// Requires: forwarLink_data filled with valid bits (1 bit per byte)
|
||||||
|
// fwd_bit_count set with number of bits to be sent
|
||||||
|
//====================================================================
|
||||||
|
void SendForward(uint8_t fwd_bit_count) {
|
||||||
|
|
||||||
|
fwd_write_ptr = forwardLink_data;
|
||||||
|
fwd_bit_sz = fwd_bit_count;
|
||||||
|
|
||||||
|
LED_D_ON();
|
||||||
|
|
||||||
|
//Field on
|
||||||
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
|
||||||
|
|
||||||
|
// Give it a bit of time for the resonant antenna to settle.
|
||||||
|
// And for the tag to fully power up
|
||||||
|
SpinDelay(150);
|
||||||
|
|
||||||
|
// force 1st mod pulse (start gap must be longer for 4305)
|
||||||
|
fwd_bit_sz--; //prepare next bit modulation
|
||||||
|
fwd_write_ptr++;
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
||||||
|
SpinDelayUs(55*8); //55 cycles off (8us each)for 4305
|
||||||
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);//field on
|
||||||
|
SpinDelayUs(16*8); //16 cycles on (8us each)
|
||||||
|
|
||||||
|
// now start writting
|
||||||
|
while(fwd_bit_sz-- > 0) { //prepare next bit modulation
|
||||||
|
if(((*fwd_write_ptr++) & 1) == 1)
|
||||||
|
SpinDelayUs(32*8); //32 cycles at 125Khz (8us each)
|
||||||
|
else {
|
||||||
|
//These timings work for 4469/4269/4305 (with the 55*8 above)
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
||||||
|
SpinDelayUs(23*8); //16-4 cycles off (8us each)
|
||||||
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);//field on
|
||||||
|
SpinDelayUs(9*8); //16 cycles on (8us each)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login (uint32_t Password) {
|
||||||
|
|
||||||
|
uint8_t fwd_bit_count;
|
||||||
|
|
||||||
|
forward_ptr = forwardLink_data;
|
||||||
|
fwd_bit_count = Prepare_Cmd( FWD_CMD_LOGIN );
|
||||||
|
fwd_bit_count += Prepare_Data( Password&0xFFFF, Password>>16 );
|
||||||
|
|
||||||
|
SendForward(fwd_bit_count);
|
||||||
|
|
||||||
|
//Wait for command to complete
|
||||||
|
SpinDelay(20);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
|
||||||
|
|
||||||
|
uint8_t fwd_bit_count;
|
||||||
|
uint8_t *dest = (uint8_t *)BigBuf;
|
||||||
|
int m=0, i=0;
|
||||||
|
|
||||||
|
//If password mode do login
|
||||||
|
if (PwdMode == 1) Login(Pwd);
|
||||||
|
|
||||||
|
forward_ptr = forwardLink_data;
|
||||||
|
fwd_bit_count = Prepare_Cmd( FWD_CMD_READ );
|
||||||
|
fwd_bit_count += Prepare_Addr( Address );
|
||||||
|
|
||||||
|
m = sizeof(BigBuf);
|
||||||
|
// Clear destination buffer before sending the command
|
||||||
|
memset(dest, 128, m);
|
||||||
|
// Connect the A/D to the peak-detected low-frequency path.
|
||||||
|
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||||
|
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||||
|
FpgaSetupSsc();
|
||||||
|
|
||||||
|
SendForward(fwd_bit_count);
|
||||||
|
|
||||||
|
// Now do the acquisition
|
||||||
|
i = 0;
|
||||||
|
for(;;) {
|
||||||
|
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
||||||
|
AT91C_BASE_SSC->SSC_THR = 0x43;
|
||||||
|
}
|
||||||
|
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||||
|
dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
i++;
|
||||||
|
if (i >= m) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
||||||
|
LED_D_OFF();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
|
||||||
|
|
||||||
|
uint8_t fwd_bit_count;
|
||||||
|
|
||||||
|
//If password mode do login
|
||||||
|
if (PwdMode == 1) Login(Pwd);
|
||||||
|
|
||||||
|
forward_ptr = forwardLink_data;
|
||||||
|
fwd_bit_count = Prepare_Cmd( FWD_CMD_WRITE );
|
||||||
|
fwd_bit_count += Prepare_Addr( Address );
|
||||||
|
fwd_bit_count += Prepare_Data( Data&0xFFFF, Data>>16 );
|
||||||
|
|
||||||
|
SendForward(fwd_bit_count);
|
||||||
|
|
||||||
|
//Wait for write to complete
|
||||||
|
SpinDelay(20);
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
||||||
|
LED_D_OFF();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -423,14 +423,115 @@ int CmdEM410xWrite(const char *Cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CmdReadWord(const char *Cmd)
|
||||||
|
{
|
||||||
|
int Word = 16; //default to invalid word
|
||||||
|
UsbCommand c;
|
||||||
|
|
||||||
|
sscanf(Cmd, "%d", &Word);
|
||||||
|
|
||||||
|
if (Word > 15) {
|
||||||
|
PrintAndLog("Word must be between 0 and 15");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLog("Reading word %d", Word);
|
||||||
|
|
||||||
|
c.cmd = CMD_EM4X_READ_WORD;
|
||||||
|
c.d.asBytes[0] = 0x0; //Normal mode
|
||||||
|
c.arg[0] = 0;
|
||||||
|
c.arg[1] = Word;
|
||||||
|
c.arg[2] = 0;
|
||||||
|
SendCommand(&c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CmdReadWordPWD(const char *Cmd)
|
||||||
|
{
|
||||||
|
int Word = 16; //default to invalid word
|
||||||
|
int Password = 0xFFFFFFFF; //default to blank password
|
||||||
|
UsbCommand c;
|
||||||
|
|
||||||
|
sscanf(Cmd, "%d %x", &Word, &Password);
|
||||||
|
|
||||||
|
if (Word > 15) {
|
||||||
|
PrintAndLog("Word must be between 0 and 15");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLog("Reading word %d with password %08X", Word, Password);
|
||||||
|
|
||||||
|
c.cmd = CMD_EM4X_READ_WORD;
|
||||||
|
c.d.asBytes[0] = 0x1; //Password mode
|
||||||
|
c.arg[0] = 0;
|
||||||
|
c.arg[1] = Word;
|
||||||
|
c.arg[2] = Password;
|
||||||
|
SendCommand(&c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CmdWriteWord(const char *Cmd)
|
||||||
|
{
|
||||||
|
int Word = 16; //default to invalid block
|
||||||
|
int Data = 0xFFFFFFFF; //default to blank data
|
||||||
|
UsbCommand c;
|
||||||
|
|
||||||
|
sscanf(Cmd, "%x %d", &Data, &Word);
|
||||||
|
|
||||||
|
if (Word > 15) {
|
||||||
|
PrintAndLog("Word must be between 0 and 15");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLog("Writting word %d with data %08X", Word, Data);
|
||||||
|
|
||||||
|
c.cmd = CMD_EM4X_WRITE_WORD;
|
||||||
|
c.d.asBytes[0] = 0x0; //Normal mode
|
||||||
|
c.arg[0] = Data;
|
||||||
|
c.arg[1] = Word;
|
||||||
|
c.arg[2] = 0;
|
||||||
|
SendCommand(&c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CmdWriteWordPWD(const char *Cmd)
|
||||||
|
{
|
||||||
|
int Word = 8; //default to invalid word
|
||||||
|
int Data = 0xFFFFFFFF; //default to blank data
|
||||||
|
int Password = 0xFFFFFFFF; //default to blank password
|
||||||
|
UsbCommand c;
|
||||||
|
|
||||||
|
sscanf(Cmd, "%x %d %x", &Data, &Word, &Password);
|
||||||
|
|
||||||
|
if (Word > 15) {
|
||||||
|
PrintAndLog("Word must be between 0 and 15");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLog("Writting word %d with data %08X and password %08X", Word, Data, Password);
|
||||||
|
|
||||||
|
c.cmd = CMD_EM4X_WRITE_WORD;
|
||||||
|
c.d.asBytes[0] = 0x1; //Password mode
|
||||||
|
c.arg[0] = Data;
|
||||||
|
c.arg[1] = Word;
|
||||||
|
c.arg[2] = Password;
|
||||||
|
SendCommand(&c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static command_t CommandTable[] =
|
static command_t CommandTable[] =
|
||||||
{
|
{
|
||||||
{"help", CmdHelp, 1, "This help"},
|
{"help", CmdHelp, 1, "This help"},
|
||||||
{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
|
{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
|
||||||
{"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
|
{"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
|
||||||
{"em410xwatch", CmdEM410xWatch, 0, "Watches for EM410x tags"},
|
{"em410xwatch", CmdEM410xWatch, 0, "Watches for EM410x tags"},
|
||||||
{"em410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> -- Write EM410x UID to T5555(Q5) or T55x7 tag"},
|
{"em410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> -- Write EM410x UID to T5555(Q5) or T55x7 tag"},
|
||||||
{"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
|
{"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
|
||||||
|
{"readword", CmdReadWord, 1, "<Word> -- Read EM4xxx word data"},
|
||||||
|
{"readwordPWD", CmdReadWordPWD, 1, "<Word> <Password> -- Read EM4xxx word data in password mode"},
|
||||||
|
{"writeword", CmdWriteWord, 1, "<Data> <Word> -- Write EM4xxx word data"},
|
||||||
|
{"writewordPWD", CmdWriteWordPWD, 1, "<Data> <Word> <Password> -- Write EM4xxx word data in password mode"},
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,5 +18,9 @@ int CmdEM410xSim(const char *Cmd);
|
||||||
int CmdEM410xWatch(const char *Cmd);
|
int CmdEM410xWatch(const char *Cmd);
|
||||||
int CmdEM410xWrite(const char *Cmd);
|
int CmdEM410xWrite(const char *Cmd);
|
||||||
int CmdEM4x50Read(const char *Cmd);
|
int CmdEM4x50Read(const char *Cmd);
|
||||||
|
int CmdReadWord(const char *Cmd);
|
||||||
|
int CmdReadWordPWD(const char *Cmd);
|
||||||
|
int CmdWriteWord(const char *Cmd);
|
||||||
|
int CmdWriteWordPWD(const char *Cmd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -75,6 +75,8 @@ typedef struct {
|
||||||
#define CMD_T55XX_WRITE_BLOCK 0x0215
|
#define CMD_T55XX_WRITE_BLOCK 0x0215
|
||||||
#define CMD_T55XX_READ_TRACE 0x0216
|
#define CMD_T55XX_READ_TRACE 0x0216
|
||||||
#define CMD_PCF7931_READ 0x0217
|
#define CMD_PCF7931_READ 0x0217
|
||||||
|
#define CMD_EM4X_READ_WORD 0x0218
|
||||||
|
#define CMD_EM4X_WRITE_WORD 0x0219
|
||||||
|
|
||||||
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue