Frida遍历启动App所有Activity/Service

news2025/1/13 8:10:14

说明:仅供学习使用,请勿用于非法用途,若有侵权,请联系博主删除

作者:zhu6201976

一、需求

在一些大型App中,往往注册了大量的Activity和Service,这在App的AndroidManifest.xml文件可以清晰呈现。那么,如果给定任意App,在不反编译的前提下,如何获取并自动化批量遍历启动App所有Activity或Service?

二、在不反编译的前提下,如何获取启动App所有Activity或Service?

Android自带adb命令可以轻松获取Activity或Service相关信息,具体命令参考如下:

获取App四大组件相关信息命令:adb shell am

# 启动Android系统中任意App Activity
am start-activity -n com.android.settings/.Settings$NetworkDashboardActivity

# 启动Android系统中任意App Service
am start-service --user 0 com.android.internal.widget.ILockSettings

# 停止Android系统中任意App Service
am stop-service --user 0 com.android.internal.widget.ILockSettings

# 发送Android系统中任意App broadcast
am broadcast --user 0 android.intent.action.BATTERY_CHANGED
am broadcast android.provider.Telephony.SMS_RECEIVED

获取App服务相关信息命令:adb shell service/servicemanager

# 过滤查看包含settings关键词的系统service
service list | grep settings

# 过滤查看包含mosheng关键词的非系统service
dumpsys activity services | grep mosheng

三、如何获取并自动化批量遍历启动App所有Activity或Service?

根据上述描述可知,在Android系统中,adb相关命令可以轻松获取并管理Activity或Service相关信息,功能十分强大,但无法做到自动化批量遍历启动App所有Activity或Service。当然你可以写相关程序执行调用adb命令实现上述功能。

而基于Frida实现的objection功能非常强大,不仅可以枚举App中所有的四大组件相关信息,而且提供了单个组件启动服务,但仍然未实现批量自动化hook。自动化批量遍历启动App所有Activity或Service这种需求在某些特定场景,比如逆向、测试等,为开发者检查App页面及可能存在的页面跳转漏洞提供了一些便利,因此具有某些实际意义。GitHub - sensepost/objection: 📱 objection - runtime mobile exploration

四、Frida遍历启动App所有Activity/Service

基于上述需求,本人站在开发和借鉴objection的基础上,通过Frida主动调用实现了该功能,并在多个App中测试通过,项目已开源,github地址:https://github.com/zhu6201976/frida_intent.git 欢迎star、交流。

参考代码如下:

/**
 * @Time : 2023/6/28 22:00
 * @Author : Tesla
 * @Csdn : https://blog.csdn.net/zhu6201976
 *
 * Frida遍历启动App所有Activity/Service
 * attach模式:
 *     frida -UF -l hook_intent.js
 * spawn模式:
 *     frida -U -l hook_intent.js -f com.mosheng
 */

var context = null;
var packageName = null;
var delay = 1500;

function getContextPackageNameV1() {
    Java.choose('android.app.ActivityThread', {
        onMatch(instance) {
            const currentApplication = instance.currentApplication();
            context = currentApplication.getApplicationContext();
            packageName = context.getPackageName();
            console.log('getContextPackageNameV1', 'context', context, 'packageName', packageName);
        }, onComplete() {
        }
    });
}

function getContextPackageNameV2() {
    const ActivityThread = Java.use("android.app.ActivityThread");
    const currentApplication = ActivityThread.currentApplication();
    context = currentApplication.getApplicationContext();
    packageName = context.getPackageName();
    console.log('getContextPackageNameV2', 'context', context, 'packageName', packageName);
}

function sleep(delay) {
    const start = (new Date()).getTime();
    while ((new Date()).getTime() - start < delay) {
    }
}

/*
public void getAllActivity() {
    PackageManager packageManager = getPackageManager();
    PackageInfo packageInfo = null;
    try {
        packageInfo = packageManager.getPackageInfo(getPackageName(), PackageManager.GET_ACTIVITIES);
        ActivityInfo[] activities = packageInfo.activities;
        for (ActivityInfo activity :activities ) {
            Class<?> aClass = Class.forName(activity.name);
        }
    } catch (PackageManager.NameNotFoundException | ClassNotFoundException e) {
        e.printStackTrace();
    }
}
 */
function getActivities() {
    const packageManager = Java.use("android.content.pm.PackageManager");
    const GET_ACTIVITIES = packageManager.GET_ACTIVITIES.value;
    return Array.prototype.concat(context.getPackageManager()
        .getPackageInfo(context.getPackageName(), GET_ACTIVITIES).activities.value.map((activityInfo) => {
            const activity = activityInfo.name.value;
            // return activity;  // 返回所有Activity
            if (activity.indexOf(packageName) !== -1) {  // 返回app自定义Activity
                return activity;
            }
        }));
}

/*
Intent intent = new Intent(MyActivity.this, MyOtherActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
 */
function startActivities() {
    const activities = getActivities();
    const set = new Set();
    activities.forEach(function (activity) {
        set.add(activity);
    });
    console.log('getActivities Found ' + set.size + ' activities');

    set.forEach(function (activity) {
        console.log('getActivities start_activity', activity);
        try {
            const Clazz = Java.use(activity);
            const Intent = Java.use('android.content.Intent');
            const intent = Intent.$new(context, Clazz.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK.value);
            context.startActivity(intent);
        } catch (e) {
            console.log('getActivities', e);
        }

        sleep(delay);
    });
}

function getServices() {
    const activityThread = Java.use("android.app.ActivityThread");
    const arrayMap = Java.use("android.util.ArrayMap");
    const packageManager = Java.use("android.content.pm.PackageManager");
    const GET_SERVICES = packageManager.GET_SERVICES.value;
    const currentApplication = activityThread.currentApplication();
    let services = [];
    currentApplication.mLoadedApk.value.mServices.value.values().toArray().map((potentialServices) => {
        Java.cast(potentialServices, arrayMap).keySet().toArray().map((service) => {
            // services.push(service.$className);
            if (service.$className.indexOf(packageName) !== -1) {
                // console.log('getServices 1', service);
                services.push(service.$className);
            }
        });
    });
    services = services.concat(context.getPackageManager()
        .getPackageInfo(context.getPackageName(), GET_SERVICES).services.value.map((activityInfo) => {
            const service = activityInfo.name.value;
            if (service.indexOf(packageName) !== -1) {
                // console.log('getServices 2', service);
                return service;
            }
        }));
    return services;
}

/*
Intent intent = new Intent(this, TestService.class);
startService(intent);
stopService(intent);
 */
function startServices() {
    const services = getServices();
    const set = new Set();
    services.forEach(function (service) {
        set.add(service);
    });
    console.log('startServices Found ' + set.size + ' services');

    set.forEach(function (service) {
        console.log('startServices start_service', service);
        try {
            const Clazz = Java.use(service);
            const Intent = Java.use('android.content.Intent');
            const intent = Intent.$new(context, Clazz.class);
            // context.stopService(intent);
            context.startService(intent);
        } catch (e) {
            console.log('startServices', e);
        }

        sleep(delay);
    });
}

function main() {
    Java.perform(function () {
        try {
            getContextPackageNameV1();
        } catch (e) {
            getContextPackageNameV2();
        }
        startActivities();
        startServices();
    });
}

setTimeout(main, 1500);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/693784.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Centos7完整安装

一、前言 由于使用VMware workstation使用典型安装以及默认安装方式进行安装的Centos多存在组件不足的问题&#xff0c;这使得使用上述方式进行安装的系统在一些特定情况下需要安装组件&#xff0c;致使系统不是很便利&#xff0c;本文提供了在VMware workstation下进行完整安装…

Verdi之nTrace/nSchema

目录 3.nTrace介绍 3.1 启动Verdi 3.2查看Verdi中的设计结构 3.3查看Verdi中的验证结构 3.4 查找模块和trace信号 3.5 查找string 3.6 信号drive/load 3.7 快速查看设计有哪些信号 4 nSchema 4.1 如何打开原理图 4.2 如何查找 nShema window中器件的源码 4.3 如何显示原理…

【Java面试题】框架篇——Redis

文章目录 Redis的使用场景Redis支持的数据类型如何在Redis中实现分布式锁Redis和Mysql的事务有什么区别&#xff1f;Redis缓存穿透如何解决&#xff1f;Redis缓存雪崩如何解决&#xff1f;什么是缓存击穿&#xff0c;如何解决&#xff1f;Redis是单线程模式的&#xff0c;为什么…

chatgpt赋能python:Python超大数计算

Python超大数计算 介绍 在日常编程中&#xff0c;我们常常需要处理大量数据。这些数据可以是普通的整数或浮点数&#xff0c;但有时候我们需要计算的数据可能会超出计算机处理的数值范围。这时&#xff0c;我们需要使用更为高级的算法来进行超大数计算。 Python语言因为其简…

【Java】 Java 中处理 null 或缺失数据

本文仅供学习参考&#xff01; 相关教程地址&#xff1a; https://juejin.cn/post/7234924083842154556 https://cloud.tencent.com/developer/article/1107739?areaSource106005.3 https://www.developer.com/java/null-data-java/ 将某些内容表示为空白或不存在始终是编程中…

TX Text Control 31 sp3 for ActiveX-VB6-Crack

Visual Basic 6 应用程序的文档处理 适用于 Visual Basic 6 和基于 COM 的语言的综合文字处理和报告 视窗用户界面 功能齐全的文档编辑器 TX Text Control 是一款免版税、完全可编程的丰富编辑控件&#xff0c;它在专为 Visual Studio 设计的可重用组件中为开发人员提供了广泛的…

数字空间【高校版】上线

WRITE-BUG团队一直在致力于推动科技创新与科研学习数字化建设&#xff0c;为学生的学习、老师的工作&#xff0c;插上数字化的翅膀。 目前&#xff0c;我们注意到高校在大力推进数字化建设&#xff0c;在内容管理上遇到以下问题亟待解决&#xff1a; 各个科研实验室资料、项目…

【后端面经-Java】Synchronize和ReentrantLock区别

【后端面经-Java】Synchronize和ReentrantLock区别 1. 概念介绍1.1 线程安全锁1.2 公平锁1.3 响应中断/等待可中断 2. 区别2.1 底层实现2.2 锁的用法2.3 锁的特点2.4 性能比较2.5 适用场景 3. 总结比较参考文献 1. 概念介绍 1.1 线程安全锁 Synchronize&#xff08;同步锁&am…

Spring Boot 中的 @PutMapping 注解是什么,原理,如何使用

Spring Boot 中的 PutMapping 注解是什么&#xff0c;原理&#xff0c;如何使用 在 Spring Boot 中&#xff0c;PutMapping 是一种注解&#xff0c;它可以将 HTTP PUT 请求映射到指定的处理方法上。本文将介绍 PutMapping 的原理以及如何在 Spring Boot 中使用它。 PutMapping…

【软考网络管理员】2023年软考网管初级常见知识考点(31)-著作权、商标权、专利权详解

涉及知识点 著作权保护期限&#xff0c;著作权人的确定&#xff0c;侵权如何去判定&#xff0c;商标权是什么&#xff1f;专利权详解&#xff0c;软考网络管理员常考知识点&#xff0c;软考网络管理员网络安全&#xff0c;网络管理员考点汇总。 原创于&#xff1a;CSDN博主-《…

Visual C++中的虚函数和纯虚函数(对比学习法之一)

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天来说说Visual C中的虚函数和纯虚函数。该系列帖子全部使用我本人自创的对比学习法。也就是当C学不下去的时候&#xff0c;就用JAVA实现同样的代码&#xff0c;然后再用对比的方法把C学会。 直接说虚函数…

初识mysql数据库之表的约束

目录 一、表的约束的概念 二、非空约束&#xff08;空属性&#xff09; 2. 空属性的使用 三、default约束&#xff08;默认值&#xff09; 1. 默认值的含义 2. 默认值的使用 3. 默认值与非空约束的关系 3.1 默认值与非空约束的生效问题 3.2 default自动生成与not null的…

Linux 学习记录40(C++篇)

Linux 学习记录40(C/QT篇) 本文目录 Linux 学习记录40(C/QT篇)一、QT软件的使用1. 新建工程 二、C语言和C的区别1. C对C的扩充2. C对C的兼容 三、第一个C程序1. cout标准输出流对象(1.介绍&#xff1a;(2. 运算符(3. cout的使用 2. cin标准输出流对象(1.介绍&#xff1a;(3. ci…

python【爬虫】【批量下载】年报抓取

python年报爬取更新 本人测试发现&#xff0c;ju chao网的年报爬取距离我上一篇博客并没有啥变化&#xff0c;逻辑没变&#xff0c;应好多朋友的需要&#xff0c;这里补充代码 import json import osimport requestsweb_url 改成网站的域名&#xff0c;因为csdn屏蔽 def load…

深入了解cookie以及实际项目中的应用

目录 cookie的原理 cookie是不可跨域的 cookie 的属性 Cookie与Session的区别 在git中的应用 cookie的原理 什么是cookie呢&#xff1f; 众所周知&#xff1a;http都是无状态的 但随着 Web 的不断发展&#xff0c;这种 无状态 的特性出现了弊端。当你登录到一家购物网站…

RabbitMQ保证消息的可靠投递,Java实现RabbitMQ消息的可靠投递,Springboot实现RabbitMQ消息的可靠投递

文章目录 一、RabbitMQ消息可靠性概述1、引出问题2、RabbitMQ消息可靠性保证的四个环节 二、保证生产者消息发送到RabbitMQ服务器1、服务端确认&#xff1a;Transaction模式&#xff08;1&#xff09;JavaAPI&#xff08;2&#xff09;springbootAPI 2、服务端确认&#xff1a;…

【Matlab】根据伯德图计算pid参数方法原理

在学习鲁棒控制的过程中&#xff0c;有一些步骤需要根据一些性能参数来计算pid参数&#xff0c;因此记录一下根据伯德图的性能来计算pid参数的原理。 系统开环响应的几个关键参数 在使用开环响应初调控制器参数时&#xff0c;主要就是调整几个需要注意的关键参数&#xff0c;…

nbcio-vue中formdesigner的组件显示不正常的处理

今天看演示系统的formdesigner组件显示不正常&#xff0c;也不知道是什么时候开始的事情&#xff0c; 如下&#xff1a; 对组件的操作倒是正常&#xff0c;但看本地是正常的&#xff0c;如下&#xff1a; 开始也不知道是什么原因&#xff0c;看代码也是一样的&#xff0c;应该…

11 MFC 制作记事本

文章目录 界面制作制作菜单设置编译框随着窗口的变化而变化OnSize打开文件文件另存为设置字体颜色修改字体文件的查找与替换查找与替换对话框显示&#xff08;非模态对话框&#xff09;对话框消息与对话框处理函数 全部代码 界面制作 制作菜单 选择Menu 点击新建 将内容写入&qu…

Nightingle夜莺Docker版SNMP监控

起因 对夜莺很感兴趣&#xff0c;想使用一下。我看官方提供了v6版本的docker-compose。而且我之前有使用过promtheus和grafana&#xff0c;虽然很好但是总觉得还是得二开。总有一天有人去搞一个不错的玩意儿出来。官方文档地址 安装与配置 直接运行docker版本的demo&#xf…