【原創(chuàng)】機(jī)械鍵盤USB協(xié)議逆向和利用
作者論壇賬號(hào): JuncoJet
[.前言]
Hello大家好,我應(yīng)該有好久沒(méi)在52發(fā)帖了吧,灌水除外。原因大概,近段時(shí)間都在搞(補(bǔ)習(xí))硬件(模電)方面的東西,不涉及軟件/逆向等。不過(guò)現(xiàn)在終于得住機(jī)會(huì),能夠有個(gè)擦邊內(nèi)容可以擬個(gè)帖子分享大家了。
最近新入手了個(gè)D87 RGB單模機(jī)械鍵盤,整體都不錯(cuò),奢華內(nèi)涵有檔次,就這。
以前用過(guò)的鍵盤不少,青軸60%、青軸104、靜電容108等,大多數(shù)沒(méi)有RGB燈,有燈的只有藍(lán)牙控制,臺(tái)式電腦也沒(méi)藍(lán)牙,用手機(jī)去控制也不方便,這就問(wèn)尷尬不尷尬。這次新鍵盤有比較完善的鍵盤驅(qū)動(dòng),可以設(shè)置鍵盤宏和燈效,軟件界面友好功能完善。只可惜燈效方面只能內(nèi)置(動(dòng)態(tài))和自定義靜態(tài)燈效。然后萌生出一個(gè)新奇的想法,能否讓鍵盤燈效玩貪吃蛇,像某賊船鍵盤一樣。但后來(lái)我放棄了,原因并不是不行,而是這燈廠太華麗了。
下面內(nèi)容由逆向分析展開(kāi),以及程序驗(yàn)證POC,最終寫(xiě)成一個(gè)完整的開(kāi)發(fā)框架。
[.USB協(xié)議逆向]
逆向,其實(shí)是挺有意思的東西,和推理一樣,把已知的線索都羅列出來(lái),推理是用時(shí)間線貫穿,逆向則是用邏輯貫穿。去除掉所有的干擾和不可能,剩下的無(wú)論怎么不可思議,他都是正確的結(jié)果。雖然會(huì)有彎路,但總是樂(lè)此不疲。
說(shuō)了這么多,只是要告訴大家,逆向分析都是會(huì)比較繞,有很多彎路,請(qǐng)耐心看完。
首先,安裝驅(qū)動(dòng)、打開(kāi)鍵盤設(shè)置軟件,燈效設(shè)置。使用USBlyzer進(jìn)行抓包。

設(shè)置第一個(gè)按鍵(ESC)為紅色,然后我們可以看到抓取到的USB數(shù)據(jù)如下圖

接著我們把顏色改成綠色,可以看到抓取的數(shù)據(jù)如下圖,看上去沒(méi)有加密,這是個(gè)好兆頭。

然后抓取第二個(gè)鍵F1,

發(fā)現(xiàn)這好像有空了3個(gè)字節(jié)

繼續(xù)驗(yàn)證后面的按鍵,可能鍵盤空的地方,其實(shí)是存在按鍵的?
經(jīng)過(guò)一系列的抓包,然后整理出來(lái)一些猜測(cè),比如每個(gè)按鍵的控制都是明碼,傳輸?shù)氖荝GB數(shù)據(jù)占用3字節(jié)。
每條報(bào)文(是這么叫的么?)頭部有12字節(jié)是協(xié)議頭或者命令,共計(jì)發(fā)送6條數(shù)據(jù)給鍵盤

分析之初其實(shí)還是有很多彎路的,這是我的筆記,避免把你們看的云里霧里的我就略過(guò)了,比如猜測(cè)RGB數(shù)據(jù)是RGB還是RGBA。
很多錯(cuò)誤的東西我就不提了,感興趣可以看下這個(gè)筆記的截圖
最終整理得到這樣的一組信息,后面還會(huì)介紹到
[.程序驗(yàn)證POC]
本來(lái)打算用VB6來(lái)寫(xiě)的,開(kāi)發(fā)速度快,賊好用。后來(lái)想想還是算了,QT來(lái)寫(xiě),使用C++開(kāi)發(fā)框架,這樣的話方便開(kāi)源大家一起來(lái)完善。而且還能移植到Linux等環(huán)境,底層USB庫(kù)使用libusb-1.0本身具備跨平臺(tái)性。
第0個(gè)簡(jiǎn)單的驗(yàn)證程序如圖,點(diǎn)亮所有LED,變幻顏色。驗(yàn)證失?。?/span>
鍵盤死了,USB?Bulk數(shù)據(jù)發(fā)送給鍵盤后貌似需要讀出返回的數(shù)據(jù),不然鍵盤會(huì)假死(可能真)狀態(tài)。
返回的數(shù)據(jù),明面上看的話可能是覆蓋燈效前的原始數(shù)據(jù),未具體研究和驗(yàn)證,因?yàn)閷?duì)我來(lái)說(shuō)用途不大。修正BUG后,接著驗(yàn)證。
如此低級(jí)錯(cuò)誤,就不補(bǔ)圖了,例子同下面,只是缺少發(fā)送后接收數(shù)據(jù)的代碼。
第1個(gè)簡(jiǎn)單的驗(yàn)證程序如圖,點(diǎn)亮所有LED,變幻顏色。驗(yàn)證成功!


第2個(gè)驗(yàn)證程序如圖,順序點(diǎn)亮所有的LED。驗(yàn)證失??!

失敗的主要原因,猜測(cè)可能存在空鍵位,當(dāng)順序點(diǎn)亮到空鍵位的時(shí)候,會(huì)出現(xiàn)IO錯(cuò)亂問(wèn)題

因?yàn)橐话沔I盤或者LED燈(無(wú)關(guān)共陰極、共陽(yáng)極),都采用矩陣結(jié)構(gòu),這樣可以減少M(fèi)CU?GPIO的使用。如果不使用矩陣結(jié)構(gòu)的話,87個(gè)RGB LED,需要261?GPIO來(lái)控制,這是相當(dāng)燒錢的(需要更高級(jí)的MCU或者更多MCU分工、或者使用到鎖存器)。
對(duì)協(xié)議分析,大致的能夠推測(cè)出空鍵位所在位置,然后對(duì)鍵位建立映射關(guān)系,實(shí)現(xiàn)一個(gè)完整的控制、開(kāi)發(fā)框架。經(jīng)過(guò)很漫長(zhǎng)的分析,最終結(jié)果就是上面一張圖說(shuō)明問(wèn)題。
[.完整開(kāi)發(fā)框架]
通過(guò)逆向和上面的驗(yàn)證,基本上了解到了幾個(gè)信息,USB協(xié)議共計(jì)發(fā)送數(shù)據(jù)6次,每次發(fā)送的是一行鍵位的RGB數(shù)據(jù),每個(gè)RGB以3字節(jié)存儲(chǔ)。鍵位有可能存在空位,也就是我們必須去除掉這些空位,并且提升實(shí)際對(duì)鍵盤燈效操作時(shí)的簡(jiǎn)潔度。所以我大致的把程序?qū)懗蛇@么幾層
TKbdObj 鍵盤類。繼承下面這些東西,改動(dòng)下面內(nèi)容可保持上層名稱統(tǒng)一。
TKeyMap 按鍵映射層。負(fù)責(zé)轉(zhuǎn)換鍵盤鍵值名稱到XY矩陣數(shù)據(jù),提供on/off和轉(zhuǎn)換方法。

TLEDS LED邏輯控制層。負(fù)責(zé)實(shí)際控制LED?XY矩陣數(shù)據(jù)邏輯,以及提供R、G、B->RGB的轉(zhuǎn)換方法和向下發(fā)送USB層功能。

TUSB USB驅(qū)動(dòng)層。負(fù)責(zé)主機(jī)->鍵盤底層協(xié)議交互。

介紹完框架結(jié)構(gòu)完了,給大家分享幾個(gè)簡(jiǎn)單的實(shí)例。因?yàn)閼?,所以沒(méi)有使用多線程或者Timer之類,QT里面的Timer需要代碼自己碼,相比VB6難用很多。
點(diǎn)亮鍵盤最右側(cè)按鍵,用于檢測(cè)KeyMap映射數(shù)據(jù)是否缺損

顯示I Love You,簡(jiǎn)單的字節(jié)數(shù)組顯示點(diǎn)亮鍵盤LED


掃描燈,看過(guò)霹靂游俠的應(yīng)該有記憶,童年經(jīng)典必須復(fù)刻一下

漸變點(diǎn)亮,簡(jiǎn)單的由暗到亮點(diǎn)亮

完整的效果如下,例子還有很多,感興趣可以自行下載源碼研究

程序需要QT Creator 4編譯,沒(méi)有包含QT庫(kù),無(wú)法直接運(yùn)行。
連接鍵盤時(shí)依賴 libusb-1.0 驅(qū)動(dòng),可以使用zadig來(lái)安裝,后期將會(huì)在github上發(fā)布更新目前沒(méi)上傳。論壇原文地址:https://www.52pojie.cn/thread-1455086-1-1.html