AuthenticationMessageUtils.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /* Copyright (C) 2014-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 System.Collections.Generic;
  9. using System.Text;
  10. using Utilities;
  11. namespace SMBLibrary.Authentication
  12. {
  13. public class AuthenticationMessageUtils
  14. {
  15. public static string ReadAnsiStringBufferPointer(byte[] buffer, int offset)
  16. {
  17. byte[] bytes = ReadBufferPointer(buffer, offset);
  18. return ASCIIEncoding.Default.GetString(bytes);
  19. }
  20. public static string ReadUnicodeStringBufferPointer(byte[] buffer, int offset)
  21. {
  22. byte[] bytes = ReadBufferPointer(buffer, offset);
  23. return UnicodeEncoding.Unicode.GetString(bytes);
  24. }
  25. public static byte[] ReadBufferPointer(byte[] buffer, int offset)
  26. {
  27. ushort length = LittleEndianConverter.ToUInt16(buffer, offset);
  28. ushort maxLength = LittleEndianConverter.ToUInt16(buffer, offset + 2);
  29. uint bufferOffset = LittleEndianConverter.ToUInt32(buffer, offset + 4);
  30. if (length == 0)
  31. {
  32. return new byte[0];
  33. }
  34. else
  35. {
  36. return ByteReader.ReadBytes(buffer, (int)bufferOffset, length);
  37. }
  38. }
  39. public static void WriteBufferPointer(byte[] buffer, int offset, ushort bufferLength, uint bufferOffset)
  40. {
  41. LittleEndianWriter.WriteUInt16(buffer, offset, bufferLength);
  42. LittleEndianWriter.WriteUInt16(buffer, offset + 2, bufferLength);
  43. LittleEndianWriter.WriteUInt32(buffer, offset + 4, bufferOffset);
  44. }
  45. public static bool IsSignatureValid(byte[] messageBytes)
  46. {
  47. if (messageBytes.Length < 8)
  48. {
  49. return false;
  50. }
  51. string signature = ByteReader.ReadAnsiString(messageBytes, 0, 8);
  52. return (signature == AuthenticateMessage.ValidSignature);
  53. }
  54. /// <summary>
  55. /// If NTLM v1 Extended Security is used, LMResponse starts with 8-byte challenge, followed by 16 bytes of padding (set to zero).
  56. /// </summary>
  57. /// <remarks>
  58. /// LMResponse is 24 bytes for NTLM v1, NTLM v1 Extended Security and NTLM v2.
  59. /// </remarks>
  60. public static bool IsNTLMv1ExtendedSecurity(byte[] lmResponse)
  61. {
  62. if (lmResponse.Length == 24)
  63. {
  64. if (ByteUtils.AreByteArraysEqual(ByteReader.ReadBytes(lmResponse, 0, 8), new byte[8]))
  65. {
  66. // Challenge not present, cannot be NTLM v1 Extended Security
  67. return false;
  68. }
  69. return ByteUtils.AreByteArraysEqual(ByteReader.ReadBytes(lmResponse, 8, 16), new byte[16]);
  70. }
  71. return false;
  72. }
  73. /// <remarks>
  74. /// NTLM v1 / NTLM v1 Extended Security NTResponse is 24 bytes.
  75. /// </remarks>
  76. public static bool IsNTLMv2NTResponse(byte[] ntResponse)
  77. {
  78. return (ntResponse.Length >= 48 &&
  79. ntResponse[16] == NTLMv2ClientChallenge.StructureVersion &&
  80. ntResponse[17] == NTLMv2ClientChallenge.StructureVersion);
  81. }
  82. public static MessageTypeName GetMessageType(byte[] messageBytes)
  83. {
  84. return (MessageTypeName)LittleEndianConverter.ToUInt32(messageBytes, 8);
  85. }
  86. }
  87. }