android免root运行adb高级权限命令,例如修改手机设置等(转)

14 篇文章 0 订阅

免Root实现静默安装和点击任意位置

0 前言

最近有了个需求:免 root 实现任意位置点击和静默安装。这个做过的小伙伴应该都知道正常情况下是不可能实现的。无障碍只能实现对已知控件的点击,并不能指定坐标。但是确实有人另辟蹊径做出来了,譬如做游戏手柄的飞智,他们是用一个激活器,手机开 usb 调试,然后插在激活器上并授权,飞智游戏厅就被「激活」了,然后可以实现任意位置点击。如果不了解的可以去他们官网了解下,在这里不多赘述了。无独有偶,黑域也使用了类似的手段,也可以用电脑的usb调试激活。我们知道,任意位置坐标xy点击是可以在 pc 上通过 shell 命令「input tap x y」来实现的,也不需要 root 权限。但是在应用内通过「Runtime.getRuntime().exec」执行这个 shell 命令却提示「permission denied」也就是权限不足。但是飞智或者黑域却好像使用了某种魔法,提升了自己的权限,那么问题来了:如何用 usb 调试给 app 提权?

1 原理揭晓

「如何用 usb 调试给 app 提权」这个问题乍一看确实没问题,但是知乎有个回答是「先问是不是,再问为什么」我觉得说的很好。我被这个问题给困扰了很久,最后发现我问错了。先放出结论「并不是给 app 提权,而是运行了一个有 shell 权限的新程序」

刚才的问题先放一边,我来问大家个新问题,怎样让 app 获取 root 权限?这个问题答案已经有不少了,网上一查便可知其实是获取「Runtime.getRuntime().exec」的流,在里面用su提权,然后就可以执行需要 root 权限的 shell 命令,比如挂载 system 读写,访问 data 分区,用 shell 命令静默安装,等等。话说回来,是不是和我们今天的主题有点像,如何使 app 获取 shell 权限?嗯,其实差不多,思路也类似,因为本来 root 啦, shell 啦,根本就不是 Android 应用层的名词呀,他们本来就是 Linux 里的名词,只不过是 Android 框架运行于 Linux 层之上, 我们可以调用 shell 命令,也可以在shell 里调用 su 来使shell 获取 root 权限,来绕过 Android 层做一些被限制的事。然而在 app 里调用 shell 命令,其进程还是 app 的,权限还是受限。所以就不能在 app 里运行 shell 命令,那么问题来了,不在 app 里运行在哪运行?答案是在 pc 上运行。当然不可能是 pc 一直连着手机啦,而是 pc 上在 shell 里运行独立的一个 java 程序,这个程序因为是在 shell 里启动的,所以具有 shell 权限。我们想一下,这个 Java 程序在 shell 里运行,建立本地 socket 服务器,和 app 通信,远程执行 app 下发的代码。因为即使拔掉了数据线,这个 Java 程序也不会停止,只要不重启他就一直活着,执行我们的命令,这不就是看起来 app 有了 shell 权限?现在真相大白,飞智和黑域用 usb 调试激活的那一下,其实是启动那个 Java 程序,飞智是执行模拟按键,黑域是监听系统事件,你想干啥就任你开发了。「注:黑域和飞智由于进程管理的需要,其实是先用 shell 启动一个 so ,然后再用 so 做跳板启动 Java 程序,而且 so 也充当守护进程,当 Java 意外停止可以重新启动,读着有兴趣可以自行研究,在此不多做说明」

2 好耶!是 app_process

那么如何具体用 shell 运行 Java 程序呢?肯定不是「java xxx.jar」啦,Android 能运行的格式是 dex 。没错,就是apk 里那个 dex 。然后我们可以通过「app_process」开启动 Java 。app_process 的参数如下

app_process [vm-options] cmd-dir [options] start-class-name [main-options]

这个诡异又可怕的东西是没有 -help 的。我们要么看源码,要么看别人分析好的。本人水平有限,这里选择看别人分析好的:

vm-options – VM 选项
cmd-dir –父目录 (/system/bin)
options –运行的参数 :
    –zygote
    –start-system-server
    –application (api>=14)
    –nice-name=nice_proc_name (api>=14)
start-class-name –包含main方法的主类  (com.android.commands.am.Am)
main-options –启动时候传递到main方法中的参数

3 实践

因为是 dex 我们就直接在 as 里写吧,提取 dex 也方便。新建个空白项目,初始结构是这样:

我们新建个包,存放我们要在 shell 下运行的 Java 代码:

这里我们补全 Main 方法,因为我们这个不是个 Android 程序,只是编译成 dex 的纯 Java 程序,所以我们这个的入口是 Main :

package shellService;

public class Main {
    public static void main(String[] args){
        System.out.println("我是在 shell 里运行的!!!");
    }
}

我们在代码里只是打印一行「我是在 shell 里运行的!!!」,因为这里是纯 Java 所以也用的 println。现在编译 apk:

因为 apk 就是 zip 所以我们直接解压出 apk 文件里的classes.dex,然后执行 :

adb push classes.dex /data/local/tmp
cd /data/local/tmp
app_process -Djava.class.path=/data/local/tmp/classes.dex /system/bin shellService.Main

这时就能看到已经成功运行啦:

这里因为 utf8 在 Windows shell 里有问题,所以乱码了,但是还是说明我们成功了。

##4 具有实用性

只能输出肯定是不行的,不具有实用性。我们之前说过,我们应该建立个本地 socket 服务器来接受命令并执行,这里的「Service」类实现了这个功能,因为如何建立 socket 不是文章的重点,所以大家只要知道这个类内部实现了一个「ServiceGetText」接口,在收到命令之后会把命令内容作为参数回掉 getText 方法,然后我们执行 shell 命令之后,吧结果作为字符串返回即可,具体实现可以看查看源码Service

我们新建一个「ServiceThread」来运行「Service」服务和执行设立了命令:

public class ServiceThread extends Thread {
    private static int ShellPORT = 4521;

    @Override
    public void run() {
        System.out.println(">>>>>>Shell服务端程序被调用<<<<<<");
        new Service(new Service.ServiceGetText() {
            @Override
            public String getText(String text) {
                if (text.startsWith("###AreYouOK")){
                    return "###IamOK#";
                }
                try{
                    ServiceShellUtils.ServiceShellCommandResult sr =  ServiceShellUtils.execCommand(text, false);
                    if (sr.result == 0){
                        return "###ShellOK#" + sr.successMsg;
                    } else {
                        return "###ShellError#" + sr.errorMsg;
                    }
                }catch (Exception e){
                    return "###CodeError#" + e.toString();
                }
            }
        }, ShellPORT);
    }
}

其中 ServiceShellUtils 用到了开源项目 ShellUtils 在此感谢。这个类用来执行 shell 命令。

然后在 Main 中调用这个线程:

public class Main {

    public static void main(String[] args){
        new ServiceThread().start();
        while (true);
    }

}

这样,我们服务端就准备好了,我们来写控制服务端的 app 。我们新建类「SocketClient」用来和服务端进行通信,并在活动里调用他(完整代码请参看SocketClientMainActivity):

private void runShell(final String cmd){
        if (TextUtils.isEmpty(cmd)) return;
        new Thread(new Runnable() {
            @Override
            public void run() {
              new SocketClient(cmd, new SocketClient.onServiceSend() {
                  @Override
                  public void getSend(String result) {
                      showTextOnTextView(result);
                  }
              });
            }
        }).start();
    }

然后重复 3 小节的操作,运行这个服务端:

然后安装 apk ,运行:

input text HelloWord

可以看到,在不 root 的情况下,成功的执行了需要 shell 权限的命令

5 最可爱的人

最后,我真的是要由衷的感谢各种技术分析文章和开源项目,真的太感谢了,没有无条件的奉献就没有互联网这么快的进步。

我对 app_process 利用方法的研究离不开以下项目和前辈的汗水:

Brevent 最早利用app_process进程实现无 root 权限使用的开源应用(虽然已经闭源,仍然尊重并感谢 liudongmiao

Android system log viewer on Android phone without root. 利用app_process进程实现无 root 权限使用的优秀开源应用

Android上app_process启动java进程 通俗易懂的教程

使用 app_process 来调用高权限 API 分析的很深刻的教程

本文的项目可以在GitHub上获取:https://github.com/gtf35/app_process-shell-use

本文转发自:https://github.com/gtf35/app_process-shell-use
如果转发地址失效了或访问404,可访问我fork的
https://github.com/miqt/app_process-shell-use

  • 7
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
android adb shell 命令大全 1. 显示系统中全部Android平台: android list targets 2. 显示系统中全部AVD(模拟器): android list avd 3. 创建AVD(模拟器): android create avd --name 名称 --target 平台编号 4. 启动模拟器: emulator -avd 名称 -sdcard ~/名称.img (-skin 1280x800) 5. 删除AVD(模拟器): android delete avd --name 名称 6. 创建SDCard: mksdcard 1024M ~/名称.img 7. AVD(模拟器)所在位置: Linux(~/.android/avd) Windows(C:\Documents and Settings\Administrator\.android\avd) 8. 启动DDMS: ddms 9. 显示当前运行的全部模拟器: adb devices 10. 对某一模拟器执行命令: abd -s 模拟器编号 命令 11. 安装应用程序: adb install -r 应用程序.apk 12. 获取模拟器中的文件: adb pull 13. 向模拟器中写文件: adb push 14. 进入模拟器的shell模式: adb shell 15. 启动SDK,文档,实例下载管理器: android 16. 缷载apk包: adb shell cd data/app rm apk包 exit adb uninstall apk包的主包名 adb install -r apk包 17. 查看adb命令帮助信息: adb help 18. 在命令行中查看LOG信息: adb logcat -s 标签名 19. adb shell后面跟的命令主要来自: 源码\system\core\toolbox目录和源码\frameworks\base\cmds目录。 20. 删除系统应用: adb remount (重新挂载系统分区,使系统分区重新可写)。 adb shell cd system/app rm *.apk 21. 获取管理员权限adb root 22. 启动Activity: adb shell am start -n 包名/包名+类名(-n 类名,-a action,-d date,-m MIME-TYPE,-c category,-e 扩展数据,等)。 23、发布端口: 你可以设置任意的端口号,做为主机向模拟器或设备的请求端口。如: adb forward tcp:5555 tcp:8000 24、复制文件: 你可向一个设备或从一个设备中复制文件, 复制一个文件或目录到设备或模拟器上: adb push 如:adb push test.txt /tmp/test.txt 从设备或模拟器上复制一个文件或目录: adb pull 如:adb pull /addroid/lib/libwebcore.so . 25、搜索模拟器/设备的实例: 取得当前运行的模拟器/设备的实例的列表及每个实例的状态: adb devices 26、查看bug报告: adb bugreport 27、记录无线通讯日志: 一般来说,无线通讯的日志非常多,在运行时没必要去记录,但我们还是可以通过命令设置记录: adb shell logcat -b radio 28、获取设备的ID和序列号: adb get-product adb get-serialno 29、访问数据库SQLite3 adb shell sqlite3 #cd system/sd/data //进入系统内指定文件夹 #ls //列表显示当前文件夹内容 #rm -r xxx //删除名字为xxx的文件夹及其里面的所有文件 #rm xxx //删除文件xxx #rmdir xxx //删除xxx的文件夹
root获取adb权限是指在Android手机中,不需要进行root操作,仍能够获取并使用adbAndroid Debug Bridge)的权限。 在传统的情况下,如果想要使用adb命令进行连接手机并执行一些操作,通常需要先对手机进行root操作,以获得足够的权限来执行adb命令。但是,对手机进行root操作可能会导致潜在的安全问题,例如存在恶意软件或应用的权限滥用风险。 为了解决这个问题,一些手机制造商和开发者提供了一种root获取adb权限的方法。这种方法通常需要满足以下条件: 1. 开启开发者选项:在手机设置中,需要进入关于手机的页面,点击多次版本号或者构建号,即可激活开发者选项。 2. 启用USB调试:在开发者选项中,需要打开USB调试选项。 3. 授权USB调试,允许电脑或其他设备连接:当你通过USB数据线将手机连接到电脑时,手机会弹出一个提示框,询问是否信任该电脑。选择信任后,即可授权USB调试模式。 4. 安装ADB驱动和平台工具:在电脑中下载并安装相应的ADB驱动和平台工具,以便能够在电脑中执行adb命令。 通过以上步骤,即可在不进行root操作的情况下,使用ADB命令进行相关操作,如文件传输、安装应用程序等。这种方法大大降低了安全风险,并方便了开发者和普通用户的adb操作。同时,具体的步骤可能因手机品牌和操作系统版本的不同而有所差异,可以根据具体操作说明进行操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值