![游戲外掛常用程序_第1頁](http://file4.renrendoc.com/view/eba3227ab8b71ceee9138af32b3776ae/eba3227ab8b71ceee9138af32b3776ae1.gif)
![游戲外掛常用程序_第2頁](http://file4.renrendoc.com/view/eba3227ab8b71ceee9138af32b3776ae/eba3227ab8b71ceee9138af32b3776ae2.gif)
![游戲外掛常用程序_第3頁](http://file4.renrendoc.com/view/eba3227ab8b71ceee9138af32b3776ae/eba3227ab8b71ceee9138af32b3776ae3.gif)
![游戲外掛常用程序_第4頁](http://file4.renrendoc.com/view/eba3227ab8b71ceee9138af32b3776ae/eba3227ab8b71ceee9138af32b3776ae4.gif)
![游戲外掛常用程序_第5頁](http://file4.renrendoc.com/view/eba3227ab8b71ceee9138af32b3776ae/eba3227ab8b71ceee9138af32b3776ae5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
一、前言
所謂游戲外掛,其實是一種游戲外輔程序,它可以協(xié)助玩家自動產(chǎn)生游戲動作、修改游戲網(wǎng)絡(luò)數(shù)據(jù)包以及修改游戲內(nèi)存數(shù)據(jù)等,以實現(xiàn)玩家用最少的時間和金錢去完成功力升級和過關(guān)斬將。雖然,現(xiàn)在對游戲外掛程序的“合法”身份眾說紛紜,在這里我不想對此發(fā)表任何個人意見,讓時間去說明一切吧。
隨著網(wǎng)絡(luò)游戲的時代的來臨,游戲外掛在原有的功能之上進(jìn)行了新的發(fā)展,它變得更加多種多樣,功能更加強(qiáng)大,操作更加簡單,以至有些游戲的外掛已經(jīng)成為一個體系,比如《石器時代》,外掛品種達(dá)到了幾十種,自動戰(zhàn)斗、自動行走、自動練級、自動補(bǔ)血、加速、不遇敵、原地遇敵、快速增加經(jīng)驗值、按鍵精靈……幾乎無所不包。
游戲外掛的設(shè)計主要是針對于某個游戲開發(fā)的,我們可以根據(jù)它針對的游戲的類型可大致可將外掛分為兩種大類。
一類是將游戲中大量繁瑣和無聊的攻擊動作使用外掛自動完成,以幫助玩家輕松搞定攻擊對象并可以快速的增加玩家的經(jīng)驗值。比如在《龍族》中有一種工作的設(shè)定,玩家的工作等級越高,就可以駕馭越好的裝備。但是增加工作等級卻不是一件有趣的事情,毋寧說是重復(fù)枯燥的機(jī)械勞動。如果你想做法師用的杖,首先需要做基本工作--?砍樹。砍樹的方法很簡單,在一棵大樹前不停的點鼠標(biāo)就可以了,每10000的經(jīng)驗升一級。這就意味著玩家要在大樹前不停的點擊鼠標(biāo),這種無聊的事情通過"按鍵精靈"就可以解決。外掛的"按鍵精靈"功能可以讓玩家擺脫無趣的點擊鼠標(biāo)的工作。
另一類是由外掛程序產(chǎn)生欺騙性的網(wǎng)絡(luò)游戲封包,并將這些封包發(fā)送到網(wǎng)絡(luò)游戲服務(wù)器,利用這些虛假信息欺騙服務(wù)器進(jìn)行游戲數(shù)值的修改,達(dá)到修改角色能力數(shù)值的目的。這類外掛程序針對性很強(qiáng),一般在設(shè)計時都是針對某個游戲某個版本來做的,因為每個網(wǎng)絡(luò)游戲服務(wù)器與客戶端交流的數(shù)據(jù)包各不相同,外掛程序必須要對欺騙的網(wǎng)絡(luò)游戲服務(wù)器的數(shù)據(jù)包進(jìn)行分析,才能產(chǎn)生服務(wù)器識別的數(shù)據(jù)包。這類外掛程序也是當(dāng)前最流利的一類游戲外掛程序。
另外,現(xiàn)在很多外掛程序功能強(qiáng)大,不僅實現(xiàn)了自動動作代理和封包功能,而且還提供了對網(wǎng)絡(luò)游戲的客戶端程序的數(shù)據(jù)進(jìn)行修改,以達(dá)到欺騙網(wǎng)絡(luò)游戲服務(wù)器的目的。我相信,隨著網(wǎng)絡(luò)游戲商家的反外掛技術(shù)的進(jìn)展,游戲外掛將會產(chǎn)生更多更優(yōu)秀的技術(shù),讓我們期待著看場技術(shù)大戰(zhàn)吧
三、外掛技術(shù)綜述
可以將開發(fā)游戲外掛程序的過程大體上劃分為兩個部分:
前期部分工作是對外掛的主體游戲進(jìn)行分析,不同類型的外掛分析主體游戲的內(nèi)容也不相同。如外掛為上述談到的外掛類型中的第一類時,其分析過程常是針對游戲的場景中的攻擊對象的位置和分布情況進(jìn)行分析,以實現(xiàn)外掛自動進(jìn)行攻擊以及位置移動。如外掛為外掛類型中的第二類時,其分析過程常是針對游戲服務(wù)器與客戶端之間通訊包數(shù)據(jù)的結(jié)構(gòu)、內(nèi)容以及加密算法的分析。因網(wǎng)絡(luò)游戲公司一般都不會公布其游戲產(chǎn)品的通訊包數(shù)據(jù)的結(jié)構(gòu)、內(nèi)容和加密算法的信息,所以對于開發(fā)第二類外掛成功的關(guān)鍵在于是否能正確分析游戲包數(shù)據(jù)的結(jié)構(gòu)、內(nèi)容以及加密算法,雖然可以使用一些工具輔助分析,但是這還是一種堅苦而復(fù)雜的工作。后期部分工作主要是根據(jù)前期對游戲的分析結(jié)果,使用大量的程序開發(fā)技術(shù)編寫外掛程序以實現(xiàn)對游戲的控制或修改。如外掛程序為第一類外掛時,通常會使用到鼠標(biāo)模擬技術(shù)來實現(xiàn)游戲角色的自動位置移動,使用鍵盤模擬技術(shù)來實現(xiàn)游戲角色的自動攻擊。如外掛程序為第二類外掛時,通常會使用到擋截Sock和擋截API函數(shù)技術(shù),以擋截游戲服務(wù)器傳來的網(wǎng)絡(luò)數(shù)據(jù)包并將數(shù)據(jù)包修改后封包后傳給游戲服務(wù)器。另外,還有許多外掛使用對游戲客戶端程序內(nèi)存數(shù)據(jù)修改技術(shù)以及游戲加速技術(shù)。
本文主要是針對開發(fā)游戲外掛程序后期使用的程序開發(fā)技術(shù)進(jìn)行探討,重點介紹的如下幾種在游戲外掛中常使用的程序開發(fā)技術(shù):
●動作模擬技術(shù):主要包括鍵盤模擬技術(shù)和鼠標(biāo)模擬技術(shù)。
●封包技術(shù):主要包括擋截Sock技術(shù)和擋截API技術(shù)。
四、動作模擬技術(shù)
我們在前面介紹過,幾乎所有的游戲都有大量繁瑣和無聊的攻擊動作以增加玩家的功力,還有那些數(shù)不完的迷宮,這些好像已經(jīng)成為了角色游戲的代名詞?,F(xiàn)在,外掛可以幫助玩家從這些繁瑣而無聊的工作中擺脫出來,專注于游戲情節(jié)的進(jìn)展。外掛程序為了實現(xiàn)自動角色位置移動和自動攻擊等功能,需要使用到鍵盤模擬技術(shù)和鼠標(biāo)模擬技術(shù)。下面我們將重點介紹這些技術(shù)并編寫一個簡單的實例幫助讀者理解動作模擬技術(shù)的實現(xiàn)過程。
1.鼠標(biāo)模擬技術(shù)
幾乎所有的游戲中都使用了鼠標(biāo)來改變角色的位置和方向,玩家僅用一個小小的鼠標(biāo),就可以使角色暢游天下。那么,我們?nèi)绾螌崿F(xiàn)在沒有玩家的參與下角色也可以自動行走呢。其實實現(xiàn)這個并不難,僅僅幾個WindowsAPI函數(shù)就可以搞定,讓我們先來認(rèn)識認(rèn)識這些API函數(shù)。
(1)模擬鼠標(biāo)動作API函數(shù)mouse_event,它可以實現(xiàn)模擬鼠標(biāo)按下和放開等動作。
VOIDmouse_event(
DWORDdwFlags,//鼠標(biāo)動作標(biāo)識。
DWORDdx,//鼠標(biāo)水平方向位置。
DWORDdy,//鼠標(biāo)垂直方向位置。
DWORDdwData,//鼠標(biāo)輪子轉(zhuǎn)動的數(shù)量。
DWORDdwExtraInfo//一個關(guān)聯(lián)鼠標(biāo)動作輔加信息。
);
其中,dwFlags表示了各種各樣的鼠標(biāo)動作和點擊活動,它的常用取值如下:
MOUSEEVENTF_MOVE表示模擬鼠標(biāo)移動事件。
MOUSEEVENTF_LEFTDOWN表示模擬按下鼠標(biāo)左鍵。
MOUSEEVENTF_LEFTUP表示模擬放開鼠標(biāo)左鍵。
MOUSEEVENTF_RIGHTDOWN表示模擬按下鼠標(biāo)右鍵。
MOUSEEVENTF_RIGHTUP表示模擬放開鼠標(biāo)右鍵。
MOUSEEVENTF_MIDDLEDOWN表示模擬按下鼠標(biāo)中鍵。
MOUSEEVENTF_MIDDLEUP表示模擬放開鼠標(biāo)中鍵。
(2)、設(shè)置和獲取當(dāng)前鼠標(biāo)位置的API函數(shù)。獲取當(dāng)前鼠標(biāo)位置使用GetCursorPos()函數(shù),設(shè)置當(dāng)前鼠標(biāo)位置使用SetCursorPos()函數(shù)。
BOOLGetCursorPos(
LPPOINTlpPoint//返回鼠標(biāo)的當(dāng)前位置。
);
BOOLSetCursorPos(
intX,//鼠標(biāo)的水平方向位置。
intY//鼠標(biāo)的垂直方向位置。
);
通常游戲角色的行走都是通過鼠標(biāo)移動至目的地,然后按一下鼠標(biāo)的按鈕就搞定了。下面我們使用上面介紹的API函數(shù)來模擬角色行走過程。CPointoldPoint,newPoint;
GetCursorPos(&oldPoint);//保存當(dāng)前鼠標(biāo)位置。
newPoint.x=oldPoint.x+40;
newPoint.y=oldPoint.y+10;
SetCursorPos(newPoint.x,newPoint.y);//設(shè)置目的地位置。
mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);//模擬按下鼠標(biāo)右鍵。
mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);//模擬放開鼠標(biāo)右鍵。消息說明WM_LBUTTONDBLCLKOnLButtonBlclk(UINTnFlag,CPointpoint)鼠標(biāo)左鍵被雙擊WM_LBUTTONDDOWNOnLButtonDown(UINTnFlag,CPointpoint)鼠標(biāo)左鍵被按下WM_LBUTTONDUPOnLButtonUp(UINTnFlag,CPointpoint)鼠標(biāo)左鍵被釋放WM_MBUTTONDBLCLKOnLMButtonBlclk(UINTnFlag,CPointpoint)鼠標(biāo)中間鍵被雙擊WM_MBUTTONDDOWNOnLMButtonDown(UINTnFlag,CPointpoint)鼠標(biāo)中間鍵被壓下WM_MBUTTONDUPOnLMButtonUp(UINTnFlag,CPointpoint)鼠標(biāo)中間鍵被釋放WM_MOUSEMOVEOnMoveMove(UINTnFlag,CPointpoint)鼠標(biāo)移動穿過客戶區(qū)域WM_RBUTTONDBLCKLOnRButtonBlclk(UINTnFlag,CPointpoint)鼠標(biāo)右鍵被雙擊WM_RBUTTONDDOWNOnRButtonDown(UINTnFlag,CPointpoint)鼠標(biāo)右鍵被按下WM_RBUTTONDUPOnRButtonUp(UINTnFlag,CPointpoint)鼠標(biāo)右鍵被釋放
2.鍵盤模擬技術(shù)
在很多游戲中,不僅提供了鼠標(biāo)的操作,而且還提供了鍵盤的操作,在對攻擊對象進(jìn)行攻擊時還可以使用快捷鍵。為了使這些攻擊過程能夠自動進(jìn)行,外掛程序需要使用鍵盤模擬技術(shù)。像鼠標(biāo)模擬技術(shù)一樣,WindowsAPI也提供了一系列API函數(shù)來完成對鍵盤動作的模擬。
模擬鍵盤動作API函數(shù)keydb_event,它可以模擬對鍵盤上的某個或某些鍵進(jìn)行按下或放開的動作。
VOIDkeybd_event(
BYTEbVk,//虛擬鍵值。
BYTEbScan,//硬件掃描碼。
DWORDdwFlags,//動作標(biāo)識。
DWORDdwExtraInfo//與鍵盤動作關(guān)聯(lián)的輔加信息。
);
其中,bVk表示虛擬鍵值,其實它是一個BYTE類型值的宏,其取值范圍為1-254。有關(guān)虛擬鍵值表請在MSDN上使用關(guān)鍵字“Virtual-KeyCodes”查找相關(guān)資料。bScan表示當(dāng)鍵盤上某鍵被按下和放開時,鍵盤系統(tǒng)硬件產(chǎn)生的掃描碼,我們可以MapVirtualKey()函數(shù)在虛擬鍵值與掃描碼之間進(jìn)行轉(zhuǎn)換。dwFlags表示各種各樣的鍵盤動作,它有兩種取值:
KEYEVENTF_EXTENDEDKEY和KEYEVENTF_KEYUP。
下面我們使用一段代碼實現(xiàn)在游戲中按下Shift+R快捷鍵對攻擊對象進(jìn)行攻擊。
keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),0,0);//按下CTRL鍵。
keybd_event(0x52,MapVirtualKey(0x52,0),0,0);//鍵下R鍵。
keybd_event(0x52,MapVirtualKey(0x52,0),KEYEVENTF_KEYUP,0);//放開R鍵。
keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),
KEYEVENTF_KEYUP,0);//放開CTRL鍵。3.激活外掛
上面介紹的鼠標(biāo)和鍵盤模擬技術(shù)實現(xiàn)了對游戲角色的動作部分的模擬,但要想外掛能工作于游戲之上,還需要將其與游戲的場景窗口聯(lián)系起來或者使用一個激活鍵,就象按鍵精靈的那個激活鍵一樣。我們可以用GetWindow函數(shù)來枚舉窗口,也可以用Findwindow函數(shù)來查找特定的窗口。另外還有一個FindWindowEx函數(shù)可以找到窗口的子窗口,當(dāng)游戲切換場景的時候我們可以用FindWindowEx來確定一些當(dāng)前窗口的特征,從而判斷是否還在這個場景,方法很多了,比如可以GetWindowInfo來確定一些東西,比如當(dāng)查找不到某個按鈕的時候就說明游戲場景已經(jīng)切換了等等辦法。當(dāng)使用激活鍵進(jìn)行關(guān)聯(lián),需要使用Hook技術(shù)開發(fā)一個全局鍵盤鉤子,在這里就不具體介紹全局鉤子的開發(fā)過程了,在后面的實例中我們將會使用到全局鉤子,到時將學(xué)習(xí)到全局鉤子的相關(guān)知識。
4.實例實現(xiàn)
通過上面的學(xué)習(xí),我們已經(jīng)基本具備了編寫動作式游戲外掛的能力了。下面我們將創(chuàng)建一個畫筆程序外掛,它實現(xiàn)自動移動畫筆字光標(biāo)的位置并寫下一個紅色的“R”字。以這個實例為基礎(chǔ),加入相應(yīng)的游戲動作規(guī)則,就可以實現(xiàn)一個完整的游戲外掛。這里作者不想使用某個游戲作為例子來開發(fā)外掛(因沒有游戲商家的授權(quán)?。。?,如讀者感興趣的話可以找一個游戲試試,最好僅做測試技術(shù)用。
首先,我們需要編寫一個全局鉤子,使用它來激活外掛,激活鍵為F10。創(chuàng)建全局鉤子步驟如下:
(1).選擇MFCAppWizard(DLL)創(chuàng)建項目ActiveKey,并選擇MFCExtensionDLL(共享MFC拷貝)類型。
(2).插入新文件ActiveKey.h,在其中輸入如下代碼:
#ifndef_KEYDLL_H
#define_KEYDLL_H
classAFX_EXT_CLASSCKeyHook:publicCObject
{
public:
CKeyHook();
~CKeyHook();
HHOOKStart();//安裝鉤子
BOOLStop();//卸載鉤子
};
#endif
(3).在ActiveKey.cpp文件中加入聲明"#includeActiveKey.h"。
(4).在ActiveKey.cpp文件中加入共享數(shù)據(jù)段,代碼如下:
//Shareddatasection
#pragmadata_seg("sharedata")
HHOOKglhHook=NULL;//鉤子句柄。
HINSTANCEglhInstance=NULL;//DLL實例句柄。
#pragmadata_seg()
(5).在ActiveKey.def文件中設(shè)置共享數(shù)據(jù)段屬性,代碼如下:
SETCTIONS
shareddataREADWRITESHARED
(6).在ActiveKey.cpp文件中加入CkeyHook類的實現(xiàn)代碼和鉤子函數(shù)代碼:
//鍵盤鉤子處理函數(shù)。
extern"C"LRESULTWINAPIKeyboardProc(intnCode,WPARAMwParam,LPARAMlParam)
{
if(nCode>=0)
{
if(wParam==0X79)//當(dāng)按下F10鍵時,激活外掛。
{
//外掛實現(xiàn)代碼。
CPointnewPoint,oldPoint;
GetCursorPos(&oldPoint);
newPoint.x=oldPoint.x+40;
newPoint.y=oldPoint.y+10;
SetCursorPos(newPoint.x,newPoint.y);
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);//模擬按下鼠標(biāo)左鍵。
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);//模擬放開鼠標(biāo)左鍵。
keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,0),0,0);//按下SHIFT鍵。keybd_event(0x52,MapVirtualKey(0x52,0),0,0);//按下R鍵。
keybd_event(0x52,MapVirtualKey(0x52,0),KEYEVENTF_KEYUP,0);//放開R鍵。
keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,0),KEYEVENTF_KEYUP,0);//放開SHIFT鍵。
SetCursorPos(oldPoint.x,oldPoint.y);
}
}
returnCallNextHookEx(glhHook,nCode,wParam,lParam);
}
CKeyHook::CKeyHook(){}
CKeyHook::~CKeyHook()
{
if(glhHook)
Stop();
}
//安裝全局鉤子。
HHOOKCKeyHook::Start()
{
glhHook=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,glhInstance,0);//設(shè)置鍵盤鉤子。
returnglhHook;
}
//卸載全局鉤子。
BOOLCKeyHook::Stop()
{
BOOLbResult=TRUE;
if(glhHook)
bResult=UnhookWindowsHookEx(glhHook);//卸載鍵盤鉤子。
returnbResult;
}
(7).修改DllMain函數(shù),代碼如下:
extern"C"intAPIENTRY
DllMain(HINSTANCEhInstance,DWORDdwReason,LPVOIDlpReserved)
{
//如果使用lpReserved參數(shù)則刪除下面這行
UNREFERENCED_PARAMETER(lpReserved);
if(dwReason==DLL_PROCESS_ATTACH)
{
TRACE0("NOtePadHOOK.DLLInitializing!\n");
//擴(kuò)展DLL僅初始化一次
if(!AfxInitExtensionModule(ActiveKeyDLL,hInstance))
return0;
newCDynLinkLibrary(ActiveKeyDLL);
//把DLL加入動態(tài)MFC類庫中
glhInstance=hInstance;
//插入保存DLL實例句柄
}
elseif(dwReason==DLL_PROCESS_DETACH)
{
TRACE0("NotePadHOOK.DLLTerminating!\n");
//終止這個鏈接庫前調(diào)用它
AfxTermExtensionModule(ActiveKeyDLL);
}
return1;
}
(8).編譯項目ActiveKey,生成ActiveKey.DLL和ActiveKey.lib。
接著,我們還需要創(chuàng)建一個外殼程序?qū)⑷帚^子安裝了Windows系統(tǒng)中,這個外殼程序編寫步驟如下:
(1).創(chuàng)建一個對話框模式的應(yīng)用程序,項目名為Simulate。
(2).在主對話框中加入一個按鈕,使用ClassWizard為其創(chuàng)建CLICK事件。
(3).將ActiveKey項目Debug目錄下的ActiveKey.DLL和ActiveKey.lib拷貝到Simulate項目目錄下。
(4).從“工程”菜單中選擇“設(shè)置”,彈出ProjectSetting對話框,選擇Link標(biāo)簽,在“對象/庫模塊”中輸入ActiveKey.lib。
(5).將ActiveKey項目中的ActiveKey.h頭文件加入到Simulate項目中,并在Stdafx.h中加入#includeActiveKey.h。
(6).在按鈕單擊事件函數(shù)輸入如下代碼:
voidCSimulateDlg::OnButton1()
{
//TODAddyourcontrolnotificationhandlercodehere
if(!bSetup)
{
m_hook.Start();//激活全局鉤子。
}
else
{
m_hook.Stop();//撤消全局鉤子。
}
bSetup=!bSetup;
}
(7).編譯項目,并運行程序,單擊按鈕激活外掛。
(8).啟動畫筆程序,選擇文本工具并將筆的顏色設(shè)置為紅色,將鼠標(biāo)放在任意位置后,按F10鍵,畫筆程序自動移動鼠標(biāo)并寫下一個紅色的大寫R。圖一展示了按F10鍵前的畫筆程序的狀態(tài),圖二展示了按F10鍵后的畫筆程序的狀態(tài)。五、封包技術(shù)
通過對動作模擬技術(shù)的介紹,我們對游戲外掛有了一定程度上的認(rèn)識,也學(xué)會了使用動作模擬技術(shù)來實現(xiàn)簡單的動作模擬型游戲外掛的制作。這種動作模擬型游戲外掛有一定的局限性,它僅僅只能解決使用計算機(jī)代替人力完成那么有規(guī)律、繁瑣而無聊的游戲動作。但是,隨著網(wǎng)絡(luò)游戲的盛行和復(fù)雜度的增加,很多游戲要求將客戶端動作信息及時反饋回服務(wù)器,通過服務(wù)器對這些動作信息進(jìn)行有效認(rèn)證后,再向客戶端發(fā)送下一步游戲動作信息,這樣動作模擬技術(shù)將失去原有的效應(yīng)。為了更好地“外掛”這些游戲,游戲外掛程序也進(jìn)行了升級換代,它們將以前針對游戲用戶界面層的模擬推進(jìn)到數(shù)據(jù)通訊層,通過封包技術(shù)在客戶端擋截游戲服務(wù)器發(fā)送來的游戲控制數(shù)據(jù)包,分析數(shù)據(jù)包并修改數(shù)據(jù)包;同時還需按照游戲數(shù)據(jù)包結(jié)構(gòu)創(chuàng)建數(shù)據(jù)包,再模擬客戶端發(fā)送給游戲服務(wù)器,這個過程其實就是一個封包的過程。
封包的技術(shù)是實現(xiàn)第二類游戲外掛的最核心的技術(shù)。封包技術(shù)涉及的知識很廣泛,實現(xiàn)方法也很多,如擋截WinSock、擋截API函數(shù)、擋截消息、VxD驅(qū)動程序等。在此我們也不可能在此文中將所有的封包技術(shù)都進(jìn)行詳細(xì)介紹,故選擇兩種在游戲外掛程序中最常用的兩種方法:擋截WinSock和擋截API函數(shù)。
1.擋截WinSock
眾所周知,Winsock是Windows網(wǎng)絡(luò)編程接口,它工作于Windows應(yīng)用層,它提供與底層傳輸協(xié)議無關(guān)的高層數(shù)據(jù)傳輸編程接口。在Windows系統(tǒng)中,使用WinSock接口為應(yīng)用程序提供基于TCP/IP協(xié)議的網(wǎng)絡(luò)訪問服務(wù),這些服務(wù)是由Wsock32.DLL動態(tài)鏈接庫提供的函數(shù)庫來完成的。
由上說明可知,任何Windows基于TCP/IP的應(yīng)用程序都必須通過WinSock接口訪問網(wǎng)絡(luò),當(dāng)然網(wǎng)絡(luò)游戲程序也不例外。
由此我們可以想象一下,如果我們可以控制WinSock接口的話,那么控制游戲客戶端程序與服務(wù)器之間的數(shù)據(jù)包也將易如反掌。按著這個思路,下面的工作就是如何完成控制WinSock接口了。由上面的介紹可知,WinSock接口其實是由一個動態(tài)鏈接庫提供的一系列函數(shù),由這些函數(shù)實現(xiàn)對網(wǎng)絡(luò)的訪問。有了這層的認(rèn)識,問題就好辦多了,我們可以制作一個類似的動態(tài)鏈接庫來代替原WinSock接口庫,在其中實現(xiàn)WinSock32.dll中實現(xiàn)的所有函數(shù),并保證所有函數(shù)的參數(shù)個數(shù)和順序、返回值類型都應(yīng)與原庫相同。在這個自制作的動態(tài)庫中,可以對我們感興趣的函數(shù)(如發(fā)送、接收等函數(shù))進(jìn)行擋截,放入外掛控制代碼,最后還繼續(xù)調(diào)用原WinSock庫中提供的相應(yīng)功能函數(shù),這樣就可以實現(xiàn)對網(wǎng)絡(luò)數(shù)據(jù)包的擋截、修改和發(fā)送等封包功能。
下面重點介紹創(chuàng)建擋截WinSock外掛程序的基本步驟:
(1)創(chuàng)建DLL項目,選擇Win32Dynamic-LinkLibrary,再選擇AnemptyDLLproject。
(2)新建文件wsock32.h,按如下步驟輸入代碼:
①加入相關(guān)變量聲明:
HMODULEhModule=NULL;//模塊句柄
charbuffer[1000];//緩沖區(qū)
FARPROCproc;//函數(shù)入口指針
②定義指向原WinSock庫中的所有函數(shù)地址的指針變量,因WinSock庫共提供70多個函數(shù),限于篇幅,在此就只選擇幾個常用的函數(shù)列出,有關(guān)這些庫函數(shù)的說明可參考MSDN相關(guān)內(nèi)容。
//定義指向原WinSock庫函數(shù)地址的指針變量。SOCKET(__stdcall*socket1)(int,int,int);//創(chuàng)建Sock函數(shù)。
int(__stdcall*WSAStartup1)(WORD,LPWSADATA);//初始化WinSock庫函數(shù)。
int(__stdcall*WSACleanup1)();//清除WinSock庫函數(shù)。
int(__stdcall*recv1)(SOCKET,charFAR*,int,int);//接收數(shù)據(jù)函數(shù)。
int(__stdcall*send1)(SOCKET,constchar*,int,int);//發(fā)送數(shù)據(jù)函數(shù)。
int(__stdcall*connect1)(SOCKET,conststructsockaddr*,int);//創(chuàng)建連接函數(shù)。
int(__stdcall*bind1)(SOCKET,conststructsockaddr*,int);//綁定函數(shù)。
其它函數(shù)地址指針的定義略。
(3)新建wsock32.cpp文件,按如下步驟輸入代碼:
①加入相關(guān)頭文件聲明:
#include
#include
#include"wsock32.h"
②添加DllMain函數(shù),在此函數(shù)中首先需要加載原WinSock庫,并獲取此庫中所有函數(shù)的地址。代碼如下:
BOOLWINAPIDllMain(HANDLEhInst,ULONGul_reason_for_call,LPVOIDlpReserved)
{
if(hModule==NULL){
//加載原WinSock庫,原WinSock庫已復(fù)制為wsock32.001。
hModule=LoadLibrary("wsock32.001");
}
elsereturn1;
//獲取原WinSock庫中的所有函數(shù)的地址并保存,下面僅列出部分代碼。
if(hModule!=NULL){
//獲取原WinSock庫初始化函數(shù)的地址,并保存到WSAStartup1中。
proc=GetProcAddress(hModule,"WSAStartup");
WSAStartup1=(int(_stdcall*)(WORD,LPWSADATA))proc;
//獲取原WinSock庫消除函數(shù)的地址,并保存到WSACleanup1中。
proc=GetProcAddress(hModulei,"WSACleanup");
WSACleanup1=(int(_stdcall*)())proc;
//獲取原創(chuàng)建Sock函數(shù)的地址,并保存到socket1中。
proc=GetProcAddress(hModule,"socket");
socket1=(SOCKET(_stdcall*)(int,int,int))proc;
//獲取原創(chuàng)建連接函數(shù)的地址,并保存到connect1中。
proc=GetProcAddress(hModule,"connect");
connect1=(int(_stdcall*)(SOCKET,conststructsockaddr*,int))proc;
//獲取原發(fā)送函數(shù)的地址,并保存到send1中。
proc=GetProcAddress(hModule,"send");
send1=(int(_stdcall*)(SOCKET,constchar*,int,int))proc;
//獲取原接收函數(shù)的地址,并保存到recv1中。
proc=GetProcAddress(hModule,"recv");
recv1=(int(_stdcall*)(SOCKET,charFAR*,int,int))proc;
其它獲取函數(shù)地址代碼略。
}
elsereturn0;
return1;
}
③定義庫輸出函數(shù),在此可以對我們感興趣的函數(shù)中添加外掛控制代碼,在所有的輸出函數(shù)的最后一步都調(diào)用原WinSock庫的同名函數(shù)。部分輸出函數(shù)定義代碼如下:
//庫輸出函數(shù)定義。
//WinSock初始化函數(shù)。
intPASCALFARWSAStartup(WORDwVersionRequired,LPWSADATAlpWSAData)
{
//調(diào)用原WinSock庫初始化函數(shù)
returnWSAStartup1(wVersionRequired,lpWSAData);
}
//WinSock結(jié)束清除函數(shù)。
intPASCALFARWSACleanup(void)
{
returnWSACleanup1();//調(diào)用原WinSock庫結(jié)束清除函數(shù)。
}
//創(chuàng)建Socket函數(shù)。
SOCKETPASCALFARsocket(intaf,inttype,intprotocol)
{
//調(diào)用原WinSock庫創(chuàng)建Socket函數(shù)。
returnsocket1(af,type,protocol);
}
//發(fā)送數(shù)據(jù)包函數(shù)
intPASCALFARsend(SOCKETs,constchar*buf,intlen,intflags)
{
//在此可以對發(fā)送的緩沖buf的內(nèi)容進(jìn)行修改,以實現(xiàn)欺騙服務(wù)器。
外掛代碼
//調(diào)用原WinSock庫發(fā)送數(shù)據(jù)包函數(shù)。
returnsend1(s,buf,len,flags);
}
//接收數(shù)據(jù)包函數(shù)。
intPASCALFARrecv(SOCKETs,charFAR*buf,intlen,intflags)
{
//在此可以擋截到服務(wù)器端發(fā)送到客戶端的數(shù)據(jù)包,先將其保存到buffer中。
strcpy(buffer,buf);
//對buffer數(shù)據(jù)包數(shù)據(jù)進(jìn)行分析后,對其按照玩家的指令進(jìn)行相關(guān)修改。
外掛代碼
//最后調(diào)用原WinSock中的接收數(shù)據(jù)包函數(shù)。
returnrecv1(s,buffer,len,flags);
}
其它函數(shù)定義代碼略。
(4)、新建wsock32.def配置文件,在其中加入所有庫輸出函數(shù)的聲明,部分聲明代碼如下:
LIBRARY"wsock32"
EXPORTS
WSAStartup@1
WSACleanup@2
recv@3
send@4
socket@5
bind@6
closesocket@7
connect@8
其它輸出函數(shù)聲明代碼略。
(5)、從“工程”菜單中選擇“設(shè)置”,彈出ProjectSetting對話框,選擇Link標(biāo)簽,在“對象/庫模塊”中輸入Ws2_32.lib。
(6)、編譯項目,產(chǎn)生wsock32.dll庫文件。
(7)、將系統(tǒng)目錄下原wsock32.dll庫文件拷貝到被外掛程序的目錄下,并將其改名為wsock.001;再將上面產(chǎn)生的wsock32.dll文件同樣拷貝到被外掛程序的目錄下。重新啟動游戲程序,此時游戲程序?qū)⑾燃虞d我們自己制作的wsock32.dll文件,再通過該庫文件間接調(diào)用原WinSock接口函數(shù)來實現(xiàn)訪問網(wǎng)絡(luò)。上面我們僅僅介紹了擋載WinSock的實現(xiàn)過程,至于如何加入外掛控制代碼,還需要外掛開發(fā)人員對游戲數(shù)據(jù)包結(jié)構(gòu)、內(nèi)容、加密算法等方面的仔細(xì)分析(這個過程將是一個艱辛的過程),再生成外掛控制代碼。關(guān)于數(shù)據(jù)包分析方法和技巧,不是本文講解的范圍,如您感興趣可以到網(wǎng)上查查相關(guān)資料。
(3)、注入外掛代碼進(jìn)入被掛游戲進(jìn)程中
完成了定位和修改程序中調(diào)用API函數(shù)代碼后,我們就可以隨意設(shè)計自定義的API函數(shù)的替代函數(shù)了。做完這一切后,還需要將這些代碼注入到被外掛游戲程序進(jìn)程內(nèi)存空間中,不然游戲進(jìn)程根本不會訪問到替代函數(shù)代碼。注入方法有很多,如利用全局鉤子注入、利用注冊表注入擋截User32庫中的API函數(shù)、利用CreateRemoteThread注入(僅限于NT/2000)、利用BHO注入等。因為我們在動作模擬技術(shù)一節(jié)已經(jīng)接觸過全局鉤子,我相信聰明的讀者已經(jīng)完全掌握了全局鉤子的制作過程,所以我們在后面的實例中,將繼續(xù)利用這個全局鉤子。至于其它幾種注入方法,如果感興趣可參閱MSDN有關(guān)內(nèi)容。有了以上理論基礎(chǔ),我們下面就開始制作一個擋截MessageBoxA和recv函數(shù)的實例,在開發(fā)游戲外掛程序時,可以此實例為框架,加入相應(yīng)的替代函數(shù)和處理代碼即可。此實例的開發(fā)過程如下:
(1)打開前面創(chuàng)建的ActiveKey項目。
(2)在ActiveKey.h文件中加入HOOKAPI結(jié)構(gòu),此結(jié)構(gòu)用來存儲被擋截API函數(shù)名稱、原API函數(shù)地址和替代函數(shù)地址。
typedefstructtag_HOOKAPI
{
LPCSTRszFunc;//被HOOK的API函數(shù)名稱。
PROCpNewProc;//替代函數(shù)地址。
PROCpOldProc;//原API函數(shù)地址。
}HOOKAPI,*LPHOOKAPI;
(3)打開ActiveKey.cpp文件,首先加入一個函數(shù),用于定位輸入庫在輸入數(shù)據(jù)段中的IAT地址。代碼如下:
extern"C"__declspec(dllexport)PIMAGE_IMPORT_DESCRIPTOR
LocationIAT(HMODULEhModule,LPCSTRszImportMod)
//其中,hModule為進(jìn)程模塊句柄;szImportMod為輸入庫名稱。
{
//檢查是否為DOS程序,如是返回NULL,因DOS程序沒有IAT。
PIMAGE_DOS_HEADERpDOSHeader=(PIMAGE_DOS_HEADER)hModule;
if(pDOSHeader->e_magic!=IMAGE_DOS_SIGNATURE)returnNULL;
//檢查是否為NT標(biāo)志,否則返回NULL。
PIMAGE_NT_HEADERSpNTHeader=(PIMAGE_NT_HEADERS)((DWORD)pDOSHeader+(DWORD)(pDOSHeader->e_lfanew));
if(pNTHeader->Signature!=IMAGE_NT_SIGNATURE)returnNULL;
//沒有IAT表則返回NULL。
if(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress==0)
returnNULL;
//定位第一個IAT位置。
PIMAGE_IMPORT_DESCRIPTORpImportDesc=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDOSHeader+(DWORD)
(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
//根據(jù)輸入庫名稱循環(huán)檢查所有的IAT,如匹配則返回該IAT地址,否則檢測下一個IAT。
while(pImportDesc->Name)
{
//獲取該IAT描述的輸入庫名稱。
PSTRszCurrMod=(PSTR)((DWORD)pDOSHeader+(DWORD)(pImportDesc->Name));
if(stricmp(szCurrMod,szImportMod)==0)break;
pImportDesc++;
}
if(pImportDesc->Name==NULL)returnNULL;
returnpImportDesc;
}
再加入一個函數(shù),用來定位被擋截API函數(shù)的IAT項并修改其內(nèi)容為替代函數(shù)地址。代碼如下:
extern"C"__declspec(dllexport)
HookAPIByName(HMODULEhModule,LPCSTRszImportMod,LPHOOKAPIpHookApi)
//其中,hModule為進(jìn)程模塊句柄;szImportMod為輸入庫名稱;pHookAPI為HOOKAPI結(jié)構(gòu)指針。
{
//定位szImportMod輸入庫在輸入數(shù)據(jù)段中的IAT地址。
PIMAGE_IMPORT_DESCRIPTORpImportDesc=LocationIAT(hModule,szImportMod);
if(pImportDesc==NULL)returnFALSE;
//第一個Thunk地址。
PIMAGE_THUNK_DATApOrigThunk=(PIMAGE_THUNK_DATA)((DWORD)hModule+(DWORD)(pImportDesc->OriginalFirstThunk));
//第一個IAT項的Thunk地址。
PIMAGE_THUNK_DATApRealThunk=(PIMAGE_THUNK_DATA)((DWORD)hModule+(DWORD)(pImportDesc->FirstThunk));
//循環(huán)查找被截API函數(shù)的IAT項,并使用替代函數(shù)地址修改其值。
while(pOrigThunk->u1.Function)
{
//檢測此Thunk是否為IAT項。
if((pOrigThunk->u1.Ordinal&IMAGE_ORDINAL_FLAG)!=IMAGE_ORDINAL_FLAG)
{
//獲取此IAT項所描述的函數(shù)名稱。
PIMAGE_IMPORT_BY_NAMEpByName=(PIMAGE_IMPORT_BY_NAME)((DWORD)hModule+(DWORD)(pOrigThunk->u1.AddressOfData));
if(pByName->Name[0]=='\0')returnFALSE;
//檢測是否為擋截函數(shù)。
if(strcmpi(pHookApi->szFunc,(char*)pByName->Name)==0)
{
MEMORY_BASIC_INformATIONmbi_thunk;
//查詢修改頁的信息。
VirtualQuery(pRealThunk,&mbi_thunk,sizeof(MEMORY_BASIC_INformATION));
//改變修改頁保護(hù)屬性為PAGE_READWRITE。
VirtualProtect(mbi_thunk.BaseAd
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 湘師大版道德與法治九年級下冊3.1《多民族的大家庭》聽課評課記錄
- 教科版道德與法治八年級上冊6.2《公民的責(zé)任》聽課評課記錄
- 魯教版數(shù)學(xué)六年級上冊2.1《0科學(xué)計數(shù)法》聽評課記錄
- 岳麓版歷史七年級上冊第18課《漢代的科技與文化》聽課評課記錄
- 蘇科版數(shù)學(xué)九年級下冊5.1《二次函數(shù)》講聽評課記錄
- 五年級數(shù)學(xué)聽評課記錄表
- 人教版九年級數(shù)學(xué)上冊第二十二章二次函數(shù)《22.2二次函數(shù)與一元二次方程》第1課時聽評課記錄
- 【2022年新課標(biāo)】部編版七年級上冊道德與法治第六課 交友的智慧 2課時聽課評課記錄
- 韓式餐廳承包經(jīng)營合同范本
- 個人入股分紅協(xié)議書范本
- 2025年電力鐵塔市場分析現(xiàn)狀
- 中國服裝零售行業(yè)發(fā)展環(huán)境、市場運行格局及前景研究報告-智研咨詢(2025版)
- 臨床提高膿毒性休克患者1h集束化措施落實率PDCA品管圈
- GB/T 3478.1-1995圓柱直齒漸開線花鍵模數(shù)基本齒廓公差
- GB/T 1346-2001水泥標(biāo)準(zhǔn)稠度用水量、凝結(jié)時間、安定性檢驗方法
- FZ/T 25001-2012工業(yè)用毛氈
- 瑞幸咖啡SWOT分析
- DL∕T 1867-2018 電力需求響應(yīng)信息交換規(guī)范
- 小學(xué)生品德發(fā)展水平指標(biāo)評價體系(小學(xué))
- 水利工程地震應(yīng)急預(yù)案
- 日歷表空白每月打印計劃表
評論
0/150
提交評論