My attempt to reverse the Discord Nitro tokens.

My attempt to reverse the Discord Nitro tokens.

If you are not familiar with Discord, nitro is a kind of membership, you pay to get access and do some cool things on Discord, like get a GIF profile picture or upload large size photos and videos, and in order to get it you must either buy it directly or having someone offer it to you, in the second case it would be something like this: https://discord.gift/hNN5SBsnHTPFFh3Z

The Discord Gift URL followed by a 16-length code will redirect you to the claim page.

First look:

At first sight it looks like Base64 encoded, using Burp Suite Decoder we will be able to get this result:

00000000 84 d3 79 48 1b 27 1d 33 c5 16 1d d9 -- -- -- -- �ÓyH�'�3Å��Ù

After searching for what each byte in a 12-byte string is, I was able to sort each character and see what the code actually consisted of, 4 extended characters and 8 printable/non-printable characters, you can check https://www.rapidtables.com/code/text/ascii-table.html to know more about those type of characters.

  • Extended: 0x84 0xd3 0xc5 0xd9
  • Printable/Non-Printable (Non-Extended): 0x79 0x48 0x1b 0x27 0x1d 0x33 0x16 0x1d

Doing this over and over again will take a lot of time, so I coded this function that automates the work, feel free to use it:

Finding a Pattern:


In order to find a pattern, I used the function above to sort different valid codes, and the result I got is:

From this I was able to know a few rules that must be followed in creating the code:

  • Extended characters can be lower or higher than normal (printable / non-printable) characters.
  • There are no duplicate characters.
  • There is a pattern with 3,4,5,7,8,9.

Looking at the numbers we can see a pattern, if we choose 3 extended characters from the other side, we'll have a 9 normal characters, it's something like Caesar Cipher, and to simplify it:

Putting everything together, we can create a function that generates valid instructions for our code:

An example:

Note that I've seen some 24-length nitro codes, but I'm assuming you can just find the right map to generate this type of codes.

Generation:

In order to create a generation function, by putting everything together according to the rules above, by creating a function that takes the coordinates from generate_map() function, a random extended and printable/non-printable characters and shuffle them together and convert them to hex, we will end up with this:

An example (Hex):

0xd3 0x38 0xe3 0x68 0xd0 0xf6 0xa9 0xfe 0xa7 0xad 0x13 0xb9

Base64:

0zjjaND2qf6nrRO5

Extended: 0xd3 0xe3 0xd0 0xf6 0xa9 0xfe 0xa7 0xad 0xb9

Normal: 0x38 0x68 0x13

Extended: 9, Normal: 3

After few tries I was able to generate a valid token code, but after couple of days (I had to contact the nitro owner explaning the whole context to her) ...


Remember: This is just for research, and I hope no one uses it for bad purposes.