McTools/McDecryptor/Program.cs

290 lines
10 KiB
C#

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<Thread> threads = new List<Thread>();
//Now Create all of the directories
foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
{
Thread thrd = new Thread(() =>
{
Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPath));
});
thrd.Priority = ThreadPriority.Highest;
thrd.Start();
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<int> toDecrypt = new List<int>();
while (true)
{
Console.Write("Which do you want to decrypt? ");
try
{
string readText = Console.ReadLine();
if (readText.ToUpper() == "ALL")
{
for(int i = 0; i < total-1; i++)
toDecrypt.Add(i);
break;
}
string[] 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
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();
}
}
}