+\r
+int CmdHF14AMfCSetUID(const char *Cmd)\r
+{\r
+ uint8_t wipeCard = 0;\r
+ uint8_t uid[8] = {0x00};\r
+ uint8_t oldUid[8] = {0x00};\r
+ int res;\r
+\r
+ if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {\r
+ PrintAndLog("Usage: hf mf csetuid <UID 8 hex symbols> <w>");\r
+ PrintAndLog("sample: hf mf csetuid 01020304 w");\r
+ PrintAndLog("Set UID for magic Chinese card (only works with!!!)");\r
+ PrintAndLog("If you want wipe card then add 'w' into command line. \n");\r
+ return 0;\r
+ } \r
+\r
+ if (param_getchar(Cmd, 0) && param_gethex(Cmd, 0, uid, 8)) {\r
+ PrintAndLog("UID must include 8 HEX symbols");\r
+ return 1;\r
+ }\r
+\r
+ char ctmp = param_getchar(Cmd, 1);\r
+ if (ctmp == 'w' || ctmp == 'W') wipeCard = 1;\r
+ \r
+ PrintAndLog("--wipe card:%02x uid:%s", wipeCard, sprint_hex(uid, 4));\r
+\r
+ res = mfCSetUID(uid, oldUid, wipeCard);\r
+ if (res) {\r
+ PrintAndLog("Can't set UID. error=%d", res);\r
+ return 1;\r
+ }\r
+ \r
+ PrintAndLog("old UID:%s", sprint_hex(oldUid, 4));\r
+ PrintAndLog("new UID:%s", sprint_hex(uid, 4));\r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMfCSetBlk(const char *Cmd)\r
+{\r
+ uint8_t uid[8];\r
+ uint8_t memBlock[16];\r
+ uint8_t blockNo = 0;\r
+ int res;\r
+ memset(memBlock, 0x00, sizeof(memBlock));\r
+\r
+ if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {\r
+ PrintAndLog("Usage: hf mf csetblk <block number> <block data (32 hex symbols)>");\r
+ PrintAndLog("sample: hf mf csetblk 1 01020304050607080910111213141516");\r
+ PrintAndLog("Set block data for magic Chinese card (only works with!!!)");\r
+ PrintAndLog("If you want wipe card then add 'w' into command line. \n");\r
+ return 0;\r
+ } \r
+\r
+ blockNo = param_get8(Cmd, 0);\r
+\r
+ if (param_gethex(Cmd, 1, memBlock, 32)) {\r
+ PrintAndLog("block data must include 32 HEX symbols");\r
+ return 1;\r
+ }\r
+\r
+ PrintAndLog("--block number:%2d data:%s", blockNo, sprint_hex(memBlock, 16));\r
+\r
+ res = mfCSetBlock(blockNo, memBlock, uid, 0, CSETBLOCK_SINGLE_OPER);\r
+ if (res) {\r
+ PrintAndLog("Can't write block. error=%d", res);\r
+ return 1;\r
+ }\r
+ \r
+ PrintAndLog("UID:%s", sprint_hex(uid, 4));\r
+ return 0;\r
+}\r
+\r
+\r
+int CmdHF14AMfCLoad(const char *Cmd)\r
+{\r
+ FILE * f;\r
+ char filename[FILE_PATH_SIZE];\r
+ char * fnameptr = filename;\r
+ char buf[64];\r
+ uint8_t buf8[64];\r
+ uint8_t fillFromEmulator = 0;\r
+ int i, len, blockNum, flags;\r
+ \r
+ memset(filename, 0, sizeof(filename));\r
+ memset(buf, 0, sizeof(buf));\r
+\r
+ if (param_getchar(Cmd, 0) == 'h' || param_getchar(Cmd, 0)== 0x00) {\r
+ PrintAndLog("It loads magic Chinese card (only works with!!!) from the file `filename.eml`");\r
+ PrintAndLog("or from emulator memory (option `e`)");\r
+ PrintAndLog("Usage: hf mf cload <file name w/o `.eml`>");\r
+ PrintAndLog(" or: hf mf cload e ");\r
+ PrintAndLog(" sample: hf mf cload filename");\r
+ return 0;\r
+ } \r
+\r
+ char ctmp = param_getchar(Cmd, 0);\r
+ if (ctmp == 'e' || ctmp == 'E') fillFromEmulator = 1;\r
+ \r
+ if (fillFromEmulator) {\r
+ flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC;\r
+ for (blockNum = 0; blockNum < 16 * 4; blockNum += 1) {\r
+ if (mfEmlGetMem(buf8, blockNum, 1)) {\r
+ PrintAndLog("Cant get block: %d", blockNum);\r
+ return 2;\r
+ }\r
+ \r
+ if (blockNum == 2) flags = 0;\r
+ if (blockNum == 16 * 4 - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD;\r
+\r
+ if (mfCSetBlock(blockNum, buf8, NULL, 0, flags)) {\r
+ PrintAndLog("Cant set magic card block: %d", blockNum);\r
+ return 3;\r
+ }\r
+ }\r
+ return 0;\r
+ } else {\r
+ len = strlen(Cmd);\r
+ if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;\r
+\r
+ memcpy(filename, Cmd, len);\r
+ fnameptr += len;\r
+\r
+ sprintf(fnameptr, ".eml"); \r
+ \r
+ // open file\r
+ f = fopen(filename, "r");\r
+ if (f == NULL) {\r
+ PrintAndLog("File not found or locked.");\r
+ return 1;\r
+ }\r
+ \r
+ blockNum = 0;\r
+ flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC;\r
+ while(!feof(f)){\r
+ memset(buf, 0, sizeof(buf));\r
+ if (fgets(buf, sizeof(buf), f) == NULL) {\r
+ PrintAndLog("File reading error.");\r
+ return 2;\r
+ }\r
+\r
+ if (strlen(buf) < 32){\r
+ if(strlen(buf) && feof(f))\r
+ break;\r
+ PrintAndLog("File content error. Block data must include 32 HEX symbols");\r
+ return 2;\r
+ }\r
+ for (i = 0; i < 32; i += 2)\r
+ sscanf(&buf[i], "%02x", (unsigned int *)&buf8[i / 2]);\r
+\r
+ if (blockNum == 2) flags = 0;\r
+ if (blockNum == 16 * 4 - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD;\r
+\r
+ if (mfCSetBlock(blockNum, buf8, NULL, 0, flags)) {\r
+ PrintAndLog("Can't set magic card block: %d", blockNum);\r
+ return 3;\r
+ }\r
+ blockNum++;\r
+ \r
+ if (blockNum >= 16 * 4) break; // magic card type - mifare 1K\r
+ }\r
+ fclose(f);\r
+ \r
+ if (blockNum != 16 * 4 && blockNum != 32 * 4 + 8 * 16){\r
+ PrintAndLog("File content error. There must be 64 blocks");\r
+ return 4;\r
+ }\r
+ PrintAndLog("Loaded from file: %s", filename);\r
+ return 0;\r
+ }\r
+}\r
+\r
+int CmdHF14AMfCGetBlk(const char *Cmd) {\r
+ uint8_t memBlock[16];\r
+ uint8_t blockNo = 0;\r
+ int res;\r
+ memset(memBlock, 0x00, sizeof(memBlock));\r
+\r
+ if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {\r
+ PrintAndLog("Usage: hf mf cgetblk <block number>");\r
+ PrintAndLog("sample: hf mf cgetblk 1");\r
+ PrintAndLog("Get block data from magic Chinese card (only works with!!!)\n");\r
+ return 0;\r
+ } \r
+\r
+ blockNo = param_get8(Cmd, 0);\r
+\r
+ PrintAndLog("--block number:%2d ", blockNo);\r
+\r
+ res = mfCGetBlock(blockNo, memBlock, CSETBLOCK_SINGLE_OPER);\r
+ if (res) {\r
+ PrintAndLog("Can't read block. error=%d", res);\r
+ return 1;\r
+ }\r
+ \r
+ PrintAndLog("block data:%s", sprint_hex(memBlock, 16));\r
+ return 0;\r
+}\r
+\r
+\r
+int CmdHF14AMfCGetSc(const char *Cmd) {\r
+ uint8_t memBlock[16];\r
+ uint8_t sectorNo = 0;\r
+ int i, res, flags;\r
+ memset(memBlock, 0x00, sizeof(memBlock));\r
+\r
+ if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {\r
+ PrintAndLog("Usage: hf mf cgetsc <sector number>");\r
+ PrintAndLog("sample: hf mf cgetsc 0");\r
+ PrintAndLog("Get sector data from magic Chinese card (only works with!!!)\n");\r
+ return 0;\r
+ } \r
+\r
+ sectorNo = param_get8(Cmd, 0);\r
+ if (sectorNo > 15) {\r
+ PrintAndLog("Sector number must be in [0..15] as in MIFARE classic.");\r
+ return 1;\r
+ }\r
+\r
+ PrintAndLog("--sector number:%d ", sectorNo);\r
+\r
+ flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC;\r
+ for (i = 0; i < 4; i++) {\r
+ if (i == 1) flags = 0;\r
+ if (i == 3) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD;\r
+\r
+ res = mfCGetBlock(sectorNo * 4 + i, memBlock, flags);\r
+ if (res) {\r
+ PrintAndLog("Can't read block. %d error=%d", sectorNo * 4 + i, res);\r
+ return 1;\r
+ }\r
+ \r
+ PrintAndLog("block %3d data:%s", sectorNo * 4 + i, sprint_hex(memBlock, 16));\r
+ }\r
+ return 0;\r
+}\r
+\r
+\r
+int CmdHF14AMfCSave(const char *Cmd) {\r
+\r
+ FILE * f;\r
+ char filename[FILE_PATH_SIZE];\r
+ char * fnameptr = filename;\r
+ uint8_t fillFromEmulator = 0;\r
+ uint8_t buf[64];\r
+ int i, j, len, flags;\r
+ \r
+ memset(filename, 0, sizeof(filename));\r
+ memset(buf, 0, sizeof(buf));\r
+\r
+ if (param_getchar(Cmd, 0) == 'h') {\r
+ PrintAndLog("It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml`");\r
+ PrintAndLog("or into emulator memory (option `e`)");\r
+ PrintAndLog("Usage: hf mf esave [file name w/o `.eml`][e]");\r
+ PrintAndLog(" sample: hf mf esave ");\r
+ PrintAndLog(" hf mf esave filename");\r
+ PrintAndLog(" hf mf esave e \n");\r
+ return 0;\r
+ } \r
+\r
+ char ctmp = param_getchar(Cmd, 0);\r
+ if (ctmp == 'e' || ctmp == 'E') fillFromEmulator = 1;\r
+\r
+ if (fillFromEmulator) {\r
+ // put into emulator\r
+ flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC;\r
+ for (i = 0; i < 16 * 4; i++) {\r
+ if (i == 1) flags = 0;\r
+ if (i == 16 * 4 - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD;\r
+ \r
+ if (mfCGetBlock(i, buf, flags)) {\r
+ PrintAndLog("Cant get block: %d", i);\r
+ break;\r
+ }\r
+ \r
+ if (mfEmlSetMem(buf, i, 1)) {\r
+ PrintAndLog("Cant set emul block: %d", i);\r
+ return 3;\r
+ }\r
+ }\r
+ return 0;\r
+ } else {\r
+ len = strlen(Cmd);\r
+ if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;\r
+ \r
+ if (len < 1) {\r
+ // get filename\r
+ if (mfCGetBlock(0, buf, CSETBLOCK_SINGLE_OPER)) {\r
+ PrintAndLog("Cant get block: %d", 0);\r
+ return 1;\r
+ }\r
+ for (j = 0; j < 7; j++, fnameptr += 2)\r
+ sprintf(fnameptr, "%02x", buf[j]); \r
+ } else {\r
+ memcpy(filename, Cmd, len);\r
+ fnameptr += len;\r
+ }\r
+\r
+ sprintf(fnameptr, ".eml"); \r
+ \r
+ // open file\r
+ f = fopen(filename, "w+");\r
+\r
+ // put hex\r
+ flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC;\r
+ for (i = 0; i < 16 * 4; i++) {\r
+ if (i == 1) flags = 0;\r
+ if (i == 16 * 4 - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD;\r
+ \r
+ if (mfCGetBlock(i, buf, flags)) {\r
+ PrintAndLog("Cant get block: %d", i);\r
+ break;\r
+ }\r
+ for (j = 0; j < 16; j++)\r
+ fprintf(f, "%02x", buf[j]); \r
+ fprintf(f,"\n");\r
+ }\r
+ fclose(f);\r
+ \r
+ PrintAndLog("Saved to file: %s", filename);\r
+ \r
+ return 0;\r
+ }\r
+}\r
+\r
+\r
+int CmdHF14AMfSniff(const char *Cmd){\r
+\r
+ bool wantLogToFile = 0;\r
+ bool wantDecrypt = 0;\r
+ //bool wantSaveToEml = 0; TODO\r
+ bool wantSaveToEmlFile = 0;\r
+\r
+ //var \r
+ int res = 0;\r
+ int len = 0;\r
+ int blockLen = 0;\r
+ int num = 0;\r
+ int pckNum = 0;\r
+ uint8_t uid[7];\r
+ uint8_t uid_len;\r
+ uint8_t atqa[2];\r
+ uint8_t sak;\r
+ bool isTag;\r
+ uint8_t buf[3000];\r
+ uint8_t * bufPtr = buf;\r
+ memset(buf, 0x00, 3000);\r
+ \r
+ if (param_getchar(Cmd, 0) == 'h') {\r
+ PrintAndLog("It continuously gets data from the field and saves it to: log, emulator, emulator file.");\r
+ PrintAndLog("You can specify:");\r
+ PrintAndLog(" l - save encrypted sequence to logfile `uid.log`");\r
+ PrintAndLog(" d - decrypt sequence and put it to log file `uid.log`");\r
+ PrintAndLog(" n/a e - decrypt sequence, collect read and write commands and save the result of the sequence to emulator memory");\r
+ PrintAndLog(" f - decrypt sequence, collect read and write commands and save the result of the sequence to emulator dump file `uid.eml`");\r
+ PrintAndLog("Usage: hf mf sniff [l][d][e][f]");\r
+ PrintAndLog(" sample: hf mf sniff l d e");\r
+ return 0;\r
+ } \r
+ \r
+ for (int i = 0; i < 4; i++) {\r
+ char ctmp = param_getchar(Cmd, i);\r
+ if (ctmp == 'l' || ctmp == 'L') wantLogToFile = true;\r
+ if (ctmp == 'd' || ctmp == 'D') wantDecrypt = true;\r
+ //if (ctmp == 'e' || ctmp == 'E') wantSaveToEml = true; TODO\r
+ if (ctmp == 'f' || ctmp == 'F') wantSaveToEmlFile = true;\r
+ }\r
+ \r
+ printf("-------------------------------------------------------------------------\n");\r
+ printf("Executing command. \n");\r
+ printf("Press the key on the proxmark3 device to abort both proxmark3 and client.\n");\r
+ printf("Press the key on pc keyboard to abort the client.\n");\r
+ printf("-------------------------------------------------------------------------\n");\r
+\r
+ UsbCommand c = {CMD_MIFARE_SNIFFER, {0, 0, 0}};\r
+ clearCommandBuffer();\r
+ SendCommand(&c);\r
+\r
+ // wait cycle\r
+ while (true) {\r
+ printf(".");\r
+ fflush(stdout);\r
+ if (ukbhit()) {\r
+ getchar();\r
+ printf("\naborted via keyboard!\n");\r
+ break;\r
+ }\r
+ \r
+ UsbCommand resp;\r
+ if (WaitForResponseTimeout(CMD_ACK,&resp,2000)) {\r
+ res = resp.arg[0] & 0xff;\r
+ len = resp.arg[1];\r
+ num = resp.arg[2];\r
+ \r
+ if (res == 0) return 0;\r
+ if (res == 1) {\r
+ if (num ==0) {\r
+ bufPtr = buf;\r
+ memset(buf, 0x00, 3000);\r
+ }\r
+ memcpy(bufPtr, resp.d.asBytes, len);\r
+ bufPtr += len;\r
+ pckNum++;\r
+ }\r
+ if (res == 2) {\r
+ blockLen = bufPtr - buf;\r
+ bufPtr = buf;\r
+ printf(">\n");\r
+ PrintAndLog("received trace len: %d packages: %d", blockLen, pckNum);\r
+ num = 0;\r
+ while (bufPtr - buf < blockLen) {\r
+ bufPtr += 6;\r
+ len = *((uint16_t *)bufPtr);\r
+\r
+ if(len & 0x8000) {\r
+ isTag = true;\r
+ len &= 0x7fff;\r
+ } else {\r
+ isTag = false;\r
+ }\r
+ bufPtr += 2;\r
+ if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[12] == 0xff) && (bufPtr[13] == 0xff)) {\r
+ \r
+ memcpy(uid, bufPtr + 2, 7);\r
+ memcpy(atqa, bufPtr + 2 + 7, 2);\r
+ uid_len = (atqa[0] & 0xC0) == 0x40 ? 7 : 4;\r
+ sak = bufPtr[11];\r
+ \r
+ PrintAndLog("tag select uid:%s atqa:0x%02x%02x sak:0x%02x", \r
+ sprint_hex(uid + (7 - uid_len), uid_len),\r
+ atqa[1], \r
+ atqa[0], \r
+ sak);\r
+ if (wantLogToFile || wantDecrypt) {\r
+ FillFileNameByUID(logHexFileName, uid + (7 - uid_len), ".log", uid_len);\r
+ AddLogCurrentDT(logHexFileName);\r
+ } \r
+ if (wantDecrypt) \r
+ mfTraceInit(uid, atqa, sak, wantSaveToEmlFile);\r
+ } else {\r
+ PrintAndLog("%s(%d):%s", isTag ? "TAG":"RDR", num, sprint_hex(bufPtr, len));\r
+ if (wantLogToFile) \r
+ AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len);\r
+ if (wantDecrypt) \r
+ mfTraceDecode(bufPtr, len, wantSaveToEmlFile);\r
+ }\r
+ bufPtr += len;\r
+ bufPtr += ((len-1)/8+1); // ignore parity\r
+ num++;\r
+ }\r
+ }\r
+ } // resp not NULL\r
+ } // while (true)\r
+ \r
+ return 0;\r
+}\r
+\r
+// Tries to identify cardsize.\r
+// Returns <num> where num is:\r
+// -1 unidentified\r
+// 0 - MINI (320bytes)\r
+// 1 - 1K\r
+// 2 - 2K\r
+// 4 - 4K\r
+int GetCardSize()\r
+{\r
+ UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};\r
+ SendCommand(&c);\r
+\r
+ UsbCommand resp;\r
+ WaitForResponse(CMD_ACK,&resp);\r
+\r
+ if(resp.arg[0] == 0) {\r
+ PrintAndLog("iso14443a card select failed");\r
+ return -1;\r
+ }\r
+ \r
+ iso14a_card_select_t *card = (iso14a_card_select_t *)resp.d.asBytes;\r
+\r
+ PrintAndLog("Trying to detect card size.");\r
+ \r
+ uint16_t atqa = 0;\r
+ uint8_t sak = 0;\r
+ atqa = (card->atqa[1] & 0xff) << 8;\r
+ atqa += card->atqa[0] & 0xff;\r
+ sak = card->sak;\r
+ \r
+ // https://code.google.com/p/libnfc/source/browse/libnfc/target-subr.c\r
+ \r
+ PrintAndLog("found ATAQ: %04X SAK: %02X", atqa, sak);\r
+ \r
+ \r
+ // NXP MIFARE Mini 0.3k\r
+ if ( ( (atqa & 0xff0f) == 0x0004) && (sak == 0x09) ) return 0;\r
+ \r
+ // MIFARE Classic 1K\r
+ if ( ((atqa & 0xff0f) == 0x0004) && (sak == 0x08) ) return 1;\r
+ \r
+ // MIFARE Classik 4K\r
+ if ( ((atqa & 0xff0f) == 0x0002) && (sak == 0x18) ) return 4;\r
+ \r
+ // SmartMX with MIFARE 1K emulation \r
+ if ( ((atqa & 0xf0ff) == 0x0004) ) return 1;\r
+\r
+ // SmartMX with MIFARE 4K emulation \r
+ if ( ((atqa & 0xf0ff) == 0x0002) ) return 4; \r
+ \r
+ // Infineon MIFARE CLASSIC 1K\r
+ if ( ((atqa & 0xffff) == 0x0004) && (sak == 0x88) ) return 1;\r
+ \r
+ // MFC 4K emulated by Nokia 6212 Classic\r
+ if ( ((atqa & 0xffff) == 0x0002) && (sak == 0x38) ) return 4;\r
+\r
+ // MFC 4K emulated by Nokia 6131 NFC\r
+ if ( ((atqa & 0xffff) == 0x0008) && (sak == 0x38) ) return 4;\r
+\r
+ \r
+ PrintAndLog("BEFOOO 1K %02X", (atqa & 0xff0f));\r
+ \r
+ // MIFARE Plus (4 Byte UID or 4 Byte RID)\r
+ // MIFARE Plus (7 Byte UID)\r
+ if (\r
+ ((atqa & 0xffff) == 0x0002) |\r
+ ((atqa & 0xffff) == 0x0004) |\r
+ ((atqa & 0xffff) == 0x0042) | \r
+ ((atqa & 0xffff) == 0x0044) \r
+ )\r
+ {\r
+ switch(sak){\r
+ case 0x08:\r
+ case 0x10: {\r
+ //case 0x20:\r
+ PrintAndLog("2");\r
+ return 2;\r
+ break;\r
+ }\r
+ case 0x11:\r
+ case 0x18:{\r
+ //case 0x20:\r
+ PrintAndLog("4");\r
+ return 4;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ \r
+ return -1;\r
+}\r
+\r