逆向分析智能窗帘頻射協議
近來我熱衷於對家庭自動化設備的破解,然後將它們添加到我的Homekit集成包之中。這事情要從幾個月前說起,當時我爸訂購了大批量的
RAEX 433MHz射頻電動窗帘,以替代老式的手動式窗帘。
注意:你可以在Spotlight網店搜索Motion Motorised Roller Blind找到該窗帘。
我對這個電動窗帘非常滿意,有了它我就不用跑上跑下的去打開/關閉窗戶,可是為了控制它們,你需要購買RAEX的遙控器。RAEX有許多不同類型的遙控器產品,其中我選擇購買了以下兩種遙控器:
R 型遙控器 (YRL2016)
X 型遙控器 (YR3144)
給每間房都裝上一個遙控器是不現實的,相反數個房間可以使用同一個遙控器倒還挺實在的。然而也正是因此,遙控器的局限性也就體現出來了。
另外的備選方案則是使用一塊被稱為RM Pro的硬體,通過使用他們的應用程序進行遠程控制。
於我而言該App卡頓,bug又多,不太適合用於家庭自動化生態系統。我希望電動窗帘可以通過Apple Homekit進行行為。
為了控制這些窗帘,我知道我需要達成以下條件中的一個:
逆向App中RM Pro與轉子直接的通信協議
逆向遙控器中用於與窗帘通信的射頻協議
嘗試第一個條件,發現無法攔截iPhone與集線器之間的通信流量。所以給我的選擇只有逆向射頻協議咯。
在Ebay上購置了一對433MHz的Arduino發射器/接收器。如果鏈接失效你可以在Ebay上搜索433Mhz RF transmitter receiver link kit
初步研究
通過谷歌搜索,沒有獲取到許多RAEX所使用協議的相關技術說明的結果:
通過FCC或專利查詢未能找到協議的技術說明
向RM Pro官方發送電子郵件尋求技術說明文檔,然而他們沒能理解我的意思
向RAEX官方發送電子郵件尋求技術說明文檔,回應說他們因為保密協議不會提供給我
我發現RFXTRX能夠通過BlindsT4模式控制窗帘,該模式也適用於Outlook智能窗帘。
打開其中一個遙控器之後辨識其使用的微控制器,然而無法找到確定其用於解析的通用射頻編碼方案。
似乎可以通過遙控器上的I2C匯流排轉儲ROM晶元對該固件進行逆向分析
這與允許遙控器在引導後的任何時候進行轉儲有異曲同工之妙
數據捕獲
當數據包到達連接到Arduino的接收器,之後開始搜尋用於捕獲傳輸數據的Arduino sketches設計。雖然嘗試多次都失敗了,但功夫不負有心人最終找到了一個可能用的
確定理解這些知識點(1,2,3)然後看了一些射頻逆向分析的相關文章。其中大部分的想法都是通過接收器插入計算機的麥克風埠,使用Audacity來抓取信號。這個思路很不錯,就這麼搞!
捕獲到大量數據,其中有4種R型號遙控器數據,以及2種X型號遙控器數據。更有趣的是8種不同設備都與Broadlink RM Pro(B型號)配對成功。
至此,我確定了一些事情:
傳輸過程沒有滾動碼進行身份驗證,因此可以將捕獲的信號重放並使智能窗帘每次都重複該行為。如果無法逆向該協議,這將是最壞的情況。
傳輸至少重複3次(根據所使用的遙控器類型而有所不同)
縮放波形,我們可以看出所捕獲信息的不同之處。以下例子是捕獲到的配對行為:
放大:
在縮放圖像中,您可以看到傳輸以振蕩的0101 AGC模式開始,隨後是另一個雙寬度報頭模式,再然後是一個更長的數據頭模式,最後則是傳輸的數據。對於R型遙控器,報頭,數據頭及數據將重複3次(AGC模式僅在傳輸開始時發送一次),這可以在第一個圖像中看到。
僅觀察波形數據對我們幫助不會太多,我們將其數字化以分析其二進位,然後確定不同的遙控器,信道以及行為之間的關係。
波形解碼
我們需要確定波形是如何進行編碼的。這類硬體應用通常都使用以下編碼方式:
曼徹斯特編碼
三態/三位(Tri-State/Tri-bit)編碼(參考信息)
PWM編碼
RAW? high long = 11,high short = 1,low long = 00,low short = 0
參考一些資料後,確定其使用的編碼可能是曼徹斯特編碼。
將數據數字化
一開始我是以上面提到的RAW方案處理數據(即使我確認是曼徹斯特編碼)。這是因為如果碰巧不是曼徹斯特編碼,我可以用另一種方案來嘗試解碼。
我將每個捕獲數據都寫入Google電子表格。將每個信道中對應的行為寫入表格大概就花費了5分鐘,且一個遙控器就有6個信道。
當我搜集完2個遙控器的8個不同信道的所有行為就停了下來。這一下就拿到了32個捕捉數據,從這些數據推斷出RAW bits相關信息:
每個信道的位有些許變化
每個遙控器的位有些許變化
信道/遙控器/行為組合,有些位似乎會進行隨機性變化(這是某種校驗和?)
此外我需要一個腳本來處理我通過Audacity捕獲的WAV文件。我寫了一個腳本,用於檢測數據頭並提取等效於RAW編碼的數據(之前都是手工完成)。該腳本以JSON格式進行輸出,因此我可以添加額外的metadata,並用波形再次確認捕獲的數據:
[
{
"filename": "/Users/nickw/Dropbox/RF_Blinds/Export_Audio2/tracks2/R1_CH1.wav",
"captures": [
{
"data": "01100101100110011001100101101001011010010110011010011010101010101010101010011001101010101010101010101010101",
"header_pos": 15751,
"preamble_pos": 15071
},
{
"data": "01100101100110011001100101101001011010010110011010100110101010101001101010011001101010101010101010101010101",
"header_pos": 46307,
"preamble_pos": 45628
},
{
"data": "01100101100110011001100101101001011010010110011010010110101010101010011010011001101010101010101010101010101",
"header_pos": 73514,
"preamble_pos": 72836
},
{
"data": "01100101100110011001100101101001011010010110011010101010101010100101010101101001011010101010101010101010101",
"header_pos": 103575,
"preamble_pos": 102895
}
]
}
]
驗證完成後,將這些數據進行列表並將其插入電子表格進行後續處理。數據太多,不得不小心應對:
如果以曼徹斯特編碼進行解密那就最好了。為此我又寫了一個腳本,將捕獲到的RAW數據轉換成曼徹斯特編碼(或其他類型編碼)。將這些數據上傳到電子表格中,之後進行一系列分析
從這些數據中,可以立馬發現二進位位與其目的之間的一些聯繫:
信道(C)有6 bits
行為(A)有2 bits
用於校驗和的6 bits,似乎存在一個行為與信道之間的函數關係F(A, C)
當行為改變時會變化
當信道改變時會變化
由於沒有等效的信道,所以不能確定它們在遙控器中會發生改變
1 bit似乎是與行為相關的函數F(A)
1 bit似乎與函數F(A)相關,即G(F(A))。其取決於F(A)值,有時是1對1映射,有時是逆映射
經過進一步的檢測,我確定對於同一個遙控器和信道,每個不同的行為,F(A, C)函數的值將增加1(考慮高位優先)
同時對於相鄰信道,與C(信道)相關的位向上/向後計數(X型遙控器向上計數,R型遙控器向後計數)。注意C列,此外F(C)還會同時增加/減少。
至此我確定了F(A, C)與信道C之間的關係,例如F(A, C) = F(PAIR, C0) == F(PAIR, C1) ± 1。有了這個發現之後,我還確定了F(A, C)和行為A之間的數學關係。
獲取更多數據
從我們現在已經獲取到信息來看,似乎可以通過改變6位信道數據以及對應的校驗和,然後遵循上面發現的數學關係來創建一個新的遙控器。即我們可以從一個子母信道生成64個信道,這麼多信道已經足以控制房子里所有的智能窗帘。但是我真的想完全解碼校驗和欄位,以此生成一個幾乎無上限信道的遙控器。
我寫了一個工具輸出捕獲到的字幕信道:
./remote-gen generate 01000110110100100001010110111111111010101
...
我推斷後面生成的這些數據可以幫助我們確認校驗和的形成,當然這得我們在同一信道上去觀察不同的遙控器信息,即R0CH0,R1CH0,X1CH0,等…
從本質上來講我們要解決的就是有關函數G的方程式:
F(ACTION_PAIR, CH0) == G(F(ACTION_PAIR, CH0))
然而,查看所有信道0的配對行為捕獲,校驗和似乎依舊混亂/隨機:
觀察數據的同時,另一種模式出現在我們視野中。G(F(A))與F(A)隔了一個完整的位元組偏移量(8 bits)F(A)。此外F(A, C)的前2 bits位於位元組邊界且與行為A對齊。隨著行動A的增加,F(A, C)也增加。
我們需要確認一些基於前4個位元組產生已知校驗和的函數。在開頭我嘗試在位元組上進行XOR操作:
不太成功,輸出似乎是隨機的,並且使用校驗和進行XOR輸出沒有產生常數鍵。因此,我推斷校驗和不是通過XOR生成的。會不會是數學上的加法呢?我們已經看到前文提到的加法/減法關係。
對於同類型遙控器的不同信道,其中存在一個定量差異。或許是程序有BUG,所以不同類型的遙控器直接那個定值有所不同嗎?在校驗和或者信道改變時,我們或許沒有正確封裝bits數量或使用了錯誤的位元組邊界?
解決校驗和
查看原始捕獲信息,並執行相同的模增加,我們確定校驗和是通過4個主要位元組和按模增加3來計算的。不同於RAEX想要使其解碼的校驗和更加困難或者說是確保一個恰當的傳輸模式,我不知道這裡為什麼要增加3
我重構了應用程序以處理剛剛識別的邊界:
type RemoteCode struct {
LeadingBit uint // Single bit
Channel uint8
Remote uint16
Action uint8
Checksum uint8
}
事實證明,F(A)不是與行動A相關的函數,它實際上是被傳輸的行為數據的一部分:
type BlindAction struct {
Name string
Value uint8
}
var validActions = []BlindAction{
BlindAction{Value: 127, Name: "PAIR"},
BlindAction{Value: 252, Name: "DOWN"},
BlindAction{Value: 253, Name: "STOP"},
BlindAction{Value: 254, Name: "UP"},
}
此外,信道和遙控器之間的聯繫也許並沒有那麼重要。它可能就是一個任意的24位整數,不管怎樣它更容易被拆分為一個8位整型數據和一個16位整型數據。總算可以寫校驗和函數了:
func (r *RemoteCode) GuessChecksum() uint8 {
return r.Channel + r.Remote.GetHigh() + r.Remote.GetLow() + r.Action.Value + 3
}
附加工具
remote-gen程序本就是用於生成子母遙控器代碼(儘管出現了封裝問題),我們現在再添加一些其他功能,讓其更強大。
我需要一種從捕獲數據中提取信息,然後驗證其校驗和是否與我們生成的校驗和規則集一致:
./remote-gen info 00010001110001001101010111011111101010100 --validate
Channel: 196
Remote: 54673
Action: STOP
Checksum: 42
Guessed Checksum: 42
如果兩個校驗和不相同,則運行—validate就會出現錯誤。添加的另一個功能則是能夠生成任意代碼以創建屬於我們自己的遙控器:
./remote-gen create --channel=196 --remote=54654 --verbose
00010001101111110101010111111111010011001 Action: PAIR
00010001101111110101010110011111101101000 Action: DOWN
00010001101111110101010111011111111101000 Action: STOP
00010001101111110101010110111111100011000 Action: UP
你可以通過nickw444/homekit/blindkit查看項目所有的資源
全文終!
*參考來源:nickwhyte,freebuf小編鳶尾編譯,轉載請註明來自FreeBuf.com
※反擊「貓眼電影」網站的反爬蟲策略
※國外研究員主題演講:某中國公司仍在大量收集Android手機簡訊、聯繫人等信息
※【BlackHat 2017】美國黑客大會首日議題匯總,演講PPT下載也在這裡
※【信息安全有獎問卷】最後的機會!截至7月底,聽到您的聲音!
※基於Tor的通訊軟體Briar:斷網也能用的通信軟體
TAG:FreeBuf |