From fbc687db9ef4580c430ec4ab50cf6962e4e777e7 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Sat, 18 Feb 2023 16:53:41 +0100 Subject: [PATCH] feat(inject): allow passing in arguments and returning 32bit value --- src/Inject/NosSmooth.Inject/nossmooth.cpp | 13 +++--- src/Inject/NosSmooth.Inject/nossmooth.h | 1 + .../Commands/InjectCommand.cs | 24 +++++++--- .../NosSmooth.Injector/InjectionResult.cs | 11 ++--- src/Inject/NosSmooth.Injector/LoadParams.cs | 5 +++ .../ManagedMemoryAllocation.cs | 7 ++- src/Inject/NosSmooth.Injector/NosInjector.cs | 41 ++++++++++++++---- .../NosSmooth.Injector/NosSmooth.Inject.dll | Bin 53248 -> 53248 bytes 8 files changed, 71 insertions(+), 31 deletions(-) diff --git a/src/Inject/NosSmooth.Inject/nossmooth.cpp b/src/Inject/NosSmooth.Inject/nossmooth.cpp index ae07bcc..9ac580e 100644 --- a/src/Inject/NosSmooth.Inject/nossmooth.cpp +++ b/src/Inject/NosSmooth.Inject/nossmooth.cpp @@ -105,17 +105,17 @@ int LoadAndCallMethod(LoadParams* params) { if (!load_hostfxr()) { - return 2; + return 0; } load_assembly_and_get_function_pointer_fn load_assembly_and_get_function_pointer = nullptr; load_assembly_and_get_function_pointer = get_dotnet_load_assembly(params->runtimeConfigPath); if (load_assembly_and_get_function_pointer == nullptr) { - return 3; + return 1; } - typedef void (CORECLR_DELEGATE_CALLTYPE* main_entry_point_fn)(); + typedef int (CORECLR_DELEGATE_CALLTYPE* main_entry_point_fn)(char* data); main_entry_point_fn main = nullptr; int rc = load_assembly_and_get_function_pointer( params->libraryPath, @@ -123,12 +123,11 @@ int LoadAndCallMethod(LoadParams* params) params->methodName, UNMANAGEDCALLERSONLY_METHOD, nullptr, - (void**)&main); + reinterpret_cast(&main)); if (rc != 0 || main == nullptr) { - return 4; + return 2; } - main(); - return 1; + return main(params->userData) + 3; } \ No newline at end of file diff --git a/src/Inject/NosSmooth.Inject/nossmooth.h b/src/Inject/NosSmooth.Inject/nossmooth.h index 3e24d1a..25cf482 100644 --- a/src/Inject/NosSmooth.Inject/nossmooth.h +++ b/src/Inject/NosSmooth.Inject/nossmooth.h @@ -8,6 +8,7 @@ struct LoadParams wchar_t *runtimeConfigPath; wchar_t *typePath; wchar_t *methodName; + char *userData; }; #pragma pack(pop) #define DllExport extern "C" __declspec( dllexport ) diff --git a/src/Inject/NosSmooth.Injector.CLI/Commands/InjectCommand.cs b/src/Inject/NosSmooth.Injector.CLI/Commands/InjectCommand.cs index c0c9818..ce561c9 100644 --- a/src/Inject/NosSmooth.Injector.CLI/Commands/InjectCommand.cs +++ b/src/Inject/NosSmooth.Injector.CLI/Commands/InjectCommand.cs @@ -37,7 +37,7 @@ namespace NosSmooth.Injector.CLI.Commands /// The name of the UnmanagedCallersOnly method. Default is Main. /// A result that may or may not have succeeded. [Command("inject")] - public Task Inject + public async Task Inject ( [Description("The id of the process to inject into.")] string process, @@ -51,18 +51,32 @@ namespace NosSmooth.Injector.CLI.Commands { if (!int.TryParse(process, out var processId)) { - var foundProcess = Process.GetProcesses().FirstOrDefault(x => x.ProcessName.Contains(process, StringComparison.OrdinalIgnoreCase)); + var foundProcess = Process.GetProcesses().FirstOrDefault + (x => x.ProcessName.Contains(process, StringComparison.OrdinalIgnoreCase)); if (foundProcess is null) { - return Task.FromResult(Result.FromError(new NotFoundError("Could not find the given process."))); + return Result.FromError(new NotFoundError("Could not find the given process.")); } processId = foundProcess.Id; } var dllName = Path.GetFileNameWithoutExtension(dllPath); - return Task.FromResult - (_injector.Inject(processId, dllPath, typeName ?? $"{dllName}.DllMain, {dllName}", methodName ?? "Main")); + var result = _injector.Inject + ( + processId, + dllPath, + typeName ?? $"{dllName}.DllMain, {dllName}", + methodName ?? "Main", + new byte[] { 1, 2, 3, 4, 5 } + ); + if (!result.IsSuccess) + { + return Result.FromError(result); + } + + Console.WriteLine($"Got {result.Entity} from the managed injected dll."); + return Result.FromSuccess(); } } } \ No newline at end of file diff --git a/src/Inject/NosSmooth.Injector/InjectionResult.cs b/src/Inject/NosSmooth.Injector/InjectionResult.cs index d540225..c69254b 100644 --- a/src/Inject/NosSmooth.Injector/InjectionResult.cs +++ b/src/Inject/NosSmooth.Injector/InjectionResult.cs @@ -11,15 +11,10 @@ namespace NosSmooth.Injector; /// public enum InjectionResult { - /// - /// Successful result. - /// - Ok = 1, - /// /// Hostfxr.dll was not found, is .NET installed? It should be as this is a .NET application injecting the dll... /// - HostfxrNotFound = 2, + HostfxrNotFound = 0, /// /// A runtimeconfig.json of the assembly to be injected was not found. @@ -28,7 +23,7 @@ public enum InjectionResult /// Be sure to include true /// in a library that will be injected. /// - RuntimeConfigNotFound = 3, + RuntimeConfigNotFound = 1, /// /// The specified class or type was not found. @@ -37,5 +32,5 @@ public enum InjectionResult /// Be sure to put it in this format: "namespace.type.method, assembly", /// see samples. /// - ClassOrMethodNotFound = 4 + ClassOrMethodNotFound = 2 } \ No newline at end of file diff --git a/src/Inject/NosSmooth.Injector/LoadParams.cs b/src/Inject/NosSmooth.Injector/LoadParams.cs index e249612..e741db2 100644 --- a/src/Inject/NosSmooth.Injector/LoadParams.cs +++ b/src/Inject/NosSmooth.Injector/LoadParams.cs @@ -40,5 +40,10 @@ namespace NosSmooth.Injector /// The name of the method to execute. /// public int MethodName; + + /// + /// The user data to pass. + /// + public int UserData; } } diff --git a/src/Inject/NosSmooth.Injector/ManagedMemoryAllocation.cs b/src/Inject/NosSmooth.Injector/ManagedMemoryAllocation.cs index 7d8726a..3035c66 100644 --- a/src/Inject/NosSmooth.Injector/ManagedMemoryAllocation.cs +++ b/src/Inject/NosSmooth.Injector/ManagedMemoryAllocation.cs @@ -41,7 +41,10 @@ internal class ManagedMemoryAllocation : IDisposable /// public void Dispose() { - _memory.Free(Pointer); - Pointer = nuint.Zero; + if (Allocated) + { + _memory.Free(Pointer); + Pointer = nuint.Zero; + } } } \ No newline at end of file diff --git a/src/Inject/NosSmooth.Injector/NosInjector.cs b/src/Inject/NosSmooth.Injector/NosInjector.cs index 7869e06..a222038 100644 --- a/src/Inject/NosSmooth.Injector/NosInjector.cs +++ b/src/Inject/NosSmooth.Injector/NosInjector.cs @@ -47,17 +47,19 @@ public class NosInjector /// The absolute path to the dll to inject. /// The full path to the class. Such as "MyLibrary.DllMain, MyLibrary". /// The name of the method to execute. The method should return void and have no parameters. + /// The data to pass to the process. The array will be allocated inside the target process. /// A result that may or may not have succeeded. - public Result Inject + public Result Inject ( int processId, string dllPath, string classPath, - string methodName = "Main" + string methodName = "Main", + byte[]? data = default ) { using var process = Process.GetProcessById(processId); - return Inject(process, dllPath, classPath, methodName); + return Inject(process, dllPath, classPath, methodName, data); } /// @@ -70,13 +72,15 @@ public class NosInjector /// The absolute path to the dll to inject. /// The full path to the class. Such as "MyLibrary.DllMain, MyLibrary". /// The name of the method to execute. The method should return void and have no parameters. + /// The data to pass to the process. The array will be allocated inside the target process. /// A result that may or may not have succeeded. - public Result Inject + public Result Inject ( Process process, string dllPath, string classPath, - string methodName = "Main" + string methodName = "Main", + byte[]? data = default ) { try @@ -100,7 +104,7 @@ public class NosInjector if (!netHostInjectionResult.IsSuccess) { - return netHostInjectionResult; + return Result.FromError(netHostInjectionResult); } var directoryName = Path.GetDirectoryName(dllPath); @@ -121,6 +125,7 @@ public class NosInjector using var classPathMemory = AllocateString(memory, classPath); using var methodNameMemory = AllocateString(memory, methodName); using var runtimePathMemory = AllocateString(memory, runtimePath); + using var userDataMemory = Allocate(memory, data ?? Array.Empty()); if (!dllPathMemory.Allocated || !classPathMemory.Allocated || !methodNameMemory.Allocated || !runtimePathMemory.Allocated) @@ -133,7 +138,8 @@ public class NosInjector LibraryPath = (int)dllPathMemory.Pointer, MethodName = (int)methodNameMemory.Pointer, RuntimeConfigPath = (int)runtimePathMemory.Pointer, - TypePath = (int)classPathMemory.Pointer + TypePath = (int)classPathMemory.Pointer, + UserData = (int)userDataMemory.Pointer }; var nosSmoothInjectPath = Path.GetFullPath(_options.NosSmoothInjectPath); @@ -153,7 +159,7 @@ public class NosInjector injector.Eject(nosSmoothInjectPath); - if (functionResult != 1) + if (functionResult < 3) { return new InjectionFailedError ( @@ -163,7 +169,7 @@ public class NosInjector ); } - return Result.FromSuccess(); + return functionResult - 3; } catch (UnauthorizedAccessException) { @@ -216,4 +222,21 @@ public class NosInjector memory.SafeWriteRaw(allocated, bytes); return new ManagedMemoryAllocation(memory, allocated); } + + private ManagedMemoryAllocation Allocate(IMemory memory, byte[] data) + { + if (data.Length == 0) + { + return new ManagedMemoryAllocation(memory, nuint.Zero); + } + + var allocated = memory.Allocate(data.Length); + if (allocated == nuint.Zero) + { + return new ManagedMemoryAllocation(memory, allocated); + } + + memory.SafeWriteRaw(allocated, data); + return new ManagedMemoryAllocation(memory, allocated); + } } \ No newline at end of file diff --git a/src/Inject/NosSmooth.Injector/NosSmooth.Inject.dll b/src/Inject/NosSmooth.Injector/NosSmooth.Inject.dll index 7f5470d223e3050d6a3c176089ec95250803b124..95960e24b811ec8ebffbef2df69b015964e60dec 100644 GIT binary patch delta 188 zcmZozz}&EadBP87#}6Mi{x*=;H9qjNk%58Xxa$`n$b!|NqTLSUO$5 zG}nG%C}rQl2$XysJvlZ)|2H0a0n}^#=0zV+uKQ{1;j{@LbKiiJ|NsA=1<3v}`J=*} d%@-B>s~K4~C(fO%&AQX(h0T}Ej3@uI0RV50Sgrs7 delta 191 zcmZozz}&EadBP9oBFVQKe;df_?qFhIV0c|~-1Q5PX6Sb1==NXl(O$&2B`|09HC&J$O2*tc7ORF`oj9li^D*bI~ajNLEUEqdPN`TFbcc~0E$IK z#m7Z=`~ERL`=aB?|No6gUI5itzj-kkDA)Zo_AtLZ14!2kkoy1s|AP$u0%YeVX68-) f$bNJ4MaBMVM&`|lb7yO_Zn1e{^I