ubuntu 20.04系统AOSP(Android 11)集成Frida

参考 ubuntu 20.04编译Android 11源代码&模拟器 完成Android 11源代码的编译工作,保证能编译通过。

想自己手工编译`Frida`源代码的话,请参照下面:

$ git clone https://github.com/frida/frida.git

$ cd frida

$ make

$ export ANDROID_NDK_ROOT=/data/Android/android-sdk-linux/ndk/22.0.6917172

$ sudo apt-get install npm

$ sudo apt install python3-pip

$ pip3 install colorama prompt-toolkit pygments

$ rm -rf build

$ make core-android-x86_64

$ make core-android-x86

# 最后生成的文件在 build/frida-android-x86 build/frida-android-x86_64 
# 如果需要调整编译参数,在releng/setup-env.sh中进行调整 比如: meson_common_flags="['-g']"

如果想直接下载对应版本的`Frida`库并存放到已经编译过的库位置,由于`64`位系统需要兼容`32`位应用,因此需要安装两个版本的动态库:

$ cd ~/AndSrc/aosp/

$ cd out/target/product/generic_x86_64/system/lib64

$ wget https://github.com/frida/frida/releases/download/14.2.2/frida-gadget-14.2.2-android-x86_64.so.xz

$ xz -d frida-gadget-14.2.2-android-x86_64.so.xz

# Android要求动态库必须是lib开头
$ mv frida-gadget-14.2.2-android-x86_64.so libfrida-gadget-14.2.2-android-x86_64.so

$ cd ~/AndSrc/aosp/

$ cd out/target/product/generic_x86_64/system/lib

$ wget https://github.com/frida/frida/releases/download/14.2.2/frida-gadget-14.2.2-android-x86.so.xz

$ xz -d frida-gadget-14.2.2-android-x86.so.xz

# Android要求动态库必须是lib开头
$ mv frida-gadget-14.2.2-android-x86.so libfrida-gadget-14.2.2-android-x86.so

创建`Frida Gadget`库的配置文件

$ cd ~/AndSrc/aosp/

$ cd out/target/product/generic_x86_64/system/lib64

$ touch libfrida-gadget-14.2.2-android-x86_64.config.so

$ cd ~/AndSrc/aosp/

$ cd out/target/product/generic_x86_64/system/lib

$ touch libfrida-gadget-14.2.2-android-x86.config.so

里面的配置内容如下:

{
  "interaction": {
    "type": "listen",
    "address": "127.0.0.1",
    "port": 27042,
    "on_load": "resume"
  }
}

观察`Frida`源代码,发现在 `frida-core/lib/gadget/gadget-glue.c`中配置了`lib`库的入口函数

__attribute__ ((constructor)) static void
frida_on_load (void)
{
  frida_gadget_load (NULL, NULL, NULL);
}

这就意味着只要使用`dlopen`加载`frida-gadget`,我们就能实现对于指定应用的`Hook`。

我们只需要监听子进程,不需要在`Zygote`中加载,因此只需要在源代码` frameworks/base/core/jni/com_android_internal_os_Zygote.cpp` 的`com_android_internal_os_Zygote_nativeForkAndSpecialize`函数中增加加载代码:

    /*
     * 在虚拟机,系统框架初始化完成之后,加载frida框架
     * 需要增加头文件的引用 #include <dlfcn.h>
     */
#if defined(__x86_64__) || defined(__i386__)
      {
          #if defined(__x86_64__)
              #define FRIDA_LIB "/system/lib64/libfrida-gadget-14.2.2-android-x86_64.so"
          #else
              #define FRIDA_LIB "/system/lib/libfrida-gadget-14.2.2-android-x86.so"
          #endif
          const char *name = env->GetStringUTFChars(nice_name, 0);
          void* frida = dlopen(FRIDA_LIB, RTLD_NOW);
          if(NULL == frida) {
              ALOGE("(%s) load frida-gadget(%s) failed, err= %d\n", name, FRIDA_LIB, errno);
          } else {
              ALOGI("(%s) load frida-gadget(%s) success\n", name, FRIDA_LIB);
          }
          env->ReleaseStringUTFChars(nice_name, name);
      }
#endif

具体添加位置如下:

static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
        jint runtime_flags, jobjectArray rlimits,
        jint mount_external, jstring se_info, jstring nice_name,
        jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
        jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
        jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list,
        jboolean mount_data_dirs, jboolean mount_storage_dirs) {
    jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);

    if (UNLIKELY(managed_fds_to_close == nullptr)) {
      ZygoteFailure(env, "zygote", nice_name, "Zygote received a null fds_to_close vector.");
    }

    std::vector<int> fds_to_close =
        ExtractJIntArray(env, "zygote", nice_name, managed_fds_to_close).value();
    std::vector<int> fds_to_ignore =
        ExtractJIntArray(env, "zygote", nice_name, managed_fds_to_ignore)
            .value_or(std::vector<int>());

    std::vector<int> usap_pipes = MakeUsapPipeReadFDVector();

    fds_to_close.insert(fds_to_close.end(), usap_pipes.begin(), usap_pipes.end());
    fds_to_ignore.insert(fds_to_ignore.end(), usap_pipes.begin(), usap_pipes.end());

    fds_to_close.push_back(gUsapPoolSocketFD);

    if (gUsapPoolEventFD != -1) {
      fds_to_close.push_back(gUsapPoolEventFD);
      fds_to_ignore.push_back(gUsapPoolEventFD);
    }

    if (gSystemServerSocketFd != -1) {
        fds_to_close.push_back(gSystemServerSocketFd);
        fds_to_ignore.push_back(gSystemServerSocketFd);
    }

    pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true);

    if (pid == 0) {
      SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                       capabilities, capabilities,
                       mount_external, se_info, nice_name, false,
                       is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
                       is_top_app == JNI_TRUE, pkg_data_info_list,
                       whitelisted_data_info_list,
                       mount_data_dirs == JNI_TRUE,
                       mount_storage_dirs == JNI_TRUE);

    /*
     * 在虚拟机,系统框架初始化完成之后,加载frida框架
     * 需要增加头文件的引用 #include <dlfcn.h>
     */
#if defined(__x86_64__) || defined(__i386__)
      {
          #if defined(__x86_64__)
              #define FRIDA_LIB "/system/lib64/libfrida-gadget-14.2.2-android-x86_64.so"
          #else
              #define FRIDA_LIB "/system/lib/libfrida-gadget-14.2.2-android-x86.so"
          #endif
          const char *name = env->GetStringUTFChars(nice_name, 0);
          void* frida = dlopen(FRIDA_LIB, RTLD_NOW);
          if(NULL == frida) {
              ALOGE("(%s) load frida-gadget(%s) failed, err= %d\n", name, FRIDA_LIB, errno);
          } else {
              ALOGI("(%s) load frida-gadget(%s) success\n", name, FRIDA_LIB);
          }
          env->ReleaseStringUTFChars(nice_name, name);
      }
#endif

    }
    return pid;
}

编译并重新生成系统镜像:

$ cd ~/AndSrc/aosp/

$ export USE_CCACHE=1  

$ source build/envsetup.sh

$ lunch aosp_x86_64-eng

$ cd frameworks/base

$ mmm

# 如果只是替换镜像里面的so文件,不修改源代码,则需要执行 make snod 才能重新生成镜像
# cd ~/AndSrc/aosp/
# make snod
运行镜像

选择system-qemu.img和vendor-qemu.img,这两个镜像是专门为qemu运行制作的,如果选择system.img 和vendor.img,则avd运行失败。

$ cd ~/AndSrc/aosp

$ export ANDROID_BUILD_TOP=~/AndSrc/aosp

$ export PATH=$PATH:$ANDROID_BUILD_TOP/out/host/linux-x86/bin

$ export ANDROID_SWT=$ANDROID_BUILD_TOP/out/host/linux-x86/framework

$ export ANDROID_PRODUCT_OUT=$ANDROID_BUILD_TOP/out/target/product/generic_x86_64

$ ./prebuilts/android-emulator/linux-x86_64/emulator -system ./out/target/product/generic_x86_64/system-qemu.img -data ./out/target/product/generic_x86_64/data.img -ramdisk ./out/target/product/generic_x86_64/ramdisk-qemu.img -vendor ./out/target/product/generic_x86_64/vendor-qemu.img -verbose -show-kernel

上面运行起来的镜像是从`~/AndSrc/aosp/out/debug/target/product/generic/hardware-qemu.ini`即可读取配置信息的,但是这个文件直接修改无效,我们如果需要修改参数,只能从启动参数中设置。
比如我们如果需要增大内存,开启`GPU`的支持,则执行如下命令:

$ ./prebuilts/android-emulator/linux-x86_64/emulator -system ./out/target/product/generic_x86_64/system-qemu.img -data ./out/target/product/generic_x86_64/data.img -ramdisk ./out/target/product/generic_x86_64/ramdisk-qemu.img -vendor ./out/target/product/generic_x86_64/vendor-qemu.img -gpu on -memory 4096 -verbose -show-kernel

参考链接


发布者

《ubuntu 20.04系统AOSP(Android 11)集成Frida》上有4条评论

    1. 这个需要增加JS的解析引擎来处理的,底层注册JS扩展方法到引擎层,常见的就是V8、quickjs,如果曾经开发过 React Native 的话,Facebook也开发了一套JS解析引擎,这一块还是挺多的。

回复 默默 取消回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注