参考 ubuntu 20.04编译Android 11源代码&模拟器 完成Android 11源代码的编译工作,保证能编译通过。
想自己手工编译Frida
源代码的话,请参照下面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
$ 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
位应用,因此需要安装两个版本的动态库:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$ 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
库的配置文件
1 2 3 4 5 6 7 8 9 10 11 |
$ 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 |
里面的配置内容如下:
1 2 3 4 5 6 7 8 |
{ "interaction": { "type": "listen", "address": "127.0.0.1", "port": 27042, "on_load": "resume" } } |
观察Frida
源代码,发现在 frida-core/lib/gadget/gadget-glue.c
中配置了lib
库的入口函数
1 2 3 4 5 |
__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
函数中增加加载代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/* * 在虚拟机,系统框架初始化完成之后,加载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 |
具体添加位置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
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; } |
编译并重新生成系统镜像:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ 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运行失败。
1 2 3 4 5 6 7 8 9 10 11 |
$ 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
的支持,则执行如下命令:
1 |
$ ./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 |
参考链接
- xposed源码编译与集成
- ubuntu 20.04编译Android 11源代码&模拟器
- Magisk与EdXposed框架安装实践(Android P及以上)
- YAHFA
- YAHFA--ART环境下的Hook框架
- YAHFA--ART环境下的Hook框架
- android N : UnsatisfiedLinkError 只能访问设置为公用库的so库
- linux下SO中INIT函数中添加自己的代码
- Framework基础:Android N 公共so库怎么定义呢?
- 在Android N上对Java方法做hook遇到的坑
- EdXposed & ART Hook 细节分享
- linkedin / dexmaker
- Android动态类生成预加载-dexmaker使用
- Android Frida 框架
- Frida源码分析
- hook工具frida原理及使用
- Global hook for customized AOSP
- Frida官方文档-Gadget
- Android ART VM的启动流程(五)
- Frida 安装和使用
- Frida releases
- Frida's Gadget Injection on Android: No Root, 2 Methods
- Android8.0 系统启动之孵化
- Android runtime机制(二)zygote进程的启动流程
- Gadget
- build python-macos on Apple M1 failed #1565
- Understanding Android: Zygote and DalvikVM
- 这恐怕是学习Frida最详细的笔记了(3)
大佬 看了你的文章我也尝试改了下 但是有些问题想请教 不知道如何联系你
留言即可
有个疑问,怎么加载我们平时写的js脚本,对app进行hook呢
这个需要增加JS的解析引擎来处理的,底层注册JS扩展方法到引擎层,常见的就是V8、quickjs,如果曾经开发过 React Native 的话,Facebook也开发了一套JS解析引擎,这一块还是挺多的。