mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
fix: 'hf iclass clone' - last block write fails, see (https://github.com/RfidResearchGroup/proxmark3/issues/183)
chg: 'hf iclass clone' - now tries ten times, behavies better, obey verbose nicer, drop field constant. Uses NG. chg: 'hf iclass dump' - now tries ten times, in general nice outputs..
This commit is contained in:
parent
d8217a13d9
commit
9a2a0116e4
3 changed files with 145 additions and 87 deletions
|
@ -1271,7 +1271,13 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_ICLASS_CLONE: {
|
case CMD_HF_ICLASS_CLONE: {
|
||||||
iClass_Clone(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
struct p {
|
||||||
|
uint8_t startblock;
|
||||||
|
uint8_t endblock;
|
||||||
|
uint8_t data[];
|
||||||
|
} PACKED;
|
||||||
|
struct p *payload = (struct p *)packet->data.asBytes;
|
||||||
|
iClass_Clone(payload->startblock, payload->endblock, payload->data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2520,23 +2520,19 @@ void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
|
||||||
int total_block = (endblock - startblock) + 1;
|
int total_block = (endblock - startblock) + 1;
|
||||||
for (i = 0; i < total_block; i++) {
|
for (i = 0; i < total_block; i++) {
|
||||||
// block number
|
// block number
|
||||||
if (iClass_WriteBlock_ext(i + startblock, data + (i * 12))) {
|
if (iClass_WriteBlock_ext(startblock + i, data + (i * 12))) {
|
||||||
Dbprintf("Write block [%02x] successful", i + startblock);
|
Dbprintf("Write block [%02x] successful", startblock + i);
|
||||||
written++;
|
written++;
|
||||||
} else {
|
} else {
|
||||||
if (iClass_WriteBlock_ext(i + startblock, data + (i * 12))) {
|
Dbprintf("Write block [%02x] failed", startblock + i);
|
||||||
Dbprintf("Write block [%02x] successful", i + startblock);
|
|
||||||
written++;
|
|
||||||
} else {
|
|
||||||
Dbprintf("Write block [%02x] failed", i + startblock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (written == total_block)
|
|
||||||
DbpString("Clone complete");
|
|
||||||
else
|
|
||||||
DbpString("Clone incomplete");
|
|
||||||
|
|
||||||
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
|
||||||
switch_off();
|
switch_off();
|
||||||
|
|
||||||
|
uint8_t isOK = 0;
|
||||||
|
if (written == total_block)
|
||||||
|
isOK = 1;
|
||||||
|
|
||||||
|
reply_ng(CMD_HF_ICLASS_CLONE, PM3_SUCCESS, (uint8_t *)&isOK, sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1118,6 +1118,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
|
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo"));
|
||||||
elite = true;
|
elite = true;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
|
@ -1149,6 +1150,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
|
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode"));
|
||||||
rawkey = true;
|
rawkey = true;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
|
@ -1180,7 +1182,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
|
||||||
PrintAndLogEx(WARNING, "command execute timeout");
|
PrintAndLogEx(WARNING, "command execute timeout");
|
||||||
DropField();
|
DropField();
|
||||||
return 0;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
DropField();
|
DropField();
|
||||||
|
|
||||||
|
@ -1189,7 +1191,8 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
|
|
||||||
if (readStatus == 0) {
|
if (readStatus == 0) {
|
||||||
PrintAndLogEx(FAILED, "no tag found");
|
PrintAndLogEx(FAILED, "no tag found");
|
||||||
return 0;
|
DropField();
|
||||||
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readStatus & (FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_CC)) {
|
if (readStatus & (FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_CC)) {
|
||||||
|
@ -1202,14 +1205,16 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// authenticate debit key and get div_key - later store in dump block 3
|
// authenticate debit key and get div_key - later store in dump block 3
|
||||||
if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) {
|
int numberAuthRetries = ICLASS_AUTH_RETRY;
|
||||||
//try twice - for some reason it sometimes fails the first time...
|
do {
|
||||||
PrintAndLogEx(SUCCESS, "retry to select card");
|
if (select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose))
|
||||||
if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) {
|
break;
|
||||||
|
} while (numberAuthRetries--);
|
||||||
|
|
||||||
|
if ( numberAuthRetries <= 0) {
|
||||||
PrintAndLogEx(WARNING, "failed authenticating with debit key");
|
PrintAndLogEx(WARNING, "failed authenticating with debit key");
|
||||||
DropField();
|
DropField();
|
||||||
return 0;
|
return PM3_ESOFT;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// begin dump
|
// begin dump
|
||||||
|
@ -1233,7 +1238,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
uint8_t isOK = resp.oldarg[0] & 0xff;
|
||||||
if (!isOK && !blocksRead) {
|
if (!isOK && !blocksRead) {
|
||||||
PrintAndLogEx(WARNING, "read block failed");
|
PrintAndLogEx(WARNING, "read block failed");
|
||||||
return 0;
|
return PM3_ESOFt;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t startindex = resp.oldarg[2];
|
uint32_t startindex = resp.oldarg[2];
|
||||||
|
@ -1245,7 +1250,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
// response ok - now get bigbuf content of the dump
|
// response ok - now get bigbuf content of the dump
|
||||||
if (!GetFromDevice(BIG_BUF, tag_data + (blockno * 8), blocksRead * 8, startindex, NULL, 0, NULL, 2500, false)) {
|
if (!GetFromDevice(BIG_BUF, tag_data + (blockno * 8), blocksRead * 8, startindex, NULL, 0, NULL, 2500, false)) {
|
||||||
PrintAndLogEx(WARNING, "command execution time out");
|
PrintAndLogEx(WARNING, "command execution time out");
|
||||||
return 0;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t gotBytes = blocksRead * 8 + blockno * 8;
|
size_t gotBytes = blocksRead * 8 + blockno * 8;
|
||||||
|
@ -1254,16 +1259,22 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
if (have_credit_key) {
|
if (have_credit_key) {
|
||||||
//turn off hf field before authenticating with different key
|
//turn off hf field before authenticating with different key
|
||||||
DropField();
|
DropField();
|
||||||
|
|
||||||
memset(MAC, 0, 4);
|
memset(MAC, 0, 4);
|
||||||
|
|
||||||
// AA2 authenticate credit key and git c_div_key - later store in dump block 4
|
// AA2 authenticate credit key and git c_div_key - later store in dump block 4
|
||||||
if (!select_and_auth(CreditKEY, MAC, c_div_key, true, elite, rawkey, verbose)) {
|
numberAuthRetries = ICLASS_AUTH_RETRY;
|
||||||
//try twice - for some reason it sometimes fails the first time...
|
do {
|
||||||
if (!select_and_auth(CreditKEY, MAC, c_div_key, true, elite, rawkey, verbose)) {
|
if (select_and_auth(CreditKEY, MAC, c_div_key, true, elite, rawkey, verbose))
|
||||||
|
break;
|
||||||
|
} while (numberAuthRetries--);
|
||||||
|
|
||||||
|
if ( numberAuthRetries <= 0) {
|
||||||
PrintAndLogEx(WARNING, "failed authenticating with credit key");
|
PrintAndLogEx(WARNING, "failed authenticating with credit key");
|
||||||
DropField();
|
DropField();
|
||||||
return 0;
|
return PM3_ESOFT;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// do we still need to read more block? (aa2 enabled?)
|
// do we still need to read more block? (aa2 enabled?)
|
||||||
if (maxBlk > blockno + numblks + 1) {
|
if (maxBlk > blockno + numblks + 1) {
|
||||||
// setup dump and start
|
// setup dump and start
|
||||||
|
@ -1271,13 +1282,13 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
SendCommandMIX(CMD_HF_ICLASS_DUMP, blockno + blocksRead, maxBlk - (blockno + blocksRead), 0, NULL, 0);
|
SendCommandMIX(CMD_HF_ICLASS_DUMP, blockno + blocksRead, maxBlk - (blockno + blocksRead), 0, NULL, 0);
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
|
||||||
PrintAndLogEx(WARNING, "command execute timeout 2");
|
PrintAndLogEx(WARNING, "command execute timeout 2");
|
||||||
return 0;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
isOK = resp.oldarg[0] & 0xff;
|
isOK = resp.oldarg[0] & 0xff;
|
||||||
blocksRead = resp.oldarg[1];
|
blocksRead = resp.oldarg[1];
|
||||||
if (!isOK && !blocksRead) {
|
if (!isOK && !blocksRead) {
|
||||||
PrintAndLogEx(WARNING, "read block failed 2");
|
PrintAndLogEx(WARNING, "read block failed 2");
|
||||||
return 0;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
startindex = resp.oldarg[2];
|
startindex = resp.oldarg[2];
|
||||||
|
@ -1288,7 +1299,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
// get dumped data from bigbuf
|
// get dumped data from bigbuf
|
||||||
if (!GetFromDevice(BIG_BUF, tag_data + gotBytes, blocksRead * 8, startindex, NULL, 0, NULL, 2500, false)) {
|
if (!GetFromDevice(BIG_BUF, tag_data + gotBytes, blocksRead * 8, startindex, NULL, 0, NULL, 2500, false)) {
|
||||||
PrintAndLogEx(WARNING, "command execution time out");
|
PrintAndLogEx(WARNING, "command execution time out");
|
||||||
return 0;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
gotBytes += blocksRead * 8;
|
gotBytes += blocksRead * 8;
|
||||||
|
@ -1298,16 +1309,20 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
DropField();
|
DropField();
|
||||||
|
|
||||||
// add diversified keys to dump
|
// add diversified keys to dump
|
||||||
if (have_debit_key) memcpy(tag_data + (3 * 8), div_key, 8);
|
if (have_debit_key)
|
||||||
if (have_credit_key) memcpy(tag_data + (4 * 8), c_div_key, 8);
|
memcpy(tag_data + (3 * 8), div_key, 8);
|
||||||
|
|
||||||
|
if (have_credit_key)
|
||||||
|
memcpy(tag_data + (4 * 8), c_div_key, 8);
|
||||||
|
|
||||||
|
|
||||||
// print the dump
|
// print the dump
|
||||||
PrintAndLogEx(NORMAL, "------+--+-------------------------+\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "CSN |00| %s|\n", sprint_hex(tag_data, 8));
|
PrintAndLogEx(NORMAL, "------+--+-------------------------+");
|
||||||
|
PrintAndLogEx(NORMAL, "CSN |00| %s|", sprint_hex(tag_data, 8));
|
||||||
printIclassDumpContents(tag_data, 1, (gotBytes / 8), gotBytes);
|
printIclassDumpContents(tag_data, 1, (gotBytes / 8), gotBytes);
|
||||||
|
|
||||||
if (filename[0] == 0) {
|
if (filename[0] == 0) {
|
||||||
|
|
||||||
//Use the first block (CSN) for filename
|
//Use the first block (CSN) for filename
|
||||||
strcat(filename, "hf-iclass-");
|
strcat(filename, "hf-iclass-");
|
||||||
FillFileNameByUID(filename, tag_data, "-data", 8);
|
FillFileNameByUID(filename, tag_data, "-data", 8);
|
||||||
|
@ -1469,6 +1484,7 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
||||||
uint8_t startblock = 0;
|
uint8_t startblock = 0;
|
||||||
uint8_t endblock = 0;
|
uint8_t endblock = 0;
|
||||||
uint8_t dataLen = 0;
|
uint8_t dataLen = 0;
|
||||||
|
bool got_startblk = false, got_endblk = false;
|
||||||
bool use_credit_key = false;
|
bool use_credit_key = false;
|
||||||
bool elite = false;
|
bool elite = false;
|
||||||
bool rawkey = false;
|
bool rawkey = false;
|
||||||
|
@ -1480,17 +1496,17 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
||||||
case 'h':
|
case 'h':
|
||||||
return usage_hf_iclass_clone();
|
return usage_hf_iclass_clone();
|
||||||
case 'b':
|
case 'b':
|
||||||
if (param_gethex(Cmd, cmdp + 1, &startblock, 2)) {
|
startblock = param_get8ex(Cmd, cmdp + 1, 07, 16);
|
||||||
PrintAndLogEx(WARNING, "start block No must include 2 HEX symbols\n");
|
got_startblk = true;
|
||||||
errors = true;
|
|
||||||
}
|
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
|
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("CREDIT"));
|
||||||
use_credit_key = true;
|
use_credit_key = true;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
|
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo"));
|
||||||
elite = true;
|
elite = true;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
|
@ -1509,6 +1525,7 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
||||||
} else if (dataLen == 1) {
|
} else if (dataLen == 1) {
|
||||||
keyNbr = param_get8(Cmd, cmdp + 1);
|
keyNbr = param_get8(Cmd, cmdp + 1);
|
||||||
if (keyNbr < ICLASS_KEYS_MAX) {
|
if (keyNbr < ICLASS_KEYS_MAX) {
|
||||||
|
PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8 ));
|
||||||
memcpy(KEY, iClass_Key_Table[keyNbr], 8);
|
memcpy(KEY, iClass_Key_Table[keyNbr], 8);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n");
|
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n");
|
||||||
|
@ -1521,13 +1538,12 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
if (param_gethex(Cmd, cmdp + 1, &endblock, 2)) {
|
endblock = param_get8ex(Cmd, cmdp + 1, 07, 16);
|
||||||
PrintAndLogEx(WARNING, "start Block No must include 2 HEX symbols\n");
|
got_endblk = true;
|
||||||
errors = true;
|
|
||||||
}
|
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
|
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode"));
|
||||||
rawkey = true;
|
rawkey = true;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
|
@ -1541,53 +1557,66 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ( got_endblk == false || got_startblk == false)
|
||||||
|
errors = true;
|
||||||
|
|
||||||
if (errors || cmdp < 8) return usage_hf_iclass_clone();
|
if (errors || cmdp < 8) return usage_hf_iclass_clone();
|
||||||
|
|
||||||
FILE *f;
|
if (startblock < 5) {
|
||||||
|
PrintAndLogEx(WARNING, "you cannot write key blocks this way. yet... make your start block > 4");
|
||||||
iclass_block_t tag_data[PM3_CMD_DATA_SIZE / 12];
|
return PM3_EINVARG;
|
||||||
|
|
||||||
if ((endblock - startblock + 1) * 12 > PM3_CMD_DATA_SIZE) {
|
|
||||||
PrintAndLogEx(NORMAL, "Trying to write too many blocks at once. Max: %d", PM3_CMD_DATA_SIZE / 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int total_bytes = (((endblock - startblock) + 1) * 12);
|
||||||
|
|
||||||
|
if (total_bytes > PM3_CMD_DATA_SIZE - 2) {
|
||||||
|
PrintAndLogEx(NORMAL, "Trying to write too many blocks at once. Max: %d", PM3_CMD_DATA_SIZE / 8);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
// file handling and reading
|
// file handling and reading
|
||||||
f = fopen(filename, "rb");
|
FILE *f = fopen(filename, "rb");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename);
|
PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename);
|
||||||
return PM3_EFILE;
|
return PM3_EFILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startblock < 5) {
|
iclass_block_t tag_data[PM3_CMD_DATA_SIZE / 12];
|
||||||
PrintAndLogEx(WARNING, "you cannot write key blocks this way. yet... make your start block > 4");
|
|
||||||
fclose(f);
|
// read data from file from block 6 --- 19
|
||||||
return 0;
|
// we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
|
||||||
}
|
// then copy to usbcommand->asbytes;
|
||||||
// now read data from the file from block 6 --- 19
|
// max is 32 - 6 = 28 block. 28 x 12 bytes gives 336 bytes
|
||||||
// ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
|
|
||||||
// then copy to usbcommand->asbytes; the max is 32 - 6 = 24 block 12 bytes each block 288 bytes then we can only accept to clone 21 blocks at the time,
|
|
||||||
// else we have to create a share memory
|
|
||||||
int i;
|
int i;
|
||||||
fseek(f, startblock * 8, SEEK_SET);
|
fseek(f, startblock * 8, SEEK_SET);
|
||||||
size_t bytes_read = fread(tag_data, sizeof(iclass_block_t), endblock - startblock + 1, f);
|
size_t bytes_read = fread(tag_data, sizeof(iclass_block_t), endblock - startblock + 1, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
if (bytes_read == 0) {
|
if (bytes_read == 0) {
|
||||||
PrintAndLogEx(ERR, "file reading error.");
|
PrintAndLogEx(ERR, "file reading error.");
|
||||||
fclose(f);
|
return PM3_EFILE;
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00};
|
uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00};
|
||||||
uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) {
|
int numberAuthRetries = ICLASS_AUTH_RETRY;
|
||||||
return 0;
|
do {
|
||||||
|
if (select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose))
|
||||||
|
break;
|
||||||
|
} while (numberAuthRetries--);
|
||||||
|
|
||||||
|
if ( numberAuthRetries <= 0 ) {
|
||||||
|
PrintAndLogEx(ERR, "failed to authenticate");
|
||||||
|
DropField();
|
||||||
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t data[(endblock - startblock) * 12];
|
uint8_t data[total_bytes];
|
||||||
|
|
||||||
// calculate all mac for every the block we will write
|
// calculate all mac for every the block we will write
|
||||||
for (i = startblock; i <= endblock; i++) {
|
for (i = startblock; i <= endblock; i++) {
|
||||||
|
|
||||||
Calc_wb_mac(i, tag_data[i - startblock].d, div_key, MAC);
|
Calc_wb_mac(i, tag_data[i - startblock].d, div_key, MAC);
|
||||||
// usb command d start pointer = d + (i - 6) * 12
|
// usb command d start pointer = d + (i - 6) * 12
|
||||||
// memcpy(pointer,tag_data[i - 6],8) 8 bytes
|
// memcpy(pointer,tag_data[i - 6],8) 8 bytes
|
||||||
|
@ -1597,22 +1626,49 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
||||||
memcpy(ptr, &(tag_data[i - startblock].d[0]), 8);
|
memcpy(ptr, &(tag_data[i - startblock].d[0]), 8);
|
||||||
memcpy(ptr + 8, MAC, 4);
|
memcpy(ptr + 8, MAC, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( verbose ) {
|
||||||
|
PrintAndLogEx(NORMAL,"------+--------------------------+-------------");
|
||||||
|
PrintAndLogEx(NORMAL,"block | data | mac");
|
||||||
|
PrintAndLogEx(NORMAL,"------+--------------------------+-------------");
|
||||||
uint8_t p[12];
|
uint8_t p[12];
|
||||||
for (i = 0; i <= endblock - startblock; i++) {
|
for (i = 0; i <= endblock - startblock; i++) {
|
||||||
memcpy(p, data + (i * 12), 12);
|
memcpy(p, data + (i * 12), 12);
|
||||||
PrintAndLogEx(NORMAL, "Block |%02x|", i + startblock);
|
char *s = calloc(70, sizeof(uint8_t));
|
||||||
PrintAndLogEx(NORMAL, " %02x%02x%02x%02x%02x%02x%02x%02x |", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
|
sprintf(s, "| %s ", sprint_hex(p, 8));
|
||||||
PrintAndLogEx(NORMAL, " MAC |%02x%02x%02x%02x|\n", p[8], p[9], p[10], p[11]);
|
sprintf(s + strlen(s), "| %s", sprint_hex(p + 8, 4));
|
||||||
|
PrintAndLogEx(NORMAL, " %02X %s", i + startblock, s );
|
||||||
|
free(s);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct p {
|
||||||
|
uint8_t startblock;
|
||||||
|
uint8_t endblock;
|
||||||
|
uint8_t data[PM3_CMD_DATA_SIZE - 2];
|
||||||
|
} PACKED payload;
|
||||||
|
|
||||||
|
payload.startblock = startblock;
|
||||||
|
payload.endblock = endblock;
|
||||||
|
memcpy(payload.data, data, total_bytes);
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandOLD(CMD_HF_ICLASS_CLONE, startblock, endblock, 0, data, (endblock - startblock) * 12);
|
SendCommandNG(CMD_HF_ICLASS_CLONE, (uint8_t*)&payload, total_bytes + 2 );
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
|
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_ICLASS_CLONE, &resp, 4500) == 0) {
|
||||||
PrintAndLogEx(WARNING, "command execute timeout");
|
PrintAndLogEx(WARNING, "command execute timeout");
|
||||||
return 0;
|
DropField();
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
return PM3_SUCCESS;
|
|
||||||
|
if (resp.status == PM3_SUCCESS) {
|
||||||
|
if ( resp.data.asBytes[0] == 1 )
|
||||||
|
PrintAndLogEx(SUCCESS, "Clone successful");
|
||||||
|
else
|
||||||
|
PrintAndLogEx(WARNING, "Clone failed");
|
||||||
|
}
|
||||||
|
return resp.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose, bool auth) {
|
static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose, bool auth) {
|
||||||
|
@ -1809,13 +1865,13 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e
|
||||||
//PrintAndLog ("startblock: %d, endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d",startblock, endblock,filesize, maxmemcount, filemaxblock);
|
//PrintAndLog ("startblock: %d, endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d",startblock, endblock,filesize, maxmemcount, filemaxblock);
|
||||||
|
|
||||||
int i = startblock;
|
int i = startblock;
|
||||||
PrintAndLogEx(NORMAL, "------+--+-------------------------+\n");
|
PrintAndLogEx(NORMAL, "------+--+-------------------------+");
|
||||||
while (i <= endblock) {
|
while (i <= endblock) {
|
||||||
uint8_t *blk = iclass_dump + (i * 8);
|
uint8_t *blk = iclass_dump + (i * 8);
|
||||||
PrintAndLogEx(NORMAL, " |%02X| %s\n", i, sprint_hex_ascii(blk, 8));
|
PrintAndLogEx(NORMAL, " |%02X| %s", i, sprint_hex_ascii(blk, 8));
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "------+--+-------------------------+\n");
|
PrintAndLogEx(NORMAL, "------+--+-------------------------+");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHFiClassReadTagFile(const char *Cmd) {
|
static int CmdHFiClassReadTagFile(const char *Cmd) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue