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.
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:
char[] password = new char[8]; 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++; password[i] = a; }
Test the endresult here: UPC WPA2 Lookup
Feel free to leave a comment below via Facebook.