static void Scan(ScanOptions options) { var data = File.ReadAllBytes(options.File); var scanner = new DatScanner(data); var files = scanner.FindFiles(options.Dat); var json = scanner.GetFiles(files); if (json.Count > 0) { Directory.CreateDirectory(Path.GetDirectoryName(options.OutputPath)); if (options.AllowDuplicates) { for (int x = 0; x < json.Count; x++) { var filePath = Path.GetFileNameWithoutExtension(options.OutputPath) + "_" + ".json"; var jsonText = json[x].ToFile(); File.WriteAllText(filePath, jsonText); PrintFileOutput(filePath); } } else { var jsonFile = json[0]; var jsonText = jsonFile.ToFile(); File.WriteAllText(options.OutputPath, jsonText); PrintFileOutput(options.OutputPath); } } void PrintFileOutput(string path) { Console.WriteLine($"Saved file to {path}"); } }
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); }