mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
Merge branch 'master' into master
Signed-off-by: Iceman <iceman@iuse.se>
This commit is contained in:
@@ -6,6 +6,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||
- Changed `hf iclass info` - now checks for cards silicon version (@antiklesys)
|
||||
- Changed `hf iclass legrec` - updated script implementation to ensure functionality (@antiklesys)
|
||||
- Added recovered iclass custom key to dictionary (@antiklesys)
|
||||
- Added support for all Hitag S response protocol mode (@douniwan5788)
|
||||
- Fixed 'hf_young.c' - flags declaration was missing a semicolon (@jakkpotts)
|
||||
- Changed `hf mf sim` - add option to allow key b to be used even if readable (@doegox)
|
||||
- Changed `data num` - outputed binary strings are now properly zero padded (@iceman1001)
|
||||
- Changed `hf iclass info` - now tries default keys and decode if legacy (@iceman1001)
|
||||
|
||||
@@ -236,7 +236,7 @@ void RunMod(void) {
|
||||
int button_pressed = BUTTON_HELD(1000);
|
||||
if (button_pressed == BUTTON_NO_CLICK) { // No button action, proceed with sim
|
||||
|
||||
uint16_t flags = 0
|
||||
uint16_t flags = 0;
|
||||
FLAG_SET_UID_IN_DATA(flags, 4);
|
||||
uint8_t data[PM3_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break
|
||||
|
||||
|
||||
+168
-190
File diff suppressed because it is too large
Load Diff
+7
-1
@@ -1534,7 +1534,7 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
|
||||
continue;
|
||||
};
|
||||
|
||||
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, NULL, NULL)) {
|
||||
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2, NULL)) {
|
||||
continue;
|
||||
};
|
||||
|
||||
@@ -1544,6 +1544,12 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo,
|
||||
};
|
||||
|
||||
nt3 = bytes_to_num(receivedAnswer, 4);
|
||||
// fix for cards with distance 0
|
||||
if (nt1 == nt2) {
|
||||
target_nt[0] = nt1;
|
||||
target_nt[1] = nt1;
|
||||
target_ks[0] = nt3 ^ target_nt[0];
|
||||
}
|
||||
target_ks[1] = nt3 ^ target_nt[1];
|
||||
|
||||
isOK = PM3_SUCCESS;
|
||||
|
||||
@@ -191,7 +191,7 @@ local function read_config()
|
||||
if magicconfig == nil then lib14a.disconnect(); return nil, "can't read configuration, "..err_lock end
|
||||
if #magicconfig ~= 64 and #magicconfig ~= 68 then lib14a.disconnect(); return nil, "partial read of configuration, "..err_lock end
|
||||
if gtumode == '00' then gtustr = 'Pre-write/Shadow Mode'
|
||||
elseif gtumode == '01' then gtustr = 'Restore Mode'
|
||||
elseif gtumode == '01' or gtumode == '04' then gtustr = 'Restore Mode'
|
||||
elseif gtumode == '02' then gtustr = 'Disabled'
|
||||
elseif gtumode == '03' then gtustr = 'Disabled, high speed R/W mode for Ultralight'
|
||||
end
|
||||
@@ -553,7 +553,7 @@ local function write_gtu(gtu)
|
||||
if gtu == '00' then
|
||||
print('Enabling GTU Pre-Write')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
elseif gtu == '01' then
|
||||
elseif gtu == '01' or gtu == '04' then
|
||||
print('Enabling GTU Restore Mode')
|
||||
send('CF'.._key..'32'..gtu)
|
||||
elseif gtu == '02' then
|
||||
|
||||
@@ -76,6 +76,10 @@ parser.add_argument('-x', '--init-check', action='store_true', help='Run an init
|
||||
parser.add_argument('-y', '--final-check', action='store_true', help='Run a final fchk with the found keys')
|
||||
parser.add_argument('-k', '--keep', action='store_true', help='Keep generated dictionaries after processing')
|
||||
parser.add_argument('-d', '--debug', action='store_true', help='Enable debug mode')
|
||||
parser.add_argument('-s', '--supply-chain', action='store_true', help='Enable supply-chain mode. Look for hf-mf-XXXXXXXX-default_nonces.json')
|
||||
# Such json can be produced from the json saved by
|
||||
# "hf mf isen --collect_fm11rf08s --key A396EFA4E24F" on a wiped card, then processed with
|
||||
# jq '{Created: .Created, FileType: "fm11rf08s_default_nonces", nt: .nt | del(.["32"]) | map_values(.a)}'
|
||||
args = parser.parse_args()
|
||||
|
||||
start_time = time.time()
|
||||
@@ -191,6 +195,22 @@ if os.path.isfile(DICT_DEF_PATH):
|
||||
else:
|
||||
print(f"Warning, {DICT_DEF} not found.")
|
||||
|
||||
dict_dnwd = None
|
||||
def_nt = ["" for _ in range(NUM_SECTORS)]
|
||||
if args.supply_chain:
|
||||
try:
|
||||
default_nonces = f'{save_path}hf-mf-{uid:04X}-default_nonces.json'
|
||||
with open(default_nonces, 'r') as file:
|
||||
# Load and parse the JSON data
|
||||
dict_dnwd = json.load(file)
|
||||
for sec in range(NUM_SECTORS):
|
||||
def_nt[sec] = dict_dnwd["nt"][f"{sec}"].lower()
|
||||
print(f"Loaded default nonces from {default_nonces}.")
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
except json.decoder.JSONDecodeError:
|
||||
print(f"Error parsing {default_nonces}, skipping.")
|
||||
|
||||
print("Running staticnested_1nt & 2x1nt when doable...")
|
||||
keys = [[set(), set()] for _ in range(NUM_SECTORS + NUM_EXTRA_SECTORS)]
|
||||
all_keys = set()
|
||||
@@ -225,9 +245,21 @@ for sec in range(NUM_SECTORS + NUM_EXTRA_SECTORS):
|
||||
keys[sec][key_type] = keys_set.copy()
|
||||
duplicates.update(all_keys.intersection(keys_set))
|
||||
all_keys.update(keys_set)
|
||||
# Prioritize default keys
|
||||
keys_def_set = DEFAULT_KEYS.intersection(keys_set)
|
||||
keys_set.difference_update(DEFAULT_KEYS)
|
||||
if dict_dnwd is not None and sec < NUM_SECTORS:
|
||||
# Prioritize keys from supply-chain attack
|
||||
cmd = [tools["staticnested_2x1nt1key"], def_nt[sec], "FFFFFFFFFFFF", f"keys_{uid:08x}_{real_sec:02}_{nt[sec][key_type]}_filtered.dic"]
|
||||
if args.debug:
|
||||
print(' '.join(cmd))
|
||||
result = subprocess.run(cmd, capture_output=True, text=True).stdout
|
||||
keys_def_set = set()
|
||||
for line in result.split('\n'):
|
||||
if "MATCH:" in line:
|
||||
keys_def_set.add(line[12:])
|
||||
keys_set.difference_update(keys_def_set)
|
||||
else:
|
||||
# Prioritize default keys
|
||||
keys_def_set = DEFAULT_KEYS.intersection(keys_set)
|
||||
keys_set.difference_update(keys_def_set)
|
||||
# Prioritize sector 32 keyB starting with 0000
|
||||
if real_sec == 32:
|
||||
keyb32cands = set(x for x in keys_set if x.startswith("0000"))
|
||||
@@ -257,9 +289,21 @@ for sec in range(NUM_SECTORS + NUM_EXTRA_SECTORS):
|
||||
keys[sec][key_type] = keys_set.copy()
|
||||
duplicates.update(all_keys.intersection(keys_set))
|
||||
all_keys.update(keys_set)
|
||||
# Prioritize default keys
|
||||
keys_def_set = DEFAULT_KEYS.intersection(keys_set)
|
||||
keys_set.difference_update(DEFAULT_KEYS)
|
||||
if dict_dnwd is not None and sec < NUM_SECTORS:
|
||||
# Prioritize keys from supply-chain attack
|
||||
cmd = [tools["staticnested_2x1nt1key"], def_nt[sec], "FFFFFFFFFFFF", f"keys_{uid:08x}_{real_sec:02}_{nt[sec][key_type]}.dic"]
|
||||
if args.debug:
|
||||
print(' '.join(cmd))
|
||||
result = subprocess.run(cmd, capture_output=True, text=True).stdout
|
||||
keys_def_set = set()
|
||||
for line in result.split('\n'):
|
||||
if "MATCH:" in line:
|
||||
keys_def_set.add(line[12:])
|
||||
keys_set.difference_update(keys_def_set)
|
||||
else:
|
||||
# Prioritize default keys
|
||||
keys_def_set = DEFAULT_KEYS.intersection(keys_set)
|
||||
keys_set.difference_update(keys_def_set)
|
||||
if len(keys_def_set) > 0:
|
||||
found_default[sec][key_type] = True
|
||||
with (open(f"keys_{uid:08x}_{real_sec:02}_{nt[sec][key_type]}.dic", "w")) as f:
|
||||
@@ -484,6 +528,7 @@ if abort:
|
||||
print("Brute-forcing phase aborted via keyboard!")
|
||||
args.final_check = False
|
||||
|
||||
plus = "[" + color("+", fg="green") + "] "
|
||||
if args.final_check:
|
||||
print("Letting fchk do a final dump, just for confirmation and display...")
|
||||
keys_set = set([i for sl in found_keys for i in sl if i != ""])
|
||||
@@ -495,7 +540,6 @@ if args.final_check:
|
||||
print(cmd)
|
||||
p.console(cmd, passthru=True)
|
||||
else:
|
||||
plus = "[" + color("+", fg="green") + "] "
|
||||
print()
|
||||
print(plus + color("found keys:", fg="green"))
|
||||
print()
|
||||
|
||||
@@ -1311,6 +1311,52 @@ static int CmdGallagherDecode(const char *cmd) {
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int CmdGallagherEncode (const char *cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf gallagher encode",
|
||||
"Encode a Gallagher credential block\n"
|
||||
"Credential block can be specified with or without the bitwise inverse.",
|
||||
"hf gallagher encode --rc 1 --fc 22153 --cn 1253518 --il 1"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_u64_1("r", "rc", "<dec>", "Region code. 4 bits max"),
|
||||
arg_u64_1("f", "fc", "<dec>", "Facility code. 2 bytes max"),
|
||||
arg_u64_1("c", "cn", "<dec>", "Card number. 3 bytes max"),
|
||||
arg_u64_1("i", "il", "<dec>", "Issue level. 4 bits max"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, cmd, argtable, false);
|
||||
|
||||
uint64_t region_code = arg_get_u64(ctx, 1); // uint4, input will be validated later
|
||||
uint64_t facility_code = arg_get_u64(ctx, 2); // uint16
|
||||
uint64_t card_number = arg_get_u64(ctx, 3); // uint24
|
||||
uint64_t issue_level = arg_get_u64(ctx, 4); // uint4
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
GallagherCredentials_t creds = {
|
||||
.region_code = region_code,
|
||||
.facility_code = facility_code,
|
||||
.card_number = card_number,
|
||||
.issue_level = issue_level,
|
||||
};
|
||||
|
||||
|
||||
uint8_t contents[16] = {0};
|
||||
|
||||
gallagher_encode_creds(contents, &creds);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
contents[i + 8] = contents[i] ^ 0xFF;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Raw: " _YELLOW_("%s"), sprint_hex_inrow(contents, ARRAYLEN(contents)/2));
|
||||
PrintAndLogEx(SUCCESS, "Bitwise: " _YELLOW_("%s"), sprint_hex_inrow(contents, ARRAYLEN(contents)));
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
@@ -1319,6 +1365,7 @@ static command_t CommandTable[] = {
|
||||
{"delete", CmdGallagherDelete, IfPm3Iso14443, "Delete Gallagher credentials from a DESFire card"},
|
||||
{"diversifykey", CmdGallagherDiversify, AlwaysAvailable, "Diversify Gallagher key"},
|
||||
{"decode", CmdGallagherDecode, AlwaysAvailable, "Decode Gallagher credential block"},
|
||||
{"encode", CmdGallagherEncode, AlwaysAvailable, "Encode Gallagher credential block"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -4131,15 +4131,12 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
||||
uint8_t uid[10] = {0};
|
||||
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||
|
||||
char uidsize[9] = {0};
|
||||
if (uidlen > 0) {
|
||||
FLAG_SET_UID_IN_DATA(flags, uidlen);
|
||||
if (IS_FLAG_UID_IN_EMUL(flags)) {
|
||||
PrintAndLogEx(WARNING, "Invalid parameter for UID");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
} else {
|
||||
snprintf(uidsize, sizeof(uidsize), "%i bytes", uidlen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4247,9 +4244,9 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, _YELLOW_("MIFARE %s") " | %s UID " _YELLOW_("%s") ""
|
||||
PrintAndLogEx(INFO, _YELLOW_("MIFARE %s") " | %i bytes UID " _YELLOW_("%s") ""
|
||||
, csize
|
||||
, uidsize
|
||||
, uidlen
|
||||
, (uidlen == 0) ? "n/a" : sprint_hex(uid, uidlen)
|
||||
);
|
||||
|
||||
|
||||
@@ -147,6 +147,13 @@ static int process_hitags_common_args(CLIParserContext *ctx, lf_hitag_data_t *co
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint8_t mode = arg_get_int_def(ctx, 5, 3);
|
||||
|
||||
if (mode > 3) {
|
||||
PrintAndLogEx(WARNING, "Wrong response protocol mode, expected 0, 1, 2 or 3, got %d", mode);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
// complete options
|
||||
switch (key_len) {
|
||||
case HITAG_PASSWORD_SIZE:
|
||||
@@ -194,6 +201,21 @@ static int process_hitags_common_args(CLIParserContext *ctx, lf_hitag_data_t *co
|
||||
PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag S") " in Crypto mode");
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
packet->mode = HITAGS_UID_REQ_STD;
|
||||
break;
|
||||
case 1:
|
||||
packet->mode = HITAGS_UID_REQ_ADV1;
|
||||
break;
|
||||
case 2:
|
||||
packet->mode = HITAGS_UID_REQ_ADV2;
|
||||
break;
|
||||
default:
|
||||
packet->mode = HITAGS_UID_REQ_FADV;
|
||||
break;
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -226,6 +248,9 @@ static void print_error(int8_t reason) {
|
||||
case -10:
|
||||
PrintAndLogEx(FAILED, "Write to page failed!");
|
||||
break;
|
||||
case -11:
|
||||
PrintAndLogEx(FAILED, "Read page failed!");
|
||||
break;
|
||||
default:
|
||||
// PM3_REASON_UNKNOWN
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Hitag S failed");
|
||||
@@ -254,8 +279,9 @@ static int CmdLFHitagSRead(const char *Cmd) {
|
||||
arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
|
||||
arg_lit0(NULL, "crypto", "crypto mode"),
|
||||
arg_str0("k", "key", "<hex>", "pwd or key, 4 or 6 hex bytes"),
|
||||
arg_int0("m", "mode", "<dec>", "response protocol mode. 0 (Standard 00110), 1 (Advanced 11000), 2 (Advanced 11001), 3 (Fast Advanced 11010) (def: 3)"),
|
||||
arg_int0("p", "page", "<dec>", "page address to read from"),
|
||||
arg_int0("c", "count", "<dec>", "how many pages to read. '0' reads all pages up to the end page (default: 1)"),
|
||||
arg_int0("c", "count", "<dec>", "how many pages to read. '0' reads all pages up to the end page (def: 1)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
@@ -264,14 +290,14 @@ static int CmdLFHitagSRead(const char *Cmd) {
|
||||
|
||||
if (process_hitags_common_args(ctx, &packet) < 0) return PM3_EINVARG;
|
||||
|
||||
uint32_t page = arg_get_int_def(ctx, 5, 0);
|
||||
uint32_t page = arg_get_int_def(ctx, 6, 0);
|
||||
|
||||
if (page > 255) {
|
||||
PrintAndLogEx(WARNING, "Page address Invalid.");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint32_t count = arg_get_int_def(ctx, 6, 1);
|
||||
uint32_t count = arg_get_int_def(ctx, 7, 1);
|
||||
|
||||
if (count > HITAGS_MAX_PAGES) {
|
||||
PrintAndLogEx(WARNING, "No more than 64 pages can be read at once.");
|
||||
@@ -404,8 +430,10 @@ static int CmdLFHitagSRead(const char *Cmd) {
|
||||
PrintAndLogEx(NORMAL, "Key");
|
||||
} else
|
||||
PrintAndLogEx(NORMAL, "Data");
|
||||
} else
|
||||
PrintAndLogEx(INFO, "%02u | -- -- -- -- | read failed reason: " _YELLOW_("%d"), page_addr, card->pages_reason[i]);
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "% 3u | -- -- -- -- | .... | N/A | " NOLF, page_addr);
|
||||
print_error(card->pages_reason[i]);
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "----+-------------+-------+------+------");
|
||||
@@ -438,6 +466,7 @@ static int CmdLFHitagSWrite(const char *Cmd) {
|
||||
arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
|
||||
arg_lit0(NULL, "crypto", "crypto mode"),
|
||||
arg_str0("k", "key", "<hex>", "pwd or key, 4 or 6 hex bytes"),
|
||||
arg_int0("m", "mode", "<dec>", "response protocol mode. 0 (Standard 00110), 1 (Advanced 11000), 2 (Advanced 11001), 3 (Fast Advanced 11010) (def: 3)"),
|
||||
arg_int1("p", "page", "<dec>", "page address to write to"),
|
||||
arg_str1("d", "data", "<hex>", "data, 4 hex bytes"),
|
||||
arg_param_end
|
||||
@@ -448,12 +477,12 @@ static int CmdLFHitagSWrite(const char *Cmd) {
|
||||
|
||||
if (process_hitags_common_args(ctx, &packet) < 0) return PM3_EINVARG;
|
||||
|
||||
int page = arg_get_int_def(ctx, 5, 0);
|
||||
int page = arg_get_int_def(ctx, 6, 0);
|
||||
|
||||
uint8_t data[HITAGS_PAGE_SIZE];
|
||||
int data_len = 0;
|
||||
|
||||
int res = CLIParamHexToBuf(arg_get_str(ctx, 6), data, HITAGS_PAGE_SIZE, &data_len);
|
||||
int res = CLIParamHexToBuf(arg_get_str(ctx, 7), data, HITAGS_PAGE_SIZE, &data_len);
|
||||
if (res != 0) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
@@ -538,7 +567,7 @@ static int CmdLFHitagSSim(const char *Cmd) {
|
||||
CLIParserFree(ctx);
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_HITAGS_SIMULATE, NULL, 0);
|
||||
SendCommandMIX(CMD_LF_HITAGS_SIMULATE, false, 0, 0, NULL, 0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
+27
-34
@@ -65,30 +65,6 @@ typedef enum {
|
||||
HT2_LAST_CMD = HT2F_UID_ONLY,
|
||||
} PACKED hitag_function;
|
||||
|
||||
typedef struct {
|
||||
hitag_function cmd;
|
||||
uint8_t page;
|
||||
uint8_t page_count;
|
||||
uint8_t data[HITAGS_PAGE_SIZE];
|
||||
uint8_t NrAr[HITAG_NRAR_SIZE];
|
||||
// unaligned access to key as uint64_t will abort.
|
||||
// todo: Why does the compiler without -munaligned-access generate unaligned-access code in the first place?
|
||||
uint8_t key[HITAG_CRYPTOKEY_SIZE] __attribute__((aligned(4)));
|
||||
uint8_t pwd[HITAG_PASSWORD_SIZE];
|
||||
|
||||
// Hitag 1 section.
|
||||
// will reuse pwd or key field.
|
||||
uint8_t key_no;
|
||||
uint8_t logdata_0[4];
|
||||
uint8_t logdata_1[4];
|
||||
uint8_t nonce[4];
|
||||
} PACKED lf_hitag_data_t;
|
||||
|
||||
typedef struct {
|
||||
int status;
|
||||
uint8_t data[256];
|
||||
} PACKED lf_hitag_crack_response_t;
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Hitag S
|
||||
//---------------------------------------------------------
|
||||
@@ -111,15 +87,6 @@ typedef enum TAG_STATE {
|
||||
HT_WRITING_BLOCK_DATA
|
||||
} TSATE;
|
||||
|
||||
//number of start-of-frame bits
|
||||
typedef enum SOF_TYPE {
|
||||
HT_STANDARD = 0,
|
||||
HT_ADVANCED,
|
||||
HT_FAST_ADVANCED,
|
||||
HT_ONE,
|
||||
HT_NO_BITS
|
||||
} stype;
|
||||
|
||||
typedef struct {
|
||||
// con0
|
||||
uint8_t MEMT : 2;
|
||||
@@ -156,7 +123,6 @@ struct hitagS_tag {
|
||||
TSATE tstate; // tag-state
|
||||
|
||||
int max_page;
|
||||
stype mode;
|
||||
|
||||
union {
|
||||
uint8_t pages[64][4];
|
||||
@@ -177,6 +143,33 @@ struct hitagS_tag {
|
||||
|
||||
} PACKED;
|
||||
|
||||
typedef struct {
|
||||
hitag_function cmd;
|
||||
uint8_t page;
|
||||
uint8_t page_count;
|
||||
uint8_t data[HITAGS_PAGE_SIZE];
|
||||
uint8_t NrAr[HITAG_NRAR_SIZE];
|
||||
// unaligned access to key as uint64_t will abort.
|
||||
// todo: Why does the compiler without -munaligned-access generate unaligned-access code in the first place?
|
||||
uint8_t key[HITAG_CRYPTOKEY_SIZE] __attribute__((aligned(4)));
|
||||
uint8_t pwd[HITAG_PASSWORD_SIZE];
|
||||
|
||||
// Hitag 1 section.
|
||||
// will reuse pwd or key field.
|
||||
uint8_t key_no;
|
||||
uint8_t logdata_0[4];
|
||||
uint8_t logdata_1[4];
|
||||
uint8_t nonce[4];
|
||||
|
||||
//Hitag s section
|
||||
uint8_t mode;
|
||||
} PACKED lf_hitag_data_t;
|
||||
|
||||
typedef struct {
|
||||
int status;
|
||||
uint8_t data[256];
|
||||
} PACKED lf_hitag_crack_response_t;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
uint8_t asBytes[HITAGS_PAGE_SIZE];
|
||||
|
||||
Reference in New Issue
Block a user