Android系统run-as命令原理(权限访问)

1.功能

以root身份运行命令,可以在未root的情况下查看某个(debug模式的)应用的内部信息(沙盒文件夹)

2.介绍

非root手机run-as命令获取debug版本apk里面的数据(shared_prefs文件、lib下面的so、数据库文件)

在没有root过的手机中,用户权限是无法查看很多信息的,包括各个应用的沙盒

而run-as就向开发者提供了未root情况下访问沙盒信息的权限

执行run-as + 包名,就可以直接以root权限进入该应用的沙盒中查看包括数据库、xml、各种信息文件

adb shell
run-as package-name

图片

Android7.1.2(Nexus5手机已Root)

图片

图片

Android10(Redmi 9A手机未Root)

图片

ls -al

图片

3.条件

应用需为debug模式,即AndroidManifest.xml文件中,android:debugable需要为true

android:debuggable="true"

如果签名了,并且指定设置了android:debuggable="false",将无法使用该命令

android:debuggable="false"

图片

4.原理

Linux系统下除了rwx三个基本权限以外,还有特殊的s(setuid)权限和g(setgid)权限

s权限可以使得低权限用户以该程序的所有者的权限去执行命令

在某些情况下可以提供极大的方便,例如普通用户想要修改密码或者一些关键程序,就可以通过root用户设定好的特定程序来在规则内修改本无法修改的文件

但是s权限也具有相当程度的危险性,当该程序存在漏洞,最坏的情况下具备任意代码执行的能力时,则说可以利用其提权,即普通用户可以通过它得到完全的root权限

回到正题

run-as程序正是通过s权限使得普通用户可以在满足条件(应用为debug模式时、操作目录仅在应用沙盒下)时具备root权限

5.延伸

除了提权以外,s权限还可以用来降权

root用户可以更改文件的拥有者,从而可以通过s权限任意更改程序执行时的权限

在安卓系统中,所有进程都是由zygote进程fork出来的,如果不降权的话则所有进程都与父进程相同、具备了root权限,这显然是不安全的。因此zygote通过forkAndSpecializeCommon函数来进行降权处理,使得子进程具备可控的权限

6.补充

/data/data/package/lib目录是可以直接访问的,adb shell后虽然无法读取/data目录,但是可以直接访问这个目录下的文件,可以通过run-as命令看得出其权限与其他目录的权限是不同的,为system权限,这为多apk共享so提供了便利。

关于共享数据也可以研究/data/data/package/files,使用openFileOutput的第二个参数来指定访问权限

函数声明:

FileOutputStream openFileOutput (String name, int mode)

作用:

可以方便地在手机中创建文件,并返回文件输出流,用于对文件做写入操作。

openFileOutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。创建的文件保存在/data/data/<package name>/files目录。

openFileOutput()方法的第二参数用于指定操作模式,有四种模式,分别为:

Context.MODE_PRIVATE = 0
Context.MODE_APPEND = 32768
Context.MODE_WORLD_READABLE = 1
Context.MODE_WORLD_WRITEABLE = 2

Context.MODE_PRIVATE
为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中,可以使用Context.MODE_APPEND。

Context.MODE_APPEND
模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。

Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE
用来控制其他应用是否有权限读写该文件。

MODE_WORLD_READABLE
表示当前文件可以被其他应用读取;

MODE_WORLD_WRITEABLE
表示当前文件可以被其他应用写入。

如果希望文件被其他应用读和写,可以传入:

openFileOutput("itcast.txt", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);

Android有一套自己的安全模型,当应用程序(.apk)在安装时系统就会分配给他一个userid,当该应用要去访问其他资源比如文件的时候,就需要userid匹配默认情况下,任何应用创建的文件,sharedpreferences,数据库都应该是私有的(位于/data/data/<package name>/files),其他程序无法访问。除非在创建时指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE ,只有这样其他程序才能正确访问。

(1).判读文件是否存在

public boolean existsFile(String fileName){
     String path = this.getFilesDir().getPath()+"//";
  File file = new File(path+fileName);
  if(file.exists()){
    return true;
  }
  return false;
}

(2).读取文件

public String readFile(String fileName) throws IOException{
  FileInputStream fis = context.openFileInput(fileName);
  int len = fis.available();
  byte []buffer = new byte[len];
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  while((fis.read(buffer))!=-1){
    baos.write(buffer);
  }
  byte []data = baos.toByteArray();
  baos.close();
  fis.close();
  return new String(data);
}

public void load() {
    try {
        FileInputStream inStream=this.openFileInput(“a.txt”);
        ByteArrayOutputStream stream=new ByteArrayOutputStream();
        byte[] buffer=new byte[1024];
        int length=-1;
        while((length=inStream.read(buffer))!=-1)   {
            stream.write(buffer,0,length);
        }
        stream.close();
        inStream.close();
        text.setText(stream.toString());
        Toast.makeText(MyActivity.this,”Loaded”,Toast.LENGTH_LONG).show();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    catch (IOException e){
        return ;
    }
}

返回文件输入流,用于对文件的读操作
FileInputStream openFileInput (String name)

对于私有文件只能被创建该文件的应用访问,如果希望文件能被其他应用读和写,可以在创建文件时,指定Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE权限。
Activity还提供了getCacheDir()和getFilesDir()方法:
getCacheDir()方法用于获取/data/data/<package name>/cache目录
getFilesDir()方法用于获取/data/data/<package name>/files目录

(3).把文件放入SD卡

使用Activity的openFileOutput()方法保存文件,文件是存放在手机空间上,一般手机的存储空间不是很大,存放些小文件还行,如果要存放像视频这样的大文件,是不可行的。对于像视频这样的大文件,可以把它存放在SDCard.

在程序中访问SDCard,你需要申请访问SDCard的权限。在AndroidManifest.xml中加入访问SDCard的权限,如下所示:

<!– 在SDCard中创建与删除文件权限 –>
<uses-permission android:name=”android.permission.MOUNT_UNMOUNT_FILESYSTEMS”/>

<!– 往SDCard写入数据权限 –>
<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>

访问SDCard必须在AndroidManifest.xml中加入访问SDCard的权限,要往SDCard存放文件,程序必须先判断手机是否装有SDCard,并且可以进行读写。

if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
  File sdCardDir = Environment.getExternalStorageDirectory();//获取SDCard目录
  File saveFile = new File(sdCardDir, “a.txt”);
  FileOutputStream outStream = new FileOutputStream(saveFile);
  outStream.write(“test”.getBytes());
  outStream.close();
}

Environment.getExternalStorageState()方法用于获取SDCard的状态,如果手机装有SDCard,并且可以进行读写,那么方法返回的状态等于Environment.MEDIA_MOUNTED。
Environment.getExternalStorageDirectory()方法用于获取SDCard的目录,当然要获取SDCard的目录,你也可以这样写:
File sdCardDir = new File(“/sdcard”); //获取SDCard目录
File saveFile = new File(sdCardDir, “itcast.txt”); 

//上面两句代码可以合成一句:
File saveFile = new File(“/sdcard/a.txt”);
FileOutputStream outStream = new FileOutputStream(saveFile);
outStream.write(“test”.getBytes());
outStream.close();

(4).保存文件

public void saveFile(String fileName, String str) throws IOException{
  FileOutputStream fos = context.openFileOutput(fileName, Activity.MODE_APPEND);
  byte[]bytes=str.getBytes();
  fos.write(bytes);
  fos.flush();
  fos.close();
}

原文链接

​Android系统run-as命令原理(权限访问)

如果对文章感兴趣,可以扫一扫微信二维码关注作者的微信公众号,后续会推送更多干货文章,感谢您的支持。

图片

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哆啦安全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值