給網遊寫一個掛吧(三) – 啟動外掛下

來源:互聯網
上載者:User

前面的文章給網遊寫一個掛吧 啟動外掛上介紹了IME注入的方法,本文解釋第二種方法。

 

有的遊戲限制比較多,可能會將IME注入也禁用掉……這個時候就需要另想方法了。其實我們的目的很簡單,就是要讓不知道我們掛存在的遊戲,在某個時刻將掛作為遊戲的一個組件載入進來。IME注入是作業系統強制塞給遊戲的,當然遊戲有權利選擇不要。那麼我們可以用暴力解決,強制遊戲載入外掛:

1.         比如利用緩衝區溢位漏洞(參考文章 如何利用緩衝區溢位的程式錯誤來運行駭客程式 和 如何利用緩衝區溢位的程式錯誤來運行駭客程式(續))。

2.         還有就是在遊戲每次都會執行的函數上掛個鉤子 ,但是一般的Windows鉤子都會被遊戲禁用掉……而本文的方法是Hook DirectX EndScene函數,即遊戲在繪圖結束後調用的函數,而且遊戲會在一秒內經常調用這個函數,簡直就是把它當訊息佇列使!

 

WOW – 使用DirectX EndScene注入技術

這個方法可以用在WOW 3.3.5.13930上,現在已經不行了,有興趣的朋友可以自己搭一個3.3.5.13930的私服試試。據說有很多方法可以注入(DirectX EndScene函數在d3d9.dll檔案中):

1、 在遊戲檔案夾裡放一個d3d9.dll,因為Windows是先搜尋遊戲的工作目錄再尋找system32檔案夾的,所以會載入到自訂的d3d9.dll。

2、 直接在遊戲啟動前把system32檔案夾中的d3d9.dll換成自己的。

3、 使用IDA直接擷取EndScene的地址,並且在遊戲啟動後,修改這個地址的彙編碼,使其先調用我們的函數,再由我們的函數將控制權交還給真實的EndScene程式。

4、 在外掛裡啟動遊戲,啟動時先將遊戲進程暫停,執行一系列Hook操作:

a)         先Hook LoadLibrary以便在遊戲載入d3d9.dll的時候;

b)         再Hook d3d9.dll裡的Direct3DCreate9函數,

c)         再通過Hook過的Direct3DCreate9函數擷取D3D9的指標,

d)         從D3D9指標處Hook D3D9->CreateDevice函數,以擷取指向裝置的指標Device。

e)         再從Device指標處Hook Device->EndScene函數。

5、 在Windows作業系統裡建立一個自己的Device。

6、 或者就是使用SetWindowsHookEx API安裝一個系統層級的Hook,然後我們的外掛就會被載入進每一個進程!參考文檔:http://www.woodmann.com/forum/archive/index.php/t-11023.htm

 

這裡我只用過第4種方法,因此本文也只介紹第4種方法,這裡我們用到EasyHook這個庫,這個庫允許我們使用C#代碼Hook系統API。EasyHook的用法很簡單:

1、 在包含Hook函數的託管DLL裡,建立一個類,實現了EasyHook.IEntryPoint這個介面。

2、 在類的建構函式裡建立與宿主進程的串連。

3、 然後在IEntryPoint.Run函數裡,註冊你的Hook,下面是以CreateFile這個系統API為例:

 1、    public void Run(RemoteHooking.IContext InContext, String InChannelName)

2、    {
3、       CreateFileHook = LocalHook.Create(
4、           LocalHook.GetProcAddress("kernel32.dll", "CreateFileW"),
5、           new DCreateFile(CreateFile_Hooked),
6、           this);
7、    
8、       CreateFileHook.ThreadACL.SetExclusiveACL(new Int32[] {0});
9、    }

 

在第5行裡,那個DCreateFile就是CreateFile在C#中的委託表現方式,因為是通過函數指標的方式執行的,因此會聲明成一個委託。

4、 最後在外掛裡,使用下面的代碼註冊Hook:

1、 static void Main(string[] args)
2、 {
3、     Config.Register(
4、     "A FileMon like demo application.",
5、     "FileMon.exe",
6、     "FileMonInject.dll");
7、 
8、     RemoteHooking.IpcCreateServer<FileMonInterface>(
9、         ref ChannelName, WellKnownObjectMode.SingleCall);
10、 
11、    RemoteHooking.Inject(
12、        Int32.Parse(args[0]),
13、        "FileMonInject.dll",
14、        "FileMonInject.dll",
15、        ChannelName);

16、 } 


5、 代碼裡,還有一個關鍵的地方,就是Hook後擷取的指標是一個COM介面,即拿到的是一個虛函數表,因此在Hook EndScene方法的時候,就是把這個COM介面的EndScene的虛函數指標換成我們自己的,如下表的介面定義和替換方法:

1、    public unsafe class D3D9
2、    {
3、        [StructLayout(LayoutKind.Sequential, Pack = 4)]
4、        public struct IDirect3DDevice9
5、        {
6、            public IntPtr** VFTable;
7、        }
8、    }
9、    public IDirect3DDevice9(D3D9.IDirect3D9* InNativeIDirect3D9, 
10、    D3D9.IDirect3DDevice9* InNativeIDirect3DDevice9)
11、    {
12、    NativeIDirect3D9 = InNativeIDirect3D9;
13、    NativeIDirect3DDevice9 = InNativeIDirect3DDevice9;

14、    OverrideFunctions();
15、    }

16、    public D3D9.IDirect3D9* NativeIDirect3D9 
17、    { 
18、    get; private set; 
19、    }

20、    public D3D9.IDirect3DDevice9* NativeIDirect3DDevice9 
21、    {
22、    get; private set; 
23、    }

24、    private void OverrideFunctions()
25、    {
26、    OriginalEndScene = NativeIDirect3DDevice9->VFTable[0][42];

27、    RealEndScene =
28、    (DelegateEndScene)Marshal.GetDelegateForFunctionPointer(
29、    OriginalEndScene, typeof (DelegateEndScene));

30、    MyEndScene = EndScene;
31、    IntPtr PointerToMyEndScene = Marshal.GetFunctionPointerForDelegate(MyEndScene);

32、    NativeIDirect3DDevice9->VFTable[0][42] = PointerToMyEndScene;
33、    }

34、    public uint EndScene(D3D9.IDirect3DDevice9 Device)
35、    {
36、    // 防止多線程訪問
37、    lock (LuaInterface.dataLock)
38、    {
39、    // 先做我們自己的事情,然後再將控制權轉移給真正的EndScene函數

40、    return RealEndScene(Device);
41、    }

42、    } 


比如在第37行 – 41行,就是在EndScene調用的時候,先做我們的事情,然後再把控制權交給真正的EndScene。而第26行,EndScene函數IDirect3DDevice9的第42個函數,因為在第3行,代碼已經將IDirect3DDevice9介面(實際就是一個虛函數表)當成一個普通的C/C++結構體處理 – 而且是32位機上的結構體(如果要支援64位改一下就可以了),而第6行代碼,就是把這個虛函數表當作一個普通的數組處理。不過據說在DirectX10裡已經把EndScene去掉了……

 

這種方式,網上已經有完整的原始碼,請在此下載(這個代碼跟本文講解使用的代碼是不同的,因此有興趣的朋友可以自行研究下面的代碼):

https://github.com/spazzarama/Direct3DHook

 

而EasyHook的使用方式和詳細原理,請參考文檔:

http://www.codeproject.com/Articles/27637/EasyHook-The-reinvention-of-Windows-API-hooking 

 

最後如果大家對調試技術感興趣的話,可以考慮購買我的新書: 應用程式調試技術,這套視頻除了講解調試的技巧外,還盡量完整地講解了周邊用到的技術,這是因為調試技術要好的話,需要基礎功和背景知識紮實才行。 

未完待續…… 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.