mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-22 14:13:42 -07:00
hf mf chk multisector works
This commit is contained in:
parent
93dc631353
commit
c0de54da0f
5 changed files with 102 additions and 61 deletions
|
@ -982,10 +982,10 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
TKeyIndex keyIndex = {0};
|
||||
uint8_t sectorCnt = blockNo;
|
||||
int res = MifareMultisectorChk(datain, keyCount, sectorCnt, keyType, OLD_MF_DBGLEVEL, &keyIndex);
|
||||
Dbprintf("[0][0]=%d [0][13]=%d [0][15]=%d ", keyIndex[0][0], keyIndex[0][13], keyIndex[0][15]);
|
||||
Dbprintf("[0][0]=%d [0][13]=%d [0][15]=%d [1][15]=%d ", keyIndex[0][0], keyIndex[0][13], keyIndex[0][15], keyIndex[1][15]);
|
||||
|
||||
LED_B_ON();
|
||||
if (res > 0) {
|
||||
if (res >= 0) {
|
||||
cmd_send(CMD_ACK, 1, 0, 0, keyIndex, 80);
|
||||
} else {
|
||||
cmd_send(CMD_ACK, 0, 0, 0, NULL, 0);
|
||||
|
|
|
@ -854,24 +854,23 @@ int MifareChkBlockKeys(uint8_t *keys, uint8_t keyCount, uint8_t blockNo, uint8_t
|
|||
int MifareMultisectorChk(uint8_t *keys, uint8_t keyCount, uint8_t SectorCount, uint8_t keyType, uint8_t debugLevel, TKeyIndex *keyIndex) {
|
||||
int res = 0;
|
||||
|
||||
// 3.2 ms/auth
|
||||
int clk = GetCountSspClk();
|
||||
|
||||
for(int sc = 0; sc < SectorCount; sc++){
|
||||
for(int key = keyType & 0x01; key < 2; keyType==2?(key++):(key = 2)) {
|
||||
int keyAB = keyType;
|
||||
do {
|
||||
WDT_HIT();
|
||||
res = MifareChkBlockKeys(keys, keyCount, FirstBlockOfSector(sc), key, debugLevel);
|
||||
if (res < 0) {
|
||||
res = MifareChkBlockKeys(keys, keyCount, FirstBlockOfSector(sc), keyAB & 0x01, debugLevel);
|
||||
if (res < 0){
|
||||
return res;
|
||||
}
|
||||
if (res > 0){
|
||||
(*keyIndex)[key][sc] = res;
|
||||
break;
|
||||
(*keyIndex)[keyAB & 0x01][sc] = res;
|
||||
}
|
||||
}
|
||||
} while(--keyAB > 0);
|
||||
}
|
||||
|
||||
Dbprintf("%d %d", GetCountSspClk() - clk, (GetCountSspClk() - clk)/(SectorCount*keyCount*2));
|
||||
Dbprintf("%d %d", GetCountSspClk() - clk, (GetCountSspClk() - clk)/(SectorCount*keyCount*(keyType==2?2:1)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
103
client/cmdhfmf.c
103
client/cmdhfmf.c
|
@ -524,13 +524,6 @@ int CmdHF14AMfRestore(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint64_t Key[2];
|
||||
int foundKey[2];
|
||||
} sector_t;
|
||||
|
||||
|
||||
# define NESTED_KEY_COUNT 15
|
||||
int CmdHF14AMfNested(const char *Cmd)
|
||||
{
|
||||
|
@ -1037,6 +1030,8 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
|
||||
int transferToEml = 0;
|
||||
int createDumpFile = 0;
|
||||
|
||||
sector_t *e_sector = NULL;
|
||||
|
||||
keyBlock = calloc(stKeyBlock, 6);
|
||||
if (keyBlock == NULL) return 1;
|
||||
|
@ -1055,10 +1050,10 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
ctmp = param_getchar(Cmd, 1);
|
||||
switch (ctmp) {
|
||||
case 'a': case 'A':
|
||||
keyType = !0;
|
||||
keyType = 0;
|
||||
break;
|
||||
case 'b': case 'B':
|
||||
keyType = !1;
|
||||
keyType = 1;
|
||||
break;
|
||||
case '?':
|
||||
keyType = 2;
|
||||
|
@ -1069,6 +1064,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
return 1;
|
||||
};
|
||||
|
||||
// transfer to emulator & create dump file
|
||||
ctmp = param_getchar(Cmd, 2);
|
||||
if (ctmp == 't' || ctmp == 'T') transferToEml = 1;
|
||||
else if (ctmp == 'd' || ctmp == 'D') createDumpFile = 1;
|
||||
|
@ -1138,6 +1134,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
}
|
||||
}
|
||||
|
||||
// fill with default keys
|
||||
if (keycnt == 0) {
|
||||
PrintAndLog("No key specified, trying default keys");
|
||||
for (;keycnt < defaultKeysSize; keycnt++)
|
||||
|
@ -1147,54 +1144,59 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
}
|
||||
|
||||
// initialize storage for found keys
|
||||
bool validKey[2][40];
|
||||
uint8_t foundKey[2][40][6];
|
||||
for (uint16_t t = 0; t < 2; t++) {
|
||||
e_sector = calloc(SectorsCnt, sizeof(sector_t));
|
||||
if (e_sector == NULL) return 1;
|
||||
for (uint16_t keyAB = 0; keyAB < 2; keyAB++) {
|
||||
for (uint16_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) {
|
||||
validKey[t][sectorNo] = false;
|
||||
for (uint16_t i = 0; i < 6; i++) {
|
||||
foundKey[t][sectorNo][i] = 0xff;
|
||||
}
|
||||
e_sector[sectorNo].foundKey[keyAB] = false;
|
||||
e_sector[sectorNo].Key[keyAB] = 0xffffffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
bool foundAKey = false;
|
||||
printf("--");
|
||||
for ( int t = !keyType; t < 2; keyType==2?(t++):(t=2) ) {
|
||||
for (int i = 0; (i < SectorsCnt) || (SectorsCnt == 0); ++i) {
|
||||
// PrintAndLog("--sector:%2d, block:%3d, key type:%C, key count:%2d ", i, FirstBlockOfSector(i), t?'B':'A', keycnt);
|
||||
uint32_t max_keys = keycnt>USB_CMD_DATA_SIZE/6?USB_CMD_DATA_SIZE/6:keycnt;
|
||||
uint32_t max_keys = keycnt > USB_CMD_DATA_SIZE / 6 ? USB_CMD_DATA_SIZE / 6 : keycnt;
|
||||
if (SectorsCnt) {
|
||||
printf("--");
|
||||
for (uint32_t c = 0; c < keycnt; c += max_keys) {
|
||||
|
||||
for (uint32_t c = 0; c < keycnt; c+=max_keys) {
|
||||
uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c;
|
||||
res = mfCheckKeysSec(SectorsCnt, keyType, true, size, &keyBlock[6 * c], e_sector);
|
||||
|
||||
uint32_t size = keycnt-c>max_keys?max_keys:keycnt-c;
|
||||
res = mfCheckKeys(SectorsCnt == 0?blockNo:FirstBlockOfSector(i), t, true, size, &keyBlock[6*c], &key64);
|
||||
|
||||
if (res != 1) {
|
||||
if (!res) {
|
||||
// PrintAndLog("Found valid key:[%012" PRIx64 "]",key64);
|
||||
printf("o");
|
||||
num_to_bytes(key64, 6, foundKey[t][i]);
|
||||
validKey[t][i] = true;
|
||||
foundAKey = true;
|
||||
} else {
|
||||
printf(".");
|
||||
}
|
||||
if (res != 1) {
|
||||
if (!res) {
|
||||
printf("o");
|
||||
foundAKey = true;
|
||||
} else {
|
||||
printf("\n");
|
||||
PrintAndLog("Command execute timeout");
|
||||
printf(".");
|
||||
}
|
||||
} else {
|
||||
printf("\n");
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint32_t c = 0; c < keycnt; c+=max_keys) {
|
||||
|
||||
uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c;
|
||||
res = mfCheckKeys(blockNo, keyType, true, size, &keyBlock[6*c], &key64); // t=keyType
|
||||
|
||||
if (res != 1) {
|
||||
if (!res) {
|
||||
PrintAndLog("Found valid key:[%012" PRIx64 "]",key64);
|
||||
e_sector[blockNo / 4].Key[0] = key64; // t!!!!!!!!!!!
|
||||
e_sector[blockNo / 4].foundKey[0] = true;
|
||||
foundAKey = true;
|
||||
}
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
if (SectorsCnt == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
|
||||
// print result
|
||||
if (foundAKey) {
|
||||
if (SectorsCnt == 0) {
|
||||
PrintAndLog("block=%d key=%012"PRIx64, blockNo, bytes_to_num(foundKey[keyType - 1][0], 6), validKey[keyType][0]?1:0);
|
||||
PrintAndLog("block=%d key=%012"PRIx64" type=", blockNo, e_sector[blockNo / 4].Key[keyType], e_sector[blockNo / 4].foundKey[keyType]?'B':'A'); //!!!!!!!!!!!!!!
|
||||
} else {
|
||||
PrintAndLog("");
|
||||
PrintAndLog("|---|----------------|---|----------------|---|");
|
||||
|
@ -1202,7 +1204,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
PrintAndLog("|---|----------------|---|----------------|---|");
|
||||
for (i = 0; i < SectorsCnt; i++) {
|
||||
PrintAndLog("|%03d| %012" PRIx64 " | %d | %012" PRIx64 " | %d |", i,
|
||||
bytes_to_num(foundKey[0][i], 6), validKey[0][i]?1:0, bytes_to_num(foundKey[1][i], 6), validKey[1][i]?1:0);
|
||||
e_sector[i].Key[0], e_sector[i].foundKey[0]?1:0, e_sector[i].Key[1], e_sector[i].foundKey[1]?1:0);
|
||||
}
|
||||
PrintAndLog("|---|----------------|---|----------------|---|");
|
||||
}
|
||||
|
@ -1211,14 +1213,15 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
PrintAndLog("No valid keys found.");
|
||||
}
|
||||
|
||||
|
||||
if (transferToEml) {
|
||||
uint8_t block[16];
|
||||
for (uint16_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) {
|
||||
if (validKey[0][sectorNo] || validKey[1][sectorNo]) {
|
||||
if (e_sector[sectorNo].foundKey[0] || e_sector[sectorNo].foundKey[1]) {
|
||||
mfEmlGetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
|
||||
for (uint16_t t = 0; t < 2; t++) {
|
||||
if (validKey[t][sectorNo]) {
|
||||
memcpy(block + t*10, foundKey[t][sectorNo], 6);
|
||||
if (e_sector[sectorNo].foundKey[t]) {
|
||||
num_to_bytes(e_sector[sectorNo].Key[t], 6, block + t * 10);
|
||||
}
|
||||
}
|
||||
mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
|
||||
|
@ -1234,8 +1237,12 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
free(keyBlock);
|
||||
return 1;
|
||||
}
|
||||
for (uint16_t t = 0; t < 2; t++) {
|
||||
fwrite(foundKey[t], 1, 6*SectorsCnt, fkeys);
|
||||
uint8_t mkey[6];
|
||||
for (uint8_t t = 0; t < 2; t++) {
|
||||
for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) {
|
||||
num_to_bytes(e_sector[sectorNo].Key[t], 6, mkey);
|
||||
fwrite(mkey, 1, 6, fkeys);
|
||||
}
|
||||
}
|
||||
fclose(fkeys);
|
||||
PrintAndLog("Found keys have been dumped to file dumpkeys.bin. 0xffffffffffff has been inserted for unknown keys.");
|
||||
|
|
|
@ -228,17 +228,46 @@ int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t key
|
|||
|
||||
*key = -1;
|
||||
|
||||
UsbCommand c = {CMD_MIFARE_CHKKEYS, {((blockNo & 0xff) | ((keyType&0xff)<<8)), clear_trace, keycnt}};
|
||||
UsbCommand c = {CMD_MIFARE_CHKKEYS, {((blockNo & 0xff) | ((keyType & 0xff) << 8)), clear_trace, keycnt}};
|
||||
memcpy(c.d.asBytes, keyBlock, 6 * keycnt);
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) return 1;
|
||||
if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) return 1;
|
||||
if ((resp.arg[0] & 0xff) != 0x01) return 2;
|
||||
*key = bytes_to_num(resp.d.asBytes, 6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mfCheckKeysSec(uint8_t sectorCnt, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, sector_t * e_sector){
|
||||
|
||||
uint8_t keyPtr = 0;
|
||||
|
||||
if (e_sector == NULL)
|
||||
return -1;
|
||||
|
||||
UsbCommand c = {CMD_MIFARE_CHKKEYS, {((sectorCnt & 0xff) | ((keyType & 0xff) << 8)), clear_trace | 0x02, keycnt}};
|
||||
memcpy(c.d.asBytes, keyBlock, 6 * keycnt);
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, MAX(3000, 1000 + 13 * sectorCnt * keycnt * (keyType == 2 ? 2 : 1)))) return 1; // timeout: 13 ms / fail auth
|
||||
if ((resp.arg[0] & 0xff) != 0x01) return 2;
|
||||
|
||||
bool foundAKey = false;
|
||||
for(int sec = 0; sec < sectorCnt; sec++){
|
||||
for(int keyAB = 0; keyAB < 2; keyAB++){
|
||||
keyPtr = *(resp.d.asBytes + keyAB * 40 + sec);
|
||||
if (keyPtr){
|
||||
e_sector[sec].foundKey[keyAB] = true;
|
||||
e_sector[sec].Key[keyAB] = bytes_to_num(keyBlock + (keyPtr - 1) * 6, 6);
|
||||
foundAKey = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return foundAKey ? 0 : 3;
|
||||
}
|
||||
|
||||
// Compare 16 Bits out of cryptostate
|
||||
int Compare16Bits(const void * a, const void * b) {
|
||||
if ((*(uint64_t*)b & 0x00ff000000ff0000) == (*(uint64_t*)a & 0x00ff000000ff0000)) return 0;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Merlok, 2011
|
||||
// Merlok, 2011, 2017
|
||||
// people from mifare@nethemba.com, 2010
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
|
@ -24,11 +24,17 @@
|
|||
#define CSETBLOCK_SINGLE_OPER 0x1F
|
||||
#define CSETBLOCK_MAGIC_1B 0x40
|
||||
|
||||
typedef struct {
|
||||
uint64_t Key[2];
|
||||
int foundKey[2];
|
||||
} sector_t;
|
||||
|
||||
extern char logHexFileName[FILE_PATH_SIZE];
|
||||
|
||||
extern int mfDarkside(uint64_t *key);
|
||||
extern int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *ResultKeys, bool calibrate);
|
||||
extern int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key);
|
||||
extern int mfCheckKeysSec(uint8_t sectorCnt, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, sector_t * e_sector);
|
||||
|
||||
extern int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);
|
||||
extern int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue