Skip to content

Instantly share code, notes, and snippets.

@andshrew
Last active June 14, 2026 15:57
Show Gist options
  • Select an option

  • Save andshrew/bf6e5e8fa09b957caffc09c6dee58472 to your computer and use it in GitHub Desktop.

Select an option

Save andshrew/bf6e5e8fa09b957caffc09c6dee58472 to your computer and use it in GitHub Desktop.
VMware Workstation VM encryption passwords saved in the the Windows Credential Manager

Retrieving VMware Workstation VM encryption passwords saved in the the Windows Credential Manager

When creating an encrypted VM, VMware Workstation gives you the option to remember the password. It does this by storing the password in the Windows Credential Manager.

VMware does not provide a way to retrieve this stored password, but it can be accessed via the Win32 CredReadW API function.

There are a number of PowerShell projects including PowerShell Credential Manager which provide access to this API, but in testing I found they were unable to correctly display the VMware password.

This PowerShell example has been tested using Windows PowerShell (v5.1) and PowerShell (v7) using VMware Workstation 17.5 on Windows 11 23H2. Windows Terminal is used as the host for command line apps. It has been written with the assistance of ChatGPT.

1. Locate Encrypted VMs GUID

Open the .vmx file for your VM and look for encryptedVM.guid. This is the name of the credential within Windows Credential Manager. For example:

encryptedVM.guid = "{833AB4F5-587E-4B11-9260-4DB13742FA7F}"

2. Retrieve the password via PowerShell

Open PowerShell or Windows PowerShell, copy and paste the below code. This provides an interface to the Win32 API via C#.

Add-Type @"
using System;
using System.Runtime.InteropServices;

public class Win32Cred
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct CREDENTIAL
    {
        public int Flags;
        public int Type;
        public IntPtr TargetName;
        public IntPtr Comment;
        public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
        public int CredentialBlobSize;
        public IntPtr CredentialBlob;
        public int Persist;
        public int AttributeCount;
        public IntPtr Attributes;
        public IntPtr TargetAlias;
        public IntPtr UserName;
    }

    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern bool CredReadW(string target, int type, int reservedFlag, out IntPtr credentialPtr);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern void CredFree(IntPtr buffer);

    public static string CredRead(string targetName, int type = 1)
    {
        IntPtr credPtr;
        if (CredReadW(targetName, type, 0, out credPtr))
        {
            CREDENTIAL cred = (CREDENTIAL)Marshal.PtrToStructure(credPtr, typeof(CREDENTIAL));
            string pass = Marshal.PtrToStringAnsi(cred.CredentialBlob, cred.CredentialBlobSize);
            CredFree(credPtr);
            return pass;
        }
        throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
    }
}
"@

Run the following command replacing {encryptedVM.guid} with the GUID identified in step 1:

[Win32Cred]::CredRead("{encryptedVM.guid}")

For example:

[Win32Cred]::CredRead("{833AB4F5-587E-4B11-9260-4DB13742FA7F}")

3. End of Procedure

The password should be output to the screen:

PS C:\Users\Andrew [Win32Cred]::CredRead("{833AB4F5-587E-4B11-9260-4DB13742FA7F}")
MySecretPassword

A note on Marshal.PtrToString

In this example I use Marshal.PtrToStringAnsi to convert the pointer to the password into a string.

This works in both Windows PowerShell and PowerShell, as it is a C# method available in both .NET Framework and modern .NET (Core).

Marshal.PtrToStringUni does not seem to work, but Marshal.PtrToStringUTF8 does and may be more flexible. This would require the use of PowerShell as this method is only implemented in modern .NET.

It may be preferable to use this, as not all characters will display using ANSI. For example, say your password was made up of emoji characters. Using the above example with Marshal.PtrToStringAnsi the password is going to be output as incorrect characters:

Marshal.PtrToStringAnsi Emoji Example

But using Marshal.PtrToStringUTF8 the password will be correctly displayed, and can be copied/pasted as required:

Marshal.PtrToStringUTF8 Emoji Example

So if this doesn't work for you, you may want to try swapping these functions in the above code, from:

string pass = Marshal.PtrToStringAnsi(cred.CredentialBlob, cred.CredentialBlobSize);

To:

string pass = Marshal.PtrToStringUTF8(cred.CredentialBlob, cred.CredentialBlobSize);

Remember, you must use PowerShell and not Windows PowerShell when using this method.

Here is the full code example using Marshal.PtrToStringUTF8:

Add-Type @"
using System;
using System.Runtime.InteropServices;

public class Win32Cred
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct CREDENTIAL
    {
        public int Flags;
        public int Type;
        public IntPtr TargetName;
        public IntPtr Comment;
        public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
        public int CredentialBlobSize;
        public IntPtr CredentialBlob;
        public int Persist;
        public int AttributeCount;
        public IntPtr Attributes;
        public IntPtr TargetAlias;
        public IntPtr UserName;
    }

    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern bool CredReadW(string target, int type, int reservedFlag, out IntPtr credentialPtr);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern void CredFree(IntPtr buffer);

    public static string CredRead(string targetName, int type = 1)
    {
        IntPtr credPtr;
        if (CredReadW(targetName, type, 0, out credPtr))
        {
            CREDENTIAL cred = (CREDENTIAL)Marshal.PtrToStructure(credPtr, typeof(CREDENTIAL));
            string pass = Marshal.PtrToStringUTF8(cred.CredentialBlob, cred.CredentialBlobSize);
            CredFree(credPtr);
            return pass;
        }
        throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
    }
}
"@

You then invoke it in the same was as in step 2.

@andshrew

Copy link
Copy Markdown
Author

@Tanquen is this running Workstation on a Windows host, and what version of Workstation.

@Tanquen

Tanquen commented Dec 27, 2025

Copy link
Copy Markdown

I'm running Workstation 17 Pro V17.5.2 build-23775571

The host OS is Windows 11, 25H2

It looks like I did this to install the newer version of Windows 11, 24H2 in the VM but forgot. I have no idea what the password is. All the updates until then in the VM are not checking for the TPM This one checks again and forces you to add it before you can install the update.

@andshrew

Copy link
Copy Markdown
Author

@Tanquen I'm not sure how it's working in your case. The only option my version gives me for remembering passwords (Win 11 25H2, 17.6.4) is to store them in the Windows Credential Manager, and whenever that option has been used the VMs .vmx file has the encryptedVM.guid option added which is then the same identifier used for the password in Credential Manager. If it's still automatically decrypting for you without this information then perhaps manually look in the Credential Manager via Control Panel and decrypt any Windows Credential where the purpose isn't obvious (you would enter the "Internet or Network address name" for the credential when using this script to read them).

If you have only partially encrypted the VM (ie. the TPM files) then you might still be able to access the vmdk files directly and recover your data that way, assuming you haven't also enabled file system level encryption too.

@Tanquen

Tanquen commented Dec 29, 2025

Copy link
Copy Markdown

It's very frustrating, I'm not sure what happened when but my original base VM install for Windows 11 I had removed the TMP and any checks for it so I could install and set up the VM.

The VMware wizard even states that it's going to keep the information in the Windows Credential Manager but there appears to be no entry for it there. So I'm at a loss as to how and when this was done and where it's cashing the credentials because it does work when I boot into this version of the OS but not others.

The next copy of that same VM I did the same thing and the third one it automatically turned it on somehow. I don't remember doing it and on the desktop I have a command file to skip the TMP check. So it's like VMware added it anyway somehow. I honestly don't remember adding it and was actively trying to circumvent it so that when I boot my machine into a different OS the VM is not encrypted. :(
I tried going back to previous copy of the VM and when I try to install the updates it won't let me unless I add a TPM.

@mikethebos

mikethebos commented Jan 11, 2026

Copy link
Copy Markdown

For those without encryptedVM.guid, the key is encrypted by Windows DPAPI. Luckily, there is a tool for both bootable and non bootable systems to decrypt data from DPAPI: https://www.nirsoft.net/utils/dpapi_data_decryptor.html
(You must know your Windows password, but I succeeded in decryption even from a Windows boot disk with a borked SAM.)

Fill out the paths as needed in the tool and select manual entry for encrypted data.

Copy encryption.encryptedKey into https://cryptii.com/pipes/base64-to-hex to get a hex string of the key.

Capitalize the hex string using https://onlinestringtools.com/convert-string-to-uppercase

Paste into the NirSoft tool to decrypt.

After decryption, select the first entry in the NirSoft tool.

Two 16 byte hex strings are displayed in the bottom panel - combine them like:

AA B4 BD 32 7E 88 BB F0 C3 12 27 09 14 6F 6A 3F E5 A9 BD 8F 47 4A 37 C2 0D 8C BF D6 D3 BA 3A 11

Return to cryptii.com as linked above. Click Encode and paste in the 32 byte hex string. The VM password appears!

References:
https://xmcyber.com/blog/decrypting-vmware-workstation-passwords-for-fun/
https://www.syvik.com/multidesk/howto.win11.vmware16.en.html

@lowg1974

Copy link
Copy Markdown

Addendum 1: I have a VM which I'd cloned from another encrypted VM on my same system. VMWare did not save the encrypted password to the Credential manager, but it was never an issue until I upgraded to the latest (26H1) Workstation version and then it prompted for it on the newer clone. The original had an entry in the Credential Manager and I was able to retrieve its password with this method, and it was the same on the clone, so it worked!

Addendum 2: I'm not sure whether it was before or after the upgrade when this changed, but the Credential Manager did have a few entries with GUIDs as the name, but also had several for my newest VMs where it was named like "VMWare Encrypted VM: C:\path\to\VM.vmx" and making sure to remove the curly brackets and just put that name into the quotes, the call worked equally well. Just mentioned due to the changes, and also in case someone is just looking for the ones named after the GUIDs and overlooks it like I almost did.

@andshrew

Copy link
Copy Markdown
Author

@lowg1974 Thanks for sharing that.

Yes, it looks like in the 26H1 release of Workstation they've changed the name that they save the credential under in the Credential Manager to try and make it clearer that it's related to VMware Workstation. I'll add a note to the original instructions to mention that.

@c44448

c44448 commented Jun 14, 2026

Copy link
Copy Markdown

@lowg1974 Thanks for sharing that.

Yes, it looks like in the 26H1 release of Workstation they've changed the name that they save the credential under in the Credential Manager to try and make it clearer that it's related to VMware Workstation. I'll add a note to the original instructions to mention that.

maybe include a step to check what name it has in the credential manager, i made the vm in an old version of vmware worksation and while upgrading to 26H1 it just renamed it to VMWare Encrypted VM: D:(path to the .vmx file). I did not see your comment up untill 3 hours later. With the correct nameing your script works perfectly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment