Skip to content

Commit

Permalink
Merge pull request #21 from odedshimon/kerberos-tickets
Browse files Browse the repository at this point in the history
Kerberos tickets
  • Loading branch information
odedshimon authored Jul 26, 2020
2 parents 9eaf3ce + ef29769 commit 421c813
Show file tree
Hide file tree
Showing 22 changed files with 560 additions and 18 deletions.
13 changes: 13 additions & 0 deletions BruteShark/BruteForce/Hashes/KerberosTgsRepHash.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace BruteForce
{
public class KerberosTgsRepHash : Hash
{
public string Realm { get; set; }
public string Username { get; set; }
public string ServiceName { get; set; }
}
}
22 changes: 22 additions & 0 deletions BruteShark/BruteForce/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public static string ConvertToHashcatFormat(Hash hash)
{
res = ConvertToHashcatFormat(hash as KerberosHash);
}
else if (hash is KerberosTgsRepHash)
{
res = ConvertToHashcatFormat(hash as KerberosTgsRepHash);
}
else
{
throw new Exception("Hash type not supported");
Expand All @@ -32,6 +36,24 @@ public static string ConvertToHashcatFormat(Hash hash)
return res;
}


public static string ConvertToHashcatFormat(KerberosTgsRepHash kerberosHash)
{
// Acording to Hashcat examples page this is the format:
// $krb5tgs$23$*user$realm$test/spn*$63386d22d359fe42230300d56852c9eb$891ad31d09ab89c6b3b8c5e5de6....
// return string.Format("$krb5tgs$23${0}${1}${2}${3}${4}",
// kerberosHash.Username,
// kerberosHash.Realm,
// kerberosHash.ServiceName,
// kerberosHash.HashedData.Substring(0, 32),
// kerberosHash.HashedData.Substring(32));

// But at other places i saw this format, this is worked great with Hashcat 6.0.
return string.Format("$krb5tgs$23${0}${1}",
kerberosHash.HashedData.Substring(0, 32),
kerberosHash.HashedData.Substring(32));
}

public static string ConvertToHashcatFormat(KerberosHash kerberosHash)
{
return string.Format("$krb5pa$23${0}${1}$dummy${2}",
Expand Down
29 changes: 22 additions & 7 deletions BruteShark/BruteSharkDesktop/Casting.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using BruteForce;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
Expand Down Expand Up @@ -81,15 +82,19 @@ public static BruteForce.Hash CastAnalyzerHashToBruteForceHash(PcapAnalyzer.Netw
}
else if (hash is PcapAnalyzer.CramMd5Hash)
{
res = CastAnalyzerrHashToBruteForceHash(hash as PcapAnalyzer.CramMd5Hash);
res = CastAnalyzerHashToBruteForceHash(hash as PcapAnalyzer.CramMd5Hash);
}
else if (hash is PcapAnalyzer.NtlmHash)
{
res = CastAnalyzerrHashToBruteForceHash(hash as PcapAnalyzer.NtlmHash);
res = CastAnalyzerHashToBruteForceHash(hash as PcapAnalyzer.NtlmHash);
}
else if (hash is PcapAnalyzer.KerberosHash)
{
res = CastAnalyzerrHashToBruteForceHash(hash as PcapAnalyzer.KerberosHash);
res = CastAnalyzerHashToBruteForceHash(hash as PcapAnalyzer.KerberosHash);
}
else if (hash is PcapAnalyzer.KerberosTgsRepHash)
{
res = CastAnalyzerHashToBruteForceHash(hash as PcapAnalyzer.KerberosTgsRepHash);
}
else
{
Expand All @@ -99,6 +104,16 @@ public static BruteForce.Hash CastAnalyzerHashToBruteForceHash(PcapAnalyzer.Netw
return res;
}

private static Hash CastAnalyzerHashToBruteForceHash(PcapAnalyzer.KerberosTgsRepHash kerberosTgsRepHash)
{
return new BruteForce.KerberosTgsRepHash()
{
ServiceName = kerberosTgsRepHash.ServiceName,
Realm = kerberosTgsRepHash.Realm,
HashedData = kerberosTgsRepHash.Hash,
Username = kerberosTgsRepHash.Username
};
}

public static BruteForce.Hash CastAnalyzerHashToBruteForceHash(PcapAnalyzer.HttpDigestHash httpDigestHash)
{
Expand All @@ -117,7 +132,7 @@ public static BruteForce.Hash CastAnalyzerHashToBruteForceHash(PcapAnalyzer.Http
};
}

public static BruteForce.Hash CastAnalyzerrHashToBruteForceHash(PcapAnalyzer.NtlmHash ntlmHash)
public static BruteForce.Hash CastAnalyzerHashToBruteForceHash(PcapAnalyzer.NtlmHash ntlmHash)
{
return new BruteForce.NtlmHash()
{
Expand All @@ -130,7 +145,7 @@ public static BruteForce.Hash CastAnalyzerrHashToBruteForceHash(PcapAnalyzer.Ntl
};
}

public static BruteForce.Hash CastAnalyzerrHashToBruteForceHash(PcapAnalyzer.KerberosHash kerberosHash)
public static BruteForce.Hash CastAnalyzerHashToBruteForceHash(PcapAnalyzer.KerberosHash kerberosHash)
{
return new BruteForce.KerberosHash()
{
Expand All @@ -140,7 +155,7 @@ public static BruteForce.Hash CastAnalyzerrHashToBruteForceHash(PcapAnalyzer.Ker
};
}

public static BruteForce.Hash CastAnalyzerrHashToBruteForceHash(PcapAnalyzer.CramMd5Hash cramMd5Hash)
public static BruteForce.Hash CastAnalyzerHashToBruteForceHash(PcapAnalyzer.CramMd5Hash cramMd5Hash)
{
return new BruteForce.CramMd5Hash()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public class FtpPasswordParser : IPasswordParser
{
private Regex _ftpSuccessfullLoginRegex = new Regex(@"220(.*)\r\nUSER\s(?<Username>.*)\r\n331(.*)\r\nPASS\s(?<Password>.*)\r\n");

public NetworkLayerObject Parse(UdpPacket udpPacket) => null;

public NetworkLayerObject Parse(TcpPacket tcpPacket) => null;

public NetworkLayerObject Parse(TcpSession tcpSession)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ public class HttpBasicPasswordParser : IPasswordParser
{
private Regex _httpBasicAuthenticationRegex = new Regex(@"(.*)HTTP([\s\S]*)(Authorization: Basic )(?<Credentials>.*)");


public NetworkLayerObject Parse(UdpPacket udpPacket) => null;

public NetworkLayerObject Parse(TcpPacket tcpPacket)
{
NetworkPassword credential = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ class HttpDigestHashParser : IPasswordParser
private const string _httpDigestClientHeader = "Authorization: Digest";
private Regex _clientHeaderRegex = new Regex($@"{_httpDigestClientHeader} (?<HeaderData>.*)\r\n");


public NetworkLayerObject Parse(UdpPacket udpPacket) => null;

public NetworkLayerObject Parse(TcpPacket tcpPacket)
{
HttpDigestHash hash = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class ImapPasswordParser : IPasswordParser
private Regex _imapAuthenticateLoginRegex = new Regex($@"({ImapCommandTag})?((?i)AUTHENTICATE PLAIN)((\r\n(\+ )\r\n)| )(?<CredentialsBase64>.*)(\r\n)({ImapCommandTag})?OK");
private Regex _imapCramMd5Regex = new Regex($@"({ImapCommandTag})?((?i)AUTHENTICATE CRAM-MD5)\r\n\+ (?<Challenge>.*)\r\n(?<Response>.*)\r\n({ImapCommandTag})?OK");

public NetworkLayerObject Parse(UdpPacket udpPacket) => null;

public NetworkLayerObject Parse(TcpPacket tcpPacket) => null;

public NetworkLayerObject Parse(TcpSession tcpSession)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using Asn1;
using System;

namespace PcapAnalyzer
{
// EncryptedData::= SEQUENCE {
// etype[0] ENCTYPE, -- EncryptionType
// kvno[1] krb5uint32 OPTIONAL,
// cipher[2] OCTET STRING -- ciphertext
// }
//
// ENCTYPE ::= INTEGER {
// KRB5_ENCTYPE_NULL(0),
// KRB5_ENCTYPE_DES_CBC_CRC(1),
// KRB5_ENCTYPE_DES_CBC_MD4(2),
// KRB5_ENCTYPE_DES_CBC_MD5(3),
// KRB5_ENCTYPE_DES3_CBC_MD5(5),
// KRB5_ENCTYPE_OLD_DES3_CBC_SHA1(7),
// KRB5_ENCTYPE_SIGN_DSA_GENERATE(8),
// KRB5_ENCTYPE_ENCRYPT_RSA_PRIV(9),
// KRB5_ENCTYPE_ENCRYPT_RSA_PUB(10),
// KRB5_ENCTYPE_DES3_CBC_SHA1(16), -- with key derivation
// KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96(17),
// KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96(18),
// KRB5_ENCTYPE_ARCFOUR_HMAC_MD5(23),
// KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56(24),
// KRB5_ENCTYPE_ENCTYPE_PK_CROSS(48),
// - - some "old" windows types
// KRB5_ENCTYPE_ARCFOUR_MD4(-128),
// KRB5_ENCTYPE_ARCFOUR_HMAC_OLD(-133),
// KRB5_ENCTYPE_ARCFOUR_HMAC_OLD_EXP(-135),
// - - these are for Heimdal internal use
// KRB5_ENCTYPE_DES_CBC_NONE(-0x1000),
// KRB5_ENCTYPE_DES3_CBC_NONE(-0x1001),
// KRB5_ENCTYPE_DES_CFB64_NONE(-0x1002),
// KRB5_ENCTYPE_DES_PCBC_NONE(-0x1003),
// KRB5_ENCTYPE_DIGEST_MD5_NONE(-0x1004), -- private use, [email protected]
// KRB5_ENCTYPE_CRAM_MD5_NONE(-0x1005) -- private use, [email protected]
// }
public class KerberosEncrypedData
{
public uint Kvno { get; private set; }
public int Etype { get; private set; }
public byte[] Cipher { get; private set; }

public KerberosEncrypedData(AsnElt encrypedData)
{
foreach (AsnElt s in encrypedData.Sub)
{
switch (s.TagValue)
{
case 0:
this.Etype = Convert.ToInt32(s.Sub[0].GetInteger());
break;
case 1:
this.Kvno = Convert.ToUInt32(s.Sub[0].GetInteger());
break;
case 2:
this.Cipher = s.Sub[0].GetOctetString();
break;
default:
break;
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Text;
using Asn1;

namespace PcapAnalyzer
{
// All objects definitions are from: http://web.mit.edu/freebsd/head/crypto/heimdal/lib/asn1/krb5.asn1
public static class KerberosPacketParser
{
// 13 - Get service ticket (Response to KRB_TGS_REQ request)
public enum MessageType : byte
{
krb_tgs_rep = 13,
}

public static object GetKerberosPacket(byte[] kerberosBuffer)
{
object result = null;
byte[] asn_buffer = AsnIO.FindBER(kerberosBuffer);

if (asn_buffer != null)
{
AsnElt asn_object = AsnElt.Decode(asn_buffer);

try
{
// Get the application number
switch (asn_object.TagValue)
{
case (int)MessageType.krb_tgs_rep:
result = new KerberosTgsRepPacket(kdc_rep: asn_object.Sub[0].Sub);
break;
}
}
catch
{
// TODO: log
}
}

return result;
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using Asn1;
using System;
using System.Collections.Generic;
using System.Text;

namespace PcapAnalyzer
{
// PrincipalName::= SEQUENCE {
// name-type[0] NAME-TYPE,
// name-string[1] SEQUENCE OF GeneralString
// }
//
// NAME-TYPE::= INTEGER {
// KRB5_NT_UNKNOWN(0), -- Name type not known
//
// KRB5_NT_PRINCIPAL(1), -- Just the name of the principal as in
// KRB5_NT_SRV_INST(2), -- Service and other unique instance(krbtgt)
// KRB5_NT_SRV_HST(3), -- Service with host name as instance
// KRB5_NT_SRV_XHST(4), -- Service with host as remaining components
// KRB5_NT_UID(5), -- Unique ID
// KRB5_NT_X500_PRINCIPAL(6), -- PKINIT
// KRB5_NT_SMTP_NAME(7), -- Name in form of SMTP email name
// KRB5_NT_ENTERPRISE_PRINCIPAL(10), -- Windows 2000 UPN
// KRB5_NT_WELLKNOWN(11), -- Wellknown
// KRB5_NT_ENT_PRINCIPAL_AND_ID(-130), -- Windows 2000 UPN and SID
// KRB5_NT_MS_PRINCIPAL(-128), -- NT 4 style name
// KRB5_NT_MS_PRINCIPAL_AND_ID(-129), -- NT style name and SID
// KRB5_NT_NTLM(-1200) -- NTLM name, realm is domain
// }
public class KerberosPrincipalName
{
const int KRB5_NT_PRINCIPAL = 1;
const int KRB5_NT_SRV_INST = 2;

public int NameType { get; private set; }
public List<string> NameString { get; private set; }
public string Name
{
get
{
if (this.NameType == KRB5_NT_PRINCIPAL && this.NameString.Count >= 1)
{
return this.NameString[0];
}
else if (this.NameType == KRB5_NT_SRV_INST && this.NameString.Count >= 2)
{
return this.NameString[0] + "/" + this.NameString[1];
}

return null;
}
}

public KerberosPrincipalName(AsnElt principalNameData)
{
this.NameString = new List<string>();

foreach (AsnElt s in principalNameData.Sub)
{
switch (s.TagValue)
{
case 0:
this.NameType = Convert.ToInt32(s.Sub[0].GetInteger());
break;
case 1:
foreach (AsnElt i in s.Sub[0].Sub)
{
this.NameString.Add(Encoding.ASCII.GetString(i.GetOctetString()));
}
break;
}
}
}
}
}
Loading

0 comments on commit 421c813

Please sign in to comment.