使用 Bliss OS 搭建带 Magisk 的 Android 9.0 调试环境 ======================== - VirtualBox 建立机器,选择 Linux 2.6 / 3.x / 4.x 64-bit,CPU 核数、内存、磁盘、显存拉高,加载 Bliss OS 安装镜像,图像驱动器选 VBoxVGA,3D 加速不要勾选。可按需增加一个 Bridged Adapter 或者 Host-only Adapter,方便之后网络连接。 - 使用 VBoxManager 命令行工具增加一个视频模式: ``` VBoxManage setextradata "<虚拟机名称>" "CustomVideoMode1" "640x1080x32" ``` 640x1080x32 中分辨率可以自行设置,但最后的色彩位数一定要置为 32。 - 安装过程同安装 Android x86 的过程,中间有几个点要注意的。 - 启动后先进 debug mode ``` cd /mnt/grub cp menu.lst menu.lst.bak vi menu.lst # 主启动项上加参数 vga=864,去掉 quiet。如 864 不对,加 vga=ask 后进系统确认下数字,再 16 进制转成 10 进制。 ``` - `sync` 后 `Host键 + R` - 进系统后,安装必要软件(可连接 VirtWifi 后,通过 10.0.2.2 访问宿主机)。使用以下脚本传输 ADB 公钥到系统:(调出软键盘按 Alt+F1 可以进 root 命令行,Alt+F7 切回来) ``` #!/bin/sh # receive-adb-key.sh # 后续可将整个文件部署至 Magisk 的 service.d # 再将 ip addr 的这句移至 post-fs-data.d nohup sh -c 'while true; do if [ "$(getprop sys.boot_completed)" = "1" ]; then break ; fi ; sleep 2 ; done ; ip addr add 192.168.68.121/24 dev eth1;' > /dev/null & THIS_SCRIPT_PATH="$(realpath "$0")" if [ "$1" = "worker" ]; then exec 2>&1 echo -e Please input content from file "\"adbkey.pub\":""\r" >&2 echo -e ==================="\r" >&2 read INPUT_ADB_KEY echo "$INPUT_ADB_KEY" >> /data/misc/adb/adb_keys chown system:shell /data/misc/adb/adb_keys chmod 0640 /data/misc/adb/adb_keys stop adbd setprop service.adb.tcp.port 5555 setprop persist.adb.tcp.port 5555 start adbd echo -e ==================="\r" >&2 echo -e Done."\r" >&2 exit fi stop adbd setprop service.adb.tcp.port 5555 setprop persist.adb.tcp.port 5555 start adbd while true; do busybox nc -l -p 15555 -e sh "$THIS_SCRIPT_PATH" worker sleep 1 done ``` - 修改 Magisk。checkout 8aaa45c62(修改过版本号的 23.0,注意不要直接 checkout tag v23.0) ``` diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4c50bed2b..33999e6c4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -27,7 +27,7 @@ android { vectorDrawables.useSupportLibrary = true versionName = Config.version versionCode = Config.versionCode - ndk.abiFilters("armeabi-v7a", "arm64-v8a", "x86", "x86_64") + ndk.abiFilters("x86") } buildTypes { @@ -100,10 +100,10 @@ val createStubLibs by tasks.registering { doLast { val arm64 = project.file("src/main/jniLibs/arm64-v8a/libstub.so") arm64.parentFile.mkdirs() - arm64.createNewFile() + // arm64.createNewFile() val x64 = project.file("src/main/jniLibs/x86_64/libstub.so") x64.parentFile.mkdirs() - x64.createNewFile() + // x64.createNewFile() } } diff --git a/app/src/main/java/com/topjohnwu/magisk/core/Const.kt b/app/src/main/java/com/topjohnwu/magisk/core/Const.kt index 5ddb8c148..386f80e0a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/Const.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/Const.kt @@ -8,8 +8,8 @@ import java.io.File @Suppress("DEPRECATION") object Const { - val CPU_ABI: String = Build.SUPPORTED_ABIS[0] - val CPU_ABI_32: String = Build.SUPPORTED_32_BIT_ABIS.firstOrNull() ?: CPU_ABI + val CPU_ABI: String = "x86_64" + val CPU_ABI_32: String = "x86" // Paths lateinit var MAGISKTMP: String diff --git a/native/jni/Application.mk b/native/jni/Application.mk index e1d65f416..c4c214e17 100644 --- a/native/jni/Application.mk +++ b/native/jni/Application.mk @@ -12,7 +12,7 @@ endif # Build 64 bit binaries ifdef B_64BIT -APP_ABI += arm64-v8a x86_64 +APP_ABI += arm64-v8a endif # Busybox should use stock libc.a diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index 336a4b0ea..7f869c96d 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -26,20 +27,49 @@ static bool safe_mode = false; #define MNT_DIR_IS(dir) (me->mnt_dir == string_view(dir)) #define SETMIR(b, part) sprintf(b, "%s/" MIRRDIR "/" #part, MAGISKTMP.data()) #define SETBLK(b, part) sprintf(b, "%s/" BLOCKDIR "/" #part, MAGISKTMP.data()) +#define SETTMPBLK(b, part) sprintf(b, "%s/tmpblk_" #part, MAGISKTMP.data()) +#define SETTMPMNT(b, part) sprintf(b, "%s/tmpmnt_" #part, MAGISKTMP.data()) -#define do_mount_mirror(part, flag) {\ +#define do_mount_mirror(part, flag, is_loop) {\ SETMIR(buf1, part); \ SETBLK(buf2, part); \ unlink(buf2); \ - mknod(buf2, S_IFBLK | 0600, st.st_dev); \ + if (is_loop) {\ + SETTMPBLK(buf3, part); \ + mknod(buf3, S_IFBLK | 0600, st.st_dev); \ + tmp_dev_fd = open(buf3, O_RDWR); \ + if (tmp_dev_fd < -1) { LOGE("%s tmp_dev_fd fail\n", buf1); return false; } \ + loop_dev_fd = open("/dev/block/loop6", O_RDWR); \ + if (loop_dev_fd < -1) { LOGE("%s loop_dev_fd fail\n", buf1); return false; } \ + if (ioctl(loop_dev_fd, 0x4C00 /* LOOP_SET_FD */, tmp_dev_fd) < 0) { LOGE("%s ioctl fail\n", buf1); return false; } \ + close(tmp_dev_fd); \ + if (fstat(loop_dev_fd, &loop_st) < 0) { LOGE("%s fstat fail\n", buf1); return false; } \ + close(loop_dev_fd); \ + mknod(buf2, S_IFBLK | 0600, loop_st.st_rdev); \ + } else { \ + mknod(buf2, S_IFBLK | 0600, st.st_dev); \ + } \ xmkdir(buf1, 0755); \ - xmount(buf2, buf1, me->mnt_type, flag, nullptr); \ + if (flag & MS_BIND) { \ + /* shunf4: for BlissOS's /data partition, we need to mount the subdirectory "/bliss-x86-11.13/data" of the block device, thus MS_BIND. */ \ + SETTMPMNT(buf3, part); \ + xmkdir(buf3, 0755); \ + xmount(buf2, buf3, me->mnt_type, flag & ~MS_BIND, nullptr); \ + tmp_data_root = opendir(buf3); \ + if (!tmp_data_root) { LOGE("%s opendir fail\n", buf1); return false; } \ + buf4[0] = '\0'; \ + while ((tmp_data_dirent = readdir(tmp_data_root)) != NULL) { if (strncmp(tmp_data_dirent->d_name, "bliss-", 6) == 0) { sprintf(buf4, "%s/%s/data", buf3, tmp_data_dirent->d_name); break; } } \ + closedir(tmp_data_root); \ + if (buf4[0] == '\0') { LOGE("%s bliss dir not found\n", buf1); return false; } \ + xmount(buf4, buf1, 0, MS_BIND, nullptr); \ + } else \ + xmount(buf2, buf1, me->mnt_type, flag, nullptr); \ LOGI("mount: %s\n", buf1); \ } -#define mount_mirror(part, flag) \ +#define mount_mirror(part, flag, is_loop) \ else if (MNT_DIR_IS("/" #part) && me->mnt_type != "tmpfs"sv && lstat(me->mnt_dir, &st) == 0) \ - do_mount_mirror(part, flag) + do_mount_mirror(part, flag, is_loop) #define link_mirror(part) \ SETMIR(buf1, part); \ @@ -61,17 +91,24 @@ else if (MNT_DIR_IS(dir) && me->mnt_type != "tmpfs"sv) { \ static void mount_mirrors() { char buf1[4096]; char buf2[4096]; + char buf3[4096]; + char buf4[4096]; + int tmp_dev_fd; + int loop_dev_fd; + struct stat loop_st; + DIR* tmp_data_root; + struct dirent* tmp_data_dirent; LOGI("* Mounting mirrors\n"); parse_mnt("/proc/mounts", [&](mntent *me) { struct stat st; if (0) {} - mount_mirror(system, MS_RDONLY) - mount_mirror(vendor, MS_RDONLY) - mount_mirror(product, MS_RDONLY) - mount_mirror(system_ext, MS_RDONLY) - mount_mirror(data, 0) + mount_mirror(system, MS_RDONLY, 1) + mount_mirror(vendor, MS_RDONLY, 0) + mount_mirror(product, MS_RDONLY, 0) + mount_mirror(system_ext, MS_RDONLY, 0) + mount_mirror(data, MS_BIND, 0) link_orig(cache) link_orig(metadata) link_orig(persist) @@ -88,7 +125,7 @@ static void mount_mirrors() { parse_mnt("/proc/mounts", [&](mntent *me) { struct stat st; if (MNT_DIR_IS("/") && me->mnt_type != "rootfs"sv && stat("/", &st) == 0) { - do_mount_mirror(system_root, MS_RDONLY) + do_mount_mirror(system_root, MS_RDONLY, 0) return false; } return true; ``` This is my build (Download and rename extension to .zip): `https://user-images.githubusercontent.com/20991618/147526309-be931ff0-744d-4169-8414-cc67f4c47210.gif` - 安装修改版本后的 Magisk: https://web.archive.org/web/20210228102356/https://wiki.blissroms.org/index.php?title=Bliss_OS/Extras - 目前使用 Magisk 23.0 正式版,因为需要在隐藏 Root 的情况下 hook,因此 MagiskHide 必不可少。 - ~但 Magisk 23.0 的 APK 无法在 x86_64 下处理 boot.img(提示失败),因此在 Shell 下解包 Magisk 的 APK,手动调用 boot_patch.sh。~ 修改后的 Magisk 23.0 已经可以按原教程正常使用。 - 重启后进 debug 模式部署三个文件,**记得删掉两处的 su 二进制文件。没有 SuperUser APP, 无需删除。** 多打几次 sync 总没坏处。 - ~将 /data/app/com.topj..../lib/arm 下的 lib*.so 文件全部换成 x86 版本。~ 修改后的 Magisk 无需这步。 - 再重启到系统,进 Magisk,应提示已经安装,无任何错误。 - ~但切换到 log 标签页看不到日志,检查 /cache/magisk.log 发现启动时出现了 busybox 错误,原因是 /sbin/.magisk/busybox/busybox 链接到了 ARM 版本的 busybox。做 Snapshot 后替换,将 /data/adb/magisk/ 下有关二进制全部链向 x86 的版本,重启。~ 修改后的 Magisk 无需这步。 - 现在可以启动 MagiskHide、隐藏 Magisk App、安装 receive-adb-key 服务、安装各种模块了。 - 其他调整: - Settings - Display - Smallest width 改为 480dp,可以调整 DPI。 - `VBoxManage modifyvm "" --defaultfrontend headless`