UT181A是優(yōu)利德門下旗艦級手持數(shù)字萬用表辉词,主打數(shù)據(jù)記錄(Data Logging)功能禽绪,支持USB聯(lián)機通訊÷乱蓿基本評測可以看我前面發(fā)的文章旧困。前文說到,其官方或第三方軟件功能有限茫孔,缺少最重要的導(dǎo)出功能叮喳。另外,數(shù)據(jù)傳輸?shù)乃俣纫脖容^慢缰贝。
所以,欲對其協(xié)議進行分析畔濒,方便擴展剩晴、改進、和其它設(shè)備(比如樹莓派)連接、等等赞弥。
本文的破解/破譯方法及結(jié)論應(yīng)該適用于UT171系列毅整;UT71系列也可以參考。對破譯其它聯(lián)機通訊的設(shè)備也有借鑒意義绽左。
可行性分析
UT181A使用了Silicon Labs HID-to-UART接口模塊CP2110. 在操作系統(tǒng)里呈現(xiàn)為一個HID設(shè)備悼嫉,這樣的好處是不用裝驅(qū)動。既然它最終表現(xiàn)為UART協(xié)議拼窥,應(yīng)該比較容易重寫其通訊協(xié)議戏蔑。其實UT71系列也是類似的方案(HID轉(zhuǎn)UART),只不過用的南京沁恒的模塊鲁纠。
找了一個CP2110的代碼在Linux下試了下总棵,可以對UT181A進行基本的連接設(shè)置。但因為會話層的協(xié)議未知改含,所以嘗試讀寫操作時沒反應(yīng)情龄。
為了得到會話的詳情,最直接和萬能的辦法是用USB Sniffer捍壤。 試了一下Free USB Analyzer骤视,可以看到一些數(shù)據(jù),但不能解碼為UART層的數(shù)據(jù)鹃觉。從USB到HID专酗,再到UART,實際上是隔了兩層帜慢,需要層層剝殼笼裳,還是有點繁瑣。Free USB Analyzer的HID解碼粱玲,是解為鍵盤/鼠標(biāo)數(shù)據(jù)的躬柬;也許它的收費版可以解碼為UART。
不過我還有另一條完全不同的思路抽减,也許會更簡單允青。
API Hook
十幾年前,我用過這種方法對SCSI設(shè)備的通訊進行劫獲卵沉。這些設(shè)備的通訊軟件颠锉,通常會有一個通訊模塊(動態(tài)庫),提供諸如Send/Receive的API史汗。所以琼掠,只要自己寫一個提供同樣API的動態(tài)庫取代原有的動態(tài)庫,但在每個API的實現(xiàn)上停撞,還是轉(zhuǎn)到原動態(tài)庫上瓷蛙,就可以實現(xiàn)鉤子(Hook)的效果悼瓮。這樣截獲的數(shù)據(jù)塊是應(yīng)用層/會話層的,比數(shù)據(jù)鏈路層/驅(qū)動層的數(shù)據(jù)有更好的可讀性艰猬。同時横堡,還可以根據(jù)API的調(diào)用順序,得到和設(shè)備的交互流程冠桃,比如:初始化時要進行哪些設(shè)置命贴,通訊參數(shù),等等食听。
查看UT181A軟件的目錄胸蛛,果然有兩個這樣的動態(tài)庫。用dumpbin /exports查看其API碳蛋,初步判斷應(yīng)該只要替換SLABHIDtoUART.dll 就可以了胚泌。
從版本信息上,可以看到這個動態(tài)庫來自Silicon Labs肃弟。到其網(wǎng)站上找到了CP2110/4 的SDK玷室,用SDK里的動態(tài)庫替換這兩個動態(tài)庫,64位版崩潰笤受,換32位版穷缤,果然可以運行。
其實優(yōu)利德使用的版本較老(2010年的1.4)箩兽,SDK里的版本是2017年的6.7津肛。其中,API數(shù)目由42增加到了58汗贫。不管怎樣身坐,能跑。這樣就容易開展下一步的工作了落包。
有了SDK就有了頭文件部蛇,有頭文件就可以寫出八股文一樣的代碼了。弄兩行腳本咐蝇,自動生成大部分苦力代碼涯鲁。。
很快有序,就有了一個“山寨”動態(tài)庫抹腿。
正版的要改名;山寨版要記住它名字旭寿【ǎ——活都找它干。
弄好了盅称,發(fā)現(xiàn)山寨版的比老正版的API都少了2個房蝉。能跑僚匆,就沒深究了微渠,畢竟優(yōu)利德的軟件不會用到所有API搭幻。
看看Log文件,API的調(diào)用一目了然逞盆。這樣檀蹋,我們就有了一個堅實的基礎(chǔ)。
CP211x SDK
發(fā)現(xiàn)CP211x的SDK里還提供了Linux版Library(-lslabhidtouart -lslabhiddevice)的源代碼及例子云芦。
這兩個Library和Windows的SLABHIDtoUART.dll俯逾,SLABHIDDevice.dll對應(yīng)。于是舅逸,重寫通訊協(xié)議就更容易了桌肴。對Makefile略做修改后,可以在Intel和ARM(樹莓派)架構(gòu)下編譯琉历、運行坠七。
直接用SDK里的例子做個測試,發(fā)出第一條命令”AB CD 04 00 05 01 0A 00”后旗笔,就可以源源不斷地收到數(shù)據(jù)了彪置。
后續(xù)的工作就是根據(jù)API Hook的Log,給UT181A發(fā)不同的命令蝇恶,研究其反應(yīng)拳魁,搜集更多的數(shù)據(jù),以便發(fā)現(xiàn)數(shù)據(jù)的模式(Pattern)撮弧。
協(xié)議解碼
起始碼潘懊、長度字
上圖中,通過觀察每個輸入/輸出的數(shù)據(jù)包贿衍,發(fā)現(xiàn)會間隔地出現(xiàn)”AB CD”授舟。用這兩個字節(jié)對包進行分隔后,數(shù)據(jù)看起來更有規(guī)律舌厨,然后可以看出接下來兩個字節(jié)應(yīng)該是包的長度岂却。長度可以和起始字起到相互驗證/確認的作用。
結(jié)束碼/檢驗字
對收到的數(shù)據(jù)包與其實際意義進行初步的對應(yīng)后裙椭,發(fā)現(xiàn)最后兩字節(jié)是多余的躏哩。推測應(yīng)該是校驗字。在CRC在線計算網(wǎng)站上對包中的數(shù)據(jù)做CRC計算揉燃,發(fā)現(xiàn)與任何一種CRC編碼都不能匹配扫尺。
其實,對收到的數(shù)據(jù)炊汤,可以忽略這個校驗碼正驻,因為USB協(xié)議保證了數(shù)據(jù)不會出錯弊攘,除非是軟件層發(fā)生了錯誤。但后來發(fā)現(xiàn)姑曙,對發(fā)送的命令襟交,也多了兩個字節(jié)。如果萬用表那端要對它收到的數(shù)據(jù)做校驗伤靠,主機端則必須生成校驗碼了捣域。
下圖的命令中,帶有參數(shù)宴合。9字節(jié)長的包中有一個參數(shù)焕梅,13字節(jié)長的包有2個參數(shù)。根據(jù)參數(shù)的變化卦洽,可以觀察出最后兩字節(jié)的變化規(guī)律贞言。觀察9字節(jié)長的包,發(fā)現(xiàn)最后兩字節(jié)是在參數(shù)上增加了0x11阀蒂,但這顯然不能解釋13字節(jié)長的包该窗。進一步的分析發(fā)現(xiàn),原來這個校驗就是最簡單的“校驗和”脂新,即把前面的所有字節(jié)(除起始碼”AB CD”外)相加挪捕。對于長達2258字節(jié)的包也是這樣,只不過高位溢出忽略争便。
浮點數(shù)的表示
理論上级零,測量值可以用整數(shù)或小數(shù)表示,小數(shù)又可以用定點或浮點滞乙。
可以用程控電源輸出不同的電壓來聯(lián)機測量奏纪,觀察數(shù)據(jù)的變化規(guī)律。當(dāng)然斩启,也可以直接猜一猜序调,反正就只有3種可能。下圖是一個例 子兔簇。
圖中標(biāo)示了27.0, 27.1, 27.2发绢。
不太像整型,直接拿浮點試一試垄琐。
運氣不錯边酒,就是普通的浮點。同時狸窘,可以看出墩朦,二進制的數(shù)據(jù)并不是萬用表或軟件界面上顯示的值,而是看起來有著“更高精度”的原始數(shù)據(jù)翻擒。當(dāng)然氓涣,這個“更高精度”應(yīng)該是無意義的牛哺。事實上,每個數(shù)值后面還有一個字節(jié)(10/20/30)劳吠,應(yīng)該是用于描述其精度(有效位)的引润。
日期/時間的表示
最后剩下的,也是最難的赴背,就是日期時間了椰拒。時間戳也是增加UT181A價值的地方。像UT71D雖然也記錄數(shù)據(jù)凰荚,但測量值沒有時間戳,只有序號褒脯。
抓取采樣數(shù)據(jù)進行分析便瑟,每個數(shù)據(jù)包最大是2258字節(jié),250個采樣番川,所以每個采樣用了9個字節(jié):4字節(jié)浮點值到涂,1字節(jié)描述精度,還有4字節(jié)就是時間了颁督。是的践啄,只有4字節(jié),用來表示年/月/日/時/分/秒沉御∮旆恚——夠嗎?
在采集的數(shù)據(jù)中吠裆,每個采樣對應(yīng)于什么時間是已知的伐谈。取一段連續(xù)的采樣數(shù)據(jù),觀察其變化規(guī)律试疙。尤其是分鐘诵棵,小時,日期和月份發(fā)生變化時祝旷,看數(shù)據(jù)如何變化履澳。如下圖。
理論上怀跛,這種時間的表示可以用一個整型距贷,像Unix時間戳那樣。但分析上面的變化規(guī)律敌完,看起來像是位域表示法储耐。據(jù)此推演,結(jié)果如下滨溉。
由于年份使用的6 bit什湘,需要固定加上2000长赞。所以,這意味著UT181A只能用到2063年(的最后一天)闽撤。當(dāng)然得哆,這總比用Unix時間戳編碼要好一點,因為后者只能用到2038年哟旗。
傳輸速度
非常遺憾贩据,波特率只能設(shè)置為9600。通過API調(diào)用闸餐,設(shè)置更高的波特率是成功的饱亮。但傳輸中得到的數(shù)據(jù)是亂的。
在樹莓派上測試傳輸133685個采樣舍沙,耗時1401秒近上,傳輸速度為95.42采樣/秒。這與PC上的速度(自己寫的代碼或官方軟件)是一致的拂铡。
樹莓派
在Debian系的Linux上(Ubuntu或樹莓派)壹无,CP2110都被識別為HID設(shè)備,不需要安裝驅(qū)動即可使用感帅。而且斗锭,樹莓派的ARM和Intel都是小字節(jié)序,所以不用改代碼失球,重新編譯一下就可以運行岖是。
下圖是在樹莓派上(遠程)編譯、運行她倘。
上一張和樹莓派的合影璧微。
2063年測試
在2016年2月12日,據(jù)披露硬梁,如果把蘋果iPhone前硫、iPad等設(shè)備的系統(tǒng)時間設(shè)置為1970年1月1日,隨后重啟設(shè)備荧止,它會直接變磚屹电。
心懷忐忑與好奇,我決定確認一下2063年12月31日的問題跃巡,于是準(zhǔn)備把時間設(shè)置到那天的最后一分鐘危号。
但優(yōu)利德的工程師似乎看穿了我的心思:時間只能設(shè)置到2060年!
等了1分鐘后素邪,時間變成了2061年外莲。
但,如果我想看它出洋相,需要等上3年偷线!——太狡猾了磨确!
結(jié)語
通過API Hook的手段,在Windows上截獲了 CP2110的通訊詳情声邦,破譯了UT181A命令和數(shù)據(jù)的編碼方式乏奥,重寫了主要的會話過程,實現(xiàn)了:實時聯(lián)機采集數(shù)據(jù)亥曹、傳輸離線采集的數(shù)據(jù)并保存為CSV的功能邓了。代碼可以在Linux PC和樹莓派上運行(理論上,也可以移植到Windows上)媳瞪。
受硬件限制骗炉,不能設(shè)置非9600的波特率,所以不能提高傳輸速度材失。
“致命缺陷”是:由于時間的編碼方式痕鳍, UT181A只能使用到2063年。
參考
- UT181A的基本評測
- 一個Free的USB Sniffer軟件: Free USB Analyzer
- ut71dmm龙巨,針對UT71C開發(fā),但我在Ubuntu和樹莓派上試過熊响,UT71D和UT181A都用不了旨别。
- CP211x SDK, 選CP2110/4 Software package for Windows, 6.7.4
- CP2110 API文檔
- 在線CRC計算
- 蘋果確認iPhone/iPad時間設(shè)置不對會變磚