使用libsu来在Android中访问超级用户权限
本文最后更新于 535 天前,其中的信息可能已经有所发展或是发生改变。

在Android中,APP自身无法获得root权限(uid变成0)。

我尝试过在内核态修改APP的uid,但是这样做会导致APP进程卡死。

所以,需要使用root权限进行一些复杂操作时,最好的方法就是启动一个具备root权限的守护进程,由守护进程来操作。而这样启动的守护进程无法绘制UI,虽然有一些手段可以绘制,但是存在很多问题,比如触摸穿透。

所以,通行的方法是,由APP启动守护进程(下文称为Core),然后和守护进程之间建立某种连接,通过进程间通信来指挥Core行驶权限,数据在Core中分析完毕后,交由APP来呈现给用户。

进程间通信的手段有很多,共享内存,Unix Domain Socket,管道等等等等,但是这些方法都不太方便,需要自己手动维护连接,并且编码将变成C/S结构,代码中将大量使用回调,变得很不直观。

libsu可以方便的自动完成以上操作,并且得益于Android的AIDL机制,可以像工作在同一个进程中一样编码。

libsu是由Magisk的主要维护者John Wu开发的一款开源库,旨在简化root开发流程。引入libsu库非常简单,只需要在项目设置中引入如下仓库

maven("https://jitpack.io")

然后在需要使用的模块中

dependencies {
    val libsuVersion = "5.3.0"

    // The core module that provides APIs to a shell
    implementation("com.github.topjohnwu.libsu:core:$libsuVersion")

    // Optional: APIs for creating root services. Depends on ":core"
    implementation("com.github.topjohnwu.libsu:service:$libsuVersion")

    // Optional: Provides remote file system support
    implementation("com.github.topjohnwu.libsu:nio:$libsuVersion")
}

libsu本质上依然是在进程间进行通信,你必须先掌握AIDL的使用方法,本文不做赘述。

首先,定义如下AIDL

package ling.core;


interface IRootProcess {
    int getUid();
}

然后需要先build一下项目,才会生成它的代理类。

你需要在运行配置中,启用 Always install with package manager 选项,否则更改可能不会生效。

实现IRootProcess,这将成为APP调用的接口。

public class RootProcess extends IRootProcess.Stub {
    @Override
    public int getUid() throws RemoteException {
        //此处已经在root进程中
        return Process.myUid();
    }
}

然后,定义一个Service,继承自RootService。

RootService相较Android的Service有很多改动,不要将它用在其他地方!

public class RootService extends com.topjohnwu.superuser.ipc.RootService {
    static {
        //由于将要在APP中请求启动此服务,
        //所以APP中的类加载器也会载入它
        //仅在root进程中加载需要的库
        if (Process.myUid() == 0) {
            System.loadLibrary("CoreTask");
        }
    }

    @Override
    public IBinder onBind(@NonNull Intent intent) {
        //此处已经在Root进程中!
        //这是刚刚IRootProcess的实现类
        //此对象将作为接口交由APP调用
        return new RootProcess();
    }
}

在连接Core之前,需要一个类来获取结果:

public class RootConnection implements ServiceConnection {

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        //连接成功,root就是刚刚返回的RootProcess的代理类
        //像平常一样调用其中的方法,实际执行将在Core中完成。
        IRootProcess root = IRootProcess.Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
         //连接断开
    }
}

然后,在一个合适的位置启动这一切:

RootService.bind(new Intent(this, RootService.class), new RootConnection());

大功告成!

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇