Created
February 2, 2025 10:08
-
-
Save ashquarky/ea277578e33053b7ddb3b8af25c149bb to your computer and use it in GitHub Desktop.
Brute-force the pairing code for a Wii U GamePad (using drc-sim/Vanilla compatible wifi chipsets)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# go get wpa_supplicant and wpa_cli from a Vanilla compile tree | |
# the wiiu will go out of pairing mode after a while and the brute will time out, update the starting code | |
# below, go back into pairing mode, and try again | |
# SPADE 0 | |
# HEART 1 | |
# DIMND 2 | |
# CLUB 3 | |
import time | |
import pexpect | |
wpa = pexpect.spawn( | |
"./wpa_cli", | |
["-p/var/run/wpa_supplicant_drc"], | |
) | |
wpa.expect("\r\n>") | |
def scan() -> list[(str, str)]: | |
print("Trying to start scan...") | |
wpa.sendline("SCAN") | |
if wpa.expect(["OK", "FAIL-"]) == 1: | |
return [] | |
print("Scan in progress...") | |
wpa.expect("<3>CTRL-EVENT-SCAN-RESULTS") | |
wpa.sendline("SCAN_RESULTS") | |
wpa.expect("bssid / frequency / signal level / flags / ssid\r\n") | |
aps = [] | |
line = wpa.readline().decode("utf-8").strip() | |
while not line.startswith(">"): | |
bits = line.split("\t") | |
if len(bits) == 5: | |
bssid, freq, signal, flag, ssid = bits | |
aps.append((bssid, ssid)) | |
line = wpa.readline().decode("utf-8").strip() | |
return aps | |
def base_n(num, b, numerals="0123456789abcdefghijklmnopqrstuvwxyz"): | |
return ((num == 0) and numerals[0]) or ( | |
base_n(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b] | |
) | |
def connect(bssid: str, pin: int) -> bool: | |
pin4 = int(base_n(pin, 4)) | |
print(f"Trying {pin4:04d}") | |
wpa.sendline(f"WPS_PIN {bssid} {pin4:04d}5678") | |
res = wpa.expect(["<3>WPS-CRED-RECEIVED", "<3>WPS-TIMEOUT", "<3>WPS-FAIL"]) | |
if res == 1: | |
print("WiiU went offline! Retrying") | |
return True | |
elif res == 2: | |
return False | |
print(f"PIN IS {pin4:04d} YAY") | |
exit(0) | |
def go(): | |
while True: | |
aps = scan() | |
wiius = [ap for ap in aps if ap[1].startswith("WiiU")] | |
if len(wiius) > 0: | |
bssid, ssid = wiius[0] | |
break | |
time.sleep(1) | |
print(f"Found {bssid} / {ssid}") | |
# put the pin here instead of "0" if you want to restart after a failure and keep progress | |
for pin in range(int("0000", base=4), int("3333", base=4)): | |
connect(bssid, pin) | |
print("Failed to find pin!") | |
wpa.interact() | |
go() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have been informed the PIN code is derived from the MAC address of the console, which is in the SSID https://github.com/GaryOderNichts/recovery_menu/blob/837690bc1e54ec28b13933ba808bcce51ead9dfc/ios_mcp/source/ccr.c#L119-L132
This code is therefore pointless but I will leave it as testament to what a bad idea, python, and an afternoon can get you