[Frida集成篇]FD_01.三种方案实现Frida脚本持久化研究

FD_01.三种方案实现Frida脚本持久化研究

主要内容:

  • frida-gadget持久化研究

  • frida-gumjs脚本持久化研究

  • frida-inject脚本持久化研究

1.frida-gadget持久化研究

frida-gadget是一个动态共享库,可以在App中加载该动态库然后执行js代码功能。
frida-gadget动态库下载地址:

https://github.com/frida/frida/releases/tag/14.2.15

根据官方介绍,在AndroidApp中可以重打包方式将frida-gadget动态库放到lib下面对应的平台目录,然后编写对应的配置文件。例如我的一个Demo Apk,使用apktool反编译之后。可以像如下操作将frida-gadget动态库添加进去,并配置执行指定的脚本。参考如下:

# arm64-v8a加入对应的arm64-v8a版本的libfrida-gadget.so
DemoApp/lib/arm64-v8a/libfrida-gadget.so
DemoApp/lib/arm64-v8a/libfrida-gadget.config.so

# armeabi-v7a加入对应的armeabi-v7a版本的libfrida-gadget.so
DemoApp/lib/armeabi-v7a/libfrida-gadget.so
DemoApp/lib/armeabi-v7a/libfrida-gadget.config.so

libfrida-gadget.config.so中配置的内容如下:

{
  "interaction": {
    "type": "script",
    "path": "/sdcard/test.js"
  }
}

将以上内容配置到apk中之后,还需要将加载frida-gadget动态库的代码插入到App的启动代码中。由于Android App中启动首先执行Application相关类,所以可以通过反编译找到Applicatoin相关的类,然后插入如下smali代码进去。插入的加载动态库代码如下:

# direct methods
.method static constructor ()V
    .registers 1

    .prologue
    .line 10
    const-string v0, "frida-gadget"

    invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

    .line 11
    return-void
.end method

根据以上frida-gadget重打包实现加载js的思路,可以在安卓系统源码中按照如下思路实现一个加载js的方案。

方案思路:

(1).寻找系统源码中App启动加载的合适时机加载frida-gadget动态库

安卓系统中App启动的时候主入口为ActivityThread.java。可以在该文件中找到一个合适的时机加载frida-gadget动态库,为了达到更好的hacking效果,最好在ApplicationattachBaseContext执行之前加载。比如该文件中handleBindApplication方法是一个不错的选择。

(2).在frida-gadaget动态库存放的目录同时添加相应的脚本配置规则文件

比如frida-gadget动态库文件名libtestgadget.so,那么需要在相同目录下面创建文件libtestgadget.config.so文件,并将如下内容加入(内容中的path值根据自己的脚本路径设置):

{
  "interaction": {
    "type": "script",
    "path": "/sdcard/test.js"
  }
}

该方案主要解决的问题:

(1).frida-gadget动态库集成到系统

(2).App读写权限配置,比如有权限读取配置的js文件路径

该方案参考项目:

https://github.com/hanbinglengyue/FridaManager

2.frida-gumjs脚本持久化研究

frida-gumjsfrida中核心模块frida-gum的脚本执行接口封装。以下是frida整个架构图:

[Frida集成篇]FD_01.三种方案实现Frida脚本持久化研究_第1张图片

从以上架构中分析出平时PC端使用frida 命令执行执行App脚本加载的时候,实际上在App端加载了一个frida-agent-64.so或者frida-agent-32.so动态库,该动态库中使用了frida-gumjs封装的接口来执行js内容。官方提供了libfrida-gumjs.a的下载,可以下载集成到App工程中使App直接调用对应的接口来执行js脚本。下载地址:

https://github.com/frida/frida/releases/tag/14.2.15

比如frida-gumjs中提供的一个接口:

//source参数指定了执行的js脚本内容
GUM_API GumScript * gum_script_backend_create_sync (GumScriptBackend * self,
    const gchar * name, const gchar * source, GCancellable * cancellable,
    GError ** error);

从以上接口可以看出直接调用接口执行js脚本非常的方便。

有了frida-gumjs提供的接口,可以设计如下的一个方案来进行系统中App的持久化运行。

方案如下:

(1).将frida-gumjs链接到开发的动态库中,并提供封装jni接口,提供Java api对外调用。

(2).将开发的动态库以及提供的Java api接口集成到系统

(3).在Android App启动入口ActivityThread.java中找一个合适的位置调用开发的Java api接口,传入配置的js文件路径

该方案主要解决的问题:

(1).frida-gumjs封装为Java api接口

(2).系统集成开发的so以及Java api

(3).App读写权限配置,比如有权限读取配置的js文件路径

frida-gumjs集成接口封装开发参考项目:

https://github.com/svengong/xcubebase

3.frida-inject脚本持久化研究

frida-inject是一个可执行程序,执行的时候可以传入进程pid以及执行的js文件路径实现对app js载入。使用frida-inject需要超级Root权限。在之前我们已经实现了通过socket连接到超级Root权限进程中去执行命令。所以系统中只需要在App入口的地方找到合适的调用点,将要执行的命令通过socket连接发送到超级Root权限进程执行,从而实现js载入。

frida-inject持久化方案:

在App入口ActivityThread.java中找到一个调用点,比如函数handleBindApplication方法。然后socket连接到超级Root权限去执行frida-inject命令。

该方案主要解决的问题:

(1).frida-injec集成到系统

(2).开发配置超级Root权限后台进程

(3).封装socket连接超级Root进程的Java Api接口

Application**方法。然后socket连接到超级Root权限去执行frida-inject命令。

该方案主要解决的问题:

(1).frida-injec集成到系统

(2).开发配置超级Root权限后台进程

(3).封装socket连接超级Root进程的Java Api接口

(4).App读写权限配置,比如有权限读取配置的js文件路径

你可能感兴趣的:(android,frida,java,安卓源码开发)