| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- package ntlmssp
- import (
- "bytes"
- "crypto/hmac"
- "crypto/md5"
- "encoding/binary"
- "fmt"
- "strings"
- "unicode/utf16"
- "imuslab.com/smb/driver/mod/smb/encoder"
- "golang.org/x/crypto/md4"
- )
- /*
- func convertUTF16ToLittleEndianBytes(u []uint16) []byte {
- b := make([]byte, 2*len(u))
- for index, value := range u {
- binary.LittleEndian.PutUint16(b[index*2:], value)
- }
- return b
- }
- // s.encode('utf-16le')
- func UnicodeEncode(p string) []byte {
- return convertUTF16ToLittleEndianBytes(utf16.Encode([]rune(p)))
- }
- func MD4(data []byte) []byte {
- h := md4.New()
- h.Write(data)
- return h.Sum(nil)
- }
- func MD5(data []byte) []byte {
- h := md5.New()
- h.Write(data)
- return h.Sum(nil)
- }
- func HMAC_MD5(key, data []byte) []byte {
- h := hmac.New(md5.New, key)
- h.Write(data)
- return h.Sum(nil)
- }
- // Version 2 of NTLM hash function
- func Ntowfv2(password, user, domain string) []byte {
- return HMAC_MD5(MD4(UnicodeEncode(password)), UnicodeEncode(strings.ToUpper(user)+domain))
- }
- // Same as NTOWFv2
- func Lmowfv2(password, user, domain string) []byte {
- return Ntowfv2(password, user, domain)
- }
- */
- func Ntowfv1(pass string) []byte {
- hash := md4.New()
- hash.Write(encoder.ToUnicode(pass))
- return hash.Sum(nil)
- }
- func Ntowfv2(pass, user, domain string) []byte {
- h := hmac.New(md5.New, Ntowfv1(pass))
- h.Write(encoder.ToUnicode(strings.ToUpper(user) + domain))
- return h.Sum(nil)
- }
- func Lmowfv2(pass, user, domain string) []byte {
- return Ntowfv2(pass, user, domain)
- }
- func NTPasswordHash(password string) string {
- input := utf16.Encode([]rune(password))
- h := md4.New()
- if err := binary.Write(h, binary.LittleEndian, input); err != nil {
- // these are all in-memory operations with no error modes,
- // but just in case
- panic(fmt.Errorf("impossible error hashing password: %w", err))
- }
- output := h.Sum(nil)
- // encode to conventional uppercase hex
- return fmt.Sprintf("%X", output)
- }
- func ComputeResponseNTLMv2(nthash, lmhash, clientChallenge, serverChallenge, timestamp, serverName []byte) []byte {
- temp := []byte{1, 1}
- temp = append(temp, 0, 0, 0, 0, 0, 0)
- temp = append(temp, timestamp...)
- temp = append(temp, clientChallenge...)
- temp = append(temp, 0, 0, 0, 0)
- temp = append(temp, serverName...)
- temp = append(temp, 0, 0, 0, 0)
- return ComputeResponseNTLMv2Check(nthash, serverChallenge, temp)
- // h := hmac.New(md5.New, nthash)
- // h.Write(append(serverChallenge, temp...))
- // ntproof := h.Sum(nil)
- // return append(ntproof, temp...)
- }
- func ComputeResponseNTLMv2Check(nthash, serverChallenge, temp []byte) []byte {
- h := hmac.New(md5.New, nthash)
- h.Write(append(serverChallenge, temp...))
- ntproof := h.Sum(nil)
- return append(ntproof, temp...)
- }
- func NTLMv2KeyExchangeKey(ntProofStr []byte, password, name, domain string) []byte {
- // // https://msdn.microsoft.com/en-us/library/cc236700.aspx
- // byte[] responseKeyNT = NTLMCryptography.NTOWFv2(password, message.UserName, message.DomainName);
- // byte[] ntProofStr = ByteReader.ReadBytes(message.NtChallengeResponse, 0, 16);
- // sessionBaseKey = new HMACMD5(responseKeyNT).ComputeHash(ntProofStr);
- // keyExchangeKey = sessionBaseKey;
- nthash := Ntowfv2(password, name, domain)
- h := hmac.New(md5.New, nthash)
- h.Write(ntProofStr)
- return h.Sum(nil)
- }
- func NTLMv2Verify(serverChallenge, clientChallengeStructurePadded []byte, password, name, domain string) []byte {
- nthash := Ntowfv2(password, name, domain)
- // logx.Printf("nthash: %v", nthash)
- temp := clientChallengeStructurePadded
- w := bytes.NewBuffer(make([]byte, 0))
- binary.Write(w, binary.LittleEndian, serverChallenge)
- h := hmac.New(md5.New, nthash)
- h.Write(append(serverChallenge, temp...))
- return h.Sum(nil)
- // return ComputeResponseNTLMv2Check(nthash, w.Bytes(), tail)
- }
|