Upload src

This commit is contained in:
Li 2023-05-09 02:17:44 +12:00
parent df72a81caf
commit 11bc128354
43 changed files with 76263 additions and 9 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
*.suo
*/bin/*
*/obj/*
.vs/*

View File

@ -1,10 +1,5 @@
This is free and unencumbered software released into the public domain.
All code is hereby entered into the Public Domain
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.
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 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.
For more information, please refer to <http://unlicense.org/>
- Abolish Interlectual Property -

73
McCrypt/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;
}
}
}
}
}

302
McCrypt/Keys.cs Normal file
View File

@ -0,0 +1,302 @@
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[versionkey.Length];
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 padLastTileAccountId(string lastTitleAccountId)
{
StringBuilder deriveText = new StringBuilder();
for (int i = 0; i < 32; i++)
deriveText.Append(lastTitleAccountId[i % lastTitleAccountId.Length]);
return deriveText.ToString();
}
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 = padLastTileAccountId(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;
}
}
}

59
McCrypt/LibMcCrypt.csproj Normal file
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
McCrypt/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
McCrypt/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
McCrypt/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();
}
}
}

4
McCrypt/packages.config Normal file
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>

6
McDecryptor/App.config Normal file
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>

199
McDecryptor/Config.cs Normal file
View File

@ -0,0 +1,199 @@
using McDecryptor.Properties;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace McDecryptor
{
internal class Config
{
public static string LocalAppdata = Environment.GetEnvironmentVariable("LOCALAPPDATA");
public static string RoamingAppdata = Environment.GetEnvironmentVariable("APPDATA");
public static string ApplicationDirectory;
private static List<string> searchFolders = new List<string>();
private static List<string> searchModules = new List<string>();
public static string MinecraftFolder;
public static string LocalState;
public static string LocalCache;
public static string KeysDbPath;
public static string PremiumCache;
public static string ServerPackCache;
public static string RealmsPremiumCache;
public static string OptionsTxt;
public static string OutFolder;
public static bool CrackPacks;
public static bool ZipPacks;
public static string[] SearchFolders
{
get
{
return searchFolders.ToArray();
}
}
public static string[] SearchModules
{
get
{
return searchModules.ToArray();
}
}
private static void rebaseSearchFolders()
{
searchFolders.Clear();
searchFolders.Add(ApplicationDirectory);
searchFolders.Add(PremiumCache);
searchFolders.Add(ServerPackCache);
searchFolders.Add(RealmsPremiumCache);
searchModules.Clear();
searchModules.Add("resource_packs");
searchModules.Add("skin_packs");
searchModules.Add("world_templates");
searchModules.Add("persona");
searchModules.Add("behaviour_packs");
searchModules.Add("resource");
}
private static void rebaseLocalData()
{
OutFolder = Path.Combine(LocalState, "games", "com.mojang");
PremiumCache = Path.Combine(LocalState, "premium_cache");
ServerPackCache = Path.Combine(LocalCache, "packcache");
RealmsPremiumCache = Path.Combine(LocalCache, "premiumcache");
rebaseSearchFolders();
}
private static void rebaseAll()
{
LocalState = Path.Combine(MinecraftFolder, "LocalState");
LocalCache = Path.Combine(MinecraftFolder, "LocalCache", "minecraftpe");
rebaseLocalData();
}
private static string resolve(string str)
{
str = str.Trim();
str = str.Replace("$LOCALAPPDATA", LocalAppdata);
str = str.Replace("$APPDATA", RoamingAppdata);
str = str.Replace("$MCDIR", MinecraftFolder);
str = str.Replace("$EXECDIR", ApplicationDirectory);
str = str.Replace("$LOCALSTATE", LocalState);
str = str.Replace("$LOCALCACHE", LocalCache);
str = str.Replace("$PREMIUMCACHE", PremiumCache);
str = str.Replace("$SERVERPACKCACHE", ServerPackCache);
str = str.Replace("$REALMSPREMIUMCACHE", RealmsPremiumCache);
str = str.Replace("$OUTFOLDER", OutFolder);
return str;
}
public static void Init()
{
CrackPacks = true;
ZipPacks = false;
ApplicationDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
KeysDbPath = Path.Combine(ApplicationDirectory, "keys.db");
MinecraftFolder = Path.Combine(LocalAppdata, "Packages", "Microsoft.MinecraftUWP_8wekyb3d8bbwe");
rebaseAll();
}
public static void ReadConfig(string configFile)
{
if (File.Exists(configFile))
{
string[] configLines = File.ReadAllLines(configFile);
foreach(string line in configLines)
{
if (line.Trim().StartsWith("#"))
continue;
if (!line.Contains(":"))
continue;
string[] keyvalpair = line.Trim().Split(':');
if (keyvalpair.Length < 2)
continue;
switch(keyvalpair[0])
{
case "MinecraftFolder":
MinecraftFolder = resolve(keyvalpair[1]);
rebaseAll();
break;
case "LocalState":
LocalState = resolve(keyvalpair[1]);
rebaseLocalData();
break;
case "LocalCache":
LocalCache = resolve(keyvalpair[1]);
rebaseLocalData();
break;
case "PremiumCache":
PremiumCache = resolve(keyvalpair[1]);
rebaseSearchFolders();
break;
case "ServerPackCache":
ServerPackCache = resolve(keyvalpair[1]);
rebaseSearchFolders();
break;
case "RealmsPremiumCache":
RealmsPremiumCache = resolve(keyvalpair[1]);
rebaseSearchFolders();
break;
case "OutputFolder":
OutFolder = resolve(keyvalpair[1]);
break;
case "KeysDb":
KeysDbPath = resolve(keyvalpair[1]);
break;
case "OptionsTxt":
OptionsTxt = resolve(keyvalpair[1]);
break;
case "AdditionalSearchDir":
searchFolders.Add(resolve(keyvalpair[1]));
break;
case "AdditionalModuleDir":
searchModules.Add(resolve(keyvalpair[1]));
break;
case "CrackThePacks":
CrackPacks = (resolve(keyvalpair[1]).ToLower() == "yes");
break;
case "ZipThePacks":
ZipPacks = (resolve(keyvalpair[1]).ToLower() == "yes");
break;
}
}
}
else
{
File.WriteAllBytes(configFile, Resources.DefaultConfigFile);
ReadConfig(configFile);
}
}
}
}

View File

@ -0,0 +1,81 @@
<?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>{3E522B6D-5247-4F69-9DAE-DD0385DAE88E}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>McDecryptor</RootNamespace>
<AssemblyName>McDecryptor</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</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>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>illager.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<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="Config.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="default.cfg" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\McCrypt\LibMcCrypt.csproj">
<Project>{4bef6f52-6545-4bb9-8053-50335a1c6789}</Project>
<Name>LibMcCrypt</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Content Include="illager.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

245
McDecryptor/Program.cs Normal file
View File

@ -0,0 +1,245 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Threading;
using McCrypt;
namespace McDecryptor
{
class Program
{
public struct ContentListing
{
public string Path;
public string Type;
public string Name;
public int Id;
}
public static string EscapeFilename(string filename)
{
return filename.Replace("/", "_").Replace("\\", "_").Replace(":", "_").Replace("?", "_").Replace("*", "_").Replace("<", "_").Replace(">", "_").Replace("|", "_").Replace("\"", "_");
}
static void CopyFile(string src, string dst)
{
using (FileStream fs = File.OpenRead(src))
{
using(FileStream wfd = File.OpenWrite(dst))
{
fs.CopyTo(wfd);
}
}
}
static void CopyDirectory(string sourcePath, string targetPath)
{
List<Thread> threads = new List<Thread>();
//Now Create all of the directories
foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
{
Thread thrd = new Thread(() =>
{
Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPath));
});
thrd.Priority = ThreadPriority.Highest;
thrd.Start();
threads.Add(thrd);
}
foreach (Thread t in threads.ToArray())
t.Join();
threads.Clear();
//Copy all the files & Replaces any files with the same name
foreach (string newPath in Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories))
{
Thread thrd = new Thread(() =>
{
CopyFile(newPath, newPath.Replace(sourcePath, targetPath));
});
thrd.Priority = ThreadPriority.Highest;
thrd.Start();
threads.Add(thrd);
}
foreach (Thread t in threads.ToArray())
t.Join();
threads.Clear();
}
static void Main(string[] args)
{
Console.WriteLine("-- McDecryptor --");
Console.WriteLine("Reading Configuration File...");
Config.Init();
Directory.SetCurrentDirectory(Config.ApplicationDirectory);
Config.ReadConfig("McDecryptor.cfg");
Keys.KeyDbFile = Config.KeysDbPath;
if (File.Exists(Config.KeysDbPath))
{
Console.WriteLine("Parsing Key Database File...");
Keys.ReadKeysDb(Config.KeysDbPath);
}
if (File.Exists(Config.OptionsTxt))
{
Keys.ReadOptionsTxt(Config.OptionsTxt);
}
Console.WriteLine("Minecraft Folder: " + Config.MinecraftFolder);
if (Directory.Exists(Config.MinecraftFolder))
{
string[] entFiles = Directory.GetFiles(Config.LocalState, "*.ent", SearchOption.TopDirectoryOnly);
foreach (string entFile in entFiles)
{
Console.WriteLine("Reading Entitlement File: " + Path.GetFileName(entFile));
Keys.ReadEntitlementFile(entFile);
}
}
string[] entFilesWorkDir = Directory.GetFiles(Config.ApplicationDirectory, "*.ent", SearchOption.TopDirectoryOnly);
foreach (string entFile in entFilesWorkDir)
{
Console.WriteLine("Reading Entitlement File: " + Path.GetFileName(entFile));
Keys.ReadEntitlementFile(entFile);
}
List<ContentListing> premiumContents = new List<ContentListing>();
Console.WriteLine("\n\n");
Console.WriteLine("Select what to decrypt: ");
int total = 1;
foreach (string searchFolder in Config.SearchFolders)
{
foreach(string searchModule in Config.SearchModules)
{
string moduleFolder = Path.Combine(searchFolder, searchModule);
if (Directory.Exists(moduleFolder))
{
foreach (string moduleItem in Directory.GetDirectories(moduleFolder, "*", SearchOption.TopDirectoryOnly))
{
ContentListing cList = new ContentListing();
cList.Name = Manifest.ReadName(Path.Combine(moduleItem, "manifest.json"));
cList.Type = searchModule;
cList.Id = total;
cList.Path = moduleItem;
premiumContents.Add(cList);
Console.WriteLine(cList.Id.ToString() + ") (" + cList.Type + ") " + cList.Name);
total++;
}
}
}
}
Console.WriteLine("Select multiple (seperated by ',') or write \"ALL\"");
List<int> toDecrypt = new List<int>();
while (true)
{
Console.Write("Which do you want to decrypt? ");
try
{
string readText = Console.ReadLine();
if (readText.ToUpper() == "ALL")
{
for(int i = 0; i < total-1; i++)
toDecrypt.Add(i);
break;
}
string[] entries = readText.Split(',');
foreach(string entry in entries) {
int tdc = Convert.ToInt32(entry.Trim())-1;
if (tdc < 0 || tdc >= total)
continue;
toDecrypt.Add(tdc);
}
break;
}
catch (Exception) { }
}
foreach (int decryptMe in toDecrypt.ToArray())
{
ContentListing cListing = premiumContents.ToArray()[decryptMe];
string outFolder = Path.Combine(Config.OutFolder, cListing.Type, EscapeFilename(cListing.Name));
int counter = 1;
string ogOutFolder = outFolder;
while (Directory.Exists(outFolder))
{
outFolder = ogOutFolder + "_" + counter.ToString();
counter++;
}
new Thread(() =>
{
Console.WriteLine("Decrypting: " + cListing.Name);
Directory.CreateDirectory(outFolder);
CopyDirectory(cListing.Path, outFolder);
try
{
string levelDatFile = Path.Combine(outFolder, "level.dat");
string skinsJsonFile = Path.Combine(outFolder, "skins.json");
string oldSchoolZipe = Path.Combine(outFolder, "content.zipe");
Marketplace.DecryptContents(outFolder);
if (Config.CrackPacks)
{
if (File.Exists(oldSchoolZipe))
Marketplace.CrackZipe(oldSchoolZipe);
if (File.Exists(levelDatFile))
Marketplace.CrackLevelDat(levelDatFile);
if (File.Exists(skinsJsonFile))
Marketplace.CrackSkinsJson(skinsJsonFile);
}
if (Config.ZipPacks)
{
string ext = "";
if (File.Exists(levelDatFile))
ext += ".mctemplate";
else
ext += ".mcpack";
ZipFile.CreateFromDirectory(outFolder, outFolder + ext, CompressionLevel.NoCompression, false);
Directory.Delete(outFolder, true);
}
}
catch (Exception)
{
Console.Error.WriteLine("Failed to decrypt: " + cListing.Name);
Directory.Delete(outFolder, true);
}
}).Start();
}
}
}
}

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("McDecryptor")]
[assembly: AssemblyDescription("Minecraft Marketplace Decryptor")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("The Pillager Bay")]
[assembly: AssemblyProduct("McDecryptor")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyTrademark("The Pillager Bay")]
[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("3e522b6d-5247-4f69-9dae-dd0385dae88e")]
// 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,73 @@
//------------------------------------------------------------------------------
// <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 McDecryptor.Properties {
using System;
/// <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", "17.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 (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("McDecryptor.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;
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] DefaultConfigFile {
get {
object obj = ResourceManager.GetObject("DefaultConfigFile", resourceCulture);
return ((byte[])(obj));
}
}
}
}

View File

@ -0,0 +1,124 @@
<?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.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="DefaultConfigFile" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\default.cfg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

57
McDecryptor/default.cfg Normal file
View File

@ -0,0 +1,57 @@
# The Pillager Bay's McDecryptor Configuration File
# The path at which Minecraft keeps its resource packs and other data
# May need to change if your using a different version of bedrock (eg education edition)
# Otherwise this default is probably fine
MinecraftFolder: $LOCALAPPDATA\Packages\Microsoft.MinecraftUWP_8wekyb3d8bbwe
KeysDb: $EXECDIR\keys.db
# LocalState and LocalCache folders
# These folders only exist in UWP Versions of Bedrock
# On WIN32 versions it may be under "internalStorage"
LocalState: $MCDIR\LocalState
LocalCache: $MCDIR\LocalCache\McDecryptor
# Path to options.txt
# needed to decrypt .ent files since beta 1.19.
OptionsTxt: $LOCALSTATE\games\com.mojang\minecraftpe\options.txt
# Locations of Premium Cache (marketplace contents)
# Server Pack Cache (server resource packs)
# Realms Premium Cache (realms resource packs)
PremiumCache: $LOCALSTATE\premium_cache
ServerPackCache: $LOCALCACHE\packcache
RealmsPremiumCache: $LOCALCACHE\premiumcache
# Should it crack the packs (change skin packs to free, remove prid from worlds)
CrackThePacks: yes
# Should i zip packs to .mcpack/.mctemplate
ZipThePacks: no
# Where to output the decrypted data, (deafult to install into the game)
OutputFolder: $LOCALSTATE\games\com.mojang
# You can also add more search locations ontop of the default ones.
# Do this by using AdditionalSearchDir and a path, it will look there
# for packs.
# You can use AdditionalModuleDir to add new folders to look for encrypted data inside of the search folders
# normally it'll just look inside say "resource_packs" "skin_packs" "persona" etc
#AdditionalSearchDir: C:\Some\Folder\With\ResourcePacks
#AdditionalSearchDir: C:\Some\Other\Folder\With\ResourcePacks
#AdditionalModuleDir: worlds
# All Macros
# $LOCALAPPDATA - Local Application Data folder
# $APPDATA - Roaming Application Data folder
# $MCDIR - Minecraft Install Folder
# $EXECDIR - Folder the program is running in
# $LOCALSTATE - LocalState Folder
# $LOCALCACHE - LocalCache Folder.
# $PREMIUMCACHE - Premium Cache Folder
# $SERVERPACKCACHE - Server Pack Cache Folder
# $REALMSPREMIUMCACHE - Realms Pack Cache Folder
# $OUTFOLDER - Output folder

BIN
McDecryptor/illager.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

6
McEncryptor/App.config Normal file
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,64 @@
<?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>{E3B51165-8EE7-4DEE-AD04-CDF1089371A7}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>McEncryptor</RootNamespace>
<AssemblyName>McEncryptor</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</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>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>illager.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\McCrypt\LibMcCrypt.csproj">
<Project>{4bef6f52-6545-4bb9-8053-50335a1c6789}</Project>
<Name>LibMcCrypt</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="illager.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

46
McEncryptor/Program.cs Normal file
View File

@ -0,0 +1,46 @@
using McCrypt;
using System;
using System.IO;
using System.Reflection;
using System.Text;
namespace McEncryptor
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("-- McEncryptor --");
string runningInFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string keysDbFile = Path.Combine(runningInFolder, "keys.db");
Directory.SetCurrentDirectory(runningInFolder);
if (File.Exists(keysDbFile))
{
Console.WriteLine("Parsing Key Cache File. (keys.db)");
Keys.ReadKeysDb(keysDbFile);
}
Console.WriteLine("Path to pack file: ");
string packPath = Console.ReadLine();
string uuid = Manifest.ReadUUID(Path.Combine(packPath, "manifest.json"));
byte[] ckey = Keys.LookupKey(uuid);
string contentKey = "s5s5ejuDru4uchuF2drUFuthaspAbepE";
if (ckey == null)
ckey = Encoding.UTF8.GetBytes(contentKey);
if (ckey != null)
contentKey = Encoding.UTF8.GetString(ckey);
Console.WriteLine("uuid: " + uuid);
Manifest.SignManifest(packPath);
Marketplace.EncryptContents(packPath, uuid, contentKey);
}
}
}

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("McEncryptor")]
[assembly: AssemblyDescription("Marketplace Contents Encryptor")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("The Pillager Bay")]
[assembly: AssemblyProduct("McEncryptor")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyTrademark("The Pillager Bay")]
[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("e3b51165-8ee7-4dee-ad04-cdf1089371a7")]
// 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")]

BIN
McEncryptor/illager.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

43
McTools.sln Normal file
View File

@ -0,0 +1,43 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32120.378
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "McDecryptor", "McDecryptor\McDecryptor.csproj", "{3E522B6D-5247-4F69-9DAE-DD0385DAE88E}"
ProjectSection(ProjectDependencies) = postProject
{4BEF6F52-6545-4BB9-8053-50335A1C6789} = {4BEF6F52-6545-4BB9-8053-50335A1C6789}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibMcCrypt", "McCrypt\LibMcCrypt.csproj", "{4BEF6F52-6545-4BB9-8053-50335A1C6789}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "McEncryptor", "McEncryptor\McEncryptor.csproj", "{E3B51165-8EE7-4DEE-AD04-CDF1089371A7}"
ProjectSection(ProjectDependencies) = postProject
{4BEF6F52-6545-4BB9-8053-50335A1C6789} = {4BEF6F52-6545-4BB9-8053-50335A1C6789}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3E522B6D-5247-4F69-9DAE-DD0385DAE88E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E522B6D-5247-4F69-9DAE-DD0385DAE88E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E522B6D-5247-4F69-9DAE-DD0385DAE88E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E522B6D-5247-4F69-9DAE-DD0385DAE88E}.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
{E3B51165-8EE7-4DEE-AD04-CDF1089371A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E3B51165-8EE7-4DEE-AD04-CDF1089371A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E3B51165-8EE7-4DEE-AD04-CDF1089371A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E3B51165-8EE7-4DEE-AD04-CDF1089371A7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {225D8EE0-BADA-4233-BDC1-A27217CD52F9}
EndGlobalSection
EndGlobal

View File

@ -1,3 +1,3 @@
# McDecryptor
# McUtils
Minecraft Marketplace Content Decryptor.
Utilities to decrypt Minecraft Marketplace Contents

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