From d95112f8211ae1d9cb01868abbb559d0dbb2d3fb Mon Sep 17 00:00:00 2001 From: Foxushka <135865149+Foxushka@users.noreply.github.com> Date: Sat, 9 Aug 2025 17:51:57 +0300 Subject: [PATCH] Bump NETDATA_MAX_DATA_LENGTH from 512 to 4096 USB + BLE are tested Closes #272 --- CHANGELOG.md | 2 ++ firmware/application/src/app_cmd.c | 2 +- firmware/application/src/utils/dataframe.c | 2 +- firmware/application/src/utils/netdata.h | 6 ++-- software/script/chameleon_cli_unit.py | 35 ++++++++-------------- software/script/chameleon_com.py | 2 +- software/script/tests/test_hard_acquire.py | 4 +-- 7 files changed, 22 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24e27d4..981571b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Extend max packet data size from 512 to 4096 bytes (@Foxushka) + - HID Prox support (@TeCHiScy) - Added cmd for fetching all slots nicks (@Foxushka) - Added `hf mf senested` for recovering keys from static encrypted cards via backdoor (https://eprint.iacr.org/2024/1275) (@Foxushka) - Added cmd for faster bulk key checking on one block (~33 keys per second) (@Foxushka) diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index d4ba55e..a5afcae 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -426,7 +426,7 @@ static data_frame_tx_t *cmd_processor_mf1_hardnested_nonces_acquire(uint16_t cmd payload_t *payload = (payload_t *)data; // It is enough to collect 110 nonces at a time. The total transmitted data payload is 495 + 1 bytes - // Then, the total length can be controlled within 512, so that when encountering a BLE host that supports large packets, one communication can be completed. + // Then, the total length can be controlled within 4096, so that when encountering a BLE host that supports large packets, one communication can be completed. // There is no need to send or receive packets in separate packets, which improves communication speed. uint8_t nonces[500] = { 0x00 }; if (length < 11) { diff --git a/firmware/application/src/utils/dataframe.c b/firmware/application/src/utils/dataframe.c index 15a088e..a2baad0 100644 --- a/firmware/application/src/utils/dataframe.c +++ b/firmware/application/src/utils/dataframe.c @@ -40,7 +40,7 @@ data_frame_tx_t *data_frame_make(uint16_t cmd, uint16_t status, uint16_t data_le NRF_LOG_ERROR("data_frame_make error, null pointer."); return NULL; } - if (data_length > 512) { + if (data_length > 4096) { NRF_LOG_ERROR("data_frame_make error, too much data."); return NULL; } diff --git a/firmware/application/src/utils/netdata.h b/firmware/application/src/utils/netdata.h index 37390f1..cb0ceff 100644 --- a/firmware/application/src/utils/netdata.h +++ b/firmware/application/src/utils/netdata.h @@ -5,7 +5,7 @@ #include #include "utils.h" -#define NETDATA_MAX_DATA_LENGTH 512 +#define NETDATA_MAX_DATA_LENGTH 4096 /* * ********************************************************************************************************************************* @@ -17,8 +17,8 @@ * SOF(1byte) LRC(1byte) CMD(2byte) Status(2byte) Data Length(2byte) Frame Head LRC(1byte) Data(length) Frame All LRC(1byte) * 0x11 0xEF cmd(u16) status(u16) length(u16) lrc(u8) data(u8*) lrc(u8) * - * The data length max is 512, frame length is 1 + 1 + 2 + 2 + 2 + 1 + n + 1 = (10 + n) - * So, one frame will be between 10 and 522 bytes. + * The data length max is 4096, frame length is 1 + 1 + 2 + 2 + 2 + 1 + n + 1 = (10 + n) + * So, one frame will be between 10 and 4106 bytes. * ********************************************************************************************************************************* */ diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index c1938c6..3abaa69 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -376,7 +376,6 @@ class MFUAuthArgsUnit(ReaderRequiredUnit): if key is not None and args.swap_endian: key = bytearray(key) for i in range(len(key)): - tmp = key[i] key[i] = key[len(key) - 1 - i] key = bytes(key) @@ -843,7 +842,7 @@ class HFMFNested(ReaderRequiredUnit): nt_level = self.cmd.mf1_detect_prng() print(f" - NT vulnerable: {CY}{self.from_nt_level_code_to_str(nt_level)}{C0}") if nt_level == 2: - print(" [!] HardNested has not been implemented yet.") + print(" [!] Use hf mf hardnested") return None # acquire @@ -1038,7 +1037,7 @@ class HFMFHardNested(ReaderRequiredUnit): :param max_attempts: Maximum number of full acquisition attempts. :return: Recovered key as a hex string, or None if not found. """ - print(f" - Starting HardNested attack...") + print(" - Starting HardNested attack...") nonces_buffer = bytearray() # This will hold the final data for the file uid_bytes = b'' # To store UID from the successful attempt @@ -2344,7 +2343,7 @@ class HFMFEConfig(SlotIndexArgsAndGoUnit, HF14AAntiCollArgsUnit, DeviceRequiredU @hf_mfu.command('ercnt') -class HFMFUVERSION(DeviceRequiredUnit): +class HFMFUERCNT(DeviceRequiredUnit): def args_parser(self) -> ArgumentParserNoExit: parser = ArgumentParserNoExit() parser.description = 'Read MIFARE Ultralight / NTAG counter value.' @@ -2361,7 +2360,7 @@ class HFMFUVERSION(DeviceRequiredUnit): @hf_mfu.command('ewcnt') -class HFMFUVERSION(DeviceRequiredUnit): +class HFMFUEWCNT(DeviceRequiredUnit): def args_parser(self) -> ArgumentParserNoExit: parser = ArgumentParserNoExit() parser.description = 'Write MIFARE Ultralight / NTAG counter value.' @@ -2409,7 +2408,7 @@ class HFMFURDPG(MFUAuthArgsUnit): failed_auth = len(resp) < 2 if not failed_auth: print(f" - PACK: {resp[:2].hex()}") - except Exception as e: + except Exception: # failed auth may cause tags to be lost failed_auth = True @@ -2467,7 +2466,7 @@ class HFMFUWRPG(MFUAuthArgsUnit): failed_auth = len(resp) < 2 if not failed_auth: print(f" - PACK: {resp[:2].hex()}") - except Exception as e: + except Exception: # failed auth may cause tags to be lost failed_auth = True @@ -2482,7 +2481,7 @@ class HFMFUWRPG(MFUAuthArgsUnit): data=struct.pack('!BB', 0xA2, args.page)+data) if resp[0] == 0x0A: - print(f" - Ok") + print(" - Ok") else: print(f"{CR}Write failed ({resp[0]:#04x}).{C0}") else: @@ -2502,16 +2501,7 @@ class HFMFUEVIEW(DeviceRequiredUnit): parser.description = 'MIFARE Ultralight / NTAG view emulator data' return parser - def get_param(self, args): - class Param: - def __init__(self): - pass - - return Param() - def on_exec(self, args: argparse.Namespace): - param = self.get_param(args) - nr_pages = self.cmd.mfu_get_emu_pages_count() page = 0 while page < nr_pages: @@ -2585,7 +2575,7 @@ class HFMFUELOAD(DeviceRequiredUnit): self.cmd.mfu_write_emu_page_data(page, page_data) page += cur_count - print(f" - Ok") + print(" - Ok") @hf_mfu.command('esave') @@ -2661,7 +2651,7 @@ class HFMFUESAVE(DeviceRequiredUnit): page += cur_count - print(f" - Ok") + print(" - Ok") @hf_mfu.command('rcnt') @@ -2693,7 +2683,7 @@ class HFMFURCNT(MFUAuthArgsUnit): failed_auth = len(resp) < 2 if not failed_auth: print(f" - PACK: {resp[:2].hex()}") - except Exception as e: + except Exception: # failed auth may cause tags to be lost failed_auth = True @@ -2835,7 +2825,7 @@ class HFMFUDUMP(MFUAuthArgsUnit): needs_stop = len(resp) < 2 if not needs_stop: print(f" - PACK: {resp[:2].hex()}") - except Exception as e: + except Exception: # failed auth may cause tags to be lost needs_stop = True @@ -2853,7 +2843,6 @@ class HFMFUDUMP(MFUAuthArgsUnit): if param.key is not None and not needs_stop: resp = self.cmd.hf14a_raw(options=options, resp_timeout_ms=200, data=struct.pack('!B', 0x1B)+param.key) options['auto_select'] = 0 # prevent resets - pack = resp[:2].hex() # disable the rf field after the last command if i == (stop_page - 1) or needs_stop: @@ -3190,7 +3179,7 @@ class LFHIDProxWriteT55xx(LFHIDIdArgsUnit, ReaderRequiredUnit): if args.oem > 0: print(f" OEM: {args.oem}") print(f" CN: {args.cn}") - print(f"write done.") + print("write done.") @lf_hid_prox.command('econfig') class LFHIDProxEconfig(SlotIndexArgsAndGoUnit, LFHIDIdArgsUnit): diff --git a/software/script/chameleon_com.py b/software/script/chameleon_com.py index cf11728..74fc844 100644 --- a/software/script/chameleon_com.py +++ b/software/script/chameleon_com.py @@ -50,7 +50,7 @@ class ChameleonCom: Communication and Data frame implemented """ data_frame_sof = 0x11 - data_max_length = 512 + data_max_length = 4096 commands = [] def __init__(self): diff --git a/software/script/tests/test_hard_acquire.py b/software/script/tests/test_hard_acquire.py index f0ef424..37fa3b5 100644 --- a/software/script/tests/test_hard_acquire.py +++ b/software/script/tests/test_hard_acquire.py @@ -32,7 +32,7 @@ def test_hardnested_acquire(): # ------------------------ SET DEVICE MODE ------------------------ print("Setting device mode to HF Reader...") - status = cml_cmd.set_device_reader_mode() + cml_cmd.set_device_reader_mode() # ------------------------ append tag info ------------------------ @@ -63,7 +63,7 @@ def test_hardnested_acquire(): acquire_count += 1 print(f"Acquire success, count: {acquire_count}") else: - raise Exception(f"acquire failed") + raise Exception("acquire failed") # 2. check data data_check_index = 0 while data_check_index < len(acquire_datas):