hf mf restore - now takes bin/eml/json as dump files. It also checks for ALL ZERO accessrights in dump and replaces them with default configuration instead to prevent unwanted experiences

This commit is contained in:
iceman1001 2022-02-05 09:18:24 +01:00
commit 08970f51c2
3 changed files with 125 additions and 100 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Fixes `hf mf restore` - now takes bin/eml/json as dump files (@iceman1001)
- Added `trace extract` - extract authentication parts from trace (@iceman1001)
- Added luascript `hf_mf_ultimatecard.lua` - Script for Ultimate Magic Card (GEN4) (@startrk1995)
- Added new tool `brute_key` - MIFARE DESFire Telenot access AES recovery (@x41sec)

View file

@ -204,22 +204,6 @@ static uint8_t NumOfSectors(char card) {
}
}
static uint8_t FirstBlockOfSector(uint8_t sectorNo) {
if (sectorNo < 32) {
return sectorNo * 4;
} else {
return 32 * 4 + (sectorNo - 32) * 16;
}
}
static uint8_t NumBlocksPerSector(uint8_t sectorNo) {
if (sectorNo < 32) {
return 4;
} else {
return 16;
}
}
static uint8_t GetSectorFromBlockNo(uint8_t blockNo) {
if (blockNo < 32 * 4)
return blockNo / 4;
@ -227,8 +211,8 @@ static uint8_t GetSectorFromBlockNo(uint8_t blockNo) {
return 32 + ((blockNo - (32 * 4)) / 16);
}
static char GetFormatFromSector(uint8_t sectorNo) {
switch (sectorNo) {
static char GetFormatFromSector(uint8_t sectors) {
switch (sectors) {
case MIFARE_MINI_MAXSECTOR:
return '0';
case MIFARE_1K_MAXSECTOR:
@ -550,8 +534,8 @@ static int CmdHF14AMfRdSc(const char *Cmd) {
int res = mfReadSector(sector, keytype, key, data);
if (res == PM3_SUCCESS) {
uint8_t blocks = NumBlocksPerSector(sector);
uint8_t start = FirstBlockOfSector(sector);
uint8_t blocks = mfNumBlocksPerSector(sector);
uint8_t start = mfFirstBlockOfSector(sector);
mf_print_sector_hdr(sector);
for (int i = 0; i < blocks; i++) {
@ -747,7 +731,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout);
payload.blockno = FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1;
payload.blockno = mfFirstBlockOfSector(sectorNo) + mfNumBlocksPerSector(sectorNo) - 1;
payload.keytype = MF_KEY_A;
memcpy(payload.key, keyA[sectorNo], sizeof(payload.key));
@ -780,13 +764,13 @@ static int CmdHF14AMfDump(const char *Cmd) {
PrintAndLogEx(INFO, "Dumping all blocks from card...");
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
for (blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
for (blockNo = 0; blockNo < mfNumBlocksPerSector(sectorNo); blockNo++) {
bool received = false;
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 == mfNumBlocksPerSector(sectorNo) - 1) { // sector trailer. At least the Access Conditions can always be read with key A.
payload.blockno = FirstBlockOfSector(sectorNo) + blockNo;
payload.blockno = mfFirstBlockOfSector(sectorNo) + blockNo;
payload.keytype = MF_KEY_A;
memcpy(payload.key, keyA[sectorNo], sizeof(payload.key));
@ -797,7 +781,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
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
payload.blockno = FirstBlockOfSector(sectorNo) + blockNo;
payload.blockno = mfFirstBlockOfSector(sectorNo) + blockNo;
payload.keytype = 1;
memcpy(payload.key, keyB[sectorNo], sizeof(payload.key));
@ -810,7 +794,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
break;
} else { // key A would work
payload.blockno = FirstBlockOfSector(sectorNo) + blockNo;
payload.blockno = mfFirstBlockOfSector(sectorNo) + blockNo;
payload.keytype = MF_KEY_A;
memcpy(payload.key, keyA[sectorNo], sizeof(payload.key));
@ -829,13 +813,14 @@ static int CmdHF14AMfDump(const char *Cmd) {
if (received) {
uint8_t *data = resp.data.asBytes;
if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer. Fill in the keys.
if (blockNo == mfNumBlocksPerSector(sectorNo) - 1) { // sector trailer. Fill in the keys.
data[0] = (keyA[sectorNo][0]);
data[1] = (keyA[sectorNo][1]);
data[2] = (keyA[sectorNo][2]);
data[3] = (keyA[sectorNo][3]);
data[4] = (keyA[sectorNo][4]);
data[5] = (keyA[sectorNo][5]);
data[10] = (keyB[sectorNo][0]);
data[11] = (keyB[sectorNo][1]);
data[12] = (keyB[sectorNo][2]);
@ -844,7 +829,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
data[15] = (keyB[sectorNo][5]);
}
if (resp.status == PM3_SUCCESS) {
memcpy(carddata[FirstBlockOfSector(sectorNo) + blockNo], data, 16);
memcpy(carddata[mfFirstBlockOfSector(sectorNo) + blockNo], data, 16);
PrintAndLogEx(SUCCESS, "successfully read block %2d of sector %2d.", blockNo, sectorNo);
} else {
PrintAndLogEx(FAILED, "could not read block %2d of sector %2d", blockNo, sectorNo);
@ -870,7 +855,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
free(fptr);
}
uint16_t bytes = 16 * (FirstBlockOfSector(numSectors - 1) + NumBlocksPerSector(numSectors - 1));
uint16_t bytes = 16 * (mfFirstBlockOfSector(numSectors - 1) + mfNumBlocksPerSector(numSectors - 1));
saveFile(dataFilename, ".bin", (uint8_t *)carddata, bytes);
saveFileEML(dataFilename, (uint8_t *)carddata, bytes, MFBLOCK_SIZE);
@ -887,10 +872,11 @@ static int CmdHF14AMfRestore(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf restore",
"Restore MIFARE Classic binary file to tag.\n"
"Restore MIFARE Classic dump file to tag.\n"
"\n"
"The key file and data file will program the card sector trailers.\n"
"The key file and dump file will program the card sector trailers.\n"
"By default we authenticate to card with key B 0xFFFFFFFFFFFF.\n"
"If access rights in dump file is all zeros, it will be replaced with default values\n"
"\n"
"`--uid` param is used for filename templates `hf-mf-<uid>-dump.bin` and `hf-mf-<uid>-key.bin.\n"
" If not specified, it will read the card uid instead.\n"
@ -909,7 +895,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
arg_str0("u", "uid", "<hex>", "uid, 6 hex bytes"),
arg_str0("f", "file", "<fn>", "data filename"),
arg_str0("f", "file", "<fn>", "specify dump filename (bin/eml/json)"),
arg_str0("k", "kfn", "<fn>", "key filename"),
arg_lit0(NULL, "ka", "use specified keyfile to authenticate"),
arg_param_end
@ -944,15 +930,6 @@ static int CmdHF14AMfRestore(const char *Cmd) {
m1 = true;
}
if(datafnlen > 4 && !strcmp(datafilename + strlen(datafilename) - 4, ".eml")) {
PrintAndLogEx(WARNING, "File must be a binary dump, not a .eml");
return PM3_EINVARG;
}
if(datafnlen > 5 && !strcmp(datafilename + strlen(datafilename) - 5, ".json")) {
PrintAndLogEx(WARNING, "File must be a binary dump, not a .json");
return PM3_EINVARG;
}
uint8_t sectors = MIFARE_1K_MAXSECTOR;
if (m0) {
@ -1022,7 +999,6 @@ static int CmdHF14AMfRestore(const char *Cmd) {
}
}
fclose(f);
f = NULL;
// try reading card uid and create filename
if (datafnlen == 0) {
@ -1035,40 +1011,70 @@ static int CmdHF14AMfRestore(const char *Cmd) {
}
// read dump file
if ((f = fopen(datafilename, "rb")) == NULL) {
PrintAndLogEx(WARNING, "Could not find file " _YELLOW_("%s"), datafilename);
bytes_read = 0;
uint8_t *dump = NULL;
int res = 0;
DumpFileType_t dftype = getfiletype(datafilename);
switch (dftype) {
case BIN: {
res = loadFile_safe(datafilename, ".bin", (void **)&dump, &bytes_read);
break;
}
case EML: {
res = loadFileEML_safe(datafilename, (void **)&dump, &bytes_read);
break;
}
case JSON: {
dump = calloc(MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK, sizeof(uint8_t));
if (dump == NULL) {
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
return PM3_EMALLOC;
}
res = loadFileJSON(datafilename, (void *)dump, MIFARE_4K_MAXBLOCK * MFBLOCK_SIZE, &bytes_read, NULL);
break;
}
case DICTIONARY: {
PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed");
free(dump);
return PM3_EINVARG;
}
}
if (res != PM3_SUCCESS) {
free(dump);
return PM3_EFILE;
}
// default authentication key
uint8_t default_key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
PrintAndLogEx(INFO, "Restoring " _YELLOW_("%s")" to card", datafilename);
// main loop for restoreing.
// a bit more complicated than needed
// this is because of two things.
// 1. we are setting keys from a key file or using the existing ones in the dump
// 2. we need to authenticate against a card which might not have default keys.
uint8_t *ref_dump = dump;
for (uint8_t s = 0; s < sectors; s++) {
for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) {
for (uint8_t b = 0; b < mfNumBlocksPerSector(s); b++) {
uint8_t data[26];
uint8_t bldata[MFBLOCK_SIZE] = {0x00};
bytes_read = fread(bldata, 1, MFBLOCK_SIZE, f);
if (bytes_read != sizeof(bldata)) {
PrintAndLogEx(ERR, "File reading error " _YELLOW_("%s"), datafilename);
fclose(f);
f = NULL;
return PM3_EFILE;
}
memcpy(bldata, dump, MFBLOCK_SIZE);
if (use_keyfile_for_auth == false) {
// sector trailer
if (b == NumBlocksPerSector(s) - 1) {
// if sector trailer replace key
if (mfNumBlocksPerSector(s)-1 == b) {
// replace KEY A
bldata[0] = (keyA[s][0]);
bldata[1] = (keyA[s][1]);
bldata[2] = (keyA[s][2]);
bldata[3] = (keyA[s][3]);
bldata[4] = (keyA[s][4]);
bldata[5] = (keyA[s][5]);
// replace KEY B
bldata[10] = (keyB[s][0]);
bldata[11] = (keyB[s][1]);
bldata[12] = (keyB[s][2]);
@ -1078,21 +1084,34 @@ static int CmdHF14AMfRestore(const char *Cmd) {
}
}
memcpy(data + 10, bldata, sizeof(bldata));
if (mfNumBlocksPerSector(s)-1 == b) {
// ensure accessright isn't messed up.
if (memcmp(bldata + 6, "\x00\x00\x00\x00", 4) == 0) {
memcpy(bldata + 6, "\xFF\x07\x80\x69", 4);
}
}
if (bytes_read) {
dump += MFBLOCK_SIZE;
bytes_read -= MFBLOCK_SIZE;
}
uint8_t wdata[26];
memcpy(wdata + 10, bldata, sizeof(bldata));
if (use_keyfile_for_auth) {
for (int8_t kt = MF_KEY_B; kt > -1; kt--) {
if (kt == MF_KEY_A)
memcpy(data, keyA[s], 6);
memcpy(wdata, keyA[s], 6);
else
memcpy(data, keyB[s], 6);
memcpy(wdata, keyB[s], 6);
PrintAndLogEx(INFO, "block %3d: %s", mfFirstBlockOfSector(s) + b, sprint_hex(bldata, sizeof(bldata)));
PrintAndLogEx(INFO, "block %3d: %s", FirstBlockOfSector(s) + b, sprint_hex(bldata, sizeof(bldata)));
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(s) + b, kt, 0, data, sizeof(data));
SendCommandMIX(CMD_HF_MIFARE_WRITEBL, mfFirstBlockOfSector(s) + b, kt, 0, wdata, sizeof(wdata));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
if (isOK == 0) {
@ -1110,11 +1129,12 @@ static int CmdHF14AMfRestore(const char *Cmd) {
}
}
} else {
memcpy(data, default_key, 6);
PrintAndLogEx(INFO, "block %3d: %s", FirstBlockOfSector(s) + b, sprint_hex(bldata, sizeof(bldata)));
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(s) + b, MF_KEY_B, 0, data, sizeof(data));
// use default key to authenticate for the write command
memcpy(wdata, default_key, 6);
PrintAndLogEx(INFO, "block %3d: %s", mfFirstBlockOfSector(s) + b, sprint_hex(bldata, sizeof(bldata)));
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_WRITEBL, mfFirstBlockOfSector(s) + b, MF_KEY_B, 0, wdata, sizeof(wdata));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
@ -1128,10 +1148,11 @@ static int CmdHF14AMfRestore(const char *Cmd) {
} else {
PrintAndLogEx(WARNING, "Command execute timeout");
}
}
}
}
fclose(f);
} // end use_keyfile_for_auth
} // end loop B
} // end loop S
free(ref_dump);
PrintAndLogEx(INFO, "Done!");
return PM3_SUCCESS;
}
@ -1333,7 +1354,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
if (e_sector[sectorNo].foundKey[trgKeyType]) continue;
int16_t isOK = mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate);
int16_t isOK = mfnested(blockNo, keyType, key, mfFirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate);
switch (isOK) {
case PM3_ETIMEOUT:
PrintAndLogEx(ERR, "Command execute timeout\n");
@ -1374,7 +1395,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
// KEY A but not KEY B
if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) {
uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1);
uint8_t sectrail = (mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1);
PrintAndLogEx(SUCCESS, "reading block %d", sectrail);
@ -1415,7 +1436,7 @@ jumptoend:
// fast push mode
g_conn.block_after_ACK = true;
for (int i = 0; i < SectorsCnt; i++) {
mfEmlGetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
mfEmlGetMem(keyBlock, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1);
if (e_sector[i].foundKey[0])
num_to_bytes(e_sector[i].Key[0], 6, keyBlock);
@ -1427,7 +1448,7 @@ jumptoend:
// Disable fast mode on last packet
g_conn.block_after_ACK = false;
}
mfEmlSetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
mfEmlSetMem(keyBlock, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1);
}
PrintAndLogEx(SUCCESS, "keys transferred to emulator memory.");
}
@ -1586,7 +1607,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) {
if (e_sector[sectorNo].foundKey[trgKeyType]) continue;
int16_t isOK = mfStaticNested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock);
int16_t isOK = mfStaticNested(blockNo, keyType, key, mfFirstBlockOfSector(sectorNo), trgKeyType, keyBlock);
switch (isOK) {
case PM3_ETIMEOUT :
PrintAndLogEx(ERR, "Command execute timeout");
@ -1621,7 +1642,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) {
// KEY A but not KEY B
if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) {
uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1);
uint8_t sectrail = (mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1);
PrintAndLogEx(SUCCESS, "reading block %d", sectrail);
@ -1662,7 +1683,7 @@ jumptoend:
// fast push mode
g_conn.block_after_ACK = true;
for (int i = 0; i < SectorsCnt; i++) {
mfEmlGetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
mfEmlGetMem(keyBlock, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1);
if (e_sector[i].foundKey[0])
num_to_bytes(e_sector[i].Key[0], 6, keyBlock);
@ -1674,7 +1695,7 @@ jumptoend:
// Disable fast mode on last packet
g_conn.block_after_ACK = false;
}
mfEmlSetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
mfEmlSetMem(keyBlock, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1);
}
PrintAndLogEx(SUCCESS, "keys transferred to emulator memory.");
}
@ -2139,7 +2160,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
PrintAndLogEx(INFO, "======================= " _YELLOW_("START KNOWN KEY ATTACK") " =======================");
}
if (mfCheckKeys(FirstBlockOfSector(sectorno), keytype, true, 1, key, &key64) == PM3_SUCCESS) {
if (mfCheckKeys(mfFirstBlockOfSector(sectorno), keytype, true, 1, key, &key64) == PM3_SUCCESS) {
PrintAndLogEx(INFO, "target sector %3u key type %c -- using valid key [ " _GREEN_("%s") "] (used for nested / hardnested attack)",
sectorno,
(keytype == MF_KEY_B) ? 'B' : 'A',
@ -2165,7 +2186,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
for (int i = 0; i < sector_cnt; i++) {
for (int j = MF_KEY_A; j <= MF_KEY_B; j++) {
if (e_sector[i].foundKey[j] == 0) {
if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, key, &key64) == PM3_SUCCESS) {
if (mfCheckKeys(mfFirstBlockOfSector(i), j, true, 1, key, &key64) == PM3_SUCCESS) {
e_sector[i].Key[j] = bytes_to_num(key, 6);
e_sector[i].foundKey[j] = 'U';
@ -2240,7 +2261,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout);
if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, (keyBlock + (6 * k)), &key64) == PM3_SUCCESS) {
if (mfCheckKeys(mfFirstBlockOfSector(i), j, true, 1, (keyBlock + (6 * k)), &key64) == PM3_SUCCESS) {
e_sector[i].Key[j] = bytes_to_num((keyBlock + (6 * k)), 6);
e_sector[i].foundKey[j] = 'D';
++num_found_keys;
@ -2323,7 +2344,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
if (verbose) {
PrintAndLogEx(INFO, "======================= " _YELLOW_("START DARKSIDE ATTACK") " =======================");
}
isOK = mfDarkside(FirstBlockOfSector(sectorno), keytype + 0x60, &key64);
isOK = mfDarkside(mfFirstBlockOfSector(sectorno), keytype + 0x60, &key64);
switch (isOK) {
case -1 :
@ -2389,7 +2410,7 @@ noValidKeyFound:
continue;
// Check if the key works
if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, tmp_key, &key64) == PM3_SUCCESS) {
if (mfCheckKeys(mfFirstBlockOfSector(i), j, true, 1, tmp_key, &key64) == PM3_SUCCESS) {
e_sector[i].Key[j] = bytes_to_num(tmp_key, 6);
e_sector[i].foundKey[j] = 'R';
PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]",
@ -2412,7 +2433,7 @@ noValidKeyFound:
current_sector_i,
(current_key_type_i == MF_KEY_B) ? 'B' : 'A');
}
uint8_t sectrail = (FirstBlockOfSector(current_sector_i) + NumBlocksPerSector(current_sector_i) - 1);
uint8_t sectrail = (mfFirstBlockOfSector(current_sector_i) + mfNumBlocksPerSector(current_sector_i) - 1);
mf_readblock_t payload;
payload.blockno = sectrail;
@ -2468,7 +2489,7 @@ skipReadBKey:
(current_key_type_i == MF_KEY_B) ? 'B' : 'A');
}
tryNested:
isOK = mfnested(FirstBlockOfSector(sectorno), keytype, key, FirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key, calibrate);
isOK = mfnested(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key, calibrate);
switch (isOK) {
case PM3_ETIMEOUT: {
@ -2526,7 +2547,7 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack
slow ? "Yes" : "No");
}
isOK = mfnestedhard(FirstBlockOfSector(sectorno), keytype, key, FirstBlockOfSector(current_sector_i), current_key_type_i, NULL, false, false, slow, 0, &foundkey, NULL);
isOK = mfnestedhard(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, NULL, false, false, slow, 0, &foundkey, NULL);
DropField();
if (isOK) {
switch (isOK) {
@ -2562,7 +2583,7 @@ tryStaticnested:
(current_key_type_i == MF_KEY_B) ? 'B' : 'A');
}
isOK = mfStaticNested(sectorno, keytype, key, FirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key);
isOK = mfStaticNested(sectorno, keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key);
DropField();
switch (isOK) {
case PM3_ETIMEOUT: {
@ -2629,7 +2650,7 @@ all_found:
if (e_sector[current_sector_i].foundKey[1])
num_to_bytes(e_sector[current_sector_i].Key[1], 6, block + 10);
mfEmlSetMem(block, FirstBlockOfSector(current_sector_i) + NumBlocksPerSector(current_sector_i) - 1, 1);
mfEmlSetMem(block, mfFirstBlockOfSector(current_sector_i) + mfNumBlocksPerSector(current_sector_i) - 1, 1);
}
// use ecfill trick
@ -2935,7 +2956,7 @@ out:
g_conn.block_after_ACK = true;
uint8_t block[16] = {0x00};
for (i = 0; i < sectorsCnt; ++i) {
uint8_t b = FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1;
uint8_t b = mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1;
mfEmlGetMem(block, b, 1);
if (e_sector[i].foundKey[0])
@ -3238,8 +3259,8 @@ static int CmdHF14AMfChk(const char *Cmd) {
if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) {
uint8_t s = GetSectorFromBlockNo(b);
uint8_t sectrail = (FirstBlockOfSector(s) + NumBlocksPerSector(s) - 1);
PrintAndLogEx(INFO, "Sector: %u, First block: %u, Last block: %u, Num of blocks: %u", s, FirstBlockOfSector(s), sectrail, NumBlocksPerSector(s));
uint8_t sectrail = (mfFirstBlockOfSector(s) + mfNumBlocksPerSector(s) - 1);
PrintAndLogEx(INFO, "Sector: %u, First block: %u, Last block: %u, Num of blocks: %u", s, mfFirstBlockOfSector(s), sectrail, mfNumBlocksPerSector(s));
PrintAndLogEx(INFO, "Reading sector trailer");
mf_readblock_t payload;
@ -3284,7 +3305,7 @@ out:
g_conn.block_after_ACK = true;
uint8_t block[16] = {0x00};
for (int i = 0; i < SectorsCnt; ++i) {
uint8_t blockno = FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1;
uint8_t blockno = mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1;
mfEmlGetMem(block, blockno, 1);
if (e_sector[i].foundKey[0])
@ -3728,8 +3749,8 @@ static int CmdHF14AMfEGetSc(const char *Cmd) {
uint8_t sector = (uint8_t)s;
mf_print_sector_hdr(sector);
uint8_t blocks = NumBlocksPerSector(sector);
uint8_t start = FirstBlockOfSector(sector);
uint8_t blocks = mfNumBlocksPerSector(sector);
uint8_t start = mfFirstBlockOfSector(sector);
uint8_t data[16] = {0};
for (int i = 0; i < blocks; i++) {
@ -4290,8 +4311,8 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) {
// download keys from EMUL
for (int i = 0; i < sectors_cnt; i++) {
if (mfEmlGetMem(data, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1) != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "error get block %d", FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1);
if (mfEmlGetMem(data, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1) != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "error get block %d", mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1);
e_sector[i].foundKey[0] = false;
e_sector[i].foundKey[1] = false;
} else {
@ -6023,7 +6044,7 @@ static int CmdHF14AMfWipe(const char *Cmd) {
// time to wipe card
for (uint8_t s = 0; s < num_sectors; s++) {
for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) {
for (uint8_t b = 0; b < mfNumBlocksPerSector(s); b++) {
// Skipp write to manufacture block if not enforced
if (s == 0 && b == 0 && gen2 == false) {
@ -6051,9 +6072,9 @@ static int CmdHF14AMfWipe(const char *Cmd) {
else
memcpy(data, keyB + (s * 6), 6);
PrintAndLogEx(INFO, "block %3d: %s" NOLF, FirstBlockOfSector(s) + b, sprint_hex(data + 10, MFBLOCK_SIZE));
PrintAndLogEx(INFO, "block %3d: %s" NOLF, mfFirstBlockOfSector(s) + b, sprint_hex(data + 10, MFBLOCK_SIZE));
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(s) + b, kt, 0, data, sizeof(data));
SendCommandMIX(CMD_HF_MIFARE_WRITEBL, mfFirstBlockOfSector(s) + b, kt, 0, data, sizeof(data));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;

View file

@ -502,6 +502,7 @@ uint8_t mfFirstBlockOfSector(uint8_t sectorNo) {
return 32 * 4 + (sectorNo - 32) * 16;
}
// assumes blockno is 0-255..
uint8_t mfSectorTrailer(uint8_t blockNo) {
if (blockNo < 32 * 4) {
return (blockNo | 0x03);
@ -510,10 +511,12 @@ uint8_t mfSectorTrailer(uint8_t blockNo) {
}
}
// assumes blockno is 0-255..
bool mfIsSectorTrailer(uint8_t blockNo) {
return (blockNo == mfSectorTrailer(blockNo));
}
// assumes blockno is 0-255..
uint8_t mfSectorNum(uint8_t blockNo) {
if (blockNo < 32 * 4)
return blockNo / 4;