Research, development and trades concerning the powerful Proxmark3 device.
Remember; sharing is caring. Bring something back to the community.
"Learn the tools of the trade the hard way." +Fravia
You are not logged in.
Time changes and with it the technology
Proxmark3 @ discord
Users of this forum, please be aware that information stored on this site is not private.
Hi,
I'm using the latest code for Proxmark3 from SVN (Revision 468) on Ubuntu Linux.
I'm testing against a Touchatag reader with libnfc 1.4.2
When playing with the "hf 14a sim" command I noticed some problems. While the client tool likes to tell you that the Proxmark3 is emulating a tag with your specified ID, the device itself is actually using a fixed one (04 21 3f 51 48 1d 80). Not only that, but in the first cascade level the BCC is wrong - it is 4d and should be 92.
Does anyone know of any reasons for this? If not, I'll be trying to make it more flexible at the start of next week/this weekend which I will share in the hope that someone can put it into SVN. If there is a good reason, is there a more flexible iso14443a.c file floating about anywhere?
Also, when checking with libnfc, the emulation on the proxmark is only noticed when using the nfc-anticol command, but not with nfc-list. All I get with nfc-list is the proxmark side of things saying: "#db# Unknown command received from reader: 78 44 44 4", libnfc output just acts as if there is nothing within range. This was discussed to some extent in: http://www.proxmark.org/forum/topic/565 … t-working/ but no solution seemed to come out of that
If anyone has any comments they would be very welcome! I think I've enough background reading on this subject to understand most parts of it, but if you disagree feel free to point me towards some more documentation.
Regards
Offline
I have added the ability to use the custom UIDs sent from the pc client to the Proxmark3 and tidied up the code a bit. It supports both 4 byte UIDs and 7 byte UIDs.
However, I have coded it to behave like a Mifare Classic 4k as opposed to the DESFire from before. This is just because I am using a 4k myself.
I haven't seen any example traces or documentation for Mifare Classic cards with a 7 byte UID yet - they were supposedly coming into the market towards the end of 2010: http://www.mifare.net/index.php/downloa … view/118/. So I calculated some of the ATQA and SAK values based on what I thought they should be from NXP documentation such as AN10833.
I have also somehow fixed the problem I was having with nfc-list not picking up the Proxmark3. It works 100% of the time now but I actually don't know which bit of my code changing fixed it...
According to ISO 14443-3 commands beginning with 78 are proprietary, so I assume the nfc-list spits that out looking for some card that I do not know of, which explains the "#db# Unknown command received from reader: 78 44 44 4" output from the Proxmark3.
The code for the function is below. Note that I believe the type of the arguments should be changed to unsigned int, but that requires making a change to the header file as well.
//-----------------------------------------------------------------------------
// Main loop of simulated tag: receive commands from reader, decide what
// response to send, and send it.
//-----------------------------------------------------------------------------
void SimulateIso14443aTag(int hi, int lo)
{
// This function contains the tag emulation
// Prepare protocol messages
// static const uint8_t cmd1[] = { 0x26 };
// Assumed ATQA for a Classic 4k with 7 byte UID (7th bit set to 1)
// Note that the bit numbering in ISO 14443 goes from 1 - x rather than 0 - x i.e. LSB = 1
// Why are the ATQA bytes swapped here to what is shown in AN10833 (i.e. 0x42 00 instead of 0x00 42)
uint8_t response1[] = { 0x42, 0x00 };
// Classic 4k with 4 byte UID
//static const uint8_t response1[] = { 0x02, 0x00 };
//static const uint8_t response1[] = { 0x44, 0x03 }; // Says: I am a DESFire Tag, ph33r me
//static const uint8_t response1[] = { 0x44, 0x00 }; // Says: I am a ULTRALITE Tag, 0wn me
// static const uint8_t cmd2[] = { 0x93, 0x20 };
// Example UID response - 04 21 4f 51 48 1d 80
// Example UID part 1. Note cascade (0x88), 2nd byte (0x04) = NXP/Phillips
uint8_t response2[] = { 0x88, 0x04, 0x21, 0x3f, 0x92 };
// static const uint8_t cmd2[] = { 0x93, 0x70, 0x88, 0x04, 0x21, 0x3f, 0x92, CRC, CRC };
// When reader selects us during cascade1 it will send cmd3
// SAK Select (cascade1) successful response. 0x04 is default for all Mifare at
// cascade level one apart from DESFire (ref. AN10883)
uint8_t response3[] = { 0x04, 0x00, 0x00 };
ComputeCrc14443(CRC_14443_A, response3, 1, &response3[1], &response3[2]);
//uint8_t response3[] = { 0x04, 0x00, 0x00 }; // SAK Select (cascade1) successful response (ULTRALITE)
//uint8_t response3[] = { 0x24, 0x00, 0x00 }; // SAK Select (cascade1) successful response (DESFire)
// send cascade2 2nd half of UID (4 bytes) + BCCheck
uint8_t response2a[] = { 0x51, 0x48, 0x1d, 0x80, 0x84 };
// static const uint8_t cmd3a[] = { 0x95, 0x70, 0x51, 0x48, 0x1d, 0x80, 0x84, CRC, CRC };
// When reader selects us during cascade2 it will send cmd3a
//uint8_t response3a[] = { 0x00, 0x00, 0x00 }; // SAK Select (cascade2) successful response (ULTRALITE)
//uint8_t response3a[] = { 0x20, 0x00, 0x00 }; // SAK Select (cascade2) successful response (DESFire)
uint8_t response3a[] = { 0x18, 0x00, 0x00 }; // SAK Select (cascade2) successful response (Classic 4k)
ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
// From the UsbCommand struct arg[0] is hi (1st 3 bytes of UID for 7 byte UIDs, nothing for 4 byte UIDs)
// and arg[1] is lo (last 4 bytes of UID for 7 byte UIDs, or full UID for 4 byte UIDs)
// They should be unsigned ints...
if(hi == 0) {
// As it is a four byte UID change the ATQA to 02 00 (Mifare 4k - 7th bit unset)
response1[0] = 0x02;
// Handle 4 byte UID
response2[0] = lo >> 24;
response2[1] = lo >> 16;
response2[2] = lo >> 8;
response2[3] = lo;
response2[4] = response2[0] ^ response2[1] ^ response2[2] ^ response2[3];
// Change the SAK to say that the UID is complete (Mifare 4k default of 0x18)
response3[0] = 0x18;
ComputeCrc14443(CRC_14443_A, response3, 1, &response3[1], &response3[2]);
} else {
// 7 byte UID (Lets just ignore the 10 byte option for now)
// Cascade, first 3 bytes of UID then BCC
response2[0] = 0x88;
response2[1] = hi >> 16;
response2[2] = hi >> 8;
response2[3] = hi;
response2[4] = response2[0] ^ response2[1] ^ response2[2] ^ response2[3];
// Last four bytes of UID then BCC
response2a[0] = lo >> 24;
response2a[1] = lo >> 16;
response2a[2] = lo >> 8;
response2a[3] = lo;
response2a[4] = response2a[0] ^ response2a[1] ^ response2a[2] ^ response2a[3];
}
static const uint8_t response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce
uint8_t *resp;
int respLen;
// Longest possible response will be 16 bytes + 2 CRC = 18 bytes
// This will need
// 144 data bits (18 * 8)
// 18 parity bits
// 2 Start and stop
// 1 Correction bit (Answer in 1172 or 1236 periods, see FPGA)
// 1 just for the case
// ----------- +
// 166
//
// 166 bytes, since every bit that needs to be send costs us a byte
//
// Respond with card type
uint8_t *resp1 = (((uint8_t *)BigBuf) + 800);
int resp1Len;
// Anticollision cascade1 - respond with uid
uint8_t *resp2 = (((uint8_t *)BigBuf) + 970);
int resp2Len;
// Anticollision cascade2 - respond with 2nd half of uid if asked
// we're only going to be asked if we set the 1st byte of the UID (during cascade1) to 0x88
uint8_t *resp2a = (((uint8_t *)BigBuf) + 1140);
int resp2aLen;
// Acknowledge select - cascade 1
uint8_t *resp3 = (((uint8_t *)BigBuf) + 1310);
int resp3Len;
// Acknowledge select - cascade 2
uint8_t *resp3a = (((uint8_t *)BigBuf) + 1480);
int resp3aLen;
// Response to a read request - not implemented atm
uint8_t *resp4 = (((uint8_t *)BigBuf) + 1550);
int resp4Len;
// Authenticate response - nonce
uint8_t *resp5 = (((uint8_t *)BigBuf) + 1720);
int resp5Len;
uint8_t *receivedCmd = (uint8_t *)BigBuf;
int len;
int i;
int u;
uint8_t b;
// To control where we are in the protocol
int order = 0;
int lastorder;
// Just to allow some checks
int happened = 0;
int happened2 = 0;
int cmdsRecvd = 0;
int fdt_indicator;
memset(receivedCmd, 0x44, 400);
// Prepare the responses of the anticollision phase
// there will be not enough time to do this at the moment the reader sends it REQA
// Answer to request
CodeIso14443aAsTag(response1, sizeof(response1));
memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;
// Send our UID (cascade 1)
CodeIso14443aAsTag(response2, sizeof(response2));
memcpy(resp2, ToSend, ToSendMax); resp2Len = ToSendMax;
// Answer to select (cascade1)
CodeIso14443aAsTag(response3, sizeof(response3));
memcpy(resp3, ToSend, ToSendMax); resp3Len = ToSendMax;
// Send the cascade 2 2nd part of the uid
CodeIso14443aAsTag(response2a, sizeof(response2a));
memcpy(resp2a, ToSend, ToSendMax); resp2aLen = ToSendMax;
// Answer to select (cascade 2)
CodeIso14443aAsTag(response3a, sizeof(response3a));
memcpy(resp3a, ToSend, ToSendMax); resp3aLen = ToSendMax;
// Strange answer is an example of rare message size (3 bits)
CodeStrangeAnswer();
memcpy(resp4, ToSend, ToSendMax); resp4Len = ToSendMax;
// Authentication answer (random nonce)
CodeIso14443aAsTag(response5, sizeof(response5));
memcpy(resp5, ToSend, ToSendMax); resp5Len = ToSendMax;
// We need to listen to the high-frequency, peak-detected path.
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
FpgaSetupSsc();
cmdsRecvd = 0;
LED_A_ON();
for(;;) {
if(!GetIso14443aCommandFromReader(receivedCmd, &len, 100)) {
DbpString("button press");
break;
}
// doob - added loads of debug strings so we can see what the reader is saying to us during the sim as hi14alist is not populated
// Okay, look at the command now.
lastorder = order;
i = 1; // first byte transmitted
if(receivedCmd[0] == 0x26) {
// Received a REQUEST
resp = resp1; respLen = resp1Len; order = 1;
//DbpString("Hello request from reader:");
} else if(receivedCmd[0] == 0x52) {
// Received a WAKEUP
resp = resp1; respLen = resp1Len; order = 6;
// DbpString("Wakeup request from reader:");
} else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x93) { // greg - cascade 1 anti-collision
// Received request for UID (cascade 1)
resp = resp2; respLen = resp2Len; order = 2;
// DbpString("UID (cascade 1) request from reader:");
// DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);
} else if(receivedCmd[1] == 0x20 && receivedCmd[0] ==0x95) { // greg - cascade 2 anti-collision
// Received request for UID (cascade 2)
resp = resp2a; respLen = resp2aLen; order = 20;
// DbpString("UID (cascade 2) request from reader:");
// DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);
} else if(receivedCmd[1] == 0x70 && receivedCmd[0] ==0x93) { // greg - cascade 1 select
// Received a SELECT
resp = resp3; respLen = resp3Len; order = 3;
// DbpString("Select (cascade 1) request from reader:");
// DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);
} else if(receivedCmd[1] == 0x70 && receivedCmd[0] ==0x95) { // greg - cascade 2 select
// Received a SELECT
resp = resp3a; respLen = resp3aLen; order = 30;
// DbpString("Select (cascade 2) request from reader:");
// DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);
} else if(receivedCmd[0] == 0x30) {
// Received a READ
resp = resp4; respLen = resp4Len; order = 4; // Do nothing
Dbprintf("Read request from reader: %x %x %x",
receivedCmd[0], receivedCmd[1], receivedCmd[2]);
} else if(receivedCmd[0] == 0x50) {
// Received a HALT
resp = resp1; respLen = 0; order = 5; // Do nothing
DbpString("Reader requested we HALT!:");
} else if(receivedCmd[0] == 0x60) {
// Received an authentication request
resp = resp5; respLen = resp5Len; order = 7;
Dbprintf("Authenticate request from reader: %x %x %x",
receivedCmd[0], receivedCmd[1], receivedCmd[2]);
} else if(receivedCmd[0] == 0xE0) {
// Received a RATS request
resp = resp1; respLen = 0;order = 70;
Dbprintf("RATS request from reader: %x %x %x",
receivedCmd[0], receivedCmd[1], receivedCmd[2]);
} else {
// Never seen this command before
Dbprintf("Unknown command received from reader: %x %x %x %x %x %x %x %x %x",
receivedCmd[0], receivedCmd[1], receivedCmd[2],
receivedCmd[3], receivedCmd[3], receivedCmd[4],
receivedCmd[5], receivedCmd[6], receivedCmd[7]);
// Do not respond
resp = resp1; respLen = 0; order = 0;
}
// Count number of wakeups received after a halt
if(order == 6 && lastorder == 5) { happened++; }
// Count number of other messages after a halt
if(order != 6 && lastorder == 5) { happened2++; }
// Look at last parity bit to determine timing of answer
if((Uart.parityBits & 0x01) || receivedCmd[0] == 0x52) {
// 1236, so correction bit needed
i = 0;
}
memset(receivedCmd, 0x44, 32);
if(cmdsRecvd > 999) {
DbpString("1000 commands later...");
break;
}
else {
cmdsRecvd++;
}
if(respLen <= 0) continue;
// Modulate Manchester
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD);
AT91C_BASE_SSC->SSC_THR = 0x00;
FpgaSetupSsc();
// ### Transmit the response ###
u = 0;
b = 0x00;
fdt_indicator = FALSE;
for(;;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
volatile uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
(void)b;
}
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
if(i > respLen) {
b = 0x00;
u++;
} else {
b = resp[i];
i++;
}
AT91C_BASE_SSC->SSC_THR = b;
if(u > 4) {
break;
}
}
if(BUTTON_PRESS()) {
break;
}
}
}
Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
LED_A_OFF();
}
Offline