題:
什麼是DLL注入?如何將其用於反向?
user2142
2013-06-14 20:07:25 UTC
view on stackexchange narkive permalink

我正在閱讀有關將進程的一部分轉儲到進程內存中的討論,有人建議使用DLL注入來做到這一點。我會說實話,因為我不太了解。 DLL注入如何工作以及您可以使用哪種反向任務?

二 答案:
Rolf Rolles
2013-06-15 01:13:55 UTC
view on stackexchange narkive permalink

DCoder的答案是一個很好的答案。為了進行某種擴展,我經常在強制現有進程通過CreateRemoteThread加載DLL的情況下使用DLL注入。從那裡,DLL的入口點將在加載後由操作系統執行。然後,在入口點中,我將調用一個例程,該例程對我感興趣的原始二進製文件中的所有位置執行內存內修補,然後通過各種修改將其執行重定向到我的DLL中。如果我有興趣修改或觀察進程與某些導入函數的交互,那麼我將覆蓋該函數的IAT(導入地址表)條目,並用指向我控制的對象的指針替換它。如果要對二進製文件中存在的某些功能執行相同的操作,則將在該功能的開頭進行一些繞行樣式的補丁。我什至可以在任意位置進行非常外科手術和針對性的掛鉤,類似於老式的字節修補。我的DLL在單獨的鉤子中開展業務,然後被編程為將控制重定向到原始進程。

DLL注入提供了一個用於操縱正在運行的進程的執行的平台。在逆向工程時,它非常常用於記錄信息。例如,您可以掛鉤給定導入的操作系統庫函數的IAT條目,然後將函數參數記錄到磁盤上。這為您提供了一個數據源,可以幫助您快速對目標進行反向工程。

DLL注入不僅限於日誌記錄。鑑於您可以自由執行程序地址空間中所需的任何代碼,因此您可以選擇任何方式修改程序。此技術在遊戲黑客界經常用於編寫機器人代碼。

與字節修補有關的任何事情,都可以與DLL注入有關。除了DLL注入之外,它可能更容易,更快捷,因為您可以使用C而不是彙編語言來編寫補丁程序,並且不必費心對二進製文件及其PE結構進行手動修改,查找代碼陷阱等。DLL注入幾乎完全不需要在修改二進製文件時使用彙編語言;唯一需要的彙編語言是在特定鉤子的入口和出口附近的一小段代碼,以保存和恢復寄存器/標誌的值。它還使二進制修改既快速又簡單,並且不會更改您要修補的可執行文件的加密簽名。 (有關加密簽名的註釋適用於磁盤上的可執行文件,而不是內存中的可執行文件;當然,更改內存中的內容會影響根據更改後的內存內容計算出的加密簽名。)

可以使用DLL注入解決高度不平凡的逆向工程問題。由於未公開協議,以下示例在某些方面一定是含糊的。

我對經常更新的程序(有時每天更新多次)產生了濃厚的興趣。該程序中包含許多部分,這些部分在編譯後會在磁盤上加密,並且必須在運行時解密。該軟件包括一個內核模塊,該模塊執行運行時加密/解密。為了請求給定節的加密或解密,該程序附帶了DLL,該DLL導出了一個函數,該函數將節的編號和作為布爾值的布爾值用作參數,該布爾值指示應加密還是解密該節。所有組件都經過數字簽名。

我採用了基於DLL注入的解決方案,其工作方式如下:

  • 創建暫停的進程。
  • 注入DLL。
  • DLL在程序的IAT中將GetProcAddress掛鉤。
  • GetProcAddress鉤子等待提供特定的字符串,然後返回該函數的自身鉤子版本。
  • 鉤子函數檢查堆棧上的返回地址兩幀,直到找出起始地址為止
  • 鉤子函數然後為每個加密段調用Func,指示其解密每個段。為了使這項工作有效,鉤子函數必須將對這些調用的調用傳遞給DLL中的適當函數。
  • 這樣做之後,對於鉤子函數的每個後續調用,它僅返回1
  • 已經對所有部分進行了解密,現在,DLL將進程的映像轉儲到磁盤上並重建導入信息。
  • 然後,它進行了一堆操作

最初,我是為每個新版本手工完成所有這些工作的。那太乏味了。我曾經編寫過DLL注入版本的代碼,我再也不必進行大量的手動工作。

DLL注入在遊戲黑客之外的逆向工程中並不廣為人知或使用。這是非常不幸的,因為它是一種非常強大,靈活且簡單的技術,應該成為每個人的曲目中的一部分。我已經使用了數十次,它似乎在我所有的動態項目中都找到了作用。當我的任務變得繁瑣而無法使用調試器腳本執行時,我切換到DLL注入。

在逆向工程技術領域,動態二進制工具(DBI)工具可提供DLL注入的所有功能同樣,DBI仍然更加強大。但是,DBI 並非隱秘的,並且會在內存消耗和性能方面帶來嚴重的開銷。在切換到DBI之前,我總是嘗試使用DLL注入。

DLL注入不是廣為人知的,也不是在遊戲黑客之外的逆向工程中使用的。+1它通常被視為一種“攻擊”技術,即使我們如您所展示的那樣可以充分利用它!
真是一個了不起的答案。您可能已經改變了我永遠使用REing複雜應用程序的方式。
+1-您提到了我跳過的很多細節,這個答案可能值得接受,而不是我的。
您可能應該提到Detours :)
+1這是我在任何stackexchange網站上看到的最好的答案之一。
撲克機器人程序鏈接似乎已斷開。
DCoder
2013-06-14 21:02:35 UTC
view on stackexchange narkive permalink

DLL注入的工作原理是欺騙/強制目標進程加載您選擇的DLL。之後,該DLL中的代碼將作為目標進程的一部分被執行,並且能夠執行進程本身可以執行的所有操作。有趣的部分是弄清楚如何讓目標進程調用您的代碼。


可以通過以下方式註入DLL:

  • 用DLL替換為該過程通常使用一種方法-例如,如果您將DLL ddraw.dll 命名為DLL,那麼很多遊戲將很高興地加載它,而不是真正的Direct Draw DLL。我已經看到這樣做可以迫使遊戲僅在軟件仿真模式下使用Direct Draw,以在特定GPU上加速遊戲。
  • 促使加載程序從其他文件夾加載已知的DLL-請參見 The Old New Thing
  • 用一些指令來替換某些過程代碼以加載DLL。
  • 使用許多其他方式

下一步將是使您的DLL代碼實際執行。但是,如果您想做有意義的事情,這將很困難-您需要知道流程的工作,流程使用的數據結構等,因此您很可能需要反彙編它。

  • 您可以在目標進程中創建一個新線程,以從DLL中調用一個函數。首先掛起現有線程,以保持理智,避免出現時髦的多線程錯誤。
  • 如果用自己的DLL替換了已知的DLL,則該過程將期望您的DLL響應特定的函數調用-您最好知道這些函數是什麼,並在DLL中提供它們的替換。
  • 如果您更改了可執行文件以調用DLL (除了已知的DLLs ),則必須將可執行文件拆開。現在去尋找一些有趣的地方,並在其中插入對DLL函數的調用。請參見密碼洞穴

我通過將目標進程作為被調試進程啟動來執行DLL注入,並使用調用 LoadLibrary(“ mydll.dll”)的自定義代碼序列覆蓋其啟動代碼中的某些字節; GetProcAddress(myLib,“ myFunc”); ,然後在可執行文件中重寫一些代碼,以跳轉到DLL中的函數。

使用此方法,一些朋友和我為 Command & Conquer:Red Alert 2 寫了一個相當大的非官方錯誤修復/增強DLL-如今,DLL的大小大約為原始遊戲可執行文件。結果,後來對該遊戲的正式更新僅限於其工作人員無需重新編譯二進製文件就可以做的事情,這在EA上通常是不錯的。

除了注入代碼,您還可以將DLL添加到導入表中(靜態或動態)。
執行LoadLibrary()的行為會使加載的DLL中的代碼開始運行。您不需要任何其他操作,因為DLLMain可以自己執行所有必要的修改。
您可能應該提到Detours :)


該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 3.0許可。
Loading...