Page 1 of 1

DS/Wii Communication Reverse Engineering

Posted: Fri Jun 27, 2025 12:09 am
by hatkirby
Okay so this is a Gen 4 Pokemon thing but it's way more insane and I think it should be a separate thread. Basically I am interested in reverse engineering the method by which the Wii and the DS communicate when connecting a Gen 4 game to My Pokemon Ranch. It'd be useful because it'd be a way to wirelessly transmit information about the Pokemon on your cartridge. And since this is something that is not documented yet, it'd be a good idea to write down what I discover as it happens.

The first step was putting my laptop's wireless card into monitor mode and sniffing packets with Wireshark. This was harder than expected, but eventually I figured out I had to disable Ubuntu's NetworkManager so that I could control what frequency the card was listening on. My Wii and DS seem to be communicating on channel 7, but GBATEK says that it randomly chooses 1, 7, or 11, so that might come up later.

After I clicked CONNECT TO DS in My Pokemon Ranch, the Wii started transmitting a bunch of beacon frames (broadcast messages intended to make devices aware of the existence of an access point; in NiFi, the host in a connection pretty much is an access point that the other device is associating with). The important part of the frame (besides the transmitter's MAC address) is a vendor specific tag (tag ID: 221) with the OUI 00:09:BF. This is Nintendo's vendor ID and this tag is where they transmit their special data.

The tag value in all of these frames is 136 bytes long. Each one starts with the OUI, then 00:FF:FF, and then what appears to be two random bytes. I haven't yet figured out if those bytes mean anything. Then, the rest of the bytes in the tag is some kind of data payload. I observed 10* different payloads, broadcast cyclically in the same order. My methodology was to capture ~100 packets, isolate this tag value, remove the first eight bytes to eliminate the random part, and then sort/uniq.

Again, I'm not yet sure what the data in these tags mean yet, nor how they are processed by the DS. But it seems reasonable to guess that if I wanted to spoof a Wii running My Pokemon Ranch, I could broadcast beacon frames with properly crafted 802.11 headers and just loop through the 10 payloads I isolated. Hopefully what that would do is cause the CONNECT TO WII option to appear on the main menu of the Gen 4 DS games. I don't even really need to know Why these payloads do that, as long as they Do do that.

Here are the 10 payloads (no 802.11 frame, and the first eight bytes are dropped):

Payload 1

Code: Select all

010001088602400069367001f0010800    ......@.i6p.....
86024000000000009ffc00096200586f    ..@.........b.Xo
20496255c461466eeb7ea418ac009e01     IbU.aFn.~......
ff7b8c31fa00b7000000000000001011    .{.1............
11111111111111222222112222321122    .......""".""2."
22331122324311223344113243541111    "3."2C."3D.2CT..
11111111111122333333334344444344    ......"3333CDDCD
555544556166556166666466c7881111    UUDUafUaffdf....
Payload 2

Code: Select all

010001088602400069367001f0010800    ......@.i6p.....
86024000000000019375010962001111    ..@......u..b...
11111111333333224444343355554434    ....333"DD43UUD4
6616554466661655887c664611111101    f.UDff.U.|fF....
11111111222222112322221133222211    ....""".#"".3"".
34232211443322114534231111324345    4#".D3".E4#..2CE
11324465113354611143546611431576    .2De.3Ta.CTf.C.v
114365c6114365861143656666878888    .Ce..Ce..Ceff...
Payload 3

Code: Select all

010001088602400069367001f0010800    ......@.i6p.....
8602400000000002607202096200b688    ..@.....`r..b...
8888878888888888b86788886b6688b8    .........g..kf..
660a8878a69966660699888878668888    f..x..ff....xf..
886b88888878768b888866b68888a066    .k...xv...f....f
8b88996a878899606666543423115644    ...j...`ffT4#.VD
23111645331166453411675134116c56    #..E3.fE4.gQ4.lV
34116856341166563411114365661143    4.hV4.fV4..Cef.C
Payload 4

Code: Select all

010001088602400069367001f0010800    ......@.i6p.....
8602400000000003f25f030962006596    ..@......_..b.e.
11436506114315a61143546611335461    .Ce..C...CTf.3Ta
11324465113243456666069999a9a699    .2De.2CEff......
9909660a999960669099096a9a999999    ..f...`f...j....
a6999999660a999999606666996a9a99    ....f....`ff.j..
a066909966069999a6909909999999a9    .f..f...........
9999996a9999a0666656341169563411    ...j...ffV4.iV4.
Payload 5

Code: Select all

010001088602400069367001f0010800    ......@.i6p.....
86024000000000040c63040962006056    ..@......c..b.`V
34116a51341166453411164533115644    4.jQ4.fE4..E3.VD
23115434231111324354112233441122    #.T4#..2CT."3D."
32431122223311222232112222221111    2C.""3.""2."""..
11111011111164660a90556166664455    ......df..UaffDU
61664344555533434444223333331111    afCDUU3CDD"333..
11111111111109a06646666616556616    ........fFff.Uf.
Payload 6

Code: Select all

010001088602400069367001f0010800    ......@.i6p.....
86024000000000057483050962005544    ..@.....t...b.UD
55554434444434333333332211111111    UUD4DD43333"....
11111111453423114433221134232211    ....E4#.D3".4#".
33222211232222112222221111111111    3"".#"".""".....
11111101000357006900690000000000    ......W.i.i.....
00000000000000000000020050006f00    ............P.o.
6b0065006d006f006e00200046006100    k.e.m.o.n. .F.a.
Payload 7

Code: Select all

010001088602400069367001f0010800    ......@.i6p.....
860240000000000659f3060962007200    ..@.....Y...b.r.
6d000000000000000000000000000000    m...............
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
000000000000000000004e0049004e00    ..........N.I.N.
540045004e0044004f00000000000000    T.E.N.D.O.......
Payload 8

Code: Select all

010001088602400069367001f0010800    ......@.i6p.....
860240000000000796f6070962000000    ..@.........b...
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
Payload 9

Code: Select all

010001088602400069367001f0010800    ......@.i6p.....
8602400000000008aff6080948000000    ..@.........H...
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
Payload 10

Code: Select all

010001088602400069367001f0010800    ......@.i6p.....
8602400002000009fdff010001000000    ..@.............
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
00000000000000000000000000000000    ................
THINGS TO NOTE: The first ~20 bytes of these payloads appear to be the same every time, EXCEPT in the very first beacon frame that showed up, where the 12th byte was a 3 rather than a 1. So there's probably a bit flag for "first packet" or something like that. That bit was never set again in any of the other packets. The 24th byte also appears to be some kind of sequence counter for this cycle of 10 payloads, as it increases from 0 to 9 throughout the cycle.

Additionally: even though these are beacon frames, there's no SSID attached, because it's not a real access point. Also thank goodness these connections are completely unencrypted. Not even WEP.

This is the first thing I want to try out. After the beacon frames, I also saw a standard access point association (Authentication packet back and forth and then Association Request / Association Response). The DS tried connecting to a strange SSID, but the GBATEK doc I linked earlier seems to suggest this SSID might not matter?

And then after that there's a ton of packets between the Wii and DS which Wireshark considers malformed because they do not adhere to any regular packet type. Nintendo just made up their own protocol I guess. And the prospect of getting information out of this landslide of packets is kind of daunting but I'll try my best. The first thing I'll probably do with that is try to find byte sequences that match the data structure of Pokemon I know are on the cartridge.

Re: DS/Wii Communication Reverse Engineering

Posted: Sat Jun 28, 2025 1:58 am
by hatkirby
It worked! My program cycles through the ten beacon payloads and emits them, waiting 102.4ms in between each (according to the internet that's a standard beacon frame interval). For some reason I see each beacon frame in Wireshark twice, once with the barebones Radiotap header I put in and one with a few of the flags enabled (does the driver like, re-send the packet with a better header or something?).

In addition to the Nintendo specific vendor tag and the tag containing the channel number, I also had to include two tags detailing the supported rates of the access point (my computer). I then had to modify libwifi (the library I'm using to make 802.11 frames) so that you don't have to add an SSID to the beacon frame. Simply removing the SSID tag after creating the frame was resulting with a malformed packet, so it's easier to just not force me to add one to begin with.

And voila! If I start the program and then press start on the title screen of Pokemon Diamond, I see CONNECT TO WII show up! It thinks my computer is a Wii!

Here's some packet headers from Wireshark.

Code: Select all

   1386 99.170192407   Intel_64:04:10        Broadcast             802.11   206    Beacon frame, SN=295, FN=0, Flags=........, BI=100
   1387 99.270429932   Intel_64:04:10        Broadcast             802.11   201    Beacon frame, SN=296, FN=0, Flags=........, BI=100
   1388 99.274575953   Intel_64:04:10        Broadcast             802.11   206    Beacon frame, SN=296, FN=0, Flags=........, BI=100
   1389 99.373061267   Intel_64:04:10        Broadcast             802.11   201    Beacon frame, SN=297, FN=0, Flags=........, BI=100
   1390 99.380431072   Intel_64:04:10        Broadcast             802.11   206    Beacon frame, SN=297, FN=0, Flags=........, BI=100
   1391 99.475627668   Intel_64:04:10        Broadcast             802.11   201    Beacon frame, SN=298, FN=0, Flags=........, BI=100
   1392 99.479684927   Intel_64:04:10        Broadcast             802.11   206    Beacon frame, SN=298, FN=0, Flags=........, BI=100
   1393 99.578298473   Intel_64:04:10        Broadcast             802.11   201    Beacon frame, SN=299, FN=0, Flags=........, BI=100
   1394 99.580876315   Intel_64:04:10        Broadcast             802.11   206    Beacon frame, SN=299, FN=0, Flags=........, BI=100
   1395 99.583395556   Nintendo_6e:87:b6     Intel_64:04:10        802.11   88     Authentication, SN=0, FN=0, Flags=...P....C
   1396 99.584154046   Nintendo_6e:87:b6     Intel_64:04:10        802.11   88     Authentication, SN=0, FN=0, Flags=...PR...C
   1397 99.586038140   Nintendo_6e:87:b6     Intel_64:04:10        802.11   88     Authentication, SN=0, FN=0, Flags=...PR...C
   1398 99.588378224   Nintendo_6e:87:b6     Intel_64:04:10        802.11   88     Authentication, SN=0, FN=0, Flags=...PR...C
   1399 99.598085048   Nintendo_6e:87:b6     Intel_64:04:10        802.11   88     Authentication, SN=0, FN=0, Flags=...PR...C
   1400 99.598832054   Nintendo_6e:87:b6     Intel_64:04:10        802.11   88     Authentication, SN=0, FN=0, Flags=...PR...C
   1401 99.612260437   Nintendo_6e:87:b6     Intel_64:04:10        802.11   88     Authentication, SN=0, FN=0, Flags=...PR...C
   1402 99.619057087   Nintendo_6e:87:b6     Intel_64:04:10        802.11   88     Authentication, SN=0, FN=0, Flags=...PR...C
   1403 99.681051812   Intel_64:04:10        Broadcast             802.11   201    Beacon frame, SN=300, FN=0, Flags=........, BI=100
   1404 99.683576627   Intel_64:04:10        Broadcast             802.11   206    Beacon frame, SN=300, FN=0, Flags=........, BI=100
   1405 99.783604595   Intel_64:04:10        Broadcast             802.11   201    Beacon frame, SN=301, FN=0, Flags=........, BI=100
   1406 99.794505445   Intel_64:04:10        Broadcast             802.11   206    Beacon frame, SN=301, FN=0, Flags=........, BI=100
   1404 99.683576627   Intel_64:04:10        Broadcast             802.11   206    Beacon frame, SN=300, FN=0, Flags=........, BI=100
   1405 99.783604595   Intel_64:04:10        Broadcast             802.11   201    Beacon frame, SN=301, FN=0, Flags=........, BI=100
   1406 99.794505445   Intel_64:04:10        Broadcast             802.11   206    Beacon frame, SN=301, FN=0, Flags=........, BI=100
   
The beacon frames are from my computer. When I pressed CONNECT TO WII on the DS, it sent Authentication packets to my computer! Which didn't respond, because I haven't coded it to be able to yet. So the DS gave up pretty quickly. But this is a great start. Lotta new stuff for me.

The code repo: https://code.fourisland.com/gen4uploader/

Re: DS/Wii Communication Reverse Engineering

Posted: Wed Jul 02, 2025 1:39 pm
by hatkirby
Quick update on this while I am at work and thus not near my dev computer: I got stuck for a little bit but I'm making progress again. I updated my program to listen for an Authentication packet from the DS and to 1) ACK it, and 2) send an Authentication response. This worked, sort of. The main problem was that the DS was then supposed to ACK my response and send an Association Request packet, and it did neither. It was baffling because I was sending pretty much the exact same packets that the Wii was sending in the packet dump I recorded, so it should have the same result when I send them, right? I tried adding little sleeps in the code so that the timing would be different, but that didn't help things either.

What eventually worked was: sending the packet twice. For some reason. I updated my code so that it retransmits the packet until it gets an ACK, which is how 802.11 is supposed to work anyway, and now it consistently gets an ACK and an Association Request! I watched a video about 802.11 retries and it's a pretty interesting protocol.

I'm still kind of baffled at how the ACK thing really works, because ACK packets have no sender, only a receiver. So how does the transmitter know what packet to stop resending? Is the transmitter only able to transmit one packet at a time, to one destination at a time? I feel like that's gotta really bottleneck everything, but I dunno. It'd be interesting to take a little class on 802.11 at some point or something because it's a pretty in-depth subject matter and it is kind of difficult to find good information about it online. To be fair, I am doing something that generally only wireless card firmware designers have to worry about. Most people do not need to write and parse raw 802.11 packets. Everything gets done at a higher level, like IP.

Anyway, the next thing to do will be to receive the Association Request packet, ACK it, send a response, and then it's go time baby. I've seen in the packet dump that there's a bunch of packets that get sent back and forth between the DS and Wii. It seems like there's some kind of heartbeat that just gets sent repeatedly, so that shouldn't be difficult to replicate hopefully. But then there's the actual data payload. Kind of worried about whether or not I'll be able to figure out what's actually in it / what I need to send.