From 6d759899d85939c95f2b97c8e041d7b4865208f9 Mon Sep 17 00:00:00 2001 From: WitherOrNot Date: Sat, 1 Mar 2025 02:01:39 -0500 Subject: [PATCH 01/34] Add partial support (zcid, rtmr, non-functional kms4k) for vista Co-authored-by: InvoxiPlayGames <22731889+InvoxiPlayGames@users.noreply.github.com> --- LibTSforge/Activators/AVMA4K.cs | 14 +- LibTSforge/Activators/KMS4K.cs | 134 ++++--- LibTSforge/Activators/ZeroCID.cs | 71 +++- LibTSforge/Common.cs | 195 +--------- LibTSforge/Crypto/CryptoUtils.cs | 13 +- LibTSforge/Crypto/PhysStoreCrypto.cs | 25 +- LibTSforge/Modifiers/GenPKeyInstall.cs | 31 +- LibTSforge/Modifiers/GracePeriodReset.cs | 6 +- LibTSforge/Modifiers/KMSHostCharge.cs | 22 +- LibTSforge/Modifiers/KeyChangeLockDelete.cs | 6 +- LibTSforge/Modifiers/RearmReset.cs | 5 +- LibTSforge/Modifiers/TamperedFlagsDelete.cs | 5 +- LibTSforge/Modifiers/UniqueIdDelete.cs | 8 +- LibTSforge/PhysicalStore/Common.cs | 7 + .../PhysicalStore/PhysicalStoreModern.cs | 4 +- .../PhysicalStore/PhysicalStoreVista.cs | 356 ++++++++++++++++++ LibTSforge/PhysicalStore/PhysicalStoreWin7.cs | 4 +- LibTSforge/PhysicalStore/VariableBag.cs | 102 ++++- LibTSforge/SPP/ProductKey.cs | 10 +- LibTSforge/SPP/SLAPI.cs | 22 +- LibTSforge/SPP/SPPUtils.cs | 275 ++++++++++++++ LibTSforge/SPP/SPSys.cs | 47 +++ README.md | 1 + TSforgeCLI/Program.cs | 7 +- 24 files changed, 1023 insertions(+), 347 deletions(-) create mode 100644 LibTSforge/PhysicalStore/PhysicalStoreVista.cs create mode 100644 LibTSforge/SPP/SPPUtils.cs create mode 100644 LibTSforge/SPP/SPSys.cs 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; + + string vistaTimerName = string.Format("msft:sl/timer/VLExpiration/VOLUME/{0}/{1}", appId, actId); + + 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() + } + }); } - - VariableBag kmsBinding = new VariableBag(); - - kmsBinding.Blocks.AddRange(new CRCBlock[] + 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 versionTable = new Dictionary { + {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 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 values = new List { 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 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 Blocks = new List(); + 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 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 FindBlocks(string valueSearch) + { + List results = new List(); + + 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 FindBlocks(uint valueSearch) + { + List results = new List(); + + 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 Blocks = new List(); + 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) { From f2ad15e5a25c9cc2cdf0d198927be0562f466156 Mon Sep 17 00:00:00 2001 From: WitherOrNot Date: Sun, 2 Mar 2025 19:02:36 -0500 Subject: [PATCH 02/34] fix vista kms4k, add reset support --- LibTSforge/Activators/KMS4K.cs | 17 ++++++++++++----- LibTSforge/Common.cs | 4 ++-- LibTSforge/Modifiers/KeyChangeLockDelete.cs | 3 +++ LibTSforge/Modifiers/RearmReset.cs | 13 +++++++++++-- LibTSforge/Modifiers/TamperedFlagsDelete.cs | 17 ++++++++++------- LibTSforge/SPP/SPPUtils.cs | 4 ++++ 6 files changed, 42 insertions(+), 16 deletions(-) diff --git a/LibTSforge/Activators/KMS4K.cs b/LibTSforge/Activators/KMS4K.cs index 315e082..01b7395 100644 --- a/LibTSforge/Activators/KMS4K.cs +++ b/LibTSforge/Activators/KMS4K.cs @@ -1,6 +1,7 @@ namespace LibTSforge.Activators { using System; + using System.IO; using LibTSforge.PhysicalStore; using LibTSforge.SPP; @@ -62,12 +63,18 @@ namespace LibTSforge.Activators { VistaTimer vistaTimer = new VistaTimer(); vistaTimer.Time = time2; - vistaTimer.Expiry = expiry; + vistaTimer.Expiry = Constants.TimerMax; string vistaTimerName = string.Format("msft:sl/timer/VLExpiration/VOLUME/{0}/{1}", appId, actId); store.DeleteBlock(key, vistaTimerName); - store.DeleteBlock(key, "45E81E65-6944-422E-9C02-D83F7E5F5A58"); + store.DeleteBlock(key, actId.ToString()); + + BinaryWriter writer = new BinaryWriter(new MemoryStream()); + writer.Write(Constants.KMSv4Response.Length); + writer.Write(Constants.KMSv4Response); + writer.Write(Constants.UniversalHWIDBlock); + byte[] kmsData = writer.GetBytes(); store.AddBlocks(new PSBlock[] { @@ -84,8 +91,8 @@ namespace LibTSforge.Activators Type = BlockType.NAMED, Flags = 0, KeyAsStr = key, - ValueAsStr = "45E81E65-6944-422E-9C02-D83F7E5F5A58", - Data = new Guid().ToByteArray() + ValueAsStr = actId.ToString(), + Data = kmsData } }); } @@ -191,7 +198,7 @@ namespace LibTSforge.Activators } } - SPPUtils.RestartSPP(version); + SPPUtils.RestartSPP(version); SLApi.FireStateChangedEvent(appId); Logger.WriteLine("Activated using KMS4k successfully."); } diff --git a/LibTSforge/Common.cs b/LibTSforge/Common.cs index 6973f6f..a1b4294 100644 --- a/LibTSforge/Common.cs +++ b/LibTSforge/Common.cs @@ -87,8 +87,8 @@ namespace LibTSforge 0x92, 0xA6, 0x56, 0x96 }; - // 2^31 - 1 minutes - public static ulong TimerMax = (ulong)TimeSpan.FromMinutes(2147483647).Ticks; + // 2^31 - 8 minutes + public static ulong TimerMax = (ulong)TimeSpan.FromMinutes(2147483640).Ticks; public static readonly string ZeroCID = new string('0', 48); } diff --git a/LibTSforge/Modifiers/KeyChangeLockDelete.cs b/LibTSforge/Modifiers/KeyChangeLockDelete.cs index 5150a41..3883d3c 100644 --- a/LibTSforge/Modifiers/KeyChangeLockDelete.cs +++ b/LibTSforge/Modifiers/KeyChangeLockDelete.cs @@ -5,11 +5,14 @@ namespace LibTSforge.Modifiers using LibTSforge.PhysicalStore; using LibTSforge.SPP; using LibTSforge; + using System; public static class KeyChangeLockDelete { public static void Delete(PSVersion version, bool production) { + if (version == PSVersion.Vista) throw new NotSupportedException("This feature is not supported on Windows Vista/Server 2008."); + SPPUtils.KillSPP(version); Logger.WriteLine("Writing TrustedStore data..."); using (IPhysicalStore store = SPPUtils.GetStore(version, production)) diff --git a/LibTSforge/Modifiers/RearmReset.cs b/LibTSforge/Modifiers/RearmReset.cs index a17c005..4b611b6 100644 --- a/LibTSforge/Modifiers/RearmReset.cs +++ b/LibTSforge/Modifiers/RearmReset.cs @@ -2,6 +2,7 @@ namespace LibTSforge.Modifiers { using System; using System.Collections.Generic; + using System.Data; using System.Linq; using LibTSforge.PhysicalStore; using LibTSforge.SPP; @@ -18,7 +19,11 @@ namespace LibTSforge.Modifiers { List blocks; - if (version == PSVersion.Win7) + if (version == PSVersion.Vista) + { + blocks = store.FindBlocks("740D70D8-6448-4b2f-9063-4A7A463600C5").ToList(); + } + else if (version == PSVersion.Win7) { blocks = store.FindBlocks(0xA0000).ToList(); } @@ -29,7 +34,11 @@ namespace LibTSforge.Modifiers foreach (PSBlock block in blocks) { - if (version == PSVersion.Win7) + if (version == PSVersion.Vista) + { + store.DeleteBlock(block.KeyAsStr, block.ValueAsStr); + } + else if (version == PSVersion.Win7) { store.SetBlock(block.KeyAsStr, block.ValueAsInt, new byte[8]); } diff --git a/LibTSforge/Modifiers/TamperedFlagsDelete.cs b/LibTSforge/Modifiers/TamperedFlagsDelete.cs index 55ba1ec..ecd9267 100644 --- a/LibTSforge/Modifiers/TamperedFlagsDelete.cs +++ b/LibTSforge/Modifiers/TamperedFlagsDelete.cs @@ -15,21 +15,24 @@ namespace LibTSforge.Modifiers using (IPhysicalStore store = SPPUtils.GetStore(version, production)) { - if (version != PSVersion.Win7) + if (version == PSVersion.Vista) { - string recreatedFlag = "__##USERSEP-RESERVED##__$$RECREATED-FLAG$$"; - string recoveredFlag = "__##USERSEP-RESERVED##__$$RECOVERED-FLAG$$"; - - DeleteFlag(store, recreatedFlag); - DeleteFlag(store, recoveredFlag); + DeleteFlag(store, "6BE8425B-E3CF-4e86-A6AF-5863E3DCB606"); + } + else if (version == PSVersion.Win7) + { + SetFlag(store, 0xA0001); } else { - SetFlag(store, 0xA0001); + DeleteFlag(store, "__##USERSEP-RESERVED##__$$RECREATED-FLAG$$"); + DeleteFlag(store, "__##USERSEP-RESERVED##__$$RECOVERED-FLAG$$"); } Logger.WriteLine("Successfully cleared the tamper state."); } + + SPPUtils.RestartSPP(version); } private static void DeleteFlag(IPhysicalStore store, string flag) diff --git a/LibTSforge/SPP/SPPUtils.cs b/LibTSforge/SPP/SPPUtils.cs index f1aa32f..08dbe03 100644 --- a/LibTSforge/SPP/SPPUtils.cs +++ b/LibTSforge/SPP/SPPUtils.cs @@ -252,6 +252,8 @@ namespace LibTSforge.SPP File.WriteAllBytes(filePath, PhysStoreCrypto.DecryptPhysicalStore(encrData, production, version)); } + RestartSPP(version); + Logger.WriteLine("Store dumped successfully to '" + filePath + "'."); } @@ -269,6 +271,8 @@ namespace LibTSforge.SPP store.WriteRaw(File.ReadAllBytes(filePath)); } + RestartSPP(version); + Logger.WriteLine("Loaded store file succesfully."); } } From 1cf9823ad3defaf063f7306540e5f1bcbf9acbe7 Mon Sep 17 00:00:00 2001 From: WitherOrNot Date: Sun, 2 Mar 2025 20:04:15 -0500 Subject: [PATCH 03/34] remove debug prints, partially fix compatibility with vista rtm --- LibTSforge/Activators/ZeroCID.cs | 6 ------ LibTSforge/SPP/SLAPI.cs | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/LibTSforge/Activators/ZeroCID.cs b/LibTSforge/Activators/ZeroCID.cs index 6264f1d..255eea2 100644 --- a/LibTSforge/Activators/ZeroCID.cs +++ b/LibTSforge/Activators/ZeroCID.cs @@ -116,13 +116,7 @@ namespace LibTSforge.Activators 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) diff --git a/LibTSforge/SPP/SLAPI.cs b/LibTSforge/SPP/SLAPI.cs index 336d88f..c25fb03 100644 --- a/LibTSforge/SPP/SLAPI.cs +++ b/LibTSforge/SPP/SLAPI.cs @@ -165,7 +165,7 @@ namespace LibTSforge.SPP uint count; IntPtr pProductKeyIds; - status = SLGetInstalledProductKeyIds(sl.Handle, ref actId, out count, out pProductKeyIds); + status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_PRODUCT_SKU, ref actId, SLIDTYPE.SL_ID_PKEY, out count, out pProductKeyIds); if (status != 0 || count == 0) { From 74cce5e941aee0fa24062da84b285b19db3c79f5 Mon Sep 17 00:00:00 2001 From: WitherOrNot Date: Sun, 2 Mar 2025 20:10:04 -0500 Subject: [PATCH 04/34] disable kmsc support for vista until it can be implemented --- LibTSforge/Modifiers/KMSHostCharge.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LibTSforge/Modifiers/KMSHostCharge.cs b/LibTSforge/Modifiers/KMSHostCharge.cs index a2f2423..b10a864 100644 --- a/LibTSforge/Modifiers/KMSHostCharge.cs +++ b/LibTSforge/Modifiers/KMSHostCharge.cs @@ -9,6 +9,8 @@ namespace LibTSforge.Modifiers { public static void Charge(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) { actId = SLApi.GetDefaultActivationID(SLApi.WINDOWS_APP_ID, true); From 4c7c58e62d8176c253c860360ef5211b6bcdb40e Mon Sep 17 00:00:00 2001 From: WitherOrNot Date: Mon, 3 Mar 2025 14:37:29 -0500 Subject: [PATCH 05/34] Add kmsc support for vista --- LibTSforge/Modifiers/KMSHostCharge.cs | 153 ++++++++++++++++---------- 1 file changed, 95 insertions(+), 58 deletions(-) diff --git a/LibTSforge/Modifiers/KMSHostCharge.cs b/LibTSforge/Modifiers/KMSHostCharge.cs index b10a864..94f4dfd 100644 --- a/LibTSforge/Modifiers/KMSHostCharge.cs +++ b/LibTSforge/Modifiers/KMSHostCharge.cs @@ -9,8 +9,6 @@ namespace LibTSforge.Modifiers { public static void Charge(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) { actId = SLApi.GetDefaultActivationID(SLApi.WINDOWS_APP_ID, true); @@ -33,76 +31,113 @@ namespace LibTSforge.Modifiers string key = string.Format("SPPSVC\\{0}", appId); long ldapTimestamp = DateTime.Now.ToFileTime(); + byte[] cmidGuids = new byte[] { }; + byte[] reqCounts = new byte[] { }; + byte[] kmsChargeData = new byte[] { }; + BinaryWriter writer = new BinaryWriter(new MemoryStream()); - for (int i = 0; i < currClients; i++) + if (version == PSVersion.Vista) { - writer.Write(ldapTimestamp - (10 * (i + 1))); - writer.Write(Guid.NewGuid().ToByteArray()); + writer.Write(new byte[44]); + writer.Seek(0, SeekOrigin.Begin); + + writer.Write(totalClients); + writer.Write(43200); + writer.Write(32); + + writer.Seek(20, SeekOrigin.Begin); + writer.Write((byte)currClients); + + writer.Seek(32, SeekOrigin.Begin); + writer.Write((byte)currClients); + + writer.Seek(0, SeekOrigin.End); + + for (int i = 0; i < currClients; i++) + { + writer.Write(Guid.NewGuid().ToByteArray()); + writer.Write(ldapTimestamp - (10 * (i + 1))); + } + + kmsChargeData = writer.GetBytes(); + } + else + { + for (int i = 0; i < currClients; i++) + { + writer.Write(ldapTimestamp - (10 * (i + 1))); + writer.Write(Guid.NewGuid().ToByteArray()); + } + + cmidGuids = writer.GetBytes(); + + writer = new BinaryWriter(new MemoryStream()); + + writer.Write(new byte[40]); + + writer.Seek(4, SeekOrigin.Begin); + writer.Write((byte)currClients); + + writer.Seek(24, SeekOrigin.Begin); + writer.Write((byte)currClients); + + reqCounts = writer.GetBytes(); } - byte[] cmidGuids = writer.GetBytes(); - - writer = new BinaryWriter(new MemoryStream()); - - writer.Write(new byte[40]); - - writer.Seek(4, SeekOrigin.Begin); - writer.Write((byte)currClients); - - writer.Seek(24, SeekOrigin.Begin); - writer.Write((byte)currClients); - byte[] reqCounts = writer.GetBytes(); - SPPUtils.KillSPP(version); Logger.WriteLine("Writing TrustedStore data..."); using (IPhysicalStore store = SPPUtils.GetStore(version, production)) { - VariableBag kmsCountData = new VariableBag(version); - kmsCountData.Blocks.AddRange(new CRCBlockModern[] + if (version != PSVersion.Vista) { - new CRCBlockModern + VariableBag kmsCountData = new VariableBag(version); + kmsCountData.Blocks.AddRange(new CRCBlockModern[] { - DataType = CRCBlockType.BINARY, - KeyAsStr = "SppBindingLicenseData", - Value = hwidBlock - }, - new CRCBlockModern - { - DataType = CRCBlockType.UINT, - Key = new byte[] { }, - ValueAsInt = (uint)totalClients - }, - new CRCBlockModern - { - DataType = CRCBlockType.UINT, - Key = new byte[] { }, - ValueAsInt = 1051200000 - }, - new CRCBlockModern - { - DataType = CRCBlockType.UINT, - Key = new byte[] { }, - ValueAsInt = (uint)currClients - }, - new CRCBlockModern - { - DataType = CRCBlockType.BINARY, - Key = new byte[] { }, - Value = cmidGuids - }, - new CRCBlockModern - { - DataType = CRCBlockType.BINARY, - Key = new byte[] { }, - Value = reqCounts - } - }); + new CRCBlockModern + { + DataType = CRCBlockType.BINARY, + KeyAsStr = "SppBindingLicenseData", + Value = hwidBlock + }, + new CRCBlockModern + { + DataType = CRCBlockType.UINT, + Key = new byte[] { }, + ValueAsInt = (uint)totalClients + }, + new CRCBlockModern + { + DataType = CRCBlockType.UINT, + Key = new byte[] { }, + ValueAsInt = 1051200000 + }, + new CRCBlockModern + { + DataType = CRCBlockType.UINT, + Key = new byte[] { }, + ValueAsInt = (uint)currClients + }, + new CRCBlockModern + { + DataType = CRCBlockType.BINARY, + Key = new byte[] { }, + Value = cmidGuids + }, + new CRCBlockModern + { + DataType = CRCBlockType.BINARY, + Key = new byte[] { }, + Value = reqCounts + } + }); - byte[] kmsChargeData = kmsCountData.Serialize(); - string countVal = string.Format("msft:spp/kms/host/2.0/store/counters/{0}", appId); + kmsChargeData = kmsCountData.Serialize(); + } + + string countVal = version == PSVersion.Vista ? "C8F6FFF1-79CE-404C-B150-F97991273DF1" : string.Format("msft:spp/kms/host/2.0/store/counters/{0}", appId); store.DeleteBlock(key, countVal); store.AddBlock(new PSBlock @@ -116,6 +151,8 @@ namespace LibTSforge.Modifiers Logger.WriteLine(string.Format("Set charge count to {0} successfully.", currClients)); } + + SPPUtils.RestartSPP(version); } } } From 137f634f1dff751bc4d00a715f45c97502446521 Mon Sep 17 00:00:00 2001 From: WitherOrNot Date: Mon, 3 Mar 2025 14:58:51 -0500 Subject: [PATCH 06/34] Update README.md --- README.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7ad1011..4e2103c 100644 --- a/README.md +++ b/README.md @@ -73,9 +73,26 @@ You can use the `/igpk` switch in TSforge in order to install licenses by only u You can use the `/igpk` and `/zcid` options with the activation ID of the KMS Host SKU to be activated. You can then use the `/kmsc` option with this activation ID to charge the KMS server with 25 clients. Please note that KMS servers will maintain their client counts for a maximum of 30 days. -### Why is Windows Vista not supported by any activation methods? +### What features are implemented in Windows Vista? -Windows Vista contains a driver which holds a permanent [handle](https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/object-handles) to the physical store, even when SLSvc is stopped after initial startup. This prevents TSforge from writing new trusted store data while the system is booted. There are theoretical workarounds to this issue, but they require an extraordinary amount of bug-prone, specialized code specific to Vista. For these reasons, we do not plan to support Vista/Server 2008. +The following options are implemented: + + - `/dump` + - `/load` + - `/zcid` + - `/kms4k` + - `/rtmr` + - `/rrmc` + - `/kmsc` + - `/ctpr` + +The following options are NOT implemented: + + - `/duid` + - `/igpk` + - `/revl` + + Effectively, this means that a product key must be provided to activate a given SKU. Additionally, ZeroCID on Vista/Server 2008 lacks protection against WGA. ### How do I prevent de-activation due to WAT on Windows 7? From bcebe2248cba255b5102b3e329841de2d388fd41 Mon Sep 17 00:00:00 2001 From: WitherOrNot Date: Mon, 3 Mar 2025 15:08:01 -0500 Subject: [PATCH 07/34] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4e2103c..f411c9f 100644 --- a/README.md +++ b/README.md @@ -88,9 +88,9 @@ The following options are implemented: The following options are NOT implemented: - - `/duid` - - `/igpk` - - `/revl` + - `/duid` - Key Unique ID is not removable from Vista physical store + - `/igpk` - Product key data is derived directly from the key string, preventing forgery + - `/revl` - Eval key lock is not present on Vista Effectively, this means that a product key must be provided to activate a given SKU. Additionally, ZeroCID on Vista/Server 2008 lacks protection against WGA. From 07f43e261381c8b9229fcf376e310d8f02ccb16d Mon Sep 17 00:00:00 2001 From: Lyssa Date: Wed, 2 Apr 2025 13:53:00 +0400 Subject: [PATCH 08/34] move detectcurrentkey to common --- LibTSforge/Common.cs | 18 ------------------ LibTSforge/SPP/SPPUtils.cs | 20 ++++++++++++++++++-- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/LibTSforge/Common.cs b/LibTSforge/Common.cs index a1b4294..4a95a08 100644 --- a/LibTSforge/Common.cs +++ b/LibTSforge/Common.cs @@ -243,24 +243,6 @@ namespace LibTSforge throw new NotSupportedException("Unable to auto-detect version info"); } - - public static bool DetectCurrentKey() - { - SLApi.RefreshLicenseStatus(); - - using (RegistryKey wpaKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\WPA")) - { - foreach (string subKey in wpaKey.GetSubKeyNames()) - { - if (subKey.StartsWith("8DEC0AF1")) - { - return subKey.Contains("P"); - } - } - } - - throw new FileNotFoundException("Failed to autodetect key type, specify physical store key with /prod or /test arguments."); - } } public static class Logger diff --git a/LibTSforge/SPP/SPPUtils.cs b/LibTSforge/SPP/SPPUtils.cs index 08dbe03..1046439 100644 --- a/LibTSforge/SPP/SPPUtils.cs +++ b/LibTSforge/SPP/SPPUtils.cs @@ -5,11 +5,9 @@ namespace LibTSforge.SPP 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 { @@ -130,6 +128,24 @@ namespace LibTSforge.SPP SLApi.RefreshLicenseStatus(); } + public static bool DetectCurrentKey() + { + SLApi.RefreshLicenseStatus(); + + using (RegistryKey wpaKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\WPA")) + { + foreach (string subKey in wpaKey.GetSubKeyNames()) + { + if (subKey.StartsWith("8DEC0AF1")) + { + return subKey.Contains("P"); + } + } + } + + throw new FileNotFoundException("Failed to autodetect key type, specify physical store key with /prod or /test arguments."); + } + public static string GetPSPath(PSVersion version) { switch (version) From b8558d8fb2de25a97572ec9d3e33618b8fac3027 Mon Sep 17 00:00:00 2001 From: Lyssa Date: Wed, 2 Apr 2025 14:06:52 +0400 Subject: [PATCH 09/34] basic cleanup --- LibTSforge/Activators/KMS4K.cs | 8 +++-- LibTSforge/Common.cs | 6 ---- LibTSforge/Crypto/PhysStoreCrypto.cs | 2 -- LibTSforge/Modifiers/GracePeriodReset.cs | 1 - LibTSforge/Modifiers/RearmReset.cs | 2 -- LibTSforge/Modifiers/TamperedFlagsDelete.cs | 1 - LibTSforge/PhysicalStore/VariableBag.cs | 3 +- LibTSforge/SPP/PKeyConfig.cs | 36 ++++++++++++--------- LibTSforge/SPP/SPSys.cs | 7 ++-- LibTSforge/TokenStore/TokenStoreModern.cs | 5 ++- 10 files changed, 30 insertions(+), 41 deletions(-) diff --git a/LibTSforge/Activators/KMS4K.cs b/LibTSforge/Activators/KMS4K.cs index 01b7395..a68e263 100644 --- a/LibTSforge/Activators/KMS4K.cs +++ b/LibTSforge/Activators/KMS4K.cs @@ -61,9 +61,11 @@ namespace LibTSforge.Activators if (version == PSVersion.Vista) { - VistaTimer vistaTimer = new VistaTimer(); - vistaTimer.Time = time2; - vistaTimer.Expiry = Constants.TimerMax; + VistaTimer vistaTimer = new VistaTimer + { + Time = time2, + Expiry = Constants.TimerMax + }; string vistaTimerName = string.Format("msft:sl/timer/VLExpiration/VOLUME/{0}/{1}", appId, actId); diff --git a/LibTSforge/Common.cs b/LibTSforge/Common.cs index 4a95a08..75e31e4 100644 --- a/LibTSforge/Common.cs +++ b/LibTSforge/Common.cs @@ -1,16 +1,10 @@ namespace LibTSforge { - using Microsoft.Win32; using System; using System.IO; using System.Linq; using System.Runtime.InteropServices; - using System.ServiceProcess; using System.Text; - using LibTSforge.Crypto; - using LibTSforge.PhysicalStore; - using LibTSforge.SPP; - using LibTSforge.TokenStore; public enum PSVersion { diff --git a/LibTSforge/Crypto/PhysStoreCrypto.cs b/LibTSforge/Crypto/PhysStoreCrypto.cs index c0491db..b0acc2e 100644 --- a/LibTSforge/Crypto/PhysStoreCrypto.cs +++ b/LibTSforge/Crypto/PhysStoreCrypto.cs @@ -2,10 +2,8 @@ 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 diff --git a/LibTSforge/Modifiers/GracePeriodReset.cs b/LibTSforge/Modifiers/GracePeriodReset.cs index ddca3f7..059b1c5 100644 --- a/LibTSforge/Modifiers/GracePeriodReset.cs +++ b/LibTSforge/Modifiers/GracePeriodReset.cs @@ -1,6 +1,5 @@ namespace LibTSforge.Modifiers { - using System; using System.Collections.Generic; using System.Linq; using LibTSforge.PhysicalStore; diff --git a/LibTSforge/Modifiers/RearmReset.cs b/LibTSforge/Modifiers/RearmReset.cs index 4b611b6..89a12f3 100644 --- a/LibTSforge/Modifiers/RearmReset.cs +++ b/LibTSforge/Modifiers/RearmReset.cs @@ -1,8 +1,6 @@ namespace LibTSforge.Modifiers { - using System; using System.Collections.Generic; - using System.Data; using System.Linq; using LibTSforge.PhysicalStore; using LibTSforge.SPP; diff --git a/LibTSforge/Modifiers/TamperedFlagsDelete.cs b/LibTSforge/Modifiers/TamperedFlagsDelete.cs index ecd9267..8369d4e 100644 --- a/LibTSforge/Modifiers/TamperedFlagsDelete.cs +++ b/LibTSforge/Modifiers/TamperedFlagsDelete.cs @@ -1,6 +1,5 @@ namespace LibTSforge.Modifiers { - using System; using System.Linq; using LibTSforge.PhysicalStore; using LibTSforge.SPP; diff --git a/LibTSforge/PhysicalStore/VariableBag.cs b/LibTSforge/PhysicalStore/VariableBag.cs index 76098a9..ebe413f 100644 --- a/LibTSforge/PhysicalStore/VariableBag.cs +++ b/LibTSforge/PhysicalStore/VariableBag.cs @@ -3,7 +3,6 @@ namespace LibTSforge.PhysicalStore using System; using System.Collections.Generic; using System.IO; - using System.Runtime.CompilerServices; public enum CRCBlockType : uint { @@ -155,7 +154,7 @@ namespace LibTSforge.PhysicalStore public class VariableBag { public List Blocks = new List(); - private PSVersion Version; + private readonly PSVersion Version; public void Deserialize(byte[] data) { diff --git a/LibTSforge/SPP/PKeyConfig.cs b/LibTSforge/SPP/PKeyConfig.cs index a608608..6733940 100644 --- a/LibTSforge/SPP/PKeyConfig.cs +++ b/LibTSforge/SPP/PKeyConfig.cs @@ -75,7 +75,7 @@ namespace LibTSforge.SPP public class PKeyConfig { public Dictionary Products = new Dictionary(); - private List loadedPkeyConfigs = new List(); + private readonly List loadedPkeyConfigs = new List(); public void LoadConfig(Guid actId) { @@ -136,12 +136,14 @@ namespace LibTSforge.SPP ranges[refActIdStr] = new List(); } - KeyRange keyRange = new KeyRange(); - keyRange.Start = int.Parse(rangeNode.SelectSingleNode("./p:Start", nsmgr).InnerText); - keyRange.End = int.Parse(rangeNode.SelectSingleNode("./p:End", nsmgr).InnerText); - keyRange.EulaType = rangeNode.SelectSingleNode("./p:EulaType", nsmgr).InnerText; - keyRange.PartNumber = rangeNode.SelectSingleNode("./p:PartNumber", nsmgr).InnerText; - keyRange.Valid = rangeNode.SelectSingleNode("./p:IsValid", nsmgr).InnerText.ToLower() == "true"; + KeyRange keyRange = new KeyRange + { + Start = int.Parse(rangeNode.SelectSingleNode("./p:Start", nsmgr).InnerText), + End = int.Parse(rangeNode.SelectSingleNode("./p:End", nsmgr).InnerText), + EulaType = rangeNode.SelectSingleNode("./p:EulaType", nsmgr).InnerText, + PartNumber = rangeNode.SelectSingleNode("./p:PartNumber", nsmgr).InnerText, + Valid = rangeNode.SelectSingleNode("./p:IsValid", nsmgr).InnerText.ToLower() == "true" + }; ranges[refActIdStr].Add(keyRange); } @@ -155,15 +157,17 @@ namespace LibTSforge.SPP if (keyRanges.Count > 0 && !Products.ContainsKey(refActId)) { - ProductConfig productConfig = new ProductConfig(); - productConfig.GroupId = group; - productConfig.Edition = configNode.SelectSingleNode("./p:EditionId", nsmgr).InnerText; - productConfig.Description = configNode.SelectSingleNode("./p:ProductDescription", nsmgr).InnerText; - productConfig.Channel = configNode.SelectSingleNode("./p:ProductKeyType", nsmgr).InnerText; - productConfig.Randomized = configNode.SelectSingleNode("./p:ProductKeyType", nsmgr).InnerText.ToLower() == "true"; - productConfig.Algorithm = algorithms[group]; - productConfig.Ranges = keyRanges; - productConfig.ActivationId = refActId; + ProductConfig productConfig = new ProductConfig + { + GroupId = group, + Edition = configNode.SelectSingleNode("./p:EditionId", nsmgr).InnerText, + Description = configNode.SelectSingleNode("./p:ProductDescription", nsmgr).InnerText, + Channel = configNode.SelectSingleNode("./p:ProductKeyType", nsmgr).InnerText, + Randomized = configNode.SelectSingleNode("./p:ProductKeyType", nsmgr).InnerText.ToLower() == "true", + Algorithm = algorithms[group], + Ranges = keyRanges, + ActivationId = refActId + }; Products[refActId] = productConfig; } diff --git a/LibTSforge/SPP/SPSys.cs b/LibTSforge/SPP/SPSys.cs index 10b8d04..18b3655 100644 --- a/LibTSforge/SPP/SPSys.cs +++ b/LibTSforge/SPP/SPSys.cs @@ -2,10 +2,7 @@ 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 { @@ -24,7 +21,7 @@ namespace LibTSforge.SPP { SafeFileHandle file = CreateFileSafe(@"\\.\SpDevice"); IntPtr buffer = Marshal.AllocHGlobal(1); - int bytesReturned = 0; + int bytesReturned; DeviceIoControl(file, 0x80006008, IntPtr.Zero, 0, buffer, 1, out bytesReturned, IntPtr.Zero); bool running = Marshal.ReadByte(buffer) != 0; Marshal.FreeHGlobal(buffer); @@ -36,7 +33,7 @@ namespace LibTSforge.SPP { SafeFileHandle file = CreateFileSafe(@"\\.\SpDevice"); IntPtr buffer = Marshal.AllocHGlobal(4); - int bytesReturned = 0; + int bytesReturned; DeviceIoControl(file, start ? 0x8000a000 : 0x8000a004, IntPtr.Zero, 0, buffer, 4, out bytesReturned, IntPtr.Zero); int result = Marshal.ReadInt32(buffer); Marshal.FreeHGlobal(buffer); diff --git a/LibTSforge/TokenStore/TokenStoreModern.cs b/LibTSforge/TokenStore/TokenStoreModern.cs index c3483ff..cfb35d0 100644 --- a/LibTSforge/TokenStore/TokenStoreModern.cs +++ b/LibTSforge/TokenStore/TokenStoreModern.cs @@ -25,17 +25,16 @@ namespace LibTSforge.TokenStore if (TokensFile.Length < BLOCK_SIZE) return; TokensFile.Seek(0x24, SeekOrigin.Begin); - uint nextBlock = 0; + uint nextBlock; BinaryReader reader = new BinaryReader(TokensFile); do { - uint curOffset = reader.ReadUInt32(); nextBlock = reader.ReadUInt32(); for (int i = 0; i < ENTRIES_PER_BLOCK; i++) { - curOffset = reader.ReadUInt32(); + uint curOffset = reader.ReadUInt32(); bool populated = reader.ReadUInt32() == 1; uint contentOffset = reader.ReadUInt32(); uint contentLength = reader.ReadUInt32(); From accbed0c514fc4ad1eaf5691cb89421f0485b5d6 Mon Sep 17 00:00:00 2001 From: Lyssa Date: Wed, 2 Apr 2025 14:34:11 +0400 Subject: [PATCH 10/34] fix build --- LibTSforge/Activators/ZeroCID.cs | 3 ++- TSforgeCLI/Program.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/LibTSforge/Activators/ZeroCID.cs b/LibTSforge/Activators/ZeroCID.cs index 255eea2..1675173 100644 --- a/LibTSforge/Activators/ZeroCID.cs +++ b/LibTSforge/Activators/ZeroCID.cs @@ -111,7 +111,8 @@ namespace LibTSforge.Activators try { shortauth = BitConverter.ToUInt64(Convert.FromBase64String(uniqueId.Split('&')[1]), 0); - } catch + } + catch { throw new FormatException("Key Unique ID has invalid format."); } diff --git a/TSforgeCLI/Program.cs b/TSforgeCLI/Program.cs index 8581b5c..2c636b4 100644 --- a/TSforgeCLI/Program.cs +++ b/TSforgeCLI/Program.cs @@ -52,7 +52,7 @@ namespace TSforgeCLI } PSVersion version = options.Version ?? Utils.DetectVersion(); - bool production = options.Production ?? Utils.DetectCurrentKey(); + bool production = options.Production ?? SPPUtils.DetectCurrentKey(); if (options.Dump) { From 1286b585015b085672afbadcc1408584bab94df2 Mon Sep 17 00:00:00 2001 From: Lyssa Date: Wed, 2 Apr 2025 18:23:16 +0400 Subject: [PATCH 11/34] fix dumping vista store (really hacky fix) --- LibTSforge/SPP/SPPUtils.cs | 33 ++++++++++++++-------- TSforgeCLI/Properties/launchSettings.json | 8 ++++++ vista.dat | Bin 0 -> 21788 bytes 3 files changed, 30 insertions(+), 11 deletions(-) create mode 100644 TSforgeCLI/Properties/launchSettings.json create mode 100644 vista.dat diff --git a/LibTSforge/SPP/SPPUtils.cs b/LibTSforge/SPP/SPPUtils.cs index 1046439..1a6ef62 100644 --- a/LibTSforge/SPP/SPPUtils.cs +++ b/LibTSforge/SPP/SPPUtils.cs @@ -46,8 +46,9 @@ namespace LibTSforge.SPP { continue; } - catch (InvalidOperationException) + catch (InvalidOperationException ex) { + Logger.WriteLine("Warning: Stopping sppsvc failed, retrying. Details:" + ex.Message); System.Threading.Thread.Sleep(500); continue; } @@ -110,8 +111,9 @@ namespace LibTSforge.SPP { continue; } - catch (InvalidOperationException) + catch (InvalidOperationException ex) { + Logger.WriteLine("Warning: Starting slsvc failed, retrying. Details:" + ex.Message); System.Threading.Thread.Sleep(500); continue; } @@ -250,9 +252,13 @@ namespace LibTSforge.SPP public static void DumpStore(PSVersion version, bool production, string filePath, string encrFilePath) { + bool manageSpp = false; + if (encrFilePath == null) { encrFilePath = GetPSPath(version); + manageSpp = true; + KillSPP(version); } if (string.IsNullOrEmpty(encrFilePath) || !File.Exists(encrFilePath)) @@ -260,17 +266,22 @@ namespace LibTSforge.SPP 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)) + try { - byte[] encrData = fs.ReadAllBytes(); - File.WriteAllBytes(filePath, PhysStoreCrypto.DecryptPhysicalStore(encrData, production, version)); + using (FileStream fs = File.Open(encrFilePath, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + byte[] encrData = fs.ReadAllBytes(); + File.WriteAllBytes(filePath, PhysStoreCrypto.DecryptPhysicalStore(encrData, production, version)); + } + Logger.WriteLine("Store dumped successfully to '" + filePath + "'."); + } + finally + { + if (manageSpp) + { + RestartSPP(version); + } } - - RestartSPP(version); - - Logger.WriteLine("Store dumped successfully to '" + filePath + "'."); } public static void LoadStore(PSVersion version, bool production, string filePath) diff --git a/TSforgeCLI/Properties/launchSettings.json b/TSforgeCLI/Properties/launchSettings.json new file mode 100644 index 0000000..112530f --- /dev/null +++ b/TSforgeCLI/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "TSforgeCLI": { + "commandName": "Project", + "commandLineArgs": "/dump vista.dat blah.dat /ver vista" + } + } +} \ No newline at end of file diff --git a/vista.dat b/vista.dat new file mode 100644 index 0000000000000000000000000000000000000000..97ff49778873106e1718cf29ab3cc6f785cae8e4 GIT binary patch literal 21788 zcmeHP3wTt;*`5R>B8sWD3TggnRDix zJ!ig|Z@&5Fd%u}E3xkCWU2*J#=oH!bIYpjG5Cyo?N0f;QQ7wu@A`EOQ$UY6g)jQbi{IGvMDOk%8+tH?6~$ zR0wj@u;U!-PFISFqEyt1!8lLAFH#hvl*MA4D8Zdtl)46~NRc8c<^6PAO~t!sjE6VP z{baVSvSR1|#cX|K^q2#^x9$oVcO>^z)cKsdKX3eZ?@5zK7Yz8K_sVS_t^53~l`p%V zy?gYC2Y;Piof?UK5%%bJwl8{ay%a5bBUF&ohzKC=zt&=Q&8ae~MK--m+Bsy&gl3^_Qq z-G*#cB@JU*wWeyv0^}Db+mI3z2O3E-FCn@h*Hbqu3IcNFUp)>DSiJdP%g^Q2)vQ|nVXs@e zuPDhF_w2f+(CLdhf4XkE?RCdrUMLNlmmRV{IHkwpx7XEuv~ksex__lRFO`j)vt|Cl z#(l32n|(U*waw9m>06#Z{pai_Tup02)5FYZ+x}--_t?z`d#3KKa#x}f=k9BVzS8-< zJqzBPuye}xwKHBZHbo`ze#Bs>`zc7Cp1fvlDMRe5S!nI%UaR=-?6qXhK(urHTN?dw zy3!}z1d;9`y{i2+-QnH(f$TRLEq`U3{B7nkHKhSMCIdVl;+C+Wv$xI21Gzpi`QWX$ zt~Np!mI@Q}UkQ#jyjv(7!j5PVRuPS}OWrHRRTNUC&_~gDt{7Jqq>MN-B}6B!0dekV z{l2i!bpy#!rv{^D&)}?e+}8TN7P_($_2XzX5oc=E1n?;mrPrtSk&tZ*_+Wz;tHB78 zjZtqBXyt%fEvSyiwUE3r;phMli}AbxX%o)mHThqH91OTBMLs5^$X_c`e7Y3>nUIqa zca?6Z`~*V3x0V^3Y=71w8l|zKq%M@sj%&({3wK$1N|6P1Qva678dK7uPzRf=r4YBE z4qE7FnfaTCO%MyBQHYvN(pqL{5m0WbF$!1U%+WVeS_UQJVYCC=li`isl)+d;+89^Q z?_qF+`4uBpp;fD;MAjltGu~%j(oVpcc0xEJgRkYIbk`tfmT$b6hO0=}HI#a4)xICz zvpfFz*Bptrglt?ev*6VBG)u30UhcN!c;7px&!0OW^wFiHJqwY2Nvn$u?HP~uN<;~n zW*ggND>9Xg`|+~1jp$R9Uyia?w0ttI*vt4t5`ID)fr^MsA&vM}G)iS(C;=TM`-PAr z_D<5EoRO{_TqAAjs3_bmM&wgPc&-FzD{^J-pPg%~9(Mfiz*9-cAx`FEMad|Qq~SnW z;=3N<>p!u?lb2i z(4)36;C?BtqER0k?y=^jxUwNv=AKZ%BYE{0qShX*WkJbP3FL`d#O2mOE@&Xia3u1h zzV^SrMxuO_fo3`V?<$)E-!6NkF*Sg;In+Mxn0OZ#aZ^f)_m2tY>*Poah)mJ0apCz zmuY^77KzG>{jt5EU$1YEitqpVf?a&i?fR3~ItN9U*GJE!lo&hFVMy6dZ}2kyGB zvGTF+mz@o}e?!&Dtl+Ybo)}@MS>Mw&D0J%`r;fey^Bxxm*VmrStv}$LlD_ijfMuKW z(PyZ8*?;)cbVs20a@Tq*r7x z{?*4G>MO@Xj)`#?kB4JqS84BKjEIp{eM59}vK}0h`?RWux1Es${*0IQJUs)7TfXYg z(I0QU!10HccE471ve6FAvjk;Tz6bglG#^BwOc&xUA&%E{DeXGt-x>3A<9_wk#JP`q z_E-6U`>=C&Y60mDa$kG5k9WN?QLBld>q)0uAL7qhh@Kc%KYsvopS!m$8v0`O*g2%Z zzb9!5u?rd?IT1aVP3y zXesJV?}Y)a^&gj^EJN| zITPZ9HsVaB5Va>dZ()AH=%SR%ac=x%mb@n4Xk#kB7rmFrr(Pf?$J6Z}MJrRPwy*fq!&P4Y+PkZz`PD5lhoCt8sDXeE8P+qO4K zpS-Wyk6Dc?m7x1hZDWx0cc@rDEa}}2k2W0M970( z%K1#rp$>*;EDs}CdLRh9X?W5PAlb{LHs&WaaU6|6?1AV#9$Xned6wIgZ_mBkZ#47M z4>#$h5&HrgYZxgBx;Ry?m3avA#+m0lX_E{CYErmq{$me*%6bqtwdRXAzGw?KT}f{q z|IUrQI6mo(lQ{k|u*?i;%O|hdJ|Il^i<9aWw}oN!!%3Vs9hlS>4SjLafiE@tHZVBp z%{^=h#%moXadw95OE~MxxmMc4Tuno(i1rcZcsXlr#8dp2o?`xQlJ9V}O|-P)g`fra z$r&7E=;(QzFCx+hlaSW#L<-*=Cv|;xP0_-Y9|u_%Y58>oPMYAxN%X^W-i)g^Ie*Sk zkr6Ai$aZ)<8C(#k{PzsRJ5FjR^ zwoIh*ahEHzxLzjOji0h{XBhrtD>LYYlal}R@++EsPu=W2UU}=~mh((jl%Hj`fT$THz$S)nJt~Ogxx?lPorqICdLwQeF{YlEq*$TaBc3 z>^3Uzu{&zJPpRMWw35+x@A;tY@L$Sz>y49USKP_!h;!vbf34L|51d5KlD94S%2i;# z#mF&F0QT|yFPOF?9UpH ze=+C6{^gTS{H*_P2A$uLHEiEWd-+pe9gO+p!9P?zeSSl&W%;>1Lz?1N9nCWy90eU) z~dTB(?FO|8GQVKkvX<{;B z4dw70$Cb<6*V6zs6Q)Qk!-8GUN>K@%l#o{KAw)hhKBpCTbc zM`N-so$sZhxZLaf!(=_r9GbQob63NsYI39pCi5&`JTA08?CV^Z+UduAeL0wc({`&k zRjp^wI__- z6`y84soW!#FYPMZxna#2y|HoLkHRL9Qm>RzN3{CsfsM&ou5ebIC0{)`>+2jM_oMkX zhp6A^p!n|Z@k+jMfAhWm{Y+pPm!5w=B=4a|iynS)QdrX;n=b4RDPKJQWbMGm*6r}b#?-aS2g*Jc znBa|#GodR3IfLkp%>z?oZz>n7Ei2AI()Jr4w z#W+3=qx}#dTw`r({K79E;NUm zL?RQ;HL2bC+*9q6*0s7re8-()TusV%iLq`%JU~?-Lr42K{xtS=Ht-j|LMP@7mqvWi=^z+lfaedMCklt23Mr>yA=GN-VW}g<*I5vO@9bIgOt2Y zr|z0UZNRiY`%H&HpJXC$e&r?_{4it3KpN87plrv?K#ELT;Pc3l>5)kB3m++<%b=H! zBRH)`KMkAHzW25@uQva$zDz)k(t4g+`8cxVDtYYPSb5gru(zYBi!bGDtH;n$sR)OR0;exrjv+`Za7mOfOj=W?xZpk<#v z|IhP%ej2jzT8SNMiR|S%OU}&{P zWpTe>j-W1%K>RvBjw|u4d`06}=GPxlA0LNa8nJnQX&LbDNE!LPwJLZ#MgSuXkUkI1 z$I;RA|2_X+RnKusZ(oP%pUBu927b2w=#C%w@9R+W|ICy&W2ig#))=(y?{a?q{h0Gs LQHmG?f%pCcE?fw> literal 0 HcmV?d00001 From 6c2df14898532996db6f23a220513e9d52eb6430 Mon Sep 17 00:00:00 2001 From: Lyssa Date: Wed, 2 Apr 2025 20:00:42 +0400 Subject: [PATCH 12/34] remove 8early --- LibTSforge/Common.cs | 1 - TSforgeCLI/Program.cs | 3 +-- vista.dat | Bin 21788 -> 0 bytes 3 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 vista.dat diff --git a/LibTSforge/Common.cs b/LibTSforge/Common.cs index 75e31e4..b9c274a 100644 --- a/LibTSforge/Common.cs +++ b/LibTSforge/Common.cs @@ -10,7 +10,6 @@ namespace LibTSforge { Vista, Win7, - Win8Early, Win8, WinBlue, WinModern diff --git a/TSforgeCLI/Program.cs b/TSforgeCLI/Program.cs index 2c636b4..865e51d 100644 --- a/TSforgeCLI/Program.cs +++ b/TSforgeCLI/Program.cs @@ -223,7 +223,7 @@ namespace TSforgeCLI Logger.WriteLine("\t/revl Remove the key change lock in evaluation edition store."); Logger.WriteLine("\t/prod Use SPP production key."); Logger.WriteLine("\t/test Use SPP test key."); - Logger.WriteLine("\t/ver Override the detected version. Available versions: vista, 7, 8early, 8, blue, modern."); + Logger.WriteLine("\t/ver Override the detected version. Available versions: vista, 7, 8, blue, modern."); Logger.WriteLine("\t A specific activation ID. Useful if you want to activate specific addons like ESU."); Logger.WriteLine("\t/? Display this help message."); } @@ -234,7 +234,6 @@ namespace TSforgeCLI { case "vista": return PSVersion.Vista; case "7": return PSVersion.Win7; - case "8early": return PSVersion.Win8Early; case "8": return PSVersion.Win8; case "blue": return PSVersion.WinBlue; case "modern": return PSVersion.WinModern; diff --git a/vista.dat b/vista.dat deleted file mode 100644 index 97ff49778873106e1718cf29ab3cc6f785cae8e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21788 zcmeHP3wTt;*`5R>B8sWD3TggnRDix zJ!ig|Z@&5Fd%u}E3xkCWU2*J#=oH!bIYpjG5Cyo?N0f;QQ7wu@A`EOQ$UY6g)jQbi{IGvMDOk%8+tH?6~$ zR0wj@u;U!-PFISFqEyt1!8lLAFH#hvl*MA4D8Zdtl)46~NRc8c<^6PAO~t!sjE6VP z{baVSvSR1|#cX|K^q2#^x9$oVcO>^z)cKsdKX3eZ?@5zK7Yz8K_sVS_t^53~l`p%V zy?gYC2Y;Piof?UK5%%bJwl8{ay%a5bBUF&ohzKC=zt&=Q&8ae~MK--m+Bsy&gl3^_Qq z-G*#cB@JU*wWeyv0^}Db+mI3z2O3E-FCn@h*Hbqu3IcNFUp)>DSiJdP%g^Q2)vQ|nVXs@e zuPDhF_w2f+(CLdhf4XkE?RCdrUMLNlmmRV{IHkwpx7XEuv~ksex__lRFO`j)vt|Cl z#(l32n|(U*waw9m>06#Z{pai_Tup02)5FYZ+x}--_t?z`d#3KKa#x}f=k9BVzS8-< zJqzBPuye}xwKHBZHbo`ze#Bs>`zc7Cp1fvlDMRe5S!nI%UaR=-?6qXhK(urHTN?dw zy3!}z1d;9`y{i2+-QnH(f$TRLEq`U3{B7nkHKhSMCIdVl;+C+Wv$xI21Gzpi`QWX$ zt~Np!mI@Q}UkQ#jyjv(7!j5PVRuPS}OWrHRRTNUC&_~gDt{7Jqq>MN-B}6B!0dekV z{l2i!bpy#!rv{^D&)}?e+}8TN7P_($_2XzX5oc=E1n?;mrPrtSk&tZ*_+Wz;tHB78 zjZtqBXyt%fEvSyiwUE3r;phMli}AbxX%o)mHThqH91OTBMLs5^$X_c`e7Y3>nUIqa zca?6Z`~*V3x0V^3Y=71w8l|zKq%M@sj%&({3wK$1N|6P1Qva678dK7uPzRf=r4YBE z4qE7FnfaTCO%MyBQHYvN(pqL{5m0WbF$!1U%+WVeS_UQJVYCC=li`isl)+d;+89^Q z?_qF+`4uBpp;fD;MAjltGu~%j(oVpcc0xEJgRkYIbk`tfmT$b6hO0=}HI#a4)xICz zvpfFz*Bptrglt?ev*6VBG)u30UhcN!c;7px&!0OW^wFiHJqwY2Nvn$u?HP~uN<;~n zW*ggND>9Xg`|+~1jp$R9Uyia?w0ttI*vt4t5`ID)fr^MsA&vM}G)iS(C;=TM`-PAr z_D<5EoRO{_TqAAjs3_bmM&wgPc&-FzD{^J-pPg%~9(Mfiz*9-cAx`FEMad|Qq~SnW z;=3N<>p!u?lb2i z(4)36;C?BtqER0k?y=^jxUwNv=AKZ%BYE{0qShX*WkJbP3FL`d#O2mOE@&Xia3u1h zzV^SrMxuO_fo3`V?<$)E-!6NkF*Sg;In+Mxn0OZ#aZ^f)_m2tY>*Poah)mJ0apCz zmuY^77KzG>{jt5EU$1YEitqpVf?a&i?fR3~ItN9U*GJE!lo&hFVMy6dZ}2kyGB zvGTF+mz@o}e?!&Dtl+Ybo)}@MS>Mw&D0J%`r;fey^Bxxm*VmrStv}$LlD_ijfMuKW z(PyZ8*?;)cbVs20a@Tq*r7x z{?*4G>MO@Xj)`#?kB4JqS84BKjEIp{eM59}vK}0h`?RWux1Es${*0IQJUs)7TfXYg z(I0QU!10HccE471ve6FAvjk;Tz6bglG#^BwOc&xUA&%E{DeXGt-x>3A<9_wk#JP`q z_E-6U`>=C&Y60mDa$kG5k9WN?QLBld>q)0uAL7qhh@Kc%KYsvopS!m$8v0`O*g2%Z zzb9!5u?rd?IT1aVP3y zXesJV?}Y)a^&gj^EJN| zITPZ9HsVaB5Va>dZ()AH=%SR%ac=x%mb@n4Xk#kB7rmFrr(Pf?$J6Z}MJrRPwy*fq!&P4Y+PkZz`PD5lhoCt8sDXeE8P+qO4K zpS-Wyk6Dc?m7x1hZDWx0cc@rDEa}}2k2W0M970( z%K1#rp$>*;EDs}CdLRh9X?W5PAlb{LHs&WaaU6|6?1AV#9$Xned6wIgZ_mBkZ#47M z4>#$h5&HrgYZxgBx;Ry?m3avA#+m0lX_E{CYErmq{$me*%6bqtwdRXAzGw?KT}f{q z|IUrQI6mo(lQ{k|u*?i;%O|hdJ|Il^i<9aWw}oN!!%3Vs9hlS>4SjLafiE@tHZVBp z%{^=h#%moXadw95OE~MxxmMc4Tuno(i1rcZcsXlr#8dp2o?`xQlJ9V}O|-P)g`fra z$r&7E=;(QzFCx+hlaSW#L<-*=Cv|;xP0_-Y9|u_%Y58>oPMYAxN%X^W-i)g^Ie*Sk zkr6Ai$aZ)<8C(#k{PzsRJ5FjR^ zwoIh*ahEHzxLzjOji0h{XBhrtD>LYYlal}R@++EsPu=W2UU}=~mh((jl%Hj`fT$THz$S)nJt~Ogxx?lPorqICdLwQeF{YlEq*$TaBc3 z>^3Uzu{&zJPpRMWw35+x@A;tY@L$Sz>y49USKP_!h;!vbf34L|51d5KlD94S%2i;# z#mF&F0QT|yFPOF?9UpH ze=+C6{^gTS{H*_P2A$uLHEiEWd-+pe9gO+p!9P?zeSSl&W%;>1Lz?1N9nCWy90eU) z~dTB(?FO|8GQVKkvX<{;B z4dw70$Cb<6*V6zs6Q)Qk!-8GUN>K@%l#o{KAw)hhKBpCTbc zM`N-so$sZhxZLaf!(=_r9GbQob63NsYI39pCi5&`JTA08?CV^Z+UduAeL0wc({`&k zRjp^wI__- z6`y84soW!#FYPMZxna#2y|HoLkHRL9Qm>RzN3{CsfsM&ou5ebIC0{)`>+2jM_oMkX zhp6A^p!n|Z@k+jMfAhWm{Y+pPm!5w=B=4a|iynS)QdrX;n=b4RDPKJQWbMGm*6r}b#?-aS2g*Jc znBa|#GodR3IfLkp%>z?oZz>n7Ei2AI()Jr4w z#W+3=qx}#dTw`r({K79E;NUm zL?RQ;HL2bC+*9q6*0s7re8-()TusV%iLq`%JU~?-Lr42K{xtS=Ht-j|LMP@7mqvWi=^z+lfaedMCklt23Mr>yA=GN-VW}g<*I5vO@9bIgOt2Y zr|z0UZNRiY`%H&HpJXC$e&r?_{4it3KpN87plrv?K#ELT;Pc3l>5)kB3m++<%b=H! zBRH)`KMkAHzW25@uQva$zDz)k(t4g+`8cxVDtYYPSb5gru(zYBi!bGDtH;n$sR)OR0;exrjv+`Za7mOfOj=W?xZpk<#v z|IhP%ej2jzT8SNMiR|S%OU}&{P zWpTe>j-W1%K>RvBjw|u4d`06}=GPxlA0LNa8nJnQX&LbDNE!LPwJLZ#MgSuXkUkI1 z$I;RA|2_X+RnKusZ(oP%pUBu927b2w=#C%w@9R+W|ICy&W2ig#))=(y?{a?q{h0Gs LQHmG?f%pCcE?fw> From 84a0c754a353cfcee721a2c78769cc4a87b35cc1 Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Thu, 3 Apr 2025 15:03:57 -0400 Subject: [PATCH 13/34] remove launchsettings.json --- .gitignore | 2 ++ TSforgeCLI/Properties/launchSettings.json | 8 -------- 2 files changed, 2 insertions(+), 8 deletions(-) delete mode 100644 TSforgeCLI/Properties/launchSettings.json diff --git a/.gitignore b/.gitignore index eaa9902..3aeb500 100644 --- a/.gitignore +++ b/.gitignore @@ -361,3 +361,5 @@ MigrationBackup/ # Fody - auto-generated XML schema FodyWeavers.xsd + +launchSettings.json diff --git a/TSforgeCLI/Properties/launchSettings.json b/TSforgeCLI/Properties/launchSettings.json deleted file mode 100644 index 112530f..0000000 --- a/TSforgeCLI/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "TSforgeCLI": { - "commandName": "Project", - "commandLineArgs": "/dump vista.dat blah.dat /ver vista" - } - } -} \ No newline at end of file From 17a7c90245ccd45b6e32d8bbe01a1a3eddeeae4d Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Thu, 3 Apr 2025 18:22:33 -0400 Subject: [PATCH 14/34] miscellaneous fixes --- LibTSforge/Activators/AVMA4K.cs | 2 +- LibTSforge/Common.cs | 9 ++++++--- LibTSforge/SPP/SPPUtils.cs | 4 ++-- LibTSforge/TokenStore/TokenStoreModern.cs | 1 + TSforgeCLI/Program.cs | 2 ++ 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/LibTSforge/Activators/AVMA4K.cs b/LibTSforge/Activators/AVMA4K.cs index ec09daf..2127652 100644 --- a/LibTSforge/Activators/AVMA4K.cs +++ b/LibTSforge/Activators/AVMA4K.cs @@ -8,7 +8,7 @@ namespace LibTSforge.Activators { public static void Activate(PSVersion version, bool production, Guid actId) { - if (version != PSVersion.WinModern) + if (version != PSVersion.WinModern && version != PSVersion.WinBlue) { throw new NotSupportedException("AVMA licenses are not available for this product."); } diff --git a/LibTSforge/Common.cs b/LibTSforge/Common.cs index b9c274a..4d61770 100644 --- a/LibTSforge/Common.cs +++ b/LibTSforge/Common.cs @@ -183,6 +183,12 @@ namespace LibTSforge public static class Utils { + [DllImport("kernel32.dll")] + public static extern uint GetSystemDefaultLCID(); + + [DllImport("kernel32.dll")] + public static extern bool Wow64EnableWow64FsRedirection(bool Wow64FsEnableRedirection); + public static string DecodeString(byte[] data) { return Encoding.Unicode.GetString(data).Trim('\0'); @@ -193,9 +199,6 @@ namespace LibTSforge return Encoding.Unicode.GetBytes(str + '\0'); } - [DllImport("kernel32.dll")] - public static extern uint GetSystemDefaultLCID(); - public static uint CRC32(byte[] data) { const uint polynomial = 0x04C11DB7; diff --git a/LibTSforge/SPP/SPPUtils.cs b/LibTSforge/SPP/SPPUtils.cs index 1a6ef62..5621305 100644 --- a/LibTSforge/SPP/SPPUtils.cs +++ b/LibTSforge/SPP/SPPUtils.cs @@ -33,7 +33,7 @@ namespace LibTSforge.SPP bool stopped = false; - for (int i = 0; stopped == false && i < 360; i++) + for (int i = 0; stopped == false && i < 1080; i++) { try { @@ -48,7 +48,7 @@ namespace LibTSforge.SPP } catch (InvalidOperationException ex) { - Logger.WriteLine("Warning: Stopping sppsvc failed, retrying. Details:" + ex.Message); + Logger.WriteLine("Warning: Stopping sppsvc failed, retrying. Details: " + ex.Message); System.Threading.Thread.Sleep(500); continue; } diff --git a/LibTSforge/TokenStore/TokenStoreModern.cs b/LibTSforge/TokenStore/TokenStoreModern.cs index cfb35d0..ee51e7a 100644 --- a/LibTSforge/TokenStore/TokenStoreModern.cs +++ b/LibTSforge/TokenStore/TokenStoreModern.cs @@ -30,6 +30,7 @@ namespace LibTSforge.TokenStore BinaryReader reader = new BinaryReader(TokensFile); do { + reader.ReadUInt32(); nextBlock = reader.ReadUInt32(); for (int i = 0; i < ENTRIES_PER_BLOCK; i++) diff --git a/TSforgeCLI/Program.cs b/TSforgeCLI/Program.cs index 865e51d..86945d5 100644 --- a/TSforgeCLI/Program.cs +++ b/TSforgeCLI/Program.cs @@ -35,6 +35,8 @@ namespace TSforgeCLI { Logger.WriteLine("TSforge (c) MASSGRAVE 2025"); + Utils.Wow64EnableWow64FsRedirection(false); + try { if (args.Length == 0) From 736c722880ef33cc2072f5ff28e6d051fed0c782 Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Thu, 3 Apr 2025 20:51:33 -0400 Subject: [PATCH 15/34] attempt at arm fix --- LibTSforge/SPP/SPPUtils.cs | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/LibTSforge/SPP/SPPUtils.cs b/LibTSforge/SPP/SPPUtils.cs index 5621305..21db680 100644 --- a/LibTSforge/SPP/SPPUtils.cs +++ b/LibTSforge/SPP/SPPUtils.cs @@ -161,14 +161,15 @@ namespace LibTSforge.SPP default: return Path.Combine( Environment.ExpandEnvironmentVariables( - (string)Registry.GetValue( - @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform", + (string)RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, Environment.MachineName) + .OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SoftwareProtectionPlatform") + .GetValue( "TokenStore", string.Empty - ) - ), - "data.dat" - ); + ) + ), + "data.dat" + ); } } @@ -189,14 +190,15 @@ namespace LibTSforge.SPP default: return Path.Combine( Environment.ExpandEnvironmentVariables( - (string)Registry.GetValue( - @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform", + (string)RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, Environment.MachineName) + .OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SoftwareProtectionPlatform") + .GetValue( "TokenStore", string.Empty - ) - ), - "tokens.dat" - ); + ) + ), + "tokens.dat" + ); } } @@ -204,14 +206,11 @@ namespace LibTSforge.SPP { string psPath; - try + { psPath = GetPSPath(version); } - catch - { - throw new FileNotFoundException("Failed to get path of physical store."); - } + if (string.IsNullOrEmpty(psPath) || !File.Exists(psPath)) { From aa0801c643729177454fc329f092456afb86f3ab Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Thu, 3 Apr 2025 21:02:50 -0400 Subject: [PATCH 16/34] fix error handling --- LibTSforge/SPP/SPPUtils.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/LibTSforge/SPP/SPPUtils.cs b/LibTSforge/SPP/SPPUtils.cs index 21db680..a0b3a77 100644 --- a/LibTSforge/SPP/SPPUtils.cs +++ b/LibTSforge/SPP/SPPUtils.cs @@ -206,12 +206,15 @@ namespace LibTSforge.SPP { 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)); @@ -238,7 +241,7 @@ namespace LibTSforge.SPP } catch { - throw new FileNotFoundException("Failed to get path of physical store."); + throw new FileNotFoundException("Failed to get path of token store."); } if (string.IsNullOrEmpty(tokPath) || !File.Exists(tokPath)) From e86f43a2864585f8430e01849a04a51bc46c1908 Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Fri, 4 Apr 2025 00:21:07 -0400 Subject: [PATCH 17/34] hack fix for arm64 in absence of better solutions --- LibTSforge/SPP/ProductKey.cs | 9 ++++++++- LibTSforge/SPP/SPPUtils.cs | 16 +++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/LibTSforge/SPP/ProductKey.cs b/LibTSforge/SPP/ProductKey.cs index b5fca9a..ce454d8 100644 --- a/LibTSforge/SPP/ProductKey.cs +++ b/LibTSforge/SPP/ProductKey.cs @@ -32,6 +32,11 @@ namespace LibTSforge.SPP get { return BitConverter.GetBytes(klow).Concat(BitConverter.GetBytes(khigh)).ToArray(); } } + public ProductKey() + { + + } + public ProductKey(int serial, ulong security, bool upgrade, PKeyAlgorithm algorithm, ProductConfig config, KeyRange range) { Group = config.GroupId; @@ -254,7 +259,9 @@ namespace LibTSforge.SPP int serialLow = Serial % 1000000; BinaryWriter writer = new BinaryWriter(new MemoryStream()); - writer.Write(new Guid("B8731595-A2F6-430B-A799-FBFFB81A8D73").ToByteArray()); + string algoId = Algorithm == PKeyAlgorithm.PKEY2005 ? "B8731595-A2F6-430B-A799-FBFFB81A8D73" : "660672EF-7809-4CFD-8D54-41B7FB738988"; + + writer.Write(new Guid(algoId).ToByteArray()); writer.Write(Group); writer.Write(serialHigh); writer.Write(serialLow); diff --git a/LibTSforge/SPP/SPPUtils.cs b/LibTSforge/SPP/SPPUtils.cs index a0b3a77..ad3840d 100644 --- a/LibTSforge/SPP/SPPUtils.cs +++ b/LibTSforge/SPP/SPPUtils.cs @@ -113,7 +113,7 @@ namespace LibTSforge.SPP } catch (InvalidOperationException ex) { - Logger.WriteLine("Warning: Starting slsvc failed, retrying. Details:" + ex.Message); + Logger.WriteLine("Warning: Starting slsvc failed, retrying. Details: " + ex.Message); System.Threading.Thread.Sleep(500); continue; } @@ -161,11 +161,10 @@ namespace LibTSforge.SPP default: return Path.Combine( Environment.ExpandEnvironmentVariables( - (string)RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, Environment.MachineName) - .OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SoftwareProtectionPlatform") - .GetValue( + (string)Registry.GetValue( + @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform", "TokenStore", - string.Empty + @"C:\Windows\System32\spp\store\2.0" ) ), "data.dat" @@ -190,11 +189,10 @@ namespace LibTSforge.SPP default: return Path.Combine( Environment.ExpandEnvironmentVariables( - (string)RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, Environment.MachineName) - .OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SoftwareProtectionPlatform") - .GetValue( + (string)Registry.GetValue( + @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform", "TokenStore", - string.Empty + @"C:\Windows\System32\spp\store\2.0" ) ), "tokens.dat" From 28acb8012f3471262aa999071fbadde5ebe7edf9 Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Fri, 4 Apr 2025 03:43:27 -0400 Subject: [PATCH 18/34] add /siid option --- LibTSforge/Modifiers/SetIIDParams.cs | 69 +++++++++++++++++++++++++ LibTSforge/SPP/ProductKey.cs | 6 +-- TSforgeCLI/Program.cs | 76 +++++++++++++++++++++------- 3 files changed, 130 insertions(+), 21 deletions(-) create mode 100644 LibTSforge/Modifiers/SetIIDParams.cs diff --git a/LibTSforge/Modifiers/SetIIDParams.cs b/LibTSforge/Modifiers/SetIIDParams.cs new file mode 100644 index 0000000..d7fa2c5 --- /dev/null +++ b/LibTSforge/Modifiers/SetIIDParams.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using LibTSforge.PhysicalStore; +using LibTSforge.SPP; + +namespace LibTSforge.Modifiers +{ + public static class SetIIDParams + { + public static void SetParams(PSVersion version, bool production, Guid actId, PKeyAlgorithm algorithm, int group, int serial, ulong security) + { + if (version == PSVersion.Vista) throw new NotSupportedException("This feature is not supported on Windows Vista/Server 2008."); + + Guid appId; + + if (actId == Guid.Empty) + { + appId = SLApi.WINDOWS_APP_ID; + actId = SLApi.GetDefaultActivationID(appId, true); + + if (actId == Guid.Empty) + { + throw new Exception("No applicable activation IDs found."); + } + } + else + { + appId = SLApi.GetAppId(actId); + } + + Guid pkeyId = SLApi.GetInstalledPkeyID(actId); + + SPPUtils.KillSPP(version); + + Logger.WriteLine("Writing TrustedStore data..."); + + using (IPhysicalStore store = SPPUtils.GetStore(version, production)) + { + string key = string.Format("SPPSVC\\{0}\\{1}", appId, actId); + PSBlock keyBlock = store.GetBlock(key, pkeyId.ToString()); + + if (keyBlock == null) + { + throw new InvalidDataException("Failed to get product key data for activation ID " + actId + "."); + } + + VariableBag pkb = new VariableBag(keyBlock.Data, version); + + ProductKey pkey = new ProductKey + { + Group = group, + Serial = serial, + Security = security, + Algorithm = algorithm, + Upgrade = false + }; + + string blockName = version == PSVersion.Win7 ? "SppPkeyShortAuthenticator" : "SppPkeyPhoneActivationData"; + pkb.SetBlock(blockName, pkey.GetPhoneData(version)); + store.SetBlock(key, pkeyId.ToString(), pkb.Serialize()); + } + + Logger.WriteLine("Successfully set IID parameters."); + } + } +} diff --git a/LibTSforge/SPP/ProductKey.cs b/LibTSforge/SPP/ProductKey.cs index ce454d8..ae48893 100644 --- a/LibTSforge/SPP/ProductKey.cs +++ b/LibTSforge/SPP/ProductKey.cs @@ -249,10 +249,8 @@ namespace LibTSforge.SPP { if (version == PSVersion.Win7) { - Random rnd = new Random(Group * 1000000000 + Serial); - byte[] data = new byte[8]; - rnd.NextBytes(data); - return data; + ulong shortauth = ((ulong)Group << 41) | ((ulong)Security << 31) | ((ulong)Serial << 1) | (Upgrade ? (ulong)1 : 0); + return BitConverter.GetBytes(shortauth); } int serialHigh = Serial / 1000000; diff --git a/TSforgeCLI/Program.cs b/TSforgeCLI/Program.cs index 86945d5..2c72265 100644 --- a/TSforgeCLI/Program.cs +++ b/TSforgeCLI/Program.cs @@ -25,10 +25,15 @@ namespace TSforgeCLI public bool KMSHostCharge = false; public bool TamperedFlagsDelete = false; public bool KeyChangeLockDelete = false; + public bool SetIIDParams = false; public bool? Production = null; public PSVersion? Version = null; public Guid ActivationId = Guid.Empty; public bool ShowHelp = false; + public PKeyAlgorithm? Algorithm = null; + public int Group = 0; + public int Serial = 0; + public ulong Security = 0; } public static void Main(string[] args) @@ -103,6 +108,10 @@ namespace TSforgeCLI else if (options.KeyChangeLockDelete) { KeyChangeLockDelete.Delete(version, production); + } + else if (options.SetIIDParams) + { + SetIIDParams.SetParams(version, production, options.ActivationId, options.Algorithm.Value, options.Group, options.Serial, options.Security); } else { @@ -187,6 +196,38 @@ namespace TSforgeCLI break; case "/revl": options.KeyChangeLockDelete = true; + break; + case "/siid": + options.SetIIDParams = true; + + if (args.Length - i - 1 < 4) throw new ArgumentException("Not enough arguments specified."); + + string algoType = args[++i]; + + if (algoType == "5") + { + options.Algorithm = PKeyAlgorithm.PKEY2005; + } + else if (algoType == "9") + { + options.Algorithm = PKeyAlgorithm.PKEY2009; + } + else + { + throw new ArgumentException("Invalid key algorithm specified."); + } + + try + { + options.Group = int.Parse(args[++i]); + options.Serial = int.Parse(args[++i]); + options.Security = ulong.Parse(args[++i]); + } + catch + { + throw new ArgumentException("Failed to parse key parameters."); + } + break; default: try @@ -211,23 +252,24 @@ namespace TSforgeCLI string exeName = typeof(Program).Namespace; Logger.WriteLine("Usage: " + exeName + " [/dump ()] [/load ] [/kms4k] [/avma4k] [/zcid] [/rtmr] [/duid] [/igpk] [/kmsc] [/ctpr] [/revl] [/prod] [/test] [] [/ver ]"); Logger.WriteLine("Options:"); - Logger.WriteLine("\t/dump () Dump and decrypt the physical store to the specified path."); - Logger.WriteLine("\t/load Load and re-encrypt the physical store from the specified path."); - Logger.WriteLine("\t/kms4k Activate using KMS4k. Only supports KMS-activatable editions."); - Logger.WriteLine("\t/avma4k Activate using AVMA4k. Only supports Windows Server 2012 R2+."); - Logger.WriteLine("\t/zcid Activate using ZeroCID. Only supports phone-activatable editions."); - Logger.WriteLine("\t/rtmr Reset grace/evaluation period timers."); - Logger.WriteLine("\t/rrmc Reset the rearm count."); - Logger.WriteLine("\t/duid Delete product key Unique ID used in online key validation."); - Logger.WriteLine("\t/igpk Install auto-generated/fake product key according to the specified Activation ID"); - Logger.WriteLine("\t/kmsc Reset the charged count on the local KMS server to 25. Requires an activated KMS host."); - Logger.WriteLine("\t/ctpr Remove the tamper flags that get set in the physical store when sppsvc detects an attempt to tamper with it."); - Logger.WriteLine("\t/revl Remove the key change lock in evaluation edition store."); - Logger.WriteLine("\t/prod Use SPP production key."); - Logger.WriteLine("\t/test Use SPP test key."); - Logger.WriteLine("\t/ver Override the detected version. Available versions: vista, 7, 8, blue, modern."); - Logger.WriteLine("\t A specific activation ID. Useful if you want to activate specific addons like ESU."); - Logger.WriteLine("\t/? Display this help message."); + Logger.WriteLine("\t/dump () Dump and decrypt the physical store to the specified path."); + Logger.WriteLine("\t/load Load and re-encrypt the physical store from the specified path."); + Logger.WriteLine("\t/kms4k Activate using KMS4k. Only supports KMS-activatable editions."); + Logger.WriteLine("\t/avma4k Activate using AVMA4k. Only supports Windows Server 2012 R2+."); + Logger.WriteLine("\t/zcid Activate using ZeroCID. Only supports phone-activatable editions."); + Logger.WriteLine("\t/rtmr Reset grace/evaluation period timers."); + Logger.WriteLine("\t/rrmc Reset the rearm count."); + Logger.WriteLine("\t/duid Delete product key Unique ID used in online key validation."); + Logger.WriteLine("\t/igpk Install auto-generated/fake product key according to the specified Activation ID"); + Logger.WriteLine("\t/kmsc Reset the charged count on the local KMS server to 25. Requires an activated KMS host."); + Logger.WriteLine("\t/ctpr Remove the tamper flags that get set in the physical store when sppsvc detects an attempt to tamper with it."); + Logger.WriteLine("\t/revl Remove the key change lock in evaluation edition store."); + Logger.WriteLine("\t/siid <5/9> Set Installation ID parameters independently of installed key. 5/9 argument specifies PKEY200[5/9] key algorithm."); + Logger.WriteLine("\t/prod Use SPP production key."); + Logger.WriteLine("\t/test Use SPP test key."); + Logger.WriteLine("\t/ver Override the detected version. Available versions: vista, 7, 8, blue, modern."); + Logger.WriteLine("\t A specific activation ID. Useful if you want to activate specific addons like ESU."); + Logger.WriteLine("\t/? Display this help message."); } private static PSVersion ParseVersion(string ver) From 93b29d3acc9c40dc820d93f856f731a125df4277 Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Fri, 4 Apr 2025 03:44:14 -0400 Subject: [PATCH 19/34] Update README.md --- README.md | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index f411c9f..f00f2e6 100644 --- a/README.md +++ b/README.md @@ -26,23 +26,24 @@ Included methods and tools: ``` Usage: TSforge [/dump ()] [/load ] [/kms4k] [/avma4k] [/zcid] [/rtmr] [/duid] [/igpk] [/kmsc] [/ctpr] [/revl] [/prod] [/test] [] [/ver ] Options: - /dump () Dump and decrypt the physical store to the specified path. - /load Load and re-encrypt the physical store from the specified path. - /kms4k Activate using KMS4k. Only supports KMS-activatable editions. - /avma4k Activate using AVMA4k. Only supports Windows Server 2012 R2+. - /zcid Activate using ZeroCID. Only supports phone-activatable editions. - /rtmr Reset grace/evaluation period timers. - /rrmc Reset the rearm count. - /duid Delete product key Unique ID used in online key validation. - /igpk Install auto-generated/fake product key according to the specified Activation ID. - /kmsc Reset the charged count on the local KMS server to 25. Requires an activated KMS host. - /ctpr Clear the physical store tamper state. - /revl Remove the key change lock in evaluation edition store. - /prod Use SPP production key. - /test Use SPP test key. - /ver Override the detected version. Available versions: vista, 7, 8early, 8, blue, modern. - A specific activation ID. Useful if you want to activate specific addons like ESU. - /? Display this help message. + /dump () Dump and decrypt the physical store to the specified path. + /load Load and re-encrypt the physical store from the specified path. + /kms4k Activate using KMS4k. Only supports KMS-activatable editions. + /avma4k Activate using AVMA4k. Only supports Windows Server 2012 R2+. + /zcid Activate using ZeroCID. Only supports phone-activatable editions. + /rtmr Reset grace/evaluation period timers. + /rrmc Reset the rearm count. + /duid Delete product key Unique ID used in online key validation. + /igpk Install auto-generated/fake product key according to the specified Activation ID + /kmsc Reset the charged count on the local KMS server to 25. Requires an activated KMS host. + /ctpr Remove the tamper flags that get set in the physical store when sppsvc detects an attempt to tamper with it. + /revl Remove the key change lock in evaluation edition store. + /siid <5/9> Set Installation ID parameters independently of installed key. 5/9 argument specifies PKEY200[5/9] key algorithm. + /prod Use SPP production key. + /test Use SPP test key. + /ver Override the detected version. Available versions: vista, 7, 8, blue, modern. + A specific activation ID. Useful if you want to activate specific addons like ESU. + /? Display this help message. ``` ## FAQ From 3a1b9c481df88e96515a89083034e17a90a26e86 Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Fri, 4 Apr 2025 05:24:33 -0400 Subject: [PATCH 20/34] slightly improve arm64 fix --- LibTSforge/SPP/SPPUtils.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/LibTSforge/SPP/SPPUtils.cs b/LibTSforge/SPP/SPPUtils.cs index ad3840d..187d4f3 100644 --- a/LibTSforge/SPP/SPPUtils.cs +++ b/LibTSforge/SPP/SPPUtils.cs @@ -164,7 +164,10 @@ namespace LibTSforge.SPP (string)Registry.GetValue( @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform", "TokenStore", - @"C:\Windows\System32\spp\store\2.0" + Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.System), + @"spp\store\2.0" + ) ) ), "data.dat" @@ -192,7 +195,10 @@ namespace LibTSforge.SPP (string)Registry.GetValue( @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform", "TokenStore", - @"C:\Windows\System32\spp\store\2.0" + Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.System), + @"spp\store\2.0" + ) ) ), "tokens.dat" @@ -204,13 +210,13 @@ namespace LibTSforge.SPP { string psPath; - try + //try { psPath = GetPSPath(version); } - catch + //catch { - throw new FileNotFoundException("Failed to get path of physical store."); + //throw new FileNotFoundException("Failed to get path of physical store."); } if (string.IsNullOrEmpty(psPath) || !File.Exists(psPath)) From 233be2dd1446b1bfca18dff77bb25f57155ada15 Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Fri, 4 Apr 2025 11:01:48 -0400 Subject: [PATCH 21/34] . --- LibTSforge/SPP/SPPUtils.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LibTSforge/SPP/SPPUtils.cs b/LibTSforge/SPP/SPPUtils.cs index 187d4f3..8cf2643 100644 --- a/LibTSforge/SPP/SPPUtils.cs +++ b/LibTSforge/SPP/SPPUtils.cs @@ -210,13 +210,13 @@ namespace LibTSforge.SPP { string psPath; - //try + try { psPath = GetPSPath(version); } - //catch + catch { - //throw new FileNotFoundException("Failed to get path of physical store."); + throw new FileNotFoundException("Failed to get path of physical store."); } if (string.IsNullOrEmpty(psPath) || !File.Exists(psPath)) From 001c27ca1d96231b8d6282f48fcff31d51e86a30 Mon Sep 17 00:00:00 2001 From: Lyssa Date: Fri, 4 Apr 2025 19:15:35 +0400 Subject: [PATCH 22/34] explicitly set AnyCPU PlatformTarget in LibTSforge project file (appears to do nothing but just in case) --- LibTSforge/LibTSforge.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/LibTSforge/LibTSforge.csproj b/LibTSforge/LibTSforge.csproj index 8c3504a..4dfead2 100644 --- a/LibTSforge/LibTSforge.csproj +++ b/LibTSforge/LibTSforge.csproj @@ -7,6 +7,7 @@ 3 README.md false + AnyCPU From 6d971c2f6df56bb6597c52700983871a81258f32 Mon Sep 17 00:00:00 2001 From: WitherOrNot Date: Fri, 4 Apr 2025 23:23:57 -0400 Subject: [PATCH 23/34] add fallback path search --- LibTSforge/SPP/SPPUtils.cs | 130 ++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 54 deletions(-) diff --git a/LibTSforge/SPP/SPPUtils.cs b/LibTSforge/SPP/SPPUtils.cs index 8cf2643..a535bc7 100644 --- a/LibTSforge/SPP/SPPUtils.cs +++ b/LibTSforge/SPP/SPPUtils.cs @@ -159,19 +159,44 @@ namespace LibTSforge.SPP "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", - Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.System), - @"spp\store\2.0" - ) - ) - ), - "data.dat" + string psDir = Environment.ExpandEnvironmentVariables( + (string)Registry.GetValue( + @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform", + "TokenStore", + "" + ) ); + string psPath = Path.Combine(psDir, "data.dat"); + + if (string.IsNullOrEmpty(psDir) || !File.Exists(psPath)) + { + string[] psDirs = + { + @"spp\store", + @"spp\store\2.0", + @"spp\store_test", + @"spp\store_test\2.0" + }; + + foreach (string dir in psDirs) + { + psPath = Path.Combine( + Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.System), + dir + ), + "data.dat" + ); + + if (File.Exists(psPath)) return psPath; + } + } + else + { + return psPath; + } + + throw new FileNotFoundException("Failed to locate physical store."); } } @@ -190,39 +215,50 @@ namespace LibTSforge.SPP @"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", - Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.System), - @"spp\store\2.0" - ) - ) - ), - "tokens.dat" + string tokDir = Environment.ExpandEnvironmentVariables( + (string)Registry.GetValue( + @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform", + "TokenStore", + "" + ) ); + string tokPath = Path.Combine(tokDir, "tokens.dat"); + + if (string.IsNullOrEmpty(tokDir) || !File.Exists(tokPath)) + { + string[] tokDirs = + { + @"spp\store", + @"spp\store\2.0", + @"spp\store_test", + @"spp\store_test\2.0" + }; + + foreach (string dir in tokDirs) + { + tokPath = Path.Combine( + Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.System), + dir + ), + "tokens.dat" + ); + + if (File.Exists(tokPath)) return tokPath; + } + } + else + { + return tokPath; + } + + throw new FileNotFoundException("Failed to locate token store."); } } 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)); - } + string psPath = GetPSPath(version); switch (version) { @@ -237,21 +273,7 @@ namespace LibTSforge.SPP public static ITokenStore GetTokenStore(PSVersion version) { - string tokPath; - - try - { - tokPath = GetTokensPath(version); - } - catch - { - throw new FileNotFoundException("Failed to get path of token store."); - } - - if (string.IsNullOrEmpty(tokPath) || !File.Exists(tokPath)) - { - throw new FileNotFoundException(string.Format("Token store not found at expected path {0}.", tokPath)); - } + string tokPath = GetTokensPath(version); return new TokenStoreModern(tokPath); } From f6353e567a585f9f456627b050f5c8b63767bf0e Mon Sep 17 00:00:00 2001 From: Lyssa Date: Sun, 6 Apr 2025 19:27:33 +0400 Subject: [PATCH 24/34] remove redundant break --- TSforgeCLI/Program.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/TSforgeCLI/Program.cs b/TSforgeCLI/Program.cs index 2c72265..7c1a50b 100644 --- a/TSforgeCLI/Program.cs +++ b/TSforgeCLI/Program.cs @@ -238,7 +238,6 @@ namespace TSforgeCLI { Logger.WriteLine("Argument doesn't exist or the specified activation ID is invalid."); options.ShowHelp = true; - break; } break; } From be6682e8c3920a41ea67616582744c132def0f97 Mon Sep 17 00:00:00 2001 From: Lyssa Date: Sun, 6 Apr 2025 19:33:14 +0400 Subject: [PATCH 25/34] readonly usage inconsistency --- LibTSforge/Common.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibTSforge/Common.cs b/LibTSforge/Common.cs index 4d61770..a45870d 100644 --- a/LibTSforge/Common.cs +++ b/LibTSforge/Common.cs @@ -81,7 +81,7 @@ namespace LibTSforge }; // 2^31 - 8 minutes - public static ulong TimerMax = (ulong)TimeSpan.FromMinutes(2147483640).Ticks; + public static readonly ulong TimerMax = (ulong)TimeSpan.FromMinutes(2147483640).Ticks; public static readonly string ZeroCID = new string('0', 48); } From 3f1c87831802817f0cb3effacde954d3cbadfb6c Mon Sep 17 00:00:00 2001 From: Lyssa Date: Sun, 6 Apr 2025 19:35:08 +0400 Subject: [PATCH 26/34] remove unused CastToStruct function --- LibTSforge/Common.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/LibTSforge/Common.cs b/LibTSforge/Common.cs index a45870d..6b05bce 100644 --- a/LibTSforge/Common.cs +++ b/LibTSforge/Common.cs @@ -149,20 +149,6 @@ namespace LibTSforge } return result; } - - public static T CastToStruct(this byte[] data) where T : struct - { - GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); - try - { - IntPtr ptr = handle.AddrOfPinnedObject(); - return (T)Marshal.PtrToStructure(ptr, typeof(T)); - } - finally - { - handle.Free(); - } - } } public static class FileStreamExt From b885f518ab6ff8e07a4867347163baf4f1b43c18 Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Mon, 7 Apr 2025 07:00:35 -0400 Subject: [PATCH 27/34] Update README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f00f2e6..aa639ea 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Included methods and tools: - KMS Charger - Charge an existing KMS server to allow immediate use for activation - Clear Tamper State - Clear the tamper state set due to store corruption or deletion - Remove Evaluation Key Lock - Remove the product key change lock set for evaluation product keys +- Set IID Parameters - Set parameters for IID independently of installed key ## Usage @@ -91,6 +92,7 @@ The following options are NOT implemented: - `/duid` - Key Unique ID is not removable from Vista physical store - `/igpk` - Product key data is derived directly from the key string, preventing forgery + - `/siid` - IID is also derived directly from the key string - `/revl` - Eval key lock is not present on Vista Effectively, this means that a product key must be provided to activate a given SKU. Additionally, ZeroCID on Vista/Server 2008 lacks protection against WGA. @@ -103,6 +105,10 @@ If generic keys are installed, you need to run `TSforge.exe /duid` to remove the Windows doesn't support AVMA activation under VM software that fails to provide [Hyper-V Enlightenments](https://www.qemu.org/docs/master/system/i386/hyperv.html). This primarily means that AVMA4k is only supported on VMs running under a [correctly configured QEMU instance](https://blog.wikichoon.com/2014/07/enabling-hyper-v-enlightenments-with-kvm.html) or Hyper-V. If your VM's activation status is `Notification` with the status code `0xC004FD01` after using AVMA4k, you will need to use another activation method. +## Does TSforge support beta versions of Windows? + +It can, though we do not provide official support for these versions. TSforge works on most insider/beta builds of Windows past Windows 8.1. Beta builds prior to build 9600 are likely to face issues, as the internal data formats used by SPP were constantly changing during this period of development. Builds with similar licensing behavior to retail versions are the most likely to work with the current TSforge codebase. For other builds, you may need to manually edit the source code of LibTSforge to get it to work. + ### How do I remove this activation? Run [Microsoft Activation Scripts](https://massgrave.dev), select `Troubleshoot` > `Fix Licensing`. This will reset the physical store and revert any changes made by TSforge. @@ -134,7 +140,6 @@ 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 From bdd201061daf7492fb116b86a54cd349c01fbb0a Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Mon, 7 Apr 2025 07:01:45 -0400 Subject: [PATCH 28/34] header --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aa639ea..411e464 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ If generic keys are installed, you need to run `TSforge.exe /duid` to remove the Windows doesn't support AVMA activation under VM software that fails to provide [Hyper-V Enlightenments](https://www.qemu.org/docs/master/system/i386/hyperv.html). This primarily means that AVMA4k is only supported on VMs running under a [correctly configured QEMU instance](https://blog.wikichoon.com/2014/07/enabling-hyper-v-enlightenments-with-kvm.html) or Hyper-V. If your VM's activation status is `Notification` with the status code `0xC004FD01` after using AVMA4k, you will need to use another activation method. -## Does TSforge support beta versions of Windows? +### Does TSforge support beta versions of Windows? It can, though we do not provide official support for these versions. TSforge works on most insider/beta builds of Windows past Windows 8.1. Beta builds prior to build 9600 are likely to face issues, as the internal data formats used by SPP were constantly changing during this period of development. Builds with similar licensing behavior to retail versions are the most likely to work with the current TSforge codebase. For other builds, you may need to manually edit the source code of LibTSforge to get it to work. From 0c8b1efaa9005de1d101ebab5e66117edfaec3b2 Mon Sep 17 00:00:00 2001 From: Lyssa Date: Mon, 7 Apr 2025 19:19:24 +0400 Subject: [PATCH 29/34] Minor fixups --- LibTSforge/Activators/AVMA4K.cs | 22 +++---- LibTSforge/Activators/KMS4K.cs | 12 ++-- LibTSforge/Activators/ZeroCID.cs | 13 ++-- LibTSforge/Crypto/PhysStoreCrypto.cs | 48 +++++++-------- LibTSforge/Modifiers/GenPKeyInstall.cs | 12 ++-- LibTSforge/Modifiers/GracePeriodReset.cs | 4 +- LibTSforge/Modifiers/KMSHostCharge.cs | 12 ++-- LibTSforge/Modifiers/KeyChangeLockDelete.cs | 5 +- LibTSforge/Modifiers/RearmReset.cs | 4 +- LibTSforge/Modifiers/SetIIDParams.cs | 12 ++-- LibTSforge/Modifiers/TamperedFlagsDelete.cs | 6 +- LibTSforge/Modifiers/UniqueIdDelete.cs | 5 +- LibTSforge/PhysicalStore/Common.cs | 4 +- .../PhysicalStore/PhysicalStoreModern.cs | 60 ++++++++++--------- .../PhysicalStore/PhysicalStoreVista.cs | 4 +- LibTSforge/PhysicalStore/PhysicalStoreWin7.cs | 4 +- LibTSforge/PhysicalStore/VariableBag.cs | 3 +- LibTSforge/SPP/PKeyConfig.cs | 7 +-- LibTSforge/SPP/ProductKey.cs | 26 ++++---- LibTSforge/SPP/SLAPI.cs | 27 ++++----- LibTSforge/SPP/SPPUtils.cs | 10 ++-- LibTSforge/SPP/SPSys.cs | 2 +- LibTSforge/TokenStore/Common.cs | 4 +- LibTSforge/TokenStore/TokenStoreModern.cs | 14 ++--- TSforgeCLI/Program.cs | 42 ++++++------- 25 files changed, 168 insertions(+), 194 deletions(-) diff --git a/LibTSforge/Activators/AVMA4K.cs b/LibTSforge/Activators/AVMA4K.cs index 2127652..51b546a 100644 --- a/LibTSforge/Activators/AVMA4K.cs +++ b/LibTSforge/Activators/AVMA4K.cs @@ -1,8 +1,8 @@ namespace LibTSforge.Activators { using System; - using LibTSforge.PhysicalStore; - using LibTSforge.SPP; + using PhysicalStore; + using SPP; public static class AVMA4k { @@ -42,24 +42,20 @@ namespace LibTSforge.Activators { string key = string.Format("SPPSVC\\{0}\\{1}", appId, actId); - ulong unknown = 0; - ulong time1; - ulong crcBindTime = (ulong)DateTime.UtcNow.ToFileTime(); - ulong timerTime; - - ulong expiry = Constants.TimerMax; - long creationTime = BitConverter.ToInt64(store.GetBlock("__##USERSEP##\\$$_RESERVED_$$\\NAMESPACE__", "__##USERSEP-RESERVED##__$$GLOBAL-CREATION-TIME$$").Data, 0); long tickCount = BitConverter.ToInt64(store.GetBlock("__##USERSEP##\\$$_RESERVED_$$\\NAMESPACE__", "__##USERSEP-RESERVED##__$$GLOBAL-TICKCOUNT-UPTIME$$").Data, 0); long deltaTime = BitConverter.ToInt64(store.GetBlock(key, "__##USERSEP-RESERVED##__$$UP-TIME-DELTA$$").Data, 0); - time1 = (ulong)(creationTime + tickCount + deltaTime); - timerTime = crcBindTime / 10000; + const ulong unknown = 0; + ulong time1 = (ulong)(creationTime + tickCount + deltaTime); + ulong crcBindTime = (ulong)DateTime.UtcNow.ToFileTime(); + ulong timerTime = crcBindTime / 10000; + ulong expiry = Constants.TimerMax; expiry /= 10000; VariableBag avmaBinding = new VariableBag(version); - avmaBinding.Blocks.AddRange(new CRCBlockModern[] + avmaBinding.Blocks.AddRange(new[] { new CRCBlockModern { @@ -97,7 +93,7 @@ namespace LibTSforge.Activators store.DeleteBlock(key, storeVal); store.DeleteBlock(key, timerVal); - store.AddBlocks(new PSBlock[] + store.AddBlocks(new[] { new PSBlock { diff --git a/LibTSforge/Activators/KMS4K.cs b/LibTSforge/Activators/KMS4K.cs index a68e263..6287c39 100644 --- a/LibTSforge/Activators/KMS4K.cs +++ b/LibTSforge/Activators/KMS4K.cs @@ -2,8 +2,8 @@ namespace LibTSforge.Activators { using System; using System.IO; - using LibTSforge.PhysicalStore; - using LibTSforge.SPP; + using PhysicalStore; + using SPP; public class KMS4k { @@ -78,7 +78,7 @@ namespace LibTSforge.Activators writer.Write(Constants.UniversalHWIDBlock); byte[] kmsData = writer.GetBytes(); - store.AddBlocks(new PSBlock[] + store.AddBlocks(new[] { new PSBlock { @@ -121,7 +121,7 @@ namespace LibTSforge.Activators VariableBag kmsBinding = new VariableBag(version); - kmsBinding.Blocks.AddRange(new CRCBlockModern[] + kmsBinding.Blocks.AddRange(new[] { new CRCBlockModern { @@ -145,7 +145,7 @@ namespace LibTSforge.Activators if (version == PSVersion.WinModern) { - kmsBinding.Blocks.AddRange(new CRCBlockModern[] + kmsBinding.Blocks.AddRange(new[] { new CRCBlockModern { @@ -178,7 +178,7 @@ namespace LibTSforge.Activators store.DeleteBlock(key, storeVal); store.DeleteBlock(key, timerVal); - store.AddBlocks(new PSBlock[] + store.AddBlocks(new[] { new PSBlock { diff --git a/LibTSforge/Activators/ZeroCID.cs b/LibTSforge/Activators/ZeroCID.cs index 1675173..147dceb 100644 --- a/LibTSforge/Activators/ZeroCID.cs +++ b/LibTSforge/Activators/ZeroCID.cs @@ -3,14 +3,13 @@ namespace LibTSforge.Activators using System; using System.IO; using System.Linq; - using System.Text.RegularExpressions; - using LibTSforge.Crypto; - using LibTSforge.PhysicalStore; - using LibTSforge.SPP; + using Crypto; + using PhysicalStore; + using SPP; public static class ZeroCID { - public static void Deposit(Guid actId, string instId) + private static void Deposit(Guid actId, string instId) { uint status = SLApi.DepositConfirmationID(actId, instId, Constants.ZeroCID); Logger.WriteLine(string.Format("Depositing fake CID status {0:X}", status)); @@ -98,7 +97,7 @@ namespace LibTSforge.Activators string uniqueId = Utils.DecodeString(pkeyData.Skip(0x120).Take(0x80).ToArray()); string extPid = Utils.DecodeString(pkeyData.Skip(0x1A0).Take(0x80).ToArray()); - uint group = 0; + uint group; uint.TryParse(extPid.Split('-')[1], out group); if (group == 0) @@ -154,7 +153,7 @@ namespace LibTSforge.Activators store.DeleteBlock(key, hwidBlockName); store.DeleteBlock(key, pkeyInfoName); - store.AddBlocks(new PSBlock[] { + store.AddBlocks(new[] { new PSBlock { Type = BlockType.NAMED, diff --git a/LibTSforge/Crypto/PhysStoreCrypto.cs b/LibTSforge/Crypto/PhysStoreCrypto.cs index b0acc2e..083841d 100644 --- a/LibTSforge/Crypto/PhysStoreCrypto.cs +++ b/LibTSforge/Crypto/PhysStoreCrypto.cs @@ -18,31 +18,31 @@ namespace LibTSforge.Crypto if (CryptoUtils.RSAVerifySignature(rsaKey, encAesKey, aesKeySig)) { - byte[] aesKey = CryptoUtils.RSADecrypt(rsaKey, encAesKey); - byte[] decData = CryptoUtils.AESDecrypt(br.ReadBytes((int)br.BaseStream.Length - 0x110), aesKey); - 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 (version != PSVersion.Vista) - { - 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; + throw new Exception("Failed to decrypt physical store."); } - throw new Exception("Failed to decrypt physical store."); + byte[] aesKey = CryptoUtils.RSADecrypt(rsaKey, encAesKey); + byte[] decData = CryptoUtils.AESDecrypt(br.ReadBytes((int)br.BaseStream.Length - 0x110), aesKey); + 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 (version != PSVersion.Vista) + { + 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; } public static byte[] EncryptPhysicalStore(byte[] data, bool production, PSVersion version) @@ -65,7 +65,7 @@ namespace LibTSforge.Crypto byte[] aesKeySig = CryptoUtils.RSASign(rsaKey, encAesKey); byte[] hmacSig = version != PSVersion.Vista ? CryptoUtils.HMACSign(hmacKey, data) : CryptoUtils.SaltSHASum(hmacKey, data); - byte[] decData = new byte[] { }; + byte[] decData = { }; decData = decData.Concat(hmacKey).Concat(hmacSig).Concat(BitConverter.GetBytes(0)).Concat(data).ToArray(); byte[] encData = CryptoUtils.AESEncrypt(decData, aesKey); diff --git a/LibTSforge/Modifiers/GenPKeyInstall.cs b/LibTSforge/Modifiers/GenPKeyInstall.cs index 2e4c23d..a747952 100644 --- a/LibTSforge/Modifiers/GenPKeyInstall.cs +++ b/LibTSforge/Modifiers/GenPKeyInstall.cs @@ -3,9 +3,9 @@ namespace LibTSforge.Modifiers using System; using System.IO; using Microsoft.Win32; - using LibTSforge.PhysicalStore; - using LibTSforge.SPP; - using LibTSforge.TokenStore; + using PhysicalStore; + using SPP; + using TokenStore; public static class GenPKeyInstall { @@ -58,7 +58,7 @@ namespace LibTSforge.Modifiers if (pkey.Algorithm == PKeyAlgorithm.PKEY2009) { uint status = SLApi.InstallProductKey(pkey); - Logger.WriteLine(string.Format("Installing generated product key {0} status {1:X}", pkey.ToString(), status)); + Logger.WriteLine(string.Format("Installing generated product key {0} status {1:X}", pkey, status)); if ((int)status < 0) { @@ -74,7 +74,7 @@ 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(version); - pkb.Blocks.AddRange(new CRCBlockModern[] + pkb.Blocks.AddRange(new[] { new CRCBlockModern { @@ -169,7 +169,7 @@ namespace LibTSforge.Modifiers uriMap.Data[pkeyId] = pkey.GetAlgoUri(); tks.SetEntry(uriMapName, "xml", uriMap.Serialize()); - string skuMetaName = actId.ToString() + metSuffix; + string skuMetaName = actId + metSuffix; TokenMeta skuMeta = tks.GetMetaEntry(skuMetaName); foreach (string k in skuMeta.Data.Keys) diff --git a/LibTSforge/Modifiers/GracePeriodReset.cs b/LibTSforge/Modifiers/GracePeriodReset.cs index 059b1c5..3d0f6a3 100644 --- a/LibTSforge/Modifiers/GracePeriodReset.cs +++ b/LibTSforge/Modifiers/GracePeriodReset.cs @@ -2,8 +2,8 @@ namespace LibTSforge.Modifiers { using System.Collections.Generic; using System.Linq; - using LibTSforge.PhysicalStore; - using LibTSforge.SPP; + using PhysicalStore; + using SPP; public static class GracePeriodReset { diff --git a/LibTSforge/Modifiers/KMSHostCharge.cs b/LibTSforge/Modifiers/KMSHostCharge.cs index 94f4dfd..153c700 100644 --- a/LibTSforge/Modifiers/KMSHostCharge.cs +++ b/LibTSforge/Modifiers/KMSHostCharge.cs @@ -2,8 +2,8 @@ namespace LibTSforge.Modifiers { using System; using System.IO; - using LibTSforge.PhysicalStore; - using LibTSforge.SPP; + using PhysicalStore; + using SPP; public static class KMSHostCharge { @@ -31,9 +31,9 @@ namespace LibTSforge.Modifiers string key = string.Format("SPPSVC\\{0}", appId); long ldapTimestamp = DateTime.Now.ToFileTime(); - byte[] cmidGuids = new byte[] { }; - byte[] reqCounts = new byte[] { }; - byte[] kmsChargeData = new byte[] { }; + byte[] cmidGuids = { }; + byte[] reqCounts = { }; + byte[] kmsChargeData = { }; BinaryWriter writer = new BinaryWriter(new MemoryStream()); @@ -94,7 +94,7 @@ namespace LibTSforge.Modifiers if (version != PSVersion.Vista) { VariableBag kmsCountData = new VariableBag(version); - kmsCountData.Blocks.AddRange(new CRCBlockModern[] + kmsCountData.Blocks.AddRange(new[] { new CRCBlockModern { diff --git a/LibTSforge/Modifiers/KeyChangeLockDelete.cs b/LibTSforge/Modifiers/KeyChangeLockDelete.cs index 3883d3c..f6ec3de 100644 --- a/LibTSforge/Modifiers/KeyChangeLockDelete.cs +++ b/LibTSforge/Modifiers/KeyChangeLockDelete.cs @@ -2,9 +2,8 @@ namespace LibTSforge.Modifiers { using System.Collections.Generic; using System.Linq; - using LibTSforge.PhysicalStore; - using LibTSforge.SPP; - using LibTSforge; + using PhysicalStore; + using SPP; using System; public static class KeyChangeLockDelete diff --git a/LibTSforge/Modifiers/RearmReset.cs b/LibTSforge/Modifiers/RearmReset.cs index 89a12f3..e909316 100644 --- a/LibTSforge/Modifiers/RearmReset.cs +++ b/LibTSforge/Modifiers/RearmReset.cs @@ -2,8 +2,8 @@ namespace LibTSforge.Modifiers { using System.Collections.Generic; using System.Linq; - using LibTSforge.PhysicalStore; - using LibTSforge.SPP; + using PhysicalStore; + using SPP; public static class RearmReset { diff --git a/LibTSforge/Modifiers/SetIIDParams.cs b/LibTSforge/Modifiers/SetIIDParams.cs index d7fa2c5..2f34a7d 100644 --- a/LibTSforge/Modifiers/SetIIDParams.cs +++ b/LibTSforge/Modifiers/SetIIDParams.cs @@ -1,13 +1,9 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using LibTSforge.PhysicalStore; -using LibTSforge.SPP; - namespace LibTSforge.Modifiers { + using PhysicalStore; + using SPP; + using System.IO; + using System; public static class SetIIDParams { public static void SetParams(PSVersion version, bool production, Guid actId, PKeyAlgorithm algorithm, int group, int serial, ulong security) diff --git a/LibTSforge/Modifiers/TamperedFlagsDelete.cs b/LibTSforge/Modifiers/TamperedFlagsDelete.cs index 8369d4e..a9edc55 100644 --- a/LibTSforge/Modifiers/TamperedFlagsDelete.cs +++ b/LibTSforge/Modifiers/TamperedFlagsDelete.cs @@ -1,8 +1,8 @@ namespace LibTSforge.Modifiers { using System.Linq; - using LibTSforge.PhysicalStore; - using LibTSforge.SPP; + using PhysicalStore; + using SPP; public static class TamperedFlagsDelete { @@ -14,7 +14,7 @@ namespace LibTSforge.Modifiers using (IPhysicalStore store = SPPUtils.GetStore(version, production)) { - if (version == PSVersion.Vista) + if (version == PSVersion.Vista) { DeleteFlag(store, "6BE8425B-E3CF-4e86-A6AF-5863E3DCB606"); } diff --git a/LibTSforge/Modifiers/UniqueIdDelete.cs b/LibTSforge/Modifiers/UniqueIdDelete.cs index d1851c4..b66954a 100644 --- a/LibTSforge/Modifiers/UniqueIdDelete.cs +++ b/LibTSforge/Modifiers/UniqueIdDelete.cs @@ -1,8 +1,8 @@ namespace LibTSforge.Modifiers { using System; - using LibTSforge.PhysicalStore; - using LibTSforge.SPP; + using PhysicalStore; + using SPP; public static class UniqueIdDelete { @@ -27,7 +27,6 @@ namespace LibTSforge.Modifiers appId = SLApi.GetAppId(actId); } - string instId = SLApi.GetInstallationID(actId); Guid pkeyId = SLApi.GetInstalledPkeyID(actId); SPPUtils.KillSPP(version); diff --git a/LibTSforge/PhysicalStore/Common.cs b/LibTSforge/PhysicalStore/Common.cs index d0ad4fe..aef77f8 100644 --- a/LibTSforge/PhysicalStore/Common.cs +++ b/LibTSforge/PhysicalStore/Common.cs @@ -4,9 +4,9 @@ namespace LibTSforge.PhysicalStore public enum BlockType : uint { - NONE, + NONE, // unused NAMED, - ATTRIBUTE, + ATTRIBUTE, //unused TIMER } diff --git a/LibTSforge/PhysicalStore/PhysicalStoreModern.cs b/LibTSforge/PhysicalStore/PhysicalStoreModern.cs index 9d8bb73..b76852a 100644 --- a/LibTSforge/PhysicalStore/PhysicalStoreModern.cs +++ b/LibTSforge/PhysicalStore/PhysicalStoreModern.cs @@ -3,7 +3,7 @@ namespace LibTSforge.PhysicalStore using System; using System.Collections.Generic; using System.IO; - using LibTSforge.Crypto; + using Crypto; public class ModernBlock { @@ -93,7 +93,7 @@ namespace LibTSforge.PhysicalStore public sealed class PhysicalStoreModern : IPhysicalStore { - private byte[] PreHeaderBytes = new byte[] { }; + private byte[] PreHeaderBytes = { }; private readonly Dictionary> Data = new Dictionary>(); private readonly FileStream TSFile; private readonly PSVersion Version; @@ -281,40 +281,44 @@ namespace LibTSforge.PhysicalStore public void DeleteBlock(string key, string value) { - if (Data.ContainsKey(key)) + if (!Data.ContainsKey(key)) { - List blocks = Data[key]; - - foreach (ModernBlock block in blocks) - { - if (block.ValueAsStr == value) - { - blocks.Remove(block); - break; - } - } - - Data[key] = blocks; + return; } + + List blocks = Data[key]; + + foreach (ModernBlock block in blocks) + { + if (block.ValueAsStr == value) + { + blocks.Remove(block); + break; + } + } + + Data[key] = blocks; } public void DeleteBlock(string key, uint value) { - if (Data.ContainsKey(key)) + if (!Data.ContainsKey(key)) { - List blocks = Data[key]; - - foreach (ModernBlock block in blocks) - { - if (block.ValueAsInt == value) - { - blocks.Remove(block); - break; - } - } - - Data[key] = blocks; + return; } + + List blocks = Data[key]; + + foreach (ModernBlock block in blocks) + { + if (block.ValueAsInt == value) + { + blocks.Remove(block); + break; + } + } + + Data[key] = blocks; } public PhysicalStoreModern(string tsPath, bool production, PSVersion version) diff --git a/LibTSforge/PhysicalStore/PhysicalStoreVista.cs b/LibTSforge/PhysicalStore/PhysicalStoreVista.cs index 809be77..5251914 100644 --- a/LibTSforge/PhysicalStore/PhysicalStoreVista.cs +++ b/LibTSforge/PhysicalStore/PhysicalStoreVista.cs @@ -3,7 +3,7 @@ namespace LibTSforge.PhysicalStore using System; using System.Collections.Generic; using System.IO; - using LibTSforge.Crypto; + using Crypto; public class VistaBlock { @@ -88,7 +88,7 @@ namespace LibTSforge.PhysicalStore public sealed class PhysicalStoreVista : IPhysicalStore { - private byte[] PreHeaderBytes = new byte[] { }; + private byte[] PreHeaderBytes = { }; private readonly List Blocks = new List(); private readonly FileStream TSPrimary; private readonly FileStream TSSecondary; diff --git a/LibTSforge/PhysicalStore/PhysicalStoreWin7.cs b/LibTSforge/PhysicalStore/PhysicalStoreWin7.cs index d03bf9a..006c8df 100644 --- a/LibTSforge/PhysicalStore/PhysicalStoreWin7.cs +++ b/LibTSforge/PhysicalStore/PhysicalStoreWin7.cs @@ -3,7 +3,7 @@ namespace LibTSforge.PhysicalStore using System; using System.Collections.Generic; using System.IO; - using LibTSforge.Crypto; + using Crypto; public class Win7Block { @@ -105,7 +105,7 @@ namespace LibTSforge.PhysicalStore public sealed class PhysicalStoreWin7 : IPhysicalStore { - private byte[] PreHeaderBytes = new byte[] { }; + private byte[] PreHeaderBytes = { }; private readonly List Blocks = new List(); private readonly FileStream TSPrimary; private readonly FileStream TSSecondary; diff --git a/LibTSforge/PhysicalStore/VariableBag.cs b/LibTSforge/PhysicalStore/VariableBag.cs index ebe413f..bca0e32 100644 --- a/LibTSforge/PhysicalStore/VariableBag.cs +++ b/LibTSforge/PhysicalStore/VariableBag.cs @@ -74,7 +74,6 @@ namespace LibTSforge.PhysicalStore 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(); @@ -156,7 +155,7 @@ namespace LibTSforge.PhysicalStore public List Blocks = new List(); private readonly PSVersion Version; - public void Deserialize(byte[] data) + private void Deserialize(byte[] data) { int len = data.Length; diff --git a/LibTSforge/SPP/PKeyConfig.cs b/LibTSforge/SPP/PKeyConfig.cs index 6733940..83fc981 100644 --- a/LibTSforge/SPP/PKeyConfig.cs +++ b/LibTSforge/SPP/PKeyConfig.cs @@ -74,7 +74,7 @@ namespace LibTSforge.SPP public class PKeyConfig { - public Dictionary Products = new Dictionary(); + public readonly Dictionary Products = new Dictionary(); private readonly List loadedPkeyConfigs = new List(); public void LoadConfig(Guid actId) @@ -210,10 +210,5 @@ namespace LibTSforge.SPP } } } - - public PKeyConfig() - { - - } } } diff --git a/LibTSforge/SPP/ProductKey.cs b/LibTSforge/SPP/ProductKey.cs index ae48893..f4cf15a 100644 --- a/LibTSforge/SPP/ProductKey.cs +++ b/LibTSforge/SPP/ProductKey.cs @@ -3,8 +3,8 @@ namespace LibTSforge.SPP using System; using System.IO; using System.Linq; - using LibTSforge.Crypto; - using LibTSforge.PhysicalStore; + using Crypto; + using PhysicalStore; public class ProductKey { @@ -18,16 +18,16 @@ namespace LibTSforge.SPP public ulong Security; public bool Upgrade; public PKeyAlgorithm Algorithm; - public string EulaType; - public string PartNumber; - public string Edition; - public string Channel; - public Guid ActivationId; + private readonly string EulaType; + private readonly string PartNumber; + public readonly string Edition; + public readonly string Channel; + private readonly Guid ActivationId; private string mpc; private string pid2; - public byte[] KeyBytes + private byte[] KeyBytes { get { return BitConverter.GetBytes(klow).Concat(BitConverter.GetBytes(khigh)).ToArray(); } } @@ -66,7 +66,7 @@ namespace LibTSforge.SPP public Guid GetPkeyId() { VariableBag pkb = new VariableBag(PSVersion.WinModern); - pkb.Blocks.AddRange(new CRCBlockModern[] + pkb.Blocks.AddRange(new[] { new CRCBlockModern { @@ -91,7 +91,7 @@ namespace LibTSforge.SPP return new Guid(CryptoUtils.SHA256Hash(pkb.Serialize()).Take(16).ToArray()); } - public string GetDefaultMPC() + private string GetDefaultMPC() { int build = Environment.OSVersion.Version.Build; string defaultMPC = build >= 10240 ? "03612" : @@ -111,7 +111,7 @@ namespace LibTSforge.SPP mpc = GetDefaultMPC(); // setup.cfg doesn't exist in Windows 8+ - string setupcfg = string.Format("{0}\\oobe\\{1}", Environment.SystemDirectory, "setup.cfg"); + string setupcfg = string.Format(@"{0}\oobe\{1}", Environment.SystemDirectory, "setup.cfg"); if (!File.Exists(setupcfg) || Edition.Contains(";")) { @@ -205,7 +205,7 @@ namespace LibTSforge.SPP return writer.GetBytes(); } - public string GetExtendedPid() + private string GetExtendedPid() { string mpc = GetMPC(); int serialHigh = Serial / 1000000; @@ -249,7 +249,7 @@ namespace LibTSforge.SPP { if (version == PSVersion.Win7) { - ulong shortauth = ((ulong)Group << 41) | ((ulong)Security << 31) | ((ulong)Serial << 1) | (Upgrade ? (ulong)1 : 0); + ulong shortauth = ((ulong)Group << 41) | (Security << 31) | ((ulong)Serial << 1) | (Upgrade ? (ulong)1 : 0); return BitConverter.GetBytes(shortauth); } diff --git a/LibTSforge/SPP/SLAPI.cs b/LibTSforge/SPP/SLAPI.cs index c25fb03..fc5823b 100644 --- a/LibTSforge/SPP/SLAPI.cs +++ b/LibTSforge/SPP/SLAPI.cs @@ -86,9 +86,6 @@ namespace LibTSforge.SPP [DllImport("slc.dll", CharSet = CharSet.Unicode)] private static extern uint SLGetProductSkuInformation(IntPtr hSLC, ref Guid pProductSkuId, string pwszValueName, out SLDATATYPE peDataType, out uint pcbValue, out IntPtr ppbValue); - [DllImport("slc.dll", CharSet = CharSet.Unicode)] - private static extern uint SLGetProductSkuInformation(IntPtr hSLC, ref Guid pProductSkuId, string pwszValueName, IntPtr peDataType, out uint pcbValue, out IntPtr ppbValue); - [DllImport("slc.dll", CharSet = CharSet.Unicode)] private static extern uint SLGetLicense(IntPtr hSLC, ref Guid pLicenseFileId, out uint pcbLicenseFile, out IntPtr ppbLicenseFile); @@ -98,7 +95,7 @@ namespace LibTSforge.SPP [DllImport("slc.dll", CharSet = CharSet.Unicode)] private static extern uint SLFireEvent(IntPtr hSLC, string pwszEventId, ref Guid pApplicationId); - public class SLContext : IDisposable + private class SLContext : IDisposable { public readonly IntPtr Handle; @@ -161,11 +158,10 @@ namespace LibTSforge.SPP { using (SLContext sl = new SLContext()) { - uint status; uint count; IntPtr pProductKeyIds; - status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_PRODUCT_SKU, ref actId, SLIDTYPE.SL_ID_PKEY, out count, out pProductKeyIds); + uint status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_PRODUCT_SKU, ref actId, SLIDTYPE.SL_ID_PKEY, out count, out pProductKeyIds); if (status != 0 || count == 0) { @@ -189,7 +185,7 @@ namespace LibTSforge.SPP SLConsumeWindowsRight(0); } - public static bool RefreshTrustedTime(Guid actId) + public static void RefreshTrustedTime(Guid actId) { using (SLContext sl = new SLContext()) { @@ -197,8 +193,7 @@ namespace LibTSforge.SPP uint count; IntPtr ppbValue; - uint status = SLGetProductSkuInformation(sl.Handle, ref actId, "TrustedTime", out type, out count, out ppbValue); - return (int)status >= 0 && status != 0xC004F012; + SLGetProductSkuInformation(sl.Handle, ref actId, "TrustedTime", out type, out count, out ppbValue); } } @@ -214,11 +209,10 @@ namespace LibTSforge.SPP { using (SLContext sl = new SLContext()) { - uint status; uint count; IntPtr pAppIds; - status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_PRODUCT_SKU, ref actId, SLIDTYPE.SL_ID_APPLICATION, out count, out pAppIds); + uint status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_PRODUCT_SKU, ref actId, SLIDTYPE.SL_ID_APPLICATION, out count, out pAppIds); if (status != 0 || count == 0) { @@ -242,15 +236,14 @@ namespace LibTSforge.SPP } } - public static Guid GetLicenseFileId(Guid licId) + private static Guid GetLicenseFileId(Guid licId) { using (SLContext sl = new SLContext()) { - uint status; uint count; IntPtr ppReturnLics; - status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_LICENSE, ref licId, SLIDTYPE.SL_ID_LICENSE_FILE, out count, out ppReturnLics); + uint status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_LICENSE, ref licId, SLIDTYPE.SL_ID_LICENSE_FILE, out count, out ppReturnLics); if (status != 0 || count == 0) { @@ -312,7 +305,7 @@ namespace LibTSforge.SPP IntPtr ppbValue; uint status = SLGetProductSkuInformation(sl.Handle, ref actId, "msft:sl/EUL/PHONE/PUBLIC", out type, out count, out ppbValue); - return status >= 0 && status != 0xC004F012; + return status != 0xC004F012; } } @@ -395,11 +388,11 @@ namespace LibTSforge.SPP } } - public static uint UninstallProductKey(Guid pkeyId) + public static void UninstallProductKey(Guid pkeyId) { using (SLContext sl = new SLContext()) { - return SLUninstallProofOfPurchase(sl.Handle, ref pkeyId); + SLUninstallProofOfPurchase(sl.Handle, ref pkeyId); } } diff --git a/LibTSforge/SPP/SPPUtils.cs b/LibTSforge/SPP/SPPUtils.cs index a535bc7..062e5ca 100644 --- a/LibTSforge/SPP/SPPUtils.cs +++ b/LibTSforge/SPP/SPPUtils.cs @@ -1,13 +1,13 @@ namespace LibTSforge.SPP { - using LibTSforge.Crypto; - using LibTSforge.PhysicalStore; - using LibTSforge.TokenStore; using Microsoft.Win32; using System; using System.IO; using System.Linq; using System.ServiceProcess; + using Crypto; + using PhysicalStore; + using TokenStore; public static class SPPUtils { @@ -148,7 +148,7 @@ namespace LibTSforge.SPP throw new FileNotFoundException("Failed to autodetect key type, specify physical store key with /prod or /test arguments."); } - public static string GetPSPath(PSVersion version) + private static string GetPSPath(PSVersion version) { switch (version) { @@ -328,7 +328,7 @@ namespace LibTSforge.SPP RestartSPP(version); - Logger.WriteLine("Loaded store file succesfully."); + Logger.WriteLine("Loaded store file successfully."); } } } diff --git a/LibTSforge/SPP/SPSys.cs b/LibTSforge/SPP/SPSys.cs index 18b3655..ecc331c 100644 --- a/LibTSforge/SPP/SPSys.cs +++ b/LibTSforge/SPP/SPSys.cs @@ -15,7 +15,7 @@ namespace LibTSforge.SPP [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); + private 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() { diff --git a/LibTSforge/TokenStore/Common.cs b/LibTSforge/TokenStore/Common.cs index 1dda7e7..d7133f2 100644 --- a/LibTSforge/TokenStore/Common.cs +++ b/LibTSforge/TokenStore/Common.cs @@ -14,7 +14,7 @@ namespace LibTSforge.TokenStore public class TokenMeta { public string Name; - public Dictionary Data = new Dictionary(); + public readonly Dictionary Data = new Dictionary(); public byte[] Serialize() { @@ -37,7 +37,7 @@ namespace LibTSforge.TokenStore return writer.GetBytes(); } - public void Deserialize(byte[] data) + private void Deserialize(byte[] data) { BinaryReader reader = new BinaryReader(new MemoryStream(data)); reader.ReadInt32(); diff --git a/LibTSforge/TokenStore/TokenStoreModern.cs b/LibTSforge/TokenStore/TokenStoreModern.cs index ee51e7a..2c39ca8 100644 --- a/LibTSforge/TokenStore/TokenStoreModern.cs +++ b/LibTSforge/TokenStore/TokenStoreModern.cs @@ -4,7 +4,7 @@ namespace LibTSforge.TokenStore using System.Collections.Generic; using System.IO; using System.Linq; - using LibTSforge.Crypto; + using Crypto; public class TokenStoreModern : ITokenStore { @@ -18,7 +18,7 @@ namespace LibTSforge.TokenStore private static readonly byte[] CONTS_FOOTER = Enumerable.Repeat((byte)0xAA, 0x20).ToArray(); private List Entries = new List(); - public FileStream TokensFile; + private readonly FileStream TokensFile; public void Deserialize() { @@ -40,7 +40,7 @@ namespace LibTSforge.TokenStore uint contentOffset = reader.ReadUInt32(); uint contentLength = reader.ReadUInt32(); uint allocLength = reader.ReadUInt32(); - byte[] contentData = new byte[] { }; + byte[] contentData = { }; if (populated) { @@ -140,11 +140,10 @@ namespace LibTSforge.TokenStore writer.WritePadding(BLOCK_PAD_SIZE); writer.BaseStream.Seek(curBlockOffset, SeekOrigin.Begin); - byte[] blockHash; byte[] blockData = new byte[BLOCK_SIZE - 0x20]; + byte[] blockHash = CryptoUtils.SHA256Hash(blockData); tokens.Read(blockData, 0, BLOCK_SIZE - 0x20); - blockHash = CryptoUtils.SHA256Hash(blockData); writer.BaseStream.Seek(curBlockOffset + BLOCK_SIZE - 0x20, SeekOrigin.Begin); writer.Write(blockHash); @@ -275,11 +274,6 @@ namespace LibTSforge.TokenStore Deserialize(); } - public TokenStoreModern() - { - - } - public void Dispose() { Serialize(); diff --git a/TSforgeCLI/Program.cs b/TSforgeCLI/Program.cs index 7c1a50b..d7073fe 100644 --- a/TSforgeCLI/Program.cs +++ b/TSforgeCLI/Program.cs @@ -10,30 +10,30 @@ namespace TSforgeCLI { private class Options { - public bool Dump = false; + public bool Dump; public string DumpFilePath = "dump.dat"; - public string EncrFilePath = null; - public bool Load = false; + public string EncrFilePath; + public bool Load; public string LoadFilePath = "load.dat"; - public bool KMS4k = false; - public bool AVMA4k = false; - public bool ZCID = false; - public bool TimerReset = false; - public bool RearmReset = false; - public bool DeleteUniqueId = false; - public bool InstallGenPKey = false; - public bool KMSHostCharge = false; - public bool TamperedFlagsDelete = false; - public bool KeyChangeLockDelete = false; - public bool SetIIDParams = false; - public bool? Production = null; - public PSVersion? Version = null; + public bool KMS4k; + public bool AVMA4k; + public bool ZCID; + public bool TimerReset; + public bool RearmReset; + public bool DeleteUniqueId; + public bool InstallGenPKey; + public bool KMSHostCharge; + public bool TamperedFlagsDelete; + public bool KeyChangeLockDelete; + public bool SetIIDParams; + public bool? Production; + public PSVersion? Version; public Guid ActivationId = Guid.Empty; - public bool ShowHelp = false; - public PKeyAlgorithm? Algorithm = null; - public int Group = 0; - public int Serial = 0; - public ulong Security = 0; + public bool ShowHelp; + public PKeyAlgorithm? Algorithm; + public int Group; + public int Serial; + public ulong Security; } public static void Main(string[] args) From 103981762f471dc2d2e33c1556b9013b1ab77425 Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Mon, 7 Apr 2025 18:01:39 -0400 Subject: [PATCH 30/34] fix bugs --- LibTSforge/Crypto/PhysStoreCrypto.cs | 2 +- LibTSforge/TokenStore/TokenStoreModern.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LibTSforge/Crypto/PhysStoreCrypto.cs b/LibTSforge/Crypto/PhysStoreCrypto.cs index 083841d..08978e2 100644 --- a/LibTSforge/Crypto/PhysStoreCrypto.cs +++ b/LibTSforge/Crypto/PhysStoreCrypto.cs @@ -16,7 +16,7 @@ namespace LibTSforge.Crypto byte[] aesKeySig = br.ReadBytes(0x80); byte[] encAesKey = br.ReadBytes(0x80); - if (CryptoUtils.RSAVerifySignature(rsaKey, encAesKey, aesKeySig)) + if (!CryptoUtils.RSAVerifySignature(rsaKey, encAesKey, aesKeySig)) { throw new Exception("Failed to decrypt physical store."); } diff --git a/LibTSforge/TokenStore/TokenStoreModern.cs b/LibTSforge/TokenStore/TokenStoreModern.cs index 2c39ca8..2ced532 100644 --- a/LibTSforge/TokenStore/TokenStoreModern.cs +++ b/LibTSforge/TokenStore/TokenStoreModern.cs @@ -141,9 +141,9 @@ namespace LibTSforge.TokenStore writer.BaseStream.Seek(curBlockOffset, SeekOrigin.Begin); byte[] blockData = new byte[BLOCK_SIZE - 0x20]; - byte[] blockHash = CryptoUtils.SHA256Hash(blockData); tokens.Read(blockData, 0, BLOCK_SIZE - 0x20); + byte[] blockHash = CryptoUtils.SHA256Hash(blockData); writer.BaseStream.Seek(curBlockOffset + BLOCK_SIZE - 0x20, SeekOrigin.Begin); writer.Write(blockHash); From 91e85088480b4734a9d7302cc980be761f68161b Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Mon, 7 Apr 2025 18:12:53 -0400 Subject: [PATCH 31/34] stylistic fixes --- LibTSforge/Activators/AVMA4K.cs | 3 +-- LibTSforge/Modifiers/SetIIDParams.cs | 1 + LibTSforge/PhysicalStore/Common.cs | 4 ++-- LibTSforge/SPP/ProductKey.cs | 27 +++++++++++---------------- LibTSforge/SPP/SPPUtils.cs | 2 +- 5 files changed, 16 insertions(+), 21 deletions(-) diff --git a/LibTSforge/Activators/AVMA4K.cs b/LibTSforge/Activators/AVMA4K.cs index 51b546a..236b727 100644 --- a/LibTSforge/Activators/AVMA4K.cs +++ b/LibTSforge/Activators/AVMA4K.cs @@ -50,8 +50,7 @@ namespace LibTSforge.Activators ulong time1 = (ulong)(creationTime + tickCount + deltaTime); ulong crcBindTime = (ulong)DateTime.UtcNow.ToFileTime(); ulong timerTime = crcBindTime / 10000; - ulong expiry = Constants.TimerMax; - expiry /= 10000; + ulong expiry = Constants.TimerMax / 10000; VariableBag avmaBinding = new VariableBag(version); diff --git a/LibTSforge/Modifiers/SetIIDParams.cs b/LibTSforge/Modifiers/SetIIDParams.cs index 2f34a7d..3d54b9d 100644 --- a/LibTSforge/Modifiers/SetIIDParams.cs +++ b/LibTSforge/Modifiers/SetIIDParams.cs @@ -4,6 +4,7 @@ namespace LibTSforge.Modifiers using SPP; using System.IO; using System; + public static class SetIIDParams { public static void SetParams(PSVersion version, bool production, Guid actId, PKeyAlgorithm algorithm, int group, int serial, ulong security) diff --git a/LibTSforge/PhysicalStore/Common.cs b/LibTSforge/PhysicalStore/Common.cs index aef77f8..d0ad4fe 100644 --- a/LibTSforge/PhysicalStore/Common.cs +++ b/LibTSforge/PhysicalStore/Common.cs @@ -4,9 +4,9 @@ namespace LibTSforge.PhysicalStore public enum BlockType : uint { - NONE, // unused + NONE, NAMED, - ATTRIBUTE, //unused + ATTRIBUTE, TIMER } diff --git a/LibTSforge/SPP/ProductKey.cs b/LibTSforge/SPP/ProductKey.cs index f4cf15a..03eb729 100644 --- a/LibTSforge/SPP/ProductKey.cs +++ b/LibTSforge/SPP/ProductKey.cs @@ -18,16 +18,16 @@ namespace LibTSforge.SPP public ulong Security; public bool Upgrade; public PKeyAlgorithm Algorithm; - private readonly string EulaType; - private readonly string PartNumber; + public readonly string EulaType; + public readonly string PartNumber; public readonly string Edition; public readonly string Channel; - private readonly Guid ActivationId; + public readonly Guid ActivationId; private string mpc; private string pid2; - private byte[] KeyBytes + public byte[] KeyBytes { get { return BitConverter.GetBytes(klow).Concat(BitConverter.GetBytes(khigh)).ToArray(); } } @@ -91,16 +91,6 @@ namespace LibTSforge.SPP return new Guid(CryptoUtils.SHA256Hash(pkb.Serialize()).Take(16).ToArray()); } - private string GetDefaultMPC() - { - int build = Environment.OSVersion.Version.Build; - string defaultMPC = build >= 10240 ? "03612" : - build >= 9600 ? "06401" : - build >= 9200 ? "05426" : - "55041"; - return defaultMPC; - } - public string GetMPC() { if (mpc != null) @@ -108,7 +98,12 @@ namespace LibTSforge.SPP return mpc; } - mpc = GetDefaultMPC(); + int build = Environment.OSVersion.Version.Build; + + mpc = build >= 10240 ? "03612" : + build >= 9600 ? "06401" : + build >= 9200 ? "05426" : + "55041"; // setup.cfg doesn't exist in Windows 8+ string setupcfg = string.Format(@"{0}\oobe\{1}", Environment.SystemDirectory, "setup.cfg"); @@ -205,7 +200,7 @@ namespace LibTSforge.SPP return writer.GetBytes(); } - private string GetExtendedPid() + public string GetExtendedPid() { string mpc = GetMPC(); int serialHigh = Serial / 1000000; diff --git a/LibTSforge/SPP/SPPUtils.cs b/LibTSforge/SPP/SPPUtils.cs index 062e5ca..fc4967b 100644 --- a/LibTSforge/SPP/SPPUtils.cs +++ b/LibTSforge/SPP/SPPUtils.cs @@ -148,7 +148,7 @@ namespace LibTSforge.SPP throw new FileNotFoundException("Failed to autodetect key type, specify physical store key with /prod or /test arguments."); } - private static string GetPSPath(PSVersion version) + public static string GetPSPath(PSVersion version) { switch (version) { From 22bbb93e909154da94aee1b55e551038a3a37e6c Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Mon, 7 Apr 2025 18:17:43 -0400 Subject: [PATCH 32/34] make public --- LibTSforge/SPP/SLAPI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibTSforge/SPP/SLAPI.cs b/LibTSforge/SPP/SLAPI.cs index fc5823b..ec27381 100644 --- a/LibTSforge/SPP/SLAPI.cs +++ b/LibTSforge/SPP/SLAPI.cs @@ -236,7 +236,7 @@ namespace LibTSforge.SPP } } - private static Guid GetLicenseFileId(Guid licId) + public static Guid GetLicenseFileId(Guid licId) { using (SLContext sl = new SLContext()) { From cb5c97d443982e547a8dd5a76032de8fa6859b61 Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Mon, 7 Apr 2025 19:23:07 -0400 Subject: [PATCH 33/34] update usage, readme --- README.md | 4 ++-- TSforgeCLI/Program.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 411e464..4580f0c 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Included methods and tools: ## Usage ``` -Usage: TSforge [/dump ()] [/load ] [/kms4k] [/avma4k] [/zcid] [/rtmr] [/duid] [/igpk] [/kmsc] [/ctpr] [/revl] [/prod] [/test] [] [/ver ] +Usage: TSforge [/dump ()] [/load ] [/kms4k] [/avma4k] [/zcid] [/rtmr] [/duid] [/igpk] [/kmsc] [/ctpr] [/revl] [/siid <5/9> ] [/prod] [/test] [] [/ver ] Options: /dump () Dump and decrypt the physical store to the specified path. /load Load and re-encrypt the physical store from the specified path. @@ -95,7 +95,7 @@ The following options are NOT implemented: - `/siid` - IID is also derived directly from the key string - `/revl` - Eval key lock is not present on Vista - Effectively, this means that a product key must be provided to activate a given SKU. Additionally, ZeroCID on Vista/Server 2008 lacks protection against WGA. + Effectively, this means that a product key must be provided to activate a given SKU. Additionally, ZeroCID on Vista/Server 2008 lacks protection against deactivation due to the WGA update KB929391, though this update is no longer offered via Windows Update. ### How do I prevent de-activation due to WAT on Windows 7? diff --git a/TSforgeCLI/Program.cs b/TSforgeCLI/Program.cs index 7c1a50b..25e132f 100644 --- a/TSforgeCLI/Program.cs +++ b/TSforgeCLI/Program.cs @@ -249,7 +249,7 @@ namespace TSforgeCLI private static void DisplayUsage() { string exeName = typeof(Program).Namespace; - Logger.WriteLine("Usage: " + exeName + " [/dump ()] [/load ] [/kms4k] [/avma4k] [/zcid] [/rtmr] [/duid] [/igpk] [/kmsc] [/ctpr] [/revl] [/prod] [/test] [] [/ver ]"); + Logger.WriteLine("Usage: " + exeName + " [/dump ()] [/load ] [/kms4k] [/avma4k] [/zcid] [/rtmr] [/duid] [/igpk] [/kmsc] [/ctpr] [/revl] [/siid <5/9> ] [/prod] [/test] [] [/ver ]"); Logger.WriteLine("Options:"); Logger.WriteLine("\t/dump () Dump and decrypt the physical store to the specified path."); Logger.WriteLine("\t/load Load and re-encrypt the physical store from the specified path."); From 912f83c11b75c93f38b7966d7b727144eee7f23d Mon Sep 17 00:00:00 2001 From: Wither OrNot Date: Tue, 15 Apr 2025 16:07:03 -0400 Subject: [PATCH 34/34] fix vista varbag --- LibTSforge/PhysicalStore/VariableBag.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/LibTSforge/PhysicalStore/VariableBag.cs b/LibTSforge/PhysicalStore/VariableBag.cs index bca0e32..c99695e 100644 --- a/LibTSforge/PhysicalStore/VariableBag.cs +++ b/LibTSforge/PhysicalStore/VariableBag.cs @@ -74,6 +74,7 @@ namespace LibTSforge.PhysicalStore public override void Decode(BinaryReader reader) { uint type = reader.ReadUInt32(); + reader.ReadUInt32(); uint lenName = reader.ReadUInt32(); uint lenVal = reader.ReadUInt32(); uint crc = reader.ReadUInt32();