commit 006f9f84e39bc8c9d39b011505c41de62402e0c2
parent a355ea966727fe86e35cd962dd2c9c59b649e8a8
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Tue, 11 Jun 2024 00:09:13 +0200

refactor(native): remap sections

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

Diffstat:
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt | 5+++++
Mnative/jni/src/dobby_helper.h | 1+
Mnative/jni/src/library.cpp | 18++++++++++++++++--
Mnative/jni/src/util.h | 11+++++++----
Mnative/src/main/kotlin/me/rhunk/snapenhance/nativelib/NativeLib.kt | 1+
5 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt @@ -5,6 +5,7 @@ import android.app.Application import android.content.Context import android.content.res.Resources import android.os.Build +import dalvik.system.BaseDexClassLoader import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -27,6 +28,7 @@ import me.rhunk.snapenhance.core.util.LSPatchUpdater import me.rhunk.snapenhance.core.util.hook.HookAdapter import me.rhunk.snapenhance.core.util.hook.HookStage import me.rhunk.snapenhance.core.util.hook.hook +import me.rhunk.snapenhance.core.util.hook.hookConstructor import kotlin.system.exitProcess import kotlin.system.measureTimeMillis @@ -205,6 +207,9 @@ class SnapEnhance { request.canceled = canceled } } + BaseDexClassLoader::class.java.hookConstructor(HookStage.AFTER) { + appContext.native.hideAnonymousDexFiles() + } appContext.reloadNativeConfig() } }.also { unhook = { it.unhook() } } diff --git a/native/jni/src/dobby_helper.h b/native/jni/src/dobby_helper.h @@ -9,5 +9,6 @@ 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); 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 @@ -4,9 +4,9 @@ #include <vector> #include <thread> -#include "dobby_helper.h" #include "logger.h" #include "common.h" +#include "dobby_helper.h" #include "hooks/unary_call.h" #include "hooks/fstat_hook.h" #include "hooks/sqlite_mutex.h" @@ -93,6 +93,16 @@ 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) || + line.find("dalvik-DEX") != std::string::npos || + line.find("dalvik-classes") != std::string::npos + ); + }); +} + extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *_) { common::java_vm = vm; JNIEnv *env = nullptr; @@ -104,8 +114,12 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *_) { methods.push_back({"lockDatabase", "(Ljava/lang/String;Ljava/lang/Runnable;)V", (void *)lock_database}); methods.push_back({"setComposerLoader", "(Ljava/lang/String;)V", (void *) ComposerHook::setComposerLoader}); methods.push_back({"composerEval", "(Ljava/lang/String;)Ljava/lang/String;",(void *) ComposerHook::composerEval}); + 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(BUILD_PACKAGE); + 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,14 +52,13 @@ namespace util { return { start_offset, end_offset - start_offset }; } - static void remap_sections(const char* path) { + static void remap_sections(std::function<bool(const std::string &, size_t)> filter) { char buff[256]; auto maps = fopen("/proc/self/maps", "rt"); while (fgets(buff, sizeof buff, maps) != NULL) { int len = strlen(buff); if (len > 0 && buff[len - 1] == '\n') buff[--len] = '\0'; - if (strstr(buff, path) == nullptr) continue; size_t start, end, offset; char flags[4]; @@ -67,7 +66,7 @@ namespace util { if (sscanf(buff, "%zx-%zx %c%c%c%c %zx", &start, &end, &flags[0], &flags[1], &flags[2], &flags[3], &offset) != 7) continue; - LOGD("Remapping 0x%zx-0x%zx", start, end); + if (!filter(buff, end - start)) continue; auto section_size = end - start; auto section_ptr = mmap(0, section_size, PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); @@ -84,7 +83,11 @@ namespace util { break; } - mprotect((void *)start, section_size, (flags[0] == 'r' ? PROT_READ : 0) | (flags[1] == 'w' ? PROT_WRITE : 0) | (flags[2] == 'x' ? PROT_EXEC : 0)); + 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) { + new_prot &= ~PROT_READ; + } + mprotect((void *)start, section_size, new_prot); } fclose(maps); } diff --git a/native/src/main/kotlin/me/rhunk/snapenhance/nativelib/NativeLib.kt b/native/src/main/kotlin/me/rhunk/snapenhance/nativelib/NativeLib.kt @@ -59,4 +59,5 @@ class NativeLib { private external fun lockDatabase(name: String, callback: Runnable) external fun setComposerLoader(code: String) external fun composerEval(code: String): String? + external fun hideAnonymousDexFiles() } \ No newline at end of file