mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 13:00:42 -07:00
hf mf rdbl - uses NG
This commit is contained in:
parent
ffc24d672b
commit
cee2fc7a34
9 changed files with 178 additions and 129 deletions
|
@ -1054,9 +1054,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
case CMD_READER_MIFARE:
|
case CMD_READER_MIFARE:
|
||||||
ReaderMifare(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]);
|
ReaderMifare(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]);
|
||||||
break;
|
break;
|
||||||
case CMD_MIFARE_READBL:
|
case CMD_MIFARE_READBL: {
|
||||||
MifareReadBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
mf_readblock_t *payload = (mf_readblock_t *)packet->data.asBytes;
|
||||||
|
MifareReadBlock(payload->blockno, payload->keytype, payload->key);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CMD_MIFAREU_READBL:
|
case CMD_MIFAREU_READBL:
|
||||||
MifareUReadBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
MifareUReadBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -146,7 +146,8 @@ void EPA_PACE_Collect_Nonce(PacketCommandNG *c);
|
||||||
void EPA_PACE_Replay(PacketCommandNG *c);
|
void EPA_PACE_Replay(PacketCommandNG *c);
|
||||||
|
|
||||||
// mifarecmd.h
|
// mifarecmd.h
|
||||||
void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain);
|
||||||
|
|
||||||
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||||
void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes);
|
void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes);
|
||||||
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
||||||
|
|
|
@ -38,18 +38,16 @@ static uint8_t dummy_answer = 0;
|
||||||
// Select, Authenticate, Read a MIFARE tag.
|
// Select, Authenticate, Read a MIFARE tag.
|
||||||
// read block
|
// read block
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain) {
|
||||||
// params
|
// params
|
||||||
uint8_t blockNo = arg0;
|
|
||||||
uint8_t keyType = arg1;
|
|
||||||
uint64_t ui64Key = 0;
|
uint64_t ui64Key = 0;
|
||||||
ui64Key = bytes_to_num(datain, 6);
|
ui64Key = bytes_to_num(datain, 6);
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
uint8_t isOK = 0;
|
|
||||||
uint8_t dataoutbuf[16] = {0x00};
|
uint8_t dataoutbuf[16] = {0x00};
|
||||||
uint8_t uid[10] = {0x00};
|
uint8_t uid[10] = {0x00};
|
||||||
uint32_t cuid = 0;
|
uint32_t cuid = 0, status = PM3_EOPABORTED;
|
||||||
|
|
||||||
struct Crypto1State mpcs = {0, 0};
|
struct Crypto1State mpcs = {0, 0};
|
||||||
struct Crypto1State *pcs;
|
struct Crypto1State *pcs;
|
||||||
pcs = &mpcs;
|
pcs = &mpcs;
|
||||||
|
@ -84,7 +82,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
isOK = 1;
|
status = PM3_SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +91,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
|
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
reply_old(CMD_ACK, isOK, 0, 0, dataoutbuf, 16);
|
reply_ng(CMD_MIFARE_READBL, status, dataoutbuf, 16);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
@ -129,7 +127,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes) {
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
reply_old(CMD_ACK, 1, 0, 0, 0, 0);
|
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arg0 = BlockNo,
|
// Arg0 = BlockNo,
|
||||||
|
@ -189,7 +187,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
reply_old(CMD_ACK, 1, 0, 0, dataout, 16);
|
reply_mix(CMD_ACK, 1, 0, 0, dataout, 16);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
@ -352,7 +350,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
|
||||||
|
|
||||||
countblocks *= 4;
|
countblocks *= 4;
|
||||||
|
|
||||||
reply_old(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0);
|
reply_mix(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
|
@ -419,7 +417,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||||
|
|
||||||
reply_old(CMD_ACK, isOK, 0, 0, 0, 0);
|
reply_mix(CMD_ACK, isOK, 0, 0, 0, 0);
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
|
@ -461,7 +459,7 @@ void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||||
|
|
||||||
reply_old(CMD_ACK,1,0,0,0,0);
|
reply_mix(CMD_ACK,1,0,0,0,0);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
@ -530,7 +528,7 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||||
|
|
||||||
reply_old(CMD_ACK, 1, 0, 0, 0, 0);
|
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
|
@ -603,7 +601,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain) {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
reply_old(CMD_ACK, 1, 0, 0, 0, 0);
|
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
|
@ -1054,7 +1052,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain)
|
||||||
memcpy(buf + 16, &target_ks[1], 4);
|
memcpy(buf + 16, &target_ks[1], 4);
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
reply_old(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));
|
reply_mix(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");
|
if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");
|
||||||
|
@ -1512,7 +1510,7 @@ OUT:
|
||||||
BigBuf_Clear_ext(false);
|
BigBuf_Clear_ext(false);
|
||||||
} else {
|
} else {
|
||||||
// partial/none keys found
|
// partial/none keys found
|
||||||
reply_old(CMD_ACK, foundkeys, 0, 0, 0, 0);
|
reply_mix(CMD_ACK, foundkeys, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1862,7 +1860,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
|
||||||
} // end while
|
} // end while
|
||||||
|
|
||||||
if (isOK)
|
if (isOK)
|
||||||
reply_old(CMD_ACK, 1, 0, 0, uid, sizeof(uid));
|
reply_mix(CMD_ACK, 1, 0, 0, uid, sizeof(uid));
|
||||||
else
|
else
|
||||||
OnErrorMagic(errormsg);
|
OnErrorMagic(errormsg);
|
||||||
|
|
||||||
|
@ -2102,7 +2100,7 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");
|
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");
|
||||||
reply_old(CMD_ACK, 1, cuid, 0, dataout, sizeof(dataout));
|
reply_mix(CMD_ACK, 1, cuid, 0, dataout, sizeof(dataout));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) {
|
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) {
|
||||||
|
|
184
client/cmdhfmf.c
184
client/cmdhfmf.c
|
@ -549,14 +549,14 @@ static int CmdHF14AMfRdBl(const char *Cmd) {
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)>");
|
PrintAndLogEx(NORMAL, "Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)>");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " hf mf rdbl 0 A FFFFFFFFFFFF ");
|
PrintAndLogEx(NORMAL, " hf mf rdbl 0 A FFFFFFFFFFFF ");
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
blockNo = param_get8(Cmd, 0);
|
blockNo = param_get8(Cmd, 0);
|
||||||
cmdp = tolower(param_getchar(Cmd, 1));
|
cmdp = tolower(param_getchar(Cmd, 1));
|
||||||
if (cmdp == 0x00) {
|
if (cmdp == 0x00) {
|
||||||
PrintAndLogEx(NORMAL, "Key type must be A or B");
|
PrintAndLogEx(NORMAL, "Key type must be A or B");
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmdp != 'a')
|
if (cmdp != 'a')
|
||||||
|
@ -564,23 +564,27 @@ static int CmdHF14AMfRdBl(const char *Cmd) {
|
||||||
|
|
||||||
if (param_gethex(Cmd, 2, key, 12)) {
|
if (param_gethex(Cmd, 2, key, 12)) {
|
||||||
PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols");
|
PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols");
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "--block no:%d, key type:%c, key:%s ", blockNo, keyType ? 'B' : 'A', sprint_hex(key, 6));
|
PrintAndLogEx(NORMAL, "--block no:%d, key type:%c, key:%s ", blockNo, keyType ? 'B' : 'A', sprint_hex(key, 6));
|
||||||
|
|
||||||
|
mf_readblock_t payload;
|
||||||
|
payload.blockno = blockNo;
|
||||||
|
payload.keytype = keyType;
|
||||||
|
memcpy(payload.key, key, sizeof(payload.key));
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandOLD(CMD_MIFARE_READBL, blockNo, keyType, 0, key, 6);
|
SendCommandNG(CMD_MIFARE_READBL, (uint8_t*)&payload, sizeof(mf_readblock_t));
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
if (WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500)) {
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
|
||||||
uint8_t *data = resp.data.asBytes;
|
uint8_t *data = resp.data.asBytes;
|
||||||
|
|
||||||
if (isOK) {
|
if (resp.status == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(NORMAL, "isOk:%02x data:%s", isOK, sprint_hex(data, 16));
|
PrintAndLogEx(NORMAL, "data: %s", sprint_hex(data, 16));
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(NORMAL, "isOk:%02x", isOK);
|
PrintAndLogEx(FAILED, "failed reading block");
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mfIsSectorTrailer(blockNo) && (data[6] || data[7] || data[8])) {
|
if (mfIsSectorTrailer(blockNo) && (data[6] || data[7] || data[8])) {
|
||||||
|
@ -595,7 +599,7 @@ static int CmdHF14AMfRdBl(const char *Cmd) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "Command execute timeout");
|
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||||
return 2;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -612,19 +616,19 @@ static int CmdHF14AMfRdSc(const char *Cmd) {
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf mf rdsc <sector number> <key A/B> <key (12 hex symbols)>");
|
PrintAndLogEx(NORMAL, "Usage: hf mf rdsc <sector number> <key A/B> <key (12 hex symbols)>");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " hf mf rdsc 0 A FFFFFFFFFFFF ");
|
PrintAndLogEx(NORMAL, " hf mf rdsc 0 A FFFFFFFFFFFF ");
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
sectorNo = param_get8(Cmd, 0);
|
sectorNo = param_get8(Cmd, 0);
|
||||||
if (sectorNo > MIFARE_4K_MAXSECTOR) {
|
if (sectorNo > MIFARE_4K_MAXSECTOR) {
|
||||||
PrintAndLogEx(NORMAL, "Sector number must be less than 40");
|
PrintAndLogEx(NORMAL, "Sector number must be less than 40");
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdp = tolower(param_getchar(Cmd, 1));
|
cmdp = tolower(param_getchar(Cmd, 1));
|
||||||
if (cmdp != 'a' && cmdp != 'b') {
|
if (cmdp != 'a' && cmdp != 'b') {
|
||||||
PrintAndLogEx(NORMAL, "Key type must be A or B");
|
PrintAndLogEx(NORMAL, "Key type must be A or B");
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmdp != 'a')
|
if (cmdp != 'a')
|
||||||
|
@ -632,7 +636,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) {
|
||||||
|
|
||||||
if (param_gethex(Cmd, 2, key, 12)) {
|
if (param_gethex(Cmd, 2, key, 12)) {
|
||||||
PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols");
|
PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols");
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "--sector no:%d key type:%c key:%s ", sectorNo, keyType ? 'B' : 'A', sprint_hex(key, 6));
|
PrintAndLogEx(NORMAL, "--sector no:%d key type:%c key:%s ", sectorNo, keyType ? 'B' : 'A', sprint_hex(key, 6));
|
||||||
|
|
||||||
|
@ -665,7 +669,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) {
|
||||||
PrintAndLogEx(WARNING, "Command execute timeout");
|
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t NumOfBlocks(char card) {
|
static uint16_t NumOfBlocks(char card) {
|
||||||
|
@ -761,14 +765,14 @@ static int CmdHF14AMfDump(const char *Cmd) {
|
||||||
if (keyFilename[0] == 0x00) {
|
if (keyFilename[0] == 0x00) {
|
||||||
fptr = GenerateFilename("hf-mf-", "-key.bin");
|
fptr = GenerateFilename("hf-mf-", "-key.bin");
|
||||||
if (fptr == NULL)
|
if (fptr == NULL)
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
|
|
||||||
strcpy(keyFilename, fptr);
|
strcpy(keyFilename, fptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((f = fopen(keyFilename, "rb")) == NULL) {
|
if ((f = fopen(keyFilename, "rb")) == NULL) {
|
||||||
PrintAndLogEx(WARNING, "Could not find file " _YELLOW_("%s"), keyFilename);
|
PrintAndLogEx(WARNING, "Could not find file " _YELLOW_("%s"), keyFilename);
|
||||||
return 1;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read keys A from file
|
// Read keys A from file
|
||||||
|
@ -778,7 +782,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
|
||||||
if (bytes_read != 6) {
|
if (bytes_read != 6) {
|
||||||
PrintAndLogEx(WARNING, "File reading error.");
|
PrintAndLogEx(WARNING, "File reading error.");
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 2;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -788,7 +792,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
|
||||||
if (bytes_read != 6) {
|
if (bytes_read != 6) {
|
||||||
PrintAndLogEx(WARNING, "File reading error.");
|
PrintAndLogEx(WARNING, "File reading error.");
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 2;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -799,14 +803,21 @@ static int CmdHF14AMfDump(const char *Cmd) {
|
||||||
uint8_t tries;
|
uint8_t tries;
|
||||||
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
|
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
|
||||||
for (tries = 0; tries < MIFARE_SECTOR_RETRY; tries++) {
|
for (tries = 0; tries < MIFARE_SECTOR_RETRY; tries++) {
|
||||||
|
printf(".");
|
||||||
|
fflush(NULL);
|
||||||
|
|
||||||
|
mf_readblock_t payload;
|
||||||
|
payload.blockno = FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1;
|
||||||
|
payload.keytype = 0;
|
||||||
|
memcpy(payload.key, keyA[sectorNo], sizeof(payload.key));
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandOLD(CMD_MIFARE_READBL, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 0, 0, keyA[sectorNo], 6);
|
SendCommandNG(CMD_MIFARE_READBL, (uint8_t*)&payload, sizeof(mf_readblock_t));
|
||||||
|
|
||||||
|
if (WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500)) {
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
|
||||||
uint8_t *data = resp.data.asBytes;
|
uint8_t *data = resp.data.asBytes;
|
||||||
if (isOK) {
|
if (resp.status == PM3_SUCCESS) {
|
||||||
rights[sectorNo][0] = ((data[7] & 0x10) >> 2) | ((data[8] & 0x1) << 1) | ((data[8] & 0x10) >> 4); // C1C2C3 for data area 0
|
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][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][2] = ((data[7] & 0x40) >> 4) | ((data[8] & 0x4) >> 1) | ((data[8] & 0x40) >> 6); // C1C2C3 for data area 2
|
||||||
|
@ -824,43 +835,63 @@ static int CmdHF14AMfDump(const char *Cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
printf("\n");
|
||||||
PrintAndLogEx(SUCCESS, "Finished reading sector access bits");
|
PrintAndLogEx(SUCCESS, "Finished reading sector access bits");
|
||||||
PrintAndLogEx(INFO, "Dumping all blocks from card...");
|
PrintAndLogEx(INFO, "Dumping all blocks from card...");
|
||||||
|
|
||||||
bool isOK = true;
|
mf_readblock_t payload;
|
||||||
for (sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) {
|
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
|
||||||
for (blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
|
for (blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
|
||||||
bool received = false;
|
bool received = false;
|
||||||
|
|
||||||
for (tries = 0; tries < MIFARE_SECTOR_RETRY; tries++) {
|
for (tries = 0; tries < MIFARE_SECTOR_RETRY; 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.
|
||||||
clearCommandBuffer();
|
|
||||||
SendCommandOLD(CMD_MIFARE_READBL, FirstBlockOfSector(sectorNo) + blockNo, 0, 0, keyA[sectorNo], 6);
|
payload.blockno = FirstBlockOfSector(sectorNo) + blockNo;
|
||||||
received = WaitForResponseTimeout(CMD_ACK, &resp, 1500);
|
payload.keytype = 0;
|
||||||
|
memcpy(payload.key, keyA[sectorNo], sizeof(payload.key));
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_MIFARE_READBL, (uint8_t*)&payload, sizeof(mf_readblock_t));
|
||||||
|
received = WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500);
|
||||||
|
printf("A\n");
|
||||||
} 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;
|
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
|
||||||
SendCommandOLD(CMD_MIFARE_READBL, FirstBlockOfSector(sectorNo) + blockNo, 1, 0, keyB[sectorNo], 6);
|
|
||||||
received = WaitForResponseTimeout(CMD_ACK, &resp, 1500);
|
payload.blockno = FirstBlockOfSector(sectorNo) + blockNo;
|
||||||
} else if (rights[sectorNo][data_area] == 0x07) { // no key would work
|
payload.keytype = 1;
|
||||||
isOK = false;
|
memcpy(payload.key, keyB[sectorNo], sizeof(payload.key));
|
||||||
PrintAndLogEx(WARNING, "access rights do not allow reading of sector %2d block %3d", sectorNo, blockNo);
|
|
||||||
tries = MIFARE_SECTOR_RETRY;
|
|
||||||
} else { // key A would work
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandOLD(CMD_MIFARE_READBL, FirstBlockOfSector(sectorNo) + blockNo, 0, 0, keyA[sectorNo], 6);
|
SendCommandNG(CMD_MIFARE_READBL, (uint8_t*)&payload, sizeof(mf_readblock_t));
|
||||||
received = WaitForResponseTimeout(CMD_ACK, &resp, 1500);
|
received = WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500);
|
||||||
|
printf("B\n");
|
||||||
|
} else if (rights[sectorNo][data_area] == 0x07) { // no key would work
|
||||||
|
PrintAndLogEx(WARNING, "access rights do not allow reading of sector %2d block %3d", sectorNo, blockNo);
|
||||||
|
// where do you want to go?? Next sector or block?
|
||||||
|
break;
|
||||||
|
} else { // key A would work
|
||||||
|
|
||||||
|
payload.blockno = FirstBlockOfSector(sectorNo) + blockNo;
|
||||||
|
payload.keytype = 0;
|
||||||
|
memcpy(payload.key, keyA[sectorNo], sizeof(payload.key));
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_MIFARE_READBL, (uint8_t*)&payload, sizeof(mf_readblock_t));
|
||||||
|
received = WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500);
|
||||||
|
printf("C\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (received) {
|
if (received) {
|
||||||
isOK = resp.oldarg[0] & 0xff;
|
if (resp.status == PM3_SUCCESS) {
|
||||||
if (isOK) break;
|
// break the re-try loop
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (received) {
|
if (received) {
|
||||||
isOK = resp.oldarg[0] & 0xff;
|
|
||||||
uint8_t *data = resp.data.asBytes;
|
uint8_t *data = resp.data.asBytes;
|
||||||
if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer. Fill in the keys.
|
if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer. Fill in the keys.
|
||||||
data[0] = (keyA[sectorNo][0]);
|
data[0] = (keyA[sectorNo][0]);
|
||||||
|
@ -876,7 +907,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
|
||||||
data[14] = (keyB[sectorNo][4]);
|
data[14] = (keyB[sectorNo][4]);
|
||||||
data[15] = (keyB[sectorNo][5]);
|
data[15] = (keyB[sectorNo][5]);
|
||||||
}
|
}
|
||||||
if (isOK) {
|
if (resp.status == PM3_SUCCESS) {
|
||||||
memcpy(carddata[FirstBlockOfSector(sectorNo) + blockNo], data, 16);
|
memcpy(carddata[FirstBlockOfSector(sectorNo) + blockNo], data, 16);
|
||||||
PrintAndLogEx(SUCCESS, "successfully read block %2d of sector %2d.", blockNo, sectorNo);
|
PrintAndLogEx(SUCCESS, "successfully read block %2d of sector %2d.", blockNo, sectorNo);
|
||||||
} else {
|
} else {
|
||||||
|
@ -884,19 +915,13 @@ static int CmdHF14AMfDump(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
isOK = false;
|
|
||||||
PrintAndLogEx(WARNING, "command execute timeout when trying to read block %2d of sector %2d.", blockNo, sectorNo);
|
PrintAndLogEx(WARNING, "command execute timeout when trying to read block %2d of sector %2d.", blockNo, sectorNo);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOK == 0) {
|
PrintAndLogEx(SUCCESS, "\nSucceded in dumping all blocks");
|
||||||
PrintAndLogEx(FAILED, "Something went wrong");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "\nSuccedded in dumping all blocks");
|
|
||||||
|
|
||||||
if (strlen(dataFilename) < 1) {
|
if (strlen(dataFilename) < 1) {
|
||||||
fptr = dataFilename;
|
fptr = dataFilename;
|
||||||
|
@ -909,7 +934,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
|
||||||
saveFile(dataFilename, ".bin", (uint8_t *)carddata, bytes);
|
saveFile(dataFilename, ".bin", (uint8_t *)carddata, bytes);
|
||||||
saveFileEML(dataFilename, (uint8_t *)carddata, bytes, MFBLOCK_SIZE);
|
saveFileEML(dataFilename, (uint8_t *)carddata, bytes, MFBLOCK_SIZE);
|
||||||
saveFileJSON(dataFilename, jsfCardMemory, (uint8_t *)carddata, bytes);
|
saveFileJSON(dataFilename, jsfCardMemory, (uint8_t *)carddata, bytes);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHF14AMfRestore(const char *Cmd) {
|
static int CmdHF14AMfRestore(const char *Cmd) {
|
||||||
|
@ -1051,7 +1076,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
|
||||||
}
|
}
|
||||||
fclose(fdump);
|
fclose(fdump);
|
||||||
PrintAndLogEx(INFO, "Finish restore");
|
PrintAndLogEx(INFO, "Finish restore");
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHF14AMfNested(const char *Cmd) {
|
static int CmdHF14AMfNested(const char *Cmd) {
|
||||||
|
@ -1081,7 +1106,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
|
||||||
|
|
||||||
if (ctmp != 'a' && ctmp != 'b') {
|
if (ctmp != 'a' && ctmp != 'b') {
|
||||||
PrintAndLogEx(WARNING, "key type must be A or B");
|
PrintAndLogEx(WARNING, "key type must be A or B");
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctmp != 'a')
|
if (ctmp != 'a')
|
||||||
|
@ -1089,7 +1114,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
|
||||||
|
|
||||||
if (param_gethex(Cmd, 3, key, 12)) {
|
if (param_gethex(Cmd, 3, key, 12)) {
|
||||||
PrintAndLogEx(WARNING, "key must include 12 HEX symbols");
|
PrintAndLogEx(WARNING, "key must include 12 HEX symbols");
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmdp == 'o') {
|
if (cmdp == 'o') {
|
||||||
|
@ -1097,7 +1122,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
|
||||||
ctmp = tolower(param_getchar(Cmd, 5));
|
ctmp = tolower(param_getchar(Cmd, 5));
|
||||||
if (ctmp != 'a' && ctmp != 'b') {
|
if (ctmp != 'a' && ctmp != 'b') {
|
||||||
PrintAndLogEx(WARNING, "target key type must be A or B");
|
PrintAndLogEx(WARNING, "target key type must be A or B");
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
if (ctmp != 'a') {
|
if (ctmp != 'a') {
|
||||||
trgKeyType = 1;
|
trgKeyType = 1;
|
||||||
|
@ -1158,16 +1183,16 @@ static int CmdHF14AMfNested(const char *Cmd) {
|
||||||
mfEmlSetMem(keyBlock, sectortrailer, 1);
|
mfEmlSetMem(keyBlock, sectortrailer, 1);
|
||||||
PrintAndLogEx(SUCCESS, "Key transferred to emulator memory.");
|
PrintAndLogEx(SUCCESS, "Key transferred to emulator memory.");
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
default :
|
default :
|
||||||
PrintAndLogEx(WARNING, "Unknown Error.\n");
|
PrintAndLogEx(WARNING, "Unknown Error.\n");
|
||||||
}
|
}
|
||||||
return 2;
|
return PM3_SUCCESS;
|
||||||
} else { // ------------------------------------ multiple sectors working
|
} else { // ------------------------------------ multiple sectors working
|
||||||
uint64_t t1 = msclock();
|
uint64_t t1 = msclock();
|
||||||
|
|
||||||
e_sector = calloc(SectorsCnt, sizeof(sector_t));
|
e_sector = calloc(SectorsCnt, sizeof(sector_t));
|
||||||
if (e_sector == NULL) return 1;
|
if (e_sector == NULL) return PM3_EMALLOC;
|
||||||
|
|
||||||
//test current key and additional standard keys first
|
//test current key and additional standard keys first
|
||||||
// add parameter key
|
// add parameter key
|
||||||
|
@ -1222,7 +1247,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
|
||||||
PrintAndLogEx(WARNING, "unknown Error.\n");
|
PrintAndLogEx(WARNING, "unknown Error.\n");
|
||||||
}
|
}
|
||||||
free(e_sector);
|
free(e_sector);
|
||||||
return 2;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1241,16 +1266,19 @@ static int CmdHF14AMfNested(const char *Cmd) {
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "reading block %d", sectrail);
|
PrintAndLogEx(SUCCESS, "reading block %d", sectrail);
|
||||||
|
|
||||||
uint8_t txdata[6];
|
mf_readblock_t payload;
|
||||||
num_to_bytes(e_sector[i].Key[0], 6, txdata); // KEY A
|
payload.blockno = sectrail;
|
||||||
|
payload.keytype = 0;
|
||||||
|
|
||||||
|
num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandOLD(CMD_MIFARE_READBL, sectrail, 0, 0, txdata, sizeof(txdata));
|
SendCommandNG(CMD_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t) );
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) continue;
|
if (!WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500)) continue;
|
||||||
|
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
if (resp.status != PM3_SUCCESS) continue;
|
||||||
if (!isOK) continue;
|
|
||||||
|
|
||||||
uint8_t *data = resp.data.asBytes;
|
uint8_t *data = resp.data.asBytes;
|
||||||
key64 = bytes_to_num(data + 10, 6);
|
key64 = bytes_to_num(data + 10, 6);
|
||||||
|
@ -1272,10 +1300,13 @@ static int CmdHF14AMfNested(const char *Cmd) {
|
||||||
conn.block_after_ACK = true;
|
conn.block_after_ACK = true;
|
||||||
for (i = 0; i < SectorsCnt; i++) {
|
for (i = 0; i < SectorsCnt; i++) {
|
||||||
mfEmlGetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
|
mfEmlGetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
|
||||||
|
|
||||||
if (e_sector[i].foundKey[0])
|
if (e_sector[i].foundKey[0])
|
||||||
num_to_bytes(e_sector[i].Key[0], 6, keyBlock);
|
num_to_bytes(e_sector[i].Key[0], 6, keyBlock);
|
||||||
|
|
||||||
if (e_sector[i].foundKey[1])
|
if (e_sector[i].foundKey[1])
|
||||||
num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]);
|
num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]);
|
||||||
|
|
||||||
if (i == SectorsCnt - 1) {
|
if (i == SectorsCnt - 1) {
|
||||||
// Disable fast mode on last packet
|
// Disable fast mode on last packet
|
||||||
conn.block_after_ACK = false;
|
conn.block_after_ACK = false;
|
||||||
|
@ -1290,13 +1321,13 @@ static int CmdHF14AMfNested(const char *Cmd) {
|
||||||
fptr = GenerateFilename("hf-mf-", "-key.bin");
|
fptr = GenerateFilename("hf-mf-", "-key.bin");
|
||||||
if (fptr == NULL) {
|
if (fptr == NULL) {
|
||||||
free(e_sector);
|
free(e_sector);
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fkeys = fopen(fptr, "wb")) == NULL) {
|
if ((fkeys = fopen(fptr, "wb")) == NULL) {
|
||||||
PrintAndLogEx(WARNING, "could not create file " _YELLOW_("%s"), fptr);
|
PrintAndLogEx(WARNING, "could not create file " _YELLOW_("%s"), fptr);
|
||||||
free(e_sector);
|
free(e_sector);
|
||||||
return 1;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "saving keys to binary file " _YELLOW_("%s"), fptr);
|
PrintAndLogEx(SUCCESS, "saving keys to binary file " _YELLOW_("%s"), fptr);
|
||||||
|
@ -1321,7 +1352,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
|
||||||
}
|
}
|
||||||
free(e_sector);
|
free(e_sector);
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHF14AMfNestedHard(const char *Cmd) {
|
static int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
|
@ -1997,16 +2028,19 @@ static int CmdHF14AMfChk(const char *Cmd) {
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Reading block %d", sectrail);
|
PrintAndLogEx(NORMAL, "Reading block %d", sectrail);
|
||||||
|
|
||||||
uint8_t txdata[6];
|
mf_readblock_t payload;
|
||||||
num_to_bytes(e_sector[i].Key[0], 6, txdata); // KEY A
|
payload.blockno = sectrail;
|
||||||
|
payload.keytype = 0;
|
||||||
|
|
||||||
|
num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandOLD(CMD_MIFARE_READBL, sectrail, 0, 0, txdata, sizeof(txdata));
|
SendCommandNG(CMD_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t) );
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) continue;
|
if (!WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500)) continue;
|
||||||
|
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
if (resp.status != PM3_SUCCESS) continue;
|
||||||
if (!isOK) continue;
|
|
||||||
|
|
||||||
uint8_t *data = resp.data.asBytes;
|
uint8_t *data = resp.data.asBytes;
|
||||||
key64 = bytes_to_num(data + 10, 6);
|
key64 = bytes_to_num(data + 10, 6);
|
||||||
|
|
|
@ -90,14 +90,15 @@ static int CmdHF14ADesRb(const char *Cmd) {
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
|
PrintAndLogEx(NORMAL, "--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
|
||||||
|
|
||||||
SendCommandOLD(CMD_MIFARE_READBL, blockNo, keyType, 0, key, 6);
|
|
||||||
|
mf_readblock_t payload = { blockNo, keyType, key };
|
||||||
|
SendCommandNG(CMD_MIFARE_READBL, (uint8_t *)payload, sizeof(mf_readblock_t) );
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
if (WaitForResponseTimeout(CMD_MIFARE_READBL, &resp, 1500)) {
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
|
||||||
uint8_t * data = resp.data.asBytes;
|
uint8_t * data = resp.data.asBytes;
|
||||||
|
|
||||||
if (isOK)
|
if (resp.status == PM3_SUCCESS)
|
||||||
PrintAndLogEx(NORMAL, "isOk:%02x data:%s", isOK, sprint_hex(data, 16));
|
PrintAndLogEx(NORMAL, "isOk:%02x data:%s", isOK, sprint_hex(data, 16));
|
||||||
else
|
else
|
||||||
PrintAndLogEx(NORMAL, "isOk:%02x", isOK);
|
PrintAndLogEx(NORMAL, "isOk:%02x", isOK);
|
||||||
|
|
|
@ -49,6 +49,7 @@ local lsh = bit32.lshift
|
||||||
local rsh = bit32.rshift
|
local rsh = bit32.rshift
|
||||||
|
|
||||||
-- Some globals
|
-- Some globals
|
||||||
|
local PM3_SUCCESS = 0
|
||||||
local FOO = 'AF62D2EC0491968CC52A1A7165F865FE'
|
local FOO = 'AF62D2EC0491968CC52A1A7165F865FE'
|
||||||
local BAR = '286329204469736E65792032303133'
|
local BAR = '286329204469736E65792032303133'
|
||||||
local MIS = '0A14FD0507FF4BCD026BA83F0A3B89A9'
|
local MIS = '0A14FD0507FF4BCD026BA83F0A3B89A9'
|
||||||
|
@ -463,20 +464,19 @@ local function getblockdata(response)
|
||||||
if not response then
|
if not response then
|
||||||
return nil, 'No response from device'
|
return nil, 'No response from device'
|
||||||
end
|
end
|
||||||
|
if response.Status == PM3_SUCCESS then
|
||||||
local count, cmd, arg0 = bin.unpack('LL', response)
|
return response.Data
|
||||||
if arg0 == 1 then
|
|
||||||
local count, arg1, arg2, data = bin.unpack('LLH511', response, count)
|
|
||||||
return data:sub(1, 32)
|
|
||||||
else
|
else
|
||||||
return nil, "Couldn't read block.. ["..arg0.."]"
|
return nil, "Couldn't read block.. ["..response.Status.."]"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function readblock( blocknum, key )
|
local function readblock( blockno, key )
|
||||||
-- Read block N
|
-- Read block N
|
||||||
local c = Command:newMIX{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, data = key}
|
local keytype = '00'
|
||||||
local b, err = getblockdata(c:sendMIX())
|
local data = ('%02x%s%s'):format(blockno, keytype, key)
|
||||||
|
local c = Command:newNG{cmd = cmds.CMD_MIFARE_READBL, data = data}
|
||||||
|
local b, err = getblockdata(c:sendNG(false))
|
||||||
if not b then return oops(err) end
|
if not b then return oops(err) end
|
||||||
return b
|
return b
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,6 +40,9 @@ Arguments:
|
||||||
023c - Special
|
023c - Special
|
||||||
0020 - Swapforce
|
0020 - Swapforce
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
local PM3_SUCCESS = 0
|
||||||
|
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
|
@ -63,20 +66,19 @@ local function getblockdata(response)
|
||||||
if not response then
|
if not response then
|
||||||
return nil, 'No response from device'
|
return nil, 'No response from device'
|
||||||
end
|
end
|
||||||
|
if response.Status == PM3_SUCCESS then
|
||||||
local count, cmd, arg0 = bin.unpack('LL', response)
|
return response.Data
|
||||||
if arg0 == 1 then
|
|
||||||
local count, arg1, arg2, data = bin.unpack('LLH511', response, count)
|
|
||||||
return data:sub(1, 32)
|
|
||||||
else
|
else
|
||||||
return nil, "Couldn't read block.. ["..arg0.."]"
|
return nil, "Couldn't read block.. ["..response.Status.."]"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function readblock( blocknum, keyA )
|
local function readblock( blocknum, keyA )
|
||||||
-- Read block N
|
-- Read block N
|
||||||
local c = Command:newMIX{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, data = keyA}
|
local keytype = '00'
|
||||||
local b, err = getblockdata(c:sendMIX())
|
local data = ('%02x%s%s'):format(blocknum, keytype, keyA)
|
||||||
|
local c = Command:newNG{cmd = cmds.CMD_MIFARE_READBL, data = data}
|
||||||
|
local b, err = getblockdata(c:sendNG(false))
|
||||||
if not b then return oops(err) end
|
if not b then return oops(err) end
|
||||||
return b
|
return b
|
||||||
end
|
end
|
||||||
|
|
|
@ -35,6 +35,8 @@ Arguments:
|
||||||
-p : Use the precalc to find all keys
|
-p : Use the precalc to find all keys
|
||||||
-o : filename for the saved dumps
|
-o : filename for the saved dumps
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
local PM3_SUCCESS = 0
|
||||||
local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
|
local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
|
||||||
local DEBUG = false -- the debug flag
|
local DEBUG = false -- the debug flag
|
||||||
local numBlocks = 64
|
local numBlocks = 64
|
||||||
|
@ -91,13 +93,10 @@ local function getblockdata(response)
|
||||||
if not response then
|
if not response then
|
||||||
return nil, 'No response from device'
|
return nil, 'No response from device'
|
||||||
end
|
end
|
||||||
|
if response.Status == PM3_SUCCESS then
|
||||||
local count, cmd, arg0 = bin.unpack('LL', response)
|
return response.Data
|
||||||
if arg0 == 1 then
|
|
||||||
local count, arg1, arg2, data = bin.unpack('LLH511', response, count)
|
|
||||||
return data:sub(1, 32)
|
|
||||||
else
|
else
|
||||||
return nil, "Couldn't read block.. ["..arg0.."]"
|
return nil, "Couldn't read block.. ["..response.Status.."]"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -167,16 +166,21 @@ local function main(args)
|
||||||
local block0, block1
|
local block0, block1
|
||||||
-- Read block 0
|
-- Read block 0
|
||||||
dbg('Reading block 0')
|
dbg('Reading block 0')
|
||||||
cmd = Command:newMIX{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0, data = keyA}
|
local blockno = '00'
|
||||||
block0, err = getblockdata(cmd:sendMIX(false))
|
local keytype = '00'
|
||||||
|
local data = ('%s%s%s'):format(blockno, keytype, keyA)
|
||||||
|
cmd = Command:newNG{cmd = cmds.CMD_MIFARE_READBL, data = data}
|
||||||
|
block0, err = getblockdata(cmd:sendNG(false))
|
||||||
if not block0 then return oops(err) end
|
if not block0 then return oops(err) end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
-- Read block 1
|
-- Read block 1
|
||||||
dbg('Reading block 1')
|
dbg('Reading block 1')
|
||||||
cmd = Command:newMIX{cmd = cmds.CMD_MIFARE_READBL, arg1 = 1, data = keyA}
|
local blockno = '01'
|
||||||
block1, err = getblockdata(cmd:sendMIX(false))
|
data = ('%s%s%s'):format(blockno, keytype, keyA)
|
||||||
|
cmd = Command:newNG{cmd = cmds.CMD_MIFARE_READBL, data = data}
|
||||||
|
block1, err = getblockdata(cmd:sendNG(false))
|
||||||
if not block1 then return oops(err) end
|
if not block1 then return oops(err) end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
@ -203,8 +207,9 @@ local function main(args)
|
||||||
|
|
||||||
pos = (math.floor( blockNo / 4 ) * 12)+1
|
pos = (math.floor( blockNo / 4 ) * 12)+1
|
||||||
key = akeys:sub(pos, pos + 11 )
|
key = akeys:sub(pos, pos + 11 )
|
||||||
cmd = Command:newMIX{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo, data = key}
|
data = ('%02x%s%s'):format(blockNo, keytype, key)
|
||||||
local blockdata, err = getblockdata(cmd:sendMIX(false))
|
cmd = Command:newNG{cmd = cmds.CMD_MIFARE_READBL, data = data}
|
||||||
|
local blockdata, err = getblockdata(cmd:sendNG(false))
|
||||||
if not blockdata then return oops(err) end
|
if not blockdata then return oops(err) end
|
||||||
|
|
||||||
if blockNo%4 ~= 3 then
|
if blockNo%4 ~= 3 then
|
||||||
|
|
|
@ -202,6 +202,12 @@ typedef struct {
|
||||||
uint8_t data[];
|
uint8_t data[];
|
||||||
} PACKED lf_psksim_t;
|
} PACKED lf_psksim_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t blockno;
|
||||||
|
uint8_t keytype;
|
||||||
|
uint8_t key[6];
|
||||||
|
} PACKED mf_readblock_t;
|
||||||
|
|
||||||
|
|
||||||
// For the bootloader
|
// For the bootloader
|
||||||
#define CMD_DEVICE_INFO 0x0000
|
#define CMD_DEVICE_INFO 0x0000
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue