diff options
Diffstat (limited to 'LibTSforge/SPP')
| -rw-r--r-- | LibTSforge/SPP/ProductKey.cs | 10 | ||||
| -rw-r--r-- | LibTSforge/SPP/SLAPI.cs | 22 | ||||
| -rw-r--r-- | LibTSforge/SPP/SPPUtils.cs | 275 | ||||
| -rw-r--r-- | LibTSforge/SPP/SPSys.cs | 47 |
4 files changed, 338 insertions, 16 deletions
diff --git a/LibTSforge/SPP/ProductKey.cs b/LibTSforge/SPP/ProductKey.cs index 7a933da..b5fca9a 100644 --- a/LibTSforge/SPP/ProductKey.cs +++ b/LibTSforge/SPP/ProductKey.cs @@ -60,22 +60,22 @@ namespace LibTSforge.SPP public Guid GetPkeyId() { - VariableBag pkb = new VariableBag(); - pkb.Blocks.AddRange(new CRCBlock[] + VariableBag pkb = new VariableBag(PSVersion.WinModern); + pkb.Blocks.AddRange(new CRCBlockModern[] { - new CRCBlock + new CRCBlockModern { DataType = CRCBlockType.STRING, KeyAsStr = "SppPkeyBindingProductKey", ValueAsStr = ToString() }, - new CRCBlock + new CRCBlockModern { DataType = CRCBlockType.BINARY, KeyAsStr = "SppPkeyBindingMiscData", Value = new byte[] { } }, - new CRCBlock + new CRCBlockModern { DataType = CRCBlockType.STRING, KeyAsStr = "SppPkeyBindingAlgorithm", diff --git a/LibTSforge/SPP/SLAPI.cs b/LibTSforge/SPP/SLAPI.cs index cfd7dc5..336d88f 100644 --- a/LibTSforge/SPP/SLAPI.cs +++ b/LibTSforge/SPP/SLAPI.cs @@ -44,40 +44,40 @@ namespace LibTSforge.SPP public static readonly Guid WINDOWS_APP_ID = new Guid("55c92734-d682-4d71-983e-d6ec3f16059f"); - [DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)] + [DllImport("slc.dll", CharSet = CharSet.Unicode, PreserveSig = false)] private static extern void SLOpen(out IntPtr hSLC); - [DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)] + [DllImport("slc.dll", CharSet = CharSet.Unicode, PreserveSig = false)] private static extern void SLClose(IntPtr hSLC); [DllImport("slc.dll", CharSet = CharSet.Unicode)] private static extern uint SLGetWindowsInformationDWORD(string ValueName, ref int Value); - [DllImport("sppc.dll", CharSet = CharSet.Unicode)] + [DllImport("slc.dll", CharSet = CharSet.Unicode)] private static extern uint SLInstallProofOfPurchase(IntPtr hSLC, string pwszPKeyAlgorithm, string pwszPKeyString, uint cbPKeySpecificData, byte[] pbPKeySpecificData, ref Guid PKeyId); - [DllImport("sppc.dll", CharSet = CharSet.Unicode)] + [DllImport("slc.dll", CharSet = CharSet.Unicode)] private static extern uint SLUninstallProofOfPurchase(IntPtr hSLC, ref Guid PKeyId); - [DllImport("sppc.dll", CharSet = CharSet.Unicode)] + [DllImport("slc.dll", CharSet = CharSet.Unicode)] private static extern uint SLGetPKeyInformation(IntPtr hSLC, ref Guid pPKeyId, string pwszValueName, out SLDATATYPE peDataType, out uint pcbValue, out IntPtr ppbValue); - [DllImport("sppcext.dll", CharSet = CharSet.Unicode)] + [DllImport("slcext.dll", CharSet = CharSet.Unicode)] private static extern uint SLActivateProduct(IntPtr hSLC, ref Guid pProductSkuId, byte[] cbAppSpecificData, byte[] pvAppSpecificData, byte[] pActivationInfo, string pwszProxyServer, ushort wProxyPort); - [DllImport("sppc.dll", CharSet = CharSet.Unicode)] + [DllImport("slc.dll", CharSet = CharSet.Unicode)] private static extern uint SLGenerateOfflineInstallationId(IntPtr hSLC, ref Guid pProductSkuId, ref string ppwszInstallationId); - [DllImport("sppc.dll", CharSet = CharSet.Unicode)] + [DllImport("slc.dll", CharSet = CharSet.Unicode)] private static extern uint SLDepositOfflineConfirmationId(IntPtr hSLC, ref Guid pProductSkuId, string pwszInstallationId, string pwszConfirmationId); - [DllImport("sppc.dll", CharSet = CharSet.Unicode)] + [DllImport("slc.dll", CharSet = CharSet.Unicode)] private static extern uint SLGetSLIDList(IntPtr hSLC, SLIDTYPE eQueryIdType, ref Guid pQueryId, SLIDTYPE eReturnIdType, out uint pnReturnIds, out IntPtr ppReturnIds); - [DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)] + [DllImport("slc.dll", CharSet = CharSet.Unicode, PreserveSig = false)] private static extern void SLGetLicensingStatusInformation(IntPtr hSLC, ref Guid pAppID, IntPtr pProductSkuId, string pwszRightName, out uint pnStatusCount, out IntPtr ppLicensingStatus); - [DllImport("sppc.dll", CharSet = CharSet.Unicode)] + [DllImport("slc.dll", CharSet = CharSet.Unicode)] private static extern uint SLGetInstalledProductKeyIds(IntPtr hSLC, ref Guid pProductSkuId, out uint pnProductKeyIds, out IntPtr ppProductKeyIds); [DllImport("slc.dll", CharSet = CharSet.Unicode)] diff --git a/LibTSforge/SPP/SPPUtils.cs b/LibTSforge/SPP/SPPUtils.cs new file mode 100644 index 0000000..f1aa32f --- /dev/null +++ b/LibTSforge/SPP/SPPUtils.cs @@ -0,0 +1,275 @@ +namespace LibTSforge.SPP +{ + using LibTSforge.Crypto; + using LibTSforge.PhysicalStore; + using LibTSforge.TokenStore; + using Microsoft.Win32; + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.ServiceProcess; + using System.Text; + + public static class SPPUtils + { + public static void KillSPP(PSVersion version) + { + ServiceController sc; + + string svcName = version == PSVersion.Vista ? "slsvc" : "sppsvc"; + + try + { + sc = new ServiceController(svcName); + + if (sc.Status == ServiceControllerStatus.Stopped) + return; + } + catch (InvalidOperationException ex) + { + throw new InvalidOperationException(string.Format("Unable to access {0}: ", svcName) + ex.Message); + } + + Logger.WriteLine(string.Format("Stopping {0}...", svcName)); + + bool stopped = false; + + for (int i = 0; stopped == false && i < 360; i++) + { + try + { + if (sc.Status != ServiceControllerStatus.StopPending) + sc.Stop(); + + sc.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromMilliseconds(500)); + } + catch (System.ServiceProcess.TimeoutException) + { + continue; + } + catch (InvalidOperationException) + { + System.Threading.Thread.Sleep(500); + continue; + } + + stopped = true; + } + + if (!stopped) + throw new System.TimeoutException(string.Format("Failed to stop {0}", svcName)); + + Logger.WriteLine(string.Format("{0} stopped successfully.", svcName)); + + if (version == PSVersion.Vista && SPSys.IsSpSysRunning()) + { + Logger.WriteLine("Unloading spsys..."); + + int status = SPSys.ControlSpSys(false); + + if (status < 0) + { + throw new IOException("Failed to unload spsys"); + } + + Logger.WriteLine("spsys unloaded successfully."); + } + } + + public static void RestartSPP(PSVersion version) + { + if (version == PSVersion.Vista) + { + ServiceController sc; + + try + { + sc = new ServiceController("slsvc"); + + if (sc.Status == ServiceControllerStatus.Running) + return; + } + catch (InvalidOperationException ex) + { + throw new InvalidOperationException("Unable to access slsvc: " + ex.Message); + } + + Logger.WriteLine("Starting slsvc..."); + + bool started = false; + + for (int i = 0; started == false && i < 360; i++) + { + try + { + if (sc.Status != ServiceControllerStatus.StartPending) + sc.Start(); + + sc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromMilliseconds(500)); + } + catch (System.ServiceProcess.TimeoutException) + { + continue; + } + catch (InvalidOperationException) + { + System.Threading.Thread.Sleep(500); + continue; + } + + started = true; + } + + if (!started) + throw new System.TimeoutException("Failed to start slsvc"); + + Logger.WriteLine("slsvc started successfully."); + } + + SLApi.RefreshLicenseStatus(); + } + + public static string GetPSPath(PSVersion version) + { + switch (version) + { + case PSVersion.Vista: + case PSVersion.Win7: + return Directory.GetFiles( + Environment.GetFolderPath(Environment.SpecialFolder.System), + "7B296FB0-376B-497e-B012-9C450E1B7327-*.C7483456-A289-439d-8115-601632D005A0") + .FirstOrDefault() ?? ""; + default: + return Path.Combine( + Environment.ExpandEnvironmentVariables( + (string)Registry.GetValue( + @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform", + "TokenStore", + string.Empty + ) + ), + "data.dat" + ); + } + } + + public static string GetTokensPath(PSVersion version) + { + switch (version) + { + case PSVersion.Vista: + return Path.Combine( + Environment.ExpandEnvironmentVariables("%WINDIR%"), + @"ServiceProfiles\NetworkService\AppData\Roaming\Microsoft\SoftwareLicensing\tokens.dat" + ); + case PSVersion.Win7: + return Path.Combine( + Environment.ExpandEnvironmentVariables("%WINDIR%"), + @"ServiceProfiles\NetworkService\AppData\Roaming\Microsoft\SoftwareProtectionPlatform\tokens.dat" + ); + default: + return Path.Combine( + Environment.ExpandEnvironmentVariables( + (string)Registry.GetValue( + @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform", + "TokenStore", + string.Empty + ) + ), + "tokens.dat" + ); + } + } + + public static IPhysicalStore GetStore(PSVersion version, bool production) + { + string psPath; + + try + { + psPath = GetPSPath(version); + } + catch + { + throw new FileNotFoundException("Failed to get path of physical store."); + } + + if (string.IsNullOrEmpty(psPath) || !File.Exists(psPath)) + { + throw new FileNotFoundException(string.Format("Physical store not found at expected path {0}.", psPath)); + } + + switch (version) + { + case PSVersion.Vista: + return new PhysicalStoreVista(psPath, production); + case PSVersion.Win7: + return new PhysicalStoreWin7(psPath, production); + default: + return new PhysicalStoreModern(psPath, production, version); + } + } + + public static ITokenStore GetTokenStore(PSVersion version) + { + string tokPath; + + try + { + tokPath = GetTokensPath(version); + } + catch + { + throw new FileNotFoundException("Failed to get path of physical store."); + } + + if (string.IsNullOrEmpty(tokPath) || !File.Exists(tokPath)) + { + throw new FileNotFoundException(string.Format("Token store not found at expected path {0}.", tokPath)); + } + + return new TokenStoreModern(tokPath); + } + + public static void DumpStore(PSVersion version, bool production, string filePath, string encrFilePath) + { + if (encrFilePath == null) + { + encrFilePath = GetPSPath(version); + } + + if (string.IsNullOrEmpty(encrFilePath) || !File.Exists(encrFilePath)) + { + throw new FileNotFoundException("Store does not exist at expected path '" + encrFilePath + "'."); + } + + KillSPP(version); + + using (FileStream fs = File.Open(encrFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) + { + byte[] encrData = fs.ReadAllBytes(); + File.WriteAllBytes(filePath, PhysStoreCrypto.DecryptPhysicalStore(encrData, production, version)); + } + + Logger.WriteLine("Store dumped successfully to '" + filePath + "'."); + } + + public static void LoadStore(PSVersion version, bool production, string filePath) + { + if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) + { + throw new FileNotFoundException("Store file '" + filePath + "' does not exist."); + } + + KillSPP(version); + + using (IPhysicalStore store = GetStore(version, production)) + { + store.WriteRaw(File.ReadAllBytes(filePath)); + } + + Logger.WriteLine("Loaded store file succesfully."); + } + } +} diff --git a/LibTSforge/SPP/SPSys.cs b/LibTSforge/SPP/SPSys.cs new file mode 100644 index 0000000..10b8d04 --- /dev/null +++ b/LibTSforge/SPP/SPSys.cs @@ -0,0 +1,47 @@ +namespace LibTSforge.SPP +{ + using Microsoft.Win32.SafeHandles; + using System; + using System.Collections.Generic; + using System.Linq; + using System.Runtime.InteropServices; + using System.Text; + + public class SPSys + { + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); + private static SafeFileHandle CreateFileSafe(string device) + { + return new SafeFileHandle(CreateFile(device, 0xC0000000, 0, IntPtr.Zero, 3, 0, IntPtr.Zero), true); + } + + [return: MarshalAs(UnmanagedType.Bool)] + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool DeviceIoControl([In] SafeFileHandle hDevice, [In] uint dwIoControlCode, [In] IntPtr lpInBuffer, [In] int nInBufferSize, [Out] IntPtr lpOutBuffer, [In] int nOutBufferSize, out int lpBytesReturned, [In] IntPtr lpOverlapped); + + public static bool IsSpSysRunning() + { + SafeFileHandle file = CreateFileSafe(@"\\.\SpDevice"); + IntPtr buffer = Marshal.AllocHGlobal(1); + int bytesReturned = 0; + DeviceIoControl(file, 0x80006008, IntPtr.Zero, 0, buffer, 1, out bytesReturned, IntPtr.Zero); + bool running = Marshal.ReadByte(buffer) != 0; + Marshal.FreeHGlobal(buffer); + file.Close(); + return running; + } + + public static int ControlSpSys(bool start) + { + SafeFileHandle file = CreateFileSafe(@"\\.\SpDevice"); + IntPtr buffer = Marshal.AllocHGlobal(4); + int bytesReturned = 0; + DeviceIoControl(file, start ? 0x8000a000 : 0x8000a004, IntPtr.Zero, 0, buffer, 4, out bytesReturned, IntPtr.Zero); + int result = Marshal.ReadInt32(buffer); + Marshal.FreeHGlobal(buffer); + file.Close(); + return result; + } + } +} |
