2015-07-11 76 views
3

在我的情况,我想加载自定义.NET程序集到运行.NET过程的域名,例如Windows Explorer,我曾尝试已是刚刚注射大会explorer.exe但这似乎并没有没有明显的理由工作。将.Net程序集加载/注入到现有的.net进程中?

喷油器代码:

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

如何验证程序集没有注入?你是否在'sDllPath'变量中发送了同样的程序集?该程序集是否位于与注入过程的可执行文件相同的文件夹中?顺便说一句,资源管理器不是.Net进程,所以它可能没有运行CLR里面。在这种情况下,另一种方式是注入自己的C++组件,并创造新的AppDomain并在注射过程中运行的汇编 –

+0

@SergeyLitvinov是否有装载我的。NET组装成浏览器?一个好办法,我都想尽单路我能找到没有运气。我使用procexplorer来查看我的程序集是否已加载到目标进程中。 –

回答

3

您也可以使用现有的库的另一个选项 - ManagedInjector - https://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是用Managed C++代码编写的。基本上它将自己的非托管C++方法作为MessageHookProc挂钩,它将在注入后启动指定的程序集并运行指定的方法。它应该适用于托管和非托管程序。在我的情况下,我将它用于非托管程序。

UPDATE

我在本地测试,它成功地注入在Windows 8.1 x64的我的消息框到Explorer进程。我编译了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"); 
     }); 
    } 
} 
+0

它不断抛出FileLoadException,即使没有调用进样法..任何帮助,因为你的解决方案似乎有趣。 –

+0

我在注射器使用中出现错误。第二个参数应该指向程序集的位置,所以它可能无法加载它。我已更新答案并添加了工作示例。 –

+0

很抱歉,但我不能建立注射器项目中,我不断收到'错误5错误LNK2022:元数据操作失败(80131195):自定义属性并不一致:(0x0c000089).' –