mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-07-16 02:03:00 -07:00
Add: new option 'd' in 'hf mf ekeyprn' to create dumpkeys.bin from emulator memory (#822)
(and whitespace fixes)
This commit is contained in:
parent
9ebbfd898c
commit
a39af1cb9c
1 changed files with 302 additions and 270 deletions
476
client/cmdhfmf.c
476
client/cmdhfmf.c
|
@ -34,7 +34,7 @@
|
|||
#include "mifare/ndef.h"
|
||||
#include "emv/dump.h"
|
||||
|
||||
#define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up
|
||||
#define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
|
@ -65,7 +65,7 @@ int CmdHF14AMfWrBl(const char *Cmd)
|
|||
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
|
||||
uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
char cmdp = 0x00;
|
||||
char cmdp = 0x00;
|
||||
|
||||
if (strlen(Cmd)<3) {
|
||||
PrintAndLog("Usage: hf mf wrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
|
||||
|
@ -113,7 +113,7 @@ int CmdHF14AMfRdBl(const char *Cmd)
|
|||
uint8_t keyType = 0;
|
||||
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
|
||||
|
||||
char cmdp = 0x00;
|
||||
char cmdp = 0x00;
|
||||
|
||||
|
||||
if (strlen(Cmd)<3) {
|
||||
|
@ -177,7 +177,7 @@ int CmdHF14AMfRdSc(const char *Cmd)
|
|||
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
|
||||
uint8_t isOK = 0;
|
||||
uint8_t *data = NULL;
|
||||
char cmdp = 0x00;
|
||||
char cmdp = 0x00;
|
||||
|
||||
if (strlen(Cmd)<3) {
|
||||
PrintAndLog("Usage: hf mf rdsc <sector number> <key A/B> <key (12 hex symbols)>");
|
||||
|
@ -220,13 +220,13 @@ int CmdHF14AMfRdSc(const char *Cmd)
|
|||
PrintAndLog("trailer: %s", sprint_hex(data + (sectorNo<32?3:15) * 16, 16));
|
||||
|
||||
PrintAndLogEx(NORMAL, "Trailer decoded:");
|
||||
int bln = mfFirstBlockOfSector(sectorNo);
|
||||
int blinc = (mfNumBlocksPerSector(sectorNo) > 4) ? 5 : 1;
|
||||
for (i = 0; i < 4; i++) {
|
||||
PrintAndLogEx(NORMAL, "Access block %d%s: %s", bln, ((blinc > 1) && (i < 3) ? "+" : "") , mfGetAccessConditionsDesc(i, &(data + (sectorNo<32?3:15) * 16)[6]));
|
||||
bln += blinc;
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&(data + (sectorNo<32?3:15) * 16)[9], 1));
|
||||
int bln = mfFirstBlockOfSector(sectorNo);
|
||||
int blinc = (mfNumBlocksPerSector(sectorNo) > 4) ? 5 : 1;
|
||||
for (i = 0; i < 4; i++) {
|
||||
PrintAndLogEx(NORMAL, "Access block %d%s: %s", bln, ((blinc > 1) && (i < 3) ? "+" : "") , mfGetAccessConditionsDesc(i, &(data + (sectorNo<32?3:15) * 16)[6]));
|
||||
bln += blinc;
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&(data + (sectorNo<32?3:15) * 16)[9], 1));
|
||||
}
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
|
@ -371,7 +371,7 @@ int CmdHF14AMfDump(const char *Cmd)
|
|||
for (blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
|
||||
bool received = false;
|
||||
for (tries = 0; tries < 3; tries++) {
|
||||
if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer. At least the Access Conditions can always be read with key A.
|
||||
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, keys[0][sectorNo], 6);
|
||||
SendCommand(&c);
|
||||
|
@ -387,14 +387,14 @@ int CmdHF14AMfDump(const char *Cmd)
|
|||
// Don't try the other one on success.
|
||||
if (resp.arg[0] & 0xff) break;
|
||||
}
|
||||
} else { // data block. Check if it can be read with key A or key B
|
||||
} 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] == 0x03) || (rights[sectorNo][data_area] == 0x05)) { // 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, keys[1][sectorNo], 6);
|
||||
SendCommand(&c);
|
||||
received = WaitForResponseTimeout(CMD_ACK,&resp,1500);
|
||||
} else if (rights[sectorNo][data_area] == 0x07) { // no key would work
|
||||
} else if (rights[sectorNo][data_area] == 0x07) { // no key would work
|
||||
PrintAndLog("Access rights do not allow reading of sector %2d block %3d", sectorNo, blockNo);
|
||||
if (nullMissingKeys) {
|
||||
memset(resp.d.asBytes, 0, 16);
|
||||
|
@ -405,7 +405,7 @@ int CmdHF14AMfDump(const char *Cmd)
|
|||
isOK = false;
|
||||
tries = 2;
|
||||
}
|
||||
} else { // key A would work
|
||||
} else { // key A would work
|
||||
UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 0, 0}};
|
||||
memcpy(c.d.asBytes, keys[0][sectorNo], 6);
|
||||
SendCommand(&c);
|
||||
|
@ -421,13 +421,13 @@ int CmdHF14AMfDump(const char *Cmd)
|
|||
if (received) {
|
||||
isOK = resp.arg[0] & 0xff;
|
||||
uint8_t *data = resp.d.asBytes;
|
||||
if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer. Fill in the keys.
|
||||
if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer. Fill in the keys.
|
||||
memcpy(data, keys[0][sectorNo], 6);
|
||||
memcpy(data + 10, keys[1][sectorNo], 6);
|
||||
}
|
||||
if (isOK) {
|
||||
memcpy(carddata[FirstBlockOfSector(sectorNo) + blockNo], data, 16);
|
||||
PrintAndLog("Successfully read block %2d of sector %2d.", blockNo, sectorNo);
|
||||
PrintAndLog("Successfully read block %2d of sector %2d.", blockNo, sectorNo);
|
||||
} else {
|
||||
PrintAndLog("Could not read block %2d of sector %2d", blockNo, sectorNo);
|
||||
break;
|
||||
|
@ -530,7 +530,7 @@ int CmdHF14AMfRestore(const char *Cmd)
|
|||
return 2;
|
||||
}
|
||||
|
||||
if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer
|
||||
if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer
|
||||
bldata[0] = (keyA[sectorNo][0]);
|
||||
bldata[1] = (keyA[sectorNo][1]);
|
||||
bldata[2] = (keyA[sectorNo][2]);
|
||||
|
@ -721,9 +721,9 @@ int CmdHF14AMfNested(const char *Cmd)
|
|||
// transfer key to the emulator
|
||||
if (transferToEml) {
|
||||
uint8_t sectortrailer;
|
||||
if (trgBlockNo < 32*4) { // 4 block sector
|
||||
if (trgBlockNo < 32*4) { // 4 block sector
|
||||
sectortrailer = trgBlockNo | 0x03;
|
||||
} else { // 16 block sector
|
||||
} else { // 16 block sector
|
||||
sectortrailer = trgBlockNo | 0x0f;
|
||||
}
|
||||
mfEmlGetMem(keyBlock, sectortrailer, 1);
|
||||
|
@ -1072,8 +1072,8 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
uint16_t stKeyBlock = 20;
|
||||
|
||||
int i, res;
|
||||
int keycnt = 0;
|
||||
char ctmp = 0x00;
|
||||
int keycnt = 0;
|
||||
char ctmp = 0x00;
|
||||
int clen = 0;
|
||||
uint8_t blockNo = 0;
|
||||
uint8_t SectorsCnt = 0;
|
||||
|
@ -1142,7 +1142,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
}
|
||||
PrintAndLog("chk 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)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6);
|
||||
keycnt++;
|
||||
} else {
|
||||
// May be a dic file
|
||||
|
@ -1159,7 +1159,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
|
||||
while (fgetc(f) != '\n' && !feof(f)) ; //goto next line
|
||||
|
||||
if( buf[0]=='#' ) continue; //The line start with # is comment, skip
|
||||
if( buf[0]=='#' ) continue; //The line start with # is comment, skip
|
||||
|
||||
if (!isxdigit((unsigned char)buf[0])){
|
||||
PrintAndLog("File content error. '%s' must include 12 HEX symbols",buf);
|
||||
|
@ -1200,7 +1200,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
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)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6);
|
||||
}
|
||||
|
||||
// initialize storage for found keys
|
||||
|
@ -1320,7 +1320,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
|
||||
void readerAttack(nonces_t ar_resp[], bool setEmulatorMem, bool doStandardAttack) {
|
||||
#define ATTACK_KEY_COUNT 7 // keep same as define in iso14443a.c -> Mifare1ksim()
|
||||
// cannot be more than 7 or it will overrun c.d.asBytes(512)
|
||||
// cannot be more than 7 or it will overrun c.d.asBytes(512)
|
||||
uint64_t key = 0;
|
||||
typedef struct {
|
||||
uint64_t keyA;
|
||||
|
@ -1329,7 +1329,7 @@ void readerAttack(nonces_t ar_resp[], bool setEmulatorMem, bool doStandardAttack
|
|||
st_t sector_trailer[ATTACK_KEY_COUNT];
|
||||
memset(sector_trailer, 0x00, sizeof(sector_trailer));
|
||||
|
||||
uint8_t stSector[ATTACK_KEY_COUNT];
|
||||
uint8_t stSector[ATTACK_KEY_COUNT];
|
||||
memset(stSector, 0x00, sizeof(stSector));
|
||||
uint8_t key_cnt[ATTACK_KEY_COUNT];
|
||||
memset(key_cnt, 0x00, sizeof(key_cnt));
|
||||
|
@ -1392,7 +1392,7 @@ void readerAttack(nonces_t ar_resp[], bool setEmulatorMem, bool doStandardAttack
|
|||
if (setEmulatorMem) {
|
||||
for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) {
|
||||
if (key_cnt[i]>0) {
|
||||
uint8_t memBlock[16];
|
||||
uint8_t memBlock[16];
|
||||
memset(memBlock, 0x00, sizeof(memBlock));
|
||||
char cmd1[36];
|
||||
memset(cmd1,0x00,sizeof(cmd1));
|
||||
|
@ -1580,7 +1580,7 @@ int CmdHF14AMfSim(const char *Cmd) {
|
|||
cardsize == '2' ? "2K" :
|
||||
cardsize == '4' ? "4K" : "1K",
|
||||
flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):
|
||||
flags & FLAG_7B_UID_IN_DATA ? sprint_hex(uid,7): "N/A",
|
||||
flags & FLAG_7B_UID_IN_DATA ? sprint_hex(uid,7): "N/A",
|
||||
exitAfterNReads,
|
||||
flags,
|
||||
flags);
|
||||
|
@ -1615,7 +1615,7 @@ int CmdHF14AMfSim(const char *Cmd) {
|
|||
cardsize == '2' ? "2K" :
|
||||
cardsize == '4' ? "4K" : "1K",
|
||||
flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):
|
||||
flags & FLAG_7B_UID_IN_DATA ? sprint_hex(uid,7): "N/A",
|
||||
flags & FLAG_7B_UID_IN_DATA ? sprint_hex(uid,7): "N/A",
|
||||
exitAfterNReads,
|
||||
flags,
|
||||
flags);
|
||||
|
@ -1951,31 +1951,37 @@ int CmdHF14AMfECFill(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdHF14AMfEKeyPrn(const char *Cmd)
|
||||
{
|
||||
int i;
|
||||
uint8_t numSectors;
|
||||
uint8_t numSectors = 16;
|
||||
uint8_t data[16];
|
||||
uint64_t keyA, keyB;
|
||||
bool createDumpFile = false;
|
||||
|
||||
if (param_getchar(Cmd, 0) == 'h') {
|
||||
PrintAndLog("It prints the keys loaded in the emulator memory");
|
||||
PrintAndLog("Usage: hf mf ekeyprn [card memory]");
|
||||
PrintAndLog("Usage: hf mf ekeyprn [card memory] [d]");
|
||||
PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K");
|
||||
PrintAndLog(" [d] : write keys to binary file dumpkeys.bin");
|
||||
PrintAndLog("");
|
||||
PrintAndLog(" sample: hf mf ekeyprn 1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
|
||||
switch (cmdp) {
|
||||
case '0' : numSectors = 5; break;
|
||||
case '1' :
|
||||
case '\0': numSectors = 16; break;
|
||||
case '2' : numSectors = 32; break;
|
||||
case '4' : numSectors = 40; break;
|
||||
default: numSectors = 16;
|
||||
uint8_t cmdp = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00) {
|
||||
switch (param_getchar(Cmd, cmdp)) {
|
||||
case '0' : numSectors = 5; break;
|
||||
case '1' :
|
||||
case '\0': numSectors = 16; break;
|
||||
case '2' : numSectors = 32; break;
|
||||
case '4' : numSectors = 40; break;
|
||||
case 'd' :
|
||||
case 'D' : createDumpFile = true; break;
|
||||
}
|
||||
cmdp++;
|
||||
}
|
||||
|
||||
PrintAndLog("|---|----------------|----------------|");
|
||||
|
@ -1992,9 +1998,35 @@ int CmdHF14AMfEKeyPrn(const char *Cmd)
|
|||
}
|
||||
PrintAndLog("|---|----------------|----------------|");
|
||||
|
||||
// Create dump file
|
||||
if (createDumpFile) {
|
||||
FILE *fkeys;
|
||||
if ((fkeys = fopen("dumpkeys.bin","wb")) == NULL) {
|
||||
PrintAndLog("Could not create file dumpkeys.bin");
|
||||
return 1;
|
||||
}
|
||||
PrintAndLog("Printing keys to binary file dumpkeys.bin...");
|
||||
for(i = 0; i < numSectors; i++) {
|
||||
if (mfEmlGetMem(data, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1)) {
|
||||
PrintAndLog("error get block %d", FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1);
|
||||
break;
|
||||
}
|
||||
fwrite(data+6, 1, 6, fkeys);
|
||||
}
|
||||
for(i = 0; i < numSectors; i++) {
|
||||
if (mfEmlGetMem(data, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1)) {
|
||||
PrintAndLog("error get block %d", FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1);
|
||||
break;
|
||||
}
|
||||
fwrite(data+10, 1, 6, fkeys);
|
||||
}
|
||||
fclose(fkeys);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdHF14AMfCSetUID(const char *Cmd)
|
||||
{
|
||||
uint8_t uid[8] = {0x00};
|
||||
|
@ -2213,9 +2245,9 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
|||
PrintAndLog("Cant get block: %d", blockNum);
|
||||
return 2;
|
||||
}
|
||||
if (blockNum == 0) flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC; // switch on field and send magic sequence
|
||||
if (blockNum == 1) flags = 0; // just write
|
||||
if (blockNum == numblock - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD; // Done. Magic Halt and switch off field.
|
||||
if (blockNum == 0) flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC; // switch on field and send magic sequence
|
||||
if (blockNum == 1) flags = 0; // just write
|
||||
if (blockNum == numblock - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD; // Done. Magic Halt and switch off field.
|
||||
|
||||
if (gen == 2)
|
||||
/* generation 1b magic card */
|
||||
|
@ -2265,9 +2297,9 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
|||
for (i = 0; i < 32; i += 2)
|
||||
sscanf(&buf[i], "%02x", (unsigned int *)&buf8[i / 2]);
|
||||
|
||||
if (blockNum == 0) flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC; // switch on field and send magic sequence
|
||||
if (blockNum == 1) flags = 0; // just write
|
||||
if (blockNum == numblock - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD; // Done. Switch off field.
|
||||
if (blockNum == 0) flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC; // switch on field and send magic sequence
|
||||
if (blockNum == 1) flags = 0; // just write
|
||||
if (blockNum == numblock - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD; // Done. Switch off field.
|
||||
|
||||
if (gen == 2)
|
||||
/* generation 1b magic card */
|
||||
|
@ -2392,17 +2424,17 @@ int CmdHF14AMfCGetSc(const char *Cmd) {
|
|||
PrintAndLog("block %3d data:%s", baseblock + i, sprint_hex(memBlock, 16));
|
||||
|
||||
if (mfIsSectorTrailer(baseblock + i)) {
|
||||
PrintAndLogEx(NORMAL, "Trailer decoded:");
|
||||
PrintAndLogEx(NORMAL, "Key A: %s", sprint_hex_inrow(memBlock, 6));
|
||||
PrintAndLogEx(NORMAL, "Key B: %s", sprint_hex_inrow(&memBlock[10], 6));
|
||||
int bln = baseblock;
|
||||
int blinc = (mfNumBlocksPerSector(sectorNo) > 4) ? 5 : 1;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
PrintAndLogEx(NORMAL, "Access block %d%s: %s", bln, ((blinc > 1) && (i < 3) ? "+" : "") , mfGetAccessConditionsDesc(i, &memBlock[6]));
|
||||
bln += blinc;
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&memBlock[9], 1));
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "Trailer decoded:");
|
||||
PrintAndLogEx(NORMAL, "Key A: %s", sprint_hex_inrow(memBlock, 6));
|
||||
PrintAndLogEx(NORMAL, "Key B: %s", sprint_hex_inrow(&memBlock[10], 6));
|
||||
int bln = baseblock;
|
||||
int blinc = (mfNumBlocksPerSector(sectorNo) > 4) ? 5 : 1;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
PrintAndLogEx(NORMAL, "Access block %d%s: %s", bln, ((blinc > 1) && (i < 3) ? "+" : "") , mfGetAccessConditionsDesc(i, &memBlock[6]));
|
||||
bln += blinc;
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&memBlock[9], 1));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -2599,17 +2631,17 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
uint16_t traceLen = resp.arg[1];
|
||||
len = resp.arg[2];
|
||||
|
||||
if (res == 0) { // we are done
|
||||
if (res == 0) { // we are done
|
||||
break;
|
||||
}
|
||||
|
||||
if (res == 1) { // there is (more) data to be transferred
|
||||
if (pckNum == 0) { // first packet, (re)allocate necessary buffer
|
||||
if (res == 1) { // there is (more) data to be transferred
|
||||
if (pckNum == 0) { // first packet, (re)allocate necessary buffer
|
||||
if (traceLen > bufsize || buf == NULL) {
|
||||
uint8_t *p;
|
||||
if (buf == NULL) { // not yet allocated
|
||||
if (buf == NULL) { // not yet allocated
|
||||
p = malloc(traceLen);
|
||||
} else { // need more memory
|
||||
} else { // need more memory
|
||||
p = realloc(buf, traceLen);
|
||||
}
|
||||
if (p == NULL) {
|
||||
|
@ -2628,13 +2660,13 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
pckNum++;
|
||||
}
|
||||
|
||||
if (res == 2) { // received all data, start displaying
|
||||
if (res == 2) { // received all data, start displaying
|
||||
blockLen = bufPtr - buf;
|
||||
bufPtr = buf;
|
||||
printf(">\n");
|
||||
PrintAndLog("received trace len: %d packages: %d", blockLen, pckNum);
|
||||
while (bufPtr - buf < blockLen) {
|
||||
bufPtr += 6; // skip (void) timing information
|
||||
bufPtr += 6; // skip (void) timing information
|
||||
len = *((uint16_t *)bufPtr);
|
||||
if(len & 0x8000) {
|
||||
isTag = true;
|
||||
|
@ -2676,7 +2708,7 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
num++;
|
||||
}
|
||||
bufPtr += len;
|
||||
bufPtr += parlen; // ignore parity
|
||||
bufPtr += parlen; // ignore parity
|
||||
}
|
||||
pckNum = 0;
|
||||
}
|
||||
|
@ -2737,196 +2769,196 @@ int CmdHF14AMfAuth4(const char *cmd) {
|
|||
// https://www.nxp.com/docs/en/application-note/AN10787.pdf
|
||||
int CmdHF14AMfMAD(const char *cmd) {
|
||||
|
||||
CLIParserInit("hf mf mad",
|
||||
"Checks and prints Mifare Application Directory (MAD)",
|
||||
"Usage:\n\thf mf mad -> shows MAD if exists\n"
|
||||
"\thf mf mad -a 03e1 -k ffffffffffff -b -> shows NDEF data if exists. read card with custom key and key B\n");
|
||||
CLIParserInit("hf mf mad",
|
||||
"Checks and prints Mifare Application Directory (MAD)",
|
||||
"Usage:\n\thf mf mad -> shows MAD if exists\n"
|
||||
"\thf mf mad -a 03e1 -k ffffffffffff -b -> shows NDEF data if exists. read card with custom key and key B\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("vV", "verbose", "show technical data"),
|
||||
arg_str0("aA", "aid", "print all sectors with aid", NULL),
|
||||
arg_str0("kK", "key", "key for printing sectors", NULL),
|
||||
arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(cmd, argtable, true);
|
||||
bool verbose = arg_get_lit(1);
|
||||
uint8_t aid[2] = {0};
|
||||
int aidlen;
|
||||
CLIGetHexWithReturn(2, aid, &aidlen);
|
||||
uint8_t key[6] = {0};
|
||||
int keylen;
|
||||
CLIGetHexWithReturn(3, key, &keylen);
|
||||
bool keyB = arg_get_lit(4);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("vV", "verbose", "show technical data"),
|
||||
arg_str0("aA", "aid", "print all sectors with aid", NULL),
|
||||
arg_str0("kK", "key", "key for printing sectors", NULL),
|
||||
arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(cmd, argtable, true);
|
||||
bool verbose = arg_get_lit(1);
|
||||
uint8_t aid[2] = {0};
|
||||
int aidlen;
|
||||
CLIGetHexWithReturn(2, aid, &aidlen);
|
||||
uint8_t key[6] = {0};
|
||||
int keylen;
|
||||
CLIGetHexWithReturn(3, key, &keylen);
|
||||
bool keyB = arg_get_lit(4);
|
||||
|
||||
CLIParserFree();
|
||||
CLIParserFree();
|
||||
|
||||
if (aidlen != 2 && keylen > 0) {
|
||||
PrintAndLogEx(WARNING, "do not need a key without aid.");
|
||||
}
|
||||
if (aidlen != 2 && keylen > 0) {
|
||||
PrintAndLogEx(WARNING, "do not need a key without aid.");
|
||||
}
|
||||
|
||||
uint8_t sector0[16 * 4] = {0};
|
||||
uint8_t sector10[16 * 4] = {0};
|
||||
if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) {
|
||||
PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys.");
|
||||
return 2;
|
||||
}
|
||||
uint8_t sector0[16 * 4] = {0};
|
||||
uint8_t sector10[16 * 4] = {0};
|
||||
if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) {
|
||||
PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys.");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
for (int i = 0; i < 4; i ++)
|
||||
PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or0[i * 16], 16));
|
||||
}
|
||||
if (verbose) {
|
||||
for (int i = 0; i < 4; i ++)
|
||||
PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or0[i * 16], 16));
|
||||
}
|
||||
|
||||
bool haveMAD2 = false;
|
||||
MAD1DecodeAndPrint(sector0, verbose, &haveMAD2);
|
||||
bool haveMAD2 = false;
|
||||
MAD1DecodeAndPrint(sector0, verbose, &haveMAD2);
|
||||
|
||||
if (haveMAD2) {
|
||||
if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) {
|
||||
PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys.");
|
||||
return 2;
|
||||
}
|
||||
if (haveMAD2) {
|
||||
if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) {
|
||||
PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys.");
|
||||
return 2;
|
||||
}
|
||||
|
||||
MAD2DecodeAndPrint(sector10, verbose);
|
||||
}
|
||||
MAD2DecodeAndPrint(sector10, verbose);
|
||||
}
|
||||
|
||||
if (aidlen == 2) {
|
||||
uint16_t aaid = (aid[0] << 8) + aid[1];
|
||||
PrintAndLogEx(NORMAL, "\n-------------- AID 0x%04x ---------------", aaid);
|
||||
if (aidlen == 2) {
|
||||
uint16_t aaid = (aid[0] << 8) + aid[1];
|
||||
PrintAndLogEx(NORMAL, "\n-------------- AID 0x%04x ---------------", aaid);
|
||||
|
||||
uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
|
||||
size_t madlen = 0;
|
||||
if (MADDecode(sector0, sector10, mad, &madlen)) {
|
||||
PrintAndLogEx(ERR, "can't decode mad.");
|
||||
return 10;
|
||||
}
|
||||
uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
|
||||
size_t madlen = 0;
|
||||
if (MADDecode(sector0, sector10, mad, &madlen)) {
|
||||
PrintAndLogEx(ERR, "can't decode mad.");
|
||||
return 10;
|
||||
}
|
||||
|
||||
uint8_t akey[6] = {0};
|
||||
memcpy(akey, g_mifare_ndef_key, 6);
|
||||
if (keylen == 6) {
|
||||
memcpy(akey, key, 6);
|
||||
}
|
||||
uint8_t akey[6] = {0};
|
||||
memcpy(akey, g_mifare_ndef_key, 6);
|
||||
if (keylen == 6) {
|
||||
memcpy(akey, key, 6);
|
||||
}
|
||||
|
||||
for (int i = 0; i < madlen; i++) {
|
||||
if (aaid == mad[i]) {
|
||||
uint8_t vsector[16 * 4] = {0};
|
||||
if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, akey, vsector)) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(ERR, "read sector %d error.", i + 1);
|
||||
return 2;
|
||||
}
|
||||
for (int i = 0; i < madlen; i++) {
|
||||
if (aaid == mad[i]) {
|
||||
uint8_t vsector[16 * 4] = {0};
|
||||
if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, akey, vsector)) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(ERR, "read sector %d error.", i + 1);
|
||||
return 2;
|
||||
}
|
||||
|
||||
for (int j = 0; j < (verbose ? 4 : 3); j ++)
|
||||
PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < (verbose ? 4 : 3); j ++)
|
||||
PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHFMFNDEF(const char *cmd) {
|
||||
|
||||
CLIParserInit("hf mf ndef",
|
||||
"Prints NFC Data Exchange Format (NDEF)",
|
||||
"Usage:\n\thf mf ndef -> shows NDEF data\n"
|
||||
"\thf mf ndef -a 03e1 -k ffffffffffff -b -> shows NDEF data with custom AID, key and with key B\n");
|
||||
CLIParserInit("hf mf ndef",
|
||||
"Prints NFC Data Exchange Format (NDEF)",
|
||||
"Usage:\n\thf mf ndef -> shows NDEF data\n"
|
||||
"\thf mf ndef -a 03e1 -k ffffffffffff -b -> shows NDEF data with custom AID, key and with key B\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_litn("vV", "verbose", 0, 2, "show technical data"),
|
||||
arg_str0("aA", "aid", "replace default aid for NDEF", NULL),
|
||||
arg_str0("kK", "key", "replace default key for NDEF", NULL),
|
||||
arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(cmd, argtable, true);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_litn("vV", "verbose", 0, 2, "show technical data"),
|
||||
arg_str0("aA", "aid", "replace default aid for NDEF", NULL),
|
||||
arg_str0("kK", "key", "replace default key for NDEF", NULL),
|
||||
arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(cmd, argtable, true);
|
||||
|
||||
bool verbose = arg_get_lit(1);
|
||||
bool verbose2 = arg_get_lit(1) > 1;
|
||||
uint8_t aid[2] = {0};
|
||||
int aidlen;
|
||||
CLIGetHexWithReturn(2, aid, &aidlen);
|
||||
uint8_t key[6] = {0};
|
||||
int keylen;
|
||||
CLIGetHexWithReturn(3, key, &keylen);
|
||||
bool keyB = arg_get_lit(4);
|
||||
bool verbose = arg_get_lit(1);
|
||||
bool verbose2 = arg_get_lit(1) > 1;
|
||||
uint8_t aid[2] = {0};
|
||||
int aidlen;
|
||||
CLIGetHexWithReturn(2, aid, &aidlen);
|
||||
uint8_t key[6] = {0};
|
||||
int keylen;
|
||||
CLIGetHexWithReturn(3, key, &keylen);
|
||||
bool keyB = arg_get_lit(4);
|
||||
|
||||
CLIParserFree();
|
||||
CLIParserFree();
|
||||
|
||||
uint16_t ndefAID = 0x03e1;
|
||||
if (aidlen == 2)
|
||||
ndefAID = (aid[0] << 8) + aid[1];
|
||||
uint16_t ndefAID = 0x03e1;
|
||||
if (aidlen == 2)
|
||||
ndefAID = (aid[0] << 8) + aid[1];
|
||||
|
||||
uint8_t ndefkey[6] = {0};
|
||||
memcpy(ndefkey, g_mifare_ndef_key, 6);
|
||||
if (keylen == 6) {
|
||||
memcpy(ndefkey, key, 6);
|
||||
}
|
||||
uint8_t ndefkey[6] = {0};
|
||||
memcpy(ndefkey, g_mifare_ndef_key, 6);
|
||||
if (keylen == 6) {
|
||||
memcpy(ndefkey, key, 6);
|
||||
}
|
||||
|
||||
uint8_t sector0[16 * 4] = {0};
|
||||
uint8_t sector10[16 * 4] = {0};
|
||||
uint8_t data[4096] = {0};
|
||||
int datalen = 0;
|
||||
uint8_t sector0[16 * 4] = {0};
|
||||
uint8_t sector10[16 * 4] = {0};
|
||||
uint8_t data[4096] = {0};
|
||||
int datalen = 0;
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) {
|
||||
PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys.");
|
||||
return 2;
|
||||
}
|
||||
if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) {
|
||||
PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys.");
|
||||
return 2;
|
||||
}
|
||||
|
||||
bool haveMAD2 = false;
|
||||
int res = MADCheck(sector0, NULL, verbose, &haveMAD2);
|
||||
if (res) {
|
||||
PrintAndLogEx(ERR, "MAD error %d.", res);
|
||||
return res;
|
||||
}
|
||||
bool haveMAD2 = false;
|
||||
int res = MADCheck(sector0, NULL, verbose, &haveMAD2);
|
||||
if (res) {
|
||||
PrintAndLogEx(ERR, "MAD error %d.", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
if (haveMAD2) {
|
||||
if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) {
|
||||
PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys.");
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
if (haveMAD2) {
|
||||
if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) {
|
||||
PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys.");
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
|
||||
size_t madlen = 0;
|
||||
if (MADDecode(sector0, (haveMAD2 ? sector10 : NULL), mad, &madlen)) {
|
||||
PrintAndLogEx(ERR, "can't decode mad.");
|
||||
return 10;
|
||||
}
|
||||
uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
|
||||
size_t madlen = 0;
|
||||
if (MADDecode(sector0, (haveMAD2 ? sector10 : NULL), mad, &madlen)) {
|
||||
PrintAndLogEx(ERR, "can't decode mad.");
|
||||
return 10;
|
||||
}
|
||||
|
||||
printf("data reading:");
|
||||
for (int i = 0; i < madlen; i++) {
|
||||
if (ndefAID == mad[i]) {
|
||||
uint8_t vsector[16 * 4] = {0};
|
||||
if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector)) {
|
||||
PrintAndLogEx(ERR, "read sector %d error.", i + 1);
|
||||
return 2;
|
||||
}
|
||||
printf("data reading:");
|
||||
for (int i = 0; i < madlen; i++) {
|
||||
if (ndefAID == mad[i]) {
|
||||
uint8_t vsector[16 * 4] = {0};
|
||||
if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector)) {
|
||||
PrintAndLogEx(ERR, "read sector %d error.", i + 1);
|
||||
return 2;
|
||||
}
|
||||
|
||||
memcpy(&data[datalen], vsector, 16 * 3);
|
||||
datalen += 16 * 3;
|
||||
memcpy(&data[datalen], vsector, 16 * 3);
|
||||
datalen += 16 * 3;
|
||||
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
printf(" OK\n");
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
printf(" OK\n");
|
||||
|
||||
if (!datalen) {
|
||||
PrintAndLogEx(ERR, "no NDEF data.");
|
||||
return 11;
|
||||
}
|
||||
if (!datalen) {
|
||||
PrintAndLogEx(ERR, "no NDEF data.");
|
||||
return 11;
|
||||
}
|
||||
|
||||
if (verbose2) {
|
||||
PrintAndLogEx(NORMAL, "NDEF data:");
|
||||
dump_buffer(data, datalen, stdout, 1);
|
||||
}
|
||||
if (verbose2) {
|
||||
PrintAndLogEx(NORMAL, "NDEF data:");
|
||||
dump_buffer(data, datalen, stdout, 1);
|
||||
}
|
||||
|
||||
NDEFDecodeAndPrint(data, datalen, verbose);
|
||||
NDEFDecodeAndPrint(data, datalen, verbose);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] =
|
||||
|
@ -2936,7 +2968,7 @@ static command_t CommandTable[] =
|
|||
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic 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"},
|
||||
{"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},
|
||||
{"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},
|
||||
{"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"},
|
||||
{"chk", CmdHF14AMfChk, 0, "Test block keys"},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue