Android ROOT System权限 设备管理器

申明:本文部分内容为网络相关资料整理,并结合本人实际工作总结而成。请引用或者转载注明出处,对于文章内容有疑问请留言。

一、Android ROOT

1.ROOT原理

ROOT也叫系统管理员用户,该账户拥有整个系统的最高权限,他可以访问和修改手机几乎所有的文件。只有ROOT才能具备最该级别的管理员权限,我们ROOT手机就是获取手机最高权限的过程。同时为了防止不良软件也取得ROOT用户的权限,当我们在ROOT手机的过程中会给系统安装一个叫做Superuser.apk的APP。当某些程序执行su指令时想去的系统最高权限时,Superuser就会自动启动,拦截该动作并作出询问,当用户认为该程序可以安全使用时,那就选择允许,程序就可以获取到ROOT权限。否则,可以禁止该程序继续取得最高权限。Root的过程其实就是把su文件放到/system/bin/ Superuser.apk 放到system/app下面,还需要设置/system/bin/su可以让任意用户可运行,有set uidset gid的权限。即要在android机器上运行命令:adb shell chmod 4755 /system/bin/su。而通常,厂商是不会允许我们随便这么去做的,我们就需要利用操作系统的各种漏洞,来完成这个过程

2.对于ROOT的思考(转自:http://www.zhihu.com/question/21074979

你想在Linux下获取root权限的时候就是执行sudo或者su,接下来系统会提示你输入root用户的密码,密码正确就获得root权限了。Android本身就不想让你获得Root权限,大部分手机出厂的时候根本就没有su这个程序。所以你想获得Android的root权限,第一步就是要把编译好的su文件拷贝到Android手机的/system/bin或者/system/xbin/目录下。我们先假设你可以把su放在xbin下,接下来你可以在Android手机的adb shell或者串口下输入su了。

Linux下su以后输入密码就可以root了,但Android里的su和Linux里的su是不一样的,Android里的su不是靠验证密码的,而是看你原来的权限是什么。意思就是如果你是root,那你可以通过su切换到别的用户,比如说shell,wifi,audio什么的。但如果你是root之外的其他用户,就不能切换回root了,会提示你permission denied。也就说用root运行su才有用,但我这个时候还没有root怎么办呢?这就涉及到另外个问题。

一般我们在Linux的console下输入 ls -l 会列出所有文件的权限。比如:-rwxr-xr-x,用过Linux的人都知道r代表该文件可读,w代表可写,x代表可执行,- 就代表没有该权限。第一个rwx代表文件所有者的权限,第二个rwx代表和所有者同组人的权限,第三个rwx代表其他用户对该文件的权限。但下面这个文件就比较特殊。

rws,它的执行权限标志位是一个s,s代表当任何一个用户执行该文件的时候都拥有文件所有者的权限,这文件的所有者是root,简单点说就是不管谁执行这个文件,他执行的时候都是以root身份执行的。也就说即使我不是root也有可能以root身份来执行程序,那么我就把一个所有者是root的su程序权限标志位置成-rwsr-xr-x,那么不管谁执行它,都是root身份执行,su就可以顺利执行成功了,执行成功之后我就是root身份了。

问题都清楚了,就是你需要把一个所有者是root的su拷贝到Android手机上,并且把su的权限标志位置成-rwsr-xr-x。能把这个事情搞定你就成功root了一个手机。
大概意思就是两行代码
cp /data/tmp/su /system/bin/ #copy su 到/system/分区
chown root:root su #su的所有者置成root
chmod 4775 /system/bin/su #把su置成-rwsr-xr-x
熟悉Android的同学都知道,执行上面的每一行代码都需要root权限才能成功。意思就是说,你只有有root权限的情况下才能执行上面两行代码,而这两行代码就是为了让你获得root权限的,这是一个逻辑闭环,那么如何打破这个逻辑闭环呢?一个办法就是找一个本身已经有root权限的进程来启动我上面的两行代码,那我这两行代码一启动就是root权限,就可以顺利执行了。但是已经有root权限的进程都是出厂时候就装到手机上的,代码写死了,你没法控制它执行你自己的代码啊。这个时候就需要你找漏洞了,比如用来破解Android2.3 root权限的zergRush漏洞就是利用一个拥有root权限的进程栈溢出漏洞。

为什么su一定要放到/system/bin/或者/system/xbin/ ?su不能放在data分区原因是因为data分区在mount时就指定了不能给可执行程序加s位。你在adb shell里执行mount就可以看到,或者看下面的截图。
下面有下划线的部分是原作者的解释:
/*
* 首先,你当然可以把su这个程序copy到/data/分区,但你adb push进去的时候,su有这个程序的所
* 有者肯定不是root,一般是shell什么的(记不清了,应该是和adbd这个进程的所有者一样),这个时
* 候即使你把它权限置为-rwsr-xr-x,哪你运行它的时候也是shell身份运行的,su会提示你输入密码
* 的。
* 第二我们root手机的目的是为了运行需要root权限的APP,比如goagent或者什么的。这些APP里代
* 码需要获得root的时候是这么写的:
* Process p = Runtime.getRuntime().exec("su");
* 也就是它们在代码里调用了一下su这个程序,哪可以写成下面这个样子吗?
* Process p = Runtime.getRuntime().exec("./data/tmp/su");
* 我没写过APP,不太清楚,估计是不行的。换句话说你必须把su放到环境变量PATH所有的目录
* 里,APP才能调用到它。如果你不想放到bin或者xbin下,你就必须给PATH增加一个目录。PATH是
* root权限才能修改的,你如果能修改PATH,说明你已经有root权限了,修改PATH就没必要了,还
* 不如直接放到bin下面。
*/

3.APP获取ROOT权限(转自:http://blog.csdn.net/jingwen3699/article/details/8175937)

A.要让Android应用获取ROOT权限,首先Android设备需要具有ROOT权限。下面代码为判断设备是否具有ROOT权限
<span style="font-size:18px;">  public static boolean runRootCommand(String command) {
  Process process = null;
  DataOutputStream os = null;
  try {
  process = Runtime.getRuntime().exec("su");
  os = new DataOutputStream(process.getOutputStream());
  os.writeBytes(command+"\n");\\os.writeBytes("echo \"Do I have root?\" >/system/sd/temporary.txt\n");
   os.writeBytes("exit\n");
  os.flush();
  process.waitFor();
  } catch (Exception e) {
  Log.d(TAG, "the device is not rooted, error message: " + e.getMessage());
  return false;
  } finally {
  try {
  if (os != null) {
  os.close();
  }
  if(process != null) {
  process.destroy();
  }
  } catch (Exception e) {
  e.printStackTrace();
  }
  }
  return true;
  }</span><pre name="code" class="java"><span style="font-size:18px;">
</span>
<span style="font-size:18px;">或者:
   /**
     * 判断当前手机是否有ROOT权限
     * @return
     */
    public boolean isRoot(){
        boolean bool = false;
        try{  
            if ((!new File("/system/bin/su").exists()) && (!new File("/system/xbin/su").exists())){
                bool = false;
            } else {
                bool = true;
            }
            Log.d(TAG, "bool = " + bool);
        } catch (Exception e) {

        } 
        return bool;
    }</span>

 
  B.在设备具有ROOT权限的前提下,执行su命令,这时会提示用户进行授权。 
 
<span style="font-size:18px;">import java.io.DataOutputStream;
import android.app.Activity;
import android.util.Log;
  /**
     * 应用程序运行命令获取 Root权限,设备必须已破解(获得ROOT权限)
     * @param command 命令:String apkRoot="chmod 777 "+getPackageCodePath(); RootCommand(apkRoot);
     * @return 应用程序是/否获取Root权限
     */
    public  boolean RootCommand(String command)
    {
        Process process = null;
        DataOutputStream os = null;
        try
        {
            process = Runtime.getRuntime().exec("su");
            os = new DataOutputStream(process.getOutputStream());
            os.writeBytes(command + "\n");
            os.writeBytes("exit\n");
            os.flush();
            process.waitFor();
        } catch (Exception e)
        {
            Log.d("*** DEBUG ***", "ROOT REE" + e.getMessage());
            return false;
        } finally
        {
            try
            {
                if (os != null)
                {
                    os.close();
                }
                process.destroy();
            } catch (Exception e)
            {
            }
        }
        Log.d("*** DEBUG ***", "Root SUC ");
        return true;
    }
}</span>
C.对上述代码进行调用
<span style="font-size:18px;">public class MainActivity extends Activity
{
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        String apkRoot="chmod 777 "+getPackageCodePath();</span>
<pre name="code" class="cpp"><span style="font-size:18px;">        //读、写、运行三项权限可以用数字表示,就是r=4,w=2,x=1。所以,上面的例子中的rw-r--r--用数字表示成644。
        //反过来说777就是rwxrwxrwx,意思是该登录用户(可以用命令id查看)、他所在的组和其他人都有最高权限。
        //getPackageCodePath():获取自身APK路径
        SystemManager.RootCommand(apkRoot);</span><pre name="code" class="java"><span style="font-size:18px;">}</span>
 
  
 
  

二、System权限

1.System权限介绍(目前没有深入研究,待以后补充)

在linux系统中是只有ROOT权限和普通权限的,Android包装了一套自己的权限体系,有platform、media、shared等的权限。ROOT权限是超级权限,如果得到ROOT权限则可以对系统进行任意操作。Android系统肯定不会让APK获得这种权限,但是提供了访问system目录的权限,即system权限,对应Android的权限体系为platform。 一般情况下system用户可以在系统中创建和删除文件,访问设备等等。但是有些情况下system权限还是不够的。比如:设置网卡IP地址,ifconfig命令是需要ROOT权限的。安卓系统并不像windows,system权限(uid1000)并不是最高权限,仅仅比普通用户拥有少量的特殊权限,比如安装软件无需弹窗。而系统中最高权限是root权限(uid0)。所以综上:ROOT权限高于System权限。

2.如何获取System权限(下述方法未亲自验证)

A.一般权限的添加
一般情况下,设定apk的权限,可在AndroidManifest.xml中添加android:sharedUserId="android.uid.xxx>
例如: 给apk添加system权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ... ... 
android:sharedUserId="android.uid.system">
同时还需要在对应的Android.mk中添加LOCAL_CERTIFICATE := platform这一项。即用系统的签名,通过这种方式只能使apk的权限升级到system级别,系统中要求权限才能访问的文件,apk还是不能访问。比如在android 的API中有提供 SystemClock.setCurrentTimeMillis()函数来修改系统时间,这个函数需要root权限或者运行与系统进程中才可以用。第一个方法简单点,不过需要在Android系统源码的环境下用make来编译,综上:
a. 在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。
b. 修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行
c. 使用mm命令来编译,生成的apk就有修改系统时间的权限了。

B.修改密钥

a.在代码中,AndroidManifest.xml文件的manifest项中,添加android:sharedUserId="android.uid.system"

b.编译程序,得到APK文件,如src.apk

c.将APK文件用压缩软件打开,删除META-INF目录里面的CERT.SF和CERT.RSA两个文件

d.给*.apk文件签名

这步需要在android源码中进行

cd build/tools/signapk

javac signapk.java(这里产生*.class)
mkdir test/com/android/signapk
cp *.class test/com/android/signapk
jar cvfm signapk.jar SignApk.mf -C test/ .(这里产生signapk.jar)

e.运行命令(其中signapk.jar platform.x509.pem platform.pk8这3个文件在源码的build目录下可以找到)

mkdir SignApk
步骤4中产生的signapk.jar拷贝到SignApk文件夹中
cp build/target/product/security/{platform.x509.pem,platform.pk8} SignApk

java -jar signapk.jar platform.x509.pem platform.pk8 src.apk dst.apk

f.dst.apk安装后就有system权限,就可以访问设备


C.直接把eclipse编出来的apk用系统的签名文件签名
a. 加入android:sharedUserId="android.uid.system"这个属性。
b. 使用eclipse编译出apk文件。
c. 使用目标系统的platform密钥来重新给apk文件签名。首先找到密钥文件,在我ndroid源码目录中的位置是"build/target/product/security",下面的platform.pk8和platform.x509.pem两个文件。然后用Android提供的Signapk工具来签名,signapk的源代码是在"build/tools/signapk"下,编译后在out/host/linux-x86/framework下,用法为java -jar signapk.jar  platform.x509.pem platform.pk8 input.apk output.apk"。加入android:sharedUserId="android.uid.system"这个属性。通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中。那么把程序的UID配成android.uid.system,也就是要让程序运行在系统进程中,这样就有权限来修改系统时间了。只是加入UID还不够,如果这时候安装APK的话发现无法安装,提示签名不符,原因是程序想要运行在系统进程中还要有目标系统的platform key,就是上面第二个方法提到的platform.pk8和platform.x509.pem两个文件。用这两个key签名后apk才真正可以放入系统进程中。第一个方法中加入LOCAL_CERTIFICATE := platform其实就是用这两个key来签名。

这也有一个问题,就是这样生成的程序只有在原始的Android系统或者是自己编译的系统中才可以用,因为这样的系统才可以拿到platform.pk8和platform.x509.pem两个文件。要是别家公司做的Android上连安装都安装不了。试试原始的Android中的key来签名,程序在模拟器上运行OK,不过放到G3上安装直接提示"Package ... has no signatures that match those in shared user android.uid.system",这样也是保护了系统的安全。

注:将APP安装到system/app目录下可以用于防卸载,以后会出一个Android防卸载专题。

三、设备管理器

1.关于设备管理器

Android2.2后提供了设备管理器,通过API可以对Android设备进行更多权限的管理和操作,如清除所有数据、更改屏幕解锁密码及规则、锁定屏幕、设置存储设备加密、停用相机、锁屏时禁用某些功能等等,而且相同功能的程序之间的权限互不冲突。

2.代码示例(转自:http://blog.csdn.net/etzmico/article/details/6848061)

第一步,注册一个广播类,用于监听权限的变化:

[java]  view plain  copy
  1. <receiver android:name=".deviceAdminReceiver" android:label="@string/app_name"  
  2.     android:description="@string/description" android:permission="android.permission.BIND_DEVICE_ADMIN">  
  3.   
  4.     <meta-data android:name="android.app.device_admin"  
  5.                 android:resource="@xml/device_admin" />  
  6.   
  7.     <intent-filter>  
  8.         <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />  
  9.     </intent-filter>  
  10.   
  11. </receiver>  

android:permission 表示此功能需要的权限。

android:name="android.app.action.DEVICE_ADMIN_ENABLED"表示此动作的跳转界面。

<meta-data android:name="android.app.device_admin"android:resource="@xml/device_admin" />表示这个应用可以管理的权限清单。

 

XML清单:

[java]  view plain  copy
  1. <span style="color:#000000;"><?xml version="1.0" encoding="utf-8"?>  
  2. <device-admin xmlns:android="<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>">  
  3.  <uses-policies>  
  4.    <limit-password />  
  5.         <watch-login />  
  6.         <reset-password />  
  7.         <force-lock />  
  8.         <wipe-data />  
  9.    </uses-policies>  
  10. </device-admin></span>  

 第二步,广播服务类的JAVA代码,重写一些必要的实现函数:

广播类deviceAdminReceiver 继承DeviceAdminReceiver

[java]  view plain  copy
  1. package cn.etzmico;  
  2.   
  3. import android.app.admin.DeviceAdminReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.content.SharedPreferences;  
  7. import android.widget.Toast;  
  8.   
  9. public class deviceAdminReceiver extends DeviceAdminReceiver {  
  10.   
  11.     /** 
  12.      * 获取设备存储的数值 
  13.      *  
  14.      * @param context 
  15.      * @return 
  16.      */  
  17.     public static SharedPreferences getDevicePreference(Context context) {  
  18.         return context.getSharedPreferences(  
  19.                 DeviceAdminReceiver.class.getName(), 0);  
  20.     }  
  21.   
  22.     // 密码的特点  
  23.     public static String PREF_PASSWORD_QUALITY = "password_quality";  
  24.     // 密码的长度  
  25.     public static String PREF_PASSWORD_LENGTH = "password_length";  
  26.   
  27.     public static String PREF_MAX_FAILED_PW = "max_failed_pw";  
  28.   
  29.     void showToast(Context context, CharSequence text) {  
  30.         Toast.makeText(context, text, Toast.LENGTH_SHORT).show();  
  31.     }  
  32.   
  33.     @Override  
  34.     public void onEnabled(Context context, Intent intent) {  
  35.         // TODO Auto-generated method stub  
  36.         showToast(context, "设备管理:可用");  
  37.     }  
  38.   
  39.     @Override  
  40.     public void onDisabled(Context context, Intent intent) {  
  41.         // TODO Auto-generated method stub  
  42.         showToast(context, "设备管理:不可用");  
  43.     }  
  44.   
  45.     @Override  
  46.     public CharSequence onDisableRequested(Context context, Intent intent) {  
  47.         // TODO Auto-generated method stub  
  48.         return "这是一个可选的消息,警告有关禁止用户的请求";  
  49.     }  
  50.   
  51.     @Override  
  52.     public void onPasswordChanged(Context context, Intent intent) {  
  53.         // TODO Auto-generated method stub  
  54.         showToast(context, "设备管理:密码己经改变");  
  55.     }  
  56.   
  57.     @Override  
  58.     public void onPasswordFailed(Context context, Intent intent) {  
  59.         // TODO Auto-generated method stub  
  60.         showToast(context, "设备管理:改变密码失败");  
  61.     }  
  62.   
  63.     @Override  
  64.     public void onPasswordSucceeded(Context context, Intent intent) {  
  65.         // TODO Auto-generated method stub  
  66.         showToast(context, "设备管理:改变密码成功");  
  67.     }  
  68.   
  69. }  

 第三步,也就是最关键的操作代码了


激活相关

[java]  view plain  copy
  1. Intent intent = new Intent(  
  2.         DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);  
  3. intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,  
  4.         mDeviceComponentName);  
  5. intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,  
  6.         "(自定义区域2)");  
  7. startActivityForResult(intent, RESULT_ENABLE);  

代码中的自定义区域2是可以输入一些自己想说的话,和广播类中的android:description="@string/description"一样。

这个是系统提供的两个自定义区域。

[java]  view plain  copy
  1. <string name="description">(可自定义区域1)</string>  

 锁屏相关

[java]  view plain  copy
  1. // ""中为设置的PIN密码,默认为123456  
  2. <span style="white-space:pre">              </span>mDPM.resetPassword("123456",  
  3. <span style="white-space:pre">                      </span>DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY);  
  4. <span style="white-space:pre">              </span>mDPM.lockNow();  

锁屏操作,由于是模拟器不能做到真正错屏,只能停到初始模拟器进来需要解锁的状态,屏幕不会变暗。

 

设置屏幕灯光变暗时间相关

[java]  view plain  copy
  1. long timeout = 1000L * Long.parseLong(et.getText().toString());  
  2. mDPM.setMaximumTimeToLock(mDeviceComponentName, timeout);  

et是定义的一个EditText,用于进行时间的输入

屏幕变暗最小时间为5秒

 

恢复出厂设置相关

[java]  view plain  copy
  1. mDPM.wipeData(0);  

恢复出厂设置只能通过真机去操作,模拟器操作后会停留在正在关机的dialog画面

恢复后数据会被清空,因此要做好备份操作。


注:激活设备管理器也可以用于防卸载,只是到Android5.0以上版本,可能会失灵。









  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值