2016-11-04 81 views
1

這是一個很奇怪的問題,但我相信這是SO的主題。CreateRemoteThread失敗ERROR_NOT_ENOUGH_MEMORY

簡介:

我有一個服務,C#編寫的,它調用我的C++庫。 C++庫通過WinExec執行一些第三方軟件。

第三方軟件通過CreateRemoteThread注入DLL。我沒有這個軟件的源文件。

主要部分

我有2個電腦 - 的Win2008和Win10。

對於Win10-這個frankenstein工作正常,Service運行DLL,DLL運行第三方DLL注入器,DLL注入器注入東西。

對於Win2008,情況有所不同。如果我從CMD運行3rdparty DLL注入器 - 它的工作完美無瑕。但是,如果我運行服務 - 注入器返回,他從CreateRemoteThread得到ERROR_NOT_ENOUGH_MEMORY。

服務從LocalService帳戶的工作,一切是在Windows 10,我正在尋找可能的想法\線索,確定爲什麼會出現與服務(記住,CMD正常工作)和一個問題僅適用於Windows 2008

回答

2

這個問題可能與創建跨權限級別遠程線程,如下面的博客文章中解釋:

Injecting Code Into Privileged Win32 Processes

與XP SP2或更高版本(2003,Vista)的一些新的安全措施,防止傳統的C reateRemoteThread()函數正常工作。您應該能夠打開進程,在其堆上分配內存,並將數據寫入分配的區域,但嘗試調用遠程線程時,它將失敗並顯示ERROR_NOT_ENOUGH_MEMORY。

...

對於XP SP2我做了一些調試,發現裏面CreateRemoteThread的(),還有就是ZwCreateThread(),這是從ntdll.dll的導出的呼叫。這個調用是在指定線程應該開始暫停的情況下進行的,但是在調用ZwResumeThread()之前仍然在CreateRemoteThread()內部的道路上,調用CsrClientCallServer()會失敗並最終導致錯誤信息。

的文章解釋了注入不同版本的Windows的遠程線程,以避免錯誤的一些不同的方式,用這樣的結論結尾:

在這一點上,我們能夠成功地執行遠程線程注入特權進程跨所有目標平臺,但如前所述,其相當混亂。我們正在使用三種不同的,基本上沒有記錄的功能,並根據操作系統版本自動檢測使用哪一種功能。

更好的解決方案是創建一個輔助程序,將服務對象(您的注射器程序)添加到目標系統上的服務控制管理器數據庫。由於您是管理員,無論如何,您都可以添加這些條目並啓動服務。這將使注入程序能夠以不同於普通代碼的不同訪問權運行,並且傳統的CreateRemoteThread()可以在Windows 2000,所有XP和2003/Vista上正常運行。用於添加和控制服務的API函數由MSDN記錄並在所有平臺中保持一致。

因此,我們可以使用許多不同的函數將代碼注入特權遠程進程,包括XP SP2上的RtlCreateUserThread()和Vista上的NtCreateThreadEx(),但最佳方式是安裝臨時服務並允許CreateRemoteThread()成爲完成所有平臺任務的單個API。

當然,這些都不重要,因爲您沒有注入器的源代碼,因此無法改變它的工作原理。

此外,您無法跨會話邊界創建遠程線程。在服務中調用WinExec()將在與服務相同的會話(即會話0)中運行注入器進程。如果它試圖注入正在用戶會話中運行的進程,則該進程將無法工作。這也解釋了爲什麼從CMD運行注入器的工作原理,如果CMD與注入的進程在同一個會話中運行。

+0

感謝您的輸入。但我主要關心的是,一切都在Windows 10下工作。可能是一些Windows 2008設置或類似的東西? – Starl1ght