mirror of
https://silica.codes/BedrockReverse/McTools.git
synced 2025-04-17 10:21:30 +12:00
Compare commits
No commits in common. "main" and "1.0" have entirely different histories.
17 changed files with 181 additions and 661 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,6 +1,4 @@
|
||||||
*.suo
|
*.suo
|
||||||
*/bin/*
|
*/bin/*
|
||||||
*/obj/*
|
*/obj/*
|
||||||
.vs/*
|
.vs/*
|
||||||
McEncryptor/.vs/*
|
|
||||||
McDecryptor/.vs/*
|
|
5
LICENSE
Normal file
5
LICENSE
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
All code is hereby entered into the Public Domain
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- Abolish Interlectual Property -
|
|
@ -1 +0,0 @@
|
||||||
{"RootPath":"C:\\Users\\Li\\Desktop\\git\\McTools\\McCrypt","ProjectFileName":"LibMcCrypt.csproj","Configuration":"Debug|AnyCPU","FrameworkPath":"","Sources":[{"SourceFile":"Crypto.cs"},{"SourceFile":"Keys.cs"},{"SourceFile":"Manifest.cs"},{"SourceFile":"Marketplace.cs"},{"SourceFile":"Properties\\AssemblyInfo.cs"},{"SourceFile":"Utils.cs"},{"SourceFile":"obj\\Debug\\.NETFramework,Version=v4.8.AssemblyAttributes.cs"}],"References":[{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\Microsoft.CSharp.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\mscorlib.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Users\\Li\\Desktop\\git\\McTools\\packages\\Newtonsoft.Json.13.0.1\\lib\\net45\\Newtonsoft.Json.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Core.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Data.DataSetExtensions.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Data.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.IO.Compression.FileSystem.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Net.Http.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Xml.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Xml.Linq.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""}],"Analyzers":[],"Outputs":[{"OutputItemFullPath":"C:\\Users\\Li\\Desktop\\git\\McTools\\McCrypt\\bin\\Debug\\LibMcCrypt.dll","OutputItemRelativePath":"LibMcCrypt.dll"},{"OutputItemFullPath":"C:\\Users\\Li\\Desktop\\git\\McTools\\McCrypt\\bin\\Debug\\LibMcCrypt.pdb","OutputItemRelativePath":"LibMcCrypt.pdb"}],"CopyToOutputEntries":[]}
|
|
102
McCrypt/Keys.cs
102
McCrypt/Keys.cs
|
@ -1,11 +1,9 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace McCrypt
|
namespace McCrypt
|
||||||
{
|
{
|
||||||
|
@ -131,42 +129,15 @@ namespace McCrypt
|
||||||
|
|
||||||
contentList.Add(content);
|
contentList.Add(content);
|
||||||
}
|
}
|
||||||
private static void handleEntitlements(dynamic entitlements, byte[] userKey)
|
|
||||||
|
private static void readReceipt(string receiptData)
|
||||||
{
|
{
|
||||||
|
dynamic recData = Utils.JsonDecodeCloserToMinecraft(receiptData);
|
||||||
// Derive content keys
|
string userId = recData.Receipt.EntityId;
|
||||||
int totalEntitlements = entitlements.Count;
|
|
||||||
|
|
||||||
for (int i = 0; i < totalEntitlements; i++)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string friendlyId = entitlements[i].FriendlyId;
|
|
||||||
if (friendlyId == null)
|
|
||||||
friendlyId = entitlements[i].PackId;
|
|
||||||
|
|
||||||
if (friendlyId == null) continue;
|
|
||||||
|
|
||||||
string contentKeyB64 = entitlements[i].ContentKey;
|
|
||||||
if (contentKeyB64 == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
byte[] contentKey = Utils.ForceDecodeBase64(contentKeyB64);
|
|
||||||
byte[] realContentKey = deriveContentKey(userKey, contentKey);
|
|
||||||
|
|
||||||
AddKey(friendlyId, realContentKey);
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception) { continue; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static void readInnerReceipt(dynamic recData)
|
|
||||||
{
|
|
||||||
string userId = recData.EntityId;
|
|
||||||
string deviceId = "";
|
string deviceId = "";
|
||||||
|
|
||||||
if (recData.ReceiptData != null)
|
if (recData.Receipt.ReceiptData != null)
|
||||||
deviceId = recData.ReceiptData.DeviceId;
|
deviceId = recData.Receipt.ReceiptData.DeviceId;
|
||||||
|
|
||||||
if (deviceId == "" || deviceId == null)
|
if (deviceId == "" || deviceId == null)
|
||||||
deviceId = lastDeviceId;
|
deviceId = lastDeviceId;
|
||||||
|
@ -178,19 +149,27 @@ namespace McCrypt
|
||||||
|
|
||||||
byte[] userKey = deriveUserKey(userId, deviceId);
|
byte[] userKey = deriveUserKey(userId, deviceId);
|
||||||
|
|
||||||
if (recData.Entitlements != null)
|
// Derive content keys
|
||||||
handleEntitlements(recData.Entitlements, userKey);
|
int totalEntitlements = recData.Receipt.Entitlements.Count;
|
||||||
else
|
|
||||||
handleEntitlements(recData.EntitlementReceipts, userKey);
|
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; }
|
||||||
|
}
|
||||||
|
|
||||||
private static void readReceipt(string receiptData)
|
|
||||||
{
|
|
||||||
dynamic recData = Utils.JsonDecodeCloserToMinecraft(receiptData);
|
|
||||||
if (recData.Receipt != null)
|
|
||||||
readInnerReceipt(recData.Receipt);
|
|
||||||
else
|
|
||||||
readInnerReceipt(recData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ReadOptionsTxt(string optionsTxtPath)
|
public static void ReadOptionsTxt(string optionsTxtPath)
|
||||||
|
@ -267,36 +246,29 @@ namespace McCrypt
|
||||||
}
|
}
|
||||||
catch (Exception) { return; }
|
catch (Exception) { return; }
|
||||||
|
|
||||||
string receiptB64 = entData.GetValue("Receipt", StringComparison.InvariantCultureIgnoreCase);
|
string receiptB64 = entData.Receipt;
|
||||||
|
|
||||||
if (receiptB64 == null)
|
if (receiptB64 == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string receiptData = null;
|
|
||||||
if (receiptB64.Split('.').Length <= 1)
|
if (receiptB64.Split('.').Length <= 1)
|
||||||
receiptData = Encoding.UTF8.GetString(Utils.ForceDecodeBase64(receiptB64));
|
|
||||||
else
|
|
||||||
receiptData = Encoding.UTF8.GetString(Utils.ForceDecodeBase64(receiptB64.Split('.')[1]));
|
|
||||||
if (receiptData == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
string receiptData = Encoding.UTF8.GetString(Utils.ForceDecodeBase64(receiptB64.Split('.')[1]));
|
||||||
readReceipt(receiptData);
|
readReceipt(receiptData);
|
||||||
if(entData.Items != null)
|
int totalItems = entData.Items.Count;
|
||||||
|
for (int i = 0; i < totalItems; i++)
|
||||||
{
|
{
|
||||||
int totalItems = entData.Items.Count;
|
string b64Data = entData.Items[i].Receipt;
|
||||||
for (int i = 0; i < totalItems; i++)
|
|
||||||
{
|
|
||||||
string b64Data = entData.Items[i].Receipt;
|
|
||||||
|
|
||||||
if (b64Data == null)
|
if (b64Data == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (b64Data.Split('.').Length <= 1)
|
if (b64Data.Split('.').Length <= 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
string recept = Encoding.UTF8.GetString(Utils.ForceDecodeBase64(b64Data.Split('.')[1]));
|
string recept = Encoding.UTF8.GetString(Utils.ForceDecodeBase64(b64Data.Split('.')[1]));
|
||||||
readReceipt(recept);
|
readReceipt(recept);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static void ReadKeysDb(string keyFile)
|
public static void ReadKeysDb(string keyFile)
|
||||||
|
|
|
@ -45,30 +45,15 @@
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Config.cs" />
|
|
||||||
<Compile Include="Crypto.cs" />
|
<Compile Include="Crypto.cs" />
|
||||||
<Compile Include="Keys.cs" />
|
<Compile Include="Keys.cs" />
|
||||||
<Compile Include="Manifest.cs" />
|
<Compile Include="Manifest.cs" />
|
||||||
<Compile Include="Marketplace.cs" />
|
<Compile Include="Marketplace.cs" />
|
||||||
<Compile Include="PackData\PEntry.cs" />
|
|
||||||
<Compile Include="PackData\PReader.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Properties\Resources.Designer.cs">
|
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
|
||||||
<AutoGen>True</AutoGen>
|
|
||||||
<DesignTime>True</DesignTime>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Utils.cs" />
|
<Compile Include="Utils.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="default.cfg" />
|
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Include="Properties\Resources.resx">
|
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
|
||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
|
||||||
</EmbeddedResource>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -4,7 +4,6 @@ using System.Linq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace McCrypt
|
namespace McCrypt
|
||||||
{
|
{
|
||||||
|
@ -44,66 +43,6 @@ namespace McCrypt
|
||||||
string signaturesJsonFile = Path.Combine(basePath, "signatures.json");
|
string signaturesJsonFile = Path.Combine(basePath, "signatures.json");
|
||||||
File.WriteAllText(signaturesJsonFile, signatureJson);
|
File.WriteAllText(signaturesJsonFile, signatureJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ReadType(string manifestFile)
|
|
||||||
{
|
|
||||||
string manifestStr = File.ReadAllText(manifestFile);
|
|
||||||
dynamic manifestData = JsonConvert.DeserializeObject(manifestStr);
|
|
||||||
if(manifestData.modules != null)
|
|
||||||
{
|
|
||||||
if(manifestData.modules.Count >= 1)
|
|
||||||
{
|
|
||||||
return manifestData.modules[0].type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Path.GetFileName(Path.GetDirectoryName(Path.GetDirectoryName(manifestFile)));
|
|
||||||
}
|
|
||||||
public static string ReadProductType(string manifestFile)
|
|
||||||
{
|
|
||||||
string manifestStr = File.ReadAllText(manifestFile);
|
|
||||||
dynamic manifestData = JsonConvert.DeserializeObject(manifestStr);
|
|
||||||
if (manifestData.metadata != null)
|
|
||||||
{
|
|
||||||
if (manifestData.metadata.product_type != null)
|
|
||||||
{
|
|
||||||
return manifestData.metadata.product_type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string[] ReadWorldPackList(string packListFile)
|
|
||||||
{
|
|
||||||
List<string> depUuidList = new List<string>();
|
|
||||||
string packStr = File.ReadAllText(packListFile);
|
|
||||||
dynamic packListData = JsonConvert.DeserializeObject(packStr);
|
|
||||||
|
|
||||||
for (int i = 0; i < packListData.Count; i++)
|
|
||||||
{
|
|
||||||
dynamic packData = packListData[i];
|
|
||||||
if(packData.pack_id != null) depUuidList.Add(packData.pack_id.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return depUuidList.ToArray();
|
|
||||||
}
|
|
||||||
public static string[] ReadDependancyUuids(string manifestFile)
|
|
||||||
{
|
|
||||||
List<string> depUuidList = new List<string>();
|
|
||||||
string manifestStr = File.ReadAllText(manifestFile);
|
|
||||||
dynamic manifestData = JsonConvert.DeserializeObject(manifestStr);
|
|
||||||
if (manifestData.dependencies != null)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < manifestData.dependencies.Count; i++)
|
|
||||||
{
|
|
||||||
dynamic manifestDependancy = manifestData.dependencies[i];
|
|
||||||
if(manifestDependancy.uuid != null)
|
|
||||||
{
|
|
||||||
depUuidList.Add(manifestDependancy.uuid.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return depUuidList.ToArray();
|
|
||||||
}
|
|
||||||
public static string ReadName(string manifestFile)
|
public static string ReadName(string manifestFile)
|
||||||
{
|
{
|
||||||
string defaultName = Path.GetFileName(Path.GetDirectoryName(manifestFile));
|
string defaultName = Path.GetFileName(Path.GetDirectoryName(manifestFile));
|
||||||
|
|
|
@ -12,6 +12,8 @@ namespace McCrypt
|
||||||
public class Marketplace
|
public class Marketplace
|
||||||
{
|
{
|
||||||
// Hi mojang <3
|
// 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 static string[] dontEncrypt = new string[] { "manifest.json", "contents.json", "texts", "pack_icon.png", "ui"};
|
||||||
private struct contentsJson
|
private struct contentsJson
|
||||||
|
@ -56,37 +58,6 @@ namespace McCrypt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if prid tag is present in a world
|
|
||||||
// can be used to check if its encrypted.
|
|
||||||
public static bool IsLevelEncrypted(string levelPath)
|
|
||||||
{
|
|
||||||
string ldbPath = Path.Combine(levelPath, "db");
|
|
||||||
if (!Directory.Exists(ldbPath)) return false;
|
|
||||||
|
|
||||||
string[] ldbFiles = Directory.GetFiles(ldbPath, "*.ldb", SearchOption.TopDirectoryOnly);
|
|
||||||
foreach (string ldbFile in ldbFiles)
|
|
||||||
{
|
|
||||||
string file = Path.Combine(ldbPath, ldbFile);
|
|
||||||
using (FileStream fs = File.OpenRead(file)) // Open file for reading
|
|
||||||
{
|
|
||||||
using (BinaryReader br = new BinaryReader(fs)) // Create a binary reader overlay of it
|
|
||||||
{
|
|
||||||
|
|
||||||
if (fs.Length <= 0x10)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uint version = br.ReadUInt32();
|
|
||||||
uint magic = br.ReadUInt32();
|
|
||||||
UInt64 unk = br.ReadUInt64();
|
|
||||||
|
|
||||||
if (version == 0 && magic == 0x9bcfb9fc) // is valid header?
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change all skins type to "free" instead of "paid"
|
// Change all skins type to "free" instead of "paid"
|
||||||
// This makes the game let you actually apply them
|
// This makes the game let you actually apply them
|
||||||
public static void CrackSkinsJson(string skinsJsonFile)
|
public static void CrackSkinsJson(string skinsJsonFile)
|
||||||
|
@ -189,53 +160,54 @@ namespace McCrypt
|
||||||
// For the file types that have a header-
|
// For the file types that have a header-
|
||||||
private static byte[] worldOrContentsJsonDecrypt(string file)
|
private static byte[] worldOrContentsJsonDecrypt(string file)
|
||||||
{
|
{
|
||||||
using (FileStream fs = File.OpenRead(file))
|
FileStream fs = File.OpenRead(file); // Open file for reading
|
||||||
{ // Open file for reading
|
BinaryReader br = new BinaryReader(fs); // Create a binary reader overlay of it
|
||||||
using (BinaryReader br = new BinaryReader(fs))
|
|
||||||
{
|
|
||||||
// Create a binary reader overlay of it
|
|
||||||
|
|
||||||
if (fs.Length <= 0)
|
if (fs.Length <= 0)
|
||||||
return new byte[0] { };
|
{
|
||||||
|
fs.Dispose();
|
||||||
|
return new byte[0] { };
|
||||||
|
}
|
||||||
|
|
||||||
uint version = br.ReadUInt32();
|
uint version = br.ReadUInt32();
|
||||||
uint magic = br.ReadUInt32();
|
uint magic = br.ReadUInt32();
|
||||||
UInt64 unk = br.ReadUInt64();
|
UInt64 unk = br.ReadUInt64();
|
||||||
|
|
||||||
if (version == 0 && magic == 0x9bcfb9fc) // is valid header?
|
if (version == 0 && magic == 0x9bcfb9fc) // is valid header?
|
||||||
{
|
{
|
||||||
|
|
||||||
int len = fs.ReadByte();
|
int len = fs.ReadByte();
|
||||||
string uuid = Utils.ReadString(fs, len); // Read the pack UUID for this file
|
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
|
byte[] key = Keys.LookupKey(uuid); // Look for key inside .ent / keys.db
|
||||||
|
|
||||||
|
|
||||||
if (key == null)
|
if (key == null)
|
||||||
key = Encoding.UTF8.GetBytes("s5s5ejuDru4uchuF2drUFuthaspAbepE"); // Generic skinpack key
|
key = Encoding.UTF8.GetBytes("s5s5ejuDru4uchuF2drUFuthaspAbepE"); // Generic skinpack key
|
||||||
// Every skinpack has the same key lol
|
// Every skinpack has the same key lol
|
||||||
// This might be wrong, but hey! if it works, it works :D
|
// This might be wrong, but hey! if it works, it works :D
|
||||||
fs.Seek(0x100, SeekOrigin.Begin); // Read ciphertext
|
fs.Seek(0x100, SeekOrigin.Begin); // Read ciphertext
|
||||||
byte[] ciphertext = new byte[fs.Length - 0x100];
|
byte[] ciphertext = new byte[fs.Length - 0x100];
|
||||||
fs.Read(ciphertext, 0x00, ciphertext.Length);
|
fs.Read(ciphertext, 0x00, ciphertext.Length);
|
||||||
|
|
||||||
|
|
||||||
byte[] iv = new byte[16]; // Copy first 16 bytes of Key for IV
|
byte[] iv = new byte[16]; // Copy first 16 bytes of Key for IV
|
||||||
Array.Copy(key, iv, iv.Length);
|
Array.Copy(key, iv, iv.Length);
|
||||||
|
|
||||||
byte[] plaintext = Crypto.Aes256CfbDecrypt(key, iv, ciphertext); // Decrypt data
|
byte[] plaintext = Crypto.Aes256CfbDecrypt(key, iv, ciphertext); // Decrypt data
|
||||||
|
|
||||||
return plaintext;
|
fs.Dispose();
|
||||||
|
return plaintext;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new InvalidDataException("Not a valid LEVELDB or CONTENTS.JSON file.");
|
fs.Dispose();
|
||||||
}
|
throw new InvalidDataException("Not a valid LEVELDB or CONTENTS.JSON file.");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Read contents.json, and decrypt all files inside
|
// Read contents.json, and decrypt all files inside
|
||||||
// Now Multi-Threaded for speed!
|
// Now Multi-Threaded for speed!
|
||||||
private static void decryptContentsJsonFiles(string contentsJsonPath, List<Thread> threadList)
|
private static void decryptContentsJsonFiles(string contentsJsonPath, List<Thread> threadList)
|
||||||
|
@ -252,9 +224,6 @@ namespace McCrypt
|
||||||
if (decKey == null)
|
if (decKey == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (Path.GetFileName(relPath).ToLowerInvariant() == "manifest.json")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Thread thrd = new Thread(() =>
|
Thread thrd = new Thread(() =>
|
||||||
{
|
{
|
||||||
string filePath = Path.Combine(baseDirectory, relPath); // Combine pack dir, with file relative path
|
string filePath = Path.Combine(baseDirectory, relPath); // Combine pack dir, with file relative path
|
||||||
|
@ -267,9 +236,8 @@ namespace McCrypt
|
||||||
File.WriteAllBytes(filePath, plainText); // Write back decrypted filie
|
File.WriteAllBytes(filePath, plainText); // Write back decrypted filie
|
||||||
});
|
});
|
||||||
thrd.Priority = ThreadPriority.Highest;
|
thrd.Priority = ThreadPriority.Highest;
|
||||||
|
threadList.Add(thrd);
|
||||||
thrd.Start();
|
thrd.Start();
|
||||||
if (!Config.MultiThread) thrd.Join();
|
|
||||||
else threadList.Add(thrd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,12 +308,13 @@ namespace McCrypt
|
||||||
File.WriteAllBytes(fileToDecrypt, decryptedData); // Write to disk
|
File.WriteAllBytes(fileToDecrypt, decryptedData); // Write to disk
|
||||||
}
|
}
|
||||||
catch (InvalidDataException)
|
catch (InvalidDataException)
|
||||||
{ }
|
{
|
||||||
|
Console.Error.WriteLine("Failed to decrypt db/" + Path.GetFileName(levelDbFile));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
thrd.Priority = ThreadPriority.Highest;
|
thrd.Priority = ThreadPriority.Highest;
|
||||||
|
threadList.Add(thrd);
|
||||||
thrd.Start();
|
thrd.Start();
|
||||||
if (!Config.MultiThread) thrd.Join();
|
|
||||||
else threadList.Add(thrd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,184 +0,0 @@
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace McCrypt.PackData
|
|
||||||
{
|
|
||||||
public class PEntry
|
|
||||||
{
|
|
||||||
|
|
||||||
private string originalPath;
|
|
||||||
public String FilePath
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return originalPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public String ManifestPath
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Path.Combine(originalPath, "manifest.json");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public String WorldResourcePacksPath
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Path.Combine(this.FilePath, "world_resource_packs.json");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String WorldBehaviourPacksPath
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Path.Combine(this.FilePath, "world_behavior_packs.json");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String SubResourcePacks
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Path.Combine(this.FilePath, "resource_packs");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String SubBehaviourPacks
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Path.Combine(this.FilePath, "behavior_packs");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsEncrypted
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (this.ProductType != "minecraftWorlds") return true;
|
|
||||||
else return Marketplace.IsLevelEncrypted(this.FilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasDependancies
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return DependsUUID.Length >= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public String[] DependsUUID
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (File.Exists(this.ManifestPath))
|
|
||||||
{
|
|
||||||
return Manifest.ReadDependancyUuids(this.ManifestPath);
|
|
||||||
}
|
|
||||||
else if(this.Type == "minecraftWorlds")
|
|
||||||
{
|
|
||||||
List<String> uuids = new List<String>();
|
|
||||||
if(File.Exists(WorldResourcePacksPath)) uuids.AddRange(Manifest.ReadWorldPackList(WorldResourcePacksPath));
|
|
||||||
if(File.Exists(WorldBehaviourPacksPath)) uuids.AddRange(Manifest.ReadWorldPackList(WorldBehaviourPacksPath));
|
|
||||||
return uuids.ToArray();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new String[0] { };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String Name
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (File.Exists(this.ManifestPath))
|
|
||||||
return Manifest.ReadName(this.ManifestPath);
|
|
||||||
else if (File.Exists(Path.Combine(FilePath, "levelname.txt")))
|
|
||||||
return File.ReadAllText(Path.Combine(FilePath, "levelname.txt"));
|
|
||||||
else
|
|
||||||
return "Untitled";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public String Type {
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if(File.Exists(this.ManifestPath))
|
|
||||||
return Manifest.ReadType(this.ManifestPath);
|
|
||||||
else if (File.Exists(Path.Combine(FilePath, "levelname.txt")))
|
|
||||||
return "minecraftWorlds";
|
|
||||||
else
|
|
||||||
return Path.GetFileName(Path.GetDirectoryName(this.FilePath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String ProductType
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (File.Exists(this.ManifestPath))
|
|
||||||
{
|
|
||||||
string ptype = Manifest.ReadProductType(this.ManifestPath);
|
|
||||||
if (ptype == null)
|
|
||||||
{
|
|
||||||
string type = Manifest.ReadType(this.ManifestPath);
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case "resources":
|
|
||||||
return "resource_packs";
|
|
||||||
case "skin_pack":
|
|
||||||
return "skin_packs";
|
|
||||||
case "world_template":
|
|
||||||
return "world_templates";
|
|
||||||
case "data":
|
|
||||||
return "behaviour_packs";
|
|
||||||
case "persona_piece":
|
|
||||||
return "persona";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ptype;
|
|
||||||
}
|
|
||||||
else if (File.Exists(Path.Combine(FilePath, "levelname.txt")))
|
|
||||||
{
|
|
||||||
return "minecraftWorlds";
|
|
||||||
}
|
|
||||||
else if (this.HasDependancies)
|
|
||||||
{
|
|
||||||
return "addon";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Path.GetFileName(Path.GetDirectoryName(this.FilePath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public String Uuid
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if(File.Exists(this.ManifestPath))
|
|
||||||
{
|
|
||||||
return Manifest.ReadUUID(this.ManifestPath);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new Guid().ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PEntry(string path)
|
|
||||||
{
|
|
||||||
this.originalPath = path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
using McCrypt.PackData;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace McCrypt.PackData
|
|
||||||
{
|
|
||||||
public class PReader
|
|
||||||
{
|
|
||||||
private List<PEntry> entries = new List<PEntry>();
|
|
||||||
private HashSet<string> hiddenUuids = new HashSet<String>();
|
|
||||||
public PEntry[] GetDependancies(PEntry baseentry)
|
|
||||||
{
|
|
||||||
List<PEntry> dependancyList = new List<PEntry>();
|
|
||||||
foreach (PEntry pentry in entries)
|
|
||||||
{
|
|
||||||
if (baseentry.DependsUUID.Contains<string>(pentry.Uuid))
|
|
||||||
dependancyList.Add(pentry);
|
|
||||||
|
|
||||||
// check sub packs in world templates ..
|
|
||||||
if(pentry.ProductType == "world_templates")
|
|
||||||
{
|
|
||||||
if (Directory.Exists(pentry.SubResourcePacks))
|
|
||||||
{
|
|
||||||
foreach (string resourcePack in Directory.GetDirectories(pentry.SubResourcePacks, "*", SearchOption.TopDirectoryOnly))
|
|
||||||
{
|
|
||||||
PEntry subPentry = new PEntry(Path.Combine(pentry.SubResourcePacks, resourcePack));
|
|
||||||
if (baseentry.DependsUUID.Contains<string>(subPentry.Uuid))
|
|
||||||
dependancyList.Add(subPentry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Directory.Exists(pentry.SubBehaviourPacks))
|
|
||||||
{
|
|
||||||
foreach (string behaviourPack in Directory.GetDirectories(pentry.SubBehaviourPacks, "*", SearchOption.TopDirectoryOnly))
|
|
||||||
{
|
|
||||||
PEntry subPentry = new PEntry(Path.Combine(pentry.SubBehaviourPacks, behaviourPack));
|
|
||||||
if (baseentry.DependsUUID.Contains<string>(subPentry.Uuid))
|
|
||||||
dependancyList.Add(subPentry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return dependancyList.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PEntry[] PEntryList
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
List<PEntry> publicEntries = new List<PEntry>();
|
|
||||||
foreach (PEntry entry in entries)
|
|
||||||
{
|
|
||||||
if (!hiddenUuids.Contains(entry.Uuid))
|
|
||||||
{
|
|
||||||
publicEntries.Add(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return publicEntries.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public PReader()
|
|
||||||
{
|
|
||||||
// search premium cache
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
PEntry entry = new PEntry(moduleItem);
|
|
||||||
if (entry.ProductType == "minecraftWorlds" && !Config.DecryptExistingWorlds) continue;
|
|
||||||
if (entry.ProductType != "minecraftWorlds" && !hiddenUuids.Contains(entry.Uuid)) foreach (string uuid in entry.DependsUUID) hiddenUuids.Add(uuid);
|
|
||||||
if (!entry.IsEncrypted) continue;
|
|
||||||
|
|
||||||
entries.Add(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (Config.DecryptExistingWorlds && Directory.Exists(Config.WorldsFolder))
|
|
||||||
{
|
|
||||||
foreach (string moduleItem in Directory.GetDirectories(Config.WorldsFolder, "*", SearchOption.TopDirectoryOnly))
|
|
||||||
{
|
|
||||||
PEntry entry = new PEntry(moduleItem);
|
|
||||||
|
|
||||||
if (entry.ProductType != "minecraftWorlds" && !hiddenUuids.Contains(entry.Uuid)) foreach (string uuid in entry.DependsUUID) hiddenUuids.Add(uuid);
|
|
||||||
if (!entry.IsEncrypted) continue;
|
|
||||||
|
|
||||||
entries.Add(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,4 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -9,7 +8,7 @@ namespace McCrypt
|
||||||
internal class Utils
|
internal class Utils
|
||||||
{
|
{
|
||||||
|
|
||||||
internal static Object JsonDecodeCloserToMinecraft(string json)
|
internal static object JsonDecodeCloserToMinecraft(string json)
|
||||||
{
|
{
|
||||||
for (int i = json.Length; i > 0; i--)
|
for (int i = json.Length; i > 0; i--)
|
||||||
{
|
{
|
||||||
|
|
6
McDecryptor/App.config
Normal file
6
McDecryptor/App.config
Normal 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>
|
|
@ -1,4 +1,4 @@
|
||||||
using McCrypt.Properties;
|
using McDecryptor.Properties;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -7,9 +7,9 @@ using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace McCrypt
|
namespace McDecryptor
|
||||||
{
|
{
|
||||||
public class Config
|
internal class Config
|
||||||
{
|
{
|
||||||
public static string LocalAppdata = Environment.GetEnvironmentVariable("LOCALAPPDATA");
|
public static string LocalAppdata = Environment.GetEnvironmentVariable("LOCALAPPDATA");
|
||||||
public static string RoamingAppdata = Environment.GetEnvironmentVariable("APPDATA");
|
public static string RoamingAppdata = Environment.GetEnvironmentVariable("APPDATA");
|
||||||
|
@ -23,21 +23,18 @@ namespace McCrypt
|
||||||
|
|
||||||
public static string LocalState;
|
public static string LocalState;
|
||||||
public static string LocalCache;
|
public static string LocalCache;
|
||||||
public static string ComMojang;
|
|
||||||
|
|
||||||
public static string KeysDbPath;
|
public static string KeysDbPath;
|
||||||
public static string PremiumCache;
|
public static string PremiumCache;
|
||||||
public static string ServerPackCache;
|
public static string ServerPackCache;
|
||||||
public static string RealmsPremiumCache;
|
public static string RealmsPremiumCache;
|
||||||
public static string WorldsFolder;
|
|
||||||
|
|
||||||
public static string OptionsTxt;
|
public static string OptionsTxt;
|
||||||
public static string OutFolder;
|
public static string OutFolder;
|
||||||
|
|
||||||
public static bool CrackPacks;
|
public static bool CrackPacks;
|
||||||
public static bool ZipPacks;
|
public static bool ZipPacks;
|
||||||
public static bool MultiThread;
|
|
||||||
public static bool DecryptExistingWorlds;
|
|
||||||
public static string[] SearchFolders
|
public static string[] SearchFolders
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -67,19 +64,15 @@ namespace McCrypt
|
||||||
searchModules.Add("skin_packs");
|
searchModules.Add("skin_packs");
|
||||||
searchModules.Add("world_templates");
|
searchModules.Add("world_templates");
|
||||||
searchModules.Add("persona");
|
searchModules.Add("persona");
|
||||||
searchModules.Add("behavior_packs");
|
searchModules.Add("behaviour_packs");
|
||||||
searchModules.Add("resource");
|
searchModules.Add("resource");
|
||||||
searchModules.Add("minecraftWorlds");
|
|
||||||
}
|
}
|
||||||
private static void rebaseLocalData()
|
private static void rebaseLocalData()
|
||||||
{
|
{
|
||||||
|
OutFolder = Path.Combine(LocalState, "games", "com.mojang");
|
||||||
PremiumCache = Path.Combine(LocalState, "premium_cache");
|
PremiumCache = Path.Combine(LocalState, "premium_cache");
|
||||||
ServerPackCache = Path.Combine(LocalCache, "packcache");
|
ServerPackCache = Path.Combine(LocalCache, "packcache");
|
||||||
RealmsPremiumCache = Path.Combine(LocalCache, "premiumcache");
|
RealmsPremiumCache = Path.Combine(LocalCache, "premiumcache");
|
||||||
ComMojang = Path.Combine(LocalState, "games", "com.mojang");
|
|
||||||
OptionsTxt = Path.Combine(ComMojang, "minecraftpe", "options.txt");
|
|
||||||
WorldsFolder = Path.Combine(ComMojang, "minecraftWorlds");
|
|
||||||
|
|
||||||
rebaseSearchFolders();
|
rebaseSearchFolders();
|
||||||
}
|
}
|
||||||
private static void rebaseAll()
|
private static void rebaseAll()
|
||||||
|
@ -99,7 +92,6 @@ namespace McCrypt
|
||||||
|
|
||||||
str = str.Replace("$LOCALSTATE", LocalState);
|
str = str.Replace("$LOCALSTATE", LocalState);
|
||||||
str = str.Replace("$LOCALCACHE", LocalCache);
|
str = str.Replace("$LOCALCACHE", LocalCache);
|
||||||
str = str.Replace("$COMMOJANG", ComMojang);
|
|
||||||
|
|
||||||
str = str.Replace("$PREMIUMCACHE", PremiumCache);
|
str = str.Replace("$PREMIUMCACHE", PremiumCache);
|
||||||
str = str.Replace("$SERVERPACKCACHE", ServerPackCache);
|
str = str.Replace("$SERVERPACKCACHE", ServerPackCache);
|
||||||
|
@ -117,7 +109,6 @@ namespace McCrypt
|
||||||
ApplicationDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
ApplicationDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||||
KeysDbPath = Path.Combine(ApplicationDirectory, "keys.db");
|
KeysDbPath = Path.Combine(ApplicationDirectory, "keys.db");
|
||||||
MinecraftFolder = Path.Combine(LocalAppdata, "Packages", "Microsoft.MinecraftUWP_8wekyb3d8bbwe");
|
MinecraftFolder = Path.Combine(LocalAppdata, "Packages", "Microsoft.MinecraftUWP_8wekyb3d8bbwe");
|
||||||
|
|
||||||
rebaseAll();
|
rebaseAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,14 +159,6 @@ namespace McCrypt
|
||||||
rebaseSearchFolders();
|
rebaseSearchFolders();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "ComMojang":
|
|
||||||
ComMojang = resolve(keyvalpair[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "WorldsFolder":
|
|
||||||
WorldsFolder = resolve(keyvalpair[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "OutputFolder":
|
case "OutputFolder":
|
||||||
OutFolder = resolve(keyvalpair[1]);
|
OutFolder = resolve(keyvalpair[1]);
|
||||||
break;
|
break;
|
||||||
|
@ -201,12 +184,7 @@ namespace McCrypt
|
||||||
case "ZipThePacks":
|
case "ZipThePacks":
|
||||||
ZipPacks = (resolve(keyvalpair[1]).ToLower() == "yes");
|
ZipPacks = (resolve(keyvalpair[1]).ToLower() == "yes");
|
||||||
break;
|
break;
|
||||||
case "MultiThread":
|
|
||||||
MultiThread = (resolve(keyvalpair[1]).ToLower() == "yes");
|
|
||||||
break;
|
|
||||||
case "DecryptExistingWorlds":
|
|
||||||
DecryptExistingWorlds = (resolve(keyvalpair[1]).ToLower() == "yes");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -49,8 +49,18 @@
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Config.cs" />
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\McCrypt\LibMcCrypt.csproj">
|
<ProjectReference Include="..\McCrypt\LibMcCrypt.csproj">
|
||||||
|
@ -58,6 +68,12 @@
|
||||||
<Name>LibMcCrypt</Name>
|
<Name>LibMcCrypt</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="illager.ico" />
|
<Content Include="illager.ico" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -2,11 +2,8 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Net.Configuration;
|
|
||||||
using System.Runtime.Remoting.Messaging;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using McCrypt;
|
using McCrypt;
|
||||||
using McCrypt.PackData;
|
|
||||||
|
|
||||||
namespace McDecryptor
|
namespace McDecryptor
|
||||||
{
|
{
|
||||||
|
@ -48,8 +45,7 @@ namespace McDecryptor
|
||||||
});
|
});
|
||||||
thrd.Priority = ThreadPriority.Highest;
|
thrd.Priority = ThreadPriority.Highest;
|
||||||
thrd.Start();
|
thrd.Start();
|
||||||
if (!Config.MultiThread) thrd.Join();
|
threads.Add(thrd);
|
||||||
else threads.Add(thrd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Thread t in threads.ToArray())
|
foreach (Thread t in threads.ToArray())
|
||||||
|
@ -66,8 +62,7 @@ namespace McDecryptor
|
||||||
});
|
});
|
||||||
thrd.Priority = ThreadPriority.Highest;
|
thrd.Priority = ThreadPriority.Highest;
|
||||||
thrd.Start();
|
thrd.Start();
|
||||||
if (!Config.MultiThread) thrd.Join();
|
threads.Add(thrd);
|
||||||
else threads.Add(thrd);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,28 +72,6 @@ namespace McDecryptor
|
||||||
threads.Clear();
|
threads.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DecryptPack(string filePath)
|
|
||||||
{
|
|
||||||
string levelDatFile = Path.Combine(filePath, "level.dat");
|
|
||||||
string skinsJsonFile = Path.Combine(filePath, "skins.json");
|
|
||||||
string oldSchoolZipe = Path.Combine(filePath, "content.zipe");
|
|
||||||
|
|
||||||
Marketplace.DecryptContents(filePath);
|
|
||||||
|
|
||||||
if (Config.CrackPacks)
|
|
||||||
{
|
|
||||||
if (File.Exists(oldSchoolZipe))
|
|
||||||
Marketplace.CrackZipe(oldSchoolZipe);
|
|
||||||
|
|
||||||
if (File.Exists(levelDatFile))
|
|
||||||
Marketplace.CrackLevelDat(levelDatFile);
|
|
||||||
|
|
||||||
if (File.Exists(skinsJsonFile))
|
|
||||||
Marketplace.CrackSkinsJson(skinsJsonFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
Console.WriteLine("-- McDecryptor --");
|
Console.WriteLine("-- McDecryptor --");
|
||||||
|
@ -145,21 +118,39 @@ namespace McDecryptor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
List<ContentListing> premiumContents = new List<ContentListing>();
|
||||||
Console.WriteLine("\n\n");
|
Console.WriteLine("\n\n");
|
||||||
Console.WriteLine("Select what to decrypt: ");
|
Console.WriteLine("Select what to decrypt: ");
|
||||||
int total = 1;
|
int total = 1;
|
||||||
|
|
||||||
PReader pReader = new PReader();
|
|
||||||
PEntry[] entries = pReader.PEntryList;
|
|
||||||
|
|
||||||
foreach (PEntry entry in entries)
|
foreach (string searchFolder in Config.SearchFolders)
|
||||||
{
|
{
|
||||||
Console.WriteLine(total.ToString() + ") (" + entry.ProductType + ") " + entry.Name);
|
foreach(string searchModule in Config.SearchModules)
|
||||||
|
{
|
||||||
|
string moduleFolder = Path.Combine(searchFolder, searchModule);
|
||||||
|
|
||||||
total++;
|
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 one or multiple (seperated by ',') or write \"ALL\", numerical values");
|
Console.WriteLine("Select multiple (seperated by ',') or write \"ALL\"");
|
||||||
|
|
||||||
List<int> toDecrypt = new List<int>();
|
List<int> toDecrypt = new List<int>();
|
||||||
while (true)
|
while (true)
|
||||||
|
@ -174,9 +165,9 @@ namespace McDecryptor
|
||||||
toDecrypt.Add(i);
|
toDecrypt.Add(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
string[] txtentries = readText.Split(',');
|
string[] entries = readText.Split(',');
|
||||||
|
|
||||||
foreach(string entry in txtentries) {
|
foreach(string entry in entries) {
|
||||||
int tdc = Convert.ToInt32(entry.Trim())-1;
|
int tdc = Convert.ToInt32(entry.Trim())-1;
|
||||||
if (tdc < 0 || tdc >= total)
|
if (tdc < 0 || tdc >= total)
|
||||||
continue;
|
continue;
|
||||||
|
@ -185,15 +176,15 @@ namespace McDecryptor
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (Exception e) { Console.WriteLine("Error: " + e.Message); }
|
catch (Exception) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
foreach (int decryptMe in toDecrypt.ToArray())
|
foreach (int decryptMe in toDecrypt.ToArray())
|
||||||
{
|
{
|
||||||
PEntry cEntry = entries[decryptMe];
|
ContentListing cListing = premiumContents.ToArray()[decryptMe];
|
||||||
string outFolder = Path.Combine(Config.OutFolder, cEntry.ProductType, EscapeFilename(cEntry.Name));
|
string outFolder = Path.Combine(Config.OutFolder, cListing.Type, EscapeFilename(cListing.Name));
|
||||||
|
|
||||||
int counter = 1;
|
int counter = 1;
|
||||||
string ogOutFolder = outFolder;
|
string ogOutFolder = outFolder;
|
||||||
|
@ -203,89 +194,51 @@ namespace McDecryptor
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Decrypting: " + cEntry.Name);
|
new Thread(() =>
|
||||||
Directory.CreateDirectory(outFolder);
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (cEntry.ProductType == "addon")
|
Console.WriteLine("Decrypting: " + cListing.Name);
|
||||||
|
Directory.CreateDirectory(outFolder);
|
||||||
|
CopyDirectory(cListing.Path, outFolder);
|
||||||
|
try
|
||||||
{
|
{
|
||||||
// copy & decrypt main file
|
string levelDatFile = Path.Combine(outFolder, "level.dat");
|
||||||
string subDir = Path.Combine(outFolder, cEntry.Type);
|
string skinsJsonFile = Path.Combine(outFolder, "skins.json");
|
||||||
Directory.CreateDirectory(subDir);
|
string oldSchoolZipe = Path.Combine(outFolder, "content.zipe");
|
||||||
CopyDirectory(cEntry.FilePath, subDir);
|
|
||||||
DecryptPack(subDir);
|
|
||||||
|
|
||||||
// copy & decrypt file dependancies
|
Marketplace.DecryptContents(outFolder);
|
||||||
PEntry[] deps = pReader.GetDependancies(cEntry);
|
|
||||||
foreach (PEntry dependancy in deps)
|
if (Config.CrackPacks)
|
||||||
{
|
{
|
||||||
string newDir = Path.Combine(outFolder, dependancy.Type);
|
if (File.Exists(oldSchoolZipe))
|
||||||
Console.WriteLine("Decrypting dependancy: " + dependancy.Type + "/" + dependancy.Name);
|
Marketplace.CrackZipe(oldSchoolZipe);
|
||||||
Directory.CreateDirectory(newDir);
|
|
||||||
|
|
||||||
CopyDirectory(dependancy.FilePath, newDir);
|
if (File.Exists(levelDatFile))
|
||||||
DecryptPack(newDir);
|
Marketplace.CrackLevelDat(levelDatFile);
|
||||||
|
|
||||||
|
if (File.Exists(skinsJsonFile))
|
||||||
|
Marketplace.CrackSkinsJson(skinsJsonFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if (Config.ZipPacks)
|
||||||
else if(cEntry.ProductType == "minecraftWorlds")
|
|
||||||
{
|
|
||||||
CopyDirectory(cEntry.FilePath, outFolder);
|
|
||||||
DecryptPack(outFolder);
|
|
||||||
|
|
||||||
PEntry[] deps = pReader.GetDependancies(cEntry);
|
|
||||||
foreach (PEntry dependancy in deps)
|
|
||||||
{
|
{
|
||||||
Console.WriteLine("Decrypting dependancy: " + dependancy.ProductType+"/"+dependancy.Name);
|
string ext = "";
|
||||||
string newDir = Path.Combine(outFolder, dependancy.ProductType, Path.GetFileName(dependancy.FilePath));
|
if (File.Exists(levelDatFile))
|
||||||
|
ext += ".mctemplate";
|
||||||
|
else
|
||||||
|
ext += ".mcpack";
|
||||||
|
|
||||||
CopyDirectory(dependancy.FilePath, newDir);
|
ZipFile.CreateFromDirectory(outFolder, outFolder + ext, CompressionLevel.NoCompression, false);
|
||||||
DecryptPack(newDir);
|
Directory.Delete(outFolder, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
catch (Exception)
|
||||||
{
|
{
|
||||||
CopyDirectory(cEntry.FilePath, outFolder);
|
Console.Error.WriteLine("Failed to decrypt: " + cListing.Name);
|
||||||
DecryptPack(outFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Config.ZipPacks)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Zipping: " + cEntry.Name);
|
|
||||||
|
|
||||||
string ext = "";
|
|
||||||
if (cEntry.ProductType == "world_templates")
|
|
||||||
ext += ".mctemplate";
|
|
||||||
else if (cEntry.ProductType == "minecraftWorlds")
|
|
||||||
ext += ".mcworld";
|
|
||||||
else if (cEntry.ProductType == "addon")
|
|
||||||
ext += ".mcaddon";
|
|
||||||
else if (cEntry.ProductType == "persona")
|
|
||||||
ext += ".mcpersona";
|
|
||||||
else
|
|
||||||
ext += ".mcpack";
|
|
||||||
|
|
||||||
string fname = outFolder + ext;
|
|
||||||
|
|
||||||
if (File.Exists(fname))
|
|
||||||
File.Delete(fname);
|
|
||||||
|
|
||||||
ZipFile.CreateFromDirectory(outFolder, fname, CompressionLevel.NoCompression, false);
|
|
||||||
Directory.Delete(outFolder, true);
|
Directory.Delete(outFolder, true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine("Failed to decrypt: " + cEntry.Name + " " + e.Message);
|
|
||||||
Directory.Delete(outFolder, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}).Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Finished.");
|
|
||||||
Console.ReadKey();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// </auto-generated>
|
// </auto-generated>
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace McCrypt.Properties {
|
namespace McDecryptor.Properties {
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace McCrypt.Properties {
|
||||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
get {
|
get {
|
||||||
if (object.ReferenceEquals(resourceMan, null)) {
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("McCrypt.Properties.Resources", typeof(Resources).Assembly);
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("McDecryptor.Properties.Resources", typeof(Resources).Assembly);
|
||||||
resourceMan = temp;
|
resourceMan = temp;
|
||||||
}
|
}
|
||||||
return resourceMan;
|
return resourceMan;
|
|
@ -11,14 +11,11 @@ KeysDb: $EXECDIR\keys.db
|
||||||
# These folders only exist in UWP Versions of Bedrock
|
# These folders only exist in UWP Versions of Bedrock
|
||||||
# On WIN32 versions it may be under "internalStorage"
|
# On WIN32 versions it may be under "internalStorage"
|
||||||
LocalState: $MCDIR\LocalState
|
LocalState: $MCDIR\LocalState
|
||||||
LocalCache: $MCDIR\LocalCache
|
LocalCache: $MCDIR\LocalCache\McDecryptor
|
||||||
|
|
||||||
# location of games/com.mojang folder
|
|
||||||
ComMojang: $LOCALSTATE\games\com.mojang
|
|
||||||
|
|
||||||
# Path to options.txt
|
# Path to options.txt
|
||||||
# needed to decrypt .ent files since beta 1.19.
|
# needed to decrypt .ent files since beta 1.19.
|
||||||
OptionsTxt: $COMMOJANG\minecraftpe\options.txt
|
OptionsTxt: $LOCALSTATE\games\com.mojang\minecraftpe\options.txt
|
||||||
|
|
||||||
# Locations of Premium Cache (marketplace contents)
|
# Locations of Premium Cache (marketplace contents)
|
||||||
# Server Pack Cache (server resource packs)
|
# Server Pack Cache (server resource packs)
|
||||||
|
@ -26,29 +23,22 @@ OptionsTxt: $COMMOJANG\minecraftpe\options.txt
|
||||||
PremiumCache: $LOCALSTATE\premium_cache
|
PremiumCache: $LOCALSTATE\premium_cache
|
||||||
ServerPackCache: $LOCALCACHE\packcache
|
ServerPackCache: $LOCALCACHE\packcache
|
||||||
RealmsPremiumCache: $LOCALCACHE\premiumcache
|
RealmsPremiumCache: $LOCALCACHE\premiumcache
|
||||||
WorldsFolder: $COMMOJANG\minecraftWorlds
|
|
||||||
|
|
||||||
# Should i allow decrypting pre-existing world files
|
|
||||||
DecryptExistingWorlds: yes
|
|
||||||
|
|
||||||
# Should it crack the packs (change skin packs to free, remove prid from worlds)
|
# Should it crack the packs (change skin packs to free, remove prid from worlds)
|
||||||
CrackThePacks: yes
|
CrackThePacks: yes
|
||||||
|
|
||||||
# Should i zip packs to .mcpack/.mctemplate
|
# Should i zip packs to .mcpack/.mctemplate
|
||||||
ZipThePacks: yes
|
ZipThePacks: no
|
||||||
|
|
||||||
# Use Multiple threads to decrypt (faster, but requires good CPU)
|
|
||||||
MultiThread: yes
|
|
||||||
|
|
||||||
# Where to output the decrypted data, (deafult to install into the game)
|
# Where to output the decrypted data, (deafult to install into the game)
|
||||||
OutputFolder: $EXECDIR\output_packs
|
OutputFolder: $LOCALSTATE\games\com.mojang
|
||||||
|
|
||||||
# You can also add more search locations ontop of the default ones.
|
# You can also add more search locations ontop of the default ones.
|
||||||
# Do this by using AdditionalSearchDir and a path, it will look there
|
# Do this by using AdditionalSearchDir and a path, it will look there
|
||||||
# for packs.
|
# for packs.
|
||||||
|
|
||||||
# You can use AdditionalModuleDir to add new folders to look for encrypted data inside of the search folders
|
# 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", "behaviour_packs" etc
|
# normally it'll just look inside say "resource_packs" "skin_packs" "persona" etc
|
||||||
|
|
||||||
#AdditionalSearchDir: C:\Some\Folder\With\ResourcePacks
|
#AdditionalSearchDir: C:\Some\Folder\With\ResourcePacks
|
||||||
#AdditionalSearchDir: C:\Some\Other\Folder\With\ResourcePacks
|
#AdditionalSearchDir: C:\Some\Other\Folder\With\ResourcePacks
|
||||||
|
@ -61,8 +51,7 @@ OutputFolder: $EXECDIR\output_packs
|
||||||
# $EXECDIR - Folder the program is running in
|
# $EXECDIR - Folder the program is running in
|
||||||
# $LOCALSTATE - LocalState Folder
|
# $LOCALSTATE - LocalState Folder
|
||||||
# $LOCALCACHE - LocalCache Folder.
|
# $LOCALCACHE - LocalCache Folder.
|
||||||
# $COMMOJANG - ComMojang Folder.
|
|
||||||
# $PREMIUMCACHE - Premium Cache Folder
|
# $PREMIUMCACHE - Premium Cache Folder
|
||||||
# $SERVERPACKCACHE - Server Pack Cache Folder
|
# $SERVERPACKCACHE - Server Pack Cache Folder
|
||||||
# $REALMSPREMIUMCACHE - Realms Pack Cache Folder
|
# $REALMSPREMIUMCACHE - Realms Pack Cache Folder
|
||||||
# $OUTFOLDER - Output folder
|
# $OUTFOLDER - Output folder
|
Loading…
Add table
Add a link
Reference in a new issue