mohamad-aljeiawi/mem_tool-kernel-module-security-research

GitHub: mohamad-aljeiawi/mem_tool-kernel-module-security-research

针对 Android ARM64 内核 rootkit「mem_tool/RT驱动」的逆向工程静态分析笔记与净室源码审计重建,帮助安全研究人员系统理解其隐匿机制、攻击原语与威胁模型。

Stars: 0 | Forks: 0

# RTdrivers / `mem_tool` — Android ARM64 内核 Rootkit 逆向工程与分析 静态逆向工程笔记、IDA Pro 演练、ioctl 映射、加载器剖析,以及对野外流传的 Android ARM64 内核模块的来源审计重建,该模块以 **RT驱动**、**RTdrivers** 和 **Cycle1337**(内部符号前缀:`mem_tool_*`)为名分发。 分析目标:`dev/` 中的八个 `.sh` 自解压安装程序(原名为 `dev增强版过检测/`)以及用户态 C++ 客户端头文件 `dev增强版对接.h`。 ## 0. 署名、免责声明与目的 ### 0.1 我不是此驱动程序的作者 本代码库是一个**独立的逆向工程与静态分析集合**。我**没有**编写原始的 `.ko`、`.sh` 加载器或用户态客户端头文件。这些工件的所有版权均属于其原始作者。 - **原始作者/分发者:** Telegram 上的 **`@RTdrivers`** — - **在野发现的名称:** `RT驱动`、`RTdrivers`、`Cycle1337`,内部 C 符号 `mem_tool_dev_t` / `mem_tool_class` / `memdev`。 - **本代码库由**第三方研究员维护,纯粹作为逆向工程和教育资源。与 `@RTdrivers` **无关联**,也**未获其认可**。 如果您是原始作者,并希望澄清署名或移除某个工件,请提出 issue — 这里的目的是公共安全研究,而非重新分发。 ### 0.2 为什么存在本代码库 作为开源的**安全研究工件**发布。它的存在是为了让其他研究人员、防御者和好奇的工程师能够: 1. **分析驱动程序的安全态势** — 对其行为进行分类(rootkit、信息窃取器、作弊引擎、后门等),并衡量加载它的设备所面临的实际风险。 2. **阅读代码层面的分析** — ioctl 接口、隐匿原语(模块自我隐藏、tmpfs 覆盖、随机化设备名称)、ARM64 **PAN 绕过**路径、硬件断点机制,以及运行时 `kallsyms_lookup_name` 解析器。 3. **深入理解其运作机制** — 自解压 `.sh` 加载器如何在 `#离` 标记之后嵌入 ELF,`.ko` 如何从 `lsmod` / `/proc/modules` / `/sys/module` 中隐藏自身,以及 `kernel_client.h` 中的用户态客户端如何发现随机化的 `/dev/` 节点。 4. **重建部分代码以进行手动验证。** `devwh-src/` 包含了相同原语的净室 C 语言重新实现,以便对二进制文件中观察到的行为可以手动重新编译和测试。它与上游的 `.ko` **并非**字节级一致,也**并非**旨在作为直接替代品。 ### 0.3 威胁模型警告 — 请勿在真实设备上运行 `mem_tool_driver/` 下的 `.ko` 文件属于 **rootkit 级别的内核模块**,保留在此**仅供静态分析使用**。请**不要**在任何您关心的设备上对它们执行 `insmod`。一旦加载,该驱动程序将: - 通过随机化的字符设备,向系统上的所有其他进程暴露 ring-0 级别的读写权限, - 从 `lsmod` / `/proc/modules` / `/sys/module` 中隐藏自身, - 从全局任务列表中隐藏任意 PID, - 在 `/data/local/tmp/` 上覆盖 tmpfs 以隐藏伴随文件, - 通过直接写入 `TTBR0_EL1` 绕过 ARM64 PAN。 任何找到该随机设备文件的进程都将获得对银行应用、密码管理器、消息密钥以及设备上任何其他内容的内核级访问权限 — 从而绕过 Android 的 per-uid 沙箱。详细的威胁概况请参见 §5 *结论*。 ### 0.4 许可证/合法使用 此处的原始二进制文件和用户态头文件是出于安全分析、恶意软件分类和教育性逆向工程的目的,基于**研究/合理使用**的主张 reproduced。无任何保证。 使用本代码库中的任何工件来获取对系统的未经授权访问、分发作弊程序,或违反任何法律或服务条款,**均由用户自行承担责任**。如果您是平台供应商、杀毒厂商或权利持有人并需要削减此集合,请提出 issue。 ## 1. 代码库布局 ``` kernel-module/ ├── README.md ← this file (analysis overview) ├── CLIENT.md ← userland client API reference ├── RUNBOOK.md ← how the loaders work + load checklist ├── load_driver.sh ← clean auto-selecting loader ├── extract_all.py ← reproducible extractor │ ├── dev增强版对接.h ← original userland client header (C++) ├── dev/ (was dev增强版过检测/) ← original installers, untouched │ ├── 5.4.sh 5.4b.sh 5.4c.sh │ ├── 5.10.sh 5.15.sh │ └── 6.1.sh 6.6.sh 6.12.sh │ ├── mem_tool_driver/ ← extracted, organized analysis bundle │ ├── 5.4.ko 5.4b.ko 5.4c.ko ELF64 / aarch64 / ET_REL │ ├── 5.10.ko 5.15.ko │ ├── 6.1.ko 6.6.ko 6.12.ko │ └── kernel_client.h copy of the userland header │ └── devwh-src/ ← from-source audit rebuild of the .ko ├── Makefile Kbuild README.md ├── uapi/devwh_uapi.h ioctl contract (matches kernel_client.h) ├── main.c rand.c kallsyms.c ├── hide.c memrw.c hwbp.c fops.c ``` ### 文档快速参考 | 文件 | 解答的问题 | |-----------------|------------------------------------------------------------------| | `README.md` | 这是什么,二进制文件里有什么,它是否恶意 | | `CLIENT.md` | 我如何在我自己的应用中使用 `kernel_client.h` | | `RUNBOOK.md` | `.sh` 加载器是如何工作的,我该如何干净地加载 | | `load_driver.sh`| 干净的加载器本身 (运行 `sh load_driver.sh --help`) | | `devwh-src/README.md` | 从源代码构建模块而不是运行二进制文件 | 文件夹名称 `mem_tool_driver` 取自二进制文件自身的内部符号 (`mem_tool_dev_t`、`mem_tool_class`、`memdev`) — 这是作者在代码内部对该项目的称呼。 ## 2. `.sh` 文件不是 Shell 脚本 每个 `*.sh` 都是一个**自解压安装程序**:一小段 Shell 前导码,接着是 `#离` 行,然后是附加在后面的原始 ELF 内核模块。 前导码: 1. 需要 root 权限 (`id -u` 检查)。 2. 通过检查 `/storage/emulated/0/Android/data//cache/...` 下 `@RTdrivers` 频道缓存的 Telegram 媒体文件来执行“频道验证”关卡。 失败后会提示用户在浏览器中打开 `https://t.me/RTdrivers`。 3. 使用 `sed "1,/^#离/d" "$0" > /data/tmpf` 剥离自身,将尾随的 ELF 落盘。 4. `chmod u+x /data/tmpf && insmod /data/tmpf`。 5. 成功时,打印 100 次 "RT驱动加载成功" 并运行 `dmesg -C` 以清除内核日志(反取证)。 6. 失败时,删除临时文件并威胁重启。 脚本与 ELF 之间的标记是 UTF-8 字节序列 `0x23 0xE7 0xA6 0xBB 0x0A` (`#离\n`)。`离` 的意思是“离开/分离”。 ## 3. 可复现的提取 `extract_all.py` 遍历 `dev增强版过检测/`,在每个 `.sh` 中找到 `#离` 标记,切出尾随的 ELF,验证 ELF 魔数,并写入 `mem_tool_driver/.ko`。它还会将 `dev增强版对接.h` 复制为 `mem_tool_driver/kernel_client.h`。 ``` python extract_all.py ``` 所有八个文件的验证结果: | 文件 | 大小 (字节) | 类别 | 架构 | e_type | |------------|--------------|--------|---------|-------------------| | 5.4.ko | 738 464 | ELF64 | aarch64 | ET_REL (0x1) | | 5.4b.ko | 731 936 | ELF64 | aarch64 | ET_REL (0x1) | | 5.4c.ko | 739 176 | ELF64 | aarch64 | ET_REL (0x1) | | 5.10.ko | 904 016 | ELF64 | aarch64 | ET_REL (0x1) | | 5.15.ko | 918 576 | ELF64 | aarch64 | ET_REL (0x1) | | 6.1.ko | 881 568 | ELF64 | aarch64 | ET_REL (0x1) | | 6.6.ko | 746 320 | ELF64 | aarch64 | ET_REL (0x1) | | 6.12.ko | 692 272 | ELF64 | aarch64 | ET_REL (0x1) | 这八个文件在功能上是同一个项目,针对八个不同的 Android 内核 ABI 版本进行了重新编译(文件名与上游 Linux 内核发行版匹配)。大小的差异主要由 `.modinfo` / `__versions`(被 `insmod` 消耗的 per-symbol CRC 表)主导 — 实际的 `.text` 体积很小。 ## 4. IDA Pro 分析(以 `6.6.ko` 作为规范样本) - 文件:`mem_tool_driver/6.6.ko` - 架构:ARM64 (`e_machine = 0xB7`) - 映像大小:`0xb078`,`.text` 位于 `0xd5c — 0x4818` (~14 KB) - 函数:共 112 个,自动分析后已有 89 个被命名 - 哈希值: - MD5 `f401458ba0227d251840d5856bc8c770` - SHA-256 `8eb479d6062c5ff8bd036026dbd8ae4083569e4eb7b1e1a410cc9a32dc6d808f` ### 4.1 入口点清单(由 IDA 命名) | addr | symbol | role | |----------|---------------------------------|--------------------------------------| | `0x9008` | `init_module` / `driver_entry` | 模块加载 | | `0x9520` | `cleanup_module` / `driver_unload` | 模块卸载 | | `0xfd8` | `dispatch_ioctl` | 主 ioctl 路由器 | | `0x1c3c` | `dispatch_open` | `file_operations.open` | | `0x1c54` | `dispatch_close` | `file_operations.release` | | `0x578` | `dispatch_functions` | `struct file_operations` | | `0xd60` | `get_rand_str` | 随机 6 字符设备名生成器 | | `0xf30` | `util_find_kallsyms` | 解析未导出的 `kallsyms_lookup_name` | | `0xf98` | `util_kallsyms_lookup_name` | 包装器 | | `0x1c60` | `hide_module` | 从 `lsmod`/sysfs 自隐藏 | | `0x1f9c` | `hide_mount_tmpfs` | 在路径上覆盖 tmpfs | | `0x16fc` | `manage_process_visibility` | 通过 PID 隐藏/恢复任务 | | `0x224c` | `my_get_task_struct_by_pid` | 任务查找辅助函数 | | `0x22b8` | `translate_linear_address` | 手动页表漫游 | | `0x232c` | `my_copy_to_user` | 绕过 PAN 的 copy_to_user | | `0x2484` | `read_physical_address` | 通过 vmap 进行物理读取 | | `0x2770` | `write_physical_address` | 通过 vmap 进行物理写入 | | `0x2a3c` | `read_process_memory` | 跨进程 VM 读取 | | `0x2f80` | `write_process_memory` | 跨进程 VM 写入 | | `0x36a8` | `install_hw_bp` | 添加 HW 断点 | | `0x4334` | `clear_all_hw_bps` | 清除所有断点 | | `0x4420` | `enable_hw_bp` / `0x46f4 disable_hw_bp` | 切换 | | `0x409c` | `get_hw_bp_hits` | 耗尽命中环缓冲 | | `0x3120` | `toggle_bp_registers_directly` | 直接进行 DBGBVR/DBGBCR MSR 写入 | | `0x450` | `devicename` (数据) | 随机化设备名称槽 | ### 4.2 ioctl 命令表(与 `kernel_client.h` 匹配) | cmd | name | argument | behaviour | |----------|-----------------------|---------------------------------------|-----------| | `0x800` | `OP_INIT_KEY` | `char[256]` 许可证/认证字符串 | 限制进一步使用 | | `0x801` |OP_READ_MEM` | `COPY_MEMORY{pid,addr,buf,size}` | 跨进程 VM 读取 | | `0x802` | `OP_WRITE_MEM` | `COPY_MEMORY{pid,addr,buf,size}` | 跨进程 VM 写入 | | `0x803` | `OP_MODULE_BASE` | `MODULE_BASE{pid,name,base,index}` | 遍历目标 VMAs,匹配 `d_path` 基本名称,返回基地址 | | `0x804` | `OP_CMD_HWBP_ADD` | `HW_BP_INFO` | 安装 ARM64 硬件断点 | | `0x805` | `OP_CMD_HWBP_GET_HITS`| `HWBP_HIT_ARGS` | 耗尽命中记录的环形缓冲区 (regs+pc+sp+pstate) | | `0x806` | `OP_CMD_HWBP_ENABLE` | `HW_BP_INFO` | 重新启用 + 更新 | | `0x807` | `OP_CMD_HWBP_CLEAR` | - | 清除所有断点 | | `0x809` | `OP_CMD_HWBP_DISABLE` | `HW_BP_INFO{pid,addr}` | 禁用 | | `0x810` | `OP_CMD_HIDE_PROCESS` | (无 — 使用调用者 pid) | 将调用者从任务列表取消链接 | | `0x811` | `OP_CMD_RECOVER_PROCESS` | (无) | 重新链接 | 您在每个 read/write 用例中看到的 `_ReadStatusReg(SP_EL0)` / `WriteStatusReg(TTBR0_EL1, ...)` 堆叠调用是 **PAN 绕过**:驱动程序翻转 `TTBR0_EL1` 以允许特权读取通常被 ARM64 PAN 阻止的用户态地址。 ### 4.3 `init_module` 中的隐匿/反检测机制 1. `util_find_kallsyms()` — 定位 `kallsyms_lookup_name`(在内核 5.7+ 中未导出)。这是必需的,因为驱动程序想要调用非导出的 API。 2. `get_rand_str()` — 生成一个随机的 6 字符设备名称。`kernel_client.h::driver_path()` 中的用户态客户端通过扫描 `/dev` 来发现此设备,寻找满足 `atime == ctime`、`size == 0`、`uid == gid == 0`、1980 年后 `ctime` 的 6 字符 chardev/blockdev。匹配条件被故意设置得很严格,以逃避基于签名的扫描器。 3. 在运行时解析未导出的符号:`kern_path`、`path_mount`、`path_umount`、`path_put`、`tasklist_lock`、`init_task`、`vmap_area_list`、`vmap_area_root`。 4. 注册字符设备(`alloc_chrdev_region` + `cdev_init` + `cdev_add`),在该随机名称下创建类和设备。 5. `hide_mount_tmpfs("/sys/class/")` 和 `("/sys/devices/virtual/")` — 在每个 sysfs 路径上覆盖一个空的 tmpfs (`MS_NOATIME|MS_NODEV|MS_NOEXEC`),这样用户态工具在这些目录下看不到任何东西。 6. `hide_module()` — 模块级别的 rootkit: - 遍历 `vmap_area_list` / `vmap_area_root`,定位覆盖 `&__this_module` 的条目,将其从链表中取消链接,使用 `0xDEAD000000000100` / `0xDEAD000000000122` 下毒,并通过 `rb_erase` 从红黑树中移除。从 `/proc/vmallocinfo` 隐藏模块的 vmap 分配。 - 将 `__this_module` 从全局模块列表(`off_9888` / `off_9890` `list_head`)中取消链接。从 `lsmod` 和 `/proc/modules` 隐藏。 - 对模块的 kobject 执行 `kobject_del`。从 `/sys/module/` 隐藏。 - 遍历 `mod->modinfo_attrs` 并 `sysfs_remove_link` 移除 `devwh` 属性的符号链接,释放属性结构。 - 向 dmesg 打印 `[hook] Module hidden successfully.\n`(随后加载脚本会使用 `dmesg -C` 清除它)。 7. `hide_mount_tmpfs("/data/local/tmp/")` — 在 dropbox 目录上覆盖 tmpfs,这样在挂载之前放置的任何伴随文件对用户态都是不可见的,直到下次重启。 ### 4.4 二进制文件中**没有**什么 以下每个类别都对照导入表和函数列表进行了检查。均不存在: | capability | indicators | present | |-----------------------------|-----------------------------------------------------|---------| | 网络渗透 | `sock_create_kern`, `kernel_sendmsg`, `kernel_connect`, `tcp_*`, `udp_*` | NO | | 加密 | any `crypto_*`, AES, SHA | NO | | 文件写入 | `vfs_write`, `kernel_write`, `filp_open` write mode | NO | | 后台线程 | `kthread_run`, `kthread_create`, workqueues | NO | | 系统调用表挂钩 | writes to `sys_call_table`, ftrace trampolines | NO | | 提权原语 | `commit_creds(prepare_kernel_cred(NULL))` | NO | | 持久化 | filesystem writes to init scripts / properties | NO | 内核到外部世界的唯一 I/O 是 `_printk` (dmesg) 和向调用用户态进程的 `__arch_copy_to_user`。导入的 `register_kprobe` / `unregister_kprobe` 仅用于硬件断点命中处理程序的管道连接,不用于系统调用范围广泛的挂钩。 您在反编译中看到的 CFI 完整性检查(在对解析的 kallsyms 地址进行每次间接调用之前的 `*((DWORD*)fnptr - 1) != `)是 LLVM/Clang 的 Control-Flow-Integrity 保护,并非恶意的 — 它们证实了这是一个经过加固的 Clang 构建。 ## 5. 结论 这是一个**中国安卓游戏作弊 rootkit**(“RT驱动 / RTdrivers / Cycle1337”谱系),几乎可以肯定是针对 FPS / MOBA 手游的。 - 按照任何合理的定义,它都是真正的 rootkit:模块自隐藏、sysfs tmpfs 覆盖、进程隐藏、随机化设备名称、加载脚本中的 dmesg 清除、运行时解析未导出的内核符号。 - 它**不是**数据窃取载荷。`.ko` 内部没有隐蔽通道,没有加密传输,没有文件写入,没有后台工作线程,也没有任何形式的网络栈使用。 - 因此,运行它的危险并不在于*由驱动程序*进行的渗透,而在于它通过随机 `/dev/` 设备暴露的完全开放的内核级读/写原语。一旦该文件描述符可被访问,**任何持有它的进程都可以转储设备上所有其他应用的内存** — 银行会话、密码管理器、端到端加密的信使密钥、ART 托管堆等。作弊客户端只是其中一个消费者。 - 封装脚本中的 Telegram 频道“验证”关卡是一种变现手段(必须订阅 `@RTdrivers` 才能使用驱动程序),而不是后门或远程控制通道。 ## 6. 从二进制文件重建? `.ko` 无法还原回字节级一致的源代码。IDA 的伪代码有助于理解,但不能替代源代码。此集合中的八个文件是针对八个不同的内核 ABI 编译的同一个逻辑项目,但这里不存在任何源代码。 从头开始重写相同的原语会产生一个同样危险的 rootkit,并且不是安全上的改进 — 威胁在于*能力*,而不在于二进制形式。如果您不信任上游,正确的做法是**根本不要加载此类驱动程序**,而不是加载一个手工克隆的版本。 ## 7. 有用的后续行动 - 转储每个 `.ko` 的 `.modinfo` 节以确认 `vermagic` / 目标内核构建标志。对比这八个文件以验证“同项目,不同 ABI”的假设。 - 在这八个文件之间逐字节比较 `.text`(重定位后)——几乎所有的体积差异都将存在于 `.modinfo` 和 `__versions` 中。 - 对 `5.4.ko` 和 `6.12.ko`(体积的两个极端)重新运行 IDA 分析,并对比函数清单以确认具备相同的能力集。 *作为 2026-04-25 对该集合静态分析的一部分生成。文件仅保留用于分析目的。*
标签:0day挖掘, Android安全, ARM64, Cutter, DAST, IDA Pro, ioctl, Linux内核模块, PAN绕过, Rootkit, RT驱动, Zeek, 二进制分析, 云安全监控, 云安全运维, 云资产清单, 免杀技术, 内核安全, 反作弊, 后门分析, 威胁情报, 客户端加密, 开发者工具, 恶意软件分析, 手机安全, 暴力破解检测, 游戏安全, 逆向工具, 逆向工程, 隐藏技术, 静态分析, 驱动分析