Upload v1.0

This commit is contained in:
Li 2022-08-12 00:55:31 +12:00
parent 02a911de75
commit b3a80a479a
46 changed files with 76594 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
.vs/*
LibMcCrypt/bin/*
LibMcCrypt/obj/*
PremiumPackInstaller/obj/*
PremiumPackInstaller/bin/*
obj/*
bin/*

73
LibMcCrypt/Crypto.cs Normal file
View File

@ -0,0 +1,73 @@
using System;
using System.IO;
using System.Security.Cryptography;
namespace McCrypt
{
internal class Crypto
{
internal static byte[] Sha256(byte[] data)
{
SHA256 sha256 = SHA256.Create();
byte[] hash = sha256.ComputeHash(data);
sha256.Dispose();
return hash;
}
internal static byte[] Aes256CfbEncrypt(byte[] key, byte[] iv, byte[] data)
{
Aes aes = Aes.Create();
aes.Mode = CipherMode.CFB;
aes.Padding = PaddingMode.None;
aes.BlockSize = 128;
aes.KeySize = 256;
ICryptoTransform aesEncryptor = aes.CreateEncryptor(key, iv);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, aesEncryptor, CryptoStreamMode.Write))
{
csEncrypt.Write(data, 0, data.Length);
long totalWritten = data.Length;
while ((totalWritten % 16 != 0))
{
csEncrypt.WriteByte(0);
totalWritten++;
}
msEncrypt.Seek(0x00, SeekOrigin.Begin);
return msEncrypt.ToArray();
}
}
}
internal static byte[] Aes256CfbDecrypt(byte[] key, byte[] iv, byte[] data)
{
Aes aes = Aes.Create();
aes.Mode = CipherMode.CFB;
aes.Padding = PaddingMode.Zeros;
aes.BlockSize = 128;
aes.KeySize = 256;
ICryptoTransform aesDecryptor = aes.CreateDecryptor(key, iv);
using (MemoryStream msDecrypt = new MemoryStream())
{
msDecrypt.Write(data, 0, data.Length);
while (msDecrypt.Length % 16 != 0)
msDecrypt.WriteByte(0);
msDecrypt.Seek(0x00, SeekOrigin.Begin);
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, aesDecryptor, CryptoStreamMode.Read))
{
byte[] plaintext = new byte[msDecrypt.Length];
csDecrypt.Read(plaintext, 0x00, plaintext.Length);
Array.Copy(plaintext, data, data.Length);
return data;
}
}
}
}
}

289
LibMcCrypt/Keys.cs Normal file
View File

@ -0,0 +1,289 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace McCrypt
{
public class Keys
{
private static Random rng = new Random();
public static string KeyDbFile = "";
internal struct content
{
public string FriendlyId;
public byte[] ContentKey;
}
public struct keysJsonStruct
{
public string id;
public string contentKey;
}
public static string lastTitleAccountId = "";
public static string lastMinecraftId = "";
private static string lastDeviceId = "";
private static List<content> contentList = new List<content>();
public static string ExportKeysJson()
{
List<keysJsonStruct> keysJson = new List<keysJsonStruct>();
foreach (content key in contentList.ToArray())
{
string ckey = Encoding.UTF8.GetString(key.ContentKey);
if (ckey == "s5s5ejuDru4uchuF2drUFuthaspAbepE")
continue;
keysJsonStruct kjs = new keysJsonStruct();
kjs.id = key.FriendlyId;
kjs.contentKey = ckey;
keysJson.Add(kjs);
}
return JsonConvert.SerializeObject(keysJson);
}
private static byte[] deriveUserKey(string UserId, string DeviceId)
{
byte[] userBytes = Encoding.Unicode.GetBytes(UserId);
byte[] deviceBytes = Encoding.Unicode.GetBytes(DeviceId);
int kLen = userBytes.Length;
if (deviceBytes.Length < kLen)
kLen = deviceBytes.Length;
byte[] key = new byte[kLen];
for (int i = 0; i < kLen; i++)
{
key[i] = (byte)(deviceBytes[i] ^ userBytes[i]);
}
return key;
}
internal static string GenerateKey()
{
string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
string key = "";
for (int i = 0; i < 32; i++)
{
key += allowedChars[rng.Next(0, allowedChars.Length)];
}
return key;
}
private static byte[] deriveEntKey(byte[] versionkey, byte[] titleaccountId)
{
int kLen = versionkey.Length;
if (titleaccountId.Length < kLen)
kLen = titleaccountId.Length;
byte[] key = new byte[kLen];
for (int i = 0; i < kLen; i++)
{
key[i] = (byte)(versionkey[i] ^ titleaccountId[i]);
}
return key;
}
private static byte[] deriveContentKey(byte[] UserKey, byte[] ContentKey)
{
int kLen = UserKey.Length;
if (ContentKey.Length < kLen)
kLen = ContentKey.Length;
byte[] key = new byte[kLen];
for (int i = 0; i < kLen; i++)
{
key[i] = (byte)(UserKey[i] ^ ContentKey[i]);
}
int ckLen = kLen / 2;
byte[] contentKey = new byte[ckLen];
for (int i = 0; i < kLen; i += 2)
{
contentKey[i / 2] = key[i];
}
return contentKey;
}
public static void AddKey(string FriendlyId, byte[] ContentKey, bool addToKeyCache = true)
{
if (LookupKey(FriendlyId) != null)
return;
string keyCacheEntry = FriendlyId + "=" + Encoding.UTF8.GetString(ContentKey);
if (addToKeyCache && KeyDbFile != "")
File.AppendAllText(KeyDbFile, keyCacheEntry + "\n");
content content = new content();
content.FriendlyId = FriendlyId;
content.ContentKey = ContentKey;
contentList.Add(content);
}
private static void readReceipt(string receiptData)
{
dynamic recData = Utils.JsonDecodeCloserToMinecraft(receiptData);
string userId = recData.Receipt.EntityId;
string deviceId = "";
if (recData.Receipt.ReceiptData != null)
deviceId = recData.Receipt.ReceiptData.DeviceId;
if (deviceId == "" || deviceId == null)
deviceId = lastDeviceId;
if (deviceId == "" || deviceId == null)
return;
lastDeviceId = deviceId;
byte[] userKey = deriveUserKey(userId, deviceId);
// Derive content keys
int totalEntitlements = recData.Receipt.Entitlements.Count;
for (int i = 0; i < totalEntitlements; i++)
{
try
{
string friendlyId = recData.Receipt.Entitlements[i].FriendlyId;
string contentKeyB64 = recData.Receipt.Entitlements[i].ContentKey;
if (contentKeyB64 == null)
continue;
byte[] contentKey = Utils.ForceDecodeBase64(contentKeyB64);
byte[] realContentKey = deriveContentKey(userKey, contentKey);
AddKey(friendlyId, realContentKey);
}
catch (Exception) { continue; }
}
}
public static void ReadOptionsTxt(string optionsTxtPath)
{
string[] optionsTxt = File.ReadAllLines(optionsTxtPath);
foreach (string option in optionsTxt)
{
string opt = option.Replace("\r", "").Replace("\n", "").Trim();
string[] kvpair = opt.Split(':');
if (kvpair.Length >= 2)
{
if (kvpair[0].Trim() == "last_minecraft_id")
{
lastMinecraftId = kvpair[1].Trim().ToUpper();
}
if (kvpair[0].Trim() == "last_title_account_id")
{
lastTitleAccountId = kvpair[1].Trim().ToUpper();
}
}
}
}
private static string decryptEntitlementFile(string encryptedEnt)
{
int version = Int32.Parse(encryptedEnt.Substring(7, 1));
byte[] versionkey;
switch (version)
{
case 2:
default:
versionkey = Encoding.UTF8.GetBytes("X(nG*ejm&E8)m+8c;-SkLTjF)*QdN6_Y");
break;
}
string deriveText = lastTitleAccountId + lastTitleAccountId;
byte[] entKey = deriveEntKey(versionkey, Encoding.UTF8.GetBytes(deriveText));
string entBase64 = encryptedEnt.Substring(8);
byte[] entCiphertext = Utils.ForceDecodeBase64(entBase64);
byte[] entPlaintext = Marketplace.decryptEntitlementBuffer(entCiphertext, entKey);
return Encoding.UTF8.GetString(entPlaintext);
}
public static void ReadEntitlementFile(string entPath)
{
string jsonData = File.ReadAllText(entPath);
if(jsonData.StartsWith("Version")) // Thanks mojang, this was a fun challange <3
{
jsonData = decryptEntitlementFile(jsonData);
}
dynamic entData;
try
{
entData = Utils.JsonDecodeCloserToMinecraft(jsonData);
}
catch (Exception) { return; }
string receiptB64 = entData.Receipt;
if (receiptB64 == null)
return;
if (receiptB64.Split('.').Length <= 1)
return;
string receiptData = Encoding.UTF8.GetString(Utils.ForceDecodeBase64(receiptB64.Split('.')[1]));
readReceipt(receiptData);
int totalItems = entData.Items.Count;
for (int i = 0; i < totalItems; i++)
{
string b64Data = entData.Items[i].Receipt;
if (b64Data == null)
continue;
if (b64Data.Split('.').Length <= 1)
continue;
string recept = Encoding.UTF8.GetString(Utils.ForceDecodeBase64(b64Data.Split('.')[1]));
readReceipt(recept);
}
}
public static void ReadKeysDb(string keyFile)
{
KeyDbFile = keyFile;
string[] keyList = File.ReadAllLines(keyFile);
foreach (string key in keyList)
{
if (key.Contains('='))
{
string[] keys = key.Split('=');
if (keys.Length >= 2)
{
string friendlyId = keys[0];
byte[] contentKey = Encoding.UTF8.GetBytes(keys[1]);
AddKey(friendlyId, contentKey, false);
}
}
}
}
public static byte[] LookupKey(string FriendlyId)
{
foreach (content content in contentList)
{
if (content.FriendlyId == FriendlyId)
return content.ContentKey;
}
return null;
}
}
}

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4BEF6F52-6545-4BB9-8053-50335A1C6789}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>McCrypt</RootNamespace>
<AssemblyName>LibMcCrypt</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Crypto.cs" />
<Compile Include="Keys.cs" />
<Compile Include="Manifest.cs" />
<Compile Include="Marketplace.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utils.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

125
LibMcCrypt/Manifest.cs Normal file
View File

@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using System.IO;
using System.Text;
namespace McCrypt
{
public class Manifest
{
private struct signatureBlock
{
public string hash;
public string path;
}
public static string SignManifestString(string manifestJson, string setPath)
{
signatureBlock signBlock = new signatureBlock();
signBlock.path = setPath;
signBlock.hash = Convert.ToBase64String(Crypto.Sha256(Encoding.UTF8.GetBytes(manifestJson)));
List<signatureBlock> signatureData = new List<signatureBlock>();
signatureData.Add(signBlock);
string signatureJson = JsonConvert.SerializeObject(signatureData);
return signatureJson;
}
public static void SignManifest(string basePath)
{
string manifestPath = Path.Combine(basePath, "manifest.json");
signatureBlock signBlock = new signatureBlock();
signBlock.path = manifestPath.Remove(0, basePath.Length + 1);
signBlock.hash = Convert.ToBase64String(Crypto.Sha256(File.ReadAllBytes(manifestPath)));
List<signatureBlock> signatureData = new List<signatureBlock>();
signatureData.Add(signBlock);
string signatureJson = JsonConvert.SerializeObject(signatureData);
string signaturesJsonFile = Path.Combine(basePath, "signatures.json");
File.WriteAllText(signaturesJsonFile, signatureJson);
}
public static string ReadName(string manifestFile)
{
string defaultName = Path.GetFileName(Path.GetDirectoryName(manifestFile));
if (!File.Exists(manifestFile))
return Utils.TrimName(defaultName);
string manifestStr = File.ReadAllText(manifestFile);
dynamic manifestData = JsonConvert.DeserializeObject(manifestStr);
if (manifestData.header != null)
{
if (manifestData.header.name != null)
{
string name = manifestData.header.name;
string englishLanguageFile = Path.Combine(Path.GetDirectoryName(manifestFile), "texts", "en_US.lang");
if (File.Exists(englishLanguageFile))
{
string[] lines = File.ReadAllLines(englishLanguageFile);
foreach (string line in lines)
{
if (!line.Contains('='))
continue;
string[] values = line.Split('=');
// How tf does this work??!!
if (values.Length <= 0)
continue;
if (values[0] == name)
return Utils.TrimName(values[1]);
if (values[0] == "pack.name")
return Utils.TrimName(values[1]);
if (values[0].Contains('.'))
{
string[] values2 = values[0].Split('.');
if (values2.Length <= 0)
return Utils.TrimName(defaultName);
if (values[0].Split('.').Last() == name)
return Utils.TrimName(values[1]);
if (values2[0] == "skinpack")
return Utils.TrimName(values[1]);
}
if (values[0].Contains(name))
return Utils.TrimName(values[1]);
}
if (name.Contains("."))
return Utils.TrimName(defaultName);
else
return Utils.TrimName(name);
}
else
return Utils.TrimName(defaultName);
}
}
return Utils.TrimName(defaultName);
}
public static string ReadUUID(string manifestPath)
{
dynamic manifest = JsonConvert.DeserializeObject(File.ReadAllText(manifestPath));
return manifest.header.uuid.ToString();
}
public static void ChangeUUID(string manifestPath, string newUUID)
{
dynamic manifest = JsonConvert.DeserializeObject(File.ReadAllText(manifestPath));
manifest.header.uuid = newUUID;
File.WriteAllText(manifestPath, JsonConvert.SerializeObject(manifest));
}
}
}

329
LibMcCrypt/Marketplace.cs Normal file
View File

@ -0,0 +1,329 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading;
namespace McCrypt
{
public class Marketplace
{
// Hi mojang <3
// https://www.youtube.com/watch?v=jIM6dN3ogbk
// https://www.youtube.com/watch?v=mnnYCJNhw7w
private static string[] dontEncrypt = new string[] { "manifest.json", "contents.json", "texts", "pack_icon.png", "ui"};
private struct contentsJson
{
public int version;
public List<Object> content;
}
private struct contentKeys
{
public string key;
public string path;
}
private struct content
{
public string path;
}
// Checks if file is inside the filename blacklist
private static bool shouldEncrypt(string relPath)
{
foreach (string part in relPath.Split('/'))
if (dontEncrypt.Contains(part))
return false;
return true;
}
// Removes "prid" NBT tag
// This is the one that makes the game tell you to plz buy the pack
public static void CrackLevelDat(string levelDatFile)
{
byte[] find = Encoding.UTF8.GetBytes("prid"); // bytes to locate
byte[] leveldat = File.ReadAllBytes(levelDatFile); // read level.dat
Int64 location = Utils.FindData(leveldat, find); // locate where "prid" is inside level.dat
if (location != -1)
{
FileStream fs = File.Open(levelDatFile, FileMode.Open, FileAccess.ReadWrite); // Open the file for writing
fs.Seek(location + 3, SeekOrigin.Begin);
fs.WriteByte((byte)'a'); // Change to "pria" which the game will just ignore
fs.Close();
}
}
// Change all skins type to "free" instead of "paid"
// This makes the game let you actually apply them
public static void CrackSkinsJson(string skinsJsonFile)
{
File.WriteAllText(skinsJsonFile, File.ReadAllText(skinsJsonFile).Replace("\"paid\"", "\"free\"")); // Read file, replace all "paid" with "free", write file back
}
// Extract a zipe file to the folder its contained in
// And delete the zipe file.
public static void CrackZipe(string zipeFile)
{
ZipFile.ExtractToDirectory(zipeFile, Path.GetDirectoryName(zipeFile));
File.Delete(zipeFile);
}
// EncryptContents Overload to generate keys
public static string EncryptContents(string basePath, string uuid)
{
return EncryptContents(basePath, uuid, Keys.GenerateKey());
}
// Encrypts a contents.json and all files in it-
public static string EncryptContents(string basePath, string uuid, string ContentKey)
{
string contentsJsonPath = Path.Combine(basePath, "contents.json"); // Path to contents.json
contentsJson contentsJson = new contentsJson();
contentsJson.version = 1;
contentsJson.content = new List<object>();
foreach (string entry in Directory.GetFileSystemEntries(basePath, "*", SearchOption.AllDirectories))
{
string relPath = entry.Remove(0, basePath.Length + 1); // Get path relative to pack folder
relPath = relPath.Replace("\\", "/"); // Replace Windows-Style paths, with UNIX paths
bool shouldEnc = shouldEncrypt(relPath);
if (Utils.IsDirectory(entry)) // If its a directroy, add "/" to the end to signify this
{
relPath += "/";
shouldEnc = false;
}
if (shouldEnc) // Check file is not blacklisted file
{
contentKeys keys = new contentKeys();
keys.path = relPath;
keys.key = Keys.GenerateKey(); // Generate a random key for this file
byte[] key = Encoding.UTF8.GetBytes(keys.key); // Copy first 16 bytes of key as IV
byte[] iv = new byte[16];
Array.Copy(key, iv, 16);
byte[] encryptedData = Crypto.Aes256CfbEncrypt(key, iv, File.ReadAllBytes(entry)); // Encrypt the file
File.WriteAllBytes(entry, encryptedData); // Write file
contentsJson.content.Add(keys); // add to content list
}
else // Just add to the content list without encrypting it
{
content content = new content();
content.path = relPath;
contentsJson.content.Add(content);
}
}
string json = JsonConvert.SerializeObject(contentsJson); // JSON Encode contents.json
byte[] contentKey = Encoding.UTF8.GetBytes(ContentKey); // Copy first 16 bytes of the key for IV
byte[] contentIv = new byte[16];
Array.Copy(contentKey, contentIv, 16);
byte[] encryptedJson = Crypto.Aes256CfbEncrypt(contentKey, contentIv, Encoding.UTF8.GetBytes(json)); // Encrypt JSON
// Create encrypted file w header
FileStream fs = File.OpenWrite(contentsJsonPath);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write((uint)0);
bw.Write((uint)0x9BCFB9FC);
bw.Write((UInt64)0);
fs.WriteByte((byte)uuid.Length);
Utils.WriteString(fs, uuid, 0xEF);
fs.Write(encryptedJson, 0, encryptedJson.Length);
fs.Close();
return ContentKey;
}
// Decrypt encrypted entitlement buffer using a specified ent key
internal static byte[] decryptEntitlementBuffer(byte[] EntCiphertext, byte[] EntKey)
{
byte[] iv = new byte[16];
Array.Copy(EntKey, iv, iv.Length);
return Crypto.Aes256CfbDecrypt(EntKey, iv, EntCiphertext);
}
// Decrypt a world (leveldb) or contents.json file
// For the file types that have a header-
private static byte[] worldOrContentsJsonDecrypt(string file)
{
FileStream fs = File.OpenRead(file); // Open file for reading
BinaryReader br = new BinaryReader(fs); // Create a binary reader overlay of it
if (fs.Length <= 0)
{
fs.Dispose();
return new byte[0] { };
}
uint version = br.ReadUInt32();
uint magic = br.ReadUInt32();
UInt64 unk = br.ReadUInt64();
if (version == 0 && magic == 0x9bcfb9fc) // is valid header?
{
int len = fs.ReadByte();
string uuid = Utils.ReadString(fs, len); // Read the pack UUID for this file
byte[] key = Keys.LookupKey(uuid); // Look for key inside .ent / keys.db
if (key == null)
key = Encoding.UTF8.GetBytes("s5s5ejuDru4uchuF2drUFuthaspAbepE"); // Generic skinpack key
// Every skinpack has the same key lol
// This might be wrong, but hey! if it works, it works :D
fs.Seek(0x100, SeekOrigin.Begin); // Read ciphertext
byte[] ciphertext = new byte[fs.Length - 0x100];
fs.Read(ciphertext, 0x00, ciphertext.Length);
byte[] iv = new byte[16]; // Copy first 16 bytes of Key for IV
Array.Copy(key, iv, iv.Length);
byte[] plaintext = Crypto.Aes256CfbDecrypt(key, iv, ciphertext); // Decrypt data
fs.Dispose();
return plaintext;
}
else
{
fs.Dispose();
throw new InvalidDataException("Not a valid LEVELDB or CONTENTS.JSON file.");
}
}
// Read contents.json, and decrypt all files inside
// Now Multi-Threaded for speed!
private static void decryptContentsJsonFiles(string contentsJsonPath, List<Thread> threadList)
{
string baseDirectory = Path.GetDirectoryName(contentsJsonPath); // Get pack folder
string contentsJson = File.ReadAllText(contentsJsonPath); // Read contents.json
dynamic contentsJsonData = Utils.JsonDecodeCloserToMinecraft(contentsJson); // Parse contents.json
int totalContents = contentsJsonData.content.Count;
for (int i = 0; i < totalContents; i++)
{
string relPath = contentsJsonData.content[i].path; // Relative path to file to be decrypted
string decKey = contentsJsonData.content[i].key; // Key for file to be decrypted
if (decKey == null)
continue;
Thread thrd = new Thread(() =>
{
string filePath = Path.Combine(baseDirectory, relPath); // Combine pack dir, with file relative path
byte[] key = Encoding.UTF8.GetBytes(decKey); // Get key bytes
byte[] iv = new byte[16];
Array.Copy(key, iv, iv.Length); // Copy first 16 bytes of key as IV
byte[] cipherText = File.ReadAllBytes(filePath); // Read the file
byte[] plainText = Crypto.Aes256CfbDecrypt(key, iv, cipherText); // Decrypt the file
File.WriteAllBytes(filePath, plainText); // Write back decrypted filie
});
thrd.Priority = ThreadPriority.Highest;
threadList.Add(thrd);
thrd.Start();
}
}
// Decrypt an entire pack / world
// Recursively decrypts all sub-packs.
// Mutli-Threaded.
public static void DecryptContents(string contentsPath)
{
List<Thread> threadList = new List<Thread>();
string oldSchoolZipe = Path.Combine(contentsPath, "content.zipe");
string contentsJsonPath = Path.Combine(contentsPath, "contents.json");
if (File.Exists(oldSchoolZipe)) // Resource packs or Skin Packs
{
byte[] decryptedData = worldOrContentsJsonDecrypt(oldSchoolZipe); // Decrypt the zipe file
File.WriteAllBytes(oldSchoolZipe, decryptedData); // Write decrypted zip back to disk
}
else if (File.Exists(contentsJsonPath)) // Resource packs or Skin Packs
{
string subPacksFolder = Path.Combine(contentsPath, "subpacks");
byte[] decryptedData = worldOrContentsJsonDecrypt(contentsJsonPath); // Decrypt the contents.json file
File.WriteAllBytes(contentsJsonPath, decryptedData); // Write decrypted contents.json back to disk
decryptContentsJsonFiles(contentsJsonPath, threadList); // Decrypt all files in contents.json
// Decrypt all Sub-packs
if (Directory.Exists(subPacksFolder))
{
string[] subPacks = Directory.GetDirectories(subPacksFolder, "*", SearchOption.TopDirectoryOnly);
foreach (string subPack in subPacks)
DecryptContents(Path.Combine(subPacksFolder, subPack));
}
}
else // World Templates
{
string behaviourPacksFolder = Path.Combine(contentsPath, "behavior_packs"); // Get World Resource Packs folder
string resourcePacksFolder = Path.Combine(contentsPath, "resource_packs"); // Get World Behaviour Packs folder
string levelDbFolder = Path.Combine(contentsPath, "db"); // Get leveldb folder
// Decrypt all sub-behavour packs
if (Directory.Exists(behaviourPacksFolder))
{
string[] behaviourPacks = Directory.GetDirectories(behaviourPacksFolder, "*", SearchOption.TopDirectoryOnly);
foreach (string behaviourPack in behaviourPacks)
DecryptContents(Path.Combine(behaviourPacksFolder, behaviourPack));
}
// Decrypt all sub-resource packs
if (Directory.Exists(resourcePacksFolder))
{
string[] resourcePacks = Directory.GetDirectories(resourcePacksFolder, "*", SearchOption.TopDirectoryOnly);
foreach (string resourcePack in resourcePacks)
DecryptContents(Path.Combine(resourcePacksFolder, resourcePack));
}
// Decrypt leveldb files
if (Directory.Exists(levelDbFolder))
{
string[] levelDbFiles = Directory.GetFiles(levelDbFolder, "*", SearchOption.AllDirectories);
foreach (string levelDbFile in levelDbFiles)
{
Thread thrd = new Thread(() =>
{
string fileToDecrypt = Path.Combine(levelDbFolder, levelDbFile); // Get full path to leveldb file
byte[] decryptedData;
try
{
decryptedData = worldOrContentsJsonDecrypt(fileToDecrypt); // Decrypr file
File.WriteAllBytes(fileToDecrypt, decryptedData); // Write to disk
}
catch (InvalidDataException)
{
Console.Error.WriteLine("Failed to decrypt db/" + Path.GetFileName(levelDbFile));
}
});
thrd.Priority = ThreadPriority.Highest;
threadList.Add(thrd);
thrd.Start();
}
}
}
Thread[] threads = threadList.ToArray();
threadList.Clear();
foreach(Thread t in threads)
t.Join();
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("McCrypt")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("McCrypt")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4bef6f52-6545-4bb9-8053-50335a1c6789")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

97
LibMcCrypt/Utils.cs Normal file
View File

@ -0,0 +1,97 @@
using Newtonsoft.Json;
using System;
using System.IO;
using System.Text;
namespace McCrypt
{
internal class Utils
{
internal static object JsonDecodeCloserToMinecraft(string json)
{
for (int i = json.Length; i > 0; i--)
{
try
{
return JsonConvert.DeserializeObject(json.Substring(0, i));
}
catch (Exception) { };
}
throw new Exception();
}
internal static bool IsDirectory(string path)
{
if (Directory.Exists(path))
return true;
else if (File.Exists(path))
return false;
else
throw new FileNotFoundException("Cannot find file: " + path);
}
internal static Int64 FindData(byte[] data, byte[] pattern)
{
for (Int64 i = 0; i < data.LongLength - pattern.LongLength; i++)
{
bool match = true;
for (Int64 k = 0; k < pattern.LongLength; k++)
{
if (data[i + k] != pattern[k])
{
match = false;
break;
}
}
if (match)
{
return i;
}
}
return -1;
}
internal static string ReadString(Stream str, int len)
{
byte[] stringBytes = new byte[len];
str.Read(stringBytes, 0x00, len);
return Encoding.UTF8.GetString(stringBytes);
}
internal static void WriteString(Stream stream, string str, long totalLength)
{
byte[] data = Encoding.UTF8.GetBytes(str);
long paddingLen = totalLength - data.Length;
byte[] padding = new byte[paddingLen];
stream.Write(data, 0, data.Length);
stream.Write(padding, 0, padding.Length);
}
internal static byte[] ForceDecodeBase64(string base64Data)
{
for (int i = 0; i < 20; i++)
{
try
{
return Convert.FromBase64String(base64Data);
}
catch (Exception)
{
base64Data += "=";
}
}
return null;
}
internal static string TrimName(string name)
{
if (name.Contains("#"))
{
return name.Substring(0, name.IndexOf("#")).Trim();
}
return name.Trim();
}
}
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net48" />
</packages>

31
PremiumPackInstaller.sln Normal file
View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32611.2
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PremiumPackInstaller", "PremiumPackInstaller\PremiumPackInstaller.csproj", "{6EDC5573-14BE-429A-B663-60E4AE604079}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibMcCrypt", "LibMcCrypt\LibMcCrypt.csproj", "{4BEF6F52-6545-4BB9-8053-50335A1C6789}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6EDC5573-14BE-429A-B663-60E4AE604079}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6EDC5573-14BE-429A-B663-60E4AE604079}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6EDC5573-14BE-429A-B663-60E4AE604079}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6EDC5573-14BE-429A-B663-60E4AE604079}.Release|Any CPU.Build.0 = Release|Any CPU
{4BEF6F52-6545-4BB9-8053-50335A1C6789}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4BEF6F52-6545-4BB9-8053-50335A1C6789}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4BEF6F52-6545-4BB9-8053-50335A1C6789}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4BEF6F52-6545-4BB9-8053-50335A1C6789}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DD7BE535-6084-456D-A3DE-F6E06369CB13}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>

View File

@ -0,0 +1,147 @@
namespace PremiumPackInstaller
{
partial class MainWindow
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainWindow));
this.getMoreSkinsList = new System.Windows.Forms.ListBox();
this.label1 = new System.Windows.Forms.Label();
this.refreshButton = new System.Windows.Forms.Button();
this.clientVersion = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.replacePack = new System.Windows.Forms.Button();
this.label3 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// getMoreSkinsList
//
this.getMoreSkinsList.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.getMoreSkinsList.FormattingEnabled = true;
this.getMoreSkinsList.Location = new System.Drawing.Point(12, 61);
this.getMoreSkinsList.Name = "getMoreSkinsList";
this.getMoreSkinsList.Size = new System.Drawing.Size(776, 355);
this.getMoreSkinsList.TabIndex = 0;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(9, 41);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(109, 13);
this.label1.TabIndex = 1;
this.label1.Text = "\"Get More\" Skins List";
//
// refreshButton
//
this.refreshButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.refreshButton.Enabled = false;
this.refreshButton.Location = new System.Drawing.Point(692, 34);
this.refreshButton.Name = "refreshButton";
this.refreshButton.Size = new System.Drawing.Size(96, 26);
this.refreshButton.TabIndex = 2;
this.refreshButton.Text = "Refresh List";
this.refreshButton.UseVisualStyleBackColor = true;
this.refreshButton.Click += new System.EventHandler(this.refreshButton_Click);
//
// clientVersion
//
this.clientVersion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.clientVersion.Location = new System.Drawing.Point(728, 8);
this.clientVersion.Name = "clientVersion";
this.clientVersion.Size = new System.Drawing.Size(60, 20);
this.clientVersion.TabIndex = 3;
this.clientVersion.Text = "1.19.20";
this.clientVersion.TextChanged += new System.EventHandler(this.clientVersion_TextChanged);
//
// label2
//
this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(648, 9);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(74, 13);
this.label2.TabIndex = 4;
this.label2.Text = "Client Version:";
//
// replacePack
//
this.replacePack.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.replacePack.Enabled = false;
this.replacePack.Location = new System.Drawing.Point(15, 422);
this.replacePack.Name = "replacePack";
this.replacePack.Size = new System.Drawing.Size(773, 28);
this.replacePack.TabIndex = 5;
this.replacePack.Text = "Replace with new pack";
this.replacePack.UseVisualStyleBackColor = true;
this.replacePack.Click += new System.EventHandler(this.replacePack_Click);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 8);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(191, 26);
this.label3.TabIndex = 6;
this.label3.Text = "Discovered by and programmed by Li - \r\nTrans rights are Human Rights";
//
// MainWindow
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 465);
this.Controls.Add(this.label3);
this.Controls.Add(this.replacePack);
this.Controls.Add(this.label2);
this.Controls.Add(this.clientVersion);
this.Controls.Add(this.refreshButton);
this.Controls.Add(this.label1);
this.Controls.Add(this.getMoreSkinsList);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "MainWindow";
this.Text = "Premium Packs Installer";
this.Load += new System.EventHandler(this.MainWindow_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ListBox getMoreSkinsList;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button refreshButton;
private System.Windows.Forms.TextBox clientVersion;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button replacePack;
private System.Windows.Forms.Label label3;
}
}

View File

@ -0,0 +1,216 @@
using McCrypt;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace PremiumPackInstaller
{
public partial class MainWindow : Form
{
public Dictionary<String, String> SkinpacksList = new Dictionary<String, String>();
public Random rng = new Random();
string LocalAppdata;
string MinecraftFolder;
string LocalState;
string PremiumCache;
string PremiumSkins;
public MainWindow()
{
LocalAppdata = Environment.GetEnvironmentVariable("LOCALAPPDATA");
MinecraftFolder = Path.Combine(LocalAppdata, "Packages", "Microsoft.MinecraftUWP_8wekyb3d8bbwe");
LocalState = Path.Combine(MinecraftFolder, "LocalState");
PremiumCache = Path.Combine(LocalState, "premium_cache");
PremiumSkins = Path.Combine(PremiumCache, "skin_packs");
InitializeComponent();
}
private void LoginPlayfab()
{
Task.Run(() =>
{
try
{
PlayFab.PlayFab.PullEntityTokenOutOfMyAss();
RefreshItemList();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
});
}
private string FindInPremiumCache(string uuid)
{
foreach(string premiumSkinFolder in Directory.GetDirectories(PremiumSkins, "*", SearchOption.TopDirectoryOnly))
{
try
{
string manifestJson = Path.Combine(premiumSkinFolder, "manifest.json");
if (Manifest.ReadUUID(manifestJson) == uuid)
return premiumSkinFolder;
}
catch (Exception)
{
continue;
}
}
byte[] randomBytes = new byte[8];
rng.NextBytes(randomBytes);
string name = Convert.ToBase64String(randomBytes);
if (Directory.Exists(name))
return FindInPremiumCache(uuid);
return Path.Combine(PremiumSkins, name);
}
private void RefreshPlayfab()
{
SkinpacksList.Clear();
dynamic results = PlayFab.PlayFab.Search("", "((contentType eq 'MarketplaceDurableCatalog_V1.2' and contents/any(c: c/minClientVersion le '" + clientVersion.Text + "' and c/maxClientVersion gt '" + clientVersion.Text + "'))) and platforms/any(tp: tp eq 'uwp.store' and tp eq 'title.bedrockvanilla') and (tags/any(t: t eq 'skinpack' or t eq 'mashup' or t eq 'has_skinpack')) and not tags/any(t: t eq 'hidden_offer' or t eq 'realms_plus')", 0, "startDate desc");
foreach (dynamic result in results.Items)
{
JObject resultTitle = result.Title;
if (resultTitle.First == null)
continue;
if (resultTitle.First.First == null)
continue;
string packTitle = resultTitle.First.First.ToString();
if (result.DisplayProperties != null)
if (result.DisplayProperties.packIdentity != null)
foreach (dynamic identity in result.DisplayProperties.packIdentity)
{
if (identity.type.ToString() == "skinpack" || identity.type.ToString() == "skin_pack")
{
string packUuid = identity.uuid.ToString();
if(!SkinpacksList.ContainsKey(packUuid))
SkinpacksList.Add(packUuid, packTitle);
}
}
}
}
private void RefreshItemList()
{
Task.Run(() =>
{
try
{
this.Invoke((Action)delegate { replacePack.Enabled = false; });
this.Invoke((Action)delegate { refreshButton.Enabled = false; });
this.Invoke((Action)delegate { getMoreSkinsList.Items.Clear(); });
RefreshPlayfab();
foreach(KeyValuePair<String, String> SkinPack in SkinpacksList)
{
string skinsListEntry = SkinPack.Value;
string manifestFile = Path.Combine(FindInPremiumCache(SkinPack.Key), "manifest.json");
if (File.Exists(manifestFile))
{
try
{
string installedName = Manifest.ReadName(manifestFile);
if (installedName.Trim() != SkinPack.Value.Trim())
skinsListEntry += " => " + installedName;
}
catch (Exception) { };
}
this.Invoke((Action)delegate { getMoreSkinsList.Items.Add(skinsListEntry); });
this.Invoke((Action)delegate { getMoreSkinsList.SelectedIndex = 0; });
}
this.Invoke((Action)delegate { refreshButton.Enabled = true; });
this.Invoke((Action)delegate { replacePack.Enabled = true; });
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
});
}
private void MainWindow_Load(object sender, EventArgs e)
{
string verStr = PlayFab.Config.GetConfValue("ClientVersion");
if(verStr == null)
{
verStr = "1.19.20";
PlayFab.Config.WriteConfValue("ClientVersion", verStr);
}
clientVersion.Text = verStr;
LoginPlayfab();
}
private void refreshButton_Click(object sender, EventArgs e)
{
RefreshItemList();
}
private void replacePack_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Minecraft Skin Pack|*.mcpack";
ofd.Title = "Select a MCPack File";
if (ofd.ShowDialog() == DialogResult.OK)
{
try
{
string mcpack = ofd.FileName;
string uuid = SkinpacksList.ElementAt(getMoreSkinsList.SelectedIndex).Key;
string contentKey = "s5s5ejuDru4uchuF2drUFuthaspAbepE";
string skinPackPath = FindInPremiumCache(uuid);
if (Directory.Exists(skinPackPath))
Directory.Delete(skinPackPath, true);
Directory.CreateDirectory(skinPackPath);
ZipFile.ExtractToDirectory(mcpack, skinPackPath);
string manifestJson = Path.Combine(skinPackPath, "manifest.json");
Manifest.ChangeUUID(manifestJson, uuid);
Manifest.SignManifest(skinPackPath);
Marketplace.EncryptContents(skinPackPath, uuid, contentKey);
RefreshItemList();
MessageBox.Show("Pack replaced!", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch(Exception ex)
{
MessageBox.Show("Pack replace fail: "+ex.Message, "Fail", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void clientVersion_TextChanged(object sender, EventArgs e)
{
while (true)
{
try
{
PlayFab.Config.WriteConfValue("ClientVersion", clientVersion.Text);
break;
}
catch (Exception) { };
}
}
}
}

View File

@ -0,0 +1,197 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAMMOAADDDgAAAAAAAAAA
AAAfHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8e
Hv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8e
Hv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8dHf8fHR3/Hx0d/x8dHf8fHR3/Hx0d/x8dHf8fHR3/Hx0d/x8d
Hf8fHR3/Hx0d/x8dHf8fHR3/Hx0d/x8dHf8fHR3/Hx0d/x8dHf8fHR3/Hx0d/x8eHv8fHh7/Hx4e/x8e
Hv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fISD/Hy4o/x8vKP8fLyj/Hy8o/x8vKP8fLyj/Hy8o/x8v
KP8fLyj/Hy8o/x8vKP8fLyj/Hy8o/x8vKP8fLyj/Hy8o/x8vKP8fLyj/Hy8o/x8vKP8fLif/ICMh/yAi
IP8gIiD/ICIg/yAiIP8fHx7/Hx4e/x8eHv8fHh7/Hx0d/x8uJ/8eb0v/HnJN/x5yTf8eck3/HnJN/x5y
Tf8eck3/HnJN/x5yTf8eck3/HnJN/x5yTf8eck3/HnJN/x5yTf8eck3/HnJN/x5yTf8eck3/HnJN/x5r
Sf8iOi3/IjMp/yIzKf8iMyn/IjIp/yAiIP8fHh7/Hx4e/x8eHv8fHR3/Hy8o/x5yTf8edU//HnNO/x5z
Tv8ec07/HnNO/x5zTv8ec07/HnNO/x5zTv8ec07/HnNO/x5zTv8ec07/HnNO/x5zTv8ec07/HnNO/x5z
Tv8ec07/HmxK/yI7Lf8iNCn/IjQp/yI0Kf8iMyn/ICIg/x8eHv8fHh7/Hx4e/x8dHf8fLyj/HnJN/x5z
Tv8gSzb/IUAw/yFBMP8hQTD/IUEw/yFBMP8hQTD/IUEw/yFBMP8hQTD/IUEw/yFBMP8hQTD/IUEw/yFB
MP8hQTD/IUEw/yFBMP8hQC//IjUq/yI0Kf8iNCn/IjQp/yIzKf8gIiD/Hx4e/x8eHv8fHh7/Hx0d/x8v
KP8eck3/HnNO/yFAMP8iMif/IjMo/yIyKP8iMij/IjIo/yIyKP8iMij/IjIo/yIyKP8iMij/IjIo/yIy
KP8iMij/IjIo/yIyKP8iMij/IjIo/yIyKP8iMyj/IjMo/yIzKP8iMyj/IjIo/yAiIP8fHh7/Hx4e/x8e
Hv8fHR3/Hy8o/x5yTf8ec07/IUEw/yIzKP8jNSr/J0A0/yhBNf8oQTX/KEE1/yhBNf8oQTX/KEE1/yhB
Nf8oQTX/KEE1/yhBNf8oQTX/KEE1/yhBNf8oQTX/KEE1/yhBNf8oQTX/KEE1/yhBNf8oQDT/ISUi/x8e
Hv8fHh7/Hx4e/x8dHf8fLyj/HnJN/x5zTv8hQTD/IjIo/yc/NP9Rk4T/Vp+Q/1aej/9Wno//Vp6P/1ae
j/9Wno//Vp6P/1aej/9Wno//Vp6P/1aej/9Wno//Vp6P/1aej/9Wno//Vp6P/1aej/9Wno//Vp6P/1SZ
i/8qNzT/Hhwc/x8eHv8fHh7/Hx0d/x8vKP8eck3/HnNO/yFBMP8iMij/KEE1/1afkP9crZ3/XKyc/12t
nf9drZ3/Xa2d/12tnf9drZ3/Xa2d/12tnf9drZ3/Xa2d/12tnf9drZ3/Xa2d/12tnf9drZ3/Xa2d/12t
nf9crJz/WqeX/ys6N/8eHBz/Hx4e/x8eHv8fHR3/Hy8o/x5yTf8ec07/IUEw/yIyKP8oQTX/Vp6P/12s
nP9ap5f/U5mK/1OYif9TmIn/U5iJ/1OYif9TmIn/U5iJ/1OYif9TmIn/U5iJ/1OYif9TmIn/U5iJ/1OY
if9TmIn/VZyN/1yqmv9appb/Kzo2/x4cHP8fHh7/Hx4e/x8dHf8fLyj/HnJN/x5zTv8hQTD/IjIo/yhB
Nf9Wno//Xa2d/1OZif8xUUP/L05A/y9NQP8vTUD/L01A/y9NQP8vTUD/L01A/y9NQP8vTUD/L01A/y9N
QP8vTUD/L05A/y5NP/84YFL/WqiY/1qml/8rOjb/Hhwc/x8eHv8fHh7/Hx0d/x8vKP8eck3/HnNO/yFB
MP8iMij/KEE1/1aej/9drZ3/U5iJ/y9OQP8tSj3/L0w//y9NQP8vTUD/L01A/y9NQP8vTUD/L01A/y9N
QP8vTUD/L01A/y9NQP8tSj3/LEk8/zZdT/9aqJj/WqaX/ys6Nv8eHBz/Hx4e/x8eHv8fHR3/Hy8o/x5y
Tf8ec07/IUEw/yIyKP8oQTX/Vp6P/12tnf9TmIn/L01A/y5NQP9MiXr/VJmK/1OYif9TmIn/U5iJ/1OY
if9TmIn/U5iJ/1OYif9TmYn/T5CB/zFSRf8sSDv/Nl1P/1qomP9appf/Kzo2/x4cHP8fHh7/Hx4e/x8d
Hf8fLyj/HnJN/x5zTv8hQTD/IjIo/yhBNf9Wno//Xa2d/1OYiP8vTD//L00//1SZiv9erp7/Xa2d/12t
nf9drZ3/Xa2d/12tnf9drZ3/Xa2d/12unv9YopP/MlRG/yxHOv82XE//WqiY/1qml/8rOjb/Hhwc/x8e
Hv8fHh7/Hx0d/x8vKP8eck3/HnNO/yFBMP8iMij/KEE1/1aej/9drZ3/VJqL/zRXSv8zV0r/UJKD/1ii
kv9XoZH/V6GR/1ehkf9XoZH/V6GR/1ehkf9XoZH/V6KR/1OZif82XE//MVJF/zplV/9bqJj/WqaX/ys6
Nv8eHBz/Hx4e/x8eHv8fHR3/Hy8o/x5yTf8ec07/IUEw/yIyKP8oQTX/Vp6P/1ysnP9bqZn/V6GR/1ae
jv85Y1X/MVNG/zJUR/8yVEf/MlRH/zJUR/8yVEf/MlRH/zJUR/8yU0f/NlxP/1OZif9XoZH/WKOT/1yr
m/9appb/Kzo2/x4cHP8fHh7/Hx4e/x8dHf8fLyj/HnJN/x5zTv8hQTD/IjIo/yhBNf9Wno//XKyc/1yr
m/9crJz/WqiY/zVcTv8rRzr/LEg7/yxIO/8sSDv/LEg7/y1JPP8tSTz/LEg7/yxHOv8xU0X/V6GS/1yt
nf9crJz/XKub/1qmlv8rOjb/Hhwc/x8eHv8fHh7/Hx0d/x8vKP8eck3/HnNO/yFBMP8iMij/KEE1/1ae
j/9crJz/XKub/1yrm/9bqJj/PWxe/zVcTv82XU//Nl1P/zZdT/80WUv/LUs+/y1LPv80WUv/Nl1P/zpl
V/9Yo5P/XKyb/1yrm/9cq5v/WqaW/ys6Nv8eHBz/Hx4e/x8eHv8fHR3/Hy8o/x5yTf8ec07/IUEw/yIy
KP8oQTX/Vp6P/1ysnP9cq5v/XKub/1yrm/9aqZn/WqiY/1qomP9ap5j/W6iZ/1GVhv8vTUD/L01A/1GW
hv9bqZn/WqiY/1yrm/9cq5v/XKub/1yrm/9appb/Kzo2/x4cHP8fHh7/Hx4e/x8dHf8fLyj/HnJN/x5z
Tv8hQTD/IjIo/yhBNf9Wno//XKyc/1yrm/9cq5v/XKub/1qpmf9aqJj/WqiY/1yrm/9drJz/U5mJ/zFR
Q/8xUUP/UpaH/1upmf9aqJj/XKub/1yrm/9cq5v/XKub/1qmlv8rOjb/Hhwc/x8eHv8fHh7/Hx0d/x8v
KP8eck3/HnNO/yFBMP8iMij/KEE1/1aej/9crJz/XKub/1yrm/9bqJj/PWxe/zVbTf86ZVf/WKOT/1ys
nP9ap5f/U5mK/1KWh/88aVr/NVxO/zplV/9Yo5P/XKyb/1yrm/9cq5v/WqaW/ys6Nv8eHBz/Hx4e/x8e
Hv8fHR3/Hy8o/x5yTf8ec07/IUEw/yIyKP8oQTX/Vp6P/1ysnP9cq5v/XKub/1qnl/81W07/K0Y5/zFT
Rf9XoZL/XK2d/1ysnP9drZ3/W6mZ/zZcTv8rRjn/MVJF/1ehkf9crJz/XKub/1yrm/9appb/Kzo2/x4c
HP8fHh7/Hx4e/x8dHf8fLif/HmtJ/x5sSv8hPzD/IjIo/yhBNf9Wno//XKyc/1yrm/9cq5v/WqiY/zpl
V/8xUkX/NlxP/1OZif9XopH/V6GR/1ehkf9Wno7/OWNV/zFSRf82XVD/WKKS/1ysnP9cq5v/XKub/1qm
lv8rOjb/Hhwc/x8eHv8fHh7/Hx4e/yAkIf8iOiz/Ijst/yI1Kv8iMyj/KEE1/1aej/9crJz/XKub/1yr
m/9cq5v/WKOT/1ehkf9TmYn/NlxP/zJTR/8yVEf/MlRH/zNXSv9QkoP/V6KS/1iikv9bqpr/XKub/1yr
m/9cq5v/WqaW/ys6Nv8eHBz/Hx4e/x8eHv8fHh7/ICIg/yIzKf8iNCn/IjQp/yIzKP8oQTX/Vp6P/1ys
nP9cq5v/XKub/1yrm/9crJz/XK2d/1ehkv8xU0X/LEc6/yxIO/8sSDv/Lkw//1OYif9drZ3/XKyc/1yr
m/9cq5v/XKub/1yrm/9appb/Kzo2/x4cHP8fHh7/Hx4e/x8eHv8gIiD/IjMp/yI0Kf8iNCn/IjMo/yhB
Nf9Wno//XKyc/1yrm/9cq5v/XKub/1yrm/9crJv/WKOT/zplV/82XE//Nl1P/zZdT/83YFL/VZyM/12s
nP9cq5v/XKub/1yrm/9cq5v/XKub/1qmlv8rOjb/Hhwc/x8eHv8fHh7/Hx4e/yAiIP8iMyn/IjQp/yI0
Kf8iMyj/KEE1/1aej/9crJz/XKub/1yrm/9cq5v/XKub/1yrm/9cq5v/WqiY/1qomP9aqJj/WqiY/1qo
mP9cqpr/XKub/1yrm/9cq5v/XKub/1yrm/9cq5v/WqaW/ys6Nv8eHBz/Hx4e/x8eHv8fHh7/ICIg/yIy
Kf8iMyn/IjMp/yIyKP8oPzX/VJqK/1qnl/9appb/WqaW/1qmlv9appb/WqaW/1qmlv9appf/WqaX/1qm
l/9appf/WqaX/1qmlv9appb/WqaW/1qmlv9appb/WqaW/1qmlv9YoZL/Kzk1/x4cHP8fHh7/Hx4e/x8e
Hv8fHx7/ICIg/yAiIP8gIiD/ICIg/yElIv8qNzT/Kzo2/ys6Nv8rOjb/Kzo2/ys6Nv8rOjb/Kzo2/ys6
Nv8rOjb/Kzo2/ys6Nv8rOjb/Kzo2/ys6Nv8rOjb/Kzo2/ys6Nv8rOjb/Kzo2/ys5Nf8hIyP/Hx4e/x8e
Hv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x4cHP8eHBz/Hhwc/x4cHP8eHBz/Hhwc/x4c
HP8eHBz/Hhwc/x4cHP8eHBz/Hhwc/x4cHP8eHBz/Hhwc/x4cHP8eHBz/Hhwc/x4cHP8eHBz/Hhwc/x8e
Hv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8e
Hv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8e
Hv8fHh7/Hx4e/x8eHv8fHh7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
</value>
</data>
</root>

View File

@ -0,0 +1,65 @@
using System;
using System.IO;
using System.Linq;
namespace PlayFab
{
internal class Config
{
public static string DataFolder = Path.Combine(Environment.GetEnvironmentVariable("APPDATA"), "PremiumPackInstaller");
public static string ConfigFile = Path.Combine(DataFolder, "playfab.conf");
private static void initConfig()
{
Directory.CreateDirectory(DataFolder);
File.WriteAllText(ConfigFile, "");
}
private static void replaceConfValue(string key, string newval)
{
if (!File.Exists(ConfigFile))
initConfig();
string[] keyValuePairs = File.ReadAllLines(ConfigFile);
for (int i = 0; i < keyValuePairs.Length; i++)
{
string[] kvp = keyValuePairs[i].Split(':');
if (kvp[0] == key)
keyValuePairs[i] = key + ":" + newval;
}
File.WriteAllLines(ConfigFile, keyValuePairs);
}
public static string GetConfValue(string key)
{
if (!File.Exists(ConfigFile))
initConfig();
string[] keyValuePairs = File.ReadAllLines(ConfigFile);
foreach (string keyValuePair in keyValuePairs)
{
string[] kvp = keyValuePair.Split(':');
if (kvp[0] == key)
return String.Join(":", kvp.Skip(1).ToArray());
}
return null;
}
public static void WriteConfValue(string key, string value)
{
if (!File.Exists(ConfigFile))
initConfig();
string curConfValue = GetConfValue(key);
if (curConfValue == value)
return;
if (curConfValue != null)
replaceConfValue(key, value);
else
File.AppendAllLines(ConfigFile, new string[] { key + ":" + value });
}
}
}

View File

@ -0,0 +1,18 @@

using System.Net;
using System;
namespace PlayFab
{
class McClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;
if (request == null)
return null;
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
return request;
}
}
}

View File

@ -0,0 +1,234 @@
using Newtonsoft.Json;
using System;
using System.Dynamic;
using System.Net;
using System.Security.Cryptography;
using System.Text;
namespace PlayFab
{
public class PlayFab
{
public static string PLAYFAB_VERSION = "XPlatCppSdk-3.6.190304";
public static string CPP_REST_VERSION = "cpprestsdk/2.9.0";
public static string TITLE_ID = "20CA2";
public static string TITLE_SECRET = "S8RS53ZEIGMYTYG856U3U19AORWXQXF41J7FT3X9YCWAC7I35X";
public static byte[] PUBLIC_KEY = null;
public static string ENTITY_TOKEN = null;
public static string ENTITY_ID = null;
public static string ENTITY_TYPE = null;
public static dynamic GetProductInformation(string uuid)
{
dynamic dyn = new ExpandoObject();
dyn.ItemId = uuid;
dyn.ETag = "";
return POST(dyn, "/Catalog/GetPublishedItem");
}
public static dynamic Search(string query, string filter = "", int skip = 0, string orderBy= "creationDate DESC")
{
dynamic dyn = new ExpandoObject();
dyn.count = true;
dyn.filter = filter;
dyn.search = query;
dyn.orderBy = orderBy;
dyn.top = 300;
dyn.skip = skip;
return POST(dyn, "/Catalog/Search");
}
public static dynamic POST(dynamic data, string url, string clientsecret = null, bool incSDK = false)
{
McClient wc = new McClient();
string body = JsonConvert.SerializeObject(data, (incSDK ? Formatting.Indented : Formatting.None));
// Pretend to be minecraft ...
wc.Headers.Set("Accept", "application/json");
wc.Headers.Set("Accept-Language", "en-US");
wc.Headers.Set("Accept-Encoding", "gzip, deflate, br");
wc.Headers.Set("User-Agent", CPP_REST_VERSION);
wc.Headers.Set("x-playfabsdk", PLAYFAB_VERSION);
wc.Headers.Set("x-reporterrorassuccess", "true");
wc.Headers.Set("content-type", "application/json; charset=utf-8");
if (clientsecret != null)
{
string signature;
string timestamp = DateTime.UtcNow.ToString("O");
using (SHA256 hash = SHA256.Create())
{
string msg = body + "." + timestamp + "." + clientsecret;
byte[] bytesToHash = Encoding.UTF8.GetBytes(msg);
signature = Convert.ToBase64String(hash.ComputeHash(bytesToHash));
}
wc.Headers.Set("x-playfab-signature", signature);
wc.Headers.Set("x-playfab-timestamp", timestamp);
}
if (ENTITY_TOKEN != null)
wc.Headers.Set("x-entitytoken", ENTITY_TOKEN);
string response = wc.UploadString(GetPlayfabApiUrl() + url + (incSDK ? SdkMsg() : ""), body);
dynamic resp = JsonConvert.DeserializeObject(response);
wc.Dispose();
return resp.data;
}
public static string RefreshEntityTokenBullshit()
{
dynamic dyn = new ExpandoObject();
dyn.Entity = new ExpandoObject();
dyn.Entity.Id = ENTITY_ID;
dyn.Entity.Type = ENTITY_TYPE;
dynamic resp = POST(dyn, "/Authentication/GetEntityToken", null, true);
ENTITY_TOKEN = resp.EntityToken.ToString();
return ENTITY_TOKEN;
}
public static string SdkMsg()
{
return "?sdk=" + PLAYFAB_VERSION;
}
public static string GenerateClientSecret()
{
Random r = new Random(Guid.NewGuid().GetHashCode());
byte[] clientSecret = new byte[0x20];
r.NextBytes(clientSecret);
return Convert.ToBase64String(clientSecret);
}
public static string GenerateCustomId()
{
Random r = new Random(Guid.NewGuid().GetHashCode());
byte[] customId = new byte[0x10];
r.NextBytes(customId);
return "MCPF" + BitConverter.ToString(customId).Replace("-", "").ToUpper();
}
public static string GetPlayfabApiUrl()
{
return "https://" + TITLE_ID + ".playfabapi.com";
}
// How 2 find TitleSharedSecret:
// 1- delete all mc data
// 2- open fiddler
// 3- open minecraft
// 4- check for https://20ca2.playfabapi.com/Client/GetTitlePublicKey...
public static void GetPublicKeyAndMicrosoftTakesABigL()
{
dynamic dyn = new ExpandoObject();
dyn.TitleId = TITLE_ID;
dyn.TitleSharedSecret = TITLE_SECRET;
dynamic resp = POST(dyn, "/Client/GetTitlePublicKey", null, true);
PUBLIC_KEY = Convert.FromBase64String(resp.RSAPublicKey.ToString());
}
public static string EncryptCustomIdLoginToken(string customId, string clientSecret)
{
dynamic dyn = new ExpandoObject();
dyn.CustomId = customId;
dyn.PlayerSecret = clientSecret;
return EncryptRequest(JsonConvert.SerializeObject(dyn));
}
public static string LoginWithCustomId(bool newUser = true, string customId = null, string clientSecret = null)
{
dynamic dyn = new ExpandoObject();
if (newUser)
dyn.CreateAccount = true;
else
dyn.CreateAccount = null;
dyn.CustomId = customId;
if (clientSecret == null)
clientSecret = GenerateClientSecret();
if (customId == null)
customId = GenerateCustomId();
if (newUser)
dyn.EncryptedRequest = EncryptCustomIdLoginToken(customId, clientSecret);
else
dyn.EncryptedRequest = null;
dyn.InfoRequestParameters = new ExpandoObject();
dyn.InfoRequestParameters.GetCharacterInventories = false;
dyn.InfoRequestParameters.GetCharacterList = false;
dyn.InfoRequestParameters.GetPlayerProfile = true;
dyn.InfoRequestParameters.GetPlayerStatistics = false;
dyn.InfoRequestParameters.GetTitleData = false;
dyn.InfoRequestParameters.GetUserAccountInfo = true;
dyn.InfoRequestParameters.GetUserData = false;
dyn.InfoRequestParameters.GetUserInventory = false;
dyn.InfoRequestParameters.GetUserReadOnlyData = false;
dyn.InfoRequestParameters.PlayerStatisticNames = null;
dyn.InfoRequestParameters.ProfileConstraints = null;
dyn.InfoRequestParameters.TitleDataKeys = null;
dyn.InfoRequestParameters.UserDataKeys = null;
dyn.InfoRequestParameters.UserReadOnlyDataKeys = null;
dyn.PlayerSecret = null;
dyn.TitleId = TITLE_ID;
dynamic resp = POST(dyn, "/Client/LoginWithCustomID", newUser ? null : clientSecret, true);
Config.WriteConfValue("CustomId", customId);
Config.WriteConfValue("ClientSecret", clientSecret);
ENTITY_TOKEN = resp.EntityToken.EntityToken.ToString();
ENTITY_ID = resp.PlayFabId.ToString();
ENTITY_TYPE = "master_player_account";
return ENTITY_TOKEN;
}
public static string EncryptRequest(string plaintext)
{
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportCspBlob(PUBLIC_KEY);
byte[] bytesToEncrypt = Encoding.UTF8.GetBytes(plaintext);
byte[] encryptedBytes = rsa.Encrypt(bytesToEncrypt, false);
return Convert.ToBase64String(encryptedBytes);
}
}
public static string PullEntityTokenOutOfMyAss()
{
if (Config.GetConfValue("CustomId") == null && Config.GetConfValue("ClientSecret") == null)
{
GetPublicKeyAndMicrosoftTakesABigL();
LoginWithCustomId();
return RefreshEntityTokenBullshit();
}
else
{
string customId = Config.GetConfValue("CustomId");
string clientSecret = Config.GetConfValue("ClientSecret");
LoginWithCustomId(false, customId, clientSecret);
return RefreshEntityTokenBullshit();
}
}
}
}

View File

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{6EDC5573-14BE-429A-B663-60E4AE604079}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>PremiumPackInstaller</RootNamespace>
<AssemblyName>PremiumPackInstaller</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>1</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>skins.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<ManifestCertificateThumbprint>5D7635155E697A9AC53D2F49356F5D5FF9607505</ManifestCertificateThumbprint>
</PropertyGroup>
<PropertyGroup>
<ManifestKeyFile>PremiumPackInstaller_TemporaryKey.pfx</ManifestKeyFile>
</PropertyGroup>
<PropertyGroup>
<GenerateManifests>true</GenerateManifests>
</PropertyGroup>
<PropertyGroup>
<SignManifests>true</SignManifests>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="PlayFab\Config.cs" />
<Compile Include="MainWindow.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainWindow.Designer.cs">
<DependentUpon>MainWindow.cs</DependentUpon>
</Compile>
<Compile Include="PlayFab\McClient.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="PlayFab\PlayFab.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="MainWindow.resx">
<DependentUpon>MainWindow.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="packages.config" />
<None Include="PremiumPackInstaller_TemporaryKey.pfx" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\Li\Documents\git\McTools\McCrypt\LibMcCrypt.csproj">
<Project>{4BEF6F52-6545-4BB9-8053-50335A1C6789}</Project>
<Name>LibMcCrypt</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="skins.ico" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.8">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.8 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishUrlHistory />
<InstallUrlHistory />
<SupportUrlHistory />
<UpdateUrlHistory />
<BootstrapperUrlHistory />
<ErrorReportUrlHistory />
<FallbackCulture>en-US</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,19 @@
using System;
using System.Windows.Forms;
namespace PremiumPackInstaller
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainWindow());
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Premium Packs Installer")]
[assembly: AssemblyDescription("Allows you to replace ads in skin pack list with any skin pack you want.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Li")]
[assembly: AssemblyProduct("Premium Packs Installer")]
[assembly: AssemblyCopyright("Public Domain 2022")]
[assembly: AssemblyTrademark("Trans Rights")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("6edc5573-14be-429a-b663-60e4ae604079")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace PremiumPackInstaller.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PremiumPackInstaller.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace PremiumPackInstaller.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net48" />
</packages>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2007 James Newton-King
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB