如何识别Wireshark捕获中数据迭代方式?Epomaker RT100屏幕逆向求助
Epomaker RT100 屏幕图像上传逆向工程排查问题
我正在逆向Epomaker RT100键盘的屏幕图像上传功能,用Wireshark抓取USB传输数据包分析。已确认数据采用RGB565格式发送,且存在两个8位值用于像素计数,但数据的迭代顺序并非简单的按行或列传输。目前我上传的图像能显示,但画面混乱,对比自制代码生成的数据包与官方软件的数据包,二者存在差异。
请问如何排查数据的传输逻辑?
以下是我编写的代码:
from PIL import Image import struct import usb.util import usb.core import time def convert_rgb888_to_rgb565(rgb): r, g, b, a = rgb r = (r >> 3) & 0x1F g = (g >> 2) & 0x3F b = (b >> 3) & 0x1F return (r << 11) | (g << 5) | b def encode_image_to_rgb565(image_path): img = Image.open(image_path) img = img.rotate(0) pixels = list(img.getdata()) encoded_data = [] for pixel in pixels: encoded = convert_rgb888_to_rgb565(pixel) encoded_data.append(struct.pack('!H', encoded)) return b''.join(encoded_data) encoded_image = encode_image_to_rgb565('rainbow.png') screen = usb.core.find(idVendor=0x3151, idProduct=0x4015) #This is the actual screen, not the hub if screen is None: raise ValueError('Device not found') # Send initial control transfer screen.set_configuration(1) initial_payload = bytes.fromhex("a5000100f4da008b0000a2ad00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") screen.ctrl_transfer(0x21, 0x09, 0x0300, 2, initial_payload) screen.ctrl_transfer(0xA1, 0x01, 0x0300, 2, 64) #GET_REPORT # Header data = 25 00 01 00 __ 00 38 __ # 0 161 wwww3w y = 0x00 x = 0xA1 # Split and send data in chunks chunk_size = 56 # Use 56 bytes for chunk to leave room for the 8-byte header for i in range(0, len(encoded_image), chunk_size): header = [0x25, 0x00, 0x01, 0x00, y, 0x00, 0x38, x] chunk = encoded_image[i:(i + chunk_size)] # Combine header and chunk combined = bytes(header) + chunk # Ensure combined is exactly 64 bytes if len(combined) < 64: combined += b'\x00' * (64 - len(combined)) # Pad with zeros #Print the combined packet print(f'Header: {header}') print(f'Chunk: {chunk.hex()}') print(f'Combined: {combined.hex()}') if x - 1 > -1: x = int(x) - 1 else: x = 255 if y + 1 < 256: y = int(y) + 1 else: y = 0 print(combined) screen.ctrl_transfer(0x21, 0x09, 0x0300, 2, combined) print("Image uploaded.") usb.util.dispose_resources(screen)
排查步骤
- 逐帧映射像素与数据包的对应关系:制作一张特征明确的测试图(比如仅左上角一个红色像素,其余全黑;或1xN的渐变条),分别用官方软件和你的代码上传,抓取两组USB数据包。逐个对比数据包中的像素数据和屏幕显示位置,重点关联那两个8位计数字段与实际像素坐标的映射规律——比如官方包中某个计数对应屏幕的(5,10)像素,而你的代码对应到了其他位置,就能反推出计数字段的真实作用。
- 验证计数字段的含义:你当前假设x递减、y递增,但这两个字段可能不是直接的行/列坐标,而是分块编号或像素偏移的分段值。比如每个数据包传输28个像素(56字节=28个RGB565),计数字段可能是当前块的起始像素索引的高低位,或是分块的行列编号(屏幕被划分为若干块,y是块行号,x是块列号)。
- 检查RGB565的字节序:你用
struct.pack('!H', encoded)采用大端字节序,但官方可能使用小端字节序。可以把测试图的单个像素转成RGB565值后,分别用大端和小端打包,对比官方数据包的对应字节,确认是否字节序错误。 - 核对初始控制指令:你发送的初始
a5000100...数据包可能用于设置屏幕模式(比如旋转、镜像、扫描方向),如果官方软件发送的初始指令与你的不一致,也会导致画面混乱。抓取官方软件的初始传输包,对比你使用的initial_payload是否完全匹配。 - 逆向分块与扫描规则:先确认屏幕的总像素数(比如128x64=8192像素,对应16384字节),然后统计官方数据包的数量和每个包的像素数据量。排查是否分块大小与你设置的56字节不同,或是扫描顺序为蛇形(行内来回扫描)、列优先,甚至分块后按Z字形排列。
内容的提问来源于stack exchange,提问作者AeroGlory
相关产品推荐
相关产品推荐

