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:
parent
8aa1f9078d
commit
6d759899d8
@ -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[] { },
|
||||
|
@ -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.");
|
||||
}
|
||||
|
@ -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.");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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())
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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.");
|
||||
}
|
||||
}
|
||||
|
@ -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[] { },
|
||||
|
@ -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>
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
356
LibTSforge/PhysicalStore/PhysicalStoreVista.cs
Normal file
356
LibTSforge/PhysicalStore/PhysicalStoreVista.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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
275
LibTSforge/SPP/SPPUtils.cs
Normal 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
47
LibTSforge/SPP/SPSys.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user