mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
Merge remote-tracking branch 'origin'
This commit is contained in:
commit
db7598ff6b
12 changed files with 380 additions and 52 deletions
4
.github/workflows/windows.yml
vendored
4
.github/workflows/windows.yml
vendored
|
@ -98,9 +98,9 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: WSL setup
|
||||
uses: Vampire/setup-wsl@v1
|
||||
uses: Vampire/setup-wsl@v2
|
||||
with:
|
||||
distribution: Ubuntu-20.04
|
||||
distribution: Ubuntu-22.04
|
||||
update: "true"
|
||||
additional-packages: git
|
||||
ca-certificates
|
||||
|
|
|
@ -21,6 +21,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
|||
- Added `--back` option to `clear` command to clear the scrollback buffer (@wh201906)
|
||||
- Changed `hf iclass decrypt` - mark credentials as decrypted in the dump (@natesales)
|
||||
- Changed `hf iclass view` - show credentials on a decrypted dump (@natesales)
|
||||
- Show NTAG213TT tamper info in `hf mfu info` and add commands for configuring it's tamper feature (@mjaksn)
|
||||
- Add Mifare Classic EV1 signature write support to gen4 magic tag lua script (@augustozanellato)
|
||||
|
||||
## [Nitride.4.16191][2023-01-29]
|
||||
- Changed `build_all_firmwares.sh` to fit GENERIC 256kb firmware images (@doegox)
|
||||
|
|
|
@ -2028,3 +2028,5 @@ F72CD208FDF9
|
|||
#
|
||||
# 1k - waldorf astoria
|
||||
011C6CF459E8
|
||||
# Food GEM
|
||||
6686FADE5566
|
||||
|
|
|
@ -13,7 +13,7 @@ local err_lock = 'use -k or change cfg0 block'
|
|||
local _print = 0
|
||||
copyright = ''
|
||||
author = 'Nathan Glaser'
|
||||
version = 'v1.0.4'
|
||||
version = 'v1.0.5'
|
||||
date = 'Created - Jan 2022'
|
||||
desc = 'This script enables easy programming of an Ultimate Mifare Magic card'
|
||||
example = [[
|
||||
|
@ -483,17 +483,29 @@ local function write_signature(data)
|
|||
end
|
||||
local info = connect()
|
||||
if not info then return false, "Can't select card" end
|
||||
if ulprotocol == '00' then return nil, 'Magic Card is not using the Ultralight Protocol' end
|
||||
print('Writing new signature',data)
|
||||
local b,c
|
||||
local cmd = 'A2F%d%s'
|
||||
local j = 2
|
||||
for i = 1, #data, 8 do
|
||||
b = data:sub(i,i+7)
|
||||
c = cmd:format(j,b)
|
||||
local resp = send(c)
|
||||
if resp ~= '0A' then lib14a.disconnect(); return nil, oops('Failed to write signature') end
|
||||
j = j + 1
|
||||
if ulprotocol == '00' then
|
||||
print('Writing new MFC signature',data)
|
||||
send('CF'.._key..'6B48')
|
||||
lib14a.disconnect()
|
||||
connect() -- not 100% sure why it's needed, but without this blocks aren't actually written
|
||||
local sig1 = data:sub(1, 32)
|
||||
local sig2 = data:sub(33, 64)
|
||||
|
||||
send('CF'.._key..'CD45'..sig1)
|
||||
send('CF'.._key..'CD46'..sig2)
|
||||
send('CF'.._key..'CD475C8FF9990DA270F0F8694B791BEA7BCC')
|
||||
else
|
||||
print('Writing new MFUL signature',data)
|
||||
local b,c
|
||||
local cmd = 'A2F%d%s'
|
||||
local j = 2
|
||||
for i = 1, #data, 8 do
|
||||
b = data:sub(i,i+7)
|
||||
c = cmd:format(j,b)
|
||||
local resp = send(c)
|
||||
if resp ~= '0A' then lib14a.disconnect(); return nil, oops('Failed to write signature') end
|
||||
j = j + 1
|
||||
end
|
||||
end
|
||||
lib14a.disconnect()
|
||||
return true, 'Ok'
|
||||
|
|
|
@ -392,6 +392,12 @@ static int ul_auth_select(iso14a_card_select_t *card, TagTypeUL_t tagtype, bool
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int ntagtt_getTamperStatus(uint8_t *response, uint16_t responseLength) {
|
||||
uint8_t cmd[] = {NTAGTT_CMD_READ_TT, 0x00};
|
||||
int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int ulev1_getVersion(uint8_t *response, uint16_t responseLength) {
|
||||
uint8_t cmd[] = {MIFARE_ULEV1_VERSION};
|
||||
int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
|
||||
|
@ -748,8 +754,75 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st
|
|||
|
||||
PrintAndLogEx(INFO, " cfg0 [%u/0x%02X]: %s", startPage, startPage, sprint_hex(data, 4));
|
||||
|
||||
if ((tagtype & (NTAG_213_F | NTAG_213_TT | NTAG_216_F))) {
|
||||
uint8_t mirror_conf = (data[0] & 0xC0);
|
||||
//NTAG213TT has different ASCII mirroring options and config bytes interpretation from other ulev1 class tags
|
||||
if (tagtype & NTAG_213_TT) {
|
||||
uint8_t mirror_conf = ((data[0] & 0xE0) >> 5);
|
||||
uint8_t mirror_byte = ((data[0] & 0x18) >> 3);
|
||||
uint8_t mirror_page = data[2];
|
||||
|
||||
switch (mirror_conf) {
|
||||
case 0:
|
||||
PrintAndLogEx(INFO, " - no ASCII mirror");
|
||||
break;
|
||||
case 1:
|
||||
PrintAndLogEx(INFO, " - UID ASCII mirror");
|
||||
break;
|
||||
case 2:
|
||||
PrintAndLogEx(INFO, " - NFC counter ASCII mirror");
|
||||
break;
|
||||
case 3:
|
||||
PrintAndLogEx(INFO, " - UID and NFC counter ASCII mirror");
|
||||
break;
|
||||
case 4:
|
||||
PrintAndLogEx(INFO, " - tag tamper ASCII mirror");
|
||||
break;
|
||||
case 5:
|
||||
PrintAndLogEx(INFO, " - UID and tag tamper ASCII mirror");
|
||||
break;
|
||||
case 6:
|
||||
PrintAndLogEx(INFO, " - NFC counter and tag tamper ASCII mirror");
|
||||
break;
|
||||
case 7:
|
||||
PrintAndLogEx(INFO, " - UID, NFC counter, and tag tamper ASCII mirror");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (mirror_conf) {
|
||||
uint8_t mirror_user_mem_start_byte = (4 * (mirror_page - 4)) + mirror_byte;
|
||||
uint8_t bytes_required_for_mirror_data = 0;
|
||||
|
||||
switch (mirror_conf) {
|
||||
case 1:
|
||||
bytes_required_for_mirror_data = 14;
|
||||
break;
|
||||
case 2:
|
||||
bytes_required_for_mirror_data = 6;
|
||||
break;
|
||||
case 3:
|
||||
bytes_required_for_mirror_data = 8;
|
||||
break;
|
||||
case 4:
|
||||
bytes_required_for_mirror_data = 21;
|
||||
break;
|
||||
case 5:
|
||||
bytes_required_for_mirror_data = 23;
|
||||
break;
|
||||
case 6:
|
||||
bytes_required_for_mirror_data = 15;
|
||||
break;
|
||||
case 7:
|
||||
bytes_required_for_mirror_data = 30;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
PrintAndLogEx(INFO, " mirror start page %02X | byte pos %02X - %s", mirror_page, mirror_byte, (mirror_page >= 0x4 && ((mirror_user_mem_start_byte + bytes_required_for_mirror_data) <= 144)) ? _GREEN_("OK") : _YELLOW_("Invalid value"));
|
||||
}
|
||||
|
||||
} else if (tagtype & (NTAG_213_F | NTAG_216_F)) {
|
||||
uint8_t mirror_conf = ((data[0] & 0xC0) >> 6);
|
||||
uint8_t mirror_byte = (data[0] & 0x30);
|
||||
bool sleep_en = (data[0] & 0x08);
|
||||
strg_mod_en = (data[0] & 0x04);
|
||||
|
@ -791,7 +864,7 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st
|
|||
break;
|
||||
}
|
||||
// valid mirror start page and byte position within start page.
|
||||
if ((tagtype & NTAG_213_F) || (tagtype & NTAG_213_TT)) {
|
||||
if (tagtype & NTAG_213_F) {
|
||||
switch (mirror_conf) {
|
||||
case 1:
|
||||
{ PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0x24) ? "OK" : "Invalid value"); break;}
|
||||
|
@ -822,6 +895,35 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st
|
|||
else
|
||||
PrintAndLogEx(INFO, " - pages don't need authentication");
|
||||
|
||||
uint8_t tt_enabled = 0;
|
||||
uint8_t tt_message[4] = {0x00};
|
||||
uint8_t tt_msg_resp_len = 0;
|
||||
uint8_t tt_status_resp[5] = {0x00};
|
||||
|
||||
if (tagtype & NTAG_213_TT) {
|
||||
tt_enabled = (data[1] & 0x02);
|
||||
tt_msg_resp_len = ul_read(45, tt_message, 4);
|
||||
|
||||
PrintAndLogEx(INFO, " - tamper detection feature is %s"
|
||||
, (tt_enabled) ? _GREEN_("ENABLED") : "disabled"
|
||||
);
|
||||
|
||||
switch (data[1] & 0x06) {
|
||||
case 0x00:
|
||||
PrintAndLogEx(INFO, " - tamper message is unlocked and read/write enabled");
|
||||
break;
|
||||
case 0x02:
|
||||
PrintAndLogEx(INFO, " - tamper message is reversibly read/write locked in memory while the tamper feature is enabled");
|
||||
break;
|
||||
case 0x04:
|
||||
case 0x06:
|
||||
PrintAndLogEx(INFO, " - tamper message is permanently read/write locked in memory");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, " cfg1 [%u/0x%02X]: %s", startPage + 1, startPage + 1, sprint_hex(data + 4, 4));
|
||||
if (authlim == 0)
|
||||
PrintAndLogEx(INFO, " - " _GREEN_("Unlimited password attempts"));
|
||||
|
@ -837,6 +939,55 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st
|
|||
PrintAndLogEx(INFO, " PWD [%u/0x%02X]: %s- (cannot be read)", startPage + 2, startPage + 2, sprint_hex(data + 8, 4));
|
||||
PrintAndLogEx(INFO, " PACK [%u/0x%02X]: %s - (cannot be read)", startPage + 3, startPage + 3, sprint_hex(data + 12, 2));
|
||||
PrintAndLogEx(INFO, " RFU [%u/0x%02X]: %s- (cannot be read)", startPage + 3, startPage + 3, sprint_hex(data + 14, 2));
|
||||
|
||||
if (tagtype & NTAG_213_TT) {
|
||||
if (data[1] & 0x06) {
|
||||
PrintAndLogEx(INFO, "TT_MSG [45/0x2D]: %s- (cannot be read)", sprint_hex(tt_message, tt_msg_resp_len));
|
||||
PrintAndLogEx(INFO, " - tamper message is masked in memory");
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "TT_MSG [45/0x2D]: %s", sprint_hex(tt_message, tt_msg_resp_len));
|
||||
PrintAndLogEx(INFO, " - tamper message is %s and is readable/writablbe in memory", sprint_hex(tt_message, tt_msg_resp_len));
|
||||
}
|
||||
}
|
||||
|
||||
//The NTAG213TT only returns meaningful information for the fields below if the tamper feature is enabled
|
||||
if ((tagtype & NTAG_213_TT) && tt_enabled) {
|
||||
|
||||
uint8_t tt_status_len = ntagtt_getTamperStatus(tt_status_resp, 5);
|
||||
|
||||
if (tt_status_len != 5) {
|
||||
PrintAndLogEx(WARNING, "Error sending the READ_TT_STATUS command to tag\n");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Tamper Status"));
|
||||
PrintAndLogEx(INFO, " READ_TT_STATUS: %s", sprint_hex(tt_status_resp, 5));
|
||||
|
||||
PrintAndLogEx(INFO, " Tamper status result from this power-up:");
|
||||
switch (tt_status_resp[4]) {
|
||||
case 0x43:
|
||||
PrintAndLogEx(INFO, " - Tamper loop was detcted as closed during this power-up");
|
||||
break;
|
||||
case 0x4F:
|
||||
PrintAndLogEx(INFO, " - Tamper loop was detected as open during this power-up");
|
||||
break;
|
||||
case 0x49:
|
||||
PrintAndLogEx(INFO, " - Tamper loop measurement was not enabled or not valid during this power-up");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, " Tamper detection permanent memory:");
|
||||
if ((tt_status_resp[0] | tt_status_resp [1] | tt_status_resp[2] | tt_status_resp[3]) == 0x00)
|
||||
|
||||
PrintAndLogEx(INFO, " - Tamper loop has never been detected as open during power-up");
|
||||
else {
|
||||
PrintAndLogEx(INFO, " - Tamper loop was detected as open during power-up at least once");
|
||||
PrintAndLogEx(INFO, " - Tamper message returned by READ_TT_STATUS command: %s", sprint_hex(tt_status_resp, 4));
|
||||
}
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1757,7 +1908,6 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
uint8_t startconfigblock = 0;
|
||||
uint8_t ulev1_conf[16] = {0x00};
|
||||
|
||||
// config blocks always are last 4 pages
|
||||
for (uint8_t i = 0; i < ARRAYLEN(UL_TYPES_ARRAY); i++) {
|
||||
if (tagtype & UL_TYPES_ARRAY[i]) {
|
||||
startconfigblock = UL_MEMORY_ARRAY[i] - 3;
|
||||
|
@ -2529,6 +2679,142 @@ static void wait4response(uint8_t b) {
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
//Configure tamper feature of NTAG 213TT
|
||||
//
|
||||
int CmdHF14MfUTamper(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfu tamper",
|
||||
"Set the congiguration of the NTAG 213TT tamper feature\n"
|
||||
"Supports:\n"
|
||||
"NTAG 213TT\n",
|
||||
"hf mfu tamper -e -> enable tamper feature\n"
|
||||
"hf mfu tamper -d -> disable tamper feature\n"
|
||||
"hf mfu tamper -m 0A0A0A0A -> set the tamper message to 0A0A0A0A\n"
|
||||
"hf mfu tamper --lockmessage -> permanently lock the tamper message and mask it from memory\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("e", "enable", "Enable the tamper feature"),
|
||||
arg_lit0("d", "disable", "Disable the tamper feature"),
|
||||
arg_str0("m", "message", "<hex>", "Set the tamper message (4 bytes)"),
|
||||
arg_lit0(NULL, "lockmessage", "Permanently lock the tamper message and mask it from memory (does not lock tamper feature itself)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int tt_cfg_page = 41;
|
||||
int tt_msg_page = 45;
|
||||
int msg_len = 0;
|
||||
uint8_t msg_data[4] = {0x00};
|
||||
CLIGetHexWithReturn(ctx, 3, msg_data, &msg_len);
|
||||
bool use_msg = (msg_len > 0);
|
||||
|
||||
if (use_msg && msg_len != 4) {
|
||||
PrintAndLogEx(WARNING, "The tamper message must be 4 hex bytes if provided");
|
||||
DropField();
|
||||
CLIParserFree(ctx);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
bool lock_msg = arg_get_lit(ctx, 4);
|
||||
bool enable = arg_get_lit(ctx, 1);
|
||||
bool disable = arg_get_lit(ctx, 2);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
TagTypeUL_t tagtype = GetHF14AMfU_Type();
|
||||
if (tagtype == UL_ERROR) {
|
||||
PrintAndLogEx(WARNING, "Tag type not detected");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
if (tagtype != NTAG_213_TT) {
|
||||
PrintAndLogEx(WARNING, "Tag type not NTAG 213TT");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
DropField();
|
||||
iso14a_card_select_t card;
|
||||
|
||||
if (enable && disable) {
|
||||
PrintAndLogEx(WARNING, "You can only select one of the options enable/disable tamper feature");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
if (use_msg) {
|
||||
if (ul_select(&card) == false) {
|
||||
DropField();
|
||||
return UL_ERROR;
|
||||
}
|
||||
PrintAndLogEx(INFO, "Trying to write tamper message\n");
|
||||
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, tt_msg_page, 0, 0, msg_data, 4);
|
||||
|
||||
PacketResponseNG resp;
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
||||
if (!isOK)
|
||||
PrintAndLogEx(WARNING, "Failed to write tamper message");
|
||||
else
|
||||
PrintAndLogEx(SUCCESS, "Tamper message written successfully");
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||
}
|
||||
}
|
||||
|
||||
if (enable | disable | lock_msg) {
|
||||
|
||||
if (ul_select(&card) == false) {
|
||||
PrintAndLogEx(ERR, "Unable to select tag");
|
||||
DropField();
|
||||
return UL_ERROR;
|
||||
}
|
||||
|
||||
uint8_t cfg_page[4] = {0x00};
|
||||
uint8_t cmd[] = {ISO14443A_CMD_READBLOCK, tt_cfg_page};
|
||||
int status = ul_send_cmd_raw(cmd, sizeof(cmd), cfg_page, 4);
|
||||
DropField();
|
||||
|
||||
if (status <= 0) {
|
||||
PrintAndLogEx(WARNING, "Problem reading current config from tag");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
cfg_page[1] = cfg_page[1] | 0x02;
|
||||
PrintAndLogEx(INFO, "Enabling tamper feature");
|
||||
}
|
||||
if (disable) {
|
||||
cfg_page[1] = cfg_page[1] & 0xFD;
|
||||
PrintAndLogEx(INFO, "Disabling tamper feature");
|
||||
}
|
||||
if (lock_msg) {
|
||||
cfg_page[1] = cfg_page[1] | 0x04;
|
||||
PrintAndLogEx(INFO, "Locking tamper message");
|
||||
}
|
||||
|
||||
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, tt_cfg_page, 0, 0, cfg_page, 4);
|
||||
PacketResponseNG resp;
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
||||
if (!isOK)
|
||||
PrintAndLogEx(WARNING, "Failed to write tamper configuration");
|
||||
else
|
||||
PrintAndLogEx(SUCCESS, "Tamper configuration written successfully");
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||
}
|
||||
}
|
||||
|
||||
DropField();
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Restore dump file onto tag
|
||||
//
|
||||
|
@ -4406,6 +4692,7 @@ static command_t CommandTable[] = {
|
|||
{"restore", CmdHF14AMfURestore, IfPm3Iso14443a, "Restore a dump onto a MFU MAGIC tag"},
|
||||
{"view", CmdHF14AMfuView, AlwaysAvailable, "Display content from tag dump file"},
|
||||
{"wrbl", CmdHF14AMfUWrBl, IfPm3Iso14443a, "Write block"},
|
||||
{"tamper", CmdHF14MfUTamper, IfPm3Iso14443a, "Cofigure the tamper feature on an NTAG 213TT"},
|
||||
{"---------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"},
|
||||
{"eload", CmdHF14AMfUeLoad, IfPm3Iso14443a, "Load Ultralight dump file into emulator memory"},
|
||||
{"esave", CmdHF14AMfuESave, IfPm3Iso14443a, "Save Ultralight dump file from emulator memory"},
|
||||
|
|
|
@ -50,6 +50,7 @@ int trace_mfuc_try_default_3des_keys(uint8_t **correct_key, int state, uint8_t (
|
|||
|
||||
int CmdHFMFUltra(const char *Cmd);
|
||||
int CmdHF14MfuNDEFRead(const char *Cmd);
|
||||
int CmdHF14MfUTamper(const char *Cmd);
|
||||
|
||||
uint16_t ul_ev1_packgen_VCNEW(uint8_t *uid, uint32_t pwd);
|
||||
uint32_t ul_ev1_otpgenA(uint8_t *uid);
|
||||
|
|
|
@ -86,9 +86,9 @@ static int demod_guard_raw(uint8_t *raw, uint8_t rlen) {
|
|||
}
|
||||
|
||||
if (unknown)
|
||||
PrintAndLogEx(SUCCESS, "G-Prox-II - Unknown len: " _GREEN_("%u") ", Raw: %s", fmtlen, sprint_hex_inrow(raw, rlen));
|
||||
PrintAndLogEx(SUCCESS, "G-Prox-II - xorKey: " _GREEN_("%u")" Unknown len: " _GREEN_("%u") ", Raw: %s", xorKey, fmtlen, sprint_hex_inrow(raw, rlen));
|
||||
else
|
||||
PrintAndLogEx(SUCCESS, "G-Prox-II - len: " _GREEN_("%u")" FC: " _GREEN_("%u") " Card: " _GREEN_("%u") ", Raw: %s", fmtlen, FC, Card, sprint_hex_inrow(raw, rlen));
|
||||
PrintAndLogEx(SUCCESS, "G-Prox-II - xorKey: " _GREEN_("%u")" Len: " _GREEN_("%u")" FC: " _GREEN_("%u") " Card: " _GREEN_("%u") ", Raw: %s", xorKey, fmtlen, FC, Card, sprint_hex_inrow(raw, rlen));
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -142,9 +142,11 @@ int demodGuard(bool verbose) {
|
|||
|
||||
// get key and then get all 8 bytes of payload decoded
|
||||
xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8);
|
||||
PrintAndLogEx(DEBUG, "DEBUG: gProxII xorKey: %u", xorKey);
|
||||
|
||||
for (size_t idx = 0; idx < 8; idx++) {
|
||||
plain[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer + 8 + (idx * 8), 8)) ^ xorKey;
|
||||
PrintAndLogEx(DEBUG, "DEBUG: gProxII byte %zu after xor: %02x", idx, plain[idx]);
|
||||
PrintAndLogEx(DEBUG, "DEBUG: gProxII byte %zu after xor: %02x (%02x before xor)", idx, plain[idx], bytebits_to_byteLSBF(bits_no_spacer + 8 + (idx * 8), 8));
|
||||
}
|
||||
|
||||
setDemodBuff(g_DemodBuffer, 96, preambleIndex);
|
||||
|
@ -161,6 +163,12 @@ int demodGuard(bool verbose) {
|
|||
bool unknown = false;
|
||||
switch (fmtLen) {
|
||||
case 36:
|
||||
PrintAndLogEx(DEBUG, "DEBUG: FC 1: %x", (plain[3] & 0x7F) << 7);
|
||||
PrintAndLogEx(DEBUG, "DEBUG: FC 2: %x", plain[4] >> 1);
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Card 1: %x", (plain[4] & 1) << 19);
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Card 2: %x", plain[5] << 11);
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Card 3: %x", plain[6] << 3);
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Card 4: %x", (plain[7] & 0xE0) >> 5);
|
||||
FC = ((plain[3] & 0x7F) << 7) | (plain[4] >> 1);
|
||||
Card = ((plain[4] & 1) << 19) | (plain[5] << 11) | (plain[6] << 3) | ((plain[7] & 0xE0) >> 5);
|
||||
break;
|
||||
|
@ -173,9 +181,9 @@ int demodGuard(bool verbose) {
|
|||
break;
|
||||
}
|
||||
if (!unknown)
|
||||
PrintAndLogEx(SUCCESS, "G-Prox-II - len: " _GREEN_("%u")" FC: " _GREEN_("%u") " Card: " _GREEN_("%u") ", Raw: %08x%08x%08x", fmtLen, FC, Card, raw1, raw2, raw3);
|
||||
PrintAndLogEx(SUCCESS, "G-Prox-II - xorKey: " _GREEN_("%u") " Len: " _GREEN_("%u")" FC: " _GREEN_("%u") " Card: " _GREEN_("%u") ", Raw: %08x%08x%08x", xorKey, fmtLen, FC, Card, raw1, raw2, raw3);
|
||||
else
|
||||
PrintAndLogEx(SUCCESS, "G-Prox-II - Unknown len: " _GREEN_("%u") ", Raw: %08x%08x%08x", fmtLen, raw1, raw2, raw3);
|
||||
PrintAndLogEx(SUCCESS, "G-Prox-II - xorKey: " _GREEN_("%u") " Unknown len: " _GREEN_("%u") ", Raw: %08x%08x%08x", xorKey, fmtLen, raw1, raw2, raw3);
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -243,16 +251,17 @@ static int CmdGuardReader(const char *Cmd) {
|
|||
static int CmdGuardClone(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf gproxii clone",
|
||||
"clone a Guardall tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
|
||||
"Clone a Guardall tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
|
||||
"The facility-code is 8-bit and the card number is 20-bit. Larger values are truncated.\n"
|
||||
"Currently work only on 26 | 36 bit format",
|
||||
"lf gproxii clone --fmt 26 --fc 123 --cn 1337 -> encode for T55x7 tag\n"
|
||||
"lf gproxii clone --fmt 26 --fc 123 --cn 1337 --q5 -> encode for Q5/T5555 tag\n"
|
||||
"lf gproxii clone --fmt 26 --fc 123 --cn 1337 --em -> encode for EM4305/4469"
|
||||
"lf gproxii clone --xor 141 --fmt 26 --fc 123 --cn 1337 -> encode for T55x7 tag\n"
|
||||
"lf gproxii clone --xor 141 --fmt 26 --fc 123 --cn 1337 --q5 -> encode for Q5/T5555 tag\n"
|
||||
"lf gproxii clone --xor 141 --fmt 26 --fc 123 --cn 1337 --em -> encode for EM4305/4469"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_u64_1(NULL, "xor", "<dec>", "8-bit xor value (installation dependant)"),
|
||||
arg_u64_1(NULL, "fmt", "<dec>", "format length 26|32|36|40"),
|
||||
arg_u64_1(NULL, "fc", "<dec>", "8-bit value facility code"),
|
||||
arg_u64_1(NULL, "cn", "<dec>", "16-bit value card number"),
|
||||
|
@ -262,11 +271,13 @@ static int CmdGuardClone(const char *Cmd) {
|
|||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
uint32_t fmtlen = arg_get_u32_def(ctx, 1, 0);
|
||||
uint32_t fc = arg_get_u32_def(ctx, 2, 0);
|
||||
uint32_t cn = arg_get_u32_def(ctx, 3, 0);
|
||||
bool q5 = arg_get_lit(ctx, 4);
|
||||
bool em = arg_get_lit(ctx, 5);
|
||||
uint32_t xorval = arg_get_u32_def(ctx, 1, 0);
|
||||
uint32_t fmtlen = arg_get_u32_def(ctx, 2, 0);
|
||||
uint32_t fc = arg_get_u32_def(ctx, 3, 0);
|
||||
uint32_t cn = arg_get_u32_def(ctx, 4, 0);
|
||||
|
||||
bool q5 = arg_get_lit(ctx, 5);
|
||||
bool em = arg_get_lit(ctx, 6);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (q5 && em) {
|
||||
|
@ -280,7 +291,7 @@ static int CmdGuardClone(const char *Cmd) {
|
|||
|
||||
//GuardProxII - compat mode, ASK/Biphase, data rate 64, 3 data blocks
|
||||
uint8_t *bs = calloc(96, sizeof(uint8_t));
|
||||
if (getGuardBits(fmtlen, facilitycode, cardnumber, bs) != PM3_SUCCESS) {
|
||||
if (getGuardBits(xorval, fmtlen, facilitycode, cardnumber, bs) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
|
||||
free(bs);
|
||||
return PM3_ESOFT;
|
||||
|
@ -306,10 +317,11 @@ static int CmdGuardClone(const char *Cmd) {
|
|||
|
||||
free(bs);
|
||||
|
||||
PrintAndLogEx(INFO, "Preparing to clone Guardall to " _YELLOW_("%s") " with Facility Code: " _GREEN_("%u") " Card Number: " _GREEN_("%u")
|
||||
PrintAndLogEx(INFO, "Preparing to clone Guardall to " _YELLOW_("%s") " with Facility Code: " _GREEN_("%u") " Card Number: " _GREEN_("%u") " xorKey: " _GREEN_("%u")
|
||||
, cardtype
|
||||
, facilitycode
|
||||
, cardnumber
|
||||
, xorval
|
||||
);
|
||||
print_blocks(blocks, ARRAYLEN(blocks));
|
||||
|
||||
|
@ -332,11 +344,12 @@ static int CmdGuardSim(const char *Cmd) {
|
|||
"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 26 | 36 bit format",
|
||||
"lf gproxii sim --fmt 26 --fc 123 --cn 1337\n"
|
||||
"lf gproxii sim --xor 141 --fmt 26 --fc 123 --cn 1337\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_u64_1(NULL, "xor", "<dec>", "8-bit xor value (installation dependant)"),
|
||||
arg_u64_1(NULL, "fmt", "<dec>", "format length 26|32|36|40"),
|
||||
arg_u64_1(NULL, "fc", "<dec>", "8-bit value facility code"),
|
||||
arg_u64_1(NULL, "cn", "<dec>", "16-bit value card number"),
|
||||
|
@ -344,9 +357,10 @@ static int CmdGuardSim(const char *Cmd) {
|
|||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
uint32_t fmtlen = arg_get_u32_def(ctx, 1, 0);
|
||||
uint32_t fc = arg_get_u32_def(ctx, 2, 0);
|
||||
uint32_t cn = arg_get_u32_def(ctx, 3, 0);
|
||||
uint32_t xorval = arg_get_u32_def(ctx, 1, 0);
|
||||
uint32_t fmtlen = arg_get_u32_def(ctx, 2, 0);
|
||||
uint32_t fc = arg_get_u32_def(ctx, 3, 0);
|
||||
uint32_t cn = arg_get_u32_def(ctx, 4, 0);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
fmtlen &= 0x7F;
|
||||
|
@ -356,12 +370,13 @@ static int CmdGuardSim(const char *Cmd) {
|
|||
uint8_t bs[96];
|
||||
memset(bs, 0x00, sizeof(bs));
|
||||
|
||||
if (getGuardBits(fmtlen, facilitycode, cardnumber, bs) != PM3_SUCCESS) {
|
||||
if (getGuardBits(xorval, fmtlen, facilitycode, cardnumber, bs) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Simulating Guardall Prox - Facility Code: " _YELLOW_("%u") " CardNumber: " _YELLOW_("%u")
|
||||
PrintAndLogEx(SUCCESS, "Simulating Guardall Prox - xorKey: " _YELLOW_("%u") " Facility Code: " _YELLOW_("%u") " CardNumber: " _YELLOW_("%u")
|
||||
, xorval
|
||||
, facilitycode
|
||||
, cardnumber
|
||||
);
|
||||
|
@ -435,9 +450,8 @@ int detectGProxII(uint8_t *bits, size_t *size) {
|
|||
}
|
||||
|
||||
// Works for 26bits.
|
||||
int getGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) {
|
||||
int getGuardBits(uint8_t xorKey, uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) {
|
||||
|
||||
uint8_t xorKey = 0x66;
|
||||
uint8_t i;
|
||||
uint8_t pre[96];
|
||||
uint8_t rawbytes[12];
|
||||
|
@ -448,7 +462,6 @@ int getGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) {
|
|||
switch (fmtlen) {
|
||||
case 32: {
|
||||
rawbytes[1] = (32 << 2);
|
||||
|
||||
break;
|
||||
}
|
||||
case 36: {
|
||||
|
@ -456,6 +469,7 @@ int getGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) {
|
|||
// Get wiegand from FacilityCode 14bits, CardNumber 20bits
|
||||
uint8_t wiegand[36];
|
||||
memset(wiegand, 0x00, sizeof(wiegand));
|
||||
|
||||
num_to_bytebits(fc, 14, wiegand);
|
||||
num_to_bytebits(cn, 20, wiegand + 14);
|
||||
|
||||
|
|
|
@ -23,5 +23,5 @@
|
|||
int CmdLFGuard(const char *Cmd);
|
||||
int detectGProxII(uint8_t *bits, size_t *size);
|
||||
int demodGuard(bool verbose);
|
||||
int getGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits);
|
||||
int getGuardBits(uint8_t xorKey, uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits);
|
||||
#endif
|
||||
|
|
|
@ -384,6 +384,7 @@ const static vocabulory_t vocabulory[] = {
|
|||
{ 0, "hf mfu rdbl" },
|
||||
{ 0, "hf mfu restore" },
|
||||
{ 1, "hf mfu view" },
|
||||
{ 0, "hf mfu tamper" },
|
||||
{ 0, "hf mfu wrbl" },
|
||||
{ 0, "hf mfu eload" },
|
||||
{ 0, "hf mfu esave" },
|
||||
|
|
|
@ -223,6 +223,9 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
#define NTAG_I2C_SELECT_SECTOR 0xC2
|
||||
#define NTAG_I2C_FASTWRITE 0xA6
|
||||
|
||||
//NTAG 213TT (tamper) command
|
||||
#define NTAGTT_CMD_READ_TT 0xA4
|
||||
|
||||
// mifare 4bit card answers
|
||||
#define CARD_ACK 0x0A // 1010 - ACK
|
||||
#define CARD_NACK_IV 0x00 // 0000 - NACK, invalid argument (invalid page address)
|
||||
|
|
|
@ -139,10 +139,13 @@ static void print_time(uint64_t at) {
|
|||
(void)localtime_r(&t, <);
|
||||
#endif
|
||||
|
||||
char res[32];
|
||||
strftime(res, sizeof(res), "%Y-%m-%d %H:%M:%S", <);
|
||||
|
||||
printf("%u ( '%s' )\n", (unsigned)t, res);
|
||||
char res[70];
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
strftime(res, sizeof(res), "('%Y-%m-%d %H:%M:%S')", <);
|
||||
#else
|
||||
strftime(res, sizeof(res), "%s ('%Y-%m-%d %H:%M:%S')", <);
|
||||
#endif
|
||||
printf("%s\n", res);
|
||||
}
|
||||
|
||||
static void *brute_thread(void *arguments) {
|
||||
|
|
|
@ -169,10 +169,13 @@ static void print_time(uint64_t at) {
|
|||
(void)localtime_r(&t, <);
|
||||
#endif
|
||||
|
||||
char res[32];
|
||||
strftime(res, sizeof(res), "%Y-%m-%d %H:%M:%S", <);
|
||||
|
||||
printf("%"PRIu64" ( '%s' )\n", t, res);
|
||||
char res[70];
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
strftime(res, sizeof(res), "('%Y-%m-%d %H:%M:%S')", <);
|
||||
#else
|
||||
strftime(res, sizeof(res), "%s ('%Y-%m-%d %H:%M:%S')", <);
|
||||
#endif
|
||||
printf("%s\n", res);
|
||||
}
|
||||
|
||||
static void *brute_thread(void *arguments) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue