type
status
date
slug
summary
tags
category
icon
password

00. 背景

买的键盘不支持 VIA,改建只能找客服,这家店的技术有点忙,还有点傻。等了三天,没给我改成功 🤬,哥们是什么善茬吗?直接 Ghidra 启动!
详情
notion image

01. 基本按键映射修改

芯片是南京沁恒的 CH582 ,用的一个32位的RISC处理器,支持RV32IMAC指令集。客服给的固件是 intel hex 格式的,肯定是没有任何符号信息了,但是根据字符串拿官方库 bindiff 固件可以恢复 90% 的符号。
研究了一下,代码都是从第一行指令开始执行,最开始的代码都是把一堆东西映射到 0x20000000 这个地址,这个地址应该是 RAM 地址,为了把常用的东西放到 RAM 里提升效率,代码里看到 0x20000000 的地址自己映射一下就行了,本文实际上没用到,不再展开。
基本按键映射比较简单,一般来说都有一个数组来保存像这样,所以修改基本按键映射应该不用分析
notion image
我尝试搜索 14 26 08 15 17 (即,QWERT)但是搜索不到,拿到原版和修改版之后 diff 一下。
0x40(这个键实际上是右边的 alt) → 0x35(~`)
0x20(这个键实际上是右边的shift) → 0x40(F7)
0x4C(DEL) → 0x41(F8)
notion image
提取出来之后发现是按列存储的,如下图
notion image
其中红色的部分是键盘中不包含的按键,未知按键中 0xfe 为Fn,其他的按下图中解释即可。
notion image
这里上图中的 8 个并不是正常的 value,在协议中和正常的按键位置不同,所以在代码中必然有针对他们的判断,配置好内存映射,直接交叉引用就看到了。
notion image
逻辑基本上就是判断位置,这里我们把要修改成不是控制按键的地方全都改成 0xff 让他永远都不成立就行了。
notion image
剩下的修改基本按键映射,修改这个数组中的对应位置即可。
 

02. Fn 组合键修改

基本按键映射修改好了,但是更关键的是组合键。为此,我看了一下 Github 上一些开源键盘的 Fn 组合键的实现方式,一般是类似基本按键也有一个映射表。如果是这样就简单了,和上面类似只需要diff 一下找到这个映射表,对着修改就行了,但是很不幸这个开发者没有这样做。
要分析代码实现了吗?有点绝望,突然发现一个字符串 f12_deal 这不就是我要找的 Fn 组合键处理逻辑吗!因为这是一个左移 64 的小键盘没有 f1 - f12 ,需要用 Fn + 数字键实现。
notion image
f12_deal 这个没有找到交叉引用(使用 Binary Ninja 查看有交叉引用),但是和它相邻的 f10_deal 有。直接跟过去看看:
notion image
发现相邻的很多函数都是 Fn 组合键处理逻辑,但是这些函数找交叉引用都找不到,合理怀疑是用函数指针调用的,因为一般实现都是有个表,直接 010 Editor 搜一下:
notion image
很明显的结构:
交叉引用看看对这个表的处理,首先是对 fn_layer 所支持按键的扫描处理:
notion image
其中 fn_layer_key 是我自己命名的名字,数据是一堆 key-code。把里面的数据拿出来,根据卖键盘的给我的说明书翻译一下,刚好包含了说明书里的所有 Fn 组合键。
扫描完之后就是处理了,和说明书里对应的非常完美刚好是最后 4 个是长按。
notion image
这就比较明朗了,只需要修改 fn_layer_key 数组里的值和对应位置的 fn_layer_handler_arr 的函数的实现即可实现对 Fn 层快捷键的 VIA。

03. Patch 实现

keystone 不支持 RISC-V,直接用编译器生成。
notion image
然后修改一下 ld 文件,把 .patch_code 段放到指定地址,然后提出来直接用即可。
notion image
 
下面是完整实现
Patch 完之后烧写测试发现功能和预期完全一样,不禁大喊一声:高玉灿牛逼 😋