Add partial support (zcid, rtmr, non-functional kms4k) for vista

Co-authored-by: InvoxiPlayGames <22731889+InvoxiPlayGames@users.noreply.github.com>
This commit is contained in:
2025-03-01 02:01:39 -05:00
parent 8aa1f9078d
commit 6d759899d8
24 changed files with 1023 additions and 347 deletions

View File

@ -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",

View File

@ -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)]

275
LibTSforge/SPP/SPPUtils.cs Normal file
View File

@ -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.");
}
}
}

47
LibTSforge/SPP/SPSys.cs Normal file
View File

@ -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;
}
}
}