From: Oleg Moiseenko Date: Fri, 22 Sep 2017 17:40:42 +0000 (+0300) Subject: reworking magic cheneese card wipe (#365) X-Git-Tag: v3.1.0~169 X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/3a05a1e73940bfa13ce5f732fd5d14ee333c6977?ds=inline reworking magic cheneese card wipe (#365) Implement hf mf cwipe. Remove wipe parameter from hf mf csetuid. --- diff --git a/CHANGELOG.md b/CHANGELOG.md index f34b78f0..da0e30ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ### Changed - Improved backdoor detection missbehaving magic s50/1k tag (Fl0-0) +- Deleted wipe functionality from `hf mf csetuid` (Merlok) ### Fixed @@ -17,6 +18,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added backdoor detection for gen1b magic s70/4k tag (Fl0-0) - Added data fsktonrz, a fsk cleaning/demodulating routine for weak fsk signal. Note: follow this up with a `data rawdemod nr` to finish demoding your signal. (marshmellow) - Added lf em 410xbrute, LF EM410x reader bruteforce attack by simulating UIDs from a file (Fl0-0) +- Added `hf mf cwipe` command. It wipes "magic Chinese" card. For 1a generation it uses card's "wipe" command. For gen1a and gen1b it uses a write command. (Merlok) ## [3.0.1][2017-06-08] diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 25285396..b375c3ce 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1199,6 +1199,9 @@ void UsbPacketReceived(uint8_t *packet, int len) break; // Work with "magic Chinese" card + case CMD_MIFARE_CWIPE: + MifareCWipe(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; case CMD_MIFARE_CSETBLOCK: MifareCSetBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; diff --git a/armsrc/apps.h b/armsrc/apps.h index aa5b47fb..1ce3215f 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -134,7 +134,8 @@ void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); -void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card +void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card +void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareCIdent(); // is "magic chinese" card? void MifareUSetPwd(uint8_t arg0, uint8_t *datain); diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 0e9c3672..60a85c80 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1170,6 +1170,143 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai // Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn) // //----------------------------------------------------------------------------- + +static bool isBlockTrailer(int blockN) { + if (blockN >= 0 && blockN < 128) { + return ((blockN & 0x03) == 0x03); + } + if (blockN >= 128 && blockN <= 256) { + return ((blockN & 0x0F) == 0x0F); + } + return FALSE; +} + +void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ + // var + byte_t isOK = 0; + uint32_t numBlocks = arg0; + // cmdParams: + // bit 0 - wipe gen1a + // bit 1 - fill card with default data + // bit 2 - gen1a = 0, gen1b = 1 + uint8_t cmdParams = arg1; + bool needWipe = cmdParams & 0x01; + bool needFill = cmdParams & 0x02; + bool gen1b = cmdParams & 0x04; + + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; + + uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF}; + uint8_t block1[16] = {0x00}; + uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + uint8_t d_block[18] = {0x00}; + + // card commands + uint8_t wupC1[] = { 0x40 }; + uint8_t wupC2[] = { 0x43 }; + uint8_t wipeC[] = { 0x41 }; + + // iso14443 setup + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + // tracing + clear_trace(); + set_tracing(true); + + while (true){ + // wipe + if (needWipe){ + ReaderTransmitBitsPar(wupC1,7,0, NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); + break; + }; + + ReaderTransmit(wipeC, sizeof(wipeC), NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error"); + break; + }; + + if(mifare_classic_halt(NULL, 0)) { + if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); + }; + }; + + // put default data + if (needFill){ + // select commands + ReaderTransmitBitsPar(wupC1, 7, 0, NULL); + + // gen1b magic tag : do no issue wupC2 and don't expect 0x0a response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command) + if (!gen1b) { + + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); + break; + }; + + ReaderTransmit(wupC2, sizeof(wupC2), NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); + break; + }; + } + + // send blocks command + for (int blockNo = 0; blockNo < numBlocks; blockNo++) { + if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error"); + break; + }; + + // check type of block and add crc + if (!isBlockTrailer(blockNo)){ + memcpy(d_block, block1, 16); + } else { + memcpy(d_block, blockK, 16); + } + if (blockNo == 0) { + memcpy(d_block, block0, 16); + } + AppendCrc14443a(d_block, 16); + + // send write command + ReaderTransmit(d_block, sizeof(d_block), NULL); + if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error"); + break; + }; + } + + // halt + // do no issue halt command for gen1b + if (!gen1b) { + if (mifare_classic_halt(NULL, 0)) { + if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); + break; + } + } + } + break; + } + + // send USB response + LED_B_ON(); + cmd_send(CMD_ACK,isOK,0,0,NULL,0); + LED_B_OFF(); + + // reset fpga + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + + return; +} + void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ // params @@ -1214,13 +1351,14 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai if (workFlags & 0x01) { if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - break; + // Continue, if we set wrong UID or wrong UID checksum or some ATQA or SAK we will can't select card. But we need to write block 0 to make card work. + //break; }; if(mifare_classic_halt(NULL, cuid)) { if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); // Continue, some magic tags misbehavies and send an answer to it. - // break; + // break; }; }; @@ -1239,7 +1377,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai break; }; - if(mifare_classic_halt(NULL, cuid)) { + if(mifare_classic_halt(NULL, 0)) { if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); // Continue, some magic tags misbehavies and send an answer to it. // break; @@ -1283,7 +1421,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai if (workFlags & 0x04) { // do no issue halt command for gen1b magic tag (#db# halt error. response len: 1) if (!(workFlags & 0x40)) { - if (mifare_classic_halt(NULL, cuid)) { + if (mifare_classic_halt(NULL, 0)) { if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); // Continue, some magic tags misbehavies and send an answer to it. // break; diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 90ebc27b..5a9896de 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1783,70 +1783,148 @@ int CmdHF14AMfEKeyPrn(const char *Cmd) int CmdHF14AMfCSetUID(const char *Cmd) { - uint8_t wipeCard = 0; uint8_t uid[8] = {0x00}; uint8_t oldUid[8] = {0x00}; uint8_t atqa[2] = {0x00}; uint8_t sak[1] = {0x00}; - uint8_t atqaPresent = 1; + uint8_t atqaPresent = 0; int res; - char ctmp; - int argi=0; - if (strlen(Cmd) < 1 || param_getchar(Cmd, argi) == 'h') { - PrintAndLog("Usage: hf mf csetuid [ATQA 4 hex symbols SAK 2 hex symbols] [w]"); + uint8_t needHelp = 0; + char cmdp = 1; + + if (param_getchar(Cmd, 0) && param_gethex(Cmd, 0, uid, 8)) { + PrintAndLog("UID must include 8 HEX symbols"); + return 1; + } + + if (param_getlength(Cmd, 1) > 1 && param_getlength(Cmd, 2) > 1) { + atqaPresent = 1; + cmdp = 3; + + if (param_gethex(Cmd, 1, atqa, 4)) { + PrintAndLog("ATQA must include 4 HEX symbols"); + return 1; + } + + if (param_gethex(Cmd, 2, sak, 2)) { + PrintAndLog("SAK must include 2 HEX symbols"); + return 1; + } + } + + while(param_getchar(Cmd, cmdp) != 0x00) + { + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + case 'H': + needHelp = 1; + break; + default: + PrintAndLog("ERROR: Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + needHelp = 1; + break; + } + cmdp++; + } + + if (strlen(Cmd) < 1 || needHelp) { + PrintAndLog(""); + PrintAndLog("Usage: hf mf csetuid [ATQA 4 hex symbols SAK 2 hex symbols]"); PrintAndLog("sample: hf mf csetuid 01020304"); - PrintAndLog("sample: hf mf csetuid 01020304 0004 08 w"); + PrintAndLog("sample: hf mf csetuid 01020304 0004 08"); PrintAndLog("Set UID, ATQA, and SAK for magic Chinese card (only works with such cards)"); - PrintAndLog("If you also want to wipe the card then add 'w' at the end of the command line."); return 0; } - if (param_getchar(Cmd, argi) && param_gethex(Cmd, argi, uid, 8)) { - PrintAndLog("UID must include 8 HEX symbols"); - return 1; + PrintAndLog("uid:%s", sprint_hex(uid, 4)); + if (atqaPresent) { + PrintAndLog("--atqa:%s sak:%02x", sprint_hex(atqa, 2), sak[0]); } - argi++; - ctmp = param_getchar(Cmd, argi); - if (ctmp == 'w' || ctmp == 'W') { - wipeCard = 1; - atqaPresent = 0; + res = mfCSetUID(uid, (atqaPresent)?atqa:NULL, (atqaPresent)?sak:NULL, oldUid); + if (res) { + PrintAndLog("Can't set UID. Error=%d", res); + return 1; + } + + PrintAndLog("old UID:%s", sprint_hex(oldUid, 4)); + PrintAndLog("new UID:%s", sprint_hex(uid, 4)); + return 0; +} + +static int ParamGetCardSize(const char c) { + int numBlocks = 16 * 4; + switch (c) { + case '0' : numBlocks = 5 * 4; break; + case '2' : numBlocks = 32 * 4; break; + case '4' : numBlocks = 32 * 4 + 8 * 16; break; + default: numBlocks = 16 * 4; } + return numBlocks; +} - if (atqaPresent) { - if (param_getchar(Cmd, argi)) { - if (param_gethex(Cmd, argi, atqa, 4)) { - PrintAndLog("ATQA must include 4 HEX symbols"); - return 1; - } - argi++; - if (!param_getchar(Cmd, argi) || param_gethex(Cmd, argi, sak, 2)) { - PrintAndLog("SAK must include 2 HEX symbols"); - return 1; - } - argi++; - } else - atqaPresent = 0; +int CmdHF14AMfCWipe(const char *Cmd) +{ + int res, gen = 0; + int numBlocks = 16 * 4; + bool wipeCard = false; + bool fillCard = false; + + if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') { + PrintAndLog("Usage: hf mf cwipe [card size] [w] [p]"); + PrintAndLog("sample: hf mf cwipe 1 w s"); + PrintAndLog("[card size]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); + PrintAndLog("w - Wipe magic Chinese card (only works with gen:1a cards)"); + PrintAndLog("f - Fill the card with default data and keys (works with gen:1a and gen:1b cards only)"); + return 0; } - if(!wipeCard) { - ctmp = param_getchar(Cmd, argi); - if (ctmp == 'w' || ctmp == 'W') { + gen = mfCIdentify(); + if ((gen != 1) && (gen != 2)) + return 1; + + numBlocks = ParamGetCardSize(param_getchar(Cmd, 0)); + + char cmdp = 0; + while(param_getchar(Cmd, cmdp) != 0x00){ + switch(param_getchar(Cmd, cmdp)) { + case 'w': + case 'W': wipeCard = 1; + break; + case 'f': + case 'F': + fillCard = 1; + break; + default: + break; } + cmdp++; } - PrintAndLog("--wipe card:%s uid:%s", (wipeCard)?"YES":"NO", sprint_hex(uid, 4)); + if (!wipeCard && !fillCard) + wipeCard = TRUE; - res = mfCSetUID(uid, (atqaPresent)?atqa:NULL, (atqaPresent)?sak:NULL, oldUid, wipeCard); - if (res) { - PrintAndLog("Can't set UID. error=%d", res); - return 1; + PrintAndLog("--blocks count:%2d wipe:%c fill:%c", numBlocks, (wipeCard)?'y':'n', (fillCard)?'y':'n'); + + if (gen == 2) { + /* generation 1b magic card */ + if (wipeCard) { + PrintAndLog("WARNING: can't wipe magic card 1b generation"); } + res = mfCWipe(numBlocks, true, false, fillCard); + } else { + /* generation 1a magic card by default */ + res = mfCWipe(numBlocks, false, wipeCard, fillCard); + } - PrintAndLog("old UID:%s", sprint_hex(oldUid, 4)); - PrintAndLog("new UID:%s", sprint_hex(uid, 4)); + if (res) { + PrintAndLog("Can't wipe. error=%d", res); + return 1; + } + PrintAndLog("OK"); return 0; } @@ -1866,6 +1944,8 @@ int CmdHF14AMfCSetBlk(const char *Cmd) } gen = mfCIdentify(); + if ((gen != 1) && (gen != 2)) + return 1; blockNo = param_get8(Cmd, 0); @@ -2398,6 +2478,7 @@ static command_t CommandTable[] = {"esave", CmdHF14AMfESave, 0, "Save to file emul dump"}, {"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"}, {"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"}, + {"cwipe", CmdHF14AMfCWipe, 0, "Wipe magic Chinese card"}, {"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"}, {"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"}, {"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"}, diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index fc87b228..235fd86d 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -34,6 +34,7 @@ extern int CmdHF14AMfELoad(const char* cmd); extern int CmdHF14AMfESave(const char* cmd); extern int CmdHF14AMfECFill(const char* cmd); extern int CmdHF14AMfEKeyPrn(const char* cmd); +extern int CmdHF14AMfCWipe(const char* cmd); extern int CmdHF14AMfCSetUID(const char* cmd); extern int CmdHF14AMfCSetBlk(const char* cmd); extern int CmdHF14AMfCGetBlk(const char* cmd); diff --git a/client/mifarehost.c b/client/mifarehost.c index 92ffbd4e..8a840d47 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -396,7 +396,8 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) { UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}}; SendCommand(&c); - UsbCommand resp; + + UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) return 1; memcpy(data, resp.d.asBytes, blocksCount * 16); return 0; @@ -416,6 +417,7 @@ int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) { UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, 0, blockNo}}; SendCommand(&c); + UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { isOK = resp.arg[0] & 0xff; @@ -434,8 +436,9 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uin UsbCommand c = {CMD_MIFARE_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}}; memcpy(c.d.asBytes, data, 16); SendCommand(&c); + UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { isOK = resp.arg[0] & 0xff; if (uid != NULL) memcpy(uid, resp.d.asBytes, 4); @@ -445,25 +448,40 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uin PrintAndLog("Command execute timeout"); return 1; } + return 0; } -int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, bool wantWipe) { +int mfCWipe(uint32_t numSectors, bool gen1b, bool wantWipe, bool wantFill) { + uint8_t isOK = 0; + uint8_t cmdParams = wantWipe + wantFill * 0x02 + gen1b * 0x04; + UsbCommand c = {CMD_MIFARE_CWIPE, {numSectors, cmdParams, 0}}; + SendCommand(&c); + + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); + isOK = resp.arg[0] & 0xff; + + return isOK; +} + +int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID) { uint8_t oldblock0[16] = {0x00}; uint8_t block0[16] = {0x00}; - int old, gen = 0; + int gen = 0, res; gen = mfCIdentify(); + /* generation 1a magic card by default */ + uint8_t cmdParams = CSETBLOCK_SINGLE_OPER; if (gen == 2) { /* generation 1b magic card */ - old = mfCGetBlock(0, oldblock0, CSETBLOCK_SINGLE_OPER | CSETBLOCK_MAGIC_1B); - } else { - /* generation 1a magic card by default */ - old = mfCGetBlock(0, oldblock0, CSETBLOCK_SINGLE_OPER); + cmdParams = CSETBLOCK_SINGLE_OPER | CSETBLOCK_MAGIC_1B; } + + res = mfCGetBlock(0, oldblock0, cmdParams); - if (old == 0) { + if (res == 0) { memcpy(block0, oldblock0, 16); PrintAndLog("old block 0: %s", sprint_hex(block0,16)); } else { @@ -474,25 +492,73 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, bool w // UID memcpy(block0, uid, 4); // Mifare UID BCC - block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; + block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3]; // mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed) - if (sak!=NULL) - block0[5]=sak[0]; - if (atqa!=NULL) { - block0[6]=atqa[1]; - block0[7]=atqa[0]; + if (sak != NULL) + block0[5] = sak[0]; + if (atqa != NULL) { + block0[6] = atqa[1]; + block0[7] = atqa[0]; } - PrintAndLog("new block 0: %s", sprint_hex(block0,16)); + PrintAndLog("new block 0: %s", sprint_hex(block0, 16)); - if (gen == 2) { - /* generation 1b magic card */ - return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER | CSETBLOCK_MAGIC_1B); - } else { - /* generation 1a magic card by default */ - return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER); + res = mfCSetBlock(0, block0, oldUID, false, cmdParams); + if (res) { + PrintAndLog("Can't set block 0. Error: %d", res); + return res; } + + return 0; +} + +int mfCIdentify() +{ + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + SendCommand(&c); + + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); + + iso14a_card_select_t card; + memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + + uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + + if(select_status != 0) { + uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 + c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; + c.arg[1] = 2; + c.arg[2] = 0; + memcpy(c.d.asBytes, rats, 2); + SendCommand(&c); + WaitForResponse(CMD_ACK,&resp); + } + + c.cmd = CMD_MIFARE_CIDENT; + c.arg[0] = 0; + c.arg[1] = 0; + c.arg[2] = 0; + SendCommand(&c); + WaitForResponse(CMD_ACK,&resp); + + uint8_t isGeneration = resp.arg[0] & 0xff; + switch( isGeneration ){ + case 1: PrintAndLog("Chinese magic backdoor commands (GEN 1a) detected"); break; + case 2: PrintAndLog("Chinese magic backdoor command (GEN 1b) detected"); break; + default: PrintAndLog("No chinese magic backdoor command detected"); break; + } + + // disconnect + c.cmd = CMD_READER_ISO_14443a; + c.arg[0] = 0; + c.arg[1] = 0; + c.arg[2] = 0; + SendCommand(&c); + + return (int) isGeneration; } + // SNIFFER // constants @@ -531,7 +597,7 @@ int isBlockEmpty(int blockN) { } int isBlockTrailer(int blockN) { - return ((blockN & 0x03) == 0x03); + return ((blockN & 0x03) == 0x03); } int saveTraceCard(void) { @@ -593,6 +659,7 @@ int loadTraceCard(uint8_t *tuid) { blockNum++; } fclose(f); + return 0; } @@ -613,6 +680,7 @@ int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFil uid = bytes_to_num(tuid + 3, 4); traceState = TRACE_IDLE; + return 0; } @@ -815,6 +883,8 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { return 0; } +// DECODING + int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len){ /* uint32_t nt; // tag challenge @@ -835,48 +905,3 @@ int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, return 0; } -int mfCIdentify() -{ - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; - SendCommand(&c); - UsbCommand resp; - WaitForResponse(CMD_ACK,&resp); - - iso14a_card_select_t card; - memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - - uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - - if(select_status != 0) { - uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 - c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; - c.arg[1] = 2; - c.arg[2] = 0; - memcpy(c.d.asBytes, rats, 2); - SendCommand(&c); - WaitForResponse(CMD_ACK,&resp); - } - - c.cmd = CMD_MIFARE_CIDENT; - c.arg[0] = 0; - c.arg[1] = 0; - c.arg[2] = 0; - SendCommand(&c); - WaitForResponse(CMD_ACK,&resp); - - uint8_t isGeneration = resp.arg[0] & 0xff; - switch( isGeneration ){ - case 1: PrintAndLog("Chinese magic backdoor commands (GEN 1a) detected"); break; - case 2: PrintAndLog("Chinese magic backdoor command (GEN 1b) detected"); break; - default: PrintAndLog("No chinese magic backdoor command detected"); break; - } - - // disconnect - c.cmd = CMD_READER_ISO_14443a; - c.arg[0] = 0; - c.arg[1] = 0; - c.arg[2] = 0; - SendCommand(&c); - - return (int) isGeneration; -} diff --git a/client/mifarehost.h b/client/mifarehost.h index 7f9a2b45..34793a29 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -33,7 +33,8 @@ extern int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint extern int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount); extern int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); -extern int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, bool wantWipe); +extern int mfCWipe(uint32_t numSectors, bool gen1b, bool wantWipe, bool wantFill); +extern int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID); extern int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uint8_t params); extern int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params); diff --git a/client/util.c b/client/util.c index 38dd3a12..86e8c502 100644 --- a/client/util.c +++ b/client/util.c @@ -322,7 +322,7 @@ char * printBits(size_t const size, void const * const ptr) // ------------------------------------------------------------------------- // line - param line -// bg, en - symbol numbers in param line of beginning an ending parameter +// bg, en - symbol numbers in param line of beginning and ending parameter // paramnum - param number (from 0) // ------------------------------------------------------------------------- int param_getptr(const char *line, int *bg, int *en, int paramnum) @@ -355,6 +355,15 @@ int param_getptr(const char *line, int *bg, int *en, int paramnum) } +int param_getlength(const char *line, int paramnum) +{ + int bg, en; + + if (param_getptr(line, &bg, &en, paramnum)) return 0; + + return en - bg + 1; +} + char param_getchar(const char *line, int paramnum) { int bg, en; diff --git a/client/util.h b/client/util.h index 640ef434..6177dd93 100644 --- a/client/util.h +++ b/client/util.h @@ -51,6 +51,7 @@ extern uint32_t SwapBits(uint32_t value, int nrbits); extern uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize); extern void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest); +extern int param_getlength(const char *line, int paramnum); extern char param_getchar(const char *line, int paramnum); extern int param_getptr(const char *line, int *bg, int *en, int paramnum); extern uint8_t param_get8(const char *line, int paramnum); diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 0ab9730e..194a9d53 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -175,6 +175,7 @@ typedef struct{ #define CMD_MIFARE_CSETBLOCK 0x0605 #define CMD_MIFARE_CGETBLOCK 0x0606 #define CMD_MIFARE_CIDENT 0x0607 +#define CMD_MIFARE_CWIPE 0x0608 #define CMD_SIMULATE_MIFARE_CARD 0x0610