将.Net汇编加载/注入现有的.net流程?

在我的情况下,我想将一个自定义的.net程序集加载到一个正在运行的.net进程的域中,例如Windows Explorer ,我已经尝试过的只是将程序集注入到explorer.exe但是这似乎没有用到没有明显的原因。

注射器代码:

 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; } } 

作为另一种选择,您可以使用现有库 – ManagedInjectorhttps://github.com/cplotts/snoopwpf/tree/master/ManagedInjector 。 有一个工具snoopwpf可以显示任何WPF进程的详细信息,并且它使用进程注入。 我前段时间使用它并且效果很好。

你需要构建它,添加到你的项目作为参考,并像这样调用:

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

Loader是将加载到进程中的类型名称, Inject是将要执行的静态方法。 在我的情况下,我有:

 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"); } } 

ManagedInjector是用托管C ++代码编写的。 基本上它将自己的非托管C ++方法挂钩为MessageHookProc,它将在注入后启动指定的程序集并运行指定的方法。 它应该适用于托管和非托管程序。 就我而言,我将它用于非托管程序。

UPDATE

我在本地测试它,它成功地将我的消息框注入Windows 8.1 x64下的资源管理器进程。 我编译了ManagedInjector64-4.0,我的示例控制台项目在平台选择中也有x64。 这是我的工作代码:

 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"); }); } }