X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/79db03ef6302ab9cda439cff0bf5ab7808646a21..3c05723ee224b72138884c150b78c4c45ae841ba:/client/cmdhfmf.c diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 9ccfef95..1d2de683 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -7,7 +7,7 @@ //----------------------------------------------------------------------------- // High frequency MIFARE commands //----------------------------------------------------------------------------- - +#include "../include/mifare.h" #include "cmdhfmf.h" static int CmdHelp(const char *Cmd); @@ -140,6 +140,7 @@ int CmdHF14AMfWrBl(const char *Cmd) return 0; } +/* dublett finns i CMDHFMFU.C int CmdHF14AMfUWrBl(const char *Cmd) { uint8_t blockNo = 0; @@ -249,8 +250,7 @@ int CmdHF14AMfUWrBl(const char *Cmd) } return 0; } - - +*/ int CmdHF14AMfRdBl(const char *Cmd) { uint8_t blockNo = 0; @@ -299,6 +299,7 @@ int CmdHF14AMfRdBl(const char *Cmd) return 0; } +/* dublett finns i CMDHFMFU.C int CmdHF14AMfURdBl(const char *Cmd) { uint8_t blockNo = 0; @@ -330,8 +331,9 @@ int CmdHF14AMfURdBl(const char *Cmd) return 0; } +*/ - +/* dublett finns i CMDHFMFU.C int CmdHF14AMfURdCard(const char *Cmd) { int i; @@ -422,7 +424,7 @@ int CmdHF14AMfURdCard(const char *Cmd) } return 0; } - +*/ int CmdHF14AMfRdSc(const char *Cmd) { @@ -517,7 +519,14 @@ int CmdHF14AMfDump(const char *Cmd) UsbCommand resp; + int size = GetCardSize(); char cmdp = param_getchar(Cmd, 0); + + if ( size > -1) + cmdp = (char)(48+size); + + PrintAndLog("Got %d",cmdp); + switch (cmdp) { case '0' : numSectors = 5; break; case '1' : @@ -537,28 +546,30 @@ int CmdHF14AMfDump(const char *Cmd) } if ((fin = fopen("dumpkeys.bin","rb")) == NULL) { - PrintAndLog("Could not find file dumpkeys.bin"); + PrintAndLog("Could not find file dumpkeys.bin"); return 1; } - // Read key file - + // Read keys A from file for (sectorNo=0; sectorNo>4) | ((data[8] & 0x1)<<1) | ((data[8] & 0x10)>>2); - rights[sectorNo][1] = ((data[7] & 0x20)>>5) | ((data[8] & 0x2)<<0) | ((data[8] & 0x20)>>3); - rights[sectorNo][2] = ((data[7] & 0x40)>>6) | ((data[8] & 0x4)>>1) | ((data[8] & 0x40)>>4); - rights[sectorNo][3] = ((data[7] & 0x80)>>7) | ((data[8] & 0x8)>>2) | ((data[8] & 0x80)>>5); + rights[sectorNo][0] = ((data[7] & 0x10)>>2) | ((data[8] & 0x1)<<1) | ((data[8] & 0x10)>>4); // C1C2C3 for data area 0 + rights[sectorNo][1] = ((data[7] & 0x20)>>3) | ((data[8] & 0x2)<<0) | ((data[8] & 0x20)>>5); // C1C2C3 for data area 1 + rights[sectorNo][2] = ((data[7] & 0x40)>>4) | ((data[8] & 0x4)>>1) | ((data[8] & 0x40)>>6); // C1C2C3 for data area 2 + rights[sectorNo][3] = ((data[7] & 0x80)>>5) | ((data[8] & 0x8)>>2) | ((data[8] & 0x80)>>7); // C1C2C3 for sector trailer } else { PrintAndLog("Could not get access rights for sector %2d. Trying with defaults...", sectorNo); - rights[sectorNo][0] = rights[sectorNo][1] = rights[sectorNo][2] = rights[sectorNo][3] = 0x01; + rights[sectorNo][0] = rights[sectorNo][1] = rights[sectorNo][2] = 0x00; + rights[sectorNo][3] = 0x01; } } else { PrintAndLog("Command execute timeout when trying to read access rights for sector %2d. Trying with defaults...", sectorNo); - rights[sectorNo][0] = rights[sectorNo][1] = rights[sectorNo][2] = rights[sectorNo][3] = 0x01; + rights[sectorNo][0] = rights[sectorNo][1] = rights[sectorNo][2] = 0x00; + rights[sectorNo][3] = 0x01; } } - // Read blocks and print to file - PrintAndLog("|-----------------------------------------|"); PrintAndLog("|----- Dumping all blocks to file... -----|"); PrintAndLog("|-----------------------------------------|"); @@ -596,6 +607,7 @@ int CmdHF14AMfDump(const char *Cmd) for (sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { for (blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { bool received = false; + if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer. At least the Access Conditions can always be read with key A. UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 0, 0}}; memcpy(c.d.asBytes, keyA[sectorNo], 6); @@ -603,19 +615,19 @@ int CmdHF14AMfDump(const char *Cmd) received = WaitForResponseTimeout(CMD_ACK,&resp,1500); } else { // data block. Check if it can be read with key A or key B uint8_t data_area = sectorNo<32?blockNo:blockNo/5; - if ((rights[sectorNo][data_area] == 3) || (rights[sectorNo][data_area] == 5)) { // only key B would work + if ((rights[sectorNo][data_area] == 0x03) || (rights[sectorNo][data_area] == 0x05)) { // only key B would work UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 1, 0}}; memcpy(c.d.asBytes, keyB[sectorNo], 6); SendCommand(&c); received = WaitForResponseTimeout(CMD_ACK,&resp,1500); - } else if (rights[sectorNo][data_area] == 7) { // no key would work + } else if (rights[sectorNo][data_area] == 0x07) { // no key would work isOK = false; - PrintAndLog("Access rights do not allow reading of sector %2d block %3d", sectorNo, blockNo); + PrintAndLog("Access rights do not allow reading of sector %2d block %3d", sectorNo, blockNo); } else { // key A would work - UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 0, 0}}; - memcpy(c.d.asBytes, keyA[sectorNo], 6); - SendCommand(&c); - received = WaitForResponseTimeout(CMD_ACK,&resp,1500); + UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 0, 0}}; + memcpy(c.d.asBytes, keyA[sectorNo], 6); + SendCommand(&c); + received = WaitForResponseTimeout(CMD_ACK,&resp,1500); } } @@ -650,7 +662,6 @@ int CmdHF14AMfDump(const char *Cmd) break; } } - } if (isOK) { @@ -663,8 +674,7 @@ int CmdHF14AMfDump(const char *Cmd) fclose(fout); PrintAndLog("Dumped %d blocks (%d bytes) to file dumpdata.bin", numblocks, 16*numblocks); } - - fclose(fin); + return 0; } @@ -783,7 +793,7 @@ int CmdHF14AMfNested(const char *Cmd) uint8_t trgKeyType = 0; uint8_t SectorsCnt = 0; uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t keyBlock[6*6]; + uint8_t keyBlock[13*6]; uint64_t key64 = 0; bool transferToEml = false; @@ -813,11 +823,15 @@ int CmdHF14AMfNested(const char *Cmd) cmdp = param_getchar(Cmd, 0); blockNo = param_get8(Cmd, 1); ctmp = param_getchar(Cmd, 2); + if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') { PrintAndLog("Key type must be A or B"); return 1; } - if (ctmp != 'A' && ctmp != 'a') keyType = 1; + + if (ctmp != 'A' && ctmp != 'a') + keyType = 1; + if (param_gethex(Cmd, 3, key, 12)) { PrintAndLog("Key must include 12 HEX symbols"); return 1; @@ -831,8 +845,12 @@ int CmdHF14AMfNested(const char *Cmd) PrintAndLog("Target key type must be A or B"); return 1; } - if (ctmp != 'A' && ctmp != 'a') trgKeyType = 1; + if (ctmp != 'A' && ctmp != 'a') + trgKeyType = 1; } else { + + + switch (cmdp) { case '0': SectorsCnt = 05; break; case '1': SectorsCnt = 16; break; @@ -894,6 +912,14 @@ int CmdHF14AMfNested(const char *Cmd) num_to_bytes(0xa0a1a2a3a4a5, 6, (uint8_t*)(keyBlock + 3 * 6)); num_to_bytes(0xb0b1b2b3b4b5, 6, (uint8_t*)(keyBlock + 4 * 6)); num_to_bytes(0xaabbccddeeff, 6, (uint8_t*)(keyBlock + 5 * 6)); + num_to_bytes(0x4d3a99c351dd, 6, (uint8_t*)(keyBlock + 6 * 6)); + num_to_bytes(0x1a982c7e459a, 6, (uint8_t*)(keyBlock + 7 * 6)); + num_to_bytes(0xd3f7d3f7d3f7, 6, (uint8_t*)(keyBlock + 8 * 6)); + num_to_bytes(0x714c5c886e97, 6, (uint8_t*)(keyBlock + 9 * 6)); + num_to_bytes(0x587ee5f9350f, 6, (uint8_t*)(keyBlock + 10 * 6)); + num_to_bytes(0xa0478cc39091, 6, (uint8_t*)(keyBlock + 11 * 6)); + num_to_bytes(0x533cb6c723f6, 6, (uint8_t*)(keyBlock + 12 * 6)); + num_to_bytes(0x8fd0a4f256e9, 6, (uint8_t*)(keyBlock + 13 * 6)); PrintAndLog("Testing known keys. Sector count=%d", SectorsCnt); for (i = 0; i < SectorsCnt; i++) { @@ -1002,6 +1028,18 @@ int CmdHF14AMfNested(const char *Cmd) int CmdHF14AMfChk(const char *Cmd) { + if (strlen(Cmd)<3) { + PrintAndLog("Usage: hf mf chk |<*card memory> [t|d] [] []"); + PrintAndLog(" * - all sectors"); + PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); + PrintAndLog("d - write keys to binary file\n"); + PrintAndLog("t - write keys to emulator memory"); + PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic"); + PrintAndLog(" hf mf chk *1 ? t"); + PrintAndLog(" hf mf chk *1 ? d"); + return 0; + } + FILE * f; char filename[256]={0}; char buf[13]; @@ -1045,16 +1083,6 @@ int CmdHF14AMfChk(const char *Cmd) num_to_bytes(defaultKeys[defaultKeyCounter], 6, (uint8_t*)(keyBlock + defaultKeyCounter * 6)); } - if (strlen(Cmd)<3) { - PrintAndLog("Usage: hf mf chk |<*card memory> [t] [] []"); - PrintAndLog(" * - all sectors"); - PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); - PrintAndLog("d - write keys to binary file\n"); - PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic"); - PrintAndLog(" hf mf chk *1 ? t"); - return 0; - } - if (param_getchar(Cmd, 0)=='*') { blockNo = 3; switch(param_getchar(Cmd+1, 0)) { @@ -1142,11 +1170,12 @@ int CmdHF14AMfChk(const char *Cmd) keycnt++; memset(buf, 0, sizeof(buf)); } + fclose(f); } else { PrintAndLog("File: %s: not found or locked.", filename); free(keyBlock); return 1; - fclose(f); + } } } @@ -1155,8 +1184,8 @@ int CmdHF14AMfChk(const char *Cmd) PrintAndLog("No key specified, trying default keys"); for (;keycnt < defaultKeysSize; keycnt++) PrintAndLog("chk default key[%2d] %02x%02x%02x%02x%02x%02x", keycnt, - (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], - (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); + (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], + (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); } // initialize storage for found keys @@ -1201,13 +1230,13 @@ int CmdHF14AMfChk(const char *Cmd) for (uint16_t t = 0; t < 2; t++) { if (validKey[t][sectorNo]) { memcpy(block + t*10, foundKey[t][sectorNo], 6); - } - } + } + } mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); } } PrintAndLog("Found keys have been transferred to the emulator memory"); - } + } if (createDumpFile) { FILE *fkeys = fopen("dumpkeys.bin","wb"); @@ -1215,7 +1244,7 @@ int CmdHF14AMfChk(const char *Cmd) PrintAndLog("Could not create file dumpkeys.bin"); free(keyBlock); return 1; - } + } for (uint16_t t = 0; t < 2; t++) { fwrite(foundKey[t], 1, 6*SectorsCnt, fkeys); } @@ -1225,7 +1254,7 @@ int CmdHF14AMfChk(const char *Cmd) free(keyBlock); - return 0; + return 0; } @@ -1319,7 +1348,6 @@ int CmdHF14AMfDbg(const char *Cmd) return 0; } - int CmdHF14AMfEGet(const char *Cmd) { uint8_t blockNo = 0; @@ -1428,6 +1456,7 @@ int CmdHF14AMfELoad(const char *Cmd) break; } PrintAndLog("File reading error."); + fclose(f); return 2; } if (strlen(buf) < 32){ @@ -1452,6 +1481,7 @@ int CmdHF14AMfELoad(const char *Cmd) if ((blockNum != 16*4) && (blockNum != 32*4 + 8*16)) { PrintAndLog("File content error. There must be 64 or 256 blocks."); + fclose(f); return 4; } PrintAndLog("Loaded %d blocks from file: %s", blockNum, filename); @@ -1584,8 +1614,8 @@ int CmdHF14AMfEKeyPrn(const char *Cmd) int CmdHF14AMfCSetUID(const char *Cmd) { uint8_t wipeCard = 0; - uint8_t uid[8]; - uint8_t oldUid[8]; + uint8_t uid[8] = {0x00}; + uint8_t oldUid[8] = {0x00}; int res; if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') { @@ -1616,7 +1646,6 @@ int CmdHF14AMfCSetUID(const char *Cmd) return 0; } - int CmdHF14AMfCSetBlk(const char *Cmd) { uint8_t uid[8]; @@ -1742,7 +1771,7 @@ int CmdHF14AMfCLoad(const char *Cmd) } fclose(f); - if (blockNum != 16 * 4){ + if (blockNum != 16 * 4 && blockNum != 32 * 4 + 8 * 16){ PrintAndLog("File content error. There must be 64 blocks"); return 4; } @@ -1751,7 +1780,6 @@ int CmdHF14AMfCLoad(const char *Cmd) } } - int CmdHF14AMfCGetBlk(const char *Cmd) { uint8_t memBlock[16]; uint8_t blockNo = 0; @@ -2013,30 +2041,128 @@ int CmdHF14AMfSniff(const char *Cmd){ FillFileNameByUID(logHexFileName, uid + (7 - uid_len), ".log", uid_len); AddLogCurrentDT(logHexFileName); } - if (wantDecrypt) mfTraceInit(uid, atqa, sak, wantSaveToEmlFile); + if (wantDecrypt) + mfTraceInit(uid, atqa, sak, wantSaveToEmlFile); } else { PrintAndLog("%s(%d):%s", isTag ? "TAG":"RDR", num, sprint_hex(bufPtr, len)); - if (wantLogToFile) AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len); - if (wantDecrypt) mfTraceDecode(bufPtr, len, parity, wantSaveToEmlFile); + if (wantLogToFile) + AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len); + if (wantDecrypt) + mfTraceDecode(bufPtr, len, parity, wantSaveToEmlFile); } bufPtr += len; num++; } } - } // resp not NILL + } // resp not NULL } // while (true) return 0; } +// Tries to identify cardsize. +// Returns where num is: +// -1 unidentified +// 0 - MINI (320bytes) +// 1 - 1K +// 2 - 2K +// 4 - 4K +int GetCardSize() +{ + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; + SendCommand(&c); + + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); + + if(resp.arg[0] == 0) { + PrintAndLog("iso14443a card select failed"); + return -1; + } + + iso14a_card_select_t *card = (iso14a_card_select_t *)resp.d.asBytes; + + PrintAndLog("Trying to detect card size."); + + uint16_t atqa = 0; + uint8_t sak = 0; + atqa = (card->atqa[1] & 0xff) << 8; + atqa += card->atqa[0] & 0xff; + sak = card->sak; + + // https://code.google.com/p/libnfc/source/browse/libnfc/target-subr.c + + PrintAndLog("found ATAQ: %04X SAK: %02X", atqa, sak); + + + // NXP MIFARE Mini 0.3k + if ( ( (atqa & 0xff0f) == 0x0004) && (sak == 0x09) ) return 0; + + // MIFARE Classic 1K + if ( ((atqa & 0xff0f) == 0x0004) && (sak == 0x08) ) return 1; + + // MIFARE Classik 4K + if ( ((atqa & 0xff0f) == 0x0002) && (sak == 0x18) ) return 4; + + // SmartMX with MIFARE 1K emulation + if ( ((atqa & 0xf0ff) == 0x0004) ) return 1; + + // SmartMX with MIFARE 4K emulation + if ( ((atqa & 0xf0ff) == 0x0002) ) return 4; + + // Infineon MIFARE CLASSIC 1K + if ( ((atqa & 0xffff) == 0x0004) && (sak == 0x88) ) return 1; + + // MFC 4K emulated by Nokia 6212 Classic + if ( ((atqa & 0xffff) == 0x0002) && (sak == 0x38) ) return 4; + + // MFC 4K emulated by Nokia 6131 NFC + if ( ((atqa & 0xffff) == 0x0008) && (sak == 0x38) ) return 4; + + + PrintAndLog("BEFOOO 1K %02X", (atqa & 0xff0f)); + + // MIFARE Plus (4 Byte UID or 4 Byte RID) + // MIFARE Plus (7 Byte UID) + if ( + ((atqa & 0xffff) == 0x0002) | + ((atqa & 0xffff) == 0x0004) | + ((atqa & 0xffff) == 0x0042) | + ((atqa & 0xffff) == 0x0044) + ) + { + switch(sak){ + case 0x08: + case 0x10: { + //case 0x20: + PrintAndLog("2"); + return 2; + break; + } + case 0x11: + case 0x18:{ + //case 0x20: + PrintAndLog("4"); + return 4; + break; + } + } + } + + return -1; +} + + + + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, - {"urdbl", CmdHF14AMfURdBl, 0, "Read MIFARE Ultralight block"}, - {"urdcard", CmdHF14AMfURdCard, 0,"Read MIFARE Ultralight Card"}, - {"uwrbl", CmdHF14AMfUWrBl, 0,"Write MIFARE Ultralight block"}, + //{"urdbl", CmdHF14AMfURdBl, 0, "Read MIFARE Ultralight block"}, + //{"urdcard", CmdHF14AMfURdCard, 0,"Read MIFARE Ultralight Card"}, + //{"uwrbl", CmdHF14AMfUWrBl, 0,"Write MIFARE Ultralight block"}, {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"}, {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"}, {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},