Merge branch 'master' into allin

update 201127
This commit is contained in:
tharexde
2020-11-27 21:24:33 +01:00
44 changed files with 3012 additions and 1877 deletions

View File

@@ -10,3 +10,5 @@ AEA684A6DAB23278 # AA1
F0E1D2C3B4A59687 # Kd from PicoPass 2k documentation
5CBCF1DA45D5FB4F # PicoPass Default Exchange Key
31ad7ebd2f282168 # From HID multiclassSE reader
6EFD46EFCBB3C875 # From pastebin: https://pastebin.com/uHqpjiuU
E033CA419AEE43F9 # From pastebin: https://pastebin.com/uHqpjiuU

View File

@@ -1275,4 +1275,7 @@ AABAFFCC7612
# gamefactory
# ozdilek
#
17D071403C20
17D071403C20
#
534F4C415249
534f4c303232

View File

@@ -1178,11 +1178,11 @@ static int CmdHF14AAPDU(const char *Cmd) {
}
CLIParserFree(ctx);
PrintAndLogEx(SUCCESS, "( " _YELLOW_("%s%s%s")" )",
activateField ? "select" : "",
leaveSignalON ? ", keep" : "",
decodeTLV ? ", TLV" : ""
);
PrintAndLogEx(SUCCESS, "( " _YELLOW_("%s%s%s")" )",
activateField ? "select" : "",
leaveSignalON ? ", keep" : "",
decodeTLV ? ", TLV" : ""
);
PrintAndLogEx(SUCCESS, ">>> %s", sprint_hex_inrow(data, datalen));
if (decodeAPDU) {
@@ -1217,7 +1217,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
"Sends an raw bytes over ISO14443a. With option to use TOPAZ 14a mode.",
"hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n"
"hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n"
);
);
void *argtable[] = {
arg_param_begin,
@@ -1344,13 +1344,13 @@ static int waitCmd(bool i_select, uint32_t timeout) {
if (i_select == false && len >= 3) {
bool crc = check_crc(CRC_14443_A, data, len);
char s[16];
sprintf(s,
(crc) ? _GREEN_("%02X %02X") : _RED_("%02X %02X"),
data[len - 2],
data[len - 1]
);
sprintf(s,
(crc) ? _GREEN_("%02X %02X") : _RED_("%02X %02X"),
data[len - 2],
data[len - 1]
);
PrintAndLogEx(SUCCESS, "%s[ %s ]", sprint_hex(data, len - 2), s);
} else {

View File

@@ -1725,7 +1725,7 @@ static int CmdHF15Write(const char *Cmd) {
AddCrc15(req, reqlen);
reqlen += 2;
PrintAndLogEx(INFO, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum);
PrintAndLogEx(INFO, "iso15693 writing to page %02d (0x%02X) | data [ %s ] ", pagenum, pagenum, sprint_hex(req, reqlen));
PacketResponseNG resp;
clearCommandBuffer();

File diff suppressed because it is too large Load Diff

View File

@@ -5444,7 +5444,7 @@ static command_t CommandTable[] = {
{"esave", CmdHF14AMfESave, IfPm3Iso14443a, "Save to file emul dump"},
{"eset", CmdHF14AMfESet, IfPm3Iso14443a, "Set simulator memory block"},
{"eview", CmdHF14AMfEView, IfPm3Iso14443a, "View emul memory"},
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic") " -----------------------"},
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen1") " -----------------------"},
{"cgetblk", CmdHF14AMfCGetBlk, IfPm3Iso14443a, "Read block"},
{"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector"},
{"cload", CmdHF14AMfCLoad, IfPm3Iso14443a, "Load dump"},

View File

@@ -395,9 +395,9 @@ static char *getCardSizeStr(uint8_t fsize) {
// is LSB set?
if (fsize & 1)
snprintf(retStr, sizeof(buf), "0x%02X (" _GREEN_("%d - %d bytes") ")", fsize, usize, lsize);
snprintf(retStr, sizeof(buf), "0x%02X ( " _GREEN_("%d - %d bytes") " )", fsize, usize, lsize);
else
snprintf(retStr, sizeof(buf), "0x%02X (" _GREEN_("%d bytes") ")", fsize, lsize);
snprintf(retStr, sizeof(buf), "0x%02X ( " _GREEN_("%d bytes") " )", fsize, lsize);
return buf;
}
@@ -407,14 +407,14 @@ static char *getProtocolStr(uint8_t id, bool hw) {
char *retStr = buf;
if (id == 0x04) {
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id);
snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("ISO 14443-3 MIFARE, 14443-4") " )", id);
} else if (id == 0x05) {
if (hw)
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-2, 14443-3") ")", id);
snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("ISO 14443-2, 14443-3") " )", id);
else
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-3, 14443-4") ")", id);
snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("ISO 14443-3, 14443-4") " )", id);
} else {
snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("Unknown") ")", id);
snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("Unknown") " )", id);
}
return buf;
}
@@ -425,19 +425,21 @@ static char *getVersionStr(uint8_t major, uint8_t minor) {
char *retStr = buf;
if (major == 0x00)
snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire MF3ICD40") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire MF3ICD40") " )", major, minor);
else if (major == 0x01 && minor == 0x00)
snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire EV1") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV1") " )", major, minor);
else if (major == 0x12 && minor == 0x00)
snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire EV2") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV2") " )", major, minor);
else if (major == 0x42 && minor == 0x00)
snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV2") " )", major, minor);
else if (major == 0x33 && minor == 0x00)
snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire EV3") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV3") " )", major, minor);
else if (major == 0x30 && minor == 0x00)
snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire Light") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire Light") " )", major, minor);
else if (major == 0x10 && minor == 0x00)
snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("NTAG413DNA") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("NTAG413DNA") " )", major, minor);
else
snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("Unknown") ")", major, minor);
snprintf(retStr, sizeof(buf), "%x.%x ( " _YELLOW_("Unknown") " )", major, minor);
return buf;
//04 01 01 01 00 1A 05
@@ -1180,7 +1182,7 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n
key 8b
cpy 8b
crc 2b
padding
padding
*/
// Variable length ciphered key data 24-42 bytes plus padding..
@@ -1188,11 +1190,11 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n
sAPDU apdu = {0x90, MFDES_CHANGE_KEY, 0x00, 0x00, 0x01, data}; // 0xC4
size_t cmdcnt = 0;
uint8_t new_key_length = 16;
switch (new_algo) {
case MFDES_ALGO_DES:
// double
// double
memcpy(data + cmdcnt + 1, new_key, new_key_length);
memcpy(data + cmdcnt + 1 + new_key_length, new_key, new_key_length);
break;
@@ -1381,15 +1383,43 @@ static int handler_desfire_signature(uint8_t *signature, size_t *signature_len)
return res;
}
// --- KEY SETTING
static int desfire_print_keysetting(uint8_t key_settings, uint8_t num_keys, int algo) {
// --- KEY VERSION
static int desfire_print_keyversion(uint8_t key_idx, uint8_t key_version) {
PrintAndLogEx(SUCCESS, " Key [%u] Version : %d (0x%02x)", key_idx, key_version, key_version);
return PM3_SUCCESS;
}
static int handler_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) {
if (num_versions == NULL) {
PrintAndLogEx(DEBUG, "NUM_VERSIONS=NULL");
return PM3_EINVARG;
}
sAPDU apdu = {0x90, MFDES_GET_KEY_VERSION, 0x00, 0x00, 0x01, &curr_key}; //0x64
uint32_t recv_len = 0;
uint16_t sw = 0;
int res = send_desfire_cmd(&apdu, false, num_versions, &recv_len, &sw, 0, true);
if (res != PM3_SUCCESS)
return res;
if (sw != status(MFDES_S_OPERATION_OK))
return PM3_ESOFT;
return res;
}
// --- KEY SETTING Application Master Key
static int desfire_print_amk_keysetting(uint8_t key_settings, uint8_t num_keys, int algo) {
PrintAndLogEx(SUCCESS, " AID Key settings : 0x%02x", key_settings);
// 2 MSB denotes
const char *str = " Max key number and type : %d, " _YELLOW_("%s");
if (algo == MFDES_ALGO_DES) PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "(3)DES");
else if (algo == MFDES_ALGO_AES) PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "AES");
else if (algo == MFDES_ALGO_3K3DES) PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "3K3DES");
if (algo == MFDES_ALGO_DES)
PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "(3)DES");
else if (algo == MFDES_ALGO_AES)
PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "AES");
else if (algo == MFDES_ALGO_3K3DES)
PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "3K3DES");
//PrintAndLogEx(SUCCESS, " Max number of keys in AID : %d", num_keys & 0x3F);
PrintAndLogEx(INFO, "-------------------------------------------------------------");
@@ -1408,14 +1438,69 @@ static int desfire_print_keysetting(uint8_t key_settings, uint8_t num_keys, int
PrintAndLogEx(SUCCESS, " -- All keys (except AMK,see Bit0) within this application are frozen");
break;
default:
PrintAndLogEx(SUCCESS, " -- Authentication with the specified key is necessary to change any key.\nA change key and a PICC master key (CMK) can only be changed after authentication with the master key.\nFor keys other then the master or change key, an authentication with the same key is needed.");
PrintAndLogEx(SUCCESS,
" -- Authentication with the specified key is necessary to change any key.\n"
"A change key and a PICC master key (CMK) can only be changed after authentication with the master key.\n"
"For keys other then the master or change key, an authentication with the same key is needed."
);
break;
}
PrintAndLogEx(SUCCESS, " [0x08] Configuration changeable : %s", (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO");
PrintAndLogEx(SUCCESS, " [0x04] AMK required for create/delete : %s", (key_settings & (1 << 2)) ? "NO" : "YES");
PrintAndLogEx(SUCCESS, " [0x02] Directory list access with AMK : %s", (key_settings & (1 << 1)) ? "NO" : "YES");
PrintAndLogEx(SUCCESS, " [0x01] AMK is changeable : %s", (key_settings & (1 << 0)) ? _GREEN_("YES") : "NO");
PrintAndLogEx(SUCCESS, " [1000] AMK Configuration changeable : %s", (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)");
PrintAndLogEx(SUCCESS, " [0100] AMK required for create/delete : %s", (key_settings & (1 << 2)) ? "NO" : "YES");
PrintAndLogEx(SUCCESS, " [0010] Directory list access with AMK : %s", (key_settings & (1 << 1)) ? "NO" : "YES");
PrintAndLogEx(SUCCESS, " [0001] AMK is changeable : %s", (key_settings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)");
return PM3_SUCCESS;
}
// --- KEY SETTING PICC Master Key (CMK)
static int desfire_print_piccmk_keysetting(uint8_t key_settings, uint8_t num_keys, int algo) {
//PrintAndLogEx(INFO, "--- " _CYAN_("PICC Master Key (CMK) settings"));
// number of Master keys (0x01)
PrintAndLogEx(SUCCESS, " Number of Masterkeys : " _YELLOW_("%u"), (num_keys & 0x3F));
const char *str = " Operation of PICC master key : " _YELLOW_("%s");
if (algo == MFDES_ALGO_DES)
PrintAndLogEx(SUCCESS, str, "(3)DES");
else if (algo == MFDES_ALGO_AES)
PrintAndLogEx(SUCCESS, str, "AES");
else if (algo == MFDES_ALGO_3K3DES)
PrintAndLogEx(SUCCESS, str, "3K3DES");
uint8_t cmk_num_versions = 0;
if (handler_desfire_keyversion(0, &cmk_num_versions) == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, " PICC Master key Version : " _YELLOW_("%d (0x%02x)"), cmk_num_versions, cmk_num_versions);
}
PrintAndLogEx(INFO, " ----------------------------------------------------------");
// Authentication tests
int res = test_desfire_authenticate();
if (res == PM3_SUCCESS)
PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO");
res = test_desfire_authenticate_iso();
if (res == PM3_SUCCESS)
PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO");
res = test_desfire_authenticate_aes();
if (res == PM3_SUCCESS)
PrintAndLogEx(SUCCESS, " [0xAA] Authenticate AES : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO");
PrintAndLogEx(INFO, "-------------------------------------------------------------");
PrintAndLogEx(INFO, " Key setting: 0x%02X [%c%c%c%c]",
key_settings,
(key_settings & (1 << 3)) ? '1' : '0',
(key_settings & (1 << 2)) ? '1' : '0',
(key_settings & (1 << 1)) ? '1' : '0',
(key_settings & (1 << 0)) ? '1' : '0'
);
PrintAndLogEx(SUCCESS, " [1...] CMK Configuration changeable : %s", (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)");
PrintAndLogEx(SUCCESS, " [.1..] CMK required for create/delete : %s", (key_settings & (1 << 2)) ? _GREEN_("NO") : "YES");
PrintAndLogEx(SUCCESS, " [..1.] Directory list access with CMK : %s", (key_settings & (1 << 1)) ? _GREEN_("NO") : "YES");
PrintAndLogEx(SUCCESS, " [...1] CMK is changeable : %s", (key_settings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)");
return PM3_SUCCESS;
}
@@ -1445,31 +1530,6 @@ static int handler_desfire_getkeysettings(uint8_t *key_settings, uint8_t *num_ke
return res;
}
// --- KEY VERSION
static int desfire_print_keyversion(uint8_t key_idx, uint8_t key_version) {
PrintAndLogEx(SUCCESS, " Key [%u] Version : %d (0x%02x)", key_idx, key_version, key_version);
return PM3_SUCCESS;
}
static int handler_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) {
if (num_versions == NULL) {
PrintAndLogEx(DEBUG, "NUM_VERSIONS=NULL");
return PM3_EINVARG;
}
sAPDU apdu = {0x90, MFDES_GET_KEY_VERSION, 0x00, 0x00, 0x01, &curr_key}; //0x64
uint32_t recv_len = 0;
uint16_t sw = 0;
int res = send_desfire_cmd(&apdu, false, num_versions, &recv_len, &sw, 0, true);
if (res != PM3_SUCCESS)
return res;
if (sw != status(MFDES_S_OPERATION_OK))
return PM3_ESOFT;
return res;
}
static int handler_desfire_getuid(uint8_t *uid) {
if (uid == NULL) {
PrintAndLogEx(DEBUG, "UID=NULL");
@@ -1585,14 +1645,14 @@ static int handler_desfire_select_application(uint8_t *aid) {
sAPDU apdu = {0x90, MFDES_SELECT_APPLICATION, 0x00, 0x00, 0x03, aid}; //0x5a
uint32_t recv_len = 0;
uint16_t sw = 0;
int res = send_desfire_cmd(&apdu, !tag->rf_field_on, NULL, &recv_len, &sw, sizeof(dfname_t), true);
if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING,
_RED_(" Can't select AID 0x%X -> %s"),
(aid[2] << 16) + (aid[1] << 8) + aid[0],
GetErrorString(res, &sw)
);
_RED_(" Can't select AID 0x%X -> %s"),
(aid[2] << 16) + (aid[1] << 8) + aid[0],
GetErrorString(res, &sw)
);
DropFieldDesfire();
return res;
}
@@ -1672,17 +1732,17 @@ static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid
apdu.Lc = apdu.Lc - sizeof(aidhdr->fid);
}
uint8_t *data = NULL;
// skip over FID if not used.
if (usefid == false && usename) {
data = calloc(apdu.Lc, sizeof(uint8_t));
apdu.data = data;
memcpy(data, aidhdr->aid, sizeof(aidhdr->aid));
data[3] = aidhdr->keysetting1;
data[4] = aidhdr->keysetting2;
memcpy(data + 5, aidhdr->name, sizeof(aidhdr->name));
PrintAndLogEx(INFO, "new data: %s", sprint_hex_inrow(data, apdu.Lc));
}
@@ -2006,6 +2066,8 @@ static int handler_desfire_create_backup_file(mfdes_file_t *file) {
static int getKeySettings(uint8_t *aid) {
if (aid == NULL) return PM3_EINVARG;
uint8_t num_keys = 0;
uint8_t key_setting = 0;
int res = 0;
if (memcmp(aid, "\x00\x00\x00", 3) == 0) {
@@ -2013,50 +2075,15 @@ static int getKeySettings(uint8_t *aid) {
//PrintAndLogEx(INFO, "--- " _CYAN_("CMK - PICC, Card Master Key settings"));
// KEY Settings - AMK
uint8_t num_keys = 0;
uint8_t key_setting = 0;
mifare_des_authalgo_t algo = MFDES_ALGO_DES;
res = key_setting_to_algo(aid, &key_setting, &algo, &num_keys);
if (res == PM3_SUCCESS) {
// number of Master keys (0x01)
PrintAndLogEx(SUCCESS, " Number of Masterkeys : " _YELLOW_("%u"), (num_keys & 0x3F));
PrintAndLogEx(SUCCESS, " [0x08] Configuration changeable : %s", (key_setting & (1 << 3)) ? _GREEN_("YES") : "NO");
PrintAndLogEx(SUCCESS, " [0x04] CMK required for create/delete : %s", (key_setting & (1 << 2)) ? _GREEN_("YES") : "NO");
PrintAndLogEx(SUCCESS, " [0x02] Directory list access with CMK : %s", (key_setting & (1 << 1)) ? _GREEN_("YES") : "NO");
PrintAndLogEx(SUCCESS, " [0x01] CMK is changeable : %s", (key_setting & (1 << 0)) ? _GREEN_("YES") : "NO");
desfire_print_piccmk_keysetting(key_setting, num_keys, algo);
} else {
PrintAndLogEx(WARNING, _RED_(" Can't read Application Master key settings"));
PrintAndLogEx(WARNING, _RED_(" Can't read PICC Master key settings"));
}
const char *str = " Operation of PICC master key : " _YELLOW_("%s");
if (algo == MFDES_ALGO_DES) PrintAndLogEx(SUCCESS, str, "(3)DES");
else if (algo == MFDES_ALGO_AES) PrintAndLogEx(SUCCESS, str, "AES");
else if (algo == MFDES_ALGO_3K3DES) PrintAndLogEx(SUCCESS, str, "3K3DES");
uint8_t cmk_num_versions = 0;
if (handler_desfire_keyversion(0, &cmk_num_versions) == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, " PICC Master key Version : " _YELLOW_("%d (0x%02x)"), cmk_num_versions, cmk_num_versions);
PrintAndLogEx(INFO, " ----------------------------------------------------------");
}
// Authentication tests
res = test_desfire_authenticate();
if (res == PM3_ETIMEOUT) return res;
PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO");
res = test_desfire_authenticate_iso();
if (res == PM3_ETIMEOUT) return res;
PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO");
res = test_desfire_authenticate_aes();
if (res == PM3_ETIMEOUT) return res;
PrintAndLogEx(SUCCESS, " [0xAA] Authenticate AES : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO");
PrintAndLogEx(INFO, "-------------------------------------------------------------");
} else {
// AID - APPLICATION MASTER KEYS
@@ -2065,12 +2092,10 @@ static int getKeySettings(uint8_t *aid) {
if (res != PM3_SUCCESS) return res;
// KEY Settings - AMK
uint8_t num_keys = 0;
uint8_t key_setting = 0;
mifare_des_authalgo_t algo = MFDES_ALGO_DES;
res = key_setting_to_algo(aid, &key_setting, &algo, &num_keys);
if (res == PM3_SUCCESS) {
desfire_print_keysetting(key_setting, num_keys, algo);
desfire_print_amk_keysetting(key_setting, num_keys, algo);
} else {
PrintAndLogEx(WARNING, _RED_(" Can't read Application Master key settings"));
}
@@ -2393,7 +2418,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
if (usefid)
memcpy(aidhdr.fid, fid, sizeof(aidhdr.fid));
if (usename)
if (usename)
memcpy(aidhdr.name, name, sizeof(aidhdr.name));
PrintAndLogEx(INFO, "Creating AID using:");
@@ -2405,14 +2430,14 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
if (usename)
PrintAndLogEx(INFO, "DF Name %s", aidhdr.name);
/*
uint8_t rootaid[3] = {0x00, 0x00, 0x00};
int res = handler_desfire_select_application(rootaid);
if (res != PM3_SUCCESS) {
DropFieldDesfire();
return res;
}
*/
/*
uint8_t rootaid[3] = {0x00, 0x00, 0x00};
int res = handler_desfire_select_application(rootaid);
if (res != PM3_SUCCESS) {
DropFieldDesfire();
return res;
}
*/
int res = handler_desfire_createapp(&aidhdr, usename, usefid);
DropFieldDesfire();
@@ -3436,6 +3461,8 @@ static int CmdHF14ADesInfo(const char *Cmd) {
PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") " / " _GREEN_("20%02x"), info.details[12], info.details[13]);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Hardware Information"));
PrintAndLogEx(INFO, " raw: %s", sprint_hex_inrow(info.versionHW, sizeof(info.versionHW)));
PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(info.versionHW[0]));
PrintAndLogEx(INFO, " Type: " _YELLOW_("0x%02X"), info.versionHW[1]);
PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), info.versionHW[2]);
@@ -3444,6 +3471,7 @@ static int CmdHF14ADesInfo(const char *Cmd) {
PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(info.versionHW[6], true));
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Software Information"));
PrintAndLogEx(INFO, " raw: %s", sprint_hex_inrow(info.versionSW, sizeof(info.versionSW)));
PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(info.versionSW[0]));
PrintAndLogEx(INFO, " Type: " _YELLOW_("0x%02X"), info.versionSW[1]);
PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), info.versionSW[2]);
@@ -3670,7 +3698,7 @@ static int CmdHF14ADesDump(const char *Cmd) {
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
(void)Cmd; // Cmd is not used so far
DropFieldDesfire();

View File

@@ -1882,7 +1882,7 @@ uint32_t static em4x05_Sniff_GetBlock(char *bits, bool fwd) {
if (parity != (bits[35] - '0'))
parityerror = true;
if (parityerror)
if (parityerror)
PrintAndLogEx(ERR, "parity error : ");
if (!fwd) {

View File

@@ -179,68 +179,56 @@ static int CmdKeriDemod(const char *Cmd) {
return demodKeri(true);
}
static int CmdKeriRead(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
lf_read(false, 10000);
return demodKeri(true);
}
static int CmdKeriClone(const char *Cmd) {
bool q5 = false, em = false;
uint8_t keritype[2] = {'i'}; // default to internalid
int typeLen = 0;
uint32_t fc = 0;
uint32_t cid = 0;
uint32_t internalid = 0;
uint32_t blocks[3] = {
T55x7_TESTMODE_DISABLED |
T55x7_X_MODE |
T55x7_MODULATION_PSK1 |
T55x7_PSKCF_RF_2 |
2 << T55x7_MAXBLOCK_SHIFT,
0,
0
};
// dynamic bitrate used
blocks[0] |= 0xF << 18;
static int CmdKeriReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf keri clone",
"clone a KERI tag to a T55x7, Q5/T5555 or EM4305/4469 tag",
"lf keri clone -t i --id 12345\n"
"lf keri clone -t m --fc 6 --id 12345\n");
CLIParserInit(&ctx, "lf keri reader",
"read a keri tag",
"lf keri reader -@ -> continuous reader mode"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
do {
lf_read(false, 10000);
demodKeri(!cm);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
static int CmdKeriClone(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf keri clone",
"clone a KERI tag to a T55x7, Q5/T5555 or EM4305/4469 tag",
"lf keri clone -t i --cn 12345 -> Internal ID\n"
"lf keri clone -t m --fc 6 --cn 12345 -> MS ID\n");
void *argtable[] = {
arg_param_begin,
arg_lit0("q", "q5", "specify writing to Q5/T5555 tag"),
arg_str0("t", "type", "<m|i>", "Type m - MS, i - Internal ID"),
arg_int0(NULL, "fc", "<dec>", "Facility Code"),
arg_int1(NULL, "id", "<dec>", "Keri ID"),
arg_lit0(NULL, "em", "specify writing to EM4305/4469 tag"),
arg_int1(NULL, "cn", "<dec>", "KERI card ID"),
arg_lit0(NULL, "q5", "specify writing to Q5/T5555 tag"),
arg_lit0(NULL, "em", "specify writing to EM4305/4469 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
char cardtype[16] = {"T55x7"};
if (arg_get_lit(ctx, 1)) {
blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
q5 = true;
}
if (arg_get_lit(ctx, 5)) {
blocks[0] = EM4305_KERI_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
em = true;
}
uint8_t keritype[2] = {'i'}; // default to internalid
int typeLen = sizeof(keritype);
CLIGetStrWithReturn(ctx, 1, keritype, &typeLen);
typeLen = sizeof(keritype);
CLIGetStrWithReturn(ctx, 2, keritype, &typeLen);
fc = arg_get_int_def(ctx, 3, 0);
cid = arg_get_int_def(ctx, 4, 0);
uint32_t fc = arg_get_int_def(ctx, 2, 0);
uint32_t cid = arg_get_int_def(ctx, 3, 0);
bool q5 = arg_get_lit(ctx, 4);
bool em = arg_get_lit(ctx, 5);
CLIParserFree(ctx);
if (q5 && em) {
@@ -249,6 +237,7 @@ static int CmdKeriClone(const char *Cmd) {
}
// Setup card data/build internal id
uint32_t internalid = 0;
switch (keritype[0]) {
case 'i' : // Internal ID
// MSB is ONE
@@ -262,6 +251,24 @@ static int CmdKeriClone(const char *Cmd) {
return PM3_EINVARG;
}
uint32_t blocks[3];
blocks[0] = T55x7_TESTMODE_DISABLED | T55x7_X_MODE | T55x7_MODULATION_PSK1 | T55x7_PSKCF_RF_2 | 2 << T55x7_MAXBLOCK_SHIFT;
// dynamic bitrate used
blocks[0] |= 0xF << 18;
char cardtype[16] = {"T55x7"};
if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
if (em) {
blocks[0] = EM4305_KERI_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
// Prepare and write to card
// 3 LSB is ONE
uint64_t data = ((uint64_t)internalid << 3) + 7;
@@ -288,19 +295,18 @@ static int CmdKeriSim(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf keri sim",
"Enables simulation of KERI card with card number.",
"lf keri sim --id 112233"
"Enables simulation of KERI card with internal ID.\n"
"You supply a KERI card id and it will converted to a KERI internal ID.",
"lf keri sim --cn 112233"
);
void *argtable[] = {
arg_param_begin,
arg_int1(NULL, "id", "<dec>", "KERI Internal ID"),
arg_u64_1(NULL, "id", "<dec>", "KERI card ID"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint64_t internalid = arg_get_int_def(ctx, 1, 0);
uint64_t internalid = arg_get_u64_def(ctx, 1, 0);
CLIParserFree(ctx);
internalid |= 0x80000000;
@@ -314,7 +320,7 @@ static int CmdKeriSim(const char *Cmd) {
bs[j++] = ((internalid >> i) & 1);
}
PrintAndLogEx(SUCCESS, "Simulating KERI - Internal Id: %" PRIu64, internalid);
PrintAndLogEx(SUCCESS, "Simulating KERI - Internal Id " _YELLOW_("%" PRIu64), internalid);
lf_psksim_t *payload = calloc(1, sizeof(lf_psksim_t) + sizeof(bs));
payload->carrier = 2;
@@ -322,8 +328,6 @@ static int CmdKeriSim(const char *Cmd) {
payload->clock = 32;
memcpy(payload->data, bs, sizeof(bs));
PrintAndLogEx(INFO, "Simulating");
clearCommandBuffer();
SendCommandNG(CMD_LF_PSK_SIMULATE, (uint8_t *)payload, sizeof(lf_psksim_t) + sizeof(bs));
free(payload);
@@ -338,11 +342,11 @@ static int CmdKeriSim(const char *Cmd) {
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdKeriDemod, AlwaysAvailable, "Demodulate an KERI tag from the GraphBuffer"},
{"read", CmdKeriRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdKeriClone, IfPm3Lf, "clone KERI tag to T55x7 or Q5/T5555"},
{"sim", CmdKeriSim, IfPm3Lf, "simulate KERI tag"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdKeriDemod, AlwaysAvailable, "Demodulate an KERI tag from the GraphBuffer"},
{"reader", CmdKeriReader, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdKeriClone, IfPm3Lf, "clone KERI tag to T55x7 or Q5/T5555"},
{"sim", CmdKeriSim, IfPm3Lf, "simulate KERI tag"},
{NULL, NULL, NULL, NULL}
};

View File

@@ -9,22 +9,20 @@
// PSK1, RF/32, 64 bits long, at 74 kHz
//-----------------------------------------------------------------------------
#include "cmdlfmotorola.h"
#include <ctype.h> //tolower
#include "commonutil.h" // ARRAYLEN
#include <ctype.h> // tolower
#include "commonutil.h" // ARRAYLEN
#include "common.h"
#include "cmdparser.h" // command_t
#include "comms.h"
#include "ui.h"
#include "cmddata.h"
#include "cmdlf.h"
#include "lfdemod.h" // preamble test
#include "protocols.h" // t55xx defines
#include "cmdlft55xx.h" // clone..
#include "cmdlf.h" // cmdlfconfig
#include "cliparser.h" // cli parse input
#include "lfdemod.h" // preamble test
#include "protocols.h" // t55xx defines
#include "cmdlft55xx.h" // clone..
#include "cmdlf.h" // cmdlfconfig
#include "cliparser.h" // cli parse input
#include "cmdlfem4x05.h" // EM defines
static int CmdHelp(const char *Cmd);
@@ -124,7 +122,22 @@ static int CmdMotorolaDemod(const char *Cmd) {
return demodMotorola(true);
}
static int CmdMotorolaRead(const char *Cmd) {
static int CmdMotorolaReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf motorola reader",
"read a Motorola tag",
"lf motorola reader -@ -> continuous reader mode"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
// Motorola Flexpass seem to work at 74 kHz
// and take about 4400 samples to befor modulating
sample_config sc = {
@@ -138,61 +151,86 @@ static int CmdMotorolaRead(const char *Cmd) {
};
lf_config(&sc);
// 64 * 32 * 2 * n-ish
lf_read(false, 5000);
do {
// 64 * 32 * 2 * n-ish
lf_read(false, 5000);
demodMotorola(!cm);
} while (cm && !kbd_enter_pressed());
// reset back to 125 kHz
sc.divisor = LF_DIVISOR_125;
sc.samples_to_skip = 0;
lf_config(&sc);
return demodMotorola(true);
return PM3_SUCCESS;
}
static int CmdMotorolaClone(const char *Cmd) {
uint32_t blocks[3] = {0};
uint8_t data[8];
int datalen = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf motorola clone",
"clone Motorola UID to T55x7 or Q5/T5555 tag\n"
"clone Motorola UID to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
"defaults to 64 bit format",
"lf motorola clone -r a0000000a0002021"
"lf motorola clone --raw a0000000a0002021\n"
"lf motorola clone --q5 --raw a0000000a0002021 -> encode for Q5/T5555 tag\n"
"lf motorola clone --em --raw a0000000a0002021 -> encode for EM4305/4469"
);
void *argtable[] = {
arg_param_begin,
arg_strx1("r", "raw", "<hex>", "raw bytes"),
arg_lit0("q", "Q5", "optional - specify writing to Q5/T5555 tag"),
arg_strx1("r", "raw", "<hex>", "raw hex bytes. 8 bytes"),
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
CLIGetHexWithReturn(ctx, 1, data, &datalen);
bool is_t5555 = arg_get_lit(ctx, 2);
int raw_len = 0;
uint8_t raw[8];
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
bool q5 = arg_get_lit(ctx, 2);
bool em = arg_get_lit(ctx, 3);
CLIParserFree(ctx);
//TODO add selection of chip for Q5 or T55x7
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
PrintAndLogEx(INFO, "Target chip " _YELLOW_("%s"), (is_t5555) ? "Q5/T5555" : "T55x7");
//TODO add selection of chip for Q5 or T55x7
uint32_t blocks[3] = {0};
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT);
char cardtype[16] = {"T55x7"};
// Q5
if (q5) {
blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
// EM4305
if (em) {
blocks[0] = EM4305_MOTOROLA_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
blocks[1] = bytes_to_num(raw, 4);
blocks[2] = bytes_to_num(raw + 4, 4);
// config for Motorola 64 format (RF/32;PSK1 with RF/2; Maxblock=2)
PrintAndLogEx(INFO, "Preparing to clone Motorola 64bit tag");
PrintAndLogEx(INFO, "Using raw " _GREEN_("%s"), sprint_hex_inrow(data, datalen));
if (is_t5555)
blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;
else
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT);
blocks[1] = bytes_to_num(data, 4);
blocks[2] = bytes_to_num(data + 4, 4);
PrintAndLogEx(INFO, "Preparing to clone Motorola 64bit to " _YELLOW_("%s") " with raw " _GREEN_("%s")
, cardtype
, sprint_hex_inrow(raw, sizeof(raw))
);
print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
int res;
if (em) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf motorola read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf motorola reader`") " to verify");
return res;
}
@@ -205,11 +243,11 @@ static int CmdMotorolaSim(const char *Cmd) {
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdMotorolaDemod, AlwaysAvailable, "Demodulate an MOTOROLA tag from the GraphBuffer"},
{"read", CmdMotorolaRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdMotorolaClone, IfPm3Lf, "clone MOTOROLA tag to T55x7"},
{"sim", CmdMotorolaSim, IfPm3Lf, "simulate MOTOROLA tag"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdMotorolaDemod, AlwaysAvailable, "Demodulate an MOTOROLA tag from the GraphBuffer"},
{"reader", CmdMotorolaReader, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdMotorolaClone, IfPm3Lf, "clone MOTOROLA tag to T55x7"},
{"sim", CmdMotorolaSim, IfPm3Lf, "simulate MOTOROLA tag"},
{NULL, NULL, NULL, NULL}
};
@@ -266,5 +304,5 @@ int detectMotorola(uint8_t *dest, size_t *size) {
}
int readMotorolaUid(void) {
return (CmdMotorolaRead("") == PM3_SUCCESS);
return (CmdMotorolaReader("") == PM3_SUCCESS);
}

View File

@@ -9,20 +9,21 @@
//-----------------------------------------------------------------------------
#include "cmdlfnexwatch.h"
#include <inttypes.h> // PRIu
#include <inttypes.h> // PRIu
#include <string.h>
#include <ctype.h> // tolower
#include <stdlib.h> // free, alloc
#include "commonutil.h" // ARRAYLEN
#include "cmdparser.h" // command_t
#include <ctype.h> // tolower
#include <stdlib.h> // free, alloc
#include "commonutil.h" // ARRAYLEN
#include "cmdparser.h" // command_t
#include "comms.h"
#include "ui.h"
#include "cmddata.h" // preamblesearch
#include "cmddata.h" // preamblesearch
#include "cmdlf.h"
#include "lfdemod.h"
#include "protocols.h" // t55xx defines
#include "cmdlft55xx.h" // clone..
#include "protocols.h" // t55xx defines
#include "cmdlft55xx.h" // clone..
#include "cmdlfem4x05.h" //
#include "cliparser.h"
typedef enum {
SCRAMBLE,
@@ -31,49 +32,6 @@ typedef enum {
static int CmdHelp(const char *Cmd);
static int usage_lf_nexwatch_clone(void) {
PrintAndLogEx(NORMAL, "clone a Nexwatch tag to a T55x7 tag.");
PrintAndLogEx(NORMAL, "You can use raw hex values or create a credential based on id, mode");
PrintAndLogEx(NORMAL, "and type of credential (Nexkey/Quadrakey)");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf nexwatch clone [h] [b <raw hex>] [c <id>] [m <mode>] [n|q]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " r <raw hex> : raw hex data. 12 bytes max");
PrintAndLogEx(NORMAL, " c <id> : card id (decimal)");
PrintAndLogEx(NORMAL, " m <mode> : mode (decimal) (0-15, defaults to 1)");
PrintAndLogEx(NORMAL, " n : Nexkey credential");
PrintAndLogEx(NORMAL, " q : Quadrakey credential");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf nexwatch clone r 5600000000213C9F8F150C"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf nexwatch clone c 521512301 m 1 n") " -- Nexkey credential");
PrintAndLogEx(NORMAL, _YELLOW_(" lf nexwatch clone c 521512301 m 1 q") " -- Quadrakey credential");
return PM3_SUCCESS;
}
static int usage_lf_nexwatch_sim(void) {
PrintAndLogEx(NORMAL, "Enables simulation of Nexwatch card");
PrintAndLogEx(NORMAL, "You can use raw hex values or create a credential based on id, mode");
PrintAndLogEx(NORMAL, "and type of credential (Nexkey/Quadrakey)");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf nexwatch sim [h] <r raw hex> [c <id>] [m <mode>] [n|q]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " r <raw hex> : raw hex data. 16 bytes max");
PrintAndLogEx(NORMAL, " c <id> : card id (decimal)");
PrintAndLogEx(NORMAL, " m <mode> : mode (decimal) (0-15, defaults to 1)");
PrintAndLogEx(NORMAL, " n : Nexkey credential");
PrintAndLogEx(NORMAL, " q : Quadrakey credential");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf nexwatch sim r 5600000000213C9F8F150C"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf nexwatch sim c 521512301 m 1 n") " -- Nexkey credential");
PrintAndLogEx(NORMAL, _YELLOW_(" lf nexwatch sim c 521512301 m 1 q") " -- Quadrakey credential");
return PM3_SUCCESS;
}
// scramble parity (1234) -> (4231)
static uint8_t nexwatch_parity_swap(uint8_t parity) {
uint8_t a = (((parity >> 3) & 1));
@@ -263,168 +221,230 @@ static int CmdNexWatchDemod(const char *Cmd) {
return demodNexWatch(true);
}
//by marshmellow
//see ASKDemod for what args are accepted
static int CmdNexWatchRead(const char *Cmd) {
(void)Cmd;
lf_read(false, 20000);
return demodNexWatch(true);
static int CmdNexWatchReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf nexwatch reader",
"read a nexwatch tag",
"lf nexwatch reader -@ -> continuous reader mode"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
do {
lf_read(false, 20000);
demodNexWatch(!cm);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
static int CmdNexWatchClone(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf nexwatch clone",
"clone a Nexwatch tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
"You can use raw hex values or create a credential based on id, mode\n"
"and type of credential (Nexkey / Quadrakey)",
"lf nexwatch clone --raw 5600000000213C9F8F150C00\n"
"lf nexwatch clone --cn 521512301 -m 1 -n -> Nexkey credential\n"
"lf nexwatch clone --cn 521512301 -m 1 -q -> Quadrakey credential\n"
);
// 56000000 00213C9F 8F150C00
uint32_t blocks[4];
bool use_raw = false;
bool errors = false;
uint8_t cmdp = 0;
int datalen = 0;
uint8_t magic = 0xBE;
uint32_t cn = 0;
uint8_t rawhex[12] = {0x56, 0};
void *argtable[] = {
arg_param_begin,
arg_str0("r", "raw", "<hex>", "raw hex data. 12 bytes"),
arg_u64_0(NULL, "cn", "<dec>", "card id"),
arg_u64_0("m", "mode", "<dec>", "mode (decimal) (0-15, defaults to 1)"),
arg_lit0("n", NULL, "Nexkey credential"),
arg_lit0("q", NULL, "Quadrakey credential"),
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_lf_nexwatch_clone();
case 'r': {
int res = param_gethex_to_eol(Cmd, cmdp + 1, rawhex, sizeof(rawhex), &datalen);
if (res != 0)
errors = true;
int raw_len = 0;
// skip first block, 3*4 = 12 bytes left
uint8_t raw[12] = {0x56, 0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
use_raw = true;
cmdp += 2;
break;
}
case 'c': {
cn = param_get32ex(Cmd, cmdp + 1, 0, 10);
uint32_t scrambled;
nexwatch_scamble(SCRAMBLE, &cn, &scrambled);
num_to_bytes(scrambled, 4, rawhex + 5);
cmdp += 2;
break;
}
case 'm': {
uint8_t mode = param_get8ex(Cmd, cmdp + 1, 1, 10);
mode &= 0x0F;
rawhex[9] |= (mode << 4);
cmdp += 2;
break;
}
case 'n': {
magic = 0x88;
cmdp++;
break;
}
case 'q': {
magic = 0xBE;
cmdp++;
break;
}
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
uint32_t cn = arg_get_u32_def(ctx, 2, -1);
uint32_t mode = arg_get_u32_def(ctx, 3, -1);
bool use_nexkey = arg_get_lit(ctx, 4);
bool use_quadrakey = arg_get_lit(ctx, 5);
bool q5 = arg_get_lit(ctx, 6);
bool em = arg_get_lit(ctx, 7);
CLIParserFree(ctx);
if (use_nexkey && use_quadrakey) {
PrintAndLogEx(FAILED, "Can't specify both Nexkey and Quadrakey at the same time");
return PM3_EINVARG;
}
if (errors || cmdp == 0) return usage_lf_nexwatch_clone();
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
// 56000000 00213C9F 8F150C00
bool use_raw = (raw_len != 0);
if (use_raw && cn != -1) {
PrintAndLogEx(FAILED, "Can't specify both Raw and Card id at the same time");
return PM3_EINVARG;
}
if (cn != -1) {
uint32_t scrambled;
nexwatch_scamble(SCRAMBLE, &cn, &scrambled);
num_to_bytes(scrambled, 4, raw + 5);
}
if (mode != -1) {
if (mode > 15) {
mode = 1;
}
mode &= 0x0F;
raw[9] |= (mode << 4);
}
uint8_t magic = 0xBE;
if (use_nexkey)
magic = 0x88;
if (use_quadrakey)
magic = 0xBE;
uint32_t blocks[4];
//Nexwatch - compat mode, PSK, data rate 40, 3 data blocks
blocks[0] = T55x7_MODULATION_PSK1 | T55x7_BITRATE_RF_32 | 3 << T55x7_MAXBLOCK_SHIFT;
char cardtype[16] = {"T55x7"};
// Q5
if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
// EM4305
if (em) {
blocks[0] = EM4305_NEXWATCH_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
if (use_raw == false) {
uint8_t parity = nexwatch_parity(rawhex + 5) & 0xF;
rawhex[9] |= parity;
rawhex[10] |= nexwatch_checksum(magic, cn, parity);
uint8_t parity = nexwatch_parity(raw + 5) & 0xF;
raw[9] |= parity;
raw[10] |= nexwatch_checksum(magic, cn, parity);
}
for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) {
blocks[i] = bytes_to_num(rawhex + ((i - 1) * 4), sizeof(uint32_t));
blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t));
}
PrintAndLogEx(INFO, "Preparing to clone NexWatch to T55x7 with raw hex");
PrintAndLogEx(INFO, "Preparing to clone NexWatch to " _YELLOW_("%s") " raw " _YELLOW_("%s"), cardtype, sprint_hex_inrow(raw, sizeof(raw)));
print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
int res;
if (em) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf nexwatch read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf nexwatch reader`") " to verify");
return res;
}
static int CmdNexWatchSim(const char *Cmd) {
uint8_t cmdp = 0;
bool errors = false;
bool use_raw = false;
uint8_t rawhex[12] = {0x56, 0};
int rawlen = sizeof(rawhex);
uint8_t magic = 0xBE;
uint32_t cn = 0;
uint8_t bs[128];
memset(bs, 0, sizeof(bs));
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf nexwatch sim",
"Enables simulation of secura card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.\n"
"You can use raw hex values or create a credential based on id, mode\n"
"and type of credential (Nexkey/Quadrakey)",
"lf nexwatch sim --raw 5600000000213C9F8F150C00\n"
"lf nexwatch sim --cn 521512301 -m 1 -n -> Nexkey credential\n"
"lf nexwatch sim --cn 521512301 -m 1 -q -> Quadrakey credential"
);
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_lf_nexwatch_clone();
case 'r': {
int res = param_gethex_to_eol(Cmd, cmdp + 1, rawhex, sizeof(rawhex), &rawlen);
if (res != 0)
errors = true;
void *argtable[] = {
arg_param_begin,
arg_str0("r", "raw", "<hex>", "raw hex data. 12 bytes"),
arg_u64_0(NULL, "cn", "<dec>", "card id"),
arg_u64_0("m", "mode", "<dec>", "mode (decimal) (0-15, defaults to 1)"),
arg_lit0("n", NULL, "Nexkey credential"),
arg_lit0("q", NULL, "Quadrakey credential"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
use_raw = true;
cmdp += 2;
break;
}
case 'c': {
cn = param_get32ex(Cmd, cmdp + 1, 0, 10);
uint32_t scrambled;
nexwatch_scamble(SCRAMBLE, &cn, &scrambled);
num_to_bytes(scrambled, 4, rawhex + 5);
cmdp += 2;
break;
}
case 'm': {
uint8_t mode = param_get8ex(Cmd, cmdp + 1, 1, 10);
mode &= 0x0F;
rawhex[9] |= (mode << 4);
cmdp += 2;
break;
}
case 'n': {
magic = 0x88;
cmdp++;
break;
}
case 'q': {
magic = 0xBE;
cmdp++;
break;
}
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
int raw_len = 0;
// skip first block, 3*4 = 12 bytes left
uint8_t raw[12] = {0x56, 0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
uint32_t cn = arg_get_u32_def(ctx, 2, -1);
uint32_t mode = arg_get_u32_def(ctx, 3, -1);
bool use_nexkey = arg_get_lit(ctx, 4);
bool use_quadrakey = arg_get_lit(ctx, 5);
CLIParserFree(ctx);
if (use_nexkey && use_quadrakey) {
PrintAndLogEx(FAILED, "Can't specify both Nexkey and Quadrakey at the same time");
return PM3_EINVARG;
}
if (errors || cmdp == 0) return usage_lf_nexwatch_sim();
bool use_raw = (raw_len != 0);
if (use_raw && cn != -1) {
PrintAndLogEx(FAILED, "Can't specify both Raw and Card id at the same time");
return PM3_EINVARG;
}
if (cn != -1) {
uint32_t scrambled;
nexwatch_scamble(SCRAMBLE, &cn, &scrambled);
num_to_bytes(scrambled, 4, raw + 5);
}
if (mode != -1) {
if (mode > 15) {
mode = 1;
}
mode &= 0x0F;
raw[9] |= (mode << 4);
}
uint8_t magic = 0xBE;
if (use_nexkey)
magic = 0x88;
if (use_quadrakey)
magic = 0xBE;
if (use_raw == false) {
uint8_t parity = nexwatch_parity(rawhex + 5) & 0xF;
rawhex[9] |= parity;
rawhex[10] |= nexwatch_checksum(magic, cn, parity);
uint8_t parity = nexwatch_parity(raw + 5) & 0xF;
raw[9] |= parity;
raw[10] |= nexwatch_checksum(magic, cn, parity);
}
// hex to bits.
uint32_t rawblocks[3];
for (size_t i = 0; i < ARRAYLEN(rawblocks); i++) {
rawblocks[i] = bytes_to_num(rawhex + (i * sizeof(uint32_t)), sizeof(uint32_t));
num_to_bytebits(rawblocks[i], sizeof(uint32_t) * 8, bs + (i * sizeof(uint32_t) * 8));
uint8_t bs[96];
memset(bs, 0, sizeof(bs));
// hex to bits. (3 * 32 == 96)
for (size_t i = 0; i < 3; i++) {
uint32_t tmp = bytes_to_num(raw + (i * sizeof(uint32_t)), sizeof(uint32_t));
num_to_bytebits(tmp, sizeof(uint32_t) * 8, bs + (i * sizeof(uint32_t) * 8));
}
PrintAndLogEx(SUCCESS, "Simulating NexWatch - raw: %s", sprint_hex_inrow(rawhex, rawlen));
PrintAndLogEx(SUCCESS, "Simulating NexWatch - raw " _YELLOW_("%s"), sprint_hex_inrow(raw, sizeof(raw)));
lf_psksim_t *payload = calloc(1, sizeof(lf_psksim_t) + sizeof(bs));
payload->carrier = 2;
@@ -447,11 +467,11 @@ static int CmdNexWatchSim(const char *Cmd) {
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdNexWatchDemod, AlwaysAvailable, "Demodulate a NexWatch tag (nexkey, quadrakey) from the GraphBuffer"},
{"read", CmdNexWatchRead, IfPm3Lf, "Attempt to Read and Extract tag data from the antenna"},
{"clone", CmdNexWatchClone, IfPm3Lf, "clone NexWatch tag to T55x7"},
{"sim", CmdNexWatchSim, IfPm3Lf, "simulate NexWatch tag"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdNexWatchDemod, AlwaysAvailable, "Demodulate a NexWatch tag (nexkey, quadrakey) from the GraphBuffer"},
{"reader", CmdNexWatchReader, IfPm3Lf, "Attempt to Read and Extract tag data from the antenna"},
{"clone", CmdNexWatchClone, IfPm3Lf, "clone NexWatch tag to T55x7"},
{"sim", CmdNexWatchSim, IfPm3Lf, "simulate NexWatch tag"},
{NULL, NULL, NULL, NULL}
};

View File

@@ -8,52 +8,23 @@
// ASK/Manchester, STT, RF/32, 96 bits long (some bits unknown)
//-----------------------------------------------------------------------------
#include "cmdlfnoralsy.h"
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "commonutil.h" // ARRAYLEN
#include "commonutil.h" // ARRAYLEN
#include "cmdparser.h" // command_t
#include "comms.h"
#include "ui.h"
#include "cmddata.h"
#include "cmdlf.h"
#include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest
#include "cmdlft55xx.h" // verifywrite
#include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest
#include "cmdlft55xx.h" // verifywrite
#include "cmdlfem4x05.h" //
#include "cliparser.h"
static int CmdHelp(const char *Cmd);
static int usage_lf_noralsy_clone(void) {
PrintAndLogEx(NORMAL, "clone a Noralsy tag to a T55x7 or Q5/T5555 tag.");
PrintAndLogEx(NORMAL, "Usage: lf noralsy clone [h] <card id> <year> <Q5>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <card id> : Noralsy card ID");
PrintAndLogEx(NORMAL, " <year> : Tag allocation year");
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf noralsy clone 112233"));
return PM3_SUCCESS;
}
static int usage_lf_noralsy_sim(void) {
PrintAndLogEx(NORMAL, "Enables simulation of Noralsy card with specified card number.");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf noralsy sim [h] <card id> <year>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <card id> : Noralsy card ID");
PrintAndLogEx(NORMAL, " <year> : Tag allocation year");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf noralsy sim 112233"));
return PM3_SUCCESS;
}
static uint8_t noralsy_chksum(uint8_t *bits, uint8_t len) {
uint8_t sum = 0;
for (uint8_t i = 0; i < len; i += 4)
@@ -136,28 +107,72 @@ static int CmdNoralsyDemod(const char *Cmd) {
return demodNoralsy(true);
}
static int CmdNoralsyRead(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
lf_read(false, 8000);
return demodNoralsy(true);
static int CmdNoralsyReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf noralsy reader",
"read a noralsy tag",
"lf noralsy reader -@ -> continuous reader mode"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
do {
lf_read(false, 8000);
demodNoralsy(!cm);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
static int CmdNoralsyClone(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf noralsy clone",
"clone a noralsy tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
"lf noralsy clone --cn 112233\n"
"lf noralsy clone --cn 112233 --q5 -> encode for Q5/T5555 tag\n"
"lf noralsy clone --cn 112233 --em -> encode for EM4305/4469"
);
void *argtable[] = {
arg_param_begin,
arg_u64_1(NULL, "cn", "<dec>", "Noralsy card ID"),
arg_u64_0("y", "year", "<dec>", "tag allocation year"),
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint32_t id = arg_get_u32_def(ctx, 1, 0);
uint16_t year = arg_get_u32_def(ctx, 2, 2000);
bool q5 = arg_get_lit(ctx, 3);
bool em = arg_get_lit(ctx, 4);
CLIParserFree(ctx);
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
uint16_t year = 0;
uint32_t id = 0;
uint32_t blocks[4] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | T55x7_ST_TERMINATOR | 3 << T55x7_MAXBLOCK_SHIFT, 0, 0};
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_noralsy_clone();
id = param_get32ex(Cmd, 0, 0, 10);
year = param_get32ex(Cmd, 1, 2000, 10);
char cardtype[16] = {"T55x7"};
//Q5
bool q5 = tolower(param_getchar(Cmd, 2) == 'q');
if (q5)
if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(32) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
// EM4305
if (em) {
blocks[0] = EM4305_NORALSY_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
uint8_t *bits = calloc(96, sizeof(uint8_t));
if (getnoralsyBits(id, year, bits) != PM3_SUCCESS) {
@@ -172,36 +187,50 @@ static int CmdNoralsyClone(const char *Cmd) {
free(bits);
PrintAndLogEx(INFO, "Preparing to clone Noralsy to " _YELLOW_("%s") " with CardId: %u", (q5) ? "Q5/T5555" : "T55x7", id);
PrintAndLogEx(INFO, "Preparing to clone Noralsy to " _YELLOW_("%s") " with Card id: " _GREEN_("%u"), cardtype, id);
print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
int res;
if (em) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf noralsy read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf noralsy reader`") " to verify");
return res;
}
static int CmdNoralsySim(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf noralsy sim",
"Enables simulation of Noralsy card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.\n",
"lf noralsy sim --cn 1337\n"
"lf noralsy sim --cn 1337 --year 2010"
);
void *argtable[] = {
arg_param_begin,
arg_u64_1(NULL, "cn", "<dec>", "Noralsy card ID"),
arg_u64_0("y", "year", "<dec>", "tag allocation year"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint32_t id = arg_get_u32_def(ctx, 1, 0);
uint16_t year = arg_get_u32_def(ctx, 2, 2000);
CLIParserFree(ctx);
uint8_t bs[96];
memset(bs, 0, sizeof(bs));
uint16_t year = 0;
uint32_t id = 0;
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h')
return usage_lf_noralsy_sim();
id = param_get32ex(Cmd, 0, 0, 10);
year = param_get32ex(Cmd, 1, 2000, 10);
if (getnoralsyBits(id, year, bs) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
return PM3_ESOFT;
}
PrintAndLogEx(SUCCESS, "Simulating Noralsy - CardId: %u", id);
PrintAndLogEx(SUCCESS, "Simulating Noralsy - CardId: " _YELLOW_("%u") " year " _YELLOW_("%u"), id, year);
lf_asksim_t *payload = calloc(1, sizeof(lf_asksim_t) + sizeof(bs));
payload->encoding = 1;
@@ -225,11 +254,11 @@ static int CmdNoralsySim(const char *Cmd) {
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdNoralsyDemod, AlwaysAvailable, "Demodulate an Noralsy tag from the GraphBuffer"},
{"read", CmdNoralsyRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdNoralsyClone, IfPm3Lf, "clone Noralsy tag to T55x7 or Q5/T5555"},
{"sim", CmdNoralsySim, IfPm3Lf, "simulate Noralsy tag"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdNoralsyDemod, AlwaysAvailable, "Demodulate an Noralsy tag from the GraphBuffer"},
{"reader", CmdNoralsyReader, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdNoralsyClone, IfPm3Lf, "clone Noralsy tag to T55x7 or Q5/T5555"},
{"sim", CmdNoralsySim, IfPm3Lf, "simulate Noralsy tag"},
{NULL, NULL, NULL, NULL}
};
@@ -272,7 +301,6 @@ int getnoralsyBits(uint32_t id, uint16_t year, uint8_t *bits) {
return PM3_SUCCESS;
}
// by iceman
// find Noralsy preamble in already demoded data
int detectNoralsy(uint8_t *dest, size_t *size) {
if (*size < 96) return -1; //make sure buffer has data

View File

@@ -25,40 +25,14 @@
#include "protocols.h" // t55xx defines
#include "cmdlft55xx.h" // clone
#include "parity.h"
#include "cmdlfem4x05.h" //
#include "cliparser.h"
static int CmdHelp(const char *Cmd);
static int usage_lf_pac_clone(void) {
PrintAndLogEx(NORMAL, "clone a PAC/Stanley tag to a T55x7 tag.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf pac clone [h] [c <card id>] [b <raw hex>]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " c <card id> : 8 byte card ID");
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 16 bytes max");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf pac clone c CD4F5552 "));
PrintAndLogEx(NORMAL, _YELLOW_(" lf pac clone b FF2049906D8511C593155B56D5B2649F "));
return PM3_SUCCESS;
}
static int usage_lf_pac_sim(void) {
PrintAndLogEx(NORMAL, "Enables simulation of PAC/Stanley card with specified card number.");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "The card ID is 8 byte number. Larger values are truncated.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf pac sim <Card-ID>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " <Card ID> : 8 byte PAC/Stanley card id");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf pac sim 12345678"));
return PM3_SUCCESS;
}
// PAC_8byte format: preamble (8 mark/idle bits), ascii STX (02), ascii '2' (32), ascii '0' (30), ascii bytes 0..7 (cardid), then xor checksum of cardid bytes
// all bytes following 8 bit preamble are one start bit (0), 7 data bits (lsb first), odd parity bit, and one stop bit (1)
static int demodbuf_to_pacid(uint8_t *src, const size_t src_size, uint8_t *dst, const size_t dst_size) {
static int pac_buf_to_cardid(uint8_t *src, const size_t src_size, uint8_t *dst, const size_t dst_size) {
const size_t byteLength = 10; // start bit, 7 data bits, parity bit, stop bit
const size_t startIndex = 8 + (3 * byteLength) + 1; // skip 8 bits preamble, STX, '2', '0', and first start bit
const size_t dataLength = 9;
@@ -93,35 +67,33 @@ static int demodbuf_to_pacid(uint8_t *src, const size_t src_size, uint8_t *dst,
return PM3_SUCCESS;
}
/*
// convert a 16 byte array of raw demod data (FF204990XX...) to 8 bytes of PAC_8byte ID
// performs no parity or checksum validation
static void pacRawToCardId(uint8_t* outCardId, const uint8_t* rawBytes) {
static void pac_raw_to_cardid(const uint8_t* src, uint8_t *dst) {
for (int i = 4; i < 12; i++) {
uint8_t shift = 7 - (i + 3) % 4 * 2;
size_t index = i + (i - 1) / 4;
outCardId[i - 4] = reflect8((((rawBytes[index] << 8) | (rawBytes[index + 1])) >> shift) & 0xFE);
dst[i - 4] = reflect8((((src[index] << 8) | (src[index + 1])) >> shift) & 0xFE);
}
}
*/
// convert 8 bytes of PAC_8byte ID to 16 byte array of raw data (FF204990XX...)
static void pacCardIdToRaw(uint8_t *outRawBytes, const char *cardId) {
static void pac_cardid_to_raw(const char *src, uint8_t *dst) {
uint8_t idbytes[10];
// prepend PAC_8byte card type "20"
idbytes[0] = '2';
idbytes[1] = '0';
for (size_t i = 0; i < 8; i++)
idbytes[i + 2] = toupper(cardId[i]);
idbytes[i + 2] = toupper(src[i]);
// initialise array with start and stop bits
for (size_t i = 0; i < 16; i++)
outRawBytes[i] = 0x40 >> (i + 3) % 5 * 2;
dst[i] = 0x40 >> (i + 3) % 5 * 2;
outRawBytes[0] = 0xFF; // mark + stop
outRawBytes[1] = 0x20; // start + reflect8(STX)
dst[0] = 0xFF; // mark + stop
dst[1] = 0x20; // start + reflect8(STX)
uint8_t checksum = 0;
for (size_t i = 2; i < 13; i++) {
@@ -138,8 +110,8 @@ static void pacCardIdToRaw(uint8_t *outRawBytes, const char *cardId) {
}
pattern <<= shift;
outRawBytes[index] |= pattern >> 8 & 0xFF;
outRawBytes[index + 1] |= pattern & 0xFF;
dst[index] |= pattern >> 8 & 0xFF;
dst[index + 1] |= pattern & 0xFF;
}
}
@@ -176,7 +148,7 @@ int demodPac(bool verbose) {
const size_t idLen = 9; // 8 bytes + null terminator
uint8_t cardid[idLen];
int retval = demodbuf_to_pacid(DemodBuffer, DemodBufferLen, cardid, sizeof(cardid));
int retval = pac_buf_to_cardid(DemodBuffer, DemodBufferLen, cardid, sizeof(cardid));
if (retval == PM3_SUCCESS)
PrintAndLogEx(SUCCESS, "PAC/Stanley - Card: " _GREEN_("%s") ", Raw: %08X%08X%08X%08X", cardid, raw1, raw2, raw3, raw4);
@@ -189,93 +161,183 @@ static int CmdPacDemod(const char *Cmd) {
return demodPac(true);
}
static int CmdPacRead(const char *Cmd) {
(void)Cmd;
lf_read(false, 4096 * 2 + 20);
return demodPac(true);
static int CmdPacReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf pac reader",
"read a pac tag",
"lf pac reader -@ -> continuous reader mode"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
do {
lf_read(false, 4096 * 2 + 20);
demodPac(!cm);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
static int CmdPacClone(const char *Cmd) {
uint32_t blocks[5];
bool errors = false;
uint8_t cmdp = 0;
int datalen = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf pac clone",
"clone a PAC/Stanley tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
"lf pac clone --cn CD4F5552\n"
"lf pac clone --cn CD4F5552 --q5 -> encode for Q5/T5555 tag\n"
"lf pac clone --cn CD4F5552 --em -> encode for EM4305/4469\n"
"lf pac clone --raw FF2049906D8511C593155B56D5B2649F"
);
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_lf_pac_clone();
case 'c': {
// skip first block, 4*4 = 16 bytes left
uint8_t rawhex[16] = {0};
char cardid[9];
int res = param_getstr(Cmd, cmdp + 1, cardid, sizeof(cardid));
if (res < 8)
errors = true;
void *argtable[] = {
arg_param_begin,
arg_str0(NULL, "cn", "<dec>", "8 byte PAC/Stanley card ID"),
arg_str0("r", "raw", "<hex>", "raw hex data. 16 bytes max"),
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
pacCardIdToRaw(rawhex, cardid);
for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) {
blocks[i] = bytes_to_num(rawhex + ((i - 1) * 4), sizeof(uint32_t));
}
cmdp += 2;
break;
}
case 'b': {
// skip first block, 4*4 = 16 bytes left
uint8_t rawhex[16] = {0};
int res = param_gethex_to_eol(Cmd, cmdp + 1, rawhex, sizeof(rawhex), &datalen);
if (res != 0)
errors = true;
uint8_t cnstr[9];
int cnlen = 9;
memset(cnstr, 0x00, sizeof(cnstr));
CLIGetStrWithReturn(ctx, 1, cnstr, &cnlen);
for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) {
blocks[i] = bytes_to_num(rawhex + ((i - 1) * 4), sizeof(uint32_t));
}
cmdp += 2;
break;
}
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
// skip first block, 4*4 = 16 bytes left
int raw_len = 0;
uint8_t raw[16] = {0};
CLIGetHexWithReturn(ctx, 2, raw, &raw_len);
bool q5 = arg_get_lit(ctx, 3);
bool em = arg_get_lit(ctx, 4);
CLIParserFree(ctx);
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
if (cnlen && raw_len) {
PrintAndLogEx(FAILED, "Can't specify both CardID and raw hex at the same time");
return PM3_EINVARG;
}
if (errors || cmdp == 0) return usage_lf_pac_clone();
if (cnlen && cnlen < 8) {
PrintAndLogEx(FAILED, "Card ID must be 8 or 9 hex digits (%d)", cnlen);
return PM3_EINVARG;
}
//Pac - compat mode, NRZ, data rate 32, 3 data blocks
if (cnlen == 8 || cnlen == 9) {
pac_cardid_to_raw((char*)cnstr, raw);
} else {
pac_raw_to_cardid(raw, cnstr);
}
uint32_t blocks[5];
for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) {
blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t));
}
// Pac - compat mode, NRZ, data rate 32, 3 data blocks
blocks[0] = T55x7_MODULATION_DIRECT | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT;
char cardtype[16] = {"T55x7"};
// Q5
if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_DIRECT | T5555_SET_BITRATE(32) | 4 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
// EM4305
if (em) {
blocks[0] = EM4305_PAC_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
PrintAndLogEx(INFO, "Preparing to clone PAC/Stanley tag to " _YELLOW_("%s") " with ID " _GREEN_("%s") " raw " _GREEN_("%s")
, cardtype
, cnstr
, sprint_hex_inrow(raw, sizeof(raw))
);
PrintAndLogEx(INFO, "Preparing to clone PAC/Stanley tag to T55x7 with raw hex");
print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
int res;
if (em) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pac read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pac reader`") " to verify");
return res;
}
static int CmdPacSim(const char *Cmd) {
// NRZ sim.
char cardid[9] = { 0 };
uint8_t rawBytes[16] = { 0 };
uint32_t rawBlocks[4];
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_pac_sim();
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf pac sim",
"Enables simulation of PAC/Stanley card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.\n"
"The card ID is 8 byte number. Larger values are truncated.",
"lf pac sim --cn CD4F5552\n"
"lf pac sim --raw FF2049906D8511C593155B56D5B2649F"
);
int res = param_getstr(Cmd, 0, cardid, sizeof(cardid));
if (res < 8) return usage_lf_pac_sim();
void *argtable[] = {
arg_param_begin,
arg_str0(NULL, "cn", "<dec>", "8 byte PAC/Stanley card ID"),
arg_str0("r", "raw", "<hex>", "raw hex data. 16 bytes max"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint8_t bs[128];
pacCardIdToRaw(rawBytes, cardid);
for (size_t i = 0; i < ARRAYLEN(rawBlocks); i++) {
rawBlocks[i] = bytes_to_num(rawBytes + (i * sizeof(uint32_t)), sizeof(uint32_t));
num_to_bytebits(rawBlocks[i], sizeof(uint32_t) * 8, bs + (i * sizeof(uint32_t) * 8));
uint8_t cnstr[10];
int cnlen = 9;
memset(cnstr, 0x00, sizeof(cnstr));
CLIGetStrWithReturn(ctx, 1, cnstr, &cnlen);
// skip first block, 4*4 = 16 bytes left
int raw_len = 0;
uint8_t raw[16] = {0};
CLIGetHexWithReturn(ctx, 2, raw, &raw_len);
CLIParserFree(ctx);
if (cnlen && raw_len) {
PrintAndLogEx(FAILED, "Can't specify both CardID and raw hex at the same time");
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS, "Simulating PAC/Stanley - ID " _YELLOW_("%s")" raw "_YELLOW_("%08X%08X%08X%08X"), cardid, rawBlocks[0], rawBlocks[1], rawBlocks[2], rawBlocks[3]);
if (cnlen && cnlen < 8) {
PrintAndLogEx(FAILED, "Card ID must be 8 or 9 hex digits (%d)", cnlen);
return PM3_EINVARG;
}
if (cnlen == 8 || cnlen == 9) {
pac_cardid_to_raw((char*)cnstr, raw);
} else {
pac_raw_to_cardid(raw, cnstr);
}
uint8_t bs[128];
for (size_t i = 0; i < 4; i++) {
uint32_t tmp = bytes_to_num(raw + (i * sizeof(uint32_t)), sizeof(uint32_t));
num_to_bytebits(tmp, sizeof(uint32_t) * 8, bs + (i * sizeof(uint32_t) * 8));
}
PrintAndLogEx(SUCCESS, "Simulating PAC/Stanley - ID " _YELLOW_("%s")" raw " _YELLOW_("%s")
, cnstr
, sprint_hex_inrow(raw, sizeof(raw))
);
// NRZ sim.
lf_nrzsim_t *payload = calloc(1, sizeof(lf_nrzsim_t) + sizeof(bs));
payload->invert = 0;
payload->separator = 0;
@@ -297,11 +359,11 @@ static int CmdPacSim(const char *Cmd) {
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdPacDemod, AlwaysAvailable, "Demodulate a PAC tag from the GraphBuffer"},
{"read", CmdPacRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdPacClone, IfPm3Lf, "clone PAC tag to T55x7"},
{"sim", CmdPacSim, IfPm3Lf, "simulate PAC tag"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdPacDemod, AlwaysAvailable, "Demodulate a PAC tag from the GraphBuffer"},
{"reader", CmdPacReader, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdPacClone, IfPm3Lf, "clone PAC tag to T55x7"},
{"sim", CmdPacSim, IfPm3Lf, "simulate PAC tag"},
{NULL, NULL, NULL, NULL}
};

View File

@@ -1,4 +1,5 @@
//-----------------------------------------------------------------------------
// Marshmellow
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
@@ -8,13 +9,11 @@
// FSK2a, rf/50, 96 bits (completely known)
//-----------------------------------------------------------------------------
#include "cmdlfparadox.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "commonutil.h" // ARRAYLEN
#include "commonutil.h" // ARRAYLEN
#include "cmdparser.h" // command_t
#include "comms.h"
#include "ui.h"
@@ -25,40 +24,11 @@
#include "protocols.h" // t55xx defines
#include "cmdlft55xx.h" // clone..
#include "crc.h" // maxim
#include "cmdlfem4x05.h" //
#include "cliparser.h"
static int CmdHelp(const char *Cmd);
static int usage_lf_paradox_clone(void) {
PrintAndLogEx(NORMAL, "clone a Paradox tag to a T55x7 tag.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf paradox clone [h] [b <raw hex>]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf paradox clone b 0f55555695596a6a9999a59a"));
return PM3_SUCCESS;
}
/*
static int usage_lf_paradox_sim(void) {
PrintAndLogEx(NORMAL, "Enables simulation of Paradox card with specified card number.");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf paradox sim [h] <Facility-Code> <Card-Number>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " <Facility-Code> : 8-bit value facility code");
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf paradox sim 123 11223"));
return PM3_SUCCESS;
}
*/
const uint8_t paradox_lut[] = {
0xDB, 0xFC, 0x3F, 0xC5, 0x50, 0x14, 0x05, 0x47,
0x9F, 0xED, 0x7D, 0x59, 0x22, 0x84, 0x21, 0x4E,
@@ -71,9 +41,9 @@ const uint8_t paradox_lut[] = {
#define PARADOX_PREAMBLE_LEN 8
//by marshmellow
//Paradox Prox demod - FSK2a RF/50 with preamble of 00001111 (then manchester encoded)
//print full Paradox Prox ID and some bit format details if found
// by marshmellow
// Paradox Prox demod - FSK2a RF/50 with preamble of 00001111 (then manchester encoded)
// print full Paradox Prox ID and some bit format details if found
int demodParadox(bool verbose) {
(void) verbose; // unused so far
@@ -204,91 +174,141 @@ static int CmdParadoxDemod(const char *Cmd) {
return demodParadox(true);
}
//by marshmellow
//see ASKDemod for what args are accepted
static int CmdParadoxRead(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
lf_read(false, 10000);
return demodParadox(true);
static int CmdParadoxReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf paradox reader",
"read a Paradox tag",
"lf Paradox reader -@ -> continuous reader mode"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
do {
lf_read(false, 10000);
demodParadox(!cm);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
static int CmdParadoxClone(const char *Cmd) {
uint32_t blocks[4];
bool errors = false;
uint8_t cmdp = 0;
int datalen = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf paradox clone",
"clone a paradox tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
"lf paradox clone --raw 0f55555695596a6a9999a59a\n"
"lf paradox clone -r 0f55555695596a6a9999a59a --q5 -> encode for Q5/T5555 tag\n"
"lf paradox clone -r 0f55555695596a6a9999a59a --em -> encode for EM4305/4469"
);
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_lf_paradox_clone();
case 'b': {
// skip first block, 3*4 =12 bytes left
uint8_t rawhex[12] = {0};
int res = param_gethex_to_eol(Cmd, cmdp + 1, rawhex, sizeof(rawhex), &datalen);
if (res != 0)
errors = true;
void *argtable[] = {
arg_param_begin,
arg_str0("r", "raw", "<hex>", "raw hex data. 12 bytes max"),
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) {
blocks[i] = bytes_to_num(rawhex + ((i - 1) * 4), sizeof(uint32_t));
}
cmdp += 2;
break;
}
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
int raw_len = 0;
// skip first block, 3*4 = 12 bytes left
uint8_t raw[12] = {0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
bool q5 = arg_get_lit(ctx, 2);
bool em = arg_get_lit(ctx, 3);
CLIParserFree(ctx);
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
if (errors || cmdp == 0) return usage_lf_paradox_clone();
if (raw_len != 12) {
PrintAndLogEx(ERR, "Data must be 12 bytes (24 HEX characters) %d", raw_len);
return PM3_EINVARG;
}
//Securakey - compat mode, ASK/Man, data rate 40, 3 data blocks
uint32_t blocks[4];
for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) {
blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t));
}
// Paradox - FSK2a, data rate 50, 3 data blocks
blocks[0] = T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 3 << T55x7_MAXBLOCK_SHIFT;
char cardtype[16] = {"T55x7"};
// Q5
if (q5) {
blocks[0] = T5555_FIXED | T5555_INVERT_OUTPUT | T5555_MODULATION_FSK2 | T5555_SET_BITRATE(50) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
PrintAndLogEx(INFO, "Preparing to clone Paradox to T55x7 with raw hex");
// EM4305
if (em) {
blocks[0] = EM4305_PARADOX_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
PrintAndLogEx(INFO, "Preparing to clone Paradox to " _YELLOW_("%s") " with raw hex", cardtype);
print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
int res;
if (em) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf paradox read`") " to verify");
return res;
}
static int CmdParadoxSim(const char *Cmd) {
PrintAndLogEx(INFO, " To be implemented, feel free to contribute!");
return PM3_SUCCESS;
}
/*
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_paradox_sim();
uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf paradox sim",
"Enables simulation of paradox card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.",
"lf paradox sim --raw 0f55555695596a6a9999a59a"
);
uint8_t bs[96];
memset(bs, 0x00, sizeof(bs));
void *argtable[] = {
arg_param_begin,
arg_str0("r", "raw", "<hex>", " raw hex data. 12 bytes"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int raw_len = 0;
// skip first block, 3*4 = 12 bytes left
uint8_t raw[12] = {0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
CLIParserFree(ctx);
if (raw_len != 12) {
PrintAndLogEx(ERR, "Data must be 12 bytes (24 HEX characters) %d", raw_len);
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS, "Simulating Paradox - raw " _YELLOW_("%s"), sprint_hex_inrow(raw, sizeof(raw)));
uint8_t bs[sizeof(raw) * 8];
bytes_to_bytebits(raw, sizeof(raw), bs);
// Paradox uses: fcHigh: 10, fcLow: 8, clk: 50, invert: 1 FSK2a
uint8_t clk = 50, invert = 1, high = 10, low = 8;
if (sscanf(Cmd, "%u %u", &fc, &cn) != 2) return usage_lf_paradox_sim();
facilitycode = (fc & 0x000000FF);
cardnumber = (cn & 0x0000FFFF);
// if ( GetParadoxBits(facilitycode, cardnumber, bs) != PM3_SUCCESS) {
// PrintAndLogEx(ERR, "Error with tag bitstream generation.");
// return 1;
// }
PrintAndLogEx(NORMAL, "Simulating Paradox - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber);
uint8_t clk = 50, high = 10, low = 8;
lf_fsksim_t *payload = calloc(1, sizeof(lf_fsksim_t) + sizeof(bs));
payload->fchigh = high;
payload->fclow = low;
payload->separator = invert;
payload->separator = 0;
payload->clock = clk;
memcpy(payload->data, bs, sizeof(bs));
@@ -302,15 +322,29 @@ static int CmdParadoxSim(const char *Cmd) {
PrintAndLogEx(INFO, "Done");
if (resp.status != PM3_EOPABORTED)
return resp.status;
return PM3_SUCCESS;
}
return PM3_SUCCESS;}
/*
if (sscanf(Cmd, "%u %u", &fc, &cn) != 2) return usage_lf_paradox_sim();
facilitycode = (fc & 0x000000FF);
cardnumber = (cn & 0x0000FFFF);
// if ( GetParadoxBits(facilitycode, cardnumber, bs) != PM3_SUCCESS) {
// PrintAndLogEx(ERR, "Error with tag bitstream generation.");
// return 1;
// }
PrintAndLogEx(NORMAL, "Simulating Paradox - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber);
*/
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdParadoxDemod, AlwaysAvailable, "Demodulate a Paradox FSK tag from the GraphBuffer"},
{"read", CmdParadoxRead, IfPm3Lf, "Attempt to read and Extract tag data from the antenna"},
{"clone", CmdParadoxClone, IfPm3Lf, "clone paradox tag to T55x7"},
{"sim", CmdParadoxSim, IfPm3Lf, "simulate paradox tag"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdParadoxDemod, AlwaysAvailable, "Demodulate a Paradox FSK tag from the GraphBuffer"},
{"reader", CmdParadoxReader, IfPm3Lf, "Attempt to read and Extract tag data from the antenna"},
{"clone", CmdParadoxClone, IfPm3Lf, "clone paradox tag"},
{"sim", CmdParadoxSim, IfPm3Lf, "simulate paradox tag"},
{NULL, NULL, NULL, NULL}
};

View File

@@ -8,51 +8,64 @@
//-----------------------------------------------------------------------------
#include "cmdlfpresco.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "commonutil.h" // ARRAYLEN
#include "commonutil.h" // ARRAYLEN
#include "cmdparser.h" // command_t
#include "comms.h"
#include "ui.h"
#include "cmddata.h"
#include "cmdlf.h"
#include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest
#include "cmdlft55xx.h" // verifywrite
#include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest
#include "cmdlft55xx.h" // verifywrite
#include "cmdlfem4x05.h" //
#include "cliparser.h"
static int CmdHelp(const char *Cmd);
static int usage_lf_presco_clone(void) {
PrintAndLogEx(NORMAL, "clone a Presco tag to a T55x7 or Q5/T5555 tag.");
PrintAndLogEx(NORMAL, "Usage: lf presco clone [h] d <Card-ID> c <hex-ID> <Q5>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " d <Card-ID> : 9 digit presco card ID");
PrintAndLogEx(NORMAL, " c <hex-ID> : 8 digit hex card number");
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf presco clone d 123456789"));
// find presco preamble 0x10D in already demoded data
static int detectPresco(uint8_t *dest, size_t *size) {
if (*size < 128 * 2) return -1; //make sure buffer has data
size_t startIdx = 0;
uint8_t preamble[] = {0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx))
return -2; //preamble not found
if (*size != 128) return -3; //wrong demoded size
//return start position
return (int)startIdx;
}
// convert base 12 ID to sitecode & usercode & 8 bit other unknown code
static int getWiegandFromPrintedPresco(void *arr, uint32_t *fullcode) {
char *s = (char*)arr;
uint8_t val = 0;
for (int i = 0; i < strlen(s); ++i) {
// Get value from number string.
if (s[i] == '*')
val = 10;
if (s[i] == '#')
val = 11;
if (s[i] >= 0x30 && s[i] <= 0x39)
val = s[i] - 0x30;
*fullcode += val;
// last digit is only added, not multipled.
if (i < strlen(s) - 1)
*fullcode *= 12;
}
return PM3_SUCCESS;
}
static int usage_lf_presco_sim(void) {
PrintAndLogEx(NORMAL, "Enables simulation of presco card with specified card number.");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "Per presco format, the card number is 9 digit number and can contain *# chars. Larger values are truncated.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf presco sim [h] d <Card-ID> or c <hex-ID>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " d <Card-ID> : 9 digit presco card number");
PrintAndLogEx(NORMAL, " c <hex-ID> : 8 digit hex card number");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf presco sim d 123456789"));
// calc not certain - intended to get bitstream for programming / sim
static int getPrescoBits(uint32_t fullcode, uint8_t *prescoBits) {
num_to_bytebits(0x10D00000, 32, prescoBits);
num_to_bytebits(0x00000000, 32, prescoBits + 32);
num_to_bytebits(0x00000000, 32, prescoBits + 64);
num_to_bytebits(fullcode, 32, prescoBits + 96);
return PM3_SUCCESS;
}
@@ -85,15 +98,16 @@ int demodPresco(bool verbose) {
uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32);
uint32_t raw3 = bytebits_to_byte(DemodBuffer + 64, 32);
uint32_t raw4 = bytebits_to_byte(DemodBuffer + 96, 32);
uint32_t cardid = raw4;
PrintAndLogEx(SUCCESS, "Presco - Card: " _GREEN_("%08X") ", Raw: %08X%08X%08X%08X", cardid, raw1, raw2, raw3, raw4);
uint32_t fullcode = raw4;
uint32_t usercode = fullcode & 0x0000FFFF;
uint32_t sitecode = (fullcode >> 24) & 0x000000FF;
uint32_t sitecode = 0, usercode = 0, fullcode = 0;
bool Q5 = false;
char cmd[12] = {0};
sprintf(cmd, "H %08X", cardid);
getWiegandFromPresco(cmd, &sitecode, &usercode, &fullcode, &Q5);
PrintAndLogEx(SUCCESS, "SiteCode: " _GREEN_("%u") " UserCode: " _GREEN_("%u") " FullCode: " _GREEN_("%08X"), sitecode, usercode, fullcode);
PrintAndLogEx(SUCCESS, "Presco Site code: " _GREEN_("%u") " User code: " _GREEN_("%u") " Full code: " _GREEN_("%08X") " Raw: " _YELLOW_("%08X%08X%08X%08X")
, sitecode
, usercode
, fullcode
, raw1, raw2, raw3, raw4
);
return PM3_SUCCESS;
}
@@ -103,35 +117,108 @@ static int CmdPrescoDemod(const char *Cmd) {
}
//see ASKDemod for what args are accepted
static int CmdPrescoRead(const char *Cmd) {
// Presco Number: 123456789 --> Sitecode 30 | usercode 8665
(void)Cmd; // Cmd is not used so far
lf_read(false, 12000);
return demodPresco(true);
static int CmdPrescoReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf presco reader",
"read a presco tag",
"lf presco reader -@ -> continuous reader mode"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
do {
lf_read(false, 12000);
demodPresco(!cm);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
// takes base 12 ID converts to hex
// Or takes 8 digit hex ID
static int CmdPrescoClone(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf presco clone",
"clone a presco tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
"lf presco clone -d 018363467\n"
"lf presco clone -d 018363467 --q5 -> encode for Q5/T5555 tag\n"
"lf presco clone -d 018363467 --em -> encode for EM4305/4469"
);
void *argtable[] = {
arg_param_begin,
arg_str0("c", NULL, "<hex>", "8 digit hex card number"),
arg_str0("d", NULL, "<digits>", "9 digit presco card ID"),
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int hex_len = 0;
uint8_t hex[4] = {0,0,0,0};
CLIGetHexWithReturn(ctx, 1, hex, &hex_len);
uint8_t idstr[11];
int slen = 9;
memset(idstr, 0x00, sizeof(idstr));
CLIGetStrWithReturn(ctx, 2, idstr, &slen);
bool q5 = arg_get_lit(ctx, 3);
bool em = arg_get_lit(ctx, 4);
CLIParserFree(ctx);
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
uint32_t fullcode = 0;
if (hex_len) {
fullcode = bytes_to_num(hex, hex_len);
} else {
//param get string int param_getstr(const char *line, int paramnum, char * str)
if (slen < 2) {
PrintAndLogEx(ERR, "Must contain atleast 2 digits");
return PM3_EINVARG;
}
getWiegandFromPrintedPresco(idstr, &fullcode);
}
uint32_t usercode = fullcode & 0x0000FFFF; //% 65566
uint32_t sitecode = (fullcode >> 24) & 0x000000FF; // /= 16777216;
bool Q5 = false;
uint32_t sitecode = 0, usercode = 0, fullcode = 0;
uint32_t blocks[5] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT | T55x7_ST_TERMINATOR, 0, 0, 0, 0};
// get wiegand from printed number.
if (getWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == PM3_EINVARG) return usage_lf_presco_clone();
if (Q5)
char cardtype[16] = {"T55x7"};
// Q5
if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(32) | 4 << T5555_MAXBLOCK_SHIFT | T5555_ST_TERMINATOR;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
// EM4305
if (em) {
blocks[0] = EM4305_PRESCO_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
if ((sitecode & 0xFF) != sitecode) {
sitecode &= 0xFF;
PrintAndLogEx(INFO, "Facility-Code Truncated to 8-bits (Presco): %u", sitecode);
PrintAndLogEx(INFO, "Site code truncated to 8-bits (Presco): %u", sitecode);
}
if ((usercode & 0xFFFF) != usercode) {
usercode &= 0xFFFF;
PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (Presco): %u", usercode);
PrintAndLogEx(INFO, "User code truncated to 16-bits (Presco): %u", usercode);
}
blocks[1] = 0x10D00000; //preamble
@@ -139,25 +226,84 @@ static int CmdPrescoClone(const char *Cmd) {
blocks[3] = 0x00000000;
blocks[4] = fullcode;
PrintAndLogEx(INFO, "Preparing to clone Presco to " _YELLOW_("%s") " with SiteCode: %u, UserCode: %u, FullCode: %08x", (Q5) ? "Q5/T5555" : "T55x7", sitecode, usercode, fullcode);
PrintAndLogEx(INFO, "Preparing to clone Presco to " _GREEN_("%s") " with Site code: " _GREEN_("%u") " User code: " _GREEN_("%u") " Full code: " _GREEN_("%08x")
, cardtype
, sitecode
, usercode
, fullcode
);
print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
int res;
if (em) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf presco read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf presco reader`") " to verify");
return res;
}
// takes base 12 ID converts to hex
// Or takes 8 digit hex ID
static int CmdPrescoSim(const char *Cmd) {
uint32_t sitecode = 0, usercode = 0, fullcode = 0;
bool Q5 = false;
// get wiegand from printed number.
if (getWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == PM3_EINVARG)
return usage_lf_presco_sim();
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf presco sim",
"Enables simulation of presco card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.\n"
"Per presco format, the card number is 9 digit number and can contain *# chars. Larger values are truncated.",
"lf presco sim -d 018363467"
);
PrintAndLogEx(SUCCESS, "Simulating Presco - SiteCode: %u, UserCode: %u, FullCode: %08X", sitecode, usercode, fullcode);
void *argtable[] = {
arg_param_begin,
arg_str0("c", NULL, "<hex>", "8 digit hex card number"),
arg_str0("d", NULL, "<digits>", "9 digit presco card ID"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int hex_len = 0;
uint8_t hex[4] = {0,0,0,0};
CLIGetHexWithReturn(ctx, 1, hex, &hex_len);
uint8_t idstr[11];
int slen = 9;
memset(idstr, 0x00, sizeof(idstr));
CLIGetStrWithReturn(ctx, 2, idstr, &slen);
CLIParserFree(ctx);
uint32_t fullcode = 0;
if (hex_len) {
fullcode = bytes_to_num(hex, hex_len);
} else {
if (slen < 2) {
PrintAndLogEx(ERR, "Must contain atleast 2 digits");
return PM3_EINVARG;
}
getWiegandFromPrintedPresco(idstr, &fullcode);
}
uint32_t usercode = fullcode & 0x0000FFFF;
uint32_t sitecode = (fullcode >> 24) & 0x000000FF;
if ((sitecode & 0xFF) != sitecode) {
sitecode &= 0xFF;
PrintAndLogEx(INFO, "Site code truncated to 8-bits (Presco): %u", sitecode);
}
if ((usercode & 0xFFFF) != usercode) {
usercode &= 0xFFFF;
PrintAndLogEx(INFO, "User code truncated to 16-bits (Presco): %u", usercode);
}
PrintAndLogEx(SUCCESS, "Simulating Presco - Site Code: " _GREEN_("%u") " User Code: " _GREEN_("%u") " Full Code: " _GREEN_("%08X")
, sitecode
, usercode
, fullcode)
;
uint8_t bs[128];
getPrescoBits(fullcode, bs);
@@ -185,9 +331,9 @@ static int CmdPrescoSim(const char *Cmd) {
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdPrescoDemod, AlwaysAvailable, "demodulate Presco tag from the GraphBuffer"},
{"read", CmdPrescoRead, IfPm3Lf, "Attempt to read and Extract tag data"},
{"clone", CmdPrescoClone, IfPm3Lf, "clone presco tag to T55x7 or Q5/T5555"},
{"sim", CmdPrescoSim, IfPm3Lf, "simulate presco tag"},
{"reader", CmdPrescoReader, IfPm3Lf, "Attempt to read and Extract tag data"},
{"clone", CmdPrescoClone, IfPm3Lf, "clone presco tag to T55x7 or Q5/T5555"},
{"sim", CmdPrescoSim, IfPm3Lf, "simulate presco tag"},
{NULL, NULL, NULL, NULL}
};
@@ -201,86 +347,3 @@ int CmdLFPresco(const char *Cmd) {
clearCommandBuffer();
return CmdsParse(CommandTable, Cmd);
}
// find presco preamble 0x10D in already demoded data
int detectPresco(uint8_t *dest, size_t *size) {
if (*size < 128 * 2) return -1; //make sure buffer has data
size_t startIdx = 0;
uint8_t preamble[] = {0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx))
return -2; //preamble not found
if (*size != 128) return -3; //wrong demoded size
//return start position
return (int)startIdx;
}
// convert base 12 ID to sitecode & usercode & 8 bit other unknown code
int getWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5) {
bool hex = false, errors = false;
uint8_t cmdp = 0;
char id[11];
int stringlen = 0;
memset(id, 0x00, sizeof(id));
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return PM3_EINVARG;
case 'c':
hex = true;
//get hex
*fullcode = param_get32ex(Cmd, cmdp + 1, 0, 16);
cmdp += 2;
break;
case 'd':
//param get string int param_getstr(const char *line, int paramnum, char * str)
stringlen = param_getstr(Cmd, cmdp + 1, id, sizeof(id));
if (stringlen < 2) return PM3_EINVARG;
cmdp += 2;
break;
case 'q':
*Q5 = true;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = 1;
break;
}
}
//Validations
if (errors || cmdp == 0) return PM3_EINVARG;
if (!hex) {
uint8_t val = 0;
for (int index = 0; index < strlen(id); ++index) {
// Get value from number string.
if (id[index] == '*')
val = 10;
if (id[index] == '#')
val = 11;
if (id[index] >= 0x30 && id[index] <= 0x39)
val = id[index] - 0x30;
*fullcode += val;
// last digit is only added, not multipled.
if (index < strlen(id) - 1)
*fullcode *= 12;
}
}
*usercode = *fullcode & 0x0000FFFF; //% 65566
*sitecode = (*fullcode >> 24) & 0x000000FF; // /= 16777216;
return PM3_SUCCESS;
}
// calc not certain - intended to get bitstream for programming / sim
int getPrescoBits(uint32_t fullcode, uint8_t *prescoBits) {
num_to_bytebits(0x10D00000, 32, prescoBits);
num_to_bytebits(0x00000000, 32, prescoBits + 32);
num_to_bytebits(0x00000000, 32, prescoBits + 64);
num_to_bytebits(fullcode, 32, prescoBits + 96);
return PM3_SUCCESS;
}

View File

@@ -12,11 +12,6 @@
#include "common.h"
int CmdLFPresco(const char *Cmd);
int demodPresco(bool verbose);
int detectPresco(uint8_t *dest, size_t *size);
int getPrescoBits(uint32_t fullcode, uint8_t *prescoBits);
int getWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5);
#endif

View File

@@ -15,7 +15,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "commonutil.h" // ARRAYLEN
#include "cmdparser.h" // command_t
#include "comms.h"
@@ -27,43 +26,11 @@
#include "lfdemod.h" // parityTest
#include "crc.h"
#include "cmdlft55xx.h" // verifywrite
#include "cliparser.h"
#include "cmdlfem4x05.h" // EM Defines
static int CmdHelp(const char *Cmd);
static int usage_lf_pyramid_clone(void) {
PrintAndLogEx(NORMAL, "clone a Farpointe/Pyramid tag to a T55x7 or Q5/T5555 tag.");
PrintAndLogEx(NORMAL, "The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated. ");
PrintAndLogEx(NORMAL, "Currently only works on 26bit");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf pyramid clone [h] <Facility-Code> <Card-Number> [Q5]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " <Facility-Code> : 8-bit value facility code");
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
PrintAndLogEx(NORMAL, " Q5 : optional - specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf pyramid clone 123 11223"));
return PM3_SUCCESS;
}
static int usage_lf_pyramid_sim(void) {
PrintAndLogEx(NORMAL, "Enables simulation of Farpointe/Pyramid card with specified card number.");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated.");
PrintAndLogEx(NORMAL, "Currently work only on 26bit");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf pyramid sim [h] <Facility-Code> <Card-Number>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " <Facility-Code> : 8-bit value facility code");
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf pyramid sim 123 11223"));
return PM3_SUCCESS;
}
//Pyramid Prox demod - FSK RF/50 with preamble of 0000000000000001 (always a 128 bit data stream)
//print full Farpointe Data/Pyramid Prox ID and some bit format details if found
int demodPyramid(bool verbose) {
@@ -215,26 +182,71 @@ static int CmdPyramidDemod(const char *Cmd) {
return demodPyramid(true);
}
static int CmdPyramidRead(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
lf_read(false, 15000);
return demodPyramid(true);
static int CmdPyramidReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf pyramid reader",
"read a Farpointe/Pyramid tag",
"lf pyramid reader -@ -> continuous reader mode"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
do {
lf_read(false, 15000);
demodPyramid(true);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
static int CmdPyramidClone(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_pyramid_clone();
uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0;
if (sscanf(Cmd, "%u %u", &fc, &cn) != 2) return usage_lf_pyramid_clone();
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf pyramid clone",
"clone a Farpointe/Pyramid tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
"The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated.\n"
"Currently only works on 26bit",
"lf pyramid clone --fc 123 --cn 11223\n"
"lf pyramid clone --fc 123 --cn 11223 --q5 -> encode for Q5/T5555 tag\n"
"lf pyramid clone --fc 123 --cn 11223 --em -> encode for EM4305/4469"
);
void *argtable[] = {
arg_param_begin,
arg_u64_1(NULL, "fc", "<dec>", "8-bit value facility code"),
arg_u64_1(NULL, "cn", "<dec>", "16-bit value card number"),
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint32_t fc = arg_get_u32_def(ctx, 1, 0);
uint32_t cn = arg_get_u32_def(ctx, 2, 0);
bool q5 = arg_get_lit(ctx, 3);
bool em = arg_get_lit(ctx, 4);
CLIParserFree(ctx);
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
uint32_t blocks[5];
uint8_t *bs = calloc(128, sizeof(uint8_t));
if (bs == NULL) {
return PM3_EMALLOC;
}
facilitycode = (fc & 0x000000FF);
cardnumber = (cn & 0x0000FFFF);
uint32_t facilitycode = (fc & 0x000000FF);
uint32_t cardnumber = (cn & 0x0000FFFF);
if (getPyramidBits(facilitycode, cardnumber, bs) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
@@ -243,11 +255,18 @@ static int CmdPyramidClone(const char *Cmd) {
//Pyramid - compat mode, FSK2a, data rate 50, 4 data blocks
blocks[0] = T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 4 << T55x7_MAXBLOCK_SHIFT;
char cardtype[16] = {"T55x7"};
// Q5
bool q5 = tolower(param_getchar(Cmd, 2)) == 'q';
if (q5)
if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(50) | 4 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
// EM4305
if (em) {
blocks[0] = EM4305_PYRAMID_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
blocks[1] = bytebits_to_byte(bs, 32);
blocks[2] = bytebits_to_byte(bs + 32, 32);
@@ -256,36 +275,53 @@ static int CmdPyramidClone(const char *Cmd) {
free(bs);
PrintAndLogEx(INFO, "Preparing to clone Farpointe/Pyramid to " _YELLOW_("%s") " with Facility Code: %u, Card Number: %u", (q5) ? "Q5/T5555" : "T55x7", facilitycode, cardnumber);
PrintAndLogEx(INFO, "Preparing to clone Farpointe/Pyramid to " _YELLOW_("%s") " with Facility Code: %u, Card Number: %u", cardtype, facilitycode, cardnumber);
print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
int res;
if (em) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pyramid read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pyramid reader`") " to verify");
return res;
}
static int CmdPyramidSim(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf pyramid sim",
"Enables simulation of Farpointe/Pyramid card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.\n"
"The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated.\n"
"Currently work only on 26bit",
"lf pyramid sim --fc 123 --cn 1337"
);
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_pyramid_sim();
void *argtable[] = {
arg_param_begin,
arg_u64_1(NULL, "fc", "<dec>", "8-bit value facility code"),
arg_u64_1(NULL, "cn", "<dec>", "16-bit value card number"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint32_t fc = arg_get_u32_def(ctx, 1, 0);
uint32_t cn = arg_get_u32_def(ctx, 2, 0);
CLIParserFree(ctx);
uint32_t facilitycode = (fc & 0x000000FF);
uint32_t cardnumber = (cn & 0x0000FFFF);
uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0;
uint8_t bs[128];
memset(bs, 0x00, sizeof(bs));
if (sscanf(Cmd, "%u %u", &fc, &cn) != 2) return usage_lf_pyramid_sim();
facilitycode = (fc & 0x000000FF);
cardnumber = (cn & 0x0000FFFF);
if (getPyramidBits(facilitycode, cardnumber, bs) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
return PM3_ESOFT;
}
PrintAndLogEx(SUCCESS, "Simulating Farpointe/Pyramid - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber);
PrintAndLogEx(SUCCESS, "Simulating Farpointe/Pyramid - Facility Code: " _YELLOW_("%u") ", CardNumber: " _YELLOW_("%u"), facilitycode, cardnumber);
// Pyramid uses: fcHigh: 10, fcLow: 8, clk: 50, invert: 0
lf_fsksim_t *payload = calloc(1, sizeof(lf_fsksim_t) + sizeof(bs));
@@ -309,11 +345,11 @@ static int CmdPyramidSim(const char *Cmd) {
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "this help"},
{"demod", CmdPyramidDemod, AlwaysAvailable, "demodulate a Pyramid FSK tag from the GraphBuffer"},
{"read", CmdPyramidRead, IfPm3Lf, "attempt to read and extract tag data"},
{"clone", CmdPyramidClone, IfPm3Lf, "clone pyramid tag to T55x7 or Q5/T5555"},
{"sim", CmdPyramidSim, IfPm3Lf, "simulate pyramid tag"},
{"help", CmdHelp, AlwaysAvailable, "this help"},
{"demod", CmdPyramidDemod, AlwaysAvailable, "demodulate a Pyramid FSK tag from the GraphBuffer"},
{"reader", CmdPyramidReader, IfPm3Lf, "attempt to read and extract tag data"},
{"clone", CmdPyramidClone, IfPm3Lf, "clone pyramid tag to T55x7 or Q5/T5555"},
{"sim", CmdPyramidSim, IfPm3Lf, "simulate pyramid tag"},
{NULL, NULL, NULL, NULL}
};

View File

@@ -8,10 +8,8 @@
// ASK/Manchester, RF/40, 96 bits long (unknown cs)
//-----------------------------------------------------------------------------
#include "cmdlfsecurakey.h"
#include <string.h> // memcpy
#include <ctype.h> // tolower
#include "commonutil.h" // ARRAYLEN
#include "cmdparser.h" // command_t
#include "comms.h"
@@ -22,22 +20,11 @@
#include "parity.h" // for wiegand parity test
#include "protocols.h" // t55xx defines
#include "cmdlft55xx.h" // clone..
#include "cliparser.h"
#include "cmdlfem4x05.h" // EM defines
static int CmdHelp(const char *Cmd);
static int usage_lf_securakey_clone(void) {
PrintAndLogEx(NORMAL, "clone a Securakey tag to a T55x7 tag.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf securakey clone [h] [b <raw hex>]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf securakey clone b 7FCB400001ADEA5344300000"));
return PM3_SUCCESS;
}
//see ASKDemod for what args are accepted
int demodSecurakey(bool verbose) {
(void) verbose; // unused so far
@@ -118,9 +105,11 @@ int demodSecurakey(bool verbose) {
if (bitLen <= 32)
PrintAndLogEx(SUCCESS, "Wiegand: " _GREEN_("%08X") " parity (%s)", (lWiegand << (bitLen / 2)) | rWiegand, parity ? _GREEN_("ok") : _RED_("fail"));
PrintAndLogEx(INFO, "\nHow the FC translates to printed FC is unknown");
PrintAndLogEx(INFO, "How the checksum is calculated is unknown");
PrintAndLogEx(INFO, "Help the community identify this format further\n by sharing your tag on the pm3 forum or with forum members");
if (verbose) {
PrintAndLogEx(INFO, "\nHow the FC translates to printed FC is unknown");
PrintAndLogEx(INFO, "How the checksum is calculated is unknown");
PrintAndLogEx(INFO, "Help the community identify this format further\nby sharing your tag on the pm3 forum or discord");
}
return PM3_SUCCESS;
}
@@ -129,68 +118,160 @@ static int CmdSecurakeyDemod(const char *Cmd) {
return demodSecurakey(true);
}
static int CmdSecurakeyRead(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
lf_read(false, 8000);
return demodSecurakey(true);
static int CmdSecurakeyReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf securakey reader",
"read a Securakey tag",
"lf securakey reader -@ -> continuous reader mode"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
do {
lf_read(false, 8000);
demodSecurakey(!cm);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
static int CmdSecurakeyClone(const char *Cmd) {
uint32_t blocks[4];
bool errors = false;
uint8_t cmdp = 0;
int datalen = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf securakey clone",
"clone a Securakey tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
"lf securakey clone --raw 7FCB400001ADEA5344300000\n"
"lf securakey clone --q5 --raw 7FCB400001ADEA5344300000 -> encode for Q5/T5555 tag\n"
"lf securakey clone --em --raw 7FCB400001ADEA5344300000 -> encode for EM4305/4469"
);
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_lf_securakey_clone();
case 'b': {
// skip first block, 3*4 = 12 bytes left
uint8_t rawhex[12] = {0};
int res = param_gethex_to_eol(Cmd, cmdp + 1, rawhex, sizeof(rawhex), &datalen);
if (res != 0)
errors = true;
void *argtable[] = {
arg_param_begin,
arg_str0("r", "raw", "<hex>", "raw hex data. 12 bytes"),
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) {
blocks[i] = bytes_to_num(rawhex + ((i - 1) * 4), sizeof(uint32_t));
}
cmdp += 2;
break;
}
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
int raw_len = 0;
// skip first block, 3*4 = 12 bytes left
uint8_t raw[12] = {0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
bool q5 = arg_get_lit(ctx, 2);
bool em = arg_get_lit(ctx, 3);
CLIParserFree(ctx);
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
if (errors || cmdp == 0) return usage_lf_securakey_clone();
if (raw_len != 12) {
PrintAndLogEx(ERR, "Data must be 12 bytes (24 HEX characters) %d", raw_len);
return PM3_EINVARG;
}
uint32_t blocks[4];
for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) {
blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t));
}
//Securakey - compat mode, ASK/Man, data rate 40, 3 data blocks
blocks[0] = T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_40 | 3 << T55x7_MAXBLOCK_SHIFT;
char cardtype[16] = {"T55x7"};
// Q5
if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(40) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
PrintAndLogEx(INFO, "Preparing to clone Securakey to T55x7 with raw hex");
// EM4305
if (em) {
blocks[0] = EM4305_SECURAKEY_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
PrintAndLogEx(INFO, "Preparing to clone Securakey to " _YELLOW_("%s") " with raw hex", cardtype);
print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
int res;
if (em) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf securakey read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf securakey reader`") " to verify");
return res;
}
static int CmdSecurakeySim(const char *Cmd) {
PrintAndLogEx(INFO, " To be implemented, feel free to contribute!");
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf securakey sim",
"Enables simulation of secura card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.",
"lf securakey sim --raw 7FCB400001ADEA5344300000"
);
void *argtable[] = {
arg_param_begin,
arg_str0("r", "raw", "<hex>", " raw hex data. 12 bytes"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int raw_len = 0;
// skip first block, 3*4 = 12 bytes left
uint8_t raw[12] = {0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
CLIParserFree(ctx);
if (raw_len != 12) {
PrintAndLogEx(ERR, "Data must be 12 bytes (24 HEX characters) %d", raw_len);
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS, "Simulating SecuraKey - raw " _YELLOW_("%s"), sprint_hex_inrow(raw, sizeof(raw)));
uint8_t bs[sizeof(raw) * 8];
bytes_to_bytebits(raw, sizeof(raw), bs);
lf_asksim_t *payload = calloc(1, sizeof(lf_asksim_t) + sizeof(bs));
payload->encoding = 1;
payload->invert = 0;
payload->separator = 0;
payload->clock = 40;
memcpy(payload->data, bs, sizeof(bs));
clearCommandBuffer();
SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs));
free(payload);
PacketResponseNG resp;
WaitForResponse(CMD_LF_ASK_SIMULATE, &resp);
PrintAndLogEx(INFO, "Done");
if (resp.status != PM3_EOPABORTED)
return resp.status;
return PM3_SUCCESS;
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdSecurakeyDemod, AlwaysAvailable, "Demodulate an Securakey tag from the GraphBuffer"},
{"read", CmdSecurakeyRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdSecurakeyClone, IfPm3Lf, "clone Securakey tag to T55x7"},
{"sim", CmdSecurakeySim, IfPm3Lf, "simulate Securakey tag"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdSecurakeyDemod, AlwaysAvailable, "Demodulate an Securakey tag from the GraphBuffer"},
{"reader", CmdSecurakeyReader, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdSecurakeyClone, IfPm3Lf, "clone Securakey tag to T55x7"},
{"sim", CmdSecurakeySim, IfPm3Lf, "simulate Securakey tag"},
{NULL, NULL, NULL, NULL}
};

View File

@@ -1027,7 +1027,7 @@ static void T55xx_Print_DownlinkMode(uint8_t downlink_mode) {
}
// Define prototype to call from within detect.
static int CmdT55xxWakeUp (const char *Cmd);
static int CmdT55xxWakeUp(const char *Cmd);
static int CmdT55xxDetect(const char *Cmd) {
@@ -1054,7 +1054,7 @@ static int CmdT55xxDetect(const char *Cmd) {
return usage_t55xx_detect();
case 'p':
password = param_get32ex(Cmd, cmdp + 1, 0, 16);
sprintf (wakecmd,"p %08x q",(uint32_t)(password & 0xFFFFFFFF));
sprintf(wakecmd, "p %08x q", (uint32_t)(password & 0xFFFFFFFF));
usepwd = true;
cmdp += 2;
break;
@@ -1077,7 +1077,7 @@ static int CmdT55xxDetect(const char *Cmd) {
}
if (errors) return usage_t55xx_detect();
// detect called so clear data blocks
T55x7_ClearAllBlockData();
@@ -1096,11 +1096,11 @@ static int CmdT55xxDetect(const char *Cmd) {
if (usewake) {
// call wake
if (try_with_pwd)
CmdT55xxWakeUp (wakecmd);
CmdT55xxWakeUp(wakecmd);
else
CmdT55xxWakeUp ("q");
CmdT55xxWakeUp("q");
// sleep 90 ms
nanosleep (&sleepperiod, &sleepperiod);
nanosleep(&sleepperiod, &sleepperiod);
}
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, (try_with_pwd && usepwd), password, m) == false)
@@ -1117,11 +1117,11 @@ static int CmdT55xxDetect(const char *Cmd) {
if (usewake) {
// call wake
if (try_with_pwd)
CmdT55xxWakeUp (wakecmd);
CmdT55xxWakeUp(wakecmd);
else
CmdT55xxWakeUp ("q");
CmdT55xxWakeUp("q");
// sleep 90 ms
nanosleep (&sleepperiod, &sleepperiod);
nanosleep(&sleepperiod, &sleepperiod);
}
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, downlink_mode)) {

View File

@@ -8,10 +8,10 @@
// Low frequency TI commands
//-----------------------------------------------------------------------------
#include "cmdlfti.h"
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "cmdparser.h" // command_t
#include "commonutil.h"
#include "comms.h"
@@ -19,7 +19,7 @@
#include "ui.h"
#include "proxgui.h"
#include "graph.h"
#include "cmdlfti.h"
#include "cliparser.h"
static int CmdHelp(const char *Cmd);
@@ -277,10 +277,27 @@ static int CmdTIDemod(const char *Cmd) {
}
// read a TI tag and return its ID
static int CmdTIRead(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
clearCommandBuffer();
SendCommandNG(CMD_LF_TI_READ, NULL, 0);
static int CmdTIReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf ti reader",
"read a TI tag",
"lf ti reader -@ -> continuous reader mode"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
do {
clearCommandBuffer();
SendCommandNG(CMD_LF_TI_READ, NULL, 0);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
@@ -300,15 +317,15 @@ static int CmdTIWrite(const char *Cmd) {
clearCommandBuffer();
SendCommandMIX(CMD_LF_TI_WRITE, arg0, arg1, arg2, NULL, 0);
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf ti read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf ti reader`") " to verify");
return PM3_SUCCESS;
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdTIDemod, AlwaysAvailable, "Demodulate raw bits for TI-type LF tag from the GraphBuffer"},
{"read", CmdTIRead, IfPm3Lf, "Read and decode a TI 134 kHz tag"},
{"write", CmdTIWrite, IfPm3Lf, "Write new data to a r/w TI 134 kHz tag"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdTIDemod, AlwaysAvailable, "Demodulate raw bits for TI-type LF tag from the GraphBuffer"},
{"reader", CmdTIReader, IfPm3Lf, "Read and decode a TI 134 kHz tag"},
{"write", CmdTIWrite, IfPm3Lf, "Write new data to a r/w TI 134 kHz tag"},
{NULL, NULL, NULL, NULL}
};

View File

@@ -9,13 +9,10 @@
// ASK/Manchester, RF/32, 64 bits (complete)
//-----------------------------------------------------------------------------
#include "cmdlfviking.h"
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "common.h"
#include "cmdparser.h" // command_t
#include "comms.h"
#include "ui.h"
@@ -23,36 +20,10 @@
#include "cmdlf.h"
#include "lfdemod.h"
#include "commonutil.h" // num_to_bytes
#include "cliparser.h"
static int CmdHelp(const char *Cmd);
static int usage_lf_viking_clone(void) {
PrintAndLogEx(NORMAL, "clone a Viking AM tag to a T55x7 or Q5/T5555 tag.");
PrintAndLogEx(NORMAL, "Usage: lf viking clone <Card ID - 8 hex digits> <Q5>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " <Card Number> : 8 digit hex viking card number");
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag)");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf viking clone 1A337"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf viking clone 1A337 Q5") " - encode for Q5/T5555 tag");
return PM3_SUCCESS;
}
static int usage_lf_viking_sim(void) {
PrintAndLogEx(NORMAL, "Enables simulation of viking card with specified card number.");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "Per viking format, the card number is 8 digit hex number. Larger values are truncated.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf viking sim <Card-Number>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " <Card Number> : 8 digit hex viking card number");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf viking sim 1A337"));
return PM3_SUCCESS;
}
//see ASKDemod for what args are accepted
int demodViking(bool verbose) {
(void) verbose; // unused so far
@@ -88,40 +59,90 @@ static int CmdVikingDemod(const char *Cmd) {
}
//see ASKDemod for what args are accepted
static int CmdVikingRead(const char *Cmd) {
(void)Cmd;
lf_read(false, 10000);
return demodViking(true);
static int CmdVikingReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf viking reader",
"read a Viking AM tag",
"lf viking reader -@ -> continuous reader mode"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
do {
lf_read(false, 10000);
demodViking(true);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
static int CmdVikingClone(const char *Cmd) {
uint32_t id = 0;
uint64_t rawID = 0;
bool Q5 = false;
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_viking_clone();
id = param_get32ex(Cmd, 0, 0, 16);
if (id == 0) return usage_lf_viking_clone();
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf viking clone",
"clone a Viking AM tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
"lf viking clone --cn 01A337\n"
"lf viking clone --cn 01A337 --q5 -> encode for Q5/T5555 tag\n"
"lf viking clone --cn 112233 --em -> encode for EM4305/4469"
);
cmdp = tolower(param_getchar(Cmd, 1));
if (cmdp == 'q')
Q5 = true;
void *argtable[] = {
arg_param_begin,
arg_strx0(NULL, "cn", "<hex>", "8 digit hex viking card number"),
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
rawID = getVikingBits(id);
int raw_len = 0;
uint8_t raw[4] = {0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
bool q5 = arg_get_lit(ctx, 2);
bool em = arg_get_lit(ctx, 3);
CLIParserFree(ctx);
uint32_t id = bytes_to_num(raw, raw_len);
if (id == 0) {
PrintAndLogEx(ERR, "Cardnumber can't be zero");
return PM3_EINVARG;
}
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
uint64_t rawID = getVikingBits(id);
struct p {
bool Q5;
bool EM;
uint8_t blocks[8];
} PACKED payload;
payload.Q5 = Q5;
payload.Q5 = q5;
payload.EM = em;
num_to_bytes(rawID, 8, &payload.blocks[0]);
char cardtype[16] = {"T55x7"};
if (q5)
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
else if (em)
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
PrintAndLogEx(INFO, "Preparing to clone Viking tag on " _YELLOW_("%s") " - ID " _YELLOW_("%08X")" raw " _YELLOW_("%s")
, (Q5) ? "Q5/T5555" : "T55x7"
, cardtype
, id
, sprint_hex(payload.blocks, sizeof(payload.blocks))
, sprint_hex(payload.blocks, sizeof(payload.blocks))
);
clearCommandBuffer();
@@ -133,20 +154,40 @@ static int CmdVikingClone(const char *Cmd) {
return PM3_ETIMEOUT;
}
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf viking read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf viking reader`") " to verify");
return resp.status;
}
static int CmdVikingSim(const char *Cmd) {
uint32_t id = 0;
uint64_t rawID = 0;
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_viking_sim();
id = param_get32ex(Cmd, 0, 0, 16);
if (id == 0) return usage_lf_viking_sim();
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf viking sim",
"Enables simulation of viking card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.\n"
"Per viking format, the card number is 8 digit hex number. Larger values are truncated.",
"lf viking sim --cn 01A337"
);
rawID = getVikingBits(id);
void *argtable[] = {
arg_param_begin,
arg_strx0(NULL, "cn", "<hex>", "8 digit hex viking card number"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int raw_len = 0;
uint8_t raw[4] = {0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
uint32_t id = bytes_to_num(raw, raw_len);
if (id == 0) {
PrintAndLogEx(ERR, "Cardnumber can't be zero");
CLIParserFree(ctx);
return PM3_EINVARG;
}
CLIParserFree(ctx);
uint64_t rawID = getVikingBits(id);
PrintAndLogEx(SUCCESS, "Simulating Viking - ID " _YELLOW_("%08X") " raw " _YELLOW_("%08X%08X"), id, (uint32_t)(rawID >> 32), (uint32_t)(rawID & 0xFFFFFFFF));
@@ -176,7 +217,7 @@ static int CmdVikingSim(const char *Cmd) {
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdVikingDemod, AlwaysAvailable, "Demodulate a Viking tag from the GraphBuffer"},
{"read", CmdVikingRead, IfPm3Lf, "Attempt to read and Extract tag data from the antenna"},
{"reader", CmdVikingReader, IfPm3Lf, "Attempt to read and Extract tag data from the antenna"},
{"clone", CmdVikingClone, IfPm3Lf, "clone Viking tag to T55x7 or Q5/T5555"},
{"sim", CmdVikingSim, IfPm3Lf, "simulate Viking tag"},
{NULL, NULL, NULL, NULL}
@@ -201,7 +242,7 @@ uint64_t getVikingBits(uint32_t id) {
ret |= checksum;
return ret;
}
// by marshmellow
// find viking preamble 0xF200 in already demoded data
int detectViking(uint8_t *src, size_t *size) {
//make sure buffer has data

View File

@@ -27,41 +27,14 @@
#include "lfdemod.h" // parityTest
#include "cmdlft55xx.h" // write verify
#include "cmdlfem4x05.h" //
#include "cliparser.h"
#define BL0CK1 0x56495332
#ifndef VISA2k_BL0CK1
#define VISA2k_BL0CK1 0x56495332
#endif
static int CmdHelp(const char *Cmd);
static int usage_lf_visa2k_clone(void) {
PrintAndLogEx(NORMAL, "clone a Visa2000 tag to a T55x7 or Q5/T5555 tag.");
PrintAndLogEx(NORMAL, "Usage: lf visa2000 clone [h] <card ID> <Q5>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <card ID> : Visa2k card ID");
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, " <em4305> : specify writing to EM4305/4469 tag");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233 q5") " -- encode for Q5/T5555");
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 clone 112233 em4305") " -- encode for EM4305/4469");
return PM3_SUCCESS;
}
static int usage_lf_visa2k_sim(void) {
PrintAndLogEx(NORMAL, "Enables simulation of visa2k card with specified card number.");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf visa2000 sim [h] <card ID>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <card ID> : Visa2k card ID");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf visa2000 sim 112233"));
return PM3_SUCCESS;
}
static uint8_t visa_chksum(uint32_t id) {
uint8_t sum = 0;
for (uint8_t i = 0; i < 32; i += 4)
@@ -165,47 +138,76 @@ static int CmdVisa2kDemod(const char *Cmd) {
}
// 64*96*2=12288 samples just in case we just missed the first preamble we can still catch 2 of them
static int CmdVisa2kRead(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
lf_read(false, 20000);
return demodVisa2k(true);
static int CmdVisa2kReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf visa2000 reader",
"read a visa2000 tag",
"lf visa2000 reader -@ -> continuous reader mode"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
do {
lf_read(false, 20000);
demodVisa2k(!cm);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
static int CmdVisa2kClone(const char *Cmd) {
uint64_t id = 0;
uint32_t blocks[4] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_64 | T55x7_ST_TERMINATOR | 3 << T55x7_MAXBLOCK_SHIFT, BL0CK1, 0};
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf visa2000 clone",
"clone a Visa2000 tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
"lf visa2000 clone --cn 112233\n"
"lf visa2000 clone --cn 112233 --q5 -> encode for Q5/T5555 tag\n"
"lf visa2000 clone --cn 112233 --em -> encode for EM4305/4469"
);
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h')
return usage_lf_visa2k_clone();
void *argtable[] = {
arg_param_begin,
arg_u64_1(NULL, "cn", "<dec>", "Visa2k card ID"),
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
id = param_get32ex(Cmd, 0, 0, 10);
char cardtype[16] = {"T55x7"};
// Q5
bool q5 = tolower(param_getchar(Cmd, 1)) == 'q';
if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
// EM4305
bool em = tolower(param_getchar(Cmd, 1)) == 'e';
if (em) {
blocks[0] = EM4305_VISA2000_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
uint32_t id = arg_get_u32_def(ctx, 1, 0);
bool q5 = arg_get_lit(ctx, 2);
bool em = arg_get_lit(ctx, 3);
CLIParserFree(ctx);
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
uint32_t blocks[4] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_64 | T55x7_ST_TERMINATOR | 3 << T55x7_MAXBLOCK_SHIFT, VISA2k_BL0CK1, 0};
char cardtype[16] = {"T55x7"};
// Q5
if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
// EM4305
if (em) {
blocks[0] = EM4305_VISA2000_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
blocks[2] = id;
blocks[3] = (visa_parity(id) << 4) | visa_chksum(id);
PrintAndLogEx(INFO, "Preparing to clone Visa2000 to " _YELLOW_("%s") " with CardId: %"PRIu64, cardtype, id);
PrintAndLogEx(INFO, "Preparing to clone Visa2000 to " _YELLOW_("%s") " with CardId: %"PRIu32, cardtype, id);
print_blocks(blocks, ARRAYLEN(blocks));
int res;
@@ -215,22 +217,31 @@ static int CmdVisa2kClone(const char *Cmd) {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf visa2000 read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf visa2000 reader`") " to verify");
return res;
}
static int CmdVisa2kSim(const char *Cmd) {
uint32_t id = 0;
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h')
return usage_lf_visa2k_sim();
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf visa2000 sim",
"Enables simulation of visa2k card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.\n",
"lf visa2000 sim --cn 1337"
);
id = param_get32ex(Cmd, 0, 0, 10);
void *argtable[] = {
arg_param_begin,
arg_u64_1(NULL, "cn", "<dec>", "Visa2k card ID"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint32_t id = arg_get_u32_def(ctx, 1, 0);
CLIParserFree(ctx);
PrintAndLogEx(SUCCESS, "Simulating Visa2000 - CardId: %u", id);
PrintAndLogEx(SUCCESS, "Simulating Visa2000 - CardId:" _YELLOW_("%u"), id);
uint32_t blocks[3] = { BL0CK1, id, (visa_parity(id) << 4) | visa_chksum(id) };
uint32_t blocks[3] = { VISA2k_BL0CK1, id, (visa_parity(id) << 4) | visa_chksum(id) };
uint8_t bs[96];
for (int i = 0; i < 3; ++i)
@@ -257,11 +268,11 @@ static int CmdVisa2kSim(const char *Cmd) {
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdVisa2kDemod, AlwaysAvailable, "demodulate an VISA2000 tag from the GraphBuffer"},
{"read", CmdVisa2kRead, IfPm3Lf, "attempt to read and extract tag data from the antenna"},
{"clone", CmdVisa2kClone, IfPm3Lf, "clone Visa2000 tag to T55x7 or Q5/T5555"},
{"sim", CmdVisa2kSim, IfPm3Lf, "simulate Visa2000 tag"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdVisa2kDemod, AlwaysAvailable, "demodulate an VISA2000 tag from the GraphBuffer"},
{"reader", CmdVisa2kReader, IfPm3Lf, "attempt to read and extract tag data from the antenna"},
{"clone", CmdVisa2kClone, IfPm3Lf, "clone Visa2000 tag to T55x7 or Q5/T5555"},
{"sim", CmdVisa2kSim, IfPm3Lf, "simulate Visa2000 tag"},
{NULL, NULL, NULL, NULL}
};

View File

@@ -120,7 +120,7 @@ static int lf_search_plus(const char *Cmd) {
return retval;
}
static int CmdAuto(const char *Cmd) {
static int CmdAuto(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "auto",
"Run LF SEARCH / HF SEARCH / DATA PLOT / DATA SAVE",
@@ -136,7 +136,7 @@ static int CmdAuto(const char *Cmd) {
PrintAndLogEx(INFO, "lf search");
int ret = CmdLFfind("");
if (ret == PM3_SUCCESS)
if (ret == PM3_SUCCESS)
return ret;
PrintAndLogEx(INFO, "hf search");
@@ -193,7 +193,7 @@ static int CmdHints(const char *Cmd) {
PrintAndLogEx(ERR, "you can't turn off and on at the same time");
return PM3_EINVARG;
}
if (turn_off) {
session.show_hints = false;
} else if (turn_on) {

View File

@@ -116,7 +116,7 @@ static void asn1_tag_dump_str_time(const struct tlv *tlv, const struct asn1_tag
if (longyear == false)
PrintAndLogEx(NORMAL, "20" NOLF);
PrintAndLogEx(NORMAL, "%s-" NOLF, sprint_hex(tlv->value, startindx) );
PrintAndLogEx(NORMAL, "%s-" NOLF, sprint_hex(tlv->value, startindx));
if (len < startindx + 2)
break;
@@ -276,7 +276,7 @@ static void asn1_tag_dump_object_id(const struct tlv *tlv, const struct asn1_tag
asn1_buf.p = (uint8_t *)tlv->value;
char pstr[300];
mbedtls_oid_get_numeric_string(pstr, sizeof(pstr), &asn1_buf);
PrintAndLogEx(INFO, "%*s %s" NOLF, (level * 4), " ", pstr);
char *jsondesc = asn1_oid_description(pstr, true);

View File

@@ -462,9 +462,9 @@ static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *ta
if (val & 0x80) {
PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " ");
PrintAndLogEx(NORMAL, " %s - '%s'",
bitstrings[bit - 1],
(bits->bit == EMV_BIT(byte, bit)) ? bits->name : "Unknown"
);
bitstrings[bit - 1],
(bits->bit == EMV_BIT(byte, bit)) ? bits->name : "Unknown"
);
}
if (bits->bit == EMV_BIT(byte, bit))
bits ++;
@@ -535,10 +535,10 @@ static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *ta
static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, int level) {
PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " ");
PrintAndLogEx(NORMAL, " Date: 20%02lu.%lu.%lu",
emv_value_numeric(tlv, 0, 2),
emv_value_numeric(tlv, 2, 4),
emv_value_numeric(tlv, 4, 6)
);
emv_value_numeric(tlv, 0, 2),
emv_value_numeric(tlv, 2, 4),
emv_value_numeric(tlv, 4, 6)
);
}
static uint32_t emv_get_binary(const unsigned char *S) {
@@ -749,12 +749,12 @@ static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *t
PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " ");
PrintAndLogEx(NORMAL, " %02x %02x: '%s' '%s' and '%s' if this CVM is unsuccessful",
tlv->value[i],
tlv->value[i + 1],
method,
condition,
(tlv->value[i] & 0x40) ? "continue" : "fail"
);
tlv->value[i],
tlv->value[i + 1],
method,
condition,
(tlv->value[i] & 0x40) ? "continue" : "fail"
);
}
}

View File

@@ -778,7 +778,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) {
if (sdad_tlv) {
PrintAndLogEx(INFO, "* * Got Signed Dynamic Application Data (9F4B) form GPO. Maybe fDDA...");
const struct tlvdb *atc_db = emv_pki_recover_atc_ex(icc_pk, tlv, true);
struct tlvdb *atc_db = emv_pki_recover_atc_ex(icc_pk, tlv, true);
if (!atc_db) {
PrintAndLogEx(ERR, "Error: Can't recover IDN (ICC Dynamic Number)");
emv_pk_free(pk);
@@ -804,9 +804,10 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) {
emv_pk_free(pk);
emv_pk_free(issuer_pk);
emv_pk_free(icc_pk);
atc_db = NULL;
tlvdb_free(atc_db);
return 9;
}
} else {
struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv);
if (dac_db) {

View File

@@ -541,7 +541,7 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b
res = CborGetArrayBinStringValue(&mapsmt, der, sizeof(der), &derLen);
cbor_check(res);
if (verbose2) {
PrintAndLogEx(INFO, "DER certificate[%zu]:", derLen);
PrintAndLogEx(INFO, "DER certificate[%zu]:", derLen);
PrintAndLogEx(INFO, "------------------DER-------------------");
PrintAndLogEx(INFO, "%s", sprint_hex(der, derLen));
PrintAndLogEx(INFO, "----------------DER---------------------");

View File

@@ -468,9 +468,9 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[]) {
mbedtls_des_setkey_enc(&ctx_e, key64_stdformat);
mbedtls_des_crypt_ecb(&ctx_e, key64_negated, result);
PrintAndLogEx(NORMAL, "\n");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "-- High security custom key (Kcus) --");
PrintAndLogEx(SUCCESS, "Standard format %s", sprint_hex(key64_stdformat, 8));
PrintAndLogEx(SUCCESS, "Standard format " _GREEN_("%s"), sprint_hex(key64_stdformat, 8));
PrintAndLogEx(SUCCESS, "iClass format %s", sprint_hex(key64, 8));
if (master_key != NULL)

View File

@@ -212,23 +212,23 @@ void print_buffer(const uint8_t *data, const size_t len, int level) {
// (16 * 3) + (16) + + 1
memset(buf, 0, sizeof(buf));
sprintf(buf, "%*s%02x: ", (level * 4), " ", i);
hex_to_buffer((uint8_t *)(buf + strlen(buf)), data + i, 16, (sizeof(buf) - strlen(buf) - 1), 0, 1, true);
hex_to_buffer((uint8_t *)(buf + strlen(buf)), data + i, 16, (sizeof(buf) - strlen(buf) - 1), 0, 1, true);
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "| %s", sprint_ascii(data + i, 16));
PrintAndLogEx(INFO, "%s", buf);
}
// the last odd bytes
uint8_t mod = len % 16;
if (mod) {
memset(buf, 0, sizeof(buf));
sprintf(buf, "%*s%02x: ", (level * 4), " ", i);
hex_to_buffer((uint8_t *)(buf + strlen(buf)), data + i, mod, (sizeof(buf) - strlen(buf) - 1), 0, 1, true);
// add the spaces...
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%*s", ((16 - mod) * 3) , " ");
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%*s", ((16 - mod) * 3), " ");
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "| %s", sprint_ascii(data + i, mod));
PrintAndLogEx(INFO, "%s", buf);
}
@@ -446,6 +446,25 @@ void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest) {
}
}
void bytes_to_bytebits(void* src, size_t srclen, void* dest) {
uint8_t *s = (uint8_t*)src;
uint8_t *d = (uint8_t*)dest;
uint32_t i = srclen * 8;
while (srclen--) {
uint8_t b = s[srclen];
d[--i] = (b >> 0) & 1;
d[--i] = (b >> 1) & 1;
d[--i] = (b >> 2) & 1;
d[--i] = (b >> 3) & 1;
d[--i] = (b >> 4) & 1;
d[--i] = (b >> 5) & 1;
d[--i] = (b >> 6) & 1;
d[--i] = (b >> 7) & 1;
}
}
// aa,bb,cc,dd,ee,ff,gg,hh, ii,jj,kk,ll,mm,nn,oo,pp
// to
// hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii

View File

@@ -56,6 +56,7 @@ void print_blocks(uint32_t *data, size_t len);
int hex_to_bytes(const char *hexValue, uint8_t *bytesValue, size_t maxBytesValueLen);
void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest);
void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest);
void bytes_to_bytebits(void* src, size_t srclen, void* dest);
// Swap endian on arrays up to 64bytes.
uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize);