def openFile(self, treeId, pathName, desiredAccess = FILE_READ_DATA | FILE_WRITE_DATA, shareMode = FILE_SHARE_READ, creationOption = FILE_NON_DIRECTORY_FILE, creationDisposition = FILE_OPEN, fileAttributes = FILE_ATTRIBUTE_NORMAL, impersonationLevel = SMB2_IL_IMPERSONATION, securityFlags = 0, oplockLevel = SMB2_OPLOCK_LEVEL_NONE, createContexts = None): """ opens a remote file :param HANDLE treeId: a valid handle for the share where the file is to be opened :param string pathName: the path name to open :return: a valid file descriptor, if not raises a SessionError exception. """ if self.getDialect() == smb.SMB_DIALECT: pathName = string.replace(pathName, '/', '\\') ntCreate = smb.SMBCommand(smb.SMB.SMB_COM_NT_CREATE_ANDX) ntCreate['Parameters'] = smb.SMBNtCreateAndX_Parameters() ntCreate['Data'] = smb.SMBNtCreateAndX_Data() ntCreate['Parameters']['FileNameLength']= len(pathName) ntCreate['Parameters']['AccessMask'] = desiredAccess ntCreate['Parameters']['FileAttributes']= fileAttributes ntCreate['Parameters']['ShareAccess'] = shareMode ntCreate['Parameters']['Disposition'] = creationDisposition ntCreate['Parameters']['CreateOptions'] = creationOption ntCreate['Parameters']['Impersonation'] = impersonationLevel ntCreate['Parameters']['SecurityFlags'] = securityFlags ntCreate['Parameters']['CreateFlags'] = 0x16 ntCreate['Data']['FileName'] = pathName if createContexts is not None: print "CreateContexts not supported in SMB1" try: return self._SMBConnection.nt_create_andx(treeId, pathName, cmd = ntCreate) except (smb.SessionError, smb3.SessionError), e: raise SessionError(e.get_error_code())
def connectPipe(self): try: lock.acquire() self.server = smb.SMB( '*SMBSERVER', self.transport.get_smb_server().get_remote_host(), sess_port=self.port) user, passwd, domain, lm, nt = self.credentials self.server.login(user, passwd, domain, lm, nt) lock.release() self.tid = self.server.tree_connect_andx( '\\\\%s\\IPC$' % self.transport.get_smb_server().get_remote_name()) self.server.waitNamedPipe(self.tid, self.pipe) ntCreate = smb.SMBCommand(smb.SMB.SMB_COM_NT_CREATE_ANDX) ntCreate['Parameters'] = smb.SMBNtCreateAndX_Parameters() ntCreate['Data'] = smb.SMBNtCreateAndX_Data() ntCreate['Parameters']['FileNameLength'] = len(self.pipe) ntCreate['Parameters']['FileAttributes'] = 0x80 ntCreate['Parameters']['CreateFlags'] = 0x0 ntCreate['Parameters']['AccessMask'] = self.permissions ntCreate['Parameters']['CreateOptions'] = 0x40 ntCreate['Parameters']['ShareAccess'] = 0x7 ntCreate['Data']['FileName'] = self.pipe self.fid = self.server.nt_create_andx(self.tid, self.pipe, cmd=ntCreate) self.server.set_timeout(1000000) except: print "[!] Something wen't wrong connecting the pipes(%s), try again" % self.__class__
def createFile(self, treeId, pathName, desiredAccess=GENERIC_ALL, shareMode=FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, creationOption=FILE_NON_DIRECTORY_FILE, creationDisposition=FILE_OVERWRITE_IF, fileAttributes=FILE_ATTRIBUTE_NORMAL, impersonationLevel=SMB2_IL_IMPERSONATION, securityFlags=0, oplockLevel=SMB2_OPLOCK_LEVEL_NONE, createContexts=None): """ creates a remote file :param HANDLE treeId: a valid handle for the share where the file is to be created :param string pathName: the path name of the file to create :return: a valid file descriptor, if not raises a SessionError exception. """ if self.getDialect() == smb.SMB_DIALECT: _, flags2 = self._SMBConnection.get_flags() pathName = pathName.replace('/', '\\') pathName = pathName.encode( 'utf-16le') if flags2 & smb.SMB.FLAGS2_UNICODE else pathName ntCreate = smb.SMBCommand(smb.SMB.SMB_COM_NT_CREATE_ANDX) ntCreate['Parameters'] = smb.SMBNtCreateAndX_Parameters() ntCreate['Data'] = smb.SMBNtCreateAndX_Data(flags=flags2) ntCreate['Parameters']['FileNameLength'] = len(pathName) ntCreate['Parameters']['AccessMask'] = desiredAccess ntCreate['Parameters']['FileAttributes'] = fileAttributes ntCreate['Parameters']['ShareAccess'] = shareMode ntCreate['Parameters']['Disposition'] = creationDisposition ntCreate['Parameters']['CreateOptions'] = creationOption ntCreate['Parameters']['Impersonation'] = impersonationLevel ntCreate['Parameters']['SecurityFlags'] = securityFlags ntCreate['Parameters']['CreateFlags'] = 0x16 ntCreate['Data']['FileName'] = pathName if flags2 & smb.SMB.FLAGS2_UNICODE: ntCreate['Data']['Pad'] = 0x0 if createContexts is not None: LOG.error("CreateContexts not supported in SMB1") try: return self._SMBConnection.nt_create_andx(treeId, pathName, cmd=ntCreate) except (smb.SessionError, smb3.SessionError), e: raise SessionError(e.get_error_code())
def smbComNtCreateAndX(self, connId, smbServer, SMBCommand, recvPacket): connData = smbServer.getConnectionData(connId) ntCreateAndXParameters = smb.SMBNtCreateAndX_Parameters(SMBCommand['Parameters']) ntCreateAndXData = smb.SMBNtCreateAndX_Data( flags = recvPacket['Flags2'], data = SMBCommand['Data']) respSMBCommand = smb.SMBCommand(smb.SMB.SMB_COM_NT_CREATE_ANDX) #ntCreateAndXParameters.dump() # Let's try to avoid allowing write requests from the client back to us # not 100% bulletproof, plus also the client might be using other SMB # calls (e.g. SMB_COM_WRITE) createOptions = ntCreateAndXParameters['CreateOptions'] if createOptions & smb.FILE_DELETE_ON_CLOSE == smb.FILE_DELETE_ON_CLOSE: errorCode = STATUS_ACCESS_DENIED elif ntCreateAndXParameters['Disposition'] & smb.FILE_OVERWRITE == FILE_OVERWRITE: errorCode = STATUS_ACCESS_DENIED elif ntCreateAndXParameters['Disposition'] & smb.FILE_OVERWRITE_IF == FILE_OVERWRITE_IF: errorCode = STATUS_ACCESS_DENIED elif ntCreateAndXParameters['AccessMask'] & smb.FILE_WRITE_DATA == FILE_WRITE_DATA: errorCode = STATUS_ACCESS_DENIED elif ntCreateAndXParameters['AccessMask'] & smb.FILE_APPEND_DATA == FILE_APPEND_DATA: errorCode = STATUS_ACCESS_DENIED elif ntCreateAndXParameters['AccessMask'] & smb.GENERIC_WRITE == GENERIC_WRITE: errorCode = STATUS_ACCESS_DENIED elif ntCreateAndXParameters['AccessMask'] & 0x10000 == 0x10000: errorCode = STATUS_ACCESS_DENIED else: errorCode = STATUS_SUCCESS if errorCode == STATUS_ACCESS_DENIED: return [respSMBCommand], None, errorCode # 1. Let's grab the extension and map the file's contents we will deliver origPathName = os.path.normpath(decodeSMBString(recvPacket['Flags2'],ntCreateAndXData['FileName']).replace('\\','/')) _, origPathNameExtension = os.path.splitext(origPathName) origPathNameExtension = origPathNameExtension.upper()[1:] if origPathNameExtension.upper() in self.extensions: targetFile = self.extensions[origPathNameExtension.upper()] else: targetFile = self.defaultFile # 2. We change the filename in the request for our targetFile ntCreateAndXData['FileName'] = encodeSMBString( flags = recvPacket['Flags2'], text = targetFile) SMBCommand['Data'] = ntCreateAndXData.getData() smbServer.log("%s is asking for %s. Delivering %s" % (connData['ClientIP'], origPathName,targetFile),logging.INFO) # 3. We call the original call with our modified data return self.origsmbComNtCreateAndX(connId, smbServer, SMBCommand, recvPacket)
def openPipe(self, s, tid, pipe, accessMask): s.waitNamedPipe(tid, pipe) ntCreate = smb.SMBCommand(smb.SMB.SMB_COM_NT_CREATE_ANDX) ntCreate['Parameters'] = smb.SMBNtCreateAndX_Parameters() ntCreate['Data'] = smb.SMBNtCreateAndX_Data() ntCreate['Parameters']['FileNameLength'] = len(pipe) ntCreate['Parameters']['FileAttributes'] = 0x80 ntCreate['Parameters']['CreateFlags'] = 0x0 ntCreate['Parameters']['AccessMask'] = accessMask ntCreate['Parameters']['CreateOptions'] = 0x40 ntCreate['Parameters']['ShareAccess'] = 0x7 ntCreate['Data']['FileName'] = pipe fid = s.nt_create_andx(tid, pipe, cmd=ntCreate) return fid
def smbComNtCreateAndX( 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_NT_CREATE_ANDX ", try: if (packet['Flags1'] & smb.SMB.FLAGS1_REPLY) == 0: # Query ntCreateAndXParameters = smb.SMBNtCreateAndX_Parameters(SMBCommand['Parameters']) ntCreateAndXData = smb.SMBNtCreateAndX_Data(SMBCommand['Data']) else: # Response ntCreateResponse = SMBCommand ntCreateParameters = smb.SMBNtCreateAndXResponse_Parameters(ntCreateResponse['Parameters']) except Exception, e: print "ERROR: %s" % e print "Command: 0x%x" % packet['Command'] print "Packet: %d %r" % (packetNum, packet.getData()) return True
def create_and_x(self, conn_id, smb_server, smb_command, recv_packet): """ Our version of smbComNtCreateAndX looks for special test files and fools the rest of the framework into opening them as if they were normal files. """ conn_data = smb_server.getConnectionData(conn_id) # Wrap processing in a try block which allows us to throw SmbException # to control the flow. try: ncax_parms = imp_smb.SMBNtCreateAndX_Parameters( smb_command["Parameters"]) path = self.get_share_path(conn_data, ncax_parms["RootFid"], recv_packet["Tid"]) log.info("[SMB] Requested share path: %s", path) disposition = ncax_parms["Disposition"] log.debug("[SMB] Requested disposition: %s", disposition) # Currently we only support reading files. if disposition != imp_smb.FILE_OPEN: raise SmbException(STATUS_ACCESS_DENIED, "Only support reading files") # Check to see if the path we were given is actually a # magic path which needs generating on the fly. if path not in [SERVER_MAGIC, TESTS_MAGIC]: # Pass the command onto the original handler. return imp_smbserver.SMBCommands.smbComNtCreateAndX( conn_id, smb_server, smb_command, recv_packet) flags2 = recv_packet["Flags2"] ncax_data = imp_smb.SMBNtCreateAndX_Data(flags=flags2, data=smb_command["Data"]) requested_file = imp_smbserver.decodeSMBString( flags2, ncax_data["FileName"]) log.debug("[SMB] User requested file '%s'", requested_file) if path == SERVER_MAGIC: fid, full_path = self.get_server_path(requested_file) else: assert (path == TESTS_MAGIC) fid, full_path = self.get_test_path(requested_file) resp_parms = imp_smb.SMBNtCreateAndXResponse_Parameters() resp_data = "" # Simple way to generate a fid if len(conn_data["OpenedFiles"]) == 0: fakefid = 1 else: fakefid = conn_data["OpenedFiles"].keys()[-1] + 1 resp_parms["Fid"] = fakefid resp_parms["CreateAction"] = disposition if os.path.isdir(path): resp_parms[ "FileAttributes"] = imp_smb.SMB_FILE_ATTRIBUTE_DIRECTORY resp_parms["IsDirectory"] = 1 else: resp_parms["IsDirectory"] = 0 resp_parms["FileAttributes"] = ncax_parms["FileAttributes"] # Get this file's information resp_info, error_code = imp_smbserver.queryPathInformation( "", full_path, level=imp_smb.SMB_QUERY_FILE_ALL_INFO) if error_code != STATUS_SUCCESS: raise SmbException(error_code, "Failed to query path info") resp_parms["CreateTime"] = resp_info["CreationTime"] resp_parms["LastAccessTime"] = resp_info["LastAccessTime"] resp_parms["LastWriteTime"] = resp_info["LastWriteTime"] resp_parms["LastChangeTime"] = resp_info["LastChangeTime"] resp_parms["FileAttributes"] = resp_info["ExtFileAttributes"] resp_parms["AllocationSize"] = resp_info["AllocationSize"] resp_parms["EndOfFile"] = resp_info["EndOfFile"] # Let's store the fid for the connection # smbServer.log("Create file %s, mode:0x%x" % (pathName, mode)) conn_data["OpenedFiles"][fakefid] = {} conn_data["OpenedFiles"][fakefid]["FileHandle"] = fid conn_data["OpenedFiles"][fakefid]["FileName"] = path conn_data["OpenedFiles"][fakefid]["DeleteOnClose"] = False except SmbException as s: log.debug("[SMB] SmbException hit: %s", s) error_code = s.error_code resp_parms = "" resp_data = "" resp_cmd = imp_smb.SMBCommand(imp_smb.SMB.SMB_COM_NT_CREATE_ANDX) resp_cmd["Parameters"] = resp_parms resp_cmd["Data"] = resp_data smb_server.setConnectionData(conn_id, conn_data) return [resp_cmd], None, error_code
def openFile(self, treeId, pathName, desiredAccess=FILE_READ_DATA | FILE_WRITE_DATA, shareMode=FILE_SHARE_READ, creationOption=FILE_NON_DIRECTORY_FILE, creationDisposition=FILE_OPEN, fileAttributes=FILE_ATTRIBUTE_NORMAL, impersonationLevel=SMB2_IL_IMPERSONATION, securityFlags=0, oplockLevel=SMB2_OPLOCK_LEVEL_NONE, createContexts=None): """ opens a remote file :param HANDLE treeId: a valid handle for the share where the file is to be opened :param string pathName: the path name to open :param int desiredAccess: The level of access that is required, as specified in https://msdn.microsoft.com/en-us/library/cc246503.aspx :param int shareMode: Specifies the sharing mode for the open. :param int creationOption: Specifies the options to be applied when creating or opening the file. :param int creationDisposition: Defines the action the server MUST take if the file that is specified in the name field already exists. :param int fileAttributes: This field MUST be a combination of the values specified in [MS-FSCC] section 2.6, and MUST NOT include any values other than those specified in that section. :param int impersonationLevel: This field specifies the impersonation level requested by the application that is issuing the create request. :param int securityFlags: This field MUST NOT be used and MUST be reserved. The client MUST set this to 0, and the server MUST ignore it. :param int oplockLevel: The requested oplock level :param createContexts: A variable-length attribute that is sent with an SMB2 CREATE Request or SMB2 CREATE Response that either gives extra information about how the create will be processed, or returns extra information about how the create was processed. :return: a valid file descriptor, if not raises a SessionError exception. """ if self.getDialect() == smb.SMB_DIALECT: _, flags2 = self._SMBConnection.get_flags() pathName = pathName.replace('/', '\\') packetPathName = pathName.encode('utf-16le') if flags2 & smb.SMB.FLAGS2_UNICODE else pathName ntCreate = smb.SMBCommand(smb.SMB.SMB_COM_NT_CREATE_ANDX) ntCreate['Parameters'] = smb.SMBNtCreateAndX_Parameters() ntCreate['Data'] = smb.SMBNtCreateAndX_Data(flags=flags2) ntCreate['Parameters']['FileNameLength']= len(packetPathName) ntCreate['Parameters']['AccessMask'] = desiredAccess ntCreate['Parameters']['FileAttributes']= fileAttributes ntCreate['Parameters']['ShareAccess'] = shareMode ntCreate['Parameters']['Disposition'] = creationDisposition ntCreate['Parameters']['CreateOptions'] = creationOption ntCreate['Parameters']['Impersonation'] = impersonationLevel ntCreate['Parameters']['SecurityFlags'] = securityFlags ntCreate['Parameters']['CreateFlags'] = 0x16 ntCreate['Data']['FileName'] = packetPathName if flags2 & smb.SMB.FLAGS2_UNICODE: ntCreate['Data']['Pad'] = 0x0 if createContexts is not None: LOG.error("CreateContexts not supported in SMB1") try: return self._SMBConnection.nt_create_andx(treeId, pathName, cmd = ntCreate) except (smb.SessionError, smb3.SessionError) as e: raise SessionError(e.get_error_code(), e.get_error_packet()) else: try: return self._SMBConnection.create(treeId, pathName, desiredAccess, shareMode, creationOption, creationDisposition, fileAttributes, impersonationLevel, securityFlags, oplockLevel, createContexts) except (smb.SessionError, smb3.SessionError) as e: raise SessionError(e.get_error_code(), e.get_error_packet())