<# This modules is a modified and stripped down version of CredMan.ps1, written by "JimmyJoeBob Alooba". A link to the original script can be found below. BeetleChunks has modified and stripped this script to work in Powershell Empire. Original Script: https://gallery.technet.microsoft.com/scriptcenter/PowerShell-Credentials-d44c3cde #> [String] $PsCredmanUtils = @" using System; using System.Runtime.InteropServices; namespace PsUtils { public class CredMan { #region Imports // DllImport derives from System.Runtime.InteropServices [DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredDeleteW", CharSet = CharSet.Unicode)] private static extern bool CredDeleteW([In] string target, [In] CRED_TYPE type, [In] int reservedFlag); [DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredEnumerateW", CharSet = CharSet.Unicode)] private static extern bool CredEnumerateW([In] string Filter, [In] int Flags, out int Count, out IntPtr CredentialPtr); [DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredFree")] private static extern void CredFree([In] IntPtr cred); [DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredReadW", CharSet = CharSet.Unicode)] private static extern bool CredReadW([In] string target, [In] CRED_TYPE type, [In] int reservedFlag, out IntPtr CredentialPtr); [DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredWriteW", CharSet = CharSet.Unicode)] private static extern bool CredWriteW([In] ref Credential userCredential, [In] UInt32 flags); #endregion #region Fields public enum CRED_FLAGS : uint { NONE = 0x0, PROMPT_NOW = 0x2, USERNAME_TARGET = 0x4 } public enum CRED_ERRORS : uint { ERROR_SUCCESS = 0x0, ERROR_INVALID_PARAMETER = 0x80070057, ERROR_INVALID_FLAGS = 0x800703EC, ERROR_NOT_FOUND = 0x80070490, ERROR_NO_SUCH_LOGON_SESSION = 0x80070520, ERROR_BAD_USERNAME = 0x8007089A } public enum CRED_PERSIST : uint { SESSION = 1, LOCAL_MACHINE = 2, ENTERPRISE = 3 } public enum CRED_TYPE : uint { GENERIC = 1, DOMAIN_PASSWORD = 2, DOMAIN_CERTIFICATE = 3, DOMAIN_VISIBLE_PASSWORD = 4, GENERIC_CERTIFICATE = 5, DOMAIN_EXTENDED = 6, MAXIMUM = 7, // Maximum supported cred type MAXIMUM_EX = (MAXIMUM + 1000), // Allow new applications to run on old OSes } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct Credential { public CRED_FLAGS Flags; public CRED_TYPE Type; public string TargetName; public string Comment; public DateTime LastWritten; public UInt32 CredentialBlobSize; public string CredentialBlob; public CRED_PERSIST Persist; public UInt32 AttributeCount; public IntPtr Attributes; public string TargetAlias; public string UserName; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct NativeCredential { public CRED_FLAGS Flags; public CRED_TYPE Type; public IntPtr TargetName; public IntPtr Comment; public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten; public UInt32 CredentialBlobSize; public IntPtr CredentialBlob; public UInt32 Persist; public UInt32 AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName; } #endregion #region Child Class private class CriticalCredentialHandle : Microsoft.Win32.SafeHandles.CriticalHandleZeroOrMinusOneIsInvalid { public CriticalCredentialHandle(IntPtr preexistingHandle) { SetHandle(preexistingHandle); } private Credential XlateNativeCred(IntPtr pCred) { NativeCredential ncred = (NativeCredential)Marshal.PtrToStructure(pCred, typeof(NativeCredential)); Credential cred = new Credential(); cred.Type = ncred.Type; cred.Flags = ncred.Flags; cred.Persist = (CRED_PERSIST)ncred.Persist; long LastWritten = ncred.LastWritten.dwHighDateTime; LastWritten = (LastWritten << 32) + ncred.LastWritten.dwLowDateTime; cred.LastWritten = DateTime.FromFileTime(LastWritten); cred.UserName = Marshal.PtrToStringUni(ncred.UserName); cred.TargetName = Marshal.PtrToStringUni(ncred.TargetName); cred.TargetAlias = Marshal.PtrToStringUni(ncred.TargetAlias); cred.Comment = Marshal.PtrToStringUni(ncred.Comment); cred.CredentialBlobSize = ncred.CredentialBlobSize; if (0 < ncred.CredentialBlobSize) { cred.CredentialBlob = Marshal.PtrToStringUni(ncred.CredentialBlob, (int)ncred.CredentialBlobSize / 2); } return cred; } public Credential GetCredential() { if (IsInvalid) { throw new InvalidOperationException("Invalid CriticalHandle!"); } Credential cred = XlateNativeCred(handle); return cred; } public Credential[] GetCredentials(int count) { if (IsInvalid) { throw new InvalidOperationException("Invalid CriticalHandle!"); } Credential[] Credentials = new Credential[count]; IntPtr pTemp = IntPtr.Zero; for (int inx = 0; inx < count; inx++) { pTemp = Marshal.ReadIntPtr(handle, inx * IntPtr.Size); Credential cred = XlateNativeCred(pTemp); Credentials[inx] = cred; } return Credentials; } override protected bool ReleaseHandle() { if (IsInvalid) { return false; } CredFree(handle); SetHandleAsInvalid(); return true; } } #endregion #region Custom API public static int CredDelete(string target, CRED_TYPE type) { if (!CredDeleteW(target, type, 0)) { return Marshal.GetHRForLastWin32Error(); } return 0; } public static int CredEnum(string Filter, out Credential[] Credentials) { int count = 0; int Flags = 0x0; if (string.IsNullOrEmpty(Filter) || "*" == Filter) { Filter = null; if (6 <= Environment.OSVersion.Version.Major) { Flags = 0x1; //CRED_ENUMERATE_ALL_CREDENTIALS; only valid is OS >= Vista } } IntPtr pCredentials = IntPtr.Zero; if (!CredEnumerateW(Filter, Flags, out count, out pCredentials)) { Credentials = null; return Marshal.GetHRForLastWin32Error(); } CriticalCredentialHandle CredHandle = new CriticalCredentialHandle(pCredentials); Credentials = CredHandle.GetCredentials(count); return 0; } public static int CredRead(string target, CRED_TYPE type, out Credential Credential) { IntPtr pCredential = IntPtr.Zero; Credential = new Credential(); if (!CredReadW(target, type, 0, out pCredential)) { return Marshal.GetHRForLastWin32Error(); } CriticalCredentialHandle CredHandle = new CriticalCredentialHandle(pCredential); Credential = CredHandle.GetCredential(); return 0; } public static int CredWrite(Credential userCredential) { if (!CredWriteW(ref userCredential, 0)) { return Marshal.GetHRForLastWin32Error(); } return 0; } #endregion private static int AddCred() { Credential Cred = new Credential(); string Password = "Password"; Cred.Flags = 0; Cred.Type = CRED_TYPE.GENERIC; Cred.TargetName = "Target"; Cred.UserName = "UserName"; Cred.AttributeCount = 0; Cred.Persist = CRED_PERSIST.ENTERPRISE; Cred.CredentialBlobSize = (uint)Password.Length; Cred.CredentialBlob = Password; Cred.Comment = "Comment"; return CredWrite(Cred); } private static bool CheckError(string TestName, CRED_ERRORS Rtn) { switch(Rtn) { case CRED_ERRORS.ERROR_SUCCESS: Console.WriteLine(string.Format("'{0}' worked", TestName)); return true; case CRED_ERRORS.ERROR_INVALID_FLAGS: case CRED_ERRORS.ERROR_INVALID_PARAMETER: case CRED_ERRORS.ERROR_NO_SUCH_LOGON_SESSION: case CRED_ERRORS.ERROR_NOT_FOUND: case CRED_ERRORS.ERROR_BAD_USERNAME: Console.WriteLine(string.Format("'{0}' failed; {1}.", TestName, Rtn)); break; default: Console.WriteLine(string.Format("'{0}' failed; 0x{1}.", TestName, Rtn.ToString("X"))); break; } return false; } /* * Note: the Main() function is primarily for debugging and testing in a Visual * Studio session. Although it will work from PowerShell, it's not very useful. */ public static void Main() { Credential[] Creds = null; Credential Cred = new Credential(); int Rtn = 0; Console.WriteLine("Testing CredWrite()"); Rtn = AddCred(); if (!CheckError("CredWrite", (CRED_ERRORS)Rtn)) { return; } Console.WriteLine("Testing CredEnum()"); Rtn = CredEnum(null, out Creds); if (!CheckError("CredEnum", (CRED_ERRORS)Rtn)) { return; } Console.WriteLine("Testing CredRead()"); Rtn = CredRead("Target", CRED_TYPE.GENERIC, out Cred); if (!CheckError("CredRead", (CRED_ERRORS)Rtn)) { return; } Console.WriteLine("Testing CredDelete()"); Rtn = CredDelete("Target", CRED_TYPE.GENERIC); if (!CheckError("CredDelete", (CRED_ERRORS)Rtn)) { return; } Console.WriteLine("Testing CredRead() again"); Rtn = CredRead("Target", CRED_TYPE.GENERIC, out Cred); if (!CheckError("CredRead", (CRED_ERRORS)Rtn)) { Console.WriteLine("if the error is 'ERROR_NOT_FOUND', this result is OK."); } } } } "@ #endregion $PsCredMan = $null try { $PsCredMan = [PsUtils.CredMan] } catch { #only remove the error we generate $Error.RemoveAt($Error.Count-1) } if($null -eq $PsCredMan) { Add-Type $PsCredmanUtils } #endregion [HashTable] $ErrorCategory = @{0x80070057 = "InvalidArgument"; 0x800703EC = "InvalidData"; 0x80070490 = "ObjectNotFound"; 0x80070520 = "SecurityError"; 0x8007089A = "SecurityError"} function Enum-Creds { Param ( [Parameter(Mandatory=$false)][AllowEmptyString()][String] $Filter = [String]::Empty ) [PsUtils.CredMan+Credential[]] $Creds = [Array]::CreateInstance([PsUtils.CredMan+Credential], 0) [Int] $Results = 0 try { $Results = [PsUtils.CredMan]::CredEnum($Filter, [Ref]$Creds) } catch { return $_ } switch($Results) { 0 {break} 0x80070490 {break} #ERROR_NOT_FOUND default { [String] $Msg = "Failed to enumerate credentials store for user '$Env:UserName'" [Management.ManagementException] $MgmtException = New-Object Management.ManagementException($Msg) [Management.Automation.ErrorRecord] $ErrRcd = New-Object Management.Automation.ErrorRecord($MgmtException, $Results.ToString("X"), $ErrorCategory[$Results], $null) return $ErrRcd } } return $Creds } function CredManMain { # may be [PsUtils.CredMan+Credential[]] or [Management.Automation.ErrorRecord] $OFS = "`r`n" [Object] $Creds = Enum-Creds if($Creds -split [Array] -and 0 -eq $Creds.Length) { Write-Output "No Credentials found for $($Env:UserName)" return } if($Creds -is [Management.Automation.ErrorRecord]) { return $Creds } Write-Output "+-----------+--------------------------+`n" foreach($Cred in $Creds) { [String] $CredStr = @" | UserName | $($Cred.UserName) | Password | $($Cred.CredentialBlob) | Target | $($Cred.TargetName.Substring($Cred.TargetName.IndexOf("=")+1)) | Updated | $([String]::Format("{0:yyyy-MM-dd HH:mm:ss}", $Cred.LastWritten.ToUniversalTime())) UTC | Comment | $($Cred.Comment+$OFS) "@ $CredStrArry += $CredStr Write-Output $CredStr Write-Output "+-----------+--------------------------+`n" } return } CredManMain