private void ExpectIoctlPayload(Smb2Client client, out uint status, out byte[] payload) { if (client == null) { throw new InvalidOperationException("The transport is not connected."); } Smb2IOCtlResponsePacket response = client.ExpectPacket <Smb2IOCtlResponsePacket>(ioctlRequestMessageIds.Dequeue()); payload = null; if (response.PayLoad.OutputCount > 0) { payload = response.Buffer.Skip((int)(response.PayLoad.OutputOffset - response.BufferOffset)).Take((int)response.PayLoad.OutputCount).ToArray(); } status = response.Header.Status; }
private Smb2Packet DecodeSingleResponsePacket( byte[] messageBytes, bool ignoreCompoundFlag, ulong realSessionId, uint realTreeId, out int consumedLength, out int expectedLength ) { Packet_Header smb2Header; bool isLeaseBreakPacket = false; int offset = 0; smb2Header = TypeMarshal.ToStruct<Packet_Header>(messageBytes, ref offset); if (smb2Header.Command == Smb2Command.OPLOCK_BREAK) { ushort structureSize = TypeMarshal.ToStruct<ushort>(messageBytes, ref offset); if (structureSize == (ushort)OplockLeaseBreakStructureSize.LeaseBreakNotification || structureSize == (ushort)OplockLeaseBreakStructureSize.LeaseBreakResponse || structureSize == 9) // Add this condition temporally to handle LeaseBreakResponse is error response (i.e. structureSize == 9), but this will still hide the condition when OplockBreakResponse is error response { isLeaseBreakPacket = true; } } Smb2SinglePacket packet = null; ushort structSize = BitConverter.ToUInt16(messageBytes, Smb2Consts.Smb2HeaderLen); switch (smb2Header.Command) { case Smb2Command.CANCEL: packet = new Smb2CancelResponsePacket(); break; case Smb2Command.CHANGE_NOTIFY: packet = new Smb2ChangeNotifyResponsePacket(); break; case Smb2Command.CLOSE: packet = new Smb2CloseResponsePacket(); break; case Smb2Command.CREATE: packet = new Smb2CreateResponsePacket(); break; case Smb2Command.ECHO: packet = new Smb2EchoResponsePacket(); break; case Smb2Command.FLUSH: packet = new Smb2FlushResponsePacket(); break; case Smb2Command.IOCTL: packet = new Smb2IOCtlResponsePacket(); break; case Smb2Command.LOCK: packet = new Smb2LockResponsePacket(); break; case Smb2Command.LOGOFF: packet = new Smb2LogOffResponsePacket(); break; case Smb2Command.NEGOTIATE: packet = new Smb2NegotiateResponsePacket(); break; case Smb2Command.OPLOCK_BREAK: if (smb2Header.MessageId == ulong.MaxValue) { if (!isLeaseBreakPacket) { packet = new Smb2OpLockBreakNotificationPacket(); } else { packet = new Smb2LeaseBreakNotificationPacket(); } } else { if (!isLeaseBreakPacket) { packet = new Smb2OpLockBreakResponsePacket(); } else { packet = new Smb2LeaseBreakResponsePacket(); } } break; case Smb2Command.QUERY_DIRECTORY: packet = new Smb2QueryDirectoryResponePacket(); break; case Smb2Command.QUERY_INFO: packet = new Smb2QueryInfoResponsePacket(); break; case Smb2Command.READ: packet = new Smb2ReadResponsePacket(); break; case Smb2Command.SESSION_SETUP: packet = new Smb2SessionSetupResponsePacket(); break; case Smb2Command.SET_INFO: packet = new Smb2SetInfoResponsePacket(); break; case Smb2Command.TREE_CONNECT: packet = new Smb2TreeConnectResponsePacket(); break; case Smb2Command.TREE_DISCONNECT: packet = new Smb2TreeDisconnectResponsePacket(); break; case Smb2Command.WRITE: packet = new Smb2WriteResponsePacket(); break; default: throw new InvalidOperationException("Received an unknown packet! the type of the packet is " + smb2Header.Command.ToString()); } if (IsErrorPacket(smb2Header)) { var error = new Smb2ErrorResponsePacket(); error.FromBytes(messageBytes, out consumedLength, out expectedLength); packet.Header = error.Header; packet.Error = error; } else { packet.FromBytes(messageBytes, out consumedLength, out expectedLength); } //if ignoreCompoundFlag is false, means the process of decoding this packet //is not part of the process of decoding a compound packet. We will update //context here. if (!ignoreCompoundFlag) { // TODO } return packet; }
public Smb2IOCtlResponsePacket CreateIOCtlResponse( Smb2Endpoint endpoint, ulong messageId, byte[] input, byte[] output ) { Smb2IOCtlResponsePacket packet = new Smb2IOCtlResponsePacket(); Smb2IOCtlRequestPacket requestPacket = context.FindRequestPacket(endpoint.EndpointId, messageId) as Smb2IOCtlRequestPacket; SetHeader(packet, endpoint, messageId); packet.PayLoad.CtlCode = (uint)requestPacket.PayLoad.CtlCode; packet.PayLoad.FileId = requestPacket.PayLoad.FileId; packet.PayLoad.Flags = IOCTL_Response_Flags_Values.V1; int bufferLen = 0; if (input != null) { packet.PayLoad.InputCount = (uint)input.Length; packet.PayLoad.InputOffset = Smb2Consts.InputOffsetInIOCtlResponse; bufferLen += Smb2Utility.AlignBy8Bytes(input.Length); } if (output != null) { packet.PayLoad.OutputCount = (uint)output.Length; packet.PayLoad.OutputOffset = (uint)(Smb2Consts.InputOffsetInIOCtlResponse + bufferLen); bufferLen += output.Length; } byte[] buffer = new byte[bufferLen]; if (input != null) { Array.Copy(input, buffer, input.Length); } if (output != null) { Array.Copy(output, 0, buffer, packet.PayLoad.OutputOffset - Smb2Consts.InputOffsetInIOCtlResponse, output.Length); } packet.PayLoad.Reserved = IOCTL_Response_Reserved_Values.V1; packet.PayLoad.Reserved2 = IOCTL_Response_Reserved2_Values.V1; packet.PayLoad.StructureSize = IOCTL_Response_StructureSize_Values.V1; packet.PayLoad.Buffer = buffer; packet.Sign(); return packet; }