diff --git a/McCrypt/.vs/LibMcCrypt.csproj.dtbcache.json b/McCrypt/.vs/LibMcCrypt.csproj.dtbcache.json new file mode 100644 index 0000000..63804fc --- /dev/null +++ b/McCrypt/.vs/LibMcCrypt.csproj.dtbcache.json @@ -0,0 +1 @@ +{"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":[]} \ No newline at end of file diff --git a/McDecryptor/Config.cs b/McCrypt/Config.cs similarity index 84% rename from McDecryptor/Config.cs rename to McCrypt/Config.cs index 07eb148..664e342 100644 --- a/McDecryptor/Config.cs +++ b/McCrypt/Config.cs @@ -1,4 +1,4 @@ -using McDecryptor.Properties; +using McCrypt.Properties; using System; using System.Collections.Generic; using System.IO; @@ -7,9 +7,9 @@ using System.Reflection; using System.Text; using System.Threading.Tasks; -namespace McDecryptor +namespace McCrypt { - internal class Config + public class Config { public static string LocalAppdata = Environment.GetEnvironmentVariable("LOCALAPPDATA"); public static string RoamingAppdata = Environment.GetEnvironmentVariable("APPDATA"); @@ -23,18 +23,21 @@ namespace McDecryptor public static string LocalState; public static string LocalCache; + public static string ComMojang; public static string KeysDbPath; public static string PremiumCache; public static string ServerPackCache; public static string RealmsPremiumCache; - + public static string WorldsFolder; public static string OptionsTxt; public static string OutFolder; public static bool CrackPacks; public static bool ZipPacks; + public static bool MultiThread; + public static bool DecryptExistingWorlds; public static string[] SearchFolders { get @@ -66,13 +69,17 @@ namespace McDecryptor searchModules.Add("persona"); searchModules.Add("behavior_packs"); searchModules.Add("resource"); + searchModules.Add("minecraftWorlds"); } 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"); + ComMojang = Path.Combine(LocalState, "games", "com.mojang"); + OptionsTxt = Path.Combine(ComMojang, "minecraftpe", "options.txt"); + WorldsFolder = Path.Combine(ComMojang, "minecraftWorlds"); + rebaseSearchFolders(); } private static void rebaseAll() @@ -92,6 +99,7 @@ namespace McDecryptor str = str.Replace("$LOCALSTATE", LocalState); str = str.Replace("$LOCALCACHE", LocalCache); + str = str.Replace("$COMMOJANG", ComMojang); str = str.Replace("$PREMIUMCACHE", PremiumCache); str = str.Replace("$SERVERPACKCACHE", ServerPackCache); @@ -109,6 +117,7 @@ namespace McDecryptor ApplicationDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); KeysDbPath = Path.Combine(ApplicationDirectory, "keys.db"); MinecraftFolder = Path.Combine(LocalAppdata, "Packages", "Microsoft.MinecraftUWP_8wekyb3d8bbwe"); + rebaseAll(); } @@ -159,6 +168,14 @@ namespace McDecryptor rebaseSearchFolders(); break; + case "ComMojang": + ComMojang = resolve(keyvalpair[1]); + break; + + case "WorldsFolder": + WorldsFolder = resolve(keyvalpair[1]); + break; + case "OutputFolder": OutFolder = resolve(keyvalpair[1]); break; @@ -184,7 +201,12 @@ namespace McDecryptor case "ZipThePacks": ZipPacks = (resolve(keyvalpair[1]).ToLower() == "yes"); break; - + case "MultiThread": + MultiThread = (resolve(keyvalpair[1]).ToLower() == "yes"); + break; + case "DecryptExistingWorlds": + DecryptExistingWorlds = (resolve(keyvalpair[1]).ToLower() == "yes"); + break; } } } diff --git a/McCrypt/LibMcCrypt.csproj b/McCrypt/LibMcCrypt.csproj index d4a6c1d..3487bee 100644 --- a/McCrypt/LibMcCrypt.csproj +++ b/McCrypt/LibMcCrypt.csproj @@ -45,15 +45,30 @@ + + + + + Resources.resx + True + True + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + \ No newline at end of file diff --git a/McCrypt/Manifest.cs b/McCrypt/Manifest.cs index 1b2f228..60ab598 100644 --- a/McCrypt/Manifest.cs +++ b/McCrypt/Manifest.cs @@ -4,6 +4,7 @@ using System.Linq; using Newtonsoft.Json; using System.IO; using System.Text; +using Newtonsoft.Json.Linq; namespace McCrypt { @@ -43,6 +44,66 @@ namespace McCrypt string signaturesJsonFile = Path.Combine(basePath, "signatures.json"); 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 depUuidList = new List(); + 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 depUuidList = new List(); + 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) { string defaultName = Path.GetFileName(Path.GetDirectoryName(manifestFile)); diff --git a/McCrypt/Marketplace.cs b/McCrypt/Marketplace.cs index c9c17c8..16bd3db 100644 --- a/McCrypt/Marketplace.cs +++ b/McCrypt/Marketplace.cs @@ -12,8 +12,6 @@ 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 @@ -58,6 +56,37 @@ 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" // This makes the game let you actually apply them public static void CrackSkinsJson(string skinsJsonFile) @@ -160,54 +189,53 @@ namespace McCrypt // 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 + 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 <= 0) - { - fs.Dispose(); - return new byte[0] { }; - } + if (fs.Length <= 0) + return new byte[0] { }; - uint version = br.ReadUInt32(); - uint magic = br.ReadUInt32(); - UInt64 unk = br.ReadUInt64(); + uint version = br.ReadUInt32(); + uint magic = br.ReadUInt32(); + UInt64 unk = br.ReadUInt64(); - if (version == 0 && magic == 0x9bcfb9fc) // is valid header? - { + 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 + 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); + 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[] 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 + byte[] plaintext = Crypto.Aes256CfbDecrypt(key, iv, ciphertext); // Decrypt data - fs.Dispose(); - return plaintext; + return plaintext; - } - else - { - fs.Dispose(); - throw new InvalidDataException("Not a valid LEVELDB or CONTENTS.JSON file."); + } + else + { + 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 threadList) @@ -239,8 +267,9 @@ namespace McCrypt File.WriteAllBytes(filePath, plainText); // Write back decrypted filie }); thrd.Priority = ThreadPriority.Highest; - threadList.Add(thrd); thrd.Start(); + if (!Config.MultiThread) thrd.Join(); + else threadList.Add(thrd); } } @@ -311,13 +340,12 @@ namespace McCrypt 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(); + if (!Config.MultiThread) thrd.Join(); + else threadList.Add(thrd); } } } diff --git a/McCrypt/PackData/PEntry.cs b/McCrypt/PackData/PEntry.cs new file mode 100644 index 0000000..829d9f9 --- /dev/null +++ b/McCrypt/PackData/PEntry.cs @@ -0,0 +1,184 @@ +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.ProductType == "minecraftWorlds") + { + List uuids = new List(); + 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; + } + } +} diff --git a/McCrypt/PackData/PReader.cs b/McCrypt/PackData/PReader.cs new file mode 100644 index 0000000..907c3d9 --- /dev/null +++ b/McCrypt/PackData/PReader.cs @@ -0,0 +1,104 @@ +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 entries = new List(); + private HashSet hiddenUuids = new HashSet(); + public PEntry[] GetDependancies(PEntry baseentry) + { + List dependancyList = new List(); + foreach (PEntry pentry in entries) + { + if (baseentry.DependsUUID.Contains(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(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(subPentry.Uuid)) + dependancyList.Add(subPentry); + } + } + + } + + } + return dependancyList.ToArray(); + } + + public PEntry[] PEntryList + { + get + { + List publicEntries = new List(); + 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); + } + } + } + } +} diff --git a/McDecryptor/Properties/Resources.Designer.cs b/McCrypt/Properties/Resources.Designer.cs similarity index 95% rename from McDecryptor/Properties/Resources.Designer.cs rename to McCrypt/Properties/Resources.Designer.cs index d455984..8220686 100644 --- a/McDecryptor/Properties/Resources.Designer.cs +++ b/McCrypt/Properties/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace McDecryptor.Properties { +namespace McCrypt.Properties { using System; @@ -39,7 +39,7 @@ namespace McDecryptor.Properties { 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); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("McCrypt.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; diff --git a/McDecryptor/Properties/Resources.resx b/McCrypt/Properties/Resources.resx similarity index 100% rename from McDecryptor/Properties/Resources.resx rename to McCrypt/Properties/Resources.resx diff --git a/McDecryptor/default.cfg b/McCrypt/default.cfg similarity index 81% rename from McDecryptor/default.cfg rename to McCrypt/default.cfg index 8bdc072..fc88b23 100644 --- a/McDecryptor/default.cfg +++ b/McCrypt/default.cfg @@ -11,11 +11,14 @@ KeysDb: $EXECDIR\keys.db # These folders only exist in UWP Versions of Bedrock # On WIN32 versions it may be under "internalStorage" LocalState: $MCDIR\LocalState -LocalCache: $MCDIR\LocalCache\McDecryptor +LocalCache: $MCDIR\LocalCache + +# location of games/com.mojang folder +ComMojang: $LOCALSTATE\games\com.mojang # Path to options.txt # needed to decrypt .ent files since beta 1.19. -OptionsTxt: $LOCALSTATE\games\com.mojang\minecraftpe\options.txt +OptionsTxt: $COMMOJANG\minecraftpe\options.txt # Locations of Premium Cache (marketplace contents) # Server Pack Cache (server resource packs) @@ -23,6 +26,10 @@ OptionsTxt: $LOCALSTATE\games\com.mojang\minecraftpe\options.txt PremiumCache: $LOCALSTATE\premium_cache ServerPackCache: $LOCALCACHE\packcache 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) CrackThePacks: yes @@ -30,6 +37,9 @@ CrackThePacks: yes # Should i zip packs to .mcpack/.mctemplate ZipThePacks: yes +# Use Multiple threads to decrypt (faster, but requires good CPU) +MultiThread: yes + # Where to output the decrypted data, (deafult to install into the game) OutputFolder: $EXECDIR\output_packs @@ -38,7 +48,7 @@ OutputFolder: $EXECDIR\output_packs # 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", "behaviour packs" etc +# normally it'll just look inside say "resource_packs" "skin_packs" "persona", "behaviour_packs" etc #AdditionalSearchDir: C:\Some\Folder\With\ResourcePacks #AdditionalSearchDir: C:\Some\Other\Folder\With\ResourcePacks @@ -51,7 +61,8 @@ OutputFolder: $EXECDIR\output_packs # $EXECDIR - Folder the program is running in # $LOCALSTATE - LocalState Folder # $LOCALCACHE - LocalCache Folder. +# $COMMOJANG - ComMojang Folder. # $PREMIUMCACHE - Premium Cache Folder # $SERVERPACKCACHE - Server Pack Cache Folder # $REALMSPREMIUMCACHE - Realms Pack Cache Folder -# $OUTFOLDER - Output folder \ No newline at end of file +# $OUTFOLDER - Output folder diff --git a/McDecryptor/.vs/McDecryptor.csproj.dtbcache.json b/McDecryptor/.vs/McDecryptor.csproj.dtbcache.json new file mode 100644 index 0000000..a654af2 --- /dev/null +++ b/McDecryptor/.vs/McDecryptor.csproj.dtbcache.json @@ -0,0 +1 @@ +{"RootPath":"C:\\Users\\Li\\Desktop\\git\\McTools\\McDecryptor","ProjectFileName":"McDecryptor.csproj","Configuration":"Debug|AnyCPU","FrameworkPath":"","Sources":[{"SourceFile":"Config.cs"},{"SourceFile":"Program.cs"},{"SourceFile":"Properties\\AssemblyInfo.cs"},{"SourceFile":"Properties\\Resources.Designer.cs"},{"SourceFile":"obj\\Debug\\.NETFramework,Version=v4.8.AssemblyAttributes.cs"}],"References":[{"Reference":"C:\\Users\\Li\\Desktop\\git\\McTools\\McCrypt\\bin\\Debug\\LibMcCrypt.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":true,"ProjectPath":""},{"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:\\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\\McDecryptor\\bin\\Debug\\McDecryptor.exe","OutputItemRelativePath":"McDecryptor.exe"},{"OutputItemFullPath":"C:\\Users\\Li\\Desktop\\git\\McTools\\McDecryptor\\bin\\Debug\\McDecryptor.pdb","OutputItemRelativePath":"McDecryptor.pdb"}],"CopyToOutputEntries":[]} \ No newline at end of file diff --git a/McDecryptor/App.config b/McDecryptor/App.config deleted file mode 100644 index 92c094c..0000000 --- a/McDecryptor/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/McDecryptor/McDecryptor.csproj b/McDecryptor/McDecryptor.csproj index 3514bdc..6c588cf 100644 --- a/McDecryptor/McDecryptor.csproj +++ b/McDecryptor/McDecryptor.csproj @@ -49,18 +49,8 @@ - - - True - True - Resources.resx - - - - - @@ -68,12 +58,6 @@ LibMcCrypt - - - ResXFileCodeGenerator - Resources.Designer.cs - - diff --git a/McDecryptor/Program.cs b/McDecryptor/Program.cs index 9e8dbcc..8714c50 100644 --- a/McDecryptor/Program.cs +++ b/McDecryptor/Program.cs @@ -2,8 +2,11 @@ using System.Collections.Generic; using System.IO; using System.IO.Compression; +using System.Net.Configuration; +using System.Runtime.Remoting.Messaging; using System.Threading; using McCrypt; +using McCrypt.PackData; namespace McDecryptor { @@ -45,7 +48,8 @@ namespace McDecryptor }); thrd.Priority = ThreadPriority.Highest; thrd.Start(); - threads.Add(thrd); + if (!Config.MultiThread) thrd.Join(); + else threads.Add(thrd); } foreach (Thread t in threads.ToArray()) @@ -62,7 +66,8 @@ namespace McDecryptor }); thrd.Priority = ThreadPriority.Highest; thrd.Start(); - threads.Add(thrd); + if (!Config.MultiThread) thrd.Join(); + else threads.Add(thrd); } @@ -72,6 +77,28 @@ namespace McDecryptor 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) { Console.WriteLine("-- McDecryptor --"); @@ -118,39 +145,21 @@ namespace McDecryptor } - List premiumContents = new List(); Console.WriteLine("\n\n"); Console.WriteLine("Select what to decrypt: "); int total = 1; + PReader pReader = new PReader(); + PEntry[] entries = pReader.PEntryList; - foreach (string searchFolder in Config.SearchFolders) + foreach (PEntry entry in entries) { - foreach(string searchModule in Config.SearchModules) - { - string moduleFolder = Path.Combine(searchFolder, searchModule); + Console.WriteLine(total.ToString() + ") (" + entry.ProductType + ") " + entry.Name); - 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++; - } - } - } + total++; } - Console.WriteLine("Select multiple (seperated by ',') or write \"ALL\""); + Console.WriteLine("Select one or multiple (seperated by ',') or write \"ALL\", numerical values"); List toDecrypt = new List(); while (true) @@ -165,9 +174,9 @@ namespace McDecryptor toDecrypt.Add(i); break; } - string[] entries = readText.Split(','); + string[] txtentries = readText.Split(','); - foreach(string entry in entries) { + foreach(string entry in txtentries) { int tdc = Convert.ToInt32(entry.Trim())-1; if (tdc < 0 || tdc >= total) continue; @@ -183,8 +192,8 @@ namespace McDecryptor foreach (int decryptMe in toDecrypt.ToArray()) { - ContentListing cListing = premiumContents.ToArray()[decryptMe]; - string outFolder = Path.Combine(Config.OutFolder, cListing.Type, EscapeFilename(cListing.Name)); + PEntry cEntry = entries[decryptMe]; + string outFolder = Path.Combine(Config.OutFolder, cEntry.ProductType, EscapeFilename(cEntry.Name)); int counter = 1; string ogOutFolder = outFolder; @@ -194,38 +203,62 @@ namespace McDecryptor counter++; } - - Console.WriteLine("Decrypting: " + cListing.Name); + Console.WriteLine("Decrypting: " + cEntry.Name); Directory.CreateDirectory(outFolder); - CopyDirectory(cListing.Path, outFolder); - try + 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 (cEntry.ProductType == "addon") { - if (File.Exists(oldSchoolZipe)) - Marketplace.CrackZipe(oldSchoolZipe); + // copy & decrypt main file + string subDir = Path.Combine(outFolder, cEntry.Type); + Directory.CreateDirectory(subDir); + CopyDirectory(cEntry.FilePath, subDir); + DecryptPack(subDir); - if (File.Exists(levelDatFile)) - Marketplace.CrackLevelDat(levelDatFile); + // copy & decrypt file dependancies + PEntry[] deps = pReader.GetDependancies(cEntry); + foreach (PEntry dependancy in deps) + { + string newDir = Path.Combine(outFolder, dependancy.Type); + Console.WriteLine("Decrypting dependancy: " + dependancy.Type + "/" + dependancy.Name); + Directory.CreateDirectory(newDir); - if (File.Exists(skinsJsonFile)) - Marketplace.CrackSkinsJson(skinsJsonFile); + CopyDirectory(dependancy.FilePath, newDir); + DecryptPack(newDir); + } + + } + 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 newDir = Path.Combine(outFolder, dependancy.ProductType, Path.GetFileName(dependancy.FilePath)); + + CopyDirectory(dependancy.FilePath, newDir); + DecryptPack(newDir); + } + } + else + { + CopyDirectory(cEntry.FilePath, outFolder); + DecryptPack(outFolder); } if (Config.ZipPacks) { - Console.WriteLine("Zipping: " + cListing.Name); + Console.WriteLine("Zipping: " + cEntry.Name); string ext = ""; - if (File.Exists(levelDatFile)) + if (cEntry.ProductType == "world_templates") ext += ".mctemplate"; - else if (false) + else if (cEntry.ProductType == "minecraftWorlds") + ext += ".mcworld"; + else if (cEntry.ProductType == "addon") ext += ".mcaddon"; else ext += ".mcpack"; @@ -241,9 +274,10 @@ namespace McDecryptor } catch (Exception e) { - Console.Error.WriteLine("Failed to decrypt: " + cListing.Name+ " "+e.Message); + Console.Error.WriteLine("Failed to decrypt: " + cEntry.Name + " " + e.Message); Directory.Delete(outFolder, true); } + } diff --git a/McEncryptor/.vs/McEncryptor.csproj.dtbcache.json b/McEncryptor/.vs/McEncryptor.csproj.dtbcache.json new file mode 100644 index 0000000..b97d324 --- /dev/null +++ b/McEncryptor/.vs/McEncryptor.csproj.dtbcache.json @@ -0,0 +1 @@ +{"RootPath":"C:\\Users\\Li\\Desktop\\git\\McTools\\McEncryptor","ProjectFileName":"McEncryptor.csproj","Configuration":"Debug|AnyCPU","FrameworkPath":"","Sources":[{"SourceFile":"Program.cs"},{"SourceFile":"Properties\\AssemblyInfo.cs"},{"SourceFile":"obj\\Debug\\.NETFramework,Version=v4.8.AssemblyAttributes.cs"}],"References":[{"Reference":"C:\\Users\\Li\\Desktop\\git\\McTools\\McCrypt\\bin\\Debug\\LibMcCrypt.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":true,"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:\\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.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\\McEncryptor\\bin\\Debug\\McEncryptor.exe","OutputItemRelativePath":"McEncryptor.exe"},{"OutputItemFullPath":"C:\\Users\\Li\\Desktop\\git\\McTools\\McEncryptor\\bin\\Debug\\McEncryptor.pdb","OutputItemRelativePath":"McEncryptor.pdb"}],"CopyToOutputEntries":[]} \ No newline at end of file