Anti-Cheat – 实现一种检查内存被修改的方法

这个Anti-Cheat方法为了解决什么问题?

一般来说,一款网页\手机游戏纯靠客户端来解决反作弊(Anti-Cheat)几乎是不可能的。在这种情形下,页游\手游客户端(后文均称游戏客户端)可以利用一些手段来增加作弊\破解人员的成本,包括但不限于:代码加密,代码混淆,隐藏明文,内存混淆(加密)……

这个方法主要是避免\检测出类似CE工具对客户端内存进行恶劣修改达到关键数据变更的行为,属于上面提到的内存混淆(加密)类。

本文建立在所有源码未被对方知晓的情况下进行操作……

 

内存混淆(加密)通用做法

游戏客户端将原始数据保留二份,一份原始数据,一份加密数据。调用set()方法时,原始数据赋原始值,加密数据采用加密方法存储数据(比较基础的方法是数据异或);调用get()方法时,对加密数据与原始数据进行校验,通过校验结果是否一致来判定内存是否被修改。

我们以整形为例,大致的实现:

class IntShadow {
public:
    int get() {
        if (origi != shadow ^ salt) {
            //这里处理内存被修改
        }
        return origi;
    }

    void set(int setInt) {
        salt  = rand();
        origi = setInt;
        shadow= setInt ^ salt;
    }
private:
    int origi;
    int shadow;
    int salt;
};

 

既然是造轮子,那么这个轮子的特点 – class BinarySep

1、使用简单

这个Anti-Cheat的方法使用方式类似于std::vector,例如:

BinarySep<int32_t>; a(1);
BinarySep<int64_t>; b(12345);
BinarySep<bool>;    c(false);
2、通用

支持所有的连续内存的基础类型包括不限于int32_tdoubleboolstd::string(char *),其中string实现是将内容转化成为char *处理,也可以使用std::vector<BinarySep<int32_t> >进行嵌套使用。堆里的内容也可以转化成为char *处理。

3、混淆\加密性较强

将内存分片化处理,按32\64位机器内存对齐方式进行结构体随机数填充,来增加修改者寻找规律的复杂度。细节如下图:

BinarySep (1)

在List上,黄色\蓝色字节处为原始数据字节,其他字节均用随机字符填充。其中原始字节可以进行异或混淆或者Base64之类的方法混淆加密。

这里这样做的原因主要是struct unit_list结构体,在64位机器上若取3字节分片,那么sizeof(struct unit_list)==24,故我们将多余的5个字节当做padding填充随机字符。

需要注意的是,当分片大小取8时,padding[0]会导致部分编译器无法编译通过。

 

一些不足

占用空间大

初略计算一个占4字节的整形需要40字节的栈空间,48字节的堆空间(主要是链表)。由于链表使用的是linux内核的侵入式链表,它是双向的(这里优化点-可以改成单向,节约24字节的空间)。所以建议使用它对关键数据混淆\加密,而非所有数据。

一些类型使用需小心

比较典型是string类型,使用了堆空间进行存储,从储存到获取是一个string->char*->string的过程。对于结构体类型可以直接混淆存储或者序列化成char *存储(但是结构体里指向堆内容指针无法直接处理)。

未支持所有运算符

目前只重载了”=”运算符,对于”!=”、”==”、”>”…之类的运算符可以调用get()方法获得基本类型后比较,比如:

    BinarySep<int32_t>; a(1);
    BinarySep<int32_t>; b(2);

    if (a.get() > b.get()) {
        //...
    } else if (a.get() < 0) {
        //...
    }

 

本文对Anti-Cheat中内存混淆(加密)的源码实现未投入实际项目上线运行。

源码戳这里 -> Anti-Cheat BinarySep

(全文结束)


转载文章请注明出处:漫漫路 - lanindex.com

1 Comment

 Add your comment
  1. 我好笨,我还以为我看错了,原来亦或再异或就会回来原来的值

Leave a Comment

Your email address will not be published.