2013-04-27 61 views
4

假設我想將一個DLL注入一個想要每隔250毫秒編輯地址A值的進程。我需要使用DllMain,對吧?問題是我不允許在DllMain中等待。所以我將不得不創建一個線程?或者是否沒有繞過限制?我會如何去做這件事?DLL注入的最佳實踐?

另外,使用DLL注入來編輯應用程序的內存使用EXE有什麼好處嗎?

另外,CreateThread中的堆棧大小應該是多少?如果它太小或太大會怎樣?我如何知道我需要多少?

回答

5

從您的描述看來,您已經知道如何讓目標進程加載您的DLL。如果我的假設是正確的,那麼答案很簡單:從DLLMain創建一個線程並在線程中實現您的邏輯。只要你的代碼遵守下面列出的規則,你應該沒問題。

這個document描述了DLLMain能做什麼和不能做什麼以及爲什麼。

如記錄,你永遠不應該從內部的DllMain執行下列任務:

  • 調用LoadLibrary或LoadLibraryEx(直接或間接)。 這可能會導致死鎖或崩潰。
  • 與其他線程同步。這可能導致死鎖。
  • 獲取正在等待獲取加載程序 鎖的代碼擁有的同步對象。這可能導致死鎖。
  • 使用CoInitializeEx初始化COM線程。在某些情況下,該函數可以調用 LoadLibraryEx。
  • 調用註冊表函數。這些函數在Advapi32.dll中實現。如果Advapi32.dll沒有在您的DLL之前初始化,該DLL可以訪問未初始化的內存並導致進程崩潰。
  • 調用CreateProces。創建一個進程可以加載另一個DLL。
  • 調用ExitThread。在DLL分離期間退出線程可能會導致再次獲取加載程序鎖定,從而導致死鎖或崩潰。
  • 調用CreateThread。如果您不與其他線程同步,創建一個線程可以工作,但這是有風險的。
  • 創建一個命名管道或其他命名對象(僅限Windows 2000)。在Windows 2000中,命名對象由終端服務DLL提供。如果此DLL未初始化,對DLL的調用可能會導致進程崩潰。
  • 使用動態C運行時(CRT)中的內存管理功能。如果CRT DLL沒有初始化,調用這些函數會導致進程崩潰。
  • 在User32.dll或Gdi32.dll中調用函數。某些函數加載另一個DLL,可能無法初始化。
  • 使用託管代碼。

以下任務是安全的範圍內的DllMain執行:

  • 初始化靜態數據結構和成員在編譯時。
  • 創建並初始化同步對象
  • 分配內存和初始化動態數據結構(避免上面列出的功能。)
  • 設置線程本地存儲(TLS)。
  • 打開,讀取和寫入文件。
  • Kernel32.dll中的調用函數(上面列出的函數除外)。
  • 將全局指針設置爲NULL,推遲動態成員的初始化。在Microsoft Windows Vista™中,您可以使用一次性初始化函數來確保在多線程環境中僅執行一次代碼塊。

你的第二個問題對我來說不太清楚。要將代碼注入到另一個進程中,您必須從某處(瀏覽器,exe或其他任何地方)啓動,然後寫入目標進程內存以加載您的DLL。