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