`
ydbc
  • 浏览: 716259 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

MIUI的root权限管理分析

 
阅读更多
一、授权管理

MIUI中对与root权限的管理和控制通过两个模块实现:
su 这是一个ELF可执行文件,在系统中的路径为/system/bin/su
Superuser.apk(Superuser.odex) 授权管理app
MIUI中的app提权到root的一般过程为:

某个app通过Runtime.getRuntime().exec()方法执行提权命令”su [options]“
su被执行,将待提权app的相关信息以广播的形式发送出去,并开启local socket服务端等待客户端连接
Superuser.apk中的广播接收器接受到su发送的广播,获得用户的设置,然后将结果通过local socket返回给su

su根据Socket客户端发来的结果继续或者终止提权过程


二、问题定位


由于MIUI的su不容易被逆向分析,所以从分析Superuser.apk(Superuser.odex)入手。MIUI将系统应用程序(/sysetm/app目录下)apk文件中的classes.dex提取出来,进行优化得到odex文件,也存放到/system/app目录下。例如,Superuser这个app就分为两个部分,Superuser.apk和Superuser.odex,与典型的apk文件不同,Superuser.apk中已没有classes.dex了。

查看Superuser.apk中的AndroidManifest.xml,看到了一个比较关键的BroadcastReceiver:

<?xml version="1.0" encoding="utf-8"?>
<manifest android:versionCode="24" android:versionName="2.3.6"
    package="com.miui.uac"
    xmlns:android="http://schemas.android.com/apk/res/android">
        ...
        <receiver android:name="SuRequestReceiver">
            <intent-filter>
                <action android:name="com.miui.uac.REQUEST" />
            </intent-filter>
        </receiver>
        ...
        <uses-permission android:name="com.miui.uac.RESPOND" />
        <permission
            android:label="@string/permlab_respond"
            android:name="com.miui.uac.RESPOND"
            android:protectionLevel="signature"
            android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
            android:description="@string/permdesc_respond" />

根据名字大概可以判断,su发来的广播会被此receiver接受并进行处理(后面查看它的smali代码也验证了这个判断)。值得注意的是,这个receiver是对外暴露的,而且 看起来没有受到任何权限的保护。如何利用这一点,有两个思路:

伪造广播,看能否有”意外”作用
伪造广播接收器,实现广播监听或者劫持(虽然从AndroidManifest.xml中来看,com.miui.uac.RESPOND权限可能会成为一个障碍)


(1)伪造广播

尝试使用am发送一条空广播:
$ adb shell am broadcast -a com.miui.uac.REQUEST
授权管理app崩溃了。
查看log发现广播接收器中的数据库查询语句出了问题,应该是缺少参数导致的。看来伪造广播并发送是可行的,但是在此之前,要找到合适的广播参数,让授权管理app不会崩溃。使用baksmali反编译Superuser.apk查看com/miui/uac/SuRequestReceiver.smali的代码:

.method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V
    const/4 v2, 0x0
    const-string v0, "caller_uid" #从intent中得到caller_uid
    invoke-virtual {p2, v0, v2}, Landroid/content/Intent;->getIntExtra(Ljava/lang/String;I)I
    move-result v0

    const-string v1, "desired_uid" #从intent中得到desired_uid
    invoke-virtual {p2, v1, v2}, Landroid/content/Intent;->getIntExtra(Ljava/lang/String;I)I
    move-result v1

    const-string v2, "desired_cmd" #从intent中得到desired_cmd
    invoke-virtual {p2, v2}, Landroid/content/Intent;->getStringExtra(Ljava/lang/String;)Ljava/lang/String;
    move-result-object v2

    const-string v3, "socket" #从intent中得到socket
    invoke-virtual {p2, v3}, Landroid/content/Intent;->getStringExtra(Ljava/lang/String;)Ljava/lang/String;
    move-result-object v3

    # 从数据库中查询当前app权限配置
    new-instance v4, Lcom/miui/uac/DBHelper;
    invoke-direct {v4, p1}, Lcom/miui/uac/DBHelper;->(Landroid/content/Context;)V
    invoke-virtual {v4, v0, v1, v2}, Lcom/miui/uac/DBHelper;->checkApp(IILjava/lang/String;)Lcom/miui/uac/AppDetails;
    move-result-object v0
    invoke-virtual {v0}, Lcom/miui/uac/AppDetails;->getAllow()I
    move-result v1

    const/4 v2, -0x1
    if-ne v1, v2, :cond_3f

    # 弹框提示用户允许/拒绝当前app提权
    new-instance v0, Landroid/content/Intent;
    const-class v1, Lcom/miui/uac/SuRequest;
    invoke-direct {v0, p1, v1}, Landroid/content/Intent;->(Landroid/content/Context;Ljava/lang/Class;)V
    invoke-virtual {v0, p2}, Landroid/content/Intent;->putExtras(Landroid/content/Intent;)Landroid/content/Intent;
    const/high16 v1, 0x1000
    invoke-virtual {v0, v1}, Landroid/content/Intent;->addFlags(I)Landroid/content/Intent;
    invoke-virtual {p1, v0}, Landroid/content/Context;->startActivity(Landroid/content/Intent;)V

    :goto_3b
    invoke-virtual {v4}, Lcom/miui/uac/DBHelper;->close()V
    return-void

    :cond_3f
    # 返回结果给su
    invoke-static {p1, v0, v3}, Lcom/miui/uac/ResponseHelper;->sendResult(Landroid/content/Context;Lcom/miui/uac/AppDetails;Ljava/lang/String;)V
    goto :goto_3b
.end method
根据smali代码,可以看到intent传递过来的广播参数一共有四个,key分别为caller_uid, desired_uid, desired_cmd, socket,值依次存储在寄存器v0~v3中。DBHelper进行数据库操作时,并没有涉及到寄存器v3,因此,只要在构造的广播中加入前三个参数,也就是caller_uid, desired_uid, desired_cmd即可。
caller_uid, desired_uid很容易明白, 但是desired_cmd是什么形式的就难以琢磨了。不过既然在数据库操作中把desired_cmd传递过去了,先看看数据库中有没有相关信息。

在/data/data/com.miui.uac/databases中有一个数据库文件permissions.sqlite,其中有三个表:

# pwd
/datadata/com.miui.uac/databases
# ls -l
-rw-rw----    1 app_32   app_32      288768 Jan 21 17:01 permissions.sqlite
# sqlite3 permissions.sqlite
sqlite> .tables
android_metadata  apps              logs              prefs           
sqlite> .schema apps 
CREATE TABLE apps (_id INTEGER, uid INTEGER, package TEXT, name TEXT, 
    exec_uid INTEGER, exec_cmd TEXT, allow INTEGER, PRIMARY KEY (_id), 
    UNIQUE (uid,exec_uid,exec_cmd));
sqlite> select * from apps;
1|10058|jackpal.androidterm|终端模拟器|0|/system/bin/sh|1

结合apps表的schema和其中的内容,exec_uid对应前面提到的desired_uid,exec_cmd对应前面提到的desired_cmd。因此,把desired_cmd设置为”/system/bin/sh”就行了。(后来发现,只要不是空字符串就行……)构造以下广播:

$ adb shell am broadcast -a com.miui.uac.REQUEST \
> --ei caller_uid 10051  --ei desired_uid 0 --es desired_cmd "/system/bin/sh"

被成功接收,并且授权管理app弹出对话框提示用户进行授权。
使用代码实现的话也比较简单:

        Intent it = new Intent();
        it.setAction("com.miui.uac.REQUEST");
//      ComponentName c = new ComponentName("com.miui.uac", "com.miui.uac.SuRequestReceiver");
//      it.setComponent(c);
        it.putExtra("caller_uid", 10051);
        it.putExtra("desired_uid", 0);
        it.putExtra("desired_cmd", "/system/bin/sh");
         
        getApplicationContext().sendBroadcast(it);
(2)伪造广播接收器

自己写一个app注册广播接收器net.yurushao.uactest.FakeSuRequestReceiver:


<receiver android:name=".FakeSuRequestReceiver" >
    <intent-filter>
        <action android:name="com.miui.uac.REQUEST" />
    </intent-filter>
</receiver>

public class FakeSuRequestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context arg0, Intent arg1) {
        // TODO Auto-generated method stub      
        System.out.println(arg1.getAction());   
    }
}

选取某个正常app进行提权时,FakeSuRequestReceiver没有任何反应。查看log发现:

Permission Denial: receiving Intent { act=com.miui.uac.REQUEST (has extras) }
to net.yurushao.uactest requires com.miui.uac.RESPOND due to sender null (uid 0)
没有com.miui.uac.RESPOND权限,而这个权限是受签名保护的,因此对su发出广播的监听和劫持都是无法实现。

三、 总结

su发送 的广播可以被伪造,但是不可以被监听或者劫持。至于对广播的伪造,除了能引起授权管理app的崩溃,还没有发现可以被利用的地方。

分享到:
评论

相关推荐

    小米稳定版root

    小米2 稳定版Root 权限管理 快速获得Root权限,与开发版一样的待遇

    小米手机无需刷入Recovery获取Root权限工具包

    不需要刷入第三方Recovery,就可以获取Root权限工具,和教程,线刷/卡刷包提取boot.img工具

    root+magisk+所有手机获取root权限通用教程

    所有手机不限种类root通用教程,傻瓜式操作按照提示直接刷入,安全快捷方便,要用就用官方的。

    小米平板5 pro5G版【ENUMA】13.0.6稳定版一键获取完整root资源与详细步骤

    小米平板5 pro5G版【ENUMA】13.0.6稳定版一键获取完整root资源与详细步骤 资源内带一键刷写脚本 只需要进入fast模式运行脚本即可完美刷入自动重启系统 ...按步骤操作即可获取完整root权限 需要的友友下载使用

    Android Root工具和驱动 取得root权限工具

    Android Root工具和驱动 取得root权限工具

    小米平板2一键REC及ROOT工具.zip

    MIPAD2专用ROOT文件+MIPAD2一键REC工具

    ICS24.0 稳定版 刷ROOT权限

    最近自己的小米1s升级到ICS24.0 稳定版,发现不能使用root权限了。媳妇儿推荐这一款专为小米1/1s使用的ROOT包,安装成功重启后,ROOT权限妥妥的。压缩包内包含开启稳定版支持ROOT功能和还原稳定版不支持ROTO功能...

    红米手机必备工具包 刷机 root RE浏览器

    百度一键root软件: 获取root权限 可以自己更改一些系统参数设置 re浏览器 :在获得root权限后,可以查看手机上任意文件的信息及进行读写操作 相机设置软件: 在小米APP应用商店下载的 可以把相机的声音给取消.

    小米play 强解bl锁资源 免授权线刷救砖 root详细图文教程

    1-----资源内带强解bl锁工具和详细图文教程步骤 2-----资源内带相关驱动...7----按步骤操作可以获取root权限、 8----任何的刷机操作都有风险。小伙伴们请谨慎操作哦 请关注本人 了解安卓机型各种刷机资源和实例教程

    小米路由器mini丢失SN无法获取root权限怎么办?

    小米路由器mini丢失SN无法获取root权限怎么办?没事折腾小米路由器发现sn丢失,没办法获取root权限,这样就没法通过SSH远程连接小米mini路由系统,该怎么办呢?下面我我们就来看看详细的解决办法,需要的朋友可以...

    检测手机是否Root源码.zip

    经过分析,这是由于小米有自身的权限控制系统而导致。只需要在第二种方法的基础上,再另外判断文件拥有者对这个文件是否具有可执行权限(第4个字符的状态),就基本可以确定手机是否root了。这种方法基本可以判断所有...

    小米手机字库备份还原.rar

    高通机型备份字库:安装个MT管理器,使用root权限执行【高通字库备份.sh】即可。备份的文件在/sdcard/Rannki目录中。 高通机型还原字库:提前把之前备份好的Rannki文件夹,复制到/sdcard/Rannki,安装个MT管理器,...

    OPPO Reno6 Pro-mtk强解锁bl工具+root详细图文教程

    3---按步骤操作即可解锁bl 然后按步骤获取面具root权限 4---从此走向自己机型玩机搞机之路。安装框架 模块等等 5----需要的友友建议看图文教程3遍后在操作 6----建议备份重要资料后在操作。 7----任何的刷写操作...

    Android例子源码不弹框手机是否Root检测例子.zip

    经过分析,这是由于小米有自身的权限控制系统而导致。只需要在第二种方法的基础上,再另外判断文件拥有者对这个文件是否具有可执行权限(第4个字符的状态),就基本可以确定手机是否root了。这种方法基本可以判断所有...

    XT883 root 工具

    XT883 root工具,可以破除三网使用权限,电信基带更改

    OPPO X909 root权限破解

    主要是针对OPPO Finder 官方 miui和LePAD A2107等一系列rom更新优化移植,打造一系列,风格多,华丽和简约并存的极致的rom,发挥了机器的最强作用

    文章《Android小米手机 Root全攻略:轻松获取手机最高权限》对应资源

    文章《【Android】小米手机 Root全攻略:轻松获取手机最高权限》对应资源 https://blog.csdn.net/kinghzking/article/details/130622172 文中用到的所有资源: LSPosed-v1.8.6-6712-zygisk-release.zip Magisk-v...

    Root Essentials Premium 2.4.9.apk

    Root Essentials ...许多ROM,包括AOSP,Cyanogenmod,Paranoid和Miui都可以植根或拥有ROM中的“管理员权限”。 新功能 •在Emoji Changer中添加/更新了“Android O”和“EmojiOne”表情符号; •更新的翻译。

    MiStep:小米步数管理的重制版

     所以这一次为大家带来了可能、大概、也许、应该是最终版的小米步数管理,它拥有:增加和指定两种修改步数类型、第一次打开和0点定时(需要手动为APP启用自启动权限)两种自动修改方式、核心破解和ROOT两种修改模式...

    红米K50至尊版 V13.0.5.0.SLFCNXM 面具ROOT服务

    红米K50至尊版 V13.0.5.0.SLFCNXM 面具ROOT服务 ...刷入前请解锁bl锁(自己在这里吃了大亏),由高版本降级到低版本刷机后需要重新解锁bl锁,解锁后还需要退出小米账号 青农软件开发工作室-----青少

Global site tag (gtag.js) - Google Analytics