尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Proxmark3(Iceman Fork)NG 变长帧格式:主机-设备通信协议的设计、API 与实现剖析

Proxmark3(Iceman Fork)NG 变长帧格式:主机-设备通信协议的设计、API 与实现剖析 Proxmark3Iceman ForkNG 变长帧格式主机-设备通信协议的设计、API 与实现剖析【免费下载链接】proxmark3Iceman Fork - Proxmark3项目地址: https://gitcode.com/GitHub_Trending/pr/proxmark3本文围绕 doc/new_frame_format.md 展开系统讲解 Proxmark3 在客户端与设备之间引入的 NG新一代变长帧格式帧头/帧尾的逐字段定义、新旧格式的双向兼容策略、客户端与固件两侧的收发 API、Bootrom 的兼容边界以及 USART 重写与超时调优背后的实测依据并对照当前仓库源码给出每一处结论的文件级证据。读完本文你可以完整理解 Proxmark3 通信协议中一帧数据在线路上长什么样并具备新增命令或排查通信问题的协议层基础。需要说明的是原文档标注其主要面向开发者因此本文也定位为协议实现级内容面向需要编写、转换或调试命令处理的开发者。旧格式固定 544 字节的问题在 NG 格式出现之前主机与 Proxmark3 之间双向的帧结构是uint64_t cmd; uint64_t arg[3]; union { uint8_t asBytes[PM3_CMD_DATA_SIZE]; uint32_t asDwords[PM3_CMD_DATA_SIZE / 4]; } d;当时PM3_CMD_DATA_SIZE 512且没有任何 API 抽象——每个模块各自手工拼装/解析这类帧。由此带来两个问题帧大小固定为 544 字节哪怕只是回一个简单 ACK也要在线路上发送完整的 512 字节 payload8 24 512 544链路分片放大抓 USB 传输可以观察到主机一次发出 544B 的 Bulk 帧而设备侧受内部缓冲区限制只能按 128B、128B、128B、128B、32B 共 5 个包发回一条空 ACK被拆成 5 次发送。对于 USB 这个开销尚可忍受但对 FPC/USART/蓝牙这类低速链路9600460800 波特率而言固定 512B 的尾随浪费是致命的——这正是引入变长帧的主要动机。对应的新结构体如今定义在 include/pm3_cmd.htypedef struct { uint64_t cmd; uint64_t arg[3]; union { uint8_t asBytes[PM3_CMD_DATA_SIZE_OLD]; uint32_t asDwords[PM3_CMD_DATA_SIZE_OLD / 4]; } d; } PACKED PacketCommandOLD;注意关键点旧格式结构体改用PM3_CMD_DATA_SIZE_OLD定死在512与PM3_CMD_DATA_SIZE解耦。头文件注释include/pm3_cmd.h#L34-L36说明了原因bootloader 只说 OLD 格式若把旧结构体跟着新值变大会对所有已部署的 bootrom 破坏刷写兼容性。而PM3_CMD_DATA_SIZE本身在仓库中已按平台分化include/pm3_cmd.h#L28-L41#if defined(ON_DEVICE) !defined(PM5) #define PM3_CMD_DATA_SIZE 624 #else #define PM3_CMD_DATA_SIZE 4064 // PM5 firmware and the client #endif // 旧帧钉死在 512 #define PM3_CMD_DATA_SIZE_OLD 512 // FPC/BWM 前向缓冲较小设备经 FPC 回复时限制 payload #define PM3_FPC_MAX_DATA 2048即文档写作时暂时 512的上限在当前仓库中 PM3 设备固件为 624、PM5 固件与客户端为 4064客户端侧SendCommandNG会以g_conn.max_cmd_data_size做上限检查见下文。NG 帧的逐字段定义NG 格式从零设计即使只把旧格式的 payload 变成变长单帧最少也要 32 字节且字段任意宽收益有限因此直接重新设计。命令帧客户端 → Proxmark3uint32_t magic; uint16_t length : 15; bool ng : 1; uint16_t cmd; uint8_t data[length]; uint16_t crc;字段含义magic任意魔数PM3a0x61334d50用于出流后重新同步length变长 payload 长度0 表示无上限为PM3_CMD_DATA_SIZEng标志位数据按 NG 格式还是 OLD 格式编码过渡期用cmd16 位命令码够用了data变长 payloadcrc真实 CRCCRC-14443A或占位魔数a3应答帧Proxmark3 → 客户端uint32_t magic; uint16_t length : 15; bool ng : 1; int8_t status; int8_t reason; uint16_t cmd; uint8_t data[length]; uint16_t crc;字段差异magic为PM3b0x62334d50占位魔数为b3新增status命令执行状态与reason对指定命令的状态细化说明两个 8 位字段。CRC 的规则文档原文CRC 可选接收侧接受a3/b3作为占位值若不是占位值则按真实 CRC 校验USART 链路默认启用 CRCUSB 双向默认禁用 CRC。这一策略在当前代码中仍然成立——client/src/comms.c#L208-L214 中SendCommandNG依据send_via_fpc_usart/send_with_crc_on_fpc/send_with_crc_on_usb决定是否调用compute_crc(CRC_14443_A, ...)否则写入COMMANDNG_POSTAMBLE_MAGICa3。由此得到帧大小结论见文末参考帧NG 命令帧 10522 字节、NG 应答帧 12524 字节按上限 512 计OLD 帧恒 544 字节。以最小的hw ping为例NG 命令帧仅10 字节OLD 格式则固定544 字节——这就是 FPC/USART/BT 链路的核心收益。内部结构体与 API 抽象文档区分了两类结构体传输用打包结构体PACKED只描述线上字节PacketCommandNGPreamble、PacketCommandNGPostamble、PacketCommandNGRaw、PacketResponseNGPreamble、PacketResponseNGPostamble、PacketResponseNGRawAPI 用结构体PacketCommandNG/PacketResponseNG向开发者隐藏帧细节同时保留oldarg[3]与ng标志以兼容尚未转换的调用。两者都在 include/pm3_cmd.h。传输侧typedef struct { uint32_t magic; uint16_t length : 15; // 变长部分长度0 表示无 bool ng : 1; uint16_t cmd; } PACKED PacketCommandNGPreamble; #define COMMANDNG_PREAMBLE_MAGIC 0x61334d50 // PM3a #define COMMANDNG_POSTAMBLE_MAGIC 0x3361 // a3API 侧include/pm3_cmd.h#L67-L78typedef struct { uint16_t cmd; uint16_t length; uint32_t magic; // NG uint16_t crc; // NG uint64_t oldarg[3]; // OLD union { uint8_t asBytes[PM3_CMD_DATA_SIZE]; uint32_t asDwords[PM3_CMD_DATA_SIZE / 4]; } data; bool ng; // 存的是 NG 数据还是 OLD 数据 } PacketCommandNG;PacketResponseNG同形多出status/reason。文档明确布尔字段ng表示该结构体保存的是 NEW 还是 OLD 格式数据OLD 来源既可能是旧的 544B 帧也可能是混合帧变长但仍携带 oldargs过渡完成后可能会移除oldarg与ng字段——事实上当前仓库中 MIX 形态已删除见下文oldarg的读取方仅剩 client/src/flash.c 与 client/src/proxmark3.c 两处且都是与 bootrom 经SendCommandBL通信。客户端发送侧 APIclient/src/comms.cvoid SendCommandNG(uint16_t cmd, uint8_t *data, size_t len); void SendCommandBL(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); void SendCommandOLD(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);原型见 client/src/comms.h#L95-L97实现见 client/src/comms.c#L111-L235SendCommandNG所有命令的统一入口。参数打包进临时PACKED结构体放进data字段即可。实现中它会① 用g_conn.max_cmd_data_size检查 payload 上限PM5 场景下 4064 比设备缓冲大必须钳制② 填 preamblemagic/ng1/length/cmd③ 按链路策略计算或写入 CRC 占位④ 计算总长sizeof(PacketCommandNGPreamble) len sizeof(PacketCommandNGPostamble)⑤ 交给通信线程uart_wakeup()打断接收循环让发送尽快上线。SendCommandBLSendCommandOLD的改名别名专门标记必须保持 OLD 格式的 bootrom 帧源码注释client/src/comms.c#L108-L113写明了两类用途进入 bootloader 模式的命令可能与旧固件对话、直接发给只支持 OLD 帧的 bootloader。SendCommandOLD不再有SendCommandBL之外的其他调用者。SendCommandMIX与PM3_CMD_DATA_SIZE_MIX已删除MIX 是历史折中——NG 帧封装但前 24 字节仍放三个 64 位 oldarg。现在客户端已无法构造 MIX 帧。内部流程这些函数准备帧后经uart_communication调uart_send上线。设备接收与发送侧armsrc/接收设备侧主循环AppMain调receive_ngarmsrc/cmd.creceive_ng再调usb_read_ng/usart_read_ng取出PacketCommandNG交给PacketReceived做命令分发broker。无论来的是旧帧还是新帧检查PacketCommandNG.ng字段即可判断oldarg中是否有效数据旧 handler 仍可在oldarg里找到原参数。receive_ng_internal的实现armsrc/cmd.c#L181-L199体现了变长接收的要点先读 8 字节 preamble按其中length决定 payload 大小rx-data只在确有包进入时整体清零一次文档注释提到对主循环每次空闲轮询都清零的开销比主循环其余部分还大。发送回复 API 定义在 armsrc/cmd.h#L32 附近实现在 armsrc/cmd.c#L43-L179int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, const void *data, size_t len); int reply_ng(uint16_t cmd, int8_t status, const uint8_t *data, size_t len); int reply_reason(uint16_t cmd, int8_t status, int8_t reason, const uint8_t *data, size_t len);reply_mix已删除reply_old只保留给 bootrom 同样服务的 handler——注意它无论len是多少都发送sizeof(PacketResponseOLD)即 544 字节armsrc/cmd.c#L70-L72 中usb_write(..., sizeof(PacketResponseOLD))而reply_ng只发送你给它的精确长度双通道USB FPC/BWM同时可用时两个通道的发送结果取故障优先、USB 优先的裁决逻辑armsrc/cmd.c#L159-L168。转换完成后的典型 handler 写法——校验长度后在自己的操作码上应答文档示例可直接作为模板case CMD_FOOBAR: { if (packet-length ! sizeof(foobar_t)) { reply_ng(CMD_FOOBAR, PM3_EINVARG, NULL, 0); break; } foobar_t *payload (foobar_t *)packet-data.asBytes; ... reply_ng(CMD_FOOBAR, PM3_SUCCESS, resp, resplen); break; }过渡期部分 handler 曾有if (packet-ng) { ... } else { ... }双模分支以便新旧调用方共存目前这类分支已全部移除——不带ng位的帧现在会收到PM3_EINVARG应答。另一个值得注意的实现细节NG 应答 preamble 为 10 字节payload 会落在非字对齐偏移上而 ARM7TDMI 上非对齐 32 位读会静默位旋转而不是触发异常。reply_ng_internal用 2 字节前垫把整个帧偏移 2 字节使data[]落回字边界线上字节不变见 armsrc/cmd.c#L94-L102 的注释。客户端接收侧client/src/comms.c流程uart_communication调uart_receive构造出PacketResponseNG交给PacketResponseReceivedclient/src/comms.c#L297。它要么立即处理如调试打印要么存入环形缓冲rxBufferCMD_BUFFER_SIZE个PacketResponseNG头/尾指针 互斥锁见 client/src/comms.c#L62-L73。命令层通过WaitForResponseTimeout/WaitForResponseTimeoutW或下载场景的dl_it调getReply取包。与超时直接相关的一处关键机制在PacketResponseReceived入口client/src/comms.c#L299-L303每收到一个包就把WaitForResponseTimeout/dl_it的超时计时重置。因此实际超时是距最近一个包的时间与已收到的包数量无关——这对hw status、lf read这类先连发大量帧再收尾的命令在 9600 波特率下的存活至关重要。迁移清单与工程实践笔记把一个命令从 OLD 迁到 NG四个方向各改一处方向改动客户端发送SendCommandOLD→SendCommandNG一切参数装进临时 PACKED 结构体放data设备接收解析PacketCommandNG从oldarg改为只读data设备发送reply_old→reply_ng同样参数进 PACKED 结构体客户端接收解析PacketResponseNG从oldarg改为只读data文档从整树转换中得到的实践笔记值得逐条保留它们都是踩坑的产物用自己命令的操作码应答永远别用CMD_ACK。匿名 ACK 迫使过去做 hack——例如 iCLASS 把自己的CMD_HF_ICLASS_SIMULATE塞进回复的arg0里让客户端区分来源。成功标志放 NG 的status字段而不是塞进数据字节需要第二层区分时用reply_reason()。两边都要在解引用前校验packet-length。有多个已转换命令此前会读越短帧的尾部。PACKED不是免费的它把结构体对齐设为 1对任何宽于字节的成员取地址会触发-Werroraddress-of-packed-member且 ARM7TDMI 上非对齐 32 位加载会静默位旋转。只在去掉填充时才用 PACKED若sizeof打不打包都一样就别打。文档给了对照epa_replay_t打包uint16_t落在奇偏移对比epa_result_t、t55xx_setconfig_t未打包成员天然无填充且会被取地址。PM3_CMD_DATA_SIZE_MIX是 MIX 专用常量。任何改为 NG 的分块传输必须用PM3_CMD_DATA_SIZE - sizeof(payload_t)来定块大小。reply_old恒发 544 字节reply_ng只发给定长度。一条命令可以应答多次例如CMD_HF_ISO14443A_READER带ISO14A_CONNECT | ISO14A_RAW时会应答两次select 一次、raw 交换一次客户端必须把两次都消费掉。大块下载CMD_DOWNLOAD_BIGBUF、CMD_DOWNLOAD_EML_BIGBUF、CMD_SPIFFS_DOWNLOAD、CMD_FLASHMEM_DOWNLOAD使用download_req_t/download_chunk_t/download_done_t见 include/pm3_cmd.h。块头只带 offset——帧长本身就给出了块大小——传输以download_done_t结束且应答在原CMD_DOWNLOAD_*操作码上而非匿名 ACK。client/src/comms.c中的dl_it()仍理解 OLD 块格式因为CMD_READ_MEM_DOWNLOAD由 bootrom 服务。设备侧遗留 OLD 应答截至文档时的状态C 客户端与 ARM 固件均已完成转换。客户端无SendCommandOLD/SendCommandMIX调用点设备上仅剩三处刻意保留的 legacy 应答位置保留原因armsrc/appmain.c—CMD_READ_MEM_DOWNLOADED及其CMD_ACK终止符bootrom.c同样服务它而 bootrom 只说 OLDarmsrc/appmain.c—CMD_DEVICE_INFO同上SendCommandBL标记了必须保持 OLD 的帧不要转换它们。这些位置按PM3_CMD_DATA_SIZE_OLD而非PM3_CMD_DATA_SIZE分块reply_old会把 payload 钳制到 OLD 尺寸若发送方按 NG 尺寸分块会构造出超大块被线路截断后oldarg[1]里仍声明全长。另有一处从遗留清单中移出的案例armsrc/hfsnoop.c的CMD_FPGAMEM_DOWNLOADED曾因 FPGA 追踪 DMA 双缓冲看起来塞不下 NG 头而保留 OLD现已转换——DMA 直接写入download_chunk_t的chunk-data填满即完整 NG payload。文档特别提醒循环中每次传输只武装还差多少字节因为FPGA_TRACE_SIZE不是DOWNLOAD_CHUNK_MAX的整数倍若对最后一个短块仍武装整块会永远等待 FPGA 永远不会发送的字节。Bootrom刻意保留旧格式Bootrom 继续用 OLD 帧理由有二文档原文绝大多数 bootrom 帧恰好携带 512B payload新旧开销差异可忽略经 USART 走 flash 既危险又慢115200 波特 vs 7M 波特不值得。同时它需要保持与仍支持旧格式的其他仓库的兼容。设备侧路径bootrom/bootrom.c接收usb_readcommon/usb_cdc.c⇒UsbPacketReceivedbootrom/bootrom.c#L106⇒CMD_DEVICE_INFO/CMD_START_FLASH/CMD_FINISH_WRITE/CMD_HARDWARE_RESET另有usb_enable/usb_disable。发送reply_oldbootrom.c⇒usb_writecommon/usb_cdc.c。客户端侧的 flasherclient/src/flash.c 等因此必须继续用 OLD 帧它与现行客户端代码共用少数原语OpenProxmark、CloseProxmark、SendCommandOLD⇒ 上述四条 bootrom 命令接收侧仍走WaitForResponseTimeout ⇒ PacketResponseNG旧帧被同一套传输层支持。USART RX FIFO 重写应对未知大小的包变长帧要求 USART 侧彻底重写以应对未知尺寸的数据包。方案要点USART 全双工RX 与 TX 均为双 DMA 缓冲RX 增加内部 FIFO。各函数职责文档New usart RX FIFO一节usart_initUSART 在usart_init()后全程保持激活RX/TX 例程无需再碰pUS1-US_PTCR AT91C_PDC_RXTEN | AT91C_PDC_TXTEN。usart_writebuffer_sync仍用 DMA但接受任意包大小删掉了不必要的 memcpy返回前等待 DMA 缓冲处理完毕故称 sync可以做成异步版但调用方必须保证 DMA 缓冲在此期间不被回收既然同步就不需要第二个 DMA 缓冲。usart_read_ng调用方告知期望包长依赖usart_rxdata_available判断 FIFO 中是否有数据从 FIFO 取数重试次数是动态的随 FPC 链路速度变化。usart_rxdata_available轮询usart_fill_rxfifo返回 FIFO 中可用字节数。usart_fill_rxfifo若下一 DMA 缓冲已移入当前缓冲US_RNCR 0说明一个 DMA 缓冲已满——把当前 DMA 缓冲数据转入 FIFO、换到另一个 DMA 缓冲、把腾空的 DMA 缓冲挂为下一缓冲若当前 DMA 缓冲部分填充则转入可用数据并记录已复制量。接收侧的重试上限也在调优之列common/usart.c文档给出片段当前仓库中USART_SLOW_LINK宏在 include/pm3_cmd.h#L26 定义并注释用于 BT 等慢速链路uint32_t usart_read_ng(uint8_t *data, size_t len) { // 实测经验值3000000 / USART_BAUD_RATE // 取 10 倍 uint32_t tryconstant 0; #ifdef USART_SLOW_LINK // BT 链路在 460800 下实测过 13200 次 tryconstant 50000; #endif uint32_t maxtry 10 * (3000000 / USART_BAUD_RATE) tryconstant; ...超时与实测时延链路吞吐参考新格式引入前Linux USB#db#实测 PM3 ⇒ Client 约 545109 Bytes/sWindows 虚拟机上 ProxSpace USB 约 233998 Bytes/s。USART波特率定义于common/usart.h的USART_BAUD_RATE链路实测 PM3 ⇒ Client9600934 Bytes/s11520011137 Bytes/s46080043119 Bytes/sLinux USB666624 Bytes/s等效约 7M 波特接收超时经 USART 接收比 USB 慢得多USB 下 30ms 内完成的接收USART 上会报部分包错误。经验值FTDI 9600 hw status ⇒ 需 20ms FTDI 115200 hw status ⇒ 需 50ms FTDI 460800 hw status ⇒ 需 30ms BT 115200 hf mf fchk --1k -f file.dic ⇒ 需 140ms对应常量定义在 include/pm3_cmd.h#L1449 一带#define UART_FPC_CLIENT_RX_TIMEOUT_MS 200 #define UART_USB_CLIENT_RX_TIMEOUT_MS 20 #define UART_NET_CLIENT_RX_TIMEOUT_MS 500 #define UART_TCP_LOCAL_CLIENT_RX_TIMEOUT_MS 40 #define UART_UDP_LOCAL_CLIENT_RX_TIMEOUT_MS 20这些值最终进入uart_posix.c的timeval结构与uart_win32.c的serial_port_windows结构。初始用UART_FPC_CLIENT_RX_TIMEOUT_MS一旦检测到走 USB 就降为UART_USB_CLIENT_RX_TIMEOUT_MS切换逻辑见 client/src/comms.c#L982。超时可用hw timeout命令在线调整且下限即 USB 超时——client/src/cmdhw.c#L1565-L1567 会对小于UART_USB_CLIENT_RX_TIMEOUT_MS的取值给出告警。通信延时补偿WaitForResponseTimeout与dl_it的超时里会自动加入一段通信延时仅在走 FPC 时启用timeout 2 × 实测 FTDI 线缆经验延时// client/src/comms.c static size_t communication_delay(void) { if (conn.send_via_fpc_usart) return 2 * (12000000 / uart_speed); return 100; }hw ping -l 512实测USB 6–32ms460800 下 40–70ms9600 下 1100–1150ms。新旧应答路径的实测对比hw statusDbpStringEx耗时对比文档实测值路径USB (/dev/ttyACM0)4608001152009600reply_old2.52s3.03s4.88s26.5sreply_mix9600———7.08sreply_ng2.10s2.22s2.43s5.75slf read9600 vs 11520050.38s vs 6.28smem dumpUSB vs 115200 FPC1.48s vs 25.34s。可见reply_ng在慢链路上把单命令耗时压低了一个量级USB 上则与旧路径持平略优。快速连发fast push mode连续发送多条命令仍可能变慢客户端会周期性地等待入站 RX 帧而超时设置因 BT 而偏保守uart_posix.c的struct timeval现为 200ms。若确定下一条命令无需等待应答可以借用 flasher 的技巧——// fast push mode conn.block_after_ACK true; some loop { if (sending_last_command) // 关闭快速模式 conn.block_after_ACK false; SendCommandOLD / SendCommandMix if (WaitForResponseTimeout(CMD_ACK, resp, some_timeout) false) { ... conn.block_after_ACK false; return PM3_ETIMEOUT; } } return PM3_SUCCESS;若难以判定何时是最后一条命令// fast push mode conn.block_after_ACK true; some loop { SendCommandNG if (WaitForResponseTimeout(CMD_FOOBAR, resp, some_timeout) false) { ... conn.block_after_ACK false; return PM3_ETIMEOUT; } } // 关闭快速模式并发送一条哑命令使其生效 conn.block_after_ACK false; SendCommandNG(CMD_PING, NULL, 0); WaitForResponseTimeout(CMD_ACK, NULL, 1000); return PM3_SUCCESS;参考帧调试用帧大小的硬约束按上限 512 计OLD 命令与应答帧恒为544 字节NG MIX 命令帧10522 字节NG MIX 应答帧12524 字节。链路分片行为Linux USB发送包可为 544B接收包最大 128B故 544 12812812812832Linux UARTFTDI发送包最大 256B544 25625632接收包最大 512B544 51232。hw ping三个时代的线上字节对照十六进制小端// 旧版OLD 请求 MIX 应答 TestProxmark: SendCommandOLD(CMD_PING, 0, 0, 0, NULL, 0); -5440901000000000000000000000000000000000000000000000000000000000000 - OLD CMD_PING: reply_mix(CMD_ACK, reply_via_fpc, 0, 0, 0, 0); -36504d336218000000ff0000000000000000000000000000000000000000000000 - MIX // 中间版双向 MIX CmdPing SendCommandMIX(CMD_PING, 0, 0, 0, NULL, 0); -34504d33611800090100000000000000000000000000000000000000000000000000 - MIX CMD_PING reply_mix(CMD_ACK, reply_via_fpc, 0, 0, 0, 0); -36504d336218000000ff00000000000000000000000000000000000000000000000 - MIX // 现行 NG 版 CmdPing SendCommandNG(CMD_PING, data, len); -10504d3361008009016133 - NG CMD_PING reply_ng(CMD_PING, PM3_SUCCESS, packet-data.asBytes, packet-length); -12504d33620080000009016233 - NG解析一下现行 NG 版50 4d 33 61即小端的PM3a00 80是 length/ng 联合体length0、ng109 01是CMD_PING0x010961 33是占位魔数a3。应答50 4d 33 62PM3b、00 80、00 00status0 即PM3_SUCCESS、reason0、09 01、62 33占位b3——12 字节收尾而旧版同样语义要 544 字节请求 36 字节应答。hw ping -l 512NG的完整收发则演示了大 payload 在 128B 接收窗口下的自然分片-522504d336100820901000102030405060708090a0b0c0d0e0f1011121314151617 - NG -128504d3362008200000901000102030405060708090a0b0c0d0e0f101112131415 - NG -128767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495 -128f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415 -128767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495 -12f6f7f8f9fafbfcfdfeff6233注意请求length字段为00 820x0200512高位 ng1且整帧 522 字节 10 头 512 payload 2 CRC 尾正好落在NG 命令帧 10522的上界应答 524 字节 12 头 512 payload 2 尾落在应答帧上界随后按 128B 窗口分 5 段到达。小结NG 格式的设计取舍把 doc/new_frame_format.md 与当前仓库源码放在一起看这套协议演进遵循几条清晰的原则变长解决慢链路10 字节的空命令帧 vs 544 字节的旧帧在 9600 波特链路上就是 26.5s 与 5.75s 的差距可辨识与可重同步PM3a/PM3b魔数 可选 CRC慢链路USART/BT默认开 CRCUSB 用占位魔数省一次计算语义回到应答本身status/reason字段 用自己的操作码应答消灭了匿名CMD_ACK带来的 arg 借位 hack兼容边界精确锁定只有 bootrom 相关帧SendCommandBL/reply_old保持 OLDOLD 结构体尺寸钉死在 512其余路径完成转换后旧字段oldarg、ng、MIX 常量按计划删除。开发者定位协议问题时的入口文件字段与魔数在 include/pm3_cmd.h客户端收发在 client/src/comms.c设备侧回复与接收在 armsrc/cmd.c 与 armsrc/appmain.cbootrom 在 bootrom/bootrom.c刷写旧帧路径在 client/src/flash.c。【免费下载链接】proxmark3Iceman Fork - Proxmark3项目地址: https://gitcode.com/GitHub_Trending/pr/proxmark3创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表