commit
7f9d25ea8c
|
@ -12,6 +12,7 @@ namespace Rubeus.Commands
|
|||
{
|
||||
string user = "";
|
||||
string domain = "";
|
||||
string password = "";
|
||||
string hash = "";
|
||||
string dc = "";
|
||||
bool ptt = false;
|
||||
|
@ -39,6 +40,28 @@ namespace Rubeus.Commands
|
|||
{
|
||||
dc = arguments["/dc"];
|
||||
}
|
||||
if (arguments.ContainsKey("/password"))
|
||||
{
|
||||
password = arguments["/password"];
|
||||
if (arguments.ContainsKey("/enctype") && arguments["/enctype"].ToUpper().Equals("AES256"))
|
||||
{
|
||||
encType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
|
||||
|
||||
// compute AES key from pwd
|
||||
byte[] password_bytes = System.Text.Encoding.UTF8.GetBytes(password);
|
||||
byte[] salt = System.Text.Encoding.UTF8.GetBytes(domain.ToUpper() + user);
|
||||
|
||||
byte[] aes256_key = Crypto.ComputeAES256KerberosKey(password_bytes, salt);
|
||||
hash = System.BitConverter.ToString(aes256_key).Replace("-", "");
|
||||
}
|
||||
else // default is RC4
|
||||
{
|
||||
// compute NTLM from pwd
|
||||
encType = Interop.KERB_ETYPE.rc4_hmac;
|
||||
byte[] ntlm = Crypto.ComputeRC4KerberosKey(password); // a.k.a NTLM
|
||||
hash = System.BitConverter.ToString(ntlm).Replace("-", "");
|
||||
}
|
||||
}
|
||||
if (arguments.ContainsKey("/rc4"))
|
||||
{
|
||||
hash = arguments["/rc4"];
|
||||
|
@ -104,7 +127,7 @@ namespace Rubeus.Commands
|
|||
}
|
||||
if (String.IsNullOrEmpty(hash))
|
||||
{
|
||||
Console.WriteLine("\r\n[X] You must supply a /rc4 or /aes256 hash!\r\n");
|
||||
Console.WriteLine("\r\n[X] You must supply a /password or /rc4 hash or /aes256 hash!\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,11 +19,11 @@ namespace Rubeus.Domain
|
|||
{
|
||||
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 password/hash, optionally applying to the current logon session or a specific LUID:");
|
||||
Console.WriteLine(" Rubeus.exe asktgt /user:USER </password:PASSWORD [/enctype:RC4|AES256] | /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 TGT based on a user password/hash, start a /netonly process, and to apply the ticket to the new process/logon session:");
|
||||
Console.WriteLine(" Rubeus.exe asktgt /user:USER </password:PASSWORD [/enctype:RC4|AES256] |/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]");
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using Asn1;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.ComponentModel;
|
||||
|
@ -9,6 +8,81 @@ namespace Rubeus
|
|||
{
|
||||
public class Crypto
|
||||
{
|
||||
// Adapted from Kevin-Robertson powershell Get-KerberosAESKey: https://gist.github.com/Kevin-Robertson/9e0f8bfdbf4c1e694e6ff4197f0a4372
|
||||
// References:
|
||||
// * [MS-KILE] open spec' https://msdn.microsoft.com/library/cc233855.aspx?f=255&MSPPError=-2147217396
|
||||
// * RFC regarding AES in Kerberos https://www.rfc-editor.org/rfc/pdfrfc/rfc3962.txt.pdf
|
||||
public static byte[] ComputeAES256KerberosKey(byte[] password, byte[] salt)
|
||||
{
|
||||
byte[] AES256_CONSTANT = { 0x6B, 0x65, 0x72, 0x62, 0x65, 0x72, 0x6F, 0x73, 0x7B, 0x9B, 0x5B, 0x2B, 0x93, 0x13, 0x2B, 0x93, 0x5C, 0x9B, 0xDC, 0xDA, 0xD9, 0x5C, 0x98, 0x99, 0xC4, 0xCA, 0xE4, 0xDE, 0xE6, 0xD6, 0xCA, 0xE4 };
|
||||
const int rounds = 4096;
|
||||
var pbkdf2 = new System.Security.Cryptography.Rfc2898DeriveBytes(password, salt, rounds);
|
||||
byte[] pbkdf2_aes256_key = pbkdf2.GetBytes(32);
|
||||
|
||||
string pbkdf2_aes256_key_string = System.BitConverter.ToString(pbkdf2_aes256_key).Replace("-", "");
|
||||
|
||||
var aes = new System.Security.Cryptography.AesManaged();
|
||||
aes.Mode = System.Security.Cryptography.CipherMode.CBC;
|
||||
aes.Padding = System.Security.Cryptography.PaddingMode.None;
|
||||
aes.KeySize = 256;
|
||||
aes.Key = pbkdf2_aes256_key;
|
||||
aes.IV = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
var encryptor = aes.CreateEncryptor();
|
||||
byte[] aes256_key_part_1 = encryptor.TransformFinalBlock(AES256_CONSTANT, 0, AES256_CONSTANT.Length);
|
||||
byte[] aes256_key_part_2 = encryptor.TransformFinalBlock(aes256_key_part_1, 0, aes256_key_part_1.Length);
|
||||
byte[] aes256_key = aes256_key_part_1.Take(16).Concat(aes256_key_part_2.Take(16)).ToArray();
|
||||
return aes256_key;
|
||||
}
|
||||
|
||||
public static byte[] ComputeRC4KerberosKey(string password)
|
||||
{
|
||||
// RC4 Kerberos Key is NTLM
|
||||
byte[] password_byte = System.Text.Encoding.Unicode.GetBytes(password);
|
||||
return ComputeMD4(password_byte);
|
||||
}
|
||||
|
||||
// source: https://rosettacode.org/wiki/MD4#C.23
|
||||
private static byte[] ComputeMD4(byte[] plain)
|
||||
{
|
||||
// get padded uints from bytes
|
||||
List<byte> bytes = plain.ToList();
|
||||
uint bitCount = (uint)(bytes.Count) * 8;
|
||||
bytes.Add(128);
|
||||
while (bytes.Count % 64 != 56) bytes.Add(0);
|
||||
var uints = new List<uint>();
|
||||
for (int i = 0; i + 3 < bytes.Count; i += 4)
|
||||
uints.Add(bytes[i] | (uint)bytes[i + 1] << 8 | (uint)bytes[i + 2] << 16 | (uint)bytes[i + 3] << 24);
|
||||
uints.Add(bitCount);
|
||||
uints.Add(0);
|
||||
|
||||
// run rounds
|
||||
uint a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476;
|
||||
Func<uint, uint, uint> rol = (x, y) => x << (int)y | x >> 32 - (int)y;
|
||||
for (int q = 0; q + 15 < uints.Count; q += 16)
|
||||
{
|
||||
var chunk = uints.GetRange(q, 16);
|
||||
uint aa = a, bb = b, cc = c, dd = d;
|
||||
Action<Func<uint, uint, uint, uint>, uint[]> round = (f, y) =>
|
||||
{
|
||||
foreach (uint i in new[] { y[0], y[1], y[2], y[3] })
|
||||
{
|
||||
a = rol(a + f(b, c, d) + chunk[(int)(i + y[4])] + y[12], y[8]);
|
||||
d = rol(d + f(a, b, c) + chunk[(int)(i + y[5])] + y[12], y[9]);
|
||||
c = rol(c + f(d, a, b) + chunk[(int)(i + y[6])] + y[12], y[10]);
|
||||
b = rol(b + f(c, d, a) + chunk[(int)(i + y[7])] + y[12], y[11]);
|
||||
}
|
||||
};
|
||||
round((x, y, z) => (x & y) | (~x & z), new uint[] { 0, 4, 8, 12, 0, 1, 2, 3, 3, 7, 11, 19, 0 });
|
||||
round((x, y, z) => (x & y) | (x & z) | (y & z), new uint[] { 0, 1, 2, 3, 0, 4, 8, 12, 3, 5, 9, 13, 0x5a827999 });
|
||||
round((x, y, z) => x ^ y ^ z, new uint[] { 0, 2, 1, 3, 0, 8, 4, 12, 3, 9, 11, 15, 0x6ed9eba1 });
|
||||
a += aa; b += bb; c += cc; d += dd;
|
||||
}
|
||||
|
||||
// return hex encoded string
|
||||
byte[] outBytes = new[] { a, b, c, d }.SelectMany(BitConverter.GetBytes).ToArray();
|
||||
return outBytes;
|
||||
}
|
||||
|
||||
// Adapted from Vincent LE TOUX' "MakeMeEnterpriseAdmin"
|
||||
public static byte[] KerberosChecksum(byte[] key, byte[] data)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue