Android系统 adb shell push/pull 禁止特定文件

简介: Android系统 adb shell push/pull 禁止特定文件

在Android系统中,adb shell是一个强大的工具,可以让我们在电脑上通过命令行操作Android设备上的文件和程序。其中,push和pull命令可以实现电脑和手机之间的文件传输,非常方便。但是,有时候(客制化需求或者防止某些内容被盗取)我们可能不希望某些文件被随意传输,比如系统敏感文件或者应用白名单文件。那么,我们该如何实现adb shell push/pull的禁止特定文件功能呢?

android11源码 push/pull的流程

为了解决这个问题,需要先了解android11源码system/core/adb/daemon/file_sync_service.cpp中push/pull命令的实现流程。我们以adb pull为例,简单介绍一下主要步骤:

  1. 在电脑端,adb客户端程序接收到用户输入的adb pull命令后,会解析出要传输的源文件路径和目标文件路径,并向adb服务端程序发送一个SYNC服务请求。
  2. 在Android端,adb服务端程序收到SYNC服务请求后,会启动一个file_sync_service线程来处理文件传输相关的操作。
  3. file_sync_service线程会从adb客户端程序读取一个SyncRequest结构体,其中包含了请求的ID和路径长度。然后根据路径长度再读取相应的路径字符串。
  4. file_sync_service线程会根据请求的ID判断是push还是pull操作,并调用相应的函数来处理。对于pull操作,会调用do_recv_v1或do_recv_v2函数(根据协议版本不同而不同, 测试发现是do_recv_v1)。
static bool handle_sync_command(int fd, std::vector<char>& buffer) {
    D("sync: waiting for request");
    SyncRequest request;
    if (!ReadFdExactly(fd, &request, sizeof(request))) {
        SendSyncFail(fd, "command read failure");
        return false;
    }
    size_t path_length = request.path_length;
    if (path_length > 1024) {
        SendSyncFail(fd, "path too long11");
        return false;
    }
    char name[1025];
    if (!ReadFdExactly(fd, name, path_length)) {
        SendSyncFail(fd, "filename read failure");
        return false;
    }
    name[path_length] = 0;
    std::string id_name = sync_id_to_name(request.id);
    D("sync: %s('%s')", id_name.c_str(), name);
    // 在处理每个命令之前,检查是否禁止了pull或push操作
    std::string path(name);
    switch (request.id) {
    .............
  1. do_recv_v1或do_recv_v2函数会根据路径字符串打开手机上对应的文件,并将文件内容按照一定的格式和大小分块发送给adb客户端程序。
  2. 在电脑端,adb客户端程序收到file_sync_service线程发送的文件内容后,会根据目标文件路径创建或覆盖相应的文件,并将收到的内容写入文件中。
  3. 当file_sync_service线程发送完所有的文件内容后,会发送一个ID_DONE消息表示传输结束。adb客户端程序收到ID_DONE消息后,会关闭目标文件,并显示传输结果。

isOperationAllowed函数的作用

在android11源码中,有一个新添加的函数isOperationAllowed,它的作用是判断是否允许进行push或pull操作。它的原型如下:

// 通过属性判断是否允许操作
static bool isOperationAllowed(const char* filePath, const char* operationProperty);
static const char* appWhitelist[] = {
    "system/bin/candump",
    "system/bin/cansend",
    // Add more paths here as needed
};
// 通过属性判断是否允许操作
static bool isOperationAllowed(const char* filePath, const char* operationProperty) {
    char operationDisabledValue[PROP_VALUE_MAX];
    __system_property_get(operationProperty, operationDisabledValue);
    LOG(INFO) << operationProperty << "-filePath(" << operationDisabledValue << "," << filePath << ")";
    if (strcmp(operationDisabledValue, "1") == 0){
        LOG(INFO) << operationProperty << " = true!!!!!";
        for (const char* path : appWhitelist) {
            if (strstr(filePath, path) != nullptr){
                return false;
            }
        }
        LOG(INFO) << operationProperty << "22";
    } else {
        LOG(INFO) << operationProperty << "33";
    }
    return true;
}

它接受两个参数:filePath是要传输的文件路径,operationProperty是一个系统属性名,表示是否禁止某种操作。例如,persist.adb.push_disabled表示是否禁止push操作,persist.adb.pull_disabled表示是否禁止pull操作。

这个函数的实现逻辑如下:

  1. 从系统属性中读取operationProperty对应的值,如果值为"1",表示禁止该操作;如果值为其他或者没有设置该属性,则表示允许该操作。
  2. 如果禁止该操作,则遍历一个预定义的应用白名单数组appWhitelist,检查filePath是否包含数组中的任何一个路径。如果包含,则表示该文件属于白名单中的应用,允许该操作;如果不包含,则表示该文件不属于白名单中的应用,禁止该操作。
  3. 返回最终的判断结果,true表示允许,false表示禁止。
// 在处理每个命令之前,检查是否禁止了pull或push操作
    std::string path(name);
    switch (request.id) {
        case ID_LSTAT_V1:
            if (!do_lstat_v1(fd, name)) return false;
            break;
        case ID_LSTAT_V2:
        case ID_STAT_V2:
            if (!do_stat_v2(fd, request.id, name)) return false;
            break;
        case ID_LIST_V1:
            if (!do_list_v1(fd, name)) return false;
            break;
        case ID_LIST_V2:
            if (!do_list_v2(fd, name)) return false;
            break;
        case ID_SEND_V1:
            // 检查是否允许push操作
            if (!isOperationAllowed(name, "persist.adb.push_disabled")){
                LOG(ERROR) << "forbid_push_file";
                return false;
            }
            if (!do_send_v1(fd, name, buffer)) return false;
            break;
        case ID_SEND_V2:
            // 检查是否允许push操作
            if (!isOperationAllowed(name, "persist.adb.push_disabled")){
                LOG(ERROR) << "forbid_push_file";
                return false;
            }
            if (!do_send_v2(fd, name, buffer)) return false;
            break;
        case ID_RECV_V1:
            // 检查是否允许pull操作
            if (!isOperationAllowed(name, "persist.adb.pull_disabled")){
                LOG(ERROR) << "forbid_pull_file";
                return false;
            }
            if (!do_recv_v1(fd, name, buffer)) return false;
            break;
        case ID_RECV_V2:
            // 检查是否允许pull操作
            if (!isOperationAllowed(name, "persist.adb.pull_disabled")){
                LOG(ERROR) << "forbid_pull_file";
                return false;
            }
            if (!do_recv_v2(fd, name, buffer)) return false;
            break;
        case ID_QUIT:
            return false;
        default:
            SendSyncFail(fd, StringPrintf("unknown command %08x", request.id));
            return false;
    }
    return true;
}

这个函数被调用的地方有两个:一个是在handle_send_file函数中,用于判断是否允许push操作;另一个是在do_recv_v1或do_recv_v2函数中,用于判断是否允许pull操作。如果判断结果为false,则会向adb客户端程序发送一个ID_FAIL消息,并终止传输。

总结

通过上面的分析,android11源码中实现了adb shell push/pull禁止特定文件的功能,主要是通过新增一个isOperationAllowed函数来判断是否允许传输某个文件。这个函数的优点是可以通过设置系统属性来动态控制是否禁止push或pull操作,也可以通过修改应用白名单数组来指定哪些应用的文件可以传输。这样可以提高系统的安全性和灵活性。

希望我的博客文章对你有所帮助。如果你有任何问题或建议,请随时与我联系。谢谢!

相关实践学习
使用CLup和iSCSI共享盘快速体验PolarDB for PostgtreSQL
在Clup云管控平台中快速体验创建与管理在iSCSI共享盘上的PolarDB for PostgtreSQL。
AnalyticDB PostgreSQL 企业智能数据中台:一站式管理数据服务资产
企业在数据仓库之上可构建丰富的数据服务用以支持数据应用及业务场景;ADB PG推出全新企业智能数据平台,用以帮助用户一站式的管理企业数据服务资产,包括创建, 管理,探索, 监控等; 助力企业在现有平台之上快速构建起数据服务资产体系
相关文章
|
1月前
|
Shell Android开发
ADB更改Android设备屏幕显示方向
ADB更改Android设备屏幕显示方向
48 5
|
18天前
|
Shell 开发工具 Android开发
|
1月前
|
Java Android开发
Android 对adb命令的拦截
Android 对adb命令的拦截
27 2
|
1月前
|
Shell Android开发
Android Activity重写dump方法实现通过adb调试代码
Android Activity重写dump方法实现通过adb调试代码
24 0
|
3天前
|
安全 Java Android开发
安卓开发中的新趋势:Kotlin与Jetpack的完美结合
【6月更文挑战第20天】在不断进化的移动应用开发领域,Android平台以其开放性和灵活性赢得了全球开发者的青睐。然而,随着技术的迭代,传统Java语言在Android开发中逐渐显露出局限性。Kotlin,一种现代的静态类型编程语言,以其简洁、安全和高效的特性成为了Android开发中的新宠。同时,Jetpack作为一套支持库、工具和指南,旨在帮助开发者更快地打造优秀的Android应用。本文将探讨Kotlin与Jetpack如何共同推动Android开发进入一个新的时代,以及这对开发者意味着什么。
|
4天前
|
存储 Java 数据库连接
Android Java开发异步
【6月更文挑战第15天】
|
2天前
|
Java 开发工具 Android开发
安卓与iOS开发差异解析
【6月更文挑战第21天】本文旨在深入探讨安卓和iOS两大移动操作系统在应用开发过程中的主要差异。通过对比分析,揭示各自的设计哲学、编程语言选择、用户界面构建、性能优化策略以及发布流程的异同。文章将提供开发者视角下的实用信息,帮助他们更好地理解各自平台的特点和挑战,从而做出更明智的开发决策。
|
3天前
|
Java 开发工具 Android开发
探索安卓与iOS开发的核心差异
【6月更文挑战第20天】在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文将深入探讨这两大操作系统在开发过程中的主要区别,包括编程语言、开发工具、用户界面设计哲学、系统架构以及市场分布等方面。通过对这些关键差异的分析,旨在为开发者提供一份实用的指南,帮助他们在面对项目决策时,能够更加明智地选择合适的平台,并针对特定平台优化他们的应用。
|
3天前
|
开发工具 Android开发 iOS开发
探索安卓与iOS开发的差异:从工具到用户体验
【6月更文挑战第20天】在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文将深入探讨这两个操作系统在开发环境、编程语言、用户界面设计以及性能优化等方面的关键差异。我们将通过比较分析,揭示各自平台的独特优势和面临的挑战,为开发者提供决策参考,并为最终用户提供更深层次的用户体验洞察。