IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 系统服务的实际应用与安全风险 -> 正文阅读

[移动开发]Android 系统服务的实际应用与安全风险

Android 系统服务(service),不同于应用层的 Service(Android 四大组件之一),系统 service 处于 Android 系统的 Framwrok 层。提起系统 service,就不得不说 Service Manager
在这里插入图片描述
由知乎大佬 Gityuan 提供的图片可以知道,所有的系统 service 都是由 Service Manager 管理的,并且会在 Service Manger 注册。当我们自己的 APP 想使用系统 service,可以通过 Service Manger 获取服务并使用。

adb 调用 service

查看 Android 包含的所有系统服务

adb shell service list

一个或者多个 service 在 AOSP 源码中对应一个 .aidl 后缀名结尾的接口文件

例如打印服务,对应的源码应该是 IPrintManager.aidl

# print: [android.print.IPrintManager]
core/java/android/print/IPrintManager.aidl

aidl 接口包含 service 提供的多个函数

在这里插入图片描述

1.调用函数

若要调用 cancelPrintJob 函数,直接使用如下命令,4 代表第 4 个函数。

adb shell service call print 4

2.传递参数

i32 表示 int 类型的整数(boolean 也可以使用 0/1),s16 表示字符串

adb shell service call print 4 i32 1 i32 22 i32 333

app 调用 service

ServiceManager 作为 Android 的核心服务之一,所有的系统 service 都必须在此注册,ServiceManager 理所当然的提供了接口,让我们可以轻松获取系统所有的 service

获取系统所有服务

    /**
     * 利用反射,获取系统所有服务
     * @return 系统所有服务
     */
    public String[] listService(){
        String sm[] = {};
        try{
            sm = (String []) Class.forName("android.os.ServiceManager").getMethod("listServices").invoke(null);
            Log.d(TAG, String.valueOf(sm.length));
            for(int i = 0; i < sm.length; i++){
                Log.d(TAG, sm[i]);
            }
        }catch (Exception e){
            e.printStackTrace();
            Log.e(TAG, e.toString());
        }
        return sm;
    }

/* result */
2021-07-23 09:17:28.726 24062-24062/com.lys.androidservice D/test: media_router
2021-07-23 09:17:28.726 24062-24062/com.lys.androidservice D/test: media_resource_monitor
2021-07-23 09:17:28.726 24062-24062/com.lys.androidservice D/test: media_session
2021-07-23 09:17:28.726 24062-24062/com.lys.androidservice D/test: restrictions
2021-07-23 09:17:28.726 24062-24062/com.lys.androidservice D/test: companiondevice
2021-07-23 09:17:28.726 24062-24062/com.lys.androidservice D/test: print

获取 IBinder 接口对象

IBinder 是安卓开发中的一个接口。这个接口是能进行远程操作对象的一个基本接口。定义了为在提供进程间和跨进程间的调用时提供高性能的轻量级远程调用的核心部分。该接口描述了与远程对象进行交互的抽象协议。

    /**
     * @param serviceName 服务名
     * @return 服务的 IBinder 接口
     */
    public IBinder getIBinder(String serviceName){
        IBinder iBinder = null;
        try{
            iBinder = (IBinder) Class.forName("android.os.ServiceManager").getMethod("getService", String.class).invoke(null, serviceName);
            Log.d(TAG, iBinder.getInterfaceDescriptor());
        }catch (Exception e){
            e.printStackTrace();
            Log.e(TAG, e.toString());
        }
        return iBinder;
    }

/* result */
2021-07-23 09:17:28.729 24062-24062/com.lys.androidservice D/test: android.print.IPrintManager

通过 Binder 获取接口名
在这里插入图片描述

方法一:getInterfaceDescriptor(),如上图所示

方法二:IBinder 的主要 API:transact()

通过 transact() 发送的数据是 Parcel,Parcel 是一种一般的缓冲区,除了有数据外还带有一些描述它内容的元数据。元数据用于管理 IBinder 对象的引用,这样就能在缓冲区从一个进程移动到另一个进程时保存这些引用。这样就保证了当一个 IBinder 被写入到 Parcel 并发送到另一个进程中,如果另一个进程把同一个IBinder 的引用回发到原来的进程,那么这个原来的进程就能接收到发出的那个 IBinder的引用。这种机制使IBinder和Binder像唯一标志符那样在进程间管理。

	/**
     * @param serviceHandle 服务的IBinder接口
     * @return 接口名称
     */
    public String getInterfaceName(IBinder serviceHandle){
        Parcel data = Parcel.obtain();
        Parcel replay = Parcel.obtain();
        try {
            serviceHandle.transact(IBinder.INTERFACE_TRANSACTION, data, replay, 0);
        }catch (Exception e){
            e.printStackTrace();
            Log.e(TAG, e.toString());
        }
        String interfaceName = replay.readString();
        Log.d(TAG, interfaceName);
        data.recycle();
        replay.recycle();
        return interfaceName;
    }

通过 Binder 调用系统服务函数,并传递参数

	/**
     * @param name 服务名称
     * @param code 服务接口的函数下标
     */
    public void callServFunc(String name, int code){
        Parcel data = Parcel.obtain();
        Parcel replay = Parcel.obtain();
        IBinder iBinder = getIBinder(name);
        String in = getInterfaceName(iBinder);

        data.writeInterfaceToken(in);
        data.writeInt(1);
        data.writeInt(22);
        data.writeInt(333);
        Log.d(TAG, data.toString());
        
        try{
            iBinder.transact(code, data, replay, 0);
        }catch (Exception e){
            e.printStackTrace();
            Log.e(TAG, e.toString());
        }

        Log.d(TAG, replay.readString());
        data.recycle();
        replay.recycle();
    }

讨论与风险

AOSP 本身提供的系统服务经过多年测试,基本上已经没有什么大问题。但是各个厂商订制的 ROM 往往会包含自己的服务,这些服务很有可能会存在问题,比如传入的参数没有进行校验,导致空指针、数组越界等问题。

相应的,我们有一下两种方式进行 fuzzing

  • 通过 adb,遍历所有服务,并调用服务传参
  • 通过 app,由 Service Manager 获取所有服务,并传入参数

上述两种方式,从编程角度来说,并不困难,但是最大的问题在于如何获取 service 提供的入参个数和类型。一方面,可以通过 Android 编译环境,编写用户空间的二进制,获取所有 service 的详细信息;另外一方面,是否可以编写 app,通过反射的方式获取 service 提供的参数类型。这些都是后续有关安全工作需要考虑的问题。

本文只是简单的呈现 Android 系统服务的作用,后续如果有较好的 fuzzing 工具,如果开发完成,笔者会进行讲解。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-15 15:43:16  更:2021-08-15 15:43:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 11:07:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码