SMB2Header.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /* Copyright (C) 2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using Utilities;
  9. namespace SMBLibrary.SMB2
  10. {
  11. public class SMB2Header
  12. {
  13. public const int Length = 64;
  14. public const int SignatureOffset = 48;
  15. public static readonly byte[] ProtocolSignature = new byte[] { 0xFE, 0x53, 0x4D, 0x42 };
  16. private byte[] ProtocolId; // 4 bytes, 0xFE followed by "SMB"
  17. private ushort StructureSize;
  18. public ushort CreditCharge;
  19. public NTStatus Status;
  20. public SMB2CommandName Command;
  21. public ushort Credits; // CreditRequest or CreditResponse (The number of credits granted to the client)
  22. public SMB2PacketHeaderFlags Flags;
  23. public uint NextCommand; // offset in bytes
  24. public ulong MessageID;
  25. public uint Reserved; // Sync
  26. public uint TreeID; // Sync
  27. public ulong AsyncID; // Async
  28. public ulong SessionID;
  29. public byte[] Signature; // 16 bytes (present if SMB2_FLAGS_SIGNED is set)
  30. public SMB2Header(SMB2CommandName commandName)
  31. {
  32. ProtocolId = ProtocolSignature;
  33. StructureSize = Length;
  34. Command = commandName;
  35. Signature = new byte[16];
  36. }
  37. public SMB2Header(byte[] buffer, int offset)
  38. {
  39. ProtocolId = ByteReader.ReadBytes(buffer, offset + 0, 4);
  40. StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + 4);
  41. CreditCharge = LittleEndianConverter.ToUInt16(buffer, offset + 6);
  42. Status = (NTStatus)LittleEndianConverter.ToUInt32(buffer, offset + 8);
  43. Command = (SMB2CommandName)LittleEndianConverter.ToUInt16(buffer, offset + 12);
  44. Credits = LittleEndianConverter.ToUInt16(buffer, offset + 14);
  45. Flags = (SMB2PacketHeaderFlags)LittleEndianConverter.ToUInt32(buffer, offset + 16);
  46. NextCommand = LittleEndianConverter.ToUInt32(buffer, offset + 20);
  47. MessageID = LittleEndianConverter.ToUInt64(buffer, offset + 24);
  48. if ((Flags & SMB2PacketHeaderFlags.AsyncCommand) > 0)
  49. {
  50. AsyncID = LittleEndianConverter.ToUInt64(buffer, offset + 32);
  51. }
  52. else
  53. {
  54. Reserved = LittleEndianConverter.ToUInt32(buffer, offset + 32);
  55. TreeID = LittleEndianConverter.ToUInt32(buffer, offset + 36);
  56. }
  57. SessionID = LittleEndianConverter.ToUInt64(buffer, offset + 40);
  58. if ((Flags & SMB2PacketHeaderFlags.Signed) > 0)
  59. {
  60. Signature = ByteReader.ReadBytes(buffer, offset + 48, 16);
  61. }
  62. }
  63. public void WriteBytes(byte[] buffer, int offset)
  64. {
  65. ByteWriter.WriteBytes(buffer, offset + 0, ProtocolId);
  66. LittleEndianWriter.WriteUInt16(buffer, offset + 4, StructureSize);
  67. LittleEndianWriter.WriteUInt16(buffer, offset + 6, CreditCharge);
  68. LittleEndianWriter.WriteUInt32(buffer, offset + 8, (uint)Status);
  69. LittleEndianWriter.WriteUInt16(buffer, offset + 12, (ushort)Command);
  70. LittleEndianWriter.WriteUInt16(buffer, offset + 14, Credits);
  71. LittleEndianWriter.WriteUInt32(buffer, offset + 16, (uint)Flags);
  72. LittleEndianWriter.WriteUInt32(buffer, offset + 20, NextCommand);
  73. LittleEndianWriter.WriteUInt64(buffer, offset + 24, MessageID);
  74. if ((Flags & SMB2PacketHeaderFlags.AsyncCommand) > 0)
  75. {
  76. LittleEndianWriter.WriteUInt64(buffer, offset + 32, AsyncID);
  77. }
  78. else
  79. {
  80. LittleEndianWriter.WriteUInt32(buffer, offset + 32, Reserved);
  81. LittleEndianWriter.WriteUInt32(buffer, offset + 36, TreeID);
  82. }
  83. LittleEndianWriter.WriteUInt64(buffer, offset + 40, SessionID);
  84. if ((Flags & SMB2PacketHeaderFlags.Signed) > 0)
  85. {
  86. ByteWriter.WriteBytes(buffer, offset + 48, Signature);
  87. }
  88. }
  89. public bool IsResponse
  90. {
  91. get
  92. {
  93. return (Flags & SMB2PacketHeaderFlags.ServerToRedir) > 0;
  94. }
  95. set
  96. {
  97. if (value)
  98. {
  99. Flags |= SMB2PacketHeaderFlags.ServerToRedir;
  100. }
  101. else
  102. {
  103. Flags &= ~SMB2PacketHeaderFlags.ServerToRedir;
  104. }
  105. }
  106. }
  107. public bool IsAsync
  108. {
  109. get
  110. {
  111. return (Flags & SMB2PacketHeaderFlags.AsyncCommand) > 0;
  112. }
  113. set
  114. {
  115. if (value)
  116. {
  117. Flags |= SMB2PacketHeaderFlags.AsyncCommand;
  118. }
  119. else
  120. {
  121. Flags &= ~SMB2PacketHeaderFlags.AsyncCommand;
  122. }
  123. }
  124. }
  125. public bool IsRelatedOperations
  126. {
  127. get
  128. {
  129. return (Flags & SMB2PacketHeaderFlags.RelatedOperations) > 0;
  130. }
  131. set
  132. {
  133. if (value)
  134. {
  135. Flags |= SMB2PacketHeaderFlags.RelatedOperations;
  136. }
  137. else
  138. {
  139. Flags &= ~SMB2PacketHeaderFlags.RelatedOperations;
  140. }
  141. }
  142. }
  143. public bool IsSigned
  144. {
  145. get
  146. {
  147. return (Flags & SMB2PacketHeaderFlags.Signed) > 0;
  148. }
  149. set
  150. {
  151. if (value)
  152. {
  153. Flags |= SMB2PacketHeaderFlags.Signed;
  154. }
  155. else
  156. {
  157. Flags &= ~SMB2PacketHeaderFlags.Signed;
  158. }
  159. }
  160. }
  161. public static bool IsValidSMB2Header(byte[] buffer)
  162. {
  163. if (buffer.Length >= 4)
  164. {
  165. byte[] protocol = ByteReader.ReadBytes(buffer, 0, 4);
  166. return ByteUtils.AreByteArraysEqual(protocol, ProtocolSignature);
  167. }
  168. return false;
  169. }
  170. }
  171. }