summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWitherOrNot2025-03-01 07:01:39 +0000
committerWitherOrNot2025-03-01 07:06:21 +0000
commit6d759899d85939c95f2b97c8e041d7b4865208f9 (patch)
tree08e174f929f4ddbbaa687207cf47784b29595f4b
parent8aa1f9078d786a7b20d2b92bbeefdd77a93dd828 (diff)
downloadTSforge-6d759899d85939c95f2b97c8e041d7b4865208f9.zip
Add partial support (zcid, rtmr, non-functional kms4k) for vista
Co-authored-by: InvoxiPlayGames <[email protected]>
-rw-r--r--LibTSforge/Activators/AVMA4K.cs14
-rw-r--r--LibTSforge/Activators/KMS4K.cs132
-rw-r--r--LibTSforge/Activators/ZeroCID.cs71
-rw-r--r--LibTSforge/Common.cs195
-rw-r--r--LibTSforge/Crypto/CryptoUtils.cs13
-rw-r--r--LibTSforge/Crypto/PhysStoreCrypto.cs25
-rw-r--r--LibTSforge/Modifiers/GenPKeyInstall.cs31
-rw-r--r--LibTSforge/Modifiers/GracePeriodReset.cs6
-rw-r--r--LibTSforge/Modifiers/KMSHostCharge.cs22
-rw-r--r--LibTSforge/Modifiers/KeyChangeLockDelete.cs6
-rw-r--r--LibTSforge/Modifiers/RearmReset.cs5
-rw-r--r--LibTSforge/Modifiers/TamperedFlagsDelete.cs5
-rw-r--r--LibTSforge/Modifiers/UniqueIdDelete.cs8
-rw-r--r--LibTSforge/PhysicalStore/Common.cs7
-rw-r--r--LibTSforge/PhysicalStore/PhysicalStoreModern.cs4
-rw-r--r--LibTSforge/PhysicalStore/PhysicalStoreVista.cs356
-rw-r--r--LibTSforge/PhysicalStore/PhysicalStoreWin7.cs4
-rw-r--r--LibTSforge/PhysicalStore/VariableBag.cs102
-rw-r--r--LibTSforge/SPP/ProductKey.cs10
-rw-r--r--LibTSforge/SPP/SLAPI.cs22
-rw-r--r--LibTSforge/SPP/SPPUtils.cs275
-rw-r--r--LibTSforge/SPP/SPSys.cs47
-rw-r--r--README.md1
-rw-r--r--TSforgeCLI/Program.cs7
24 files changed, 1022 insertions, 346 deletions
diff --git a/LibTSforge/Activators/AVMA4K.cs b/LibTSforge/Activators/AVMA4K.cs
index 5ac2838..ec09daf 100644
--- a/LibTSforge/Activators/AVMA4K.cs
+++ b/LibTSforge/Activators/AVMA4K.cs
@@ -34,11 +34,11 @@ namespace LibTSforge.Activators
throw new NotSupportedException("Non-VT:IA product key installed.");
}
- Utils.KillSPP();
+ SPPUtils.KillSPP(version);
Logger.WriteLine("Writing TrustedStore data...");
- using (IPhysicalStore store = Utils.GetStore(version, production))
+ using (IPhysicalStore store = SPPUtils.GetStore(version, production))
{
string key = string.Format("SPPSVC\\{0}\\{1}", appId, actId);
@@ -57,23 +57,23 @@ namespace LibTSforge.Activators
timerTime = crcBindTime / 10000;
expiry /= 10000;
- VariableBag avmaBinding = new VariableBag();
+ VariableBag avmaBinding = new VariableBag(version);
- avmaBinding.Blocks.AddRange(new CRCBlock[]
+ avmaBinding.Blocks.AddRange(new CRCBlockModern[]
{
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.BINARY,
Key = new byte[] { },
Value = BitConverter.GetBytes(crcBindTime),
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.STRING,
Key = new byte[] { },
ValueAsStr = "AVMA4K",
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.STRING,
Key = new byte[] { },
diff --git a/LibTSforge/Activators/KMS4K.cs b/LibTSforge/Activators/KMS4K.cs
index fd09bd3..315e082 100644
--- a/LibTSforge/Activators/KMS4K.cs
+++ b/LibTSforge/Activators/KMS4K.cs
@@ -29,11 +29,11 @@ namespace LibTSforge.Activators
throw new NotSupportedException("Non-Volume:GVLK product key installed.");
}
- Utils.KillSPP();
+ SPPUtils.KillSPP(version);
Logger.WriteLine("Writing TrustedStore data...");
- using (IPhysicalStore store = Utils.GetStore(version, production))
+ using (IPhysicalStore store = SPPUtils.GetStore(version, production))
{
string key = string.Format("SPPSVC\\{0}\\{1}", appId, actId);
@@ -42,7 +42,7 @@ namespace LibTSforge.Activators
ulong time2 = (ulong)DateTime.UtcNow.ToFileTime();
ulong expiry = Constants.TimerMax;
- if (version == PSVersion.Win7)
+ if (version == PSVersion.Vista || version == PSVersion.Win7)
{
unknown = 0x800000000;
time1 = 0;
@@ -58,86 +58,119 @@ namespace LibTSforge.Activators
expiry /= 10000;
}
- byte[] hwidBlock = Constants.UniversalHWIDBlock;
- byte[] kmsResp;
-
- switch (version)
+ if (version == PSVersion.Vista)
{
- case PSVersion.Win7:
- kmsResp = Constants.KMSv4Response;
- break;
- case PSVersion.Win8:
- kmsResp = Constants.KMSv5Response;
- break;
- case PSVersion.WinBlue:
- case PSVersion.WinModern:
- kmsResp = Constants.KMSv6Response;
- break;
- default:
- throw new NotSupportedException("Unsupported PSVersion.");
- }
+ VistaTimer vistaTimer = new VistaTimer();
+ vistaTimer.Time = time2;
+ vistaTimer.Expiry = expiry;
- VariableBag kmsBinding = new VariableBag();
+ string vistaTimerName = string.Format("msft:sl/timer/VLExpiration/VOLUME/{0}/{1}", appId, actId);
- kmsBinding.Blocks.AddRange(new CRCBlock[]
+ store.DeleteBlock(key, vistaTimerName);
+ store.DeleteBlock(key, "45E81E65-6944-422E-9C02-D83F7E5F5A58");
+
+ store.AddBlocks(new PSBlock[]
+ {
+ new PSBlock
+ {
+ Type = BlockType.TIMER,
+ Flags = 0,
+ KeyAsStr = key,
+ ValueAsStr = vistaTimerName,
+ Data = vistaTimer.CastToArray()
+ },
+ new PSBlock
+ {
+ Type = BlockType.NAMED,
+ Flags = 0,
+ KeyAsStr = key,
+ ValueAsStr = "45E81E65-6944-422E-9C02-D83F7E5F5A58",
+ Data = new Guid().ToByteArray()
+ }
+ });
+ }
+ else
{
- new CRCBlock
+ byte[] hwidBlock = Constants.UniversalHWIDBlock;
+ byte[] kmsResp;
+
+ switch (version)
+ {
+ case PSVersion.Win7:
+ kmsResp = Constants.KMSv4Response;
+ break;
+ case PSVersion.Win8:
+ kmsResp = Constants.KMSv5Response;
+ break;
+ case PSVersion.WinBlue:
+ case PSVersion.WinModern:
+ kmsResp = Constants.KMSv6Response;
+ break;
+ default:
+ throw new NotSupportedException("Unsupported PSVersion.");
+ }
+
+ VariableBag kmsBinding = new VariableBag(version);
+
+ kmsBinding.Blocks.AddRange(new CRCBlockModern[]
+ {
+ new CRCBlockModern
{
DataType = CRCBlockType.BINARY,
Key = new byte[] { },
Value = kmsResp
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.STRING,
Key = new byte[] { },
ValueAsStr = "msft:rm/algorithm/hwid/4.0"
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.BINARY,
KeyAsStr = "SppBindingLicenseData",
Value = hwidBlock
}
- });
+ });
- if (version == PSVersion.WinModern)
- {
- kmsBinding.Blocks.AddRange(new CRCBlock[]
+ if (version == PSVersion.WinModern)
{
- new CRCBlock
+ kmsBinding.Blocks.AddRange(new CRCBlockModern[]
+ {
+ new CRCBlockModern
{
DataType = CRCBlockType.STRING,
Key = new byte[] { },
ValueAsStr = "massgrave.dev"
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.STRING,
Key = new byte[] { },
ValueAsStr = "6969"
}
- });
- }
+ });
+ }
- byte[] kmsBindingData = kmsBinding.Serialize();
+ byte[] kmsBindingData = kmsBinding.Serialize();
- Timer kmsTimer = new Timer
- {
- Unknown = unknown,
- Time1 = time1,
- Time2 = time2,
- Expiry = expiry
- };
+ Timer kmsTimer = new Timer
+ {
+ Unknown = unknown,
+ Time1 = time1,
+ Time2 = time2,
+ Expiry = expiry
+ };
- string storeVal = string.Format("msft:spp/kms/bind/2.0/store/{0}/{1}", appId, actId);
- string timerVal = string.Format("msft:spp/kms/bind/2.0/timer/{0}/{1}", appId, actId);
+ string storeVal = string.Format("msft:spp/kms/bind/2.0/store/{0}/{1}", appId, actId);
+ string timerVal = string.Format("msft:spp/kms/bind/2.0/timer/{0}/{1}", appId, actId);
- store.DeleteBlock(key, storeVal);
- store.DeleteBlock(key, timerVal);
+ store.DeleteBlock(key, storeVal);
+ store.DeleteBlock(key, timerVal);
- store.AddBlocks(new PSBlock[]
- {
+ store.AddBlocks(new PSBlock[]
+ {
new PSBlock
{
Type = BlockType.NAMED,
@@ -154,10 +187,11 @@ namespace LibTSforge.Activators
ValueAsStr = timerVal,
Data = kmsTimer.CastToArray()
}
- });
+ });
+ }
}
- SLApi.RefreshLicenseStatus();
+ SPPUtils.RestartSPP(version);
SLApi.FireStateChangedEvent(appId);
Logger.WriteLine("Activated using KMS4k successfully.");
}
diff --git a/LibTSforge/Activators/ZeroCID.cs b/LibTSforge/Activators/ZeroCID.cs
index 99cedee..6264f1d 100644
--- a/LibTSforge/Activators/ZeroCID.cs
+++ b/LibTSforge/Activators/ZeroCID.cs
@@ -2,6 +2,8 @@ namespace LibTSforge.Activators
{
using System;
using System.IO;
+ using System.Linq;
+ using System.Text.RegularExpressions;
using LibTSforge.Crypto;
using LibTSforge.PhysicalStore;
using LibTSforge.SPP;
@@ -46,16 +48,16 @@ namespace LibTSforge.Activators
string instId = SLApi.GetInstallationID(actId);
Guid pkeyId = SLApi.GetInstalledPkeyID(actId);
- if (version == PSVersion.Win7)
+ if (version == PSVersion.Vista || version == PSVersion.Win7)
{
Deposit(actId, instId);
}
- Utils.KillSPP();
+ SPPUtils.KillSPP(version);
Logger.WriteLine("Writing TrustedStore data...");
- using (IPhysicalStore store = Utils.GetStore(version, production))
+ using (IPhysicalStore store = SPPUtils.GetStore(version, production))
{
byte[] hwidBlock = Constants.UniversalHWIDBlock;
@@ -65,7 +67,11 @@ namespace LibTSforge.Activators
byte[] iidHash;
- if (version == PSVersion.Win7)
+ if (version == PSVersion.Vista)
+ {
+ iidHash = CryptoUtils.SHA256Hash(Utils.EncodeString(instId)).Take(0x10).ToArray();
+ }
+ else if (version == PSVersion.Win7)
{
iidHash = CryptoUtils.SHA256Hash(Utils.EncodeString(instId));
}
@@ -82,11 +88,44 @@ namespace LibTSforge.Activators
throw new InvalidDataException("Failed to get product key data for activation ID " + actId + ".");
}
- VariableBag pkb = new VariableBag(keyBlock.Data);
+ VariableBag pkb = new VariableBag(keyBlock.Data, version);
byte[] pkeyData;
- if (version == PSVersion.Win7)
+ if (version == PSVersion.Vista)
+ {
+ pkeyData = pkb.GetBlock("PKeyBasicInfo").Value;
+ string uniqueId = Utils.DecodeString(pkeyData.Skip(0x120).Take(0x80).ToArray());
+ string extPid = Utils.DecodeString(pkeyData.Skip(0x1A0).Take(0x80).ToArray());
+
+ uint group = 0;
+ uint.TryParse(extPid.Split('-')[1], out group);
+
+ if (group == 0)
+ {
+ throw new FormatException("Extended PID has invalid format.");
+ }
+
+ ulong shortauth;
+
+ try
+ {
+ shortauth = BitConverter.ToUInt64(Convert.FromBase64String(uniqueId.Split('&')[1]), 0);
+ } catch
+ {
+ throw new FormatException("Key Unique ID has invalid format.");
+ }
+
+ Console.WriteLine(group);
+ Console.WriteLine(shortauth);
+
+ shortauth |= (ulong)group << 41;
+
+ Console.WriteLine(shortauth);
+
+ pkeyData = BitConverter.GetBytes(shortauth);
+ }
+ else if (version == PSVersion.Win7)
{
pkeyData = pkb.GetBlock("SppPkeyShortAuthenticator").Value;
}
@@ -99,26 +138,34 @@ namespace LibTSforge.Activators
store.SetBlock(key, pkeyId.ToString(), pkb.Serialize());
BinaryWriter writer = new BinaryWriter(new MemoryStream());
- writer.Write(0x20);
+ writer.Write(iidHash.Length);
writer.Write(iidHash);
writer.Write(hwidBlock.Length);
writer.Write(hwidBlock);
byte[] tsHwidData = writer.GetBytes();
writer = new BinaryWriter(new MemoryStream());
- writer.Write(0x20);
+ writer.Write(iidHash.Length);
writer.Write(iidHash);
writer.Write(pkeyData.Length);
writer.Write(pkeyData);
byte[] tsPkeyInfoData = writer.GetBytes();
+ string phoneVersion = version == PSVersion.Vista ? "6.0" : "7.0";
+ Guid indexSlid = version == PSVersion.Vista ? actId : pkeyId;
+ string hwidBlockName = string.Format("msft:Windows/{0}/Phone/Cached/HwidBlock/{1}", phoneVersion, indexSlid);
+ string pkeyInfoName = string.Format("msft:Windows/{0}/Phone/Cached/PKeyInfo/{1}", phoneVersion, indexSlid);
+
+ store.DeleteBlock(key, hwidBlockName);
+ store.DeleteBlock(key, pkeyInfoName);
+
store.AddBlocks(new PSBlock[] {
new PSBlock
{
Type = BlockType.NAMED,
Flags = 0,
KeyAsStr = key,
- ValueAsStr = "msft:Windows/7.0/Phone/Cached/HwidBlock/" + pkeyId,
+ ValueAsStr = hwidBlockName,
Data = tsHwidData
},
new PSBlock
@@ -126,18 +173,18 @@ namespace LibTSforge.Activators
Type = BlockType.NAMED,
Flags = 0,
KeyAsStr = key,
- ValueAsStr = "msft:Windows/7.0/Phone/Cached/PKeyInfo/" + pkeyId,
+ ValueAsStr = pkeyInfoName,
Data = tsPkeyInfoData
}
});
}
- if (version != PSVersion.Win7)
+ if (version != PSVersion.Vista && version != PSVersion.Win7)
{
Deposit(actId, instId);
}
- SLApi.RefreshLicenseStatus();
+ SPPUtils.RestartSPP(version);
SLApi.FireStateChangedEvent(appId);
Logger.WriteLine("Activated using ZeroCID successfully.");
}
diff --git a/LibTSforge/Common.cs b/LibTSforge/Common.cs
index d414ab5..6973f6f 100644
--- a/LibTSforge/Common.cs
+++ b/LibTSforge/Common.cs
@@ -226,157 +226,6 @@ namespace LibTSforge
return ~crc;
}
- public static void KillSPP()
- {
- ServiceController sc;
-
- try
- {
- sc = new ServiceController("sppsvc");
-
- if (sc.Status == ServiceControllerStatus.Stopped)
- return;
- }
- catch (InvalidOperationException ex)
- {
- throw new InvalidOperationException("Unable to access sppsvc: " + ex.Message);
- }
-
- Logger.WriteLine("Stopping sppsvc...");
-
- bool stopped = false;
-
- for (int i = 0; stopped == false && i < 60; 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("Failed to stop sppsvc");
-
- Logger.WriteLine("sppsvc stopped successfully.");
- }
-
- public static string GetPSPath(PSVersion version)
- {
- switch (version)
- {
- case PSVersion.Win7:
- return Directory.GetFiles(
- Environment.GetFolderPath(Environment.SpecialFolder.System),
- "7B296FB0-376B-497e-B012-9C450E1B7327-*.C7483456-A289-439d-8115-601632D005A0")
- .FirstOrDefault() ?? "";
- case PSVersion.Win8Early:
- case PSVersion.WinBlue:
- case PSVersion.Win8:
- case PSVersion.WinModern:
- return Path.Combine(
- Environment.ExpandEnvironmentVariables(
- (string)Registry.GetValue(
- @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform",
- "TokenStore",
- string.Empty
- )
- ),
- "data.dat"
- );
- default:
- return "";
- }
- }
-
- public static string GetTokensPath(PSVersion version)
- {
- switch (version)
- {
- case PSVersion.Win7:
- return Path.Combine(
- Environment.ExpandEnvironmentVariables("%WINDIR%"),
- @"ServiceProfiles\NetworkService\AppData\Roaming\Microsoft\SoftwareProtectionPlatform\tokens.dat"
- );
- case PSVersion.Win8Early:
- case PSVersion.WinBlue:
- case PSVersion.Win8:
- case PSVersion.WinModern:
- return Path.Combine(
- Environment.ExpandEnvironmentVariables(
- (string)Registry.GetValue(
- @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform",
- "TokenStore",
- string.Empty
- )
- ),
- "tokens.dat"
- );
- default:
- return "";
- }
- }
-
- 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));
- }
-
- if (version == PSVersion.Vista)
- {
- throw new NotSupportedException("Physical store editing is not supported for Windows Vista.");
- }
-
- return version == PSVersion.Win7 ? new PhysicalStoreWin7(psPath, production) : (IPhysicalStore)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 string GetArchitecture()
{
string arch = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE", EnvironmentVariableTarget.Machine).ToUpperInvariant();
@@ -392,7 +241,7 @@ namespace LibTSforge
if (build >= 7600 && build <= 7602) return PSVersion.Win7;
if (build == 9200) return PSVersion.Win8;
- throw new NotSupportedException("Unable to auto-detect version info, please specify one manually using the /ver argument.");
+ throw new NotSupportedException("Unable to auto-detect version info");
}
public static bool DetectCurrentKey()
@@ -403,7 +252,7 @@ namespace LibTSforge
{
foreach (string subKey in wpaKey.GetSubKeyNames())
{
- if (subKey.StartsWith("8DEC0AF1") && subKey.EndsWith("-1"))
+ if (subKey.StartsWith("8DEC0AF1"))
{
return subKey.Contains("P");
}
@@ -412,46 +261,6 @@ namespace LibTSforge
throw new FileNotFoundException("Failed to autodetect key type, specify physical store key with /prod or /test arguments.");
}
-
- 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();
-
- using (FileStream fs = File.Open(encrFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
- {
- byte[] encrData = fs.ReadAllBytes();
- File.WriteAllBytes(filePath, PhysStoreCrypto.DecryptPhysicalStore(encrData, production));
- }
-
- 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();
-
- using (IPhysicalStore store = GetStore(version, production))
- {
- store.WriteRaw(File.ReadAllBytes(filePath));
- }
-
- Logger.WriteLine("Loaded store file succesfully.");
- }
}
public static class Logger
diff --git a/LibTSforge/Crypto/CryptoUtils.cs b/LibTSforge/Crypto/CryptoUtils.cs
index 4851570..11c2413 100644
--- a/LibTSforge/Crypto/CryptoUtils.cs
+++ b/LibTSforge/Crypto/CryptoUtils.cs
@@ -106,10 +106,21 @@ namespace LibTSforge.Crypto
public static bool HMACVerify(byte[] key, byte[] data, byte[] signature)
{
- HMACSHA1 hmac = new HMACSHA1(key);
return Enumerable.SequenceEqual(signature, HMACSign(key, data));
}
+ public static byte[] SaltSHASum(byte[] salt, byte[] data)
+ {
+ SHA1 sha1 = SHA1.Create();
+ byte[] sha_data = salt.Concat(data).ToArray();
+ return sha1.ComputeHash(sha_data);
+ }
+
+ public static bool SaltSHAVerify(byte[] salt, byte[] data, byte[] checksum)
+ {
+ return Enumerable.SequenceEqual(checksum, SaltSHASum(salt, data));
+ }
+
public static byte[] SHA256Hash(byte[] data)
{
using (SHA256 sha256 = SHA256.Create())
diff --git a/LibTSforge/Crypto/PhysStoreCrypto.cs b/LibTSforge/Crypto/PhysStoreCrypto.cs
index 6d77897..c0491db 100644
--- a/LibTSforge/Crypto/PhysStoreCrypto.cs
+++ b/LibTSforge/Crypto/PhysStoreCrypto.cs
@@ -2,13 +2,15 @@ namespace LibTSforge.Crypto
{
using System;
using System.Collections.Generic;
+ using System.Diagnostics;
using System.IO;
using System.Linq;
+ using System.Security.Cryptography;
using System.Text;
public static class PhysStoreCrypto
{
- public static byte[] DecryptPhysicalStore(byte[] data, bool production)
+ public static byte[] DecryptPhysicalStore(byte[] data, bool production, PSVersion version)
{
byte[] rsaKey = production ? Keys.PRODUCTION : Keys.TEST;
BinaryReader br = new BinaryReader(new MemoryStream(data));
@@ -20,13 +22,23 @@ namespace LibTSforge.Crypto
{
byte[] aesKey = CryptoUtils.RSADecrypt(rsaKey, encAesKey);
byte[] decData = CryptoUtils.AESDecrypt(br.ReadBytes((int)br.BaseStream.Length - 0x110), aesKey);
- byte[] hmacKey = decData.Take(0x10).ToArray();
- byte[] hmacSig = decData.Skip(0x10).Take(0x14).ToArray();
+ byte[] hmacKey = decData.Take(0x10).ToArray(); // SHA-1 salt on Vista
+ byte[] hmacSig = decData.Skip(0x10).Take(0x14).ToArray(); // SHA-1 hash on Vista
byte[] psData = decData.Skip(0x28).ToArray();
- if (!CryptoUtils.HMACVerify(hmacKey, psData, hmacSig))
+ if (version != PSVersion.Vista)
{
- Logger.WriteLine("Warning: Failed to verify HMAC. Physical store is either corrupt or in Vista format.");
+ if (!CryptoUtils.HMACVerify(hmacKey, psData, hmacSig))
+ {
+ throw new InvalidDataException("Failed to verify HMAC. Physical store is corrupt.");
+ }
+ }
+ else
+ {
+ if (!CryptoUtils.SaltSHAVerify(hmacKey, psData, hmacSig))
+ {
+ throw new InvalidDataException("Failed to verify checksum. Physical store is corrupt.");
+ }
}
return psData;
@@ -39,6 +51,7 @@ namespace LibTSforge.Crypto
{
Dictionary<PSVersion, int> versionTable = new Dictionary<PSVersion, int>
{
+ {PSVersion.Vista, 2},
{PSVersion.Win7, 5},
{PSVersion.Win8, 1},
{PSVersion.WinBlue, 2},
@@ -52,7 +65,7 @@ namespace LibTSforge.Crypto
byte[] encAesKey = CryptoUtils.RSAEncrypt(rsaKey, aesKey);
byte[] aesKeySig = CryptoUtils.RSASign(rsaKey, encAesKey);
- byte[] hmacSig = CryptoUtils.HMACSign(hmacKey, data);
+ byte[] hmacSig = version != PSVersion.Vista ? CryptoUtils.HMACSign(hmacKey, data) : CryptoUtils.SaltSHASum(hmacKey, data);
byte[] decData = new byte[] { };
decData = decData.Concat(hmacKey).Concat(hmacSig).Concat(BitConverter.GetBytes(0)).Concat(data).ToArray();
diff --git a/LibTSforge/Modifiers/GenPKeyInstall.cs b/LibTSforge/Modifiers/GenPKeyInstall.cs
index 28d0027..2e4c23d 100644
--- a/LibTSforge/Modifiers/GenPKeyInstall.cs
+++ b/LibTSforge/Modifiers/GenPKeyInstall.cs
@@ -31,6 +31,7 @@ namespace LibTSforge.Modifiers
public static void InstallGenPKey(PSVersion version, bool production, Guid actId)
{
+ if (version == PSVersion.Vista) throw new NotSupportedException("This feature is not supported on Windows Vista/Server 2008.");
if (actId == Guid.Empty) throw new ArgumentException("Activation ID must be specified for generated product key install.");
PKeyConfig pkc = new PKeyConfig();
@@ -72,57 +73,57 @@ namespace LibTSforge.Modifiers
if (pkey.Channel == "Volume:GVLK" && version == PSVersion.Win7) throw new NotSupportedException("Fake GVLK generation is not supported on Windows 7.");
- VariableBag pkb = new VariableBag();
- pkb.Blocks.AddRange(new CRCBlock[]
+ VariableBag pkb = new VariableBag(version);
+ pkb.Blocks.AddRange(new CRCBlockModern[]
{
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.STRING,
KeyAsStr = "SppPkeyBindingProductKey",
ValueAsStr = pkey.ToString()
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.STRING,
KeyAsStr = "SppPkeyBindingMPC",
ValueAsStr = pkey.GetMPC()
},
- new CRCBlock {
+ new CRCBlockModern {
DataType = CRCBlockType.BINARY,
KeyAsStr = "SppPkeyBindingPid2",
ValueAsStr = pkey.GetPid2()
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.BINARY,
KeyAsStr = "SppPkeyBindingPid3",
Value = pkey.GetPid3()
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.BINARY,
KeyAsStr = "SppPkeyBindingPid4",
Value = pkey.GetPid4()
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.STRING,
KeyAsStr = "SppPkeyChannelId",
ValueAsStr = pkey.Channel
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.STRING,
KeyAsStr = "SppPkeyBindingEditionId",
ValueAsStr = pkey.Edition
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.BINARY,
KeyAsStr = (version == PSVersion.Win7) ? "SppPkeyShortAuthenticator" : "SppPkeyPhoneActivationData",
Value = pkey.GetPhoneData(version)
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.BINARY,
KeyAsStr = "SppPkeyBindingMiscData",
@@ -140,11 +141,11 @@ namespace LibTSforge.Modifiers
SLApi.UninstallAllProductKeys(appId);
}
- Utils.KillSPP();
+ SPPUtils.KillSPP(version);
- using (IPhysicalStore ps = Utils.GetStore(version, production))
+ using (IPhysicalStore ps = SPPUtils.GetStore(version, production))
{
- using (ITokenStore tks = Utils.GetTokenStore(version))
+ using (ITokenStore tks = SPPUtils.GetTokenStore(version))
{
Logger.WriteLine("Writing to physical store and token store...");
@@ -195,7 +196,7 @@ namespace LibTSforge.Modifiers
Data = pkb.Serialize()
});
- string cachePath = Utils.GetTokensPath(version).Replace("tokens.dat", @"cache\cache.dat");
+ string cachePath = SPPUtils.GetTokensPath(version).Replace("tokens.dat", @"cache\cache.dat");
if (File.Exists(cachePath)) File.Delete(cachePath);
}
}
diff --git a/LibTSforge/Modifiers/GracePeriodReset.cs b/LibTSforge/Modifiers/GracePeriodReset.cs
index 4743ea6..ddca3f7 100644
--- a/LibTSforge/Modifiers/GracePeriodReset.cs
+++ b/LibTSforge/Modifiers/GracePeriodReset.cs
@@ -4,15 +4,16 @@ namespace LibTSforge.Modifiers
using System.Collections.Generic;
using System.Linq;
using LibTSforge.PhysicalStore;
+ using LibTSforge.SPP;
public static class GracePeriodReset
{
public static void Reset(PSVersion version, bool production)
{
- Utils.KillSPP();
+ SPPUtils.KillSPP(version);
Logger.WriteLine("Writing TrustedStore data...");
- using (IPhysicalStore store = Utils.GetStore(version, production))
+ using (IPhysicalStore store = SPPUtils.GetStore(version, production))
{
string value = "msft:sl/timer";
List<PSBlock> blocks = store.FindBlocks(value).ToList();
@@ -23,6 +24,7 @@ namespace LibTSforge.Modifiers
}
}
+ SPPUtils.RestartSPP(version);
Logger.WriteLine("Successfully reset all grace and evaluation period timers.");
}
}
diff --git a/LibTSforge/Modifiers/KMSHostCharge.cs b/LibTSforge/Modifiers/KMSHostCharge.cs
index 5bfabdf..a2f2423 100644
--- a/LibTSforge/Modifiers/KMSHostCharge.cs
+++ b/LibTSforge/Modifiers/KMSHostCharge.cs
@@ -7,7 +7,7 @@ namespace LibTSforge.Modifiers
public static class KMSHostCharge
{
- public static void Charge(PSVersion version, Guid actId, bool production)
+ public static void Charge(PSVersion version, bool production, Guid actId)
{
if (actId == Guid.Empty)
{
@@ -52,46 +52,46 @@ namespace LibTSforge.Modifiers
writer.Write((byte)currClients);
byte[] reqCounts = writer.GetBytes();
- Utils.KillSPP();
+ SPPUtils.KillSPP(version);
Logger.WriteLine("Writing TrustedStore data...");
- using (IPhysicalStore store = Utils.GetStore(version, production))
+ using (IPhysicalStore store = SPPUtils.GetStore(version, production))
{
- VariableBag kmsCountData = new VariableBag();
- kmsCountData.Blocks.AddRange(new CRCBlock[]
+ VariableBag kmsCountData = new VariableBag(version);
+ kmsCountData.Blocks.AddRange(new CRCBlockModern[]
{
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.BINARY,
KeyAsStr = "SppBindingLicenseData",
Value = hwidBlock
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.UINT,
Key = new byte[] { },
ValueAsInt = (uint)totalClients
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.UINT,
Key = new byte[] { },
ValueAsInt = 1051200000
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.UINT,
Key = new byte[] { },
ValueAsInt = (uint)currClients
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.BINARY,
Key = new byte[] { },
Value = cmidGuids
},
- new CRCBlock
+ new CRCBlockModern
{
DataType = CRCBlockType.BINARY,
Key = new byte[] { },
diff --git a/LibTSforge/Modifiers/KeyChangeLockDelete.cs b/LibTSforge/Modifiers/KeyChangeLockDelete.cs
index e3f32c4..5150a41 100644
--- a/LibTSforge/Modifiers/KeyChangeLockDelete.cs
+++ b/LibTSforge/Modifiers/KeyChangeLockDelete.cs
@@ -3,14 +3,16 @@ namespace LibTSforge.Modifiers
using System.Collections.Generic;
using System.Linq;
using LibTSforge.PhysicalStore;
+ using LibTSforge.SPP;
using LibTSforge;
+
public static class KeyChangeLockDelete
{
public static void Delete(PSVersion version, bool production)
{
- Utils.KillSPP();
+ SPPUtils.KillSPP(version);
Logger.WriteLine("Writing TrustedStore data...");
- using (IPhysicalStore store = Utils.GetStore(version, production))
+ using (IPhysicalStore store = SPPUtils.GetStore(version, production))
{
List<string> values = new List<string>
{
diff --git a/LibTSforge/Modifiers/RearmReset.cs b/LibTSforge/Modifiers/RearmReset.cs
index be2b174..a17c005 100644
--- a/LibTSforge/Modifiers/RearmReset.cs
+++ b/LibTSforge/Modifiers/RearmReset.cs
@@ -4,16 +4,17 @@ namespace LibTSforge.Modifiers
using System.Collections.Generic;
using System.Linq;
using LibTSforge.PhysicalStore;
+ using LibTSforge.SPP;
public static class RearmReset
{
public static void Reset(PSVersion version, bool production)
{
- Utils.KillSPP();
+ SPPUtils.KillSPP(version);
Logger.WriteLine("Writing TrustedStore data...");
- using (IPhysicalStore store = Utils.GetStore(version, production))
+ using (IPhysicalStore store = SPPUtils.GetStore(version, production))
{
List<PSBlock> blocks;
diff --git a/LibTSforge/Modifiers/TamperedFlagsDelete.cs b/LibTSforge/Modifiers/TamperedFlagsDelete.cs
index 8ffb370..55ba1ec 100644
--- a/LibTSforge/Modifiers/TamperedFlagsDelete.cs
+++ b/LibTSforge/Modifiers/TamperedFlagsDelete.cs
@@ -3,16 +3,17 @@ namespace LibTSforge.Modifiers
using System;
using System.Linq;
using LibTSforge.PhysicalStore;
+ using LibTSforge.SPP;
public static class TamperedFlagsDelete
{
public static void DeleteTamperFlags(PSVersion version, bool production)
{
- Utils.KillSPP();
+ SPPUtils.KillSPP(version);
Logger.WriteLine("Writing TrustedStore data...");
- using (IPhysicalStore store = Utils.GetStore(version, production))
+ using (IPhysicalStore store = SPPUtils.GetStore(version, production))
{
if (version != PSVersion.Win7)
{
diff --git a/LibTSforge/Modifiers/UniqueIdDelete.cs b/LibTSforge/Modifiers/UniqueIdDelete.cs
index b83d328..d1851c4 100644
--- a/LibTSforge/Modifiers/UniqueIdDelete.cs
+++ b/LibTSforge/Modifiers/UniqueIdDelete.cs
@@ -8,6 +8,8 @@ namespace LibTSforge.Modifiers
{
public static void DeleteUniqueId(PSVersion version, bool production, Guid actId)
{
+ if (version == PSVersion.Vista) throw new NotSupportedException("This feature is not supported on Windows Vista/Server 2008.");
+
Guid appId;
if (actId == Guid.Empty)
@@ -28,11 +30,11 @@ namespace LibTSforge.Modifiers
string instId = SLApi.GetInstallationID(actId);
Guid pkeyId = SLApi.GetInstalledPkeyID(actId);
- Utils.KillSPP();
+ SPPUtils.KillSPP(version);
Logger.WriteLine("Writing TrustedStore data...");
- using (IPhysicalStore store = Utils.GetStore(version, production))
+ using (IPhysicalStore store = SPPUtils.GetStore(version, production))
{
string key = string.Format("SPPSVC\\{0}\\{1}", appId, actId);
PSBlock keyBlock = store.GetBlock(key, pkeyId.ToString());
@@ -42,7 +44,7 @@ namespace LibTSforge.Modifiers
throw new Exception("No product key found.");
}
- VariableBag pkb = new VariableBag(keyBlock.Data);
+ VariableBag pkb = new VariableBag(keyBlock.Data, version);
pkb.DeleteBlock("SppPkeyUniqueIdToken");
diff --git a/LibTSforge/PhysicalStore/Common.cs b/LibTSforge/PhysicalStore/Common.cs
index f73f022..d0ad4fe 100644
--- a/LibTSforge/PhysicalStore/Common.cs
+++ b/LibTSforge/PhysicalStore/Common.cs
@@ -18,4 +18,11 @@ namespace LibTSforge.PhysicalStore
public ulong Time2;
public ulong Expiry;
}
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct VistaTimer
+ {
+ public ulong Time;
+ public ulong Expiry;
+ }
}
diff --git a/LibTSforge/PhysicalStore/PhysicalStoreModern.cs b/LibTSforge/PhysicalStore/PhysicalStoreModern.cs
index f697bea..9d8bb73 100644
--- a/LibTSforge/PhysicalStore/PhysicalStoreModern.cs
+++ b/LibTSforge/PhysicalStore/PhysicalStoreModern.cs
@@ -320,7 +320,7 @@ namespace LibTSforge.PhysicalStore
public PhysicalStoreModern(string tsPath, bool production, PSVersion version)
{
TSFile = File.Open(tsPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
- Deserialize(PhysStoreCrypto.DecryptPhysicalStore(TSFile.ReadAllBytes(), production));
+ Deserialize(PhysStoreCrypto.DecryptPhysicalStore(TSFile.ReadAllBytes(), production, version));
TSFile.Seek(0, SeekOrigin.Begin);
Version = version;
Production = production;
@@ -340,7 +340,7 @@ namespace LibTSforge.PhysicalStore
public byte[] ReadRaw()
{
- byte[] data = PhysStoreCrypto.DecryptPhysicalStore(TSFile.ReadAllBytes(), Production);
+ byte[] data = PhysStoreCrypto.DecryptPhysicalStore(TSFile.ReadAllBytes(), Production, Version);
TSFile.Seek(0, SeekOrigin.Begin);
return data;
}
diff --git a/LibTSforge/PhysicalStore/PhysicalStoreVista.cs b/LibTSforge/PhysicalStore/PhysicalStoreVista.cs
new file mode 100644
index 0000000..809be77
--- /dev/null
+++ b/LibTSforge/PhysicalStore/PhysicalStoreVista.cs
@@ -0,0 +1,356 @@
+namespace LibTSforge.PhysicalStore
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using LibTSforge.Crypto;
+
+ public class VistaBlock
+ {
+ public BlockType Type;
+ public uint Flags;
+ public byte[] Value;
+ public string ValueAsStr
+ {
+ get
+ {
+ return Utils.DecodeString(Value);
+ }
+ set
+ {
+ Value = Utils.EncodeString(value);
+ }
+ }
+ public uint ValueAsInt
+ {
+ get
+ {
+ return BitConverter.ToUInt32(Value, 0);
+ }
+ set
+ {
+ Value = BitConverter.GetBytes(value);
+ }
+ }
+ public byte[] Data;
+ public string DataAsStr
+ {
+ get
+ {
+ return Utils.DecodeString(Data);
+ }
+ set
+ {
+ Data = Utils.EncodeString(value);
+ }
+ }
+ public uint DataAsInt
+ {
+ get
+ {
+ return BitConverter.ToUInt32(Data, 0);
+ }
+ set
+ {
+ Data = BitConverter.GetBytes(value);
+ }
+ }
+
+ internal void Encode(BinaryWriter writer)
+ {
+ writer.Write((uint)Type);
+ writer.Write(Flags);
+ writer.Write(Value.Length);
+ writer.Write(Data.Length);
+ writer.Write(Value);
+ writer.Write(Data);
+ }
+
+ internal static VistaBlock Decode(BinaryReader reader)
+ {
+ uint type = reader.ReadUInt32();
+ uint flags = reader.ReadUInt32();
+
+ int valueLen = reader.ReadInt32();
+ int dataLen = reader.ReadInt32();
+
+ byte[] value = reader.ReadBytes(valueLen);
+ byte[] data = reader.ReadBytes(dataLen);
+ return new VistaBlock
+ {
+ Type = (BlockType)type,
+ Flags = flags,
+ Value = value,
+ Data = data,
+ };
+ }
+ }
+
+ public sealed class PhysicalStoreVista : IPhysicalStore
+ {
+ private byte[] PreHeaderBytes = new byte[] { };
+ private readonly List<VistaBlock> Blocks = new List<VistaBlock>();
+ private readonly FileStream TSPrimary;
+ private readonly FileStream TSSecondary;
+ private readonly bool Production;
+
+ public byte[] Serialize()
+ {
+ BinaryWriter writer = new BinaryWriter(new MemoryStream());
+ writer.Write(PreHeaderBytes);
+
+ foreach (VistaBlock block in Blocks)
+ {
+ block.Encode(writer);
+ writer.Align(4);
+ }
+
+ return writer.GetBytes();
+ }
+
+ public void Deserialize(byte[] data)
+ {
+ int len = data.Length;
+
+ BinaryReader reader = new BinaryReader(new MemoryStream(data));
+ PreHeaderBytes = reader.ReadBytes(8);
+
+ while (reader.BaseStream.Position < len - 0x14)
+ {
+ Blocks.Add(VistaBlock.Decode(reader));
+ reader.Align(4);
+ }
+ }
+
+ public void AddBlock(PSBlock block)
+ {
+ Blocks.Add(new VistaBlock
+ {
+ Type = block.Type,
+ Flags = block.Flags,
+ Value = block.Value,
+ Data = block.Data
+ });
+ }
+
+ public void AddBlocks(IEnumerable<PSBlock> blocks)
+ {
+ foreach (PSBlock block in blocks)
+ {
+ AddBlock(block);
+ }
+ }
+
+ public PSBlock GetBlock(string key, string value)
+ {
+ foreach (VistaBlock block in Blocks)
+ {
+ if (block.ValueAsStr == value)
+ {
+ return new PSBlock
+ {
+ Type = block.Type,
+ Flags = block.Flags,
+ Key = new byte[0],
+ Value = block.Value,
+ Data = block.Data
+ };
+ }
+ }
+
+ return null;
+ }
+
+ public PSBlock GetBlock(string key, uint value)
+ {
+ foreach (VistaBlock block in Blocks)
+ {
+ if (block.ValueAsInt == value)
+ {
+ return new PSBlock
+ {
+ Type = block.Type,
+ Flags = block.Flags,
+ Key = new byte[0],
+ Value = block.Value,
+ Data = block.Data
+ };
+ }
+ }
+
+ return null;
+ }
+
+ public void SetBlock(string key, string value, byte[] data)
+ {
+ for (int i = 0; i < Blocks.Count; i++)
+ {
+ VistaBlock block = Blocks[i];
+
+ if (block.ValueAsStr == value)
+ {
+ block.Data = data;
+ Blocks[i] = block;
+ break;
+ }
+ }
+ }
+
+ public void SetBlock(string key, uint value, byte[] data)
+ {
+ for (int i = 0; i < Blocks.Count; i++)
+ {
+ VistaBlock block = Blocks[i];
+
+ if (block.ValueAsInt == value)
+ {
+ block.Data = data;
+ Blocks[i] = block;
+ break;
+ }
+ }
+ }
+
+ public void SetBlock(string key, string value, string data)
+ {
+ SetBlock(key, value, Utils.EncodeString(data));
+ }
+
+ public void SetBlock(string key, string value, uint data)
+ {
+ SetBlock(key, value, BitConverter.GetBytes(data));
+ }
+
+ public void SetBlock(string key, uint value, string data)
+ {
+ SetBlock(key, value, Utils.EncodeString(data));
+ }
+
+ public void SetBlock(string key, uint value, uint data)
+ {
+ SetBlock(key, value, BitConverter.GetBytes(data));
+ }
+
+ public void DeleteBlock(string key, string value)
+ {
+ foreach (VistaBlock block in Blocks)
+ {
+ if (block.ValueAsStr == value)
+ {
+ Blocks.Remove(block);
+ return;
+ }
+ }
+ }
+
+ public void DeleteBlock(string key, uint value)
+ {
+ foreach (VistaBlock block in Blocks)
+ {
+ if (block.ValueAsInt == value)
+ {
+ Blocks.Remove(block);
+ return;
+ }
+ }
+ }
+
+ public PhysicalStoreVista(string primaryPath, bool production)
+ {
+ TSPrimary = File.Open(primaryPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
+ TSSecondary = File.Open(primaryPath.Replace("-0.", "-1."), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
+ Production = production;
+
+ Deserialize(PhysStoreCrypto.DecryptPhysicalStore(TSPrimary.ReadAllBytes(), production, PSVersion.Vista));
+ TSPrimary.Seek(0, SeekOrigin.Begin);
+ }
+
+ public void Dispose()
+ {
+ if (TSPrimary.CanWrite && TSSecondary.CanWrite)
+ {
+ byte[] data = PhysStoreCrypto.EncryptPhysicalStore(Serialize(), Production, PSVersion.Vista);
+
+ TSPrimary.SetLength(data.LongLength);
+ TSSecondary.SetLength(data.LongLength);
+
+ TSPrimary.Seek(0, SeekOrigin.Begin);
+ TSSecondary.Seek(0, SeekOrigin.Begin);
+
+ TSPrimary.WriteAllBytes(data);
+ TSSecondary.WriteAllBytes(data);
+
+ TSPrimary.Close();
+ TSSecondary.Close();
+ }
+ }
+
+ public byte[] ReadRaw()
+ {
+ byte[] data = PhysStoreCrypto.DecryptPhysicalStore(TSPrimary.ReadAllBytes(), Production, PSVersion.Vista);
+ TSPrimary.Seek(0, SeekOrigin.Begin);
+ return data;
+ }
+
+ public void WriteRaw(byte[] data)
+ {
+ byte[] encrData = PhysStoreCrypto.EncryptPhysicalStore(data, Production, PSVersion.Vista);
+
+ TSPrimary.SetLength(encrData.LongLength);
+ TSSecondary.SetLength(encrData.LongLength);
+
+ TSPrimary.Seek(0, SeekOrigin.Begin);
+ TSSecondary.Seek(0, SeekOrigin.Begin);
+
+ TSPrimary.WriteAllBytes(encrData);
+ TSSecondary.WriteAllBytes(encrData);
+
+ TSPrimary.Close();
+ TSSecondary.Close();
+ }
+
+ public IEnumerable<PSBlock> FindBlocks(string valueSearch)
+ {
+ List<PSBlock> results = new List<PSBlock>();
+
+ foreach (VistaBlock block in Blocks)
+ {
+ if (block.ValueAsStr.Contains(valueSearch))
+ {
+ results.Add(new PSBlock
+ {
+ Type = block.Type,
+ Flags = block.Flags,
+ Key = new byte[0],
+ Value = block.Value,
+ Data = block.Data
+ });
+ }
+ }
+
+ return results;
+ }
+
+ public IEnumerable<PSBlock> FindBlocks(uint valueSearch)
+ {
+ List<PSBlock> results = new List<PSBlock>();
+
+ foreach (VistaBlock block in Blocks)
+ {
+ if (block.ValueAsInt == valueSearch)
+ {
+ results.Add(new PSBlock
+ {
+ Type = block.Type,
+ Flags = block.Flags,
+ Key = new byte[0],
+ Value = block.Value,
+ Data = block.Data
+ });
+ }
+ }
+
+ return results;
+ }
+ }
+}
diff --git a/LibTSforge/PhysicalStore/PhysicalStoreWin7.cs b/LibTSforge/PhysicalStore/PhysicalStoreWin7.cs
index c1af391..d03bf9a 100644
--- a/LibTSforge/PhysicalStore/PhysicalStoreWin7.cs
+++ b/LibTSforge/PhysicalStore/PhysicalStoreWin7.cs
@@ -279,7 +279,7 @@ namespace LibTSforge.PhysicalStore
TSSecondary = File.Open(primaryPath.Replace("-0.", "-1."), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
Production = production;
- Deserialize(PhysStoreCrypto.DecryptPhysicalStore(TSPrimary.ReadAllBytes(), production));
+ Deserialize(PhysStoreCrypto.DecryptPhysicalStore(TSPrimary.ReadAllBytes(), production, PSVersion.Win7));
TSPrimary.Seek(0, SeekOrigin.Begin);
}
@@ -305,7 +305,7 @@ namespace LibTSforge.PhysicalStore
public byte[] ReadRaw()
{
- byte[] data = PhysStoreCrypto.DecryptPhysicalStore(TSPrimary.ReadAllBytes(), Production);
+ byte[] data = PhysStoreCrypto.DecryptPhysicalStore(TSPrimary.ReadAllBytes(), Production, PSVersion.Win7);
TSPrimary.Seek(0, SeekOrigin.Begin);
return data;
}
diff --git a/LibTSforge/PhysicalStore/VariableBag.cs b/LibTSforge/PhysicalStore/VariableBag.cs
index ddc2efe..76098a9 100644
--- a/LibTSforge/PhysicalStore/VariableBag.cs
+++ b/LibTSforge/PhysicalStore/VariableBag.cs
@@ -3,6 +3,7 @@ namespace LibTSforge.PhysicalStore
using System;
using System.Collections.Generic;
using System.IO;
+ using System.Runtime.CompilerServices;
public enum CRCBlockType : uint
{
@@ -11,7 +12,7 @@ namespace LibTSforge.PhysicalStore
BINARY = 1 << 2
}
- public class CRCBlock
+ public abstract class CRCBlock
{
public CRCBlockType DataType;
public byte[] Key;
@@ -50,7 +51,57 @@ namespace LibTSforge.PhysicalStore
}
}
- public void Encode(BinaryWriter writer)
+ public abstract void Encode(BinaryWriter writer);
+ public abstract void Decode(BinaryReader reader);
+ public abstract uint CRC();
+ }
+
+ public class CRCBlockVista : CRCBlock
+ {
+ public override void Encode(BinaryWriter writer)
+ {
+ uint crc = CRC();
+ writer.Write((uint)DataType);
+ writer.Write(0);
+ writer.Write(Key.Length);
+ writer.Write(Value.Length);
+ writer.Write(crc);
+
+ writer.Write(Key);
+
+ writer.Write(Value);
+ }
+
+ public override void Decode(BinaryReader reader)
+ {
+ uint type = reader.ReadUInt32();
+ uint unk_zero = reader.ReadUInt32();
+ uint lenName = reader.ReadUInt32();
+ uint lenVal = reader.ReadUInt32();
+ uint crc = reader.ReadUInt32();
+
+ byte[] key = reader.ReadBytes((int)lenName);
+ byte[] value = reader.ReadBytes((int)lenVal);
+
+ DataType = (CRCBlockType)type;
+ Key = key;
+ Value = value;
+
+ if (CRC() != crc)
+ {
+ throw new InvalidDataException("Invalid CRC in variable bag.");
+ }
+ }
+
+ public override uint CRC()
+ {
+ return Utils.CRC32(Value);
+ }
+ }
+
+ public class CRCBlockModern : CRCBlock
+ {
+ public override void Encode(BinaryWriter writer)
{
uint crc = CRC();
writer.Write(crc);
@@ -65,7 +116,7 @@ namespace LibTSforge.PhysicalStore
writer.Align(8);
}
- public static CRCBlock Decode(BinaryReader reader)
+ public override void Decode(BinaryReader reader)
{
uint crc = reader.ReadUInt32();
uint type = reader.ReadUInt32();
@@ -78,22 +129,17 @@ namespace LibTSforge.PhysicalStore
byte[] value = reader.ReadBytes((int)lenVal);
reader.Align(8);
- CRCBlock block = new CRCBlock
- {
- DataType = (CRCBlockType)type,
- Key = key,
- Value = value,
- };
+ DataType = (CRCBlockType)type;
+ Key = key;
+ Value = value;
- if (block.CRC() != crc)
+ if (CRC() != crc)
{
throw new InvalidDataException("Invalid CRC in variable bag.");
}
-
- return block;
}
- public uint CRC()
+ public override uint CRC()
{
BinaryWriter wtemp = new BinaryWriter(new MemoryStream());
wtemp.Write(0);
@@ -109,6 +155,7 @@ namespace LibTSforge.PhysicalStore
public class VariableBag
{
public List<CRCBlock> Blocks = new List<CRCBlock>();
+ private PSVersion Version;
public void Deserialize(byte[] data)
{
@@ -118,7 +165,19 @@ namespace LibTSforge.PhysicalStore
while (reader.BaseStream.Position < len - 0x10)
{
- Blocks.Add(CRCBlock.Decode(reader));
+ CRCBlock block;
+
+ if (Version == PSVersion.Vista)
+ {
+ block = new CRCBlockVista();
+ }
+ else
+ {
+ block = new CRCBlockModern();
+ }
+
+ block.Decode(reader);
+ Blocks.Add(block);
}
}
@@ -128,7 +187,13 @@ namespace LibTSforge.PhysicalStore
foreach (CRCBlock block in Blocks)
{
- block.Encode(writer);
+ if (Version == PSVersion.Vista)
+ {
+ ((CRCBlockVista)block).Encode(writer);
+ } else
+ {
+ ((CRCBlockModern)block).Encode(writer);
+ }
}
return writer.GetBytes();
@@ -174,14 +239,15 @@ namespace LibTSforge.PhysicalStore
}
}
- public VariableBag(byte[] data)
+ public VariableBag(byte[] data, PSVersion version)
{
+ Version = version;
Deserialize(data);
}
- public VariableBag()
+ public VariableBag(PSVersion version)
{
-
+ Version = version;
}
}
}
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;
+ }
+ }
+}
diff --git a/README.md b/README.md
index 48a6780..7ad1011 100644
--- a/README.md
+++ b/README.md
@@ -117,6 +117,7 @@ Probably not. If they do, please tell us so we can laugh to ourselves like a bun
### Other Contributions
- SpCreatePackaedLicense - Tool development, testing
+- Emma (IPG) - Vista SPSys IOCTLs and physical store format
- May - Code formatting, build setup
### Special Thanks
diff --git a/TSforgeCLI/Program.cs b/TSforgeCLI/Program.cs
index 158af82..8581b5c 100644
--- a/TSforgeCLI/Program.cs
+++ b/TSforgeCLI/Program.cs
@@ -4,6 +4,7 @@ namespace TSforgeCLI
using LibTSforge;
using LibTSforge.Activators;
using LibTSforge.Modifiers;
+ using LibTSforge.SPP;
public class Program
{
@@ -55,11 +56,11 @@ namespace TSforgeCLI
if (options.Dump)
{
- Utils.DumpStore(version, production, options.DumpFilePath, options.EncrFilePath);
+ SPPUtils.DumpStore(version, production, options.DumpFilePath, options.EncrFilePath);
}
else if (options.Load)
{
- Utils.LoadStore(version, production, options.LoadFilePath);
+ SPPUtils.LoadStore(version, production, options.LoadFilePath);
}
else if (options.KMS4k)
{
@@ -91,7 +92,7 @@ namespace TSforgeCLI
}
else if (options.KMSHostCharge)
{
- KMSHostCharge.Charge(version, options.ActivationId, production);
+ KMSHostCharge.Charge(version, production, options.ActivationId);
}
else if (options.TamperedFlagsDelete)
{