前言

一直想学一下安卓HOOK,正好最近在折腾自动记账时遇到个问题,每次付完款使用“自动记账”自动把账单同步给“钱迹”时都会弹出系统应用跳转的警告,就像下面这种

每次都要手动去点击才能同步账单,这就很烦,于是乎就想能不能把它给干掉,真正的实现自动同步账单,说干就干。

环境准备

手机:魅族21

系统:Flyme11+Magisk+LSPosed

安卓软件:钱迹、自动记账、MT管理器

PC软件:Android Studio、jadx-gui

HOOK点分析

activity分析

首先分析上面这个操作警告应该是一层activity,既然是activity,那就在弹出的时候看看谁在最上层,用MT管理器记录Acitvity,发现当出现这个弹窗时是com.android.internal.app.AppSwitchWarningActivity ,单看这个玩意儿的名字也比较像

logcat日志分析

在扒一扒Logcat的日志,看有没有什么有用的信息,目前只知道这是哪个类了,但还不知道它在哪一个包里,想hook到还需要知道是作用在哪个作用域,一边操作,一边截取logcat的日志,搜到以下比较关键的日志,打印的是android这个包,说明作用域要选择androidonCreate 被调用说明这个activity被创建或者说是初始化了,点击打开 时日志打印onClick: -1 ,目前来看,想要的东西已经明确了。

坑:作用域填写android ,在lsp中自动勾选的是系统框架,我测试时发现死活hook不到,于是我把所有作用域全选上,最终是在system 的作用域下才生效,它在lsp中显示的是flyme系统服务 ,坑爹啊,愁了我两天

反编译包

提取了下系统中的android 这个包,把这个包拉到jadx-gui里,想要具体看下这个类都有什么内容,但是我发现怎么找都找不到,查阅一番发现,这个类应该属于系统框架中的,想要找到类本身的话,应该反编译/system/framework/framework.jar ,不知道这么理解对不对,反正最终是在framework.jar 找到了这个类,跟日志打印的也都对的上

项目搭建

新建Android项目

选择No Activity

下一步~~

项目初始化

添加仓库:编辑settings.gradle,在dependencyResolutionManagement新增maven { url 'https://api.xposed.info/' }

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url 'https://api.xposed.info/' }
    }
}

添加依赖:编辑build.gradle ,在dependencies 中添加compileOnly 'de.robv.android.xposed:api:82' ,并刷新Gradle;

dependencies {
    compileOnly 'de.robv.android.xposed:api:82'
    implementation libs.appcompat
    implementation libs.material
    testImplementation libs.junit
    androidTestImplementation libs.ext.junit
    androidTestImplementation libs.espresso.core
}

编辑AndroidManifest.xml ,添加如下信息:

<application
    android:allowBackup="true"
    android:dataExtractionRules="@xml/data_extraction_rules"
    android:fullBackupContent="@xml/backup_rules"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.SkipAppSwitchWarn"
    tools:targetApi="31" >
    <!-- 是否是xposed模块,xposed根据这个来判断是否是模块 -->
    <meta-data
        android:name="xposedmodule"
        android:value="true" />
    <!-- 模块描述,显示在xposed模块列表那里第二行 -->
    <meta-data
        android:name="xposeddescription"
        android:value="打开钱迹不显示跳转提示" />
    <!-- 最低xposed版本号(lib文件名可知,一般填54即可) -->
    <meta-data
        android:name="xposedminversion"
        android:value="54" />
    <!-- 模块作用域 -->
    <meta-data
        android:name="xposedscope"
        android:resource="@array/xposedscope"/>
</application>

新建/app/src/main/res/values/array.xml ,添加如下信息,表示推荐选择的作用域:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="xposedscope">
        <item>system</item>
    </string-array>
</resources>

新建一个Hook类,如下:

package com.coco.skipappswitchwarn;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class MainHook implements IXposedHookLoadPackage {
    
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {

    }
}

新建/app/src/main/assets/xposed_init ,写入Hook类的全类名:

com.coco.skipappswitchwarn.MainHook

按需修改启动配置:

至此,XPosed模块项目基本框架就已搭建完成。

思路&&编码

思路

结合上面日志分析,当点击打开时会调用onClick 这个方法,从反编译的源码中也能发现,最终实现跳转的方法应该是startIntentSenderForResult ,其实只要构造正确的参数,然后调用这个方法,想达到自动跳转的效果就实现了,流程上是要hookonCreate 这个方法,并且是在执行onCreate 之前实现自动跳转,然后再干掉activity就可以了。

编码

项目已提交至GitHub:

https://github.com/coco-repository/SkipAppSwitchWarn

完结撒花