Merge pull request #531 from RfidResearchGroup/hitag

Hitag
This commit is contained in:
Iceman
2020-01-22 13:06:18 +01:00
committed by GitHub
65 changed files with 22472 additions and 721 deletions

View File

@@ -314,11 +314,69 @@ static int CmdFlashMemSpiFFSDump(const char *Cmd) {
return PM3_SUCCESS;
}
int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) {
int ret_val = PM3_SUCCESS;
// We want to mount before multiple operation so the lazy writes/append will not
// trigger a mount + umount each loop iteration (lazy ops device side)
SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0);
// Send to device
uint32_t bytes_sent = 0;
uint32_t bytes_remaining = datalen;
uint32_t append = 0;
// fast push mode
conn.block_after_ACK = true;
while (bytes_remaining > 0) {
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
clearCommandBuffer();
char fdata[32 + bytes_in_packet];
memset(fdata, 0, sizeof(fdata));
memcpy(fdata, destfn, 32);
memcpy(fdata + 32, data + bytes_sent, bytes_in_packet);
if (bytes_sent > 0)
append = 1;
SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet);
bytes_remaining -= bytes_in_packet;
bytes_sent += bytes_in_packet;
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
ret_val = PM3_ETIMEOUT;
break;
}
uint8_t isok = resp.oldarg[0] & 0xFF;
if (!isok) {
PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent);
ret_val = PM3_EFLASH;
break;
}
}
// turn off fast push mode
conn.block_after_ACK = false;
// We want to unmount after these to set things back to normal but more than this
// unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory
SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0);
return ret_val;
}
static int CmdFlashMemSpiFFSLoad(const char *Cmd) {
uint32_t append = 0;
char filename[FILE_PATH_SIZE] = {0};
char destfilename[32] = {0};
uint8_t destfilename[32] = {0};
bool errors = false;
uint8_t cmdp = 0;
@@ -334,8 +392,8 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) {
cmdp += 2;
break;
case 'o':
param_getstr(Cmd, cmdp + 1, destfilename, 32);
if (strlen(destfilename) == 0) {
param_getstr(Cmd, cmdp + 1, (char*)destfilename, 32);
if (strlen((char*)destfilename) == 0) {
PrintAndLogEx(FAILED, "Destination Filename missing or invalid");
errors = true;
}
@@ -362,63 +420,14 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) {
return PM3_EFILE;
}
// We want to mount before multiple operation so the lazy writes/append will not
// trigger a mount + umount each loop iteration (lazy ops device side)
SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0);
// Send to device
uint32_t bytes_sent = 0;
uint32_t bytes_remaining = datalen;
// fast push mode
conn.block_after_ACK = true;
// SendCommandMIX(CMD_SPIFFS_COPY, 0, 0, 0, (uint8_t *)data, 65);
while (bytes_remaining > 0) {
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
clearCommandBuffer();
char fdata[32 + bytes_in_packet];
memset(fdata, 0, sizeof(fdata));
memcpy(fdata, destfilename, 32);
memcpy(fdata + 32, data + bytes_sent, bytes_in_packet);
// sprintf(fdata, "%s%s", destfilename, data + bytes_sent);
if (bytes_sent > 0)
append = 1;
SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet);
bytes_remaining -= bytes_in_packet;
bytes_sent += bytes_in_packet;
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
conn.block_after_ACK = false;
free(data);
return PM3_ETIMEOUT;
}
uint8_t isok = resp.oldarg[0] & 0xFF;
if (!isok) {
conn.block_after_ACK = false;
PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent);
free(data);
return PM3_EFLASH;
}
}
conn.block_after_ACK = false;
res = flashmem_spiffs_load(destfilename, data, datalen);
free(data);
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") "bytes to file "_GREEN_("%s"), datalen, destfilename);
// We want to unmount after these to set things back to normal but more than this
// unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory
SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0);
return PM3_SUCCESS;
if ( res == PM3_SUCCESS )
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") "bytes to file "_GREEN_("%s"), datalen, destfilename);
return res;
}
static command_t CommandTable[] = {

View File

@@ -14,5 +14,6 @@
#include "common.h"
int CmdFlashMemSpiFFS(const char *Cmd);
int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen);
#endif

View File

@@ -85,8 +85,6 @@ int CmdHFSearch(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_search();
PrintAndLogEx(INFO, "Checking for known tags...");
PROMPT_CLEARLINE;
PrintAndLogEx(INPLACE, "Searching for ThinFilm tag...");
if (IfPm3NfcBarcode()) {
@@ -170,9 +168,8 @@ int CmdHFSearch(const char *Cmd) {
}
PROMPT_CLEARLINE;
PrintAndLogEx(INPLACE, "done");
PrintAndLogEx(INPLACE, _RED_("No known/supported 13.56 MHz tags found"));
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(FAILED, _RED_("No known/supported 13.56 MHz tags found"));
return PM3_ESOFT;
}
@@ -272,15 +269,16 @@ static command_t CommandTable[] = {
{"15", CmdHF15, AlwaysAvailable, "{ ISO15693 RFIDs... }"},
{"epa", CmdHFEPA, AlwaysAvailable, "{ German Identification Card... }"},
{"felica", CmdHFFelica, AlwaysAvailable, "{ ISO18092 / Felica RFIDs... }"},
{"legic", CmdHFLegic, AlwaysAvailable, "{ LEGIC RFIDs... }"},
{"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"},
{"iclass", CmdHFiClass, AlwaysAvailable, "{ ICLASS RFIDs... }"},
{"legic", CmdHFLegic, AlwaysAvailable, "{ LEGIC RFIDs... }"},
{"lto", CmdHFLTO, AlwaysAvailable, "{ LTO Cartridge Memory RFIDs... }"},
{"mf", CmdHFMF, AlwaysAvailable, "{ MIFARE RFIDs... }"},
{"mfp", CmdHFMFP, AlwaysAvailable, "{ MIFARE Plus RFIDs... }"},
{"mfu", CmdHFMFUltra, AlwaysAvailable, "{ MIFARE Ultralight RFIDs... }"},
{"mfdes", CmdHFMFDes, AlwaysAvailable, "{ MIFARE Desfire RFIDs... }"},
{"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"},
{"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"},
{"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"},
{"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"},
{"list", CmdTraceList, AlwaysAvailable, "List protocol data in trace buffer"},
{"plot", CmdHFPlot, IfPm3Hfplot, "Plot signal"},
{"tune", CmdHFTune, IfPm3Present, "Continuously measure HF antenna tuning"},

View File

@@ -2805,6 +2805,7 @@ int readIclass(bool loop, bool verbose) {
FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE |
FLAG_ICLASS_READER_ONE_TRY;
uint32_t res = PM3_ETIMEOUT;
// loop in client not device - else on windows have a communication error
while (!kbd_enter_pressed()) {
@@ -2876,6 +2877,6 @@ int readIclass(bool loop, bool verbose) {
if (!loop) break;
}
DropField();
return PM3_SUCCESS;
return res;
}

View File

@@ -1101,10 +1101,10 @@ void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
snprintf(exp, size, "REQ Standard");
break;
case LTO_SELECT:
snprintf(exp, size, "SELECT");
break;
case LTO_SELECT_1:
snprintf(exp, size, "SELECT_1");
if (cmd[1] == 0x70)
snprintf(exp, size, "SELECT_UID-2");
else if (cmd[1] == 0x20)
snprintf(exp, size, "SELECT");
break;
case LTO_REQ_ALL:
snprintf(exp, size, "REQ All");

View File

@@ -42,9 +42,17 @@ static void lto_switch_on_field(void) {
}
// send a raw LTO-CM command, returns the length of the response (0 in case of error)
static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool verbose) {
static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool addcrc, bool verbose) {
SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, len, 0, cmd, len);
uint64_t arg0 = ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS;
uint32_t arg1 = (len == 1) ? (7 << 16) : 0;
arg1 |= len;
if (addcrc) {
arg0 |= ISO14A_APPEND_CRC;
}
SendCommandOLD(CMD_HF_ISO14443A_READER, arg0, arg1, 0, cmd, len);
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
@@ -55,7 +63,6 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16
if (resp.oldarg[0] == *response_len) {
*response_len = resp.oldarg[0];
PrintAndLogEx(INFO, "%s", sprint_hex(resp.data.asBytes, *response_len));
if (*response_len > 0) {
memcpy(response, resp.data.asBytes, *response_len);
}
@@ -66,7 +73,6 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16
return PM3_SUCCESS;
}
// select a LTO-CM tag. Send WUPA and RID.
static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) {
// Todo: implement anticollision
@@ -75,26 +81,27 @@ static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) {
uint16_t resp_len;
uint8_t wupa_cmd[] = {LTO_REQ_STANDARD};
uint8_t select_cmd[] = {LTO_SELECT, 0x20};
uint8_t select_1_cmd[] = {LTO_SELECT_1, 0x70, 0, 0, 0, 0, 0};
uint8_t select_1_cmd[] = {LTO_SELECT, 0x70, 0, 0, 0, 0, 0};
lto_switch_on_field();
resp_len = 2;
int status = lto_send_cmd_raw(wupa_cmd, sizeof(wupa_cmd), resp, &resp_len, verbose);
int status = lto_send_cmd_raw(wupa_cmd, sizeof(wupa_cmd), resp, &resp_len, false, verbose);
if (status == PM3_ETIMEOUT || status == PM3_ESOFT) {
lto_switch_off_field();
return PM3_ESOFT; // WUPA failed
}
resp_len = id_len;
status = lto_send_cmd_raw(select_cmd, sizeof(select_cmd), id_response, &resp_len, verbose);
status = lto_send_cmd_raw(select_cmd, sizeof(select_cmd), id_response, &resp_len, false, verbose);
if (status == PM3_ETIMEOUT || status == PM3_ESOFT) {
lto_switch_off_field();
return PM3_EWRONGANSVER; // SELECT failed
}
memcpy(select_1_cmd + 2, id_response, sizeof(select_1_cmd) - 2);
resp_len = 1;
status = lto_send_cmd_raw(select_1_cmd, sizeof(select_1_cmd), resp, &resp_len, verbose);
status = lto_send_cmd_raw(select_1_cmd, sizeof(select_1_cmd), resp, &resp_len, true, verbose);
if (status == PM3_ETIMEOUT || status == PM3_ESOFT || resp[0] != 0x0A) {
lto_switch_off_field();
return PM3_EWRONGANSVER; // SELECT failed
@@ -104,7 +111,6 @@ static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) {
return PM3_SUCCESS;
}
static int CmdHfLTOInfo(const char *Cmd) {
uint8_t cmdp = 0;
@@ -126,7 +132,7 @@ static int CmdHfLTOInfo(const char *Cmd) {
return PM3_EINVARG;
}
return infoLTO(true);
return infoLTO(false);
}
int infoLTO(bool verbose) {
@@ -134,18 +140,20 @@ int infoLTO(bool verbose) {
clearCommandBuffer();
uint8_t serial_number[5];
uint8_t serial_len = 0;
uint8_t serial_len = sizeof(serial_number);
int ret_val = lto_select(serial_number, serial_len, verbose);
lto_switch_off_field();
/*
-- "hf 14a raw -a -p -b 7 45"
-- "hf 14a raw -c -p 9320"
-- "hf 14a raw -c -p 9370%s", serial_number
-- "disconnect"
if (ret_val == PM3_SUCCESS) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, " UID : " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number)));
PrintAndLogEx(SUCCESS, "TYPE : ");
// todo: add printing of all configuration
} else {
if (verbose) PrintAndLogEx(WARNING, "LTO-CM card select failed");
}
/* read block:
SendCommandNG(CMD_HF_THINFILM_READ, NULL, 0);
PacketResponseNG resp;

View File

@@ -339,7 +339,7 @@ int CmdLFCommandRead(const char *Cmd) {
// bitbang mode
if (payload.delay == 0) {
if (payload.zeros < 7 || payload.ones < 7) {
PrintAndLogEx(WARNING, "Warning periods cannot be less than 7us in bit bang mode");
PrintAndLogEx(WARNING, "warning periods cannot be less than 7us in bit bang mode");
return PM3_EINVARG;
}
}
@@ -347,15 +347,14 @@ int CmdLFCommandRead(const char *Cmd) {
//Validations
if (errors || cmdp == 0) return usage_lf_cmdread();
PrintAndLogEx(SUCCESS, "Sending");
PrintAndLogEx(SUCCESS, "sending");
clearCommandBuffer();
SendCommandNG(CMD_LF_MOD_THEN_ACQ_RAW_ADC, (uint8_t *)&payload, 8 + datalen);
printf("\n");
PacketResponseNG resp;
uint8_t i = 10;
// 20sec wait loop
while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) && i != 0) {
printf(".");
fflush(stdout);
@@ -365,15 +364,15 @@ int CmdLFCommandRead(const char *Cmd) {
if (resp.status == PM3_SUCCESS) {
if (i) {
PrintAndLogEx(SUCCESS, "Downloading response signal data");
getSamples(0, false);
PrintAndLogEx(SUCCESS, "downloading response signal data");
getSamples(0, true);
return PM3_SUCCESS;
} else {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
}
PrintAndLogEx(WARNING, "Command failed.");
PrintAndLogEx(WARNING, "command failed.");
return PM3_ESOFT;
}
@@ -1214,17 +1213,18 @@ int CmdLFfind(const char *Cmd) {
// only run these tests if device is online
if (isOnline) {
if (IfPm3Hitag()) {
if (readHitagUid()) {
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Hitag") "found!");
return PM3_SUCCESS;
}
}
// only run if graphbuffer is just noise as it should be for hitag
// The improved noise detection will find Cotag.
if (getSignalProperties()->isnoise) {
if (IfPm3Hitag()) {
if (readHitagUid()) {
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Hitag") "found!");
return PM3_SUCCESS;
}
}
if (readMotorolaUid()) {
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Motorola FlexPass ID") "found!");
return PM3_SUCCESS;

View File

@@ -18,6 +18,7 @@
#include "commonutil.h"
#include "hitag.h"
#include "fileutils.h" // savefile
#include "protocols.h" // defines
static int CmdHelp(const char *Cmd);
@@ -35,7 +36,7 @@ static int usage_hitag_sniff(void) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag sniff");
return 0;
return PM3_SUCCESS;
}
static int usage_hitag_sim(void) {
PrintAndLogEx(NORMAL, "Simulate " _YELLOW_("Hitag2 / HitagS")" transponder");
@@ -49,7 +50,7 @@ static int usage_hitag_sim(void) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag sim 2 b lf-hitag-dump");
return 0;
return PM3_SUCCESS;
}
static int usage_hitag_info(void) {
PrintAndLogEx(NORMAL, "Usage: lf hitag info [h] p <pwd>");
@@ -58,7 +59,7 @@ static int usage_hitag_info(void) {
PrintAndLogEx(NORMAL, " p <pwd> password");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag info");
return 0;
return PM3_SUCCESS;
}
/*
static int usage_hitag_dump(void) {
@@ -71,7 +72,7 @@ static int usage_hitag_dump(void) {
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag dump f mydump");
PrintAndLogEx(NORMAL, " lf hitag dump p 4D494B52 f mydump");
return 0;
return PM3_SUCCESS;
}
*/
static int usage_hitag_reader(void) {
@@ -85,12 +86,12 @@ static int usage_hitag_reader(void) {
PrintAndLogEx(NORMAL, " Hitag1 (1*)");
PrintAndLogEx(NORMAL, " Not implemented");
PrintAndLogEx(NORMAL, " Hitag2 (2*)");
PrintAndLogEx(NORMAL, " 21 <password> Read all pages, password mode. Default: 4D494B52 (\"MIKR\")");
PrintAndLogEx(NORMAL, " 21 <password> Read all pages, password mode. Default: " _YELLOW_("4D494B52") "(\"MIKR\")");
PrintAndLogEx(NORMAL, " 22 <nr> <ar> Read all pages, challenge mode");
PrintAndLogEx(NORMAL, " 23 <key> Read all pages, crypto mode. Key format: ISK high + ISK low. Default: 4F4E4D494B52 (\"ONMIKR\")");
PrintAndLogEx(NORMAL, " 23 <key> Read all pages, crypto mode. Key format: ISK high + ISK low. Default: " _YELLOW_("4F4E4D494B52") "(\"ONMIKR\")");
PrintAndLogEx(NORMAL, " 25 Test recorded authentications");
PrintAndLogEx(NORMAL, " 26 Just read UID");
return 0;
return PM3_SUCCESS;
}
static int usage_hitag_writer(void) {
PrintAndLogEx(NORMAL, "Hitag writer functions");
@@ -106,7 +107,7 @@ static int usage_hitag_writer(void) {
PrintAndLogEx(NORMAL, " 24 <key> <page> <byte0...byte3> Write page, crypto mode. Key format: ISK high + ISK low.");
PrintAndLogEx(NORMAL, " Default: 4F4E4D494B52 (\"ONMIKR\"). Set key=0 for no auth");
PrintAndLogEx(NORMAL, " 27 <password> <page> <byte0...byte3> Write page, password mode. Default: 4D494B52 (\"MIKR\")");
return 0;
return PM3_SUCCESS;
}
static int usage_hitag_checkchallenges(void) {
PrintAndLogEx(NORMAL, "Check challenges, load a file with save hitag crypto challenges and test them all.");
@@ -119,19 +120,19 @@ static int usage_hitag_checkchallenges(void) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag cc f lf-hitag-challenges");
return 0;
return PM3_SUCCESS;
}
static int CmdLFHitagList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("hitag");
return 0;
CmdTraceList("hitag2");
return PM3_SUCCESS;
/*
uint8_t *got = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));
if (!got) {
PrintAndLogEx(WARNING, "Cannot allocate memory for trace");
return 2;
return PM3_EMALLOC;
}
// Query for the actual size of the trace
@@ -139,7 +140,7 @@ static int CmdLFHitagList(const char *Cmd) {
if (!GetFromDevice(BIG_BUF, got, PM3_CMD_DATA_SIZE, 0, NULL, 0, &response, 2500, false)) {
PrintAndLogEx(WARNING, "command execution time out");
free(got);
return 2;
return PM3_ETIMEOUT;
}
uint16_t traceLen = response.arg[2];
@@ -148,13 +149,13 @@ static int CmdLFHitagList(const char *Cmd) {
if (p == NULL) {
PrintAndLogEx(WARNING, "Cannot allocate memory for trace");
free(got);
return 2;
return PM3_EMALLOC;
}
got = p;
if (!GetFromDevice(BIG_BUF, got, traceLen, 0, NULL, 0, NULL, 2500, false)) {
PrintAndLogEx(WARNING, "command execution time out");
free(got);
return 2;
return PM3_ETIMEOUT;
}
}
@@ -251,7 +252,7 @@ static int CmdLFHitagList(const char *Cmd) {
}
free(got);
return 0;
return PM3_SUCCES;
*/
}
@@ -262,7 +263,7 @@ static int CmdLFHitagSniff(const char *Cmd) {
clearCommandBuffer();
SendCommandNG(CMD_LF_HITAG_SNIFF, NULL, 0);
return 0;
return PM3_SUCCESS;
}
static int CmdLFHitagSim(const char *Cmd) {
@@ -343,7 +344,7 @@ static int CmdLFHitagSim(const char *Cmd) {
}
free(data);
return 0;
return PM3_SUCCESS;
}
static void printHitagConfiguration(uint8_t config) {
@@ -483,21 +484,20 @@ static int CmdLFHitagInfo(const char *Cmd) {
// read UID
uint32_t uid = 0;
if (getHitagUid(&uid) == false)
return 1;
return PM3_ESOFT;
PrintAndLogEx(SUCCESS, "UID: %08X", uid);
PrintAndLogEx(SUCCESS, "UID: " _YELLOW_("%08X"), uid);
// how to detemine Hitag types?
// read block3, get configuration byte.
PrintAndLogEx(FAILED, _RED_("TODO: This is a hardcoded example!"));
// common configurations.
printHitagConfiguration(0x06);
// printHitagConfiguration(0x06);
//printHitagConfiguration( 0x0E );
//printHitagConfiguration( 0x02 );
//printHitagConfiguration( 0x00 );
//printHitagConfiguration( 0x04 );
return 0;
return PM3_SUCCESS;
}
// TODO: iceman
@@ -550,21 +550,22 @@ static int CmdLFHitagReader(const char *Cmd) {
}
clearCommandBuffer();
SendCommandOLD(cmd, htf, 0, 0, &htd, sizeof(htd));
SendCommandMIX(cmd, htf, 0, 0, &htd, sizeof(htd));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 1;
return PM3_ETIMEOUT;
}
if (resp.oldarg[0] == false) {
PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed");
return 1;
return PM3_ESOFT;
}
uint32_t id = bytes_to_num(resp.data.asBytes, 4);
PrintAndLogEx(SUCCESS, "Valid Hitag2 tag found - UID: %08x", id);
PrintAndLogEx(SUCCESS, " UID: " _YELLOW_("%08x"), id);
if (htf != RHT2F_UID_ONLY) {
PrintAndLogEx(SUCCESS, "Dumping tag memory...");
@@ -575,6 +576,8 @@ static int CmdLFHitagReader(const char *Cmd) {
fnameptr += sprintf(fnameptr, "lf-hitag-");
FillFileNameByUID(fnameptr, data, "-dump", 4);
saveFile(filename, ".bin", data, 48);
saveFileEML(filename, data, 48, 4);
saveFileJSON(filename, jsfHitag, data, 48);
@@ -582,7 +585,7 @@ static int CmdLFHitagReader(const char *Cmd) {
// block3, 1 byte
printHitagConfiguration(data[4 * 3]);
}
return 0;
return PM3_SUCCESS;
}
static int CmdLFHitagCheckChallenges(const char *Cmd) {
@@ -631,7 +634,7 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) {
SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES, 0, 0, 0, NULL, 0);
free(data);
return 0;
return PM3_SUCCESS;
}
static int CmdLFHitagWriter(const char *Cmd) {
@@ -675,14 +678,14 @@ static int CmdLFHitagWriter(const char *Cmd) {
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 1;
return PM3_ETIMEOUT;
}
if (resp.oldarg[0] == false) {
PrintAndLogEx(DEBUG, "DEBUG: Error - hitag write failed");
return 1;
return PM3_ESOFT;
}
return 0;
return PM3_SUCCESS;
}
/*
@@ -692,10 +695,50 @@ static int CmdLFHitagDump(const char *Cmd) {
char ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'h') return usage_hitag_dump();
return 0;
return PM3_SUCCESS;
}
*/
// Annotate HITAG protocol
void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
}
void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
uint8_t cmdbits = (cmd[0] & 0xC0) >> 6;
if (cmdsize == 1) {
if (cmdbits == HITAG2_START_AUTH) {
snprintf(exp, size, "START AUTH");
return;
}
if (cmdbits == HITAG2_HALT) {
snprintf(exp, size, "HALT");
return;
}
}
if (cmdsize == 2) {
if (cmdbits == HITAG2_START_AUTH) {
// C 1 C 0
// 1100 0 00 1 1100 000
uint8_t page = (cmd[0] & 0x38) >> 3;
uint8_t inv_page = ((cmd[0] & 0x1) << 2) | ((cmd[1] & 0xC0) >> 6);
snprintf(exp, size, "READ page(%x) %x", page, inv_page);
return;
}
if (cmdbits == HITAG2_WRITE_PAGE) {
uint8_t page = (cmd[0] & 0x38) >> 3;
uint8_t inv_page = ((cmd[0] & 0x1) << 2) | ((cmd[1] & 0xC0) >> 6);
snprintf(exp, size, "WRITE page(%x) %x", page, inv_page);
return;
}
}
}
void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help" },
{"list", CmdLFHitagList, IfPm3Hitag, "List Hitag trace history" },
@@ -711,7 +754,7 @@ static command_t CommandTable[] = {
static int CmdHelp(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdsHelp(CommandTable);
return 0;
return PM3_SUCCESS;
}
int CmdLFHitag(const char *Cmd) {
@@ -720,5 +763,5 @@ int CmdLFHitag(const char *Cmd) {
}
int readHitagUid(void) {
return CmdLFHitagReader("26") == 0;
return (CmdLFHitagReader("26") == PM3_SUCCESS);
}

View File

@@ -16,5 +16,7 @@
int CmdLFHitag(const char *Cmd);
int readHitagUid(void);
void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
#endif

View File

@@ -17,6 +17,7 @@
#include "cmdhflist.h" // annotations
#include "comms.h" // for sending cmds to device. GetFromBigBuf
#include "fileutils.h" // for saveFile
#include "cmdlfhitag.h" // annotate hitag
static int CmdHelp(const char *Cmd);
@@ -45,7 +46,9 @@ static int usage_trace_list() {
PrintAndLogEx(NORMAL, " iclass - interpret data as iclass communications");
PrintAndLogEx(NORMAL, " legic - interpret data as LEGIC communications");
PrintAndLogEx(NORMAL, " felica - interpret data as ISO18092 / FeliCa communications");
PrintAndLogEx(NORMAL, " hitag - interpret data as Hitag2 / HitagS communications");
PrintAndLogEx(NORMAL, " hitag1 - interpret data as Hitag1 communications");
PrintAndLogEx(NORMAL, " hitag2 - interpret data as Hitag2 communications");
PrintAndLogEx(NORMAL, " hitags - interpret data as HitagS communications");
PrintAndLogEx(NORMAL, " lto - interpret data as LTO-CM communications");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
@@ -281,7 +284,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
crcStatus = iso15693_CRC_check(frame, data_len);
break;
case ISO_7816_4:
case PROTO_HITAG:
case PROTO_HITAG1:
case PROTO_HITAG2:
case PROTO_HITAGS:
default:
break;
}
@@ -301,7 +306,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
&& protocol != ISO_15693
&& protocol != ICLASS
&& protocol != ISO_7816_4
&& protocol != PROTO_HITAG
&& protocol != PROTO_HITAG1
&& protocol != PROTO_HITAG2
&& protocol != PROTO_HITAGS
&& protocol != THINFILM
&& protocol != FELICA
&& protocol != LTO
@@ -385,6 +392,15 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
case LTO:
annotateLTO(explanation, sizeof(explanation), frame, data_len);
break;
case PROTO_HITAG1:
annotateHitag1(explanation, sizeof(explanation), frame, data_len);
break;
case PROTO_HITAG2:
annotateHitag2(explanation, sizeof(explanation), frame, data_len);
break;
case PROTO_HITAGS:
annotateHitagS(explanation, sizeof(explanation), frame, data_len);
break;
default:
break;
}
@@ -593,7 +609,9 @@ int CmdTraceList(const char *Cmd) {
else if (strcmp(type, "15") == 0) protocol = ISO_15693;
else if (strcmp(type, "felica") == 0) protocol = FELICA;
else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE;
else if (strcmp(type, "hitag") == 0) protocol = PROTO_HITAG;
else if (strcmp(type, "hitag1") == 0) protocol = PROTO_HITAG1;
else if (strcmp(type, "hitag2") == 0) protocol = PROTO_HITAG2;
else if (strcmp(type, "hitags") == 0) protocol = PROTO_HITAGS;
else if (strcmp(type, "thinfilm") == 0) protocol = THINFILM;
else if (strcmp(type, "lto") == 0) protocol = LTO;
else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations
@@ -644,8 +662,7 @@ int CmdTraceList(const char *Cmd) {
}
}
PrintAndLogEx(SUCCESS, "Recorded Activity (TraceLen = %lu bytes)", traceLen);
PrintAndLogEx(INFO, "");
PrintAndLogEx(SUCCESS, "Recorded activity (trace len = " _YELLOW_("%lu") "bytes)", traceLen);
/*
if (protocol == FELICA) {
@@ -657,27 +674,27 @@ int CmdTraceList(const char *Cmd) {
tracepos = printHexLine(tracepos, traceLen, trace, protocol);
}
} else {
PrintAndLogEx(NORMAL, "Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
PrintAndLogEx(INFO, _YELLOW_("Start") "= Start of Start Bit, " _YELLOW_("End") "= End of last modulation. " _YELLOW_("Src") "= Source of Transfer");
if (protocol == ISO_14443A || protocol == PROTO_MIFARE || protocol == MFDES || protocol == TOPAZ || protocol == LTO)
PrintAndLogEx(NORMAL, "ISO14443A - All times are in carrier periods (1/13.56MHz)");
PrintAndLogEx(INFO, "ISO14443A - All times are in carrier periods (1/13.56MHz)");
if (protocol == THINFILM)
PrintAndLogEx(NORMAL, "Thinfilm - All times are in carrier periods (1/13.56MHz)");
PrintAndLogEx(INFO, "Thinfilm - All times are in carrier periods (1/13.56MHz)");
if (protocol == ICLASS)
PrintAndLogEx(NORMAL, "iClass - Timings are not as accurate");
PrintAndLogEx(INFO, "iClass - Timings are not as accurate");
if (protocol == LEGIC)
PrintAndLogEx(NORMAL, "LEGIC - Reader Mode: Timings are in ticks (1us == 1.5ticks)\n"
PrintAndLogEx(INFO, "LEGIC - Reader Mode: Timings are in ticks (1us == 1.5ticks)\n"
" Tag Mode: Timings are in sub carrier periods (1/212 kHz == 4.7us)");
if (protocol == ISO_14443B)
PrintAndLogEx(NORMAL, "ISO14443B"); // Timings ?
PrintAndLogEx(INFO, "ISO14443B"); // Timings ?
if (protocol == ISO_15693)
PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate");
PrintAndLogEx(INFO, "ISO15693 - Timings are not as accurate");
if (protocol == ISO_7816_4)
PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet");
if (protocol == PROTO_HITAG)
PrintAndLogEx(NORMAL, "Hitag2 / HitagS - Timings in ETU (8us)");
PrintAndLogEx(INFO, "ISO7816-4 / Smartcard - Timings N/A yet");
if (protocol == PROTO_HITAG1 || protocol == PROTO_HITAG2 || protocol == PROTO_HITAGS)
PrintAndLogEx(INFO, "Hitag1 / Hitag2 / HitagS - Timings in ETU (8us)");
if (protocol == FELICA)
PrintAndLogEx(NORMAL, "ISO18092 / FeliCa - Timings are not as accurate");
PrintAndLogEx(INFO, "ISO18092 / FeliCa - Timings are not as accurate");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation");
PrintAndLogEx(NORMAL, "------------+------------+-----+-------------------------------------------------------------------------+-----+--------------------");

View File

@@ -125,15 +125,16 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
}
}
PrintAndLogEx(SUCCESS, "found " _YELLOW_("%u") "candidate key%s\n", keycount, (keycount > 1) ? "s." : ".");
PrintAndLogEx(SUCCESS, "found " _YELLOW_("%u") "candidate key%s", keycount, (keycount > 1) ? "s." : ".");
*key = UINT64_C(-1);
uint8_t keyBlock[PM3_CMD_DATA_SIZE];
uint32_t max_keys = KEYS_IN_BLOCK;
for (uint32_t i = 0; i < keycount; i += max_keys) {
uint32_t size = keycount - i > max_keys ? max_keys : keycount - i;
for (uint32_t j = 0; j < size; j++) {
uint8_t size = keycount - i > max_keys ? max_keys : keycount - i;
register uint8_t j;
for (j = 0; j < size; j++) {
if (par_list == 0) {
num_to_bytes(last_keylist[i * max_keys + j], 6, keyBlock + (j * 6));
} else {
@@ -159,6 +160,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
free(keylist);
return PM3_SUCCESS;
}
int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key) {
*key = -1;
clearCommandBuffer();
@@ -308,7 +310,7 @@ int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultk
}
// Compare 16 Bits out of cryptostate
static int Compare16Bits(const void *a, const void *b) {
inline static int Compare16Bits(const void *a, const void *b) {
if ((*(uint64_t *)b & 0x00ff000000ff0000) == (*(uint64_t *)a & 0x00ff000000ff0000)) return 0;
if ((*(uint64_t *)b & 0x00ff000000ff0000) > (*(uint64_t *)a & 0x00ff000000ff0000)) return 1;
return -1;
@@ -330,13 +332,14 @@ __attribute__((force_align_arg_pointer))
statelist->len = p1 - statelist->head.slhead;
statelist->tail.sltail = --p1;
qsort(statelist->head.slhead, statelist->len, sizeof(uint64_t), Compare16Bits);
return statelist->head.slhead;
}
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate) {
uint16_t i;
uint32_t uid;
StateList_t statelists[2];
struct Crypto1State *p1, *p2, *p3, *p4;
@@ -385,7 +388,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
memcpy(&uid, package->cuid, sizeof(package->cuid));
for (i = 0; i < 2; i++) {
for (uint8_t i = 0; i < 2; i++) {
statelists[i].blockNo = package->block;
statelists[i].keyType = package->keytype;
statelists[i].uid = uid;
@@ -402,11 +405,11 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
pthread_t thread_id[2];
// create and run worker threads
for (i = 0; i < 2; i++)
for (uint8_t i = 0; i < 2; i++)
pthread_create(thread_id + i, NULL, nested_worker_thread, &statelists[i]);
// wait for threads to terminate:
for (i = 0; i < 2; i++)
for (uint8_t i = 0; i < 2; i++)
pthread_join(thread_id[i], (void *)&statelists[i].head.slhead);
// the first 16 Bits of the cryptostate already contain part of our key.
@@ -457,6 +460,8 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
uint32_t keycnt = statelists[0].len;
if (keycnt == 0) goto out;
PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "candidate keys", keycnt);
memset(resultKey, 0, 6);
uint64_t key64 = -1;
@@ -464,11 +469,14 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
uint32_t max_keys = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt;
uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00};
for (i = 0; i < keycnt; i += max_keys) {
uint64_t start_time = msclock();
int size = keycnt - i > max_keys ? max_keys : keycnt - i;
for (uint32_t i = 0; i < keycnt; i += max_keys) {
for (int j = 0; j < size; j++) {
uint8_t size = keycnt - i > max_keys ? max_keys : keycnt - i;
register uint8_t j;
for (j = 0; j < size; j++) {
crypto1_get_lfsr(statelists[0].head.slhead + i, &key64);
num_to_bytes(key64, 6, keyBlock + j * 6);
}
@@ -485,6 +493,13 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
);
return -5;
}
float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(msclock() - start_time) * 1000.0;
start_time = msclock();
if ( i + 1 % 10 == 0)
PrintAndLogEx(INFO, " %8d keys left | %5.1f keys/sec | worst case %6.1f seconds remaining", keycnt - i, bruteforce_per_second, (keycnt-i) / bruteforce_per_second);
}
out:
@@ -499,7 +514,7 @@ out:
}
int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey) {
uint16_t i;
uint32_t uid;
StateList_t statelists[1];
struct Crypto1State *p1, *p3;
@@ -589,16 +604,18 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
uint32_t max_keys_slice = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt;
uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00};
for (i = 0; i < keycnt; i += max_keys_slice) {
uint64_t start_time = msclock();
for (uint32_t i = 0; i < keycnt; i += max_keys_slice) {
PrintAndLogEx(INFO, "Testing %u / %u ", i, keycnt);
// PrintAndLogEx(INFO, "Testing %u / %u ", i, keycnt);
key64 = 0;
int size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i;
uint8_t size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i;
// copy x keys to device.
for (int j = 0; j < size; j++) {
register uint8_t j;
for (j = 0; j < size; j++) {
crypto1_get_lfsr(statelists[0].head.slhead + i + j, &key64);
num_to_bytes(key64, 6, keyBlock + j * 6);
}
@@ -617,6 +634,12 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
);
return PM3_SUCCESS;
}
float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(msclock() - start_time) * 1000.0;
start_time = msclock();
if ( i+1 % 10 == 0)
PrintAndLogEx(INFO, " %8d keys left | %5.1f keys/sec | worst case %6.1f seconds remaining", keycnt - i, bruteforce_per_second, (keycnt-i) / bruteforce_per_second);
}
out: