You've already forked ZygiskNext
mirror of
https://github.com/Dr-TSNG/ZygiskNext.git
synced 2025-08-27 23:46:34 +00:00
add 32 bit support back & fix x86-64 support & fix jni hook restore (#59)
* Add back 32 bit support & some fix * fix system server crash on android 10 * Refine code --------- Co-authored-by: Nullptr <noreply@nullptr.icu>
This commit is contained in:
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -46,6 +46,8 @@ jobs:
|
|||||||
rustup override set nightly
|
rustup override set nightly
|
||||||
rustup target add aarch64-linux-android
|
rustup target add aarch64-linux-android
|
||||||
rustup target add x86_64-linux-android
|
rustup target add x86_64-linux-android
|
||||||
|
rustup target add i686-linux-android
|
||||||
|
rustup target add armv7-linux-androideabi
|
||||||
|
|
||||||
- name: Set up ccache
|
- name: Set up ccache
|
||||||
uses: hendrikmuhs/ccache-action@v1.2
|
uses: hendrikmuhs/ccache-action@v1.2
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
ndkBuild {
|
ndkBuild {
|
||||||
abiFilters("arm64-v8a", "x86_64")
|
|
||||||
ccachePatch?.let {
|
ccachePatch?.let {
|
||||||
arguments += "NDK_CCACHE=$it"
|
arguments += "NDK_CCACHE=$it"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,13 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
constexpr auto kCPSocketPath = "/dev/zygisk/cp.sock";
|
#if defined(__LP64__)
|
||||||
|
# define LP_SELECT(lp32, lp64) lp64
|
||||||
|
#else
|
||||||
|
# define LP_SELECT(lp32, lp64) lp32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
constexpr auto kCPSocketPath = "/dev/zygisk/" LP_SELECT("cp32", "cp64") ".sock";
|
||||||
|
|
||||||
class UniqueFd {
|
class UniqueFd {
|
||||||
using Fd = int;
|
using Fd = int;
|
||||||
|
|||||||
@@ -5,16 +5,13 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef LOG_TAG
|
#ifndef LOG_TAG
|
||||||
#define LOG_TAG "zygisk-core"
|
#if defined(__LP64__)
|
||||||
|
# define LOG_TAG "zygisk-core64"
|
||||||
|
#else
|
||||||
|
# define LOG_TAG "zygisk-core32"
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LOG_DISABLED
|
|
||||||
#define LOGD(...)
|
|
||||||
#define LOGV(...)
|
|
||||||
#define LOGI(...)
|
|
||||||
#define LOGW(...)
|
|
||||||
#define LOGE(...)
|
|
||||||
#else
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#define LOGD(...) logging::log(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
#define LOGD(...) logging::log(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
||||||
#define LOGV(...) logging::log(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
|
#define LOGV(...) logging::log(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
|
||||||
@@ -27,7 +24,6 @@
|
|||||||
#define LOGE(...) logging::log(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
|
#define LOGE(...) logging::log(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
|
||||||
#define LOGF(...) logging::log(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__)
|
#define LOGF(...) logging::log(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__)
|
||||||
#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno))
|
#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno))
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace logging {
|
namespace logging {
|
||||||
void setfd(int fd);
|
void setfd(int fd);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ using xstring = jni_hook::string;
|
|||||||
|
|
||||||
static void hook_unloader();
|
static void hook_unloader();
|
||||||
static void unhook_functions();
|
static void unhook_functions();
|
||||||
|
static void restore_jni_env(JNIEnv *env);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -84,8 +85,16 @@ struct HookContext {
|
|||||||
vector<RegisterInfo> register_info;
|
vector<RegisterInfo> register_info;
|
||||||
vector<IgnoreInfo> ignore_info;
|
vector<IgnoreInfo> ignore_info;
|
||||||
|
|
||||||
HookContext() : env(nullptr), args{nullptr}, process(nullptr), pid(-1), info_flags(0),
|
HookContext(JNIEnv *env, void *args) :
|
||||||
hook_info_lock(PTHREAD_MUTEX_INITIALIZER) { g_ctx = this; }
|
env(env), args{args}, process(nullptr), pid(-1), info_flags(0),
|
||||||
|
hook_info_lock(PTHREAD_MUTEX_INITIALIZER) {
|
||||||
|
static bool restored_env = false;
|
||||||
|
if (!restored_env) {
|
||||||
|
restore_jni_env(env);
|
||||||
|
restored_env = true;
|
||||||
|
}
|
||||||
|
g_ctx = this;
|
||||||
|
}
|
||||||
~HookContext();
|
~HookContext();
|
||||||
|
|
||||||
/* Zygisksu changed: Load module fds */
|
/* Zygisksu changed: Load module fds */
|
||||||
@@ -685,12 +694,6 @@ HookContext::~HookContext() {
|
|||||||
|
|
||||||
should_unmap_zygisk = true;
|
should_unmap_zygisk = true;
|
||||||
|
|
||||||
// Restore JNIEnv
|
|
||||||
if (env->functions == new_functions) {
|
|
||||||
env->functions = old_functions;
|
|
||||||
delete new_functions;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unhook JNI methods
|
// Unhook JNI methods
|
||||||
for (const auto &[clz, methods] : *jni_hook_list) {
|
for (const auto &[clz, methods] : *jni_hook_list) {
|
||||||
if (!methods.empty() && env->RegisterNatives(
|
if (!methods.empty() && env->RegisterNatives(
|
||||||
@@ -713,6 +716,12 @@ HookContext::~HookContext() {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
static void restore_jni_env(JNIEnv *env) {
|
||||||
|
env->functions = old_functions;
|
||||||
|
delete new_functions;
|
||||||
|
new_functions = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static bool hook_commit() {
|
static bool hook_commit() {
|
||||||
if (lsplt::CommitHook()) {
|
if (lsplt::CommitHook()) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ namespace {
|
|||||||
void *nativeForkAndSpecialize_orig = nullptr;
|
void *nativeForkAndSpecialize_orig = nullptr;
|
||||||
[[clang::no_stack_protector]] jint nativeForkAndSpecialize_l(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jstring instruction_set, jstring app_data_dir) {
|
[[clang::no_stack_protector]] jint nativeForkAndSpecialize_l(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jstring instruction_set, jstring app_data_dir) {
|
||||||
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<decltype(&nativeForkAndSpecialize_l)>(nativeForkAndSpecialize_orig)(
|
reinterpret_cast<decltype(&nativeForkAndSpecialize_l)>(nativeForkAndSpecialize_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, instruction_set, app_data_dir
|
||||||
@@ -18,9 +16,7 @@ void *nativeForkAndSpecialize_orig = nullptr;
|
|||||||
[[clang::no_stack_protector]] jint nativeForkAndSpecialize_o(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jstring instruction_set, jstring app_data_dir) {
|
[[clang::no_stack_protector]] jint nativeForkAndSpecialize_o(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jstring instruction_set, jstring app_data_dir) {
|
||||||
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
args.fds_to_ignore = &fds_to_ignore;
|
args.fds_to_ignore = &fds_to_ignore;
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<decltype(&nativeForkAndSpecialize_o)>(nativeForkAndSpecialize_orig)(
|
reinterpret_cast<decltype(&nativeForkAndSpecialize_o)>(nativeForkAndSpecialize_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir
|
||||||
@@ -32,9 +28,7 @@ void *nativeForkAndSpecialize_orig = nullptr;
|
|||||||
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
args.fds_to_ignore = &fds_to_ignore;
|
args.fds_to_ignore = &fds_to_ignore;
|
||||||
args.is_child_zygote = &is_child_zygote;
|
args.is_child_zygote = &is_child_zygote;
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<decltype(&nativeForkAndSpecialize_p)>(nativeForkAndSpecialize_orig)(
|
reinterpret_cast<decltype(&nativeForkAndSpecialize_p)>(nativeForkAndSpecialize_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir
|
||||||
@@ -47,9 +41,7 @@ void *nativeForkAndSpecialize_orig = nullptr;
|
|||||||
args.fds_to_ignore = &fds_to_ignore;
|
args.fds_to_ignore = &fds_to_ignore;
|
||||||
args.is_child_zygote = &is_child_zygote;
|
args.is_child_zygote = &is_child_zygote;
|
||||||
args.is_top_app = &is_top_app;
|
args.is_top_app = &is_top_app;
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<decltype(&nativeForkAndSpecialize_q_alt)>(nativeForkAndSpecialize_orig)(
|
reinterpret_cast<decltype(&nativeForkAndSpecialize_q_alt)>(nativeForkAndSpecialize_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app
|
||||||
@@ -66,9 +58,7 @@ void *nativeForkAndSpecialize_orig = nullptr;
|
|||||||
args.whitelisted_data_info_list = &whitelisted_data_info_list;
|
args.whitelisted_data_info_list = &whitelisted_data_info_list;
|
||||||
args.mount_data_dirs = &mount_data_dirs;
|
args.mount_data_dirs = &mount_data_dirs;
|
||||||
args.mount_storage_dirs = &mount_storage_dirs;
|
args.mount_storage_dirs = &mount_storage_dirs;
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<decltype(&nativeForkAndSpecialize_r)>(nativeForkAndSpecialize_orig)(
|
reinterpret_cast<decltype(&nativeForkAndSpecialize_r)>(nativeForkAndSpecialize_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs
|
||||||
@@ -78,9 +68,7 @@ void *nativeForkAndSpecialize_orig = nullptr;
|
|||||||
}
|
}
|
||||||
[[clang::no_stack_protector]] jint nativeForkAndSpecialize_samsung_m(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _0, jint _1, jstring nice_name, jintArray fds_to_close, jstring instruction_set, jstring app_data_dir) {
|
[[clang::no_stack_protector]] jint nativeForkAndSpecialize_samsung_m(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _0, jint _1, jstring nice_name, jintArray fds_to_close, jstring instruction_set, jstring app_data_dir) {
|
||||||
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_m)>(nativeForkAndSpecialize_orig)(
|
reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_m)>(nativeForkAndSpecialize_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _0, _1, nice_name, fds_to_close, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _0, _1, nice_name, fds_to_close, instruction_set, app_data_dir
|
||||||
@@ -90,9 +78,7 @@ void *nativeForkAndSpecialize_orig = nullptr;
|
|||||||
}
|
}
|
||||||
[[clang::no_stack_protector]] jint nativeForkAndSpecialize_samsung_n(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _2, jint _3, jstring nice_name, jintArray fds_to_close, jstring instruction_set, jstring app_data_dir, jint _4) {
|
[[clang::no_stack_protector]] jint nativeForkAndSpecialize_samsung_n(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _2, jint _3, jstring nice_name, jintArray fds_to_close, jstring instruction_set, jstring app_data_dir, jint _4) {
|
||||||
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_n)>(nativeForkAndSpecialize_orig)(
|
reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_n)>(nativeForkAndSpecialize_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _2, _3, nice_name, fds_to_close, instruction_set, app_data_dir, _4
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _2, _3, nice_name, fds_to_close, instruction_set, app_data_dir, _4
|
||||||
@@ -103,9 +89,7 @@ void *nativeForkAndSpecialize_orig = nullptr;
|
|||||||
[[clang::no_stack_protector]] jint nativeForkAndSpecialize_samsung_o(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _5, jint _6, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jstring instruction_set, jstring app_data_dir) {
|
[[clang::no_stack_protector]] jint nativeForkAndSpecialize_samsung_o(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _5, jint _6, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jstring instruction_set, jstring app_data_dir) {
|
||||||
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
args.fds_to_ignore = &fds_to_ignore;
|
args.fds_to_ignore = &fds_to_ignore;
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_o)>(nativeForkAndSpecialize_orig)(
|
reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_o)>(nativeForkAndSpecialize_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _5, _6, nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _5, _6, nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir
|
||||||
@@ -117,9 +101,7 @@ void *nativeForkAndSpecialize_orig = nullptr;
|
|||||||
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
args.fds_to_ignore = &fds_to_ignore;
|
args.fds_to_ignore = &fds_to_ignore;
|
||||||
args.is_child_zygote = &is_child_zygote;
|
args.is_child_zygote = &is_child_zygote;
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_p)>(nativeForkAndSpecialize_orig)(
|
reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_p)>(nativeForkAndSpecialize_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _7, _8, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _7, _8, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir
|
||||||
@@ -180,9 +162,7 @@ void *nativeSpecializeAppProcess_orig = nullptr;
|
|||||||
[[clang::no_stack_protector]] void nativeSpecializeAppProcess_q(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir) {
|
[[clang::no_stack_protector]] void nativeSpecializeAppProcess_q(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir) {
|
||||||
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
args.is_child_zygote = &is_child_zygote;
|
args.is_child_zygote = &is_child_zygote;
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeSpecializeAppProcess_pre();
|
ctx.nativeSpecializeAppProcess_pre();
|
||||||
reinterpret_cast<decltype(&nativeSpecializeAppProcess_q)>(nativeSpecializeAppProcess_orig)(
|
reinterpret_cast<decltype(&nativeSpecializeAppProcess_q)>(nativeSpecializeAppProcess_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir
|
||||||
@@ -193,9 +173,7 @@ void *nativeSpecializeAppProcess_orig = nullptr;
|
|||||||
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
args.is_child_zygote = &is_child_zygote;
|
args.is_child_zygote = &is_child_zygote;
|
||||||
args.is_top_app = &is_top_app;
|
args.is_top_app = &is_top_app;
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeSpecializeAppProcess_pre();
|
ctx.nativeSpecializeAppProcess_pre();
|
||||||
reinterpret_cast<decltype(&nativeSpecializeAppProcess_q_alt)>(nativeSpecializeAppProcess_orig)(
|
reinterpret_cast<decltype(&nativeSpecializeAppProcess_q_alt)>(nativeSpecializeAppProcess_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app
|
||||||
@@ -210,9 +188,7 @@ void *nativeSpecializeAppProcess_orig = nullptr;
|
|||||||
args.whitelisted_data_info_list = &whitelisted_data_info_list;
|
args.whitelisted_data_info_list = &whitelisted_data_info_list;
|
||||||
args.mount_data_dirs = &mount_data_dirs;
|
args.mount_data_dirs = &mount_data_dirs;
|
||||||
args.mount_storage_dirs = &mount_storage_dirs;
|
args.mount_storage_dirs = &mount_storage_dirs;
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeSpecializeAppProcess_pre();
|
ctx.nativeSpecializeAppProcess_pre();
|
||||||
reinterpret_cast<decltype(&nativeSpecializeAppProcess_r)>(nativeSpecializeAppProcess_orig)(
|
reinterpret_cast<decltype(&nativeSpecializeAppProcess_r)>(nativeSpecializeAppProcess_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs
|
||||||
@@ -222,9 +198,7 @@ void *nativeSpecializeAppProcess_orig = nullptr;
|
|||||||
[[clang::no_stack_protector]] void nativeSpecializeAppProcess_samsung_q(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _9, jint _10, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir) {
|
[[clang::no_stack_protector]] void nativeSpecializeAppProcess_samsung_q(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _9, jint _10, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir) {
|
||||||
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
args.is_child_zygote = &is_child_zygote;
|
args.is_child_zygote = &is_child_zygote;
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeSpecializeAppProcess_pre();
|
ctx.nativeSpecializeAppProcess_pre();
|
||||||
reinterpret_cast<decltype(&nativeSpecializeAppProcess_samsung_q)>(nativeSpecializeAppProcess_orig)(
|
reinterpret_cast<decltype(&nativeSpecializeAppProcess_samsung_q)>(nativeSpecializeAppProcess_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _9, _10, nice_name, is_child_zygote, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _9, _10, nice_name, is_child_zygote, instruction_set, app_data_dir
|
||||||
@@ -258,9 +232,7 @@ constexpr int nativeSpecializeAppProcess_methods_num = std::size(nativeSpecializ
|
|||||||
void *nativeForkSystemServer_orig = nullptr;
|
void *nativeForkSystemServer_orig = nullptr;
|
||||||
[[clang::no_stack_protector]] jint nativeForkSystemServer_l(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities) {
|
[[clang::no_stack_protector]] jint nativeForkSystemServer_l(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities) {
|
||||||
ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities);
|
ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities);
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeForkSystemServer_pre();
|
ctx.nativeForkSystemServer_pre();
|
||||||
reinterpret_cast<decltype(&nativeForkSystemServer_l)>(nativeForkSystemServer_orig)(
|
reinterpret_cast<decltype(&nativeForkSystemServer_l)>(nativeForkSystemServer_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities, effective_capabilities
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities, effective_capabilities
|
||||||
@@ -270,9 +242,7 @@ void *nativeForkSystemServer_orig = nullptr;
|
|||||||
}
|
}
|
||||||
[[clang::no_stack_protector]] jint nativeForkSystemServer_samsung_q(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jint _11, jint _12, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities) {
|
[[clang::no_stack_protector]] jint nativeForkSystemServer_samsung_q(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jint _11, jint _12, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities) {
|
||||||
ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities);
|
ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities);
|
||||||
HookContext ctx;
|
HookContext ctx(env, &args);
|
||||||
ctx.env = env;
|
|
||||||
ctx.args = { &args };
|
|
||||||
ctx.nativeForkSystemServer_pre();
|
ctx.nativeForkSystemServer_pre();
|
||||||
reinterpret_cast<decltype(&nativeForkSystemServer_samsung_q)>(nativeForkSystemServer_orig)(
|
reinterpret_cast<decltype(&nativeForkSystemServer_samsung_q)>(nativeForkSystemServer_orig)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, _11, _12, rlimits, permitted_capabilities, effective_capabilities
|
env, clazz, uid, gid, gids, runtime_flags, _11, _12, rlimits, permitted_capabilities, effective_capabilities
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ androidComponents.onVariants { variant ->
|
|||||||
into(moduleDir)
|
into(moduleDir)
|
||||||
from("${rootProject.projectDir}/README.md")
|
from("${rootProject.projectDir}/README.md")
|
||||||
from("$projectDir/src") {
|
from("$projectDir/src") {
|
||||||
exclude("module.prop", "customize.sh", "service.sh")
|
exclude("module.prop", "customize.sh", "post-fs-data.sh", "service.sh")
|
||||||
filter<FixCrLfFilter>("eol" to FixCrLfFilter.CrLf.newInstance("lf"))
|
filter<FixCrLfFilter>("eol" to FixCrLfFilter.CrLf.newInstance("lf"))
|
||||||
}
|
}
|
||||||
from("$projectDir/src") {
|
from("$projectDir/src") {
|
||||||
@@ -52,7 +52,7 @@ androidComponents.onVariants { variant ->
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
from("$projectDir/src") {
|
from("$projectDir/src") {
|
||||||
include("customize.sh", "service.sh")
|
include("customize.sh", "post-fs-data.sh", "service.sh")
|
||||||
val tokens = mapOf(
|
val tokens = mapOf(
|
||||||
"DEBUG" to if (buildTypeLowered == "debug") "true" else "false",
|
"DEBUG" to if (buildTypeLowered == "debug") "true" else "false",
|
||||||
"MIN_KSU_VERSION" to "$minKsuVersion",
|
"MIN_KSU_VERSION" to "$minKsuVersion",
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# check architecture
|
# check architecture
|
||||||
if [ "$ARCH" != "arm64" ] && [ "$ARCH" != "x64" ]; then
|
if [ "$ARCH" != "arm" ] && [ "$ARCH" != "arm64" ] && [ "$ARCH" != "x86" ] && [ "$ARCH" != "x64" ]; then
|
||||||
abort "! Unsupported platform: $ARCH"
|
abort "! Unsupported platform: $ARCH"
|
||||||
else
|
else
|
||||||
ui_print "- Device platform: $ARCH"
|
ui_print "- Device platform: $ARCH"
|
||||||
@@ -101,28 +101,54 @@ extract "$ZIPFILE" 'post-fs-data.sh' "$MODPATH"
|
|||||||
extract "$ZIPFILE" 'service.sh' "$MODPATH"
|
extract "$ZIPFILE" 'service.sh' "$MODPATH"
|
||||||
mv "$TMPDIR/sepolicy.rule" "$MODPATH"
|
mv "$TMPDIR/sepolicy.rule" "$MODPATH"
|
||||||
|
|
||||||
|
HAS32BIT=false && [ -d "/system/lib" ] && HAS32BIT=true
|
||||||
|
|
||||||
mkdir "$MODPATH/bin"
|
mkdir "$MODPATH/bin"
|
||||||
mkdir "$MODPATH/system"
|
mkdir "$MODPATH/system"
|
||||||
mkdir "$MODPATH/system/lib64"
|
mkdir "$MODPATH/system/lib64"
|
||||||
|
[ "$HAS32BIT" = true ] && mkdir "$MODPATH/system/lib"
|
||||||
|
|
||||||
|
if [ "$ARCH" = "x86" ] || [ "$ARCH" = "x64" ]; then
|
||||||
|
if [ "$HAS32BIT" = true ]; then
|
||||||
|
ui_print "- Extracting x86 libraries"
|
||||||
|
extract "$ZIPFILE" 'bin/x86/zygiskd' "$MODPATH/bin" true
|
||||||
|
mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd32"
|
||||||
|
extract "$ZIPFILE" 'lib/x86/libzygisk.so' "$MODPATH/system/lib" true
|
||||||
|
ln -sf "zygiskd32" "$MODPATH/bin/zygisk-cp32"
|
||||||
|
ln -sf "zygiskd32" "$MODPATH/bin/zygisk-ptrace32"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$ARCH" = "x64" ]; then
|
|
||||||
ui_print "- Extracting x64 libraries"
|
ui_print "- Extracting x64 libraries"
|
||||||
extract "$ZIPFILE" 'bin/x86_64/zygiskd' "$MODPATH/bin" true
|
extract "$ZIPFILE" 'bin/x86_64/zygiskd' "$MODPATH/bin" true
|
||||||
|
mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd64"
|
||||||
extract "$ZIPFILE" 'lib/x86_64/libzygisk.so' "$MODPATH/system/lib64" true
|
extract "$ZIPFILE" 'lib/x86_64/libzygisk.so' "$MODPATH/system/lib64" true
|
||||||
ln -sf "zygiskd" "$MODPATH/bin/zygisk-wd"
|
ln -sf "zygiskd64" "$MODPATH/bin/zygisk-wd"
|
||||||
ln -sf "zygiskd" "$MODPATH/bin/zygisk-fuse"
|
ln -sf "zygiskd64" "$MODPATH/bin/zygisk-fuse"
|
||||||
ln -sf "zygiskd" "$MODPATH/bin/zygisk-cp"
|
ln -sf "zygiskd64" "$MODPATH/bin/zygisk-cp64"
|
||||||
|
ln -sf "zygiskd64" "$MODPATH/bin/zygisk-ptrace64"
|
||||||
else
|
else
|
||||||
|
if [ "$HAS32BIT" = true ]; then
|
||||||
|
ui_print "- Extracting arm libraries"
|
||||||
|
extract "$ZIPFILE" 'bin/armeabi-v7a/zygiskd' "$MODPATH/bin" true
|
||||||
|
mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd32"
|
||||||
|
extract "$ZIPFILE" 'lib/armeabi-v7a/libzygisk.so' "$MODPATH/system/lib" true
|
||||||
|
ln -sf "zygiskd32" "$MODPATH/bin/zygisk-cp32"
|
||||||
|
ln -sf "zygiskd32" "$MODPATH/bin/zygisk-ptrace32"
|
||||||
|
fi
|
||||||
|
|
||||||
ui_print "- Extracting arm64 libraries"
|
ui_print "- Extracting arm64 libraries"
|
||||||
extract "$ZIPFILE" 'bin/arm64-v8a/zygiskd' "$MODPATH/bin" true
|
extract "$ZIPFILE" 'bin/arm64-v8a/zygiskd' "$MODPATH/bin" true
|
||||||
|
mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd64"
|
||||||
extract "$ZIPFILE" 'lib/arm64-v8a/libzygisk.so' "$MODPATH/system/lib64" true
|
extract "$ZIPFILE" 'lib/arm64-v8a/libzygisk.so' "$MODPATH/system/lib64" true
|
||||||
ln -sf "zygiskd" "$MODPATH/bin/zygisk-wd"
|
ln -sf "zygiskd64" "$MODPATH/bin/zygisk-wd"
|
||||||
ln -sf "zygiskd" "$MODPATH/bin/zygisk-fuse"
|
ln -sf "zygiskd64" "$MODPATH/bin/zygisk-fuse"
|
||||||
ln -sf "zygiskd" "$MODPATH/bin/zygisk-cp"
|
ln -sf "zygiskd64" "$MODPATH/bin/zygisk-cp64"
|
||||||
|
ln -sf "zygiskd64" "$MODPATH/bin/zygisk-ptrace64"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ui_print "- Setting permissions"
|
ui_print "- Setting permissions"
|
||||||
set_perm_recursive "$MODPATH/bin" 0 0 0755 0755
|
set_perm_recursive "$MODPATH/bin" 0 0 0755 0755
|
||||||
|
set_perm_recursive "$MODPATH/system/lib" 0 0 0755 0644 u:object_r:system_lib_file:s0
|
||||||
set_perm_recursive "$MODPATH/system/lib64" 0 0 0755 0644 u:object_r:system_lib_file:s0
|
set_perm_recursive "$MODPATH/system/lib64" 0 0 0755 0644 u:object_r:system_lib_file:s0
|
||||||
|
|
||||||
# If Huawei's Maple is enabled, system_server is created with a special way which is out of Zygisk's control
|
# If Huawei's Maple is enabled, system_server is created with a special way which is out of Zygisk's control
|
||||||
|
|||||||
@@ -19,12 +19,13 @@ memfd = "0.6"
|
|||||||
num_enum = "0.5"
|
num_enum = "0.5"
|
||||||
passfd = "0.1"
|
passfd = "0.1"
|
||||||
proc-maps = "0.3"
|
proc-maps = "0.3"
|
||||||
ptrace-do = "0.1"
|
|
||||||
rustix = { version = "0.38", features = [ "fs", "process", "mount", "net", "thread"] }
|
rustix = { version = "0.38", features = [ "fs", "process", "mount", "net", "thread"] }
|
||||||
tokio = { version = "1.28", features = ["full"] }
|
tokio = { version = "1.28", features = ["full"] }
|
||||||
|
|
||||||
binder = { git = "https://github.com/Kernel-SU/binder_rs", rev = "c9f2b62d6a744fd2264056c638c1b061a6a2932d" }
|
binder = { git = "https://github.com/Kernel-SU/binder_rs", rev = "c9f2b62d6a744fd2264056c638c1b061a6a2932d" }
|
||||||
fuser = { git = "https://github.com/Dr-TSNG/fuser", default-features = false }
|
fuser = { git = "https://github.com/Dr-TSNG/fuser", default-features = false }
|
||||||
|
ptrace-do = { git = "https://github.com/5ec1cff/ptrace-do" }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
strip = true
|
strip = true
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ plugins {
|
|||||||
alias(libs.plugins.rust.android)
|
alias(libs.plugins.rust.android)
|
||||||
}
|
}
|
||||||
|
|
||||||
val verName: String by rootProject.extra
|
|
||||||
val verCode: Int by rootProject.extra
|
|
||||||
val minKsuVersion: Int by rootProject.extra
|
val minKsuVersion: Int by rootProject.extra
|
||||||
val maxKsuVersion: Int by rootProject.extra
|
val maxKsuVersion: Int by rootProject.extra
|
||||||
val minMagiskVersion: Int by rootProject.extra
|
val minMagiskVersion: Int by rootProject.extra
|
||||||
@@ -18,14 +16,12 @@ cargo {
|
|||||||
module = "."
|
module = "."
|
||||||
libname = "zygiskd"
|
libname = "zygiskd"
|
||||||
targetIncludes = arrayOf("zygiskd")
|
targetIncludes = arrayOf("zygiskd")
|
||||||
targets = listOf("arm64", "x86_64")
|
targets = listOf("arm64", "arm", "x86", "x86_64")
|
||||||
targetDirectory = "build/intermediates/rust"
|
targetDirectory = "build/intermediates/rust"
|
||||||
val isDebug = gradle.startParameter.taskNames.any { it.toLowerCase().contains("debug") }
|
val isDebug = gradle.startParameter.taskNames.any { it.toLowerCase().contains("debug") }
|
||||||
profile = if (isDebug) "debug" else "release"
|
profile = if (isDebug) "debug" else "release"
|
||||||
exec = { spec, _ ->
|
exec = { spec, _ ->
|
||||||
spec.environment("ANDROID_NDK_HOME", android.ndkDirectory.path)
|
spec.environment("ANDROID_NDK_HOME", android.ndkDirectory.path)
|
||||||
spec.environment("VERSION_CODE", verCode)
|
|
||||||
spec.environment("VERSION_NAME", verName)
|
|
||||||
spec.environment("MIN_KSU_VERSION", minKsuVersion)
|
spec.environment("MIN_KSU_VERSION", minKsuVersion)
|
||||||
spec.environment("MAX_KSU_VERSION", maxKsuVersion)
|
spec.environment("MAX_KSU_VERSION", maxKsuVersion)
|
||||||
spec.environment("MIN_MAGISK_VERSION", minMagiskVersion)
|
spec.environment("MIN_MAGISK_VERSION", minMagiskVersion)
|
||||||
|
|||||||
@@ -4,10 +4,8 @@ use konst::primitive::parse_i32;
|
|||||||
use konst::unwrap_ctx;
|
use konst::unwrap_ctx;
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
|
use crate::lp_select;
|
||||||
|
|
||||||
pub const VERSION_NAME: &str = env!("VERSION_NAME");
|
|
||||||
pub const VERSION_CODE: &str = env!("VERSION_CODE");
|
|
||||||
pub const VERSION_FULL: &str = concatcp!(VERSION_NAME, " (", VERSION_CODE, ")");
|
|
||||||
pub const MIN_KSU_VERSION: i32 = unwrap_ctx!(parse_i32(env!("MIN_KSU_VERSION")));
|
pub const MIN_KSU_VERSION: i32 = unwrap_ctx!(parse_i32(env!("MIN_KSU_VERSION")));
|
||||||
pub const MAX_KSU_VERSION: i32 = unwrap_ctx!(parse_i32(env!("MAX_KSU_VERSION")));
|
pub const MAX_KSU_VERSION: i32 = unwrap_ctx!(parse_i32(env!("MAX_KSU_VERSION")));
|
||||||
pub const MIN_MAGISK_VERSION: i32 = unwrap_ctx!(parse_i32(env!("MIN_MAGISK_VERSION")));
|
pub const MIN_MAGISK_VERSION: i32 = unwrap_ctx!(parse_i32(env!("MIN_MAGISK_VERSION")));
|
||||||
@@ -18,19 +16,22 @@ pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Trace;
|
|||||||
pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Info;
|
pub const MAX_LOG_LEVEL: LevelFilter = LevelFilter::Info;
|
||||||
|
|
||||||
pub const PROP_CTL_RESTART: &str = "ctl.restart";
|
pub const PROP_CTL_RESTART: &str = "ctl.restart";
|
||||||
pub const ZYGISK_LIBRARY: &str = "libzygisk.so";
|
|
||||||
|
|
||||||
pub const PATH_PCL: &str = "/system/etc/preloaded-classes";
|
pub const PATH_PCL: &str = "/system/etc/preloaded-classes";
|
||||||
pub const PATH_SYSTEM_LIB: &str = "/system/lib64";
|
pub const PATH_ZYGISK_LIB: &str = concatcp!(lp_select!("/system/lib", "/system/lib64"), "/libzygisk.so");
|
||||||
pub const PATH_WORK_DIR: &str = "/dev/zygisk"; // TODO: Replace with /debug_ramdisk/zygisk
|
pub const PATH_WORK_DIR: &str = "/dev/zygisk"; // TODO: Replace with /debug_ramdisk/zygisk
|
||||||
pub const PATH_PROP_OVERLAY: &str = concatcp!(PATH_WORK_DIR, "/module.prop");
|
pub const PATH_PROP_OVERLAY: &str = concatcp!(PATH_WORK_DIR, "/module.prop");
|
||||||
pub const PATH_CP_SOCKET: &str = concatcp!(PATH_WORK_DIR, "/cp.sock");
|
pub const PATH_CP_SOCKET: &str = concatcp!(PATH_WORK_DIR, lp_select!("/cp32.sock", "/cp64.sock"));
|
||||||
pub const PATH_FUSE_DIR: &str = concatcp!(PATH_WORK_DIR, "/fuse");
|
pub const PATH_FUSE_DIR: &str = concatcp!(PATH_WORK_DIR, "/fuse");
|
||||||
pub const PATH_FUSE_PCL: &str = concatcp!(PATH_FUSE_DIR, "/preloaded-classes");
|
pub const PATH_FUSE_PCL: &str = concatcp!(PATH_FUSE_DIR, "/preloaded-classes");
|
||||||
|
|
||||||
pub const PATH_MODULES_DIR: &str = "..";
|
pub const PATH_MODULES_DIR: &str = "..";
|
||||||
pub const PATH_MODULE_PROP: &str = "module.prop";
|
pub const PATH_MODULE_PROP: &str = "module.prop";
|
||||||
pub const PATH_CP_BIN: &str = "bin/zygisk-cp";
|
pub const PATH_CP_BIN32: &str = "bin/zygisk-cp32";
|
||||||
|
pub const PATH_CP_BIN64: &str = "bin/zygisk-cp64";
|
||||||
|
pub const PATH_PTRACE_BIN32: &str = "bin/zygisk-ptrace32";
|
||||||
|
pub const PATH_PTRACE_BIN64: &str = "bin/zygisk-ptrace64";
|
||||||
|
|
||||||
|
|
||||||
pub const STATUS_LOADED: &str = "😋 Zygisksu is loaded";
|
pub const STATUS_LOADED: &str = "😋 Zygisksu is loaded";
|
||||||
pub const STATUS_CRASHED: &str = "❌ Zygiskd has crashed";
|
pub const STATUS_CRASHED: &str = "❌ Zygiskd has crashed";
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use std::ffi::{CString, OsStr};
|
use std::ffi::OsStr;
|
||||||
use std::{fs, thread};
|
use std::{fs, thread};
|
||||||
|
use std::io::Read;
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
use std::sync::{mpsc, Mutex};
|
use std::sync::{mpsc, Mutex};
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
use fuser::{FileAttr, Filesystem, FileType, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry, ReplyOpen, Request};
|
use fuser::{FileAttr, Filesystem, FileType, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry, ReplyOpen, Request};
|
||||||
use libc::ENOENT;
|
use libc::ENOENT;
|
||||||
use log::{debug, error, info};
|
use log::{error, info};
|
||||||
use proc_maps::{get_process_maps, MapRange, Pid};
|
|
||||||
use ptrace_do::{RawProcess, TracedProcess};
|
|
||||||
use rustix::fs::UnmountFlags;
|
use rustix::fs::UnmountFlags;
|
||||||
use rustix::mount::{mount_bind, unmount};
|
use rustix::mount::{mount_bind, unmount};
|
||||||
use rustix::path::Arg;
|
use rustix::path::Arg;
|
||||||
use rustix::process::getpid;
|
use crate::constants;
|
||||||
use crate::{constants, dl};
|
|
||||||
use crate::utils::LateInit;
|
use crate::utils::LateInit;
|
||||||
|
|
||||||
pub struct DelegateFilesystem;
|
pub struct DelegateFilesystem;
|
||||||
@@ -38,9 +37,6 @@ const fn attr(inode: u64, size: u64, kind: FileType) -> FileAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ANDROID_LIBC: &str = "bionic/libc.so";
|
|
||||||
const ANDROID_LIBDL: &str = "bionic/libdl.so";
|
|
||||||
|
|
||||||
const INO_DIR: u64 = 1;
|
const INO_DIR: u64 = 1;
|
||||||
const INO_PCL: u64 = 2;
|
const INO_PCL: u64 = 2;
|
||||||
|
|
||||||
@@ -57,6 +53,66 @@ const ENTRIES: &[(u64, FileType, &str)] = &[
|
|||||||
|
|
||||||
const TTL: Duration = Duration::from_secs(1);
|
const TTL: Duration = Duration::from_secs(1);
|
||||||
|
|
||||||
|
fn ptrace_zygote64(pid: u32) -> Result<()> {
|
||||||
|
static LAST: Mutex<u32> = Mutex::new(0);
|
||||||
|
|
||||||
|
let mut last = LAST.lock().unwrap();
|
||||||
|
if *last == pid {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
*last = pid;
|
||||||
|
let (sender, receiver) = mpsc::channel::<()>();
|
||||||
|
|
||||||
|
let worker = move || -> Result<()> {
|
||||||
|
let mut child = Command::new(constants::PATH_PTRACE_BIN64).stdout(Stdio::piped()).arg(format!("{}", pid)).spawn()?;
|
||||||
|
child.stdout.as_mut().unwrap().read_exact(&mut [0u8; 1])?;
|
||||||
|
info!("child attached");
|
||||||
|
sender.send(())?;
|
||||||
|
let result = child.wait()?;
|
||||||
|
info!("ptrace64 process status {}", result);
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
if let Err(e) = worker() {
|
||||||
|
error!("Crashed: {:?}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
receiver.recv()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ptrace_zygote32(pid: u32) -> Result<()> {
|
||||||
|
static LAST: Mutex<u32> = Mutex::new(0);
|
||||||
|
|
||||||
|
let mut last = LAST.lock().unwrap();
|
||||||
|
if *last == pid {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
*last = pid;
|
||||||
|
let (sender, receiver) = mpsc::channel::<()>();
|
||||||
|
|
||||||
|
let worker = move || -> Result<()> {
|
||||||
|
let mut child = Command::new(constants::PATH_PTRACE_BIN32).stdout(Stdio::piped()).arg(format!("{}", pid)).spawn()?;
|
||||||
|
child.stdout.as_mut().unwrap().read_exact(&mut [0u8; 1])?;
|
||||||
|
info!("child attached");
|
||||||
|
sender.send(())?;
|
||||||
|
let result = child.wait()?;
|
||||||
|
info!("ptrace32 process status {}", result);
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
if let Err(e) = worker() {
|
||||||
|
error!("Crashed: {:?}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
receiver.recv()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
impl Filesystem for DelegateFilesystem {
|
impl Filesystem for DelegateFilesystem {
|
||||||
fn lookup(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEntry) {
|
fn lookup(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEntry) {
|
||||||
if parent != INO_DIR {
|
if parent != INO_DIR {
|
||||||
@@ -84,8 +140,10 @@ impl Filesystem for DelegateFilesystem {
|
|||||||
let process = fs::read_to_string(process).unwrap();
|
let process = fs::read_to_string(process).unwrap();
|
||||||
let process = &process[..process.find('\0').unwrap()];
|
let process = &process[..process.find('\0').unwrap()];
|
||||||
info!("Process {} is reading preloaded-classes", process);
|
info!("Process {} is reading preloaded-classes", process);
|
||||||
if process == "zygote64" {
|
match process {
|
||||||
ptrace_zygote(pid).unwrap();
|
"zygote64" => ptrace_zygote64(pid).unwrap(),
|
||||||
|
"zygote" => ptrace_zygote32(pid).unwrap(),
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reply.opened(0, 0);
|
reply.opened(0, 0);
|
||||||
@@ -121,190 +179,6 @@ impl Filesystem for DelegateFilesystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_module_for_pid(pid: Pid, library: &str) -> Result<MapRange> {
|
|
||||||
let maps = get_process_maps(pid)?;
|
|
||||||
for map in maps.into_iter() {
|
|
||||||
if let Some(p) = map.filename() {
|
|
||||||
if p.as_str()?.contains(library) {
|
|
||||||
return Ok(map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bail!("Cannot find module {library} for pid {pid}");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_remote_procedure(
|
|
||||||
pid: Pid,
|
|
||||||
library: &str,
|
|
||||||
local_addr: usize,
|
|
||||||
) -> Result<usize> {
|
|
||||||
let local_module = find_module_for_pid(getpid().as_raw_nonzero().get(), library)?;
|
|
||||||
debug!(
|
|
||||||
"Identifed local range {library} ({:?}) at {:x}",
|
|
||||||
local_module.filename(),
|
|
||||||
local_module.start()
|
|
||||||
);
|
|
||||||
|
|
||||||
let remote_module = find_module_for_pid(pid, library)?;
|
|
||||||
debug!(
|
|
||||||
"Identifed remote range {library} ({:?}) at {:x}",
|
|
||||||
remote_module.filename(),
|
|
||||||
remote_module.start()
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(local_addr - local_module.start() + remote_module.start())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ptrace_zygote(pid: u32) -> Result<()> {
|
|
||||||
static LAST: Mutex<u32> = Mutex::new(0);
|
|
||||||
|
|
||||||
let mut last = LAST.lock().unwrap();
|
|
||||||
if *last == pid {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
*last = pid;
|
|
||||||
let (sender, receiver) = mpsc::channel::<()>();
|
|
||||||
|
|
||||||
let worker = move || -> Result<()> {
|
|
||||||
info!("Injecting into pid {}", pid);
|
|
||||||
let zygisk_lib = format!("{}/{}", constants::PATH_SYSTEM_LIB, constants::ZYGISK_LIBRARY);
|
|
||||||
let lib_dir = CString::new(constants::PATH_SYSTEM_LIB)?;
|
|
||||||
let zygisk_lib = CString::new(zygisk_lib)?;
|
|
||||||
let libc_base = find_module_for_pid(pid as i32, ANDROID_LIBC)?.start();
|
|
||||||
let mmap_remote = find_remote_procedure(
|
|
||||||
pid as i32,
|
|
||||||
ANDROID_LIBC,
|
|
||||||
libc::mmap as usize,
|
|
||||||
)?;
|
|
||||||
let munmap_remote = find_remote_procedure(
|
|
||||||
pid as i32,
|
|
||||||
ANDROID_LIBC,
|
|
||||||
libc::munmap as usize,
|
|
||||||
)?;
|
|
||||||
let dlopen_remote = find_remote_procedure(
|
|
||||||
pid as i32,
|
|
||||||
ANDROID_LIBDL,
|
|
||||||
dl::android_dlopen_ext as usize,
|
|
||||||
)?;
|
|
||||||
let dlsym_remote = find_remote_procedure(
|
|
||||||
pid as i32,
|
|
||||||
ANDROID_LIBDL,
|
|
||||||
libc::dlsym as usize,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let tracer = TracedProcess::attach(RawProcess::new(pid as i32))?;
|
|
||||||
sender.send(())?;
|
|
||||||
let frame = tracer.next_frame()?;
|
|
||||||
debug!("Waited for a frame");
|
|
||||||
|
|
||||||
// Map a buffer in the remote process
|
|
||||||
let mmap_params: [usize; 6] = [
|
|
||||||
0,
|
|
||||||
0x1000,
|
|
||||||
(libc::PROT_READ | libc::PROT_WRITE) as usize,
|
|
||||||
(libc::MAP_ANONYMOUS | libc::MAP_PRIVATE) as usize,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
];
|
|
||||||
let (regs, mut frame) = frame.invoke_remote(
|
|
||||||
mmap_remote,
|
|
||||||
libc_base,
|
|
||||||
&mmap_params,
|
|
||||||
)?;
|
|
||||||
let buf_addr = regs.return_value();
|
|
||||||
debug!("Buffer addr: {:x}", buf_addr);
|
|
||||||
|
|
||||||
// Find the address of __loader_android_create_namespace
|
|
||||||
let sym = CString::new("__loader_android_create_namespace")?;
|
|
||||||
frame.write_memory(buf_addr, sym.as_bytes_with_nul())?;
|
|
||||||
let (regs, mut frame) = frame.invoke_remote(
|
|
||||||
dlsym_remote,
|
|
||||||
libc_base,
|
|
||||||
&[libc::RTLD_DEFAULT as usize, buf_addr],
|
|
||||||
)?;
|
|
||||||
let android_create_namespace_remote = regs.return_value();
|
|
||||||
debug!("__loader_android_create_namespace addr: {:x}", android_create_namespace_remote);
|
|
||||||
|
|
||||||
// Create a linker namespace for remote process
|
|
||||||
frame.write_memory(buf_addr, zygisk_lib.as_bytes_with_nul())?;
|
|
||||||
frame.write_memory(buf_addr + 0x100, lib_dir.as_bytes_with_nul())?;
|
|
||||||
let ns_params: [usize; 7] = [
|
|
||||||
buf_addr, // name
|
|
||||||
buf_addr + 0x100, // ld_library_path
|
|
||||||
0, // default_library_path
|
|
||||||
dl::ANDROID_NAMESPACE_TYPE_SHARED as usize, // type
|
|
||||||
0, // permitted_when_isolated_path
|
|
||||||
0, // parent
|
|
||||||
dlopen_remote, // caller_addr
|
|
||||||
];
|
|
||||||
let (regs, mut frame) = frame.invoke_remote(
|
|
||||||
android_create_namespace_remote,
|
|
||||||
libc_base,
|
|
||||||
&ns_params,
|
|
||||||
)?;
|
|
||||||
let ns_addr = regs.return_value();
|
|
||||||
debug!("Linker namespace addr: {:x}", ns_addr);
|
|
||||||
|
|
||||||
// Load zygisk into remote process
|
|
||||||
let info = dl::AndroidDlextinfo {
|
|
||||||
flags: dl::ANDROID_DLEXT_USE_NAMESPACE,
|
|
||||||
reserved_addr: std::ptr::null_mut(),
|
|
||||||
reserved_size: 0,
|
|
||||||
relro_fd: 0,
|
|
||||||
library_fd: 0,
|
|
||||||
library_fd_offset: 0,
|
|
||||||
library_namespace: ns_addr as *mut _,
|
|
||||||
};
|
|
||||||
let info = unsafe {
|
|
||||||
std::slice::from_raw_parts(
|
|
||||||
&info as *const _ as *const u8,
|
|
||||||
std::mem::size_of::<dl::AndroidDlextinfo>(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
frame.write_memory(buf_addr + 0x200, info)?;
|
|
||||||
let (regs, mut frame) = frame.invoke_remote(
|
|
||||||
dlopen_remote,
|
|
||||||
libc_base,
|
|
||||||
&[buf_addr, libc::RTLD_NOW as usize, buf_addr + 0x200],
|
|
||||||
)?;
|
|
||||||
let handle = regs.return_value();
|
|
||||||
debug!("Load zygisk into remote process: {:x}", handle);
|
|
||||||
|
|
||||||
let entry = CString::new("entry")?;
|
|
||||||
frame.write_memory(buf_addr, entry.as_bytes_with_nul())?;
|
|
||||||
let (regs, frame) = frame.invoke_remote(
|
|
||||||
dlsym_remote,
|
|
||||||
libc_base,
|
|
||||||
&[handle, buf_addr],
|
|
||||||
)?;
|
|
||||||
let entry = regs.return_value();
|
|
||||||
debug!("Call zygisk entry: {:x}", entry);
|
|
||||||
let (_, frame) = frame.invoke_remote(
|
|
||||||
entry,
|
|
||||||
libc_base,
|
|
||||||
&[handle],
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
let _ = frame.invoke_remote(
|
|
||||||
munmap_remote,
|
|
||||||
libc_base,
|
|
||||||
&[buf_addr],
|
|
||||||
)?;
|
|
||||||
debug!("Cleaned up");
|
|
||||||
Ok(())
|
|
||||||
};
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
if let Err(e) = worker() {
|
|
||||||
error!("Crashed: {:?}", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
receiver.recv()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() -> Result<()> {
|
pub fn main() -> Result<()> {
|
||||||
info!("Start zygisk fuse");
|
info!("Start zygisk fuse");
|
||||||
fs::create_dir(constants::PATH_WORK_DIR)?;
|
fs::create_dir(constants::PATH_WORK_DIR)?;
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
#![feature(exclusive_range_pattern)]
|
|
||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
mod constants;
|
mod constants;
|
||||||
mod dl;
|
mod dl;
|
||||||
mod fuse;
|
mod fuse;
|
||||||
|
mod ptrace;
|
||||||
mod root_impl;
|
mod root_impl;
|
||||||
mod utils;
|
mod utils;
|
||||||
mod watchdog;
|
mod watchdog;
|
||||||
@@ -12,7 +10,6 @@ mod zygiskd;
|
|||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
|
|
||||||
fn init_android_logger(tag: &str) {
|
fn init_android_logger(tag: &str) {
|
||||||
android_logger::init_once(
|
android_logger::init_once(
|
||||||
android_logger::Config::default()
|
android_logger::Config::default()
|
||||||
@@ -32,8 +29,9 @@ fn start(name: &str) -> Result<()> {
|
|||||||
match name.trim_start_matches("zygisk-") {
|
match name.trim_start_matches("zygisk-") {
|
||||||
"wd" => async_start(watchdog::main())?,
|
"wd" => async_start(watchdog::main())?,
|
||||||
"fuse" => fuse::main()?,
|
"fuse" => fuse::main()?,
|
||||||
"cp" => zygiskd::main()?,
|
lp_select!("cp32", "cp64") => zygiskd::main()?,
|
||||||
_ => println!("Available commands: wd, fuse, cp"),
|
lp_select!("ptrace32", "ptrace64") => ptrace::main()?,
|
||||||
|
_ => println!("Available commands: wd, fuse, cp, ptrace"),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
233
zygiskd/src/ptrace.rs
Normal file
233
zygiskd/src/ptrace.rs
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
use log::{debug, info};
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::env;
|
||||||
|
use std::io::Write;
|
||||||
|
use rustix::path::Arg;
|
||||||
|
use proc_maps::{get_process_maps, MapRange, Pid};
|
||||||
|
use ptrace_do::{RawProcess, TracedProcess};
|
||||||
|
use rustix::process::getpid;
|
||||||
|
use crate::{constants, lp_select};
|
||||||
|
use anyhow::{bail, Result};
|
||||||
|
|
||||||
|
const ANDROID_LIBC: &str = "bionic/libc.so";
|
||||||
|
const ANDROID_LIBDL: &str = "bionic/libdl.so";
|
||||||
|
|
||||||
|
fn find_module_for_pid(pid: Pid, library: &str) -> Result<MapRange> {
|
||||||
|
let maps = get_process_maps(pid)?;
|
||||||
|
for map in maps.into_iter() {
|
||||||
|
if let Some(p) = map.filename() {
|
||||||
|
if p.as_str()?.contains(library) {
|
||||||
|
return Ok(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bail!("Cannot find module {library} for pid {pid}");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_remote_procedure(
|
||||||
|
pid: Pid,
|
||||||
|
library: &str,
|
||||||
|
local_addr: usize,
|
||||||
|
) -> Result<usize> {
|
||||||
|
let local_module = find_module_for_pid(getpid().as_raw_nonzero().get(), library)?;
|
||||||
|
debug!(
|
||||||
|
"Identifed local range {library} ({:?}) at {:x}",
|
||||||
|
local_module.filename(),
|
||||||
|
local_module.start()
|
||||||
|
);
|
||||||
|
|
||||||
|
let remote_module = find_module_for_pid(pid, library)?;
|
||||||
|
debug!(
|
||||||
|
"Identifed remote range {library} ({:?}) at {:x}",
|
||||||
|
remote_module.filename(),
|
||||||
|
remote_module.start()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(local_addr - local_module.start() + remote_module.start())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ptrace_zygote(pid: u32) -> Result<()> {
|
||||||
|
info!("Injecting into pid {}", pid);
|
||||||
|
let zygisk_lib = CString::new(constants::PATH_ZYGISK_LIB)?;
|
||||||
|
let libc_base = find_module_for_pid(pid as i32, ANDROID_LIBC)?.start();
|
||||||
|
let mmap_remote = find_remote_procedure(
|
||||||
|
pid as i32,
|
||||||
|
ANDROID_LIBC,
|
||||||
|
libc::mmap as usize,
|
||||||
|
)?;
|
||||||
|
let munmap_remote = find_remote_procedure(
|
||||||
|
pid as i32,
|
||||||
|
ANDROID_LIBC,
|
||||||
|
libc::munmap as usize,
|
||||||
|
)?;
|
||||||
|
let dlopen_remote = find_remote_procedure(
|
||||||
|
pid as i32,
|
||||||
|
ANDROID_LIBDL,
|
||||||
|
libc::dlopen as usize,
|
||||||
|
)?;
|
||||||
|
let dlsym_remote = find_remote_procedure(
|
||||||
|
pid as i32,
|
||||||
|
ANDROID_LIBDL,
|
||||||
|
libc::dlsym as usize,
|
||||||
|
)?;
|
||||||
|
let errno_remote = find_remote_procedure(
|
||||||
|
pid as i32,
|
||||||
|
ANDROID_LIBC,
|
||||||
|
libc::__errno as usize,
|
||||||
|
)?;
|
||||||
|
let dlerror_remote = find_remote_procedure(
|
||||||
|
pid as i32,
|
||||||
|
ANDROID_LIBDL,
|
||||||
|
libc::dlerror as usize,
|
||||||
|
)?;
|
||||||
|
let strlen_remote = find_remote_procedure(
|
||||||
|
pid as i32,
|
||||||
|
ANDROID_LIBC,
|
||||||
|
libc::strlen as usize,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let tracer = TracedProcess::attach(RawProcess::new(pid as i32))?;
|
||||||
|
std::io::stdout().write(b"1")?;
|
||||||
|
info!("attached process {}", pid);
|
||||||
|
std::io::stdout().flush()?;
|
||||||
|
let frame = tracer.next_frame()?;
|
||||||
|
debug!("Waited for a frame");
|
||||||
|
|
||||||
|
// Map a buffer in the remote process
|
||||||
|
debug!("remote mmap addr {:x}", mmap_remote);
|
||||||
|
let mmap_params: [usize; 6] = [
|
||||||
|
0,
|
||||||
|
0x1000,
|
||||||
|
(libc::PROT_READ | libc::PROT_WRITE) as usize,
|
||||||
|
(libc::MAP_ANONYMOUS | libc::MAP_PRIVATE) as usize,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
];
|
||||||
|
let mut arr: Vec<u8> = Vec::new();
|
||||||
|
for p in mmap_params {
|
||||||
|
arr.extend_from_slice(&p.to_le_bytes());
|
||||||
|
}
|
||||||
|
arr.as_slice();
|
||||||
|
let (regs, mut frame) = frame.invoke_remote(
|
||||||
|
mmap_remote,
|
||||||
|
libc_base,
|
||||||
|
&mmap_params,
|
||||||
|
)?;
|
||||||
|
let buf_addr = regs.return_value();
|
||||||
|
debug!("remote stopped at addr {:x}", regs.program_counter());
|
||||||
|
if regs.program_counter() != libc_base {
|
||||||
|
let data = std::mem::MaybeUninit::<libc::siginfo_t>::uninit();
|
||||||
|
let siginfo = unsafe {
|
||||||
|
libc::ptrace(libc::PTRACE_GETSIGINFO, pid, 0, &data);
|
||||||
|
data.assume_init()
|
||||||
|
};
|
||||||
|
bail!(
|
||||||
|
"stopped at unexpected addr {:x} signo {} si_code {} si_addr {:?}",
|
||||||
|
regs.program_counter(),
|
||||||
|
siginfo.si_signo,
|
||||||
|
siginfo.si_code,
|
||||||
|
unsafe { siginfo.si_addr() },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if buf_addr == usize::MAX {
|
||||||
|
debug!("errno remote {:x}", errno_remote);
|
||||||
|
let (regs, frame) = frame.invoke_remote(
|
||||||
|
errno_remote,
|
||||||
|
libc_base,
|
||||||
|
&[],
|
||||||
|
)?;
|
||||||
|
debug!("errno called");
|
||||||
|
if regs.program_counter() != libc_base {
|
||||||
|
bail!("stopped at unexpected addr {:x} when getting errno", regs.program_counter());
|
||||||
|
}
|
||||||
|
let err_addr = regs.return_value();
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
frame.read_memory_mut(err_addr, &mut buf)?;
|
||||||
|
let err = i32::from_le_bytes(buf);
|
||||||
|
bail!("remote failed with {}", err);
|
||||||
|
}
|
||||||
|
debug!("Buffer addr: {:x}", buf_addr);
|
||||||
|
|
||||||
|
// Load zygisk into remote process
|
||||||
|
frame.write_memory(buf_addr, zygisk_lib.as_bytes_with_nul())?;
|
||||||
|
let (regs, mut frame) = frame.invoke_remote(
|
||||||
|
dlopen_remote,
|
||||||
|
libc_base,
|
||||||
|
&[buf_addr, libc::RTLD_NOW as usize],
|
||||||
|
)?;
|
||||||
|
let handle = regs.return_value();
|
||||||
|
debug!("Load zygisk into remote process: {:x}", handle);
|
||||||
|
if regs.program_counter() != libc_base {
|
||||||
|
let data = std::mem::MaybeUninit::<libc::siginfo_t>::uninit();
|
||||||
|
let siginfo = unsafe {
|
||||||
|
libc::ptrace(libc::PTRACE_GETSIGINFO, pid, 0, &data);
|
||||||
|
data.assume_init()
|
||||||
|
};
|
||||||
|
bail!(
|
||||||
|
"stopped at unexpected addr {:x} signo {} si_code {} si_addr {:?}",
|
||||||
|
regs.program_counter(),
|
||||||
|
siginfo.si_signo,
|
||||||
|
siginfo.si_code,
|
||||||
|
unsafe { siginfo.si_addr() },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if handle == 0 {
|
||||||
|
debug!("got handle 0");
|
||||||
|
let (regs, frame) = frame.invoke_remote(
|
||||||
|
dlerror_remote,
|
||||||
|
libc_base,
|
||||||
|
&[],
|
||||||
|
)?;
|
||||||
|
let err_addr = regs.return_value();
|
||||||
|
if err_addr == 0 {
|
||||||
|
bail!("dlerror err addr 0");
|
||||||
|
}
|
||||||
|
debug!("err addr {:x}", err_addr);
|
||||||
|
let (regs, frame) = frame.invoke_remote(
|
||||||
|
strlen_remote,
|
||||||
|
libc_base,
|
||||||
|
&[err_addr],
|
||||||
|
)?;
|
||||||
|
let len = regs.return_value();
|
||||||
|
if len == 0 {
|
||||||
|
bail!("dlerror len 0");
|
||||||
|
}
|
||||||
|
debug!("err len {}", len);
|
||||||
|
let mut buf = vec![0u8; len];
|
||||||
|
frame.read_memory_mut(err_addr, buf.as_mut_slice())?;
|
||||||
|
bail!("err {:?}", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
let entry = CString::new("entry")?;
|
||||||
|
frame.write_memory(buf_addr, entry.as_bytes_with_nul())?;
|
||||||
|
let (regs, frame) = frame.invoke_remote(
|
||||||
|
dlsym_remote,
|
||||||
|
libc_base,
|
||||||
|
&[handle, buf_addr],
|
||||||
|
)?;
|
||||||
|
let entry = regs.return_value();
|
||||||
|
debug!("Call zygisk entry: {:x}", entry);
|
||||||
|
let (_, frame) = frame.invoke_remote(
|
||||||
|
entry,
|
||||||
|
libc_base,
|
||||||
|
&[handle],
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
let _ = frame.invoke_remote(
|
||||||
|
munmap_remote,
|
||||||
|
libc_base,
|
||||||
|
&[buf_addr],
|
||||||
|
)?;
|
||||||
|
debug!("Cleaned up");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() -> Result<()> {
|
||||||
|
info!("Start zygisk ptrace");
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
let pid = args[1].parse::<u32>().unwrap();
|
||||||
|
info!("ptracing {} pid {}", lp_select!("zygote32", "zygote64"), pid);
|
||||||
|
ptrace_zygote(pid)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -26,7 +26,7 @@ pub fn get_kernel_su() -> Option<Version> {
|
|||||||
match version {
|
match version {
|
||||||
0 => None,
|
0 => None,
|
||||||
MIN_KSU_VERSION..=MAX_KSU_VERSION => Some(Version::Supported),
|
MIN_KSU_VERSION..=MAX_KSU_VERSION => Some(Version::Supported),
|
||||||
1..MIN_KSU_VERSION => Some(Version::TooOld),
|
1..=MIN_KSU_VERSION => Some(Version::TooOld),
|
||||||
_ => Some(Version::Abnormal),
|
_ => Some(Version::Abnormal),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,17 @@ use std::sync::OnceLock;
|
|||||||
use rustix::net::{AddressFamily, bind_unix, listen, socket, SocketAddrUnix, SocketType};
|
use rustix::net::{AddressFamily, bind_unix, listen, socket, SocketAddrUnix, SocketType};
|
||||||
use rustix::thread::gettid;
|
use rustix::thread::gettid;
|
||||||
|
|
||||||
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! lp_select {
|
||||||
|
($lp32:expr, $lp64:expr) => { $lp64 };
|
||||||
|
}
|
||||||
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! lp_select {
|
||||||
|
($lp32:expr, $lp64:expr) => { $lp32 };
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! debug_select {
|
macro_rules! debug_select {
|
||||||
|
|||||||
@@ -36,11 +36,6 @@ async fn run() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_fuse() -> Result<()> {
|
|
||||||
Command::new("bin/zygisk-fuse").spawn()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_permission() -> Result<()> {
|
fn check_permission() -> Result<()> {
|
||||||
info!("Check permission");
|
info!("Check permission");
|
||||||
let uid = getuid();
|
let uid = getuid();
|
||||||
@@ -116,14 +111,22 @@ async fn spawn_daemon() -> Result<()> {
|
|||||||
let mut lives = 5;
|
let mut lives = 5;
|
||||||
loop {
|
loop {
|
||||||
let mut futures = FuturesUnordered::<Pin<Box<dyn Future<Output=Result<()>>>>>::new();
|
let mut futures = FuturesUnordered::<Pin<Box<dyn Future<Output=Result<()>>>>>::new();
|
||||||
let daemon = Command::new(constants::PATH_CP_BIN).spawn()?;
|
let mut child_ids = vec![];
|
||||||
let daemon_pid = daemon.id().unwrap();
|
let daemon32 = Command::new(constants::PATH_CP_BIN32).arg("daemon").spawn();
|
||||||
|
let daemon64 = Command::new(constants::PATH_CP_BIN64).arg("daemon").spawn();
|
||||||
async fn daemon_holder(mut daemon: Child) -> Result<()> {
|
async fn spawn_daemon(mut daemon: Child) -> Result<()> {
|
||||||
let result = daemon.wait().await?;
|
let result = daemon.wait().await?;
|
||||||
bail!("Daemon process {} died: {}", daemon.id().unwrap(), result);
|
log::error!("Daemon process {} died: {}", daemon.id().unwrap(), result);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
if let Ok(it) = daemon32 {
|
||||||
|
child_ids.push(it.id().unwrap());
|
||||||
|
futures.push(Box::pin(spawn_daemon(it)));
|
||||||
|
}
|
||||||
|
if let Ok(it) = daemon64 {
|
||||||
|
child_ids.push(it.id().unwrap());
|
||||||
|
futures.push(Box::pin(spawn_daemon(it)));
|
||||||
}
|
}
|
||||||
futures.push(Box::pin(daemon_holder(daemon)));
|
|
||||||
|
|
||||||
async fn binder_listener() -> Result<()> {
|
async fn binder_listener() -> Result<()> {
|
||||||
let mut binder = loop {
|
let mut binder = loop {
|
||||||
@@ -150,8 +153,10 @@ async fn spawn_daemon() -> Result<()> {
|
|||||||
error!("{}", e);
|
error!("{}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Killing child process {}", daemon_pid);
|
for child in child_ids {
|
||||||
let _ = kill_process(Pid::from_raw(daemon_pid as i32).unwrap(), Signal::Kill);
|
debug!("Killing child process {}", child);
|
||||||
|
let _ = kill_process(Pid::from_raw(child as i32).unwrap(), Signal::Kill);
|
||||||
|
}
|
||||||
|
|
||||||
lives -= 1;
|
lives -= 1;
|
||||||
if lives == 0 {
|
if lives == 0 {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
use crate::constants::{DaemonSocketAction, ProcessFlags};
|
use crate::constants::{DaemonSocketAction, ProcessFlags};
|
||||||
use crate::utils::UnixStreamExt;
|
use crate::utils::UnixStreamExt;
|
||||||
use crate::{constants, dl, root_impl, utils};
|
use crate::{constants, dl, lp_select, root_impl, utils};
|
||||||
use anyhow::Result;
|
use anyhow::{bail, Result};
|
||||||
use passfd::FdPassingExt;
|
use passfd::FdPassingExt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
@@ -32,11 +32,11 @@ pub fn main() -> Result<()> {
|
|||||||
log::info!("Start zygisk companion");
|
log::info!("Start zygisk companion");
|
||||||
set_parent_process_death_signal(Some(Signal::Kill))?;
|
set_parent_process_death_signal(Some(Signal::Kill))?;
|
||||||
|
|
||||||
let arch = utils::get_property("ro.product.cpu.abi")?;
|
let arch = get_arch()?;
|
||||||
log::debug!("Daemon architecture: {arch}");
|
log::debug!("Daemon architecture: {arch}");
|
||||||
|
|
||||||
log::info!("Load modules");
|
log::info!("Load modules");
|
||||||
let modules = load_modules(&arch)?;
|
let modules = load_modules(arch)?;
|
||||||
|
|
||||||
let context = Context {
|
let context = Context {
|
||||||
modules,
|
modules,
|
||||||
@@ -60,6 +60,17 @@ pub fn main() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_arch() -> Result<&'static str> {
|
||||||
|
let system_arch = utils::get_property("ro.product.cpu.abi")?;
|
||||||
|
if system_arch.contains("arm") {
|
||||||
|
return Ok(lp_select!("armeabi-v7a", "arm64-v8a"));
|
||||||
|
}
|
||||||
|
if system_arch.contains("x86") {
|
||||||
|
return Ok(lp_select!("x86", "x86_64"));
|
||||||
|
}
|
||||||
|
bail!("Unsupported system architecture: {}", system_arch);
|
||||||
|
}
|
||||||
|
|
||||||
fn load_modules(arch: &str) -> Result<Vec<Module>> {
|
fn load_modules(arch: &str) -> Result<Vec<Module>> {
|
||||||
let mut modules = Vec::new();
|
let mut modules = Vec::new();
|
||||||
let dir = match fs::read_dir(constants::PATH_MODULES_DIR) {
|
let dir = match fs::read_dir(constants::PATH_MODULES_DIR) {
|
||||||
|
|||||||
Reference in New Issue
Block a user