Exemplo n.º 1
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);
        }