本文以打開無線控制的電動車庫卷簾門為目标,深入研究了ASK/OOK的編/解碼,并用樹莓派+五元錢的ASK/OOK 發射子產品
背景
車庫裝了電動卷簾門,為了了解其安全性,也是為了能自主要制,研究了下其遙控原理。其實在這個過程中,我測試了家裡幾乎所有的無電線遙控器,包括電動窗簾、投影幕布、電動衣架、車鑰匙。除了車鑰匙,其它都是類似的,即ASK/OOK編碼。
ASK,簡單的了解,就是調幅,用不同的幅度來代表不同的資訊。OOK是ASK的特例,因為隻有0和1要表示,可以用有載波來代表1,無載波來代表0。但實際上并不是這麼直接,通常會加上脈寬調制(PWM)以提高抗幹擾能力。
用HackRF确定可行性
據說有的車庫門是滾動碼的(編碼是變化的),我們可以先用HackRF做個簡單的重播攻擊測試。
錄制2秒的信号并重放:
部分運作提示:
<a></a>
實測用錄制的信号是可以控制的(如果不行,注意調整HackRF放大器的增益)。但這個沒多大技術含量,而且成本高,資料量也大。我們的目标是解碼後再重新編碼/重放。
用GNU Radio錄制信号
用GNU Radio搭一個簡單的接收框圖,一方面将接收信号儲存到檔案,另一方面将信号以瀑布圖顯示作為實時回報。因為遙控信号是433.92MHz,中心頻率設在這個附近都可以;采樣率2M就夠了。
<a href="http://images2017.cnblogs.com/blog/640760/201709/640760-20170911143407391-1546693105.png" target="_blank"></a>
圖1:gnuradio-companion 連接配接框圖
下圖是運作時的瀑布圖,其中按了5次遙控器。
<a href="http://images2017.cnblogs.com/blog/640760/201709/640760-20170911143455141-1599259738.png" target="_blank"></a>
圖2:gnuradio-companion 運作時的瀑布圖
用 Inspectrum 手動解碼
用apt-get安裝inspectrum,或下載下傳最新的Inspectrum代碼,按照文檔自行編譯。試過Debian和Mac下都沒問題(Mac下用MacPorts要安裝一堆依賴)。編譯就不多說了,下面是解碼的主要步驟:
1. 用Inspectrum打開前面錄制的檔案,設定采樣率為錄制時的采樣率(2M); 2. 水準拖動,找到有信号的區域; 3. 在原始信号上右鍵,Add derived plot => Add sample plot; 4. 此時原始信号上會出現兩條水準線,用滑鼠拖動,調節中心頻率的位置和寬度; 5. 在原始信号上右鍵,Add derived plot => Add amplitude plot; 6. 在Amplitude plot上右鍵,Add derived plot => Add threshold plot; 7. 勾選”Enable cursors”,此時會出現兩條豎線; 8. Zoom放大信号圖,移動兩條豎線,使其寬度包含一個符号。注意跳過前導的高低電平(start1, start0)。資料通常是脈寬編碼的,一對高低電平的組合代表一個bit:高電平較寬的代表1,低電平較寬的代表0。從圖中應該能看出這個規律。 9. 改變符号數,使其包含整個信号區域(圖中是65個符号,這相當于完整的key),并調節首尾對齊(結束時通常有較長的低電平),這時可以得到符号的速率,即波特率(對OOK,其實等同于比特率)。

圖3:用Inspectrum解碼的步驟
最後,在Amplitude plot或Threshold plot上分别點右鍵,Extract symbols (to stdout),可以得到解碼的資料。其中前者相當于模拟信号,簡單了解:正數代表1,負數代表0;後者才是我們想要的bit流。
圖4:用Inspectrum解碼的結果
為确認解碼正确,可以再選一段信号區域,做同樣的操作,看結果是否一緻。畢竟ASK抗幹擾不強,有時候可能會差一兩個bit。通常,按一下遙控器,同樣的資料會重複發送幾次。
遙控信号編碼分析
根據前面的解碼,以及對更多遙控器的分析,可以歸納出一個模型。一個ASK信号包含如下部分(參數):
start1: 起始的高電平時間長度; start0: 起始的低電平時間長度; stop0: 結束的低電平時間長度; period: 每個bit的周期,在PWM編碼中,每個bit都對應一對高/低電平,而且總是先高後低; duty: 占空比,比如占空比是75%,則意味着一個周期内如果75%左右是高電平,則代表1; 而75%左右是低電平則代表0; bits: 實際的bit流。
這裡的占空比肯定是大于50%的,通常在75%左右比較合适,這樣既能拉開(每個周期内)兩種電平的比例差,減少接收端的誤判;又能保證接收時能采樣到兩種電平,也是為了減少誤碼。試想對于99%的占空比,1%周期的電平很可能被接收端采樣不到,導緻采樣到199%(甚至更長)周期的同一種電平,這樣解碼時就會出錯。
發射子產品
最初,我是想用GNU Radio做ASK/OOK編碼并發射的。萬能的HackRF和SDR按說能搞定這個小Case。
研究了下,發現這并不是一件容易的事。需要使用很多的子產品。這也許是一個很好的GNU Radio的練習題。但我還是先看下有沒有更簡單的辦法。
這個子產品很簡單,就是把輸入的信号以433/315M的載波調制/發射出去。DATA為高電平,就按高電平調幅輸出(請注意,這裡調制的是電平,并不是資料。也就是說,資料”1″對應多長時間的高電平,多長時間的低電平,這個子產品都不管的——這些是編碼子產品要處理的事)。
圖5:ASK/OOK 發射子產品
用Python編碼
為了代碼的子產品化,也是為了減少發射時的計算量,我們采取先編碼再發送的方案。根據前面建立的ASK信号的模型,将這個信号編碼為高低電平交替的波形,并用一個數組表示,數組中每個元素存儲高低電平切換時對應的時間戳。波形總是以高電平開始。
起始/結束電平的時長、占空比這些參數理論上并不需要嚴格準确,但這取決于接收端的寬容度,是以我們還是盡量忠實于原信号。
下面是核心的代碼片斷,其中ts是時間戳數組。
用樹莓派發送
發送工作就很簡單了:将發射子產品的DATA腳與樹莓派的某個GPIO相連,電源也直接用樹莓派的;
圖6:樹莓派與發射子產品
然後根據時間戳交替翻轉對應的GPIO就行了。
用sleep控制時間盡管有一定誤差,腳本語言的運作也沒那麼快,但實測是夠用的。下圖是示波器上看到的DATA引腳的波形圖(兩個通道都連着DATA腳)。
圖7:樹莓派産生的待調制信号
為便于觀察,我将編碼周期設定為1ms,和示波器界面的1ms/div對應。圖中測量的間距是2.78ms(預期是2.75ms),偏差是可接受的。
多種姿勢打開車庫門
把發射的裝置放在車庫内,并連上網絡,就可以無需鑰匙自主要制車庫門的開/關了。
手機開關門
不需要自己寫App,用ssh終端密鑰登入并執行指令,就可以手機一鍵開/關門了,并且可以遠端控制。
圖8:手機上用ssh開關車庫門
自動開關門
以指定手機作為鑰匙,當持手機靠近車庫時(其實是連上車庫WiFi後),就自動開門。大緻流程是:
遠端執行路由器的 iwinfo 指令(如下)檢測連接配接在上面的裝置;
如果作為鑰匙的手機的MAC在清單裡,并且信号強度(SNR)超過設定值,就計為一個有效的連接配接。當連接配接數從0變為非0時,就自動開門。
如果鑰匙手機的有效連接配接數降到0, 就自動關門。
自動關門的好處是可以防止人走了忘了關門(俺家真的發生過)。
芝麻開門
理論上可以做到,但需要可靠的聲紋識别。這個就算了。。
鎖死車庫門
把發射子產品對應的GPIO設為高電平,由于發射子產品信号強,距離近,接收端收到的總是1,導緻用真的鑰匙也開不了門。
結語
不用滾動碼編碼的車庫門其實是毫無安全性可言的。不管是簡單的原始信号重放、還是解碼後再編碼的重放都比較容易實作。但我們可以利用這種不安全為自己提供便利,更靈活地自主開/關門。另外,用發射子產品發射高電平可以幹擾鑰匙的信号達到鎖死車庫門的效果。
但如果不是通過監聽鑰匙的信号,用暴力破解Key也并不是那麼容易的。因為ASK編碼除了需要資料吻合,載波頻率相同,還需要資料編碼速率,甚至起止電平的時長都要一緻。
用廉價的硬體發射子產品配合樹莓派(或單片機)可以低成本地編碼/發射ASK/OOK信号,簡單易行。而HackRF加Inspectrum解碼僅适合實驗和調試用,實用價值不高。後續将會嘗試ASK/OOK的自動解碼。
本文轉自 K1two2 部落格園部落格,原文連結:http://www.cnblogs.com/k1two2/p/7504942.html ,如需轉載請自行聯系原作者