Massive refactor/renaming. No more upper-case filenames.

This commit is contained in:
derv82
2018-03-17 04:04:05 -04:00
parent 88bb2c0ac2
commit 622ec064a5
45 changed files with 322 additions and 319 deletions

0
wifite/util/__init__.py Normal file
View File

102
wifite/util/color.py Executable file
View File

@@ -0,0 +1,102 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import sys
class Color(object):
''' Helper object for easily printing colored text to the terminal. '''
# Basic console colors
colors = {
'W' : '\033[0m', # white (normal)
'R' : '\033[31m', # red
'G' : '\033[32m', # green
'O' : '\033[33m', # orange
'B' : '\033[34m', # blue
'P' : '\033[35m', # purple
'C' : '\033[36m', # cyan
'GR': '\033[37m', # gray
'D' : '\033[2m' # dims current color. {W} resets.
}
# Helper string replacements
replacements = {
'{+}': ' {W}[{G}+{W}]',
'{!}': ' {O}[{R}!{O}]{W}',
'{?}': ' {W}[{C}?{W}]'
}
last_sameline_length = 0
@staticmethod
def p(text):
'''
Prints text using colored format on same line.
Example:
Color.p("{R}This text is red. {W} This text is white")
'''
sys.stdout.write(Color.s(text))
sys.stdout.flush()
if '\r' in text:
text = text[text.rfind('\r')+1:]
Color.last_sameline_length = len(text)
else:
Color.last_sameline_length += len(text)
@staticmethod
def pl(text):
'''
Prints text using colored format with trailing new line.
'''
Color.p('%s\n' % text)
Color.last_sameline_length = 0
@staticmethod
def pe(text):
'''
Prints text using colored format with leading and trailing new line to STDERR.
'''
sys.stderr.write(Color.s('%s\n' % text))
Color.last_sameline_length = 0
@staticmethod
def s(text):
''' Returns colored string '''
output = text
for (key,value) in Color.replacements.iteritems():
output = output.replace(key, value)
for (key,value) in Color.colors.iteritems():
output = output.replace("{%s}" % key, value)
return output
@staticmethod
def clear_line():
spaces = ' ' * Color.last_sameline_length
sys.stdout.write('\r%s\r' % spaces)
sys.stdout.flush()
Color.last_sameline_length = 0
@staticmethod
def clear_entire_line():
import os
(rows, columns) = os.popen('stty size', 'r').read().split()
Color.p("\r" + (" " * int(columns)) + "\r")
@staticmethod
def pattack(attack_type, target, attack_name, progress):
'''
Prints a one-liner for an attack
Includes attack type (WEP/WPA), target BSSID/ESSID & power, attack type, and progress
[name] ESSID (MAC @ Pwr) Attack_Type: Progress
e.g.: [WEP] Router2G (00:11:22 @ 23db) replay attack: 102 IVs
'''
essid = "{C}%s{W}" % target.essid if target.essid_known else "{O}unknown{W}"
Color.p("\r{+} {G}%s{W} ({C}%s @ %sdb{W}) {G}%s {C}%s{W}: %s " % (
essid, target.bssid, target.power, attack_type, attack_name, progress))
if __name__ == '__main__':
Color.pl("{R}Testing{G}One{C}Two{P}Three{W}Done")
print Color.s("{C}Testing{P}String{W}")
Color.pl("{+} Good line")
Color.pl("{!} Danger")

180
wifite/util/process.py Executable file
View File

@@ -0,0 +1,180 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import time
from subprocess import Popen, PIPE
from wifite.util.color import Color
from wifite.config import Configuration
class Process(object):
''' Represents a running/ran process '''
@staticmethod
def devnull():
''' Helper method for opening devnull '''
return open('/dev/null', 'w')
@staticmethod
def call(command, cwd=None, shell=False):
'''
Calls a command (either string or list of args).
Returns tuple:
(stdout, stderr)
'''
if type(command) is not str or ' ' in command or shell:
shell = True
if Configuration.verbose > 1:
Color.pe("\n {C}[?] {W} Executing (Shell): {B}%s{W}" % command)
else:
shell = False
if Configuration.verbose > 1:
Color.pe("\n {C}[?]{W} Executing: {B}%s{W}" % command)
pid = Popen(command, cwd=cwd, stdout=PIPE, stderr=PIPE, shell=shell)
pid.wait()
(stdout, stderr) = pid.communicate()
if Configuration.verbose > 1 and stdout.strip() != '':
Color.pe("{P} [stdout] %s{W}" % '\n [stdout] '.join(stdout.split('\n')))
if Configuration.verbose > 1 and stderr.strip() != '':
Color.pe("{P} [stderr] %s{W}" % '\n [stderr] '.join(stderr.split('\n')))
return (stdout, stderr)
@staticmethod
def exists(program):
''' Checks if program is installed on this system '''
p = Process(['which', program])
stdout = p.stdout().strip()
stderr = p.stderr().strip()
if stdout == '' and stderr == '':
return False
return True
def __init__(self, command, devnull=False, stdout=PIPE, stderr=PIPE, cwd=None, bufsize=0):
''' Starts executing command '''
if type(command) is str:
# Commands have to be a list
command = command.split(' ')
self.command = command
if Configuration.verbose > 1:
Color.pe("\n {C}[?] {W} Executing: {B}%s{W}" % ' '.join(command))
self.out = None
self.err = None
if devnull:
sout = Process.devnull()
serr = Process.devnull()
else:
sout = stdout
serr = stderr
self.start_time = time.time()
self.pid = Popen(command, stdout=sout, stderr=serr, cwd=cwd, bufsize=bufsize)
def __del__(self):
'''
Ran when object is GC'd.
If process is still running at this point, it should die.
'''
if self.pid and self.pid.poll() is None:
self.interrupt()
def stdout(self):
''' Waits for process to finish, returns stdout output '''
self.get_output()
if Configuration.verbose > 1 and self.out.strip() != '':
Color.pe("{P} [stdout] %s{W}" % '\n [stdout] '.join(self.out.split('\n')))
return self.out
def stderr(self):
''' Waits for process to finish, returns stderr output '''
self.get_output()
if Configuration.verbose > 1 and self.err.strip() != '':
Color.pe("{P} [stderr] %s{W}" % '\n [stderr] '.join(self.err.split('\n')))
return self.err
def stdoutln(self):
return self.pid.stdout.readline()
def stderrln(self):
return self.pid.stderr.readline()
def get_output(self):
''' Waits for process to finish, sets stdout & stderr '''
if self.pid.poll() is None:
self.pid.wait()
if self.out is None:
(self.out, self.err) = self.pid.communicate()
return (self.out, self.err)
def poll(self):
''' Returns exit code if process is dead, otherwise "None" '''
return self.pid.poll()
def wait(self):
self.pid.wait()
def running_time(self):
''' Returns number of seconds since process was started '''
return int(time.time() - self.start_time)
def interrupt(self):
'''
Send interrupt to current process.
If process fails to exit within 1 second, terminates it.
'''
from signal import SIGINT, SIGTERM
from os import kill
from time import sleep
try:
pid = self.pid.pid
kill(pid, SIGINT)
wait_time = 0 # Time since Interrupt was sent
while self.pid.poll() is None:
# Process is still running
wait_time += 0.1
sleep(0.1)
if wait_time > 1:
# We waited over 1 second for process to die
# Terminate it and move on
kill(pid, SIGTERM)
self.pid.terminate()
break
except OSError, e:
if 'No such process' in e.__str__():
return
raise e # process cannot be killed
if __name__ == '__main__':
p = Process('ls')
print p.stdout(), p.stderr()
p.interrupt()
# Calling as list of arguments
(out, err) = Process.call(['ls', '-lah'])
print out, err
print '\n---------------------\n'
# Calling as string
(out, err) = Process.call('ls -l | head -2')
print out, err
print '"reaver" exists:', Process.exists('reaver')
# Test on never-ending process
p = Process('yes')
# After program loses reference to instance in 'p', process dies.

226
wifite/util/scanner.py Executable file
View File

@@ -0,0 +1,226 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
from wifite.tools.airodump import Airodump
from wifite.util.color import Color
from wifite.model.target import Target
from wifite.config import Configuration
from time import sleep, time
class Scanner(object):
''' Scans wifi networks & provides menu for selecting targets '''
# Console code for moving up one line
UP_CHAR = '\x1B[1F'
def __init__(self):
'''
Starts scan, prints as it goes.
Upon interrupt, sets 'targets'.
'''
self.previous_target_count = 0
self.targets = []
self.target = None # Specific target (based on ESSID/BSSID)
self.err_msg = None
Color.pl("")
# Loads airodump with interface/channel/etc from Configuration
try:
with Airodump() as airodump:
# Loop until interrupted (Ctrl+C)
scan_start_time = time()
while True:
if airodump.pid.poll() is not None:
# Airodump process died
self.err_msg = '\r{!} {R}Airodump exited unexpectedly (Code: %d){O} Command: {W}%s' % (airodump.pid.poll(), " ".join(airodump.pid.command))
raise KeyboardInterrupt
try:
self.targets = airodump.get_targets()
except Exception, e:
break
if self.found_target():
# We found the target we want
return
self.print_targets()
target_count = len(self.targets)
client_count = sum(
[len(t.clients)
for t in self.targets])
outline = "\r{+} Scanning"
if airodump.decloaking:
outline += " & decloaking"
outline += ". Found"
outline += " {G}%d{W} target(s)," % target_count
outline += " {G}%d{W} client(s)." % client_count
outline += " {O}Ctrl+C{W} when ready "
decloaked = airodump.decloaked_targets
if len(decloaked) > 0:
outline += "(decloaked"
outline += " {C}%d{W} ESSIDs:" % len(decloaked)
outline += " {G}%s{W}) " % ", ".join([x.essid for x in decloaked])
Color.clear_entire_line()
Color.p(outline)
if Configuration.scan_time > 0 and time() > scan_start_time + Configuration.scan_time:
return
sleep(1)
except KeyboardInterrupt:
pass
def found_target(self):
'''
Check if we discovered the target AP
Returns: the Target if found,
Otherwise None.
'''
bssid = Configuration.target_bssid
essid = Configuration.target_essid
if bssid is None and essid is None:
return False
for target in self.targets:
if bssid and target.bssid and bssid.lower() == target.bssid.lower():
self.target = target
break
if essid and target.essid and essid.lower() == target.essid.lower():
self.target = target
break
if self.target:
Color.pl('\n{+} {C}found target{G} %s {W}({G}%s{W})'
% (self.target.bssid, self.target.essid))
return True
return False
def print_targets(self):
'''
Prints targets to console
'''
if len(self.targets) == 0:
Color.p('\r')
return
if self.previous_target_count > 0:
# We need to "overwrite" the previous list of targets.
if Configuration.verbose <= 1:
# Don't clear screen buffer in verbose mode.
if self.previous_target_count > len(self.targets) or \
Scanner.get_terminal_height() < self.previous_target_count + 3:
# Either:
# 1) We have less targets than before, so we can't overwrite the previous list
# 2) The terminal can't display the targets without scrolling.
# Clear the screen.
from Process import Process
Process.call('clear')
else:
# We can fit the targets in the terminal without scrolling
# "Move" cursor up so we will print over the previous list
Color.pl(Scanner.UP_CHAR * (3 + self.previous_target_count))
self.previous_target_count = len(self.targets)
# Overwrite the current line
Color.p('\r')
# First row: columns
Color.p(' NUM')
Color.p(' ESSID')
if Configuration.show_bssids:
Color.p(' BSSID')
Color.pl(' CH ENCR POWER WPS? CLIENT')
# Second row: separator
Color.p(' ---')
Color.p(' -------------------------')
if Configuration.show_bssids:
Color.p(' -----------------')
Color.pl(' --- ---- ----- ---- ------')
# Remaining rows: targets
for idx, target in enumerate(self.targets, start=1):
Color.clear_entire_line()
Color.p(' {G}%s ' % str(idx).rjust(3))
Color.pl(target.to_str(Configuration.show_bssids))
@staticmethod
def get_terminal_height():
import os
(rows, columns) = os.popen('stty size', 'r').read().split()
return int(rows)
@staticmethod
def get_terminal_width():
import os
(rows, columns) = os.popen('stty size', 'r').read().split()
return int(columns)
def select_targets(self):
''' Asks user to select target(s) '''
if len(self.targets) == 0:
if self.err_msg is not None:
Color.pl(self.err_msg)
# TODO Print a more-helpful reason for failure.
# 1. Link to wireless drivers wiki,
# 2. How to check if your device supporst monitor mode,
# 3. Provide airodump-ng command being executed.
raise Exception("No targets found."
+ " You may need to wait longer,"
+ " or you may have issues with your wifi card")
if Configuration.scan_time > 0:
return self.targets
self.print_targets()
Color.clear_entire_line()
if self.err_msg is not None:
Color.pl(self.err_msg)
input_str = '{+} select target(s)'
input_str += ' ({G}1-%d{W})' % len(self.targets)
input_str += ' separated by commas, dashes'
input_str += ' or {G}all{W}: '
chosen_targets = []
for choice in raw_input(Color.s(input_str)).split(','):
if choice == 'all':
chosen_targets = self.targets
break
if '-' in choice:
# User selected a range
(lower,upper) = [int(x) - 1 for x in choice.split('-')]
for i in xrange(lower, min(len(self.targets), upper + 1)):
chosen_targets.append(self.targets[i])
elif choice.isdigit():
choice = int(choice) - 1
chosen_targets.append(self.targets[choice])
else:
pass
return chosen_targets
if __name__ == '__main__':
# Example displays targets and selects the appropriate one
Configuration.initialize()
try:
s = Scanner()
targets = s.select_targets()
except Exception, e:
Color.pl('\r {!} {R}Error{W}: %s' % str(e))
Configuration.exit_gracefully(0)
for t in targets:
Color.pl(" {W}Selected: %s" % t)
Configuration.exit_gracefully(0)

36
wifite/util/timer.py Executable file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import time
class Timer(object):
def __init__(self, seconds):
self.start_time = time.time()
self.end_time = self.start_time + seconds
def remaining(self):
return max(0, self.end_time - time.time())
def ended(self):
return self.remaining() == 0
def running_time(self):
return time.time() - self.start_time
def __str__(self):
''' Time remaining in minutes (if > 1) and seconds, e.g. 5m23s'''
return Timer.secs_to_str(self.remaining())
@staticmethod
def secs_to_str(seconds):
'''Human-readable seconds. 193 -> 3m13s'''
rem = int(seconds)
hours = rem / 3600
mins = (rem % 3600) / 60
secs = rem % 60
if hours > 0:
return "%dh%dm%ds" % (hours, mins, secs)
elif mins > 0:
return "%dm%ds" % (mins, secs)
else:
return "%ds" % secs