首页
论坛
课程
招聘
[原创]修改MagiskV24.1源码隐藏APK,使其以Root用户运行
2022-2-24 23:28 22596

[原创]修改MagiskV24.1源码隐藏APK,使其以Root用户运行

2022-2-24 23:28
22596

 

title: 修改MagiskV24.1源码隐藏APK,使其以Root用户运行
date: 2022-02-24 22:30:51
categories:

  • android
  • source_code
    tags:
  • Magisk

修改MagiskV24.1源码隐藏APK,使其以Root用户运行

修改Magisk源码,绑定APP安装包到Magisk中,在安装完Magisk后,APP能隐藏安装,并且用Root用户运行。

 

可以利用Magisk制作刷机包,这样ROM中就自带自己的APP(Root,隐藏运行)。

Magisk编译

编译参考官方给的ReadMe文档。https://github.com/topjohnwu/Magisk

  • 下载Android Studio,并且进行初始化安装。

  • 克隆源码

    1
    git clone --recurse-submodules https://github.com/topjohnwu/Magisk.git

    注意一定要加上--recurse-submodules将项目中子模块的源码一起克隆下来。

  • 安装Python 3.6+

    如果是Windows环境需要选择'Add Python to PATH',安装完成后执行 pip install colorama

  • 将Android Studio中的JDK加入到环境变量中。

    • macOS: export JAVA_HOME="/Applications/Android Studio.app/Contents/jre/Contents/Home"
    • Linux: export PATH="/path/to/androidstudio/jre/bin:$PATH"
    • Windows: Add C:\Path\To\Android Studio\jre\bin to environment variable PATH
  • 设置环境变量 ANDROID_SDK_ROOT 来指向Android Sdk的文件夹。这个路径可以在Android Studio中找到。

    注意:在编译不同版本的Magisk时,这个环境变量名是不相同。

  • 在项目根目录下执行 ./build.py ndk 。脚本会自动下载和安装对应版本的NDK。

    注意:

    1.在编译不同版本的Magisk时,需要的NDK版本不同。

    2.在切换编译不同版本Magisk时,注意设置不同的SDK路径。因为脚本在安装NDK(在Sdk路径下)时会生成都叫magisk的NDK,这样就会导致NDK的版本不对,编译会失败。

    image-20220223095148498

  • 执行脚本build.py开始编译。这里选择全部编译Release版本。build.py -r all

Magisk源码修改

将APK文件编译进magiskinit文件

参考Magisk自己的代码:

1
2
3
4
with open(stub, 'rb') as src:
    text = binary_dump(src, 'manager_xz')
    write_if_diff(op.join(native_gen_path, 'binaries.h'), text)
# 这里Magisk将自己的Magisk管理器转成二进制数组的形式保存在binaries.h文件中。

将我们自己的文件也保存到binaries.h文件中。

1
2
3
4
5
6
7
8
9
10
11
12
aas = op.join('native', 'aas.apk')
aab = op.join('native', 'aab.apk')
aac = op.join('native', 'xxxx', 'arm64-v8a', 'xxx')
with open(aas, 'rb') as src:
   text = binary_dump(src, 'aas_xz')
   write_if_diff(op.join(native_gen_path, 'binaries.h'), text)
with open(aab, 'rb') as src:
   text = binary_dump(src, 'aab_xz')
   write_if_diff(op.join(native_gen_path, 'binaries.h'), text)
with open(aac, 'rb') as src:
   text = binary_dump(src, 'aasx_xz')
   write_if_diff(op.join(native_gen_path, 'binaries.h'), text)

但是binaries.h不会在后面追加,所以还需要修改文件的打开方式。

1
2
3
4
5
6
7
8
9
def write_if_diff(file_name, text):
    do_write = True
    if op.exists(file_name):
        with open(file_name, 'r') as f:
            orig = f.read()
        do_write = orig != text
    if do_write:
        with open(file_name, 'a+') as f:#追加模式
            f.write(text)

释放APK文件

init.cpp文件中添加释放文件的方法。如果在其他地方应用,注意在init.hpp中添加需要的函数声明。

1
2
3
4
5
6
7
8
9
static int dump_aas(const char *path, mode_t mode) {
    int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
    if (fd < 0)
        return 1;
    if (!unxz(fd, service_xz, sizeof(aas_xz)))
        return 1;
    close(fd);
    return 0;
}

main函数中添加调用释放文件的方法。

1
2
3
4
5
6
7
if (argc > 1 && argv[1] == "-x"sv) {
    if (argc > 2 && argv[2] == "manager"sv)
        return dump_manager(argv[3], 0644);
    else if (argc > 2 && argv[2] == "aas"sv)
        return dump_aas(argv[3], 0644);
    return 1;
}

修改exec_script

在执行脚本这个函数中,默认用busybox,修改为/system/bin/sh

1
2
3
4
5
6
7
void exec_script(const char *script) {
    exec_t exec {
        .pre_exec = set_script_env,
        .fork = fork_no_orphan
    };
    exec_command_sync(exec, "/system/bin/sh", "-c", script);
}

安装APK和启动服务

bootstage.cpp中的boot_complete函数中添加当设备启动完成时安装APK和启动服务。

1
2
3
4
5
6
7
8
9
10
11
12
if (access(INJECTIONSERVICEAPK, F_OK) == 0) {
    rename(INJECTIONSERVICEAPK, "/data/aac.apk");
    install_apk("/data/aac.apk");
} else {
    auto init = MAGISKTMP + "/magiskinit";
    exec_command_sync(init.data(), "-x", "xxxx", "/data/aas.apk");
    install_apk("/data/aas.apk");
}
// run cmd
exec_script("cmd ...");
// run sh
//exec_command_sync("/system/bin/sh");

设置su为静默允许

su_daemon.cppget_su_info函数设置静默允许。

1
2
3
static shared_ptr<su_info> get_su_info(unsigned uid) {
    info->access = SILENT_SU_ACCESS;
}

su改名xx

将su改名为sp,需要修改2处。

  • magisk.hpp

    1
    constexpr const char *applet_names[] = { "xx", "resetprop", "magiskhide", nullptr };
  • applets.cpp

    1
    constexpr const char *applets[] = { "xx", "resetprop", "zygisk", nullptr };

总结

修改文件 修改目的
build.py 将另外的附件的apk和文件编译进最后的magiskinit文件中。
applets.cpp 将su更名为sp。
bootstage.cpp 执行dump函数、安装apk、启动服务。
magisk.hpp 将su更名为sp。定义部分宏。
init.cpp 提供dump文件的函数,并在main函数中调用。
init.hpp dump函数声明。
script.cpp /system/bin/sh代替busybox
su_daemon.cpp 设置su默认静默允许。

离线编译

在某些环境下可能全程不能联网,这个时候就需要我们进行离线编译。

 

ndk下载

 

build.py ndk命令时,脚本会自动联网下载对应的ndk,如果不能联网就会报错。

  • 先利用外网环境确定需要的ndk版本,在官网上下载后,复制到项目根目录下。

  • 修改脚本build.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    def setup_ndk(args):
        os_name = platform.system().lower()
        ndk_ver = config['ndkVersion']
        url = f'https://dl.google.com/android/repository/android-ndk-r{ndk_ver}-{os_name}.zip'
        ndk_zip = 'android-ndk-r23b-linux.zip'
     
        # header(f'* Downloading {ndk_zip}')
        # with urllib.request.urlopen(url) as response, open(ndk_zip, 'wb') as out_file:
        #   shutil.copyfileobj(response, out_file)
     
        header('* Extracting NDK zip')
        rm_rf(ndk_path)
        ...

gradle-wrapper.jar联网下载

 

在执行clean或者构建是会调用到这个Jar包,这个jar会联网,此时没有网络也会报错。

 

删除根目录下的grade(Linux下)脚本的最后一行的调用代码。

 

image-20220224113408238

 

build.py all编译二进制失败。

 

如果我们之前清理了整个项目,/out/目录下是不会编译出app-release.apkstub-release.apk,而在编译二进制之前要确保这两个apk已经编译完成了。

 

用之前外网已经编译好的apk复制到离线环境的/out/路径下,重新编译就能编译出整个项目了。


看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

收藏
点赞5
打赏
分享
最新回复 (9)
雪    币: 275
活跃值: 活跃值 (345)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
笑对VS人生 活跃值 2022-2-25 19:23
2
0
支持个,完整源码能否贴下
雪    币: 1028
活跃值: 活跃值 (914)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
nisosaikou 活跃值 1 2022-2-25 20:56
3
0
笑对VS人生 支持个,完整源码能否贴下
完整的代码几百M,有点大的,修改的代码全部写在了这里,可以参考总结的文件索引。
雪    币: 22
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
万里星河 活跃值 2022-2-27 10:38
4
0
没太明白这个效果 什么叫隐藏apk 使其以root用户运行?这样做有什么意义吗
雪    币: 1028
活跃值: 活跃值 (914)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
nisosaikou 活跃值 1 2022-2-27 23:44
5
0
万里星河 没太明白这个效果 什么叫隐藏apk 使其以root用户运行?这样做有什么意义吗[em_13]
理论上来说没啥意义,给刷机时候用的
雪    币: 625
活跃值: 活跃值 (2707)
能力值: ( LV8,RANK:125 )
在线值:
发帖
回帖
粉丝
ChicWalk 活跃值 2 2022-3-1 21:12
6
0
理论没啥意义,但是技术上来讲还是有意义的
雪    币: 289
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
tmi 活跃值 2022-3-25 10:59
7
0
今天正好用到了,前来留言
雪    币: 235
活跃值: 活跃值 (274)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
给我快乐 活跃值 2022-3-25 14:11
8
0
这个我可不可以理解成过root检测?
雪    币: 724
活跃值: 活跃值 (488)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hanhaochi 活跃值 2022-3-29 10:23
9
0
给我快乐 这个我可不可以理解成过root检测?
肯定不是啊,app都已经有root权限了,该检测还是会被检测啊,楼上都在说理论上没啥意义。
雪    币: 202
活跃值: 活跃值 (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Jecelyin 活跃值 2022-4-19 10:02
10
0
挺好的思路
游客
登录 | 注册 方可回帖
返回