Example #1
0
        public void WDigestHash_UnicodeInput()
        {
            var hashes = WDigestHash.ComputeHash(@"Příliš žluťoučký kůň úpěl ďábelské ódy. В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!".ToSecureString(), "*****@*****.**", "April", "ADATUM", "Adatum.com");

            Assert.AreEqual(WDigestHash.HashCount, hashes.Length);
            Assert.AreEqual("fad613ac9301e7ae6dcc537e2eef5021", hashes[0].ToHex());
            Assert.AreEqual("f3b76b7db452d6be096942f9bcce74ea", hashes[1].ToHex());
            Assert.AreEqual("919952d85318a3d5b67e9df5a78b7141", hashes[2].ToHex());
            Assert.AreEqual("fad613ac9301e7ae6dcc537e2eef5021", hashes[3].ToHex());
            Assert.AreEqual("35dd0ca1e7631567f2ae132e038ccd8f", hashes[4].ToHex());
            Assert.AreEqual("f6d89b7867a2d3d1cbae038091bdb0cc", hashes[5].ToHex());
            Assert.AreEqual("0bfedf219f856e2edcfec5231470c0b3", hashes[6].ToHex());
            Assert.AreEqual("df33d4e6eb9af1406b25e0e16548a2da", hashes[7].ToHex());
            Assert.AreEqual("5e2d43bdbb743c5d2601baafdd32a1af", hashes[8].ToHex());
            Assert.AreEqual("5277f1cf72b11b2ff48721cf9d431893", hashes[9].ToHex());
            Assert.AreEqual("9681f457b0767ed163b8dc8526469af6", hashes[10].ToHex());
            Assert.AreEqual("3e9ce47f72f7e39661199f18ee8bc2aa", hashes[11].ToHex());
            Assert.AreEqual("404243dbcec9a1d73d0b1cb49060c196", hashes[12].ToHex());
            Assert.AreEqual("29d93dc099bd1b5c9f20bbeb042bb4ff", hashes[13].ToHex());
            Assert.AreEqual("0ecdf90500b3189dc3082dd1bce0b5bc", hashes[14].ToHex());
            Assert.AreEqual("4a4135a2ac1daa81fea605adc9188c67", hashes[15].ToHex());
            Assert.AreEqual("0a1f7bd410a8340342045daf0cc78789", hashes[16].ToHex());
            Assert.AreEqual("be97dc768a7683e839438b29e30b6f7b", hashes[17].ToHex());
            Assert.AreEqual("7d6a36f69323172b25ef61a761f29d1b", hashes[18].ToHex());
            Assert.AreEqual("ed2d15fcde27c04892014aaf46201ec8", hashes[19].ToHex());
            Assert.AreEqual("51f43cb00d57226f530d52908a072c43", hashes[20].ToHex());
            Assert.AreEqual("35329ba52771477b8665ef47b89bebbf", hashes[21].ToHex());
            Assert.AreEqual("7515013a7da75b573467e521abb783e1", hashes[22].ToHex());
            Assert.AreEqual("9bab42c45f29cda4f4dadad0a14cc8b6", hashes[23].ToHex());
            Assert.AreEqual("26075b3e4791600800363160d217265b", hashes[24].ToHex());
            Assert.AreEqual("bbba87b75b45d71cf7fd84d4e2a22344", hashes[25].ToHex());
            Assert.AreEqual("18ca7497b2624e7fde7165854788dd49", hashes[26].ToHex());
            Assert.AreEqual("0d9a52cbff395f8df9e285b01c2a78fb", hashes[27].ToHex());
            Assert.AreEqual("c4280744f0ff1181b939b71b1ddc37f5", hashes[28].ToHex());
        }
Example #2
0
        public void WDigestHash_ASCIIInput()
        {
            var hashes = WDigestHash.ComputeHash(@"Pa$$w0rd".ToSecureString(), null, "Administrator", "ADATUM", "Adatum.com");

            Assert.AreEqual(WDigestHash.HashCount, hashes.Length);
            Assert.AreEqual("3f602ffdac6b06655481a06cce08adf3", hashes[0].ToHex());
            Assert.AreEqual("971256a81b883974fcbcf369f67ecf61", hashes[1].ToHex());
            Assert.AreEqual("ec3d57e1caf31b9cd0fc1e3bf913bbf6", hashes[2].ToHex());
            Assert.AreEqual("3f602ffdac6b06655481a06cce08adf3", hashes[3].ToHex());
            Assert.AreEqual("30c8584ec6a52de03fead6e66443b896", hashes[4].ToHex());
            Assert.AreEqual("da9aab75d2ad8152daedc92aea4e49ac", hashes[5].ToHex());
            Assert.AreEqual("eb781ca6bf2d4f3a30bc8f8ba360b1a0", hashes[6].ToHex());
            Assert.AreEqual("b70f192a3ee11e47bc1408e18835210e", hashes[7].ToHex());
            Assert.AreEqual("afebaf56c0b704ab12276306c3524d9f", hashes[8].ToHex());
            Assert.AreEqual("a4d5b0be4785b495b4b53e70c35d4990", hashes[9].ToHex());
            Assert.AreEqual("1167280ac9a9bc1ec1b49d171a8e9b62", hashes[10].ToHex());
            Assert.AreEqual("e17ff031d74e32e67ec1f1b6e0b2c26b", hashes[11].ToHex());
            Assert.AreEqual("379c029a72f4d0e649e7aa6ad659dbe0", hashes[12].ToHex());
            Assert.AreEqual("f7fcfe4c5ec50f9db38577cea6b99f28", hashes[13].ToHex());
            Assert.AreEqual("ffde532cbd677b5562ce4455099cdafd", hashes[14].ToHex());
            Assert.AreEqual("478561ada3cecab0094ea704b90b1c84", hashes[15].ToHex());
            Assert.AreEqual("51ca360a2a2d35b184a0c78fd0432137", hashes[16].ToHex());
            Assert.AreEqual("f7841c8b57a9a65875ee40a39ba270cb", hashes[17].ToHex());
            Assert.AreEqual("3b8dc2b699160e41ce1c8f1cdacd0c2c", hashes[18].ToHex());
            Assert.AreEqual("132d33c113262bd560b40c39d1cac291", hashes[19].ToHex());
            Assert.AreEqual("8b8c4f339d3736ede2c4c0bc4e53f3ff", hashes[20].ToHex());
            Assert.AreEqual("209ae3b1dc6789f90f352e2ff273111b", hashes[21].ToHex());
            Assert.AreEqual("9b22dae245b82c3e55061265b288607c", hashes[22].ToHex());
            Assert.AreEqual("bb1edeb4c9b818d829800192a1528a88", hashes[23].ToHex());
            Assert.AreEqual("f78b1d41fe8372506e31461625743eb4", hashes[24].ToHex());
            Assert.AreEqual("dd829e0cda63ba68f95f98b1750885f6", hashes[25].ToHex());
            Assert.AreEqual("177eeed7b3cf4df4e114c4ca91beafcd", hashes[26].ToHex());
            Assert.AreEqual("9c0d49ddf1ac7cff9d1e6f96cc8a55d5", hashes[27].ToHex());
            Assert.AreEqual("8da34a0b94604b06cd58f9bf69142383", hashes[28].ToHex());
        }
Example #3
0
        public void WDigestHash_EncodeProperty()
        {
            byte[]   blob   = "3100011D00000000000000000000000038723ED34D6DF84FB88972CE00B9D28952E954B1F92368D40FB88C9B54DF2D5AE275AEEBE6D0A0DA7B0572F719BB307B38723ED34D6DF84FB88972CE00B9D28952E954B1F92368D40FB88C9B54DF2D5AFE93C6CC61028BDD93B74042ED778C2338723ED34D6DF84FB88972CE00B9D289429072BFFA5BE07598CA43AE52833732429072BFFA5BE07598CA43AE528337320749C5CCFC3FCD9A23F8EE373FE0DAEC55113516DFD326403029BBC568B2FA4A429072BFFA5BE07598CA43AE52833732D04622762DF13DB90786B72C423017DB55113516DFD326403029BBC568B2FA4AC35F5A94C1F7BD9C0B654DA4526F2DA5C35F5A94C1F7BD9C0B654DA4526F2DA59C200D20FA1D18F814BD491108E3F5440784E0DD92BED5304A4589BC6751DD8C148DC7BE0270C46539CBC9A6C3509E2691F52DC6ECBF3CF2B1D802EBD9E56319D09E4A62CCF638C2B8AD1360BEBD11CED09E4A62CCF638C2B8AD1360BEBD11CEDB565E643D18D2C3BB4F3DA942B27DDC56D0DA9761F9E1BD60332B365A10677256D0DA9761F9E1BD60332B365A1067725F8A9A18636D788F56C432A6E51FE884FBB9BB6939D39D22E17DCCFFBAB6F314FC31AFC0E0C72839C51F5647D1582B83AECD3707827166AE2D55DA8A4F2A8D8B".HexToBinary();
            byte[][] hashes = WDigestHash.Parse(blob);

            byte[] newBlob = WDigestHash.Encode(hashes);
            Assert.AreEqual(blob.ToHex(), newBlob.ToHex());
        }
        public void WDigestHash_Compute_LDS()
        {
            // Property value taken from AD LDS
            string expectedBlob  = "3100011d000000000000000000000000af4156909297baece4e553b731d9d552da58c12e5880cad54a3f909c07b0792eec9d262783c811ad9cc7aeb1ab019fe0af4156909297baece4e553b731d9d552af4156909297baece4e553b731d9d552ec9d262783c811ad9cc7aeb1ab019fe0da58c12e5880cad54a3f909c07b0792e95e11e920c7405ca6639d932888cc11c53d9e953141b322f29eb1a02798c299042eea90067734b2a81abbc79618cc1519d9aac28e63107a495266e755f7a2babac6b5dfb3bfa3b7039058310d5b36ccc7c97824dd59b9a6a053b5fae3d8603f20a5e2bc3111c759efb3a91e3740633e83b12daad09e83cb92477ac59993c5a843b12daad09e83cb92477ac59993c5a843b12daad09e83cb92477ac59993c5a8471e7228faba51df979beef06b34f791820aa1475f40540f0db59f9d2d93fc3da5f88f6d82d185741a82c7fa79e801c6d8eae592a0ce55271a17de0b39cf1e5e9923354fb99887724cf2b10e88108776b427804b8a6d6ed92c11ecb94e40da72c0c997bc1906b1f0092d61bd0efee428b0c997bc1906b1f0092d61bd0efee428b0c997bc1906b1f0092d61bd0efee428bd93e9a9a7452dff036a67a5d5d333d7c4effe21b0afc142382943ef26024649aaa6a6a95c237f2b8efa2f13ecb0cb220";
            string password      = @"Pa$$w0rd";
            string userDN        = "CN=john,DC=dsinternals,DC=com";
            string namingContext = "DC=dsinternals,DC=com";

            // Compute and compare
            byte[][] hashes = WDigestHash.ComputeHash(password.ToSecureString(), userDN, namingContext);
            byte[]   blob   = WDigestHash.Encode(hashes);
            Assert.AreEqual(expectedBlob, blob.ToHex());
        }
Example #5
0
        public void SupplementalCredentials_Generate2()
        {
            var credentials = new SupplementalCredentials(@"Pa$$w0rd".ToSecureString(), "user02", null, "ADATUM", "Adatum.com");

            byte[] blob = credentials.ToByteArray();

            byte[] expectedBlob        = "000000005008000000000000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000500005003200200001005000720069006d006100720079003a004e0054004c004d002d005300740072006f006e0067002d004e0054004f005700460031643638373531326339333534646365653233376665613930643139356363373600a00101005000720069006d006100720079003a004b00650072006200650072006f0073002d004e0065007700650072002d004b0065007900730030343030303030303033303030303030303030303030303032303030323030303738303030303030303031303030303030303030303030303030303030303030303031303030303031323030303030303230303030303030393830303030303030303030303030303030303030303030303031303030303031313030303030303130303030303030623830303030303030303030303030303030303030303030303031303030303030333030303030303038303030303030633830303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303034313030343430303431303035343030353530303464303032653030343330303466303034643030373530303733303036353030373230303330303033323030363232666361316431326465316466363565383430616664356633623938343462313861373261383261656436653365353863333932353737353366646661383330363636393734636237323965663662643434663865616233323936653563313366386664333764353537613430312000c00001005000720069006d006100720079003a004b00650072006200650072006f0073003033303030303030303130303030303032303030323030303338303030303030303030303030303030303030303030303033303030303030303830303030303035383030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303034313030343430303431303035343030353530303464303032653030343330303466303034643030373530303733303036353030373230303330303033323030313366386664333764353537613430311000d80002005000610063006b0061006700650073003465303035343030346330303464303032643030353330303734303037323030366630303665303036373030326430303465303035343030346630303537303034363030303030303462303036353030373230303632303036353030373230303666303037333030326430303465303036353030373730303635303037323030326430303462303036353030373930303733303030303030346230303635303037323030363230303635303037323030366630303733303030303030353730303434303036393030363730303635303037333030373430301e00c00301005000720069006d006100720079003a00570044006900670065007300740033313030303131643030303030303030303030303030303030303030303030303963333836656664383134663734396365653066326139653665643765633633326438343535393963346266623533333732303730623362666132646339323235633063353839333430356536353138333432323132663864393564363837643963333836656664383134663734396365653066326139653665643765633633326438343535393963346266623533333732303730623362666132646339323238353037393131323334326532363433303162636566643232376536663166663963333836656664383134663734396365653066326139653665643765633633323338383064366134316161336163333730313565383262653066623033363063633634383439353232643735313239303264653236313230303431303230623934666234646333646230386133663935343731366436643264366563363062633333393036653139623034323263376638366463363866326536356165323863633634383439353232643735313239303264653236313230303431303230623536663030336262343532616633666634643163373464363464643035363139633333393036653139623034323263376638366463363866326536356165323861666437346463366633376132373732663038396364636166326436663961626366333139366136383137313439363066366463393237646137363864666263323237386336656533643064336438613261343635336666306562396630623039333962666432656338623131656262386531326563636363613766356131393538613934613463326134633262343839373230313831346235626238666230363763663335336665636232343335356466353538653837626534353432386261336634346233613037346334666364636261623934653635303533363166376133663434623361303734633466636463626162393465363530353336316637393265633665646235336238366139326634363965326339336433356135616430633331313966636536386133653331353134323131363739366531396638353462333938616139326536663633333163353630633662633939333264386436363163316136653930373937306434313662353538626563366164373736383937653439356362306334376130356661646130626638656362656130316634333965356436353337383164343366323734346535343838663762623762323838633066623339303139343864393837303766316161653436346165643563343001".HexToBinary();
            var    expectedCredentials = new SupplementalCredentials(expectedBlob);

            // Test integrity
            Assert.AreEqual(expectedCredentials.ClearText, credentials.ClearText);
            Assert.AreEqual(expectedCredentials.NTLMStrongHash.Length, credentials.NTLMStrongHash.Length);
            Assert.AreEqual(WDigestHash.Encode(expectedCredentials.WDigest).ToHex(), WDigestHash.Encode(credentials.WDigest).ToHex());
            Assert.AreEqual(expectedCredentials.Kerberos.ToByteArray().ToHex(), credentials.Kerberos.ToByteArray().ToHex());
            Assert.AreEqual(expectedCredentials.KerberosNew.ToByteArray().ToHex(), credentials.KerberosNew.ToByteArray().ToHex());
        }
Example #6
0
        public SupplementalCredentials(SecureString password, string samAccountName, string userPrincipalName, string netBiosDomainName, string dnsDomainName)
        {
            // Input validation
            Validator.AssertNotNull(password, "password");
            Validator.AssertNotNull(samAccountName, "samAccountName");
            // Note that UPN can be NULL, as it is an optional user attribute.
            Validator.AssertNotNull(netBiosDomainName, "netBiosDomainName");
            Validator.AssertNotNull(dnsDomainName, "dnsDomainName");

            // Generate Kerberos keys
            this.Kerberos    = new KerberosCredential(password, samAccountName, dnsDomainName);
            this.KerberosNew = new KerberosCredentialNew(password, samAccountName, dnsDomainName);

            // Generate WDigest hashes
            this.WDigest = WDigestHash.ComputeHash(password, userPrincipalName, samAccountName, netBiosDomainName, dnsDomainName);

            // Generate a random NTLM strong hash that is definitely not based on a password.
            this.NTLMStrongHash = NTHash.GetRandom();

            // Note that we do not want to store the password in cleartext.
        }
Example #7
0
        private void WriteProperties(BinaryWriter writer)
        {
            var propertyNames  = new List <string>();
            var propertyValues = new List <byte[]>();

            if (this.ClearText != null)
            {
                propertyNames.Add(PropertyCleartext);
                byte[] encodedPassword = Encoding.Unicode.GetBytes(this.ClearText);
                propertyValues.Add(encodedPassword);
            }

            if (this.NTLMStrongHash != null)
            {
                propertyNames.Add(PropertyNTLMStrongHash);
                propertyValues.Add(this.NTLMStrongHash);
            }

            if (this.KerberosNew != null)
            {
                propertyNames.Add(PropertyKerberosNew);
                byte[] kerberosNewerCredentials = this.KerberosNew.ToByteArray();
                propertyValues.Add(kerberosNewerCredentials);
            }

            if (this.Kerberos != null)
            {
                propertyNames.Add(PropertyKerberos);
                byte[] kerberosCredentials = this.Kerberos.ToByteArray();
                propertyValues.Add(kerberosCredentials);
            }

            // Create a placeholder for the packages property
            propertyNames.Add(PropertyPackages);
            propertyValues.Add(null);

            if (this.WDigest != null)
            {
                propertyNames.Add(PropertyWDigest);
                byte[] encodedWDigest = WDigestHash.Encode(this.WDigest);
                propertyValues.Add(encodedWDigest);
            }

            // We now know the full list of properties, so we put it instead of the placeholder.
            var    shortPropertyNames        = propertyNames.Select(propertyName => propertyName.Replace(PropertyNamePrefix, String.Empty)).Where(propertyName => propertyName != PropertyPackages);
            string concatenatedPropertyNames = String.Join(Char.MinValue.ToString(), shortPropertyNames);

            byte[] encodedPropertyNames = Encoding.Unicode.GetBytes(concatenatedPropertyNames);
            int    packageIndex         = propertyNames.LastIndexOf(PropertyPackages);

            propertyValues[packageIndex] = encodedPropertyNames;

            // We only continue if there are any credential-related properties, not just the placeholder for their list.
            if (propertyNames.Count > 1)
            {
                // PropertyCount(2 bytes): The number of USER_PROPERTY elements in the UserProperties field. When there are zero USER_PROPERTY elements in the UserProperties field, this field MUST be omitted; the resultant USER_PROPERTIES structure has a constant size of 0x6F bytes.
                writer.Write((short)propertyNames.Count);

                // UserProperties (variable): An array of PropertyCount USER_PROPERTY elements.
                for (int i = 0; i < propertyNames.Count; i++)
                {
                    WriteProperty(writer, propertyNames[i], propertyValues[i]);
                }
            }
        }
Example #8
0
        private void ReadProperties(BinaryReader reader)
        {
            // The number of USER_PROPERTY elements in the UserProperties field.
            short propertyCount = reader.ReadInt16();

            for (int i = 0; i < propertyCount; i++)
            {
                // The number of bytes, in little-endian byte order, of PropertyName.
                short nameLength = reader.ReadInt16();

                // The number of bytes contained in PropertyValue.
                short valueLength = reader.ReadInt16();

                //  This value MUST be ignored by the recipient and MAY<21> be set to arbitrary values on update.
                short reserved = reader.ReadInt16();

                //  The name of this property as a UTF-16 encoded string.
                byte[] binaryPropertyName = reader.ReadBytes(nameLength);

                //  The value of this property. The value MUST be hexadecimal-encoded using an 8-bit character size, and the values '0' through '9' inclusive and 'a' through 'f' inclusive (the specification of 'a' through 'f' is case-sensitive).
                byte[] binaryPropertyValue  = reader.ReadBytes(valueLength);
                string propertyName         = Encoding.Unicode.GetString(binaryPropertyName);
                string hexPropertyValue     = Encoding.ASCII.GetString(binaryPropertyValue);
                byte[] decodedPropertyValue = hexPropertyValue.HexToBinary();
                switch (propertyName)
                {
                case PropertyCleartext:
                    // The cleartext password.
                    this.ClearText = Encoding.Unicode.GetString(decodedPropertyValue);
                    break;

                case PropertyKerberos:
                    // Cryptographic hashes of the cleartext password for the Kerberos authentication protocol.
                    this.Kerberos = new KerberosCredential(decodedPropertyValue);
                    break;

                case PropertyKerberosNew:
                    // Cryptographic hashes of the cleartext password for the Kerberos authentication protocol.
                    this.KerberosNew = new KerberosCredentialNew(decodedPropertyValue);
                    break;

                case PropertyWDigest:
                    // Cryptographic hashes of the cleartext password for the Digest authentication protocol.
                    this.WDigest = WDigestHash.Parse(decodedPropertyValue);
                    break;

                case PropertyPackages:
                    // A list of the credential types that are stored as properties in decryptedSecret.
                    var packages = Encoding.Unicode.GetString(decodedPropertyValue).Split(Char.MinValue);
                    break;

                case PropertyNTLMStrongHash:
                    // This is a totally random value generated by DC on each password change, since Windows Server 2016.
                    this.NTLMStrongHash = decodedPropertyValue;
                    break;

                default:
                    // Unknown package. This should never happen
                    break;
                }
            }
        }
Example #9
0
 public void WDigestHash_NullInput()
 {
     var hashes = WDigestHash.ComputeHash(null, null, null, null, null);
 }