using System; 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 { class Program { public struct ContentListing { public string Path; public string Type; public string Name; public int Id; } public static string EscapeFilename(string filename) { return filename.Replace("/", "_").Replace("\\", "_").Replace(":", "_").Replace("?", "_").Replace("*", "_").Replace("<", "_").Replace(">", "_").Replace("|", "_").Replace("\"", "_"); } static void CopyFile(string src, string dst) { using (FileStream fs = File.OpenRead(src)) { using(FileStream wfd = File.OpenWrite(dst)) { fs.CopyTo(wfd); } } } static void CopyDirectory(string sourcePath, string targetPath) { List threads = new List(); //Now Create all of the directories foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories)) { Thread thrd = new Thread(() => { Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPath)); }); thrd.Priority = ThreadPriority.Highest; thrd.Start(); if (!Config.MultiThread) thrd.Join(); else threads.Add(thrd); } foreach (Thread t in threads.ToArray()) t.Join(); threads.Clear(); //Copy all the files & Replaces any files with the same name foreach (string newPath in Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories)) { Thread thrd = new Thread(() => { CopyFile(newPath, newPath.Replace(sourcePath, targetPath)); }); thrd.Priority = ThreadPriority.Highest; thrd.Start(); if (!Config.MultiThread) thrd.Join(); else threads.Add(thrd); } foreach (Thread t in threads.ToArray()) t.Join(); 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 --"); Console.WriteLine("Reading Configuration File..."); Config.Init(); Directory.SetCurrentDirectory(Config.ApplicationDirectory); Config.ReadConfig("McDecryptor.cfg"); Keys.KeyDbFile = Config.KeysDbPath; if (File.Exists(Config.KeysDbPath)) { Console.WriteLine("Parsing Key Database File..."); Keys.ReadKeysDb(Config.KeysDbPath); } if (File.Exists(Config.OptionsTxt)) { Keys.ReadOptionsTxt(Config.OptionsTxt); } Console.WriteLine("Minecraft Folder: " + Config.MinecraftFolder); if (Directory.Exists(Config.MinecraftFolder)) { string[] entFiles = Directory.GetFiles(Config.LocalState, "*.ent", SearchOption.TopDirectoryOnly); foreach (string entFile in entFiles) { Console.WriteLine("Reading Entitlement File: " + Path.GetFileName(entFile)); Keys.ReadEntitlementFile(entFile); } } string[] entFilesWorkDir = Directory.GetFiles(Config.ApplicationDirectory, "*.ent", SearchOption.TopDirectoryOnly); foreach (string entFile in entFilesWorkDir) { Console.WriteLine("Reading Entitlement File: " + Path.GetFileName(entFile)); Keys.ReadEntitlementFile(entFile); } Console.WriteLine("\n\n"); Console.WriteLine("Select what to decrypt: "); int total = 1; PReader pReader = new PReader(); PEntry[] entries = pReader.PEntryList; foreach (PEntry entry in entries) { Console.WriteLine(total.ToString() + ") (" + entry.ProductType + ") " + entry.Name); total++; } Console.WriteLine("Select one or multiple (seperated by ',') or write \"ALL\", numerical values"); List toDecrypt = new List(); while (true) { Console.Write("Which do you want to decrypt? "); try { string readText = Console.ReadLine(); if (readText.ToUpper() == "ALL") { for(int i = 0; i < total-1; i++) toDecrypt.Add(i); break; } string[] txtentries = readText.Split(','); foreach(string entry in txtentries) { int tdc = Convert.ToInt32(entry.Trim())-1; if (tdc < 0 || tdc >= total) continue; toDecrypt.Add(tdc); } break; } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } } foreach (int decryptMe in toDecrypt.ToArray()) { PEntry cEntry = entries[decryptMe]; string outFolder = Path.Combine(Config.OutFolder, cEntry.ProductType, EscapeFilename(cEntry.Name)); int counter = 1; string ogOutFolder = outFolder; while (Directory.Exists(outFolder)) { outFolder = ogOutFolder + "_" + counter.ToString(); counter++; } Console.WriteLine("Decrypting: " + cEntry.Name); Directory.CreateDirectory(outFolder); try { if (cEntry.ProductType == "addon") { // copy & decrypt main file string subDir = Path.Combine(outFolder, cEntry.Type); Directory.CreateDirectory(subDir); CopyDirectory(cEntry.FilePath, subDir); DecryptPack(subDir); // 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); 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: " + 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); } } catch (Exception e) { Console.Error.WriteLine("Failed to decrypt: " + cEntry.Name + " " + e.Message); Directory.Delete(outFolder, true); } } Console.WriteLine("Finished."); Console.ReadKey(); } } }