新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → 游戏外挂的编写原理 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 8332 个阅读者浏览上一篇主题  刷新本主题   平板显示贴子 浏览下一篇主题
     * 贴子主题: 游戏外挂的编写原理 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 

    (5).将ActiveKey项目中的ActiveKey.h头文件加入到Simulate项目中,并在
    Stdafx.h中加入#include

    ActiveKey.h。

      (6).在按钮单击事件函数输入如下代码:

       void CSimulateDlg::OnButton1()
       {
    // TODO: Add your control notification handler code here
    if( !bSetup )
    {
    m_hook.Start();//激活全局钩子。
    }
    else
    {
    m_hook.Stop();//撤消全局钩子。
    }
    bSetup = !bSetup;

       }

      (7).编译项目,并运行程序,单击按钮激活外挂。

      (8).启动画笔程序,选择文本工具并将笔的颜色设置为红色,将鼠标放在任意位置
    后,按F10键,画笔程序自动移

    动鼠标并写下一个红色的大写R。图一展示了按F10键前的画笔程序的状态,图二展示了
    按F10键后的画笔程序的状态。


    图一:按F10前状态(001.jpg)


    图二:按F10后状态(002.jpg)


    五、封包技术

      通过对动作模拟技术的介绍,我们对游戏外挂有了一定程度上的认识,也学会了使
    用动作模拟技术来实现简单的

    动作模拟型游戏外挂的制作。这种动作模拟型游戏外挂有一定的局限性,它仅仅只能解
    决使用计算机代替人力完成那

    么有规律、繁琐而无聊的游戏动作。但是,随着网络游戏的盛行和复杂度的增加,很多
    游戏要求将客户端动作信息及

    时反馈回服务器,通过服务器对这些动作信息进行有效认证后,再向客户端发送下一步
    游戏动作信息,这样动作模拟

    技术将失去原有的效应。为了更好地“外挂”这些游戏,游戏外挂程序也进行了升级换
    代,它们将以前针对游戏用户

    界面层的模拟推进到数据通讯层,通过封包技术在客户端挡截游戏服务器发送来的游戏
    控制数据包,分析数据包并修

    改数据包;同时还需按照游戏数据包结构创建数据包,再模拟客户端发送给游戏服务
    器,这个过程其实就是一个封包

    的过程。

      封包的技术是实现第二类游戏外挂的最核心的技术。封包技术涉及的知识很广泛,
    实现方法也很多,如挡截

    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

       ......其它输出函数声明代码略。

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/12/12 10:05:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/6/16 15:43:17

    本主题贴数10,分页: [1]

     *树形目录 (最近20个回帖) 顶端 
    主题:  游戏外挂的编写原理(4100字) - 卷积内核,2008年12月12日
        回复:  哦版主好强啊我顶(20字) - 秋十三,2009年1月21日
        回复:  非常感谢~~说Lua是一门写游戏脚本很好的语言所以鄙人开了一论坛~~~新论坛开张啦~~..(212字) - liuyuanyang,2009年1月16日
        回复:  谢谢了,刚做出一个 哈哈~(24字) - gtict,2008年12月31日
        回复:  能不能上传几个实例....(22字) - gtict,2008年12月31日
        回复:  (6) 在ActiveKey.cpp中加入头文件声明 "#include "wsock32.h..(621字) - 卷积内核,2008年12月12日
        回复:  (3)、注入外挂代码进入被挂游戏进程中  完成了定位和修改程序中调用API函数代码后,我们..(6195字) - 卷积内核,2008年12月12日
        回复:  (5)、从“工程”菜单中选择“设置”,弹出Project Setting对话框,选择Link标..(6941字) - 卷积内核,2008年12月12日
        回复:  (5).将ActiveKey项目中的ActiveKey.h头文件加入到Simulate项目中,..(7829字) - 卷积内核,2008年12月12日
        回复:  四、动作模拟技术  我们在前面介绍过,几乎所有的游戏都有大量繁琐和无聊的攻击动作以增加..(8867字) - 卷积内核,2008年12月12日

    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    62.500ms