mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
SendCommandOLD & errors retval: mifarehost
This commit is contained in:
parent
45afe8dec0
commit
2ac5482d9c
1 changed files with 79 additions and 99 deletions
|
@ -15,8 +15,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
||||||
uint32_t nt = 0, nr = 0, ar = 0;
|
uint32_t nt = 0, nr = 0, ar = 0;
|
||||||
uint64_t par_list = 0, ks_list = 0;
|
uint64_t par_list = 0, ks_list = 0;
|
||||||
uint64_t *keylist = NULL, *last_keylist = NULL;
|
uint64_t *keylist = NULL, *last_keylist = NULL;
|
||||||
|
bool arg0 = true;
|
||||||
PacketCommandOLD c = {CMD_READER_MIFARE, {true, blockno, key_type}, {{0}}};
|
|
||||||
|
|
||||||
// message
|
// message
|
||||||
PrintAndLogEx(NORMAL, "--------------------------------------------------------------------------------\n");
|
PrintAndLogEx(NORMAL, "--------------------------------------------------------------------------------\n");
|
||||||
|
@ -26,13 +25,13 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommandOLD(CMD_READER_MIFARE, arg0, blockno, key_type, NULL, 0);
|
||||||
|
|
||||||
//flush queue
|
//flush queue
|
||||||
while (ukbhit()) {
|
while (ukbhit()) {
|
||||||
int gc = getchar();
|
int gc = getchar();
|
||||||
(void)gc;
|
(void)gc;
|
||||||
return -5;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait cycle
|
// wait cycle
|
||||||
|
@ -42,7 +41,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
||||||
if (ukbhit()) {
|
if (ukbhit()) {
|
||||||
int gc = getchar();
|
int gc = getchar();
|
||||||
(void)gc;
|
(void)gc;
|
||||||
return -5;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
@ -62,10 +61,10 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "\n");
|
PrintAndLogEx(NORMAL, "\n");
|
||||||
|
|
||||||
if (par_list == 0 && c.arg[0] == true) {
|
if (par_list == 0 && arg0 == true) {
|
||||||
PrintAndLogEx(SUCCESS, "Parity is all zero. Most likely this card sends NACK on every authentication.");
|
PrintAndLogEx(SUCCESS, "Parity is all zero. Most likely this card sends NACK on every authentication.");
|
||||||
}
|
}
|
||||||
c.arg[0] = false;
|
arg0 = false;
|
||||||
|
|
||||||
uint32_t keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist);
|
uint32_t keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist);
|
||||||
|
|
||||||
|
@ -114,24 +113,22 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
||||||
PrintAndLogEx(FAILED, "all candidate keys failed. Restarting darkside attack");
|
PrintAndLogEx(FAILED, "all candidate keys failed. Restarting darkside attack");
|
||||||
free(last_keylist);
|
free(last_keylist);
|
||||||
last_keylist = keylist;
|
last_keylist = keylist;
|
||||||
c.arg[0] = true;
|
arg0 = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(last_keylist);
|
free(last_keylist);
|
||||||
free(keylist);
|
free(keylist);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key) {
|
int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key) {
|
||||||
*key = -1;
|
*key = -1;
|
||||||
PacketCommandOLD c = {CMD_MIFARE_CHKKEYS, { (blockNo | (keyType << 8)), clear_trace, keycnt}, {{0}}};
|
|
||||||
memcpy(c.d.asBytes, keyBlock, 6 * keycnt);
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommandOLD(CMD_MIFARE_CHKKEYS, (blockNo | (keyType << 8)), clear_trace, keycnt, keyBlock, 6 * keycnt);
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) return 1;
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) return PM3_ETIMEOUT;
|
||||||
if ((resp.oldarg[0] & 0xff) != 0x01) return 2;
|
if ((resp.oldarg[0] & 0xff) != 0x01) return PM3_EUNDEF;
|
||||||
*key = bytes_to_num(resp.data.asBytes, 6);
|
*key = bytes_to_num(resp.data.asBytes, 6);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends chunks of keys to device.
|
// Sends chunks of keys to device.
|
||||||
|
@ -145,10 +142,8 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk,
|
||||||
uint32_t timeout = 0;
|
uint32_t timeout = 0;
|
||||||
|
|
||||||
// send keychunk
|
// send keychunk
|
||||||
PacketCommandOLD c = {CMD_MIFARE_CHKKEYS_FAST, { (sectorsCnt | (firstChunk << 8) | (lastChunk << 12)), ((use_flashmemory << 8) | strategy), size}, {{0}}};
|
|
||||||
memcpy(c.d.asBytes, keyBlock, 6 * size);
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommandOLD(CMD_MIFARE_CHKKEYS_FAST, (sectorsCnt | (firstChunk << 8) | (lastChunk << 12)), ((use_flashmemory << 8) | strategy), size, keyBlock, 6 * size);
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
|
||||||
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
|
@ -160,7 +155,7 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk,
|
||||||
// takes about 97s, still some margin before abort
|
// takes about 97s, still some margin before abort
|
||||||
if (timeout > 180) {
|
if (timeout > 180) {
|
||||||
PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
|
PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
|
||||||
return 2;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t2 = msclock() - t2;
|
t2 = msclock() - t2;
|
||||||
|
@ -297,11 +292,9 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
|
||||||
StateList_t statelists[2];
|
StateList_t statelists[2];
|
||||||
struct Crypto1State *p1, *p2, *p3, *p4;
|
struct Crypto1State *p1, *p2, *p3, *p4;
|
||||||
|
|
||||||
PacketCommandOLD c = {CMD_MIFARE_NESTED, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate}, {{0}}};
|
|
||||||
memcpy(c.d.asBytes, key, 6);
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommandOLD(CMD_MIFARE_NESTED, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate, key, 6);
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1;
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return PM3_ETIMEOUT;
|
||||||
|
|
||||||
// error during nested
|
// error during nested
|
||||||
if (resp.oldarg[0]) return resp.oldarg[0];
|
if (resp.oldarg[0]) return resp.oldarg[0];
|
||||||
|
@ -419,10 +412,8 @@ out:
|
||||||
// MIFARE
|
// MIFARE
|
||||||
int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data) {
|
int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data) {
|
||||||
|
|
||||||
PacketCommandOLD c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}, {{0}}};
|
|
||||||
memcpy(c.d.asBytes, key, 6);
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommandOLD(CMD_MIFARE_READSC, sectorNo, keyType, 0, key, 6);
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
|
@ -430,27 +421,26 @@ int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data)
|
||||||
|
|
||||||
if (isOK) {
|
if (isOK) {
|
||||||
memcpy(data, resp.data.asBytes, mfNumBlocksPerSector(sectorNo) * 16);
|
memcpy(data, resp.data.asBytes, mfNumBlocksPerSector(sectorNo) * 16);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return PM3_EUNDEF;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(ERR, "Command execute timeout");
|
PrintAndLogEx(ERR, "Command execute timeout");
|
||||||
return 2;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EMULATOR
|
// EMULATOR
|
||||||
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {
|
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||||
PacketCommandOLD c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}, {{0}}};
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommandOLD(CMD_MIFARE_EML_MEMGET, blockNum, blocksCount, 0, NULL, 0);
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return 1;
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return PM3_ETIMEOUT;
|
||||||
memcpy(data, resp.data.asBytes, blocksCount * 16);
|
memcpy(data, resp.data.asBytes, blocksCount * 16);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||||
|
@ -458,11 +448,9 @@ int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) {
|
int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) {
|
||||||
PacketCommandOLD c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, blockBtWidth}, {{0}}};
|
|
||||||
memcpy(c.d.asBytes, data, blocksCount * blockBtWidth);
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommandOLD(CMD_MIFARE_EML_MEMSET, blockNum, blocksCount, blockBtWidth, data, blocksCount * blockBtWidth);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "MAGIC" CARD
|
// "MAGIC" CARD
|
||||||
|
@ -501,39 +489,36 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_
|
||||||
|
|
||||||
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) {
|
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) {
|
||||||
|
|
||||||
PacketCommandOLD c = {CMD_MIFARE_CSETBLOCK, {params, blockNo, 0}, {{0}}};
|
|
||||||
memcpy(c.d.asBytes, data, 16);
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommandOLD(CMD_MIFARE_CSETBLOCK, params, blockNo, 0, data, 16);
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
uint8_t isOK = resp.oldarg[0] & 0xff;
|
||||||
if (uid != NULL)
|
if (uid != NULL)
|
||||||
memcpy(uid, resp.data.asBytes, 4);
|
memcpy(uid, resp.data.asBytes, 4);
|
||||||
if (!isOK)
|
if (!isOK)
|
||||||
return 2;
|
return PM3_EUNDEF;
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "command execute timeout");
|
PrintAndLogEx(WARNING, "command execute timeout");
|
||||||
return 1;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {
|
int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {
|
||||||
PacketCommandOLD c = {CMD_MIFARE_CGETBLOCK, {params, blockNo, 0}, {{0}}};
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommandOLD(CMD_MIFARE_CGETBLOCK, params, blockNo, 0, NULL, 0);
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
uint8_t isOK = resp.oldarg[0] & 0xff;
|
||||||
if (!isOK)
|
if (!isOK)
|
||||||
return 2;
|
return PM3_EUNDEF;
|
||||||
memcpy(data, resp.data.asBytes, 16);
|
memcpy(data, resp.data.asBytes, 16);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "command execute timeout");
|
PrintAndLogEx(WARNING, "command execute timeout");
|
||||||
return 1;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SNIFFER
|
// SNIFFER
|
||||||
|
@ -586,7 +571,7 @@ int loadTraceCard(uint8_t *tuid, uint8_t uidlen) {
|
||||||
FillFileNameByUID(traceFileName, tuid, ".eml", uidlen);
|
FillFileNameByUID(traceFileName, tuid, ".eml", uidlen);
|
||||||
|
|
||||||
f = fopen(traceFileName, "r");
|
f = fopen(traceFileName, "r");
|
||||||
if (!f) return 1;
|
if (!f) return PM3_EFILE;
|
||||||
|
|
||||||
blockNum = 0;
|
blockNum = 0;
|
||||||
|
|
||||||
|
@ -596,14 +581,14 @@ int loadTraceCard(uint8_t *tuid, uint8_t uidlen) {
|
||||||
if (fgets(buf, sizeof(buf), f) == NULL) {
|
if (fgets(buf, sizeof(buf), f) == NULL) {
|
||||||
PrintAndLogEx(FAILED, "No trace file found or reading error.");
|
PrintAndLogEx(FAILED, "No trace file found or reading error.");
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 2;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(buf) < 32) {
|
if (strlen(buf) < 32) {
|
||||||
if (feof(f)) break;
|
if (feof(f)) break;
|
||||||
PrintAndLogEx(FAILED, "File content error. Block data must include 32 HEX symbols");
|
PrintAndLogEx(FAILED, "File content error. Block data must include 32 HEX symbols");
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 2;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
for (i = 0; i < 32; i += 2) {
|
for (i = 0; i < 32; i += 2) {
|
||||||
sscanf(&buf[i], "%02X", &tmp);
|
sscanf(&buf[i], "%02X", &tmp);
|
||||||
|
@ -615,16 +600,16 @@ int loadTraceCard(uint8_t *tuid, uint8_t uidlen) {
|
||||||
blockNum++;
|
blockNum++;
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int saveTraceCard(void) {
|
int saveTraceCard(void) {
|
||||||
|
|
||||||
if ((!strlen(traceFileName)) || (isTraceCardEmpty())) return 0;
|
if ((!strlen(traceFileName)) || (isTraceCardEmpty())) return PM3_ESOFT;
|
||||||
|
|
||||||
FILE *f;
|
FILE *f;
|
||||||
f = fopen(traceFileName, "w+");
|
f = fopen(traceFileName, "w+");
|
||||||
if (!f) return 1;
|
if (!f) return PM3_EFILE;
|
||||||
|
|
||||||
// given 4096 tracecard size, these loop will only match a 1024, 1kb card memory
|
// given 4096 tracecard size, these loop will only match a 1024, 1kb card memory
|
||||||
// 4086/16 == 256blocks.
|
// 4086/16 == 256blocks.
|
||||||
|
@ -638,7 +623,7 @@ int saveTraceCard(void) {
|
||||||
}
|
}
|
||||||
fflush(f);
|
fflush(f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile) {
|
int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile) {
|
||||||
|
@ -657,7 +642,7 @@ int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool
|
||||||
traceCurBlock = 0;
|
traceCurBlock = 0;
|
||||||
cuid = bytes_to_num(tuid + (uidlen - 4), 4);
|
cuid = bytes_to_num(tuid + (uidlen - 4), 4);
|
||||||
traceState = TRACE_IDLE;
|
traceState = TRACE_IDLE;
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted) {
|
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted) {
|
||||||
|
@ -680,11 +665,11 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
uint32_t ar_enc = 0; // encrypted reader response
|
uint32_t ar_enc = 0; // encrypted reader response
|
||||||
uint32_t at_enc = 0; // encrypted tag response
|
uint32_t at_enc = 0; // encrypted tag response
|
||||||
if (traceState == TRACE_ERROR)
|
if (traceState == TRACE_ERROR)
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
|
|
||||||
if (len > 255) {
|
if (len > 255) {
|
||||||
traceState = TRACE_ERROR;
|
traceState = TRACE_ERROR;
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t data[255];
|
uint8_t data[255];
|
||||||
|
@ -705,7 +690,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
PrintAndLogEx(NORMAL, "DEC| CRC ERROR!!!");
|
PrintAndLogEx(NORMAL, "DEC| CRC ERROR!!!");
|
||||||
AddLogLine(logHexFileName, "DEC| ", "CRC ERROR!!!");
|
AddLogLine(logHexFileName, "DEC| ", "CRC ERROR!!!");
|
||||||
traceState = TRACE_ERROR; // do not decrypt the next commands
|
traceState = TRACE_ERROR; // do not decrypt the next commands
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// AUTHENTICATION
|
// AUTHENTICATION
|
||||||
|
@ -713,29 +698,29 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
traceState = TRACE_AUTH1;
|
traceState = TRACE_AUTH1;
|
||||||
traceCurBlock = data[1];
|
traceCurBlock = data[1];
|
||||||
traceCurKey = data[0] == 60 ? 1 : 0;
|
traceCurKey = data[0] == 60 ? 1 : 0;
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
if ((len == 4) && ((data[0] == ISO14443A_CMD_READBLOCK))) {
|
if ((len == 4) && ((data[0] == ISO14443A_CMD_READBLOCK))) {
|
||||||
traceState = TRACE_READ_DATA;
|
traceState = TRACE_READ_DATA;
|
||||||
traceCurBlock = data[1];
|
traceCurBlock = data[1];
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// WRITE
|
// WRITE
|
||||||
if ((len == 4) && ((data[0] == ISO14443A_CMD_WRITEBLOCK))) {
|
if ((len == 4) && ((data[0] == ISO14443A_CMD_WRITEBLOCK))) {
|
||||||
traceState = TRACE_WRITE_OK;
|
traceState = TRACE_WRITE_OK;
|
||||||
traceCurBlock = data[1];
|
traceCurBlock = data[1];
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HALT
|
// HALT
|
||||||
if ((len == 4) && ((data[0] == ISO14443A_CMD_HALT) && (data[1] == 0x00))) {
|
if ((len == 4) && ((data[0] == ISO14443A_CMD_HALT) && (data[1] == 0x00))) {
|
||||||
traceState = TRACE_ERROR; // do not decrypt the next commands
|
traceState = TRACE_ERROR; // do not decrypt the next commands
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
|
|
||||||
case TRACE_READ_DATA:
|
case TRACE_READ_DATA:
|
||||||
if (len == 18) {
|
if (len == 18) {
|
||||||
|
@ -747,19 +732,19 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
memcpy(traceCard + traceCurBlock * 16, data, 16);
|
memcpy(traceCard + traceCurBlock * 16, data, 16);
|
||||||
}
|
}
|
||||||
if (wantSaveToEmlFile) saveTraceCard();
|
if (wantSaveToEmlFile) saveTraceCard();
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
traceState = TRACE_ERROR;
|
traceState = TRACE_ERROR;
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TRACE_WRITE_OK:
|
case TRACE_WRITE_OK:
|
||||||
if ((len == 1) && (data[0] == 0x0a)) {
|
if ((len == 1) && (data[0] == 0x0a)) {
|
||||||
traceState = TRACE_WRITE_DATA;
|
traceState = TRACE_WRITE_DATA;
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
traceState = TRACE_ERROR;
|
traceState = TRACE_ERROR;
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TRACE_WRITE_DATA:
|
case TRACE_WRITE_DATA:
|
||||||
|
@ -767,20 +752,20 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
traceState = TRACE_IDLE;
|
traceState = TRACE_IDLE;
|
||||||
memcpy(traceCard + traceCurBlock * 16, data, 16);
|
memcpy(traceCard + traceCurBlock * 16, data, 16);
|
||||||
if (wantSaveToEmlFile) saveTraceCard();
|
if (wantSaveToEmlFile) saveTraceCard();
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
traceState = TRACE_ERROR;
|
traceState = TRACE_ERROR;
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TRACE_AUTH1:
|
case TRACE_AUTH1:
|
||||||
if (len == 4) {
|
if (len == 4) {
|
||||||
traceState = TRACE_AUTH2;
|
traceState = TRACE_AUTH2;
|
||||||
//nt = bytes_to_num(data, 4);
|
//nt = bytes_to_num(data, 4);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
traceState = TRACE_ERROR;
|
traceState = TRACE_ERROR;
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TRACE_AUTH2:
|
case TRACE_AUTH2:
|
||||||
|
@ -788,10 +773,10 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
traceState = TRACE_AUTH_OK;
|
traceState = TRACE_AUTH_OK;
|
||||||
//nr_enc = bytes_to_num(data, 4);
|
//nr_enc = bytes_to_num(data, 4);
|
||||||
//ar_enc = bytes_to_num(data + 4, 4);
|
//ar_enc = bytes_to_num(data + 4, 4);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
traceState = TRACE_ERROR;
|
traceState = TRACE_ERROR;
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TRACE_AUTH_OK:
|
case TRACE_AUTH_OK:
|
||||||
|
@ -843,9 +828,9 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
traceState = TRACE_ERROR;
|
traceState = TRACE_ERROR;
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len) {
|
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len) {
|
||||||
|
@ -857,7 +842,7 @@ int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data,
|
||||||
mf_crypto1_decrypt(s, data, len, false);
|
mf_crypto1_decrypt(s, data, len, false);
|
||||||
PrintAndLogEx(SUCCESS, "decrypted data: [%s]", sprint_hex(data, len));
|
PrintAndLogEx(SUCCESS, "decrypted data: [%s]", sprint_hex(data, len));
|
||||||
crypto1_destroy(s);
|
crypto1_destroy(s);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Detect Tag Prng,
|
/* Detect Tag Prng,
|
||||||
|
@ -873,31 +858,28 @@ int detect_classic_prng(void) {
|
||||||
uint8_t cmd[] = {MIFARE_AUTH_KEYA, 0x00};
|
uint8_t cmd[] = {MIFARE_AUTH_KEYA, 0x00};
|
||||||
uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS;
|
uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS;
|
||||||
|
|
||||||
PacketCommandOLD c = {CMD_READER_ISO_14443a, {flags, sizeof(cmd), 0}, {{0}}};
|
|
||||||
memcpy(c.d.asBytes, cmd, sizeof(cmd));
|
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommandOLD(CMD_READER_ISO_14443a, flags, sizeof(cmd), 0, cmd, sizeof(cmd));
|
||||||
|
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
PrintAndLogEx(WARNING, "PRNG UID: Reply timeout.");
|
PrintAndLogEx(WARNING, "PRNG UID: Reply timeout.");
|
||||||
return -1;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if select tag failed.
|
// if select tag failed.
|
||||||
if (resp.oldarg[0] == 0) {
|
if (resp.oldarg[0] == 0) {
|
||||||
PrintAndLogEx(WARNING, "error: selecting tag failed, can't detect prng\n");
|
PrintAndLogEx(WARNING, "error: selecting tag failed, can't detect prng\n");
|
||||||
return -2;
|
return PM3_ERFTRANS;
|
||||||
}
|
}
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &respA, 2500)) {
|
if (!WaitForResponseTimeout(CMD_ACK, &respA, 2500)) {
|
||||||
PrintAndLogEx(WARNING, "PRNG data: Reply timeout.");
|
PrintAndLogEx(WARNING, "PRNG data: Reply timeout.");
|
||||||
return -3;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check respA
|
// check respA
|
||||||
if (respA.oldarg[0] != 4) {
|
if (respA.oldarg[0] != 4) {
|
||||||
PrintAndLogEx(WARNING, "PRNG data error: Wrong length: %d", respA.oldarg[0]);
|
PrintAndLogEx(WARNING, "PRNG data error: Wrong length: %d", respA.oldarg[0]);
|
||||||
return -4;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t nonce = bytes_to_num(respA.data.asBytes, respA.oldarg[0]);
|
uint32_t nonce = bytes_to_num(respA.data.asBytes, respA.oldarg[0]);
|
||||||
|
@ -913,9 +895,8 @@ returns:
|
||||||
*/
|
*/
|
||||||
int detect_classic_nackbug(bool verbose) {
|
int detect_classic_nackbug(bool verbose) {
|
||||||
|
|
||||||
PacketCommandOLD c = {CMD_MIFARE_NACK_DETECT, {0, 0, 0}, {{0}}};
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommandOLD(CMD_MIFARE_NACK_DETECT, 0, 0, 0, NULL, 0);
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
|
@ -945,7 +926,7 @@ int detect_classic_nackbug(bool verbose) {
|
||||||
if (ukbhit()) {
|
if (ukbhit()) {
|
||||||
int gc = getchar();
|
int gc = getchar();
|
||||||
(void)gc;
|
(void)gc;
|
||||||
return -1;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 500)) {
|
||||||
|
@ -961,47 +942,46 @@ int detect_classic_nackbug(bool verbose) {
|
||||||
switch (ok) {
|
switch (ok) {
|
||||||
case 99 :
|
case 99 :
|
||||||
PrintAndLogEx(WARNING, "button pressed. Aborted.");
|
PrintAndLogEx(WARNING, "button pressed. Aborted.");
|
||||||
return 0;
|
return PM3_EOPABORTED;
|
||||||
case 96 :
|
case 96 :
|
||||||
case 98 : {
|
case 98 : {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(FAILED, "card random number generator is not predictable.");
|
PrintAndLogEx(FAILED, "card random number generator is not predictable.");
|
||||||
PrintAndLogEx(WARNING, "detection failed");
|
PrintAndLogEx(WARNING, "detection failed");
|
||||||
return 2;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
case 97 : {
|
case 97 : {
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(FAILED, "card random number generator seems to be based on the well-known generating polynomial");
|
PrintAndLogEx(FAILED, "card random number generator seems to be based on the well-known generating polynomial");
|
||||||
PrintAndLogEx(NORMAL, "[- ]with 16 effective bits only, but shows unexpected behavior, try again.");
|
PrintAndLogEx(NORMAL, "[- ]with 16 effective bits only, but shows unexpected behavior, try again.");
|
||||||
}
|
}
|
||||||
return 2;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
case 2 :
|
case 2 :
|
||||||
PrintAndLogEx(SUCCESS, _GREEN_("always leak NACK detected"));
|
PrintAndLogEx(SUCCESS, _GREEN_("always leak NACK detected"));
|
||||||
return 3;
|
return PM3_SUCCESS;
|
||||||
case 1 :
|
case 1 :
|
||||||
PrintAndLogEx(SUCCESS, _GREEN_("NACK bug detected"));
|
PrintAndLogEx(SUCCESS, _GREEN_("NACK bug detected"));
|
||||||
return 1;
|
return PM3_SUCCESS;
|
||||||
case 0 :
|
case 0 :
|
||||||
PrintAndLogEx(SUCCESS, "No NACK bug detected");
|
PrintAndLogEx(SUCCESS, "No NACK bug detected");
|
||||||
return 2;
|
return PM3_SUCCESS;
|
||||||
default :
|
default :
|
||||||
PrintAndLogEx(WARNING, "errorcode from device [%i]", ok);
|
PrintAndLogEx(WARNING, "errorcode from device [%i]", ok);
|
||||||
return 0;
|
return PM3_EUNDEF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
/* try to see if card responses to "chinese magic backdoor" commands. */
|
/* try to see if card responses to "chinese magic backdoor" commands. */
|
||||||
void detect_classic_magic(void) {
|
void detect_classic_magic(void) {
|
||||||
|
|
||||||
uint8_t isGeneration = 0;
|
uint8_t isGeneration = 0;
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
PacketCommandOLD c = {CMD_MIFARE_CIDENT, {0, 0, 0}, {{0}}};
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommandOLD(CMD_MIFARE_CIDENT, 0, 0, 0, NULL, 0);
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500))
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500))
|
||||||
isGeneration = resp.oldarg[0] & 0xff;
|
isGeneration = resp.oldarg[0] & 0xff;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue