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

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

View File

@ -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[] { },

View File

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

View File

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

View File

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

View File

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

View File

@ -2,13 +2,15 @@ namespace LibTSforge.Crypto
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
public static class PhysStoreCrypto
{
public static byte[] DecryptPhysicalStore(byte[] data, bool production)
public static byte[] DecryptPhysicalStore(byte[] data, bool production, PSVersion version)
{
byte[] rsaKey = production ? Keys.PRODUCTION : Keys.TEST;
BinaryReader br = new BinaryReader(new MemoryStream(data));
@ -20,13 +22,23 @@ namespace LibTSforge.Crypto
{
byte[] aesKey = CryptoUtils.RSADecrypt(rsaKey, encAesKey);
byte[] decData = CryptoUtils.AESDecrypt(br.ReadBytes((int)br.BaseStream.Length - 0x110), aesKey);
byte[] hmacKey = decData.Take(0x10).ToArray();
byte[] hmacSig = decData.Skip(0x10).Take(0x14).ToArray();
byte[] hmacKey = decData.Take(0x10).ToArray(); // SHA-1 salt on Vista
byte[] hmacSig = decData.Skip(0x10).Take(0x14).ToArray(); // SHA-1 hash on Vista
byte[] psData = decData.Skip(0x28).ToArray();
if (!CryptoUtils.HMACVerify(hmacKey, psData, hmacSig))
if (version != PSVersion.Vista)
{
Logger.WriteLine("Warning: Failed to verify HMAC. Physical store is either corrupt or in Vista format.");
if (!CryptoUtils.HMACVerify(hmacKey, psData, hmacSig))
{
throw new InvalidDataException("Failed to verify HMAC. Physical store is corrupt.");
}
}
else
{
if (!CryptoUtils.SaltSHAVerify(hmacKey, psData, hmacSig))
{
throw new InvalidDataException("Failed to verify checksum. Physical store is corrupt.");
}
}
return psData;
@ -39,6 +51,7 @@ namespace LibTSforge.Crypto
{
Dictionary<PSVersion, int> versionTable = new Dictionary<PSVersion, int>
{
{PSVersion.Vista, 2},
{PSVersion.Win7, 5},
{PSVersion.Win8, 1},
{PSVersion.WinBlue, 2},
@ -52,7 +65,7 @@ namespace LibTSforge.Crypto
byte[] encAesKey = CryptoUtils.RSAEncrypt(rsaKey, aesKey);
byte[] aesKeySig = CryptoUtils.RSASign(rsaKey, encAesKey);
byte[] hmacSig = CryptoUtils.HMACSign(hmacKey, data);
byte[] hmacSig = version != PSVersion.Vista ? CryptoUtils.HMACSign(hmacKey, data) : CryptoUtils.SaltSHASum(hmacKey, data);
byte[] decData = new byte[] { };
decData = decData.Concat(hmacKey).Concat(hmacSig).Concat(BitConverter.GetBytes(0)).Concat(data).ToArray();

View File

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

View File

@ -4,15 +4,16 @@ namespace LibTSforge.Modifiers
using System.Collections.Generic;
using System.Linq;
using LibTSforge.PhysicalStore;
using LibTSforge.SPP;
public static class GracePeriodReset
{
public static void Reset(PSVersion version, bool production)
{
Utils.KillSPP();
SPPUtils.KillSPP(version);
Logger.WriteLine("Writing TrustedStore data...");
using (IPhysicalStore store = Utils.GetStore(version, production))
using (IPhysicalStore store = SPPUtils.GetStore(version, production))
{
string value = "msft:sl/timer";
List<PSBlock> blocks = store.FindBlocks(value).ToList();
@ -23,6 +24,7 @@ namespace LibTSforge.Modifiers
}
}
SPPUtils.RestartSPP(version);
Logger.WriteLine("Successfully reset all grace and evaluation period timers.");
}
}

View File

@ -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[] { },

View File

@ -3,14 +3,16 @@ namespace LibTSforge.Modifiers
using System.Collections.Generic;
using System.Linq;
using LibTSforge.PhysicalStore;
using LibTSforge.SPP;
using LibTSforge;
public static class KeyChangeLockDelete
{
public static void Delete(PSVersion version, bool production)
{
Utils.KillSPP();
SPPUtils.KillSPP(version);
Logger.WriteLine("Writing TrustedStore data...");
using (IPhysicalStore store = Utils.GetStore(version, production))
using (IPhysicalStore store = SPPUtils.GetStore(version, production))
{
List<string> values = new List<string>
{

View File

@ -4,16 +4,17 @@ namespace LibTSforge.Modifiers
using System.Collections.Generic;
using System.Linq;
using LibTSforge.PhysicalStore;
using LibTSforge.SPP;
public static class RearmReset
{
public static void Reset(PSVersion version, bool production)
{
Utils.KillSPP();
SPPUtils.KillSPP(version);
Logger.WriteLine("Writing TrustedStore data...");
using (IPhysicalStore store = Utils.GetStore(version, production))
using (IPhysicalStore store = SPPUtils.GetStore(version, production))
{
List<PSBlock> blocks;

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,356 @@
namespace LibTSforge.PhysicalStore
{
using System;
using System.Collections.Generic;
using System.IO;
using LibTSforge.Crypto;
public class VistaBlock
{
public BlockType Type;
public uint Flags;
public byte[] Value;
public string ValueAsStr
{
get
{
return Utils.DecodeString(Value);
}
set
{
Value = Utils.EncodeString(value);
}
}
public uint ValueAsInt
{
get
{
return BitConverter.ToUInt32(Value, 0);
}
set
{
Value = BitConverter.GetBytes(value);
}
}
public byte[] Data;
public string DataAsStr
{
get
{
return Utils.DecodeString(Data);
}
set
{
Data = Utils.EncodeString(value);
}
}
public uint DataAsInt
{
get
{
return BitConverter.ToUInt32(Data, 0);
}
set
{
Data = BitConverter.GetBytes(value);
}
}
internal void Encode(BinaryWriter writer)
{
writer.Write((uint)Type);
writer.Write(Flags);
writer.Write(Value.Length);
writer.Write(Data.Length);
writer.Write(Value);
writer.Write(Data);
}
internal static VistaBlock Decode(BinaryReader reader)
{
uint type = reader.ReadUInt32();
uint flags = reader.ReadUInt32();
int valueLen = reader.ReadInt32();
int dataLen = reader.ReadInt32();
byte[] value = reader.ReadBytes(valueLen);
byte[] data = reader.ReadBytes(dataLen);
return new VistaBlock
{
Type = (BlockType)type,
Flags = flags,
Value = value,
Data = data,
};
}
}
public sealed class PhysicalStoreVista : IPhysicalStore
{
private byte[] PreHeaderBytes = new byte[] { };
private readonly List<VistaBlock> Blocks = new List<VistaBlock>();
private readonly FileStream TSPrimary;
private readonly FileStream TSSecondary;
private readonly bool Production;
public byte[] Serialize()
{
BinaryWriter writer = new BinaryWriter(new MemoryStream());
writer.Write(PreHeaderBytes);
foreach (VistaBlock block in Blocks)
{
block.Encode(writer);
writer.Align(4);
}
return writer.GetBytes();
}
public void Deserialize(byte[] data)
{
int len = data.Length;
BinaryReader reader = new BinaryReader(new MemoryStream(data));
PreHeaderBytes = reader.ReadBytes(8);
while (reader.BaseStream.Position < len - 0x14)
{
Blocks.Add(VistaBlock.Decode(reader));
reader.Align(4);
}
}
public void AddBlock(PSBlock block)
{
Blocks.Add(new VistaBlock
{
Type = block.Type,
Flags = block.Flags,
Value = block.Value,
Data = block.Data
});
}
public void AddBlocks(IEnumerable<PSBlock> blocks)
{
foreach (PSBlock block in blocks)
{
AddBlock(block);
}
}
public PSBlock GetBlock(string key, string value)
{
foreach (VistaBlock block in Blocks)
{
if (block.ValueAsStr == value)
{
return new PSBlock
{
Type = block.Type,
Flags = block.Flags,
Key = new byte[0],
Value = block.Value,
Data = block.Data
};
}
}
return null;
}
public PSBlock GetBlock(string key, uint value)
{
foreach (VistaBlock block in Blocks)
{
if (block.ValueAsInt == value)
{
return new PSBlock
{
Type = block.Type,
Flags = block.Flags,
Key = new byte[0],
Value = block.Value,
Data = block.Data
};
}
}
return null;
}
public void SetBlock(string key, string value, byte[] data)
{
for (int i = 0; i < Blocks.Count; i++)
{
VistaBlock block = Blocks[i];
if (block.ValueAsStr == value)
{
block.Data = data;
Blocks[i] = block;
break;
}
}
}
public void SetBlock(string key, uint value, byte[] data)
{
for (int i = 0; i < Blocks.Count; i++)
{
VistaBlock block = Blocks[i];
if (block.ValueAsInt == value)
{
block.Data = data;
Blocks[i] = block;
break;
}
}
}
public void SetBlock(string key, string value, string data)
{
SetBlock(key, value, Utils.EncodeString(data));
}
public void SetBlock(string key, string value, uint data)
{
SetBlock(key, value, BitConverter.GetBytes(data));
}
public void SetBlock(string key, uint value, string data)
{
SetBlock(key, value, Utils.EncodeString(data));
}
public void SetBlock(string key, uint value, uint data)
{
SetBlock(key, value, BitConverter.GetBytes(data));
}
public void DeleteBlock(string key, string value)
{
foreach (VistaBlock block in Blocks)
{
if (block.ValueAsStr == value)
{
Blocks.Remove(block);
return;
}
}
}
public void DeleteBlock(string key, uint value)
{
foreach (VistaBlock block in Blocks)
{
if (block.ValueAsInt == value)
{
Blocks.Remove(block);
return;
}
}
}
public PhysicalStoreVista(string primaryPath, bool production)
{
TSPrimary = File.Open(primaryPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
TSSecondary = File.Open(primaryPath.Replace("-0.", "-1."), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
Production = production;
Deserialize(PhysStoreCrypto.DecryptPhysicalStore(TSPrimary.ReadAllBytes(), production, PSVersion.Vista));
TSPrimary.Seek(0, SeekOrigin.Begin);
}
public void Dispose()
{
if (TSPrimary.CanWrite && TSSecondary.CanWrite)
{
byte[] data = PhysStoreCrypto.EncryptPhysicalStore(Serialize(), Production, PSVersion.Vista);
TSPrimary.SetLength(data.LongLength);
TSSecondary.SetLength(data.LongLength);
TSPrimary.Seek(0, SeekOrigin.Begin);
TSSecondary.Seek(0, SeekOrigin.Begin);
TSPrimary.WriteAllBytes(data);
TSSecondary.WriteAllBytes(data);
TSPrimary.Close();
TSSecondary.Close();
}
}
public byte[] ReadRaw()
{
byte[] data = PhysStoreCrypto.DecryptPhysicalStore(TSPrimary.ReadAllBytes(), Production, PSVersion.Vista);
TSPrimary.Seek(0, SeekOrigin.Begin);
return data;
}
public void WriteRaw(byte[] data)
{
byte[] encrData = PhysStoreCrypto.EncryptPhysicalStore(data, Production, PSVersion.Vista);
TSPrimary.SetLength(encrData.LongLength);
TSSecondary.SetLength(encrData.LongLength);
TSPrimary.Seek(0, SeekOrigin.Begin);
TSSecondary.Seek(0, SeekOrigin.Begin);
TSPrimary.WriteAllBytes(encrData);
TSSecondary.WriteAllBytes(encrData);
TSPrimary.Close();
TSSecondary.Close();
}
public IEnumerable<PSBlock> FindBlocks(string valueSearch)
{
List<PSBlock> results = new List<PSBlock>();
foreach (VistaBlock block in Blocks)
{
if (block.ValueAsStr.Contains(valueSearch))
{
results.Add(new PSBlock
{
Type = block.Type,
Flags = block.Flags,
Key = new byte[0],
Value = block.Value,
Data = block.Data
});
}
}
return results;
}
public IEnumerable<PSBlock> FindBlocks(uint valueSearch)
{
List<PSBlock> results = new List<PSBlock>();
foreach (VistaBlock block in Blocks)
{
if (block.ValueAsInt == valueSearch)
{
results.Add(new PSBlock
{
Type = block.Type,
Flags = block.Flags,
Key = new byte[0],
Value = block.Value,
Data = block.Data
});
}
}
return results;
}
}
}

View File

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

View File

@ -3,6 +3,7 @@ namespace LibTSforge.PhysicalStore
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
public enum CRCBlockType : uint
{
@ -11,7 +12,7 @@ namespace LibTSforge.PhysicalStore
BINARY = 1 << 2
}
public class CRCBlock
public abstract class CRCBlock
{
public CRCBlockType DataType;
public byte[] Key;
@ -50,7 +51,57 @@ namespace LibTSforge.PhysicalStore
}
}
public void Encode(BinaryWriter writer)
public abstract void Encode(BinaryWriter writer);
public abstract void Decode(BinaryReader reader);
public abstract uint CRC();
}
public class CRCBlockVista : CRCBlock
{
public override void Encode(BinaryWriter writer)
{
uint crc = CRC();
writer.Write((uint)DataType);
writer.Write(0);
writer.Write(Key.Length);
writer.Write(Value.Length);
writer.Write(crc);
writer.Write(Key);
writer.Write(Value);
}
public override void Decode(BinaryReader reader)
{
uint type = reader.ReadUInt32();
uint unk_zero = reader.ReadUInt32();
uint lenName = reader.ReadUInt32();
uint lenVal = reader.ReadUInt32();
uint crc = reader.ReadUInt32();
byte[] key = reader.ReadBytes((int)lenName);
byte[] value = reader.ReadBytes((int)lenVal);
DataType = (CRCBlockType)type;
Key = key;
Value = value;
if (CRC() != crc)
{
throw new InvalidDataException("Invalid CRC in variable bag.");
}
}
public override uint CRC()
{
return Utils.CRC32(Value);
}
}
public class CRCBlockModern : CRCBlock
{
public override void Encode(BinaryWriter writer)
{
uint crc = CRC();
writer.Write(crc);
@ -65,7 +116,7 @@ namespace LibTSforge.PhysicalStore
writer.Align(8);
}
public static CRCBlock Decode(BinaryReader reader)
public override void Decode(BinaryReader reader)
{
uint crc = reader.ReadUInt32();
uint type = reader.ReadUInt32();
@ -78,22 +129,17 @@ namespace LibTSforge.PhysicalStore
byte[] value = reader.ReadBytes((int)lenVal);
reader.Align(8);
CRCBlock block = new CRCBlock
{
DataType = (CRCBlockType)type,
Key = key,
Value = value,
};
DataType = (CRCBlockType)type;
Key = key;
Value = value;
if (block.CRC() != crc)
if (CRC() != crc)
{
throw new InvalidDataException("Invalid CRC in variable bag.");
}
return block;
}
public uint CRC()
public override uint CRC()
{
BinaryWriter wtemp = new BinaryWriter(new MemoryStream());
wtemp.Write(0);
@ -109,6 +155,7 @@ namespace LibTSforge.PhysicalStore
public class VariableBag
{
public List<CRCBlock> Blocks = new List<CRCBlock>();
private PSVersion Version;
public void Deserialize(byte[] data)
{
@ -118,7 +165,19 @@ namespace LibTSforge.PhysicalStore
while (reader.BaseStream.Position < len - 0x10)
{
Blocks.Add(CRCBlock.Decode(reader));
CRCBlock block;
if (Version == PSVersion.Vista)
{
block = new CRCBlockVista();
}
else
{
block = new CRCBlockModern();
}
block.Decode(reader);
Blocks.Add(block);
}
}
@ -128,7 +187,13 @@ namespace LibTSforge.PhysicalStore
foreach (CRCBlock block in Blocks)
{
block.Encode(writer);
if (Version == PSVersion.Vista)
{
((CRCBlockVista)block).Encode(writer);
} else
{
((CRCBlockModern)block).Encode(writer);
}
}
return writer.GetBytes();
@ -174,14 +239,15 @@ namespace LibTSforge.PhysicalStore
}
}
public VariableBag(byte[] data)
public VariableBag(byte[] data, PSVersion version)
{
Version = version;
Deserialize(data);
}
public VariableBag()
public VariableBag(PSVersion version)
{
Version = version;
}
}
}

View File

@ -60,22 +60,22 @@ namespace LibTSforge.SPP
public Guid GetPkeyId()
{
VariableBag pkb = new VariableBag();
pkb.Blocks.AddRange(new CRCBlock[]
VariableBag pkb = new VariableBag(PSVersion.WinModern);
pkb.Blocks.AddRange(new CRCBlockModern[]
{
new CRCBlock
new CRCBlockModern
{
DataType = CRCBlockType.STRING,
KeyAsStr = "SppPkeyBindingProductKey",
ValueAsStr = ToString()
},
new CRCBlock
new CRCBlockModern
{
DataType = CRCBlockType.BINARY,
KeyAsStr = "SppPkeyBindingMiscData",
Value = new byte[] { }
},
new CRCBlock
new CRCBlockModern
{
DataType = CRCBlockType.STRING,
KeyAsStr = "SppPkeyBindingAlgorithm",

View File

@ -44,40 +44,40 @@ namespace LibTSforge.SPP
public static readonly Guid WINDOWS_APP_ID = new Guid("55c92734-d682-4d71-983e-d6ec3f16059f");
[DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
[DllImport("slc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
private static extern void SLOpen(out IntPtr hSLC);
[DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
[DllImport("slc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
private static extern void SLClose(IntPtr hSLC);
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLGetWindowsInformationDWORD(string ValueName, ref int Value);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLInstallProofOfPurchase(IntPtr hSLC, string pwszPKeyAlgorithm, string pwszPKeyString, uint cbPKeySpecificData, byte[] pbPKeySpecificData, ref Guid PKeyId);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLUninstallProofOfPurchase(IntPtr hSLC, ref Guid PKeyId);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLGetPKeyInformation(IntPtr hSLC, ref Guid pPKeyId, string pwszValueName, out SLDATATYPE peDataType, out uint pcbValue, out IntPtr ppbValue);
[DllImport("sppcext.dll", CharSet = CharSet.Unicode)]
[DllImport("slcext.dll", CharSet = CharSet.Unicode)]
private static extern uint SLActivateProduct(IntPtr hSLC, ref Guid pProductSkuId, byte[] cbAppSpecificData, byte[] pvAppSpecificData, byte[] pActivationInfo, string pwszProxyServer, ushort wProxyPort);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLGenerateOfflineInstallationId(IntPtr hSLC, ref Guid pProductSkuId, ref string ppwszInstallationId);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLDepositOfflineConfirmationId(IntPtr hSLC, ref Guid pProductSkuId, string pwszInstallationId, string pwszConfirmationId);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLGetSLIDList(IntPtr hSLC, SLIDTYPE eQueryIdType, ref Guid pQueryId, SLIDTYPE eReturnIdType, out uint pnReturnIds, out IntPtr ppReturnIds);
[DllImport("sppc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
[DllImport("slc.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
private static extern void SLGetLicensingStatusInformation(IntPtr hSLC, ref Guid pAppID, IntPtr pProductSkuId, string pwszRightName, out uint pnStatusCount, out IntPtr ppLicensingStatus);
[DllImport("sppc.dll", CharSet = CharSet.Unicode)]
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
private static extern uint SLGetInstalledProductKeyIds(IntPtr hSLC, ref Guid pProductSkuId, out uint pnProductKeyIds, out IntPtr ppProductKeyIds);
[DllImport("slc.dll", CharSet = CharSet.Unicode)]

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

@ -0,0 +1,275 @@
namespace LibTSforge.SPP
{
using LibTSforge.Crypto;
using LibTSforge.PhysicalStore;
using LibTSforge.TokenStore;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
public static class SPPUtils
{
public static void KillSPP(PSVersion version)
{
ServiceController sc;
string svcName = version == PSVersion.Vista ? "slsvc" : "sppsvc";
try
{
sc = new ServiceController(svcName);
if (sc.Status == ServiceControllerStatus.Stopped)
return;
}
catch (InvalidOperationException ex)
{
throw new InvalidOperationException(string.Format("Unable to access {0}: ", svcName) + ex.Message);
}
Logger.WriteLine(string.Format("Stopping {0}...", svcName));
bool stopped = false;
for (int i = 0; stopped == false && i < 360; i++)
{
try
{
if (sc.Status != ServiceControllerStatus.StopPending)
sc.Stop();
sc.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromMilliseconds(500));
}
catch (System.ServiceProcess.TimeoutException)
{
continue;
}
catch (InvalidOperationException)
{
System.Threading.Thread.Sleep(500);
continue;
}
stopped = true;
}
if (!stopped)
throw new System.TimeoutException(string.Format("Failed to stop {0}", svcName));
Logger.WriteLine(string.Format("{0} stopped successfully.", svcName));
if (version == PSVersion.Vista && SPSys.IsSpSysRunning())
{
Logger.WriteLine("Unloading spsys...");
int status = SPSys.ControlSpSys(false);
if (status < 0)
{
throw new IOException("Failed to unload spsys");
}
Logger.WriteLine("spsys unloaded successfully.");
}
}
public static void RestartSPP(PSVersion version)
{
if (version == PSVersion.Vista)
{
ServiceController sc;
try
{
sc = new ServiceController("slsvc");
if (sc.Status == ServiceControllerStatus.Running)
return;
}
catch (InvalidOperationException ex)
{
throw new InvalidOperationException("Unable to access slsvc: " + ex.Message);
}
Logger.WriteLine("Starting slsvc...");
bool started = false;
for (int i = 0; started == false && i < 360; i++)
{
try
{
if (sc.Status != ServiceControllerStatus.StartPending)
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromMilliseconds(500));
}
catch (System.ServiceProcess.TimeoutException)
{
continue;
}
catch (InvalidOperationException)
{
System.Threading.Thread.Sleep(500);
continue;
}
started = true;
}
if (!started)
throw new System.TimeoutException("Failed to start slsvc");
Logger.WriteLine("slsvc started successfully.");
}
SLApi.RefreshLicenseStatus();
}
public static string GetPSPath(PSVersion version)
{
switch (version)
{
case PSVersion.Vista:
case PSVersion.Win7:
return Directory.GetFiles(
Environment.GetFolderPath(Environment.SpecialFolder.System),
"7B296FB0-376B-497e-B012-9C450E1B7327-*.C7483456-A289-439d-8115-601632D005A0")
.FirstOrDefault() ?? "";
default:
return Path.Combine(
Environment.ExpandEnvironmentVariables(
(string)Registry.GetValue(
@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform",
"TokenStore",
string.Empty
)
),
"data.dat"
);
}
}
public static string GetTokensPath(PSVersion version)
{
switch (version)
{
case PSVersion.Vista:
return Path.Combine(
Environment.ExpandEnvironmentVariables("%WINDIR%"),
@"ServiceProfiles\NetworkService\AppData\Roaming\Microsoft\SoftwareLicensing\tokens.dat"
);
case PSVersion.Win7:
return Path.Combine(
Environment.ExpandEnvironmentVariables("%WINDIR%"),
@"ServiceProfiles\NetworkService\AppData\Roaming\Microsoft\SoftwareProtectionPlatform\tokens.dat"
);
default:
return Path.Combine(
Environment.ExpandEnvironmentVariables(
(string)Registry.GetValue(
@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform",
"TokenStore",
string.Empty
)
),
"tokens.dat"
);
}
}
public static IPhysicalStore GetStore(PSVersion version, bool production)
{
string psPath;
try
{
psPath = GetPSPath(version);
}
catch
{
throw new FileNotFoundException("Failed to get path of physical store.");
}
if (string.IsNullOrEmpty(psPath) || !File.Exists(psPath))
{
throw new FileNotFoundException(string.Format("Physical store not found at expected path {0}.", psPath));
}
switch (version)
{
case PSVersion.Vista:
return new PhysicalStoreVista(psPath, production);
case PSVersion.Win7:
return new PhysicalStoreWin7(psPath, production);
default:
return new PhysicalStoreModern(psPath, production, version);
}
}
public static ITokenStore GetTokenStore(PSVersion version)
{
string tokPath;
try
{
tokPath = GetTokensPath(version);
}
catch
{
throw new FileNotFoundException("Failed to get path of physical store.");
}
if (string.IsNullOrEmpty(tokPath) || !File.Exists(tokPath))
{
throw new FileNotFoundException(string.Format("Token store not found at expected path {0}.", tokPath));
}
return new TokenStoreModern(tokPath);
}
public static void DumpStore(PSVersion version, bool production, string filePath, string encrFilePath)
{
if (encrFilePath == null)
{
encrFilePath = GetPSPath(version);
}
if (string.IsNullOrEmpty(encrFilePath) || !File.Exists(encrFilePath))
{
throw new FileNotFoundException("Store does not exist at expected path '" + encrFilePath + "'.");
}
KillSPP(version);
using (FileStream fs = File.Open(encrFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
{
byte[] encrData = fs.ReadAllBytes();
File.WriteAllBytes(filePath, PhysStoreCrypto.DecryptPhysicalStore(encrData, production, version));
}
Logger.WriteLine("Store dumped successfully to '" + filePath + "'.");
}
public static void LoadStore(PSVersion version, bool production, string filePath)
{
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
{
throw new FileNotFoundException("Store file '" + filePath + "' does not exist.");
}
KillSPP(version);
using (IPhysicalStore store = GetStore(version, production))
{
store.WriteRaw(File.ReadAllBytes(filePath));
}
Logger.WriteLine("Loaded store file succesfully.");
}
}
}

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

@ -0,0 +1,47 @@
namespace LibTSforge.SPP
{
using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
public class SPSys
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
private static SafeFileHandle CreateFileSafe(string device)
{
return new SafeFileHandle(CreateFile(device, 0xC0000000, 0, IntPtr.Zero, 3, 0, IntPtr.Zero), true);
}
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool DeviceIoControl([In] SafeFileHandle hDevice, [In] uint dwIoControlCode, [In] IntPtr lpInBuffer, [In] int nInBufferSize, [Out] IntPtr lpOutBuffer, [In] int nOutBufferSize, out int lpBytesReturned, [In] IntPtr lpOverlapped);
public static bool IsSpSysRunning()
{
SafeFileHandle file = CreateFileSafe(@"\\.\SpDevice");
IntPtr buffer = Marshal.AllocHGlobal(1);
int bytesReturned = 0;
DeviceIoControl(file, 0x80006008, IntPtr.Zero, 0, buffer, 1, out bytesReturned, IntPtr.Zero);
bool running = Marshal.ReadByte(buffer) != 0;
Marshal.FreeHGlobal(buffer);
file.Close();
return running;
}
public static int ControlSpSys(bool start)
{
SafeFileHandle file = CreateFileSafe(@"\\.\SpDevice");
IntPtr buffer = Marshal.AllocHGlobal(4);
int bytesReturned = 0;
DeviceIoControl(file, start ? 0x8000a000 : 0x8000a004, IntPtr.Zero, 0, buffer, 4, out bytesReturned, IntPtr.Zero);
int result = Marshal.ReadInt32(buffer);
Marshal.FreeHGlobal(buffer);
file.Close();
return result;
}
}
}

View File

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

View File

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