};\r
}; \r
\r
- // write UID block\r
+ // write block\r
if (workFlags & 0x02) {\r
ReaderTransmitShort(wupC1);\r
if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r
UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
LED_B_OFF();\r
\r
- if (workFlags & 0x10) {\r
+ if ((workFlags & 0x10) || (!isOK)) {\r
// Thats it...\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
}\r
}\r
+\r
+void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
+ \r
+ // params\r
+ // bit 1 - need wupC\r
+ // bit 2 - need HALT after sequence\r
+ // bit 3 - need init FPGA and field before sequence\r
+ // bit 4 - need reset FPGA and LED\r
+ uint8_t workFlags = arg0;\r
+ uint8_t blockNo = arg2;\r
+ \r
+ // card commands\r
+ uint8_t wupC1[] = { 0x40 }; \r
+ uint8_t wupC2[] = { 0x43 }; \r
+ \r
+ // variables\r
+ byte_t isOK = 0;\r
+ uint8_t data[18];\r
+ uint32_t cuid = 0;\r
+ \r
+ memset(data, 0x00, 18);\r
+ uint8_t* receivedAnswer = mifare_get_bigbufptr();\r
+ \r
+ if (workFlags & 0x08) {\r
+ // clear trace\r
+ iso14a_clear_tracelen();\r
+ iso14a_set_tracing(TRUE);\r
+\r
+ iso14443a_setup();\r
+\r
+ LED_A_ON();\r
+ LED_B_OFF();\r
+ LED_C_OFF();\r
+ \r
+ SpinDelay(300);\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ SpinDelay(100);\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
+ }\r
+\r
+ while (true) {\r
+ if (workFlags & 0x02) {\r
+ ReaderTransmitShort(wupC1);\r
+ if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
+ break;\r
+ };\r
+\r
+ ReaderTransmit(wupC2, sizeof(wupC2));\r
+ if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
+ break;\r
+ };\r
+ }\r
+\r
+ // read block\r
+ if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer) != 18)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");\r
+ break;\r
+ };\r
+ memcpy(data, receivedAnswer, 18);\r
+ \r
+ if (workFlags & 0x04) {\r
+ if (mifare_classic_halt(NULL, cuid)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
+ break;\r
+ };\r
+ }\r
+ \r
+ isOK = 1;\r
+ break;\r
+ }\r
+ \r
+ UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r
+ if (isOK) memcpy(ack.d.asBytes, data, 18);\r
+ \r
+ // add trace trailer\r
+ memset(data, 0x44, 4);\r
+ LogTrace(data, 4, 0, 0, TRUE);\r
+\r
+ LED_B_ON();\r
+ UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
+ LED_B_OFF();\r
+\r
+ if ((workFlags & 0x10) || (!isOK)) {\r
+ // Thats it...\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ LEDsoff();\r
+ }\r
+}\r
+\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
+ if (blockNo >= 32 * 4 + 8 * 16) {\r
+ PrintAndLog("Block number must be in [0..255] as in MIFARE classic.");\r
+ return 1;\r
+ }\r
+\r
+ PrintAndLog("--block number:%02x ", 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
+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:%02x ", 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. %02x error=%d", sectorNo * 4 + i, res);\r
+ return 1;\r
+ }\r
+ \r
+ PrintAndLog("block %02x data:%s", sectorNo * 4 + i, sprint_hex(memBlock, 16));\r
+ }\r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMfCSave(const char *Cmd) {\r
+\r
+ FILE * f;\r
+ char filename[20];\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 > 14) len = 14;\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
static command_t CommandTable[] =\r
{\r
- {"help", CmdHelp, 1, "This help"},\r
- {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},\r
+ {"help", CmdHelp, 1, "This help"},\r
+ {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},\r
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},\r
{"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},\r
{"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},\r
- {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},\r
+ {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},\r
{"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},\r
- {"chk", CmdHF14AMfChk, 0, "Test block keys"},\r
+ {"chk", CmdHF14AMfChk, 0, "Test block keys"},\r
{"mifare", CmdHF14AMifare, 0, "Read parity error messages. param - <used card nonce>"},\r
{"nested", CmdHF14AMfNested, 0, "Test nested authentication"},\r
- {"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"},\r
- {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"},\r
+ {"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"},\r
+ {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"},\r
{"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"},\r
{"eset", CmdHF14AMfESet, 0, "Set simulator memory block"},\r
{"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"},\r
{"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"},\r
{"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"},\r
{"csetblk", CmdHF14AMfCSetBlk, 0, "Write block into magic Chinese card"},\r
+ {"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block from magic Chinese card"},\r
+ {"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector from magic Chinese card"},\r
{"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"},\r
+ {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"},\r
{NULL, NULL, 0, NULL}\r
};\r
\r
}\r
\r
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {\r
- UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}};\r
+ UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}};\r
\r
- SendCommand(&c);\r
+ SendCommand(&c);\r
\r
UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);\r
\r
}\r
\r
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {\r
- UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, 0}};\r
+ UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, 0}};\r
memcpy(c.d.asBytes, data, blocksCount * 16); \r
- SendCommand(&c);\r
+ SendCommand(&c);\r
return 0;\r
}\r
\r
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, int wantWipe, uint8_t params) {\r
uint8_t isOK = 0;\r
\r
- UsbCommand c = {CMD_MIFARE_EML_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}};\r
+ UsbCommand c = {CMD_MIFARE_EML_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}};\r
memcpy(c.d.asBytes, data, 16); \r
- SendCommand(&c);\r
+ SendCommand(&c);\r
\r
UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);\r
\r
}\r
return 0;\r
}\r
+\r
+int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {\r
+ uint8_t isOK = 0;\r
+\r
+ UsbCommand c = {CMD_MIFARE_EML_CGETBLOCK, {params, 0, blockNo}};\r
+ SendCommand(&c);\r
+\r
+ UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);\r
+\r
+ if (resp != NULL) {\r
+ isOK = resp->arg[0] & 0xff;\r
+ memcpy(data, resp->d.asBytes, 16); \r
+ if (!isOK) return 2;\r
+ } else {\r
+ PrintAndLog("Command execute timeout");\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r