2017-06-30 08:53:19 -04:00
# Copyright (c) 2003-2016 CORE Security Technologies
#
# This software is provided under under a slightly modified version
# of the Apache Software License. See the accompanying LICENSE file
# for more information.
#
# Copyright (C) 2001 Michael Teo <michaelteo@bigfoot.com>
# smb.py - SMB/CIFS library
#
# This software is provided 'as-is', without any express or implied warranty.
# In no event will the author be held liable for any damages arising from the
# use of this software.
#
# Permission is granted to anyone to use this software for any purpose,
# including commercial applications, and to alter it and redistribute it
# freely, subject to the following restrictions:
#
# 1. The origin of this software must not be misrepresented; you must not
# claim that you wrote the original software. If you use this software
# in a product, an acknowledgment in the product documentation would be
# appreciated but is not required.
#
# 2. Altered source versions must be plainly marked as such, and must not be
# misrepresented as being the original software.
#
# 3. This notice cannot be removed or altered from any source distribution.
#
# Altered source done by Alberto Solino (@agsolino)
# Todo:
# [ ] Try [SMB]transport fragmentation using Transact requests
# [ ] Try other methods of doing write (write_raw, transact2, write, write_and_unlock, write_and_close, write_mpx)
# [-] Try replacements for SMB_COM_NT_CREATE_ANDX (CREATE, T_TRANSACT_CREATE, OPEN_ANDX works
# [x] Fix forceWriteAndx, which needs to send a RecvRequest, because recv() will not send it
# [x] Fix Recv() when using RecvAndx and the answer comes splet in several packets
# [ ] Try [SMB]transport fragmentation with overlaping segments
# [ ] Try [SMB]transport fragmentation with out of order segments
# [x] Do chained AndX requests
# [ ] Transform the rest of the calls to structure
# [X] Implement TRANS/TRANS2 reassembly for list_path
import os
import socket
import string
from binascii import a2b_hex
import datetime
from struct import pack , unpack
from contextlib import contextmanager
from impacket import nmb , ntlm , nt_errors , LOG
from impacket . structure import Structure
from impacket . spnego import SPNEGO_NegTokenInit , TypesMech , SPNEGO_NegTokenResp
# For signing
import hashlib
unicode_support = 0
unicode_convert = 1
try :
from cStringIO import StringIO
except ImportError :
from StringIO import StringIO
# Dialect for SMB1
SMB_DIALECT = ' NT LM 0.12 '
# Shared Device Type
SHARED_DISK = 0x00
SHARED_DISK_HIDDEN = 0x80000000
SHARED_PRINT_QUEUE = 0x01
SHARED_DEVICE = 0x02
SHARED_IPC = 0x03
# Extended attributes mask
ATTR_ARCHIVE = 0x020
ATTR_COMPRESSED = 0x800
ATTR_NORMAL = 0x080
ATTR_HIDDEN = 0x002
ATTR_READONLY = 0x001
ATTR_TEMPORARY = 0x100
ATTR_DIRECTORY = 0x010
ATTR_SYSTEM = 0x004
# Service Type
SERVICE_DISK = ' A: '
SERVICE_PRINTER = ' LPT1: '
SERVICE_IPC = ' IPC '
SERVICE_COMM = ' COMM '
SERVICE_ANY = ' ????? '
# Server Type (Can be used to mask with SMBMachine.get_type() or SMBDomain.get_type())
SV_TYPE_WORKSTATION = 0x00000001
SV_TYPE_SERVER = 0x00000002
SV_TYPE_SQLSERVER = 0x00000004
SV_TYPE_DOMAIN_CTRL = 0x00000008
SV_TYPE_DOMAIN_BAKCTRL = 0x00000010
SV_TYPE_TIME_SOURCE = 0x00000020
SV_TYPE_AFP = 0x00000040
SV_TYPE_NOVELL = 0x00000080
SV_TYPE_DOMAIN_MEMBER = 0x00000100
SV_TYPE_PRINTQ_SERVER = 0x00000200
SV_TYPE_DIALIN_SERVER = 0x00000400
SV_TYPE_XENIX_SERVER = 0x00000800
SV_TYPE_NT = 0x00001000
SV_TYPE_WFW = 0x00002000
SV_TYPE_SERVER_NT = 0x00004000
SV_TYPE_POTENTIAL_BROWSER = 0x00010000
SV_TYPE_BACKUP_BROWSER = 0x00020000
SV_TYPE_MASTER_BROWSER = 0x00040000
SV_TYPE_DOMAIN_MASTER = 0x00080000
SV_TYPE_LOCAL_LIST_ONLY = 0x40000000
SV_TYPE_DOMAIN_ENUM = 0x80000000
# Options values for SMB.stor_file and SMB.retr_file
SMB_O_CREAT = 0x10 # Create the file if file does not exists. Otherwise, operation fails.
SMB_O_EXCL = 0x00 # When used with SMB_O_CREAT, operation fails if file exists. Cannot be used with SMB_O_OPEN.
SMB_O_OPEN = 0x01 # Open the file if the file exists
SMB_O_TRUNC = 0x02 # Truncate the file if the file exists
# Share Access Mode
SMB_SHARE_COMPAT = 0x00
SMB_SHARE_DENY_EXCL = 0x10
SMB_SHARE_DENY_WRITE = 0x20
SMB_SHARE_DENY_READEXEC = 0x30
SMB_SHARE_DENY_NONE = 0x40
SMB_ACCESS_READ = 0x00
SMB_ACCESS_WRITE = 0x01
SMB_ACCESS_READWRITE = 0x02
SMB_ACCESS_EXEC = 0x03
TRANS_DISCONNECT_TID = 1
TRANS_NO_RESPONSE = 2
STATUS_SUCCESS = 0x00000000
STATUS_LOGON_FAILURE = 0xC000006D
STATUS_LOGON_TYPE_NOT_GRANTED = 0xC000015B
MAX_TFRAG_SIZE = 5840
EVASION_NONE = 0
EVASION_LOW = 1
EVASION_HIGH = 2
EVASION_MAX = 3
RPC_X_BAD_STUB_DATA = 0x6F7
# SMB_FILE_ATTRIBUTES
SMB_FILE_ATTRIBUTE_NORMAL = 0x0000
SMB_FILE_ATTRIBUTE_READONLY = 0x0001
SMB_FILE_ATTRIBUTE_HIDDEN = 0x0002
SMB_FILE_ATTRIBUTE_SYSTEM = 0x0004
SMB_FILE_ATTRIBUTE_VOLUME = 0x0008
SMB_FILE_ATTRIBUTE_DIRECTORY = 0x0010
SMB_FILE_ATTRIBUTE_ARCHIVE = 0x0020
SMB_SEARCH_ATTRIBUTE_READONLY = 0x0100
SMB_SEARCH_ATTRIBUTE_HIDDEN = 0x0200
SMB_SEARCH_ATTRIBUTE_SYSTEM = 0x0400
SMB_SEARCH_ATTRIBUTE_DIRECTORY = 0x1000
SMB_SEARCH_ATTRIBUTE_ARCHIVE = 0x2000
# Session SetupAndX Action flags
SMB_SETUP_GUEST = 0x01
SMB_SETUP_USE_LANMAN_KEY = 0x02
# QUERY_INFORMATION levels
SMB_INFO_ALLOCATION = 0x0001
SMB_INFO_VOLUME = 0x0002
FILE_FS_SIZE_INFORMATION = 0x0003
SMB_QUERY_FS_VOLUME_INFO = 0x0102
SMB_QUERY_FS_SIZE_INFO = 0x0103
SMB_QUERY_FILE_EA_INFO = 0x0103
SMB_QUERY_FS_DEVICE_INFO = 0x0104
SMB_QUERY_FS_ATTRIBUTE_INFO = 0x0105
SMB_QUERY_FILE_BASIC_INFO = 0x0101
SMB_QUERY_FILE_STANDARD_INFO = 0x0102
SMB_QUERY_FILE_ALL_INFO = 0x0107
FILE_FS_FULL_SIZE_INFORMATION = 0x03EF
# SET_INFORMATION levels
SMB_SET_FILE_DISPOSITION_INFO = 0x0102
SMB_SET_FILE_BASIC_INFO = 0x0101
SMB_SET_FILE_END_OF_FILE_INFO = 0x0104
# File System Attributes
FILE_CASE_SENSITIVE_SEARCH = 0x00000001
FILE_CASE_PRESERVED_NAMES = 0x00000002
FILE_UNICODE_ON_DISK = 0x00000004
FILE_PERSISTENT_ACLS = 0x00000008
FILE_FILE_COMPRESSION = 0x00000010
FILE_VOLUME_IS_COMPRESSED = 0x00008000
# FIND_FIRST2 flags and levels
SMB_FIND_CLOSE_AFTER_REQUEST = 0x0001
SMB_FIND_CLOSE_AT_EOS = 0x0002
SMB_FIND_RETURN_RESUME_KEYS = 0x0004
SMB_FIND_CONTINUE_FROM_LAST = 0x0008
SMB_FIND_WITH_BACKUP_INTENT = 0x0010
FILE_DIRECTORY_FILE = 0x00000001
FILE_DELETE_ON_CLOSE = 0x00001000
FILE_NON_DIRECTORY_FILE = 0x00000040
SMB_FIND_INFO_STANDARD = 0x0001
SMB_FIND_FILE_DIRECTORY_INFO = 0x0101
SMB_FIND_FILE_FULL_DIRECTORY_INFO = 0x0102
SMB_FIND_FILE_NAMES_INFO = 0x0103
SMB_FIND_FILE_BOTH_DIRECTORY_INFO = 0x0104
SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO = 0x105
SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO = 0x106
# DesiredAccess flags
FILE_READ_DATA = 0x00000001
FILE_WRITE_DATA = 0x00000002
FILE_APPEND_DATA = 0x00000004
FILE_EXECUTE = 0x00000020
MAXIMUM_ALLOWED = 0x02000000
GENERIC_ALL = 0x10000000
GENERIC_EXECUTE = 0x20000000
GENERIC_WRITE = 0x40000000
GENERIC_READ = 0x80000000
# ShareAccess flags
FILE_SHARE_NONE = 0x00000000
FILE_SHARE_READ = 0x00000001
FILE_SHARE_WRITE = 0x00000002
FILE_SHARE_DELETE = 0x00000004
# CreateDisposition flags
FILE_SUPERSEDE = 0x00000000
FILE_OPEN = 0x00000001
FILE_CREATE = 0x00000002
FILE_OPEN_IF = 0x00000003
FILE_OVERWRITE = 0x00000004
FILE_OVERWRITE_IF = 0x00000005
def strerror ( errclass , errcode ) :
if errclass == 0x01 :
return ' OS error ' , ERRDOS . get ( errcode , ' Unknown error ' )
elif errclass == 0x02 :
return ' Server error ' , ERRSRV . get ( errcode , ' Unknown error ' )
elif errclass == 0x03 :
return ' Hardware error ' , ERRHRD . get ( errcode , ' Unknown error ' )
# This is not a standard error class for SMB
#elif errclass == 0x80:
# return 'Browse error', ERRBROWSE.get(errcode, 'Unknown error')
elif errclass == 0xff :
return ' Bad command ' , ' Bad command. Please file bug report '
else :
return ' Unknown error ' , ' Unknown error '
# Raised when an error has occured during a session
class SessionError ( Exception ) :
# SMB X/Open error codes for the ERRDOS error class
ERRsuccess = 0
ERRbadfunc = 1
ERRbadfile = 2
ERRbadpath = 3
ERRnofids = 4
ERRnoaccess = 5
ERRbadfid = 6
ERRbadmcb = 7
ERRnomem = 8
ERRbadmem = 9
ERRbadenv = 10
ERRbadaccess = 12
ERRbaddata = 13
ERRres = 14
ERRbaddrive = 15
ERRremcd = 16
ERRdiffdevice = 17
ERRnofiles = 18
ERRgeneral = 31
ERRbadshare = 32
ERRlock = 33
ERRunsup = 50
ERRnetnamedel = 64
ERRnosuchshare = 67
ERRfilexists = 80
ERRinvalidparam = 87
ERRcannotopen = 110
ERRinsufficientbuffer = 122
ERRinvalidname = 123
ERRunknownlevel = 124
ERRnotlocked = 158
ERRrename = 183
ERRbadpipe = 230
ERRpipebusy = 231
ERRpipeclosing = 232
ERRnotconnected = 233
ERRmoredata = 234
ERRnomoreitems = 259
ERRbaddirectory = 267
ERReasnotsupported = 282
ERRlogonfailure = 1326
ERRbuftoosmall = 2123
ERRunknownipc = 2142
ERRnosuchprintjob = 2151
ERRinvgroup = 2455
# here's a special one from observing NT
ERRnoipc = 66
# These errors seem to be only returned by the NT printer driver system
ERRdriveralreadyinstalled = 1795
ERRunknownprinterport = 1796
ERRunknownprinterdriver = 1797
ERRunknownprintprocessor = 1798
ERRinvalidseparatorfile = 1799
ERRinvalidjobpriority = 1800
ERRinvalidprintername = 1801
ERRprinteralreadyexists = 1802
ERRinvalidprintercommand = 1803
ERRinvaliddatatype = 1804
ERRinvalidenvironment = 1805
ERRunknownprintmonitor = 3000
ERRprinterdriverinuse = 3001
ERRspoolfilenotfound = 3002
ERRnostartdoc = 3003
ERRnoaddjob = 3004
ERRprintprocessoralreadyinstalled = 3005
ERRprintmonitoralreadyinstalled = 3006
ERRinvalidprintmonitor = 3007
ERRprintmonitorinuse = 3008
ERRprinterhasjobsqueued = 3009
# Error codes for the ERRSRV class
ERRerror = 1
ERRbadpw = 2
ERRbadtype = 3
ERRaccess = 4
ERRinvnid = 5
ERRinvnetname = 6
ERRinvdevice = 7
ERRqfull = 49
ERRqtoobig = 50
ERRinvpfid = 52
ERRsmbcmd = 64
ERRsrverror = 65
ERRfilespecs = 67
ERRbadlink = 68
ERRbadpermits = 69
ERRbadpid = 70
ERRsetattrmode = 71
ERRpaused = 81
ERRmsgoff = 82
ERRnoroom = 83
ERRrmuns = 87
ERRtimeout = 88
ERRnoresource = 89
ERRtoomanyuids = 90
ERRbaduid = 91
ERRuseMPX = 250
ERRuseSTD = 251
ERRcontMPX = 252
ERRbadPW = None
ERRnosupport = 0
ERRunknownsmb = 22
# Error codes for the ERRHRD class
ERRnowrite = 19
ERRbadunit = 20
ERRnotready = 21
ERRbadcmd = 22
ERRdata = 23
ERRbadreq = 24
ERRseek = 25
ERRbadmedia = 26
ERRbadsector = 27
ERRnopaper = 28
ERRwrite = 29
ERRread = 30
ERRwrongdisk = 34
ERRFCBunavail = 35
ERRsharebufexc = 36
ERRdiskfull = 39
hard_msgs = {
19 : ( " ERRnowrite " , " Attempt to write on write-protected diskette. " ) ,
20 : ( " ERRbadunit " , " Unknown unit. " ) ,
21 : ( " ERRnotready " , " Drive not ready. " ) ,
22 : ( " ERRbadcmd " , " Unknown command. " ) ,
23 : ( " ERRdata " , " Data error (CRC). " ) ,
24 : ( " ERRbadreq " , " Bad request structure length. " ) ,
25 : ( " ERRseek " , " Seek error. " ) ,
26 : ( " ERRbadmedia " , " Unknown media type. " ) ,
27 : ( " ERRbadsector " , " Sector not found. " ) ,
28 : ( " ERRnopaper " , " Printer out of paper. " ) ,
29 : ( " ERRwrite " , " Write fault. " ) ,
30 : ( " ERRread " , " Read fault. " ) ,
31 : ( " ERRgeneral " , " General failure. " ) ,
32 : ( " ERRbadshare " , " An open conflicts with an existing open. " ) ,
33 : ( " ERRlock " , " A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process. " ) ,
34 : ( " ERRwrongdisk " , " The wrong disk was found in a drive. " ) ,
35 : ( " ERRFCBUnavail " , " No FCBs are available to process request. " ) ,
36 : ( " ERRsharebufexc " , " A sharing buffer has been exceeded. " )
}
dos_msgs = {
ERRbadfunc : ( " ERRbadfunc " , " Invalid function. " ) ,
ERRbadfile : ( " ERRbadfile " , " File not found. " ) ,
ERRbadpath : ( " ERRbadpath " , " Directory invalid. " ) ,
ERRnofids : ( " ERRnofids " , " No file descriptors available " ) ,
ERRnoaccess : ( " ERRnoaccess " , " Access denied. " ) ,
ERRbadfid : ( " ERRbadfid " , " Invalid file handle. " ) ,
ERRbadmcb : ( " ERRbadmcb " , " Memory control blocks destroyed. " ) ,
ERRnomem : ( " ERRnomem " , " Insufficient server memory to perform the requested function. " ) ,
ERRbadmem : ( " ERRbadmem " , " Invalid memory block address. " ) ,
ERRbadenv : ( " ERRbadenv " , " Invalid environment. " ) ,
11 : ( " ERRbadformat " , " Invalid format. " ) ,
ERRbadaccess : ( " ERRbadaccess " , " Invalid open mode. " ) ,
ERRbaddata : ( " ERRbaddata " , " Invalid data. " ) ,
ERRres : ( " ERRres " , " reserved. " ) ,
ERRbaddrive : ( " ERRbaddrive " , " Invalid drive specified. " ) ,
ERRremcd : ( " ERRremcd " , " A Delete Directory request attempted to remove the server ' s current directory. " ) ,
ERRdiffdevice : ( " ERRdiffdevice " , " Not same device. " ) ,
ERRnofiles : ( " ERRnofiles " , " A File Search command can find no more files matching the specified criteria. " ) ,
ERRbadshare : ( " ERRbadshare " , " The sharing mode specified for an Open conflicts with existing FIDs on the file. " ) ,
ERRlock : ( " ERRlock " , " A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process. " ) ,
ERRunsup : ( " ERRunsup " , " The operation is unsupported " ) ,
ERRnosuchshare : ( " ERRnosuchshare " , " You specified an invalid share name " ) ,
ERRfilexists : ( " ERRfilexists " , " The file named in a Create Directory, Make New File or Link request already exists. " ) ,
ERRinvalidname : ( " ERRinvalidname " , " Invalid name " ) ,
ERRbadpipe : ( " ERRbadpipe " , " Pipe invalid. " ) ,
ERRpipebusy : ( " ERRpipebusy " , " All instances of the requested pipe are busy. " ) ,
ERRpipeclosing : ( " ERRpipeclosing " , " Pipe close in progress. " ) ,
ERRnotconnected : ( " ERRnotconnected " , " No process on other end of pipe. " ) ,
ERRmoredata : ( " ERRmoredata " , " There is more data to be returned. " ) ,
ERRinvgroup : ( " ERRinvgroup " , " Invalid workgroup (try the -W option) " ) ,
ERRlogonfailure : ( " ERRlogonfailure " , " Logon failure " ) ,
ERRdiskfull : ( " ERRdiskfull " , " Disk full " ) ,
ERRgeneral : ( " ERRgeneral " , " General failure " ) ,
ERRunknownlevel : ( " ERRunknownlevel " , " Unknown info level " )
}
server_msgs = {
1 : ( " ERRerror " , " Non-specific error code. " ) ,
2 : ( " ERRbadpw " , " Bad password - name/password pair in a Tree Connect or Session Setup are invalid. " ) ,
3 : ( " ERRbadtype " , " reserved. " ) ,
4 : ( " ERRaccess " , " The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID. " ) ,
5 : ( " ERRinvnid " , " The tree ID (TID) specified in a command was invalid. " ) ,
6 : ( " ERRinvnetname " , " Invalid network name in tree connect. " ) ,
7 : ( " ERRinvdevice " , " Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. " ) ,
49 : ( " ERRqfull " , " Print queue full (files) -- returned by open print file. " ) ,
50 : ( " ERRqtoobig " , " Print queue full -- no space. " ) ,
51 : ( " ERRqeof " , " EOF on print queue dump. " ) ,
52 : ( " ERRinvpfid " , " Invalid print file FID. " ) ,
64 : ( " ERRsmbcmd " , " The server did not recognize the command received. " ) ,
65 : ( " ERRsrverror " , " The server encountered an internal error, e.g., system file unavailable. " ) ,
67 : ( " ERRfilespecs " , " The file handle (FID) and pathname parameters contained an invalid combination of values. " ) ,
68 : ( " ERRreserved " , " reserved. " ) ,
69 : ( " ERRbadpermits " , " The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute. " ) ,
70 : ( " ERRreserved " , " reserved. " ) ,
71 : ( " ERRsetattrmode " , " The attribute mode in the Set File Attribute request is invalid. " ) ,
81 : ( " ERRpaused " , " Server is paused. " ) ,
82 : ( " ERRmsgoff " , " Not receiving messages. " ) ,
83 : ( " ERRnoroom " , " No room to buffer message. " ) ,
87 : ( " ERRrmuns " , " Too many remote user names. " ) ,
88 : ( " ERRtimeout " , " Operation timed out. " ) ,
89 : ( " ERRnoresource " , " No resources currently available for request. " ) ,
90 : ( " ERRtoomanyuids " , " Too many UIDs active on this session. " ) ,
91 : ( " ERRbaduid " , " The UID is not known as a valid ID on this session. " ) ,
250 : ( " ERRusempx " , " Temp unable to support Raw, use MPX mode. " ) ,
251 : ( " ERRusestd " , " Temp unable to support Raw, use standard read/write. " ) ,
252 : ( " ERRcontmpx " , " Continue in MPX mode. " ) ,
253 : ( " ERRreserved " , " reserved. " ) ,
254 : ( " ERRreserved " , " reserved. " ) ,
0xFFFF : ( " ERRnosupport " , " Function not supported. " )
}
# Error clases
ERRDOS = 0x1
error_classes = { 0 : ( " SUCCESS " , { } ) ,
ERRDOS : ( " ERRDOS " , dos_msgs ) ,
0x02 : ( " ERRSRV " , server_msgs ) ,
0x03 : ( " ERRHRD " , hard_msgs ) ,
0x04 : ( " ERRXOS " , { } ) ,
0xE1 : ( " ERRRMX1 " , { } ) ,
0xE2 : ( " ERRRMX2 " , { } ) ,
0xE3 : ( " ERRRMX3 " , { } ) ,
0xFF : ( " ERRCMD " , { } ) }
def __init__ ( self , error_string , error_class , error_code , nt_status = 0 ) :
Exception . __init__ ( self , error_string )
self . nt_status = nt_status
self . _args = error_string
if nt_status :
self . error_class = 0
self . error_code = ( error_code << 16 ) + error_class
else :
self . error_class = error_class
self . error_code = error_code
def get_error_class ( self ) :
return self . error_class
def get_error_code ( self ) :
return self . error_code
def __str__ ( self ) :
error_class = SessionError . error_classes . get ( self . error_class , None )
if not error_class :
error_code_str = self . error_code
error_class_str = self . error_class
else :
error_class_str = error_class [ 0 ]
error_code = error_class [ 1 ] . get ( self . error_code , None )
if not error_code :
error_code_str = self . error_code
else :
error_code_str = ' %s ( %s ) ' % error_code
if self . nt_status :
return ' SMB SessionError: %s ( %s ) ' % nt_errors . ERROR_MESSAGES [ self . error_code ]
else :
# Fall back to the old format
return ' SMB SessionError: class: %s , code: %s ' % ( error_class_str , error_code_str )
# Raised when an supported feature is present/required in the protocol but is not
# currently supported by pysmb
class UnsupportedFeature ( Exception ) : pass
# Contains information about a SMB shared device/service
class SharedDevice :
def __init__ ( self , name , share_type , comment ) :
self . __name = name
self . __type = share_type
self . __comment = comment
def get_name ( self ) :
return self . __name
def get_type ( self ) :
return self . __type
def get_comment ( self ) :
return self . __comment
def __repr__ ( self ) :
return ' <SharedDevice instance: name= ' + self . __name + ' , type= ' + str ( self . __type ) + ' , comment= " ' + self . __comment + ' " > '
# Contains information about the shared file/directory
class SharedFile :
def __init__ ( self , ctime , atime , mtime , filesize , allocsize , attribs , shortname , longname ) :
self . __ctime = ctime
self . __atime = atime
self . __mtime = mtime
self . __filesize = filesize
self . __allocsize = allocsize
self . __attribs = attribs
try :
self . __shortname = shortname [ : string . index ( shortname , ' \0 ' ) ]
except ValueError :
self . __shortname = shortname
try :
self . __longname = longname [ : string . index ( longname , ' \0 ' ) ]
except ValueError :
self . __longname = longname
def get_ctime ( self ) :
return self . __ctime
def get_ctime_epoch ( self ) :
return self . __convert_smbtime ( self . __ctime )
def get_mtime ( self ) :
return self . __mtime
def get_mtime_epoch ( self ) :
return self . __convert_smbtime ( self . __mtime )
def get_atime ( self ) :
return self . __atime
def get_atime_epoch ( self ) :
return self . __convert_smbtime ( self . __atime )
def get_filesize ( self ) :
return self . __filesize
def get_allocsize ( self ) :
return self . __allocsize
def get_attributes ( self ) :
return self . __attribs
def is_archive ( self ) :
return self . __attribs & ATTR_ARCHIVE
def is_compressed ( self ) :
return self . __attribs & ATTR_COMPRESSED
def is_normal ( self ) :
return self . __attribs & ATTR_NORMAL
def is_hidden ( self ) :
return self . __attribs & ATTR_HIDDEN
def is_readonly ( self ) :
return self . __attribs & ATTR_READONLY
def is_temporary ( self ) :
return self . __attribs & ATTR_TEMPORARY
def is_directory ( self ) :
return self . __attribs & ATTR_DIRECTORY
def is_system ( self ) :
return self . __attribs & ATTR_SYSTEM
def get_shortname ( self ) :
return self . __shortname
def get_longname ( self ) :
return self . __longname
def __repr__ ( self ) :
return ' <SharedFile instance: shortname= " ' + self . __shortname + ' " , longname= " ' + self . __longname + ' " , filesize= ' + str ( self . __filesize ) + ' > '
@staticmethod
def __convert_smbtime ( t ) :
x = t >> 32
2019-04-04 19:32:39 -04:00
y = t & 0xffffffff
2017-06-30 08:53:19 -04:00
geo_cal_offset = 11644473600.0 # = 369.0 * 365.25 * 24 * 60 * 60 - (3.0 * 24 * 60 * 60 + 6.0 * 60 * 60)
2019-04-04 19:32:39 -04:00
return ( x * 4.0 * ( 1 << 30 ) + ( y & 0xfff00000 ) ) * 1.0e-7 - geo_cal_offset
2017-06-30 08:53:19 -04:00
# Contain information about a SMB machine
class SMBMachine :
def __init__ ( self , nbname , nbt_type , comment ) :
self . __nbname = nbname
self . __type = nbt_type
self . __comment = comment
def __repr__ ( self ) :
return ' <SMBMachine instance: nbname= " ' + self . __nbname + ' " , type= ' + hex ( self . __type ) + ' , comment= " ' + self . __comment + ' " > '
class SMBDomain :
def __init__ ( self , nbgroup , domain_type , master_browser ) :
self . __nbgroup = nbgroup
self . __type = domain_type
self . __master_browser = master_browser
def __repr__ ( self ) :
return ' <SMBDomain instance: nbgroup= " ' + self . __nbgroup + ' " , type= ' + hex ( self . __type ) + ' , master browser= " ' + self . __master_browser + ' " > '
# Represents a SMB Packet
class NewSMBPacket ( Structure ) :
structure = (
( ' Signature ' , ' " \xff SMB ' ) ,
( ' Command ' , ' B=0 ' ) ,
( ' ErrorClass ' , ' B=0 ' ) ,
( ' _reserved ' , ' B=0 ' ) ,
( ' ErrorCode ' , ' <H=0 ' ) ,
( ' Flags1 ' , ' B=0 ' ) ,
( ' Flags2 ' , ' <H=0 ' ) ,
( ' PIDHigh ' , ' <H=0 ' ) ,
( ' SecurityFeatures ' , ' 8s= " " ' ) ,
( ' Reserved ' , ' <H=0 ' ) ,
( ' Tid ' , ' <H=0xffff ' ) ,
( ' Pid ' , ' <H=0 ' ) ,
( ' Uid ' , ' <H=0 ' ) ,
( ' Mid ' , ' <H=0 ' ) ,
( ' Data ' , ' *: ' ) ,
)
def __init__ ( self , * * kargs ) :
Structure . __init__ ( self , * * kargs )
2019-04-04 19:32:39 -04:00
if ( ' Flags2 ' in self . fields ) is False :
2017-06-30 08:53:19 -04:00
self [ ' Flags2 ' ] = 0
2019-04-04 19:32:39 -04:00
if ( ' Flags1 ' in self . fields ) is False :
2017-06-30 08:53:19 -04:00
self [ ' Flags1 ' ] = 0
2019-04-04 19:32:39 -04:00
if ' data ' not in kargs :
2017-06-30 08:53:19 -04:00
self [ ' Data ' ] = [ ]
def addCommand ( self , command ) :
if len ( self [ ' Data ' ] ) == 0 :
self [ ' Command ' ] = command . command
else :
self [ ' Data ' ] [ - 1 ] [ ' Parameters ' ] [ ' AndXCommand ' ] = command . command
self [ ' Data ' ] [ - 1 ] [ ' Parameters ' ] [ ' AndXOffset ' ] = len ( self )
self [ ' Data ' ] . append ( command )
def isMoreData ( self ) :
return ( self [ ' Command ' ] in [ SMB . SMB_COM_TRANSACTION , SMB . SMB_COM_READ_ANDX , SMB . SMB_COM_READ_RAW ] and
self [ ' ErrorClass ' ] == 1 and self [ ' ErrorCode ' ] == SessionError . ERRmoredata )
def isMoreProcessingRequired ( self ) :
return self [ ' ErrorClass ' ] == 0x16 and self [ ' ErrorCode ' ] == 0xc000
def isValidAnswer ( self , cmd ) :
# this was inside a loop reading more from the net (with recv_packet(None))
if self [ ' Command ' ] == cmd :
if ( self [ ' ErrorClass ' ] == 0x00 and
self [ ' ErrorCode ' ] == 0x00 ) :
return 1
elif self . isMoreData ( ) :
return 1
elif self . isMoreProcessingRequired ( ) :
return 1
2019-04-04 19:32:39 -04:00
raise SessionError ( " SMB Library Error " , self [ ' ErrorClass ' ] + ( self [ ' _reserved ' ] << 8 ) , self [ ' ErrorCode ' ] , self [ ' Flags2 ' ] & SMB . FLAGS2_NT_STATUS )
2017-06-30 08:53:19 -04:00
else :
2019-04-04 19:32:39 -04:00
raise UnsupportedFeature ( " Unexpected answer from server: Got %d , Expected %d " % ( self [ ' Command ' ] , cmd ) )
2017-06-30 08:53:19 -04:00
class SMBCommand ( Structure ) :
structure = (
( ' WordCount ' , ' B=len(Parameters)/2 ' ) ,
( ' _ParametersLength ' , ' _-Parameters ' , ' WordCount*2 ' ) ,
( ' Parameters ' , ' : ' ) , # default set by constructor
( ' ByteCount ' , ' <H-Data ' ) ,
( ' Data ' , ' : ' ) , # default set by constructor
)
def __init__ ( self , commandOrData = None , data = None , * * kargs ) :
if type ( commandOrData ) == type ( 0 ) :
self . command = commandOrData
else :
data = data or commandOrData
Structure . __init__ ( self , data = data , * * kargs )
if data is None :
self [ ' Parameters ' ] = ' '
self [ ' Data ' ] = ' '
class AsciiOrUnicodeStructure ( Structure ) :
UnicodeStructure = ( )
AsciiStructure = ( )
def __init__ ( self , flags = 0 , * * kargs ) :
if flags & SMB . FLAGS2_UNICODE :
self . structure = self . UnicodeStructure
else :
self . structure = self . AsciiStructure
Structure . __init__ ( self , * * kargs )
class SMBCommand_Parameters ( Structure ) :
pass
class SMBAndXCommand_Parameters ( Structure ) :
commonHdr = (
( ' AndXCommand ' , ' B=0xff ' ) ,
( ' _reserved ' , ' B=0 ' ) ,
( ' AndXOffset ' , ' <H=0 ' ) ,
)
structure = ( # default structure, overriden by subclasses
( ' Data ' , ' := " " ' ) ,
)
############# TRANSACTIONS RELATED
# TRANS2_QUERY_FS_INFORMATION
# QUERY_FS Information Levels
# SMB_QUERY_FS_ATTRIBUTE_INFO
class SMBQueryFsAttributeInfo ( Structure ) :
structure = (
( ' FileSystemAttributes ' , ' <L ' ) ,
( ' MaxFilenNameLengthInBytes ' , ' <L ' ) ,
( ' LengthOfFileSystemName ' , ' <L-FileSystemName ' ) ,
( ' FileSystemName ' , ' : ' ) ,
)
class SMBQueryFsInfoVolume ( AsciiOrUnicodeStructure ) :
commonHdr = (
( ' ulVolSerialNbr ' , ' <L=0xABCDEFAA ' ) ,
( ' cCharCount ' , ' <B-VolumeLabel ' ) ,
)
AsciiStructure = (
( ' VolumeLabel ' , ' z ' ) ,
)
UnicodeStructure = (
( ' VolumeLabel ' , ' u ' ) ,
)
# FILE_FS_SIZE_INFORMATION
class FileFsSizeInformation ( Structure ) :
structure = (
( ' TotalAllocationUnits ' , ' <q=148529400 ' ) ,
( ' AvailableAllocationUnits ' , ' <q=14851044 ' ) ,
( ' SectorsPerAllocationUnit ' , ' <L=2 ' ) ,
( ' BytesPerSector ' , ' <L=512 ' ) ,
)
# SMB_QUERY_FS_SIZE_INFO
class SMBQueryFsSizeInfo ( Structure ) :
structure = (
( ' TotalAllocationUnits ' , ' <q=148529400 ' ) ,
( ' TotalFreeAllocationUnits ' , ' <q=14851044 ' ) ,
( ' SectorsPerAllocationUnit ' , ' <L=2 ' ) ,
( ' BytesPerSector ' , ' <L=512 ' ) ,
)
# FILE_FS_FULL_SIZE_INFORMATION
class SMBFileFsFullSizeInformation ( Structure ) :
structure = (
( ' TotalAllocationUnits ' , ' <q=148529400 ' ) ,
( ' CallerAvailableAllocationUnits ' , ' <q=148529400 ' ) ,
( ' ActualAvailableAllocationUnits ' , ' <q=148529400 ' ) ,
( ' SectorsPerAllocationUnit ' , ' <L=15 ' ) ,
( ' BytesPerSector ' , ' <L=512 ' )
)
# SMB_QUERY_FS_VOLUME_INFO
class SMBQueryFsVolumeInfo ( Structure ) :
structure = (
( ' VolumeCreationTime ' , ' <q ' ) ,
( ' SerialNumber ' , ' <L=0xABCDEFAA ' ) ,
( ' VolumeLabelSize ' , ' <L=len(VolumeLabel) ' ) ,
( ' Reserved ' , ' <H=0x10 ' ) ,
( ' VolumeLabel ' , ' : ' )
)
# SMB_FIND_FILE_BOTH_DIRECTORY_INFO level
class SMBFindFileBothDirectoryInfo ( AsciiOrUnicodeStructure ) :
commonHdr = (
( ' NextEntryOffset ' , ' <L=0 ' ) ,
( ' FileIndex ' , ' <L=0 ' ) ,
( ' CreationTime ' , ' <q ' ) ,
( ' LastAccessTime ' , ' <q ' ) ,
( ' LastWriteTime ' , ' <q ' ) ,
( ' LastChangeTime ' , ' <q ' ) ,
( ' EndOfFile ' , ' <q=0 ' ) ,
( ' AllocationSize ' , ' <q=0 ' ) ,
( ' ExtFileAttributes ' , ' <L=0 ' ) ,
)
AsciiStructure = (
( ' FileNameLength ' , ' <L-FileName ' , ' len(FileName) ' ) ,
( ' EaSize ' , ' <L=0 ' ) ,
( ' ShortNameLength ' , ' <B=0 ' ) ,
( ' Reserved ' , ' <B=0 ' ) ,
( ' ShortName ' , ' 24s ' ) ,
( ' FileName ' , ' : ' ) ,
)
UnicodeStructure = (
( ' FileNameLength ' , ' <L-FileName ' , ' len(FileName)*2 ' ) ,
( ' EaSize ' , ' <L=0 ' ) ,
( ' ShortNameLength ' , ' <B=0 ' ) ,
( ' Reserved ' , ' <B=0 ' ) ,
( ' ShortName ' , ' 24s ' ) ,
( ' FileName ' , ' : ' ) ,
)
# SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO level
class SMBFindFileIdFullDirectoryInfo ( AsciiOrUnicodeStructure ) :
commonHdr = (
( ' NextEntryOffset ' , ' <L=0 ' ) ,
( ' FileIndex ' , ' <L=0 ' ) ,
( ' CreationTime ' , ' <q ' ) ,
( ' LastAccessTime ' , ' <q ' ) ,
( ' LastWriteTime ' , ' <q ' ) ,
( ' LastChangeTime ' , ' <q ' ) ,
( ' EndOfFile ' , ' <q=0 ' ) ,
( ' AllocationSize ' , ' <q=0 ' ) ,
( ' ExtFileAttributes ' , ' <L=0 ' ) ,
)
AsciiStructure = (
( ' FileNameLength ' , ' <L-FileName ' , ' len(FileName) ' ) ,
( ' EaSize ' , ' <L=0 ' ) ,
( ' FileID ' , ' <q=0 ' ) ,
( ' FileName ' , ' : ' ) ,
)
UnicodeStructure = (
( ' FileNameLength ' , ' <L-FileName ' , ' len(FileName)*2 ' ) ,
( ' EaSize ' , ' <L=0 ' ) ,
( ' FileID ' , ' <q=0 ' ) ,
( ' FileName ' , ' : ' ) ,
)
# SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO level
class SMBFindFileIdBothDirectoryInfo ( AsciiOrUnicodeStructure ) :
commonHdr = (
( ' NextEntryOffset ' , ' <L=0 ' ) ,
( ' FileIndex ' , ' <L=0 ' ) ,
( ' CreationTime ' , ' <q ' ) ,
( ' LastAccessTime ' , ' <q ' ) ,
( ' LastWriteTime ' , ' <q ' ) ,
( ' LastChangeTime ' , ' <q ' ) ,
( ' EndOfFile ' , ' <q=0 ' ) ,
( ' AllocationSize ' , ' <q=0 ' ) ,
( ' ExtFileAttributes ' , ' <L=0 ' ) ,
)
AsciiStructure = (
( ' FileNameLength ' , ' <L-FileName ' , ' len(FileName) ' ) ,
( ' EaSize ' , ' <L=0 ' ) ,
( ' ShortNameLength ' , ' <B=0 ' ) ,
( ' Reserved ' , ' <B=0 ' ) ,
( ' ShortName ' , ' 24s ' ) ,
( ' Reserved ' , ' <H=0 ' ) ,
( ' FileID ' , ' <q=0 ' ) ,
( ' FileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' FileNameLength ' , ' <L-FileName ' , ' len(FileName)*2 ' ) ,
( ' EaSize ' , ' <L=0 ' ) ,
( ' ShortNameLength ' , ' <B=0 ' ) ,
( ' Reserved ' , ' <B=0 ' ) ,
( ' ShortName ' , ' 24s ' ) ,
( ' Reserved ' , ' <H=0 ' ) ,
( ' FileID ' , ' <q=0 ' ) ,
( ' FileName ' , ' : ' ) ,
)
# SMB_FIND_FILE_DIRECTORY_INFO level
class SMBFindFileDirectoryInfo ( AsciiOrUnicodeStructure ) :
commonHdr = (
( ' NextEntryOffset ' , ' <L=0 ' ) ,
( ' FileIndex ' , ' <L=0 ' ) ,
( ' CreationTime ' , ' <q ' ) ,
( ' LastAccessTime ' , ' <q ' ) ,
( ' LastWriteTime ' , ' <q ' ) ,
( ' LastChangeTime ' , ' <q ' ) ,
( ' EndOfFile ' , ' <q=0 ' ) ,
( ' AllocationSize ' , ' <q=1 ' ) ,
( ' ExtFileAttributes ' , ' <L=0 ' ) ,
)
AsciiStructure = (
( ' FileNameLength ' , ' <L-FileName ' , ' len(FileName) ' ) ,
( ' FileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' FileNameLength ' , ' <L-FileName ' , ' len(FileName)*2 ' ) ,
( ' FileName ' , ' : ' ) ,
)
# SMB_FIND_FILE_NAMES_INFO level
class SMBFindFileNamesInfo ( AsciiOrUnicodeStructure ) :
commonHdr = (
( ' NextEntryOffset ' , ' <L=0 ' ) ,
( ' FileIndex ' , ' <L=0 ' ) ,
)
AsciiStructure = (
( ' FileNameLength ' , ' <L-FileName ' , ' len(FileName) ' ) ,
( ' FileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' FileNameLength ' , ' <L-FileName ' , ' len(FileName)*2 ' ) ,
( ' FileName ' , ' : ' ) ,
)
# SMB_FIND_FILE_FULL_DIRECTORY_INFO level
class SMBFindFileFullDirectoryInfo ( AsciiOrUnicodeStructure ) :
commonHdr = (
( ' NextEntryOffset ' , ' <L=0 ' ) ,
( ' FileIndex ' , ' <L=0 ' ) ,
( ' CreationTime ' , ' <q ' ) ,
( ' LastAccessTime ' , ' <q ' ) ,
( ' LastWriteTime ' , ' <q ' ) ,
( ' LastChangeTime ' , ' <q ' ) ,
( ' EndOfFile ' , ' <q=0 ' ) ,
( ' AllocationSize ' , ' <q=1 ' ) ,
( ' ExtFileAttributes ' , ' <L=0 ' ) ,
)
AsciiStructure = (
( ' FileNameLength ' , ' <L-FileName ' , ' len(FileName) ' ) ,
( ' EaSize ' , ' <L ' ) ,
( ' FileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' FileNameLength ' , ' <L-FileName ' , ' len(FileName)*2 ' ) ,
( ' EaSize ' , ' <L ' ) ,
( ' FileName ' , ' : ' ) ,
)
# SMB_FIND_INFO_STANDARD level
class SMBFindInfoStandard ( AsciiOrUnicodeStructure ) :
commonHdr = (
( ' ResumeKey ' , ' <L=0xff ' ) ,
( ' CreationDate ' , ' <H=0 ' ) ,
( ' CreationTime ' , ' <H=0 ' ) ,
( ' LastAccessDate ' , ' <H=0 ' ) ,
( ' LastAccessTime ' , ' <H=0 ' ) ,
( ' LastWriteDate ' , ' <H=0 ' ) ,
( ' LastWriteTime ' , ' <H=0 ' ) ,
( ' EaSize ' , ' <L ' ) ,
( ' AllocationSize ' , ' <L=1 ' ) ,
( ' ExtFileAttributes ' , ' <H=0 ' ) ,
)
AsciiStructure = (
( ' FileNameLength ' , ' <B-FileName ' , ' len(FileName) ' ) ,
( ' FileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' FileNameLength ' , ' <B-FileName ' , ' len(FileName)*2 ' ) ,
( ' FileName ' , ' : ' ) ,
)
# SET_FILE_INFORMATION structures
# SMB_SET_FILE_DISPOSITION_INFO
class SMBSetFileDispositionInfo ( Structure ) :
structure = (
( ' DeletePending ' , ' <B ' ) ,
)
# SMB_SET_FILE_BASIC_INFO
class SMBSetFileBasicInfo ( Structure ) :
structure = (
( ' CreationTime ' , ' <q ' ) ,
( ' LastAccessTime ' , ' <q ' ) ,
( ' LastWriteTime ' , ' <q ' ) ,
( ' ChangeTime ' , ' <q ' ) ,
( ' ExtFileAttributes ' , ' <H ' ) ,
( ' Reserved ' , ' <L ' ) ,
)
# FILE_STREAM_INFORMATION
class SMBFileStreamInformation ( Structure ) :
commonHdr = (
( ' NextEntryOffset ' , ' <L=0 ' ) ,
( ' StreamNameLength ' , ' <L=0 ' ) ,
( ' StreamSize ' , ' <q=0 ' ) ,
( ' StreamAllocationSize ' , ' <q=0 ' ) ,
( ' StreamName ' , ' := " " ' ) ,
)
# FILE_NETWORK_OPEN_INFORMATION
class SMBFileNetworkOpenInfo ( Structure ) :
structure = (
( ' CreationTime ' , ' <q=0 ' ) ,
( ' LastAccessTime ' , ' <q=0 ' ) ,
( ' LastWriteTime ' , ' <q=0 ' ) ,
( ' ChangeTime ' , ' <q=0 ' ) ,
( ' AllocationSize ' , ' <q=0 ' ) ,
( ' EndOfFile ' , ' <q=0 ' ) ,
( ' FileAttributes ' , ' <L=0 ' ) ,
( ' Reserved ' , ' <L=0 ' ) ,
)
# SMB_SET_FILE_END_OF_FILE_INFO
class SMBSetFileEndOfFileInfo ( Structure ) :
structure = (
( ' EndOfFile ' , ' <q ' ) ,
)
# TRANS2_FIND_NEXT2
class SMBFindNext2_Parameters ( AsciiOrUnicodeStructure ) :
commonHdr = (
( ' SID ' , ' <H ' ) ,
( ' SearchCount ' , ' <H ' ) ,
( ' InformationLevel ' , ' <H ' ) ,
( ' ResumeKey ' , ' <L ' ) ,
( ' Flags ' , ' <H ' ) ,
)
AsciiStructure = (
( ' FileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' FileName ' , ' u ' ) ,
)
class SMBFindNext2Response_Parameters ( Structure ) :
structure = (
( ' SearchCount ' , ' <H ' ) ,
( ' EndOfSearch ' , ' <H=1 ' ) ,
( ' EaErrorOffset ' , ' <H=0 ' ) ,
( ' LastNameOffset ' , ' <H=0 ' ) ,
)
class SMBFindNext2_Data ( Structure ) :
structure = (
( ' GetExtendedAttributesListLength ' , ' _-GetExtendedAttributesList ' , ' self[ " GetExtendedAttributesListLength " ] ' ) ,
( ' GetExtendedAttributesList ' , ' : ' ) ,
)
# TRANS2_FIND_FIRST2
class SMBFindFirst2Response_Parameters ( Structure ) :
structure = (
( ' SID ' , ' <H ' ) ,
( ' SearchCount ' , ' <H ' ) ,
( ' EndOfSearch ' , ' <H=1 ' ) ,
( ' EaErrorOffset ' , ' <H=0 ' ) ,
( ' LastNameOffset ' , ' <H=0 ' ) ,
)
class SMBFindFirst2_Parameters ( AsciiOrUnicodeStructure ) :
commonHdr = (
( ' SearchAttributes ' , ' <H ' ) ,
( ' SearchCount ' , ' <H ' ) ,
( ' Flags ' , ' <H ' ) ,
( ' InformationLevel ' , ' <H ' ) ,
( ' SearchStorageType ' , ' <L ' ) ,
)
AsciiStructure = (
( ' FileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' FileName ' , ' u ' ) ,
)
class SMBFindFirst2_Data ( Structure ) :
structure = (
( ' GetExtendedAttributesListLength ' , ' _-GetExtendedAttributesList ' , ' self[ " GetExtendedAttributesListLength " ] ' ) ,
( ' GetExtendedAttributesList ' , ' : ' ) ,
)
# TRANS2_SET_PATH_INFORMATION
class SMBSetPathInformation_Parameters ( AsciiOrUnicodeStructure ) :
commonHdr = (
( ' InformationLevel ' , ' <H ' ) ,
( ' Reserved ' , ' <L ' ) ,
)
AsciiStructure = (
( ' FileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' FileName ' , ' u ' ) ,
)
class SMBSetPathInformationResponse_Parameters ( Structure ) :
structure = (
( ' EaErrorOffset ' , ' <H=0 ' ) ,
)
# TRANS2_SET_FILE_INFORMATION
class SMBSetFileInformation_Parameters ( Structure ) :
structure = (
( ' FID ' , ' <H ' ) ,
( ' InformationLevel ' , ' <H ' ) ,
( ' Reserved ' , ' <H ' ) ,
)
class SMBSetFileInformationResponse_Parameters ( Structure ) :
structure = (
( ' EaErrorOffset ' , ' <H=0 ' ) ,
)
# TRANS2_QUERY_FILE_INFORMATION
class SMBQueryFileInformation_Parameters ( Structure ) :
structure = (
( ' FID ' , ' <H ' ) ,
( ' InformationLevel ' , ' <H ' ) ,
)
class SMBQueryFileInformationResponse_Parameters ( Structure ) :
structure = (
( ' EaErrorOffset ' , ' <H=0 ' ) ,
)
class SMBQueryFileInformation_Data ( Structure ) :
structure = (
( ' GetExtendedAttributeList ' , ' : ' ) ,
)
# TRANS2_QUERY_PATH_INFORMATION
class SMBQueryPathInformationResponse_Parameters ( Structure ) :
structure = (
( ' EaErrorOffset ' , ' <H=0 ' ) ,
)
class SMBQueryPathInformation_Parameters ( AsciiOrUnicodeStructure ) :
commonHdr = (
( ' InformationLevel ' , ' <H ' ) ,
( ' Reserved ' , ' <L=0 ' ) ,
)
AsciiStructure = (
( ' FileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' FileName ' , ' u ' ) ,
)
class SMBQueryPathInformation_Data ( Structure ) :
structure = (
( ' GetExtendedAttributeList ' , ' : ' ) ,
)
# SMB_QUERY_FILE_EA_INFO
class SMBQueryFileEaInfo ( Structure ) :
structure = (
( ' EaSize ' , ' <L=0 ' ) ,
)
# SMB_QUERY_FILE_BASIC_INFO
class SMBQueryFileBasicInfo ( Structure ) :
structure = (
( ' CreationTime ' , ' <q ' ) ,
( ' LastAccessTime ' , ' <q ' ) ,
( ' LastWriteTime ' , ' <q ' ) ,
( ' LastChangeTime ' , ' <q ' ) ,
( ' ExtFileAttributes ' , ' <L ' ) ,
#('Reserved','<L=0'),
)
# SMB_QUERY_FILE_STANDARD_INFO
class SMBQueryFileStandardInfo ( Structure ) :
structure = (
( ' AllocationSize ' , ' <q ' ) ,
( ' EndOfFile ' , ' <q ' ) ,
( ' NumberOfLinks ' , ' <L=0 ' ) ,
( ' DeletePending ' , ' <B=0 ' ) ,
( ' Directory ' , ' <B ' ) ,
)
# SMB_QUERY_FILE_ALL_INFO
class SMBQueryFileAllInfo ( Structure ) :
structure = (
( ' CreationTime ' , ' <q ' ) ,
( ' LastAccessTime ' , ' <q ' ) ,
( ' LastWriteTime ' , ' <q ' ) ,
( ' LastChangeTime ' , ' <q ' ) ,
( ' ExtFileAttributes ' , ' <L ' ) ,
( ' Reserved ' , ' <L=0 ' ) ,
( ' AllocationSize ' , ' <q ' ) ,
( ' EndOfFile ' , ' <q ' ) ,
( ' NumberOfLinks ' , ' <L=0 ' ) ,
( ' DeletePending ' , ' <B=0 ' ) ,
( ' Directory ' , ' <B ' ) ,
( ' Reserved ' , ' <H=0 ' ) ,
( ' EaSize ' , ' <L=0 ' ) ,
( ' FileNameLength ' , ' <L-FileName ' , ' len(FileName) ' ) ,
( ' FileName ' , ' : ' ) ,
)
# \PIPE\LANMAN NetShareEnum
class SMBNetShareEnum ( Structure ) :
structure = (
( ' RAPOpcode ' , ' <H=0 ' ) ,
( ' ParamDesc ' , ' z ' ) ,
( ' DataDesc ' , ' z ' ) ,
( ' InfoLevel ' , ' <H ' ) ,
( ' ReceiveBufferSize ' , ' <H ' ) ,
)
class SMBNetShareEnumResponse ( Structure ) :
structure = (
( ' Status ' , ' <H=0 ' ) ,
( ' Convert ' , ' <H=0 ' ) ,
( ' EntriesReturned ' , ' <H ' ) ,
( ' EntriesAvailable ' , ' <H ' ) ,
)
class NetShareInfo1 ( Structure ) :
structure = (
( ' NetworkName ' , ' 13s ' ) ,
( ' Pad ' , ' <B=0 ' ) ,
( ' Type ' , ' <H=0 ' ) ,
( ' RemarkOffsetLow ' , ' <H=0 ' ) ,
( ' RemarkOffsetHigh ' , ' <H=0 ' ) ,
)
# \PIPE\LANMAN NetServerGetInfo
class SMBNetServerGetInfoResponse ( Structure ) :
structure = (
( ' Status ' , ' <H=0 ' ) ,
( ' Convert ' , ' <H=0 ' ) ,
( ' TotalBytesAvailable ' , ' <H ' ) ,
)
class SMBNetServerInfo1 ( Structure ) :
# Level 1 Response
structure = (
( ' ServerName ' , ' 16s ' ) ,
( ' MajorVersion ' , ' B=5 ' ) ,
( ' MinorVersion ' , ' B=0 ' ) ,
( ' ServerType ' , ' <L=3 ' ) ,
( ' ServerCommentLow ' , ' <H=0 ' ) ,
( ' ServerCommentHigh ' , ' <H=0 ' ) ,
)
# \PIPE\LANMAN NetShareGetInfo
class SMBNetShareGetInfo ( Structure ) :
structure = (
( ' RAPOpcode ' , ' <H=0 ' ) ,
( ' ParamDesc ' , ' z ' ) ,
( ' DataDesc ' , ' z ' ) ,
( ' ShareName ' , ' z ' ) ,
( ' InfoLevel ' , ' <H ' ) ,
( ' ReceiveBufferSize ' , ' <H ' ) ,
)
class SMBNetShareGetInfoResponse ( Structure ) :
structure = (
( ' Status ' , ' <H=0 ' ) ,
( ' Convert ' , ' <H=0 ' ) ,
( ' TotalBytesAvailable ' , ' <H ' ) ,
)
############# Security Features
class SecurityFeatures ( Structure ) :
structure = (
( ' Key ' , ' <L=0 ' ) ,
( ' CID ' , ' <H=0 ' ) ,
( ' SequenceNumber ' , ' <H=0 ' ) ,
)
############# SMB_COM_QUERY_INFORMATION2 (0x23)
class SMBQueryInformation2_Parameters ( Structure ) :
structure = (
( ' Fid ' , ' <H ' ) ,
)
class SMBQueryInformation2Response_Parameters ( Structure ) :
structure = (
( ' CreateDate ' , ' <H ' ) ,
( ' CreationTime ' , ' <H ' ) ,
( ' LastAccessDate ' , ' <H ' ) ,
( ' LastAccessTime ' , ' <H ' ) ,
( ' LastWriteDate ' , ' <H ' ) ,
( ' LastWriteTime ' , ' <H ' ) ,
( ' FileDataSize ' , ' <L ' ) ,
( ' FileAllocationSize ' , ' <L ' ) ,
( ' FileAttributes ' , ' <L ' ) ,
)
############# SMB_COM_SESSION_SETUP_ANDX (0x73)
class SMBSessionSetupAndX_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' MaxBuffer ' , ' <H ' ) ,
( ' MaxMpxCount ' , ' <H ' ) ,
( ' VCNumber ' , ' <H ' ) ,
( ' SessionKey ' , ' <L ' ) ,
( ' AnsiPwdLength ' , ' <H ' ) ,
( ' UnicodePwdLength ' , ' <H ' ) ,
( ' _reserved ' , ' <L=0 ' ) ,
( ' Capabilities ' , ' <L ' ) ,
)
class SMBSessionSetupAndX_Extended_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' MaxBufferSize ' , ' <H ' ) ,
( ' MaxMpxCount ' , ' <H ' ) ,
( ' VcNumber ' , ' <H ' ) ,
( ' SessionKey ' , ' <L ' ) ,
( ' SecurityBlobLength ' , ' <H ' ) ,
( ' Reserved ' , ' <L=0 ' ) ,
( ' Capabilities ' , ' <L ' ) ,
)
class SMBSessionSetupAndX_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' AnsiPwdLength ' , ' _-AnsiPwd ' , ' self[ " AnsiPwdLength " ] ' ) ,
( ' UnicodePwdLength ' , ' _-UnicodePwd ' , ' self[ " UnicodePwdLength " ] ' ) ,
( ' AnsiPwd ' , ' := " " ' ) ,
( ' UnicodePwd ' , ' := " " ' ) ,
( ' Account ' , ' z= " " ' ) ,
( ' PrimaryDomain ' , ' z= " " ' ) ,
( ' NativeOS ' , ' z= " " ' ) ,
( ' NativeLanMan ' , ' z= " " ' ) ,
)
UnicodeStructure = (
( ' AnsiPwdLength ' , ' _-AnsiPwd ' , ' self[ " AnsiPwdLength " ] ' ) ,
( ' UnicodePwdLength ' , ' _-UnicodePwd ' , ' self[ " UnicodePwdLength " ] ' ) ,
( ' AnsiPwd ' , ' := " " ' ) ,
( ' UnicodePwd ' , ' := " " ' ) ,
( ' Account ' , ' u= " " ' ) ,
( ' PrimaryDomain ' , ' u= " " ' ) ,
( ' NativeOS ' , ' u= " " ' ) ,
( ' NativeLanMan ' , ' u= " " ' ) ,
)
class SMBSessionSetupAndX_Extended_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' SecurityBlobLength ' , ' _-SecurityBlob ' , ' self[ " SecurityBlobLength " ] ' ) ,
( ' SecurityBlob ' , ' : ' ) ,
( ' NativeOS ' , ' z= " " ' ) ,
( ' NativeLanMan ' , ' z= " " ' ) ,
)
UnicodeStructure = (
( ' SecurityBlobLength ' , ' _-SecurityBlob ' , ' self[ " SecurityBlobLength " ] ' ) ,
( ' SecurityBlob ' , ' : ' ) ,
( ' NativeOS ' , ' u= " " ' ) ,
( ' NativeLanMan ' , ' u= " " ' ) ,
)
class SMBSessionSetupAndXResponse_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' Action ' , ' <H ' ) ,
)
class SMBSessionSetupAndX_Extended_Response_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' Action ' , ' <H=0 ' ) ,
( ' SecurityBlobLength ' , ' <H ' ) ,
)
class SMBSessionSetupAndXResponse_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' NativeOS ' , ' z= " " ' ) ,
( ' NativeLanMan ' , ' z= " " ' ) ,
( ' PrimaryDomain ' , ' z= " " ' ) ,
)
UnicodeStructure = (
( ' NativeOS ' , ' u= " " ' ) ,
( ' NativeLanMan ' , ' u= " " ' ) ,
( ' PrimaryDomain ' , ' u= " " ' ) ,
)
class SMBSessionSetupAndX_Extended_Response_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' SecurityBlobLength ' , ' _-SecurityBlob ' , ' self[ " SecurityBlobLength " ] ' ) ,
( ' SecurityBlob ' , ' : ' ) ,
( ' NativeOS ' , ' z= " " ' ) ,
( ' NativeLanMan ' , ' z= " " ' ) ,
)
UnicodeStructure = (
( ' SecurityBlobLength ' , ' _-SecurityBlob ' , ' self[ " SecurityBlobLength " ] ' ) ,
( ' SecurityBlob ' , ' : ' ) ,
( ' NativeOS ' , ' u= " " ' ) ,
( ' NativeLanMan ' , ' u= " " ' ) ,
)
############# SMB_COM_TREE_CONNECT (0x70)
class SMBTreeConnect_Parameters ( SMBCommand_Parameters ) :
structure = (
)
class SMBTreeConnect_Data ( SMBCommand_Parameters ) :
structure = (
( ' PathFormat ' , ' " \x04 ' ) ,
( ' Path ' , ' z ' ) ,
( ' PasswordFormat ' , ' " \x04 ' ) ,
( ' Password ' , ' z ' ) ,
( ' ServiceFormat ' , ' " \x04 ' ) ,
( ' Service ' , ' z ' ) ,
)
############# SMB_COM_TREE_CONNECT_ANDX (0x75)
class SMBTreeConnectAndX_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' Flags ' , ' <H=0 ' ) ,
( ' PasswordLength ' , ' <H ' ) ,
)
class SMBTreeConnectAndXResponse_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' OptionalSupport ' , ' <H=0 ' ) ,
)
class SMBTreeConnectAndXExtendedResponse_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' OptionalSupport ' , ' <H=1 ' ) ,
( ' MaximalShareAccessRights ' , ' <L=0x1fffff ' ) ,
( ' GuestMaximalShareAccessRights ' , ' <L=0x1fffff ' ) ,
)
class SMBTreeConnectAndX_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' _PasswordLength ' , ' _-Password ' , ' self[ " _PasswordLength " ] ' ) ,
( ' Password ' , ' : ' ) ,
( ' Path ' , ' z ' ) ,
( ' Service ' , ' z ' ) ,
)
UnicodeStructure = (
( ' _PasswordLength ' , ' _-Password ' , ' self[ " _PasswordLength " ] if self[ " _PasswordLength " ] > 0 else 1 ' ) ,
( ' Password ' , ' : ' ) ,
( ' Path ' , ' u ' ) ,
( ' Service ' , ' z ' ) ,
)
class SMBTreeConnectAndXResponse_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' Service ' , ' z ' ) ,
( ' PadLen ' , ' _-Pad ' , ' self[ " PadLen " ] ' ) ,
( ' Pad ' , ' := " " ' ) ,
( ' NativeFileSystem ' , ' z ' ) ,
)
UnicodeStructure = (
( ' Service ' , ' z ' ) ,
( ' PadLen ' , ' _-Pad ' , ' self[ " PadLen " ] ' ) ,
( ' Pad ' , ' := " " ' ) ,
( ' NativeFileSystem ' , ' u ' ) ,
)
############# SMB_COM_NT_CREATE_ANDX (0xA2)
class SMBNtCreateAndX_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' _reserved ' , ' B=0 ' ) ,
( ' FileNameLength ' , ' <H ' ) , # NameLength
( ' CreateFlags ' , ' <L ' ) , # Flags
( ' RootFid ' , ' <L=0 ' ) , # RootDirectoryFID
( ' AccessMask ' , ' <L ' ) , # DesiredAccess
( ' AllocationSizeLo ' , ' <L=0 ' ) , # AllocationSize
( ' AllocationSizeHi ' , ' <L=0 ' ) ,
( ' FileAttributes ' , ' <L=0 ' ) , # ExtFileAttributes
( ' ShareAccess ' , ' <L=3 ' ) , #
( ' Disposition ' , ' <L=1 ' ) , # CreateDisposition
( ' CreateOptions ' , ' <L ' ) , # CreateOptions
( ' Impersonation ' , ' <L=2 ' ) ,
( ' SecurityFlags ' , ' B=3 ' ) ,
)
class SMBNtCreateAndXResponse_Parameters ( SMBAndXCommand_Parameters ) :
# XXX Is there a memory leak in the response for NTCreate (where the Data section would be) in Win 2000, Win XP, and Win 2003?
structure = (
( ' OplockLevel ' , ' B=0 ' ) ,
( ' Fid ' , ' <H ' ) ,
( ' CreateAction ' , ' <L ' ) ,
( ' CreateTime ' , ' <q=0 ' ) ,
( ' LastAccessTime ' , ' <q=0 ' ) ,
( ' LastWriteTime ' , ' <q=0 ' ) ,
( ' LastChangeTime ' , ' <q=0 ' ) ,
( ' FileAttributes ' , ' <L=0x80 ' ) ,
( ' AllocationSize ' , ' <q=0 ' ) ,
( ' EndOfFile ' , ' <q=0 ' ) ,
( ' FileType ' , ' <H=0 ' ) ,
( ' IPCState ' , ' <H=0 ' ) ,
( ' IsDirectory ' , ' B ' ) ,
)
class SMBNtCreateAndXExtendedResponse_Parameters ( SMBAndXCommand_Parameters ) :
# [MS-SMB] Extended response description
structure = (
( ' OplockLevel ' , ' B=0 ' ) ,
( ' Fid ' , ' <H ' ) ,
( ' CreateAction ' , ' <L ' ) ,
( ' CreateTime ' , ' <q=0 ' ) ,
( ' LastAccessTime ' , ' <q=0 ' ) ,
( ' LastWriteTime ' , ' <q=0 ' ) ,
( ' LastChangeTime ' , ' <q=0 ' ) ,
( ' FileAttributes ' , ' <L=0x80 ' ) ,
( ' AllocationSize ' , ' <q=0 ' ) ,
( ' EndOfFile ' , ' <q=0 ' ) ,
( ' FileType ' , ' <H=0 ' ) ,
( ' IPCState ' , ' <H=0 ' ) ,
( ' IsDirectory ' , ' B ' ) ,
( ' VolumeGUID ' , ' 16s ' ) ,
( ' FileIdLow ' , ' <L=0 ' ) ,
( ' FileIdHigh ' , ' <L=0 ' ) ,
( ' MaximalAccessRights ' , ' <L=0x12019b ' ) ,
( ' GuestMaximalAccessRights ' , ' <L=0x120089 ' ) ,
)
class SMBNtCreateAndX_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' FileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' Pad ' , ' B ' ) ,
( ' FileName ' , ' u ' ) ,
)
############# SMB_COM_OPEN_ANDX (0xD2)
class SMBOpenAndX_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' Flags ' , ' <H=0 ' ) ,
( ' DesiredAccess ' , ' <H=0 ' ) ,
( ' SearchAttributes ' , ' <H=0 ' ) ,
( ' FileAttributes ' , ' <H=0 ' ) ,
( ' CreationTime ' , ' <L=0 ' ) ,
( ' OpenMode ' , ' <H=1 ' ) , # SMB_O_OPEN = 1
( ' AllocationSize ' , ' <L=0 ' ) ,
( ' Reserved ' , ' 8s= " " ' ) ,
)
class SMBOpenAndX_Data ( SMBNtCreateAndX_Data ) :
pass
class SMBOpenAndXResponse_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' Fid ' , ' <H=0 ' ) ,
( ' FileAttributes ' , ' <H=0 ' ) ,
( ' LastWriten ' , ' <L=0 ' ) ,
( ' FileSize ' , ' <L=0 ' ) ,
( ' GrantedAccess ' , ' <H=0 ' ) ,
( ' FileType ' , ' <H=0 ' ) ,
( ' IPCState ' , ' <H=0 ' ) ,
( ' Action ' , ' <H=0 ' ) ,
( ' ServerFid ' , ' <L=0 ' ) ,
( ' _reserved ' , ' <H=0 ' ) ,
)
############# SMB_COM_WRITE (0x0B)
class SMBWrite_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' Fid ' , ' <H ' ) ,
( ' Count ' , ' <H ' ) ,
( ' Offset ' , ' <L ' ) ,
( ' Remaining ' , ' <H ' ) ,
)
class SMBWriteResponse_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' Count ' , ' <H ' ) ,
)
class SMBWrite_Data ( Structure ) :
structure = (
( ' BufferFormat ' , ' <B=1 ' ) ,
( ' DataLength ' , ' <H-Data ' ) ,
( ' Data ' , ' : ' ) ,
)
############# SMB_COM_WRITE_ANDX (0x2F)
class SMBWriteAndX_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' Fid ' , ' <H=0 ' ) ,
( ' Offset ' , ' <L=0 ' ) ,
( ' _reserved ' , ' <L=0xff ' ) ,
( ' WriteMode ' , ' <H=8 ' ) ,
( ' Remaining ' , ' <H=0 ' ) ,
( ' DataLength_Hi ' , ' <H=0 ' ) ,
( ' DataLength ' , ' <H=0 ' ) ,
( ' DataOffset ' , ' <H=0 ' ) ,
( ' HighOffset ' , ' <L=0 ' ) ,
)
class SMBWriteAndX_Data_Short ( Structure ) :
structure = (
( ' _PadLen ' , ' _-Pad ' , ' self[ " DataOffset " ] - 59 ' ) ,
( ' Pad ' , ' : ' ) ,
#('Pad','<B=0'),
( ' DataLength ' , ' _-Data ' , ' self[ " DataLength " ] ' ) ,
( ' Data ' , ' : ' ) ,
)
class SMBWriteAndX_Data ( Structure ) :
structure = (
( ' _PadLen ' , ' _-Pad ' , ' self[ " DataOffset " ] - 63 ' ) ,
( ' Pad ' , ' : ' ) ,
#('Pad','<B=0'),
( ' DataLength ' , ' _-Data ' , ' self[ " DataLength " ] ' ) ,
( ' Data ' , ' : ' ) ,
)
class SMBWriteAndX_Parameters_Short ( SMBAndXCommand_Parameters ) :
structure = (
( ' Fid ' , ' <H ' ) ,
( ' Offset ' , ' <L ' ) ,
( ' _reserved ' , ' <L=0xff ' ) ,
( ' WriteMode ' , ' <H=8 ' ) ,
( ' Remaining ' , ' <H ' ) ,
( ' DataLength_Hi ' , ' <H=0 ' ) ,
( ' DataLength ' , ' <H ' ) ,
( ' DataOffset ' , ' <H=0 ' ) ,
)
class SMBWriteAndXResponse_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' Count ' , ' <H ' ) ,
( ' Available ' , ' <H ' ) ,
( ' Reserved ' , ' <L=0 ' ) ,
)
############# SMB_COM_WRITE_RAW (0x1D)
class SMBWriteRaw_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' Fid ' , ' <H ' ) ,
( ' Count ' , ' <H ' ) ,
( ' _reserved ' , ' <H=0 ' ) ,
( ' Offset ' , ' <L ' ) ,
( ' Timeout ' , ' <L=0 ' ) ,
( ' WriteMode ' , ' <H=0 ' ) ,
( ' _reserved2 ' , ' <L=0 ' ) ,
( ' DataLength ' , ' <H ' ) ,
( ' DataOffset ' , ' <H=0 ' ) ,
)
############# SMB_COM_READ (0x0A)
class SMBRead_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' Fid ' , ' <H ' ) ,
( ' Count ' , ' <H ' ) ,
( ' Offset ' , ' <L ' ) ,
( ' Remaining ' , ' <H=Count ' ) ,
)
class SMBReadResponse_Parameters ( Structure ) :
structure = (
( ' Count ' , ' <H=0 ' ) ,
( ' _reserved ' , ' 8s= " " ' ) ,
)
class SMBReadResponse_Data ( Structure ) :
structure = (
( ' BufferFormat ' , ' <B=0x1 ' ) ,
( ' DataLength ' , ' <H-Data ' ) ,
( ' Data ' , ' : ' ) ,
)
############# SMB_COM_READ_RAW (0x1A)
class SMBReadRaw_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' Fid ' , ' <H ' ) ,
( ' Offset ' , ' <L ' ) ,
( ' MaxCount ' , ' <H ' ) ,
( ' MinCount ' , ' <H=MaxCount ' ) ,
( ' Timeout ' , ' <L=0 ' ) ,
( ' _reserved ' , ' <H=0 ' ) ,
)
############# SMB_COM_NT_TRANSACT (0xA0)
class SMBNTTransaction_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' MaxSetupCount ' , ' <B=0 ' ) ,
( ' Reserved1 ' , ' <H=0 ' ) ,
( ' TotalParameterCount ' , ' <L ' ) ,
( ' TotalDataCount ' , ' <L ' ) ,
( ' MaxParameterCount ' , ' <L=1024 ' ) ,
( ' MaxDataCount ' , ' <L=65504 ' ) ,
( ' ParameterCount ' , ' <L ' ) ,
( ' ParameterOffset ' , ' <L ' ) ,
( ' DataCount ' , ' <L ' ) ,
( ' DataOffset ' , ' <L ' ) ,
( ' SetupCount ' , ' <B=len(Setup)/2 ' ) ,
( ' Function ' , ' <H=0 ' ) ,
( ' SetupLength ' , ' _-Setup ' , ' SetupCount*2 ' ) ,
( ' Setup ' , ' : ' ) ,
)
class SMBNTTransactionResponse_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' Reserved1 ' , ' 3s= " " ' ) ,
( ' TotalParameterCount ' , ' <L ' ) ,
( ' TotalDataCount ' , ' <L ' ) ,
( ' ParameterCount ' , ' <L ' ) ,
( ' ParameterOffset ' , ' <L ' ) ,
( ' ParameterDisplacement ' , ' <L=0 ' ) ,
( ' DataCount ' , ' <L ' ) ,
( ' DataOffset ' , ' <L ' ) ,
( ' DataDisplacement ' , ' <L=0 ' ) ,
( ' SetupCount ' , ' <B=0 ' ) ,
( ' SetupLength ' , ' _-Setup ' , ' SetupCount*2 ' ) ,
( ' Setup ' , ' : ' ) ,
)
class SMBNTTransaction_Data ( Structure ) :
structure = (
( ' Pad1Length ' , ' _-Pad1 ' , ' self[ " Pad1Length " ] ' ) ,
( ' Pad1 ' , ' : ' ) ,
( ' NT_Trans_ParametersLength ' , ' _-NT_Trans_Parameters ' , ' self[ " NT_Trans_ParametersLength " ] ' ) ,
( ' NT_Trans_Parameters ' , ' : ' ) ,
( ' Pad2Length ' , ' _-Pad2 ' , ' self[ " Pad2Length " ] ' ) ,
( ' Pad2 ' , ' : ' ) ,
( ' NT_Trans_DataLength ' , ' _-NT_Trans_Data ' , ' self[ " NT_Trans_DataLength " ] ' ) ,
( ' NT_Trans_Data ' , ' : ' ) ,
)
class SMBNTTransactionResponse_Data ( Structure ) :
structure = (
( ' Pad1Length ' , ' _-Pad1 ' , ' self[ " Pad1Length " ] ' ) ,
( ' Pad1 ' , ' : ' ) ,
( ' Trans_ParametersLength ' , ' _-Trans_Parameters ' , ' self[ " Trans_ParametersLength " ] ' ) ,
( ' Trans_Parameters ' , ' : ' ) ,
( ' Pad2Length ' , ' _-Pad2 ' , ' self[ " Pad2Length " ] ' ) ,
( ' Pad2 ' , ' : ' ) ,
( ' Trans_DataLength ' , ' _-Trans_Data ' , ' self[ " Trans_DataLength " ] ' ) ,
( ' Trans_Data ' , ' : ' ) ,
)
############# SMB_COM_TRANSACTION2_SECONDARY (0x33)
class SMBTransaction2Secondary_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' TotalParameterCount ' , ' <H ' ) ,
( ' TotalDataCount ' , ' <H ' ) ,
( ' ParameterCount ' , ' <H ' ) ,
( ' ParameterOffset ' , ' <H ' ) ,
( ' DataCount ' , ' <H ' ) ,
( ' DataOffset ' , ' <H ' ) ,
( ' DataDisplacement ' , ' <H=0 ' ) ,
( ' FID ' , ' <H ' ) ,
)
class SMBTransaction2Secondary_Data ( Structure ) :
structure = (
( ' Pad1Length ' , ' _-Pad1 ' , ' self[ " Pad1Length " ] ' ) ,
( ' Pad1 ' , ' : ' ) ,
( ' Trans_ParametersLength ' , ' _-Trans_Parameters ' , ' self[ " Trans_ParametersLength " ] ' ) ,
( ' Trans_Parameters ' , ' : ' ) ,
( ' Pad2Length ' , ' _-Pad2 ' , ' self[ " Pad2Length " ] ' ) ,
( ' Pad2 ' , ' : ' ) ,
( ' Trans_DataLength ' , ' _-Trans_Data ' , ' self[ " Trans_DataLength " ] ' ) ,
( ' Trans_Data ' , ' : ' ) ,
)
############# SMB_COM_TRANSACTION2 (0x32)
class SMBTransaction2_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' TotalParameterCount ' , ' <H ' ) ,
( ' TotalDataCount ' , ' <H ' ) ,
( ' MaxParameterCount ' , ' <H=1024 ' ) ,
( ' MaxDataCount ' , ' <H=65504 ' ) ,
( ' MaxSetupCount ' , ' <B=0 ' ) ,
( ' Reserved1 ' , ' <B=0 ' ) ,
( ' Flags ' , ' <H=0 ' ) ,
( ' Timeout ' , ' <L=0 ' ) ,
( ' Reserved2 ' , ' <H=0 ' ) ,
( ' ParameterCount ' , ' <H ' ) ,
( ' ParameterOffset ' , ' <H ' ) ,
( ' DataCount ' , ' <H ' ) ,
( ' DataOffset ' , ' <H ' ) ,
( ' SetupCount ' , ' <B=len(Setup)/2 ' ) ,
( ' Reserved3 ' , ' <B=0 ' ) ,
( ' SetupLength ' , ' _-Setup ' , ' SetupCount*2 ' ) ,
( ' Setup ' , ' : ' ) ,
)
class SMBTransaction2Response_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' TotalParameterCount ' , ' <H ' ) ,
( ' TotalDataCount ' , ' <H ' ) ,
( ' Reserved1 ' , ' <H=0 ' ) ,
( ' ParameterCount ' , ' <H ' ) ,
( ' ParameterOffset ' , ' <H ' ) ,
( ' ParameterDisplacement ' , ' <H=0 ' ) ,
( ' DataCount ' , ' <H ' ) ,
( ' DataOffset ' , ' <H ' ) ,
( ' DataDisplacement ' , ' <H=0 ' ) ,
( ' SetupCount ' , ' <B=0 ' ) ,
( ' Reserved2 ' , ' <B=0 ' ) ,
( ' SetupLength ' , ' _-Setup ' , ' SetupCount*2 ' ) ,
( ' Setup ' , ' : ' ) ,
)
class SMBTransaction2_Data ( Structure ) :
structure = (
# ('NameLength','_-Name','1'),
# ('Name',':'),
( ' Pad1Length ' , ' _-Pad1 ' , ' self[ " Pad1Length " ] ' ) ,
( ' Pad1 ' , ' : ' ) ,
( ' Trans_ParametersLength ' , ' _-Trans_Parameters ' , ' self[ " Trans_ParametersLength " ] ' ) ,
( ' Trans_Parameters ' , ' : ' ) ,
( ' Pad2Length ' , ' _-Pad2 ' , ' self[ " Pad2Length " ] ' ) ,
( ' Pad2 ' , ' : ' ) ,
( ' Trans_DataLength ' , ' _-Trans_Data ' , ' self[ " Trans_DataLength " ] ' ) ,
( ' Trans_Data ' , ' : ' ) ,
)
class SMBTransaction2Response_Data ( Structure ) :
structure = (
( ' Pad1Length ' , ' _-Pad1 ' , ' self[ " Pad1Length " ] ' ) ,
( ' Pad1 ' , ' : ' ) ,
( ' Trans_ParametersLength ' , ' _-Trans_Parameters ' , ' self[ " Trans_ParametersLength " ] ' ) ,
( ' Trans_Parameters ' , ' : ' ) ,
( ' Pad2Length ' , ' _-Pad2 ' , ' self[ " Pad2Length " ] ' ) ,
( ' Pad2 ' , ' : ' ) ,
( ' Trans_DataLength ' , ' _-Trans_Data ' , ' self[ " Trans_DataLength " ] ' ) ,
( ' Trans_Data ' , ' : ' ) ,
)
############# SMB_COM_QUERY_INFORMATION (0x08)
class SMBQueryInformation_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' BufferFormat ' , ' B=4 ' ) ,
( ' FileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' BufferFormat ' , ' B=4 ' ) ,
( ' FileName ' , ' u ' ) ,
)
class SMBQueryInformationResponse_Parameters ( Structure ) :
structure = (
( ' FileAttributes ' , ' <H ' ) ,
( ' LastWriteTime ' , ' <L ' ) ,
( ' FileSize ' , ' <L ' ) ,
( ' Reserved ' , ' " 0123456789 ' ) ,
)
############# SMB_COM_TRANSACTION (0x25)
class SMBTransaction_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' TotalParameterCount ' , ' <H ' ) ,
( ' TotalDataCount ' , ' <H ' ) ,
( ' MaxParameterCount ' , ' <H=1024 ' ) ,
( ' MaxDataCount ' , ' <H=65504 ' ) ,
( ' MaxSetupCount ' , ' <B=0 ' ) ,
( ' Reserved1 ' , ' <B=0 ' ) ,
( ' Flags ' , ' <H=0 ' ) ,
( ' Timeout ' , ' <L=0 ' ) ,
( ' Reserved2 ' , ' <H=0 ' ) ,
( ' ParameterCount ' , ' <H ' ) ,
( ' ParameterOffset ' , ' <H ' ) ,
( ' DataCount ' , ' <H ' ) ,
( ' DataOffset ' , ' <H ' ) ,
( ' SetupCount ' , ' <B=len(Setup)/2 ' ) ,
( ' Reserved3 ' , ' <B=0 ' ) ,
( ' SetupLength ' , ' _-Setup ' , ' SetupCount*2 ' ) ,
( ' Setup ' , ' : ' ) ,
)
class SMBTransactionResponse_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' TotalParameterCount ' , ' <H ' ) ,
( ' TotalDataCount ' , ' <H ' ) ,
( ' Reserved1 ' , ' <H=0 ' ) ,
( ' ParameterCount ' , ' <H ' ) ,
( ' ParameterOffset ' , ' <H ' ) ,
( ' ParameterDisplacement ' , ' <H=0 ' ) ,
( ' DataCount ' , ' <H ' ) ,
( ' DataOffset ' , ' <H ' ) ,
( ' DataDisplacement ' , ' <H=0 ' ) ,
( ' SetupCount ' , ' <B ' ) ,
( ' Reserved2 ' , ' <B=0 ' ) ,
( ' SetupLength ' , ' _-Setup ' , ' SetupCount*2 ' ) ,
( ' Setup ' , ' : ' ) ,
)
# TODO: We should merge these both. But this will require fixing
# the instances where this structure is used on the client side
class SMBTransaction_SData ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' Name ' , ' z ' ) ,
( ' Trans_ParametersLength ' , ' _-Trans_Parameters ' ) ,
( ' Trans_Parameters ' , ' : ' ) ,
( ' Trans_DataLength ' , ' _-Trans_Data ' ) ,
( ' Trans_Data ' , ' : ' ) ,
)
UnicodeStructure = (
( ' Pad ' , ' B ' ) ,
( ' Name ' , ' u ' ) ,
( ' Trans_ParametersLength ' , ' _-Trans_Parameters ' ) ,
( ' Trans_Parameters ' , ' : ' ) ,
( ' Trans_DataLength ' , ' _-Trans_Data ' ) ,
( ' Trans_Data ' , ' : ' ) ,
)
class SMBTransaction_Data ( Structure ) :
structure = (
( ' NameLength ' , ' _-Name ' ) ,
( ' Name ' , ' : ' ) ,
( ' Trans_ParametersLength ' , ' _-Trans_Parameters ' ) ,
( ' Trans_Parameters ' , ' : ' ) ,
( ' Trans_DataLength ' , ' _-Trans_Data ' ) ,
( ' Trans_Data ' , ' : ' ) ,
)
class SMBTransactionResponse_Data ( Structure ) :
structure = (
( ' Trans_ParametersLength ' , ' _-Trans_Parameters ' ) ,
( ' Trans_Parameters ' , ' : ' ) ,
( ' Trans_DataLength ' , ' _-Trans_Data ' ) ,
( ' Trans_Data ' , ' : ' ) ,
)
############# SMB_COM_READ_ANDX (0x2E)
class SMBReadAndX_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' Fid ' , ' <H ' ) ,
( ' Offset ' , ' <L ' ) ,
( ' MaxCount ' , ' <H ' ) ,
( ' MinCount ' , ' <H=MaxCount ' ) ,
( ' _reserved ' , ' <L=0x0 ' ) ,
( ' Remaining ' , ' <H=MaxCount ' ) ,
( ' HighOffset ' , ' <L=0 ' ) ,
)
class SMBReadAndX_Parameters2 ( SMBAndXCommand_Parameters ) :
structure = (
( ' Fid ' , ' <H ' ) ,
( ' Offset ' , ' <L ' ) ,
( ' MaxCount ' , ' <H ' ) ,
( ' MinCount ' , ' <H=MaxCount ' ) ,
( ' _reserved ' , ' <L=0xffffffff ' ) ,
( ' Remaining ' , ' <H=MaxCount ' ) ,
)
class SMBReadAndXResponse_Parameters ( SMBAndXCommand_Parameters ) :
structure = (
( ' Remaining ' , ' <H=0 ' ) ,
( ' DataMode ' , ' <H=0 ' ) ,
( ' _reserved ' , ' <H=0 ' ) ,
( ' DataCount ' , ' <H ' ) ,
( ' DataOffset ' , ' <H ' ) ,
( ' DataCount_Hi ' , ' <L ' ) ,
( ' _reserved2 ' , ' 6s= " " ' ) ,
)
############# SMB_COM_ECHO (0x2B)
class SMBEcho_Data ( Structure ) :
structure = (
( ' Data ' , ' : ' ) ,
)
class SMBEcho_Parameters ( Structure ) :
structure = (
( ' EchoCount ' , ' <H ' ) ,
)
class SMBEchoResponse_Data ( Structure ) :
structure = (
( ' Data ' , ' : ' ) ,
)
class SMBEchoResponse_Parameters ( Structure ) :
structure = (
( ' SequenceNumber ' , ' <H=1 ' ) ,
)
############# SMB_COM_QUERY_INFORMATION_DISK (0x80)
class SMBQueryInformationDiskResponse_Parameters ( Structure ) :
structure = (
( ' TotalUnits ' , ' <H ' ) ,
( ' BlocksPerUnit ' , ' <H ' ) ,
( ' BlockSize ' , ' <H ' ) ,
( ' FreeUnits ' , ' <H ' ) ,
( ' Reserved ' , ' <H=0 ' ) ,
)
############# SMB_COM_LOGOFF_ANDX (0x74)
class SMBLogOffAndX ( SMBAndXCommand_Parameters ) :
strucure = ( )
############# SMB_COM_CLOSE (0x04)
class SMBClose_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' FID ' , ' <H ' ) ,
( ' Time ' , ' <L=0 ' ) ,
)
############# SMB_COM_FLUSH (0x05)
class SMBFlush_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' FID ' , ' <H ' ) ,
)
############# SMB_COM_CREATE_DIRECTORY (0x00)
class SMBCreateDirectory_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' BufferFormat ' , ' <B=4 ' ) ,
( ' DirectoryName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' BufferFormat ' , ' <B=4 ' ) ,
( ' DirectoryName ' , ' u ' ) ,
)
############# SMB_COM_DELETE (0x06)
class SMBDelete_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' BufferFormat ' , ' <B=4 ' ) ,
( ' FileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' BufferFormat ' , ' <B=4 ' ) ,
( ' FileName ' , ' u ' ) ,
)
class SMBDelete_Parameters ( Structure ) :
structure = (
( ' SearchAttributes ' , ' <H ' ) ,
)
############# SMB_COM_DELETE_DIRECTORY (0x01)
class SMBDeleteDirectory_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' BufferFormat ' , ' <B=4 ' ) ,
( ' DirectoryName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' BufferFormat ' , ' <B=4 ' ) ,
( ' DirectoryName ' , ' u ' ) ,
)
############# SMB_COM_CHECK_DIRECTORY (0x10)
class SMBCheckDirectory_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' BufferFormat ' , ' <B=4 ' ) ,
( ' DirectoryName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' BufferFormat ' , ' <B=4 ' ) ,
( ' DirectoryName ' , ' u ' ) ,
)
############# SMB_COM_RENAME (0x07)
class SMBRename_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' SearchAttributes ' , ' <H ' ) ,
)
class SMBRename_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' BufferFormat1 ' , ' <B=4 ' ) ,
( ' OldFileName ' , ' z ' ) ,
( ' BufferFormat2 ' , ' <B=4 ' ) ,
( ' NewFileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' BufferFormat1 ' , ' <B=4 ' ) ,
( ' OldFileName ' , ' u ' ) ,
( ' BufferFormat2 ' , ' <B=4 ' ) ,
( ' Pad ' , ' B=0 ' ) ,
( ' NewFileName ' , ' u ' ) ,
)
############# SMB_COM_OPEN (0x02)
class SMBOpen_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' DesiredAccess ' , ' <H=0 ' ) ,
( ' SearchAttributes ' , ' <H=0 ' ) ,
)
class SMBOpen_Data ( AsciiOrUnicodeStructure ) :
AsciiStructure = (
( ' FileNameFormat ' , ' " \x04 ' ) ,
( ' FileName ' , ' z ' ) ,
)
UnicodeStructure = (
( ' FileNameFormat ' , ' " \x04 ' ) ,
( ' FileName ' , ' z ' ) ,
)
class SMBOpenResponse_Parameters ( SMBCommand_Parameters ) :
structure = (
( ' Fid ' , ' <H=0 ' ) ,
( ' FileAttributes ' , ' <H=0 ' ) ,
( ' LastWriten ' , ' <L=0 ' ) ,
( ' FileSize ' , ' <L=0 ' ) ,
( ' GrantedAccess ' , ' <H=0 ' ) ,
)
############# EXTENDED SECURITY CLASSES
class SMBExtended_Security_Parameters ( Structure ) :
structure = (
( ' DialectIndex ' , ' <H ' ) ,
( ' SecurityMode ' , ' <B ' ) ,
( ' MaxMpxCount ' , ' <H ' ) ,
( ' MaxNumberVcs ' , ' <H ' ) ,
( ' MaxBufferSize ' , ' <L ' ) ,
( ' MaxRawSize ' , ' <L ' ) ,
( ' SessionKey ' , ' <L ' ) ,
( ' Capabilities ' , ' <L ' ) ,
( ' LowDateTime ' , ' <L ' ) ,
( ' HighDateTime ' , ' <L ' ) ,
( ' ServerTimeZone ' , ' <H ' ) ,
( ' ChallengeLength ' , ' <B ' ) ,
)
class SMBExtended_Security_Data ( Structure ) :
structure = (
( ' ServerGUID ' , ' 16s ' ) ,
( ' SecurityBlob ' , ' : ' ) ,
)
class SMBNTLMDialect_Parameters ( Structure ) :
structure = (
( ' DialectIndex ' , ' <H ' ) ,
( ' SecurityMode ' , ' <B ' ) ,
( ' MaxMpxCount ' , ' <H ' ) ,
( ' MaxNumberVcs ' , ' <H ' ) ,
( ' MaxBufferSize ' , ' <L ' ) ,
( ' MaxRawSize ' , ' <L ' ) ,
( ' SessionKey ' , ' <L ' ) ,
( ' Capabilities ' , ' <L ' ) ,
( ' LowDateTime ' , ' <L ' ) ,
( ' HighDateTime ' , ' <L ' ) ,
( ' ServerTimeZone ' , ' <H ' ) ,
( ' ChallengeLength ' , ' <B ' ) ,
)
class SMBNTLMDialect_Data ( Structure ) :
structure = (
( ' ChallengeLength ' , ' _-Challenge ' , ' self[ " ChallengeLength " ] ' ) ,
( ' Challenge ' , ' : ' ) ,
( ' Payload ' , ' : ' ) ,
# For some reason on an old Linux this field is not present, we have to check this out. There must be a flag stating this.
( ' DomainName ' , ' _ ' ) ,
( ' ServerName ' , ' _ ' ) ,
)
def __init__ ( self , data = None , alignment = 0 ) :
Structure . __init__ ( self , data , alignment )
#self['ChallengeLength']=8
def fromString ( self , data ) :
Structure . fromString ( self , data )
self [ ' DomainName ' ] = ' '
self [ ' ServerName ' ] = ' '
class SMB :
# SMB Command Codes
SMB_COM_CREATE_DIRECTORY = 0x00
SMB_COM_DELETE_DIRECTORY = 0x01
SMB_COM_OPEN = 0x02
SMB_COM_CREATE = 0x03
SMB_COM_CLOSE = 0x04
SMB_COM_FLUSH = 0x05
SMB_COM_DELETE = 0x06
SMB_COM_RENAME = 0x07
SMB_COM_QUERY_INFORMATION = 0x08
SMB_COM_SET_INFORMATION = 0x09
SMB_COM_READ = 0x0A
SMB_COM_WRITE = 0x0B
SMB_COM_LOCK_BYTE_RANGE = 0x0C
SMB_COM_UNLOCK_BYTE_RANGE = 0x0D
SMB_COM_CREATE_TEMPORARY = 0x0E
SMB_COM_CREATE_NEW = 0x0F
SMB_COM_CHECK_DIRECTORY = 0x10
SMB_COM_PROCESS_EXIT = 0x11
SMB_COM_SEEK = 0x12
SMB_COM_LOCK_AND_READ = 0x13
SMB_COM_WRITE_AND_UNLOCK = 0x14
SMB_COM_READ_RAW = 0x1A
SMB_COM_READ_MPX = 0x1B
SMB_COM_READ_MPX_SECONDARY = 0x1C
SMB_COM_WRITE_RAW = 0x1D
SMB_COM_WRITE_MPX = 0x1E
SMB_COM_WRITE_MPX_SECONDARY = 0x1F
SMB_COM_WRITE_COMPLETE = 0x20
SMB_COM_QUERY_SERVER = 0x21
SMB_COM_SET_INFORMATION2 = 0x22
SMB_COM_QUERY_INFORMATION2 = 0x23
SMB_COM_LOCKING_ANDX = 0x24
SMB_COM_TRANSACTION = 0x25
SMB_COM_TRANSACTION_SECONDARY = 0x26
SMB_COM_IOCTL = 0x27
SMB_COM_IOCTL_SECONDARY = 0x28
SMB_COM_COPY = 0x29
SMB_COM_MOVE = 0x2A
SMB_COM_ECHO = 0x2B
SMB_COM_WRITE_AND_CLOSE = 0x2C
SMB_COM_OPEN_ANDX = 0x2D
SMB_COM_READ_ANDX = 0x2E
SMB_COM_WRITE_ANDX = 0x2F
SMB_COM_NEW_FILE_SIZE = 0x30
SMB_COM_CLOSE_AND_TREE_DISC = 0x31
SMB_COM_TRANSACTION2 = 0x32
SMB_COM_TRANSACTION2_SECONDARY = 0x33
SMB_COM_FIND_CLOSE2 = 0x34
SMB_COM_FIND_NOTIFY_CLOSE = 0x35
# Used by Xenix/Unix 0x60 - 0x6E
SMB_COM_TREE_CONNECT = 0x70
SMB_COM_TREE_DISCONNECT = 0x71
SMB_COM_NEGOTIATE = 0x72
SMB_COM_SESSION_SETUP_ANDX = 0x73
SMB_COM_LOGOFF_ANDX = 0x74
SMB_COM_TREE_CONNECT_ANDX = 0x75
SMB_COM_QUERY_INFORMATION_DISK = 0x80
SMB_COM_SEARCH = 0x81
SMB_COM_FIND = 0x82
SMB_COM_FIND_UNIQUE = 0x83
SMB_COM_FIND_CLOSE = 0x84
SMB_COM_NT_TRANSACT = 0xA0
SMB_COM_NT_TRANSACT_SECONDARY = 0xA1
SMB_COM_NT_CREATE_ANDX = 0xA2
SMB_COM_NT_CANCEL = 0xA4
SMB_COM_NT_RENAME = 0xA5
SMB_COM_OPEN_PRINT_FILE = 0xC0
SMB_COM_WRITE_PRINT_FILE = 0xC1
SMB_COM_CLOSE_PRINT_FILE = 0xC2
SMB_COM_GET_PRINT_QUEUE = 0xC3
SMB_COM_READ_BULK = 0xD8
SMB_COM_WRITE_BULK = 0xD9
SMB_COM_WRITE_BULK_DATA = 0xDA
# TRANSACT codes
TRANS_TRANSACT_NMPIPE = 0x26
# TRANSACT2 codes
TRANS2_FIND_FIRST2 = 0x0001
TRANS2_FIND_NEXT2 = 0x0002
TRANS2_QUERY_FS_INFORMATION = 0x0003
TRANS2_QUERY_PATH_INFORMATION = 0x0005
TRANS2_QUERY_FILE_INFORMATION = 0x0007
TRANS2_SET_FILE_INFORMATION = 0x0008
TRANS2_SET_PATH_INFORMATION = 0x0006
# Security Share Mode (Used internally by SMB class)
SECURITY_SHARE_MASK = 0x01
SECURITY_SHARE_SHARE = 0x00
SECURITY_SHARE_USER = 0x01
SECURITY_SIGNATURES_ENABLED = 0X04
SECURITY_SIGNATURES_REQUIRED = 0X08
# Security Auth Mode (Used internally by SMB class)
SECURITY_AUTH_MASK = 0x02
SECURITY_AUTH_ENCRYPTED = 0x02
SECURITY_AUTH_PLAINTEXT = 0x00
# Raw Mode Mask (Used internally by SMB class. Good for dialect up to and including LANMAN2.1)
RAW_READ_MASK = 0x01
RAW_WRITE_MASK = 0x02
# Capabilities Mask (Used internally by SMB class. Good for dialect NT LM 0.12)
CAP_RAW_MODE = 0x00000001
CAP_MPX_MODE = 0x0002
CAP_UNICODE = 0x0004
CAP_LARGE_FILES = 0x0008
CAP_EXTENDED_SECURITY = 0x80000000
CAP_USE_NT_ERRORS = 0x40
CAP_NT_SMBS = 0x10
CAP_LARGE_READX = 0x00004000
CAP_LARGE_WRITEX = 0x00008000
CAP_RPC_REMOTE_APIS = 0x20
# Flags1 Mask
FLAGS1_LOCK_AND_READ_OK = 0x01
FLAGS1_PATHCASELESS = 0x08
FLAGS1_CANONICALIZED_PATHS = 0x10
FLAGS1_REPLY = 0x80
# Flags2 Mask
FLAGS2_LONG_NAMES = 0x0001
FLAGS2_EAS = 0x0002
FLAGS2_SMB_SECURITY_SIGNATURE = 0x0004
FLAGS2_IS_LONG_NAME = 0x0040
FLAGS2_DFS = 0x1000
FLAGS2_PAGING_IO = 0x2000
FLAGS2_NT_STATUS = 0x4000
FLAGS2_UNICODE = 0x8000
FLAGS2_COMPRESSED = 0x0008
FLAGS2_SMB_SECURITY_SIGNATURE_REQUIRED = 0x0010
FLAGS2_EXTENDED_SECURITY = 0x0800
# Dialect's Security Mode flags
NEGOTIATE_USER_SECURITY = 0x01
NEGOTIATE_ENCRYPT_PASSWORDS = 0x02
NEGOTIATE_SECURITY_SIGNATURE_ENABLE = 0x04
NEGOTIATE_SECURITY_SIGNATURE_REQUIRED = 0x08
# Tree Connect AndX Response optionalSuppor flags
SMB_SUPPORT_SEARCH_BITS = 0x01
SMB_SHARE_IS_IN_DFS = 0x02
def __init__ ( self , remote_name , remote_host , my_name = None , host_type = nmb . TYPE_SERVER , sess_port = 445 , timeout = None , UDP = 0 , session = None , negPacket = None ) :
# The uid attribute will be set when the client calls the login() method
self . _uid = 0
self . __server_name = ' '
self . __server_os = ' '
self . __server_os_major = None
self . __server_os_minor = None
self . __server_os_build = None
self . __server_lanman = ' '
self . __server_domain = ' '
self . __server_dns_domain_name = ' '
self . __remote_name = string . upper ( remote_name )
self . __remote_host = remote_host
self . __isNTLMv2 = True
self . _dialects_parameters = None
self . _dialects_data = None
# Credentials
self . __userName = ' '
self . __password = ' '
self . __domain = ' '
self . __lmhash = ' '
self . __nthash = ' '
self . __aesKey = ' '
self . __kdc = ' '
self . __TGT = None
self . __TGS = None
# Negotiate Protocol Result, used everywhere
# Could be extended or not, flags should be checked before
self . _dialect_data = 0
self . _dialect_parameters = 0
self . _action = 0
self . _sess = None
self . encrypt_passwords = True
self . tid = 0
self . fid = 0
# Signing stuff
self . _SignSequenceNumber = 0
self . _SigningSessionKey = ' '
self . _SigningChallengeResponse = ' '
self . _SignatureEnabled = False
self . _SignatureVerificationEnabled = False
self . _SignatureRequired = False
# Base flags (default flags, can be overriden using set_flags())
self . __flags1 = SMB . FLAGS1_PATHCASELESS | SMB . FLAGS1_CANONICALIZED_PATHS
self . __flags2 = SMB . FLAGS2_EXTENDED_SECURITY | SMB . FLAGS2_NT_STATUS | SMB . FLAGS2_LONG_NAMES
if timeout is None :
self . __timeout = 60
else :
self . __timeout = timeout
# If port 445 and the name sent is *SMBSERVER we're setting the name to the IP.
# This is to help some old applications still believing
# *SMSBSERVER will work against modern OSes. If port is NETBIOS_SESSION_PORT the user better
# know about *SMBSERVER's limitations
if sess_port == 445 and remote_name == ' *SMBSERVER ' :
self . __remote_name = remote_host
if session is None :
if not my_name :
my_name = socket . gethostname ( )
i = string . find ( my_name , ' . ' )
if i > - 1 :
my_name = my_name [ : i ]
if UDP :
self . _sess = nmb . NetBIOSUDPSession ( my_name , remote_name , remote_host , host_type , sess_port , self . __timeout )
else :
self . _sess = nmb . NetBIOSTCPSession ( my_name , remote_name , remote_host , host_type , sess_port , self . __timeout )
# Initialize session values (_dialect_data and _dialect_parameters)
self . neg_session ( )
# Call login() without any authentication information to
# setup a session if the remote server
# is in share mode.
if ( self . _dialects_parameters [ ' SecurityMode ' ] & SMB . SECURITY_SHARE_MASK ) == SMB . SECURITY_SHARE_SHARE :
self . login ( ' ' , ' ' )
else :
self . _sess = session
self . neg_session ( negPacket = negPacket )
# Call login() without any authentication information to
# setup a session if the remote server
# is in share mode.
if ( self . _dialects_parameters [ ' SecurityMode ' ] & SMB . SECURITY_SHARE_MASK ) == SMB . SECURITY_SHARE_SHARE :
self . login ( ' ' , ' ' )
@staticmethod
def ntlm_supported ( ) :
return False
def get_remote_name ( self ) :
return self . __remote_name
def get_remote_host ( self ) :
return self . __remote_host
def get_flags ( self ) :
return self . __flags1 , self . __flags2
def set_flags ( self , flags1 = None , flags2 = None ) :
if flags1 is not None :
self . __flags1 = flags1
if flags2 is not None :
self . __flags2 = flags2
def set_timeout ( self , timeout ) :
prev_timeout = self . __timeout
self . __timeout = timeout
return prev_timeout
def get_timeout ( self ) :
return self . __timeout
@contextmanager
def use_timeout ( self , timeout ) :
prev_timeout = self . set_timeout ( timeout )
try :
yield
finally :
self . set_timeout ( prev_timeout )
def get_session ( self ) :
return self . _sess
def get_tid ( self ) :
return self . tid
def get_fid ( self ) :
return self . fid
def isGuestSession ( self ) :
return self . _action & SMB_SETUP_GUEST
def doesSupportNTLMv2 ( self ) :
return self . __isNTLMv2
def __del__ ( self ) :
if self . _sess :
self . _sess . close ( )
def recvSMB ( self ) :
r = self . _sess . recv_packet ( self . __timeout )
return NewSMBPacket ( data = r . get_trailer ( ) )
@staticmethod
def __decode_trans ( params , data ) :
totparamcnt , totdatacnt , _ , paramcnt , paramoffset , paramds , datacnt , dataoffset , datads , setupcnt = unpack ( ' <HHHHHHHHHB ' , params [ : 19 ] )
if paramcnt + paramds < totparamcnt or datacnt + datads < totdatacnt :
has_more = 1
else :
has_more = 0
paramoffset = paramoffset - 55 - setupcnt * 2
dataoffset = dataoffset - 55 - setupcnt * 2
return has_more , params [ 20 : 20 + setupcnt * 2 ] , data [ paramoffset : paramoffset + paramcnt ] , data [ dataoffset : dataoffset + datacnt ]
# TODO: Move this to NewSMBPacket, it belongs there
def signSMB ( self , packet , signingSessionKey , signingChallengeResponse ) :
# This logic MUST be applied for messages sent in response to any of the higher-layer actions and in
# compliance with the message sequencing rules.
# * The client or server that sends the message MUST provide the 32-bit sequence number for this
# message, as specified in sections 3.2.4.1 and 3.3.4.1.
# * The SMB_FLAGS2_SMB_SECURITY_SIGNATURE flag in the header MUST be set.
# * To generate the signature, a 32-bit sequence number is copied into the
# least significant 32 bits of the SecuritySignature field and the remaining
# 4 bytes are set to 0x00.
# * The MD5 algorithm, as specified in [RFC1321], MUST be used to generate a hash of the SMB
# message from the start of the SMB Header, which is defined as follows.
# CALL MD5Init( md5context )
# CALL MD5Update( md5context, Connection.SigningSessionKey )
# CALL MD5Update( md5context, Connection.SigningChallengeResponse )
# CALL MD5Update( md5context, SMB message )
# CALL MD5Final( digest, md5context )
# SET signature TO the first 8 bytes of the digest
# The resulting 8-byte signature MUST be copied into the SecuritySignature field of the SMB Header,
# after which the message can be transmitted.
#print "seq(%d) signingSessionKey %r, signingChallengeResponse %r" % (self._SignSequenceNumber, signingSessionKey, signingChallengeResponse)
packet [ ' SecurityFeatures ' ] = pack ( ' <q ' , self . _SignSequenceNumber )
# Sign with the sequence
m = hashlib . md5 ( )
m . update ( signingSessionKey )
m . update ( signingChallengeResponse )
m . update ( str ( packet ) )
# Replace sequence with acual hash
packet [ ' SecurityFeatures ' ] = m . digest ( ) [ : 8 ]
if self . _SignatureVerificationEnabled :
self . _SignSequenceNumber + = 1
else :
self . _SignSequenceNumber + = 2
def checkSignSMB ( self , packet , signingSessionKey , signingChallengeResponse ) :
# Let's check
signature = packet [ ' SecurityFeatures ' ]
#print "Signature received: %r " % signature
self . signSMB ( packet , signingSessionKey , signingChallengeResponse )
#print "Signature calculated: %r" % packet['SecurityFeatures']
if self . _SignatureVerificationEnabled is not True :
self . _SignSequenceNumber - = 1
return packet [ ' SecurityFeatures ' ] == signature
def sendSMB ( self , smb ) :
smb [ ' Uid ' ] = self . _uid
#At least on AIX, PIDs can exceed 16 bits, so we mask them out
smb [ ' Pid ' ] = ( os . getpid ( ) & 0xFFFF )
# set flags
smb [ ' Flags1 ' ] | = self . __flags1
smb [ ' Flags2 ' ] | = self . __flags2
if self . _SignatureEnabled :
smb [ ' Flags2 ' ] | = SMB . FLAGS2_SMB_SECURITY_SIGNATURE
self . signSMB ( smb , self . _SigningSessionKey , self . _SigningChallengeResponse )
self . _sess . send_packet ( str ( smb ) )
@staticmethod
def isValidAnswer ( s , cmd ) :
while 1 :
if s . rawData ( ) :
if s . get_command ( ) == cmd :
if s . get_error_class ( ) == 0x00 and s . get_error_code ( ) == 0x00 :
return 1
else :
2019-04-04 19:32:39 -04:00
raise SessionError ( " SMB Library Error " , s . get_error_class ( ) + ( s . get_reserved ( ) << 8 ) , s . get_error_code ( ) , s . get_flags2 ( ) & SMB . FLAGS2_NT_STATUS )
2017-06-30 08:53:19 -04:00
else :
break
return 0
def neg_session ( self , extended_security = True , negPacket = None ) :
def parsePacket ( smb ) :
if smb . isValidAnswer ( SMB . SMB_COM_NEGOTIATE ) :
sessionResponse = SMBCommand ( smb [ ' Data ' ] [ 0 ] )
self . _dialects_parameters = SMBNTLMDialect_Parameters ( sessionResponse [ ' Parameters ' ] )
self . _dialects_data = SMBNTLMDialect_Data ( )
self . _dialects_data [ ' ChallengeLength ' ] = self . _dialects_parameters [ ' ChallengeLength ' ]
self . _dialects_data . fromString ( sessionResponse [ ' Data ' ] )
if self . _dialects_parameters [ ' Capabilities ' ] & SMB . CAP_EXTENDED_SECURITY :
# Whether we choose it or it is enforced by the server, we go for extended security
self . _dialects_parameters = SMBExtended_Security_Parameters ( sessionResponse [ ' Parameters ' ] )
self . _dialects_data = SMBExtended_Security_Data ( sessionResponse [ ' Data ' ] )
# Let's setup some variable for later use
if self . _dialects_parameters [ ' SecurityMode ' ] & SMB . SECURITY_SIGNATURES_REQUIRED :
self . _SignatureRequired = True
# Interestingly, the security Blob might be missing sometimes.
#spnego = SPNEGO_NegTokenInit(self._dialects_data['SecurityBlob'])
#for i in spnego['MechTypes']:
# print "Mech Found: %s" % MechTypes[i]
return 1
# If not, let's try the old way
else :
if self . _dialects_data [ ' ServerName ' ] is not None :
self . __server_name = self . _dialects_data [ ' ServerName ' ]
if self . _dialects_parameters [ ' DialectIndex ' ] == 0xffff :
2019-04-04 19:32:39 -04:00
raise UnsupportedFeature ( " Remote server does not know NT LM 0.12 " )
2017-06-30 08:53:19 -04:00
return 1
else :
return 0
if negPacket is None :
smb = NewSMBPacket ( )
negSession = SMBCommand ( SMB . SMB_COM_NEGOTIATE )
flags2 = self . get_flags ( ) [ 1 ]
if extended_security is True :
self . set_flags ( flags2 = flags2 | SMB . FLAGS2_EXTENDED_SECURITY )
else :
self . set_flags ( flags2 = flags2 & ( ~ SMB . FLAGS2_EXTENDED_SECURITY ) )
negSession [ ' Data ' ] = ' \x02 NT LM 0.12 \x00 '
smb . addCommand ( negSession )
self . sendSMB ( smb )
while 1 :
smb = self . recvSMB ( )
return parsePacket ( smb )
else :
return parsePacket ( NewSMBPacket ( data = negPacket ) )
def tree_connect ( self , path , password = ' ' , service = SERVICE_ANY ) :
LOG . warning ( " [MS-CIFS] This is an original Core Protocol command.This command has been deprecated.Client Implementations SHOULD use SMB_COM_TREE_CONNECT_ANDX " )
# return 0x800
if password :
# Password is only encrypted if the server passed us an "encryption" during protocol dialect
if self . _dialects_parameters [ ' ChallengeLength ' ] > 0 :
# this code is untested
password = self . get_ntlmv1_response ( ntlm . compute_lmhash ( password ) )
if not unicode_support :
if unicode_convert :
path = str ( path )
else :
raise Exception ( ' SMB: Can \t conver path from unicode! ' )
smb = NewSMBPacket ( )
treeConnect = SMBCommand ( SMB . SMB_COM_TREE_CONNECT )
treeConnect [ ' Parameters ' ] = SMBTreeConnect_Parameters ( )
treeConnect [ ' Data ' ] = SMBTreeConnect_Data ( )
treeConnect [ ' Data ' ] [ ' Path ' ] = path . upper ( )
treeConnect [ ' Data ' ] [ ' Password ' ] = password
treeConnect [ ' Data ' ] [ ' Service ' ] = service
smb . addCommand ( treeConnect )
self . sendSMB ( smb )
while 1 :
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_TREE_CONNECT ) :
# XXX Here we are ignoring the rest of the response
return smb [ ' Tid ' ]
return smb [ ' Tid ' ]
def get_uid ( self ) :
return self . _uid
def set_uid ( self , uid ) :
self . _uid = uid
def tree_connect_andx ( self , path , password = None , service = SERVICE_ANY , smb_packet = None ) :
if password :
# Password is only encrypted if the server passed us an "encryption" during protocol dialect
if self . _dialects_parameters [ ' ChallengeLength ' ] > 0 :
# this code is untested
password = self . get_ntlmv1_response ( ntlm . compute_lmhash ( password ) )
else :
password = ' \x00 '
if not unicode_support :
if unicode_convert :
path = str ( path )
else :
raise Exception ( ' SMB: Can \t convert path from unicode! ' )
if smb_packet is None :
smb = NewSMBPacket ( )
else :
smb = smb_packet
# Just in case this came with the full path ,let's just leave
# the sharename, we'll take care of the rest
share = path . split ( ' \\ ' ) [ - 1 ]
try :
_ , _ , _ , _ , sockaddr = socket . getaddrinfo ( self . get_remote_host ( ) , 80 , 0 , 0 , socket . IPPROTO_TCP ) [ 0 ]
remote_host = sockaddr [ 0 ]
except Exception :
remote_host = self . get_remote_host ( )
path = ' \\ \\ ' + remote_host + ' \\ ' + share
path = path . upper ( ) . encode ( ' utf-16le ' ) if self . __flags2 & SMB . FLAGS2_UNICODE else path
treeConnect = SMBCommand ( SMB . SMB_COM_TREE_CONNECT_ANDX )
treeConnect [ ' Parameters ' ] = SMBTreeConnectAndX_Parameters ( )
treeConnect [ ' Data ' ] = SMBTreeConnectAndX_Data ( flags = self . __flags2 )
treeConnect [ ' Parameters ' ] [ ' PasswordLength ' ] = len ( password )
treeConnect [ ' Data ' ] [ ' Password ' ] = password
treeConnect [ ' Data ' ] [ ' Path ' ] = path
treeConnect [ ' Data ' ] [ ' Service ' ] = service
if self . __flags2 & SMB . FLAGS2_UNICODE :
treeConnect [ ' Data ' ] [ ' Pad ' ] = 0x0
smb . addCommand ( treeConnect )
# filename = "\PIPE\epmapper"
# ntCreate = SMBCommand(SMB.SMB_COM_NT_CREATE_ANDX)
# ntCreate['Parameters'] = SMBNtCreateAndX_Parameters()
# ntCreate['Data'] = SMBNtCreateAndX_Data()
# ntCreate['Parameters']['FileNameLength'] = len(filename)
# ntCreate['Parameters']['CreateFlags'] = 0
# ntCreate['Parameters']['AccessMask'] = 0x3
# ntCreate['Parameters']['CreateOptions'] = 0x0
# ntCreate['Data']['FileName'] = filename
# smb.addCommand(ntCreate)
self . sendSMB ( smb )
while 1 :
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_TREE_CONNECT_ANDX ) :
# XXX Here we are ignoring the rest of the response
self . tid = smb [ ' Tid ' ]
return self . tid
self . tid = smb [ ' Tid ' ]
return self . tid
# backwars compatibility
connect_tree = tree_connect_andx
@staticmethod
def getDialect ( ) :
return SMB_DIALECT
def get_server_name ( self ) :
#return self._dialects_data['ServerName']
return self . __server_name
def get_session_key ( self ) :
return self . _SigningSessionKey
def set_session_key ( self , key ) :
self . _SigningSessionKey = key
def get_encryption_key ( self ) :
2019-04-04 19:32:39 -04:00
if ' Challenge ' in self . _dialects_data . fields :
2017-06-30 08:53:19 -04:00
return self . _dialects_data [ ' Challenge ' ]
else :
return None
def get_server_time ( self ) :
timestamp = self . _dialects_parameters [ ' HighDateTime ' ]
timestamp << = 32
timestamp | = self . _dialects_parameters [ ' LowDateTime ' ]
timestamp - = 116444736000000000
timestamp / = 10000000
d = datetime . datetime . utcfromtimestamp ( timestamp )
return d . strftime ( " %a , %d % b % Y % H: % M: % S GMT " )
def disconnect_tree ( self , tid ) :
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
smb . addCommand ( SMBCommand ( SMB . SMB_COM_TREE_DISCONNECT ) )
self . sendSMB ( smb )
self . recvSMB ( )
def open ( self , tid , filename , open_mode , desired_access ) :
filename = string . replace ( filename , ' / ' , ' \\ ' )
filename = filename . encode ( ' utf-16le ' ) if self . __flags2 & SMB . FLAGS2_UNICODE else filename
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
openFile = SMBCommand ( SMB . SMB_COM_OPEN )
openFile [ ' Parameters ' ] = SMBOpen_Parameters ( )
openFile [ ' Parameters ' ] [ ' DesiredAccess ' ] = desired_access
openFile [ ' Parameters ' ] [ ' OpenMode ' ] = open_mode
openFile [ ' Parameters ' ] [ ' SearchAttributes ' ] = ATTR_READONLY | ATTR_HIDDEN | ATTR_ARCHIVE
openFile [ ' Data ' ] = SMBOpen_Data ( flags = self . __flags2 )
openFile [ ' Data ' ] [ ' FileName ' ] = filename
if self . __flags2 & SMB . FLAGS2_UNICODE :
openFile [ ' Data ' ] [ ' Pad ' ] = 0x0
smb . addCommand ( openFile )
self . sendSMB ( smb )
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_OPEN ) :
# XXX Here we are ignoring the rest of the response
openFileResponse = SMBCommand ( smb [ ' Data ' ] [ 0 ] )
openFileParameters = SMBOpenResponse_Parameters ( openFileResponse [ ' Parameters ' ] )
return (
openFileParameters [ ' Fid ' ] ,
openFileParameters [ ' FileAttributes ' ] ,
openFileParameters [ ' LastWriten ' ] ,
openFileParameters [ ' FileSize ' ] ,
openFileParameters [ ' GrantedAccess ' ] ,
)
def open_andx ( self , tid , filename , open_mode , desired_access ) :
filename = string . replace ( filename , ' / ' , ' \\ ' )
filename = filename . encode ( ' utf-16le ' ) if self . __flags2 & SMB . FLAGS2_UNICODE else filename
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
openFile = SMBCommand ( SMB . SMB_COM_OPEN_ANDX )
openFile [ ' Parameters ' ] = SMBOpenAndX_Parameters ( )
openFile [ ' Parameters ' ] [ ' DesiredAccess ' ] = desired_access
openFile [ ' Parameters ' ] [ ' OpenMode ' ] = open_mode
openFile [ ' Parameters ' ] [ ' SearchAttributes ' ] = ATTR_READONLY | ATTR_HIDDEN | ATTR_ARCHIVE
openFile [ ' Data ' ] = SMBOpenAndX_Data ( flags = self . __flags2 )
openFile [ ' Data ' ] [ ' FileName ' ] = filename
if self . __flags2 & SMB . FLAGS2_UNICODE :
openFile [ ' Data ' ] [ ' Pad ' ] = 0x0
smb . addCommand ( openFile )
self . sendSMB ( smb )
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_OPEN_ANDX ) :
# XXX Here we are ignoring the rest of the response
openFileResponse = SMBCommand ( smb [ ' Data ' ] [ 0 ] )
openFileParameters = SMBOpenAndXResponse_Parameters ( openFileResponse [ ' Parameters ' ] )
return (
openFileParameters [ ' Fid ' ] ,
openFileParameters [ ' FileAttributes ' ] ,
openFileParameters [ ' LastWriten ' ] ,
openFileParameters [ ' FileSize ' ] ,
openFileParameters [ ' GrantedAccess ' ] ,
openFileParameters [ ' FileType ' ] ,
openFileParameters [ ' IPCState ' ] ,
openFileParameters [ ' Action ' ] ,
openFileParameters [ ' ServerFid ' ] ,
)
def close ( self , tid , fid ) :
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
closeFile = SMBCommand ( SMB . SMB_COM_CLOSE )
closeFile [ ' Parameters ' ] = SMBClose_Parameters ( )
closeFile [ ' Parameters ' ] [ ' FID ' ] = fid
smb . addCommand ( closeFile )
self . sendSMB ( smb )
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_CLOSE ) :
return 1
return 0
def send_trans ( self , tid , setup , name , param , data , noAnswer = 0 ) :
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
transCommand = SMBCommand ( SMB . SMB_COM_TRANSACTION )
transCommand [ ' Parameters ' ] = SMBTransaction_Parameters ( )
transCommand [ ' Data ' ] = SMBTransaction_Data ( )
transCommand [ ' Parameters ' ] [ ' Setup ' ] = setup
transCommand [ ' Parameters ' ] [ ' TotalParameterCount ' ] = len ( param )
transCommand [ ' Parameters ' ] [ ' TotalDataCount ' ] = len ( data )
transCommand [ ' Parameters ' ] [ ' ParameterCount ' ] = len ( param )
transCommand [ ' Parameters ' ] [ ' ParameterOffset ' ] = 32 + 3 + 28 + len ( setup ) + len ( name )
transCommand [ ' Parameters ' ] [ ' DataCount ' ] = len ( data )
transCommand [ ' Parameters ' ] [ ' DataOffset ' ] = transCommand [ ' Parameters ' ] [ ' ParameterOffset ' ] + len ( param )
transCommand [ ' Data ' ] [ ' Name ' ] = name
transCommand [ ' Data ' ] [ ' Trans_Parameters ' ] = param
transCommand [ ' Data ' ] [ ' Trans_Data ' ] = data
if noAnswer :
transCommand [ ' Parameters ' ] [ ' Flags ' ] = TRANS_NO_RESPONSE
smb . addCommand ( transCommand )
self . sendSMB ( smb )
def send_trans2 ( self , tid , setup , name , param , data ) :
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
command = pack ( ' <H ' , setup )
transCommand = SMBCommand ( SMB . SMB_COM_TRANSACTION2 )
transCommand [ ' Parameters ' ] = SMBTransaction2_Parameters ( )
transCommand [ ' Parameters ' ] [ ' MaxDataCount ' ] = self . _dialects_parameters [ ' MaxBufferSize ' ]
transCommand [ ' Data ' ] = SMBTransaction2_Data ( )
transCommand [ ' Parameters ' ] [ ' Setup ' ] = command
transCommand [ ' Parameters ' ] [ ' TotalParameterCount ' ] = len ( param )
transCommand [ ' Parameters ' ] [ ' TotalDataCount ' ] = len ( data )
if len ( param ) > 0 :
padLen = ( 4 - ( 32 + 2 + 28 + len ( command ) ) % 4 ) % 4
padBytes = ' \xFF ' * padLen
transCommand [ ' Data ' ] [ ' Pad1 ' ] = padBytes
else :
transCommand [ ' Data ' ] [ ' Pad1 ' ] = ' '
padLen = 0
transCommand [ ' Parameters ' ] [ ' ParameterCount ' ] = len ( param )
transCommand [ ' Parameters ' ] [ ' ParameterOffset ' ] = 32 + 2 + 28 + len ( command ) + len ( name ) + padLen
if len ( data ) > 0 :
pad2Len = ( 4 - ( 32 + 2 + 28 + len ( command ) + padLen + len ( param ) ) % 4 ) % 4
transCommand [ ' Data ' ] [ ' Pad2 ' ] = ' \xFF ' * pad2Len
else :
transCommand [ ' Data ' ] [ ' Pad2 ' ] = ' '
pad2Len = 0
transCommand [ ' Parameters ' ] [ ' DataCount ' ] = len ( data )
transCommand [ ' Parameters ' ] [ ' DataOffset ' ] = transCommand [ ' Parameters ' ] [ ' ParameterOffset ' ] + len ( param ) + pad2Len
transCommand [ ' Data ' ] [ ' Name ' ] = name
transCommand [ ' Data ' ] [ ' Trans_Parameters ' ] = param
transCommand [ ' Data ' ] [ ' Trans_Data ' ] = data
smb . addCommand ( transCommand )
self . sendSMB ( smb )
def query_file_info ( self , tid , fid , fileInfoClass = SMB_QUERY_FILE_STANDARD_INFO ) :
self . send_trans2 ( tid , SMB . TRANS2_QUERY_FILE_INFORMATION , ' \x00 ' , pack ( ' <HH ' , fid , fileInfoClass ) , ' ' )
resp = self . recvSMB ( )
if resp . isValidAnswer ( SMB . SMB_COM_TRANSACTION2 ) :
trans2Response = SMBCommand ( resp [ ' Data ' ] [ 0 ] )
trans2Parameters = SMBTransaction2Response_Parameters ( trans2Response [ ' Parameters ' ] )
# Remove Potential Prefix Padding
return trans2Response [ ' Data ' ] [ - trans2Parameters [ ' TotalDataCount ' ] : ]
def __nonraw_retr_file ( self , tid , fid , offset , datasize , callback ) :
if ( self . _dialects_parameters [ ' Capabilities ' ] & SMB . CAP_LARGE_READX ) and self . _SignatureEnabled is False :
max_buf_size = 65000
else :
max_buf_size = self . _dialects_parameters [ ' MaxBufferSize ' ] & ~ 0x3ff # Read in multiple KB blocks
read_offset = offset
while read_offset < datasize :
data = self . read_andx ( tid , fid , read_offset , max_buf_size )
callback ( data )
read_offset + = len ( data )
def __nonraw_stor_file ( self , tid , fid , offset , datasize , callback ) :
if ( self . _dialects_parameters [ ' Capabilities ' ] & SMB . CAP_LARGE_WRITEX ) and self . _SignatureEnabled is False :
max_buf_size = 65000
else :
max_buf_size = self . _dialects_parameters [ ' MaxBufferSize ' ] & ~ 0x3ff # Write in multiple KB blocks
write_offset = offset
while 1 :
data = callback ( max_buf_size )
if not data :
break
smb = self . write_andx ( tid , fid , data , write_offset )
writeResponse = SMBCommand ( smb [ ' Data ' ] [ 0 ] )
writeResponseParameters = SMBWriteAndXResponse_Parameters ( writeResponse [ ' Parameters ' ] )
write_offset + = writeResponseParameters [ ' Count ' ]
def get_server_domain ( self ) :
return self . __server_domain
def get_server_dns_domain_name ( self ) :
return self . __server_dns_domain_name
def get_server_os ( self ) :
return self . __server_os
def get_server_os_major ( self ) :
return self . __server_os_major
def get_server_os_minor ( self ) :
return self . __server_os_minor
def get_server_os_build ( self ) :
return self . __server_os_build
def set_server_os ( self , os ) :
self . __server_os = os
def get_server_lanman ( self ) :
return self . __server_lanman
def is_login_required ( self ) :
# Login is required if share mode is user.
# Otherwise only public services or services in share mode
# are allowed.
return ( self . _dialects_parameters [ ' SecurityMode ' ] & SMB . SECURITY_SHARE_MASK ) == SMB . SECURITY_SHARE_USER
def is_signing_required ( self ) :
return self . _SignatureRequired
def get_ntlmv1_response ( self , key ) :
challenge = self . _dialects_data [ ' Challenge ' ]
return ntlm . get_ntlmv1_response ( key , challenge )
def kerberos_login ( self , user , password , domain = ' ' , lmhash = ' ' , nthash = ' ' , aesKey = ' ' , kdcHost = ' ' , TGT = None , TGS = None ) :
# Importing down here so pyasn1 is not required if kerberos is not used.
from impacket . krb5 . asn1 import AP_REQ , Authenticator , TGS_REP , seq_set
from impacket . krb5 . kerberosv5 import getKerberosTGT , getKerberosTGS
from impacket . krb5 import constants
from impacket . krb5 . types import Principal , KerberosTime , Ticket
from pyasn1 . codec . der import decoder , encoder
import datetime
# login feature does not support unicode
# disable it if enabled
flags2 = self . __flags2
if flags2 & SMB . FLAGS2_UNICODE :
self . __flags2 = flags2 & ( flags2 ^ SMB . FLAGS2_UNICODE )
# If TGT or TGS are specified, they are in the form of:
# TGS['KDC_REP'] = the response from the server
# TGS['cipher'] = the cipher used
# TGS['sessionKey'] = the sessionKey
# If we have hashes, normalize them
if lmhash != ' ' or nthash != ' ' :
if len ( lmhash ) % 2 : lmhash = ' 0 %s ' % lmhash
if len ( nthash ) % 2 : nthash = ' 0 %s ' % nthash
try : # just in case they were converted already
lmhash = a2b_hex ( lmhash )
nthash = a2b_hex ( nthash )
except :
pass
self . __userName = user
self . __password = password
self . __domain = domain
self . __lmhash = lmhash
self . __nthash = nthash
self . __aesKey = aesKey
self . __kdc = kdcHost
self . __TGT = TGT
self . __TGS = TGS
# First of all, we need to get a TGT for the user
userName = Principal ( user , type = constants . PrincipalNameType . NT_PRINCIPAL . value )
if TGT is None :
if TGS is None :
tgt , cipher , oldSessionKey , sessionKey = getKerberosTGT ( userName , password , domain , lmhash , nthash , aesKey , kdcHost )
else :
tgt = TGT [ ' KDC_REP ' ]
cipher = TGT [ ' cipher ' ]
sessionKey = TGT [ ' sessionKey ' ]
# Now that we have the TGT, we should ask for a TGS for cifs
if TGS is None :
serverName = Principal ( ' cifs/ %s ' % self . __remote_name , type = constants . PrincipalNameType . NT_SRV_INST . value )
tgs , cipher , oldSessionKey , sessionKey = getKerberosTGS ( serverName , domain , kdcHost , tgt , cipher , sessionKey )
else :
tgs = TGS [ ' KDC_REP ' ]
cipher = TGS [ ' cipher ' ]
sessionKey = TGS [ ' sessionKey ' ]
smb = NewSMBPacket ( )
# Are we required to sign SMB? If so we do it, if not we skip it
if self . _SignatureRequired :
smb [ ' Flags2 ' ] | = SMB . FLAGS2_SMB_SECURITY_SIGNATURE
sessionSetup = SMBCommand ( SMB . SMB_COM_SESSION_SETUP_ANDX )
sessionSetup [ ' Parameters ' ] = SMBSessionSetupAndX_Extended_Parameters ( )
sessionSetup [ ' Data ' ] = SMBSessionSetupAndX_Extended_Data ( )
sessionSetup [ ' Parameters ' ] [ ' MaxBufferSize ' ] = 61440
sessionSetup [ ' Parameters ' ] [ ' MaxMpxCount ' ] = 2
sessionSetup [ ' Parameters ' ] [ ' VcNumber ' ] = 1
sessionSetup [ ' Parameters ' ] [ ' SessionKey ' ] = 0
sessionSetup [ ' Parameters ' ] [ ' Capabilities ' ] = SMB . CAP_EXTENDED_SECURITY | SMB . CAP_USE_NT_ERRORS | SMB . CAP_UNICODE | SMB . CAP_LARGE_READX | SMB . CAP_LARGE_WRITEX
# Let's build a NegTokenInit with the NTLMSSP
# TODO: In the future we should be able to choose different providers
blob = SPNEGO_NegTokenInit ( )
# Kerberos v5 mech
blob [ ' MechTypes ' ] = [ TypesMech [ ' MS KRB5 - Microsoft Kerberos 5 ' ] ]
# Let's extract the ticket from the TGS
tgs = decoder . decode ( tgs , asn1Spec = TGS_REP ( ) ) [ 0 ]
ticket = Ticket ( )
ticket . from_asn1 ( tgs [ ' ticket ' ] )
# Now let's build the AP_REQ
apReq = AP_REQ ( )
apReq [ ' pvno ' ] = 5
apReq [ ' msg-type ' ] = int ( constants . ApplicationTagNumbers . AP_REQ . value )
opts = list ( )
apReq [ ' ap-options ' ] = constants . encodeFlags ( opts )
seq_set ( apReq , ' ticket ' , ticket . to_asn1 )
authenticator = Authenticator ( )
authenticator [ ' authenticator-vno ' ] = 5
authenticator [ ' crealm ' ] = domain
seq_set ( authenticator , ' cname ' , userName . components_to_asn1 )
now = datetime . datetime . utcnow ( )
authenticator [ ' cusec ' ] = now . microsecond
authenticator [ ' ctime ' ] = KerberosTime . to_asn1 ( now )
encodedAuthenticator = encoder . encode ( authenticator )
# Key Usage 11
# AP-REQ Authenticator (includes application authenticator
# subkey), encrypted with the application session key
# (Section 5.5.1)
encryptedEncodedAuthenticator = cipher . encrypt ( sessionKey , 11 , encodedAuthenticator , None )
apReq [ ' authenticator ' ] = None
apReq [ ' authenticator ' ] [ ' etype ' ] = cipher . enctype
apReq [ ' authenticator ' ] [ ' cipher ' ] = encryptedEncodedAuthenticator
blob [ ' MechToken ' ] = encoder . encode ( apReq )
sessionSetup [ ' Parameters ' ] [ ' SecurityBlobLength ' ] = len ( blob )
sessionSetup [ ' Parameters ' ] . getData ( )
sessionSetup [ ' Data ' ] [ ' SecurityBlob ' ] = blob . getData ( )
# Fake Data here, don't want to get us fingerprinted
sessionSetup [ ' Data ' ] [ ' NativeOS ' ] = ' Unix '
sessionSetup [ ' Data ' ] [ ' NativeLanMan ' ] = ' Samba '
smb . addCommand ( sessionSetup )
self . sendSMB ( smb )
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_SESSION_SETUP_ANDX ) :
# We will need to use this uid field for all future requests/responses
self . _uid = smb [ ' Uid ' ]
# Now we have to extract the blob to continue the auth process
sessionResponse = SMBCommand ( smb [ ' Data ' ] [ 0 ] )
sessionParameters = SMBSessionSetupAndX_Extended_Response_Parameters ( sessionResponse [ ' Parameters ' ] )
sessionData = SMBSessionSetupAndX_Extended_Response_Data ( flags = smb [ ' Flags2 ' ] )
sessionData [ ' SecurityBlobLength ' ] = sessionParameters [ ' SecurityBlobLength ' ]
sessionData . fromString ( sessionResponse [ ' Data ' ] )
self . _action = sessionParameters [ ' Action ' ]
# If smb sign required, let's enable it for the rest of the connection
if self . _dialects_parameters [ ' SecurityMode ' ] & SMB . SECURITY_SIGNATURES_REQUIRED :
self . _SigningSessionKey = sessionKey . contents
self . _SignSequenceNumber = 2
self . _SignatureEnabled = True
# restore unicode flag if needed
if flags2 & SMB . FLAGS2_UNICODE :
self . __flags2 | = SMB . FLAGS2_UNICODE
return 1
else :
raise Exception ( ' Error: Could not login successfully ' )
def login_extended ( self , user , password , domain = ' ' , lmhash = ' ' , nthash = ' ' , use_ntlmv2 = True ) :
# login feature does not support unicode
# disable it if enabled
flags2 = self . __flags2
if flags2 & SMB . FLAGS2_UNICODE :
self . __flags2 = flags2 & ( flags2 ^ SMB . FLAGS2_UNICODE )
# Once everything's working we should join login methods into a single one
smb = NewSMBPacket ( )
# Are we required to sign SMB? If so we do it, if not we skip it
if self . _SignatureRequired :
smb [ ' Flags2 ' ] | = SMB . FLAGS2_SMB_SECURITY_SIGNATURE
sessionSetup = SMBCommand ( SMB . SMB_COM_SESSION_SETUP_ANDX )
sessionSetup [ ' Parameters ' ] = SMBSessionSetupAndX_Extended_Parameters ( )
sessionSetup [ ' Data ' ] = SMBSessionSetupAndX_Extended_Data ( )
sessionSetup [ ' Parameters ' ] [ ' MaxBufferSize ' ] = 61440
sessionSetup [ ' Parameters ' ] [ ' MaxMpxCount ' ] = 2
sessionSetup [ ' Parameters ' ] [ ' VcNumber ' ] = 1
sessionSetup [ ' Parameters ' ] [ ' SessionKey ' ] = 0
sessionSetup [ ' Parameters ' ] [ ' Capabilities ' ] = SMB . CAP_EXTENDED_SECURITY | SMB . CAP_USE_NT_ERRORS | SMB . CAP_UNICODE | SMB . CAP_LARGE_READX | SMB . CAP_LARGE_WRITEX
# Let's build a NegTokenInit with the NTLMSSP
# TODO: In the future we should be able to choose different providers
blob = SPNEGO_NegTokenInit ( )
# NTLMSSP
blob [ ' MechTypes ' ] = [ TypesMech [ ' NTLMSSP - Microsoft NTLM Security Support Provider ' ] ]
auth = ntlm . getNTLMSSPType1 ( ' ' , ' ' , self . _SignatureRequired , use_ntlmv2 = use_ntlmv2 )
blob [ ' MechToken ' ] = str ( auth )
sessionSetup [ ' Parameters ' ] [ ' SecurityBlobLength ' ] = len ( blob )
sessionSetup [ ' Parameters ' ] . getData ( )
sessionSetup [ ' Data ' ] [ ' SecurityBlob ' ] = blob . getData ( )
# Fake Data here, don't want to get us fingerprinted
sessionSetup [ ' Data ' ] [ ' NativeOS ' ] = ' Unix '
sessionSetup [ ' Data ' ] [ ' NativeLanMan ' ] = ' Samba '
smb . addCommand ( sessionSetup )
self . sendSMB ( smb )
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_SESSION_SETUP_ANDX ) :
# We will need to use this uid field for all future requests/responses
self . _uid = smb [ ' Uid ' ]
# Now we have to extract the blob to continue the auth process
sessionResponse = SMBCommand ( smb [ ' Data ' ] [ 0 ] )
sessionParameters = SMBSessionSetupAndX_Extended_Response_Parameters ( sessionResponse [ ' Parameters ' ] )
sessionData = SMBSessionSetupAndX_Extended_Response_Data ( flags = smb [ ' Flags2 ' ] )
sessionData [ ' SecurityBlobLength ' ] = sessionParameters [ ' SecurityBlobLength ' ]
sessionData . fromString ( sessionResponse [ ' Data ' ] )
respToken = SPNEGO_NegTokenResp ( sessionData [ ' SecurityBlob ' ] )
# Let's parse some data and keep it to ourselves in case it is asked
ntlmChallenge = ntlm . NTLMAuthChallenge ( respToken [ ' ResponseToken ' ] )
if ntlmChallenge [ ' TargetInfoFields_len ' ] > 0 :
av_pairs = ntlm . AV_PAIRS ( ntlmChallenge [ ' TargetInfoFields ' ] [ : ntlmChallenge [ ' TargetInfoFields_len ' ] ] )
if av_pairs [ ntlm . NTLMSSP_AV_HOSTNAME ] is not None :
try :
self . __server_name = av_pairs [ ntlm . NTLMSSP_AV_HOSTNAME ] [ 1 ] . decode ( ' utf-16le ' )
except :
# For some reason, we couldn't decode Unicode here.. silently discard the operation
pass
if av_pairs [ ntlm . NTLMSSP_AV_DOMAINNAME ] is not None :
try :
if self . __server_name != av_pairs [ ntlm . NTLMSSP_AV_DOMAINNAME ] [ 1 ] . decode ( ' utf-16le ' ) :
self . __server_domain = av_pairs [ ntlm . NTLMSSP_AV_DOMAINNAME ] [ 1 ] . decode ( ' utf-16le ' )
except :
# For some reason, we couldn't decode Unicode here.. silently discard the operation
pass
if av_pairs [ ntlm . NTLMSSP_AV_DNS_DOMAINNAME ] is not None :
try :
self . __server_dns_domain_name = av_pairs [ ntlm . NTLMSSP_AV_DNS_DOMAINNAME ] [ 1 ] . decode ( ' utf-16le ' )
except :
# For some reason, we couldn't decode Unicode here.. silently discard the operation
pass
# Parse Version to know the target Operating system name. Not provided elsewhere anymore
2019-04-04 19:32:39 -04:00
if ' Version ' in ntlmChallenge . fields :
2017-06-30 08:53:19 -04:00
version = ntlmChallenge [ ' Version ' ]
if len ( version ) > = 4 :
self . __server_os_major , self . __server_os_minor , self . __server_os_build = unpack ( ' <BBH ' , version [ : 4 ] )
type3 , exportedSessionKey = ntlm . getNTLMSSPType3 ( auth , respToken [ ' ResponseToken ' ] , user , password , domain , lmhash , nthash , use_ntlmv2 = use_ntlmv2 )
if exportedSessionKey is not None :
self . _SigningSessionKey = exportedSessionKey
smb = NewSMBPacket ( )
# Are we required to sign SMB? If so we do it, if not we skip it
if self . _SignatureRequired :
smb [ ' Flags2 ' ] | = SMB . FLAGS2_SMB_SECURITY_SIGNATURE
respToken2 = SPNEGO_NegTokenResp ( )
respToken2 [ ' ResponseToken ' ] = str ( type3 )
# Reusing the previous structure
sessionSetup [ ' Parameters ' ] [ ' SecurityBlobLength ' ] = len ( respToken2 )
sessionSetup [ ' Data ' ] [ ' SecurityBlob ' ] = respToken2 . getData ( )
# Storing some info for later use
self . __server_os = sessionData [ ' NativeOS ' ]
self . __server_lanman = sessionData [ ' NativeLanMan ' ]
smb . addCommand ( sessionSetup )
self . sendSMB ( smb )
smb = self . recvSMB ( )
self . _uid = 0
if smb . isValidAnswer ( SMB . SMB_COM_SESSION_SETUP_ANDX ) :
self . _uid = smb [ ' Uid ' ]
sessionResponse = SMBCommand ( smb [ ' Data ' ] [ 0 ] )
sessionParameters = SMBSessionSetupAndXResponse_Parameters ( sessionResponse [ ' Parameters ' ] )
self . _action = sessionParameters [ ' Action ' ]
# If smb sign required, let's enable it for the rest of the connection
if self . _dialects_parameters [ ' SecurityMode ' ] & SMB . SECURITY_SIGNATURES_REQUIRED :
self . _SignSequenceNumber = 2
self . _SignatureEnabled = True
# restore unicode flag if needed
if flags2 & SMB . FLAGS2_UNICODE :
self . __flags2 | = SMB . FLAGS2_UNICODE
return 1
else :
raise Exception ( ' Error: Could not login successfully ' )
def getCredentials ( self ) :
return (
self . __userName ,
self . __password ,
self . __domain ,
self . __lmhash ,
self . __nthash ,
self . __aesKey ,
self . __TGT ,
self . __TGS )
def getIOCapabilities ( self ) :
res = dict ( )
if ( self . _dialects_parameters [ ' Capabilities ' ] & SMB . CAP_LARGE_READX ) and self . _SignatureEnabled is False :
max_size = 65000
else :
max_size = self . _dialects_parameters [ ' MaxBufferSize ' ] # Read in multiple KB blocks
res [ ' MaxReadSize ' ] = max_size
res [ ' MaxWriteSize ' ] = max_size
return res
def login ( self , user , password , domain = ' ' , lmhash = ' ' , nthash = ' ' , ntlm_fallback = True ) :
# If we have hashes, normalize them
if lmhash != ' ' or nthash != ' ' :
if len ( lmhash ) % 2 : lmhash = ' 0 %s ' % lmhash
if len ( nthash ) % 2 : nthash = ' 0 %s ' % nthash
try : # just in case they were converted already
lmhash = a2b_hex ( lmhash )
nthash = a2b_hex ( nthash )
except :
pass
self . __userName = user
self . __password = password
self . __domain = domain
self . __lmhash = lmhash
self . __nthash = nthash
self . __aesKey = ' '
self . __TGT = None
self . __TGS = None
if self . _dialects_parameters [ ' Capabilities ' ] & SMB . CAP_EXTENDED_SECURITY :
try :
self . login_extended ( user , password , domain , lmhash , nthash , use_ntlmv2 = True )
except :
# If the target OS is Windows 5.0 or Samba, let's try using NTLMv1
if ntlm_fallback and ( ( self . get_server_lanman ( ) . find ( ' Windows 2000 ' ) != - 1 ) or ( self . get_server_lanman ( ) . find ( ' Samba ' ) != - 1 ) ) :
self . login_extended ( user , password , domain , lmhash , nthash , use_ntlmv2 = False )
self . __isNTLMv2 = False
else :
raise
elif ntlm_fallback :
self . login_standard ( user , password , domain , lmhash , nthash )
self . __isNTLMv2 = False
else :
raise SessionError ( ' Cannot authenticate against target, enable ntlm_fallback ' )
def login_standard ( self , user , password , domain = ' ' , lmhash = ' ' , nthash = ' ' ) :
# login feature does not support unicode
# disable it if enabled
flags2 = self . __flags2
if flags2 & SMB . FLAGS2_UNICODE :
self . __flags2 = flags2 & ( flags2 ^ SMB . FLAGS2_UNICODE )
# Only supports NTLMv1
# Password is only encrypted if the server passed us an "encryption key" during protocol dialect negotiation
if self . _dialects_parameters [ ' ChallengeLength ' ] > 0 :
if lmhash != ' ' or nthash != ' ' :
pwd_ansi = self . get_ntlmv1_response ( lmhash )
pwd_unicode = self . get_ntlmv1_response ( nthash )
elif password :
lmhash = ntlm . compute_lmhash ( password )
nthash = ntlm . compute_nthash ( password )
pwd_ansi = self . get_ntlmv1_response ( lmhash )
pwd_unicode = self . get_ntlmv1_response ( nthash )
else : # NULL SESSION
pwd_ansi = ' '
pwd_unicode = ' '
else :
pwd_ansi = password
pwd_unicode = ' '
smb = NewSMBPacket ( )
sessionSetup = SMBCommand ( SMB . SMB_COM_SESSION_SETUP_ANDX )
sessionSetup [ ' Parameters ' ] = SMBSessionSetupAndX_Parameters ( )
sessionSetup [ ' Data ' ] = SMBSessionSetupAndX_Data ( )
sessionSetup [ ' Parameters ' ] [ ' MaxBuffer ' ] = 61440
sessionSetup [ ' Parameters ' ] [ ' MaxMpxCount ' ] = 2
sessionSetup [ ' Parameters ' ] [ ' VCNumber ' ] = os . getpid ( )
sessionSetup [ ' Parameters ' ] [ ' SessionKey ' ] = self . _dialects_parameters [ ' SessionKey ' ]
sessionSetup [ ' Parameters ' ] [ ' AnsiPwdLength ' ] = len ( pwd_ansi )
sessionSetup [ ' Parameters ' ] [ ' UnicodePwdLength ' ] = len ( pwd_unicode )
sessionSetup [ ' Parameters ' ] [ ' Capabilities ' ] = SMB . CAP_RAW_MODE | SMB . CAP_USE_NT_ERRORS | SMB . CAP_LARGE_READX | SMB . CAP_LARGE_WRITEX
sessionSetup [ ' Data ' ] [ ' AnsiPwd ' ] = pwd_ansi
sessionSetup [ ' Data ' ] [ ' UnicodePwd ' ] = pwd_unicode
sessionSetup [ ' Data ' ] [ ' Account ' ] = str ( user )
sessionSetup [ ' Data ' ] [ ' PrimaryDomain ' ] = str ( domain )
sessionSetup [ ' Data ' ] [ ' NativeOS ' ] = str ( os . name )
sessionSetup [ ' Data ' ] [ ' NativeLanMan ' ] = ' pysmb '
smb . addCommand ( sessionSetup )
self . sendSMB ( smb )
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_SESSION_SETUP_ANDX ) :
# We will need to use this uid field for all future requests/responses
self . _uid = smb [ ' Uid ' ]
sessionResponse = SMBCommand ( smb [ ' Data ' ] [ 0 ] )
sessionParameters = SMBSessionSetupAndXResponse_Parameters ( sessionResponse [ ' Parameters ' ] )
sessionData = SMBSessionSetupAndXResponse_Data ( flags = smb [ ' Flags2 ' ] , data = sessionResponse [ ' Data ' ] )
self . _action = sessionParameters [ ' Action ' ]
# Still gotta figure out how to do this with no EXTENDED_SECURITY
if sessionParameters [ ' Action ' ] & SMB_SETUP_USE_LANMAN_KEY == 0 :
self . _SigningChallengeResponse = sessionSetup [ ' Data ' ] [ ' UnicodePwd ' ]
self . _SigningSessionKey = nthash
else :
self . _SigningChallengeResponse = sessionSetup [ ' Data ' ] [ ' AnsiPwd ' ]
self . _SigningSessionKey = lmhash
#self._SignSequenceNumber = 1
#self.checkSignSMB(smb, self._SigningSessionKey ,self._SigningChallengeResponse)
#self._SignatureEnabled = True
self . __server_os = sessionData [ ' NativeOS ' ]
self . __server_lanman = sessionData [ ' NativeLanMan ' ]
self . __server_domain = sessionData [ ' PrimaryDomain ' ]
# restore unicode flag if needed
if flags2 & SMB . FLAGS2_UNICODE :
self . __flags2 | = SMB . FLAGS2_UNICODE
return 1
else : raise Exception ( ' Error: Could not login successfully ' )
def waitNamedPipe ( self , tid , pipe , timeout = 5 , noAnswer = 0 ) :
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
transCommand = SMBCommand ( SMB . SMB_COM_TRANSACTION )
transCommand [ ' Parameters ' ] = SMBTransaction_Parameters ( )
transCommand [ ' Data ' ] = SMBTransaction_Data ( )
setup = ' \x53 \x00 \x00 \x00 '
name = ' \\ PIPE %s \x00 ' % pipe
transCommand [ ' Parameters ' ] [ ' Setup ' ] = setup
transCommand [ ' Parameters ' ] [ ' TotalParameterCount ' ] = 0
transCommand [ ' Parameters ' ] [ ' TotalDataCount ' ] = 0
transCommand [ ' Parameters ' ] [ ' MaxParameterCount ' ] = 0
transCommand [ ' Parameters ' ] [ ' MaxDataCount ' ] = 0
transCommand [ ' Parameters ' ] [ ' Timeout ' ] = timeout * 1000
transCommand [ ' Parameters ' ] [ ' ParameterCount ' ] = 0
transCommand [ ' Parameters ' ] [ ' ParameterOffset ' ] = 32 + 3 + 28 + len ( setup ) + len ( name )
transCommand [ ' Parameters ' ] [ ' DataCount ' ] = 0
transCommand [ ' Parameters ' ] [ ' DataOffset ' ] = 0
transCommand [ ' Data ' ] [ ' Name ' ] = name
transCommand [ ' Data ' ] [ ' Trans_Parameters ' ] = ' '
transCommand [ ' Data ' ] [ ' Trans_Data ' ] = ' '
if noAnswer :
transCommand [ ' Parameters ' ] [ ' Flags ' ] = TRANS_NO_RESPONSE
smb . addCommand ( transCommand )
self . sendSMB ( smb )
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_TRANSACTION ) :
return 1
return 0
def read ( self , tid , fid , offset = 0 , max_size = None , wait_answer = 1 ) :
if not max_size :
max_size = self . _dialects_parameters [ ' MaxBufferSize ' ] # Read in multiple KB blocks
# max_size is not working, because although it would, the server returns an error (More data avail)
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
read = SMBCommand ( SMB . SMB_COM_READ )
read [ ' Parameters ' ] = SMBRead_Parameters ( )
read [ ' Parameters ' ] [ ' Fid ' ] = fid
read [ ' Parameters ' ] [ ' Offset ' ] = offset
read [ ' Parameters ' ] [ ' Count ' ] = max_size
smb . addCommand ( read )
if wait_answer :
while 1 :
self . sendSMB ( smb )
ans = self . recvSMB ( )
if ans . isValidAnswer ( SMB . SMB_COM_READ ) :
readResponse = SMBCommand ( ans [ ' Data ' ] [ 0 ] )
readData = SMBReadResponse_Data ( readResponse [ ' Data ' ] )
return readData [ ' Data ' ]
return None
def read_andx ( self , tid , fid , offset = 0 , max_size = None , wait_answer = 1 , smb_packet = None ) :
if not max_size :
if ( self . _dialects_parameters [ ' Capabilities ' ] & SMB . CAP_LARGE_READX ) and self . _SignatureEnabled is False :
max_size = 65000
else :
max_size = self . _dialects_parameters [ ' MaxBufferSize ' ] # Read in multiple KB blocks
# max_size is not working, because although it would, the server returns an error (More data avail)
if smb_packet is None :
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
readAndX = SMBCommand ( SMB . SMB_COM_READ_ANDX )
readAndX [ ' Parameters ' ] = SMBReadAndX_Parameters ( )
readAndX [ ' Parameters ' ] [ ' Fid ' ] = fid
readAndX [ ' Parameters ' ] [ ' Offset ' ] = offset
readAndX [ ' Parameters ' ] [ ' MaxCount ' ] = max_size
smb . addCommand ( readAndX )
else :
smb = smb_packet
if wait_answer :
answer = ' '
while 1 :
self . sendSMB ( smb )
ans = self . recvSMB ( )
if ans . isValidAnswer ( SMB . SMB_COM_READ_ANDX ) :
# XXX Here we are only using a few fields from the response
readAndXResponse = SMBCommand ( ans [ ' Data ' ] [ 0 ] )
readAndXParameters = SMBReadAndXResponse_Parameters ( readAndXResponse [ ' Parameters ' ] )
offset = readAndXParameters [ ' DataOffset ' ]
count = readAndXParameters [ ' DataCount ' ] + 0x10000 * readAndXParameters [ ' DataCount_Hi ' ]
answer + = str ( ans ) [ offset : offset + count ]
if not ans . isMoreData ( ) :
return answer
max_size = min ( max_size , readAndXParameters [ ' Remaining ' ] )
readAndX [ ' Parameters ' ] [ ' Offset ' ] + = count # XXX Offset is not important (apparently)
else :
self . sendSMB ( smb )
ans = self . recvSMB ( )
try :
if ans . isValidAnswer ( SMB . SMB_COM_READ_ANDX ) :
return ans
else :
return None
except :
return ans
return None
def read_raw ( self , tid , fid , offset = 0 , max_size = None , wait_answer = 1 ) :
if not max_size :
max_size = self . _dialects_parameters [ ' MaxBufferSize ' ] # Read in multiple KB blocks
# max_size is not working, because although it would, the server returns an error (More data avail)
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
readRaw = SMBCommand ( SMB . SMB_COM_READ_RAW )
readRaw [ ' Parameters ' ] = SMBReadRaw_Parameters ( )
readRaw [ ' Parameters ' ] [ ' Fid ' ] = fid
readRaw [ ' Parameters ' ] [ ' Offset ' ] = offset
readRaw [ ' Parameters ' ] [ ' MaxCount ' ] = max_size
smb . addCommand ( readRaw )
self . sendSMB ( smb )
if wait_answer :
data = self . _sess . recv_packet ( self . __timeout ) . get_trailer ( )
if not data :
# If there is no data it means there was an error
data = self . read_andx ( tid , fid , offset , max_size )
return data
return None
def write ( self , tid , fid , data , offset = 0 , wait_answer = 1 ) :
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
write = SMBCommand ( SMB . SMB_COM_WRITE )
write [ ' Parameters ' ] = SMBWrite_Parameters ( )
write [ ' Data ' ] = SMBWrite_Data ( )
write [ ' Parameters ' ] [ ' Fid ' ] = fid
write [ ' Parameters ' ] [ ' Count ' ] = len ( data )
write [ ' Parameters ' ] [ ' Offset ' ] = offset
write [ ' Parameters ' ] [ ' Remaining ' ] = len ( data )
write [ ' Data ' ] [ ' Data ' ] = data
smb . addCommand ( write )
self . sendSMB ( smb )
if wait_answer :
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_WRITE ) :
return smb
return None
def write_andx ( self , tid , fid , data , offset = 0 , wait_answer = 1 , write_pipe_mode = False , smb_packet = None ) :
if smb_packet is None :
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
writeAndX = SMBCommand ( SMB . SMB_COM_WRITE_ANDX )
smb . addCommand ( writeAndX )
writeAndX [ ' Parameters ' ] = SMBWriteAndX_Parameters ( )
writeAndX [ ' Parameters ' ] [ ' Fid ' ] = fid
writeAndX [ ' Parameters ' ] [ ' Offset ' ] = offset
writeAndX [ ' Parameters ' ] [ ' WriteMode ' ] = 8
writeAndX [ ' Parameters ' ] [ ' Remaining ' ] = len ( data )
writeAndX [ ' Parameters ' ] [ ' DataLength ' ] = len ( data )
writeAndX [ ' Parameters ' ] [ ' DataOffset ' ] = len ( smb ) # this length already includes the parameter
writeAndX [ ' Data ' ] = data
if write_pipe_mode is True :
# First of all we gotta know what the MaxBuffSize is
maxBuffSize = self . _dialects_parameters [ ' MaxBufferSize ' ]
if len ( data ) > maxBuffSize :
chunks_size = maxBuffSize - 60
writeAndX [ ' Parameters ' ] [ ' WriteMode ' ] = 0x0c
sendData = ' \xff \xff ' + data
totalLen = len ( sendData )
writeAndX [ ' Parameters ' ] [ ' DataLength ' ] = chunks_size
writeAndX [ ' Parameters ' ] [ ' Remaining ' ] = totalLen - 2
writeAndX [ ' Data ' ] = sendData [ : chunks_size ]
self . sendSMB ( smb )
if wait_answer :
smbResp = self . recvSMB ( )
smbResp . isValidAnswer ( SMB . SMB_COM_WRITE_ANDX )
alreadySent = chunks_size
sendData = sendData [ chunks_size : ]
while alreadySent < totalLen :
writeAndX [ ' Parameters ' ] [ ' WriteMode ' ] = 0x04
writeAndX [ ' Parameters ' ] [ ' DataLength ' ] = len ( sendData [ : chunks_size ] )
writeAndX [ ' Data ' ] = sendData [ : chunks_size ]
self . sendSMB ( smb )
if wait_answer :
smbResp = self . recvSMB ( )
smbResp . isValidAnswer ( SMB . SMB_COM_WRITE_ANDX )
alreadySent + = writeAndX [ ' Parameters ' ] [ ' DataLength ' ]
sendData = sendData [ chunks_size : ]
return smbResp
else :
smb = smb_packet
self . sendSMB ( smb )
if wait_answer :
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_WRITE_ANDX ) :
return smb
return None
def write_raw ( self , tid , fid , data , offset = 0 , wait_answer = 1 ) :
LOG . warning ( " [MS-CIFS] This command was introduced in the CorePlus dialect, but is often listed as part of the LAN Manager 1.0 dialect.This command has been deprecated.Clients SHOULD use SMB_COM_WRITE_ANDX " )
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
writeRaw = SMBCommand ( SMB . SMB_COM_WRITE_RAW )
writeRaw [ ' Parameters ' ] = SMBWriteRaw_Parameters ( )
writeRaw [ ' Parameters ' ] [ ' Fid ' ] = fid
writeRaw [ ' Parameters ' ] [ ' Offset ' ] = offset
writeRaw [ ' Parameters ' ] [ ' Count ' ] = len ( data )
writeRaw [ ' Parameters ' ] [ ' DataLength ' ] = 0
writeRaw [ ' Parameters ' ] [ ' DataOffset ' ] = 0
smb . addCommand ( writeRaw )
self . sendSMB ( smb )
self . _sess . send_packet ( data )
if wait_answer :
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_WRITE_RAW ) :
return smb
return None
def TransactNamedPipe ( self , tid , fid , data = ' ' , noAnswer = 0 , waitAnswer = 1 , offset = 0 ) :
self . send_trans ( tid , pack ( ' <HH ' , 0x26 , fid ) , ' \\ PIPE \\ \x00 ' , ' ' , data , noAnswer = noAnswer )
if noAnswer or not waitAnswer :
return
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_TRANSACTION ) :
transResponse = SMBCommand ( smb [ ' Data ' ] [ 0 ] )
transParameters = SMBTransactionResponse_Parameters ( transResponse [ ' Parameters ' ] )
return transResponse [ ' Data ' ] [ - transParameters [ ' TotalDataCount ' ] : ] # Remove Potential Prefix Padding
return None
def TransactNamedPipeRecv ( self ) :
s = self . recvSMB ( )
if s . isValidAnswer ( SMB . SMB_COM_TRANSACTION ) :
transResponse = SMBCommand ( s [ ' Data ' ] [ 0 ] )
transParameters = SMBTransactionResponse_Parameters ( transResponse [ ' Parameters ' ] )
return transResponse [ ' Data ' ] [ - transParameters [ ' TotalDataCount ' ] : ] # Remove Potential Prefix Padding
return None
def nt_create_andx ( self , tid , filename , smb_packet = None , cmd = None , shareAccessMode = FILE_SHARE_READ | FILE_SHARE_WRITE , disposition = FILE_OPEN , accessMask = 0x2019f ) :
filename = filename . replace ( ' / ' , ' \\ ' )
filename = filename . encode ( ' utf-16le ' ) if self . __flags2 & SMB . FLAGS2_UNICODE else filename
if smb_packet is None :
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
else :
smb = smb_packet
if cmd is None :
ntCreate = SMBCommand ( SMB . SMB_COM_NT_CREATE_ANDX )
ntCreate [ ' Parameters ' ] = SMBNtCreateAndX_Parameters ( )
ntCreate [ ' Data ' ] = SMBNtCreateAndX_Data ( flags = self . __flags2 )
ntCreate [ ' Parameters ' ] [ ' FileNameLength ' ] = len ( filename )
ntCreate [ ' Parameters ' ] [ ' CreateFlags ' ] = 0x16
ntCreate [ ' Parameters ' ] [ ' AccessMask ' ] = accessMask
ntCreate [ ' Parameters ' ] [ ' CreateOptions ' ] = 0x40
ntCreate [ ' Parameters ' ] [ ' ShareAccess ' ] = shareAccessMode
ntCreate [ ' Parameters ' ] [ ' Disposition ' ] = disposition
ntCreate [ ' Data ' ] [ ' FileName ' ] = filename
if self . __flags2 & SMB . FLAGS2_UNICODE :
ntCreate [ ' Data ' ] [ ' Pad ' ] = 0x0
else :
ntCreate = cmd
smb . addCommand ( ntCreate )
self . sendSMB ( smb )
while 1 :
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_NT_CREATE_ANDX ) :
# XXX Here we are ignoring the rest of the response
ntCreateResponse = SMBCommand ( smb [ ' Data ' ] [ 0 ] )
ntCreateParameters = SMBNtCreateAndXResponse_Parameters ( ntCreateResponse [ ' Parameters ' ] )
self . fid = ntCreateParameters [ ' Fid ' ]
return ntCreateParameters [ ' Fid ' ]
def logoff ( self ) :
smb = NewSMBPacket ( )
logOff = SMBCommand ( SMB . SMB_COM_LOGOFF_ANDX )
logOff [ ' Parameters ' ] = SMBLogOffAndX ( )
smb . addCommand ( logOff )
self . sendSMB ( smb )
self . recvSMB ( )
# Let's clear some fields so you can login again under the same session
self . _uid = 0
def list_path ( self , service , path = ' * ' , password = None ) :
path = path . replace ( ' / ' , ' \\ ' )
path = path . encode ( ' utf-16le ' ) if self . __flags2 & SMB . FLAGS2_UNICODE else path
tid = self . tree_connect_andx ( ' \\ \\ ' + self . __remote_name + ' \\ ' + service , password )
try :
findFirstParameter = SMBFindFirst2_Parameters ( )
findFirstParameter [ ' SearchAttributes ' ] = SMB_FILE_ATTRIBUTE_DIRECTORY | SMB_FILE_ATTRIBUTE_HIDDEN | \
SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_READONLY | \
SMB_FILE_ATTRIBUTE_ARCHIVE
findFirstParameter [ ' SearchCount ' ] = 512
findFirstParameter [ ' Flags ' ] = SMB_FIND_RETURN_RESUME_KEYS | SMB_FIND_CLOSE_AT_EOS
findFirstParameter [ ' InformationLevel ' ] = SMB_FIND_FILE_BOTH_DIRECTORY_INFO
findFirstParameter [ ' SearchStorageType ' ] = 0
findFirstParameter [ ' FileName ' ] = path + ( ' \x00 \x00 ' if self . __flags2 & SMB . FLAGS2_UNICODE else ' \x00 ' )
self . send_trans2 ( tid , SMB . TRANS2_FIND_FIRST2 , ' \x00 ' , findFirstParameter , ' ' )
files = [ ]
totalDataCount = 1
findData = ' '
findFirst2ParameterBlock = ' '
while len ( findData ) < totalDataCount :
resp = self . recvSMB ( )
if resp . isValidAnswer ( SMB . SMB_COM_TRANSACTION2 ) :
trans2Response = SMBCommand ( resp [ ' Data ' ] [ 0 ] )
trans2Parameters = SMBTransaction2Response_Parameters ( trans2Response [ ' Parameters ' ] )
totalDataCount = trans2Parameters [ ' TotalDataCount ' ]
findFirst2ParameterBlock + = trans2Response [ ' Data ' ] [ trans2Parameters [ ' ParameterOffset ' ] - 55 : ] [ : trans2Parameters [ ' ParameterCount ' ] ]
findData + = trans2Response [ ' Data ' ] [ trans2Parameters [ ' DataOffset ' ] - 55 : ]
findParameterBlock = SMBFindFirst2Response_Parameters ( findFirst2ParameterBlock )
# Save the SID for resume operations
sid = findParameterBlock [ ' SID ' ]
while True :
record = SMBFindFileBothDirectoryInfo ( data = findData )
shortname = record [ ' ShortName ' ] . decode ( ' utf-16le ' ) if self . __flags2 & SMB . FLAGS2_UNICODE else record [ ' ShortName ' ]
filename = record [ ' FileName ' ] . decode ( ' utf-16le ' ) if self . __flags2 & SMB . FLAGS2_UNICODE else record [ ' FileName ' ]
fileRecord = SharedFile ( record [ ' CreationTime ' ] , record [ ' LastAccessTime ' ] , record [ ' LastChangeTime ' ] ,
record [ ' EndOfFile ' ] , record [ ' AllocationSize ' ] , record [ ' ExtFileAttributes ' ] ,
shortname , filename )
files . append ( fileRecord )
if record [ ' NextEntryOffset ' ] > 0 and len ( findData [ record [ ' NextEntryOffset ' ] : ] ) > 0 :
findData = findData [ record [ ' NextEntryOffset ' ] : ]
else :
# More data to search?
if findParameterBlock [ ' EndOfSearch ' ] == 0 :
resume_filename = record [ ' FileName ' ]
findNextParameter = SMBFindNext2_Parameters ( )
findNextParameter [ ' SID ' ] = sid
findNextParameter [ ' SearchCount ' ] = 1024
findNextParameter [ ' InformationLevel ' ] = SMB_FIND_FILE_BOTH_DIRECTORY_INFO
findNextParameter [ ' ResumeKey ' ] = 0
findNextParameter [ ' Flags ' ] = SMB_FIND_RETURN_RESUME_KEYS | SMB_FIND_CLOSE_AT_EOS
findNextParameter [ ' FileName ' ] = resume_filename + ( ' \x00 \x00 ' if self . __flags2 & SMB . FLAGS2_UNICODE else ' \x00 ' )
self . send_trans2 ( tid , SMB . TRANS2_FIND_NEXT2 , ' \x00 ' , findNextParameter , ' ' )
findData = ' '
findNext2ParameterBlock = ' '
totalDataCount = 1
while len ( findData ) < totalDataCount :
resp = self . recvSMB ( )
if resp . isValidAnswer ( SMB . SMB_COM_TRANSACTION2 ) :
trans2Response = SMBCommand ( resp [ ' Data ' ] [ 0 ] )
trans2Parameters = SMBTransaction2Response_Parameters ( trans2Response [ ' Parameters ' ] )
totalDataCount = trans2Parameters [ ' TotalDataCount ' ]
findNext2ParameterBlock + = trans2Response [ ' Data ' ] [ trans2Parameters [ ' ParameterOffset ' ] - 55 : ] [ : trans2Parameters [ ' ParameterCount ' ] ]
findData + = trans2Response [ ' Data ' ] [ trans2Parameters [ ' DataOffset ' ] - 55 : ]
findParameterBlock = SMBFindNext2Response_Parameters ( findNext2ParameterBlock )
else :
break
finally :
self . disconnect_tree ( tid )
return files
def retr_file ( self , service , filename , callback , mode = FILE_OPEN , offset = 0 , password = None , shareAccessMode = SMB_ACCESS_READ ) :
filename = string . replace ( filename , ' / ' , ' \\ ' )
fid = - 1
tid = self . tree_connect_andx ( ' \\ \\ ' + self . __remote_name + ' \\ ' + service , password )
try :
fid = self . nt_create_andx ( tid , filename , shareAccessMode = shareAccessMode , accessMask = 0x20089 )
res = self . query_file_info ( tid , fid )
datasize = SMBQueryFileStandardInfo ( res ) [ ' EndOfFile ' ]
self . __nonraw_retr_file ( tid , fid , offset , datasize , callback )
finally :
if fid > = 0 :
self . close ( tid , fid )
self . disconnect_tree ( tid )
def stor_file ( self , service , filename , callback , mode = FILE_OVERWRITE_IF , offset = 0 , password = None , shareAccessMode = SMB_ACCESS_WRITE ) :
filename = string . replace ( filename , ' / ' , ' \\ ' )
fid = - 1
tid = self . tree_connect_andx ( ' \\ \\ ' + self . __remote_name + ' \\ ' + service , password )
try :
fid = self . nt_create_andx ( tid , filename , shareAccessMode = shareAccessMode , disposition = mode )
self . __nonraw_stor_file ( tid , fid , offset , 0 , callback )
finally :
if fid > = 0 :
self . close ( tid , fid )
self . disconnect_tree ( tid )
def stor_file_nonraw ( self , service , filename , callback , mode = FILE_OVERWRITE_IF , offset = 0 , password = None , shareAccessMode = SMB_ACCESS_WRITE ) :
filename = string . replace ( filename , ' / ' , ' \\ ' )
fid = - 1
tid = self . tree_connect_andx ( ' \\ \\ ' + self . __remote_name + ' \\ ' + service , password )
try :
fid = self . nt_create_andx ( tid , filename , shareAccessMode = shareAccessMode , disposition = mode )
self . __nonraw_stor_file ( tid , fid , offset , 0 , callback )
finally :
if fid > = 0 :
self . close ( tid , fid )
self . disconnect_tree ( tid )
def check_dir ( self , service , path , password = None ) :
path = string . replace ( path , ' / ' , ' \\ ' )
tid = self . tree_connect_andx ( ' \\ \\ ' + self . __remote_name + ' \\ ' + service , password )
try :
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
smb [ ' Mid ' ] = 0
cmd = SMBCommand ( SMB . SMB_COM_CHECK_DIRECTORY )
cmd [ ' Parameters ' ] = ' '
cmd [ ' Data ' ] = SMBCheckDirectory_Data ( flags = self . __flags2 )
cmd [ ' Data ' ] [ ' DirectoryName ' ] = path . encode ( ' utf-16le ' ) if self . __flags2 & SMB . FLAGS2_UNICODE else path
smb . addCommand ( cmd )
self . sendSMB ( smb )
while 1 :
s = self . recvSMB ( )
if s . isValidAnswer ( SMB . SMB_COM_CHECK_DIRECTORY ) :
return
finally :
self . disconnect_tree ( tid )
def remove ( self , service , path , password = None ) :
path = string . replace ( path , ' / ' , ' \\ ' )
# Perform a list to ensure the path exists
self . list_path ( service , path , password )
tid = self . tree_connect_andx ( ' \\ \\ ' + self . __remote_name + ' \\ ' + service , password )
try :
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
smb [ ' Mid ' ] = 0
cmd = SMBCommand ( SMB . SMB_COM_DELETE )
cmd [ ' Parameters ' ] = SMBDelete_Parameters ( )
cmd [ ' Parameters ' ] [ ' SearchAttributes ' ] = ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE
cmd [ ' Data ' ] = SMBDelete_Data ( flags = self . __flags2 )
cmd [ ' Data ' ] [ ' FileName ' ] = ( path + ' \x00 ' ) . encode ( ' utf-16le ' ) if self . __flags2 & SMB . FLAGS2_UNICODE else ( path + ' \x00 ' )
smb . addCommand ( cmd )
self . sendSMB ( smb )
while 1 :
s = self . recvSMB ( )
if s . isValidAnswer ( SMB . SMB_COM_DELETE ) :
return
finally :
self . disconnect_tree ( tid )
def rmdir ( self , service , path , password = None ) :
path = string . replace ( path , ' / ' , ' \\ ' )
# Check that the directory exists
self . check_dir ( service , path , password )
tid = self . tree_connect_andx ( ' \\ \\ ' + self . __remote_name + ' \\ ' + service , password )
try :
path = path . encode ( ' utf-16le ' ) if self . __flags2 & SMB . FLAGS2_UNICODE else path
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
createDir = SMBCommand ( SMB . SMB_COM_DELETE_DIRECTORY )
createDir [ ' Data ' ] = SMBDeleteDirectory_Data ( flags = self . __flags2 )
createDir [ ' Data ' ] [ ' DirectoryName ' ] = path
smb . addCommand ( createDir )
self . sendSMB ( smb )
while 1 :
s = self . recvSMB ( )
if s . isValidAnswer ( SMB . SMB_COM_DELETE_DIRECTORY ) :
return
finally :
self . disconnect_tree ( tid )
def mkdir ( self , service , path , password = None ) :
path = string . replace ( path , ' / ' , ' \\ ' )
tid = self . tree_connect_andx ( ' \\ \\ ' + self . __remote_name + ' \\ ' + service , password )
try :
path = path . encode ( ' utf-16le ' ) if self . __flags2 & SMB . FLAGS2_UNICODE else path
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
smb [ ' Mid ' ] = 0
createDir = SMBCommand ( SMB . SMB_COM_CREATE_DIRECTORY )
createDir [ ' Data ' ] = SMBCreateDirectory_Data ( flags = self . __flags2 )
createDir [ ' Data ' ] [ ' DirectoryName ' ] = path
smb . addCommand ( createDir )
self . sendSMB ( smb )
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_CREATE_DIRECTORY ) :
return 1
return 0
finally :
self . disconnect_tree ( tid )
def rename ( self , service , old_path , new_path , password = None ) :
old_path = string . replace ( old_path , ' / ' , ' \\ ' )
new_path = string . replace ( new_path , ' / ' , ' \\ ' )
tid = self . tree_connect_andx ( ' \\ \\ ' + self . __remote_name + ' \\ ' + service , password )
try :
smb = NewSMBPacket ( )
smb [ ' Tid ' ] = tid
smb [ ' Mid ' ] = 0
renameCmd = SMBCommand ( SMB . SMB_COM_RENAME )
renameCmd [ ' Parameters ' ] = SMBRename_Parameters ( )
renameCmd [ ' Parameters ' ] [ ' SearchAttributes ' ] = ATTR_SYSTEM | ATTR_HIDDEN | ATTR_DIRECTORY
renameCmd [ ' Data ' ] = SMBRename_Data ( flags = self . __flags2 )
renameCmd [ ' Data ' ] [ ' OldFileName ' ] = old_path . encode ( ' utf-16le ' ) if self . __flags2 & SMB . FLAGS2_UNICODE else old_path
renameCmd [ ' Data ' ] [ ' NewFileName ' ] = new_path . encode ( ' utf-16le ' ) if self . __flags2 & SMB . FLAGS2_UNICODE else new_path
smb . addCommand ( renameCmd )
self . sendSMB ( smb )
smb = self . recvSMB ( )
if smb . isValidAnswer ( SMB . SMB_COM_RENAME ) :
return 1
return 0
finally :
self . disconnect_tree ( tid )
def writeFile ( self , treeId , fileId , data , offset = 0 ) :
if ( self . _dialects_parameters [ ' Capabilities ' ] & SMB . CAP_LARGE_WRITEX ) and self . _SignatureEnabled is False :
max_buf_size = 65000
else :
max_buf_size = self . _dialects_parameters [ ' MaxBufferSize ' ] & ~ 0x3ff # Write in multiple KB blocks
write_offset = offset
while 1 :
if len ( data ) == 0 :
break
writeData = data [ : max_buf_size ]
data = data [ max_buf_size : ]
smb = self . write_andx ( treeId , fileId , writeData , write_offset )
writeResponse = SMBCommand ( smb [ ' Data ' ] [ 0 ] )
writeResponseParameters = SMBWriteAndXResponse_Parameters ( writeResponse [ ' Parameters ' ] )
write_offset + = writeResponseParameters [ ' Count ' ]
def get_socket ( self ) :
return self . _sess . get_socket ( )
ERRDOS = { 1 : ' Invalid function ' ,
2 : ' File not found ' ,
3 : ' Invalid directory ' ,
4 : ' Too many open files ' ,
5 : ' Access denied ' ,
6 : ' Invalid file handle. Please file a bug report. ' ,
7 : ' Memory control blocks destroyed ' ,
8 : ' Out of memory ' ,
9 : ' Invalid memory block address ' ,
10 : ' Invalid environment ' ,
11 : ' Invalid format ' ,
12 : ' Invalid open mode ' ,
13 : ' Invalid data ' ,
15 : ' Invalid drive ' ,
16 : ' Attempt to remove server \' s current directory ' ,
17 : ' Not the same device ' ,
18 : ' No files found ' ,
32 : ' Sharing mode conflicts detected ' ,
33 : ' Lock request conflicts detected ' ,
80 : ' File already exists '
}
ERRSRV = { 1 : ' Non-specific error ' ,
2 : ' Bad password ' ,
4 : ' Access denied ' ,
5 : ' Invalid tid. Please file a bug report. ' ,
6 : ' Invalid network name ' ,
7 : ' Invalid device ' ,
49 : ' Print queue full ' ,
50 : ' Print queue full ' ,
51 : ' EOF on print queue dump ' ,
52 : ' Invalid print file handle ' ,
64 : ' Command not recognized. Please file a bug report. ' ,
65 : ' Internal server error ' ,
67 : ' Invalid path ' ,
69 : ' Invalid access permissions ' ,
71 : ' Invalid attribute mode ' ,
81 : ' Server is paused ' ,
82 : ' Not receiving messages ' ,
83 : ' No room to buffer messages ' ,
87 : ' Too many remote user names ' ,
88 : ' Operation timeout ' ,
89 : ' Out of resources ' ,
91 : ' Invalid user handle. Please file a bug report. ' ,
250 : ' Temporarily unable to support raw mode for transfer ' ,
251 : ' Temporarily unable to support raw mode for transfer ' ,
252 : ' Continue in MPX mode ' ,
65535 : ' Unsupported function '
}
ERRHRD = { 19 : ' Media is write-protected ' ,
20 : ' Unknown unit ' ,
21 : ' Drive not ready ' ,
22 : ' Unknown command ' ,
23 : ' CRC error ' ,
24 : ' Bad request ' ,
25 : ' Seek error ' ,
26 : ' Unknown media type ' ,
27 : ' Sector not found ' ,
28 : ' Printer out of paper ' ,
29 : ' Write fault ' ,
30 : ' Read fault ' ,
31 : ' General failure ' ,
32 : ' Open conflicts with an existing open ' ,
33 : ' Invalid lock request ' ,
34 : ' Wrong disk in drive ' ,
35 : ' FCBs not available ' ,
36 : ' Sharing buffer exceeded '
}