干掉文件监控系统


前言

按照最近的个人项目的需求,我要对 Linux 的底层做更深层次的研究了。

简要说下我的需求:我要读取某个游戏的内存数据,但是不能被游戏检测到。

听起来很容易吧,但问题就在这里:Linux 的 inotify 机制会暴露我读取内存的事实。

不能被检测到的原因是:这个项目违反了这个游戏的服务条款,即使作为使用者也是违反了该游戏的条款(连获取自己的生产的数据也违反条款,这是不是很扯淡...),所以也很容易导致账号封禁的问题,所以我需要做好这个反检测以防止封号问题的出现。

读者们不要认为这个项目是属于那种破坏公平性的外挂,这个项目主要是重新创建原先被官方制裁掉的民间功能,让玩家知道自己分数的计算细节,其实受众其实也不算小。

不过归根到底,只不过是给自己多一个学习面位而已。

Linux 的 inotify

inotify 是 Linux 用于监视文件系统内发生的所有变化,包括:访问、打开、读写、关闭、移动等等,可以说这个机制是非常牛 b 的,只要有动静,就会通知注册监视器的进程,这里的目录或文件发生了一些变化。

可问题就是在这里:在 Linux 中,读取内存的其中一个方法就是访问 procfs 的,所以只要游戏监控 procfs,那么在我打开 /proc/pid/mem 的时候就会直接暴露“我要读取内存”的行为。同时,按照游戏开发者的思维逻辑,你访问了我的内存,那就意味着你肯定有鬼,一个手机里运行的进程,你怎么可能会读取我的内存呢?你要不就在调试我,要不就是用工具读我的内存!于是游戏记录一下对应的 UID,顺手崩溃一下,让使用者以为是读取工具不兼容,后面怎么处置就看游戏官方了。

劫持相关函数,不被抓取证据

想要正常运营这个项目,首先肯定是保护好自己的用户,首先的思路就是,关闭 inotify 机制,可这个机制是内置于 Linux 系统中的,所以不是说想关就关的。

所以,我绞尽脑汁想到的就是:Hook。那也没什么办法,既然无法从系统层面关掉这个机制,那就只能给游戏注入一个模块,提前 Hook 掉用于注册监听器的函数,然后在游戏调用这个函数时,根据传入参数欺骗游戏,告诉他已经注册成功,实际上压根就没发送到系统,这样就可以做到反检测了。

这里是我想的伪代码:

//所有用来检测的都在这里
std::vector<string> matchPaths = {"/proc/self/mem","/proc/self/maps","/proc/"+to_string(getpid())+"/maps","/proc/"+to_string(getpid())+"/mem"};

int inotify_add_watch(int fd, const char *pathname, uint32_t mask){ //覆盖原来的函数
  for(int i=0;i<matchPaths.size();i++){
    if(matchPaths[i].compare(string(pathname)) == 0){
      return rand(); //返回一个随机数q~q
    }
  }
  return RealFunction(fd,pathname,mask); //这里调用真正的函数,或者复制原本的操作
}

接着就是如何注入对应的 APP 了,在经历了无休止的搜索后,我终于找到了方法:在全局设置变量 LD_PRELOAD,即可劫持已经加载好的模块,而且从这个变量加载的模块,优先级是比动态链接的库高的,所以这个方法非常理想。

最后我又找到了这篇文章:Android 动态修改Linker实现LD_PRELOAD全局库PLT Hook - 『移动安全区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

结果发现还可以实现特定应用注入,那么最终实现就非常理想了。

在思维逻辑上,这个反检测方式虽然可以被检测出问题,但最多只能证明用户用了一些特殊手段阻止了 inotify 的创建(也不能排除是权限控制细化的插件吧),并不能证明用户读取了内存,按照这个思维来说,游戏开发组最多给你崩溃一下或者警告一下,但不能以这个理由封禁账号,那么保护用户账号的目的也达成了,后面只要想想怎么处理这种检测就行了。

希望我可以做到吧,毕竟写 C++ 不利于身心健康 q~q

分组于: 技术

发布于: 2023年10月01日 00时26分

编辑于: 2023年10月01日 00时26分

Linux
inotify
文件监控

用 Cookie 保存: 别名、Email