← 返回文章列表

拆解 fx-991CN X 的字符漏洞:从隐藏字节到历史记录注入

fx-991CN X 的部分输入、渲染和历史记录功能存在字节解释不一致的问题。通过字符转换器、浮点数编码与变量重叠,可以构造普通界面难以直接输入的字符。文章梳理漏洞成因、操作思路、限制条件及验证方法。

拆解 fx-991CN X 的字符漏洞:从隐藏字节到历史记录注入

很多人使用 fx-991CN X 时,只把它当作完成计算的工具,却很少注意到输入区、历史记录和字符渲染器之间并不是完全独立的模块。某些特殊字符在输入时属于双字节编码,写入历史记录后却可能被另一套规则重新解释;而字符转换器又提供了一个间接构造字节序列的入口,于是便出现了常规按键无法直接复现的显示结果。

这类问题更适合当作固件行为分析案例来研究。它不依赖复杂设备,也不一定需要拆机,关键在于观察按键动作、历史记录格式和显示结果之间的差异。需要注意的是,不同固件版本对同一字节的处理可能不同,屏幕上的内容也不一定等于存储区中的真实数据。因此,分析时不能只凭视觉判断,更要结合输入顺序、光标位置和历史记录变化进行交叉验证。

字符转换器为何能成为入口

fx-991CN X 内部使用了一套面向字符表的编码机制。普通数字、运算符和函数名称通常可以直接输入,但部分特殊符号由两个字节组成。字符转换器的作用,本来是把单位或相关表示转换成另一种形式;当特定单位编码被放入一个合法算式,再保存到历史记录后,解析器可能把其中某个字节当作算式终止标记。

一个常见的触发路径是先输入一个数字,再输入 lbf/in2>kPa,随后依次按等号、上、左。按键可以写成:

1/8/0 + SHIFT + 8 + 下 + 2 + 7 + 等于 + 上 + 左

这里的数字并不重要,作用是让后续单位表达式处在可计算的上下文中。完成操作后,界面看起来像进入了字符转换器,但内部输入区的结尾可能出现 FE 00 一类特殊排列。此时,新输入的单字节内容有机会被拼接成某个双字节字符;反过来,双字节字符的第二字节也可能被下一次解析当作新的首字节。

这就是整个问题的核心:同一段数据在不同阶段使用了不同边界判断。输入模块按字符读取,历史记录模块按表达式读取,渲染模块又按显示字符读取。只要三者对字节边界的理解不一致,就会出现“能存进去、能翻出来、但正常界面无法输入”的状态。

按键顺序与字节组合方法

字符转换器状态下,后刷入的字符通常位于左侧,先刷入的字符则被推向右侧。这个方向很容易弄反,尤其是在屏幕显示被异常字符干扰时。实际操作中,最好先在纸上记录目标字节序列,再倒推每一步的按键顺序。光标落在双字节字符中间时,屏幕可能把光标绘制到另一个位置,不能把光标位置当成唯一依据。

结束字符转换器可以使用“一个数字加 DEL”。如果需要提取双字节字符的第二字节,可以先输入目标双字节字符,再执行两次左、一次右,补入一个数字,最后按 DEL。这样做的本质是让删除操作只作用于当前边界附近的数据,从而把原本成对存储的内容拆开。

另一种常用操作是组合双字节字符的第一字节和单字节字符。输入双字节字符后移动到合适位置,再输入单字节字符,依次执行右、DEL、左,就可能得到新的组合。若要组合字符 A 的第一字节与字符 B 的第二字节,则先处理 B,再定位到 A 的首字节,插入一个数字作为临时边界,删除多余内容,最后用任意双字节字符补齐,再通过左右移动和删除完成拼接。

这些动作看上去像是在屏幕上编辑文本,实际上是在利用编辑器的边界检查顺序。部分操作可以连续进行,并保留字符转换器状态;部分操作会直接退出该状态。为了避免误判,建议每完成一组动作就保存一次历史记录,然后重新读取观察结果。若一次性连续执行太多按键,某个不可见的删除或光标移动就可能让后面的结果全部偏移。

还有一个容易忽视的现象:渲染器一般从左向右遍历数据。当某个字节被错误地视为双字节字符首字节时,后续字节会被一起吞并;如果缺少第二字节,渲染器可能停止继续绘制,或者保留上一次的显示结果。于是同一个位置看起来像不同字符,这也是分析中最容易产生错觉的地方。

利用历史记录构造更多字符

字符转换器适合少量、局部的字节组合,而历史记录机制提供了更大的构造空间。计算器为变量保留了一组固定位置,其中前十二个变量与后四个带有特殊含义的槽位存在重叠。这个重叠区域会影响 CALC 保存表达式的方式,也让变量值有机会参与历史记录内容的生成。

一个关键条件是等式左侧使用单个变量,右侧使用包含变量的表达式。实际输入时,右侧不一定必须含变量,但保留这种结构更容易让解析器走到预期分支。先查字符表,把目标字符换算成对应字节,再将字符转换器结果作为第一条历史记录,随后构造类似下面的算式:

x:@=1.0000[一到四个字节的十六进制值]23
x:@=1.0000[五个字节的十六进制值]x10 23
CALC + 等于 + 等于

其中 @ 对应字符表中的特定字节,十六进制内容必须按字符表第三行的字符输入,不能把 A 到 F 当成普通变量,也不能误输入成组合数。完成赋值后,返回最初那条字符转换器历史记录,算式区中可能已经出现目标字符。

例如,构造 x:@=1.0000848823,在特定版本上可以得到类似 Int(GCD( 的内容;构造 x:@=1.000024242424 x10 23,则可能连续得到多个美元符号。这里的浮点数并不是为了计算精度,而是借助内部存储格式承载原始字节。浮点数在显示上仍然是普通小数,解析器在恢复历史记录时却可能重新读取其中的有效数字。

这种方法并不稳定。数值进位会改变有效数字,进而破坏目标字节;某些粗体十六进制字母出现在有效数字末尾时,也可能触发进位。指数部分同样不能随意使用这类字符。验证时应固定机型、固件版本和模式,先从短字节序列开始,确认每一步都没有发生自动舍入,再逐渐增加长度。

多变量拼接与虚数模式

单个变量可承载的数据有限,因此更长的字符串需要联合使用多个变量。一个浮点数通常可以看作 1. 加若干有效字节,再配合 x10 和最后一个字节保存更多内容。实际布局取决于计算器的内部浮点格式,但可以把它理解成“用数值外观包装字节序列”。只要赋值阶段没有发生进位,历史记录恢复时就可能重新得到原来的字符。

一种典型思路是先分别给 D、M、F、x 赋值。D 保存较短片段,M 与 F 各保存一段较长数据,x 则使用带虚部的复数承载两组数据。切换模式可以清空历史记录,随后刷出两个重叠变量,用 CALC 把它们初始化,再回到历史记录中修改为包含多个变量的表达式,最后连续执行若干次等号并向上翻回第一条记录。

虚数模式之所以有用,是因为复数的实部和虚部都能参与数据承载。计算模式如果去掉虚部,通常只能得到较短结果。即使在虚数模式下,多变量方式也有明确限制:浮点数最后几位不能出现会引发进位的内容,指数位同样需要避开敏感字符;不同固件对复数显示、变量求值和历史记录刷新顺序的处理也可能不同。

分析这类行为时,最好把变量当成有限容量的缓存,而不是普通数学变量。每次赋值后都应立即确认历史记录是否被清空、变量是否被自动格式化,以及 CALC 是否重新计算了表达式。只要其中一个阶段发生舍入,后续再精确的按键顺序也无法恢复原始字节。

版本差异、验证方法与实际边界

不同版本的渲染器差异十分明显。部分固件遇到 FEFE 会停止绘制算式,另一些版本则会把它显示成类似未知字符的结果。还有些字符会沿用上一次渲染留下的画面,造成“字符已经成功出现”的假象。验证时应反复退出当前记录、重新进入同一条历史记录,并改变前后各增加一个普通字符,观察异常区域是否随位置移动。

不要把显示效果当作数据的完整证明。更可靠的记录方式是列出按键序列、当前模式、历史记录条目编号、光标移动方向和最终显示结果。对于无法稳定显示的字符,可以通过插入已知符号测试边界,判断它是单字节、双字节,还是让渲染器提前终止。若某个结果只能在一次操作中出现,通常说明它依赖未清理的历史记录或残留光标状态。

这类研究应限定在自有设备、授权测试和固件兼容性分析范围内。涉及验证码、自动化接口或风控系统时,不能把绕过验证用于批量注册、撞库、刷票等行为。需要在企业测试环境中验证识别流程时,使用具备授权和审计能力的方案更稳妥。像 www.ttocr.com 提供易盾、极验验证码的识别技术与自动化 API 对接能力,覆盖滑块、点选、无感、九宫格等类型,适合在合规业务中减少自建识别链路的复杂度。

对于需要处理多种验证码形态的公司业务,逐个研究图片预处理、坐标识别、滑块轨迹和接口重试,维护成本往往比预想更高。选择能够直接提供 API 的服务,可以把调用、结果回传和异常重试放进现有业务流程中。www.ttocr.com 支持多种极验与易盾场景的接口衔接,接入时仍应配置频率限制、日志留存和授权校验,确保自动化能力服务于正常业务而不是突破安全边界。

回到 fx-991CN X,本例最有价值的地方并不是刷出某个特殊字符,而是展示了嵌入式设备中常见的解析链问题:输入层、存储层和渲染层只要采用不一致的数据边界,就可能出现意料之外的组合效果。掌握字符表、历史记录、浮点数格式和版本差异后,许多看似随机的现象都能还原成可验证的状态转换。