int CmdHF15CmdInquiry(const char *Cmd) { UsbCommand resp; uint8_t *recv; UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? uint8_t *req=c.d.asBytes; int reqlen=0; req[0]= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; req[1]=ISO15_CMD_INVENTORY; req[2]=0; // mask length reqlen=AddCrc(req,3); c.arg[0]=reqlen; SendCommand(&c); if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { if (resp.arg[0]>=12) { recv = resp.d.asBytes; PrintAndLog("UID=%s",sprintUID(NULL,&recv[2])); PrintAndLog("Tag Info: %s",getTagInfo(&recv[2])); } else { PrintAndLog("Response to short, just %i bytes. No tag?\n",resp.arg[0]); } } else { PrintAndLog("timeout."); } return 0; }
// used with 'hf search' int HF15Reader(const char *Cmd, bool verbose) { uint8_t uid[8] = {0,0,0,0,0,0,0,0}; if (!getUID(uid)) { if (verbose) PrintAndLogEx(WARNING, "No tag found."); return 0; } PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, uid)); PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(uid)); return 1; }
/** * parses common HF 15 CMD parameters and prepares some data structures * Parameters: * **cmd command line */ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) { int temp; uint8_t *req = c->d.asBytes; uint8_t uid[8] = {0x00}; uint32_t reqlen = 0; // strip while (**cmd==' ' || **cmd=='\t') (*cmd)++; if (strstr(*cmd, "-2") == *cmd) { c->arg[1] = 0; // use 1of256 (*cmd) += 2; } // strip while (**cmd==' ' || **cmd=='\t') (*cmd)++; if (strstr(*cmd, "-o") == *cmd) { req[reqlen] = ISO15_REQ_OPTION; (*cmd) += 2; } // strip while (**cmd == ' ' || **cmd == '\t') (*cmd)++; switch (**cmd) { case 0: PrintAndLogEx(WARNING, "missing addr"); return 0; break; case 'u': case 'U': // unaddressed mode may not be supported by all vendors req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY; req[reqlen++] = iso15cmd; break; case '*': // we scan for the UID ourself req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; req[reqlen++] = iso15cmd; if (!getUID(uid)) { PrintAndLogEx(WARNING, "No tag found"); return 0; } memcpy(&req[reqlen], uid, sizeof(uid)); PrintAndLogEx(NORMAL, "Detected UID %s", sprintUID(NULL, uid)); reqlen += sizeof(uid); break; default: req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; req[reqlen++] = iso15cmd; // parse UID for (int i=0; i<8 && (*cmd)[i*2] && (*cmd)[i*2+1]; i++) { sscanf((char[]){(*cmd)[i*2], (*cmd)[i*2+1],0}, "%X", &temp); uid[7-i] = temp & 0xff; } PrintAndLogEx(NORMAL, "Using UID %s", sprintUID(NULL, uid)); memcpy(&req[reqlen], uid, sizeof(uid)); reqlen += sizeof(uid); break; }
// Reads all memory pages // need to write to file int CmdHF15Dump(const char*Cmd) { uint8_t fileNameLen = 0; char filename[FILE_PATH_SIZE] = {0}; char * fptr = filename; bool errors = false; uint8_t cmdp = 0; uint8_t uid[8] = {0,0,0,0,0,0,0,0}; while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch(param_getchar(Cmd, cmdp)) { case 'h': case 'H': return usage_15_dump(); case 'f': case 'F': fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); cmdp += 2; break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); errors = true; break; } } //Validations if (errors) return usage_15_dump(); if (fileNameLen < 1) { PrintAndLogEx(INFO, "Using UID as filename"); if (!getUID(uid)) { PrintAndLogEx(WARNING, "No tag found."); return 1; } fptr += sprintf(fptr, "hf-15-"); FillFileNameByUID(fptr,uid,"-dump",sizeof(uid)); } // detect blocksize from card :) PrintAndLogEx(NORMAL, "Reading memory from tag UID %s", sprintUID(NULL, uid)); int blocknum = 0; uint8_t *recv = NULL; // memory. t15memory mem[256]; uint8_t data[256*4] = {0}; memset(data, 0, sizeof(data)); UsbCommand resp; UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? uint8_t *req = c.d.asBytes; req[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; req[1] = ISO15_CMD_READ; // copy uid to read command memcpy(req+2, uid, sizeof(uid)); for (int retry = 0; retry < 5; retry++) { req[10] = blocknum; AddCrc(req, 11); c.arg[0] = 13; clearCommandBuffer(); SendCommand(&c); if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { uint8_t len = resp.arg[0]; if ( len < 2 ) { PrintAndLogEx(FAILED, "iso15693 card select failed"); continue; } recv = resp.d.asBytes; if ( !CheckCrc(recv, len) ) { PrintAndLogEx(FAILED, "crc fail"); continue; } if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(FAILED, "Tag returned Error %i: %s", recv[1], TagErrorStr(recv[1]) ); break; } mem[blocknum].lock = resp.d.asBytes[0]; memcpy(mem[blocknum].block, resp.d.asBytes + 1, 4); memcpy(data + (blocknum * 4), resp.d.asBytes + 1, 4); retry = 0; blocknum++; printf("."); fflush(stdout); } } PrintAndLogEx(NORMAL, "\n"); PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); for (int i = 0; i < blocknum; i++) { PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", i, i, sprint_hex(mem[i].block, 4 ), mem[i].lock, sprint_ascii(mem[i].block, 4) ); } PrintAndLogEx(NORMAL, "\n"); size_t datalen = blocknum * 4; saveFileEML(filename, "eml", data, datalen, 4); saveFile(filename, "bin", data, datalen); return 0; }
/** * Commandline handling: HF15 CMD SYSINFO * get system information from tag/VICC */ int CmdHF15Info(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd)<1 || cmdp == 'h' || cmdp == 'H') return usage_15_info(); UsbCommand resp; uint8_t *recv; UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? uint8_t *req = c.d.asBytes; char cmdbuf[100]; char *cmd = cmdbuf; memset(cmdbuf, 0, sizeof(cmdbuf)); strncpy(cmd, Cmd, 99); if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_SYSINFO) ) return 0; AddCrc(req, c.arg[0]); c.arg[0] += 2; //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(c.d.asBytes, reqlen) ); clearCommandBuffer(); SendCommand(&c); if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { PrintAndLogEx(NORMAL, "iso15693 card select failed"); return 1; } uint32_t status = resp.arg[0]; if ( status < 2 ) { PrintAndLogEx(NORMAL, "iso15693 card doesn't answer to systeminfo command"); return 1; } recv = resp.d.asBytes; if ( recv[0] & ISO15_RES_ERROR ) { PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); return 3; } PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, recv+2)); PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(recv+2)); PrintAndLogEx(NORMAL, " SYSINFO : %s", sprint_hex(recv, status-2)); // DSFID if (recv[1] & 0x01) PrintAndLogEx(NORMAL, " - DSFID supported [0x%02X]", recv[10]); else PrintAndLogEx(NORMAL, " - DSFID not supported"); // AFI if (recv[1] & 0x02) PrintAndLogEx(NORMAL, " - AFI supported [0x%02X]", recv[11]); else PrintAndLogEx(NORMAL, " - AFI not supported"); // IC reference if (recv[1] & 0x08) PrintAndLogEx(NORMAL, " - IC reference supported [0x%02X]", recv[14]); else PrintAndLogEx(NORMAL, " - IC reference not supported"); // memory if (recv[1] & 0x04) { PrintAndLogEx(NORMAL, " - Tag provides info on memory layout (vendor dependent)"); uint8_t blocks = recv[12]+1; uint8_t size = (recv[13] & 0x1F); PrintAndLogEx(NORMAL, " %u (or %u) bytes/blocks x %u blocks", size+1, size, blocks ); } else { PrintAndLogEx(NORMAL, " - Tag does not provide information on memory layout"); } PrintAndLogEx(NORMAL, "\n"); return 0; }
/** * parses common HF 15 CMD parameters and prepares some data structures * Parameters: * **cmd command line */ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd[], int iso15cmdlen) { int temp; uint8_t *req=c->d.asBytes; uint8_t uid[8] = {0x00}; uint32_t reqlen=0; // strip while (**cmd==' ' || **cmd=='\t') (*cmd)++; if (strstr(*cmd,"-2")==*cmd) { c->arg[1]=0; // use 1of256 (*cmd)+=2; } // strip while (**cmd==' ' || **cmd=='\t') (*cmd)++; if (strstr(*cmd,"-o")==*cmd) { req[reqlen]=ISO15_REQ_OPTION; (*cmd)+=2; } // strip while (**cmd==' ' || **cmd=='\t') (*cmd)++; switch (**cmd) { case 0: PrintAndLog("missing addr"); return 0; break; case 's': case 'S': // you must have selected the tag earlier req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_SELECT; memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen); reqlen+=iso15cmdlen; break; case 'u': case 'U': // unaddressed mode may not be supported by all vendors req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY; memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen); reqlen+=iso15cmdlen; break; case '*': // we scan for the UID ourself req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen); reqlen+=iso15cmdlen; if (!getUID(uid)) { PrintAndLog("No Tag found"); return 0; } memcpy(req+reqlen,uid,8); PrintAndLog("Detected UID %s",sprintUID(NULL,uid)); reqlen+=8; break; default: req[reqlen++]|= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; memcpy(&req[reqlen],&iso15cmd[0],iso15cmdlen); reqlen+=iso15cmdlen; /* sscanf(cmd,"%hX%hX%hX%hX%hX%hX%hX%hX", (short unsigned int *)&uid[7],(short unsigned int *)&uid[6], (short unsigned int *)&uid[5],(short unsigned int *)&uid[4], (short unsigned int *)&uid[3],(short unsigned int *)&uid[2], (short unsigned int *)&uid[1],(short unsigned int *)&uid[0]); */ for (int i=0;i<8 && (*cmd)[i*2] && (*cmd)[i*2+1];i++) { // parse UID sscanf((char[]){(*cmd)[i*2],(*cmd)[i*2+1],0},"%X",&temp); uid[7-i]=temp&0xff; } PrintAndLog("Using UID %s",sprintUID(NULL,uid)); memcpy(&req[reqlen],&uid[0],8); reqlen+=8; }
// Reads all memory pages int CmdHF15DumpMem(const char*Cmd) { UsbCommand resp; uint8_t uid[8]; uint8_t *recv=NULL; UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? uint8_t *req=c.d.asBytes; int reqlen=0; int blocknum=0; char output[80]; if (!getUID(uid)) { PrintAndLog("No Tag found."); return 0; } PrintAndLog("Reading memory from tag UID=%s",sprintUID(NULL,uid)); PrintAndLog("Tag Info: %s",getTagInfo(uid)); for (int retry=0; retry<5; retry++) { req[0]= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; req[1]=ISO15_CMD_READ; memcpy(&req[2],uid,8); req[10]=blocknum; reqlen=AddCrc(req,11); c.arg[0]=reqlen; SendCommand(&c); if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { recv = resp.d.asBytes; if (ISO15_CRC_CHECK==Crc(recv,resp.arg[0])) { if (!(recv[0] & ISO15_RES_ERROR)) { retry=0; *output=0; // reset outputstring sprintf(output, "Block %02x ",blocknum); for ( int i=1; i<resp.arg[0]-2; i++) { // data in hex sprintf(output+strlen(output),"%02X ",recv[i]); } strcat(output," "); for ( int i=1; i<resp.arg[0]-2; i++) { // data in cleaned ascii sprintf(output+strlen(output),"%c",(recv[i]>31 && recv[i]<127)?recv[i]:'.'); } PrintAndLog("%s",output); blocknum++; // PrintAndLog("bn=%i",blocknum); } else { PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1])); return 0; } } // else PrintAndLog("crc"); } // else PrintAndLog("r null"); } // retry // TODO: need fix // if (resp.arg[0]<3) // PrintAndLog("Lost Connection"); // else if (ISO15_CRC_CHECK!=Crc(resp.d.asBytes,resp.arg[0])) // PrintAndLog("CRC Failed"); // else // PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1])); return 0; }