吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 39488|回复: 223
收起左侧

[游戏安全] 游戏检测的对抗与防护艺术

    [复制链接]
鬼手56 发表于 2020-4-11 20:36
本帖最后由 鬼手56 于 2020-5-22 10:27 编辑

[toc]

前言

从游戏外挂的利用角度来看,外挂的行为无非有如下两种:

  1. 修改游戏的关键数据和代码:属于篡改行为
  2. call游戏函数:属于未授权访问行为

游戏设计者针对这两种行为产生了无数的防护机制。然而道高一尺魔高一尺,逆向人员也根据游戏内的反外挂机制衍生出了相应的对抗手段。

今天我们就来聊一聊所谓的游戏检测对抗与防护。本次用于实验的游戏的老版本的口袋西游。

首先我们需要先找到游戏中的一个功能call,通过这个call来进行游戏检测的对抗与防护

通过send函数定位吃药call

在Windows网络编程中,send函数和WSASend函数都是ws_32.dll的导出函数,主要负责发送数据包。网络游戏客户端要与服务器通讯,必须调用send函数。

只要在send函数下断,然后进行堆栈回溯分析,就能准确定位关键函数的调用链。在这条链上,进行排查就能得到想要的功能call

1586595487902.png

直接用OD附加游戏,在send API函数下断

1586184693003.png

随便吃一个药品,这里记下药品的位置是在第22格。此时游戏断下

1586184893995.png

打开调用堆栈,对每个call进行快速排查,最后可以确定吃药call是491C50,右键,显示调用

1586185074226.png

在这个地方下个断点 让程序断下,这个call只需要分析一个参数就是edx

edx的值是0x15,也就是十进制的21。药品的位置在第22格,如果从0开始计数的话,那么这个参数大概就是药品的位置了。

1586185750034.png

接着我们用注入工具调用一下这个call的代码,除去edx需要为当前的药品位置,所有的汇编全部照抄即可。调用成功以后,准备工作完成

变量检测

单纯从技术角度来看,call一个游戏函数来实现某项特定功能是很简单的,构造函数执行环境,传入必要参数,直接调用call就行了,其难点在于call游戏函数之后不被检测到

构造检测程序

由于口袋西游这个程序没有call检测,这里我们自己写了一个dll用于模拟call的检测,原理和实际的检测call是一样的。

首先打开吃药call检测,正常在游戏里吃药是不会有任何反应的

1586358107244.png

但是当我们点击吃药call的时候会弹出一个警告框。这样就构造了一个call的检测(吃药call参数写死了,记得把药品放到第一个格子)

处理变量检测

call的检测原理

当我们正常在游戏中吃药是没有检测的,那是因为我们完完整整的把游戏的代码全部调用了;而我们直接点吃药call的时候执行的代码是不完全的。

那么游戏的开发者就可以在吃药call的外层设置一个变量,并且给变量赋值,然后在吃药call内层的某一个位置对这个变量的值进行检测。如果值不对,说明代码没有被完全执行。

在检测完成之后,再修改这个变量的值到原始状态,然后进行下一次检测。整个流程的伪代码如下:

//用于检测的全局变量
int status=0;

function()
{
    //调用其他代码...........
    status=1;
    吃药call();
     //调用其他代码...........
}

吃药call()
{
     //调用其他代码...........
    if(status==1)
    {
        //正常执行代码
    }
    else
    {
        //检测到外挂 进行处理
    }
    //再对status进行赋初始值 以便进行下一次检测
    status=0;
     //调用其他代码...........
}

查找检测变量

这个变量的值其实就相当于一个标志位,0和1的可能性比较大。所以我们可以通过搜索0和1的方式来找到这个变量,如果不行再尝试未知的初始值。

1586358709325.png

首先在吃药call下断,正常吃药让程序断下,这个时候外层的检测变量已经被赋值了
1586358738782.png

我们在CE里扫描1。然后F9运行程序,这个时候吃药call执行完毕,检测标志位也被恢复到原始状态

1586358762886.png

这个时候我们搜索0。

1586358823131.png

一直重复这个过程,最后剩下十个左右的地址就可以停止搜索了。

1586523370372.png

利用二分法进行测试,将这些变量逐个修改为1,看看哪一次调用call不会被检测到。这样可以定位到唯一的一个检测标志位。

然后我们在这个标志位下一个硬件写入断点,吃药让程序断下

1586523453671.png

第一次断下的位置,[68EB2374]这个地址会被赋值为1,F9运行程序

1586523485689.png

第二次断下的位置,这个地方会在原来的值的基础上减一。接着判断地址的值是否为0,不为零则执行检测代码

变量检测处理

这里有两种处理方法,第一种直接修改游戏代码,不执行检测call。

1586523521062.png

第二种就是在调用call的时候,将检测变量赋值为正常调用call时候的数值。

堆栈检测

变量检测有一个很明显的缺点,就是需要一个实时去修改一个全局变量,这种方法很容易用CE搜索到。那么能不能通过其他方式去传递检测变量而又不被CE扫描到呢?答案是可以。这个就是堆栈检测。

堆栈检测原理 基于本地

堆栈检测的基本原理就是检测堆栈中的返回地址。如果游戏中一个正常的call被执行的话,那么堆栈中的所有的返回地址一定是本模块的;

正常调用吃药call堆栈地址如图:

1586596279136.png

所有的返回地址均为游戏主模块

相反,如果是通过自己写的dll注入到游戏内部来调用的话,那么堆栈中返回地址就全部是自己的dll模块的地址。

1586596475373.png

基于这个特点,程序只要在功能call内部去读特定的堆栈返回地址,检测返回地址是否属于本模块,就可以检测出当前的功能call是否被非法调用。

堆栈检测原理 基于服务器

另外一种情况比较少见,程序会通过一个参数将当前堆栈的一部分数据发送到服务器,服务器接收到这些数据以后,再对参数内的堆栈地址进行检测。

这种方式不太实用,首先发送这部分堆栈数据很容易被调用者发现,其次会增大服务器压力,所以这种检测方式相对比较少见。

处理一层堆栈检测

这种检测的处理方法也有两种,第一种单步跟找到这个堆栈检测call,处理掉。但是这种检测call可能处在代码的任何一个位置,找起来不是那么容易。

第二种就是修改我们自己的程序代码。首先在进入call之后将返回地址修改为游戏模块内正确返回地址,过掉检测call。然后在离开call之前将返回地址修改为我们自己的返回地址,保证游戏正常执行。其实就是写两个HOOK修改堆栈地址。

伪代码如下:

HOOK函数头()
{
    //保存原程序的返回地址
    mov g_retaddr,[esp];
    //修改返回地址为游戏内的返回地址
    mov [esp],0x12345678
}
HOOK函数尾()
{
    //修改返回地址为原程序返回地址
    mov [esp],g_retaddr;
}

处理多层堆栈检测

如果堆栈检测只检测一层返回地址的话,那么就可以用上面的方式过掉检测。但是游戏往往会检测堆栈内的多个返回地址。

多层堆栈检测处理也很简单。处理一层堆栈检测要用HOOK的方式是因为在调用游戏内部的功能call的时候,我们没有办法去修改这个call内部的代码。

但如果是多层堆栈检测,就可以在调用这个功能call之前,就布局好当前的堆栈返回地址。伪代码如下:

function()
{
    sub esp,0x28;
    //修改第一层返回地址
    mov [esp],0x12345678;
    //修改第二层返回地址
    mov [esp+0x14],0x66666666;
    //调用功能call
    call xxxxxxx;
    //还原堆栈
    add esp,0x28;
}

利用上面这种方式,不管游戏内部检测多少层堆栈返回地址,我们都可以通过直接伪造堆栈的方式达到过掉检测的目的。

CRC检测

什么是CRC检测

上述的两种方式都是对call游戏函数的未授权访问行为进行对抗防护,而CRC检测是为了防止修改游戏的关键代码的篡改行为进行防护的手段。

事实上,修改游戏代码是很容易被检测到的,只要给代码段加一个校验功能,提前计算好整个代码段的CRC值,然后单独开一个线程,循环计算CRC并且比对之前预先保存的值,如果值不相等,说明代码段被修改。

构造CRC检测

1586597244085.png

同样,我们自己先构造一个CRC检测程序,并且开启检测

1586597277600.png

然后到吃药call的位置,在这个地方下一个断点,软件断点会将当前汇编前两个字节修改为0xCC,也就等于是修改了代码段

1586597334345.png

然后弹出提示框,代表当前代码修改被检测到了

处理CRC检测

由于CRC检测需要实时的去访问整个代码段,然后计算代码段的CRC值;一般的程序是不需要对其他代码段进行访问的。

基于这个特点我们就可以在这个地方下一个内存访问断点,直接就能直接找到校验的代码

1586597514080.png

在吃药call下一个内存访问断点,游戏断下

1586597709942.png
简单分析一下上面的代码,eax就是吃药call的地址,选中的部分代码对当前的吃药call地址进行一系列的计算,然后将计算结果存储到[ebp-8]的位置,然后比较[ebp-8]的值是否等于25977C99,这个25977C99应该就是提前计算好的代码段的CRC的值。接着根据比较的结果对返回值进行赋值。

这部分就是游戏的CRC检测代码了,找到了检测代码,处理就简单的多。可以直接在函数头部让eax=0,直接返回;也可以将jnz跳转直接nop掉。只要让检测代码不执行就OK。

数据检测

在外挂行为检测方面,修改数据的行为最难定位,因为不仅外挂会修改数据,游戏本身也可能会修改数据。这个点既给游戏开发人员增加了难度,也给逆向人员增加了难度。

数据检测原理

数据检测的原理与处理方式和CRC检测基本一致。都是通过一系列的校验判断数据是否被修改,处理方式也可以通过访问关系定位到检测代码。

唯一的区别在于,程序的代码段是不需要去访问其他代码段的,所以只要在代码段下访问断点直接就能找到检测代码。

而数据段是会被游戏代码访问的,通过内存断点定位到访问代码以后,就多了一个步骤,需要从这些访问代码中找到哪个是数据检测代码。

一般来说检测代码都不在游戏主模块,会放在其他的dll模块。

构造检测程序

这里构造了一个对最大血量的数据检测程序,人物血量基址如下:

1586602879776.png

开启数据检测

1586602978497.png

在CE中修改人物血量,此时数据检测复现成功

数据检测处理

我们在血量的地址右键,查看是谁访问了这个代码。

1586603055910.png

这里有两条代码在实时访问血量地址。单从模块的角度很快就能看出第二条代码不是在游戏的主模块,如果从模块看不出来的话就只能挨个分析了。

处理方式和代码检测相同,定位到检测代码以后,对数据或者代码进行修改即可。这里不再重复。

总结

最后对以上几种检测的对抗与防护进行简单总结:

  • call游戏函数的未授权访问行为检测——变量检测:利用CE搜索出检测标志位进行修改
  • call游戏函数的未授权访问行为检测——堆栈检测:利用HOOK和内联汇编的方式伪造堆栈
  • 修改游戏的关键代码的篡改行为检测——CRC检测:利用访问关系下内存断点定位到检测代码进行处理
  • 修改游戏的关键数据的篡改行为检测——数据检测:利用访问关系下内存断点定位到检测代码以后,排查处理

免费评分

参与人数 187吾爱币 +178 热心值 +178 收起 理由
luiguan + 1 谢谢@Thanks!
IFOJL + 1 + 1 谢谢@Thanks!
wwxxeevv + 1 + 1 用心讨论,共获提升!
vanillasky0220 + 1 + 1 用心讨论,共获提升!
hedilict + 2 + 1 我很赞同!
xiahhhr + 1 + 1 谢谢@Thanks!
新手12138 + 1 + 1 我很赞同!
国际豆哥 + 1 + 1 谢谢@Thanks!
zsq + 1 + 1 谢谢@Thanks!
MUMUAA + 1 + 1 用心讨论,共获提升!
软软超甜呐 + 1 用心讨论,共获提升!
qiyukanhaia + 1 + 1 看懂了大概的原理,谢谢分享
vistaer + 1 用心讨论,共获提升!
b105 + 2 用心讨论,共获提升!
Y.S. + 1 谢谢@Thanks!
5735002 + 1 + 1 加分
wwsse345 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
路人癸 + 1 + 1 我很赞同!
俊之霜 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
shuiyu + 1 谢谢@Thanks!
hhjjkkll + 1 + 1 我很赞同!
CuteHamster + 1 + 1 我很赞同!
xyz1598753 + 1 + 1 我很赞同!
Gaara_ + 1 谢谢@Thanks!
xuexiyixiaxia + 1 + 1 谢谢@Thanks!
llpgy521 + 1 + 1 用心讨论,共获提升!
轻轻闪过 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
一点半 + 1 谢谢@Thanks!
sss2153819 + 1 + 1 用心讨论,共获提升!
Pj15119158128 + 1 谢谢@Thanks!
hanba + 1 我很赞同!
vethenc + 1 + 1 谢谢@Thanks!
xiamoyizhi + 1 汇编渣的C++ programmer表示看的很勉强
poisonbcat + 1 + 1 谢谢@Thanks!
RainH + 1 我很赞同!
HackerWen + 1 + 1 用心讨论,共获提升!
jiaocoll + 1 我很赞同!
yixiaocuo + 1 + 1 谢谢@Thanks!
HEHE139 + 1 + 1 热心回复!
diy2012 + 1 我很赞同!
lyb1713 + 1 + 1 谢谢@Thanks!
热心市民小丑 + 1 + 1 用心讨论,共获提升!
hgfty1 + 1 + 1 谢谢@Thanks!
弟di + 1 + 1 用心讨论,共获提升!
无欲无求的羔羊 + 1 我很赞同!
Sqfighting + 1 + 1 用心讨论,共获提升!
冰茶荼 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
劫狱中 + 1 + 1 我很赞同!
拂你青丝 + 1 + 1 用心讨论,共获提升!
EMZ1 + 1 + 1 用心讨论,共获提升!
挥汗如雨 + 1 热心回复!
大恩恩 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
昕悦阁丶风雪 + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
霜冷九州 + 1 + 1 用心讨论,共获提升!
lookerJ + 1 + 1 我很赞同!
lyslxx + 1 + 1 我很赞同!
dddl + 1 + 1 热心回复!
TheChosenPeople + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
醉插美人阴 + 1 + 1 用心讨论,共获提升!
tanwen19932 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
1047605365 + 1 + 1 我很赞同!
Naxior + 1 + 1 我很赞同!
lonely_coder + 1 + 1 用心讨论,共获提升!
q739806133 + 1 + 1 我很赞同!
Rossoneri_Sam + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
bologr + 1 + 1 用心讨论,共获提升!
liang681418 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
BoomJovi + 1 我很赞同!
领丶悟 + 2 + 1 我很赞同!
aym2019 + 1 谢谢@Thanks!
温柔的一哥 + 1 + 1 用心讨论,共获提升!
独眼八爷 + 1 + 1 用心讨论,共获提升!
忆魂丶天雷 + 1 + 1 我很赞同!
tomcath + 1 + 1 用心讨论,共获提升!
JuDei + 1 + 1 热心回复!
zs2_cai + 1 + 1 用心讨论,共获提升!
henryc9 + 1 + 1 用心讨论,共获提升!
zuoli886 + 1 + 1 用心讨论,共获提升!
Black_山猫 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
一人一包子 + 1 + 1 用心讨论,共获提升!
远空 + 1 + 1 我很赞同!
天空藍 + 1 + 1 thx
wuyu590059 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
ma4907758 + 1 + 1 我很赞同!
aptsuny + 1 + 1 用心讨论,共获提升!
ls0928 + 1 + 1 热心回复!
薛定谔の代码 + 1 我很赞同!
lynxtang + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
tony198911 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
全场最佳赵山河 + 1 + 1 谢谢@Thanks!
ranxiao520 + 1 + 1 用心讨论,共获提升!
生有涯知无涯 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
涛之雨 + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
不谙世事的骚年 + 1 + 1 热心回复!
halovickysun + 1 + 1 楼主的分析非常到位!学到了
Naccl + 1 + 1 我很赞同!
LL520 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
lin3369297 + 1 + 1 谢谢@Thanks!
q105277951 + 1 谢谢@Thanks!
livetome + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

hzyqpal 发表于 2020-4-12 11:07
那会会改游戏数据会找call写call,但是并不太知道游戏对抗机制,因为过不了保护就慢慢不做外挂了。如果那会看到这文章,可能可以再玩玩,现在是真老了,也玩不动了。硬盘里虽然保留着当初的写的源代码但是编程软件都不装了。
悠悠 发表于 2020-4-15 14:40
以前还学着写写外挂,随着越来越大,对着方面没有一点兴趣。逐渐就退出了。最疯狂的时候DNF外挂做到游戏更新,外挂自动更新。游戏增加保护机制,两小时后搞定保护。为了做这些不知道被封了多少测试的账号。后来自己不想做了,有的玩家主动提供账号,又坚持搞了段时间。实在是年纪大了,没有兴趣了。

点评

一样,老了,早就该有自己的事业了  发表于 2020-4-16 18:13
llsdsd 发表于 2020-7-25 19:23
放开那头公牛 发表于 2020-4-11 20:54
感谢分享这种干货
Light紫星 发表于 2020-4-11 20:54
口袋西游这个游戏要被玩坏了
寒尘丶Coldust 发表于 2020-4-11 21:08
很厉害  扩展了我的思路
克罗蒂亚 发表于 2020-4-11 21:11
只能说牛逼
浦飯 发表于 2020-4-11 21:32
6666支持一下
117882697 发表于 2020-4-11 21:32
看看,学习学习
a42010316 发表于 2020-4-11 21:58
神仙打架,凡人遭殃啊
杰夫 发表于 2020-4-11 22:38
干货 学习了
lsy832 发表于 2020-4-11 23:30
学习思路了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-25 15:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表