Blast from the past: Netbattle Encryption

Way back once upon a time in a land far far away there was a program known as ‘Pokemon Netbattle‘. This program had quite the history for mischief after the original developers left the scene, and the release of Pokemon Diamond and Pearl set the game up to die.

During this time many tools were released that exploited bugs in the program’s code that allowed servers and clients alike to be crashed, simply by sending malformed network packets. Several users at the time released either patched versions (using the leaked source code) or used packet filtering software to prevent the packets from ever being received. One of the things that hindered the few of us that made custom clients, however, is the encryption on the network protocol. This prevented the custom clients from being able to attack servers that enabled encryption between the server and clients. Today, after nearly a decade of non-use of this program and moving on to much better alternatives, I’ll explain how the encryption worked, with modern code samples.

Background

All of Netbattle’s network packets were handled internally as strings, but during the encryption process, as the original comments say “For easy manipulation”, the strings were converted to bytes. In my examples below I’m assuming the input to be bytes.

Additionally, Netbattle’s encryption only supports payloads that are even numbered. In the case that an odd-numbered payload was encountered, a null byte (0x00) was inserted at the beginning, because all netbattle packets start with an ASCII character, which makes this easy to filter out during decryption.

Also, during netbattle 9.6 (the most used version) there were 4 bytes of extra data at the end of each input for encryption flags (as that’s all that gets used). However, a user who goes online by the name of Steve changed the encryption and made the software compatible with newer windows operating systems. The change to the encryption in this new ‘9.7’ version were simply this: changing the padding to 8 bytes instead of 4. This was enough to break the chain so that old clients could no longer encrypt/decrypt packets from the newer version.

Encryption

  1. A new array is created, with a length of 8 more than the original input length. These 8 extra bytes are used for encryption checksums, and the encryption key.
  2. An encryption key is generated using a Pseudo-Random number generator. The key can be between 0 and 255, as it is only one byte in size. The key is stored as the very last byte in the output array.
  3. Next is the main encryption step. It performs a bitwise-XOR of each byte in the input against the byte in front of it, and then against the encryption key. This encryption only runs the length of the original input, not against the 8 bytes at the end of the output.
  4. 3 Different checksums are generated to ensure message integrity once decrypted on the other side. See the section below on how those work.
  5. To throw off any would-be brute force attempts, the order of bytes is then scrambled. The scramble process is run twice, but here’s how it works:
    A New array is created, the first half of it (Equal to half the length of the output inclusive of flags) is populated with all the bytes that are on odd numbered array indices.
    The second half is then filled with every byte from the original output that was on an even numbered array index.
    (Ex. abcdef would become acebdf, then after the second iteration, aedcbf)
  6. Finally, the array is split in half once again, then each half of the array is reversed in order, and then placed back together.
    (Ex. abcdef would become cbafed)

That’s it. In the end Netbattle’s encryption was just a simple XOR encryption with some scrambling techniques to keep you guessing. Now for the checksums…

Encryption Checksums

Checksum 1:

The first checksum is pretty simple, it’s an addition of the value of each unencrypted byte, xor’d against the one in front of it (excluding the last byte), and then hit with a modulo function at the end. After computation, the value is placed as the third byte from the end of the output array.

Here’s some example code (C#)

            for (var i = 0; i < iLen – 1; i++) {
check1 += (iBytes[i] ^ iBytes[i + 1]);
}
check1 = check1 % 256;

Checksum 2:

The second checksum is also pretty simple, it’s an addition of each encrypted byte, and xor’d against (255 – index), where index is the byte’s position in the array.

At the end, the result is added with the main encryption key, and then modulo’d by 256. It is not added to the output until after the third checksum runs!

Here’s some example code (C#)

            for (var i = 0; i < pLen – 3; i++) {
check2 += (oByte[i] ^ (255 – i));
}
check2 = (check2 + mainKey) % 256;

Checksum 3:

The third checksum took a lot of fiddling with to get correct with the original, and it’s a little nunanced, so I’m just going to post the code for this one:

            for (var x = 1; x < v + 1; x++) {
int working = x;
for (var y = 0; y < 4; y++) {
int z = y * v + x;

if (z != pLen – 1) {

working = working + ((y % 2 == 1 ? 8 : (6 * oByte[z – 1]) + 8));
}
}
check3 += working;
}
check3 = Math.Abs((check3 + (oByte[(mainKey % iLen)]))) % 256;

At this point in time, the second and third checksums are placed into the output array, at the second, and next to last positions respectively (remembering that the last byte is reserved for the encryption key).

Decryption

In the original code, if at any point the checksums done from the original encryption failed, the packet would be immediately rejected. The process for decryption is as follows:

  1. Undo the array reversing from the last step in the encryption process
  2. De-scramble the byte order from the scramble process towards the end.
  3. Pull the encrytpion key from the end of the now-corrected output, and perform the main decryption.
  4. Calculate the checksums again, using the same procedure as above.
  5. Trim the 8 bytes of extra info from the end of the decrypted bytes, and return it.

 

Code Samples

Finally, for the curious, I’ve uploaded a gist containing a c# class that can encrypt/decrypt using Netbattle’s 9.7 edition of encryption.

Netbattle XorModule, in C#

Enjoy!

Leave a Reply

Your email address will not be published. Required fields are marked *