mirror of
https://github.com/TalAloni/SMBLibrary.git
synced 2025-08-05 23:34:56 +02:00
NTLM: Improved CHALLENGE_MESSAGE implementation
This commit is contained in:
parent
7610056a0b
commit
3ce1ca6a30
3 changed files with 35 additions and 24 deletions
|
@ -13,36 +13,44 @@ namespace SMBLibrary.Authentication.NTLM
|
|||
{
|
||||
public class AVPairUtils
|
||||
{
|
||||
public static byte[] GetAVPairSequence(string domainName, string computerName)
|
||||
public static KeyValuePairList<AVPairKey, byte[]> GetAVPairSequence(string domainName, string computerName)
|
||||
{
|
||||
KeyValuePairList<AVPairKey, byte[]> pairs = new KeyValuePairList<AVPairKey, byte[]>();
|
||||
pairs.Add(AVPairKey.NbDomainName, UnicodeEncoding.Unicode.GetBytes(domainName));
|
||||
pairs.Add(AVPairKey.NbComputerName, UnicodeEncoding.Unicode.GetBytes(computerName));
|
||||
return AVPairUtils.GetAVPairSequenceBytes(pairs);
|
||||
return pairs;
|
||||
}
|
||||
|
||||
public static byte[] GetAVPairSequenceBytes(KeyValuePairList<AVPairKey, byte[]> pairs)
|
||||
{
|
||||
int length = 0;
|
||||
int length = GetAVPairSequenceLength(pairs);
|
||||
byte[] result = new byte[length];
|
||||
int offset = 0;
|
||||
WriteAVPairSequence(result, ref offset, pairs);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int GetAVPairSequenceLength(KeyValuePairList<AVPairKey, byte[]> pairs)
|
||||
{
|
||||
int length = 0;
|
||||
foreach (KeyValuePair<AVPairKey, byte[]> pair in pairs)
|
||||
{
|
||||
length += 4 + pair.Value.Length;
|
||||
}
|
||||
length += 4;
|
||||
return length + 4;
|
||||
}
|
||||
|
||||
byte[] result = new byte[length];
|
||||
int offset = 0;
|
||||
foreach (KeyValuePair<AVPairKey, byte[]> pair in pairs)
|
||||
public static void WriteAVPairSequence(byte[] buffer, ref int offset, KeyValuePairList<AVPairKey, byte[]> pairs)
|
||||
{
|
||||
foreach (KeyValuePair<AVPairKey, byte[]> pair in pairs)
|
||||
{
|
||||
WriteAVPair(result, ref offset, pair.Key, pair.Value);
|
||||
WriteAVPair(buffer, ref offset, pair.Key, pair.Value);
|
||||
}
|
||||
LittleEndianWriter.WriteUInt16(result, ref offset, (ushort)AVPairKey.EOL);
|
||||
LittleEndianWriter.WriteUInt16(result, ref offset, 0);
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, (ushort)AVPairKey.EOL);
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void WriteAVPair(byte[] buffer, ref int offset, AVPairKey key, byte[] value)
|
||||
private static void WriteAVPair(byte[] buffer, ref int offset, AVPairKey key, byte[] value)
|
||||
{
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, (ushort)key);
|
||||
LittleEndianWriter.WriteUInt16(buffer, ref offset, (ushort)value.Length);
|
||||
|
@ -63,7 +71,7 @@ namespace SMBLibrary.Authentication.NTLM
|
|||
return result;
|
||||
}
|
||||
|
||||
public static KeyValuePair<AVPairKey, byte[]> ReadAVPair(byte[] buffer, ref int offset)
|
||||
private static KeyValuePair<AVPairKey, byte[]> ReadAVPair(byte[] buffer, ref int offset)
|
||||
{
|
||||
AVPairKey key = (AVPairKey)LittleEndianReader.ReadUInt16(buffer, ref offset);
|
||||
ushort length = LittleEndianReader.ReadUInt16(buffer, ref offset);
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace SMBLibrary.Authentication.NTLM
|
|||
public NegotiateFlags NegotiateFlags;
|
||||
public byte[] ServerChallenge; // 8 bytes
|
||||
// Reserved - 8 bytes
|
||||
public byte[] TargetInfo; // sequence of AV_PAIR structures
|
||||
public KeyValuePairList<AVPairKey, byte[]> TargetInfo = new KeyValuePairList<AVPairKey,byte[]>();
|
||||
public NTLMVersion Version;
|
||||
|
||||
public ChallengeMessage()
|
||||
|
@ -39,7 +39,11 @@ namespace SMBLibrary.Authentication.NTLM
|
|||
NegotiateFlags = (NegotiateFlags)LittleEndianConverter.ToUInt32(buffer, 20);
|
||||
ServerChallenge = ByteReader.ReadBytes(buffer, 24, 8);
|
||||
// Reserved
|
||||
TargetInfo = AuthenticationMessageUtils.ReadBufferPointer(buffer, 40);
|
||||
byte[] targetInfoBytes = AuthenticationMessageUtils.ReadBufferPointer(buffer, 40);
|
||||
if (targetInfoBytes.Length > 0)
|
||||
{
|
||||
TargetInfo = AVPairUtils.ReadAVPairSequence(targetInfoBytes, 0);
|
||||
}
|
||||
if ((NegotiateFlags & NegotiateFlags.Version) > 0)
|
||||
{
|
||||
Version = new NTLMVersion(buffer, 48);
|
||||
|
@ -53,9 +57,10 @@ namespace SMBLibrary.Authentication.NTLM
|
|||
TargetName = String.Empty;
|
||||
}
|
||||
|
||||
byte[] targetInfoBytes = AVPairUtils.GetAVPairSequenceBytes(TargetInfo);
|
||||
if ((NegotiateFlags & NegotiateFlags.TargetInfo) == 0)
|
||||
{
|
||||
TargetInfo = new byte[0];
|
||||
targetInfoBytes = new byte[0];
|
||||
}
|
||||
|
||||
int fixedLength = 48;
|
||||
|
@ -63,7 +68,7 @@ namespace SMBLibrary.Authentication.NTLM
|
|||
{
|
||||
fixedLength += 8;
|
||||
}
|
||||
int payloadLength = TargetName.Length * 2 + TargetInfo.Length;
|
||||
int payloadLength = TargetName.Length * 2 + targetInfoBytes.Length;
|
||||
byte[] buffer = new byte[fixedLength + payloadLength];
|
||||
ByteWriter.WriteAnsiString(buffer, 0, AuthenticateMessage.ValidSignature, 8);
|
||||
LittleEndianWriter.WriteUInt32(buffer, 8, (uint)MessageType);
|
||||
|
@ -77,8 +82,8 @@ namespace SMBLibrary.Authentication.NTLM
|
|||
int offset = fixedLength;
|
||||
AuthenticationMessageUtils.WriteBufferPointer(buffer, 12, (ushort)(TargetName.Length * 2), (uint)offset);
|
||||
ByteWriter.WriteUTF16String(buffer, ref offset, TargetName);
|
||||
AuthenticationMessageUtils.WriteBufferPointer(buffer, 40, (ushort)TargetInfo.Length, (uint)offset);
|
||||
ByteWriter.WriteBytes(buffer, ref offset, TargetInfo);
|
||||
AuthenticationMessageUtils.WriteBufferPointer(buffer, 40, (ushort)targetInfoBytes.Length, (uint)offset);
|
||||
ByteWriter.WriteBytes(buffer, ref offset, targetInfoBytes);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
|
|
@ -99,8 +99,7 @@ namespace SMBLibrary
|
|||
message.Version = new NTLMVersion(6, 0, 6000, NTLMVersion.NTLMSSP_REVISION_W2K3);
|
||||
message.NegotiateFlags = NegotiateFlags.UnicodeEncoding | NegotiateFlags.OEMEncoding | NegotiateFlags.TargetNameSupplied | NegotiateFlags.Sign | NegotiateFlags.Seal | NegotiateFlags.NTLMSessionSecurity | NegotiateFlags.AlwaysSign | NegotiateFlags.TargetTypeServer | NegotiateFlags.ExtendedSessionSecurity | NegotiateFlags.TargetInfo | NegotiateFlags.Version | NegotiateFlags.Use128BitEncryption | NegotiateFlags.KeyExchange | NegotiateFlags.Use56BitEncryption;
|
||||
message.TargetName = "Server";
|
||||
byte[] serverAVPair = AVPairUtils.GetAVPairSequence("Domain", "Server");
|
||||
message.TargetInfo = serverAVPair;
|
||||
message.TargetInfo = AVPairUtils.GetAVPairSequence("Domain", "Server");
|
||||
|
||||
byte[] messageBytes = message.GetBytes();
|
||||
bool success = ByteUtils.AreByteArraysEqual(expected, messageBytes);
|
||||
|
@ -130,7 +129,6 @@ namespace SMBLibrary
|
|||
byte[] sessionKey = {0xc5, 0xda, 0xd2, 0x54, 0x4f, 0xc9, 0x79, 0x90, 0x94, 0xce, 0x1c, 0xe9, 0x0b, 0xc9, 0xd0, 0x3e};
|
||||
byte[] serverChallenge = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
|
||||
byte[] clientChallenge = new byte[] { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };
|
||||
byte[] serverAVPair = AVPairUtils.GetAVPairSequence("Domain", "Server");
|
||||
DateTime time = DateTime.FromFileTimeUtc(0); // same as new byte[8]
|
||||
NTLMv2ClientChallenge clientChallengeStructure = new NTLMv2ClientChallenge(time, clientChallenge, "Domain", "Server");
|
||||
byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue