作者峰会帐号:JuncoJet
[.序言]
Hello你们好,我应当有很久没在52发贴了吧,灌水除外。缘由大约,近段时间都在搞(辅导)硬件(模电)方面的东西,不涉及软件/逆向等。不过如今总算得住机会,还能有个擦边内容可以拟个贴子分享你们了。
近来新入手了个D87RGB多模机械鼠标,整体都不错,豪华内涵有档次,就这。
曾经用过的按键不少,键帽60%、青轴104、静电容108等,大多数没有RGB灯,有灯的只有蓝牙控制,台式笔记本也没蓝牙,用手机去控制也不便捷,这就问难堪不难堪。此次新鼠标有比较健全的按键驱动,可以设置按键宏和灯效,软件界面友好功能健全。只可惜灯效方面只能外置(动态)和自定义静态灯效。之后萌生出一个新奇的看法,能够让鼠标灯效玩贪吃蛇,像某贼船鼠标一样。但后来我舍弃了,缘由并不是不行,而是这灯厂太华丽了。
下边内容由逆向剖析展开,以及程序验证POC,最终写成一个完整的开发框架。
[.USB合同逆向]
逆向,虽然是挺有意思的东西,和推理一样,把已知的线索都罗列举来,推理是用时间线贯串,逆向则是用逻辑贯串。清除掉所有的干扰和不可能,剩下的无论如何不可思议,他都是正确的结果。似乎会有弯路,但总是乐此不疲。
说了那么多,只是要告诉你们,逆向剖析都是会比较绕,有好多弯路,请耐心看完。
首先,安装驱动、打开按键设置软件,灯效设置。使用USBlyzer进行抓包。
设置第一个按钮(ESC)为绿色,之后我们可以看见抓取到的USB数据如右图
接着我们把颜色改成红色,可以看见抓取的数据如右图,看起来没有加密,这是个好兆头。
之后抓取第二个键F1,
发觉这似乎有空了3个字节
继续验证旁边的按钮,可能按键空的地方,或许是存在键盘的?
经过一系列的抓包,之后整理下来一些猜想,例如每位键盘的控制都是明码,传输的是RGB数据占用3字节。
每条报文(是如此叫的么?)背部有12字节是合同头或则命令,共计发送6条数据给按键
剖析之初虽然还是有好多弯路的,这是我的笔记,防止把大家看的云里雾里的我就略过了,例如猜想RGB数据是RGB还是RGBA。
好多错误的东西我就不提了,感兴趣可以看下这个笔记的截图
最终整理得到这样的一组信息,旁边都会介绍到
[.程序验证POC]
原本准备用VB6来写的,开发速率快,贼好用。后来想想还是算了,QT来写,使用C++开发框架,这样的话便捷开源你们一上去构建。并且能够移植到Linux等环境,底层USB库使用libusb-1.0本身具备跨平台性。
第0个简单的验证程序如图,照亮所有LED,变幻颜色。验证失败!
按键死了,USBBulk数据发送给按键后似乎须要读出返回的数据,不然按键会假死(可能真)状态。
返回的数据,明面上看的话可能是覆盖灯效前的原始数据,未具体研究和验证,由于对我来说用途不大。修正BUG后,接着验证。
这么低级错误,就不补图了,事例同下边,只是缺乏发送后接收数据的代码。
第1个简单的验证程序如图,照亮所有LED,变幻颜色。验证成功!
第2个验证程序如图,次序照亮所有的LED。验证失败!
失败的主要诱因,推测可能存在空热键,当次序照亮到空热键的时侯,会出现IO错乱问题
由于通常按键或则LED灯(无关共阳极、共阳极),都采用矩阵结构,这样可以降低MCUGPIO的使用。若果不使用矩阵结构的话,87个RGBLED,须要261GPIO来控制,这是相当烧钱的(须要更中级的MCU或则更多MCU分工、或者使用到锁存器)。
对合同剖析,大致的才能推算出空热键所在位置,之后对热键构建映射关系,实现一个完整的控制、开发框架。经过很漫长的剖析,最终结果就是前面一张图说明问题。
[.完整开发框架]
通过逆向和里面的验证,基本上了解到了几个信息,USB合同共计发送数据6次,每次发送的是一行热键的RGB数据,每位RGB以3字节储存。热键有可能存在空位,也就是我们必须清除掉那些空位,而且提高实际对按键灯效操作时的简约度。所以我大致的把程序写成那么几层
TKbdObj按键类。承继下边这种东西,改动下边内容可保持下层名称统一。
TKeyMap键盘映射层。负责转换按键通配符名称到XY矩阵数据,提供on/off和转换方式。
TLEDSLED逻辑控制层。负责实际控制LEDXY矩阵数据逻辑,以及提供R、G、B->RGB的转换方式和向上发送USB层功能。
TUSBUSB驱动层。负责主机->按键底层合同交互。
介绍完框架结构完了,给你们分享几个简单的实例。
由于懒,所以没有使用多线程或则Timer之类,QT上面的Timer须要代码自己码,相比VB6难用好多。
照亮按键最左边键盘,用于测量KeyMap映射数据是否缺损
void MainWindow::on_pushButton_3_clicked()
{
if(!kbd)return;
int rgb=kbd->rgb(0,0,255);//blue
kbd->on("pause",rgb);
kbd->on("pu",rgb);
kbd->on("pd",rgb);
kbd->on("\r",rgb);
kbd->on("up",rgb);
kbd->on("right",rgb);
kbd->show();
}
显示ILoveYou,简单的字节链表显示照亮按键LED
void MainWindow::on_pushButton_2_clicked()
{
if(!kbd)return;
char d[2]={0},str[]="iloveyou";
for(int x=0;x<3;x++){
kbd->clear();
for(int i=0;i<sizeof(str);i++){
d[0]=str[i];
kbd->on(d,0xFF0000);//red
if(i){
d[0]=str[i-1];
kbd->on(d,0xFF00);//green
}
kbd->show();
Sleep(300);
}
}
}
扫描灯,看过霹雳游侠的应当有记忆,童年精典必须复刻一下
void MainWindow::on_pushButton_5_clicked()
{
if(!kbd)return;
int i;
char d[2]={0},str[]="asdfghjkl;'";
for(int x=0;x<3;x++){
for(i=0;i
-1 ;i++){d[0]=str[i];
kbd->on(d,0xFF0000);
if(i){
d[0]=str[i-1];
kbd->off(d);
}
kbd->show();
Sleep(30);
}
for(i=sizeof(str)-1;i>=0;i--){
d[0]=str[i];
kbd->on(d,0xFF0000);
if(i
d[0]=str[i+1];
kbd->off(d);
}
kbd->show();
Sleep(30);
}
}
kbd->clear()->show();
}
渐变照亮,简单的由暗到亮点亮
void MainWindow::on_pushButton_9_clicked()
{
if(!kbd)return;
for(int x=0;;x+=20){
if(x>255)x=255;
int rgb=kbd->rgb(0,x,0);
for(int i=0;i<17;i++){
kbd->on(i,rgb);
}
kbd->on("ins",rgb);
kbd->on("home",rgb);
kbd->on("pu",rgb);
kbd->on("del",rgb);
kbd->on("end",rgb);
kbd->on("pd",rgb);
kbd->on("up",rgb);
kbd->on("down",rgb);
kbd->on("left",rgb);
kbd->on("right",rgb);
kbd->show();
if(x==255)break;
Sleep(30);
}
}
完整的疗效如下,反例还有好多,感兴趣可以自行下载源码研究
程序须要QTCreator4编译,没有包含QT库,难以直接运行。
联接按键时依赖libusb-1.0驱动,可以使用zadig来安装,后期将会在github上发布更新目前没上传。
附件见左下角峰会原文。
--官方峰会
www.52pojie.cn
--推荐给同学