前言

手游发展至今,出现了许多的外挂,今天我们就来说说那些如果去对抗那些透视类外挂。

进入

我们都知道透视类外挂都需要读取游戏内角色坐标,所以,理论来说,只要知道角色地址是否被其他工具访问,便能解决此类问题。如何解决呢?

揭秘

当我们了解 Linux内存管理 后,会学习到一个新的词 缺页异常 ,比如我们调用mmap来映射内存,为了防止内存无效分配,该内存空间在未访问时是不会创建物理内存页的。当程序需要使用这块内存区域时,会触发缺页中断,然后系统才会创建物理内存页。由此我们诞生了一种近乎完美的外挂检测方案。通过在对局角色数组中插入缺页内存地址,使外挂无法识别是否是正常游戏角色数据,从而触发检测。

在这里我们需要学习一个函数:mincore

#include <unistd.h> 
#include <sys/mman.h>
int mincore(void *start, size_t length, unsigned char *vec);

函数说明:
mincore()请求向量,描述文件的哪些页位于核心,可以在没有磁盘访问的情况下读取。内核将为长度后面的字节开始地址。返回时,内核将填满VEC使用字节,其中最小有效位指示页是否为核心驻留。

使用

1.mmap 申请内存

char * memory= nullptr;
memory= (char*)mmap(nullptr,0x4000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);

如果不对 memory 进行读写,那么 memory 默认为缺页状态

2.mincore 判断

int pageSize = getpagesize();
unsigned char vec = 0;
//memory[0]=1; 这个操作会把memory改为非缺页状态
unsigned long addr= reinterpret_cast<unsigned long>(memory);
unsigned long start = addr & (~(pageSize - 1));
mincore((void *)start, pageSize, &vec);
if (vec == 1)
{
    LOGD("内存页:%p 存在于物理内存空间",addr);
}else{
    LOGD("内存页:%p 不存在于物理内存空间",addr);
}

到这里就很清晰了,我们通过判断在对局角色插入的缺页内存地址,即可知道玩家是否使用了外挂!例如腾讯手游,网易手游等都是使用了此方案。当然,还有使用读取 /proc/pid/pagemap 的方式去判断。这里我就不多说了。下篇文章我会说说如何去对抗这种方案。

参考

安卓手游安全 - 反外挂基础

最后修改:2023 年 04 月 07 日
如果觉得我的文章对你有用,请随意赞赏