本帖最后由 jackson 于 2017-4-16 20:55 编辑
通过参照
[FAQ11414]android KK 4.4 版本后,user 版本su 权限严重被限制问题说明
http://www.voidcn.com/blog/wds1181977/article/p-6157006.html
明确要修改三个地方:
(1)把dalvik/vm/native/dalvik_system_Zygote.cpp文件中函数forkAndSpecializeCommon里面以下代码注释掉。
for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
err = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
if (err < 0) {
if (errno == EINVAL) {
ALOGW("PR_CAPBSET_DROP %d failed: %s. "
"Please make sure your kernel is compiled with "
"file capabilities support enabled.",
i, strerror(errno));
} else {
ALOGE("PR_CAPBSET_DROP %d failed: %s.", i, strerror(errno));
dvmAbort();
}
}
}
(2)把dalvik/vm/Init.cpp文件中函数initZygote()里面的以下代码注释掉。
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
// Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
// EINVAL. Don't die on such kernels.
if (errno != EINVAL) {
SLOGE("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
return -1;
}
}
(3)关闭SELinux,可通过命令setenforce 0 临时关闭。
通过测试发现,su权限仍然被限制,无法让app临时获取root权限。系统应该在某些地方还做了权限限制。
纠结了一阵子,后面在了解Zygote相关知识的过程中发现有一种方式可以让app永久获取root权限,说明如下。
因为所有Android应用进程都是zygote fork出来的,新fork出来的应用进程还保持着root权限,这显然是不被允许
的,所以这个fork出来的子进程的权限需要被降级。
这个降级操作的代码也是在dalvik/vm/native/dalvik_system_Zygote.cpp文件中函数forkAndSpecializeCommon里面:
err = setresgid(gid, gid, gid);
if (err < 0) {
ALOGE("cannot setresgid(%d): %s", gid, strerror(errno));
dvmAbort();
}
err = setresuid(uid, uid, uid);
if (err < 0) {
ALOGE("cannot setresuid(%d): %s", uid, strerror(errno));
dvmAbort();
}
系统通过调用setresgid和setresuid将APK进程的uid/gid从root修改为App安装时分配的id,也就是做了权限退化。
尝试把这部分代码注释掉,让android所有fork出的进程都具有root,更新系统后,发现机器启动异常,查看log:
I/Zygote (31781): Accepting command socket connections
I/ (31986): System server: starting sensor init.
D/SensorService(31986): nuSensorService starting...
E/Sensors (31986): open_sensors called begin.
I/QCOM PowerHAL(31986): QCOM power HAL initing.
I/SystemServer(31986): Entered the Android system server!
I/SystemServer(31986): Waiting for installd to be ready.
I/SystemServer(31986): Enabled StrictMode logging for WM Looper
I/Installer(31986): connecting...
I/Installer(31986): disconnecting...
E/Installer(31986): connection failed
日志表明,系统应该挂在了安装应用环节。具体缘由还没去研究,估计系统作了security check,禁止某些进程
具有root权限。
于是换种方式修改:
if(gid < 10062) {
err = setresgid(gid, gid, gid);
if (err < 0) {
ALOGE("cannot setresgid(%d): %s", gid, strerror(errno));
dvmAbort();
}
}
if(uid < 10062) {
err = setresuid(uid, uid, uid);
if (err < 0) {
ALOGE("cannot setresuid(%d): %s", uid, strerror(errno));
dvmAbort();
}
}
修改思路是让安装的非内置的app具有root权限。10062这个id值不固定,根据不同机器内置的apk数量来定。android默
认10000到99000的AID是分配给应用程序的,具体可参考system/core/include/private/android_filesystem_config.h
结合上文(1)和(2)的修改(SELinux不需要关闭),安装的app具有了root权限,su权限解放。
后期补充:
经过测试,这种方式获取root会导致一些app运行不了,通过函数setcapability来bypass掉DAC检测后能正常运行app。
考虑安全性问题,请读者慎用这种方式获取root。
可通过这样的方式:在init.rc里面创建service,这样肯定具有root权限,app通过socket方式与service通信。