feat(composer_hooks): armv7 support

This commit is contained in:
rhunk 2024-04-22 23:35:48 +02:00
parent 2bb055f464
commit 33dc0c7510
6 changed files with 39 additions and 57 deletions

View File

@ -772,7 +772,7 @@
"properties": { "properties": {
"composer_hooks": { "composer_hooks": {
"name": "Composer Hooks", "name": "Composer Hooks",
"description": "Injects code into the Composer cross-platform UI framework (arm64 only)", "description": "Injects code into the Composer cross-platform UI framework",
"properties": { "properties": {
"bypass_camera_roll_limit": { "bypass_camera_roll_limit": {
"name": "Bypass Camera Roll Limit", "name": "Bypass Camera Roll Limit",
@ -780,7 +780,7 @@
}, },
"composer_console": { "composer_console": {
"name": "Composer Console", "name": "Composer Console",
"description": "Allows you to execute JavaScript code in Composer" "description": "Allows you to execute JavaScript code in Composer (arm64 only)"
}, },
"composer_logs": { "composer_logs": {
"name": "Composer Logs", "name": "Composer Logs",

View File

@ -1,9 +1,3 @@
const callExport = require('composer_core/src/DeviceBridge')[EXPORTED_FUNCTION_NAME];
if (!callExport) {
return "No export function found";
}
const config = callExport("getConfig"); const config = callExport("getConfig");
if (config.composerLogs) { if (config.composerLogs) {

View File

@ -186,21 +186,16 @@ class ComposerHooks: Feature("ComposerHooks", loadParams = FeatureLoadParams.ACT
return return
} }
val hookResult = context.native.composerEval(""" context.native.setComposerLoader("""
(() => { try { const EXPORTED_FUNCTION_NAME = "$exportedFunctionName"; $loaderScript (() => { const callExport = require('composer_core/src/DeviceBridge')["$exportedFunctionName"]; try { $loaderScript
} catch (e) { } catch (e) {
return e.toString() + "\n" + e.stack; try {
callExport("log", "error", e.toString() + "\n" + e.stack);
} catch (t) {}
} }
return "success"; })();
})()
""".trimIndent().trim()) """.trimIndent().trim())
if (hookResult != "success") {
context.shortToast(("Composer loader failed : $hookResult").also {
context.log.error(it)
})
}
if (config.composerConsole.get()) { if (config.composerConsole.get()) {
injectConsole() injectConsole()
} }
@ -221,16 +216,6 @@ class ComposerHooks: Feature("ComposerHooks", loadParams = FeatureLoadParams.ACT
} }
} }
var composerThreadTask: (() -> Unit)? = null loadHooks()
findClass("com.snap.composer.callable.ComposerFunctionNative").hook("nativePerform", HookStage.BEFORE) {
composerThreadTask?.invoke()
composerThreadTask = null
}
context.coroutineScope.launch {
context.native.waitForComposer()
composerThreadTask = ::loadHooks
}
} }
} }

View File

@ -93,20 +93,32 @@ namespace ComposerHook {
static uintptr_t global_instance; static uintptr_t global_instance;
static JSContext *global_ctx; static JSContext *global_ctx;
static std::string* composer_loader;
HOOK_DEF(JSValue, js_eval, uintptr_t instance, JSContext *ctx, uintptr_t this_obj, uint8_t *input, uintptr_t input_len, const char *filename, unsigned int flags, unsigned int scope_idx) { HOOK_DEF(JSValue, js_eval, uintptr_t instance, JSContext *ctx, uintptr_t this_obj, char *input, uintptr_t input_len, const char *filename, unsigned int flags, unsigned int scope_idx) {
if (global_instance == 0 || global_ctx == nullptr) { if (global_instance == 0 || global_ctx == nullptr) {
global_instance = instance; global_instance = instance;
global_ctx = ctx; global_ctx = ctx;
} LOGD("Injecting composer loader");
composer_loader->resize(composer_loader->size() + input_len);
memcpy((void*) (composer_loader->c_str() + composer_loader->size() - input_len), input, input_len);
input = (char*) composer_loader->c_str();
input_len = composer_loader->size();
} else {
if (composer_loader != nullptr) {
delete composer_loader;
composer_loader = nullptr;
}
}
return js_eval_original(instance, ctx, this_obj, input, input_len, filename, flags, scope_idx); return js_eval_original(instance, ctx, this_obj, input, input_len, filename, flags, scope_idx);
} }
void waitForComposer(JNIEnv *, jobject) { void setComposerLoader(JNIEnv *env, jobject, jstring code) {
while (global_instance == 0 || global_ctx == nullptr) { auto code_str = env->GetStringUTFChars(code, nullptr);
usleep(10000); composer_loader = new std::string(code_str, env->GetStringUTFLength(code));
} env->ReleaseStringUTFChars(code, code_str);
} }
jstring composerEval(JNIEnv *env, jobject, jstring script) { jstring composerEval(JNIEnv *env, jobject, jstring script) {
@ -117,7 +129,7 @@ namespace ComposerHook {
auto script_str = env->GetStringUTFChars(script, nullptr); auto script_str = env->GetStringUTFChars(script, nullptr);
auto length = env->GetStringUTFLength(script); auto length = env->GetStringUTFLength(script);
auto jsvalue = js_eval_original(global_instance, global_ctx, (uintptr_t) &global_ctx->global_obj, (uint8_t *) script_str, length, "<input>", 0, 0); auto jsvalue = js_eval_original(global_instance, global_ctx, (uintptr_t) &global_ctx->global_obj, (char *) script_str, length, "<eval>", 0, 0);
env->ReleaseStringUTFChars(script, script_str); env->ReleaseStringUTFChars(script, script_str);
if (jsvalue.tag == JS_TAG_STRING) { if (jsvalue.tag == JS_TAG_STRING) {
@ -157,12 +169,11 @@ namespace ComposerHook {
} }
void init() { void init() {
if (!ARM64) return;
auto js_eval_ptr = util::find_signature( auto js_eval_ptr = util::find_signature(
common::client_module.base, common::client_module.base,
common::client_module.size, common::client_module.size,
"00 E4 00 6F 29 00 80 52 76 00 04 8B", ARM64 ? "00 E4 00 6F 29 00 80 52 76 00 04 8B" : "A1 B0 07 92 81 46",
-0x28 ARM64 ? -0x28 : -0x7
); );
if (js_eval_ptr == 0) { if (js_eval_ptr == 0) {
LOGE("js_eval_ptr signature not found"); LOGE("js_eval_ptr signature not found");

View File

@ -2,7 +2,6 @@
#include <string> #include <string>
#include <dobby.h> #include <dobby.h>
#include <vector> #include <vector>
#include <thread>
#include "logger.h" #include "logger.h"
#include "common.h" #include "common.h"
@ -33,21 +32,13 @@ bool JNICALL init(JNIEnv *env, jobject clazz) {
util::remap_sections(BUILD_PACKAGE); util::remap_sections(BUILD_PACKAGE);
auto threads = std::vector<std::thread>(); UnaryCallHook::init(env);
AssetHook::init(env);
#define RUN(body) \ FstatHook::init();
threads.push_back(std::thread([&] { body; })) SqliteMutexHook::init();
DuplexHook::init(env);
RUN(UnaryCallHook::init(env));
RUN(AssetHook::init(env));
RUN(FstatHook::init());
RUN(SqliteMutexHook::init());
RUN(DuplexHook::init(env));
if (common::native_config->composer_hooks) { if (common::native_config->composer_hooks) {
RUN(ComposerHook::init()); ComposerHook::init();
}
for (auto &thread : threads) {
thread.join();
} }
LOGD("Native initialized"); LOGD("Native initialized");
@ -94,7 +85,7 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *_) {
methods.push_back({"init", "()Z", (void *)init}); methods.push_back({"init", "()Z", (void *)init});
methods.push_back({"loadConfig", "(L" BUILD_NAMESPACE "/NativeConfig;)V", (void *)load_config}); methods.push_back({"loadConfig", "(L" BUILD_NAMESPACE "/NativeConfig;)V", (void *)load_config});
methods.push_back({"lockDatabase", "(Ljava/lang/String;Ljava/lang/Runnable;)V", (void *)lock_database}); methods.push_back({"lockDatabase", "(Ljava/lang/String;Ljava/lang/Runnable;)V", (void *)lock_database});
methods.push_back({"waitForComposer", "()V", (void *) ComposerHook::waitForComposer}); 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({"composerEval", "(Ljava/lang/String;)Ljava/lang/String;",(void *) ComposerHook::composerEval});
env->RegisterNatives(env->FindClass(std::string(BUILD_NAMESPACE "/NativeLib").c_str()), methods.data(), methods.size()); env->RegisterNatives(env->FindClass(std::string(BUILD_NAMESPACE "/NativeLib").c_str()), methods.data(), methods.size());

View File

@ -2,6 +2,7 @@ package me.rhunk.snapenhance.nativelib
import android.util.Log import android.util.Log
@Suppress("KotlinJniMissingFunction")
class NativeLib { class NativeLib {
var nativeUnaryCallCallback: (NativeRequestData) -> Unit = {} var nativeUnaryCallCallback: (NativeRequestData) -> Unit = {}
var nativeShouldLoadAsset: (String) -> Boolean = { true } var nativeShouldLoadAsset: (String) -> Boolean = { true }
@ -62,6 +63,6 @@ class NativeLib {
private external fun init(): Boolean private external fun init(): Boolean
private external fun loadConfig(config: NativeConfig) private external fun loadConfig(config: NativeConfig)
private external fun lockDatabase(name: String, callback: Runnable) private external fun lockDatabase(name: String, callback: Runnable)
external fun waitForComposer() external fun setComposerLoader(code: String)
external fun composerEval(code: String): String? external fun composerEval(code: String): String?
} }