Switch language:

## UPC WPA2 Key Lookup Service Details

It al started on January 1st 2016, when Peter "bl4sty" Geissler posted a PoC on Twitter.

Here's the UPC WPA2 pass recovery tool! https://t.co/uoiSqrgQ97 Happy new year! ;-)

— blasty (@bl4sty) December 31, 2015

Once I saw this, I wanted to see how it worked, so I translated it to C# and wrote code to generate all possible outcomes and write them to a database; this way, I could offer an instant lookup for people who wanted to see if their modems were vulnerable without having to compile C code and do a lot of calculations.

### The algorithm

NOTE: I'll talk about the final form of the algorithm, since it was updated later on to correct earlier mistakes.

The UPC modems that we target all have a serialnumber that starts with "SAAP" and the offer 2.4 Ghz and 5 Ghz connections.

Serial numbers range from SAAP0000000 to SAAP9999999 (100 million combinations). For the 2.4 Ghz radio SSID and password, this serial number is used; for the 5Ghz radio, the serial number is reversed; the rest of the process is the same (except for a different 'magic' seed).

The SSID is calculated based on the serial number's digits split 4 ways (1, 2, 1, 4). The following calculations are applied; for 2.4 Ghz radios, 0xff8d8f20 is used, for 5 Ghz radios, 0xffd9da60 is used as the 'magic' number.

```
a = serial_number_parts[1] * 10 + serial_number_parts[2];
b = serial_number_parts[0] * 2500000 + a * 6800 + serial_number_parts[3] + magic_number;
ssid = b - (((b * 0x6b5fca6b) >> 54) - (b >> 31)) * 10000000;

```

This ssid number is then left-padded with zero's till you get 7 digits and prefixed with the letters UPC. To calculate the password, the serial number is hashed (MD5), the hash bytes are then converted to 16-bit integers, ran through a compute function, then the upper set of the hash bytes is ran through the same compute function and together, they generate a 16-digit hex string (uppercase), which in turn is hashed (MD5) again and used to generate the final password. The compute function is as followed:

```
a = ((hash_bytes[3] * 0x68de3af) >> 40) - (hash_bytes[3] >> 31);
b = (hash_bytes[3] - a * 9999 + 1) * 11ll;
result = b * (hash_bytes[1] * 100 + hash_bytes[2] * 10 + pp[0]);

```

The last part, converting the MD5 hash of the 16-char hex string into the final password makes sure the output does not contain the letters 'I', 'L' or 'O' and applies some more calculations:

```
for (i = 0; i < 8; i++)
{
a = (hash_bytes[i] & 0x1f);
a -= ((a * 0xb21642c9) >> 36) * 23;
a = (a & 0xff) + 0x41;
if (a >= 'I') a++;
if (a >= 'L') a++;
if (a >= 'O') a++;