打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Android安全之使用root权限替代无障碍服务的方式去获取TopActivity | 航行学园
userphoto

2022.09.30 河北

关注

阅读本文之前 请先阅读 我之前写的文章 《Android安全之使用root权限绕过检测机制,强行自动允许应用的悬浮窗/应用后台弹出界面等权限》

了解前篇文章里面的如下几点知识点,作为本篇的基础:
1.在linux下如何直接运行dex (java代码) 让java代码全程拥有root权限去运行一些系统api
2.导入framework.jar, 以方便进行快速的免反射开发 (可选, 但是这样的话你得自己写反射和接口代理)

首先

通过在linux下执行这段dex代码可以越权获取到topActivity

//获取顶部activity
public ComponentName getTopActivity(){
	ComponentName topActivity = null;
	for (ActivityManager.StackInfo allStackInfo : ActivityTaskManager.getService().getAllStackInfos()) {
	    if (allStackInfo.visible && allStackInfo.displayId == Display.DEFAULT_DISPLAY) {
	        topActivity =allStackInfo.topActivity;
	    }
	}
	 return topActivity;
}

然后

while(true){
    String act = getTopActivity();
    System.out.println("topActivity=" + act );
}

哈哈哈哈哈…
骗你的, 要是这么死循环获取就不会有这篇文章了…

正片开始

把以下代码 打包成jar 用dx命令打包成一个dex 运行即可 (教程在前面说的文章里)

public static void main(String[] args) throws Exception {
        Looper.prepareMainLooper();
        registerTaskStackChangedListener(new TaskStackListener() {
            @Override
            public void onTaskStackChanged() throws RemoteException {
                super.onTaskStackChanged();
                //获取顶部activity
                ComponentName topActivity = null;
                for (ActivityManager.StackInfo allStackInfo : ActivityTaskManager.getService().getAllStackInfos()) {
                    if (allStackInfo.visible && allStackInfo.displayId == Display.DEFAULT_DISPLAY) {
                        topActivity =allStackInfo.topActivity;
                    }
                }
                sendText(""+topActivity);
            }
        });
        Looper.loop();
}
//注册栈改变监听
private static void registerTaskStackChangedListener(TaskStackListener listener) throws Exception {
        if (mTaskStackListener != null) {
            ActivityTaskManager.getService().unregisterTaskStackListener(mTaskStackListener);
        }
        mTaskStackListener = (ITaskStackListener) listener;
        ActivityTaskManager.getService().registerTaskStackListener(mTaskStackListener);
}
//利用发广播的方式 实现 通讯"回调"
private static void sendText(String text) {
        String action = "com.dddd.zzzz.TEST";
        try {
            Intent intent = new Intent(action);
            intent.putExtra("text", text);
            getContext().sendBroadcast(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
}

原理:
利用root权限执行 ActivityTaskManager.getService()注册一个activity栈变化监听,避免了死循环获取, 减少耗电量, 取出当前的topActivity后 通过自己创建的上下文 通过广播发送出去, 如然后你只需用广播接收器去接收数据即可

接收数据

这没啥好说的 就是接收linux里的dex app进程发过来的广播

registerReceiver(object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        LaihuaLogger.i("onReceive MX: ${intent?.action} ${intent?.getStringExtra("text")}")
    }
}, IntentFilter("com.dddd.zzzz.TEST"))

本期知识点

1.linux下自己创建自己的上下文 解决了之前文章《Android安全之使用root权限绕过检测机制,强行自动允许应用的悬浮窗/应用后台弹出界面等权限》中 到最后无法拿到context去调用一些需要context 的api 时的抓狂…

//TODO 此处为了演示 没做上下文缓存, 会导致每次都会生成新的上下文
private static Context getContext() throws Exception {
    Class<?> ActivityThread = Class.forName("android.app.ActivityThread");
    Method systemMain = ActivityThread.getDeclaredMethod("systemMain");
    Object object = systemMain.invoke(null);
    Class<?> ContextImpl = Class.forName("android.app.ContextImpl");
    Method createSystemContext = ContextImpl.getDeclaredMethod("createSystemContext", ActivityThread);
    createSystemContext.setAccessible(true);
    return (Context) createSystemContext.invoke(null, object);
}

2.创建Handler运行环境, 某些系统api需要基于Handler环境进行运作

Looper.prepareMainLooper();
//你的代码
xxxxxxx
Looper.loop();
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
Activity启动模式SingleTask和Intent.FLAG
原创: android superuser.apk 管理root权限原理分析
玩转ADB命令(ADB命令使用大全)
Android 获取ROOT权限原理解析
adb命令大全
解密Android通信安全机制
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服