~ruther/NosSmooth.Local

fbc687db9ef4580c430ec4ab50cf6962e4e777e7 — Rutherther 2 years ago f8f7c90
feat(inject): allow passing in arguments and returning 32bit value
M src/Inject/NosSmooth.Inject/nossmooth.cpp => src/Inject/NosSmooth.Inject/nossmooth.cpp +6 -7
@@ 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<void**>(&main));
    if (rc != 0 || main == nullptr)
    {
        return 4;
        return 2;
    }

    main();
    return 1;
    return main(params->userData) + 3;
}
\ No newline at end of file

M src/Inject/NosSmooth.Inject/nossmooth.h => src/Inject/NosSmooth.Inject/nossmooth.h +1 -0
@@ 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 )

M src/Inject/NosSmooth.Injector.CLI/Commands/InjectCommand.cs => src/Inject/NosSmooth.Injector.CLI/Commands/InjectCommand.cs +19 -5
@@ 37,7 37,7 @@ namespace NosSmooth.Injector.CLI.Commands
        /// <param name="methodName">The name of the UnmanagedCallersOnly method. Default is Main.</param>
        /// <returns>A result that may or may not have succeeded.</returns>
        [Command("inject")]
        public Task<Result> Inject
        public async Task<Result> 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

M src/Inject/NosSmooth.Injector/InjectionResult.cs => src/Inject/NosSmooth.Injector/InjectionResult.cs +3 -8
@@ 12,14 12,9 @@ namespace NosSmooth.Injector;
public enum InjectionResult
{
    /// <summary>
    /// Successful result.
    /// </summary>
    Ok = 1,

    /// <summary>
    /// Hostfxr.dll was not found, is .NET installed? It should be as this is a .NET application injecting the dll...
    /// </summary>
    HostfxrNotFound = 2,
    HostfxrNotFound = 0,

    /// <summary>
    /// A runtimeconfig.json of the assembly to be injected was not found.


@@ 28,7 23,7 @@ public enum InjectionResult
    /// Be sure to include <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
    /// in a library that will be injected.
    /// </remarks>
    RuntimeConfigNotFound = 3,
    RuntimeConfigNotFound = 1,

    /// <summary>
    /// 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.
    /// </remarks>
    ClassOrMethodNotFound = 4
    ClassOrMethodNotFound = 2
}
\ No newline at end of file

M src/Inject/NosSmooth.Injector/LoadParams.cs => src/Inject/NosSmooth.Injector/LoadParams.cs +5 -0
@@ 40,5 40,10 @@ namespace NosSmooth.Injector
        /// The name of the method to execute.
        /// </summary>
        public int MethodName;

        /// <summary>
        /// The user data to pass.
        /// </summary>
        public int UserData;
    }
}

M src/Inject/NosSmooth.Injector/ManagedMemoryAllocation.cs => src/Inject/NosSmooth.Injector/ManagedMemoryAllocation.cs +5 -2
@@ 41,7 41,10 @@ internal class ManagedMemoryAllocation : IDisposable
    /// <inheritdoc />
    public void Dispose()
    {
        _memory.Free(Pointer);
        Pointer = nuint.Zero;
        if (Allocated)
        {
            _memory.Free(Pointer);
            Pointer = nuint.Zero;
        }
    }
}
\ No newline at end of file

M src/Inject/NosSmooth.Injector/NosInjector.cs => src/Inject/NosSmooth.Injector/NosInjector.cs +32 -9
@@ 47,17 47,19 @@ public class NosInjector
    /// <param name="dllPath">The absolute path to the dll to inject.</param>
    /// <param name="classPath">The full path to the class. Such as "MyLibrary.DllMain, MyLibrary".</param>
    /// <param name="methodName">The name of the method to execute. The method should return void and have no parameters.</param>
    /// <param name="data">The data to pass to the process. The array will be allocated inside the target process.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public Result Inject
    public Result<int> 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);
    }

    /// <summary>


@@ 70,13 72,15 @@ public class NosInjector
    /// <param name="dllPath">The absolute path to the dll to inject.</param>
    /// <param name="classPath">The full path to the class. Such as "MyLibrary.DllMain, MyLibrary".</param>
    /// <param name="methodName">The name of the method to execute. The method should return void and have no parameters.</param>
    /// <param name="data">The data to pass to the process. The array will be allocated inside the target process.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public Result Inject
    public Result<int> 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<int>.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<byte>());

            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

M src/Inject/NosSmooth.Injector/NosSmooth.Inject.dll => src/Inject/NosSmooth.Injector/NosSmooth.Inject.dll +0 -0
Do not follow this link