网络游戏外挂制作之我所见(7)

时间:2021-03-08 17:36:15
在本章中,我们主要来研究一下封包的制作和发送,同样,我们所采用的方法是Delphi+winsock2来制作。在以前说过在Delphi中只封装了winsock1,winsock2需要自已封装一下,我在此就不多介绍如何封装了。
下面就一步步实现我们的封包封装与发送吧:
首先,我们应该知道,封包是分两段的,一段是IP,一段是协议(TCP,UDP,其他协议),IP就像邮政编码一样,标识着你的这个封包是从哪里到哪里,而协议里记录着目标所要用到的包的格式及校验等,在网络游戏中的协议一般都是自已定义的,要破解网络游戏最重要的是学会破解网络游戏的协议网络游戏协议破解,为了不影响现运行的网络游戏的安全,我在此会以UDP协议为例,介绍一下网络协议的封包与发送的全过程。
接下来,我们就可以开始看看整个封包全过程了:
   1)我们要起动sock2,这时个要用到的WSAStartup函数,用法如下:
INTEGER WSAStartup(
                  wVersionRequired: word,
                  WSData: TWSA_DATA
                 );
在程序中wVersionRequired我们传入的值为$0002,WSData为TWSA_DATA的结构。
   2)使用socket函数创建并得到socket句柄; 用法如下:
INTEGER socket(af: Integer,
              Struct: Integer,
              protocol: Integer
             );  
注意的是在我们的程序封包中饱含了IP包头,所以我们的Struct参数这里要传入的参数值为2,表示包含了包头。该函数返回值为刚刚创建的winsocket的句柄。
   3)使用setsockopt函数设置sock的选项; 用法如下:
INTEGER setsockopt(s: Integer,
                  level: Integer,
                  optname: Integer,
                  optval: PChar,
                  optlen: Integer
                 );
在S处传入的是Socket句柄,在本程序里level输入的值为0表示IP(如果是6表示TCP,17表示UDP等~),OptName里写入2,而optval的初始值填入1,optlen为optval的大小。
   4)接下来我们要分几个步骤来实现构建封包:
 1、把IP转换成sock地址,用inet_addr来转换。
Longint  inet_addr(
                  cp: PChar
                 );
 2、定义包的总大小、IP的版本信息为IP结构:
    总包大小=IP头的大小+UDP头的大小+UDP消息的大小,
    IP的版本,在此程序里定义为4,
 3、填写IP包头的结构:
     ip.ipverlen := IP的版本 shl 4;
     ip.iptos := 0;                // IP服务类型
     ip.iptotallength := ;         // 总包大小
     ip.ipid := 0;                 // 唯一标识,一般设置为0
     ip.ipoffset := 0;             // 偏移字段
     ip.ipttl := 128;              // 超时时间
     ip.ipprotocol := $11;         // 定义协议
     ip.ipchecksum := 0 ;          // 检验总数
     ip.ipsrcaddr := ;             // 源地址
     ip.ipdestaddr := ;            // 目标地址
 4、填写UDP包头的结构:
     udp.srcportno := ;            //源端口号
     udp.dstportno := ;            //目标端口号
     udp.udplength := ;            //UDP包的大小
     udp.udpchecksum :=  ;         //检验总数
 5、把IP包头,UDP包头及消息,放入缓存。
 6、定义远程信息:
     remote.family := 2;
     remote.port :=;               //远程端口
     remote.addr.addr :=;          //远程地址

   5)我们用SendTo发送封包,用法如下:  
INTEGER sendto(s: Integer,
              var Buf: Integer,
              var len: Integer,
              var flags: Integer,
              var addrto: TSock_Addr;
              tolen: Integer
             );  
在S处传入的是Socket句柄,Buf是刚刚建好的封包,len传入封包的总长度刚刚计算过了,flag是传入标记在这里我们设为0,addto发送到的目标地址,在这里我们就传入remote就可以了,tolen写入的是remote的大小。
 
   6)到了最后别忘记了用CloseSocket(sh)关了socket和用WSACleanup关了winsock。

最后要说的是这种发送方式,只能发送完全被破解的网络协议,如果要在别人的程序中间发送数据就只有用APIHOOK或在winsock2做中间层了。如果大家还有什么问题需要和我讨论,请发邮件到microprogramer@hotmail.com或加QQ:24259132。