Proxmark3 community

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.

Announcement

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.

#1 2011-04-01 16:29:11

milkmansrevenge
Member
Registered: 2010-11-01
Posts: 2

hf 14a sim problems/solutions (SimulateIso14443aTag)

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

#2 2011-04-05 13:11:13

milkmansrevenge
Member
Registered: 2010-11-01
Posts: 2

Re: hf 14a sim problems/solutions (SimulateIso14443aTag)

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

Board footer

Powered by FluxBB