commit 552c1e4011f5bcf1c15682eae8a23ba412edfeed
parent a2f56d11c2c3a3a4b7288e72aef612ed967c5582
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Thu, 13 Jun 2024 01:16:40 +0200

fix(native): remap executable

Signed-off-by: rhunk <101876869+rhunk@users.noreply.github.com>

Diffstat:
Mcommon/src/main/assets/lang/en_US.json | 4++++
Mcommon/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Experimental.kt | 1+
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/ModContext.kt | 1+
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt | 6+++---
Mnative/jni/src/common.h | 1+
Mnative/jni/src/dobby_helper.h | 4+++-
Mnative/jni/src/library.cpp | 12++++++------
Mnative/jni/src/util.h | 4++--
Mnative/src/main/kotlin/me/rhunk/snapenhance/nativelib/NativeConfig.kt | 6++++++
9 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/common/src/main/assets/lang/en_US.json b/common/src/main/assets/lang/en_US.json @@ -992,6 +992,10 @@ "custom_emoji_font": { "name": "Custom Emoji Font", "description": "Allows you to use a custom emoji font. Only works with .ttf fonts" + }, + "remap_executable": { + "name": "Remap Executable", + "description": "Remaps executable regions in memory" } } }, diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Experimental.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Experimental.kt @@ -39,6 +39,7 @@ class Experimental : ConfigContainer() { addFlags(ConfigFlag.USER_IMPORT) filenameFilter = { it.endsWith(".ttf") } } + val remapExecutable = boolean("remap_executable") { requireRestart(); addNotices(FeatureNotice.INTERNAL_BEHAVIOR, FeatureNotice.UNSTABLE) } } class E2EEConfig : ConfigContainer(hasGlobalState = true) { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ModContext.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/ModContext.kt @@ -159,6 +159,7 @@ class ModContext( disableBitmoji = config.experimental.nativeHooks.disableBitmoji.get(), disableMetrics = config.global.disableMetrics.get(), composerHooks = config.experimental.nativeHooks.composerHooks.globalState == true, + remapExecutable = config.experimental.nativeHooks.remapExecutable.get(), customEmojiFontPath = getCustomEmojiFontPath(this) ) ) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt @@ -208,11 +208,11 @@ class SnapEnhance { request.canceled = canceled } } - BaseDexClassLoader::class.java.hookConstructor(HookStage.AFTER) { - appContext.native.hideAnonymousDexFiles() - } appContext.reloadNativeConfig() } + BaseDexClassLoader::class.java.hookConstructor(HookStage.AFTER) { + appContext.native.hideAnonymousDexFiles() + } }.also { unhook = { it.unhook() } } } diff --git a/native/jni/src/common.h b/native/jni/src/common.h @@ -13,6 +13,7 @@ typedef struct { bool disable_bitmoji; bool disable_metrics; bool composer_hooks; + bool remap_executable; char custom_emoji_font_path[256]; } native_config_t; diff --git a/native/jni/src/dobby_helper.h b/native/jni/src/dobby_helper.h @@ -9,6 +9,8 @@ static pthread_mutex_t hook_mutex = PTHREAD_MUTEX_INITIALIZER; static void inline SafeHook(void *addr, void *hook, void **original) { pthread_mutex_lock(&hook_mutex); DobbyHook(addr, hook, original); - mprotect((void *)((uintptr_t) *original & PAGE_MASK), PAGE_SIZE, PROT_EXEC); + if (common::native_config->remap_executable) { + mprotect((void *)((uintptr_t) *original & PAGE_MASK), PAGE_SIZE, PROT_EXEC); + } pthread_mutex_unlock(&hook_mutex); } \ No newline at end of file diff --git a/native/jni/src/library.cpp b/native/jni/src/library.cpp @@ -17,6 +17,9 @@ bool JNICALL init(JNIEnv *env, jobject clazz) { LOGD("Initializing native"); using namespace common; + util::remap_sections([](const std::string &line, size_t size) { + return line.find(BUILD_PACKAGE) != std::string::npos; + }, native_config->remap_executable); native_lib_object = env->NewGlobalRef(clazz); client_module = util::get_module("libclient.so"); @@ -63,6 +66,7 @@ void JNICALL load_config(JNIEnv *env, jobject, jobject config_object) { native_config->disable_bitmoji = GET_CONFIG_BOOL("disableBitmoji"); native_config->disable_metrics = GET_CONFIG_BOOL("disableMetrics"); native_config->composer_hooks = GET_CONFIG_BOOL("composerHooks"); + native_config->remap_executable = GET_CONFIG_BOOL("remapExecutable"); memset(native_config->custom_emoji_font_path, 0, sizeof(native_config->custom_emoji_font_path)); auto custom_emoji_font_path = env->GetObjectField(config_object, env->GetFieldID(native_config_clazz, "customEmojiFontPath", "Ljava/lang/String;")); @@ -96,11 +100,11 @@ void JNICALL lock_database(JNIEnv *env, jobject, jstring database_name, jobject void JNICALL hide_anonymous_dex_files(JNIEnv *, jobject) { util::remap_sections([](const std::string &line, size_t size) { return ( - (size == PAGE_SIZE && line.find("r-xp 00000000") != std::string::npos && line.find("[v") == std::string::npos) || + (common::native_config->remap_executable && size == PAGE_SIZE && line.find("r-xp 00000000 00") != std::string::npos && line.find("[v") == std::string::npos) || line.find("dalvik-DEX") != std::string::npos || line.find("dalvik-classes") != std::string::npos ); - }); + }, common::native_config->remap_executable); } extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *_) { @@ -117,9 +121,5 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *_) { methods.push_back({"hideAnonymousDexFiles", "()V", (void *)hide_anonymous_dex_files}); env->RegisterNatives(env->FindClass(std::string(BUILD_NAMESPACE "/NativeLib").c_str()), methods.data(), methods.size()); - util::remap_sections([](const std::string &line, size_t size) { - return line.find(BUILD_PACKAGE) != std::string::npos; - }); - hide_anonymous_dex_files(env, nullptr); return JNI_VERSION_1_6; } diff --git a/native/jni/src/util.h b/native/jni/src/util.h @@ -52,7 +52,7 @@ namespace util { return { start_offset, end_offset - start_offset }; } - static void remap_sections(std::function<bool(const std::string &, size_t)> filter) { + static void remap_sections(std::function<bool(const std::string &, size_t)> filter, bool remove_read_permission) { char buff[256]; auto maps = fopen("/proc/self/maps", "rt"); @@ -84,7 +84,7 @@ namespace util { } auto new_prot = (flags[0] == 'r' ? PROT_READ : 0) | (flags[1] == 'w' ? PROT_WRITE : 0) | (flags[2] == 'x' ? PROT_EXEC : 0); - if (new_prot & PROT_EXEC) { + if (remove_read_permission && flags[0] == 'r' && flags[2] == 'x') { new_prot &= ~PROT_READ; } mprotect((void *)start, section_size, new_prot); diff --git a/native/src/main/kotlin/me/rhunk/snapenhance/nativelib/NativeConfig.kt b/native/src/main/kotlin/me/rhunk/snapenhance/nativelib/NativeConfig.kt @@ -1,8 +1,14 @@ package me.rhunk.snapenhance.nativelib data class NativeConfig( + @JvmField val disableBitmoji: Boolean = false, + @JvmField val disableMetrics: Boolean = false, + @JvmField val composerHooks: Boolean = false, + @JvmField + val remapExecutable: Boolean = false, + @JvmField val customEmojiFontPath: String? = null, ) \ No newline at end of file