Archive for November, 2006

Wiimote Hacking: Dancing LEDs

Sunday, November 26th, 2006

Thanks to the impressive work by Andy over at WiiLi, I’ve been able to make my Wiimote actually do something:

http://www.wiive.net/Wiimote_LED.avi (6.5 MB)

There is a lot of work to do to make this easier in Linux, and so far I’ve given up on OS X. But I can now access Bluetooth devices directly in Parallels with a nice hack I found in the Parallels forums. Check out my post here explaining what to do.

Wiimote Hacking: Barking up the wrong PIN

Saturday, November 25th, 2006

I’m happy (though slightly contrite) to report that some of my previous posts have been totally misguided. While a nice motivation to immerse myself in the Bluetooth documentation, I have since learned at the WiiLi wiki that the Wiimote is in fact a normal HID device that requires no authentication at all.

I discovered that page on the Wiimote while booted into the most excellent Mactel Linux Live CD (based off a dev version of Ubuntu). I was finally able to diddle around with the bluez-utils and got no further than I did in OS X until I ran the magic hidd --search command. This discovered the Wiimote while it was in sync mode, and suddenly I had some communication. The Wiimote now stayed in the state with all four player LEDs blinking indefinitely. Pressing buttons (and the D-pad) now resulted in actual packets, which I could see with hcidump. The power button is special, and did not appear to send a standard packet, though I didn’t investigate that much. Shaking the remote and aiming the IR sensor at light bulbs did not generate any packets, so those features (along with the speaker) must require some sort of query by the host. I was just about to run some test code using libhid to see if I could read the events out of the HID interface, when the bluetooth driver fell over somehow and I could no longer see the local Bluetooth device.

After the reboot, I’ve been trying to understand why I cannot get a similar response from the Bluetooth drivers in OS X. The only possible initial steps seem to be:

  1. Open System Preferences
  2. Select Bluetooth
  3. Click Devices tab and and Setup New Device button
  4. Pick Any Device option and click Continue
  5. Click Passkey Options button and select “Do not use a passkey with this device”.
  6. Press 1 and 2 button on Wiimote
  7. Nintendo RVL-CNT-01 shows up in Device listing. Double click to select and continue.
  8. There is a short pause while information is gathered about the device.
  9. Click Continue.
  10. You are told “Congratulations! Your computer is now setup to use your Bluetooth device.”

But then when you Quit the Setup Assistant, you see no devices in the list. I interpreted this to mean the device really was not setup and I should investigate the other options. After playing with Linux, though, it looks more like the problem is that the HID Manager was not activated while the Wiimote was in discoverable mode. In Linux, you activate it with the hidd command, but I can’t see what the equivalent is for OS X.

Once I can figure out how to do that, the Wiimote should also lock on like it did in Linux, and I can finally start doing something interesting with this hardware.

It’s good to know that Nintendo did not go all crazy with the Wiimote communication and actually followed several standards (even if I was too paranoid to notice).

Wiimote Hacking: Is a PIN even needed?

Saturday, November 25th, 2006

While scanning the web for new Wiimote hacking information, I found this post about a guy who claims to have paired his Wiimote with his Windows desktop:

Gamer discovery: Wiimote to PC pairing

From the looks of it, no PIN was used at all. This is not at all what I observed when testing with the OS X Bluetooth Setup Assistant. Although, I can’t tell if Windows uses an empty PIN or skips the PIN entirely (still don’t know what that means precisely). If I try the “skip the PIN” method, I get a success message from the Setup Assistant, but nothing is shown in the list of connected Bluetooth devices. Perhaps I should investigate that more, however.

Based upon the Windows reports, the Wiimote does not appear to send packets like a standard keyboard or mouse device, which is not surprising. However, with any working connection, it should be possible to start dumping packets and reverse engineering the data format.

Wiimote Hacking: Brute Force Method #1

Saturday, November 25th, 2006

(Update: While entertaining, this entire exercise was unnecessary. See this post for more information.)

With only a Wiimote and no Wii, I am pretty much consigned to exploring brute force PIN discovery methods, assuming that the Wiimote will pair with any device if presented with the right PIN.

As I learned earlier, the host computer can tell if the PIN is incorrect, so an easy brute force method is to simply try many PINs. To pull this off, you need to be able to initiate pairing with a fixed PIN in a programmatic way (i.e. I don’t have to sit here and click 1000 times), and you need a way to keep the Wiimote in discoverable mode. Normally, the Wiimote immediately leaves discoverable mode when pairing fails. For a while I though it would be necessary to construct some sort of mechanism to keep activating the sync button over and over again. Just holding down the sync button does not work, so I started constructing a really hilarious looking contraption to push the sync button every 5 seconds using an oscillating table fan, a pen, and some wire twist-ties. Thankfully while putting this Rube Goldberg machine together, I stumbled upon the 1-2 sync method (hold 1 and 2 buttons down at same time), which has the nice feature that constant button pressure keeps the remote in discoverable mode. With a big eraser and some velcro cable straps, I was able to keep the 1 and 2 buttons pressed indefinitely:
Wiimote in Permanent Sync Mode
The remaining issue was now software.

Initiating Pairing Programmatically

The only Bluetooth hardware I have is in my MacBook, so I am pretty much stuck using OS X to do my Bluetooth testing. Initially, I tried using the Apple C/ObjC Bluetooth framework, IOBluetooth, to run the pairing process automatically. It was not too hard with PyObjC to experiment with the framework in Python, but eventually I hit a wall. In typical Apple fashion, IOBluetooth provides an API which only exposes the functionality you “ought” to need, and hides the lower-level Bluetooth functions. There is in fact no way to pair a device programmatically, though a related framework, IOBluetoothUI, does give you a very easy way to pop up a pairing dialog for the user to click on. However, at that point, you might as well use the Bluetooth Setup Assistant directly.

GUI Scripting

Having gotten nowhere with the ObjC frameworks, I turned to the GUI scripting features which are enabled by Apple’s Universal Access API. By allowing software to interact directly with GUI objects, like buttons and text boxes, Apple created an interface for both accessibility software, like screen readers, and for GUI scripting tools. A relatively easy way to interact with the GUI is through AppleScript, perhaps the ugliest scripting language I have ever seen. The syntax of AppleScript appears to be an attempt to make programming look as much like English as possible. In practice, it seems to combine the needless verbosity of COBOL with the confusing implicitness of Perl. (However, until I learn how to do the same thing with Python and PyObjC, it is worth putting up with.) After several hours futzing around, and making good use of UIElementInspector to discover the hierarchy of GUI elements in the Bluetooth Setup Assistant Window, I was able to generate the following code:

set the log_filename to (((path to desktop folder) as text) & "PinScan.txt")

repeat with pin from 2100 to 2500
	copy pin as string to pin_str

	tell application "System Events"
		tell application process "Bluetooth Setup Assistant"
			tell group 1 of window "Bluetooth Setup Assistant"
				set value of text field 1 to pin_str
			end tell
			click button "Continue" of window "Bluetooth Setup Assistant"
			delay 4
			tell group 1 of window "Bluetooth Setup Assistant"
				get value of static text 3
				copy result to outcome
			end tell

			click button "Go Back" of window "Bluetooth Setup Assistant"
		end tell
	end tell

	set the log_file to open for access file log_filename with write permission
	write pin_str & "
" & outcome & "
" as «class utf8» to the log_file starting at eof
	close access the log_file
end repeat

(Incidentally, I don’t even know how to type the symbols around “class utf8″. I cut and paste that entire word from a webpage directly into Script Editor.)

The repeat line is where I set the range of of PINs to test (in this case 2100 to 2500), and I have to manually get the Bluetooth Setup Assistant to the PIN input window:
PIN Input Window
And then start the script going. The 4 second pause is long enough to allow the pairing to fail if the Wiimote is already in discoverable mode. If the Wiimote has fallen out of discoverable mode, it can take the computer up to 15 seconds to fail. As it happens then, the short delay is a good failsafe to ensure the script will fail if for whatever reason the Wiimote stops being discoverable. That is preferable to having a bunch of trial PINs show up as no good when in fact the Wiimote was just off at the time.

The output of the script is a file which will contain lines like:

2100
The pairing attempt was unsuccessful. Make sure you are entering the proper passkey on your device, as displayed above. When ready, click Continue to try again.
2101
The pairing attempt was unsuccessful. Make sure you are entering the proper passkey on your device, as displayed above. When ready, click Continue to try again.
2102
The pairing attempt was unsuccessful. Make sure you are entering the proper passkey on your device, as displayed above. When ready, click Continue to try again.
2103
The pairing attempt was unsuccessful. Make sure you are entering the proper passkey on your device, as displayed above. When ready, click Continue to try again.

If the pairing were to be successful, then either the text will be different, or the script itself will bomb out since the text element it attempts to read might not even be present. In either case, it is easy to figure out which number succeeded and retry it manually to verify.

This GUI-based pin method can try 1000 PINs in a little under 2 hours. If Nintendo only used a 4-digit PIN, then it is quite feasible to find it this way in less than a day. A 5-digit PIN can be found in a week (stock up on AA batteries!), and I would regard a 6-digit PIN as impossible to discover with this method. I have found you can only run this script while not using the computer for anything else, so it will take me 2 runs overnight to finish testing all the 4 digit PINs, at which point I’ll be sure to report any successes.

Assuming the PIN is not found this way, then we will have to move to a more sophisticated technique, such as the method outlined by Shaked and Wool. Their technique requires recording the packet exchange during a successful pairing (like with a Wii) and then brute-forcing the PIN mathematically. Their performance numbers show that a 7 digit PIN can be found in 40 minutes using a Pentium III 450 MHz with no algorithmic optimization. By being clever about the calculation, they were able to get a factor of 10 improvement in speed on the same hardware, and moving to a more modern Pentium IV 3.2 GHz gets you another factor of 4. If we then throw the problem at a cluster of 5 CPUs, it would be feasible to extract an 11 digit PIN in about a week. Unfortunately, that’s only 36 of the 128 possible PIN bits, so if Nintendo used all possible bits, we would still be out of luck using a brute-force method.

For now, I’ll have to be content with the GUI method, and wait to get a hold of a Wii to start investigating the packet structure.

Wiimote Hacking: Plan of Attack

Saturday, November 25th, 2006

(Update: Totally missed the boat on this one. See this post for more information.)

In the previous post, I discovered that none of the easy options for pairing the Wiimote with a computer will work. Now we need to stop and review what we know:

  • The Wiimote so far appears to be a standard Bluetooth device.
  • The Wiimote and the Wii can be paired by pressing nothing more than the sync button on both devices.
  • Empty PIN, no PIN, and obvious 4-digit fixed pins (0000, 1111, 1234, 8888) also do not work.

Based on this we can guess at a few scenarios:

  1. The Wiimote does use a fixed PIN, but it is some difficult to guess number, either randomly chosen or selected to have some significance to a Nintendo engineer.
  2. The Wiimote may or may not use a fixed PIN, but has been designed to only pair with a device that “looks like” a Wii. Before pairing, it is possible for both devices to get the name and service description of the device at the other end. So it is possible that if a device does not report itself to be a Wii with specific services, the Wiimote will refuse to pair, no matter what PIN is used.
  3. The Wiimote generates the link key with the Wii in some custom way that we cannot easily duplicate with standard Bluetooth drivers.

These scenarios are listed in ascending levels of hopelessness. Even gathering information about scenario 2 and 3 will require me to get near a Wii base unit to observe how it interacts with the controller. Since that is not possible for now, I will focus on scenario 1.

Of course, scenario 1 is not necessarily easy either. While traditionally devices only use 4-decimal digit PINs, a Bluetooth PIN can be anywhere from 8 to 128 bits in length (3 to 39 decimal digits). With a hardcoded PIN on controller and base, Nintendo would not have much reason to limit itself to the traditional 4 digit PIN and could easily use all 128 bits if they wanted. All of the Bluetooth PIN attack methods I can find or imagine are variants of a brute force attack, which becomes effectively impossible if Nintendo used anywhere near the maximum number of bits in the PIN.

Without any evidence of Nintendo’s paranoia level, we can only barge ahead and try the easy things first, and hope we get lucky.

Entries (RSS)