如何逆向一个第三方App

最近在做大模型相关的工作,发现一款比较好用的第三方APP,模型推理的首字时间非常快,于是打算看看它的逻辑以及Prompt提示词,于是想到了一个方案:反编译加Xposed框架hook关键方法,顺着这个思路开整。

工具

  • Apktool
    Apktool是一款逆向工程Android Apk文件的工具
    Apktool官网
    官网中讲解了Windows、Linux、Mac以及Brew平台的安装方式,我们按照步骤执行即可。

  • Dex2Jar
    Dex2Jar是将 dex 文件转换为包含 class 文件的 jar 文件的工具
    Dex2Jar官网
    安装:按照下图中指示下载最新的Releases版本即可

    Dex2Jar使用说明.png

    我们选择最新版本的dex-tools-v2.4.zip即可
    Dex2Jar Release版本下载.png

  • JD-GUI
    JD-GUI是个独立的图形实用程序,用于显示".class"文件相应的Java源代码
    JD-GUI官网
    打开该应用后导入Dex2Jar转换后的Jar文件即可查看相应的Java源代码

如果觉得上面的方法繁琐,可以使用下面的简便方法

更简便工具

Jadx-GUI
  • 主要功能
    可从APK, dex, aar或zip文件反编译Dalvik字节码为Java源代码
    解码AndroidManifest.xml文件以及resources.arsc中的其它的资源文件
  • 软件下载
    Jadx官网
    打开官网按照下图指示下载即可使用
    Jadx 下载.png
  • 使用方式
    下载with-jre的版本,解压后双击"jadx-gui-1.5.1"打开该软件,点击【文件】选择要反编译的APK文件稍等片刻就完成了所有的反编译功能,包括源代码,资源文件以及AndroidManifest.xml文件


    Jadx使用界面.png
  • 混淆方法处理
    很多三方App都会混淆,如上图的类名、方法名、变量名等,对于这种代码我们一般拿不到mapping文件,本人水平有限暂时没有深入研究更好的方法处理(有经验的大神欢迎分享)
    自己的处理逻辑主要还是根据一些不可变的内容结合App界面上显示内容进行逻辑分析,找到要Hook的方法
    不可变内容:
    -- Activity的名称
    -- res/values目录中的内容
    -- native方法名

使用XPosed框架Hook应用的特定方法

框架选择

  • Xposed框架: 官方版本支持到Android 8.0/8.1 beta3版本
  • Edxposed框架:支持Android 8.0到10.0,能够完全实现Xposed框架的相关功能,并且和rove89的官方Xposed一样,是不需要虚拟机直接安装在系统中的
  • LSPosed框架:支持Android 8.1到15,是目前比较热门的Xposed框架,需要搭配Magisk使用

根据支持的版本,我们选择使用LSPosed框架

Magisk

Magisk官网
Magisk中文文档
Magisk App下载地址

前置知识
  • 用户需了解adb及fastboot
  • 用户设备需解锁引导加载程序(Bootloader)
Magisk使用步骤

参考文档

    1. 解锁 Boot loader
      注意:解锁 Bootloader 会清除数据,有重要数据请备份再操作!!!
      注意:解锁 Bootloader 会清除数据,有重要数据请备份再操作!!!
      注意:解锁 Bootloader 会清除数据,有重要数据请备份再操作!!!

      -- 首先手机或平板要处于开发者模式
      -- 在开发者选项中解锁引导加载程序,把【OEM解锁】功能打开即可,每款设备打开方式略有不同,用户可根据自己手中产品百度一下哈。
    1. 获取 boot.img 或者 init_boot.img(若有安装包,直接拷贝即可)
      如果没有boot.img文件需要用户提取该文件,参考下面连接进行操作:
      payload-dumper-go 提取 boot.img

我是在Lenovo的平板上操作的,使用boot.img文件试几次都不成功(Magisk不出现当前版本号信息,见下图),改用init_boot.img文件一次成功!用户操作时注意哈。
参考官网文档发现有三个文件,boot.img, init_boot.img, recovery.img

Maigsk安装成功界面.png

    1. 安卓设备连接电脑,开启文件传输模式,复制电脑中的.img文件到安卓设备
    1. 安卓设备Magisk App安装
      Github安装连接
      打开Magisk App下载地址,选择最新版本"Magisk-V28.1.apk"(这是写文档时最新版本,使用你看到的最新版本即可)下载安装即可
      Magisk 下载.png
    1. 修补.img镜像文件
      修补生成的文件 magisk_patched-xxx.img 在 Download 目录


      Patching Image.png
    1. adb-fastboot命令安装:直接使用SDK目录中platform-tools中的即可
    1. 设备连接电脑,开启文件传输模式,复制设备中修补后的magisk_patched-xxx.img文件到电脑
    1. 手机进入Bootloader模式
      手机关机,同时按下电源键 + 音量下键
    1. 打开CMD命令行,执行下面的刷入命令
      magisk.img 每次修补生成的名字都不一样,使用的时候请输入生成的名字
      fastboot flash boot magisk_patched-xxx.img
    1. 显示OKAY 就是成功刷入了,使用指令 fastboot reboot 重启手机即可


      image.png

LSPosed

LSPosed中文网

下载LSPosed模块(Zygisk版)

下载连接

  • 打开Magisk设置中开启Zygisk


    Zygisk开启.jpg
  • 打开Magisk - 模块 - 从本地安装


    image.png
  • 重启设备,通知栏点开通知打开管理器


    通知栏消息.jpg
  • 创建LSPosed快捷方式


    LSPosed快捷方式创建.jpg
  • LSPosed显示“已激活”则表示成功刷入


    已激活.jpg

Hook应用

    1. Android Studio 中新建一个项目
    1. setting.gradle.kts文件设置
      在setting文件中的dependencyResolutionManagement中添加xposed仓库地址:maven { url = uri("https://api.xposed.info/") } // 添加Xposed的库
    1. build.gradle设置
      在app模块的dependencies中添加xposed依赖
      compileOnly("de.robv.android.xposed:api:82")
      注意:此处只能使用compileOnly,否则会报错:
      Cannot load module: com.example.xxx(自定义的包名)
      The Xposed API classes are compiled into the module's APK.
    1. AndroidManifest.xml设置
      添加permission
      <uses-permission
      android:name="android.permission.INTERNET" />
      <uses-permission
      android:name="android.permission.ACCESS_NETWORK_STATE" />
      在application标签中添加xposed的meta信息
      <meta-data
      android:name="xposedmodule"
      android:value="true"/>
      <meta-data
      android:name="xposeddescription"
      android:value="这是一个用于hook第三方APP方法的模块"/>
      <meta-data
      android:name="xposedminversion"
      android:value="54"/>
      <meta-data
      android:name="xposedscope"
      android:resource="@array/xposed_scope"/>
    1. 目标APP包名设置
      在res\values目录下新建arrays.xml文件,在文件中输入如下内容:
      <resources>
      <string-array name="xposed_scope">
      <item>com.example.d</item>
      </string-array>
      </resources>
    1. assets目录创建
      右键点击[src]-[new]-[Directory],选择main\assets,创建assets目录,在该目录中创建文件:xposed_init,并在文件中输入:com.example.lsposed.MainHook,该类是你要创建执行的Hook的类全路径名。
    1. Hook方法
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;

public class HookTest {
    public static void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {
        if (lpparam.packageName.equals("目标APP的包名")) { // 替换为目标APP的包名
            XposedBridge.log("开始hook目标APP的方法");
            Class<?> targetClass = lpparam.classLoader.loadClass("目标类的完整路径"); // 替换为目标类的完整路径
            XposedHelpers.findAndHookMethod(targetClass, "目标方法名", new XC_MethodHook() { // 替换为目标方法名
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    XposedBridge.log("方法执行前的逻辑");
                    super.beforeHookedMethod(param);
                }

                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    XposedBridge.log("方法执行后的逻辑");
                    super.afterHookedMethod(param);
                }
            });
        }
    }
}
    1. java.lang.NoSuchMethodError处理
      因为混淆后的代码运行也是以混淆方式执行的,因此Hook的时候使用混淆后的类名、方法名称即可
      如果类名、方法名都对了还报这种错误一般是方法路径不正确,比如:
  • 8.1 Companion类的完整路径
    在 Kotlin 中,Companion 类的完整路径通常是 ClassName$Companion,例如,如果目标类是 com.example.MyClass,那么 Companion 类的完整路径就是 com.example.MyClass$Companion

    1. 带有参数的方法正确的Hook方式
      -- 通用类型参数,直接使用该类型即可
      -- 第三方App自定义的接口类型,需使用相关的classLoader.loadClass()方法加载该三方类获取类型,如下图所示


      获取三方App自定义类型.png

      以下是完整的示例,供参考

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

public class MyHook implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        if (!lpparam.packageName.equals("目标APP的包名")) { // 替换为目标APP的包名
            return;
        }
        Class<?> targetClass = lpparam.classLoader.loadClass("com.example.MyClass");
        XposedHelpers.findAndHookMethod(
            targetClass,
            "myMethod",
            String.class, // 参数类型1
            lpparam.classLoader.loadClass("com.example.ResponseCallback"), // 参数类型2,第三方自定义回调接口
            new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    android.util.Log.i("MyHook", "Hooked myMethod before: param1 = " + param.args[0]);
                    // 处理回调接口
                    Object callback = param.args[1];
                    if (callback != null) {
                        // 在回调接口中添加日志输出
                        XposedHelpers.findAndHookMethod(
                            callback.getClass(),
                            "onResponse",
                            new XC_MethodHook() {
                                @Override
                                protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
                                    super.beforeHookedMethod(param);
                                    android.util.Log.i("MyHook", "onResponse called");
                                }
                            }
                        );
                    }
                }

                @Override
                protected void afterHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    android.util.Log.i("MyHook", "Hooked myMethod after: param1 = " + param.args[0]);
                }
            }
        );
    }
}

以上就是自己在处理第三方APP的过程,如有偏颇之处欢迎批评指正。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容