Gaming Reverse engineering Pokémon Gen4 wonder card Wi-Fi distribution

Yuuto

New Member
OP
Newbie
Joined
Oct 30, 2017
Messages
1
Trophies
0
Age
27
XP
66
Country
Germany
I have been interested in distributing Gen 4 wonder cards for quite a while now and was amazed by the thought of distributing my own ones.
Using a flash cart is a viable option, but transmitting gifts myself via Wi-Fi sounded far more interesting and since nobody seems to have
done this so far (or I just was not able to find it) I decided to elaborate on how the distribution ROMs work. I don't think this will be
of interest anymore but for the sake of completeness I want to share my results.

I got all information by distributing a huge amount of different/edited wonder cards and capturing the sent packets using Wireshark and by
debugging the 2008 Deoxys Distribution ROM using no$gba.


1. Preparation

The source material for distributing mystery gifts via Wi-Fi is a wonder card in PCD format.
It has a fixed size of 856 (0x358) bytes and can be divided into the following sections:
Code:
  0x0-0x103: [data1]  actual gift data (PGT)
0x104-0x153: [header] card title, card index, supported games
0x154-0x357: [data2]  card description, icons, receive date, redistribution limit


The first step is to prepend the header section to the PCD data to form an extended PCD ("xPCD").
The resulting block of data looks like this:
Code:
0x000-0x04f: header
0x050-0x153: data1
0x154-0x1a3: header
0x1a4-0x3a7: data2


2. Encryption

The xPCD data is encrypted using the stream cipher RC4 (also known as ARC4, ARCFOUR). The encryption key for this algorithm is made of
the distributing system's (or any other transmitting device's) MAC address and a checksum that is calculated over the xPCD block.

The checksum algorithm is a simple add-and-rotate algorithm:
Code:
// the input data is treated as an array of 16-bit words
uint16_t checksum(const uint16_t *data, unsigned int length)
{
    uint16_t c = 0;
   
    while (length--)
    {
        c += *data++;
        c = (c << 1) | (c >> 15);  // rotate c left by 1
    }
   
    return c;
}


The encryption key is then generated as follows:
Code:
// c_low means the lower byte of the checksum, c_high the upper one
uint8_t key[] = { mac[0], mac[1], c_low, c_high, mac[4], mac[5], mac[2], mac[3] };


EDIT: I forgot to mention an important step in the original post:
The 8-byte key array is treated as an array of 4 halfwords and cumulatively XORed with 0x3fa2.
Code:
uint16_t *key_16 = (uint16_t*)key;
uint16_t hw = 0x3fa2;

for (int i = 0; i < 4; ++i)
{
    key_16[i] ^= hw;
    hw = key_16[i];
}


In the next step the actual RC4 encryption is performed. Unfortunately I can't post a link to the algorithm here so please look for it yourself.
The resulting block will be called "ePCD".


3. Transmission

Wonder cards are transmitted using 802.11 beacon frames which are normally used to advertise a wireless access point (AP).
After encryption the ePCD block is split into 9 equal-sized fragments of 104 (0x68) bytes with the corresponding index numbers 0 to 8.
A tenth fragment with index number -1 is made of the unencrypted PCD header padded with zeros to a total size of 104 bytes.
Those 10 distinct fragments are embedded in beacon frames as vendor-specific data.

Below is the format of the vendor-specific element. All values are in little endian order.
Code:
Length  Value/Meaning
     1  0xdd (tag ID)
     1  0x88 (tag length)
     3  0x00 0x09 0xbf (OUI, Nintendo)
     1  0x00 (OUI subtype)
    
   132  --- actual packet ---
    28  --- packet header ---
     4  0xa (frames count?)
     2  0x1
     2  0x1
     4  GGID (language code)
     2  0x0
     2  0x70
     2  0x28
     2  0xc
     2  checksum
     2  fragment index
     4  0x3a8 (payload length)
    
   104  --- packet payload ---


Possible GGID values:
Code:
0x400318 - English
0x8000cd - French
0x8000cf - Italian
0x8000d0 - Spanish
0x345    - Japanese
0xc00018 - Korean
0x8000ce - German


The resulting beacon frames are sent repeatedly by the distribution system ordered by their index in 0.010240 second interval.


4. Result

For the purpose of testing I managed to create a small board consisting of an ATMEGA324PA and an ESP8266.
I succeesfully distributed the german Secret Key to my Platinum version, so I can verify that my results are correct
or at least "correct enough" to achieve a transmission accepted by the Pokémon games.
 
Last edited by Yuuto,

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • K3Nv2 @ K3Nv2:
    Some nerd at Amazon warehouse may tell the end of the colors off
  • DinohScene @ DinohScene:
    I'd like a 990 pro tyvm <З
  • K3Nv2 @ K3Nv2:
    Gen 5s going to be crazy expensive at like 10k transfer
  • K3Nv2 @ K3Nv2:
    $300for 2tb
  • DinohScene @ DinohScene:
    don't have anything that can take PCIe5
  • K3Nv2 @ K3Nv2:
    It's still m.2 form just the next gen
  • DinohScene @ DinohScene:
    ew crucial
  • K3Nv2 @ K3Nv2:
    13,600 MB/s though
  • DinohScene @ DinohScene:
    I got a 980 pro iirc
  • K3Nv2 @ K3Nv2:
    Soldigms been pretty solid
  • DinohScene @ DinohScene:
    yeh 980 pro
  • DinohScene @ DinohScene:
    good enough tbf
  • K3Nv2 @ K3Nv2:
    https://a.co/d/gMNhZNI never heard about them but reviews are good
  • SylverReZ @ SylverReZ:
    @DinohScene, Crucial SSDs work fine. I have one installed in my Xbox.
  • SylverReZ @ SylverReZ:
    Reviews seem positive.
  • DinohScene @ DinohScene:
    I believe I had some Patriot RAM running in a computer somewhere
  • K3Nv2 @ K3Nv2:
    $250 is pretty solid considering
  • K3Nv2 @ K3Nv2:
    With the refund it'll be about $150
  • K3Nv2 @ K3Nv2:
    6tb nvme pc ftw
  • DinohScene @ DinohScene:
    500 GB NVMe, 750 GB
    SATA SSD 1 TB HDD
  • DinohScene @ DinohScene:
    honestly I don't play pc games
  • K3Nv2 @ K3Nv2:
    I don't game
  • K3Nv2 @ K3Nv2:
    Once I buy this I'll be around 20tb worth of storage tho if we're talking all my drives
  • K3Nv2 @ K3Nv2:
    All this crap I got and all I do is pick up the GabeDick to fiddle with his happy stick
    K3Nv2 @ K3Nv2: All this crap I got and all I do is pick up the GabeDick to fiddle with his happy stick