游戏外挂技术( 0 )

游戏外挂技术( 0

一、 前言

  所谓游戏外挂,其实是一种游戏外辅程序,它可以协助玩家自动产生游戏动作、修改游戏网络数据包以及修改游戏内存数据等,以实现玩家用最少的时间和金钱去完成功力升级和过关斩将。虽然,现在对游戏外挂程序的“合法”身份众说纷纭,在这里我不想对此发表任何个人意见,让时间去说明一切吧。

  随着网络游戏的时代的来临,游戏外挂在原有的功能之上进行了新的发展,它变得更加多种多样,功能更加强大,操作更加简单,以至有些游戏的外挂已经成为一个体系,比如《石器时代》,外挂品种达到了几十种,自动战斗、自动行走、自动练级、自动补血、加速、不遇敌、原地遇敌、快速增加经验值、按键精灵……几乎无所不包。

  游戏外挂的设计主要是针对于某个游戏开发的,我们可以根据它针对的游戏的类型可大致可将外挂分为两种大类。

  一类是将游戏中大量繁琐和无聊的攻击动作使用外挂自动完成,以帮助玩家轻松搞定攻击对象并可以快速的增加玩家的经验值。比如在《龙族》中有一种工作的设定,玩家的工作等级越高,就可以驾驭越好的装备。但是增加工作等级却不是一件有趣的事情,毋宁说是重复枯燥的机械劳动。如果你想做法师用的杖,首先需要做基本工作 --? 砍树。砍树的方法很简单,在一棵大树前不停的点鼠标就可以了,每 10000 的经验升一级。这就意味着玩家要在大树前不停的点击鼠标,这种无聊的事情通过 " 按键精灵 " 就可以解决。外挂的 " 按键精灵 " 功能可以让玩家摆脱无趣的点击鼠标的工作。

  另一类是由外挂程序产生欺骗性的网络游戏封包,并将这些封包发送到网络游戏服务器,利用这些虚假信息欺骗服务器进行游戏数值的修改,达到修改角色能力数值的目的。这类外挂程序针对性很强,一般在设计时都是针对某个游戏某个版本来做的,因为每个网络游戏服务器与客户端交流的数据包各不相同,外挂程序必须要对欺骗的网络游戏服务器的数据包进行分析,才能产生服务器识别的数据包。这类外挂程序也是当前最流利的一类游戏外挂程序。

另外,现在很多外挂程序功能强大,不仅实现了自动动作代理和封包功能,而且还提供了对网络游戏的客户端程序的数据进行修改,以达到欺骗网络游戏服务器的目的。我相信,随着网络游戏商家的反外挂技术的进展,游戏外挂将会产生更多更优秀的技术,让我们期待着看场技术大战吧 ......

 

二、外挂技术综述

  可以将开发游戏外挂程序的过程大体上划分为两个部分:

  前期部分工作是对外挂的主体游戏进行分析,不同类型的外挂分析主体游戏的内容也不相同。如外挂为上述谈到的外挂类型中的第一类时,其分析过程常是针对游戏的场景中的攻击对象的位置和分布情况进行分析,以实现外挂自动进行攻击以及位置移动。如外挂为外挂类型中的第二类时,其分析过程常是针对游戏服务器与客户端之间通讯包数据的结构、内容以及加密算法的分析。因网络游戏公司一般都不会公布其游戏产品的通讯包数据的结构、内容和加密算法的信息,所以对于开发第二类外挂成功的关键在于是否能正确分析游戏包数据的结构、内容以及加密算法,虽然可以使用一些工具辅助分析,但是这还是一种坚苦而复杂的工作。

  后期部分工作主要是根据前期对游戏的分析结果,使用大量的程序开发技术编写外挂程序以实现对游戏的控制或修改。如外挂程序为第一类外挂时,通常会使用到鼠标模拟技术来实现游戏角色的自动位置移动,使用键盘模拟技术来实现游戏角色的自动攻击。如外挂程序为第二类外挂时,通常会使用到挡截 Sock 和挡截 API 函数技术,以挡截游戏服务器传来的网络数据包并将数据包修改后封包后传给游戏服务器。另外,还有许多外挂使用对游戏客户端程序内存数据修改技术以及游戏加速技术。

  本文主要是针对开发游戏外挂程序后期使用的程序开发技术进行探讨,重点介绍的如下几种在游戏外挂中常使用的程序开发技术:

  ● 动作模拟技术:主要包括键盘模拟技术和鼠标模拟技术。

  ● 封包技术:主要包括挡截 Sock 技术和挡截 API 技术。

 

三、动作模拟技术

  我们在前面介绍过,几乎所有的游戏都有大量繁琐和无聊的攻击动作以增加玩家的功力,还有那些数不完的迷宫,这些好像已经成为了角色游戏的代名词。现在,外挂可以帮助玩家从这些繁琐而无聊的工作中摆脱出来,专注于游戏情节的进展。外挂程序为了实现自动角色位置移动和自动攻击等功能,需要使用到键盘模拟技术和鼠标模拟技术。下面我们将重点介绍这些技术并编写一个简单的实例帮助读者理解动作模拟技术的实现过程。

  1. 鼠标模拟技术

  几乎所有的游戏中都使用了鼠标来改变角色的位置和方向,玩家仅用一个小小的鼠标,就可以使角色畅游天下。那么,我们如何实现在没有玩家的参与下角色也可以自动行走呢。其实实现这个并不难,仅仅几个 Windows API 函数就可以搞定,让我们先来认识认识这些 API 函数。

   (1) 模拟鼠标动作 API 函数 mouse_event ,它可以实现模拟鼠标按下和放开等动作。

     VOID mouse_event(

       DWORD dwFlags, // 鼠标动作标识。

       DWORD dx, // 鼠标水平方向位置。

       DWORD dy, // 鼠标垂直方向位置。

       DWORD dwData, // 鼠标轮子转动的数量。

       DWORD dwExtraInfo // 一个关联鼠标动作辅加信息。

     );

  其中, dwFlags 表示了各种各样的鼠标动作和点击活动,它的常用取值如下:

    MOUSEEVENTF_MOVE  表示模拟鼠标移动事件。

    MOUSEEVENTF_LEFTDOWN 表示模拟按下鼠标左键。

    MOUSEEVENTF_LEFTUP 表示模拟放开鼠标左键。

    MOUSEEVENTF_RIGHTDOWN 表示模拟按下鼠标右键。

    MOUSEEVENTF_RIGHTUP 表示模拟放开鼠标右键。

    MOUSEEVENTF_MIDDLEDOWN 表示模拟按下鼠标中键。

    MOUSEEVENTF_MIDDLEUP 表示模拟放开鼠标中键。

(2) 、设置和获取当前鼠标位置的 API 函数。获取当前鼠标位置使用 GetCursorPos() 函数,设置当前鼠标位置使用 SetCursorPos() 函数。

     BOOL GetCursorPos(

      LPPOINT   lpPoint // 返回鼠标的当前位置。

     );

     BOOL SetCursorPos(

              int X, // 鼠标的水平方向位置。

       int Y // 鼠标的垂直方向位置。

     ); 

  通常游戏角色的行走都是通过鼠标移动至目的地,然后按一下鼠标的按钮就搞定了。下面我们使用上面介绍的 API 函数来模拟角色行走过程。

    CPoint oldPoint,newPoint;

    GetCursorPos(&oldPoint); // 保存当前鼠标位置。

    newPoint.x = oldPoint.x+40;

    newPoint.y = oldPoint.y+10;

    SetCursorPos(newPoint.x,newPoint.y); // 设置目的地位置。

    mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);// 模拟按下鼠标右键。

    mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);// 模拟放开鼠标右键。  

   2 键盘模拟技术

  在很多游戏中,不仅提供了鼠标的操作,而且还提供了键盘的操作,在对攻击对象进行攻击时还可以使用快捷键。为了使这些攻击过程能够自动进行,外挂程序需要使用键盘模拟技术。像鼠标模拟技术一样, Windows API 也提供了一系列 API 函数来完成对键盘动作的模拟。模拟键盘动作 API 函数 keydb_event ,它可以模拟对键盘上的某个或某些键进行按下或放开的动作。

    VOID keybd_event(

      BYTE bVk, // 虚拟键值。

      BYTE bScan, // 硬件扫描码。

      DWORD dwFlags, // 动作标识。

      DWORD dwExtraInfo // 与键盘动作关联的辅加信息。

    );

  其中, bVk 表示虚拟键值,其实它是一个 BYTE 类型值的宏,其取值范围为 1-254 。有关虚拟键值表请在 MSDN 上使用关键字“ Virtual-Key Codes ”查找相关资料。 bScan 表示当键盘上某键被按下和放开时,键盘系统硬件产生的扫描码,我们可以 MapVirtualKey() 函数在虚拟键值与扫描码之间进行转换。 dwFlags 表示各种各样的键盘动作,它有两种取值:

KEYEVENTF_EXTENDEDKEY KEYEVENTF_KEYUP

  下面我们使用一段代码实现在游戏中按下 Shift+R 快捷键对攻击对象进行攻击。

 

    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 激活外挂

  上面介绍的鼠标和键盘模拟技术实现了对游戏角色的动作部分的模拟,但要想外挂能工作于游戏之上,还需要将其与游戏的场景窗口联系起来或者使用一个激活键,就象按键精灵的那个激活键一样。我们可以用 GetWindow 函数来枚举窗口,也可以用 Findwindow 函数来查找特定的窗口。另外还有一个 FindWindowEx 函数可以找到窗口的子窗口,当游戏切换场景的时候我们可以用 FindWindowEx 来确定一些当前窗口的特征,从而判断是否还在这个场景,方法很多了,比如可以 GetWindowInfo 来确定一些东西,比如当查找不到某个按钮的时候就说明游戏场景已经切换了等等办法。当使用激活键进行关联,需要使用 Hook 技术开发一个全局键盘钩子,在这里就不具体介绍全局钩子的开发过程了,在后面的实例中我们将会使用到全局钩子,到时将学习到全局钩子的相关知识。

   4 实例实现

  通过上面的学习,我们已经基本具备了编写动作式游戏外挂的能力了。下面我们将创建一个简单的外挂。

  首先,我们需要编写一个全局钩子,使用它来激活外挂,激活键为 F10 。创建全局钩子步骤如下:

   (1) .选择 MFC AppWizard(DLL) 创建项目 ActiveKey ,并选择 MFC Extension DLL (共享 MFC 拷贝)类型。

   (2). 插入新文件 ActiveKey.h ,在其中输入如下代码:

    #ifndef _KEYDLL_H

    #define _KEYDLL_H

    class AFX_EXT_CLASS CKeyHookublic CObject

    {

     public:

                         CKeyHook();

                         ~CKeyHook();

HHOOK Start();   // 安装钩子

                         BOOL Stop();    // 卸载钩子

    };

    #endif 

   (3). ActiveKey.cpp 文件中加入声明" #include ActiveKey.h "。

   (4). ActiveKey.cpp 文件中加入共享数据段,代码如下:

    //Shared data section

    #pragma data_seg("sharedata"

    HHOOK glhHook=NULL; // 钩子句柄。

    HINSTANCE glhInstance=NULL; //DLL 实例句柄。

    #pragma data_seg() 

   (5). ActiveKey.def 文件中设置共享数据段属性,代码如下:

    SETCTIONS

    shareddata READ WRITE SHARED

   (6). ActiveKey.cpp 文件中加入 CkeyHook 类的实现代码和钩子函数代码:

    extern "C" LRESULT WINAPI KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)

    {

    if( nCode >= 0

    {

    if( wParam == 0X79) // 当按下 F10 键时,激活外挂。

         {

CPoint newPoint,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);// 模拟按下鼠标左键。

          mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);// 模拟放开鼠标左键。

            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);

}

   }

    return CallNextHookEx(glhHook,nCode,wParam,lParam);

   }

     CKeyHook::CKeyHook(){}

    CKeyHook::~CKeyHook()

    {  

    if( glhHook)

                         Stop();

    }

    // 安装全局钩子。

    HHOOK CKeyHook::Start()

    {

                      glhHook = SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,glhInstance,0); // 设置键盘钩子。

                      return glhHook;

              }

    // 卸载全局钩子。

    BOOL CKeyHook::Stop()

    {

       BOOL bResult = TRUE;

                   if( glhHook)

             bResult = UnhookWindowsHookEx(glhHook);// 卸载键盘钩子。

             return bResult;

   

   (7). 修改 DllMain 函数,代码如下:

    extern "C" int APIENTRY

    DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)

    {

                  // 如果使用 lpReserved 参数则删除下面这行

                 UNREFERENCED_PARAMETER(lpReserved);

                 if (dwReason == DLL_PROCESS_ATTACH)

                 {

           TRACE0("NOtePadHOOK.DLL Initializing!/n";

   

           if (!AfxInitExtensionModule(ActiveKeyDLL, hInstance))

                                       return 0;

                    new CDynLinkLibrary(ActiveKeyDLL);

          // DLL 加入动态 MFC 类库中

                  glhInstance = hInstance;

           // 插入保存 DLL 实例句柄

                }

             ....   

          }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值