KeepAlive 攻防指南:MIUI 为何封杀它?系统级防御与反制策略全解读
【免费下载链接】KeepAliveFighting against force-stop kill process on Android with binder ioctl / Android高级保活项目地址: https://gitcode.com/gh_mirrors/ke/KeepAlive
KeepAlive 是一个 Android 高级保活(进程复活)开源库,它通过 binder ioctl 直接与系统 binder 驱动通信,让被杀死的进程能被"守护进程"复活。本文带你彻底看懂它的攻防原理:为什么 MIUI 等定制系统会封杀它、系统层该如何防御、又该如何反制。
什么是 KeepAlive:Android 保活的"不死方案"
KeepAlive 在 Leoric(通过 JNI 复活进程)的基础上,实现了通过ioctl 复活进程,能最大程度提高复活率:
- 🪶资源占用少,用户无感知
- 🔁成功率高:在未被封杀的环境下(Android 4.4 ~ 9.0 模拟器)几乎"杀不死"
- 📚 同时是学习binder 框架的优秀案例
⚠️ 作者明确提示:真机上不能保证保活成功(MIUI 等定制系统已封杀了这个方案),不建议在 C 端产品上使用。
保活原理:三个进程如何互相"守护"
一、进程结构:主进程 + 双守护
KeepAlive 把 App 拆成三个互相监听的进程(配置见library/src/main/java/com/boolbird/keepalive/KeepAliveConfigs.java):
| 进程 | 默认名称 | 角色 |
|---|---|---|
| 主进程 | App 包名 | 业务逻辑,负责初始化保活 |
| 常驻进程 | :resident | 守护者 A,监控守护者 B |
| Daemon 助手 | android.process.daemon | 守护者 B,伪装成系统进程名 |
任一进程被杀,另外两个都会通过 binder 把它"拉起来",形成连环守护。
二、复活机制:绕过 Java API 直接喊话 AMS
核心实现在library/src/main/java/com/boolbird/keepalive/KeepAliveProcessImpl.java:
- 反射拿到
ActivityManagerNative的远程代理mRemote(即 ActivityManagerService 的 binder 对象); - 按 AIDL 协议手工构造
startService的 Parcel 数据——注意不同系统版本的 transaction code 不同(Android 9 为 24、8.0 为 30、7.x 为 26、4.4 为 34),这就是它只能覆盖 4.4~9.0 的原因; - 一旦检测到目标进程死亡,直接调用
mRemote.transact(code, parcel, null, 1),让系统"以为"是正常启动服务,进程原地复活。
三、监听机制:C++ 层的隐藏观察者
library/src/main/cpp/keep_alive.cpp(JNI 声明见library/src/main/java/com/boolbird/keepalive/NativeKeepAlive.java)实现了"进程死亡检测":
- 双重
fork派生隐藏子进程,并用setArgV0把进程名伪装成app_d,躲避ps排查; - 用 indicator 标记文件 +
flock文件锁判断对方是否还活着:进程死亡时锁自动释放,观察者立刻发起 binder 复活; - 配合
AlarmManager每 60 秒定时唤醒(见KeepAlive.launchAlarm)和bindService+linkToDeath死亡回调,多管齐下。
为防止"无限重启风暴",还内置了rebootThreshold(10s, 3):10 秒内连续重启超过 3 次就自动停用守护(实现见KeepAlive.checkProcessContinuousBootOverTimes)。
为什么 MIUI 会封杀 KeepAlive?
这套方案的隐藏前提是:"杀了我之后,系统还允许我启动新进程"。
用户点击"强制停止"(am force-stop)时,标准流程是直接杀掉该应用的进程。但如果观察者进程在被打死前抢先发出一次transact,进程就复活了,保活成功。
MIUI 等定制 ROM 正是针对这个窗口期做了两处系统级改造(README「应对方法」一节给出的官方思路):
- force-stop 期间禁止启动新进程:系统为该应用打上"正在强杀"标记,标记存续期间,所有指向该应用的 startService/startActivity 请求被直接拒绝——观察者喊话也喊不出活来;
- 批量收集后统一击杀:不再"发现一个杀一个",而是先收集好应用的全部进程,必要时先发送 SIGSTOP 冻结,再统一 kill,杜绝任何进程在间隙中"偷跑"复活请求。
反制策略:一条命令冻结并终结观察者
项目根目录的 kill_alive.sh 就是压力测试脚本:循环 100 次执行am force-stop观察复活率。在未被改造的系统上,单条 force-stop 往往杀不干净,正确的终结姿势是(README 给出):
ps -A | grep `ps -A | grep keepalive | awk '{print $1}' | head -1` | awk '{print $2}' | xargs kill -19 && am force-stop com.boolbird.keepalive拆解一下:
kill -19发送SIGSTOP,先把观察者进程冻结,让它彻底失去复活窗口;- 随后
am force-stop再整体击杀。
这正是防御策略"先 SIGSTOP、后统一 kill"在攻击侧的直接应用——攻防双方博弈的核心,都在这几百毫秒的时间窗口里。
如何快速上手:4 步集成 KeepAlive
以 demo 模块app/为例:
- 注册保活配置:在 Application 的
attachBaseContext中调用KeepAlive.init(base, configs),指定常驻 Service(demo:app/src/main/java/com/boolbird/keepalive/demo/MainApplication.java); - 声明 Service:在
app/src/main/AndroidManifest.xml中给 Service 设置独立进程:resident,Service 需继承KeepAliveService,否则在 Android 4.4 上无保活效果; - 启动服务:
startService(...)即可自动唤醒保活进程; - 可选增强:
configs.ignoreBatteryOptimization()忽略电池优化、configs.rebootThreshold(10*1000, 3)重启限频、configs.setOnBootReceivedListener(...)设置开机自启。
适用场景与注意事项
| 维度 | 说明 |
|---|---|
| ✅ 推荐 | 自研轻量定制 Android 系统对系统应用的保活 |
| ✅ 推荐 | 作为binder 框架的学习案例 |
| ⚠️ 谨慎 | C 端(消费者)产品不建议使用 |
| ⚠️ 注意 | 避免在 Application 中初始化第三方库,否则所有进程都会重复初始化 |
一句话总结:KeepAlive 用"三进程互守 + binder 直连 AMS"把复活率拉满,而 MIUI 的应对就是"强杀期间禁启 + 先冻结后集火"。理解了这场攻防,你也就读懂了 Android 进程保活与系统管控博弈的本质。
【免费下载链接】KeepAliveFighting against force-stop kill process on Android with binder ioctl / Android高级保活项目地址: https://gitcode.com/gh_mirrors/ke/KeepAlive
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考