commit
f81edcb317
2
.gitignore
vendored
2
.gitignore
vendored
@ -361,3 +361,5 @@ MigrationBackup/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
launchSettings.json
|
||||
|
@ -1,14 +1,14 @@
|
||||
namespace LibTSforge.Activators
|
||||
{
|
||||
using System;
|
||||
using LibTSforge.PhysicalStore;
|
||||
using LibTSforge.SPP;
|
||||
using PhysicalStore;
|
||||
using SPP;
|
||||
|
||||
public static class AVMA4k
|
||||
{
|
||||
public static void Activate(PSVersion version, bool production, Guid actId)
|
||||
{
|
||||
if (version != PSVersion.WinModern)
|
||||
if (version != PSVersion.WinModern && version != PSVersion.WinBlue)
|
||||
{
|
||||
throw new NotSupportedException("AVMA licenses are not available for this product.");
|
||||
}
|
||||
@ -34,46 +34,41 @@ 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);
|
||||
|
||||
ulong unknown = 0;
|
||||
ulong time1;
|
||||
ulong crcBindTime = (ulong)DateTime.UtcNow.ToFileTime();
|
||||
ulong timerTime;
|
||||
|
||||
ulong expiry = Constants.TimerMax;
|
||||
|
||||
long creationTime = BitConverter.ToInt64(store.GetBlock("__##USERSEP##\\$$_RESERVED_$$\\NAMESPACE__", "__##USERSEP-RESERVED##__$$GLOBAL-CREATION-TIME$$").Data, 0);
|
||||
long tickCount = BitConverter.ToInt64(store.GetBlock("__##USERSEP##\\$$_RESERVED_$$\\NAMESPACE__", "__##USERSEP-RESERVED##__$$GLOBAL-TICKCOUNT-UPTIME$$").Data, 0);
|
||||
long deltaTime = BitConverter.ToInt64(store.GetBlock(key, "__##USERSEP-RESERVED##__$$UP-TIME-DELTA$$").Data, 0);
|
||||
|
||||
time1 = (ulong)(creationTime + tickCount + deltaTime);
|
||||
timerTime = crcBindTime / 10000;
|
||||
expiry /= 10000;
|
||||
const ulong unknown = 0;
|
||||
ulong time1 = (ulong)(creationTime + tickCount + deltaTime);
|
||||
ulong crcBindTime = (ulong)DateTime.UtcNow.ToFileTime();
|
||||
ulong timerTime = crcBindTime / 10000;
|
||||
ulong expiry = Constants.TimerMax / 10000;
|
||||
|
||||
VariableBag avmaBinding = new VariableBag();
|
||||
VariableBag avmaBinding = new VariableBag(version);
|
||||
|
||||
avmaBinding.Blocks.AddRange(new CRCBlock[]
|
||||
avmaBinding.Blocks.AddRange(new[]
|
||||
{
|
||||
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[] { },
|
||||
@ -97,7 +92,7 @@ namespace LibTSforge.Activators
|
||||
store.DeleteBlock(key, storeVal);
|
||||
store.DeleteBlock(key, timerVal);
|
||||
|
||||
store.AddBlocks(new PSBlock[]
|
||||
store.AddBlocks(new[]
|
||||
{
|
||||
new PSBlock
|
||||
{
|
||||
|
@ -1,8 +1,9 @@
|
||||
namespace LibTSforge.Activators
|
||||
{
|
||||
using System;
|
||||
using LibTSforge.PhysicalStore;
|
||||
using LibTSforge.SPP;
|
||||
using System.IO;
|
||||
using PhysicalStore;
|
||||
using SPP;
|
||||
|
||||
public class KMS4k
|
||||
{
|
||||
@ -29,11 +30,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 +43,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 +59,127 @@ 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
|
||||
{
|
||||
Time = time2,
|
||||
Expiry = Constants.TimerMax
|
||||
};
|
||||
|
||||
string vistaTimerName = string.Format("msft:sl/timer/VLExpiration/VOLUME/{0}/{1}", appId, actId);
|
||||
|
||||
store.DeleteBlock(key, vistaTimerName);
|
||||
store.DeleteBlock(key, actId.ToString());
|
||||
|
||||
BinaryWriter writer = new BinaryWriter(new MemoryStream());
|
||||
writer.Write(Constants.KMSv4Response.Length);
|
||||
writer.Write(Constants.KMSv4Response);
|
||||
writer.Write(Constants.UniversalHWIDBlock);
|
||||
byte[] kmsData = writer.GetBytes();
|
||||
|
||||
store.AddBlocks(new[]
|
||||
{
|
||||
new PSBlock
|
||||
{
|
||||
Type = BlockType.TIMER,
|
||||
Flags = 0,
|
||||
KeyAsStr = key,
|
||||
ValueAsStr = vistaTimerName,
|
||||
Data = vistaTimer.CastToArray()
|
||||
},
|
||||
new PSBlock
|
||||
{
|
||||
Type = BlockType.NAMED,
|
||||
Flags = 0,
|
||||
KeyAsStr = key,
|
||||
ValueAsStr = actId.ToString(),
|
||||
Data = kmsData
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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[]
|
||||
{
|
||||
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[]
|
||||
{
|
||||
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[]
|
||||
{
|
||||
new PSBlock
|
||||
{
|
||||
Type = BlockType.NAMED,
|
||||
@ -154,10 +196,11 @@ namespace LibTSforge.Activators
|
||||
ValueAsStr = timerVal,
|
||||
Data = kmsTimer.CastToArray()
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
SLApi.RefreshLicenseStatus();
|
||||
SPPUtils.RestartSPP(version);
|
||||
SLApi.FireStateChangedEvent(appId);
|
||||
Logger.WriteLine("Activated using KMS4k successfully.");
|
||||
}
|
||||
|
@ -2,13 +2,14 @@ namespace LibTSforge.Activators
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using LibTSforge.Crypto;
|
||||
using LibTSforge.PhysicalStore;
|
||||
using LibTSforge.SPP;
|
||||
using System.Linq;
|
||||
using Crypto;
|
||||
using PhysicalStore;
|
||||
using SPP;
|
||||
|
||||
public static class ZeroCID
|
||||
{
|
||||
public static void Deposit(Guid actId, string instId)
|
||||
private static void Deposit(Guid actId, string instId)
|
||||
{
|
||||
uint status = SLApi.DepositConfirmationID(actId, instId, Constants.ZeroCID);
|
||||
Logger.WriteLine(string.Format("Depositing fake CID status {0:X}", status));
|
||||
@ -46,16 +47,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 +66,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 +87,39 @@ 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;
|
||||
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.");
|
||||
}
|
||||
|
||||
shortauth |= (ulong)group << 41;
|
||||
pkeyData = BitConverter.GetBytes(shortauth);
|
||||
}
|
||||
else if (version == PSVersion.Win7)
|
||||
{
|
||||
pkeyData = pkb.GetBlock("SppPkeyShortAuthenticator").Value;
|
||||
}
|
||||
@ -99,26 +132,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();
|
||||
|
||||
store.AddBlocks(new PSBlock[] {
|
||||
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[] {
|
||||
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 +167,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.");
|
||||
}
|
||||
|
@ -1,22 +1,15 @@
|
||||
namespace LibTSforge
|
||||
{
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.ServiceProcess;
|
||||
using System.Text;
|
||||
using LibTSforge.Crypto;
|
||||
using LibTSforge.PhysicalStore;
|
||||
using LibTSforge.SPP;
|
||||
using LibTSforge.TokenStore;
|
||||
|
||||
public enum PSVersion
|
||||
{
|
||||
Vista,
|
||||
Win7,
|
||||
Win8Early,
|
||||
Win8,
|
||||
WinBlue,
|
||||
WinModern
|
||||
@ -87,8 +80,8 @@ namespace LibTSforge
|
||||
0x92, 0xA6, 0x56, 0x96
|
||||
};
|
||||
|
||||
// 2^31 - 1 minutes
|
||||
public static ulong TimerMax = (ulong)TimeSpan.FromMinutes(2147483647).Ticks;
|
||||
// 2^31 - 8 minutes
|
||||
public static readonly ulong TimerMax = (ulong)TimeSpan.FromMinutes(2147483640).Ticks;
|
||||
|
||||
public static readonly string ZeroCID = new string('0', 48);
|
||||
}
|
||||
@ -156,20 +149,6 @@ namespace LibTSforge
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static T CastToStruct<T>(this byte[] data) where T : struct
|
||||
{
|
||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||
try
|
||||
{
|
||||
IntPtr ptr = handle.AddrOfPinnedObject();
|
||||
return (T)Marshal.PtrToStructure(ptr, typeof(T));
|
||||
}
|
||||
finally
|
||||
{
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class FileStreamExt
|
||||
@ -190,6 +169,12 @@ namespace LibTSforge
|
||||
|
||||
public static class Utils
|
||||
{
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern uint GetSystemDefaultLCID();
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool Wow64EnableWow64FsRedirection(bool Wow64FsEnableRedirection);
|
||||
|
||||
public static string DecodeString(byte[] data)
|
||||
{
|
||||
return Encoding.Unicode.GetString(data).Trim('\0');
|
||||
@ -200,9 +185,6 @@ namespace LibTSforge
|
||||
return Encoding.Unicode.GetBytes(str + '\0');
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern uint GetSystemDefaultLCID();
|
||||
|
||||
public static uint CRC32(byte[] data)
|
||||
{
|
||||
const uint polynomial = 0x04C11DB7;
|
||||
@ -226,157 +208,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,65 +223,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.");
|
||||
}
|
||||
|
||||
public static bool DetectCurrentKey()
|
||||
{
|
||||
SLApi.RefreshLicenseStatus();
|
||||
|
||||
using (RegistryKey wpaKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\WPA"))
|
||||
{
|
||||
foreach (string subKey in wpaKey.GetSubKeyNames())
|
||||
{
|
||||
if (subKey.StartsWith("8DEC0AF1") && subKey.EndsWith("-1"))
|
||||
{
|
||||
return subKey.Contains("P");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.");
|
||||
throw new NotSupportedException("Unable to auto-detect version info");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
|
@ -8,7 +8,7 @@ namespace LibTSforge.Crypto
|
||||
|
||||
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));
|
||||
@ -16,29 +16,40 @@ namespace LibTSforge.Crypto
|
||||
byte[] aesKeySig = br.ReadBytes(0x80);
|
||||
byte[] encAesKey = br.ReadBytes(0x80);
|
||||
|
||||
if (CryptoUtils.RSAVerifySignature(rsaKey, encAesKey, aesKeySig))
|
||||
if (!CryptoUtils.RSAVerifySignature(rsaKey, encAesKey, aesKeySig))
|
||||
{
|
||||
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[] psData = decData.Skip(0x28).ToArray();
|
||||
|
||||
if (!CryptoUtils.HMACVerify(hmacKey, psData, hmacSig))
|
||||
{
|
||||
Logger.WriteLine("Warning: Failed to verify HMAC. Physical store is either corrupt or in Vista format.");
|
||||
}
|
||||
|
||||
return psData;
|
||||
throw new Exception("Failed to decrypt physical store.");
|
||||
}
|
||||
|
||||
throw new Exception("Failed to decrypt physical store.");
|
||||
byte[] aesKey = CryptoUtils.RSADecrypt(rsaKey, encAesKey);
|
||||
byte[] decData = CryptoUtils.AESDecrypt(br.ReadBytes((int)br.BaseStream.Length - 0x110), aesKey);
|
||||
byte[] hmacKey = decData.Take(0x10).ToArray(); // SHA-1 salt on Vista
|
||||
byte[] hmacSig = decData.Skip(0x10).Take(0x14).ToArray(); // SHA-1 hash on Vista
|
||||
byte[] psData = decData.Skip(0x28).ToArray();
|
||||
|
||||
if (version != PSVersion.Vista)
|
||||
{
|
||||
if (!CryptoUtils.HMACVerify(hmacKey, psData, hmacSig))
|
||||
{
|
||||
throw new InvalidDataException("Failed to verify HMAC. Physical store is corrupt.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CryptoUtils.SaltSHAVerify(hmacKey, psData, hmacSig))
|
||||
{
|
||||
throw new InvalidDataException("Failed to verify checksum. Physical store is corrupt.");
|
||||
}
|
||||
}
|
||||
|
||||
return psData;
|
||||
}
|
||||
|
||||
public static byte[] EncryptPhysicalStore(byte[] data, bool production, PSVersion version)
|
||||
{
|
||||
Dictionary<PSVersion, int> versionTable = new Dictionary<PSVersion, int>
|
||||
{
|
||||
{PSVersion.Vista, 2},
|
||||
{PSVersion.Win7, 5},
|
||||
{PSVersion.Win8, 1},
|
||||
{PSVersion.WinBlue, 2},
|
||||
@ -52,9 +63,9 @@ 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[] { };
|
||||
byte[] decData = { };
|
||||
decData = decData.Concat(hmacKey).Concat(hmacSig).Concat(BitConverter.GetBytes(0)).Concat(data).ToArray();
|
||||
byte[] encData = CryptoUtils.AESEncrypt(decData, aesKey);
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
<LangVersion>3</LangVersion>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
|
@ -3,9 +3,9 @@ namespace LibTSforge.Modifiers
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Win32;
|
||||
using LibTSforge.PhysicalStore;
|
||||
using LibTSforge.SPP;
|
||||
using LibTSforge.TokenStore;
|
||||
using PhysicalStore;
|
||||
using SPP;
|
||||
using TokenStore;
|
||||
|
||||
public static class GenPKeyInstall
|
||||
{
|
||||
@ -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();
|
||||
@ -57,7 +58,7 @@ namespace LibTSforge.Modifiers
|
||||
if (pkey.Algorithm == PKeyAlgorithm.PKEY2009)
|
||||
{
|
||||
uint status = SLApi.InstallProductKey(pkey);
|
||||
Logger.WriteLine(string.Format("Installing generated product key {0} status {1:X}", pkey.ToString(), status));
|
||||
Logger.WriteLine(string.Format("Installing generated product key {0} status {1:X}", pkey, status));
|
||||
|
||||
if ((int)status < 0)
|
||||
{
|
||||
@ -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[]
|
||||
{
|
||||
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...");
|
||||
|
||||
@ -168,7 +169,7 @@ namespace LibTSforge.Modifiers
|
||||
uriMap.Data[pkeyId] = pkey.GetAlgoUri();
|
||||
tks.SetEntry(uriMapName, "xml", uriMap.Serialize());
|
||||
|
||||
string skuMetaName = actId.ToString() + metSuffix;
|
||||
string skuMetaName = actId + metSuffix;
|
||||
TokenMeta skuMeta = tks.GetMetaEntry(skuMetaName);
|
||||
|
||||
foreach (string k in skuMeta.Data.Keys)
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
namespace LibTSforge.Modifiers
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using LibTSforge.PhysicalStore;
|
||||
using PhysicalStore;
|
||||
using 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 +23,7 @@ namespace LibTSforge.Modifiers
|
||||
}
|
||||
}
|
||||
|
||||
SPPUtils.RestartSPP(version);
|
||||
Logger.WriteLine("Successfully reset all grace and evaluation period timers.");
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,12 @@ namespace LibTSforge.Modifiers
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using LibTSforge.PhysicalStore;
|
||||
using LibTSforge.SPP;
|
||||
using PhysicalStore;
|
||||
using SPP;
|
||||
|
||||
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)
|
||||
{
|
||||
@ -31,76 +31,113 @@ namespace LibTSforge.Modifiers
|
||||
string key = string.Format("SPPSVC\\{0}", appId);
|
||||
long ldapTimestamp = DateTime.Now.ToFileTime();
|
||||
|
||||
byte[] cmidGuids = { };
|
||||
byte[] reqCounts = { };
|
||||
byte[] kmsChargeData = { };
|
||||
|
||||
BinaryWriter writer = new BinaryWriter(new MemoryStream());
|
||||
|
||||
for (int i = 0; i < currClients; i++)
|
||||
if (version == PSVersion.Vista)
|
||||
{
|
||||
writer.Write(ldapTimestamp - (10 * (i + 1)));
|
||||
writer.Write(Guid.NewGuid().ToByteArray());
|
||||
writer.Write(new byte[44]);
|
||||
writer.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
writer.Write(totalClients);
|
||||
writer.Write(43200);
|
||||
writer.Write(32);
|
||||
|
||||
writer.Seek(20, SeekOrigin.Begin);
|
||||
writer.Write((byte)currClients);
|
||||
|
||||
writer.Seek(32, SeekOrigin.Begin);
|
||||
writer.Write((byte)currClients);
|
||||
|
||||
writer.Seek(0, SeekOrigin.End);
|
||||
|
||||
for (int i = 0; i < currClients; i++)
|
||||
{
|
||||
writer.Write(Guid.NewGuid().ToByteArray());
|
||||
writer.Write(ldapTimestamp - (10 * (i + 1)));
|
||||
}
|
||||
|
||||
kmsChargeData = writer.GetBytes();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < currClients; i++)
|
||||
{
|
||||
writer.Write(ldapTimestamp - (10 * (i + 1)));
|
||||
writer.Write(Guid.NewGuid().ToByteArray());
|
||||
}
|
||||
|
||||
cmidGuids = writer.GetBytes();
|
||||
|
||||
writer = new BinaryWriter(new MemoryStream());
|
||||
|
||||
writer.Write(new byte[40]);
|
||||
|
||||
writer.Seek(4, SeekOrigin.Begin);
|
||||
writer.Write((byte)currClients);
|
||||
|
||||
writer.Seek(24, SeekOrigin.Begin);
|
||||
writer.Write((byte)currClients);
|
||||
|
||||
reqCounts = writer.GetBytes();
|
||||
}
|
||||
|
||||
byte[] cmidGuids = writer.GetBytes();
|
||||
|
||||
writer = new BinaryWriter(new MemoryStream());
|
||||
|
||||
writer.Write(new byte[40]);
|
||||
|
||||
writer.Seek(4, SeekOrigin.Begin);
|
||||
writer.Write((byte)currClients);
|
||||
|
||||
writer.Seek(24, SeekOrigin.Begin);
|
||||
writer.Write((byte)currClients);
|
||||
byte[] reqCounts = writer.GetBytes();
|
||||
|
||||
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[]
|
||||
if (version != PSVersion.Vista)
|
||||
{
|
||||
new CRCBlock
|
||||
VariableBag kmsCountData = new VariableBag(version);
|
||||
kmsCountData.Blocks.AddRange(new[]
|
||||
{
|
||||
DataType = CRCBlockType.BINARY,
|
||||
KeyAsStr = "SppBindingLicenseData",
|
||||
Value = hwidBlock
|
||||
},
|
||||
new CRCBlock
|
||||
{
|
||||
DataType = CRCBlockType.UINT,
|
||||
Key = new byte[] { },
|
||||
ValueAsInt = (uint)totalClients
|
||||
},
|
||||
new CRCBlock
|
||||
{
|
||||
DataType = CRCBlockType.UINT,
|
||||
Key = new byte[] { },
|
||||
ValueAsInt = 1051200000
|
||||
},
|
||||
new CRCBlock
|
||||
{
|
||||
DataType = CRCBlockType.UINT,
|
||||
Key = new byte[] { },
|
||||
ValueAsInt = (uint)currClients
|
||||
},
|
||||
new CRCBlock
|
||||
{
|
||||
DataType = CRCBlockType.BINARY,
|
||||
Key = new byte[] { },
|
||||
Value = cmidGuids
|
||||
},
|
||||
new CRCBlock
|
||||
{
|
||||
DataType = CRCBlockType.BINARY,
|
||||
Key = new byte[] { },
|
||||
Value = reqCounts
|
||||
}
|
||||
});
|
||||
new CRCBlockModern
|
||||
{
|
||||
DataType = CRCBlockType.BINARY,
|
||||
KeyAsStr = "SppBindingLicenseData",
|
||||
Value = hwidBlock
|
||||
},
|
||||
new CRCBlockModern
|
||||
{
|
||||
DataType = CRCBlockType.UINT,
|
||||
Key = new byte[] { },
|
||||
ValueAsInt = (uint)totalClients
|
||||
},
|
||||
new CRCBlockModern
|
||||
{
|
||||
DataType = CRCBlockType.UINT,
|
||||
Key = new byte[] { },
|
||||
ValueAsInt = 1051200000
|
||||
},
|
||||
new CRCBlockModern
|
||||
{
|
||||
DataType = CRCBlockType.UINT,
|
||||
Key = new byte[] { },
|
||||
ValueAsInt = (uint)currClients
|
||||
},
|
||||
new CRCBlockModern
|
||||
{
|
||||
DataType = CRCBlockType.BINARY,
|
||||
Key = new byte[] { },
|
||||
Value = cmidGuids
|
||||
},
|
||||
new CRCBlockModern
|
||||
{
|
||||
DataType = CRCBlockType.BINARY,
|
||||
Key = new byte[] { },
|
||||
Value = reqCounts
|
||||
}
|
||||
});
|
||||
|
||||
byte[] kmsChargeData = kmsCountData.Serialize();
|
||||
string countVal = string.Format("msft:spp/kms/host/2.0/store/counters/{0}", appId);
|
||||
kmsChargeData = kmsCountData.Serialize();
|
||||
}
|
||||
|
||||
string countVal = version == PSVersion.Vista ? "C8F6FFF1-79CE-404C-B150-F97991273DF1" : string.Format("msft:spp/kms/host/2.0/store/counters/{0}", appId);
|
||||
|
||||
store.DeleteBlock(key, countVal);
|
||||
store.AddBlock(new PSBlock
|
||||
@ -114,6 +151,8 @@ namespace LibTSforge.Modifiers
|
||||
|
||||
Logger.WriteLine(string.Format("Set charge count to {0} successfully.", currClients));
|
||||
}
|
||||
|
||||
SPPUtils.RestartSPP(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,19 @@ namespace LibTSforge.Modifiers
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using LibTSforge.PhysicalStore;
|
||||
using LibTSforge;
|
||||
using PhysicalStore;
|
||||
using SPP;
|
||||
using System;
|
||||
|
||||
public static class KeyChangeLockDelete
|
||||
{
|
||||
public static void Delete(PSVersion version, bool production)
|
||||
{
|
||||
Utils.KillSPP();
|
||||
if (version == PSVersion.Vista) throw new NotSupportedException("This feature is not supported on Windows Vista/Server 2008.");
|
||||
|
||||
SPPUtils.KillSPP(version);
|
||||
Logger.WriteLine("Writing TrustedStore data...");
|
||||
using (IPhysicalStore store = Utils.GetStore(version, production))
|
||||
using (IPhysicalStore store = SPPUtils.GetStore(version, production))
|
||||
{
|
||||
List<string> values = new List<string>
|
||||
{
|
||||
|
@ -1,23 +1,27 @@
|
||||
namespace LibTSforge.Modifiers
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using LibTSforge.PhysicalStore;
|
||||
using PhysicalStore;
|
||||
using 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;
|
||||
|
||||
if (version == PSVersion.Win7)
|
||||
if (version == PSVersion.Vista)
|
||||
{
|
||||
blocks = store.FindBlocks("740D70D8-6448-4b2f-9063-4A7A463600C5").ToList();
|
||||
}
|
||||
else if (version == PSVersion.Win7)
|
||||
{
|
||||
blocks = store.FindBlocks(0xA0000).ToList();
|
||||
}
|
||||
@ -28,7 +32,11 @@ namespace LibTSforge.Modifiers
|
||||
|
||||
foreach (PSBlock block in blocks)
|
||||
{
|
||||
if (version == PSVersion.Win7)
|
||||
if (version == PSVersion.Vista)
|
||||
{
|
||||
store.DeleteBlock(block.KeyAsStr, block.ValueAsStr);
|
||||
}
|
||||
else if (version == PSVersion.Win7)
|
||||
{
|
||||
store.SetBlock(block.KeyAsStr, block.ValueAsInt, new byte[8]);
|
||||
}
|
||||
|
66
LibTSforge/Modifiers/SetIIDParams.cs
Normal file
66
LibTSforge/Modifiers/SetIIDParams.cs
Normal file
@ -0,0 +1,66 @@
|
||||
namespace LibTSforge.Modifiers
|
||||
{
|
||||
using PhysicalStore;
|
||||
using SPP;
|
||||
using System.IO;
|
||||
using System;
|
||||
|
||||
public static class SetIIDParams
|
||||
{
|
||||
public static void SetParams(PSVersion version, bool production, Guid actId, PKeyAlgorithm algorithm, int group, int serial, ulong security)
|
||||
{
|
||||
if (version == PSVersion.Vista) throw new NotSupportedException("This feature is not supported on Windows Vista/Server 2008.");
|
||||
|
||||
Guid appId;
|
||||
|
||||
if (actId == Guid.Empty)
|
||||
{
|
||||
appId = SLApi.WINDOWS_APP_ID;
|
||||
actId = SLApi.GetDefaultActivationID(appId, true);
|
||||
|
||||
if (actId == Guid.Empty)
|
||||
{
|
||||
throw new Exception("No applicable activation IDs found.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
appId = SLApi.GetAppId(actId);
|
||||
}
|
||||
|
||||
Guid pkeyId = SLApi.GetInstalledPkeyID(actId);
|
||||
|
||||
SPPUtils.KillSPP(version);
|
||||
|
||||
Logger.WriteLine("Writing TrustedStore data...");
|
||||
|
||||
using (IPhysicalStore store = SPPUtils.GetStore(version, production))
|
||||
{
|
||||
string key = string.Format("SPPSVC\\{0}\\{1}", appId, actId);
|
||||
PSBlock keyBlock = store.GetBlock(key, pkeyId.ToString());
|
||||
|
||||
if (keyBlock == null)
|
||||
{
|
||||
throw new InvalidDataException("Failed to get product key data for activation ID " + actId + ".");
|
||||
}
|
||||
|
||||
VariableBag pkb = new VariableBag(keyBlock.Data, version);
|
||||
|
||||
ProductKey pkey = new ProductKey
|
||||
{
|
||||
Group = group,
|
||||
Serial = serial,
|
||||
Security = security,
|
||||
Algorithm = algorithm,
|
||||
Upgrade = false
|
||||
};
|
||||
|
||||
string blockName = version == PSVersion.Win7 ? "SppPkeyShortAuthenticator" : "SppPkeyPhoneActivationData";
|
||||
pkb.SetBlock(blockName, pkey.GetPhoneData(version));
|
||||
store.SetBlock(key, pkeyId.ToString(), pkb.Serialize());
|
||||
}
|
||||
|
||||
Logger.WriteLine("Successfully set IID parameters.");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +1,37 @@
|
||||
namespace LibTSforge.Modifiers
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
using LibTSforge.PhysicalStore;
|
||||
using PhysicalStore;
|
||||
using 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)
|
||||
if (version == PSVersion.Vista)
|
||||
{
|
||||
string recreatedFlag = "__##USERSEP-RESERVED##__$$RECREATED-FLAG$$";
|
||||
string recoveredFlag = "__##USERSEP-RESERVED##__$$RECOVERED-FLAG$$";
|
||||
|
||||
DeleteFlag(store, recreatedFlag);
|
||||
DeleteFlag(store, recoveredFlag);
|
||||
DeleteFlag(store, "6BE8425B-E3CF-4e86-A6AF-5863E3DCB606");
|
||||
}
|
||||
else if (version == PSVersion.Win7)
|
||||
{
|
||||
SetFlag(store, 0xA0001);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFlag(store, 0xA0001);
|
||||
DeleteFlag(store, "__##USERSEP-RESERVED##__$$RECREATED-FLAG$$");
|
||||
DeleteFlag(store, "__##USERSEP-RESERVED##__$$RECOVERED-FLAG$$");
|
||||
}
|
||||
|
||||
Logger.WriteLine("Successfully cleared the tamper state.");
|
||||
}
|
||||
|
||||
SPPUtils.RestartSPP(version);
|
||||
}
|
||||
|
||||
private static void DeleteFlag(IPhysicalStore store, string flag)
|
||||
|
@ -1,13 +1,15 @@
|
||||
namespace LibTSforge.Modifiers
|
||||
{
|
||||
using System;
|
||||
using LibTSforge.PhysicalStore;
|
||||
using LibTSforge.SPP;
|
||||
using PhysicalStore;
|
||||
using SPP;
|
||||
|
||||
public static class UniqueIdDelete
|
||||
{
|
||||
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)
|
||||
@ -25,14 +27,13 @@ namespace LibTSforge.Modifiers
|
||||
appId = SLApi.GetAppId(actId);
|
||||
}
|
||||
|
||||
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 +43,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;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ namespace LibTSforge.PhysicalStore
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using LibTSforge.Crypto;
|
||||
using Crypto;
|
||||
|
||||
public class ModernBlock
|
||||
{
|
||||
@ -93,7 +93,7 @@ namespace LibTSforge.PhysicalStore
|
||||
|
||||
public sealed class PhysicalStoreModern : IPhysicalStore
|
||||
{
|
||||
private byte[] PreHeaderBytes = new byte[] { };
|
||||
private byte[] PreHeaderBytes = { };
|
||||
private readonly Dictionary<string, List<ModernBlock>> Data = new Dictionary<string, List<ModernBlock>>();
|
||||
private readonly FileStream TSFile;
|
||||
private readonly PSVersion Version;
|
||||
@ -281,46 +281,50 @@ namespace LibTSforge.PhysicalStore
|
||||
|
||||
public void DeleteBlock(string key, string value)
|
||||
{
|
||||
if (Data.ContainsKey(key))
|
||||
if (!Data.ContainsKey(key))
|
||||
{
|
||||
List<ModernBlock> blocks = Data[key];
|
||||
|
||||
foreach (ModernBlock block in blocks)
|
||||
{
|
||||
if (block.ValueAsStr == value)
|
||||
{
|
||||
blocks.Remove(block);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Data[key] = blocks;
|
||||
return;
|
||||
}
|
||||
|
||||
List<ModernBlock> blocks = Data[key];
|
||||
|
||||
foreach (ModernBlock block in blocks)
|
||||
{
|
||||
if (block.ValueAsStr == value)
|
||||
{
|
||||
blocks.Remove(block);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Data[key] = blocks;
|
||||
}
|
||||
|
||||
public void DeleteBlock(string key, uint value)
|
||||
{
|
||||
if (Data.ContainsKey(key))
|
||||
if (!Data.ContainsKey(key))
|
||||
{
|
||||
List<ModernBlock> blocks = Data[key];
|
||||
|
||||
foreach (ModernBlock block in blocks)
|
||||
{
|
||||
if (block.ValueAsInt == value)
|
||||
{
|
||||
blocks.Remove(block);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Data[key] = blocks;
|
||||
return;
|
||||
}
|
||||
|
||||
List<ModernBlock> blocks = Data[key];
|
||||
|
||||
foreach (ModernBlock block in blocks)
|
||||
{
|
||||
if (block.ValueAsInt == value)
|
||||
{
|
||||
blocks.Remove(block);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Data[key] = blocks;
|
||||
}
|
||||
|
||||
public PhysicalStoreModern(string tsPath, bool production, PSVersion version)
|
||||
{
|
||||
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 +344,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 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 = { };
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ namespace LibTSforge.PhysicalStore
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using LibTSforge.Crypto;
|
||||
using Crypto;
|
||||
|
||||
public class Win7Block
|
||||
{
|
||||
@ -105,7 +105,7 @@ namespace LibTSforge.PhysicalStore
|
||||
|
||||
public sealed class PhysicalStoreWin7 : IPhysicalStore
|
||||
{
|
||||
private byte[] PreHeaderBytes = new byte[] { };
|
||||
private byte[] PreHeaderBytes = { };
|
||||
private readonly List<Win7Block> Blocks = new List<Win7Block>();
|
||||
private readonly FileStream TSPrimary;
|
||||
private readonly FileStream TSSecondary;
|
||||
@ -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;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ namespace LibTSforge.PhysicalStore
|
||||
BINARY = 1 << 2
|
||||
}
|
||||
|
||||
public class CRCBlock
|
||||
public abstract class CRCBlock
|
||||
{
|
||||
public CRCBlockType DataType;
|
||||
public byte[] Key;
|
||||
@ -50,7 +50,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();
|
||||
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 +115,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 +128,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,8 +154,9 @@ namespace LibTSforge.PhysicalStore
|
||||
public class VariableBag
|
||||
{
|
||||
public List<CRCBlock> Blocks = new List<CRCBlock>();
|
||||
private readonly PSVersion Version;
|
||||
|
||||
public void Deserialize(byte[] data)
|
||||
private void Deserialize(byte[] data)
|
||||
{
|
||||
int len = data.Length;
|
||||
|
||||
@ -118,7 +164,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 +186,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 +238,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,8 +74,8 @@ namespace LibTSforge.SPP
|
||||
|
||||
public class PKeyConfig
|
||||
{
|
||||
public Dictionary<Guid, ProductConfig> Products = new Dictionary<Guid, ProductConfig>();
|
||||
private List<Guid> loadedPkeyConfigs = new List<Guid>();
|
||||
public readonly Dictionary<Guid, ProductConfig> Products = new Dictionary<Guid, ProductConfig>();
|
||||
private readonly List<Guid> loadedPkeyConfigs = new List<Guid>();
|
||||
|
||||
public void LoadConfig(Guid actId)
|
||||
{
|
||||
@ -136,12 +136,14 @@ namespace LibTSforge.SPP
|
||||
ranges[refActIdStr] = new List<KeyRange>();
|
||||
}
|
||||
|
||||
KeyRange keyRange = new KeyRange();
|
||||
keyRange.Start = int.Parse(rangeNode.SelectSingleNode("./p:Start", nsmgr).InnerText);
|
||||
keyRange.End = int.Parse(rangeNode.SelectSingleNode("./p:End", nsmgr).InnerText);
|
||||
keyRange.EulaType = rangeNode.SelectSingleNode("./p:EulaType", nsmgr).InnerText;
|
||||
keyRange.PartNumber = rangeNode.SelectSingleNode("./p:PartNumber", nsmgr).InnerText;
|
||||
keyRange.Valid = rangeNode.SelectSingleNode("./p:IsValid", nsmgr).InnerText.ToLower() == "true";
|
||||
KeyRange keyRange = new KeyRange
|
||||
{
|
||||
Start = int.Parse(rangeNode.SelectSingleNode("./p:Start", nsmgr).InnerText),
|
||||
End = int.Parse(rangeNode.SelectSingleNode("./p:End", nsmgr).InnerText),
|
||||
EulaType = rangeNode.SelectSingleNode("./p:EulaType", nsmgr).InnerText,
|
||||
PartNumber = rangeNode.SelectSingleNode("./p:PartNumber", nsmgr).InnerText,
|
||||
Valid = rangeNode.SelectSingleNode("./p:IsValid", nsmgr).InnerText.ToLower() == "true"
|
||||
};
|
||||
|
||||
ranges[refActIdStr].Add(keyRange);
|
||||
}
|
||||
@ -155,15 +157,17 @@ namespace LibTSforge.SPP
|
||||
|
||||
if (keyRanges.Count > 0 && !Products.ContainsKey(refActId))
|
||||
{
|
||||
ProductConfig productConfig = new ProductConfig();
|
||||
productConfig.GroupId = group;
|
||||
productConfig.Edition = configNode.SelectSingleNode("./p:EditionId", nsmgr).InnerText;
|
||||
productConfig.Description = configNode.SelectSingleNode("./p:ProductDescription", nsmgr).InnerText;
|
||||
productConfig.Channel = configNode.SelectSingleNode("./p:ProductKeyType", nsmgr).InnerText;
|
||||
productConfig.Randomized = configNode.SelectSingleNode("./p:ProductKeyType", nsmgr).InnerText.ToLower() == "true";
|
||||
productConfig.Algorithm = algorithms[group];
|
||||
productConfig.Ranges = keyRanges;
|
||||
productConfig.ActivationId = refActId;
|
||||
ProductConfig productConfig = new ProductConfig
|
||||
{
|
||||
GroupId = group,
|
||||
Edition = configNode.SelectSingleNode("./p:EditionId", nsmgr).InnerText,
|
||||
Description = configNode.SelectSingleNode("./p:ProductDescription", nsmgr).InnerText,
|
||||
Channel = configNode.SelectSingleNode("./p:ProductKeyType", nsmgr).InnerText,
|
||||
Randomized = configNode.SelectSingleNode("./p:ProductKeyType", nsmgr).InnerText.ToLower() == "true",
|
||||
Algorithm = algorithms[group],
|
||||
Ranges = keyRanges,
|
||||
ActivationId = refActId
|
||||
};
|
||||
|
||||
Products[refActId] = productConfig;
|
||||
}
|
||||
@ -206,10 +210,5 @@ namespace LibTSforge.SPP
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PKeyConfig()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ namespace LibTSforge.SPP
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using LibTSforge.Crypto;
|
||||
using LibTSforge.PhysicalStore;
|
||||
using Crypto;
|
||||
using PhysicalStore;
|
||||
|
||||
public class ProductKey
|
||||
{
|
||||
@ -18,11 +18,11 @@ namespace LibTSforge.SPP
|
||||
public ulong Security;
|
||||
public bool Upgrade;
|
||||
public PKeyAlgorithm Algorithm;
|
||||
public string EulaType;
|
||||
public string PartNumber;
|
||||
public string Edition;
|
||||
public string Channel;
|
||||
public Guid ActivationId;
|
||||
public readonly string EulaType;
|
||||
public readonly string PartNumber;
|
||||
public readonly string Edition;
|
||||
public readonly string Channel;
|
||||
public readonly Guid ActivationId;
|
||||
|
||||
private string mpc;
|
||||
private string pid2;
|
||||
@ -32,6 +32,11 @@ namespace LibTSforge.SPP
|
||||
get { return BitConverter.GetBytes(klow).Concat(BitConverter.GetBytes(khigh)).ToArray(); }
|
||||
}
|
||||
|
||||
public ProductKey()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ProductKey(int serial, ulong security, bool upgrade, PKeyAlgorithm algorithm, ProductConfig config, KeyRange range)
|
||||
{
|
||||
Group = config.GroupId;
|
||||
@ -60,22 +65,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[]
|
||||
{
|
||||
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",
|
||||
@ -86,16 +91,6 @@ namespace LibTSforge.SPP
|
||||
return new Guid(CryptoUtils.SHA256Hash(pkb.Serialize()).Take(16).ToArray());
|
||||
}
|
||||
|
||||
public string GetDefaultMPC()
|
||||
{
|
||||
int build = Environment.OSVersion.Version.Build;
|
||||
string defaultMPC = build >= 10240 ? "03612" :
|
||||
build >= 9600 ? "06401" :
|
||||
build >= 9200 ? "05426" :
|
||||
"55041";
|
||||
return defaultMPC;
|
||||
}
|
||||
|
||||
public string GetMPC()
|
||||
{
|
||||
if (mpc != null)
|
||||
@ -103,10 +98,15 @@ namespace LibTSforge.SPP
|
||||
return mpc;
|
||||
}
|
||||
|
||||
mpc = GetDefaultMPC();
|
||||
int build = Environment.OSVersion.Version.Build;
|
||||
|
||||
mpc = build >= 10240 ? "03612" :
|
||||
build >= 9600 ? "06401" :
|
||||
build >= 9200 ? "05426" :
|
||||
"55041";
|
||||
|
||||
// setup.cfg doesn't exist in Windows 8+
|
||||
string setupcfg = string.Format("{0}\\oobe\\{1}", Environment.SystemDirectory, "setup.cfg");
|
||||
string setupcfg = string.Format(@"{0}\oobe\{1}", Environment.SystemDirectory, "setup.cfg");
|
||||
|
||||
if (!File.Exists(setupcfg) || Edition.Contains(";"))
|
||||
{
|
||||
@ -244,17 +244,17 @@ namespace LibTSforge.SPP
|
||||
{
|
||||
if (version == PSVersion.Win7)
|
||||
{
|
||||
Random rnd = new Random(Group * 1000000000 + Serial);
|
||||
byte[] data = new byte[8];
|
||||
rnd.NextBytes(data);
|
||||
return data;
|
||||
ulong shortauth = ((ulong)Group << 41) | (Security << 31) | ((ulong)Serial << 1) | (Upgrade ? (ulong)1 : 0);
|
||||
return BitConverter.GetBytes(shortauth);
|
||||
}
|
||||
|
||||
int serialHigh = Serial / 1000000;
|
||||
int serialLow = Serial % 1000000;
|
||||
|
||||
BinaryWriter writer = new BinaryWriter(new MemoryStream());
|
||||
writer.Write(new Guid("B8731595-A2F6-430B-A799-FBFFB81A8D73").ToByteArray());
|
||||
string algoId = Algorithm == PKeyAlgorithm.PKEY2005 ? "B8731595-A2F6-430B-A799-FBFFB81A8D73" : "660672EF-7809-4CFD-8D54-41B7FB738988";
|
||||
|
||||
writer.Write(new Guid(algoId).ToByteArray());
|
||||
writer.Write(Group);
|
||||
writer.Write(serialHigh);
|
||||
writer.Write(serialLow);
|
||||
|
@ -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)]
|
||||
@ -86,9 +86,6 @@ namespace LibTSforge.SPP
|
||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern uint SLGetProductSkuInformation(IntPtr hSLC, ref Guid pProductSkuId, string pwszValueName, out SLDATATYPE peDataType, out uint pcbValue, out IntPtr ppbValue);
|
||||
|
||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern uint SLGetProductSkuInformation(IntPtr hSLC, ref Guid pProductSkuId, string pwszValueName, IntPtr peDataType, out uint pcbValue, out IntPtr ppbValue);
|
||||
|
||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern uint SLGetLicense(IntPtr hSLC, ref Guid pLicenseFileId, out uint pcbLicenseFile, out IntPtr ppbLicenseFile);
|
||||
|
||||
@ -98,7 +95,7 @@ namespace LibTSforge.SPP
|
||||
[DllImport("slc.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern uint SLFireEvent(IntPtr hSLC, string pwszEventId, ref Guid pApplicationId);
|
||||
|
||||
public class SLContext : IDisposable
|
||||
private class SLContext : IDisposable
|
||||
{
|
||||
public readonly IntPtr Handle;
|
||||
|
||||
@ -161,11 +158,10 @@ namespace LibTSforge.SPP
|
||||
{
|
||||
using (SLContext sl = new SLContext())
|
||||
{
|
||||
uint status;
|
||||
uint count;
|
||||
IntPtr pProductKeyIds;
|
||||
|
||||
status = SLGetInstalledProductKeyIds(sl.Handle, ref actId, out count, out pProductKeyIds);
|
||||
uint status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_PRODUCT_SKU, ref actId, SLIDTYPE.SL_ID_PKEY, out count, out pProductKeyIds);
|
||||
|
||||
if (status != 0 || count == 0)
|
||||
{
|
||||
@ -189,7 +185,7 @@ namespace LibTSforge.SPP
|
||||
SLConsumeWindowsRight(0);
|
||||
}
|
||||
|
||||
public static bool RefreshTrustedTime(Guid actId)
|
||||
public static void RefreshTrustedTime(Guid actId)
|
||||
{
|
||||
using (SLContext sl = new SLContext())
|
||||
{
|
||||
@ -197,8 +193,7 @@ namespace LibTSforge.SPP
|
||||
uint count;
|
||||
IntPtr ppbValue;
|
||||
|
||||
uint status = SLGetProductSkuInformation(sl.Handle, ref actId, "TrustedTime", out type, out count, out ppbValue);
|
||||
return (int)status >= 0 && status != 0xC004F012;
|
||||
SLGetProductSkuInformation(sl.Handle, ref actId, "TrustedTime", out type, out count, out ppbValue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,11 +209,10 @@ namespace LibTSforge.SPP
|
||||
{
|
||||
using (SLContext sl = new SLContext())
|
||||
{
|
||||
uint status;
|
||||
uint count;
|
||||
IntPtr pAppIds;
|
||||
|
||||
status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_PRODUCT_SKU, ref actId, SLIDTYPE.SL_ID_APPLICATION, out count, out pAppIds);
|
||||
uint status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_PRODUCT_SKU, ref actId, SLIDTYPE.SL_ID_APPLICATION, out count, out pAppIds);
|
||||
|
||||
if (status != 0 || count == 0)
|
||||
{
|
||||
@ -246,11 +240,10 @@ namespace LibTSforge.SPP
|
||||
{
|
||||
using (SLContext sl = new SLContext())
|
||||
{
|
||||
uint status;
|
||||
uint count;
|
||||
IntPtr ppReturnLics;
|
||||
|
||||
status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_LICENSE, ref licId, SLIDTYPE.SL_ID_LICENSE_FILE, out count, out ppReturnLics);
|
||||
uint status = SLGetSLIDList(sl.Handle, SLIDTYPE.SL_ID_LICENSE, ref licId, SLIDTYPE.SL_ID_LICENSE_FILE, out count, out ppReturnLics);
|
||||
|
||||
if (status != 0 || count == 0)
|
||||
{
|
||||
@ -312,7 +305,7 @@ namespace LibTSforge.SPP
|
||||
IntPtr ppbValue;
|
||||
|
||||
uint status = SLGetProductSkuInformation(sl.Handle, ref actId, "msft:sl/EUL/PHONE/PUBLIC", out type, out count, out ppbValue);
|
||||
return status >= 0 && status != 0xC004F012;
|
||||
return status != 0xC004F012;
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,11 +388,11 @@ namespace LibTSforge.SPP
|
||||
}
|
||||
}
|
||||
|
||||
public static uint UninstallProductKey(Guid pkeyId)
|
||||
public static void UninstallProductKey(Guid pkeyId)
|
||||
{
|
||||
using (SLContext sl = new SLContext())
|
||||
{
|
||||
return SLUninstallProofOfPurchase(sl.Handle, ref pkeyId);
|
||||
SLUninstallProofOfPurchase(sl.Handle, ref pkeyId);
|
||||
}
|
||||
}
|
||||
|
||||
|
334
LibTSforge/SPP/SPPUtils.cs
Normal file
334
LibTSforge/SPP/SPPUtils.cs
Normal file
@ -0,0 +1,334 @@
|
||||
namespace LibTSforge.SPP
|
||||
{
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.ServiceProcess;
|
||||
using Crypto;
|
||||
using PhysicalStore;
|
||||
using TokenStore;
|
||||
|
||||
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 < 1080; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sc.Status != ServiceControllerStatus.StopPending)
|
||||
sc.Stop();
|
||||
|
||||
sc.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromMilliseconds(500));
|
||||
}
|
||||
catch (System.ServiceProcess.TimeoutException)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
Logger.WriteLine("Warning: Stopping sppsvc failed, retrying. Details: " + ex.Message);
|
||||
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 ex)
|
||||
{
|
||||
Logger.WriteLine("Warning: Starting slsvc failed, retrying. Details: " + ex.Message);
|
||||
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 bool DetectCurrentKey()
|
||||
{
|
||||
SLApi.RefreshLicenseStatus();
|
||||
|
||||
using (RegistryKey wpaKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\WPA"))
|
||||
{
|
||||
foreach (string subKey in wpaKey.GetSubKeyNames())
|
||||
{
|
||||
if (subKey.StartsWith("8DEC0AF1"))
|
||||
{
|
||||
return subKey.Contains("P");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new FileNotFoundException("Failed to autodetect key type, specify physical store key with /prod or /test arguments.");
|
||||
}
|
||||
|
||||
public static string GetPSPath(PSVersion version)
|
||||
{
|
||||
switch (version)
|
||||
{
|
||||
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:
|
||||
string psDir = Environment.ExpandEnvironmentVariables(
|
||||
(string)Registry.GetValue(
|
||||
@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform",
|
||||
"TokenStore",
|
||||
""
|
||||
)
|
||||
);
|
||||
string psPath = Path.Combine(psDir, "data.dat");
|
||||
|
||||
if (string.IsNullOrEmpty(psDir) || !File.Exists(psPath))
|
||||
{
|
||||
string[] psDirs =
|
||||
{
|
||||
@"spp\store",
|
||||
@"spp\store\2.0",
|
||||
@"spp\store_test",
|
||||
@"spp\store_test\2.0"
|
||||
};
|
||||
|
||||
foreach (string dir in psDirs)
|
||||
{
|
||||
psPath = Path.Combine(
|
||||
Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.System),
|
||||
dir
|
||||
),
|
||||
"data.dat"
|
||||
);
|
||||
|
||||
if (File.Exists(psPath)) return psPath;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return psPath;
|
||||
}
|
||||
|
||||
throw new FileNotFoundException("Failed to locate physical store.");
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
string tokDir = Environment.ExpandEnvironmentVariables(
|
||||
(string)Registry.GetValue(
|
||||
@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform",
|
||||
"TokenStore",
|
||||
""
|
||||
)
|
||||
);
|
||||
string tokPath = Path.Combine(tokDir, "tokens.dat");
|
||||
|
||||
if (string.IsNullOrEmpty(tokDir) || !File.Exists(tokPath))
|
||||
{
|
||||
string[] tokDirs =
|
||||
{
|
||||
@"spp\store",
|
||||
@"spp\store\2.0",
|
||||
@"spp\store_test",
|
||||
@"spp\store_test\2.0"
|
||||
};
|
||||
|
||||
foreach (string dir in tokDirs)
|
||||
{
|
||||
tokPath = Path.Combine(
|
||||
Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.System),
|
||||
dir
|
||||
),
|
||||
"tokens.dat"
|
||||
);
|
||||
|
||||
if (File.Exists(tokPath)) return tokPath;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return tokPath;
|
||||
}
|
||||
|
||||
throw new FileNotFoundException("Failed to locate token store.");
|
||||
}
|
||||
}
|
||||
|
||||
public static IPhysicalStore GetStore(PSVersion version, bool production)
|
||||
{
|
||||
string psPath = GetPSPath(version);
|
||||
|
||||
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 = GetTokensPath(version);
|
||||
|
||||
return new TokenStoreModern(tokPath);
|
||||
}
|
||||
|
||||
public static void DumpStore(PSVersion version, bool production, string filePath, string encrFilePath)
|
||||
{
|
||||
bool manageSpp = false;
|
||||
|
||||
if (encrFilePath == null)
|
||||
{
|
||||
encrFilePath = GetPSPath(version);
|
||||
manageSpp = true;
|
||||
KillSPP(version);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(encrFilePath) || !File.Exists(encrFilePath))
|
||||
{
|
||||
throw new FileNotFoundException("Store does not exist at expected path '" + encrFilePath + "'.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (FileStream fs = File.Open(encrFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
byte[] encrData = fs.ReadAllBytes();
|
||||
File.WriteAllBytes(filePath, PhysStoreCrypto.DecryptPhysicalStore(encrData, production, version));
|
||||
}
|
||||
Logger.WriteLine("Store dumped successfully to '" + filePath + "'.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (manageSpp)
|
||||
{
|
||||
RestartSPP(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
RestartSPP(version);
|
||||
|
||||
Logger.WriteLine("Loaded store file successfully.");
|
||||
}
|
||||
}
|
||||
}
|
44
LibTSforge/SPP/SPSys.cs
Normal file
44
LibTSforge/SPP/SPSys.cs
Normal file
@ -0,0 +1,44 @@
|
||||
namespace LibTSforge.SPP
|
||||
{
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
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)]
|
||||
private static extern bool DeviceIoControl([In] SafeFileHandle hDevice, [In] uint dwIoControlCode, [In] IntPtr lpInBuffer, [In] int nInBufferSize, [Out] IntPtr lpOutBuffer, [In] int nOutBufferSize, out int lpBytesReturned, [In] IntPtr lpOverlapped);
|
||||
|
||||
public static bool IsSpSysRunning()
|
||||
{
|
||||
SafeFileHandle file = CreateFileSafe(@"\\.\SpDevice");
|
||||
IntPtr buffer = Marshal.AllocHGlobal(1);
|
||||
int bytesReturned;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ namespace LibTSforge.TokenStore
|
||||
public class TokenMeta
|
||||
{
|
||||
public string Name;
|
||||
public Dictionary<string, string> Data = new Dictionary<string, string>();
|
||||
public readonly Dictionary<string, string> Data = new Dictionary<string, string>();
|
||||
|
||||
public byte[] Serialize()
|
||||
{
|
||||
@ -37,7 +37,7 @@ namespace LibTSforge.TokenStore
|
||||
return writer.GetBytes();
|
||||
}
|
||||
|
||||
public void Deserialize(byte[] data)
|
||||
private void Deserialize(byte[] data)
|
||||
{
|
||||
BinaryReader reader = new BinaryReader(new MemoryStream(data));
|
||||
reader.ReadInt32();
|
||||
|
@ -4,7 +4,7 @@ namespace LibTSforge.TokenStore
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using LibTSforge.Crypto;
|
||||
using Crypto;
|
||||
|
||||
public class TokenStoreModern : ITokenStore
|
||||
{
|
||||
@ -18,29 +18,29 @@ namespace LibTSforge.TokenStore
|
||||
private static readonly byte[] CONTS_FOOTER = Enumerable.Repeat((byte)0xAA, 0x20).ToArray();
|
||||
|
||||
private List<TokenEntry> Entries = new List<TokenEntry>();
|
||||
public FileStream TokensFile;
|
||||
private readonly FileStream TokensFile;
|
||||
|
||||
public void Deserialize()
|
||||
{
|
||||
if (TokensFile.Length < BLOCK_SIZE) return;
|
||||
|
||||
TokensFile.Seek(0x24, SeekOrigin.Begin);
|
||||
uint nextBlock = 0;
|
||||
uint nextBlock;
|
||||
|
||||
BinaryReader reader = new BinaryReader(TokensFile);
|
||||
do
|
||||
{
|
||||
uint curOffset = reader.ReadUInt32();
|
||||
reader.ReadUInt32();
|
||||
nextBlock = reader.ReadUInt32();
|
||||
|
||||
for (int i = 0; i < ENTRIES_PER_BLOCK; i++)
|
||||
{
|
||||
curOffset = reader.ReadUInt32();
|
||||
uint curOffset = reader.ReadUInt32();
|
||||
bool populated = reader.ReadUInt32() == 1;
|
||||
uint contentOffset = reader.ReadUInt32();
|
||||
uint contentLength = reader.ReadUInt32();
|
||||
uint allocLength = reader.ReadUInt32();
|
||||
byte[] contentData = new byte[] { };
|
||||
byte[] contentData = { };
|
||||
|
||||
if (populated)
|
||||
{
|
||||
@ -140,11 +140,10 @@ namespace LibTSforge.TokenStore
|
||||
writer.WritePadding(BLOCK_PAD_SIZE);
|
||||
|
||||
writer.BaseStream.Seek(curBlockOffset, SeekOrigin.Begin);
|
||||
byte[] blockHash;
|
||||
byte[] blockData = new byte[BLOCK_SIZE - 0x20];
|
||||
|
||||
tokens.Read(blockData, 0, BLOCK_SIZE - 0x20);
|
||||
blockHash = CryptoUtils.SHA256Hash(blockData);
|
||||
byte[] blockHash = CryptoUtils.SHA256Hash(blockData);
|
||||
|
||||
writer.BaseStream.Seek(curBlockOffset + BLOCK_SIZE - 0x20, SeekOrigin.Begin);
|
||||
writer.Write(blockHash);
|
||||
@ -275,11 +274,6 @@ namespace LibTSforge.TokenStore
|
||||
Deserialize();
|
||||
}
|
||||
|
||||
public TokenStoreModern()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Serialize();
|
||||
|
66
README.md
66
README.md
@ -20,29 +20,31 @@ Included methods and tools:
|
||||
- KMS Charger - Charge an existing KMS server to allow immediate use for activation
|
||||
- Clear Tamper State - Clear the tamper state set due to store corruption or deletion
|
||||
- Remove Evaluation Key Lock - Remove the product key change lock set for evaluation product keys
|
||||
- Set IID Parameters - Set parameters for IID independently of installed key
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
Usage: TSforge [/dump <filePath> (<encrFilePath>)] [/load <filePath>] [/kms4k] [/avma4k] [/zcid] [/rtmr] [/duid] [/igpk] [/kmsc] [/ctpr] [/revl] [/prod] [/test] [<activation id>] [/ver <version override>]
|
||||
Usage: TSforge [/dump <filePath> (<encrFilePath>)] [/load <filePath>] [/kms4k] [/avma4k] [/zcid] [/rtmr] [/duid] [/igpk] [/kmsc] [/ctpr] [/revl] [/siid <5/9> <group> <serial> <security>] [/prod] [/test] [<activation id>] [/ver <version override>]
|
||||
Options:
|
||||
/dump <filePath> (<encrFilePath>) Dump and decrypt the physical store to the specified path.
|
||||
/load <filePath> Load and re-encrypt the physical store from the specified path.
|
||||
/kms4k Activate using KMS4k. Only supports KMS-activatable editions.
|
||||
/avma4k Activate using AVMA4k. Only supports Windows Server 2012 R2+.
|
||||
/zcid Activate using ZeroCID. Only supports phone-activatable editions.
|
||||
/rtmr Reset grace/evaluation period timers.
|
||||
/rrmc Reset the rearm count.
|
||||
/duid Delete product key Unique ID used in online key validation.
|
||||
/igpk Install auto-generated/fake product key according to the specified Activation ID.
|
||||
/kmsc Reset the charged count on the local KMS server to 25. Requires an activated KMS host.
|
||||
/ctpr Clear the physical store tamper state.
|
||||
/revl Remove the key change lock in evaluation edition store.
|
||||
/prod Use SPP production key.
|
||||
/test Use SPP test key.
|
||||
/ver <version> Override the detected version. Available versions: vista, 7, 8early, 8, blue, modern.
|
||||
<activation id> A specific activation ID. Useful if you want to activate specific addons like ESU.
|
||||
/? Display this help message.
|
||||
/dump <filePath> (<encrFilePath>) Dump and decrypt the physical store to the specified path.
|
||||
/load <filePath> Load and re-encrypt the physical store from the specified path.
|
||||
/kms4k Activate using KMS4k. Only supports KMS-activatable editions.
|
||||
/avma4k Activate using AVMA4k. Only supports Windows Server 2012 R2+.
|
||||
/zcid Activate using ZeroCID. Only supports phone-activatable editions.
|
||||
/rtmr Reset grace/evaluation period timers.
|
||||
/rrmc Reset the rearm count.
|
||||
/duid Delete product key Unique ID used in online key validation.
|
||||
/igpk Install auto-generated/fake product key according to the specified Activation ID
|
||||
/kmsc Reset the charged count on the local KMS server to 25. Requires an activated KMS host.
|
||||
/ctpr Remove the tamper flags that get set in the physical store when sppsvc detects an attempt to tamper with it.
|
||||
/revl Remove the key change lock in evaluation edition store.
|
||||
/siid <5/9> <group> <serial> <security> Set Installation ID parameters independently of installed key. 5/9 argument specifies PKEY200[5/9] key algorithm.
|
||||
/prod Use SPP production key.
|
||||
/test Use SPP test key.
|
||||
/ver <version> Override the detected version. Available versions: vista, 7, 8, blue, modern.
|
||||
<activation id> A specific activation ID. Useful if you want to activate specific addons like ESU.
|
||||
/? Display this help message.
|
||||
```
|
||||
|
||||
## FAQ
|
||||
@ -73,9 +75,27 @@ You can use the `/igpk` switch in TSforge in order to install licenses by only u
|
||||
|
||||
You can use the `/igpk` and `/zcid` options with the activation ID of the KMS Host SKU to be activated. You can then use the `/kmsc` option with this activation ID to charge the KMS server with 25 clients. Please note that KMS servers will maintain their client counts for a maximum of 30 days.
|
||||
|
||||
### Why is Windows Vista not supported by any activation methods?
|
||||
### What features are implemented in Windows Vista?
|
||||
|
||||
Windows Vista contains a driver which holds a permanent [handle](https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/object-handles) to the physical store, even when SLSvc is stopped after initial startup. This prevents TSforge from writing new trusted store data while the system is booted. There are theoretical workarounds to this issue, but they require an extraordinary amount of bug-prone, specialized code specific to Vista. For these reasons, we do not plan to support Vista/Server 2008.
|
||||
The following options are implemented:
|
||||
|
||||
- `/dump`
|
||||
- `/load`
|
||||
- `/zcid`
|
||||
- `/kms4k`
|
||||
- `/rtmr`
|
||||
- `/rrmc`
|
||||
- `/kmsc`
|
||||
- `/ctpr`
|
||||
|
||||
The following options are NOT implemented:
|
||||
|
||||
- `/duid` - Key Unique ID is not removable from Vista physical store
|
||||
- `/igpk` - Product key data is derived directly from the key string, preventing forgery
|
||||
- `/siid` - IID is also derived directly from the key string
|
||||
- `/revl` - Eval key lock is not present on Vista
|
||||
|
||||
Effectively, this means that a product key must be provided to activate a given SKU. Additionally, ZeroCID on Vista/Server 2008 lacks protection against deactivation due to the WGA update KB929391, though this update is no longer offered via Windows Update.
|
||||
|
||||
### How do I prevent de-activation due to WAT on Windows 7?
|
||||
|
||||
@ -85,6 +105,10 @@ If generic keys are installed, you need to run `TSforge.exe /duid` to remove the
|
||||
|
||||
Windows doesn't support AVMA activation under VM software that fails to provide [Hyper-V Enlightenments](https://www.qemu.org/docs/master/system/i386/hyperv.html). This primarily means that AVMA4k is only supported on VMs running under a [correctly configured QEMU instance](https://blog.wikichoon.com/2014/07/enabling-hyper-v-enlightenments-with-kvm.html) or Hyper-V. If your VM's activation status is `Notification` with the status code `0xC004FD01` after using AVMA4k, you will need to use another activation method.
|
||||
|
||||
### Does TSforge support beta versions of Windows?
|
||||
|
||||
It can, though we do not provide official support for these versions. TSforge works on most insider/beta builds of Windows past Windows 8.1. Beta builds prior to build 9600 are likely to face issues, as the internal data formats used by SPP were constantly changing during this period of development. Builds with similar licensing behavior to retail versions are the most likely to work with the current TSforge codebase. For other builds, you may need to manually edit the source code of LibTSforge to get it to work.
|
||||
|
||||
### How do I remove this activation?
|
||||
|
||||
Run [Microsoft Activation Scripts](https://massgrave.dev), select `Troubleshoot` > `Fix Licensing`. This will reset the physical store and revert any changes made by TSforge.
|
||||
@ -116,7 +140,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,36 +4,44 @@ namespace TSforgeCLI
|
||||
using LibTSforge;
|
||||
using LibTSforge.Activators;
|
||||
using LibTSforge.Modifiers;
|
||||
using LibTSforge.SPP;
|
||||
|
||||
public class Program
|
||||
{
|
||||
private class Options
|
||||
{
|
||||
public bool Dump = false;
|
||||
public bool Dump;
|
||||
public string DumpFilePath = "dump.dat";
|
||||
public string EncrFilePath = null;
|
||||
public bool Load = false;
|
||||
public string EncrFilePath;
|
||||
public bool Load;
|
||||
public string LoadFilePath = "load.dat";
|
||||
public bool KMS4k = false;
|
||||
public bool AVMA4k = false;
|
||||
public bool ZCID = false;
|
||||
public bool TimerReset = false;
|
||||
public bool RearmReset = false;
|
||||
public bool DeleteUniqueId = false;
|
||||
public bool InstallGenPKey = false;
|
||||
public bool KMSHostCharge = false;
|
||||
public bool TamperedFlagsDelete = false;
|
||||
public bool KeyChangeLockDelete = false;
|
||||
public bool? Production = null;
|
||||
public PSVersion? Version = null;
|
||||
public bool KMS4k;
|
||||
public bool AVMA4k;
|
||||
public bool ZCID;
|
||||
public bool TimerReset;
|
||||
public bool RearmReset;
|
||||
public bool DeleteUniqueId;
|
||||
public bool InstallGenPKey;
|
||||
public bool KMSHostCharge;
|
||||
public bool TamperedFlagsDelete;
|
||||
public bool KeyChangeLockDelete;
|
||||
public bool SetIIDParams;
|
||||
public bool? Production;
|
||||
public PSVersion? Version;
|
||||
public Guid ActivationId = Guid.Empty;
|
||||
public bool ShowHelp = false;
|
||||
public bool ShowHelp;
|
||||
public PKeyAlgorithm? Algorithm;
|
||||
public int Group;
|
||||
public int Serial;
|
||||
public ulong Security;
|
||||
}
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Logger.WriteLine("TSforge (c) MASSGRAVE 2025");
|
||||
|
||||
Utils.Wow64EnableWow64FsRedirection(false);
|
||||
|
||||
try
|
||||
{
|
||||
if (args.Length == 0)
|
||||
@ -51,15 +59,15 @@ namespace TSforgeCLI
|
||||
}
|
||||
|
||||
PSVersion version = options.Version ?? Utils.DetectVersion();
|
||||
bool production = options.Production ?? Utils.DetectCurrentKey();
|
||||
bool production = options.Production ?? SPPUtils.DetectCurrentKey();
|
||||
|
||||
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 +99,7 @@ namespace TSforgeCLI
|
||||
}
|
||||
else if (options.KMSHostCharge)
|
||||
{
|
||||
KMSHostCharge.Charge(version, options.ActivationId, production);
|
||||
KMSHostCharge.Charge(version, production, options.ActivationId);
|
||||
}
|
||||
else if (options.TamperedFlagsDelete)
|
||||
{
|
||||
@ -100,6 +108,10 @@ namespace TSforgeCLI
|
||||
else if (options.KeyChangeLockDelete)
|
||||
{
|
||||
KeyChangeLockDelete.Delete(version, production);
|
||||
}
|
||||
else if (options.SetIIDParams)
|
||||
{
|
||||
SetIIDParams.SetParams(version, production, options.ActivationId, options.Algorithm.Value, options.Group, options.Serial, options.Security);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -184,6 +196,38 @@ namespace TSforgeCLI
|
||||
break;
|
||||
case "/revl":
|
||||
options.KeyChangeLockDelete = true;
|
||||
break;
|
||||
case "/siid":
|
||||
options.SetIIDParams = true;
|
||||
|
||||
if (args.Length - i - 1 < 4) throw new ArgumentException("Not enough arguments specified.");
|
||||
|
||||
string algoType = args[++i];
|
||||
|
||||
if (algoType == "5")
|
||||
{
|
||||
options.Algorithm = PKeyAlgorithm.PKEY2005;
|
||||
}
|
||||
else if (algoType == "9")
|
||||
{
|
||||
options.Algorithm = PKeyAlgorithm.PKEY2009;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Invalid key algorithm specified.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
options.Group = int.Parse(args[++i]);
|
||||
options.Serial = int.Parse(args[++i]);
|
||||
options.Security = ulong.Parse(args[++i]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new ArgumentException("Failed to parse key parameters.");
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
try
|
||||
@ -194,7 +238,6 @@ namespace TSforgeCLI
|
||||
{
|
||||
Logger.WriteLine("Argument doesn't exist or the specified activation ID is invalid.");
|
||||
options.ShowHelp = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -206,25 +249,26 @@ namespace TSforgeCLI
|
||||
private static void DisplayUsage()
|
||||
{
|
||||
string exeName = typeof(Program).Namespace;
|
||||
Logger.WriteLine("Usage: " + exeName + " [/dump <filePath> (<encrFilePath>)] [/load <filePath>] [/kms4k] [/avma4k] [/zcid] [/rtmr] [/duid] [/igpk] [/kmsc] [/ctpr] [/revl] [/prod] [/test] [<activation id>] [/ver <version override>]");
|
||||
Logger.WriteLine("Usage: " + exeName + " [/dump <filePath> (<encrFilePath>)] [/load <filePath>] [/kms4k] [/avma4k] [/zcid] [/rtmr] [/duid] [/igpk] [/kmsc] [/ctpr] [/revl] [/siid <5/9> <group> <serial> <security>] [/prod] [/test] [<activation id>] [/ver <version override>]");
|
||||
Logger.WriteLine("Options:");
|
||||
Logger.WriteLine("\t/dump <filePath> (<encrFilePath>) Dump and decrypt the physical store to the specified path.");
|
||||
Logger.WriteLine("\t/load <filePath> Load and re-encrypt the physical store from the specified path.");
|
||||
Logger.WriteLine("\t/kms4k Activate using KMS4k. Only supports KMS-activatable editions.");
|
||||
Logger.WriteLine("\t/avma4k Activate using AVMA4k. Only supports Windows Server 2012 R2+.");
|
||||
Logger.WriteLine("\t/zcid Activate using ZeroCID. Only supports phone-activatable editions.");
|
||||
Logger.WriteLine("\t/rtmr Reset grace/evaluation period timers.");
|
||||
Logger.WriteLine("\t/rrmc Reset the rearm count.");
|
||||
Logger.WriteLine("\t/duid Delete product key Unique ID used in online key validation.");
|
||||
Logger.WriteLine("\t/igpk Install auto-generated/fake product key according to the specified Activation ID");
|
||||
Logger.WriteLine("\t/kmsc Reset the charged count on the local KMS server to 25. Requires an activated KMS host.");
|
||||
Logger.WriteLine("\t/ctpr Remove the tamper flags that get set in the physical store when sppsvc detects an attempt to tamper with it.");
|
||||
Logger.WriteLine("\t/revl Remove the key change lock in evaluation edition store.");
|
||||
Logger.WriteLine("\t/prod Use SPP production key.");
|
||||
Logger.WriteLine("\t/test Use SPP test key.");
|
||||
Logger.WriteLine("\t/ver <version> Override the detected version. Available versions: vista, 7, 8early, 8, blue, modern.");
|
||||
Logger.WriteLine("\t<activation id> A specific activation ID. Useful if you want to activate specific addons like ESU.");
|
||||
Logger.WriteLine("\t/? Display this help message.");
|
||||
Logger.WriteLine("\t/dump <filePath> (<encrFilePath>) Dump and decrypt the physical store to the specified path.");
|
||||
Logger.WriteLine("\t/load <filePath> Load and re-encrypt the physical store from the specified path.");
|
||||
Logger.WriteLine("\t/kms4k Activate using KMS4k. Only supports KMS-activatable editions.");
|
||||
Logger.WriteLine("\t/avma4k Activate using AVMA4k. Only supports Windows Server 2012 R2+.");
|
||||
Logger.WriteLine("\t/zcid Activate using ZeroCID. Only supports phone-activatable editions.");
|
||||
Logger.WriteLine("\t/rtmr Reset grace/evaluation period timers.");
|
||||
Logger.WriteLine("\t/rrmc Reset the rearm count.");
|
||||
Logger.WriteLine("\t/duid Delete product key Unique ID used in online key validation.");
|
||||
Logger.WriteLine("\t/igpk Install auto-generated/fake product key according to the specified Activation ID");
|
||||
Logger.WriteLine("\t/kmsc Reset the charged count on the local KMS server to 25. Requires an activated KMS host.");
|
||||
Logger.WriteLine("\t/ctpr Remove the tamper flags that get set in the physical store when sppsvc detects an attempt to tamper with it.");
|
||||
Logger.WriteLine("\t/revl Remove the key change lock in evaluation edition store.");
|
||||
Logger.WriteLine("\t/siid <5/9> <group> <serial> <security> Set Installation ID parameters independently of installed key. 5/9 argument specifies PKEY200[5/9] key algorithm.");
|
||||
Logger.WriteLine("\t/prod Use SPP production key.");
|
||||
Logger.WriteLine("\t/test Use SPP test key.");
|
||||
Logger.WriteLine("\t/ver <version> Override the detected version. Available versions: vista, 7, 8, blue, modern.");
|
||||
Logger.WriteLine("\t<activation id> A specific activation ID. Useful if you want to activate specific addons like ESU.");
|
||||
Logger.WriteLine("\t/? Display this help message.");
|
||||
}
|
||||
|
||||
private static PSVersion ParseVersion(string ver)
|
||||
@ -233,7 +277,6 @@ namespace TSforgeCLI
|
||||
{
|
||||
case "vista": return PSVersion.Vista;
|
||||
case "7": return PSVersion.Win7;
|
||||
case "8early": return PSVersion.Win8Early;
|
||||
case "8": return PSVersion.Win8;
|
||||
case "blue": return PSVersion.WinBlue;
|
||||
case "modern": return PSVersion.WinModern;
|
||||
|
Loading…
x
Reference in New Issue
Block a user