Loading / inserting a .Net assembly into an existing .net process?

In my situation, I want to load a custom .net assembly into a .net production domain, for example Windows Explorer

, what I've already tried is just injecting the assembly into explorer.exe

, but it doesn't seem to work for no obvious reason.

Injector code:

public class CodeInjector
{
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern int CloseHandle(IntPtr hObject);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr GetModuleHandle(string lpModuleName);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, IntPtr dwSize, uint flAllocationType, uint flProtect);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern int WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, int lpNumberOfBytesWritten);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttribute, IntPtr dwStackSize, IntPtr lpStartAddress,
        IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);

    private static CodeInjector _instance;

    public static CodeInjector GetInstance
    {
        get { return _instance ?? (_instance = new CodeInjector()); }
    }

    public InjectionResult Inject(string sProcName, string sDllPath)
    {
        if (!File.Exists(sDllPath))
        {
            return InjectionResult.DllNotFound;
        }

        var procs = Process.GetProcesses();
        var procId = (from t in procs where t.ProcessName == sProcName select (uint)t.Id).FirstOrDefault();

        if (procId == 0)
        {
            return InjectionResult.ProcessNotFound;
        }

        if (!Inject(procId, sDllPath))
        {
            return InjectionResult.InjectionFailed;
        }

        return InjectionResult.InjectionSucceed;
    }

    private static bool Inject(uint pToBeInjected, string sDllPath)
    {
        var hndProc = OpenProcess((0x2 | 0x8 | 0x10 | 0x20 | 0x400), 1, pToBeInjected);

        if (hndProc == IntPtr.Zero)
        {
            return false;
        }

        var lpLlAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");

        if (lpLlAddress == IntPtr.Zero)
        {
            return false;
        }

        var lpAddress = VirtualAllocEx(hndProc, (IntPtr)null, (IntPtr)sDllPath.Length, (0x1000 | 0x2000), 0X40);

        if (lpAddress == IntPtr.Zero)
        {
            return false;
        }

        var bytes = Encoding.ASCII.GetBytes(sDllPath);

        if (WriteProcessMemory(hndProc, lpAddress, bytes, (uint)bytes.Length, 0) == 0)
        {
            return false;
        }

        if (CreateRemoteThread(hndProc, (IntPtr)null, IntPtr.Zero, lpLlAddress, lpAddress, 0, (IntPtr)null) == IntPtr.Zero)
        {
            return false;
        }

        CloseHandle(hndProc);

        return true;
    }
}

      

+3


source to share


1 answer


Alternatively, you can use an existing library - ManagedInjector

- https://github.com/cplotts/snoopwpf/tree/master/ManagedInjector . There is a snoopwpf tool that can display the details of any WPF process and process injection is used for that. I used it a while ago and it worked well.

You need to build it, add it to your project as a link and call it like this:

Injector.Launch(someProcess.MainWindowHandle, 
                  typeof(Loader).Assembly.Location, 
                  typeof(Loader).FullName, 
                  "Inject");

      

Loader

is the name of the type that will be loaded into the process, and Inject

is the static method that will be executed. In my case, I:

public class Loader
{

    public static void Inject()
    {
          // i did CBT Hook on main window here 
          // and also displayed sample message box for debugging purposes
          MessageBox.Show("Hello from another process");
    }
}

      



This ManagedInjector is written in managed C ++ code. Basically it intercepts native unmanaged C ++ method as MessageHookProc and it runs the specified assembly after injection and runs the specified method. It should work well for both managed and unmanaged programs. In my case, I used it for an unmanaged program.

UPDATE

I have tested it locally and have successfully inserted my message box into explorer on Windows 8.1 x64. I have compiled ManagedInjector64-4.0 and my example console project also has x64 in platform selection. Here is my working code:

class Program
{
    static void Main(string[] args)
    {
        var proc = Process.GetProcessesByName("explorer").FirstOrDefault();
        Injector.Launch(proc.MainWindowHandle, typeof(Loader).Assembly.Location, typeof(Loader).FullName, "Inject");
    }
}

public class Loader
{
    public static void Inject()
    {
        MessageBox.Show("Hello");
        Task.Run(() =>
        {
            Thread.Sleep(3000);
            MessageBox.Show("Hello again");
            Thread.Sleep(5000);
            MessageBox.Show("Hello again again");
        });
    }
}

      

+3


source







All Articles