Last active
December 3, 2024 17:32
-
-
Save requilence/de8da32adc44d4786559789debb3bf88 to your computer and use it in GitHub Desktop.
powershell script to retrieve the anytype account key from the Credential Manager on Windows
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Prompt the user for the credential name (Target) | |
$account = Read-Host "Enter the anytype account id (starts with A)" | |
# Define necessary structs and functions using P/Invoke | |
Add-Type -TypeDefinition @" | |
using System; | |
using System.Runtime.InteropServices; | |
public class NativeMethods | |
{ | |
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] | |
public struct CREDENTIAL | |
{ | |
public UInt32 Flags; | |
public UInt32 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; | |
} | |
[DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)] | |
public static extern bool CredRead(string TargetName, uint Type, uint Flags, out IntPtr CredentialPtr); | |
[DllImport("advapi32.dll", SetLastError=true)] | |
public static extern void CredFree(IntPtr Buffer); | |
} | |
"@ | |
# Set the target name of the credential | |
$targetName = "anytype/"+$account | |
# Credential type for generic credentials | |
$CRED_TYPE_GENERIC = 1 | |
# Attempt to read the credential | |
$credentialPtr = [IntPtr]::Zero | |
$result = [NativeMethods]::CredRead($targetName, $CRED_TYPE_GENERIC, 0, [ref]$credentialPtr) | |
if ($result) { | |
try { | |
# Marshal the unmanaged CREDENTIAL structure to a managed structure | |
$credential = [Runtime.InteropServices.Marshal]::PtrToStructure( | |
$credentialPtr, [Type][NativeMethods+CREDENTIAL] | |
) | |
# Read the CredentialBlob as a byte array | |
$credentialBlobSize = $credential.CredentialBlobSize | |
$credentialBlobPtr = $credential.CredentialBlob | |
if ($credentialBlobSize -gt 0 -and $credentialBlobPtr -ne [IntPtr]::Zero) { | |
$passwordBytes = New-Object byte[] $credentialBlobSize | |
[Runtime.InteropServices.Marshal]::Copy( | |
$credentialBlobPtr, $passwordBytes, 0, $credentialBlobSize | |
) | |
# Decode the password from UTF-8 encoding | |
$password = [System.Text.Encoding]::UTF8.GetString($passwordBytes) | |
# Trim any null characters that may be at the end | |
$password = $password.TrimEnd([char]0) | |
# Now you can use the $password variable as needed | |
# For demonstration, we'll output the password (be cautious with sensitive data) | |
Write-Host "Retrieved password:" | |
Write-Host $password | |
} else { | |
Write-Error "The credential blob is empty." | |
} | |
} finally { | |
# Free the unmanaged memory allocated for the credential | |
[NativeMethods]::CredFree($credentialPtr) | |
} | |
} else { | |
$errorCode = [Runtime.InteropServices.Marshal]::GetLastWin32Error() | |
Write-Error "Failed to read credential. Error code: $errorCode" | |
} | |
Write-Host "Press Enter to exit..." | |
[void][System.Console]::ReadLine() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment