github.com/n00py/Slackor@v0.0.0-20200610224921-d007fcea1740/impacket/tests/SMB_RPC/test_smb.py (about)

     1  import unittest
     2  import os
     3  import socket
     4  import select
     5  import errno
     6  
     7  try:
     8      import ConfigParser
     9  except ImportError:
    10      import configparser as ConfigParser
    11  
    12  from binascii import unhexlify
    13  from impacket.smbconnection import SMBConnection, smb
    14  from impacket.smb3structs import SMB2_DIALECT_002,SMB2_DIALECT_21, SMB2_DIALECT_30
    15  from impacket import nt_errors, nmb
    16  
    17  # IMPORTANT NOTE:
    18  # For some reason, under Windows 8, you cannot switch between
    19  # dialects 002, 2_1 and 3_0 (it will throw STATUS_USER_SESSION_DELETED),
    20  # but you can with SMB1.
    21  # So, you can't run all test cases against the same machine.
    22  # Usually running all the tests against a Windows 7 except SMB3
    23  # would do the trick.
    24  # ToDo:
    25  # [ ] Add the rest of SMBConnection public methods
    26  
    27  class SMBTests(unittest.TestCase):
    28      def create_connection(self):
    29          if self.dialects == smb.SMB_DIALECT:
    30              # Only for SMB1 let's do manualNego
    31              s = SMBConnection(self.serverName, self.machine, preferredDialect = self.dialects, sess_port = self.sessPort, manualNegotiate=True)
    32              s.negotiateSession(self.dialects, flags2=self.flags2)
    33          else:
    34              s = SMBConnection(self.serverName, self.machine, preferredDialect = self.dialects, sess_port = self.sessPort)
    35          return s
    36  
    37      def test_aliasconnection(self):
    38          smb = SMBConnection('*SMBSERVER', self.machine, preferredDialect=self.dialects, sess_port=self.sessPort)
    39          smb.login(self.username, self.password, self.domain)
    40          smb.listPath(self.share, '*')
    41          smb.logoff()
    42  
    43      def test_reconnect(self):
    44          smb = self.create_connection()
    45          smb.login(self.username, self.password, self.domain)
    46          smb.listPath(self.share, '*')
    47          smb.logoff()
    48          smb.reconnect()
    49          smb.listPath(self.share, '*')
    50          smb.logoff()
    51  
    52      def test_reconnectKerberosHashes(self):
    53          lmhash, nthash = self.hashes.split(':')
    54          smb = self.create_connection()
    55          smb.kerberosLogin(self.username, '', self.domain, lmhash, nthash, '')
    56          credentials = smb.getCredentials()
    57          self.assertTrue( credentials == (self.username, '', self.domain, unhexlify(lmhash), unhexlify(nthash), '', None, None) )
    58          UNC = '\\\\%s\\%s' % (self.machine, self.share)
    59          smb.connectTree(UNC)
    60          smb.logoff()
    61          smb.reconnect()
    62          credentials = smb.getCredentials()
    63          self.assertTrue(
    64              credentials == (self.username, '', self.domain, unhexlify(lmhash), unhexlify(nthash), '', None, None))
    65          UNC = '\\\\%s\\%s' % (self.machine, self.share)
    66          smb.connectTree(UNC)
    67          smb.logoff()
    68  
    69      def test_connectTree(self):
    70          smb = self.create_connection()
    71          smb.login(self.username, self.password, self.domain)
    72          smb.connectTree(self.share)
    73          UNC = '\\\\%s\\%s' % (self.machine, self.share)
    74          smb.connectTree(UNC)
    75  
    76      def test_connection(self):
    77          smb = self.create_connection()
    78          smb.login(self.username, self.password, self.domain)
    79          credentials = smb.getCredentials()
    80          self.assertTrue( credentials == (self.username, self.password, self.domain, '','','', None, None))
    81          smb.logoff()
    82          del(smb)
    83          
    84      def test_close_connection(self):
    85          smb = self.create_connection()
    86          smb.login(self.username, self.password, self.domain)
    87          smb_connection_socket = smb.getSMBServer().get_socket()
    88          self.assertTrue(self.__is_socket_opened(smb_connection_socket) == True)
    89          smb.close()
    90          self.assertTrue(self.__is_socket_opened(smb_connection_socket) == False)
    91          del(smb)
    92  
    93      def test_manualNego(self):
    94          smb = self.create_connection()
    95          smb.negotiateSession(self.dialects)
    96          smb.login(self.username, self.password, self.domain)
    97          credentials = smb.getCredentials()
    98          self.assertTrue( credentials == (self.username, self.password, self.domain, '','','', None, None))
    99          smb.logoff()
   100          del(smb)
   101  
   102      def test_loginHashes(self):
   103          lmhash, nthash = self.hashes.split(':')
   104          smb = self.create_connection()
   105          smb.login(self.username, '', self.domain, lmhash, nthash)
   106          credentials = smb.getCredentials()
   107          self.assertTrue( credentials == (self.username, '', self.domain, unhexlify(lmhash), unhexlify(nthash), '', None, None) )
   108          smb.logoff()
   109  
   110      def test_loginKerberosHashes(self):
   111          lmhash, nthash = self.hashes.split(':')
   112          smb = self.create_connection()
   113          smb.kerberosLogin(self.username, '', self.domain, lmhash, nthash, '')
   114          credentials = smb.getCredentials()
   115          self.assertTrue( credentials == (self.username, '', self.domain, unhexlify(lmhash), unhexlify(nthash), '', None, None) )
   116          UNC = '\\\\%s\\%s' % (self.machine, self.share)
   117          smb.connectTree(UNC)
   118          smb.logoff()
   119  
   120      def test_loginKerberos(self):
   121          smb = self.create_connection()
   122          smb.kerberosLogin(self.username, self.password, self.domain, '', '', '')
   123          credentials = smb.getCredentials()
   124          self.assertTrue( credentials == (self.username, self.password, self.domain, '','','', None, None) )
   125          UNC = '\\\\%s\\%s' % (self.machine, self.share)
   126          smb.connectTree(UNC)
   127          smb.logoff()
   128  
   129      def test_loginKerberosAES(self):
   130          smb = self.create_connection()
   131          smb.kerberosLogin(self.username, '', self.domain, '', '', self.aesKey)
   132          credentials = smb.getCredentials()
   133          self.assertTrue( credentials == (self.username, '', self.domain, '','',self.aesKey, None, None) )
   134          UNC = '\\\\%s\\%s' % (self.machine, self.share)
   135          smb.connectTree(UNC)
   136          smb.logoff()
   137  
   138      def test_listPath(self):
   139          smb = self.create_connection()
   140          smb.login(self.username, self.password, self.domain)
   141          smb.listPath(self.share, '*')
   142          smb.logoff()
   143  
   144      def test_createFile(self):
   145          smb = self.create_connection()
   146          smb.login(self.username, self.password, self.domain)
   147          tid = smb.connectTree(self.share)
   148          fid = smb.createFile(tid, self.file)
   149          smb.closeFile(tid,fid)
   150          smb.rename(self.share, self.file, self.file + '.bak')
   151          smb.deleteFile(self.share, self.file + '.bak')
   152          smb.disconnectTree(tid)
   153          smb.logoff()
   154          
   155      def test_readwriteFile(self):
   156          smb = self.create_connection()
   157          smb.login(self.username, self.password, self.domain)
   158          tid = smb.connectTree(self.share)
   159          fid = smb.createFile(tid, self.file)
   160          smb.writeFile(tid, fid, "A"*65535)
   161          data = b''
   162          offset = 0
   163          remaining = 65535
   164          while remaining>0:
   165              data += smb.readFile(tid,fid, offset, remaining)
   166              remaining = 65535 - len(data)
   167          self.assertTrue(len(data) == 65535)
   168          self.assertTrue(data == b"A"*65535)
   169          smb.closeFile(tid,fid)
   170          fid = smb.openFile(tid, self.file)
   171          smb.closeFile(tid, fid)
   172          smb.deleteFile(self.share, self.file)
   173          smb.disconnectTree(tid)
   174          
   175          smb.logoff()
   176           
   177      def test_createdeleteDirectory(self):
   178          smb = self.create_connection()
   179          smb.login(self.username, self.password, self.domain)
   180          smb.createDirectory(self.share, self.directory)
   181          smb.deleteDirectory(self.share, self.directory)
   182          smb.createDirectory(self.share, self.directory)
   183          nested_dir = "%s\\%s" %(self.directory, self.directory)
   184          smb.createDirectory(self.share, nested_dir)
   185          try:
   186              smb.deleteDirectory(self.share, self.directory)
   187          except Exception as e:
   188              if e.error == nt_errors.STATUS_DIRECTORY_NOT_EMPTY:
   189                  smb.deleteDirectory(self.share, nested_dir)
   190                  smb.deleteDirectory(self.share, self.directory)
   191          smb.logoff()
   192   
   193      def test_getData(self):
   194          smb = self.create_connection()
   195          smb.login(self.username, self.password, self.domain)
   196          smb.getDialect()
   197          smb.getServerName()
   198          smb.getRemoteHost()
   199          smb.getServerDomain()
   200          smb.getServerOS()
   201          smb.doesSupportNTLMv2()
   202          smb.isLoginRequired()
   203          smb.logoff()
   204  
   205      def test_getServerName(self):
   206          smb = self.create_connection()
   207          smb.login(self.username, self.password, self.domain)
   208          serverName = smb.getServerName()
   209          self.assertTrue( serverName.upper() == self.serverName.upper() )
   210          smb.logoff()
   211  
   212      def test_getServerDNSDomainName(self):
   213          smb = self.create_connection()
   214          smb.login(self.username, self.password, self.domain)
   215          serverDomain = smb.getServerDNSDomainName()
   216          self.assertTrue( serverDomain.upper() == self.domain.upper())
   217          smb.logoff()
   218  
   219      def test_getServerDomain(self):
   220          smb = self.create_connection()
   221          smb.login(self.username, self.password, self.domain)
   222          serverDomain = smb.getServerDomain()
   223          self.assertTrue( serverDomain.upper() == self.domain.upper().split('.')[0])
   224          smb.logoff()
   225  
   226      def test_getRemoteHost(self):
   227          smb = self.create_connection()
   228          smb.login(self.username, self.password, self.domain)
   229          remoteHost = smb.getRemoteHost()
   230          self.assertTrue( remoteHost == self.machine)
   231          smb.logoff()
   232  
   233      def test_getDialect(self):
   234          smb = self.create_connection()
   235          smb.login(self.username, self.password, self.domain)
   236          dialect = smb.getDialect()
   237          self.assertTrue( dialect == self.dialects)
   238          smb.logoff()
   239  
   240      def test_uploadDownload(self):
   241          smb = self.create_connection()
   242          smb.login(self.username, self.password, self.domain)
   243          f = open(self.upload)
   244          smb.putFile(self.share, self.file, f.read)
   245          f.close()
   246          f = open(self.upload + '2', 'wb+')
   247          smb.getFile(self.share, self.file, f.write)
   248          f.close()
   249          os.unlink(self.upload + '2')
   250          smb.deleteFile(self.share, self.file)
   251          smb.logoff()
   252  
   253      def test_listShares(self):
   254          smb = self.create_connection()
   255          smb.login(self.username, self.password, self.domain)
   256          smb.listShares()
   257          smb.logoff()
   258  
   259      def test_getSessionKey(self):
   260          smb = self.create_connection()
   261          smb.login(self.username, self.password, self.domain)
   262          smb.getSessionKey()
   263          smb.logoff
   264          
   265      def __is_socket_opened(self, s):
   266          # We assume that if socket is selectable, it's open; and if it were not, it's closed.
   267          # Note: this method is accurate as long as the file descriptor used for the socket is not re-used
   268          is_socket_opened = True 
   269          try:
   270              select.select([s], [], [], 0)
   271          except socket.error as e:
   272              if e[0] == errno.EBADF:
   273                  is_socket_opened = False
   274          except ValueError:
   275              is_socket_opened = False
   276          return is_socket_opened
   277  
   278  class SMB1Tests(SMBTests):
   279      def setUp(self):
   280          SMBTests.setUp(self)
   281          # Put specific configuration for target machine with SMB1
   282          configFile = ConfigParser.ConfigParser()
   283          configFile.read('dcetests.cfg')
   284          self.username = configFile.get('SMBTransport', 'username')
   285          self.domain   = configFile.get('SMBTransport', 'domain')
   286          self.serverName = configFile.get('SMBTransport', 'servername')
   287          self.password = configFile.get('SMBTransport', 'password')
   288          self.machine  = configFile.get('SMBTransport', 'machine')
   289          self.hashes   = configFile.get('SMBTransport', 'hashes')
   290          self.aesKey   = configFile.get('SMBTransport', 'aesKey128')
   291          self.share    = 'C$'
   292          self.file     = '/TEST'
   293          self.directory= '/BETO'
   294          self.upload   = '../../impacket/nt_errors.py'
   295          self.flags2   = smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_EXTENDED_SECURITY | smb.SMB.FLAGS2_LONG_NAMES
   296          self.dialects = smb.SMB_DIALECT
   297          self.sessPort = nmb.SMB_SESSION_PORT
   298  
   299  class SMB1TestsNetBIOS(SMBTests):
   300      def setUp(self):
   301          SMBTests.setUp(self)
   302          # Put specific configuration for target machine with SMB1
   303          configFile = ConfigParser.ConfigParser()
   304          configFile.read('dcetests.cfg')
   305          self.username = configFile.get('SMBTransport', 'username')
   306          self.domain   = configFile.get('SMBTransport', 'domain')
   307          self.serverName = configFile.get('SMBTransport', 'servername')
   308          self.password = configFile.get('SMBTransport', 'password')
   309          self.machine  = configFile.get('SMBTransport', 'machine')
   310          self.hashes   = configFile.get('SMBTransport', 'hashes')
   311          self.aesKey   = configFile.get('SMBTransport', 'aesKey128')
   312          self.share    = 'C$'
   313          self.file     = '/TEST'
   314          self.directory= '/BETO'
   315          self.upload   = '../../impacket/nt_errors.py'
   316          self.flags2   = smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_EXTENDED_SECURITY | smb.SMB.FLAGS2_LONG_NAMES
   317          self.dialects = smb.SMB_DIALECT
   318          self.sessPort = nmb.NETBIOS_SESSION_PORT
   319  
   320  class SMB1TestsUnicode(SMBTests):
   321      def setUp(self):
   322          SMBTests.setUp(self)
   323          # Put specific configuration for target machine with SMB1
   324          configFile = ConfigParser.ConfigParser()
   325          configFile.read('dcetests.cfg')
   326          self.username = configFile.get('SMBTransport', 'username')
   327          self.domain   = configFile.get('SMBTransport', 'domain')
   328          self.serverName = configFile.get('SMBTransport', 'servername')
   329          self.password = configFile.get('SMBTransport', 'password')
   330          self.machine  = configFile.get('SMBTransport', 'machine')
   331          self.hashes   = configFile.get('SMBTransport', 'hashes')
   332          self.aesKey   = configFile.get('SMBTransport', 'aesKey128')
   333          self.share    = 'C$'
   334          self.file     = '/TEST'
   335          self.directory= '/BETO'
   336          self.upload   = '../../impacket/nt_errors.py'
   337          self.flags2   = smb.SMB.FLAGS2_UNICODE | smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_EXTENDED_SECURITY | smb.SMB.FLAGS2_LONG_NAMES
   338          self.dialects = smb.SMB_DIALECT
   339          self.sessPort = nmb.SMB_SESSION_PORT
   340  
   341  class SMB002Tests(SMBTests):
   342      def setUp(self):
   343          # Put specific configuration for target machine with SMB_002
   344          SMBTests.setUp(self)
   345          configFile = ConfigParser.ConfigParser()
   346          configFile.read('dcetests.cfg')
   347          self.username = configFile.get('SMBTransport', 'username')
   348          self.domain   = configFile.get('SMBTransport', 'domain')
   349          self.serverName = configFile.get('SMBTransport', 'servername')
   350          self.password = configFile.get('SMBTransport', 'password')
   351          self.machine  = configFile.get('SMBTransport', 'machine')
   352          self.hashes   = configFile.get('SMBTransport', 'hashes')
   353          self.aesKey   = configFile.get('SMBTransport', 'aesKey128')
   354          self.share    = 'C$'
   355          self.file     = '/TEST'
   356          self.directory= '/BETO'
   357          self.upload   = '../../impacket/nt_errors.py'
   358          self.dialects = SMB2_DIALECT_002
   359          self.sessPort = nmb.SMB_SESSION_PORT
   360  
   361  class SMB21Tests(SMBTests):
   362      def setUp(self):
   363          # Put specific configuration for target machine with SMB 2.1
   364          SMBTests.setUp(self)
   365          configFile = ConfigParser.ConfigParser()
   366          configFile.read('dcetests.cfg')
   367          self.username = configFile.get('SMBTransport', 'username')
   368          self.domain   = configFile.get('SMBTransport', 'domain')
   369          self.serverName = configFile.get('SMBTransport', 'servername')
   370          self.password = configFile.get('SMBTransport', 'password')
   371          self.machine  = configFile.get('SMBTransport', 'machine')
   372          self.hashes   = configFile.get('SMBTransport', 'hashes')
   373          self.aesKey   = configFile.get('SMBTransport', 'aesKey128')
   374          self.share    = 'C$'
   375          self.file     = '/TEST'
   376          self.directory= '/BETO'
   377          self.upload   = '../../impacket/nt_errors.py'
   378          self.dialects = SMB2_DIALECT_21
   379          self.sessPort = nmb.SMB_SESSION_PORT
   380  
   381  class SMB3Tests(SMBTests):
   382      def setUp(self):
   383          # Put specific configuration for target machine with SMB3
   384          SMBTests.setUp(self)
   385          configFile = ConfigParser.ConfigParser()
   386          configFile.read('dcetests.cfg')
   387          self.username = configFile.get('SMBTransport', 'username')
   388          self.domain   = configFile.get('SMBTransport', 'domain')
   389          self.serverName = configFile.get('SMBTransport', 'servername')
   390          self.password = configFile.get('SMBTransport', 'password')
   391          self.machine  = configFile.get('SMBTransport', 'machine')
   392          self.hashes   = configFile.get('SMBTransport', 'hashes')
   393          self.aesKey   = configFile.get('SMBTransport', 'aesKey128')
   394          self.share    = 'C$'
   395          self.file     = '/TEST'
   396          self.directory= '/BETO'
   397          self.upload   = '../../impacket/nt_errors.py'
   398          self.dialects = SMB2_DIALECT_30
   399          self.sessPort = nmb.SMB_SESSION_PORT
   400  
   401  if __name__ == "__main__":
   402      suite = unittest.TestLoader().loadTestsFromTestCase(SMB1Tests)
   403      suite.addTests(unittest.TestLoader().loadTestsFromTestCase(SMB1TestsNetBIOS))
   404      suite.addTests(unittest.TestLoader().loadTestsFromTestCase(SMB1TestsUnicode))
   405      suite.addTests(unittest.TestLoader().loadTestsFromTestCase(SMB002Tests))
   406      suite.addTests(unittest.TestLoader().loadTestsFromTestCase(SMB21Tests))
   407      suite.addTests(unittest.TestLoader().loadTestsFromTestCase(SMB3Tests))
   408      unittest.TextTestRunner(verbosity=1).run(suite)