This commit is contained in:
iceman1001 2024-01-24 18:18:13 +01:00
parent 7afe2dab8c
commit 2d9c1a941c
6 changed files with 264 additions and 296 deletions

View file

@ -69,7 +69,7 @@ void RunMod(void) {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF_15); FpgaDownloadAndGo(FPGA_BITSTREAM_HF_15);
iso15_tag_t *tag = (iso15_tag_t*) BigBuf_get_EM_addr(); iso15_tag_t *tag = (iso15_tag_t *) BigBuf_get_EM_addr();
if (tag == NULL) return; if (tag == NULL) return;
uint8_t cmd[8] = {0}; uint8_t cmd[8] = {0};
@ -90,8 +90,7 @@ void RunMod(void) {
while (1) { while (1) {
SpinDelay(200); SpinDelay(200);
LED_B_OFF(); LED_B_OFF();
if (BUTTON_HELD(500) > 0) if (BUTTON_HELD(500) > 0) {
{
LEDsoff(); LEDsoff();
Dbprintf("Quiting"); Dbprintf("Quiting");
return; return;
@ -100,18 +99,15 @@ void RunMod(void) {
res = SendDataTag(cmd, 4, true, true, recv, sizeof(recv), start_time, ISO15693_READER_TIMEOUT, &eof_time, &recvLen); res = SendDataTag(cmd, 4, true, true, recv, sizeof(recv), start_time, ISO15693_READER_TIMEOUT, &eof_time, &recvLen);
if (res < 0) if (res < 0)
continue; continue;
if (recvLen<10) // error: recv too short if (recvLen < 10) { // error: recv too short
{
Dbprintf("recvLen<10"); Dbprintf("recvLen<10");
continue; continue;
} }
if (!CheckCrc15(recv,recvLen)) // error crc not valid if (!CheckCrc15(recv, recvLen)) { // error crc not valid
{
Dbprintf("crc failed"); Dbprintf("crc failed");
continue; continue;
} }
if (recv[0] & ISO15_RES_ERROR) // received error from tag if (recv[0] & ISO15_RES_ERROR) { // received error from tag
{
Dbprintf("error received"); Dbprintf("error received");
continue; continue;
} }
@ -121,18 +117,16 @@ void RunMod(void) {
memset(tag, 0, sizeof(iso15_tag_t)); memset(tag, 0, sizeof(iso15_tag_t));
memcpy(tag->uid, &recv[2], 8); memcpy(tag->uid, &recv[2], 8);
i=10; i = 10;
if (recv[1] & 0x01) if (recv[1] & 0x01)
tag->dsfid = recv[i++]; tag->dsfid = recv[i++];
if (recv[1] & 0x02) if (recv[1] & 0x02)
tag->afi = recv[i++]; tag->afi = recv[i++];
if (recv[1] & 0x04) if (recv[1] & 0x04) {
{ tag->pagesCount = recv[i++] + 1;
tag->pagesCount = recv[i++]+1; tag->bytesPerPage = recv[i++] + 1;
tag->bytesPerPage = recv[i++]+1; } else {
} // Set default tag values (if can't be readed in SYSINFO)
else
{ // Set default tag values (if can't be readed in SYSINFO)
tag->bytesPerPage = 4; tag->bytesPerPage = 4;
tag->pagesCount = 128; tag->pagesCount = 128;
} }
@ -144,7 +138,7 @@ void RunMod(void) {
cmd[0] = ISO15_REQ_DATARATE_HIGH | ISO15_REQ_OPTION; cmd[0] = ISO15_REQ_DATARATE_HIGH | ISO15_REQ_OPTION;
cmd[1] = ISO15693_READBLOCK; cmd[1] = ISO15693_READBLOCK;
uint8_t blocknum = 0; uint8_t blocknum = 0;
int retry; int retry;
for (retry = 0; retry < 8; retry++) { for (retry = 0; retry < 8; retry++) {
@ -157,23 +151,19 @@ void RunMod(void) {
start_time = eof_time; start_time = eof_time;
res = SendDataTag(cmd, 5, false, true, recv, sizeof(recv), start_time, ISO15693_READER_TIMEOUT, &eof_time, &recvLen); res = SendDataTag(cmd, 5, false, true, recv, sizeof(recv), start_time, ISO15693_READER_TIMEOUT, &eof_time, &recvLen);
if (res < 0) if (res < 0) {
{
SpinDelay(100); SpinDelay(100);
continue; continue;
} }
if (recvLen < 4 + tag->bytesPerPage) // error: recv too short if (recvLen < 4 + tag->bytesPerPage) { // error: recv too short
{
Dbprintf("recvLen < 4 + tag->bytesPerPage"); Dbprintf("recvLen < 4 + tag->bytesPerPage");
continue; continue;
} }
if (!CheckCrc15(recv,recvLen)) // error crc not valid if (!CheckCrc15(recv, recvLen)) { // error crc not valid
{
Dbprintf("crc failed"); Dbprintf("crc failed");
continue; continue;
} }
if (recv[0] & ISO15_RES_ERROR) // received error from tag if (recv[0] & ISO15_RES_ERROR) { // received error from tag
{
Dbprintf("error received"); Dbprintf("error received");
continue; continue;
} }
@ -185,8 +175,7 @@ void RunMod(void) {
} }
LEDsoff(); LEDsoff();
if (retry >= 8) if (retry >= 8) {
{
Dbprintf("Max retry attemps exeeded"); Dbprintf("Max retry attemps exeeded");
Dbprintf("-=[ exit ]=-"); Dbprintf("-=[ exit ]=-");
return; return;

View file

@ -1332,8 +1332,7 @@ static int RAMFUNC Handle15693SampleFromReader(bool bit, DecodeReader_t *reader)
reader->posCount = -4; reader->posCount = -4;
} }
if (reader->bitCount == 8) if (reader->bitCount == 8) {
{
reader->output[reader->byteCount++] = reader->shiftReg; reader->output[reader->byteCount++] = reader->shiftReg;
if (reader->byteCount > reader->byteCountMax) { if (reader->byteCount > reader->byteCountMax) {
// buffer overflow, give up // buffer overflow, give up
@ -1344,11 +1343,11 @@ static int RAMFUNC Handle15693SampleFromReader(bool bit, DecodeReader_t *reader)
reader->bitCount = 0; reader->bitCount = 0;
reader->shiftReg = 0; reader->shiftReg = 0;
if (reader->byteCount == reader->jam_search_len) { if (reader->byteCount == reader->jam_search_len) {
if (!memcmp(reader->output, reader->jam_search_string, reader->jam_search_len)) { if (!memcmp(reader->output, reader->jam_search_string, reader->jam_search_len)) {
LED_D_ON(); LED_D_ON();
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_JAM); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_JAM);
reader->state = STATE_READER_RECEIVE_JAMMING; reader->state = STATE_READER_RECEIVE_JAMMING;
} }
} }
} }
} else if (reader->sum1 > 6) { // too long low bit } else if (reader->sum1 > 6) { // too long low bit
@ -2132,17 +2131,16 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
// free eventually allocated BigBuf memory // free eventually allocated BigBuf memory
BigBuf_free_keep_EM(); BigBuf_free_keep_EM();
iso15_tag_t *tag = (iso15_tag_t*) BigBuf_get_EM_addr(); iso15_tag_t *tag = (iso15_tag_t *) BigBuf_get_EM_addr();
if (tag == NULL) if (tag == NULL) {
{
Dbprintf("Can't allocate emulator memory"); Dbprintf("Can't allocate emulator memory");
reply_ng(CMD_HF_ISO15693_SIMULATE, PM3_EFAILED, NULL, 0); reply_ng(CMD_HF_ISO15693_SIMULATE, PM3_EFAILED, NULL, 0);
return; return;
} }
if (uid != NULL) { // new tag (need initialization) if (uid != NULL) { // new tag (need initialization)
uint8_t nullUid[8] = { 0 }; uint8_t nullUid[8] = { 0 };
if (memcmp(uid, nullUid, 8) != 0) if (memcmp(uid, nullUid, 8) != 0) {
{ // simulate a new tag bazed on client parameters // simulate a new tag bazed on client parameters
memcpy(tag->uid, uid, 8); memcpy(tag->uid, uid, 8);
tag->dsfid = 0; tag->dsfid = 0;
tag->dsfidLock = false; tag->dsfidLock = false;
@ -2156,8 +2154,8 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
} }
} }
if (tag->pagesCount > ISO15693_TAG_MAX_PAGES || \ if (tag->pagesCount > ISO15693_TAG_MAX_PAGES || \
tag->pagesCount * tag->bytesPerPage > ISO15693_TAG_MAX_SIZE || tag->pagesCount * tag->bytesPerPage > ISO15693_TAG_MAX_SIZE ||
tag->pagesCount == 0 || tag->bytesPerPage == 0) { tag->pagesCount == 0 || tag->bytesPerPage == 0) {
Dbprintf("Tag size error: pagesCount = %d, bytesPerPage=%d", tag->pagesCount, tag->bytesPerPage); Dbprintf("Tag size error: pagesCount = %d, bytesPerPage=%d", tag->pagesCount, tag->bytesPerPage);
reply_ng(CMD_HF_ISO15693_SIMULATE, PM3_EOPABORTED, NULL, 0); reply_ng(CMD_HF_ISO15693_SIMULATE, PM3_EOPABORTED, NULL, 0);
return; return;
@ -2220,7 +2218,7 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
// Shorten 0 terminated msgs // Shorten 0 terminated msgs
// (Some times received commands are prolonged with a random number of 0 bytes...) // (Some times received commands are prolonged with a random number of 0 bytes...)
while (cmd[cmd_len-1] == 0) { while (cmd[cmd_len - 1] == 0) {
cmd_len--; cmd_len--;
if (cmd_len <= 3) if (cmd_len <= 3)
break; break;
@ -2236,21 +2234,18 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
// Check CRC and drop received cmd with bad CRC // Check CRC and drop received cmd with bad CRC
uint16_t crc = CalculateCrc15(cmd, cmd_len - 2); uint16_t crc = CalculateCrc15(cmd, cmd_len - 2);
if ((( crc & 0xff ) != cmd[cmd_len - 2]) || (( crc >> 8 ) != cmd[cmd_len - 1])) { if (((crc & 0xff) != cmd[cmd_len - 2]) || ((crc >> 8) != cmd[cmd_len - 1])) {
crc = CalculateCrc15(cmd, ++cmd_len - 2); // if crc end with 00 crc = CalculateCrc15(cmd, ++cmd_len - 2); // if crc end with 00
if ((( crc & 0xff ) != cmd[cmd_len - 2]) || (( crc >> 8 ) != cmd[cmd_len - 1])) { if (((crc & 0xff) != cmd[cmd_len - 2]) || ((crc >> 8) != cmd[cmd_len - 1])) {
crc = CalculateCrc15(cmd, ++cmd_len - 2); // if crc end with 00 00 crc = CalculateCrc15(cmd, ++cmd_len - 2); // if crc end with 00 00
if ((( crc & 0xff ) != cmd[cmd_len - 2]) || (( crc >> 8 ) != cmd[cmd_len - 1])) { if (((crc & 0xff) != cmd[cmd_len - 2]) || ((crc >> 8) != cmd[cmd_len - 1])) {
if (g_dbglevel >= DBG_DEBUG) Dbprintf("CrcFail!, expected CRC=%02X%02X", crc & 0xff, crc >> 8); if (g_dbglevel >= DBG_DEBUG) Dbprintf("CrcFail!, expected CRC=%02X%02X", crc & 0xff, crc >> 8);
continue; continue;
} } else if (g_dbglevel >= DBG_DEBUG)
else if (g_dbglevel >= DBG_DEBUG)
Dbprintf("CrcOK"); Dbprintf("CrcOK");
} } else if (g_dbglevel >= DBG_DEBUG)
else if (g_dbglevel >= DBG_DEBUG)
Dbprintf("CrcOK"); Dbprintf("CrcOK");
} } else if (g_dbglevel >= DBG_DEBUG)
else if (g_dbglevel >= DBG_DEBUG)
Dbprintf("CrcOK"); Dbprintf("CrcOK");
cmd_len -= 2; // remove the CRC from the cmd cmd_len -= 2; // remove the CRC from the cmd
@ -2323,8 +2318,7 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
recv[1] = tag->dsfid; recv[1] = tag->dsfid;
memcpy(&recv[2], tag->uid, 8); memcpy(&recv[2], tag->uid, 8);
recvLen = 10; recvLen = 10;
} } else {
else {
if ((cmd[0] & ISO15_REQ_SELECT) == ISO15_REQ_SELECT) { if ((cmd[0] & ISO15_REQ_SELECT) == ISO15_REQ_SELECT) {
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Selected Request"); if (g_dbglevel >= DBG_DEBUG) Dbprintf("Selected Request");
if (tag->state != TAG_STATE_SELECTED) if (tag->state != TAG_STATE_SELECTED)
@ -2335,12 +2329,11 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
cmdCpt = 2; cmdCpt = 2;
if ((cmd[0] & ISO15_REQ_ADDRESS) == ISO15_REQ_ADDRESS) { if ((cmd[0] & ISO15_REQ_ADDRESS) == ISO15_REQ_ADDRESS) {
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Addressed Request"); if (g_dbglevel >= DBG_DEBUG) Dbprintf("Addressed Request");
if (cmd_len < cmdCpt+8) if (cmd_len < cmdCpt + 8)
continue; continue;
if (memcmp(&cmd[cmdCpt], tag->uid, 8) != 0) if (memcmp(&cmd[cmdCpt], tag->uid, 8) != 0) {
{ if (cmd_len < cmdCpt + 9 || memcmp(&cmd[cmdCpt + 1], tag->uid, 8) != 0) {
if (cmd_len < cmdCpt+9 || memcmp(&cmd[cmdCpt+1], tag->uid, 8) != 0) // check uid even if manifacturer byte is present
{ // check uid even if manifacturer byte is present
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Address don't match tag uid"); if (g_dbglevel >= DBG_DEBUG) Dbprintf("Address don't match tag uid");
if (cmd[1] == ISO15693_SELECT) if (cmd[1] == ISO15693_SELECT)
tag->state = TAG_STATE_READY; // we are not anymore the selected TAG tag->state = TAG_STATE_READY; // we are not anymore the selected TAG
@ -2349,204 +2342,200 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
cmdCpt++; cmdCpt++;
} }
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Address match tag uid"); if (g_dbglevel >= DBG_DEBUG) Dbprintf("Address match tag uid");
cmdCpt+=8; cmdCpt += 8;
} } else if (tag->state == TAG_STATE_SILENCED) {
else if (tag->state == TAG_STATE_SILENCED)
{
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Unaddressed request in quiet state: drop"); if (g_dbglevel >= DBG_DEBUG) Dbprintf("Unaddressed request in quiet state: drop");
continue; // drop unadressed request in quiet state continue; // drop unadressed request in quiet state
} }
switch(cmd[1]) { switch (cmd[1]) {
case ISO15693_INVENTORY: case ISO15693_INVENTORY:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Inventory cmd"); if (g_dbglevel >= DBG_DEBUG) Dbprintf("Inventory cmd");
recv[0] = ISO15_NOERROR;
recv[1] = tag->dsfid;
memcpy(&recv[2], tag->uid, 8);
recvLen = 10;
break;
case ISO15693_STAYQUIET:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("StayQuiet cmd");
tag->state = TAG_STATE_SILENCED;
break;
case ISO15693_READBLOCK:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("ReadBlock cmd");
pageNum = cmd[cmdCpt++];
if (pageNum >= tag->pagesCount)
error = ISO15_ERROR_BLOCK_UNAVAILABLE;
else {
recv[0] = ISO15_NOERROR; recv[0] = ISO15_NOERROR;
recvLen = 1; recv[1] = tag->dsfid;
if ((cmd[0] & ISO15_REQ_OPTION) == ISO15_REQ_OPTION) { // ask for lock status memcpy(&recv[2], tag->uid, 8);
recv[1] = tag->locks[pageNum]; recvLen = 10;
recvLen++; break;
} case ISO15693_STAYQUIET:
for (uint8_t i = 0 ; i < tag->bytesPerPage ; i++) if (g_dbglevel >= DBG_DEBUG) Dbprintf("StayQuiet cmd");
recv[recvLen+i] = tag->data[(pageNum * tag->bytesPerPage) + i]; tag->state = TAG_STATE_SILENCED;
recvLen += tag->bytesPerPage; break;
} case ISO15693_READBLOCK:
break; if (g_dbglevel >= DBG_DEBUG) Dbprintf("ReadBlock cmd");
case ISO15693_WRITEBLOCK: pageNum = cmd[cmdCpt++];
if (g_dbglevel >= DBG_DEBUG) Dbprintf("WriteBlock cmd"); if (pageNum >= tag->pagesCount)
pageNum = cmd[cmdCpt++]; error = ISO15_ERROR_BLOCK_UNAVAILABLE;
if (pageNum >= tag->pagesCount) else {
error = ISO15_ERROR_BLOCK_UNAVAILABLE; recv[0] = ISO15_NOERROR;
else { recvLen = 1;
for (uint8_t i = 0 ; i < tag->bytesPerPage ; i++) if ((cmd[0] & ISO15_REQ_OPTION) == ISO15_REQ_OPTION) { // ask for lock status
tag->data[(pageNum*tag->bytesPerPage) + i] = cmd[i + cmdCpt]; recv[1] = tag->locks[pageNum];
recv[0] = ISO15_NOERROR; recvLen++;
recvLen = 1; }
} for (uint8_t i = 0 ; i < tag->bytesPerPage ; i++)
break; recv[recvLen + i] = tag->data[(pageNum * tag->bytesPerPage) + i];
case ISO15693_LOCKBLOCK: recvLen += tag->bytesPerPage;
if (g_dbglevel >= DBG_DEBUG) Dbprintf("LockBlock cmd");
pageNum = cmd[cmdCpt++];
if (pageNum >= tag->pagesCount)
error = ISO15_ERROR_BLOCK_UNAVAILABLE;
else if (tag->locks[pageNum])
error = ISO15_ERROR_BLOCK_LOCKED_ALREADY;
else {
tag->locks[pageNum] = 1;
recv[0] = ISO15_NOERROR;
recvLen = 1;
}
break;
case ISO15693_READ_MULTI_BLOCK:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("ReadMultiBlock cmd");
pageNum = cmd[cmdCpt++];
nbPages = cmd[cmdCpt++];
if (pageNum+nbPages >= tag->pagesCount)
error = ISO15_ERROR_BLOCK_UNAVAILABLE;
else {
recv[0] = ISO15_NOERROR;
recvLen = 1;
for (int i = 0 ; i < (nbPages + 1) * tag->bytesPerPage && \
recvLen + 3 < ISO15693_MAX_RESPONSE_LENGTH ; i++) {
if ((i % tag->bytesPerPage) == 0 && (cmd[0] & ISO15_REQ_OPTION))
recv[recvLen++] = tag->locks[pageNum + (i / tag->bytesPerPage)];
recv[recvLen++] = tag->data[(pageNum * tag->bytesPerPage) + i];
} }
if (recvLen + 3 > ISO15693_MAX_RESPONSE_LENGTH) // limit response size break;
recvLen = ISO15693_MAX_RESPONSE_LENGTH - 3; // to avoid overflow case ISO15693_WRITEBLOCK:
} if (g_dbglevel >= DBG_DEBUG) Dbprintf("WriteBlock cmd");
break; pageNum = cmd[cmdCpt++];
case ISO15693_WRITE_AFI: if (pageNum >= tag->pagesCount)
if (g_dbglevel >= DBG_DEBUG) Dbprintf("WriteAFI cmd"); error = ISO15_ERROR_BLOCK_UNAVAILABLE;
if (tag->afiLock) else {
error = ISO15_ERROR_BLOCK_LOCKED; for (uint8_t i = 0 ; i < tag->bytesPerPage ; i++)
else { tag->data[(pageNum * tag->bytesPerPage) + i] = cmd[i + cmdCpt];
tag->afi = cmd[cmdCpt++]; recv[0] = ISO15_NOERROR;
recv[0] = ISO15_NOERROR; recvLen = 1;
recvLen = 1;
}
break;
case ISO15693_LOCK_AFI:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("LockAFI cmd");
if (tag->afiLock)
error = ISO15_ERROR_BLOCK_LOCKED_ALREADY;
else {
tag->afiLock = true;
recv[0] = ISO15_NOERROR;
recvLen = 1;
}
break;
case ISO15693_WRITE_DSFID:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("WriteDSFID cmd");
if (tag->dsfidLock)
error = ISO15_ERROR_BLOCK_LOCKED;
else {
tag->dsfid = cmd[cmdCpt++];
recv[0] = ISO15_NOERROR;
recvLen = 1;
}
break;
case ISO15693_LOCK_DSFID:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("LockDSFID cmd");
if (tag->dsfidLock)
error = ISO15_ERROR_BLOCK_LOCKED_ALREADY;
else {
tag->dsfidLock = true;
recv[0] = ISO15_NOERROR;
recvLen = 1;
}
break;
case ISO15693_SELECT:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Select cmd");
tag->state = TAG_STATE_SELECTED;
recv[0] = ISO15_NOERROR;
recvLen = 1;
break;
case ISO15693_RESET_TO_READY:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("ResetToReady cmd");
tag->state = TAG_STATE_READY;
recv[0] = ISO15_NOERROR;
recvLen = 1;
break;
case ISO15693_GET_SYSTEM_INFO:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("GetSystemInfo cmd");
recv[0] = ISO15_NOERROR;
recv[1] = 0x0f; // sysinfo contain all info
memcpy(&recv[2], tag->uid, 8);
recv[10] = tag->dsfid;
recv[11] = tag->afi;
recv[12] = tag->pagesCount - 1;
recv[13] = tag->bytesPerPage - 1;
recv[14] = tag->ic;
recvLen = 15;
break;
case ISO15693_READ_MULTI_SECSTATUS:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("ReadMultiSecStatus cmd");
pageNum = cmd[cmdCpt++];
nbPages = cmd[cmdCpt++];
if (pageNum + nbPages >= tag->pagesCount)
error = ISO15_ERROR_BLOCK_UNAVAILABLE;
else {
recv[0] = ISO15_NOERROR;
recvLen = 1;
for (uint8_t i = 0 ; i < nbPages + 1 ; i++)
recv[recvLen++] = tag->locks[pageNum + i];
}
break;
case ISO15693_GET_RANDOM_NUMBER:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("GetRandomNumber cmd");
tag->random[0] = (uint8_t)(reader_eof_time) ^ 0xFF; // poor random number
tag->random[1] = (uint8_t)(reader_eof_time >> 8) ^ 0xFF;
recv[0] = ISO15_NOERROR;
recv[1] = tag->random[0]; // poor random number
recv[2] = tag->random[1];
recvLen = 3;
break;
case ISO15693_SET_PASSWORD:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("SetPassword cmd");
if (cmd_len > cmdCpt+5)
cmdCpt++; // skip manifacturer code
if (cmd_len > cmdCpt+4)
{
pwdId = cmd[cmdCpt++];
if (pwdId == 4) // Privacy password
{
tag->privacyPasswd[0] = cmd[cmdCpt] ^ tag->random[0];
tag->privacyPasswd[1] = cmd[cmdCpt+1] ^ tag->random[1];
tag->privacyPasswd[2] = cmd[cmdCpt+2] ^ tag->random[0];
tag->privacyPasswd[3] = cmd[cmdCpt+3] ^ tag->random[1];
} }
} break;
recv[0] = ISO15_NOERROR; case ISO15693_LOCKBLOCK:
recvLen = 1; if (g_dbglevel >= DBG_DEBUG) Dbprintf("LockBlock cmd");
break; pageNum = cmd[cmdCpt++];
case ISO15693_ENABLE_PRIVACY: if (pageNum >= tag->pagesCount)
if (g_dbglevel >= DBG_DEBUG) Dbprintf("EnablePrivacy cmd"); error = ISO15_ERROR_BLOCK_UNAVAILABLE;
// not realy entering privacy mode else if (tag->locks[pageNum])
// just return NOERROR error = ISO15_ERROR_BLOCK_LOCKED_ALREADY;
recv[0] = ISO15_NOERROR; else {
recvLen = 1; tag->locks[pageNum] = 1;
break; recv[0] = ISO15_NOERROR;
default: recvLen = 1;
if (g_dbglevel >= DBG_DEBUG) }
Dbprintf("ISO15693 CMD 0x%2X not supported", cmd[1]); break;
case ISO15693_READ_MULTI_BLOCK:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("ReadMultiBlock cmd");
pageNum = cmd[cmdCpt++];
nbPages = cmd[cmdCpt++];
if (pageNum + nbPages >= tag->pagesCount)
error = ISO15_ERROR_BLOCK_UNAVAILABLE;
else {
recv[0] = ISO15_NOERROR;
recvLen = 1;
for (int i = 0 ; i < (nbPages + 1) * tag->bytesPerPage && \
recvLen + 3 < ISO15693_MAX_RESPONSE_LENGTH ; i++) {
if ((i % tag->bytesPerPage) == 0 && (cmd[0] & ISO15_REQ_OPTION))
recv[recvLen++] = tag->locks[pageNum + (i / tag->bytesPerPage)];
recv[recvLen++] = tag->data[(pageNum * tag->bytesPerPage) + i];
}
if (recvLen + 3 > ISO15693_MAX_RESPONSE_LENGTH) // limit response size
recvLen = ISO15693_MAX_RESPONSE_LENGTH - 3; // to avoid overflow
}
break;
case ISO15693_WRITE_AFI:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("WriteAFI cmd");
if (tag->afiLock)
error = ISO15_ERROR_BLOCK_LOCKED;
else {
tag->afi = cmd[cmdCpt++];
recv[0] = ISO15_NOERROR;
recvLen = 1;
}
break;
case ISO15693_LOCK_AFI:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("LockAFI cmd");
if (tag->afiLock)
error = ISO15_ERROR_BLOCK_LOCKED_ALREADY;
else {
tag->afiLock = true;
recv[0] = ISO15_NOERROR;
recvLen = 1;
}
break;
case ISO15693_WRITE_DSFID:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("WriteDSFID cmd");
if (tag->dsfidLock)
error = ISO15_ERROR_BLOCK_LOCKED;
else {
tag->dsfid = cmd[cmdCpt++];
recv[0] = ISO15_NOERROR;
recvLen = 1;
}
break;
case ISO15693_LOCK_DSFID:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("LockDSFID cmd");
if (tag->dsfidLock)
error = ISO15_ERROR_BLOCK_LOCKED_ALREADY;
else {
tag->dsfidLock = true;
recv[0] = ISO15_NOERROR;
recvLen = 1;
}
break;
case ISO15693_SELECT:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Select cmd");
tag->state = TAG_STATE_SELECTED;
recv[0] = ISO15_NOERROR;
recvLen = 1;
break;
case ISO15693_RESET_TO_READY:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("ResetToReady cmd");
tag->state = TAG_STATE_READY;
recv[0] = ISO15_NOERROR;
recvLen = 1;
break;
case ISO15693_GET_SYSTEM_INFO:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("GetSystemInfo cmd");
recv[0] = ISO15_NOERROR;
recv[1] = 0x0f; // sysinfo contain all info
memcpy(&recv[2], tag->uid, 8);
recv[10] = tag->dsfid;
recv[11] = tag->afi;
recv[12] = tag->pagesCount - 1;
recv[13] = tag->bytesPerPage - 1;
recv[14] = tag->ic;
recvLen = 15;
break;
case ISO15693_READ_MULTI_SECSTATUS:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("ReadMultiSecStatus cmd");
pageNum = cmd[cmdCpt++];
nbPages = cmd[cmdCpt++];
if (pageNum + nbPages >= tag->pagesCount)
error = ISO15_ERROR_BLOCK_UNAVAILABLE;
else {
recv[0] = ISO15_NOERROR;
recvLen = 1;
for (uint8_t i = 0 ; i < nbPages + 1 ; i++)
recv[recvLen++] = tag->locks[pageNum + i];
}
break;
case ISO15693_GET_RANDOM_NUMBER:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("GetRandomNumber cmd");
tag->random[0] = (uint8_t)(reader_eof_time) ^ 0xFF; // poor random number
tag->random[1] = (uint8_t)(reader_eof_time >> 8) ^ 0xFF;
recv[0] = ISO15_NOERROR;
recv[1] = tag->random[0]; // poor random number
recv[2] = tag->random[1];
recvLen = 3;
break;
case ISO15693_SET_PASSWORD:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("SetPassword cmd");
if (cmd_len > cmdCpt + 5)
cmdCpt++; // skip manifacturer code
if (cmd_len > cmdCpt + 4) {
pwdId = cmd[cmdCpt++];
if (pwdId == 4) { // Privacy password
tag->privacyPasswd[0] = cmd[cmdCpt] ^ tag->random[0];
tag->privacyPasswd[1] = cmd[cmdCpt + 1] ^ tag->random[1];
tag->privacyPasswd[2] = cmd[cmdCpt + 2] ^ tag->random[0];
tag->privacyPasswd[3] = cmd[cmdCpt + 3] ^ tag->random[1];
}
}
recv[0] = ISO15_NOERROR;
recvLen = 1;
break;
case ISO15693_ENABLE_PRIVACY:
if (g_dbglevel >= DBG_DEBUG) Dbprintf("EnablePrivacy cmd");
// not realy entering privacy mode
// just return NOERROR
recv[0] = ISO15_NOERROR;
recvLen = 1;
break;
default:
if (g_dbglevel >= DBG_DEBUG)
Dbprintf("ISO15693 CMD 0x%2X not supported", cmd[1]);
error = ISO15_ERROR_CMD_NOT_SUP; error = ISO15_ERROR_CMD_NOT_SUP;
break; break;
} }
if (error != 0) { // Error happened if (error != 0) { // Error happened
@ -2569,8 +2558,7 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
if (tag->expectFsk) { // Not suppoted yet if (tag->expectFsk) { // Not suppoted yet
if (g_dbglevel >= DBG_DEBUG) Dbprintf("%ERROR: FSK answers are not supported yet"); if (g_dbglevel >= DBG_DEBUG) Dbprintf("%ERROR: FSK answers are not supported yet");
//TransmitTo15693ReaderFSK(ts->buf,ts->max, &response_time, 0, !tag->expectFast); //TransmitTo15693ReaderFSK(ts->buf,ts->max, &response_time, 0, !tag->expectFast);
} } else
else
TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, !tag->expectFast); TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, !tag->expectFast);
LogTrace_ISO15693(recv, recvLen, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false); LogTrace_ISO15693(recv, recvLen, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);

View file

@ -532,12 +532,11 @@ static uint8_t arg_add_default(void *at[]) {
} }
static uint16_t arg_get_raw_flag(uint8_t uidlen, bool unaddressed, bool scan, bool add_option) { static uint16_t arg_get_raw_flag(uint8_t uidlen, bool unaddressed, bool scan, bool add_option) {
uint16_t flags = 0; uint16_t flags = 0;
; ;
if (uidlen == 8 || scan || unaddressed) { if (uidlen == 8 || scan || unaddressed) {
flags = (ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY); flags = (ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY);
} }
if ((!unaddressed) || scan) if ((!unaddressed) || scan) {
{
flags |= ISO15_REQ_ADDRESS; flags |= ISO15_REQ_ADDRESS;
} }
if (add_option) { if (add_option) {
@ -1278,10 +1277,9 @@ static void print_blocks_15693(uint8_t *data, uint16_t bytes, int blocksize, boo
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
if (blocksize == 0 || bytes == 0) if (blocksize == 0 || bytes == 0) {
{ PrintAndLogEx(INFO, "Tag is empty!");
PrintAndLogEx(INFO, "Tag is empty!"); return;
return;
} }
print_hrule(blocksize); print_hrule(blocksize);
@ -1432,8 +1430,7 @@ static int CmdHF15Sim(const char *Cmd) {
} }
CLIParserFree(ctx); CLIParserFree(ctx);
if (uidlen == 0) // get UID from emulator if (uidlen == 0) { // get UID from emulator
{
// reserve memory // reserve memory
iso15_tag_t *tag = calloc(1, sizeof(iso15_tag_t)); iso15_tag_t *tag = calloc(1, sizeof(iso15_tag_t));
if (tag == NULL) { if (tag == NULL) {
@ -1441,7 +1438,7 @@ static int CmdHF15Sim(const char *Cmd) {
return PM3_EMALLOC; return PM3_EMALLOC;
} }
if (GetFromDevice(BIG_BUF_EML, (uint8_t*)tag, sizeof(iso15_tag_t), 0, NULL, 0, NULL, 2500, false) == false) { if (GetFromDevice(BIG_BUF_EML, (uint8_t *)tag, sizeof(iso15_tag_t), 0, NULL, 0, NULL, 2500, false) == false) {
PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
free(tag); free(tag);
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
@ -1729,8 +1726,8 @@ static int CmdHF15Dump(const char *Cmd) {
uint8_t arglen = arg_add_default(argtable); uint8_t arglen = arg_add_default(argtable);
argtable[arglen++] = arg_str0("f", "file", "<fn>", "Specify a filename for dump file"), argtable[arglen++] = arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
argtable[arglen++] = arg_int0(NULL, "bs", "<dec>", "block size (def 4)"), argtable[arglen++] = arg_int0(NULL, "bs", "<dec>", "block size (def 4)"),
argtable[arglen++] = arg_lit0(NULL, "ns", "no save to file"), argtable[arglen++] = arg_lit0(NULL, "ns", "no save to file"),
argtable[arglen++] = arg_lit0("v", "verbose", "verbose output"); argtable[arglen++] = arg_lit0("v", "verbose", "verbose output");
argtable[arglen++] = arg_param_end; argtable[arglen++] = arg_param_end;
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -1847,21 +1844,18 @@ static int CmdHF15Dump(const char *Cmd) {
tag->dsfid = d[dCpt++]; tag->dsfid = d[dCpt++];
if (d[1] & 0x02) if (d[1] & 0x02)
tag->afi = d[dCpt++]; tag->afi = d[dCpt++];
if (d[1] & 0x04) if (d[1] & 0x04) {
{ tag->pagesCount = d[dCpt++] + 1;
tag->pagesCount = d[dCpt++]+1; tag->bytesPerPage = d[dCpt++] + 1;
tag->bytesPerPage = d[dCpt++]+1; } else {
} // Set tag memory layout values (if can't be readed in SYSINFO)
else
{ // Set tag memory layout values (if can't be readed in SYSINFO)
tag->bytesPerPage = blocksize; tag->bytesPerPage = blocksize;
tag->pagesCount = 128; tag->pagesCount = 128;
} }
if (d[1] & 0x08) if (d[1] & 0x08)
tag->ic = d[dCpt++]; tag->ic = d[dCpt++];
if (verbose) if (verbose) {
{
print_emltag_info_15693(tag); print_emltag_info_15693(tag);
} }
@ -1957,9 +1951,9 @@ static int CmdHF15Dump(const char *Cmd) {
PrintAndLogEx(INFO, "%3d/0x%02X | %s| %s | %s" PrintAndLogEx(INFO, "%3d/0x%02X | %s| %s | %s"
, i , i
, i , i
, sprint_hex(&tag->data[i*tag->bytesPerPage], tag->bytesPerPage) , sprint_hex(&tag->data[i * tag->bytesPerPage], tag->bytesPerPage)
, lck , lck
, sprint_ascii(&tag->data[i*tag->bytesPerPage], tag->bytesPerPage) , sprint_ascii(&tag->data[i * tag->bytesPerPage], tag->bytesPerPage)
); );
} }
PrintAndLogEx(INFO, "---------+-------------+---+-------"); PrintAndLogEx(INFO, "---------+-------------+---+-------");
@ -1979,7 +1973,7 @@ static int CmdHF15Dump(const char *Cmd) {
FillFileNameByUID(fptr, SwapEndian64(uid, sizeof(uid), 8), "-dump", sizeof(uid)); FillFileNameByUID(fptr, SwapEndian64(uid, sizeof(uid), 8), "-dump", sizeof(uid));
} }
pm3_save_dump(filename, (uint8_t*)tag, sizeof(iso15_tag_t), jsf15_v4); pm3_save_dump(filename, (uint8_t *)tag, sizeof(iso15_tag_t), jsf15_v4);
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -2132,7 +2132,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
} }
out: out:
mfu_fingerprint(tagtype, has_auth_key, authkeyptr, ak_len); mfu_fingerprint(tagtype, has_auth_key, authkeyptr, ak_len);
DropField(); DropField();
if (locked) { if (locked) {

View file

@ -525,19 +525,19 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data,
iso15_tag_t *tag = (iso15_tag_t *)data; iso15_tag_t *tag = (iso15_tag_t *)data;
JsonSaveBufAsHexCompact(root, "$.Card.uid", tag->uid, 8); JsonSaveBufAsHexCompact(root, "$.Card.uid", tag->uid, 8);
JsonSaveBufAsHexCompact(root, "$.Card.dsfid", &tag->dsfid, 1); JsonSaveBufAsHexCompact(root, "$.Card.dsfid", &tag->dsfid, 1);
JsonSaveBufAsHexCompact(root, "$.Card.dsfidLock", (uint8_t*)&tag->dsfidLock, 1); JsonSaveBufAsHexCompact(root, "$.Card.dsfidLock", (uint8_t *)&tag->dsfidLock, 1);
JsonSaveBufAsHexCompact(root, "$.Card.afi", &tag->afi, 1); JsonSaveBufAsHexCompact(root, "$.Card.afi", &tag->afi, 1);
JsonSaveBufAsHexCompact(root, "$.Card.afiLock", (uint8_t*)&tag->afiLock, 1); JsonSaveBufAsHexCompact(root, "$.Card.afiLock", (uint8_t *)&tag->afiLock, 1);
JsonSaveBufAsHexCompact(root, "$.Card.bytesPerPage", &tag->bytesPerPage, 1); JsonSaveBufAsHexCompact(root, "$.Card.bytesPerPage", &tag->bytesPerPage, 1);
JsonSaveBufAsHexCompact(root, "$.Card.pagesCount", &tag->pagesCount, 1); JsonSaveBufAsHexCompact(root, "$.Card.pagesCount", &tag->pagesCount, 1);
JsonSaveBufAsHexCompact(root, "$.Card.IC", &tag->ic, 1); JsonSaveBufAsHexCompact(root, "$.Card.IC", &tag->ic, 1);
JsonSaveBufAsHexCompact(root, "$.Card.locks", tag->locks, tag->pagesCount); JsonSaveBufAsHexCompact(root, "$.Card.locks", tag->locks, tag->pagesCount);
JsonSaveBufAsHexCompact(root, "$.Card.random", tag->random, 2); JsonSaveBufAsHexCompact(root, "$.Card.random", tag->random, 2);
JsonSaveBufAsHexCompact(root, "$.Card.privacyPasswd", tag->privacyPasswd, 4); JsonSaveBufAsHexCompact(root, "$.Card.privacyPasswd", tag->privacyPasswd, 4);
JsonSaveBufAsHexCompact(root, "$.Card.state", (uint8_t*)&tag->state, 1); JsonSaveBufAsHexCompact(root, "$.Card.state", (uint8_t *)&tag->state, 1);
for (size_t i = 0 ; i < tag->pagesCount ; i++) { for (size_t i = 0 ; i < tag->pagesCount ; i++) {
if (((i+1) * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) if (((i + 1) * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE)
break; break;
snprintf(path, sizeof(path), "$.blocks.%zu", i); snprintf(path, sizeof(path), "$.blocks.%zu", i);
JsonSaveBufAsHexCompact(root, path, JsonSaveBufAsHexCompact(root, path,
@ -1705,20 +1705,20 @@ int loadFileJSONex(const char *preferredName, void *data, size_t maxdatalen, siz
iso15_tag_t *tag = (iso15_tag_t *)udata.bytes; iso15_tag_t *tag = (iso15_tag_t *)udata.bytes;
JsonLoadBufAsHex(root, "$.Card.UID", tag->uid, 8, datalen); JsonLoadBufAsHex(root, "$.Card.UID", tag->uid, 8, datalen);
JsonLoadBufAsHex(root, "$.Card.dsfid", &tag->dsfid, 1, datalen); JsonLoadBufAsHex(root, "$.Card.dsfid", &tag->dsfid, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.dsfidLock", (uint8_t*)&tag->dsfidLock, 1, datalen); JsonLoadBufAsHex(root, "$.Card.dsfidLock", (uint8_t *)&tag->dsfidLock, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.afi", &tag->afi, 1, datalen); JsonLoadBufAsHex(root, "$.Card.afi", &tag->afi, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.afiLock", (uint8_t*)&tag->afiLock, 1, datalen); JsonLoadBufAsHex(root, "$.Card.afiLock", (uint8_t *)&tag->afiLock, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.bytesPerPage", &tag->bytesPerPage, 1, datalen); JsonLoadBufAsHex(root, "$.Card.bytesPerPage", &tag->bytesPerPage, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.pagesCount", &tag->pagesCount, 1, datalen); JsonLoadBufAsHex(root, "$.Card.pagesCount", &tag->pagesCount, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.IC", &tag->ic, 1, datalen); JsonLoadBufAsHex(root, "$.Card.IC", &tag->ic, 1, datalen);
JsonLoadBufAsHex(root, "$.Card.locks", tag->locks, tag->pagesCount, datalen); JsonLoadBufAsHex(root, "$.Card.locks", tag->locks, tag->pagesCount, datalen);
JsonLoadBufAsHex(root, "$.Card.random", tag->random, 2, datalen); JsonLoadBufAsHex(root, "$.Card.random", tag->random, 2, datalen);
JsonLoadBufAsHex(root, "$.Card.privacyPasswd", tag->privacyPasswd, 4, datalen); JsonLoadBufAsHex(root, "$.Card.privacyPasswd", tag->privacyPasswd, 4, datalen);
JsonLoadBufAsHex(root, "$.Card.state", (uint8_t*)&tag->state, 1, datalen); JsonLoadBufAsHex(root, "$.Card.state", (uint8_t *)&tag->state, 1, datalen);
size_t sptr = 0; size_t sptr = 0;
for (int i = 0; i < tag->pagesCount ; i++) { for (int i = 0; i < tag->pagesCount ; i++) {
if (((i+1) * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) { if (((i + 1) * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) {
PrintAndLogEx(ERR, "loadFileJSONex: maxdatalen=%zu (%04zx) block (i)=%4d (%04x) sptr=%zu (%04zx) -- exceeded maxdatalen", maxdatalen, maxdatalen, i, i, sptr, sptr); PrintAndLogEx(ERR, "loadFileJSONex: maxdatalen=%zu (%04zx) block (i)=%4d (%04x) sptr=%zu (%04zx) -- exceeded maxdatalen", maxdatalen, maxdatalen, i, i, sptr, sptr);
retval = PM3_EMALLOC; retval = PM3_EMALLOC;
goto out; goto out;

View file

@ -1662,32 +1662,28 @@
"command": "hf 15 esave", "command": "hf 15 esave",
"description": "Save emulator memory into two files (bin/json)", "description": "Save emulator memory into two files (bin/json)",
"notes": [ "notes": [
"hf 15 esave -f hf-15-01020304hf 15 esave -b 8 -c 42 -f hf-15-01020304" "hf 15 esave -f hf-15-01020304"
], ],
"offline": false, "offline": false,
"options": [ "options": [
"-h, --help This help", "-h, --help This help",
"-f, --file <fn> Specify a filename for dump file", "-f, --file <fn> Specify a filename for dump file"
"--bsize <dec> block size (def 4)",
"-c, --count <dec> number of blocks to export (def all)"
], ],
"usage": "hf 15 esave [-h] -f <fn> [--bsize <dec>] [-c <dec>]" "usage": "hf 15 esave [-h] -f <fn>"
}, },
"hf 15 eview": { "hf 15 eview": {
"command": "hf 15 eview", "command": "hf 15 eview",
"description": "It displays emulator memory", "description": "It displays emulator memory",
"notes": [ "notes": [
"hf 15 eview", "hf 15 eview",
"hf 15 eview -b 8 -c 60" "hf 15 eview -z"
], ],
"offline": false, "offline": false,
"options": [ "options": [
"-h, --help This help", "-h, --help This help",
"-b, --blocksize <dec> block size (def 4)",
"-c, --count <dec> number of blocks to display (def all)",
"-z, --dense dense dump output style" "-z, --dense dense dump output style"
], ],
"usage": "hf 15 eview [-hz] [-b <dec>] [-c <dec>]" "usage": "hf 15 eview [-hz]"
}, },
"hf 15 findafi": { "hf 15 findafi": {
"command": "hf 15 findafi", "command": "hf 15 findafi",
@ -1886,6 +1882,7 @@
"command": "hf 15 sim", "command": "hf 15 sim",
"description": "Simulate a ISO-15693 tag", "description": "Simulate a ISO-15693 tag",
"notes": [ "notes": [
"hf 15 sim",
"hf 15 sim -u E011223344556677" "hf 15 sim -u E011223344556677"
], ],
"offline": false, "offline": false,
@ -1894,7 +1891,7 @@
"-u, --uid <hex> UID, 8 hex bytes", "-u, --uid <hex> UID, 8 hex bytes",
"-b, --blocksize <dec> block size (def 4)" "-b, --blocksize <dec> block size (def 4)"
], ],
"usage": "hf 15 sim [-h] -u <hex> [-b <dec>]" "usage": "hf 15 sim [-h] [-u <hex>] [-b <dec>]"
}, },
"hf 15 slixeasdisable": { "hf 15 slixeasdisable": {
"command": "hf 15 slixeasdisable", "command": "hf 15 slixeasdisable",
@ -12341,6 +12338,6 @@
"metadata": { "metadata": {
"commands_extracted": 711, "commands_extracted": 711,
"extracted_by": "PM3Help2JSON v1.00", "extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2024-01-23T14:27:27" "extracted_on": "2024-01-24T17:12:09"
} }
} }