fix OTP simulation

This commit is contained in:
iceman1001 2025-03-19 15:22:55 +01:00
commit c8cde55a5e
6 changed files with 72 additions and 63 deletions

View file

@ -1726,11 +1726,21 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uin
} }
p_response = NULL; p_response = NULL;
} else if (receivedCmd[0] == MIFARE_ULC_WRITE && len == 8 && (tagType == 2 || tagType == 7)) { // Received a WRITE } else if (receivedCmd[0] == MIFARE_ULC_WRITE && len == 8 && (tagType == 2 || tagType == 7)) { // Received a WRITE
p_response = NULL;
// cmd + block + 4 bytes data + 2 bytes crc // cmd + block + 4 bytes data + 2 bytes crc
if (CheckCrc14A(receivedCmd, len)) { if (CheckCrc14A(receivedCmd, len)) {
uint8_t block = receivedCmd[1]; uint8_t block = receivedCmd[1];
// sanity checks
if (block > pages) {
// send NACK 0x0, invalid argument
EmSend4bit(CARD_NACK_IV);
goto jump;
}
// OTP sanity check // OTP sanity check
// Quite a bad one, one should look at all individual bits and see if anyone tries be set as zero // Quite a bad one, one should look at all individual bits and see if anyone tries be set as zero
// we cheat and do fat 00000000 check instead // we cheat and do fat 00000000 check instead
@ -1739,23 +1749,20 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uin
// OTP can't be set back to zero // OTP can't be set back to zero
// send NACK 0x0 == invalid argument, // send NACK 0x0 == invalid argument,
EmSend4bit(CARD_NACK_IV); EmSend4bit(CARD_NACK_IV);
goto jump;
} }
} }
if (block > pages) {
// send NACK 0x0 == invalid argument
EmSend4bit(CARD_NACK_IV);
} else {
// first blocks of emu are header // first blocks of emu are header
emlSetMem_xt(&receivedCmd[2], block + (MFU_DUMP_PREFIX_LENGTH / 4), 1, 4); emlSetMem_xt(&receivedCmd[2], block + (MFU_DUMP_PREFIX_LENGTH / 4), 1, 4);
// send ACK // send ACK
EmSend4bit(CARD_ACK); EmSend4bit(CARD_ACK);
}
} else { } else {
// send NACK 0x1 == crc/parity error // send NACK 0x1 == crc/parity error
EmSend4bit(CARD_NACK_PA); EmSend4bit(CARD_NACK_PA);
} }
p_response = NULL; goto jump;
} else if (receivedCmd[0] == MIFARE_ULC_COMP_WRITE && len == 4 && (tagType == 2 || tagType == 7)) { } else if (receivedCmd[0] == MIFARE_ULC_COMP_WRITE && len == 4 && (tagType == 2 || tagType == 7)) {
// cmd + block + 2 bytes crc // cmd + block + 2 bytes crc
if (CheckCrc14A(receivedCmd, len)) { if (CheckCrc14A(receivedCmd, len)) {
@ -2002,6 +2009,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uin
// Count number of other messages after a halt // Count number of other messages after a halt
// if (order != ORDER_WUPA && lastorder == ORDER_HALTED) { happened2++; } // if (order != ORDER_WUPA && lastorder == ORDER_HALTED) { happened2++; }
jump:
cmdsRecvd++; cmdsRecvd++;
@ -3239,7 +3247,7 @@ void ReaderIso14443a(PacketCommandNG *c) {
} }
if ((param & ISO14A_APDU) == ISO14A_APDU) { if ((param & ISO14A_APDU) == ISO14A_APDU) {
uint8_t res; uint8_t res = 0;
arg0 = iso14_apdu( arg0 = iso14_apdu(
cmd, cmd,
len, len,

View file

@ -1206,9 +1206,9 @@ static int CmdExchangeAPDU(bool chainingin, const uint8_t *datain, int datainlen
} }
} }
uint16_t cmdc = 0; uint16_t cmdc = (ISO14A_APDU | ISO14A_NO_DISCONNECT);
if (chainingin) { if (chainingin) {
cmdc = ISO14A_SEND_CHAINING; cmdc |= ISO14A_SEND_CHAINING;
} }
// "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
@ -1216,9 +1216,9 @@ static int CmdExchangeAPDU(bool chainingin, const uint8_t *datain, int datainlen
// here length PM3_CMD_DATA_SIZE=512 // here length PM3_CMD_DATA_SIZE=512
// timeout must be authomatically set by "get ATS" // timeout must be authomatically set by "get ATS"
if (datain) { if (datain) {
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0x1FF), 0, datain, datainlen & 0x1FF); SendCommandMIX(CMD_HF_ISO14443A_READER, cmdc, (datainlen & 0x1FF), 0, datain, (datainlen & 0x1FF));
} else { } else {
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ISO14443A_READER, cmdc, 0, 0, NULL, 0);
} }
PacketResponseNG resp; PacketResponseNG resp;

View file

@ -1482,7 +1482,8 @@ static void iclass_decode_credentials(uint8_t *data) {
char *pbin = binstr; char *pbin = binstr;
while (strlen(pbin) && *(++pbin) == '0'); while (strlen(pbin) && *(++pbin) == '0');
PrintAndLogEx(SUCCESS, "Binary... %zu - " _GREEN_("%s"), strlen(pbin), pbin); PrintAndLogEx(SUCCESS, "Binary... " _GREEN_("%s") " ( %zu )", pbin, strlen(pbin));
PrintAndLogEx(NORMAL, "");
decode_wiegand(top, mid, bot, 0); decode_wiegand(top, mid, bot, 0);
} }

View file

@ -6279,7 +6279,8 @@ static int CmdHF14AMfMAD(const char *Cmd) {
if (sector > -1) { if (sector > -1) {
// decode it // decode it
PrintAndLogEx(INFO, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "------------------------- " _CYAN_("Wiegand") " ---------------------------");
PrintAndLogEx(INFO, _CYAN_("HID PACS detected")); PrintAndLogEx(INFO, _CYAN_("HID PACS detected"));
uint8_t pacs_sector[MFBLOCK_SIZE * 3] = {0}; uint8_t pacs_sector[MFBLOCK_SIZE * 3] = {0};
@ -6302,7 +6303,6 @@ static int CmdHF14AMfMAD(const char *Cmd) {
PrintAndLogEx(SUCCESS, "Binary... " _GREEN_("%s"), pbin); PrintAndLogEx(SUCCESS, "Binary... " _GREEN_("%s"), pbin);
PrintAndLogEx(INFO, "Wiegand decode");
decode_wiegand(top, mid, bot, 0); decode_wiegand(top, mid, bot, 0);
} }
} }

View file

@ -94,7 +94,7 @@ typedef enum {
const char *nxp_cluster_to_text(uint8_t cluster) { const char *nxp_cluster_to_text(uint8_t cluster) {
switch (cluster) { switch (cluster) {
case CL_ADMIN: case CL_ADMIN:
return "card administration"; return "Card administration";
case CL_MISC1: case CL_MISC1:
case CL_MISC2: case CL_MISC2:
case CL_MISC3: case CL_MISC3:
@ -102,40 +102,40 @@ const char *nxp_cluster_to_text(uint8_t cluster) {
case CL_MISC5: case CL_MISC5:
case CL_MISC6: case CL_MISC6:
case CL_MISC7: case CL_MISC7:
return "miscellaneous applications"; return "Miscellaneous applications";
case CL_AIRLINES: case CL_AIRLINES:
return "airlines"; return "Airlines";
case CL_FERRY: case CL_FERRY:
return "ferry traffic"; return "Ferry traffic";
case CL_RAIL: case CL_RAIL:
return "railway services"; return "Railway services";
case CL_MISC: case CL_MISC:
return "miscellaneous applications"; return "Miscellaneous applications";
case CL_TRANSPORT: case CL_TRANSPORT:
return "transport"; return "Transport";
case CL_SECURITY: case CL_SECURITY:
return "security solutions"; return "Security solutions";
case CL_CITYTRAFFIC: case CL_CITYTRAFFIC:
return "city traffic"; return "City traffic";
case CL_CZECH_RAIL: case CL_CZECH_RAIL:
return "Czech Railways"; return "Czech Railways";
case CL_BUS: case CL_BUS:
return "bus services"; return "Bus services";
case CL_MMT: case CL_MMT:
return "multi modal transit"; return "Multi modal transit";
case CL_TAXI: case CL_TAXI:
return "taxi"; return "Taxi";
case CL_TOLL: case CL_TOLL:
return "road toll"; return "Road toll";
case CL_GENERIC_TRANS: case CL_GENERIC_TRANS:
return "generic transport"; return "Generic transport";
case CL_COMPANY_SERVICES: case CL_COMPANY_SERVICES:
return "company services"; return "Company services";
case CL_CITYCARD: case CL_CITYCARD:
return "city card services"; return "City card services";
case CL_ACCESS_CONTROL_1: case CL_ACCESS_CONTROL_1:
case CL_ACCESS_CONTROL_2: case CL_ACCESS_CONTROL_2:
return "access control & security"; return "Access control & security";
case CL_VIGIK: case CL_VIGIK:
return "VIGIK"; return "VIGIK";
case CL_NED_DEFENCE: case CL_NED_DEFENCE:
@ -145,63 +145,63 @@ const char *nxp_cluster_to_text(uint8_t cluster) {
case CL_EU: case CL_EU:
return "European Union Institutions"; return "European Union Institutions";
case CL_SKI_TICKET: case CL_SKI_TICKET:
return "ski ticketing"; return "Ski ticketing";
case CL_SOAA: case CL_SOAA:
return "SOAA standard for offline access standard"; return "SOAA standard for offline access standard";
case CL_ACCESS2: case CL_ACCESS2:
return "access control & security"; return "Access control & security";
case CL_FOOD: case CL_FOOD:
return "food"; return "Food";
case CL_NONFOOD: case CL_NONFOOD:
return "non-food trade"; return "Non-food trade";
case CL_HOTEL: case CL_HOTEL:
return "hotel"; return "Hotel";
case CL_LOYALTY: case CL_LOYALTY:
return "loyalty"; return "Loyalty";
case CL_AIRPORT: case CL_AIRPORT:
return "airport services"; return "Airport services";
case CL_CAR_RENTAL: case CL_CAR_RENTAL:
return "car rental"; return "Car rental";
case CL_NED_GOV: case CL_NED_GOV:
return "Dutch government"; return "Dutch government";
case CL_ADMIN2: case CL_ADMIN2:
return "administration services"; return "Administration services";
case CL_PURSE: case CL_PURSE:
return "electronic purse"; return "Electronic purse";
case CL_TV: case CL_TV:
return "television"; return "Television";
case CL_CRUISESHIP: case CL_CRUISESHIP:
return "cruise ship"; return "Cruise ship";
case CL_IOPTA: case CL_IOPTA:
return "IOPTA"; return "IOPTA";
case CL_METERING: case CL_METERING:
return "metering"; return "Metering";
case CL_TELEPHONE: case CL_TELEPHONE:
return "telephone"; return "Telephone";
case CL_HEALTH: case CL_HEALTH:
return "health services"; return "Health services";
case CL_WAREHOUSE: case CL_WAREHOUSE:
return "warehouse"; return "Warehouse";
case CL_BANKING: case CL_BANKING:
return "banking"; return "Banking";
case CL_ENTERTAIN: case CL_ENTERTAIN:
return "entertainment & sports"; return "Entertainment & sports";
case CL_PARKING: case CL_PARKING:
return "car parking"; return "Car parking";
case CL_FLEET: case CL_FLEET:
return "fleet management"; return "Fleet management";
case CL_FUEL: case CL_FUEL:
return "fuel, gasoline"; return "Fuel, gasoline";
case CL_INFO: case CL_INFO:
return "info services"; return "Info services";
case CL_PRESS: case CL_PRESS:
return "press"; return "Press";
case CL_NFC: case CL_NFC:
return "NFC Forum"; return "NFC Forum";
case CL_COMPUTER: case CL_COMPUTER:
return "computer"; return "Computer";
case CL_MAIL: case CL_MAIL:
return "mail"; return "Mail";
case CL_AMISC: case CL_AMISC:
case CL_AMISC1: case CL_AMISC1:
case CL_AMISC2: case CL_AMISC2:
@ -210,11 +210,11 @@ const char *nxp_cluster_to_text(uint8_t cluster) {
case CL_AMISC5: case CL_AMISC5:
case CL_AMISC6: case CL_AMISC6:
case CL_AMISC7: case CL_AMISC7:
return "miscellaneous applications"; return "Miscellaneous applications";
default: default:
break; break;
} }
return "reserved"; return "Reserved";
} }
static json_t *df_known_aids = NULL; static json_t *df_known_aids = NULL;