diff --git a/DotNetCTFDumper.sln b/DotNetCTFDumper.sln index 8bc3e90..e66fbb3 100644 --- a/DotNetCTFDumper.sln +++ b/DotNetCTFDumper.sln @@ -8,13 +8,19 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {86D99F9E-98FB-4E50-AB68-F5C115850C33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {86D99F9E-98FB-4E50-AB68-F5C115850C33}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86D99F9E-98FB-4E50-AB68-F5C115850C33}.Debug|Any CPU.ActiveCfg = Debug|x64 + {86D99F9E-98FB-4E50-AB68-F5C115850C33}.Debug|Any CPU.Build.0 = Debug|x64 + {86D99F9E-98FB-4E50-AB68-F5C115850C33}.Debug|x64.ActiveCfg = Debug|x64 + {86D99F9E-98FB-4E50-AB68-F5C115850C33}.Debug|x64.Build.0 = Debug|x64 {86D99F9E-98FB-4E50-AB68-F5C115850C33}.Release|Any CPU.ActiveCfg = Release|Any CPU {86D99F9E-98FB-4E50-AB68-F5C115850C33}.Release|Any CPU.Build.0 = Release|Any CPU + {86D99F9E-98FB-4E50-AB68-F5C115850C33}.Release|x64.ActiveCfg = Release|x64 + {86D99F9E-98FB-4E50-AB68-F5C115850C33}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/NetMFAPatcher/DotNetCTFDumper.csproj b/NetMFAPatcher/DotNetCTFDumper.csproj index 67b38f3..9e5fc72 100644 --- a/NetMFAPatcher/DotNetCTFDumper.csproj +++ b/NetMFAPatcher/DotNetCTFDumper.csproj @@ -48,6 +48,29 @@ prompt 4 + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + On + 7.3 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + 7.3 + prompt + MinimumRecommendedRules.ruleset + true + E:\ClickTFReader-master\DUMP\fnaf-world\CHUNKS\Ionic.Zlib.dll @@ -67,6 +90,8 @@ + + diff --git a/NetMFAPatcher/Program.cs b/NetMFAPatcher/Program.cs index cbfc54f..083a91e 100644 --- a/NetMFAPatcher/Program.cs +++ b/NetMFAPatcher/Program.cs @@ -5,6 +5,8 @@ using System; using System.IO; using System.Collections; using NetMFAPatcher.mfa; +using NetMFAPatcher.utils; +using System.Runtime.InteropServices; namespace NetMFAPatcher { @@ -33,13 +35,15 @@ namespace NetMFAPatcher bool DumpImages=true; bool DumpSounds=true; bool CreateFolders=true; + + if (args.Length == 0) { if (true) { - ByteIO mfaReader = new ByteIO(@"E:\SUPERDECOMPILER\Tests\mmftest.mfa", FileMode.Open); + ByteIO mfaReader = new ByteIO(@"E:\DotNetCTF\Tests\mmftest.mfa", FileMode.Open); var mfa = new MFA(mfaReader); mfa.Read(); diff --git a/NetMFAPatcher/Utils/ByteIO.cs b/NetMFAPatcher/Utils/ByteIO.cs index a7a8d48..4eb94bc 100644 --- a/NetMFAPatcher/Utils/ByteIO.cs +++ b/NetMFAPatcher/Utils/ByteIO.cs @@ -99,6 +99,7 @@ namespace NetMFAPatcher.Utils return str; } + public string ReadWideString(int length = -1) { diff --git a/NetMFAPatcher/Utils/Decompressor.cs b/NetMFAPatcher/Utils/Decompressor.cs index 2d626ca..4784828 100644 --- a/NetMFAPatcher/Utils/Decompressor.cs +++ b/NetMFAPatcher/Utils/Decompressor.cs @@ -31,6 +31,11 @@ namespace NetMFAPatcher.Utils { return new ByteIO(decompress_block(image_data, v, decompressed_size)); } + + internal static byte[] decompress_block(ByteIO data, uint compressed_size, uint decompressedSize) + { + throw new NotImplementedException(); + } } diff --git a/NetMFAPatcher/Utils/Decryption.cs b/NetMFAPatcher/Utils/Decryption.cs index 409bbe1..97faf19 100644 --- a/NetMFAPatcher/Utils/Decryption.cs +++ b/NetMFAPatcher/Utils/Decryption.cs @@ -1,6 +1,8 @@ -using System; +using NetMFAPatcher.Utils; +using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -8,5 +10,74 @@ namespace NetMFAPatcher.utils { class Decryption { + public static byte[] key; + public static void MakeKey(string STitle, string SCopyright,string SProject, byte MagicChar) + { + byte[] nameBytes = Encoding.ASCII.GetBytes(STitle); + var name = Marshal.AllocHGlobal(STitle.Length); + Marshal.Copy(nameBytes, 0, name, STitle.Length); + + byte[] copyrightBytes = Encoding.ASCII.GetBytes(SCopyright); + var copyright = Marshal.AllocHGlobal(SCopyright.Length); + Marshal.Copy(copyrightBytes, 0, copyright, SCopyright.Length); + + byte[] filenameBytes = Encoding.ASCII.GetBytes(SProject); + var pathfilename = Marshal.AllocHGlobal(SProject.Length); + Marshal.Copy(filenameBytes, 0, pathfilename, SProject.Length); + + var ptr = Decryption.make_key(name, copyright, pathfilename, MagicChar); + + byte[] Key = new byte[257]; + Marshal.Copy(ptr, Key, 0, 257); + Marshal.FreeHGlobal(name); + Marshal.FreeHGlobal(copyright); + Marshal.FreeHGlobal(pathfilename); + key = Key; + //some hardcoded checks for SL + + + + if (Console.ReadKey().Key==ConsoleKey.N) + { + if(key[73] == 0xB2) + { + return; + } + MakeKey("Sister Location", "Scott Cawthon", @"C:\Users\Scott\Desktop\FNAF 5\FNaF 5-157.mfa", 54); + } + } + + + public static byte[] DecodeMode3(byte[] ChunkData, int ChunkSize,int ChunkID, byte MagicChar) + { + var reader = new ByteIO(ChunkData); + var DecompressedSize = reader.ReadUInt32(); + + var chunkData = reader.ReadBytes((int)reader.Size()); + chunkData[0] ^= (byte)(((byte)ChunkID & 0xFF) ^ ((byte)ChunkID >> 0x8)); + var data = new ByteIO(DecodeChunk(chunkData,ChunkSize,MagicChar)); + var compressed_size = data.ReadUInt32(); + + return Decompressor.decompress_block(data, (int)compressed_size, (int)DecompressedSize); + } + public static byte[] DecodeChunk(byte[] ChunkData, int ChunkSize,byte MagicChar) + { + //Console.WriteLine("Decoding: "+ChunkData.Log(false,"X2")); + IntPtr InputChunkPtr = Marshal.AllocHGlobal(ChunkSize); + Marshal.Copy(ChunkData, 0, InputChunkPtr, ChunkSize-4); + var OutputChunkPtr = decode_chunk(InputChunkPtr, ChunkSize, MagicChar); + byte[] DecodedChunk = new byte[ChunkSize]; + Marshal.Copy(OutputChunkPtr, DecodedChunk,0,ChunkSize); + //Console.WriteLine("Result: " + DecodedChunk.Log(false, "X2")); + return DecodedChunk; + + + } + [DllImport("Decrypter-x64.dll", EntryPoint = "decode_chunk", CharSet = CharSet.Auto)] + public static extern IntPtr decode_chunk(IntPtr chunk_data,int chunk_size, byte magic_char); + [DllImport("Decrypter-x64.dll", EntryPoint = "make_key", CharSet = CharSet.Auto)] + public static extern IntPtr make_key(IntPtr c_title, IntPtr c_copyright, IntPtr c_project, byte magic_char); + + } } diff --git a/NetMFAPatcher/mmfparser/ChunkList.cs b/NetMFAPatcher/mmfparser/ChunkList.cs index fa54ea2..14414e1 100644 --- a/NetMFAPatcher/mmfparser/ChunkList.cs +++ b/NetMFAPatcher/mmfparser/ChunkList.cs @@ -1,4 +1,5 @@ using NetMFAPatcher.chunkloaders; +using NetMFAPatcher.utils; using NetMFAPatcher.Utils; using System; using System.Collections.Generic; @@ -9,7 +10,7 @@ namespace NetMFAPatcher.mmfparser { public class ChunkList { - List chunks = new List(); + public List chunks = new List(); public bool verbose = true; public void Read(ByteIO exeReader) @@ -30,6 +31,14 @@ namespace NetMFAPatcher.mmfparser } chunks.Add(chunk); + if (chunk.id == 8750) + { + chunk.BuildKey(); + } + if (chunk.id == 13108) + { + + } if (chunk.id == 32639) break; //LAST chunkID } @@ -73,10 +82,12 @@ namespace NetMFAPatcher.mmfparser switch (flag) { case ChunkFlags.Encrypted: - chunk_data = exeReader.ReadBytes(size); + + chunk_data = Decryption.DecodeChunk(exeReader.ReadBytes(size),size,54); break; case ChunkFlags.CompressedAndEncrypyed: - chunk_data = exeReader.ReadBytes(size); + //exeReader.ReadBytes(size); + chunk_data = Decryption.DecodeMode3(exeReader.ReadBytes(size), size,id, 54); break; case ChunkFlags.Compressed: chunk_data = Decompressor.Decompress(exeReader); @@ -94,9 +105,10 @@ namespace NetMFAPatcher.mmfparser } if(verbose) { - Print(false); + //Print(false); } + } public void Print(bool extented) @@ -106,8 +118,7 @@ namespace NetMFAPatcher.mmfparser Logger.Log($"Chunk: {name} ({uid})", true, ConsoleColor.DarkCyan); Logger.Log($" ID: {id} - 0x{id.ToString("X")}", true, ConsoleColor.DarkCyan); Logger.Log($" Flags: {flag}", true, ConsoleColor.DarkCyan); - Logger.Log($" Loader: {(loader != null ? loader.GetType().Name : "Empty Loader")}", true, - ConsoleColor.DarkCyan); + Logger.Log($" Loader: {(loader != null ? loader.GetType().Name : "Empty Loader")}", true,ConsoleColor.DarkCyan); Logger.Log($" Size: {size} B", true, ConsoleColor.DarkCyan); Logger.Log($" Decompressed Size: {decompressed_size} B", true, ConsoleColor.DarkCyan); Logger.Log("---------------------------------------------", true, ConsoleColor.DarkCyan); @@ -122,6 +133,20 @@ namespace NetMFAPatcher.mmfparser Logger.Log("---------------------------------------------", true, ConsoleColor.DarkCyan); } + } + public void BuildKey() + { + string title = ""; + string copyright = ""; + string project = ""; + title = "Sister Location";//chunk_list.get_chunk().value; + copyright = "Scott Cawthon";//chunk_list.get_chunk().value; + project = @"C:\Users\Scott\Desktop\FNAF 5\FNaF 5-157.mfa";//chunk_list.get_chunk().value; + Decryption.MakeKey(title,copyright,project,54); + Logger.Log("New Key!"); + + + } } @@ -177,6 +202,9 @@ namespace NetMFAPatcher.mmfparser case 13107: loader = new Frame(chunk); break; + case 13108: + loader = new FrameHeader(chunk); + break; case 26214: loader = new ImageBank(chunk); break; diff --git a/NetMFAPatcher/mmfparser/MFA.cs b/NetMFAPatcher/mmfparser/MFA.cs index 586af7c..14b9495 100644 --- a/NetMFAPatcher/mmfparser/MFA.cs +++ b/NetMFAPatcher/mmfparser/MFA.cs @@ -19,6 +19,26 @@ namespace NetMFAPatcher.mfa { class MFA : DataLoader { + public int mfaBuild; + public int product; + public int buildVersion; + + public string name; + public string description; + public string path; + public string author; + public string copyright; + public string company; + public string version; + + public byte[] stamp; + + public int windowX; + public int windowY; + + public ValueList globalValues; + public ValueList globalStrings; + public override void Print() { @@ -31,56 +51,55 @@ namespace NetMFAPatcher.mfa public override void Read() { Logger.Log($"MFA HEADER:{reader.ReadAscii(4)}"); - var mfaBuild = reader.ReadInt32(); - var product = reader.ReadInt32(); - var buildVersion = reader.ReadInt32(); + mfaBuild = reader.ReadInt32(); + product = reader.ReadInt32(); + buildVersion = reader.ReadInt32(); - var name = reader.ReadAscii(reader.ReadInt32()); - var description = reader.ReadAscii(reader.ReadInt32()); - var path = reader.ReadAscii(reader.ReadInt32()); - var stamp = reader.ReadBytes(reader.ReadInt32()); + name = reader.ReadAscii(reader.ReadInt32()); + description = reader.ReadAscii(reader.ReadInt32()); + path = reader.ReadAscii(reader.ReadInt32()); + stamp = reader.ReadBytes(reader.ReadInt32()); - Logger.Log(reader.ReadAscii(4)); + if(reader.ReadAscii(4)!="ATNF") + { + throw new Exception("Invalid Font Bank"); + } var fonts = new FontBank(reader); fonts.Read(); - Logger.Log("FontsDone\n"); - Logger.Log(reader.ReadAscii(4)); + if (reader.ReadAscii(4) != "APMS") + { + throw new Exception("Invalid Sound Bank"); + } var sounds = new SoundBank(reader); sounds.isCompressed = false; sounds.Read(); - Logger.Log("SoundsDone\n"); - Logger.Log(reader.ReadAscii(4)); + if (reader.ReadAscii(4) != "ASUM") + { + throw new Exception("Invalid Music Bank"); + } var music = new MusicBank(reader); music.Read(); + //Images&Icons are not implemented - Logger.Log("MusicDone\n"); - - //Logger.Log(reader.ReadAscii(4)); - //var icons = new AGMIBank(reader); - //icons.Read(); - - //Logger.Log("IconDone\n"); + reader.Seek(1191182);//hardcoded offset - //Logger.Log(reader.ReadAscii(4)); + reader.ReadInt32();//checkDefault + author = reader.ReadAscii(reader.ReadInt32()); + reader.ReadInt32();//checkDefault + copyright = reader.ReadAscii(reader.ReadInt32()); + reader.ReadInt32();//checkDefault - - reader.Seek(1191186); - - var author = reader.ReadAscii(reader.ReadInt32()); - reader.ReadInt32(); - var copyright = reader.ReadAscii(reader.ReadInt32()); - reader.ReadInt32(); - var company = reader.ReadAscii(reader.ReadInt32()); - var version = reader.ReadAscii(reader.ReadInt32()); - var windowX = reader.ReadInt32(); - var windowY = reader.ReadInt32(); + company = reader.ReadAscii(reader.ReadInt32()); + version = reader.ReadAscii(reader.ReadInt32()); + windowX = reader.ReadInt32(); + windowY = reader.ReadInt32(); var borderColor = reader.ReadBytes(4); var displayFlags = reader.ReadInt32(); var graphicFlags = reader.ReadInt32(); @@ -122,9 +141,9 @@ namespace NetMFAPatcher.mfa - var globalValues = new ValueList(reader); + globalValues = new ValueList(reader); globalValues.Read(); - var globalStrings = new ValueList(reader); + globalStrings = new ValueList(reader); globalStrings.Read(); var globalEvents = reader.ReadBytes(reader.ReadInt32()); var graphicMode = reader.ReadInt32(); @@ -144,7 +163,7 @@ namespace NetMFAPatcher.mfa var handleQ = reader.ReadInt32(); } var extCount = reader.ReadInt32(); - for (int i = 0; i < extCount; i++) + for (int i = 0; i < extCount; i++)//extensions { var handleE = reader.ReadInt32(); var filenameE = reader.ReadAscii(reader.ReadInt32()); @@ -166,7 +185,7 @@ namespace NetMFAPatcher.mfa reader.Seek(item); var testframe = new Frame(reader); testframe.Read(); - Console.WriteLine($"Done reading frame '{testframe.name}'"); + } diff --git a/NetMFAPatcher/mmfparser/chunkloaders/Frame.cs b/NetMFAPatcher/mmfparser/chunkloaders/Frame.cs index b8abf69..1ecf0ce 100644 --- a/NetMFAPatcher/mmfparser/chunkloaders/Frame.cs +++ b/NetMFAPatcher/mmfparser/chunkloaders/Frame.cs @@ -2,6 +2,7 @@ using NetMFAPatcher.Utils; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -36,11 +37,9 @@ namespace NetMFAPatcher.chunkloaders public string name; public string password; public int width; - public int height; - - //background, idk what type is it - //flags + public byte[] background; + public int flags; int top; int bottom; int left; @@ -49,6 +48,10 @@ namespace NetMFAPatcher.chunkloaders public override void Print() { + Logger.Log($"Frame: {name}", true, ConsoleColor.Green); + Logger.Log($" Password: {(password!=null ? password : "None")}", true, ConsoleColor.Green); + Logger.Log($" Size: {width}x{height}", true, ConsoleColor.Green); + Logger.Log($"-------------------------", true, ConsoleColor.Green); } public override void Read() @@ -57,9 +60,40 @@ namespace NetMFAPatcher.chunkloaders var chunks = new ChunkList(); chunks.verbose = false; - //chunks.Read(FrameReader); + chunks.Read(FrameReader); + + var name = chunks.get_chunk(); + if (name != null) + { + this.name = name.value; + } + var password = chunks.get_chunk(); + if (password != null) + { + this.password = password.value; + } + var header = chunks.get_chunk(); + width = header.width; + height = header.height; + background = header.background; + flags = header.flags; + + + + + + + foreach (var item in chunks.chunks) + { + Directory.CreateDirectory($"{Program.DumpPath}\\CHUNKS\\FRAMES\\{this.name}"); + string path = $"{Program.DumpPath}\\CHUNKS\\FRAMES\\{this.name}\\{chunk.name}.chunk"; + File.WriteAllBytes(path, item.chunk_data); + + } + + + - //var name = chunks.get_chunk(); } public Frame(ByteIO reader) : base(reader) @@ -70,4 +104,62 @@ namespace NetMFAPatcher.chunkloaders { } } + + class FrameHeader : ChunkLoader + { + public int width; + public int height; + public int flags; + public byte[] background; + public FrameHeader(ByteIO reader) : base(reader) + { + } + + public FrameHeader(ChunkList.Chunk chunk) : base(chunk) + { + } + + public override void Print() + { + + } + + public override void Read() + { + width = reader.ReadInt32(); + height = reader.ReadInt32(); + background = reader.ReadBytes(4); + flags = (int)reader.ReadUInt32(); + + + + } + } + class ObjectInstances : ChunkLoader + { + public int width; + public int height; + + public ObjectInstances(ByteIO reader) : base(reader) + { + } + + public ObjectInstances(ChunkList.Chunk chunk) : base(chunk) + { + } + + public override void Print() + { + + } + + public override void Read() + { + + + + } + } + + } \ No newline at end of file diff --git a/NetMFAPatcher/mmfparser/chunkloaders/FrameItems.cs b/NetMFAPatcher/mmfparser/chunkloaders/FrameItems.cs new file mode 100644 index 0000000..67d10b6 --- /dev/null +++ b/NetMFAPatcher/mmfparser/chunkloaders/FrameItems.cs @@ -0,0 +1,25 @@ +using NetMFAPatcher.chunkloaders; +using NetMFAPatcher.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NetMFAPatcher.mmfparser.chunkloaders +{ + class FrameItems : ChunkLoader + { + public FrameItems(ChunkList.Chunk chunk) : base(chunk) { } + public FrameItems(ByteIO reader) : base(reader) { } + public override void Print() + { + + } + + public override void Read() + { + + } + } +} diff --git a/NetMFAPatcher/mmfparser/chunkloaders/ObjectInfo.cs b/NetMFAPatcher/mmfparser/chunkloaders/ObjectInfo.cs new file mode 100644 index 0000000..3941eba --- /dev/null +++ b/NetMFAPatcher/mmfparser/chunkloaders/ObjectInfo.cs @@ -0,0 +1,25 @@ +using NetMFAPatcher.chunkloaders; +using NetMFAPatcher.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NetMFAPatcher.mmfparser.chunkloaders +{ + class ObjectInfo : ChunkLoader + { + public ObjectInfo(ChunkList.Chunk chunk) : base(chunk) { } + public ObjectInfo(ByteIO reader) : base(reader) { } + public override void Print() + { + + } + + public override void Read() + { + + } + } +} diff --git a/NetMFAPatcher/mmfparser/chunkloaders/StringChunk.cs b/NetMFAPatcher/mmfparser/chunkloaders/StringChunk.cs index f5974af..2430dee 100644 --- a/NetMFAPatcher/mmfparser/chunkloaders/StringChunk.cs +++ b/NetMFAPatcher/mmfparser/chunkloaders/StringChunk.cs @@ -21,7 +21,7 @@ namespace NetMFAPatcher.chunkloaders public override void Print() { - Logger.Log($"{chunk.name} contains: {value}\n",true,ConsoleColor.DarkCyan); + //Logger.Log($"{chunk.name} contains: {value}\n",true,ConsoleColor.DarkCyan); } diff --git a/NetMFAPatcher/mmfparser/mfaloaders/Frame.cs b/NetMFAPatcher/mmfparser/mfaloaders/Frame.cs index 5e4e7f7..58f9b3e 100644 --- a/NetMFAPatcher/mmfparser/mfaloaders/Frame.cs +++ b/NetMFAPatcher/mmfparser/mfaloaders/Frame.cs @@ -12,6 +12,10 @@ namespace NetMFAPatcher.mmfparser.mfaloaders class Frame : DataLoader { public string name = "ERROR"; + public int sizeX; + public int sizeY; + public Color background; + public int maxObjects; public Frame(ByteIO reader) : base(reader) { @@ -27,11 +31,11 @@ namespace NetMFAPatcher.mmfparser.mfaloaders { var handle = reader.ReadInt32(); name = reader.ReadAscii(reader.ReadInt32()); - var sizeX = reader.ReadInt32(); - var sizeY = reader.ReadInt32(); + sizeX = reader.ReadInt32(); + sizeY = reader.ReadInt32(); var background = reader.ReadColor(); var flags = reader.ReadInt32(); - var maxObjects = reader.ReadInt32(); + maxObjects = reader.ReadInt32(); var password = reader.ReadAscii(reader.ReadInt32()); reader.Skip(4); var lastViewedX = reader.ReadInt32();