1. 项目概述从一次鼠标双击故障开始的逆向之旅事情得从我手头这只Glorious Model O鼠标说起。作为一款在游戏玩家和极客圈里口碑不错的轻量化鼠标它的性能和手感确实没得说。但用了一年多经典的“双击”问题还是找上门了。我本打算像往常一样去官网下载个最新固件刷一下看看能不能解决。结果发现Glorious官方提供的固件更新工具其核心是一个名为Sinowealth-KB-Tool.exe的程序。这个发现让我来了兴趣——中颖电子Sinowealth的MCU在众多外设里很常见但这个配套的烧录/配置工具本身似乎藏着不少秘密。它如何与鼠标通信固件文件是什么结构能否从中提取出一些有用的信息甚至进行自定义修改这次“固件逆向分析”项目就是围绕解开Sinowealth-KB-Tool工具和 Glorious Model O 鼠标固件的秘密而展开的。这不仅仅是修个鼠标更是一次深入嵌入式设备软件层理解其工作原理和潜在可能性的实践。2. 核心思路与工具选型如何打开固件的“黑盒”面对一个打包好的Windows可执行程序Sinowealth-KB-Tool.exe和可能加密或压缩的固件文件.bin或.hex我们的目标很明确第一逆向分析上位机工具理解其与鼠标MCU的通信协议、固件文件的封装与校验逻辑第二逆向分析固件本体尝试理解其功能模块、配置参数乃至发现潜在的漏洞或定制化空间。这本质上是一个典型的“嵌入式设备软件逆向工程”任务。2.1 逆向分析工具链搭建工欲善其事必先利其器。针对这个项目我搭建了一套混合工具链兼顾静态分析和动态调试。1. 静态反汇编与反编译IDA Pro 作为主力毫无疑问IDA Pro是逆向工程的“瑞士军刀”。对于分析Sinowealth-KB-Tool.exe这种x86 Windows程序以及后续可能遇到的MCU固件基于ARM Cortex-M或8051内核IDA都能提供强大的支持。它的反汇编引擎准确图形化控制流视图CFG对于理清程序逻辑至关重要。更重要的是其反编译插件如Hex-Rays Decompiler能将汇编代码转化为更易读的伪C代码极大提升分析效率。网络上有人问“哪个ai可以分析ida逆向”目前并没有成熟的AI能完全替代逆向工程师的思维但IDA本身及其插件的智能化分析如类型传播、变量重命名已经提供了巨大帮助。2. 动态调试与行为监控x64dbg 与 API Monitor静态分析看结构动态调试看行为。对于Windows应用程序x64dbg是一个免费且强大的调试器适合用来跟踪Sinowealth-KB-Tool在运行时的内存状态、函数调用和网络/串口通信。我们可以通过它下断点观察工具在点击“更新固件”时具体调用了哪些系统API向哪个端口发送了何种数据。 同时配合使用API Monitor这样的工具可以无需修改代码就拦截程序对文件、注册表、网络套接字的操作快速定位到程序读写固件文件、尝试连接设备的关键代码区域。3. 固件文件初步勘察二进制编辑器与常见算法识别在IDA进行深度分析前先用HxD或010 Editor这样的二进制编辑器打开固件文件。直观查看文件头尾是否有明显字符串如版本号、SinoWealth标识、是否包含连续的0xFF擦除后的Flash状态或特定的数据模式。使用binwalk工具可以快速扫描文件中是否嵌入了已知的文件系统、压缩包或加密数据块。对于“易盾点选逆向分析”这类涉及验证逻辑的通常需要识别加密或校验算法而在这里我们首先需要判断固件是明文代码还是经过某种封装。4. 通信协议嗅探硬件串口监听与软件抓包工具与鼠标之间很可能通过USB虚拟的串口CDC或HID接口进行通信。要分析协议硬件监听是最直接的方法。使用一个额外的USB转串口工具或者利用支持监控的USB协议分析仪如Saleae Logic可以捕获线上传输的原始数据。如果通信是标准的串口协议也可以使用软件如Serial Port Monitor或COM Trace来拦截数据流。分析这些数据包的格式头、命令字、长度、数据、校验和是逆向通信协议的关键。注意逆向工程涉及对软件的解构请确保你拥有该软件的使用权并且所有分析活动仅用于学习、研究或修复自己拥有的设备严格遵守相关法律法规。2.2 分析策略制定由外而内由浅入深面对一个完整的系统我采用了分层递进的策略外围行为分析先运行Sinowealth-KB-Tool观察其界面、操作流程、生成的日志文件或临时文件。用Process Monitor记录它对文件系统和注册表的访问。这一步不涉及代码旨在勾勒出程序的整体行为轮廓。通信协议逆向通过动态调试和串口监听重点分析工具与设备握手、固件传输阶段的通信数据包。目标是解析出命令集和数据包格式。固件解析逻辑逆向在IDA中定位到处理固件文件如点击“打开”按钮后的函数。分析其如何读取文件、解析文件头、可能进行的解密或校验计算。固件本体分析获得原始的、可被MCU执行的二进制镜像后将其加载到IDA中根据已知的MCU型号需要从鼠标PCB或工具信息中推断如中颖的SH68F90等设置正确的处理器架构和加载地址开始逆向固件本身的业务逻辑。3. Sinowealth-KB-Tool 上位机工具逆向详解拿到Sinowealth-KB-Tool.exe第一感觉是它不是一个复杂的软件体积不大大概率是使用C或C#编写。我的第一步是将其拖入IDA Pro进行静态分析。3.1 程序结构初步探查IDA加载后首先查看导入表Imports。看到了kernel32.dll,user32.dll,setupapi.dll用于设备管理以及关键的CreateFile用于打开串口或文件、ReadFile、WriteFile、DeviceIoControl等API。没有看到明显的加密库如OpenSSL这初步判断固件传输可能使用较简单的校验而非强加密。 查看字符串常量发现了一些有用的信息比如“Open Firmware File”、“Downloading...”、“Verify Failed!”、“Success!”以及一些疑似错误码的字符串。更重要的是发现了一些与中颖MCU相关的字符串如“SH88F...”、“SH68F...”系列型号这为我们后续分析固件提供了MCU架构线索。3.2 关键功能函数定位与动态跟踪我们的核心兴趣点是“固件更新”功能。在IDA中可以通过交叉引用Xrefs查找上述字符串被哪些函数使用从而定位到核心逻辑。例如搜索“Downloading...”找到显示此信息的UI函数再向上追溯调用它的函数很可能就是固件下载的主逻辑函数。 我找到了一个名为sub_xxxxxxIDA自动命名的函数它内部调用了CreateFile打开一个形如“\\\\.\\COM3”的设备然后进行了一系列的WriteFile和ReadFile操作中间夹杂着进度更新。这很可能就是固件烧录函数。动态调试验证使用x64dbg附加到运行中的Sinowealth-KB-Tool进程。在IDA中找到的疑似烧录函数入口地址设下断点。当我在工具界面选择固件文件并点击“Download”后x64dbg成功断下。单步执行F7/F8同时打开串口监听工具我用了COM Trace虚拟了一个COM口并将工具指向它观察数据流。 通过反复测试和比对我解析出了基本的通信协议框架握手阶段工具发送一个字节的命令0x55可能是连接请求设备回复0xAA表示就绪。命令阶段工具发送包含操作码如擦除0x30、编程0x31、校验0x32和数据地址、长度的数据包。数据包通常有固定的头如0x5A、0xA5、命令字、地址4字节、长度2字节、数据、校验和可能是累加和或CRC16。数据阶段对于编程命令工具会将固件数据分块发送。每块大小可能是64、128或256字节与MCU的Flash编程页大小对齐。应答机制设备每接收一个有效数据包会回复一个应答字节如0x79表示成功0x1F表示失败。实操心得动态调试时重点关注WriteFile写入的缓冲区和ReadFile读取的缓冲区内容。可以在x64dbg中将这些内存区域的数据导出与串口监听的数据进行比对相互印证。遇到校验失败时通过修改内存中的校验值并继续执行可以快速验证校验算法。3.3 固件文件解析逻辑逆向接下来分析工具是如何读取和解析我们选择的.bin文件的。回溯调用烧录函数的代码通常会找到一个文件打开和读取的逻辑。 在IDA中定位到调用fopen或CreateFile用于文件的函数。发现工具在读取固件文件后并没有直接发送而是先进行了一些处理。通过动态调试在读取文件数据后检查内存发现原始文件内容前被添加了一个小的头部Header。头部结构分析经过分析这个头部结构大致如下具体偏移可能因版本而异偏移 0x00: 4字节魔术字例如 “SFIR” (SinoWealth Firmware Image ?) 偏移 0x04: 4字节固件数据长度。 偏移 0x08: 4字节目标MCU的型号ID或Flash起始地址。 偏移 0x0C: 2字节CRC16校验值对整个头部或包含固件的数据进行计算。 偏移 0x0E: 固件原始二进制数据开始。工具在发送时可能会跳过这个头部只发送后面的原始固件数据。但这个头部的存在至关重要它包含了固件长度和CRC校验信息。工具在“打开”固件文件时会校验这个头部如果魔术字不对或CRC校验失败就会报错“Invalid firmware file”。校验算法识别IDA的反编译视图在这里发挥了巨大作用。在文件加载函数附近可以看到一个循环计算校验值的代码段。通过观察汇编指令如加法、移位、异或和反编译后的C代码我初步判断它使用的是CRC16-CCITT多项式0x1021初始值0xFFFF算法。为了验证我写了一个小的Python脚本对抓取到的文件数据片段进行计算结果与工具内存中的值匹配确认了算法。def crc16_ccitt(data): crc 0xFFFF for byte in data: crc ^ byte 8 for _ in range(8): if crc 0x8000: crc (crc 1) ^ 0x1021 else: crc 1 crc 0xFFFF return crc # 示例计算头部假设14字节的CRC header_data bSFIR ... # 你的头部字节 calculated_crc crc16_ccitt(header_data) print(fCalculated CRC: {calculated_crc:04X})4. Glorious Model O 固件本体逆向分析在弄清楚了上位机工具的通信协议和文件格式后我们终于可以触及核心——鼠标固件本身。通过工具的解包逻辑或直接截获通信中传输的原始数据块我们提取出了纯净的MCU可执行二进制文件假设文件名为model_o_fw.bin。4.1 确定MCU架构与加载地址这是逆向固件最关键的一步。错误的结构会导致反汇编完全混乱。有几个信息来源从工具字符串推断之前发现的“SH68F...”字符串是重要线索。中颖的SH68F系列通常是8位8051内核MCU。从PCB实物查看如果拆开鼠标主控芯片上的丝印能直接告诉我们型号。从通信协议推断编程命令中的地址信息。如果工具发送的起始地址是0x0000那么MCU的Flash起始地址很可能就是0x0000。对于8051程序通常从0x0000开始。 综合判断Glorious Model O 很可能使用了中颖的SH68F90或类似型号一款增强型8051内核MCU。因此我们在IDA中新建项目时处理器类型选择“8051”并确认字节序为小端Little-endian。加载地址设置对于8051程序代码ROM通常映射到从0x0000开始的地址空间。所以我们在IDA加载model_o_fw.bin时加载地址Loading offset设置为0x0000。RAM和特殊功能寄存器SFR的地址是固定的IDA的8051模块通常有预定义。4.2 初始反汇编与关键地址定位加载后IDA会从0x0000开始反汇编。8051复位后首先执行地址0x0000处的指令这里通常是一条长跳转LJMP指令跳转到真正的初始化代码C语言中的startup代码或Bootloader。 例如你可能看到ROM:0000 ljmp loc_C000这意味着主程序代码在0xC000地址附近。我们需要让IDA在这个地址也进行分析。按G键跳转到0xC000然后按C键将此地址开始的代码反汇编。寻找中断向量表8051有多个中断源每个中断入口地址固定如外部中断0在0x0003定时器0在0x000B等。这些入口地址处也通常是跳转指令。找到这些跳转指令就能定位到各个中断服务程序ISR这是理解鼠标功能如按键扫描、光学传感器读取、USB报告描述符处理的关键。例如USB中断服务程序可能负责处理主机请求和发送鼠标移动数据。识别数据与代码段固件中除了代码还有常量数据如字符串、配置表、USB描述符。在反汇编视图看到一片区域是连续的、看似无意义的字节但被代码引用如通过MOV DPTR, #xxxxh指令那很可能就是数据区。可以按D键将其转换为数据字节或按A键尝试将其转换为字符串。4.3 核心功能模块分析对于鼠标固件我们关心以下几个核心模块1. USB HID描述符与报告这是鼠标与电脑通信的基础。我们需要找到USB设备描述符、配置描述符、接口描述符和HID报告描述符在固件中的存储位置。这些描述符是标准格式可以通过搜索已知的字节模式来定位例如报告描述符中常见的0x05, 0x01(Usage Page Generic Desktop)、0x09, 0x02(Usage Mouse)。 找到报告描述符后就能理解鼠标上报的数据结构哪些字节代表X/Y移动哪些代表按键状态左键、右键、中键、侧键哪些代表滚轮。这对于后续可能的按键映射修改或DPI调整至关重要。2. 光学传感器PAW3395驱动Glorious Model O 使用的是PixArt PAW3395传感器。固件中必然包含初始化该传感器通过I2C或SPI写入寄存器和读取其运动数据的代码。可以搜索传感器已知的寄存器地址如产品ID寄存器0x00或常见的I2C/SPI通信函数序列如启动、发送地址、读写数据、停止。理解这部分代码有助于我们了解DPI切换、LOD静默高度等参数是如何配置的。3. 按键扫描与去抖逻辑鼠标的按键是通过MCU的GPIO引脚读取的。固件会定期扫描这些引脚的电平。我们需要找到定时器中断服务程序在其中寻找读取特定端口如P1口的代码。按键去抖算法软件延时或更复杂的状态机也在这里实现。分析这里可以知道每个物理按键对应哪个GPIO为硬件改装或修复提供依据。4. 配置存储EEPROM或Flash模拟鼠标的DPI设置、RGB灯效、宏定义等用户配置需要掉电保存。MCU可能外挂了EEPROM芯片或者使用内部Flash的一部分来模拟EEPROM。寻找对非易失性存储器的读写操作如I2C通信或Flash编程指令可以定位配置数据的存储结构和地址。有时这些配置在固件更新后会被保留或重置了解其机制很重要。踩坑记录在分析8051代码时一个常见的难点是“代码银行”Code Banking机制。由于8051地址空间有限一些MCU会使用分页技术来扩展ROM。如果发现跳转指令的目标地址超出了物理ROM范围或者代码逻辑在某个点突然变得不合理可能需要考虑是否遇到了分页切换。这需要查阅具体MCU的数据手册了解分页寄存器如PAGE或BANK的操作方式并在IDA中通过自定义段Segments或使用IDAPython脚本进行模拟。5. 逆向成果应用与自定义修改探索完成逆向分析后我们获得的不仅仅是知识更是一种“能力”。下面谈谈这些分析结果可以如何应用。5.1 固件备份与恢复通过逆向得到的通信协议我们可以编写自己的上位机程序Python pySerial实现与鼠标Bootloader的通信。这样即使官方工具失效我们也能完成固件的读取备份和写入恢复操作。这对于保存特定版本的固件或修复刷坏的设备非常有用。一个简化的Python伪代码示例import serial import struct def send_command(ser, cmd, addr0, datab): # 构建数据包: 头 命令 地址 长度 数据 校验 length len(data) packet b\x5A\xA5 struct.pack(B I H, cmd, addr, length) data checksum sum(packet[2:]) 0xFF # 简单累加和示例 packet struct.pack(B, checksum) ser.write(packet) response ser.read(1) # 读取应答 return response b\x79 # 连接鼠标需进入Bootloader模式通常通过按住特定按键上电 ser serial.Serial(COM3, 115200, timeout1) if send_command(ser, 0x30, 0x0000, b): # 擦除命令 print(Erase OK) # 分块发送固件数据...5.2 配置参数解读与修改如果找到了配置数据在EEPROM或Flash中的存储结构我们就可以解读其含义。例如可能发现偏移0x10: 2字节DPI值实际值该数值 * 50。偏移0x20: 1字节RGB灯光模式。偏移0x30: 4字节按键映射表。通过编写一个小工具可以直接读取、修改这些配置数据然后写回设备。这意味着你可以实现官方驱动不支持的DPI档位如750 DPI或者自定义复杂的按键宏而无需修改主固件代码。5.3 固件功能定制化高级对于有经验的开发者逆向分析是定制化固件的第一步。例如修改USB报告描述符将鼠标伪装成键盘、游戏手柄或多功能控制器需注意USB协议兼容性。调整传感器性能修改PAW3395的寄存器配置尝试优化追踪性能或功耗风险较高可能导致传感器工作异常。添加新功能如果固件中有未使用的GPIO或足够的Flash/RAM空间理论上可以添加新功能如“双击速度调整”、“移动加速度曲线自定义”等。但这需要深厚的嵌入式开发和逆向功底并且要重新计算CRC等校验值。重要警告修改固件有风险可能导致设备变砖无法使用。务必在充分理解代码逻辑、并确保有可靠的恢复手段如通过Bootloader强制刷写后再进行尝试。对于保修期内的设备自行修改固件通常会导致保修失效。6. 常见问题与排查技巧实录在整个逆向过程中我遇到了不少坑。这里总结一下希望能帮你节省时间。6.1 工具无法连接设备现象Sinowealth-KB-Tool一直显示“查找设备”或“连接失败”。排查驱动问题确保鼠标在Bootloader模式下被电脑识别为正确的串行设备。在设备管理器中查看端口号。中颖MCU的Bootloader通常需要特定的USB驱动官方工具包内可能包含。进入Bootloader模式大多数鼠标需要特定的按键组合如按住“后退键”“中键”再插入USB才能进入固件更新模式。这个组合需要从官方说明或逆向通信代码中获知。端口占用关闭其他可能占用该串口的软件。协议不匹配用监听工具确认工具发送的握手指令是否正确。有时不同版本的工具或固件握手协议可能微调。6.2 固件文件校验失败现象工具打开固件文件时提示“文件损坏”或“校验失败”。排查文件头格式用二进制编辑器检查文件前几十个字节是否符合你逆向出来的头部结构魔术字、长度、CRC。可能是文件下载不完整或根本不是该工具支持的格式。CRC算法确认你计算的CRC算法和工具使用的完全一致多项式、初始值、输入输出是否反转。用工具打开一个已知好的固件动态调试获取它计算出的CRC值与你用脚本计算的结果对比。MCU型号匹配固件文件头中可能包含了目标MCU的ID。如果与当前连接的设备不匹配工具也会拒绝。6.3 IDA反汇编结果混乱现象加载固件后代码看起来全是无意义的指令或者交叉引用混乱。排查错误的处理器类型这是最常见的原因。确认你的MCU到底是8051、ARM Cortex-M0/M3还是其他内核。查看芯片丝印搜索其数据手册。错误的加载地址程序可能不是从0x0000开始执行。查找复位向量和中断向量看它们跳转到了哪里。那个地址才是代码段的开始。在IDA中使用“Edit - Segments - Rebase program”来调整。固件已加密或压缩少数情况下固件在传输和存储时是加密的只在运行时由Bootloader解密。这需要先逆向Bootloader的解密逻辑。通过比较原始固件文件和通过通信捕获到的、即将写入Flash的数据可以判断是否有解密过程。6.4 动态调试时数据包不完整现象串口监听工具抓到的数据包断断续续或者格式不对。排查波特率设置错误Bootloader通信的波特率可能是115200、57600或其他。尝试常见的波特率或者从工具的反汇编代码中查找设置波特率的常量。流控制Flow Control检查工具和监听软件是否启用了硬件流控RTS/CTS或软件流控XON/XOFF。如果设置不一致会导致数据丢失。在监听和调试时最好禁用所有流控制。缓冲区大小确保监听软件的接收缓冲区设置得足够大避免高速数据传输时溢出。6.5 修改固件后刷入失败现象自定义修改了固件如改了某个配置值后刷入过程成功但设备无法启动或功能异常。排查CRC校验未更新修改固件内容后相关的CRC或校验和必须重新计算并更新到文件头部。忘记这一步是导致失败的主要原因。破坏了关键代码或数据修改时不小心覆盖了相邻的代码或数据。在IDA中修改时要特别注意指令的边界和对齐。增加代码长度非常困难通常只能进行等长替换。配置数据格式错误对配置区的修改不符合固件读取时的解析逻辑。例如将1字节的枚举值改成了一个超出范围的数字。Bootloader保护有些Bootloader会校验应用程序固件的完整性如签名防止刷入未授权的固件。如果存在这种机制自定义固件将无法通过验证。这需要逆向Bootloader的校验逻辑难度极大。逆向工程就像一场解谜游戏需要耐心、细致的观察和不断的假设验证。每一次成功的分析都是对设备更深一层的理解。对于Glorious Model O鼠标通过这次对Sinowealth-KB-Tool和其固件的逆向我不仅修复了双击问题通过分析发现是按键去抖参数过于敏感在固件中微调了延时值更获得了一种对身边智能设备“知其所以然”的掌控感。如果你也打算尝试从备份原始固件开始一步步来这个过程本身带来的收获远比结果更重要。