<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [轉載]給網游寫一個掛吧(二) – 啟動外掛上

      給網游寫一個掛吧(二) – 啟動外掛上 

       

      前面的文章給網游寫一個掛吧 – 反反外掛驅動的驅動,我們已經可以訪問游戲的內存之后,接下來需要:

      1.         找到游戲里關鍵元素的偏移量,比如生命值的內存的位置。一般來說,大部分大型3D游戲都是用C++編寫的,游戲里面的元素都是面向對象的,比如玩家是一個對象,那么生命值、魔法值之類的東西都是這個對象的一個屬性。按照C++的內存布局,一般來說,只要源代碼里的結構體不發生變化,屬性的偏移量一般來說都是一樣的。

      2.         找到游戲里一些關鍵函數的地址,便于外掛程序來調用。

       

      查找關鍵元素的偏移量和關鍵函數地址一般來說都是苦力活,當然也是智力活,需要你的逆向工程水平不錯,網上有些相關的教程,這里我就不再詳述了。

       

      這里假設我們已經找到游戲的偏移量了,現在的問題是如何啟動外掛以操控游戲,一般來說有幾種選擇:

      1.         要么是內掛,將掛注入到網游進程的內存空間里,這樣掛就相當于網游自己的一個組件,對游戲進程擁有絕對的訪問權,可以讀寫游戲的虛擬內存地址以及調用游戲內置的函數。這種做法的弊端是,如果游戲有非法組件檢測線程的話,很有可能被發現。

      2.         要么是外掛,將掛作為一個獨立的進程,這樣掛可以通過Read/WriteVirtualMemory來讀寫游戲的內存,再通過CreateRemoteThread API啟動一個遠程線程來調用游戲內置的函數。這種做法可以查看文章:代碼注入的三種方法

       

      那本文我們講解第一種方法 - 內掛。并針對兩款游戲來說說注入內掛的方法:

       

      DNF – 使用輸入法注入技術

      輸入法注入技術的原理是,寫一個輸入法DLL并在系統中注冊,然后向游戲發送一個切換輸入法的消息 – 當然是切換到我們寫的輸入法,Windows會加載我們的輸入法DLL,在這個DLL的DllMain函數里,我們就可以完成一些內掛加載以及初始化的工作:

      1.         首先寫一個輸入法DLL,隨便從網上下載一個示例用的輸入法源碼即可。

      2.         在輸入法DLL的DllMain函數的DLL_PROCESS_ATTACH事件中,啟動外掛線程。

      3.         在單獨的外掛進程里 – 一般來說這個進程就是用來給外掛用戶操作的一個Windows GUI程序,在合適的地方:

      a)         用imm32.dll里的ImmInstallIMEw API函數在系統里注冊我們的輸入法。

      b)         用FindWindows API查找到所有需要注入的窗口,這里就是獲取DNF的窗口句柄。

      c)         最后用PostMessage WM_INPUTLANGCHANGEREQUEST消息強迫Windows針對DNF窗口切換我們的輸入法,從而達到加載內掛的目的。

       

      關鍵代碼如下 – 整個程序大部分代碼都是用C#完成,稍后介紹選用C#的原因:

       

      輸入法注入代碼C#部分:

       

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      public bool InjectDllToWindow(string dllPath, string windowText = "地下城與勇士",

      string classText = "地下城與勇士",bool IfMonitor=true)

      {

          InjectedDll = dllPath;

          WindowText = windowText;

          ClassText = classText;

       

          // 1, 注冊輸入法

          HKL = RegisterIME();

          if (HKL == IntPtr.Zero)

          {

              MessageBox.Show(string.Format("GetLastError: {0}", GetLastError()));

              //2,如果注冊失敗,檢查是否已經被注冊

              HKL = MImeFindByName();

          }

       

          if (HKL == IntPtr.Zero)

          {

              isRegister = false;

              return false;

          }

          isRegister = true;

       

          //3,把需要注入的dll傳遞給服務輸入法dll中

          IMESetPubString(dllPath, 0, 0, 0, 0);

       

          //4,查找所有需要注入的窗口

          List<IntPtr> windowsToInject = FindWindows(classText, windowText);

       

          //5,注入輸入法到窗口

          foreach (IntPtr window in windowsToInject)

          {

              InjectToWindow(window);

          }

       

          WindowsHaveInjected = windowsToInject;

       

          if(IfMonitor)

          {

          //6,開啟監視線程,監視新的窗口,一旦開啟,立刻注入

              WorkThread thread = new WorkThread(MonitorDNFWindow);

              workThreadAsyncResult = thread.BeginInvoke(null, null);

          }

          return true;

      }

       

      private IntPtr RegisterIME()

      {

          string tempDir = Environment.CurrentDirectory;

          Environment.CurrentDirectory = Environment.SystemDirectory;//把工作目錄切換到系統目錄

          IntPtr hkl = ImmInstallIMEW(ImeName, ImeFriendlyName); //安裝服務輸入法

          Environment.CurrentDirectory=tempDir; //切換回原目錄

          return hkl;

      }

       

      private void InjectToWindow(IntPtr hWnd)

      {

          PostMessage(hWnd, WM_INPUTLANGCHANGEREQUEST, (IntPtr)0x01, HKL);

      }

       

      在上面第9行調用47 – 54行的函數,將外掛的工作目錄切換到系統目錄,因為我們將輸入法放到系統目錄,方便系統查找,并安裝輸入法。

       

      第25行里,設置在輸入法注入成功后,需要執行的操作,一般來說就是啟動掛了。有些內掛會在注入成功后,注冊一個快捷鍵,通過快捷鍵呼出一個窗口,這個窗口可以用來跟用戶操作界面通信,執行操作界面來的命令。然而,在某些游戲里,呼出的窗口會馬上被檢查到,我們這里將介紹在游戲進程里啟動.NET程序,啟動一個.NET Remoting服務的方式。

       

      第31 - 34行,通過FindWindows系統調用枚舉系統上的窗口,找到目標窗口,執行注入操作,具體的注入操作參見56 – 59行的代碼。在.NET代碼里調用C/C++函數的方式,請參閱文章:使用Signature Tool自動生成P/Invoke調用Windows API的C#函數聲明

       

      輸入法C++部分關鍵代碼:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)

      {

         switch(fdwReason)

          {

            case DLL_PROCESS_ATTACH:

          if (CilentDLL==NULL)

          {

                if (lstrlen(g_IMEDLLString)>0)

                {

                    StartTheDotNetRuntime();

                }

          }

                break;

            case DLL_THREAD_ATTACH:

               break;

            case DLL_THREAD_DETACH:

               break;

            case DLL_PROCESS_DETACH:

              break;

            default:

              break;

          }

          return true;

      }

       

      DWORD CALLBACK StartTheDotNetRuntime(LPVOID lp)

      {

              HRESULT hr = S_OK;

              ICLRMetaHost    *m_pMetaHost = NULL;

              ICLRRuntimeInfo *m_pRuntimeInfo = NULL;

              ICLRRuntimeHost    *pClrHost = NULL;

            

      hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*) &m_pMetaHost);

      if (hr != S_OK)

          return hr;

      hr = m_pMetaHost->GetRuntime (L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID*) &m_pRuntimeInfo);

      if (hr != S_OK)

          return hr;

      hr = m_pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*) &pClrHost );

             if (FAILED(hr)) return hr;

       

          hr = pClrHost->Start();

       

          DWORD dwRet = 0;

          hr = pClrHost->ExecuteInDefaultAppDomain(

              g_IMEDLLString,

              _T("ManagedDll.Program"), _T("Start"), _T("nothing to post"), &dwRet);

       

          hr = pClrHost->Stop();

       

          pClrHost->Release();

       

          return S_OK;

      }

       

      在第10行代碼,輸入法注入成功后在游戲進程里啟動.NET虛擬機,這里啟動的4.0的運行庫 – 參看36行代碼,虛擬機成功啟動后,會返回一個ICLRRuntimeHost的COM接口,根據這個接口,外掛就可以創建托管代碼運行需要的應用程序域 – 參看45 – 47行。在應用程序域里執行代碼并不需要一個.exe的可執行文件,只需要是一個托管程序的DLL文件,這個DLL文件需要放在游戲的目錄里,因為我們的掛是運行在游戲的進程里,工作目錄也自然變成了游戲的工作目錄了。

       

      在47行,我們可以看到,可以指定DLL內部任意一個類型的靜態函數作為入口點,下面是ManagedDll.Program.Start的源代碼:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      namespace ManagedDll

      {

           public class Program

          {

              static int Start(string argument)

              {

                  RemotingServer.Start();

                  while (true)

                  {

                      Thread.Sleep(1000);

                  }

                  return 0;

              }

          }

      }

       

      在第7行,我們啟動了一個.NET Remoting服務(或者說是web服務,因為.NET Web服務本來就是基于Remoting的),等待任意一個地方的Remoting客戶端鏈接……對于在非托管進程當中啟動托管程序的方法,詳情請參看:將托管dll注入到非托管進程中

       

      設計考量

       

      之所以選用C#的原因是:

      1.         可以快速編程,而且有豐富的類庫。

      2.         垃圾回收機制可以增強掛的穩定性,而且也不用考慮內存泄露的問題。

      3.         有很強大的調試工具,以我經驗來看,暫時還沒有看到比VS更強大的調試工具。

      4.         最后,在游戲進程里的內掛和外部供用戶配置的GUI程序需要通信,沒有比.NET Remoting更方便的東西了!

       

       

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

      posted on 2012-06-16 18:27  大寶pku  閱讀(513)  評論(0)    收藏  舉報

      導航

      主站蜘蛛池模板: 欧美成人精品三级网站视频| 91精品国产蜜臀在线观看| 国产精品久久久天天影视香蕉| 亚洲成av人片天堂网无码| 亚洲精品男男一区二区| 视频一区二区三区刚刚碰| 成人资源网亚洲精品在线| 国产色无码专区在线观看| 午夜免费福利小电影| 大色综合色综合网站| 中文字幕亚洲国产精品| 国产综合色在线精品| 亚洲区中文字幕日韩精品| 91亚洲国产成人精品福利| 亚洲免费福利在线视频| 90后极品粉嫩小泬20p| 精品人妻av中文字幕乱| 蜜桃av多人一区二区三区| 东京热一精品无码av| 开心五月婷婷综合网站| 在线观看国产成人AV天堂| 内射少妇一区27p| 1000部精品久久久久久久久| 亚洲日韩性欧美中文字幕| 亚洲欧美色综合影院| 亚洲熟妇自偷自拍另欧美| 人妻中文字幕av资源站| 永久免费无码国产| 国产福利深夜在线观看| 欧美激欧美啪啪片| 中文字幕成人精品久久不卡 | 柳河县| 四虎成人精品在永久免费| 人妻少妇偷人一区二区| 精品无码一区二区三区的天堂| 极品无码国模国产在线观看| 久久精品国产福利亚洲av| 国产在线中文字幕精品| 亚洲国产性夜夜综合 | 日韩有码精品中文字幕| av区无码字幕中文色|