Cracking BeBox WPA

Cracking WEP is trivial nowadays, so I've never bothered writing up on it (it's all over the net anyway), but WPA is a different matter. So far we have no (known) vulnerabilities in the algorithm (or it's implementation) which means cracking it boils down to either a dictionary attack or brute forcing.

The problem with brute forcing is that it can take a huge amount of time. To put it in perspective, WPA uses 256bit AES, allowing for 95^256 possible passwords (assuming the 95 ASCII symbols), which would take an average PC thousands of years to get through. On the other hand, the problem with dictionary attacks is that it relies on the user putting in a dictionary word as their password. Increasingly routers are being shipped with randomly assigned passwords that are attached to stickers on the cases, making dictionary attacks useless.

When I switched my broadband provider to "Be", their router came preconfigured with  WPA encryption and a nice sticker telling me the random collection of characters which make up my password, and I was happy leaving it on the default, because it looked totally random. That was until I read this interesting piece about the BTHomeHub (GNUCITIZEN).

The thing with the BTHomeHubs is that their "random" WPA passphrase is in fact not random. It's generated from the routers serial number, as shows in the algorithms overview (modified from the GNU CITIZEN site):

Take as example: “CP0615JT109 (53)”

Remove the CC and PP values: CP0615109

Convert the “XXX” values to hexadecimal: CP0615313039

Process with SHA-1: 742da831d2b657fa53d347301ec610e1ebf8a3d0

The last 2 bytes are converted to 4 byte string, and appended to the word “BTHomeHub-” which becomes the default SSID: BTHomeHub-A3D0

The first 5 bytes are converted to a 10 byte string which becomes the default WEP/WPA key: 742DA831D2

One thing that I noticed is that the structure of the BTHomeHub's serial number looks the same as my BeBox's. I also noted that both routers are made by Thomson, just with different branding. Hence I am under the impression that the BeBox's passphrase generator is probably the same.

This is a security concern because it allows us to reduce the range of possible "random" default passwords, and thereby decrease the time required to break the WPA encryption.

What's in an ESSID?

 WPA is different to WEP in many ways, one of which is that it uses both the ESSID and the password in generating its encryption keys. In the case of the BTHomeHub router, it would append the last 2 bytes of the key as the ESSID, which leaks out information about the key and reduces the keyspace, making cracking it easier.

The BeBox on the other hand does not do this, its ESSIDs are by default "BeBox" and "BeBox3". This does not tell us anything about the encryption key, but it does mean that we can pregenerate keys for the BeBox and then use them to crack multiple routers.

The reason for this is simple. While the BTHomeHub leaked key info in it's ESSID, the fact that each BTHomeHub has a different (more or less unique) ESSID means that you would have to brute force each router seperately (because the ESSID acts as a salt).

The BeBox on the other hand does not have this, meaning that one pregenerated table should work fine against  multiple BeBox's (as long as they kept the default ESSID).  It will take longer to generate all possible keys for the BeBox as opposed to the BTHomeHub, but once generated the saved keys can be re-used on other routers.

Generating the Keys

 So we know the keys are derived from the serial number. We also know the format of the serial number, and the algorithm to generate them. This article will revolve around me generating all possible keys for the BeBox and seeing if I can crack my wireless router.

The Serial number

We know the format of the Serial number is :  CPXXXXJTYYY 

Where X is a digit from 0-9 and Y is assumed to be any alphanumeric uppercase character (A-Z,0-9)  (I don't know if the last three bytes can be digits, but I'm including them just in case). The "JT" part is not used at all, and can be ignored.

As you can imagine, this substantially reduces the number of possible passwords for the following reasons:

So the first task for me was to generate a program that will create all possible serial numbers and save them to a file. The program was a quick hack written in python:


for x_1 in numset:
        for x_2 in numset:
                for x_3 in numset:
                        for x_4 in numset:
                                for y_1 in charset:
                                        for y_2 in charset:
                                                for y_3 in charset:
                                                        print "CP" + x_1 + x_2 + x_3 + x_4 + y_1 + y_2 +y_3

The program will printout all the serial keys (which are 9 bytes long)  within the specified char/num sets, which I would then save to a file.  I am assuming that there are no symbols used, only numbers and letters of the alphabet. If this is a mistake, feel free to correct me.

In my case the generated file consisted of 446.56 million serial numbers, for total of 4.4GB of Data, which is magnitudes less than 95^256 possible passwords. The next thing I did was grep the resulting file to see if my router's serial number was in there; it was, so far so good.

Once we got the list of serial numbers, the next program would implement the algorithm specified above, to give us a 10 byte passkey like the keys randomly generated for the routers.

The Algorithm

My implementation of the algorithm was (once again) a quick hack in python, which read in the generated serial numbers above, and outputted 5 bytes hex (as a 10 byte string), which we then save. Note that WPA is case sensitive, and my password was all upper case, so I assume all passwords are upper case.

import string,hashlib,sys,os

def hashit(serial):


        for letter in serial[-3:]:
                hexit += str(hex(ord(letter)))[-2:]

        PT =  serial[:-3] + string.upper(hexit)

        return string.upper(hashlib.sha1(PT).hexdigest()[:10])

import os
fd =[1],os.O_RDONLY)

#We know each serial is ==10 bytes, no need to read more.
while True:
        serial =,10)[:-1]
        if serial == "":
                print hashit(serial)

The passkey file totaled 4.8GB. This time I grepped the file to see if my default pass key was in there, and it was!  This means in theory it should be possible to crack my connection. Next thing I have to do is generate all the WPA keys and give it a go.

Generating the WPA Keys with CUDA

WPA Key generation is slow. My Dual core AMD can only do about 250 keys a second per core, at that rate generating the serial keyspace using both cores will take 248 hours. At this point I found out about pyrit, a CUDA-based WPA key generator. I didn't have a CUDA enabled card, so I went and bought the cheapest CUDA card I could find, which was a GeForce 8400 GS (30 Euros brand new). Running pyrit on this card gave me in excess of 800 keys a second(!), more than both my AMD cores put together. That is quite an impressive improvement for the price (it would have cost me a hell of a lot more to get another AMD X2 box set up).

As pyrit can use a single CPU as well as the GPU, it gives me a rate of 1000keys/sec. At this rate it will take 124 hours to generate all the keys (5 days), all while leaving the CPU of my machine free (so I can use it with little to no slowdown). Once I finish pregenerating the keys, I shall try to crack my WPA connection.

As you can see, 5 days is really nothing compared to the amount of time you would have needed for a pure brute force attack. For those with a bit more money, they can buy any of the higher-end CUDA cards, some of which break the 30,000keys/second barrier.

Generation complete!

Well, I successfully generated all the has tables, now to try to break my personal connection and see how long it takes (if it works, which I think it should).

And the result?


Success!! I found my "random" WPA in the table, and it took ~40 minutes, a wholly reasonable timeframe for breaking a connection.

Counter measures

As you can see, this attack relies on the weakness of the original source, not WPA itself. As such to protect against this attack all you need to do is to assign a truely random password (or at least, don't use a dictionary word and don't leave the default password set!). I've changed my router password so a random set on characters I picked, despite blanking out my password in the screenshot itself; just in case.

The hash tables

A few people have asked me to send them the cowpatty tables for the default Bebox ESSIDs ("BeBox" and "BeBox3"), so they can use them for penetration testing.

I'm not going to post them at the moment. Firstly, the files are large (20 GB each), so I will probably use some sort of P2P mechanism to distribute them (otherwise my bandwidth bills will go through the roof).

Secondly, I want to give people time to react this problem before I post the files online.


Here are the hash files. They are in cowpatty format, and have all the serial numbers pre-genned.


File Name edonkey link Size md5sum
BeBox_serial_table.cow ed2k://|file|BeBox_serial_table.cow|20057802959|FF90D5D6E6AE27BAABC89765259F9DE0|/ 18.68GB  c45ad7c9c09b6b69961a250df8fb2925
BeBox3_serial_table.cow ed2k://|file|BeBox3_serial_table.cow|20057802959|5D60A91519BDAC59AB1D3D764E601150|/ 18.68GB  9b1e68aeed22032e2bb59a4a7b48f257



Update 18th May 2011:

Here are the direct downloads:

If anyone wants to mirror them, or make torrents out of them etc... contact me and I can post them here (along with your name/url if you want). md5sum's below:

9b1e68aeed22032e2bb59a4a7b48f257  ./WPA/Bebox3_serial_table.cow
c45ad7c9c09b6b69961a250df8fb2925  ./WPA/Bebox_serial_table.cow



A thanks goes out to the people at GNU Citizen for their work on the BTHomeHub, and of course to those people mentioned in the link for their work on reverse engineering the code to generate the passwords.

You like?

I'm trying out a little experiment, I've put a slashdot button down here, where you can vote this article if you like it, we shall see how this goes. If it goes well, I might consider putting it on all pages.