generate challenge messages
This commit is contained in:
parent
a9e17c39f6
commit
d5082d0f01
@ -5,7 +5,6 @@ import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type AvPairType uint16
|
||||
@ -45,6 +44,11 @@ type AvPairs struct {
|
||||
List []AvPair
|
||||
}
|
||||
|
||||
func (p *AvPairs) AddAvPair(avId AvPairType, bytes []byte) {
|
||||
a := &AvPair{AvId: avId, AvLen: uint16(len(bytes)), Value: bytes}
|
||||
p.List = append(p.List, *a)
|
||||
}
|
||||
|
||||
func ReadAvPairs(data []byte) *AvPairs {
|
||||
pairs := new(AvPairs)
|
||||
|
||||
@ -153,10 +157,26 @@ func (a *AvPair) String() string {
|
||||
switch a.AvId {
|
||||
case MsvAvEOL:
|
||||
outString = "MsvAvEOL"
|
||||
case MsvAvNbComputerName, MsvAvNbDomainName, MsvAvDnsComputerName, MsvAvDnsDomainName, MsvAvDnsTreeName, MsvAvTargetName:
|
||||
outString = fmt.Sprintf("%s: %s", reflect.TypeOf(a.AvId).Name(), a.UnicodeStringValue())
|
||||
case MsvAvFlags, MsvAvTimestamp, MsAvRestrictions, MsvChannelBindings:
|
||||
outString = fmt.Sprintf("%s: %s", reflect.TypeOf(a.AvId).Name(), hex.EncodeToString(a.Value))
|
||||
case MsvAvNbComputerName:
|
||||
outString = "MsAvNbComputerName: " + a.UnicodeStringValue()
|
||||
case MsvAvNbDomainName:
|
||||
outString = "MsvAvNbDomainName: " + a.UnicodeStringValue()
|
||||
case MsvAvDnsComputerName:
|
||||
outString = "MsvAvDnsComputerName: " + a.UnicodeStringValue()
|
||||
case MsvAvDnsDomainName:
|
||||
outString = "MsvAvDnsDomainName: " + a.UnicodeStringValue()
|
||||
case MsvAvDnsTreeName:
|
||||
outString = "MsvAvDnsTreeName: " + a.UnicodeStringValue()
|
||||
case MsvAvFlags:
|
||||
outString = "MsvAvFlags: " + hex.EncodeToString(a.Value)
|
||||
case MsvAvTimestamp:
|
||||
outString = "MsvAvTimestamp: " + hex.EncodeToString(a.Value)
|
||||
case MsAvRestrictions:
|
||||
outString = "MsAvRestrictions: " + hex.EncodeToString(a.Value)
|
||||
case MsvAvTargetName:
|
||||
outString = "MsvAvTargetName: " + a.UnicodeStringValue()
|
||||
case MsvChannelBindings:
|
||||
outString = "MsvChannelBindings: " + hex.EncodeToString(a.Value)
|
||||
default:
|
||||
outString = fmt.Sprintf("unknown pair type: '%d'", a.AvId)
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ func ParseChallengeMessage(body []byte) (*Challenge, error) {
|
||||
|
||||
func (c *Challenge) Bytes() []byte {
|
||||
payloadLen := int(c.TargetName.Len + c.TargetInfoPayloadStruct.Len)
|
||||
messageLen := 8 + 4 + 12 + 4 + 8 + 8 + 12 + 8
|
||||
messageLen := 8 + 4 + 8 + 4 + 8 + 8 + 8 + 8
|
||||
payloadOffset := uint32(messageLen)
|
||||
|
||||
messageBytes := make([]byte, 0, messageLen+payloadLen)
|
||||
@ -105,18 +105,21 @@ func (c *Challenge) Bytes() []byte {
|
||||
binary.Write(buffer, binary.LittleEndian, c.MessageType)
|
||||
|
||||
c.TargetName.Offset = payloadOffset
|
||||
payloadOffset += uint32(c.TargetName.Len)
|
||||
buffer.Write(c.TargetName.Bytes())
|
||||
payloadOffset += uint32(c.TargetName.Len)
|
||||
|
||||
binary.Write(buffer, binary.LittleEndian, c.NegotiateFlags)
|
||||
buffer.Write(c.ServerChallenge)
|
||||
buffer.Write(make([]byte, 8))
|
||||
|
||||
c.TargetInfoPayloadStruct.Offset = payloadOffset
|
||||
payloadOffset += uint32(c.TargetInfoPayloadStruct.Len)
|
||||
buffer.Write(c.TargetInfoPayloadStruct.Bytes())
|
||||
payloadOffset += uint32(c.TargetInfoPayloadStruct.Len)
|
||||
|
||||
if(c.Version != nil) {
|
||||
buffer.Write(c.Version.Bytes())
|
||||
} else {
|
||||
buffer.Write(make([]byte, 8))
|
||||
}
|
||||
|
||||
// Write out the payloads
|
||||
|
@ -46,4 +46,18 @@ func TestDecodeChallenge(t *testing.T) {
|
||||
}
|
||||
|
||||
challenge.String()
|
||||
|
||||
outBytes := challenge.Bytes()
|
||||
|
||||
if len(outBytes) > 0 {
|
||||
reparsed, err := ParseChallengeMessage(outBytes)
|
||||
if err != nil {
|
||||
t.Error("Could not re-parse challenge message")
|
||||
}
|
||||
if reparsed.String() != challenge.String() {
|
||||
t.Error("Reparsed message is not the same")
|
||||
}
|
||||
} else {
|
||||
t.Error("Invalid challenge messsage bytes")
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +138,34 @@ func (f NegotiateFlag) String() string {
|
||||
return reflect.TypeOf(f).Name()
|
||||
}
|
||||
|
||||
func GetFlagName(flag NegotiateFlag) string {
|
||||
nameMap := map[NegotiateFlag]string{
|
||||
NTLMSSP_NEGOTIATE_56: "NTLMSSP_NEGOTIATE_56",
|
||||
NTLMSSP_NEGOTIATE_KEY_EXCH: "NTLMSSP_NEGOTIATE_KEY_EXCH",
|
||||
NTLMSSP_NEGOTIATE_128: "NTLMSSP_NEGOTIATE_128",
|
||||
NTLMSSP_NEGOTIATE_VERSION: "NTLMSSP_NEGOTIATE_VERSION",
|
||||
NTLMSSP_NEGOTIATE_TARGET_INFO: "NTLMSSP_NEGOTIATE_TARGET_INFO",
|
||||
NTLMSSP_REQUEST_NON_NT_SESSION_KEY: "NTLMSSP_REQUEST_NON_NT_SESSION_KEY",
|
||||
NTLMSSP_NEGOTIATE_IDENTIFY: "NTLMSSP_NEGOTIATE_IDENTIFY",
|
||||
NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: "NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY",
|
||||
NTLMSSP_TARGET_TYPE_SERVER: "NTLMSSP_TARGET_TYPE_SERVER",
|
||||
NTLMSSP_TARGET_TYPE_DOMAIN: "NTLMSSP_TARGET_TYPE_DOMAIN",
|
||||
NTLMSSP_NEGOTIATE_ALWAYS_SIGN: "NTLMSSP_NEGOTIATE_ALWAYS_SIGN",
|
||||
NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED: "NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED",
|
||||
NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED: "NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED",
|
||||
NTLMSSP_ANONYMOUS: "NTLMSSP_ANONYMOUS",
|
||||
NTLMSSP_NEGOTIATE_NTLM: "NTLMSSP_NEGOTIATE_NTLM",
|
||||
NTLMSSP_NEGOTIATE_LM_KEY: "NTLMSSP_NEGOTIATE_LM_KEY",
|
||||
NTLMSSP_NEGOTIATE_DATAGRAM: "NTLMSSP_NEGOTIATE_DATAGRAM",
|
||||
NTLMSSP_NEGOTIATE_SEAL: "NTLMSSP_NEGOTIATE_SEAL",
|
||||
NTLMSSP_NEGOTIATE_SIGN: "NTLMSSP_NEGOTIATE_SIGN",
|
||||
NTLMSSP_REQUEST_TARGET: "NTLMSSP_REQUEST_TARGET",
|
||||
NTLM_NEGOTIATE_OEM: "NTLM_NEGOTIATE_OEM",
|
||||
NTLMSSP_NEGOTIATE_UNICODE: "NTLMSSP_NEGOTIATE_UNICODE"}
|
||||
|
||||
return nameMap[flag]
|
||||
}
|
||||
|
||||
func FlagsToString(flags uint32) string {
|
||||
allFlags := [...]NegotiateFlag{
|
||||
NTLMSSP_NEGOTIATE_56,
|
||||
@ -166,7 +194,7 @@ func FlagsToString(flags uint32) string {
|
||||
var buffer bytes.Buffer
|
||||
for i := range allFlags {
|
||||
f := allFlags[i]
|
||||
buffer.WriteString(fmt.Sprintf("%s: %v\n", f.String(), f.IsSet(flags)))
|
||||
buffer.WriteString(fmt.Sprintf("%s: %v\n", GetFlagName(f), f.IsSet(flags)))
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
||||
|
@ -81,8 +81,42 @@ func (n *V2ServerSession) ProcessNegotiateMessage(nm *messages.Negotiate) (err e
|
||||
}
|
||||
|
||||
func (n *V2ServerSession) GenerateChallengeMessage() (cm *messages.Challenge, err error) {
|
||||
// TODO: Generate this challenge message
|
||||
return
|
||||
cm = new(messages.Challenge)
|
||||
cm.Signature = []byte("NTLMSSP\x00")
|
||||
cm.MessageType = uint32(2)
|
||||
cm.TargetName,_ = messages.CreateBytePayload(make([]byte, 0))
|
||||
|
||||
flags := uint32(0)
|
||||
flags = messages.NTLMSSP_NEGOTIATE_KEY_EXCH.Set(flags)
|
||||
// NOTE: Unsetting this in order for the signatures to work
|
||||
// flags = messages.NTLMSSP_NEGOTIATE_VERSION.Set(flags)
|
||||
flags = messages.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.Set(flags)
|
||||
flags = messages.NTLMSSP_NEGOTIATE_TARGET_INFO.Set(flags)
|
||||
flags = messages.NTLMSSP_NEGOTIATE_IDENTIFY.Set(flags)
|
||||
flags = messages.NTLMSSP_NEGOTIATE_ALWAYS_SIGN.Set(flags)
|
||||
flags = messages.NTLMSSP_NEGOTIATE_NTLM.Set(flags)
|
||||
flags = messages.NTLMSSP_NEGOTIATE_DATAGRAM.Set(flags)
|
||||
flags = messages.NTLMSSP_NEGOTIATE_SIGN.Set(flags)
|
||||
flags = messages.NTLMSSP_REQUEST_TARGET.Set(flags)
|
||||
flags = messages.NTLMSSP_NEGOTIATE_UNICODE.Set(flags)
|
||||
cm.NegotiateFlags = flags
|
||||
|
||||
cm.ServerChallenge = randomBytes(8)
|
||||
cm.Reserved = make([]byte, 8)
|
||||
|
||||
// Create the AvPairs we need
|
||||
pairs := new(messages.AvPairs)
|
||||
pairs.AddAvPair(messages.MsvAvNbDomainName, messages.StringToUtf16("REUTERS"))
|
||||
pairs.AddAvPair(messages.MsvAvNbComputerName, messages.StringToUtf16("UKBP-CBTRMFE06"))
|
||||
pairs.AddAvPair(messages.MsvAvDnsDomainName, messages.StringToUtf16("Reuters.net"))
|
||||
pairs.AddAvPair(messages.MsvAvDnsComputerName, messages.StringToUtf16("ukbp-cbtrmfe06.Reuters.net"))
|
||||
pairs.AddAvPair(messages.MsvAvDnsTreeName, messages.StringToUtf16("Reuters.net"))
|
||||
pairs.AddAvPair(messages.MsvAvEOL, make([]byte, 0))
|
||||
cm.TargetInfo = pairs
|
||||
cm.TargetInfoPayloadStruct,_ = messages.CreateBytePayload(pairs.Bytes())
|
||||
|
||||
cm.Version = &messages.VersionStruct{ProductMajorVersion: uint8(5), ProductMinorVersion: uint8(1), ProductBuild: uint16(2600), NTLMRevisionCurrent: uint8(10)}
|
||||
return cm, nil
|
||||
}
|
||||
|
||||
func (n *V2ServerSession) ProcessAuthenticateMessage(am *messages.Authenticate) (err error) {
|
||||
|
@ -62,14 +62,14 @@ func TestNTLMv2(t *testing.T) {
|
||||
challengeMessageBytes, _ := hex.DecodeString("4e544c4d53535000020000000c000c003800000033828ae20123456789abcdef00000000000000002400240044000000060070170000000f53006500720076006500720002000c0044006f006d00610069006e0001000c0053006500720076006500720000000000")
|
||||
challengeMessage, err := messages.ParseChallengeMessage(challengeMessageBytes)
|
||||
if err == nil {
|
||||
challengeMessage.String()
|
||||
challengeMessage.String()
|
||||
} else {
|
||||
t.Errorf("Could not parse challenge message: %s", err)
|
||||
t.Errorf("Could not parse challenge message: %s", err)
|
||||
}
|
||||
|
||||
err = client.ProcessChallengeMessage(challengeMessage)
|
||||
if err != nil {
|
||||
t.Errorf("Could not process challenge message: %s", err)
|
||||
t.Errorf("Could not process challenge message: %s", err)
|
||||
}
|
||||
|
||||
server := new(V2ServerSession)
|
||||
@ -113,4 +113,16 @@ func TestNTLMv2(t *testing.T) {
|
||||
|
||||
checkV2Value(t, "client seal key", server.clientSealingKey, "59f600973cc4960a25480a7c196e4c58", nil)
|
||||
checkV2Value(t, "client seal key", server.clientSigningKey, "4788dc861b4782f35d43fd98fe1a2d39", nil)
|
||||
|
||||
// Have the server generate an initial challenge message
|
||||
challenge, err := server.GenerateChallengeMessage()
|
||||
challenge.String()
|
||||
|
||||
// Have the client process this server challenge message
|
||||
client = new(V2ClientSession)
|
||||
client.SetUserInfo("User", "Password", "Domain")
|
||||
err = client.ProcessChallengeMessage(challenge)
|
||||
if err != nil {
|
||||
t.Errorf("Could not process server generated challenge message: %s", err)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user