吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 16530|回复: 18
收起左侧

[Android 原创] 记一次对flyme自带root的功能的逆向

  [复制链接]
wmsuper 发表于 2016-9-23 22:33
本帖最后由 wmsuper 于 2016-9-26 16:47 编辑

1.前言
flyme一般都自带开放系统权限的功能,输入用户密码后就可以执行root功能  root后的手机会把/system/xbin/lu 改为su 并赋予S位(讨论的是flyme5.1.8.0A 下同)
S60923-21420584.jpg

2.应用层分析
找到设置的apk,Settings.apk没混淆,很容易定位关键函数

[Java] 纯文本查看 复制代码
   private void handleRootPermissionPreferenceClick() {
        if(this.isRootPermissionOpened()) {
            this.startFragment(this, RootPermissionSettingsFragment.class.getName(), 2131430221, -1, null);
        }
        else if(this.isFlymeAccountLogined()) {
            this.startActivity(new Intent("com.meizu.action.ROOT"));  //执行一个intent
        }
    }

[Java] 纯文本查看 复制代码
    private boolean needShowRootPreference() {
        boolean v0 = true;
        if(MzUtils.isGuestUser(this.getActivity())) {
            v0 = false;
        }
        else if(!this.isRootPermissionOpened()) {
            if((this.isFlymeAccountLogined()) && (MzUtils.isPackageExistAndHasAction(this.getActivity(), "com.meizu.account", "com.meizu.action.ROOT"))) { //这里可以知道com.meizu.action.ROOT在MzAccount.apk有实现
                return v0;
            }

            v0 = false;
        }

        return v0;
    }





MzAccount.apk 的内容:
[XML] 纯文本查看 复制代码
//查看MzAccount.apk的AndroidManifest.xml搜索com.meizu.action.ROOT  定位到一个activity

        <activity android:label="@string/app_name" android:name="com.meizu.root.OpenSystemRightActivity" android:screenOrientation="portrait" android:theme="@style/AccountTheme.Gray">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="com.meizu.action.ROOT" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>


com.meizu.root.OpenSystemRightActivity的内容
[Java] 纯文本查看 复制代码
protected void onCreate(Bundle arg5) {
        super.onCreate(arg5);
        ap.a(((Activity)this), null, this.getResources().getString(2131296648), 0);
        this.setContentView(2130903077);
        this.c = this.findViewById(2131755221);
        this.c.setOnCheckedChangeListener(((CompoundButton$OnCheckedChangeListener)this));
        this.a = new SystemRootHelper(((Context)this));  //看名称很特别 到这个类里面看看
        this.e = this.findViewById(2131755244);
        this.e.setEnabled(false);
        this.e.setText(this.getString(2131296645));
        this.e.setVisibility(0);
        this.e.setOnClickListener(new a(this));
    }


SystemRootHelper的内容
    public boolean a(String arg5) {  //root操作
        boolean v0 = false;
        if(this.b.b(DeviceStateManagerEx.a("Root"), Base64.decode(arg5, 0)) == 0) {  //DeviceStateManagerEx.a("Root")映射一个数字 arg5是输入密码后服务器返回的值
            v0 = true;
        }

        return v0;
    }
    public boolean b(String arg5) {   //uroot操作  这个调用没有公开
        boolean v0 = false;
        if(this.b.b(DeviceStateManagerEx.a("Unroot"), Base64.decode(arg5, 0)) == 0) {
            v0 = true;
        }

        return v0;
    }

    public int b(int arg8, byte[] arg9) {
        int v0 = -1;
        try {
            Object v1_1 = a.a(this.b, "doCommand", new Class[]{Integer.TYPE, byte[].class}, new Object[]{Integer.valueOf(arg8), arg9});  //执行服务命令doCommand
            if(v1_1 == null) {
                return v0;
            }

            v0 = Integer.parseInt(v1_1.toString());
        }
        catch(Exception v1) {
            v1.printStackTrace();
        }

        return v0;
    }
    public DeviceStateManagerEx(Context arg2) {
        super();
        this.b = arg2.getSystemService("device_states"); //使用了device_states的服务
    }



找到系统服务  下面是services.jar的内容

[Java] 纯文本查看 复制代码
static {
        System.loadLibrary("android_servers");
    }
    private native int nativeDoCheckState(int arg1) {
    }

    private native int nativeDoCommand(int arg1, byte[] arg2) {   //这就是我们找的 实现在libandroid_servers.so 里面
    }

    private native int nativeDoGetInitNo(int arg1, byte[] arg2) {
    }

    private native int nativeLockRecoveryUnchecked() {
    }

    private native int nativeLockRecoveryUncheckedByHandle(int arg1) {
    }



为了使用IDA6.8的反编译 这里选用了lib里面的32bit的libandroid_servers.so
[C] 纯文本查看 复制代码
 
signed int __fastcall android::nativeDoCommandRoot(int *a1, int a2, int a3, int a4)
{
  int v4; // r8@1
  int v5; // r6@1
  int *v6; // r4@1
  int v7; // ST00_4@1
  int v8; // r10@1
  int v9; // r8@1
  signed int result; // r0@3
  int v11; // r0@6
  __int32 v12; // r0@8
  int v13; // ST00_4@8
  int v14; // r7@8
  char v15[1124]; // [sp+10h] [bp-64h]@1
  char v16; // [sp+474h] [bp+400h]@1
  int v17; // [sp+874h] [bp+800h]@1

  v4 = a4;
  v5 = a3;
  v6 = a1;
  v17 = _stack_chk_guard;
  j_j_memset(&v15[100], 0, 0x400u);
  j_j_memset(&v16, 0, 0x400u);
  j_j_memset(v15, 0, 0x64u);
  v7 = *v6;
  j_j___android_log_print(4, "DeviceStateService", "Native: nativeDoCommand env=%x,*env=%x, handle=%d.", v6);
  v8 = sub_1A984((int)v6);
  v9 = sub_10768(v6, v4);
  if ( v5 == 1 || v5 == 2 )
  {
    v11 = 0;
    do
    {
      *(_DWORD *)&v15[v11] = 1515870810;
      v11 += 4;
    }
    while ( v11 != 64 );
    *(_DWORD *)&v15[64] = j_j_j__ZN7android20get_platform_versionEv((android *)0x40);
    *(_DWORD *)&v15[68] = v5;
    j_j___memcpy_chk(&v15[100], v8, v9, 1024);
    j_j_memcpy(&v15[v9 + 100], v15, 0x64u);
    v12 = j_j_syscall(0xF0067, 16, 2, &v15[100], &v16, v5);  //关键系统函数调用 sysno=0xF0067
    v13 = *v6;
    v14 = v12 | (v12 >> 31);
    j_j___android_log_print(
      4,
      "DeviceStateService",
      "Native: nativeDoCommandRoot env=%x,*env=%x, handle=%d, rtx.enable:%d,result:%d.",
      v6);
    result = v14;
  }
  else
  {
    result = -2;
  }
  if ( v17 != _stack_chk_guard )
    j_j___stack_chk_fail(result);
  return result;
}


可以看到这个sysno很大 这里面肯定有猫腻

3.内核浅析
本人参考了以下链接提取了内核 不同的是这是x64的内核
http://www.blogbus.com/riusksk-logs/272240986.html
http://bbs.pediy.com/showthread.php?t=194803

ida6.8对64位的arm代码支持的不是很好(6.9可以完美支持),这里需要注意的是, 内核载入ida后由于不是完美支持,导致分析不出来。
$S[P7]2~5`57I1}~G226{X2.png
可载入时先处理器改成ARM ,再将基址改为ffffffc000080000,调节段的大小为64位(如下图),  全选后再次分析即可反汇编成功
ZE%KT0252JD{IK]Q%ON(GXI.png
2R4P~{2(OCE2~`)P(@J4{GI.png
按照链接中的方法提取符号,生成idc执行来给函数命名
_Z`@W)7[%C~WR2(4Q(JY4.png


定位到el0_svc
[Asm] 纯文本查看 复制代码
:FFFFFFC000084480 el0_svc                                 ; CODE XREF: ROM:FFFFFFC000083F68j
ROM:FFFFFFC000084480                 ADRP            X27, #0xFFFFFFC000DEB000
ROM:FFFFFFC000084484                 MOV             W26, W8
ROM:FFFFFFC000084488                 MOV             X25, #0x116 ;最大的sysno
ROM:FFFFFFC00008448C
ROM:FFFFFFC00008448C el0_svc_naked                           ; CODE XREF: ROM:FFFFFFC000084080j
ROM:FFFFFFC00008448C                 STP             X0, X26, [SP,#0x110]
ROM:FFFFFFC000084490                 MRS             X16, #0, c0, c2, #2
ROM:FFFFFFC000084494                 AND             X16, X16, #0xFFFFFFFFFFFFFFFE
ROM:FFFFFFC000084498                 MSR             #0, c0, c2, #2, X16
ROM:FFFFFFC00008449C                 ISB
ROM:FFFFFFC0000844A0                 MSR             #7, #8
ROM:FFFFFFC0000844A4                 MSR             #7, #2
ROM:FFFFFFC0000844A8                 MOV             X28, SP
ROM:FFFFFFC0000844AC                 AND             X28, X28, #0xFFFFFFFFFFFFC000
ROM:FFFFFFC0000844B0                 LDR             X16, [X28]
ROM:FFFFFFC0000844B4                 TST             X16, #0xF00
ROM:FFFFFFC0000844B8                 B.NE            __sys_trace
ROM:FFFFFFC0000844BC                 ADR             X30, ret_fast_syscall
ROM:FFFFFFC0000844C0                 CMP             X26, X25 ; switch 0 cases  ;比较大小
ROM:FFFFFFC0000844C4                 B.CS            ni_sys  ; jumptable 000044CC default case  ;超出范围调用ni_sys()
ROM:FFFFFFC0000844C8                 LDR             X16, [X27,X26,LSL#3]
ROM:FFFFFFC0000844CC                 BR              X16     ; switch jump


继续往下跟踪
[Asm] 纯文本查看 复制代码
:FFFFFFC00008FF14 compat_arm_syscall                      ; CODE XREF: ROM:FFFFFFC000089238p
ROM:FFFFFFC00008FF14
ROM:FFFFFFC00008FF14 var_20          = -0x20
ROM:FFFFFFC00008FF14 var_10          = -0x10
ROM:FFFFFFC00008FF14 var_s0          =  0
ROM:FFFFFFC00008FF14
ROM:FFFFFFC00008FF14                 STP             X29, X30, [SP,#-0x10+var_20]!
ROM:FFFFFFC00008FF18                 MOV             X3, X0
ROM:FFFFFFC00008FF1C                 MOV             W0, #0x67
ROM:FFFFFFC00008FF20                 MOV             X29, SP
ROM:FFFFFFC00008FF24                 STP             X19, X20, [SP,#0x20+var_10]
ROM:FFFFFFC00008FF28                 STP             X21, X22, [SP,#0x20+var_s0]
ROM:FFFFFFC00008FF2C                 MOVK            W0, #0xF,LSL#16
ROM:FFFFFFC00008FF30                 LDR             X1, [X3,#0x38]
ROM:FFFFFFC00008FF34                 CMP             W1, W0    ;sysno是否为0xf0067 是的话就调用do_private_entry()
ROM:FFFFFFC00008FF38                 B.NE            loc_FFFFFFC00008FF64
ROM:FFFFFFC00008FF3C                 LDR             W0, [X3]
ROM:FFFFFFC00008FF40                 LDR             W1, [X3,#8]
ROM:FFFFFFC00008FF44                 LDR             X2, [X3,#0x10]
ROM:FFFFFFC00008FF48                 LDR             X3, [X3,#0x18]
ROM:FFFFFFC00008FF4C                 BL              do_private_entry
ROM:FFFFFFC00008FF50                 SBFM            X0, X0, #0, #0x1F
ROM:FFFFFFC00008FF54
ROM:FFFFFFC00008FF54 loc_FFFFFFC00008FF54                    ; CODE XREF: compat_arm_syscall+E0j
ROM:FFFFFFC00008FF54                                         ; compat_arm_syscall+E8j ...
ROM:FFFFFFC00008FF54                 LDP             X19, X20, [SP,#0x20+var_10]
ROM:FFFFFFC00008FF58                 LDP             X21, X22, [SP,#0x20+var_s0]
ROM:FFFFFFC00008FF5C                 LDP             X29, X30, [SP+0x20+var_20],#0x30
ROM:FFFFFFC00008FF60                 RET

接下来是验证数据内容,并对mmc进行写操作
4.结语
由于本人能力有限和内核动态调试十分困难,只能找到大概的流程,但是内核是如何更改lu为su 并赋予s位的过程还不是十分清楚,欢迎大牛一起分析。


免费评分

参与人数 6威望 +1 吾爱币 +1 热心值 +6 收起 理由
i-ii + 1 + 1 谢谢@Thanks!
lawlier + 1 用心讨论,共获提升!
灌汤包 + 1 我很赞同!
昧光 + 1 鼓励转贴优秀软件安全工具和文档!
yyhf + 1 没有看到跟踪 do_private_entry的过程,猜测是厂商自行添加了一个系统调用.
Hmily + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

月下孤影01 发表于 2016-11-10 06:00 来自手机
支持下楼主,因为本人用的就是魅族pro5,去手机店的时候随便问问过老板,几个都说无法刷机的,好像貌似这个魅族的root权限与Flyme锁做的好像相比同类稍微牛一点……
qtfreet00 发表于 2016-10-7 17:58
IT_K 发表于 2016-10-7 19:06
yege0201 发表于 2016-10-7 21:38
无论结果如何都要支持LZ
头像被屏蔽
xiumao 发表于 2016-10-8 12:43 来自手机
提示: 作者被禁止或删除 内容自动屏蔽
Loopher 发表于 2016-10-8 19:50
我也有点好奇,楼主在哪里弄的这个东东~不明觉厉
Kali-J 发表于 2016-10-8 23:03
毕设就是要做安卓内核的动态动态调试分析的。一起探讨
__star__ 发表于 2016-10-11 10:42
文章思路很不错,值得进一步挖掘su怎么利用
dxdeng 发表于 2016-10-11 14:30
学习了,不过好多不懂
freebuf 发表于 2016-10-15 19:05
支持 还在学习中。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-14 10:22

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表