diff --git a/Dalamud.Bootstrap/Bootstrapper.cs b/Dalamud.Bootstrap/Bootstrapper.cs index c4a08234c..2f1788833 100644 --- a/Dalamud.Bootstrap/Bootstrapper.cs +++ b/Dalamud.Bootstrap/Bootstrapper.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.IO.Pipes; +using System.Text.RegularExpressions; using CoreHook.BinaryInjection.RemoteInjection; using CoreHook.BinaryInjection.RemoteInjection.Configuration; using CoreHook.IPC.Platform; @@ -61,7 +62,7 @@ namespace Dalamud.Bootstrap var newTick = (uint)Environment.TickCount; var newKey = newTick & 0xFFFF_0000; // only the high nibble is used - + var newArgument = argument .Remove("T") .Add("T", $"{newTick}") @@ -72,6 +73,9 @@ namespace Dalamud.Bootstrap // TODO: launch new exe with the argument from encryptedArgument.ToString() // TODO: we also need to figure out where the exe is located + // This is just for poc purpose. + System.Diagnostics.Process.Start(exePath, encryptedArgument.ToString()); + process.Terminate(); } @@ -93,12 +97,12 @@ namespace Dalamud.Bootstrap { var arguments = process.ReadArguments(); - if (arguments.Length < 1) + if (arguments.Length < 2) { throw new BootstrapException($"Process id {process.GetPid()} does not have any arguments to parse."); } - var argument = arguments[0]; + var argument = arguments[1]; if (EncryptedArgument.TryParse(argument, out var encryptedArgument)) { diff --git a/Dalamud.Bootstrap/Dalamud.Bootstrap.csproj b/Dalamud.Bootstrap/Dalamud.Bootstrap.csproj index 17ed9d49c..900e7ad8e 100644 --- a/Dalamud.Bootstrap/Dalamud.Bootstrap.csproj +++ b/Dalamud.Bootstrap/Dalamud.Bootstrap.csproj @@ -9,8 +9,9 @@ + - + diff --git a/Dalamud.Bootstrap/SqexArg/ArgumentBuilder.cs b/Dalamud.Bootstrap/SqexArg/ArgumentBuilder.cs index 0ef3e210f..edc84c0b5 100644 --- a/Dalamud.Bootstrap/SqexArg/ArgumentBuilder.cs +++ b/Dalamud.Bootstrap/SqexArg/ArgumentBuilder.cs @@ -13,14 +13,19 @@ namespace Dalamud.Bootstrap.SqexArg m_dict = new Dictionary(); } + public ArgumentBuilder(IEnumerable> collection) + { + m_dict = new Dictionary(collection); + } + /// /// Creates an argument builder from the argument (e.g. /T =1234) /// /// /// - public static ArgumentBuilder Parse(string argument) + public static ArgumentBuilder Parse(ReadOnlySpan argument) { - throw new NotImplementedException("TODO"); + return new ArgumentBuilder(ArgumentParser.Parse(argument)); } public ArgumentBuilder Add(string key, string value) diff --git a/Dalamud.Bootstrap/SqexArg/ArgumentParser.cs b/Dalamud.Bootstrap/SqexArg/ArgumentParser.cs new file mode 100644 index 000000000..7830ecfc5 --- /dev/null +++ b/Dalamud.Bootstrap/SqexArg/ArgumentParser.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using Pidgin; +using static Pidgin.Parser; +using static Pidgin.Parser; + +namespace Dalamud.Bootstrap.SqexArg +{ + public static class ArgumentParser + { + private static readonly Parser KeyMarkerNoEscape = String(" "); + + private static readonly Parser KeyMarkerEscape = String(" /"); + + private static readonly Parser KeyMarker = Try(KeyMarkerEscape).Or(KeyMarkerNoEscape); + + private static readonly Parser ValueMarker = String(" ="); + + private static readonly Parser EscapedSpace = String(" ").ThenReturn(' '); + + //private static readonly Parser String = Try(EscapedSpace).Or(AnyCharExcept(' ')).ManyString(); + private static readonly Parser String = Try(EscapedSpace).Or(AnyCharExcept(' ')).ManyString(); + + private static readonly Parser> KeyValue = Map + ( + (_, key, _, value) => new KeyValuePair(key, value), + KeyMarker, String, ValueMarker, String + ); + + private static readonly Parser>> Parser = KeyValue.Many(); + + /// + /// Parses the argument + /// + /// + /// + /// Thrown when failed to parse the input. + public static IEnumerable> Parse(ReadOnlySpan input) + { + var test = KeyMarker.Parse(input); + var result = Parser.Parse(input); + + if (!result.Success) + { + throw new SqexArgException($"Failed to parse the argument.\n{result.Error}"); + } + + return result.Value; + } + } +} diff --git a/Dalamud.Bootstrap/SqexArg/EncryptedArgument.cs b/Dalamud.Bootstrap/SqexArg/EncryptedArgument.cs index 36706d4e0..9e4bdd1c3 100644 --- a/Dalamud.Bootstrap/SqexArg/EncryptedArgument.cs +++ b/Dalamud.Bootstrap/SqexArg/EncryptedArgument.cs @@ -1,6 +1,7 @@ using System; using System.Buffers; using System.Buffers.Text; +using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using Dalamud.Bootstrap.Crypto; @@ -90,7 +91,7 @@ namespace Dalamud.Bootstrap.SqexArg // plainText <- utf8Bytes <- encryptedBytes(payload) <- base64(payloadStr) // base64: 3 bytes per 4 characters - // We also want the size to be aligned with the block size. + // We also want the size to be aligned with the block size. Usually this is not a problem but we don't know what payload is actually from. var dataLength = (payload.Length / 4) * 3; var alignedDataLength = AlignBufferLength(dataLength); var encryptedData = new byte[alignedDataLength]; @@ -112,9 +113,14 @@ namespace Dalamud.Bootstrap.SqexArg blowfish.Decrypt(encryptedData, decryptedData); // utf8Bytes -> C# string - var plainText = Encoding.UTF8.GetString(decryptedData[..dataLength]); - - return plainText; + // notice that decryptedData is a null terminated string. + unsafe + { + fixed (byte* pDecryptedData = decryptedData) + { + return Marshal.PtrToStringUTF8(new IntPtr(pDecryptedData)); + } + } } /// diff --git a/Dalamud.Bootstrap/Windows/Process.cs b/Dalamud.Bootstrap/Windows/Process.cs index 451d14434..fbfc3b20f 100644 --- a/Dalamud.Bootstrap/Windows/Process.cs +++ b/Dalamud.Bootstrap/Windows/Process.cs @@ -166,7 +166,7 @@ namespace Dalamud.Bootstrap { FileTime creationTime, exitTime, kernelTime, userTime; - if (Win32.GetProcessTimes(m_handle, &creationTime, &exitTime, &kernelTime, &userTime)) + if (!Win32.GetProcessTimes(m_handle, &creationTime, &exitTime, &kernelTime, &userTime)) { ProcessException.ThrowLastOsError(GetPid()); } diff --git a/Dalamud.Injector/Options.cs b/Dalamud.Injector/Options.cs index ab473cc63..beaa0f949 100644 --- a/Dalamud.Injector/Options.cs +++ b/Dalamud.Injector/Options.cs @@ -8,10 +8,10 @@ namespace Dalamud.Injector [Option('p', "pid", Required = true, HelpText = "A target process id to inject.")] public uint Pid { get; set; } - [Option("root", Required = false)] + [Option("root")] public string? RootDirectory { get; set; } - [Option("bin", Required = false)] + [Option("bin")] public string? BinaryDirectory { get; set; } } diff --git a/Dalamud.Injector/Program.cs b/Dalamud.Injector/Program.cs index 18ba8f4b0..41ed53458 100644 --- a/Dalamud.Injector/Program.cs +++ b/Dalamud.Injector/Program.cs @@ -10,13 +10,17 @@ namespace Dalamud.Injector { private static void Main(string[] args) { + var pid = 12336u; + var binDirectory = ""; + var rootDirectory = ""; + var boot = new Bootstrapper(new BootstrapperOptions { BinaryDirectory = "", RootDirectory = "", }); - boot.Launch("", ""); + boot.Relaunch(pid); Parser.Default.ParseArguments(args) .WithParsed(Inject) @@ -25,6 +29,7 @@ namespace Dalamud.Injector private static void Inject(InjectOptions options) { + var pid = options.Pid; var binDirectory = options.BinaryDirectory ?? GetDefaultBinaryDirectory(); var rootDirectory = options.RootDirectory ?? GetDefaultRootDirectory(); @@ -34,7 +39,7 @@ namespace Dalamud.Injector RootDirectory = rootDirectory, }); - boot.Relaunch(options.Pid); + boot.Relaunch(pid); } private static void Launch(LaunchOptions options)