将Frida内置进AOSP中

将Frida内置进AOSP中

准备

  • 系统:Ubuntu20
  • aosp版本:10r2
  • 下载最新的ndk lts,我选择22,我选择最新的lts版本,在make的时候可能会要求让你选择22,所以选择lts的上一个版本即可。
  • 确保GCC的版本在7.5以上
  • 相应的工具链要在PATH中,比如ptython3,Node.JS

编译frida

下载相应的库:

sudo apt-get install build-essential curl git lib32stdc++-9-dev ibc6-dev-i386 nodejs npm python3-dev python3-pip gcc-multilib g++-multilib

将NDK加入到环境变量中:

Export ANDROID_NDK_ROOT=your_ndk_path

Export PATH=$ANDROID_NDK_ROOT:$PATH

下载frida源码:

git clone –recurse-submodules https://github.com/frida/frida.git

官方toolchainsdk下载地址如下

其中20210123fridareleng/deps.mk中的frida_deps_version

后面部分则是toolchain-{平台+架构}.tar.bz2

https://build.frida.re/deps/20210123/toolchain-linux-x86_64.tar.bz2

https://build.frida.re/deps/20210123/sdk-linux-x86_64.tar.bz2

https://build.frida.re/deps/20210123/sdk-android-arm.tar.bz2

https://build.frida.re/deps/20210123/sdk-android-arm64.tar.bz2

可以手动下载上面的文件,然后在frida的文件夹下新建build文件夹

然后将文件放入build即可

现在执行releng/setup-env.sh

不过个人认为手动方便一点,因为编译时的网络访问问题真的烦人(省略N字)

编译frida:

make core-android-arm64

编译成功:

编译AOSP10

链接:https://pan.baidu.com/s/1MYTdT4pxMo8vsq5CxPFVZg

提取码:yuov

下载aosp 10 源码。

解压后,下载驱动文件:https://developers.google.com/android/drivers#sailfishqp1a.190711.020

再执行驱动文件即可。

下载相应的库:

sudo apt-get install -y openjdk-8-jdk

sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev libgl1-mesa-dev libxml2-utils xsltproc unzip

编译源码

source build/envsetup.sh

lunch

选择好对应的版本就进行编译

M

如果出现如下错误:

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
[ 37% 50/135] test github.com/google/blueprint/pathtools
FAILED: out/soong/.bootstrap/blueprint-pathtools/test/test.passed
out/soong/.bootstrap/bin/gotestrunner -p ./build/blueprint/pathtools -f out/soong/.bootstrap/blueprint-pathtools/test/test.passed -- out/soong/.bootstrap/blueprint-pathtools/test/test -test.short
--- FAIL: TestGlobEscapes (0.00s)
--- FAIL: TestGlobEscapes//* (0.00s)
glob_test.go:562: incorrect matches list:
glob_test.go:562: pattern: "/"
glob_test.go:562: got: []string{"/", "a/", "b", "/a", "/b/", "/b/b", "a/a"}
glob_test.go:562: expected: []string{"", "/", "?", "a/", "b", "/", "/a", "/b/", "/b/b", "a/a"}
--- FAIL: TestGlobEscapes//* (0.00s)
glob_test.go:562: incorrect matches list:
glob_test.go:562: pattern: "/\"
glob_test.go:562: got: []string(nil)
glob_test.go:562: expected: []string{"", "/"}
--- FAIL: TestGlobEscapes/**/* (0.00s)
glob_test.go:562: incorrect matches list:
glob_test.go:562: pattern: "\\/"
glob_test.go:562: got: []string{"/a", "/b/"}
glob_test.go:562: expected: []string{"/", "/a", "/b/"}
--- FAIL: TestGlobEscapes/**//* (0.00s)
glob_test.go:562: incorrect matches list:
glob_test.go:562: pattern: "\\//"
glob_test.go:562: got: []string{"/a", "/b/", "/b/b"}
glob_test.go:562: expected: []string{"/", "/a", "/b/", "/b/b"}
FAIL
05:04:52 soong bootstrap failed with: exit status 1

该错误应该是源码问题,所以我后来使用repo重新同步了一次源码

1
2
3
4
5
6
7
8
9
10
11
12
13
// 创建bin目录
mkdir ~/bin
PATH=~/bin:$PATH
// 下载repo启动器
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
// 创建AOSP源码目录
mkdir aosp10r2
cd aosp10r2
// 初始化源码仓库, 选择与设备对应的源码tag版本
repo init -u https://android.googlesource.com/platform/manifest -b android-10.0.0_r2
// 下载
repo sync

我这边是挂梯子下载的,速度还行,如果不行请使用清华园或者是中科大。北清华、南科大。

编译

M -j8

修改AOSP10r2源码将frida内置

方案一,使用frida-gadget配合config文件来做配合。

根据gadget官网文档中描述的,该方案已经被人利用成功过,所以直接站在巨人的肩膀上可以省力不少,其次,该方案不需要root权限,对于内置frida来说很方便,因为root这个权限也是相当危险的。

方案二,userdebug模式,将frida内置到系统中

将编译完成的frida-gadget.so拷贝出来,放到aosp10r2/out/target/product/sailfish/system/lib64/下

如果是32位的gadget,就放到aosp10r2/out/target/product/sailfish/system/lib/下,并都添加lib前缀。

其次还需要配置config文件,文件名为libfrida-gadget.config.so,lib开头,config.so结尾,中间的名字按照放到lib下的firda文件名来确定,内容如下:

1
2
3
4
5
6
7
8
{
"interaction": {
"type": "listen",
"address": "127.0.0.1",
"port": 27042,
"on_load": "resume"
}
}

64位frida-gadget.so在frida/build/frida-android-arm64/lib/frida/64/frida-gadget.so

修改aosp/framework/base/core/jni/com_android_internal_os_Zygote.cpp中的com_android_internal_os_Zygote_nativeForkAndSpecialize函数,以及需要在文件上面添加#include <dlfcn.h>,导入dlopen相关函数。

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
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) {
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);
}

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

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);
#if defined(__arm__) || defined(__arm64__)
{
#if defined(__arm__)
#define FRIDA_LIB "/system/lib/libfrida-gadget_arm_32.so"
#else
#define FRIDA_LIB "/system/lib64/libfrida-gadget_arm_64.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;
}

刷机

Frida-ps -U没问题,但是firda -UF 会有问题。

参考: