標籤:

遊戲中注入dll是什麼意思,具體怎麼實現的?


在回答這個問題之前,首先要知道dll是什麼。

現代軟體其實都不是一個打包的一整個exe,而是一個個互相分工的模塊。這樣做的好處(多得要死,分工寫代碼/方便維護/blablabla....

其中呢,exe就是軟體的啟動模塊。在你打開exe之後,Windows會根據exe的要求,把exe需要的其他模塊(也就是dll),也一起載入進來。以這個exe為啟動點關聯起來的(exe和dll們)這麼一堆代碼,就被稱為一個進程。

所以 ,外掛只要偽裝成要被exe載入的dll,就能被載入到exe所在的進程辣~然後就可以幹壞事啦!

這裡可能有人要問了,那我為什麼不幹脆把外掛做成一個獨立的進程,然後去入侵遊戲的進程呢?

原因是操作系統不允許。自古以來,一個進程要進入別的進程的空間,乾的肯定不是什麼好事(也沒有什麼碼農希望別人可以隨意修改自己的代碼吧...)(DOS玩家請不要打我),所以現代操作系統都有專門的設計,會隔離各個進程,不可以(直接)訪問其他進程(甚至操作系統的服務進程也不能(直接)訪問!還記得今年早些的熔斷/幽靈漏洞么...就是突破了這個限制...)

為啥說不能(直接)呢....比如Windows吧...Windows的確是隔離進程的,但是同時,他又給了不少介面,有需要的進程就可以通過這些個介面,在操作系統做媒的情況下,訪問別的進程的一部分空間....(吐血)不過事實上!還是很少有外掛用這種方式搞破壞。因為操作系統提供的這些介面太謹慎了,能幹的事情還是太少了。

所以,大部分外掛還是選擇直接做成dll,直接成為遊戲進程里的一等公民,這樣就可以無痛快捷的直接訪(xiu)問(gai)整塊進程了,豈不美哉?

但是其實「偽裝」這個做法還是不夠好。你偽裝成了exe需要的dll,你的確是載入進去了,但是exe本來要用的那個模塊的功能就遭殃了...(不過說實話,答主三四年前做DNF外掛的時候,還真見過這種操作...)

所以現在的外掛進入進程,用的都是dll注入技術。聽名字就知道,就是和打針一樣,把exe不需要的dll強行載入進進程里去。

嘿嘿!事實上貼心的Windows又提供了介面,可以讓開發者直接把dll注入進其他進程去!(遊戲開發者滿臉黑線

但是魔高一尺道高一丈!現在的反外掛系統,都會監視Windows的這些個介面,發現這些介面被誰調用了!就知道外掛進來了。所以現在的遊戲dll注入,一般都用更難被檢測出來的輸入法注入 而不是Windows提供的介面(道高一尺魔高一丈((逃

輸入法注入是啥意思呢!就是Windows的一個特性,你在一個進程切換輸入法,Windows就會把輸入法的dll(輸入法dll有個別名,叫ime,但其實和dll大同小異)注入到當前進程里去。因為這個是輸入法dll,還是操作系統官方名正言順的注入,所以反外掛系統也很難判斷...

大概就是這些了!


在現代的操作系統里,每個進程都有一個獨立的運行空間。

進程和進程間互相獨立,互不干擾。

但是有時候,需要hack一個程序,最典型的用途就是(外掛!)

這個時候,需要把代碼「送入」目標進程。

「送入」目標進程方法很多,最自然簡單的就是把代碼編譯成dll,然後以dll為載體送入另一個程序。也就是所謂的dll注入了。

具體怎麼實現,方法很多。

最簡單的方法是:SetWindowsHookEx

SetWindowsHookExW function?

docs.microsoft.com圖標

這個方法只要你編譯好dll,剩下的windows都幫你做了。

再比如:CreateRemoteThread

CreateRemoteThread function?

docs.microsoft.com圖標

也經常用來做遠程注入。

方法很多,個人在這個方向研究不多,隨便講講。


1、利用一個API,CreatRemoteThread,以及一般來說都是固定位置的LoadLibrary,嗯,對,創建的線程的入口地址就是LoadLibrary。

2、利用調試API,自己查MSDN,干正經營生後,我不記得了。

3、另一個API,SetWindowsHook,就是掛個監視什麼鍵盤啦之類的鉤子,這個鉤子函數所在的DLL會被映射到目標進程空間的,在目標進程的線程中執行的。

推薦你一本書《windows核心編程》。

最後告訴各位有志青年,黑客不賺錢,賺錢不靠黑客技術,破解遊戲也不賺錢,還很麻煩,很累,像個瘋狗沒日沒夜,最後弄完了一毛錢都賺不到。

正經營生賺錢多了,體面,愉快,幫人解決了問題,又賺到了銀子,都能放在檯面上炫耀的,千萬別去做下水道的老鼠,骯髒、寂寞、沒吃的還被人打!


知乎小透明,終於有一個我好像知道的東西了,我們在windows中的這些文件比如說exe可執行文件,sys,dll等文件他們其實在本質上都是一樣的!他們都共同遵循一個文件格式,叫做PE文件格式,感興趣的同學可以去了解下,然後我們的一個進程呢,不管遊戲也好還是其他的東西也好,他們作為進程實際上只是一個空間的概念負責管理這個運行的程序的內存空間(虛擬內存)以及各種資源,比如一個典型的32位進程的4gb虛擬空間中,就會有一個exe文件加上n多個使用到的dll文件,這個exe作為這個進程的運行需要的主體,其他的dll在大部分情況下都是提供導出函數之類的活。。。

然後以上這些和dll注入有什麼關係呢,當我們想要針對一個遊戲進程做一些操作的時候,比如外掛,我想要讓這個遊戲進程做一些我想做的事,當在程序中想做些什麼操作時,那一定是執行了某些代碼,你想讓目標進程做一些你期望的事的時候就需要讓他執行一些你的代碼,這個代碼可以是進程本身帶有的,也可能是你人為加入進去的,怎麼往一個進程中加入一段你的代碼,然後並且讓他可以正常的運行呢?

最直接的就是shellcode,也就是直接把一段代碼的二進位直接寫到目標進程中去,但是這麼做很麻煩,具體麻煩在哪裡呢,以一般c/c++的代碼舉例,你在代碼中調用一個函數,在彙編層面或者二進位硬編碼層面,他可能是call 目標函數地址 或者 call [函數地址表中某一項]這兩種調用方式。

這裡對於第一種調用,他直接寫死了調用的目標函數的地址,如果你直接把這個代碼複製到其他進程空間去,那你這段代碼所指向的地址在其他進程空間中根本就不知道他此時到底指向的是什麼鬼,貿然執行百分之99.999999會跑飛,第二種間接調用也一樣,所以shellcode為了保證你注入的代碼能運行,就需要針對你的代碼做非常多的修正或者限制,太麻煩了。。。

那想要讓編寫注入的代碼和編寫普通代碼一樣簡單,想把更多精力花在功能流程上怎麼辦?這就到了我們的dll注入

之前說了我們的dll和exe本質上是一樣一樣的,dll和exe一樣也有入口函數(我指的不是那個oep而是和main函數一樣的dllmain或者叫dllenter函數)當在某些情況下,比如進程第一次載入這個dll到內存中時,或者進程卸載這個dll時,或者進程啟動一個線程時或者幹掉一個線程時這幾種情況下都會調用這個dllmain

這樣一來知道這點後我們只要想辦法把我們希望執行的代碼寫在這個dll里,然後在dllmain中調用他,最後想辦法讓目標進程載入我們這個dll就可以實現讓目標進程執行我們代碼的目的

那麼怎麼讓目標進程載入我們的dll呢?(好吧我承認我前面一直在跑題)

最簡單的方法就是使用APL CreateRemoteThread在目標進程中創建遠程線程,然後這個遠程線程的線程函數體就指向LoadLibraey載入我們自己的dll,這樣遠程線程跑起來以後就會載入我們的dll,然後因為我們的dll第一次載入進目標進程空間,所以會執行dllmain,然後就順理成章的執行了我們事先準備好的猥瑣代碼了。。。

至於怎麼讓目標進程在執行loadlibrary的時候參數是我們的的dll的路徑呢,這個可以我們用writeProcessMemory配合VirtualAllocEx將路徑事先寫入目標進程的內存空間

至於怎麼獲取目標進程中LoadLibrary這個函數在目標進程中的虛擬地址呢?實際上ntdll.dll和kernel32.dll他們在你計算機中每個進程中映射的基址都一樣,那麼也就是說這幾個dll中的函數地址不管在哪個進程中無論是你當前進程,還是目標遊戲進程中函數地址都是一樣的,拿來用就好。。

以上是最基礎的遠線程注入,實際上我們還可以通過劫持dll的方式實現dll的注入,或者直接將這個dll當作一堆數據,自己模擬系統載入pe文件的方式將這個dll複製到目標進程空間中並做各種修正,。。。不過後面這個比較麻煩。。。我打字打的手疼不想寫了。。。略略略略略略。。。。好吧以上一半時間在跑題2333如果有錯請指正或者和我打一架。。。


sigh, 樓上的比喻寫的得亂七八糟的,我不用比喻解釋一下……

  1. DLL(Dynamic Link Library)是一個封裝了代碼和數據的文件,這個文件可以載入到其他的進程中,載入了以後這個進程就可以通過某種其他的方式調用這個文件中的代碼。
  2. 因為是你要做一些壞事,所以載入這個DLL的行為不是由受害者進程的代碼做的,是你通過其他的方式做的。這種載入就會被定性成注入DLL。
  3. 具體實現參考 @跳舞的污泥 給出的鏈接,裡面說的非常詳細和全面。


推薦閱讀:

TAG:C | CC |