青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Xiao.Zhu C++

Xiao.Zhu C++

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  29 隨筆 :: 14 文章 :: 17 評論 :: 0 Trackbacks
通過對動作模擬技術的介紹,我們對游戲外掛有了一定程度上的認識,也學會了使用動作模擬技術來實現簡單的動作模擬型游戲外掛的制作。這種動作模擬型游戲外掛有一定的局限性,它僅僅只能解決使用計算機代替人力完成那么有規律、繁瑣而無聊的游戲動作。但是,隨著網絡游戲的盛行和復雜度的增加,很多游戲要求將客戶端動作信息及時反饋回服務器,通過服務器對這些動作信息進行有效認證后,再向客戶端發送下一步游戲動作信息,這樣動作模擬技術將失去原有的效應。為了更好地 外掛 這些游戲,游戲外掛程序也進行了升級換代,它們將以前針對游戲用戶界面層的模擬推進到數據通訊層,通過封包技術在客戶端擋截游戲服務器發送來的游戲控制數據包,分析數據包并修改數據包;同時還需按照游戲數據包結構創建數據包,再模擬客戶端發送給游戲服務器,這個過程其實就是一個封包的過程。
  封包的技術是實現第二類游戲外掛的最核心的技術。封包技術涉及的知識很廣泛,實現方法也很多,如擋截 WinSock 、擋截 API 函數、擋截消息、 VxD 驅動程序等。在此我們也不可能在此文中將所有的封包技術都進行詳細介紹,故選擇兩種在游戲外掛程序中最常用的兩種方法:擋截 WinSock 和擋截 API 函數。
   1  擋截WinSock
  眾所周知, Winsock Windows 網絡編程接口,它工作于 Windows 應用層,它提供與底層傳輸協議無關的高層數據傳輸編程接口。在 Windows 系統中,使用 WinSock 接口為應用程序提供基于 TCP/IP 協議的網絡訪問服務,這些服務是由 Wsock32.DLL 動態鏈接庫提供的函數庫來完成的。
  由上說明可知,任何 Windows 基于 TCP/IP 的應用程序都必須通過 WinSock 接口訪問網絡,當然網絡游戲程序也不例外。由此我們可以想象一下,如果我們可以控制 WinSock 接口的話,那么控制游戲客戶端程序與服務器之間的數據包也將易如反掌。按著這個思路,下面的工作就是如何完成控制 WinSock 接口了。由上面的介紹可知, WinSock 接口其實是由一個動態鏈接庫提供的一系列函數,由這些函數實現對網絡的訪問。有了這層的認識,問題就好辦多了,我們可以制作一個類似的動態鏈接庫來代替原 WinSock 接口庫,在其中實現 WinSock32.dll 中實現的所有函數,并保證所有函數的參數個數和順序、返回值類型都應與原庫相同。在這個自制作的動態庫中,可以對我們感興趣的函數(如發送、接收等函數)進行擋截,放入外掛控制代碼,最后還繼續調用原 WinSock 庫中提供的相應功能函數,這樣就可以實現對網絡數據包的擋截、修改和發送等封包功能。
  下面重點介紹創建擋截 WinSock 外掛程序的基本步驟:
   (1)  創建 DLL 項目,選擇 Win32 Dynamic-Link Library ,再選擇 An empty DLL project
   (2)  新建文件 wsock32.h ,按如下步驟輸入代碼:
    加入相關變量聲明:
    HMODULE hModule=NULL; // 模塊句柄
    char buffer[1000]; // 緩沖區
    FARPROC proc; // 函數入口指針 
    定義指向原WinSock庫中的所有函數地址的指針變量,因WinSock庫共提供70多個函數,限于篇幅,在此就只選擇幾個常用的函數列出,有關這些庫函數的說明可參考MSDN相關內容。
    // 定義指向原 WinSock 庫函數地址的指針變量。
    SOCKET (__stdcall *socket1)(int ,int,int);// 創建 Sock 函數。
    int   (__stdcall *WSAStartup1)(WORD,LPWSADATA);// 初始化 WinSock 庫函數。
    int   (__stdcall *WSACleanup1)();// 清除 WinSock 庫函數。
    int (__stdcall *recv1)(SOCKET ,char FAR * ,int ,int );// 接收數據函數。
    int (__stdcall *send1)(SOCKET ,const char * ,int ,int);// 發送數據函數。
    int (__stdcall *connect1)(SOCKET,const struct sockaddr *,int);// 創建連接函數。
    int (__stdcall *bind1)(SOCKET ,const struct sockaddr *,int );// 綁定函數。
    ...... 其它函數地址指針的定義略。 
   (3)  新建 wsock32.cpp 文件,按如下步驟輸入代碼:
    加入相關頭文件聲明:
    #include <windows.h>
    #include <stdio.h>
    #include "wsock32.h" 
    添加DllMain函數,在此函數中首先需要加載原WinSock庫,并獲取此庫中所有函數的地址。代碼如下:
    BOOL WINAPI DllMain (HANDLE hInst,ULONG ul_reason_for_call,LPVOID lpReserved)
    {
     if(hModule==NULL){
      // 加載原 WinSock 庫,原 WinSock 庫已復制為 wsock32.001
    hModule=LoadLibrary("wsock32.001"); 
   }
     else return 1;
//
獲取原 WinSock 庫中的所有函數的地址并保存,下面僅列出部分代碼。
if(hModule!=NULL){
      // 獲取原 WinSock 庫初始化函數的地址,并保存到 WSAStartup1 中。
proc=GetProcAddress(hModule,"WSAStartup");
    WSAStartup1=(int (_stdcall *)(WORD,LPWSADATA))proc;
      // 獲取原 WinSock 庫消除函數的地址,并保存到 WSACleanup1 中。
     proc=GetProcAddress(hModule i,"WSACleanup");
     WSACleanup1=(int (_stdcall *)())proc;
      // 獲取原創建 Sock 函數的地址,并保存到 socket1 中。
     proc=GetProcAddress(hModule,"socket");
      socket1=(SOCKET (_stdcall *)(int ,int,int))proc;
      // 獲取原創建連接函數的地址,并保存到 connect1 中。
      proc=GetProcAddress(hModule,"connect");
      connect1=(int (_stdcall *)(SOCKET ,const struct sockaddr *,int ))proc;
      // 獲取原發送函數的地址,并保存到 send1 中。
      proc=GetProcAddress(hModule,"send");
      send1=(int (_stdcall *)(SOCKET ,const char * ,int ,int ))proc;
      // 獲取原接收函數的地址,并保存到 recv1 中。
      proc=GetProcAddress(hModule,"recv");
      recv1=(int (_stdcall *)(SOCKET ,char FAR * ,int ,int ))proc;
      ...... 其它獲取函數地址代碼略。
    }
    else return 0;
    return 1;
    定義庫輸出函數,在此可以對我們感興趣的函數中添加外掛控制代碼,在所有的輸出函數的最后一步都調用原WinSock庫的同名函數。部分輸出函數定義代碼如下:
// 庫輸出函數定義。
//WinSock
初始化函數。
     int PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)
     {
      // 調用原 WinSock 庫初始化函數
      return WSAStartup1(wVersionRequired,lpWSAData);
     }
     //WinSock 結束清除函數。
     int PASCAL FAR WSACleanup(void)
     {
      return WSACleanup1(); // 調用原 WinSock 庫結束清除函數。
     }
     // 創建 Socket 函數。
     SOCKET PASCAL FAR socket (int af, int type, int protocol)
     {
      // 調用原 WinSock 庫創建 Socket 函數。
      return socket1(af,type,protocol);
     }
     // 發送數據包函數
     int PASCAL FAR send(SOCKET s,const char * buf,int len,int flags)
     {
    // 在此可以對發送的緩沖 buf 的內容進行修改,以實現欺騙服務器。
   外掛代碼 ......
    // 調用原 WinSock 庫發送數據包函數。
      return send1(s,buf,len,flags);
     }
//
接收數據包函數。
     int PASCAL FAR recv(SOCKET s, char FAR * buf, int len, int flags)
     {
    // 在此可以擋截到服務器端發送到客戶端的數據包,先將其保存到 buffer 中。
    strcpy(buffer,buf);
    // buffer 數據包數據進行分析后,對其按照玩家的指令進行相關修改。
   外掛代碼 ......
    // 最后調用原 WinSock 中的接收數據包函數。
      return recv1(s, buffer, len, flags);
      }
     ....... 其它函數定義代碼略。 
   (4) 、新建 wsock32.def 配置文件,在其中加入所有庫輸出函數的聲明,部分聲明代碼如下:
    LIBRARY "wsock32"
    EXPORTS 
     WSAStartup @1
    WSACleanup @2
     recv @3
     send @4
     socket @5
    bind @6
    closesocket @7
    connect @8 
    ...... 其它輸出函數聲明代碼略。
   (5) 、從 工程 菜單中選擇 設置 ,彈出 Project Setting 對話框,選擇 Link 標簽,在 對象 / 庫模塊 中輸入 Ws2_32.lib
   (6) 、編譯項目,產生 wsock32.dll 庫文件。
   (7) 、將系統目錄下原 wsock32.dll 庫文件拷貝到被外掛程序的目錄下,并將其改名為 wsock.001 ;再將上面產生的 wsock32.dll 文件同樣拷貝到被外掛程序的目錄下。重新啟動游戲程序,此時游戲程序將先加載我們自己制作的 wsock32.dll 文件,再通過該庫文件間接調用原 WinSock 接口函數來實現訪問網絡。上面我們僅僅介紹了擋載 WinSock 的實現過程,至于如何加入外掛控制代碼,還需要外掛開發人員對游戲數據包結構、內容、加密算法等方面的仔細分析(這個過程將是一個艱辛的過程),再生成外掛控制代碼。關于數據包分析方法和技巧,不是本文講解的范圍,如您感興趣可以到網上查查相關資料。
   2. 擋截 API
  擋截 API 技術與擋截 WinSock 技術在原理上很相似,但是前者比后者提供了更強大的功能。擋截 WinSock 僅只能擋截 WinSock 接口函數,而擋截 API 可以實現對應用程序調用的包括 WinSock API 函數在內的所有 API 函數的擋截。如果您的外掛程序僅打算對 WinSock 的函數進行擋截的話,您可以只選擇使用上小節介紹的擋截 WinSock 技術。隨著大量外掛程序在功能上的擴展,它們不僅僅只提供對數據包的擋截,而且還對游戲程序中使用的 Windows API 或其它 DLL 庫函數的擋截,以使外掛的功能更加強大。例如,可以通過擋截相關 API 函數以實現對非中文游戲的漢化功能,有了這個利器,可以使您的外掛程序無所不能了。
  擋截 API 技術的原理核心也是使用我們自己的函數來替換掉 Windows 或其它 DLL 庫提供的函數,有點同擋截 WinSock 原理相似吧。但是,其實現過程卻比擋截 WinSock 要復雜的多,如像實現擋截 Winsock 過程一樣,將應用程序調用的所有的庫文件都寫一個模擬庫有點不大可能,就只說 Windows API 就有上千個,還有很多庫提供的函數結構并未公開,所以寫一個模擬庫代替的方式不大現實,故我們必須另謀良方。
  擋截 API 的最終目標是使用自定義的函數代替原函數。那么,我們首先應該知道應用程序何時、何地、用何種方式調用原函數。接下來,需要將應用程序中調用該原函數的指令代碼進行修改,使它將調用函數的指針指向我們自己定義的函數地址。這樣,外掛程序才能完全控制應用程序調用的 API 函數,至于在其中如何加入外掛代碼,就應需求而異了。最后還有一個重要的問題要解決,如何將我們自定義的用來代替原 API 函數的函數代碼注入被外掛游戲程序進行地址空間中,因在 Windows 系統中應用程序僅只能訪問到本進程地址空間內的代碼和數據。
  綜上所述,要實現擋截 API 函數,至少需要解決如下三個問題:
   ●  如何定位游戲程序中調用 API 函數指令代碼?
   ●  如何修改游戲程序中調用 API 函數指令代碼?
   ●  如何將外掛代碼(自定義的替換函數代碼)注入到游戲程序進程地址空間?
  下面我們逐一介紹這幾個問題的解決方法:
   (1)  、定位調用 API 函數指令代碼
  我們知道,在匯編語言中使用 CALL 指令來調用函數或過程的,它是通過指令參數中的函數地址而定位到相應的函數代碼的。那么,我們如果能尋找到程序代碼中所有調用被擋截的 API 函數的 CALL 指令的話,就可以將該指令中的函數地址參數修改為替代函數的地址。雖然這是一個可行的方案,但是實現起來會很繁瑣,也不穩健。慶幸的是, Windows 系統中所使用的可執行文件( PE 格式)采用了輸入地址表機制,將所有在程序調用的 API 函數的地址信息存放在輸入地址表中,而在程序代碼 CALL 指令中使用的地址不是 API 函數的地址,而是輸入地址表中該 API 函數的地址項,如想使程序代碼中調用的 API 函數被代替掉,只用將輸入地址表中該 API 函數的地址項內容修改即可。具體理解輸入地址表運行機制,還需要了解一下 PE 格式文件結構,其中圖三列出了 PE 格式文件的大致結構。

  圖三: PE 格式大致結構圖 (003.jpg)
   PE 格式文件一開始是一段 DOS 程序,當你的程序在不支持 Windows 的環境中運行時,它就會顯示 “This Program cannot be run in DOS mode” 這樣的警告語句,接著這個 DOS 文件頭,就開始真正的 PE 文件內容了。首先是一段稱為 “IMAGE_NT_HEADER” 的數據,其中是許多關于整個 PE 文件的消息,在這段數據的尾端是一個稱為 Data Directory 的數據表,通過它能快速定位一些 PE 文件中段( section )的地址。在這段數據之后,則是一個 “IMAGE_SECTION_HEADER” 的列表,其中的每一項都詳細描述了后面一個段的相關信息。接著它就是 PE 文件中最主要的段數據了,執行代碼、數據和資源等等信息就分別存放在這些段中。
  在所有的這些段里,有一個被稱為 “.idata” 的段(輸入數據段)值得我們去注意,該段中包含著一些被稱為輸入地址表( IAT Import Address Table )的數據列表。每個用隱式方式加載的 API 所在的 DLL 都有一個 IAT 與之對應,同時一個 API 的地址也與 IAT 中一項相對應。當一個應用程序加載到內存中后,針對每一個 API 函數調用,相應的產生如下的匯編指令: 
   JMP DWORD PTR [XXXXXXXX] 
  或
   CALL DWORD PTR [XXXXXXXX]
  其中, [XXXXXXXX] 表示指向了輸入地址表中一個項,其內容是一個 DWORD ,而正是這個 DWORD 才是 API 函數在內存中的真正地址。因此我們要想攔截一個 API 的調用,只要簡單的把那個 DWORD 改為我們自己的函數的地址。
   (2)  、修改調用 API 函數代碼
  從上面對 PE 文件格式的分析可知,修改調用 API 函數代碼其實是修改被調用 API 函數在輸入地址表中 IAT 項內容。由于 Windows 系統對應用程序指令代碼地址空間的嚴密保護機制,使得修改程序指令代碼非常困難,以至于許多高手為之編寫 VxD 進入 Ring0 。在這里,我為大家介紹一種較為方便的方法修改進程內存,它僅需要調用幾個 Windows 核心 API 函數,下面我首先來學會一下這幾個 API 函數:
    DWORD VirtualQuery(
    LPCVOID lpAddress, // address of region
    PMEMORY_BASIC_INFORMATION lpBuffer, // information buffer
    DWORD dwLength // size of buffer
    ); 
  該函數用于查詢關于本進程內虛擬地址頁的信息。其中, lpAddress 表示被查詢頁的區域地址; lpBuffer 表示用于保存查詢頁信息的緩沖; dwLength 表示緩沖區大小。返回值為實際緩沖大小。
    BOOL VirtualProtect(
    LPVOID lpAddress, // region of committed pages
    SIZE_T dwSize, // size of the region
    DWORD flNewProtect, // desired access protection
    PDWORD lpflOldProtect // old protection
    ); 
  該函數用于改變本進程內虛擬地址頁的保護屬性。其中, lpAddress 表示被改變保護屬性頁區域地址; dwSize 表示頁區域大小; flNewProtect 表示新的保護屬性,可取值為 PAGE_READONLY PAGE_READWRITE PAGE_EXECUTE 等; lpflOldProtect 表示用于保存改變前的保護屬性。如果函數調用成功返回 “T” ,否則返回 “F”
  有了這兩個 API 函數,我們就可以隨心所欲的修改進程內存了。首先,調用 VirtualQuery() 函數查詢被修改內存的頁信息,再根據此信息調用 VirtualProtect() 函數改變這些頁的保護屬性為 PAGE_READWRITE ,有了這個權限您就可以任意修改進程內存數據了。下面一段代碼演示了如何將進程虛擬地址為 0x0040106c 處的字節清零。
    BYTE* pData = 0x0040106c;
    MEMORY_BASIC_INFORMATION mbi_thunk; 
    // 查詢頁信息。
    VirtualQuery(pData, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION)); 
    // 改變頁保護屬性為讀寫。
    VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize, 
    PAGE_READWRITE, &mbi_thunk.Protect); 
    // 清零。
    *pData = 0x00;
    // 恢復頁的原保護屬性。
    DWORD dwOldProtect; 
    VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize, 
    mbi_thunk.Protect, &dwOldProtect); 
   (3) 、注入外掛代碼進入被掛游戲進程中
  完成了定位和修改程序中調用 API 函數代碼后,我們就可以隨意設計自定義的 API 函數的替代函數了。做完這一切后,還需要將這些代碼注入到被外掛游戲程序進程內存空間中,不然游戲進程根本不會訪問到替代函數代碼。注入方法有很多,如利用全局鉤子注入、利用注冊表注入擋截 User32 庫中的 API 函數、利用 CreateRemoteThread 注入(僅限于 NT/2000 )、利用 BHO 注入等。因為我們在動作模擬技術一節已經接觸過全局鉤子,我相信聰明的讀者已經完全掌握了全局鉤子的制作過程,所以我們在后面的實例中,將繼續利用這個全局鉤子。至于其它幾種注入方法,如果感興趣可參閱 MSDN 有關內容。
  有了以上理論基礎,我們下面就開始制作一個擋截 MessageBoxA recv 函數的實例,在開發游戲外掛程序 時,可以此實例為框架,加入相應的替代函數和處理代碼即可。此實例的開發過程如下:
   (1)  打開前面創建的 ActiveKey 項目。
   (2)  ActiveKey.h 文件中加入 HOOKAPI 結構,此結構用來存儲被擋截 API 函數名稱、原 API 函數地址和替代函數地址。
    typedef struct tag_HOOKAPI 
   
    LPCSTR szFunc;// HOOK API 函數名稱。
    PROC pNewProc;// 替代函數地址。
    PROC pOldProc;// API 函數地址。
    }HOOKAPI, *LPHOOKAPI; 
   (3)  打開 ActiveKey.cpp 文件,首先加入一個函數,用于定位輸入庫在輸入數據段中的 IAT 地址。代碼如下:
    extern "C" __declspec(dllexport)PIMAGE_IMPORT_DESCRIPTOR 
    LocationIAT(HMODULE hModule, LPCSTR szImportMod) 
    // 其中, hModule 為進程模塊句柄; szImportMod 為輸入庫名稱。
   
    // 檢查是否為 DOS 程序,如是返回 NULL ,因 DOS 程序沒有 IAT
    PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) hModule; 
    if(pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE) return NULL; 
     // 檢查是否為 NT 標志,否則返回 NULL
     PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDOSHeader+ (DWORD)(pDOSHeader->e_lfanew)); 
     if(pNTHeader->Signature != IMAGE_NT_SIGNATURE) return NULL; 
     // 沒有 IAT 表則返回 NULL
     if(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0) return NULL; 
     // 定位第一個 IAT 位置。  
     PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDOSHeader + (DWORD)(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)); 
     // 根據輸入庫名稱循環檢查所有的 IAT ,如匹配則返回該 IAT 地址,否則檢測下一個 IAT
     while (pImportDesc->Name) 
    
      // 獲取該 IAT 描述的輸入庫名稱。
    PSTR szCurrMod = (PSTR)((DWORD)pDOSHeader + (DWORD)(pImportDesc->Name)); 
    if (stricmp(szCurrMod, szImportMod) == 0) break; 
    pImportDesc++; 
    
     if(pImportDesc->Name == NULL) return NULL; 
    return pImportDesc; 
   
  再加入一個函數,用來定位被擋截 API 函數的 IAT 項并修改其內容為替代函數地址。代碼如下:
    extern "C" __declspec(dllexport) 
    HookAPIByName( HMODULE hModule, LPCSTR szImportMod, LPHOOKAPI pHookApi) 
    // 其中, hModule 為進程模塊句柄; szImportMod 為輸入庫名稱; pHookAPI HOOKAPI 結構指針。
   
     // 定位 szImportMod 輸入庫在輸入數據段中的 IAT 地址。
     PIMAGE_IMPORT_DESCRIPTOR pImportDesc = LocationIAT(hModule, szImportMod); 
   if (pImportDesc == NULL) return FALSE; 
     // 第一個 Thunk 地址。
     PIMAGE_THUNK_DATA pOrigThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc->OriginalFirstThunk)); 
    // 第一個 IAT 項的 Thunk 地址。
     PIMAGE_THUNK_DATA pRealThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc->FirstThunk)); 
     // 循環查找被截 API 函數的 IAT 項,并使用替代函數地址修改其值。
    while(pOrigThunk->u1.Function) 

  // 檢測此 Thunk 是否為 IAT 項。
if((pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG) 
{
   // 獲取此 IAT 項所描述的函數名稱。
  PIMAGE_IMPORT_BY_NAME pByName =(PIMAGE_IMPORT_BY_NAME)((DWORD)hModule+(DWORD)(pOrigThunk->u1.AddressOfData)); 
  if(pByName->Name[0] == ‘\\0‘) return FALSE; 
   // 檢測是否為擋截函數。
if(strcmpi(pHookApi->szFunc, (char*)pByName->Name) == 0) 
   { 
        MEMORY_BASIC_INFORMATION mbi_thunk;
        // 查詢修改頁的信息。
        VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION)); 
//
改變修改頁保護屬性為 PAGE_READWRITE
        VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect); 
//
保存原來的 API 函數地址。
      if(pHookApi->pOldProc == NULL) 
pHookApi->pOldProc = (PROC)pRealThunk->u1.Function; 
  //修改API函數IAT項內容為替代函數地址。
pRealThunk->u1.Function = (PDWORD)pHookApi->pNewProc; 
//
恢復修改頁保護屬性。
DWORD dwOldProtect; 
       VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect); 
      } 

  pOrigThunk++; 
  pRealThunk++; 

  SetLastError(ERROR_SUCCESS); //設置錯誤為ERROR_SUCCESS,表示成功。
  return TRUE; 
   
   (4)  定義替代函數,此實例中只給 MessageBoxA recv 兩個 API 進行擋截。代碼如下:
    static int WINAPI MessageBoxA1 (HWND hWnd , LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
    {
     // 過濾掉原 MessageBoxA 的正文和標題內容,只顯示如下內容。
return MessageBox(hWnd, "Hook API OK!", "Hook API", uType); 
   
    static int WINAPI recv1(SOCKET s, char FAR *buf, int len, int flags )
    {
    // 此處可以擋截游戲服務器發送來的網絡數據包,可以加入分析和處理數據代碼。
    return recv(s,buf,len,flags);
   
   (5)  KeyboardProc 函數中加入激活擋截 API 代碼,在 if( wParam == 0X79 ) 語句中后面加入如下 else if 語句:
    ......
    // 當激活 F11 鍵時,啟動擋截 API 函數功能。
    else if( wParam == 0x7A )
   
     HOOKAPI api[2];
api[0].szFunc ="MessageBoxA";//
設置被擋截函數的名稱。
api[0].pNewProc = (PROC)MessageBoxA1;//
設置替代函數的地址。
api[1].szFunc ="recv";//
設置被擋截函數的名稱。
api[1].pNewProc = (PROC)recv1; //
設置替代函數的地址。
//
設置擋截 User32.dll 庫中的 MessageBoxA 函數。
HookAPIByName(GetModuleHandle(NULL),"User32.dll",&api[0]);
//
設置擋截 Wsock32.dll 庫中的 recv 函數。
HookAPIByName(GetModuleHandle(NULL),"Wsock32.dll",&api[1]);
    }
    ...... 
   (6)  ActiveKey.cpp 中加入頭文件聲明  "#include "wsock32.h"  工程菜單中選擇設置,彈出Project Setting對話框,選擇Link標簽,在對象/庫模塊中輸入Ws2_32..lib
   (7)  重新編譯 ActiveKey 項目,產生 ActiveKey.dll 文件,將其拷貝到 Simulate.exe 目錄下。運行 Simulate.exe 并啟動全局鉤子。激活任意應用程序,按 F11 鍵后,運行此程序中可能調用 MessageBoxA 函數的操作,看看信息框是不是有所變化。同樣,如此程序正在接收網絡數據包,就可以實現封包功能了。
posted on 2007-04-28 15:56 Xiao.Zhu 閱讀(758) 評論(0)  編輯 收藏 引用
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品久久久久久久久久ktv | 一本一道久久综合狠狠老精东影业 | 午夜在线电影亚洲一区| 一区二区高清在线| 夜夜嗨一区二区三区| 99热精品在线| 亚洲国产成人91精品| 国产一区二区丝袜高跟鞋图片| 国产片一区二区| 伊人久久噜噜噜躁狠狠躁| 亚洲国产欧美另类丝袜| 在线视频中文亚洲| 欧美在线一区二区三区| 老司机成人网| 日韩视频三区| 久久国产日本精品| 欧美成人高清| 国产精品视频免费观看| 黄网站免费久久| 中文久久精品| 美女91精品| 亚洲日本精品国产第一区| 亚洲精品自在在线观看| 午夜精品短视频| 欧美国产日韩精品免费观看| 国产精品日韩欧美一区二区| 亚洲电影激情视频网站| 亚洲欧美日韩一区| 欧美激情一区二区三区蜜桃视频| 亚洲精品视频在线看| 欧美一区二区三区免费视频| 欧美高清成人| 韩国三级电影一区二区| 在线天堂一区av电影| 男女视频一区二区| 亚洲欧美日本国产专区一区| 欧美大香线蕉线伊人久久国产精品| 欧美日韩一区国产| 最新亚洲电影| 久久夜色精品国产噜噜av| 亚洲最黄网站| 欧美精品三级日韩久久| 国内久久精品| 欧美在线一二三| 亚洲国产精品99久久久久久久久| 亚洲深夜福利在线| 亚洲第一偷拍| 久久久中精品2020中文| 国产日产欧美一区| 性娇小13――14欧美| 日韩网站免费观看| 欧美精品日韩| 亚洲精品国产精品国产自| 久久婷婷久久| 久久国产精品99久久久久久老狼| 国产精品乱码一区二三区小蝌蚪| 99精品久久久| 日韩亚洲国产精品| 欧美三级资源在线| 亚洲一区免费观看| 亚洲图片欧美午夜| 国产精品视频九色porn| 亚洲欧美国产77777| 亚洲精品在线视频观看| 欧美日韩国产综合久久| 中文在线资源观看网站视频免费不卡 | 国产偷国产偷精品高清尤物| 一区二区三区视频观看| 亚洲第一精品夜夜躁人人躁| 久久综合久久综合久久综合| 在线看无码的免费网站| 欧美国内亚洲| 欧美日韩国产麻豆| 午夜精品99久久免费| 久久精品99无色码中文字幕| 亚洲一区日韩| 国产日韩欧美二区| 久久久久国产精品www | 欧美日韩国产综合在线| aa国产精品| 亚洲一区中文| 精品动漫3d一区二区三区免费版| 久久影视精品| 欧美激情片在线观看| 一区二区三区精密机械公司| 99v久久综合狠狠综合久久| 国产精品成人播放| 久久久一二三| 欧美精品一区二区三区高清aⅴ| 美女脱光内衣内裤视频久久影院 | 欧美色图天堂网| 欧美怡红院视频| 久久综合国产精品| 中日韩美女免费视频网站在线观看 | 欧美成人资源| 欧美日韩一级黄| 久久免费视频在线观看| 国产日韩在线一区| 在线视频亚洲| 欧美一级视频精品观看| 欧美三级日韩三级国产三级| 蜜桃av噜噜一区| 一区在线影院| 久久精品视频在线免费观看| 欧美在线播放一区| 国产乱码精品一区二区三区av| av成人免费| 亚洲欧洲av一区二区| 国产精品成人一区二区三区夜夜夜 | 欧美激情综合| 午夜亚洲福利| 久久久久久久久久久一区| 国产精品第一页第二页第三页| 亚洲国产你懂的| 亚洲大胆人体视频| 欧美精品v日韩精品v国产精品| 免费日韩成人| 国产视频久久久久| 久久综合久久久久88| 亚洲欧美成人一区二区在线电影 | 国产美女精品| 亚洲国产毛片完整版| 国产精品一区二区久久久久| 欧美国产一区视频在线观看| 国产精品一卡二| 夜夜精品视频一区二区| 亚洲人成网站777色婷婷| 欧美一区二区三区的| 性欧美精品高清| 国产精品大片免费观看| 日韩视频免费在线观看| 亚洲精品欧美| 久久综合九色九九| 欧美成人有码| 在线播放日韩欧美| 久久久久免费视频| 久久久精品日韩欧美| 国产精品永久免费在线| 在线视频日本亚洲性| 亚洲尤物在线视频观看| 欧美日韩国产精品成人| 亚洲国产一区视频| 亚洲精品资源| 欧美激情一区二区三区四区| 欧美国产日韩视频| 在线免费不卡视频| 久久综合色影院| 欧美高清在线播放| 亚洲精品激情| 欧美精品免费在线观看| 日韩午夜精品视频| 亚洲五月婷婷| 国产伦精品一区二区三区在线观看 | 久久精品夜色噜噜亚洲aⅴ| 国产伦精品一区二区三区视频黑人 | 欧美一区二区三区婷婷月色| 久久国产视频网| 激情成人亚洲| 欧美高清视频一区二区| 在线视频精品一区| 欧美一区二视频| 亚洲动漫精品| 欧美日韩免费视频| 欧美亚洲综合在线| 欧美韩日一区二区三区| 中文国产一区| 国产在线观看91精品一区| 免费不卡中文字幕视频| 99精品福利视频| 久久久777| 日韩一二三在线视频播| 国产精品久久久久久久久久免费看 | 欧美一级久久久| 欧美丰满高潮xxxx喷水动漫| 一个色综合av| 黄网动漫久久久| 亚洲经典视频在线观看| 亚洲日本中文字幕免费在线不卡| 欧美日韩的一区二区| 欧美一级精品大片| 99视频精品全部免费在线| 久久香蕉国产线看观看av| 亚洲欧洲日本国产| 国产午夜一区二区三区| 欧美高清不卡| 欧美在线一区二区| 99国产精品国产精品久久| 久久亚洲电影| 亚洲欧美中文另类| 亚洲国产精品久久人人爱蜜臀 | 亚洲午夜电影网| 欧美国产日韩一区二区| 欧美在线一二三| 亚洲自拍电影| 亚洲国产一区二区三区青草影视| 国产精品高潮粉嫩av| 欧美激情免费观看| 午夜精品一区二区三区四区| 最新亚洲视频| 亚洲第一中文字幕在线观看|