网络游戏外挂核心封包揭密
網(wǎng)絡游戲的封包技術是大多數(shù)編程愛好者都比較關注的關注的問題之一,在這里就讓我們一起研究一下這一個問題吧。
別看這是封包這一問題,但是涉及的技術范圍很廣范,實現(xiàn)的方式也很多(比如說APIHOOK,VXD,Winsock2都可以實現(xiàn)),在這里我們不可能每種技術和方法都涉及,所以我在這里以Winsock2技術作詳細講解,就算作拋磚引玉。
由于大多數(shù)讀者對封包類編程不是很了解,我在這里就簡單介紹一下相關知識:
APIHooK:
由于Windows的把內(nèi)核提供的功能都封裝到API里面,所以大家要實現(xiàn)功能就必須通過API,換句話說就是我們要想捕獲數(shù)據(jù)封包,就必須先要得知道并且捕獲這個API,從API里面得到封包信息。
VXD:
直接通過控制VXD驅(qū)動程序來實現(xiàn)封包信息的捕獲,不過VXD只能用于win9X。
winsock2:
winsock是Windows網(wǎng)絡編程接口,winsock工作在應用層,它提供與底層傳輸協(xié)議無關的高層數(shù)據(jù)傳輸編程接口,winsock2是winsock2.0提供的服務提供者接口,但只能在win2000下用。
好了,我們開始進入winsock2封包式編程吧。
在封包編程里面我準備分兩個步驟對大家進行講解:1、封包的捕獲,2、封包的發(fā)送。
首先我們要實現(xiàn)的是封包的捕獲:
Delphi的封裝的winsock是1.0版的,很自然winsock2就用不成。如果要使用winsock2我們要對winsock2在Delphi里面做一個接口,才可以使用winsock2。
1、如何做winsock2的接口?
1)我們要先定義winsock2.0所用得到的類型,在這里我們以WSA_DATA類型做示范,大家可以舉一仿三的來實現(xiàn)winsock2其他類型的封裝。
我們要知道WSA_DATA類型會被用于WSAStartup(wVersionRequired: word; var WSData: TWSAData): Integer;,大家會發(fā)現(xiàn)WSData是引用參數(shù),在傳入?yún)?shù)時傳的是變量的地址,所以我們對WSA_DATA做以下封裝:
const
WSADESCRIPTION_LEN = 256;
WSASYS_STATUS_LEN = 128;
type
PWSA_DATA = ^TWSA_DATA;
WSA_DATA = record
wVersion: Word;
wHighVersion: Word;
szDescription: array[0..WSADESCRIPTION_LEN] of Char;
szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char;
iMaxSockets: Word;
iMaxUdpDg: Word;
lpVendorInfo: PChar;
end;
TWSA_DATA = WSA_DATA;?
2)我們要從WS2_32.DLL引入winsock2的函數(shù),在此我們也是以WSAStartup為例做函數(shù)引入:
function WSAStartup(wVersionRequired: word; var WSData: TWSAData): Integer; stdcall;
implementation
const WinSocket2 = 'WS2_32.DLL';
function WSAStartup; external winsocket name 'WSAStartup';?
通過以上方法,我們便可以對winsock2做接口,下面我們就可以用winsock2做封包捕獲了,不過首先要有一塊網(wǎng)卡。因為涉及到正在運作的網(wǎng)絡游戲安全問題,所以我們在這里以IP數(shù)據(jù)包為例做封包捕獲,如果下面的某些數(shù)據(jù)類型您不是很清楚,請您查閱MSDN:
1)我們要起動WSA,這時個要用到的WSAStartup函數(shù),用法如下:
INTEGER WSAStartup(
wVersionRequired: word,
WSData: TWSA_DATA
);
2)使用socket函數(shù)得到socket句柄,m_hSocket:=Socket(AF_INET, SOCK_RAW, IPPROTO_IP); 用法如下:
INTEGER socket(af: Integer,
Struct: Integer,
protocol: Integer
);
m_hSocket:=Socket(AF_INET, SOCK_RAW, IPPROTO_IP);
在程序里m_hSocket為socket句柄,AF_INET,SOCK_RAW,IPPROTO_IP均為常量。
3)定義SOCK_ADDR類型,跟據(jù)我們的網(wǎng)卡IP給Sock_ADDR類型附值,然后我們使用bind函數(shù)來綁定我們的網(wǎng)卡,Bind函數(shù)用法如下:
Type
IN_ADDR = record
S_addr : PChar;
End;
Type
TSOCK_ADDR = record
sin_family: Word;
sin_port: Word;
sin_addr : IN_ADDR
sin_zero: array[0..7] of Char;
End;
var
LocalAddr:TSOCK_ADDR;
LocalAddr.sin_family: = AF_INET;
LocalAddr.sin_port: = 0;
LocalAddr.sin_addr.S_addr: = inet_addr('192.168.1.1'); //這里你自己的網(wǎng)卡的IP地址,而inet_addr這個函數(shù)是winsock2的函數(shù)。
bind(m_hSocket, LocalAddr, sizeof(LocalAddr));
4)用WSAIoctl來注冊WSA的輸入輸出組件,其用法如下:
INTEGER WSAIoctl(s:INTEGER,
dwIoControlCode : INTEGER,
lpvInBuffer :INTEGER,
cbInBuffer : INTEGER,
lpvOutBuffer : INTEGER,
cbOutBuffer: INTEGER,
lpcbBytesReturned : INTEGER,
lpOverlapped : INTEGER,
lpCompletionRoutine : INTEGER
);
5)下面做死循環(huán),在死循環(huán)塊里,來實現(xiàn)數(shù)據(jù)的接收。但是徇環(huán)中間要用Sleep()做延時,不然程序會出錯。
6)在循環(huán)塊里,用recv函數(shù)來接收數(shù)據(jù),recv函數(shù)用法如下:
INTEGER recv (s : INTEGER,
buffer:Array[0..4095] of byte,
length : INTEGER,
flags : INTEGER,
);
7)在buffer里就是我們接收回來的數(shù)據(jù)了,如果我們想要知道數(shù)據(jù)是什么地方發(fā)來的,那么,我們要定義一定IP包結(jié)構(gòu),用CopyMemory()把IP信息從buffer里面讀出來就可以了,不過讀出來的是十六進制的數(shù)據(jù)需要轉(zhuǎn)換一下。
看了封包捕獲的全過程序,對你是不是有點起發(fā),然而在這里要告訴大家的是封包的獲得是很容易的,但是許多游戲的封包都是加密的,如果你想搞清楚所得到的是什么內(nèi)容還需要自己進行封包解密。
總結(jié)
以上是生活随笔為你收集整理的网络游戏外挂核心封包揭密的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sql遍历所有数据集
- 下一篇: NAT类型及检测方法