Exemple #1
0
        static void Extract(ExtractOptions options)
        {
            var datFile  = File.ReadAllBytes(options.File);
            var jsonFile = JsonDatFile.FromFile(options.JsonPath);

            Directory.CreateDirectory(options.OutputFolder);

            var datSpan = datFile.AsSpan();

            foreach (var entry in jsonFile.Files)
            {
                var filePath = Path.Combine(options.OutputFolder, entry.Name);

                // Check if first and last byte are within file size.
                if (entry.Offset > datFile.Length || entry.Offset + entry.SizeBytes > datFile.Length)
                {
                    Console.WriteLine($"Warning: Skipping file {filePath} because the start or end of file is outside of the archive.");
                    continue;
                }

                // Write file
                using var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write);
                fileStream.Write(datSpan.Slice(entry.Offset, entry.SizeBytes));
                Console.WriteLine($"Written File {filePath}.");
            }
        }
Exemple #2
0
        static void Pack(PackOptions options)
        {
            var data             = new List <byte>(150 * 1000 * 1000);
            var files            = Directory.GetFiles(options.SourceFolder).ToDictionary(Path.GetFileName, StringComparer.OrdinalIgnoreCase);
            var originalJsonFile = JsonDatFile.FromFile(options.SourceJson);
            var jsonFile         = new JsonDatFile();

            Directory.CreateDirectory(Path.GetDirectoryName(options.JsonPath));
            Directory.CreateDirectory(Path.GetDirectoryName(options.DatPath));

            foreach (var origFile in originalJsonFile.Files)
            {
                if (files.TryGetValue(origFile.Name, out var file))
                {
                    var fileBytes     = File.ReadAllBytes(file);
                    int currentOffset = data.Count;
                    var fileEntry     = new JsonFileEntry(Path.GetFileName(file), fileBytes.Length, currentOffset);

                    data.AddRange(fileBytes);
                    jsonFile.Files.Add(fileEntry);
                    data.AddPadding(2048);
                }
            }

            // Save (Note: Using FileStream to avoid copying large array)
            File.WriteAllText(options.JsonPath, jsonFile.ToFile());
            using var fileStream = new FileStream(options.DatPath, FileMode.Create);
            fileStream.Write(CollectionsMarshal.AsSpan(data));

            Console.WriteLine($"JSON file for injection written to: {options.JsonPath}");
            Console.WriteLine($"New DAT file written to: {options.DatPath}");
        }
Exemple #3
0
        static unsafe void Inject(InjectOptions options)
        {
            var elf      = File.ReadAllBytes(options.File);
            var scanner  = new DatScanner(elf);
            var files    = scanner.FindFiles(options.Dat);
            var jsonFile = JsonDatFile.FromFile(options.JsonPath);

            using var memoryStream         = new MemoryStream(elf, true);
            using var streamReader         = new BufferedStreamReader(memoryStream, 2048);
            using var extendedMemoryStream = new ExtendedMemoryStream(elf, true);

            // Patch all table entries.
            foreach (var offset in files.Keys)
            {
                Console.WriteLine($"Patching table at: {offset:X}, RAM: {scanner.RawToMemoryAddress(offset):X}");

                // Go to 2nd entry and get initial file name write pointer.
                streamReader.Seek(offset, SeekOrigin.Begin);
                streamReader.Read(out DatFileEntry firstEntry);

                // Get file name write pointer.
                streamReader.Peek(out DatFileEntry secondEntry);
                int fileNameWritePointer = scanner.MemoryToRawAddress(secondEntry.NamePtr);

                // Write archive entry
                var newFirstEntry = new DatFileEntry(firstEntry.NamePtr, jsonFile.Files[0].Offset / DatFileEntry.SECTOR_SIZE_BYTES, jsonFile.Files[0].SizeBytes);
                extendedMemoryStream.Seek(offset, SeekOrigin.Begin);
                extendedMemoryStream.Write(newFirstEntry);

                // Now write each file in order, while keeping track of the pointer.
                foreach (var entry in jsonFile.Files)
                {
                    // Make entry for the file.
                    var datEntry = new DatFileEntry(scanner.RawToMemoryAddress(fileNameWritePointer), entry.Offset / DatFileEntry.SECTOR_SIZE_BYTES, entry.SizeBytes);
                    extendedMemoryStream.Write(datEntry);

                    // Get bytes attached to the name (w/ Null Terminator).
                    var alignedTextLength = Utilities.Utilities.RoundUp(entry.Name.Length + 1, 8); // Alignment of 8
                    var nameBytes         = new byte[alignedTextLength];
                    Encoding.ASCII.GetBytes(entry.Name, nameBytes);

                    // Write bytes to pointer.
                    Array.Copy(nameBytes, 0, elf, fileNameWritePointer, nameBytes.Length);

                    // Align text to next predetermined value like in original ELF.
                    fileNameWritePointer += alignedTextLength;
                }
            }

            // Write new executable to file.
            memoryStream.Dispose();
            streamReader.Dispose();
            extendedMemoryStream.Dispose();

            Console.WriteLine($"Writing patched file to: {options.File}");
            File.WriteAllBytes(options.File, elf);
        }
Exemple #4
0
        private static void Verify(VerifyOptions options)
        {
            var jsonFile    = JsonDatFile.FromFile(options.JsonPath);
            var sourceFiles = Directory.GetFiles(options.SourceFolder).ToDictionary(Path.GetFileName, StringComparer.OrdinalIgnoreCase);

            foreach (var file in jsonFile.Files)
            {
                if (sourceFiles.TryGetValue(file.Name, out _))
                {
                    continue;
                }

                Console.WriteLine($"Missing File: {file.Name}");
            }

            Console.WriteLine($"Verify Complete");
        }