diff --git a/.vs/RMDEC/v16/.suo b/.vs/RMDEC/v16/.suo new file mode 100644 index 0000000..a278c71 Binary files /dev/null and b/.vs/RMDEC/v16/.suo differ diff --git a/RMDEC/MVProject.cs b/RMDEC/MVProject.cs index ff866ab..19c4075 100644 --- a/RMDEC/MVProject.cs +++ b/RMDEC/MVProject.cs @@ -72,8 +72,11 @@ namespace RMDEC } set { - jsonData.hasEncryptedImages = value; - File.WriteAllText(systemJsonFile, jsonData.ToString(Formatting.None)); + if(jsonData != null) + { + jsonData.hasEncryptedImages = value; + File.WriteAllText(systemJsonFile, jsonData.ToString(Formatting.None)); + } encryptedImages = value; } } @@ -86,8 +89,11 @@ namespace RMDEC } set { - jsonData.hasEncryptedAudio = value; - File.WriteAllText(systemJsonFile, jsonData.ToString(Formatting.None)); + if (jsonData != null) + { + jsonData.hasEncryptedAudio = value; + File.WriteAllText(systemJsonFile, jsonData.ToString(Formatting.None)); + } encryptedAudio = value; } } @@ -109,7 +115,7 @@ namespace RMDEC } List byteList = new List(); - + for (int i = 0; i < HexStr.Length; i += 2) { string curHex = HexStr.Substring(i, 2); @@ -123,7 +129,196 @@ namespace RMDEC } + private static byte[] guessKey(string path) // Incase you think your smart + { + string[] mzPngs = Directory.GetFiles(path, "*._png", SearchOption.AllDirectories); + string[] mvPngs = Directory.GetFiles(path, "*.rpgmvp", SearchOption.AllDirectories); + string[] mzM4as = Directory.GetFiles(path, "*._m4a", SearchOption.AllDirectories); + string[] mvM4as = Directory.GetFiles(path, "*.rpgmvm", SearchOption.AllDirectories); + List files = new List(); + files.AddRange(mzPngs); + files.AddRange(mvPngs); + + files.AddRange(mzM4as); + files.AddRange(mvM4as); + + if (files.Count <= 0) + return new byte[0x10]; + + Random rng = new Random(); + int index = rng.Next(0, files.Count); + string file = files[index]; + + byte[] encryptedHeader = new byte[0x10]; + FileStream fs = File.OpenRead(file); + fs.Seek(0x10, SeekOrigin.Begin); + fs.Read(encryptedHeader, 0x00, 0x10); + fs.Close(); + + string filetype = Path.GetExtension(file).ToLower(); + byte[] pngHeader = new byte[0x10] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52 }; + byte[] m4aHeader = new byte[0x10] { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41, 0x20, 0x00, 0x00, 0x00, 0x00 }; + + if (filetype == "._png" || filetype == ".rpgmvp") { + byte[] key = RMProject.Xor(encryptedHeader, pngHeader); + if(!tryKey(path, key)) + { + throw new Exception("Cannot find key (ITS TOO STRONG!)"); + } + else + { + return key; + } + } + else if (filetype == "._m4a" || filetype == ".rpgmvm") + { + byte[] key = RMProject.Xor(encryptedHeader, m4aHeader); + if (!tryKey(path, key)) + { + throw new Exception("Cannot find key (ITS TOO STRONG!)"); + } + else + { + return key; + } + } + // OGG Header is not 0x10 bytes unfortunately. + + throw new Exception("Cannot find key (ITS TOO STRONG!)"); + } + private static bool tryKey(string path, byte[] key) // Checks if the key really works + { + string[] mzPngs = Directory.GetFiles(path, "*._png", SearchOption.AllDirectories); + string[] mvPngs = Directory.GetFiles(path, "*.rpgmvp", SearchOption.AllDirectories); + string[] mzM4as = Directory.GetFiles(path, "*._m4a", SearchOption.AllDirectories); + string[] mvM4as = Directory.GetFiles(path, "*.rpgmvm", SearchOption.AllDirectories); + string[] mzOggs = Directory.GetFiles(path, "*._ogg", SearchOption.AllDirectories); + string[] mvOggs = Directory.GetFiles(path, "*.rpgmvo", SearchOption.AllDirectories); + + List files = new List(); + files.AddRange(mzPngs); + files.AddRange(mvPngs); + + files.AddRange(mzM4as); + files.AddRange(mvM4as); + + files.AddRange(mzOggs); + files.AddRange(mvOggs); + + if (files.Count <= 0) + return false; + + Random rng = new Random(); + int index = rng.Next(0, files.Count); + string file = files[index]; + + byte[] encryptedHeader = new byte[0x10]; + FileStream fs = File.OpenRead(file); + fs.Seek(0x10, SeekOrigin.Begin); + fs.Read(encryptedHeader, 0x00, 0x10); + fs.Close(); + + byte[] plaintextHeader = RMProject.Xor(encryptedHeader, key); + + string filetype = Path.GetExtension(file).ToLower(); + if (filetype == "._png" || filetype == ".rpgmvp") + if (Encoding.ASCII.GetString(plaintextHeader).Contains("PNG")) + return true; + else + return false; + else if (filetype == "._ogg" || filetype == ".rpgmvo") + if (Encoding.ASCII.GetString(plaintextHeader).StartsWith("OggS")) + return true; + else + return false; + else if (filetype == "._m4a" || filetype == ".rpgmvm") + if (Encoding.ASCII.GetString(plaintextHeader).Contains("ftypM4A")) + return true; + else + return false; + else // No encrypted files? + return false; + } + + private static MVProject GuessProject(string folder) + { + MVProject mvp = new MVProject(); + + mvp.MZ = false; + mvp.encryptedImages = false; + mvp.encryptedAudio = false; + folder = Path.GetDirectoryName(Path.GetDirectoryName(folder)); + string[] mzPngs = Directory.GetFiles(folder, "*._png", SearchOption.AllDirectories); + string[] mvPngs = Directory.GetFiles(folder, "*.rpgmvp", SearchOption.AllDirectories); + string[] mzM4as = Directory.GetFiles(folder, "*._m4a", SearchOption.AllDirectories); + string[] mvM4as = Directory.GetFiles(folder, "*.rpgmvm", SearchOption.AllDirectories); + string[] mzOggs = Directory.GetFiles(folder, "*._ogg", SearchOption.AllDirectories); + string[] mvOggs = Directory.GetFiles(folder, "*.rpgmvo", SearchOption.AllDirectories); + + string[] mzArtifacts = Directory.GetFiles(folder, "rmmz_*", SearchOption.AllDirectories); + string[] mvArtifacts = Directory.GetFiles(folder, "rpg_*", SearchOption.AllDirectories); + + // Look for PNG + if (mvPngs.Length > 0) + { + mvp.MZ = false; + mvp.encryptedImages = true; + } + else if (mzPngs.Length > 0) + { + mvp.MZ = true; + mvp.encryptedImages = true; + } + + // Look for M4A + if(mvM4as.Length > 0) + { + mvp.MZ = false; + mvp.encryptedAudio = true; + } + else if (mzM4as.Length > 0) + { + mvp.MZ = true; + mvp.encryptedAudio = true; + } + + // Look for OGG + if (mvOggs.Length > 0) + { + mvp.MZ = false; + mvp.encryptedAudio = true; + } + else if (mzOggs.Length > 0) + { + mvp.MZ = true; + mvp.encryptedAudio = true; + } + + // Determine MV or MZ + if(mzArtifacts.Length > 0) + { + mvp.MZ = true; + mvp.filePath = Path.GetDirectoryName(Path.GetDirectoryName(mzArtifacts[0])); + } + else if(mvArtifacts.Length > 0) + { + mvp.MZ = false; + mvp.filePath = Path.GetDirectoryName(Path.GetDirectoryName(mvArtifacts[0])); + } + + if(mvp.IsEncrypted) + { + byte[] key = guessKey(folder); + mvp.encryptionKey = key; + mvp.isKeySet = true; + } + + mvp.systemJsonFile = null; + mvp.jsonData = null; + + return mvp; + } private void genEncryptionKey() { @@ -139,13 +334,17 @@ namespace RMDEC //Public functions public static MVProject ParseSystemJson(string path) { - if (File.Exists(path)) + + //Check if valid system.json + + if (File.Exists(path) && Path.GetExtension(path).ToLower() == ".json") { + + MVProject mvp = new MVProject(); + string jsonStr = File.ReadAllText(path, Encoding.UTF8); dynamic systemJson = JObject.Parse(jsonStr); - //Check if valid system.json - MVProject mvp = new MVProject(); if (systemJson.gameTitle != null) { @@ -153,7 +352,7 @@ namespace RMDEC } else { - throw new InvalidDataException("Not a valid system.json!"); + return GuessProject(path); } if (systemJson.hasEncryptedAudio != null) @@ -169,8 +368,18 @@ namespace RMDEC if (systemJson.encryptionKey != null) { string encKey = systemJson.encryptionKey; - mvp.encryptionKey = hexStr2Bytes(encKey); - mvp.isKeySet = true; + byte[] key = hexStr2Bytes(encKey); + if(tryKey(Path.GetDirectoryName(Path.GetDirectoryName(path)), key)) + { + mvp.encryptionKey = key; + mvp.isKeySet = true; + } + else + { + key = guessKey(Path.GetDirectoryName(Path.GetDirectoryName(path))); + mvp.encryptionKey = key; + mvp.isKeySet = true; + } } mvp.filePath = Path.GetDirectoryName(Path.GetDirectoryName(path)); @@ -188,18 +397,21 @@ namespace RMDEC mvp.systemJsonFile = path; mvp.jsonData = systemJson; - return mvp; + + return mvp; } else { - throw new FileNotFoundException(path + " was not found!"); + return GuessProject(path); } - } - public void EncryptFile(Stream inStream, Stream outStream) + public void EncryptFile(Stream inStream, Stream outStream, byte[] key = null) { + if (key == null) + key = EncryptionKey; + outStream.Seek(0x00, SeekOrigin.Begin); outStream.SetLength(0x00); @@ -216,12 +428,15 @@ namespace RMDEC byte[] plaintextHeader = new byte[0x10]; inStream.Read(plaintextHeader, 0x00, 0x10); - byte[] encryptedHeader = RMProject.Xor(plaintextHeader, EncryptionKey); + byte[] encryptedHeader = RMProject.Xor(plaintextHeader, key); outStream.Write(encryptedHeader, 0x00, encryptedHeader.Length); inStream.CopyTo(outStream); } - public void DecryptFile(Stream inStream, Stream outStream) + public void DecryptFile(Stream inStream, Stream outStream, byte[] key=null) { + if (key == null) + key = EncryptionKey; + inStream.Seek(0x00, SeekOrigin.Begin); byte[] magic = new byte[0x05]; @@ -237,7 +452,7 @@ namespace RMDEC byte[] encryptedHeader = new byte[0x10]; inStream.Read(encryptedHeader, 0x00, 0x10); - byte[] plaintextHeader = RMProject.Xor(encryptedHeader, EncryptionKey); + byte[] plaintextHeader = RMProject.Xor(encryptedHeader, key); outStream.Seek(0x00, SeekOrigin.Begin); outStream.SetLength(0); diff --git a/RMDEC/projectSelector.cs b/RMDEC/projectSelector.cs index 71f31ab..d00a8ed 100644 --- a/RMDEC/projectSelector.cs +++ b/RMDEC/projectSelector.cs @@ -23,12 +23,12 @@ namespace RMDEC this.Cursor = Cursors.Arrow; } - private void tryAddProject(string projectFile) + private bool tryAddProject(string projectFile) { string relativeName = projectFile.Remove(0,projectDir.Text.Length + 1); string extension = Path.GetExtension(projectFile).ToLower(); - if (extension == ".json") + if (extension == ".json" || extension == ".js" || extension == ".png") { try { @@ -40,7 +40,7 @@ namespace RMDEC projectList.Items.Add("[RMMZ] - " + proj.GameTitle + " - " + relativeName); selectButton.Enabled = true; } - catch (Exception) { } + catch (Exception) { return false; } } else if (extension == ".rgss3a") { @@ -51,10 +51,10 @@ namespace RMDEC projectList.Items.Add("[RMVXA] - " + proj.GameTitle + " - " + relativeName); selectButton.Enabled = true; } - catch (Exception) { } + catch (Exception) { return false; } } - + return true; } private void updateProjectList(string projectDir) { @@ -72,13 +72,16 @@ namespace RMDEC { foreach (string fileEntry in fileList) { - if (Path.GetFileName(fileEntry) == "System.json" || Path.GetExtension(fileEntry).ToLower() == ".rgss3a") + bool shouldBreak = false; + if (Path.GetFileName(fileEntry).ToLower() == "system.json" || Path.GetFileName(fileEntry).ToLower().StartsWith("rmmz_core") || Path.GetFileName(fileEntry).ToLower().StartsWith("rpg_core") || Path.GetFileName(fileEntry).ToLower().StartsWith("icon.png") || Path.GetExtension(fileEntry).ToLower() == ".rgss3a") { Invoke((Action)delegate { - tryAddProject(fileEntry); + shouldBreak = tryAddProject(fileEntry); }); } + if (shouldBreak) + break; } } catch (Exception) { };