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

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

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

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

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

      (6)、编译项目,产生wsock32.dll库文件。

      (7)、将系统目录下原wsock32.dll库文件拷贝到被外挂程序的目录下,并将其改名
    为wsock.001;再将上面产生的

    wsock32.dll文件同样拷贝到被外挂程序的目录下。重新启动游戏程序,此时游戏程序
    将先加载我们自己制作的

    wsock32.dll文件,再通过该库文件间接调用原WinSock接口函数来实现访问网络。上面
    我们仅仅介绍了挡载WinSock的

    实现过程,至于如何加入外挂控制代码,还需要外挂开发人员对游戏数据包结构、内
    容、加密算法等方面的仔细分析

    (这个过程将是一个艰辛的过程),再生成外挂控制代码。关于数据包分析方法和技
    巧,不是本文讲解的范围,如您

    感兴趣可以到网上查查相关资料。

    2.挡截API

      挡截API技术与挡截WinSock技术在原理上很相似,但是前者比后者提供了更强大的
    功能。挡截WinSock仅只能挡截

    WinSock接口函数,而挡截API可以实现对应用程序调用的包括WinSock API函数在内的
    所有API函数的挡截。如果您的

    外挂程序仅打算对WinSock的函数进行挡截的话,您可以只选择使用上小节介绍的挡截
    WinSock技术。随着大量外挂程

    序在功能上的扩展,它们不仅仅只提供对数据包的挡截,而且还对游戏程序中使用的
    Windows API或其它DLL库函数的

    挡截,以使外挂的功能更加强大。例如,可以通过挡截相关API函数以实现对非中文游
    戏的汉化功能,有了这个利器,

    可以使您的外挂程序无所不能了。

      挡截API技术的原理核心也是使用我们自己的函数来替换掉Windows或其它DLL库提
    供的函数,有点同挡截WinSock

    原理相似吧。但是,其实现过程却比挡截WinSock要复杂的多,如像实现挡截Winsock过
    程一样,将应用程序调用的所

    有的库文件都写一个模拟库有点不大可能,就只说Windows API就有上千个,还有很多
    库提供的函数结构并未公开,所

    以写一个模拟库代替的方式不大现实,故我们必须另谋良方。

      挡截API的最终目标是使用自定义的函数代替原函数。那么,我们首先应该知道应
    用程序何时、何地、用何种方式

    调用原函数。接下来,需要将应用程序中调用该原函数的指令代码进行修改,使它将调
    用函数的指针指向我们自己定

    义的函数地址。这样,外挂程序才能完全控制应用程序调用的API函数,至于在其中如
    何加入外挂代码,就应需求而异

    了。最后还有一个重要的问题要解决,如何将我们自定义的用来代替原API函数的函数
    代码注入被外挂游戏程序进行地

    址空间中,因在Windows系统中应用程序仅只能访问到本进程地址空间内的代码和数
    据。

      综上所述,要实现挡截API函数,至少需要解决如下三个问题:

      ● 如何定位游戏程序中调用API函数指令代码?

      ● 如何修改游戏程序中调用API函数指令代码?

      ● 如何将外挂代码(自定义的替换函数代码)注入到游戏程序进程地址空间?

      下面我们逐一介绍这几个问题的解决方法:

      (1) 、定位调用API函数指令代码

      我们知道,在汇编语言中使用CALL指令来调用函数或过程的,它是通过指令参数中
    的函数地址而定位到相应的函

    数代码的。那么,我们如果能寻找到程序代码中所有调用被挡截的API函数的CALL指令
    的话,就可以将该指令中的函数

    地址参数修改为替代函数的地址。虽然这是一个可行的方案,但是实现起来会很繁琐,
    也不稳健。庆幸的是,Windows

    系统中所使用的可执行文件(PE格式)采用了输入地址表机制,将所有在程序调用的
    API函数的地址信息存放在输入地

    址表中,而在程序代码CALL指令中使用的地址不是API函数的地址,而是输入地址表中
    该API函数的地址项,如想使程

    序代码中调用的API函数被代替掉,只用将输入地址表中该API函数的地址项内容修改即
    可。具体理解输入地址表运行

    机制,还需要了解一下PE格式文件结构,其中图三列出了PE格式文件的大致结构。


      图三:PE格式大致结构图(003.jpg)

      PE格式文件一开始是一段DOS程序,当你的程序在不支持Windows的环境中运行时,
    它就会显示“This Program

    cannot be run in DOS mode”这样的警告语句,接着这个DOS文件头,就开始真正的PE
    文件内容了。首先是一段称为

    “IMAGE_NT_HEADER”的数据,其中是许多关于整个PE文件的消息,在这段数据的尾端
    是一个称为Data Directory的数

    据表,通过它能快速定位一些PE文件中段(section)的地址。在这段数据之后,则是
    一个“IMAGE_SECTION_HEADER”

    的列表,其中的每一项都详细描述了后面一个段的相关信息。接着它就是PE文件中最主
    要的段数据了,执行代码、数

    据和资源等等信息就分别存放在这些段中。

      在所有的这些段里,有一个被称为“.idata”的段(输入数据段)值得我们去注
    意,该段中包含着一些被称为输

    入地址表(IAT,Import Address Table)的数据列表。每个用隐式方式加载的API所在
    的DLL都有一个IAT与之对应,

    同时一个API的地址也与IAT中一项相对应。当一个应用程序加载到内存中后,针对每一
    个API函数调用,相应的产生如

    下的汇编指令:

      JMP DWORD PTR [XXXXXXXX]

      或

      CALL DWORD PTR [XXXXXXXX]

      其中,[XXXXXXXX]表示指向了输入地址表中一个项,其内容是一个DWORD,而正是
    这个DWORD才是API函数在内存中

    的真正地址。因此我们要想拦截一个API的调用,只要简单的把那个DWORD改为我们自己
    的函数的地址。

      (2) 、修改调用API函数代码

      从上面对PE文件格式的分析可知,修改调用API函数代码其实是修改被调用API函数
    在输入地址表中IAT项内容。由

    于Windows系统对应用程序指令代码地址空间的严密保护机制,使得修改程序指令代码
    非常困难,以至于许多高手为之

    编写VxD进入Ring0。在这里,我为大家介绍一种较为方便的方法修改进程内存,它仅需
    要调用几个Windows核心API函

    数,下面我首先来学会一下这几个API函数:

       DWORD VirtualQuery(
       LPCVOID lpAddress, // address of region
       PMEMORY_BASIC_INFORMATION lpBuffer, // information buffer
       DWORD dwLength // size of buffer
       );

      该函数用于查询关于本进程内虚拟地址页的信息。其中,lpAddress表示被查询页
    的区域地址;lpBuffer表示用于

    保存查询页信息的缓冲;dwLength表示缓冲区大小。返回值为实际缓冲大小。

       BOOL VirtualProtect(
       LPVOID lpAddress, // region of committed pages
       SIZE_T dwSize, // size of the region
       DWORD flNewProtect, // desired access protection
       PDWORD lpflOldProtect // old protection
       );

      该函数用于改变本进程内虚拟地址页的保护属性。其中,lpAddress表示被改变保
    护属性页区域地址;dwSize表示

    页区域大小;flNewProtect表示新的保护属性,可取值为PAGE_READONLY、
    PAGE_READWRITE、PAGE_EXECUTE等;

    lpflOldProtect表示用于保存改变前的保护属性。如果函数调用成功返回“T”,否则
    返回“F”。

      有了这两个API函数,我们就可以随心所欲的修改进程内存了。首先,调用
    VirtualQuery()函数查询被修改内存的

    页信息,再根据此信息调用VirtualProtect()函数改变这些页的保护属性为
    PAGE_READWRITE,有了这个权限您就可以

    任意修改进程内存数据了。下面一段代码演示了如何将进程虚拟地址为0x0040106c处的
    字节清零。

       BYTE* pData = 0x0040106c;
       MEMORY_BASIC_INFORMATION mbi_thunk;
       //查询页信息。
       VirtualQuery(pData, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));
       //改变页保护属性为读写。
       VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,
       PAGE_READWRITE, &mbi_thunk.Protect);
       //清零。
       *pData = 0x00;
       //恢复页的原保护属性。
       DWORD dwOldProtect;
       VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,
       mbi_thunk.Protect, &dwOldProtect);

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

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

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