SMB2Header.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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 static readonly byte[] ProtocolSignature = new byte[] { 0xFE, 0x53, 0x4D, 0x42 };
  15. public byte[] ProtocolId; // 4 bytes, 0xFE followed by "SMB"
  16. public ushort StructureSize;
  17. public ushort CreditCharge;
  18. public NTStatus Status;
  19. public SMB2CommandName Command;
  20. public ushort Credits; // CreditRequest or CreditResponse (The number of credits granted to the client)
  21. public SMB2PacketHeaderFlags Flags;
  22. public uint NextCommand; // offset in bytes
  23. public ulong MessageID;
  24. public uint Reserved; // Sync
  25. public uint TreeID; // Sync
  26. public ulong AsyncID; // Async
  27. public ulong SessionID;
  28. public byte[] Signature; // 16 bytes (present if SMB2_FLAGS_SIGNED is set)
  29. public SMB2Header(SMB2CommandName commandName)
  30. {
  31. ProtocolId = ProtocolSignature;
  32. StructureSize = Length;
  33. Command = commandName;
  34. }
  35. public SMB2Header(byte[] buffer, int offset)
  36. {
  37. ProtocolId = ByteReader.ReadBytes(buffer, offset + 0, 4);
  38. StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + 4);
  39. CreditCharge = LittleEndianConverter.ToUInt16(buffer, offset + 6);
  40. Status = (NTStatus)LittleEndianConverter.ToUInt32(buffer, offset + 8);
  41. Command = (SMB2CommandName)LittleEndianConverter.ToUInt16(buffer, offset + 12);
  42. Credits = LittleEndianConverter.ToUInt16(buffer, offset + 14);
  43. Flags = (SMB2PacketHeaderFlags)LittleEndianConverter.ToUInt32(buffer, offset + 16);
  44. NextCommand = LittleEndianConverter.ToUInt32(buffer, offset + 20);
  45. MessageID = LittleEndianConverter.ToUInt64(buffer, offset + 24);
  46. if ((Flags & SMB2PacketHeaderFlags.AsyncCommand) > 0)
  47. {
  48. AsyncID = LittleEndianConverter.ToUInt64(buffer, offset + 32);
  49. }
  50. else
  51. {
  52. Reserved = LittleEndianConverter.ToUInt32(buffer, offset + 32);
  53. TreeID = LittleEndianConverter.ToUInt32(buffer, offset + 36);
  54. }
  55. SessionID = LittleEndianConverter.ToUInt64(buffer, offset + 40);
  56. if ((Flags & SMB2PacketHeaderFlags.Signed) > 0)
  57. {
  58. Signature = ByteReader.ReadBytes(buffer, offset + 48, 16);
  59. }
  60. }
  61. public void WriteBytes(byte[] buffer, int offset)
  62. {
  63. ByteWriter.WriteBytes(buffer, offset + 0, ProtocolId);
  64. LittleEndianWriter.WriteUInt16(buffer, offset + 4, StructureSize);
  65. LittleEndianWriter.WriteUInt16(buffer, offset + 6, CreditCharge);
  66. LittleEndianWriter.WriteUInt32(buffer, offset + 8, (uint)Status);
  67. LittleEndianWriter.WriteUInt16(buffer, offset + 12, (ushort)Command);
  68. LittleEndianWriter.WriteUInt16(buffer, offset + 14, Credits);
  69. LittleEndianWriter.WriteUInt32(buffer, offset + 16, (uint)Flags);
  70. LittleEndianWriter.WriteUInt32(buffer, offset + 20, NextCommand);
  71. LittleEndianWriter.WriteUInt64(buffer, offset + 24, MessageID);
  72. if ((Flags & SMB2PacketHeaderFlags.AsyncCommand) > 0)
  73. {
  74. LittleEndianWriter.WriteUInt64(buffer, offset + 32, AsyncID);
  75. }
  76. else
  77. {
  78. LittleEndianWriter.WriteUInt32(buffer, offset + 32, Reserved);
  79. LittleEndianWriter.WriteUInt32(buffer, offset + 36, TreeID);
  80. }
  81. LittleEndianWriter.WriteUInt64(buffer, offset + 40, SessionID);
  82. if ((Flags & SMB2PacketHeaderFlags.Signed) > 0)
  83. {
  84. ByteWriter.WriteBytes(buffer, offset + 48, Signature);
  85. }
  86. }
  87. public bool IsResponse
  88. {
  89. get
  90. {
  91. return (Flags & SMB2PacketHeaderFlags.ServerToRedir) > 0;
  92. }
  93. set
  94. {
  95. if (value)
  96. {
  97. Flags |= SMB2PacketHeaderFlags.ServerToRedir;
  98. }
  99. else
  100. {
  101. Flags &= ~SMB2PacketHeaderFlags.ServerToRedir;
  102. }
  103. }
  104. }
  105. public bool IsRelatedOperations
  106. {
  107. get
  108. {
  109. return (Flags & SMB2PacketHeaderFlags.RelatedOperations) > 0;
  110. }
  111. set
  112. {
  113. if (value)
  114. {
  115. Flags |= SMB2PacketHeaderFlags.RelatedOperations;
  116. }
  117. else
  118. {
  119. Flags &= ~SMB2PacketHeaderFlags.RelatedOperations;
  120. }
  121. }
  122. }
  123. public static bool IsValidSMB2Header(byte[] buffer)
  124. {
  125. if (buffer.Length >= 4)
  126. {
  127. byte[] signature = ByteReader.ReadBytes(buffer, 0, 4);
  128. return ByteUtils.AreByteArraysEqual(signature, ProtocolSignature);
  129. }
  130. return false;
  131. }
  132. }
  133. }