Пример #1
0
        internal static TransactionTransactNamedPipeResponse GetSubcommandResponse(SMBHeader header, TransactionTransactNamedPipeRequest subcommand, NamedPipeShare share, StateObject state)
        {
            string openedFilePath = state.GetOpenedFilePath(subcommand.FID);

            if (openedFilePath == null)
            {
                header.Status = NTStatus.STATUS_INVALID_HANDLE;
                return(null);
            }

            TransactionTransactNamedPipeResponse response = new TransactionTransactNamedPipeResponse();
            RemoteService service = share.GetService(openedFilePath);

            if (service != null)
            {
                RPCPDU rpcRequest = RPCPDU.GetPDU(subcommand.WriteData);
                RPCPDU rpcReply   = RemoteServiceHelper.GetRPCReply(rpcRequest, service);
                response.ReadData = rpcReply.GetBytes();
                return(response);
            }

            // This code should not execute unless the request sequence is invalid
            header.Status = NTStatus.STATUS_INVALID_SMB;
            return(null);
        }
Пример #2
0
        public override void Write(byte[] buffer, int offset, int count)
        {
            // [MC-CIFS] In message mode, the system treats the bytes read or written in each I/O operation to the pipe as a message unit.
            RPCPDU rpcRequest = RPCPDU.GetPDU(buffer, offset);

            ProcessRPCRequest(rpcRequest);
        }
Пример #3
0
        public static List <string> ListShares(INtFileStore namedPipeShare, ShareType?shareType)
        {
            NamedPipeHelper.BindPipe(namedPipeShare, ServerService.ServicePipeName, ServerService.ServiceInterfaceGuid, ServerService.ServiceVersion, out NtHandle? pipeHandle, out int maxTransmitFragmentSize).IsSuccessElseThrow();

            NetrShareEnumRequest shareEnumRequest = new NetrShareEnumRequest
            {
                InfoStruct = new ShareEnum
                {
                    Level = 1,
                    Info  = new ShareInfo1Container()
                },
                PreferedMaximumLength = uint.MaxValue,
                ServerName            = "*"
            };

            byte[]     data       = shareEnumRequest.GetBytes();
            RequestPDU requestPdu = new RequestPDU
            {
                Flags = PacketFlags.FirstFragment | PacketFlags.LastFragment,
                DataRepresentation =
                {
                    CharacterFormat             = CharacterFormat.ASCII,
                    ByteOrder                   = ByteOrder.LittleEndian,
                    FloatingPointRepresentation = FloatingPointRepresentation.IEEE
                },
                OpNum          = (ushort)ServerServiceOpName.NetrShareEnum,
                Data           = data,
                AllocationHint = (uint)data.Length
            };

            byte[] input = requestPdu.GetBytes();
            namedPipeShare.DeviceIOControl(pipeHandle, (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE, input, out byte[]? output, maxTransmitFragmentSize);

            if (!(RPCPDU.GetPDU(output, 0) is ResponsePDU responsePdu))
            {
                throw new NtStatusException(NTStatus.STATUS_NOT_SUPPORTED);
            }

            byte[] responseData = responsePdu.Data;
            while ((responsePdu.Flags & PacketFlags.LastFragment) == 0)
            {
                namedPipeShare.ReadFile(out output, pipeHandle, 0, maxTransmitFragmentSize);

                if (!(RPCPDU.GetPDU(output, 0) is ResponsePDU responsePdu2))
                {
                    throw new NtStatusException(NTStatus.STATUS_NOT_SUPPORTED);
                }
                responseData = ByteUtils.Concatenate(responseData, responsePdu2.Data);
            }
            namedPipeShare.CloseFile(pipeHandle);
            NetrShareEnumResponse shareEnumResponse = new NetrShareEnumResponse(responseData);

            if (shareEnumResponse.InfoStruct.Info is ShareInfo1Container shareInfo1 && shareInfo1.Entries != null)
            {
                return((from entry in shareInfo1.Entries where !shareType.HasValue || shareType.Value == entry.ShareType.ShareType select entry.NetName.Value).ToList());
            }

            throw new NtStatusException(shareEnumResponse.Result == Win32Error.ERROR_ACCESS_DENIED ? NTStatus.STATUS_ACCESS_DENIED : NTStatus.STATUS_NOT_SUPPORTED);
        }
Пример #4
0
        public override void Write(byte[] buffer, int offset, int count)
        {
            int lengthOfPDUs = 0;

            do
            {
                RPCPDU rpcRequest = RPCPDU.GetPDU(buffer, offset);
                lengthOfPDUs += rpcRequest.FragmentLength;
                RPCPDU rpcReply  = RemoteServiceHelper.GetRPCReply(rpcRequest, m_service);
                byte[] replyData = rpcReply.GetBytes();
                Append(replyData);
            }while (lengthOfPDUs < count);
        }
Пример #5
0
        public static NTStatus ExecuteCall <I, O>(INTFileStore namedPipeShare, object pipeHandle, ushort OpNum, I inputArgs, out O outputData) where I : IRPCRequest
        {
            byte[]   output;
            NTStatus status;

            outputData = default(O);

            RequestPDU requestPDU = new RequestPDU();

            requestPDU.Flags = PacketFlags.FirstFragment | PacketFlags.LastFragment;
            requestPDU.DataRepresentation.CharacterFormat             = CharacterFormat.ASCII;
            requestPDU.DataRepresentation.ByteOrder                   = ByteOrder.LittleEndian;
            requestPDU.DataRepresentation.FloatingPointRepresentation = FloatingPointRepresentation.IEEE;
            requestPDU.OpNum          = OpNum;
            requestPDU.Data           = inputArgs.GetBytes();
            requestPDU.AllocationHint = (uint)requestPDU.Data.Length;
            byte[] input           = requestPDU.GetBytes();
            int    maxOutputLength = MaxTransmitFragmentSize;

            status = namedPipeShare.DeviceIOControl(pipeHandle, (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE, input, out output, maxOutputLength);
            if (status != NTStatus.STATUS_SUCCESS)
            {
                return(status);
            }
            ResponsePDU responsePDU = RPCPDU.GetPDU(output, 0) as ResponsePDU;

            if (responsePDU == null)
            {
                status = NTStatus.STATUS_NOT_SUPPORTED;
                return(status);
            }

            byte[] responseData = responsePDU.Data;
            while ((responsePDU.Flags & PacketFlags.LastFragment) == 0)
            {
                status = namedPipeShare.ReadFile(out output, pipeHandle, 0, maxOutputLength);
                if (status != NTStatus.STATUS_SUCCESS)
                {
                    return(status);
                }
                responsePDU = RPCPDU.GetPDU(output, 0) as ResponsePDU;
                if (responsePDU == null)
                {
                    status = NTStatus.STATUS_NOT_SUPPORTED;
                    return(status);
                }
                responseData = ByteUtils.Concatenate(responseData, responsePDU.Data);
            }
            outputData = (O)Activator.CreateInstance(typeof(O), new object[] { responseData });
            return(NTStatus.STATUS_SUCCESS);
        }
Пример #6
0
        public static NTStatus BindPipe(INTFileStore namedPipeShare, string pipeName, Guid interfaceGuid, uint interfaceVersion, out object pipeHandle, out int maxTransmitFragmentSize)
        {
            maxTransmitFragmentSize = 0;
            FileStatus fileStatus;
            NTStatus   status = namedPipeShare.CreateFile(out pipeHandle, out fileStatus, pipeName, (AccessMask)(FileAccessMask.FILE_READ_DATA | FileAccessMask.FILE_WRITE_DATA), 0, ShareAccess.Read | ShareAccess.Write, CreateDisposition.FILE_OPEN, 0, null);

            if (status != NTStatus.STATUS_SUCCESS)
            {
                return(status);
            }
            BindPDU bindPDU = new BindPDU();

            bindPDU.Flags = PacketFlags.FirstFragment | PacketFlags.LastFragment;
            bindPDU.DataRepresentation.CharacterFormat             = CharacterFormat.ASCII;
            bindPDU.DataRepresentation.ByteOrder                   = ByteOrder.LittleEndian;
            bindPDU.DataRepresentation.FloatingPointRepresentation = FloatingPointRepresentation.IEEE;
            bindPDU.MaxTransmitFragmentSize = 5680;
            bindPDU.MaxReceiveFragmentSize  = 5680;

            ContextElement serviceContext = new ContextElement();

            serviceContext.AbstractSyntax = new SyntaxID(interfaceGuid, interfaceVersion);
            serviceContext.TransferSyntaxList.Add(new SyntaxID(RemoteServiceHelper.NDRTransferSyntaxIdentifier, RemoteServiceHelper.NDRTransferSyntaxVersion));

            bindPDU.ContextList.Add(serviceContext);

            byte[] input = bindPDU.GetBytes();
            byte[] output;
            status = namedPipeShare.DeviceIOControl(pipeHandle, (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE, input, out output, 4096);
            if (status != NTStatus.STATUS_SUCCESS)
            {
                return(status);
            }
            BindAckPDU bindAckPDU = RPCPDU.GetPDU(output, 0) as BindAckPDU;

            if (bindAckPDU == null)
            {
                return(NTStatus.STATUS_NOT_SUPPORTED);
            }

            maxTransmitFragmentSize = bindAckPDU.MaxTransmitFragmentSize;
            return(NTStatus.STATUS_SUCCESS);
        }
Пример #7
0
        public static NTStatus BindPipe(INtFileStore namedPipeShare, string pipeName, Guid interfaceGuid, uint interfaceVersion, out NtHandle?pipeHandle, out int maxTransmitFragmentSize)
        {
            maxTransmitFragmentSize = 0;
            namedPipeShare.CreateFile(out pipeHandle, out _, pipeName, (AccessMask)(FileAccessMask.FILE_READ_DATA | FileAccessMask.FILE_WRITE_DATA), 0, ShareAccess.Read | ShareAccess.Write, CreateDisposition.FILE_OPEN, 0, null);

            BindPDU bindPdu = new BindPDU
            {
                Flags = PacketFlags.FirstFragment | PacketFlags.LastFragment,
                DataRepresentation =
                {
                    CharacterFormat             = CharacterFormat.ASCII,
                    ByteOrder                   = ByteOrder.LittleEndian,
                    FloatingPointRepresentation = FloatingPointRepresentation.IEEE
                },
                MaxTransmitFragmentSize = 5680,
                MaxReceiveFragmentSize  = 5680
            };

            ContextElement serviceContext = new ContextElement
            {
                AbstractSyntax = new SyntaxID(interfaceGuid, interfaceVersion)
            };

            serviceContext.TransferSyntaxList.Add(new SyntaxID(RemoteServiceHelper.NDRTransferSyntaxIdentifier, RemoteServiceHelper.NDRTransferSyntaxVersion));

            bindPdu.ContextList.Add(serviceContext);

            byte[] input = bindPdu.GetBytes();
            namedPipeShare.DeviceIOControl(pipeHandle, (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE, input, out byte[]? output, 4096);

            if (!(RPCPDU.GetPDU(output, 0) is BindAckPDU bindAckPDU))
            {
                return(NTStatus.STATUS_NOT_SUPPORTED);
            }

            maxTransmitFragmentSize = bindAckPDU.MaxTransmitFragmentSize;
            return(NTStatus.STATUS_SUCCESS);
        }
Пример #8
0
        public static uint PerformWrite(SMBHeader header, object share, ushort FID, ulong offset, byte[] data, StateObject state)
        {
            OpenedFileObject openedFile = state.GetOpenedFileObject(FID);

            if (openedFile == null)
            {
                header.Status = NTStatus.STATUS_INVALID_HANDLE;
                return(0);
            }
            string openedFilePath = openedFile.Path;

            if (share is NamedPipeShare)
            {
                RemoteService service = ((NamedPipeShare)share).GetService(openedFilePath);
                if (service != null)
                {
                    RPCPDU rpcRequest = RPCPDU.GetPDU(data);
                    RPCPDU rpcReply   = RemoteServiceHelper.GetRPCReply(rpcRequest, service);
                    byte[] replyData  = rpcReply.GetBytes();
                    state.StoreNamedPipeReply(FID, replyData);
                    return((uint)data.Length);
                }

                // This code should not execute unless the SMB request (sequence) is invalid
                header.Status = NTStatus.STATUS_INVALID_SMB;
                return(0);
            }
            else // FileSystemShare
            {
                FileSystemShare fileSystemShare = (FileSystemShare)share;
                IFileSystem     fileSystem      = fileSystemShare.FileSystem;

                if (openedFile.IsSequentialAccess && openedFile.Cache.Length > 0)
                {
                    openedFile.Cache = new byte[0]; // Empty cache
                }

                try
                {
                    Stream stream = fileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                    stream.Seek((long)offset, SeekOrigin.Begin);
                    stream.Write(data, 0, data.Length);
                    stream.Close();
                    return((uint)data.Length);
                }
                catch (IOException ex)
                {
                    ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
                    if (errorCode == (ushort)Win32Error.ERROR_DISK_FULL)
                    {
                        header.Status = NTStatus.STATUS_DISK_FULL;
                        return(0);
                    }
                    else if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
                    {
                        // Returning STATUS_SHARING_VIOLATION is undocumented but apparently valid
                        header.Status = NTStatus.STATUS_SHARING_VIOLATION;
                        return(0);
                    }
                    else
                    {
                        header.Status = NTStatus.STATUS_DATA_ERROR;
                        return(0);
                    }
                }
                catch (ArgumentOutOfRangeException)
                {
                    header.Status = NTStatus.STATUS_DATA_ERROR;
                    return(0);
                }
                catch (UnauthorizedAccessException)
                {
                    // The user may have tried to write to a readonly file
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(0);
                }
            }
        }
Пример #9
0
        public static List <string> ListShares(INTFileStore namedPipeShare, ShareType?shareType, out NTStatus status)
        {
            object pipeHandle;
            int    maxTransmitFragmentSize;

            status = NamedPipeHelper.BindPipe(namedPipeShare, ServerService.ServicePipeName, ServerService.ServiceInterfaceGuid, ServerService.ServiceVersion, out pipeHandle, out maxTransmitFragmentSize);
            if (status != NTStatus.STATUS_SUCCESS)
            {
                return(null);
            }

            NetrShareEnumRequest shareEnumRequest = new NetrShareEnumRequest();

            shareEnumRequest.InfoStruct            = new ShareEnum();
            shareEnumRequest.InfoStruct.Level      = 1;
            shareEnumRequest.InfoStruct.Info       = new ShareInfo1Container();
            shareEnumRequest.PreferedMaximumLength = UInt32.MaxValue;
            shareEnumRequest.ServerName            = "*";
            RequestPDU requestPDU = new RequestPDU();

            requestPDU.Flags = PacketFlags.FirstFragment | PacketFlags.LastFragment;
            requestPDU.DataRepresentation.CharacterFormat             = CharacterFormat.ASCII;
            requestPDU.DataRepresentation.ByteOrder                   = ByteOrder.LittleEndian;
            requestPDU.DataRepresentation.FloatingPointRepresentation = FloatingPointRepresentation.IEEE;
            requestPDU.OpNum          = (ushort)ServerServiceOpName.NetrShareEnum;
            requestPDU.Data           = shareEnumRequest.GetBytes();
            requestPDU.AllocationHint = (uint)requestPDU.Data.Length;
            byte[] input = requestPDU.GetBytes();
            byte[] output;
            int    maxOutputLength = maxTransmitFragmentSize;

            status = namedPipeShare.DeviceIOControl(pipeHandle, (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE, input, out output, maxOutputLength);
            if (status != NTStatus.STATUS_SUCCESS)
            {
                return(null);
            }
            ResponsePDU responsePDU = RPCPDU.GetPDU(output, 0) as ResponsePDU;

            if (responsePDU == null)
            {
                status = NTStatus.STATUS_NOT_SUPPORTED;
                return(null);
            }

            byte[] responseData = responsePDU.Data;
            while ((responsePDU.Flags & PacketFlags.LastFragment) == 0)
            {
                status = namedPipeShare.ReadFile(out output, pipeHandle, 0, maxOutputLength);
                if (status != NTStatus.STATUS_SUCCESS)
                {
                    return(null);
                }
                responsePDU = RPCPDU.GetPDU(output, 0) as ResponsePDU;
                if (responsePDU == null)
                {
                    status = NTStatus.STATUS_NOT_SUPPORTED;
                    return(null);
                }
                responseData = ByteUtils.Concatenate(responseData, responsePDU.Data);
            }
            namedPipeShare.CloseFile(pipeHandle);
            NetrShareEnumResponse shareEnumResponse = new NetrShareEnumResponse(responseData);
            ShareInfo1Container   shareInfo1        = shareEnumResponse.InfoStruct.Info as ShareInfo1Container;

            if (shareInfo1 == null || shareInfo1.Entries == null)
            {
                if (shareEnumResponse.Result == Win32Error.ERROR_ACCESS_DENIED)
                {
                    status = NTStatus.STATUS_ACCESS_DENIED;
                }
                else
                {
                    status = NTStatus.STATUS_NOT_SUPPORTED;
                }
                return(null);
            }

            List <string> result = new List <string>();

            foreach (ShareInfo1Entry entry in shareInfo1.Entries)
            {
                if (!shareType.HasValue || shareType.Value == entry.ShareType.ShareType)
                {
                    result.Add(entry.NetName.Value);
                }
            }
            return(result);
        }
Пример #10
0
        public static List <string> ListShares(INTFileStore namedPipeShare, ShareType?shareType, out NTStatus status)
        {
            object     pipeHandle;
            FileStatus fileStatus;

            status = namedPipeShare.CreateFile(out pipeHandle, out fileStatus, ServerService.ServicePipeName, (AccessMask)(FileAccessMask.FILE_READ_DATA | FileAccessMask.FILE_WRITE_DATA), 0, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, 0, null);
            if (status != NTStatus.STATUS_SUCCESS)
            {
                return(null);
            }
            BindPDU bindPDU = new BindPDU();

            bindPDU.Flags = PacketFlags.FirstFragment | PacketFlags.LastFragment;
            bindPDU.DataRepresentation.CharacterFormat             = CharacterFormat.ASCII;
            bindPDU.DataRepresentation.ByteOrder                   = ByteOrder.LittleEndian;
            bindPDU.DataRepresentation.FloatingPointRepresentation = FloatingPointRepresentation.IEEE;
            bindPDU.MaxTransmitFragmentSize = 5680;
            bindPDU.MaxReceiveFragmentSize  = 5680;

            ContextElement serverServiceContext = new ContextElement();

            serverServiceContext.AbstractSyntax = new SyntaxID(ServerService.ServiceInterfaceGuid, ServerService.ServiceVersion);
            serverServiceContext.TransferSyntaxList.Add(new SyntaxID(RemoteServiceHelper.NDRTransferSyntaxIdentifier, RemoteServiceHelper.NDRTransferSyntaxVersion));

            bindPDU.ContextList.Add(serverServiceContext);

            byte[] input = bindPDU.GetBytes();
            byte[] output;
            status = namedPipeShare.DeviceIOControl(pipeHandle, (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE, input, out output, 4096);
            if (status != NTStatus.STATUS_SUCCESS)
            {
                return(null);
            }
            BindAckPDU bindAckPDU = RPCPDU.GetPDU(output, 0) as BindAckPDU;

            if (bindAckPDU == null)
            {
                status = NTStatus.STATUS_NOT_SUPPORTED;
                return(null);
            }

            NetrShareEnumRequest shareEnumRequest = new NetrShareEnumRequest();

            shareEnumRequest.InfoStruct            = new ShareEnum();
            shareEnumRequest.InfoStruct.Level      = 1;
            shareEnumRequest.InfoStruct.Info       = new ShareInfo1Container();
            shareEnumRequest.PreferedMaximumLength = UInt32.MaxValue;
            shareEnumRequest.ServerName            = "*";
            RequestPDU requestPDU = new RequestPDU();

            requestPDU.Flags = PacketFlags.FirstFragment | PacketFlags.LastFragment;
            requestPDU.DataRepresentation.CharacterFormat             = CharacterFormat.ASCII;
            requestPDU.DataRepresentation.ByteOrder                   = ByteOrder.LittleEndian;
            requestPDU.DataRepresentation.FloatingPointRepresentation = FloatingPointRepresentation.IEEE;
            requestPDU.OpNum          = (ushort)ServerServiceOpName.NetrShareEnum;
            requestPDU.Data           = shareEnumRequest.GetBytes();
            requestPDU.AllocationHint = (uint)requestPDU.Data.Length;
            input = requestPDU.GetBytes();
            int maxOutputLength = bindAckPDU.MaxTransmitFragmentSize;

            status = namedPipeShare.DeviceIOControl(pipeHandle, (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE, input, out output, maxOutputLength);
            if (status != NTStatus.STATUS_SUCCESS)
            {
                return(null);
            }
            ResponsePDU responsePDU = RPCPDU.GetPDU(output, 0) as ResponsePDU;

            if (responsePDU == null)
            {
                status = NTStatus.STATUS_NOT_SUPPORTED;
                return(null);
            }

            byte[] responseData = responsePDU.Data;
            while ((responsePDU.Flags & PacketFlags.LastFragment) == 0)
            {
                status = namedPipeShare.ReadFile(out output, pipeHandle, 0, maxOutputLength);
                if (status != NTStatus.STATUS_SUCCESS)
                {
                    return(null);
                }
                responsePDU = RPCPDU.GetPDU(output, 0) as ResponsePDU;
                if (responsePDU == null)
                {
                    status = NTStatus.STATUS_NOT_SUPPORTED;
                    return(null);
                }
                responseData = ByteUtils.Concatenate(responseData, responsePDU.Data);
            }
            NetrShareEnumResponse shareEnumResponse = new NetrShareEnumResponse(responseData);
            ShareInfo1Container   shareInfo1        = shareEnumResponse.InfoStruct.Info as ShareInfo1Container;

            if (shareInfo1 == null || shareInfo1.Entries == null)
            {
                if (shareEnumResponse.Result == Win32Error.ERROR_ACCESS_DENIED)
                {
                    status = NTStatus.STATUS_ACCESS_DENIED;
                }
                else
                {
                    status = NTStatus.STATUS_NOT_SUPPORTED;
                }
                return(null);
            }

            List <string> result = new List <string>();

            foreach (ShareInfo1Entry entry in shareInfo1.Entries)
            {
                if (!shareType.HasValue || shareType.Value == entry.ShareType.ShareType)
                {
                    result.Add(entry.NetName.Value);
                }
            }
            return(result);
        }