Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Rubeus/Commands/Asktgt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ public void Execute(Dictionary<string, string> arguments)
else if (String.IsNullOrEmpty(certificate))
Ask.TGT(user, domain, hash, encType, outfile, ptt, dc, luid, true, opsec, servicekey, changepw, pac, proxyUrl, service);
else
Ask.TGT(user, domain, certificate, password, encType, outfile, ptt, dc, luid, true, verifyCerts, servicekey, getCredentials, proxyUrl, service, changepw);
// Ask.TGT is overloaded! This is another function implementation than the one above
Ask.TGT(user, domain, certificate, password, encType, outfile, ptt, dc, luid, true, opsec, verifyCerts, servicekey, getCredentials, proxyUrl, service, changepw);

return;
}
Expand Down
25 changes: 20 additions & 5 deletions Rubeus/lib/Ask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,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);
return InnerTGT(userHashASREQ, etype, outfile, ptt, domainController, luid, describe, true, opsec, servicekey, false, proxyUrl);
return InnerTGT(userHashASREQ, etype, outfile, ptt, domainController, luid, describe, true, servicekey, false, proxyUrl);
}
}
catch (KerberosErrorException ex)
Expand Down Expand Up @@ -186,7 +186,22 @@ public static X509Certificate2 FindCertificate(string certificate, string storeP
}
}

public static byte[] TGT(string userName, string domain, string certFile, string certPass, Interop.KERB_ETYPE etype, string outfile, bool ptt, string domainController = "", LUID luid = new LUID(), bool describe = false, bool verifyCerts = false, string servicekey = "", bool getCredentials = false, string proxyUrl = null, string service = null, bool changepw = false) {
/// <summary>
/// Use this overload to request a TGT via PKINIT and a X509 certificate
/// </summary>
public static byte[] TGT(string userName, string domain, string certFile, string certPass, Interop.KERB_ETYPE etype, string outfile, bool ptt, string domainController = "", LUID luid = new LUID(), bool describe = false, bool opsec = false, bool verifyCerts = false, string servicekey = "", bool getCredentials = false, string proxyUrl = null, string service = null, bool changepw = false)
{
// send request without Pre-Auth to emulate genuine traffic
bool preauth = false;
if (opsec)
{
try
{
preauth = NoPreAuthTGT(userName, domain, "", etype, domainController, outfile, ptt, luid, describe, true, proxyUrl);
}
catch (KerberosErrorException) { }
}

try {
X509Certificate2 cert = FindCertificate(certFile, certPass);

Expand All @@ -206,8 +221,8 @@ public static X509Certificate2 FindCertificate(string certificate, string storeP
Console.WriteLine("[*] Using PKINIT with etype {0} and subject: {1} ", etype, cert.Subject);
Console.WriteLine("[*] Building AS-REQ (w/ PKINIT preauth) for: '{0}\\{1}'", domain, userName);

AS_REQ pkinitASREQ = AS_REQ.NewASReq(userName, domain, cert, agreement, etype, verifyCerts, service, changepw);
return InnerTGT(pkinitASREQ, etype, outfile, ptt, domainController, luid, describe, true, false, servicekey, getCredentials, proxyUrl);
AS_REQ pkinitASREQ = AS_REQ.NewASReq(userName, domain, cert, agreement, etype, opsec, verifyCerts, service, changepw);
return InnerTGT(pkinitASREQ, etype, outfile, ptt, domainController, luid, describe, true, servicekey, getCredentials, proxyUrl);

} catch (KerberosErrorException ex) {
KRB_ERROR error = ex.krbError;
Expand Down Expand Up @@ -248,7 +263,7 @@ public static int GetKeySize(Interop.KERB_ETYPE etype) {
}
}

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, bool opsec = false, string serviceKey = "", bool getCredentials = false, string proxyUrl = 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, string serviceKey = "", bool getCredentials = false, string proxyUrl = null)
{
if ((ulong)luid != 0) {
Console.WriteLine("[*] Target LUID : {0}", (ulong)luid);
Expand Down
81 changes: 34 additions & 47 deletions Rubeus/lib/krb_structures/AS_REQ.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,27 +62,10 @@ public static AS_REQ NewASReq(string userName, string domain, Interop.KERB_ETYPE
req.req_body.sname.name_string.Add(domain);
}

// try to build a realistic request
if (opsec)
{
string hostName = Dns.GetHostName();
List<HostAddress> addresses = new List<HostAddress>();
addresses.Add(new HostAddress(hostName));
req.req_body.addresses = addresses;
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);
req.req_body.etypes.Add(Interop.KERB_ETYPE.rc4_hmac_exp);
req.req_body.etypes.Add(Interop.KERB_ETYPE.old_exp);
req.req_body.etypes.Add(Interop.KERB_ETYPE.des_cbc_md5);

}
else
{
// add in our encryption type
ApplyOpsecChanges(req.req_body);
else // add in our encryption type
req.req_body.etypes.Add(etype);
}

return req;
}
Expand Down Expand Up @@ -134,38 +117,21 @@ public static AS_REQ NewASReq(string userName, string domain, string keyString,
req.req_body.sname.name_string.Add("changepw");
}

// try to build a realistic request
if (opsec)
{
string hostName = Dns.GetHostName();
List<HostAddress> addresses = new List<HostAddress>();
addresses.Add(new HostAddress(hostName));
req.req_body.addresses = addresses;
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);
req.req_body.etypes.Add(Interop.KERB_ETYPE.rc4_hmac_exp);
req.req_body.etypes.Add(Interop.KERB_ETYPE.old_exp);
req.req_body.etypes.Add(Interop.KERB_ETYPE.des_cbc_md5);
}
else
{
// add in our encryption type
ApplyOpsecChanges(req.req_body);
else // add in our encryption type
req.req_body.etypes.Add(etype);
}

return req;
}

//TODO: Insert DHKeyPair parameter also.
public static AS_REQ NewASReq(string userName, string domain, X509Certificate2 cert, KDCKeyAgreement agreement, Interop.KERB_ETYPE etype, bool verifyCerts = false, string service = null, bool changepw = false) {

public static AS_REQ NewASReq(string userName, string domain, X509Certificate2 cert, KDCKeyAgreement agreement, Interop.KERB_ETYPE etype, bool opsec = false, bool verifyCerts = false, string service = null, bool changepw = 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

// set pre-auth
AS_REQ req = new AS_REQ(cert, agreement, verifyCerts);
AS_REQ req = new AS_REQ(cert, agreement, opsec, verifyCerts);

// req.padata.Add()

Expand Down Expand Up @@ -209,8 +175,10 @@ public static AS_REQ NewASReq(string userName, string domain, X509Certificate2 c
req.req_body.sname.name_string.Add("changepw");
}

// add in our encryption type
req.req_body.etypes.Add(etype);
if (opsec)
ApplyOpsecChanges(req.req_body);
else // add in our encryption type
req.req_body.etypes.Add(etype);

return req;
}
Expand Down Expand Up @@ -246,21 +214,21 @@ public AS_REQ(string keyString, Interop.KERB_ETYPE etype, bool opsec = false, bo
this.keyString = keyString;
}

public AS_REQ(X509Certificate2 pkCert, KDCKeyAgreement agreement, bool verifyCerts = false) {

public AS_REQ(X509Certificate2 pkCert, KDCKeyAgreement agreement, bool opsec = false, bool verifyCerts = false) {
// default, for creation
pvno = 5;
msg_type = 10;
msg_type = (long)Interop.KERB_MESSAGE_TYPE.AS_REQ;

padata = new List<PA_DATA>();

req_body = new KDCReqBody();
req_body = new KDCReqBody(true, opsec);

// add the include-pac == true
padata.Add(new PA_DATA());

// add the encrypted timestamp
padata.Add(new PA_DATA(pkCert, agreement, req_body, verifyCerts));
padata.Add(new PA_DATA(pkCert, agreement, req_body, verifyCerts));

}

public AS_REQ(byte[] data)
Expand Down Expand Up @@ -313,6 +281,25 @@ public AS_REQ(byte[] data)
}
}
}
/// <summary>
/// Applies opsec changes in-place to an existing, initialized KDCReqBody including
/// common etypes, the optional addresses field and the "canonicalize" kdc_option.
/// </summary>
/// <param name="req_body"></param>
private static void ApplyOpsecChanges(KDCReqBody req_body)
{
string hostName = Dns.GetHostName();
List<HostAddress> addresses = new List<HostAddress>();
addresses.Add(new HostAddress(hostName));
req_body.addresses = addresses;
req_body.kdcOptions = req_body.kdcOptions | Interop.KdcOptions.CANONICALIZE;
req_body.etypes.Add(Interop.KERB_ETYPE.aes256_cts_hmac_sha1);
req_body.etypes.Add(Interop.KERB_ETYPE.aes128_cts_hmac_sha1);
req_body.etypes.Add(Interop.KERB_ETYPE.rc4_hmac);
req_body.etypes.Add(Interop.KERB_ETYPE.rc4_hmac_exp);
req_body.etypes.Add(Interop.KERB_ETYPE.old_exp);
req_body.etypes.Add(Interop.KERB_ETYPE.des_cbc_md5);
}

public AsnElt Encode()
{
Expand Down