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

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

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

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

    四、动作模拟技术

      我们在前面介绍过,几乎所有的游戏都有大量繁琐和无聊的攻击动作以增加玩家的
    功力,还有那些数不完的迷宫

    ,这些好像已经成为了角色游戏的代名词。现在,外挂可以帮助玩家从这些繁琐而无聊
    的工作中摆脱出来,专注于游

    戏情节的进展。外挂程序为了实现自动角色位置移动和自动攻击等功能,需要使用到键
    盘模拟技术和鼠标模拟技术。

    下面我们将重点介绍这些技术并编写一个简单的实例帮助读者理解动作模拟技术的实现
    过程。

      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. 实例实现

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

    现自动移动画笔字光标的位置并写下一个红色的“R”字。以这个实例为基础,加入相
    应的游戏动作规则,就可以实现

    一个完整的游戏外挂。这里作者不想使用某个游戏作为例子来开发外挂(因没有游戏商
    家的授权啊!),如读者感兴

    趣的话可以找一个游戏试试,最好仅做测试技术用。

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

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

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

       #ifndef _KEYDLL_H
       #define _KEYDLL_H

       class AFX_EXT_CLASS CKeyHook:public 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");
       //扩展DLL仅初始化一次
      if (!AfxInitExtensionModule(ActiveKeyDLL, hInstance))
    return 0;
      new CDynLinkLibrary(ActiveKeyDLL);
          //把DLL加入动态MFC类库中
      glhInstance = hInstance;
      //插入保存DLL实例句柄
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
      TRACE0("NotePadHOOK.DLL Terminating!\n");
      //终止这个链接库前调用它
      AfxTermExtensionModule(ActiveKeyDLL);
    }
    return 1;
       }

      (8).编译项目ActiveKey,生成ActiveKey.DLL和ActiveKey.lib。

      接着,我们还需要创建一个外壳程序将全局钩子安装了Windows系统中,这个外壳
    程序编写步骤如下:

      (1).创建一个对话框模式的应用程序,项目名为Simulate。

      (2).在主对话框中加入一个按钮,使用ClassWizard为其创建CLICK事件。

      (3).将ActiveKey项目Debug目录下的ActiveKey.DLL和ActiveKey.lib拷贝到
    Simulate项目目录下。

      (4).从“工程”菜单中选择“设置”,弹出Project Setting对话框,选择Link标
    签,在“对象/库模块”中输入ActiveKey.lib。

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

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

    本主题贴数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号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    1,626.953ms