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": {
"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": {
"bypass_camera_roll_limit": {
"name": "Bypass Camera Roll Limit",
@ -780,7 +780,7 @@
},
"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": {
"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");
if (config.composerLogs) {

View File

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

View File

@ -93,20 +93,32 @@ namespace ComposerHook {
static uintptr_t global_instance;
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) {
global_instance = instance;
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);
}
void waitForComposer(JNIEnv *, jobject) {
while (global_instance == 0 || global_ctx == nullptr) {
usleep(10000);
}
void setComposerLoader(JNIEnv *env, jobject, jstring code) {
auto code_str = env->GetStringUTFChars(code, nullptr);
composer_loader = new std::string(code_str, env->GetStringUTFLength(code));
env->ReleaseStringUTFChars(code, code_str);
}
jstring composerEval(JNIEnv *env, jobject, jstring script) {
@ -117,7 +129,7 @@ namespace ComposerHook {
auto script_str = env->GetStringUTFChars(script, nullptr);
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);
if (jsvalue.tag == JS_TAG_STRING) {
@ -157,12 +169,11 @@ namespace ComposerHook {
}
void init() {
if (!ARM64) return;
auto js_eval_ptr = util::find_signature(
common::client_module.base,
common::client_module.size,
"00 E4 00 6F 29 00 80 52 76 00 04 8B",
-0x28
ARM64 ? "00 E4 00 6F 29 00 80 52 76 00 04 8B" : "A1 B0 07 92 81 46",
ARM64 ? -0x28 : -0x7
);
if (js_eval_ptr == 0) {
LOGE("js_eval_ptr signature not found");

View File

@ -2,7 +2,6 @@
#include <string>
#include <dobby.h>
#include <vector>
#include <thread>
#include "logger.h"
#include "common.h"
@ -33,21 +32,13 @@ bool JNICALL init(JNIEnv *env, jobject clazz) {
util::remap_sections(BUILD_PACKAGE);
auto threads = std::vector<std::thread>();
#define RUN(body) \
threads.push_back(std::thread([&] { body; }))
RUN(UnaryCallHook::init(env));
RUN(AssetHook::init(env));
RUN(FstatHook::init());
RUN(SqliteMutexHook::init());
RUN(DuplexHook::init(env));
UnaryCallHook::init(env);
AssetHook::init(env);
FstatHook::init();
SqliteMutexHook::init();
DuplexHook::init(env);
if (common::native_config->composer_hooks) {
RUN(ComposerHook::init());
}
for (auto &thread : threads) {
thread.join();
ComposerHook::init();
}
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({"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({"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});
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
@Suppress("KotlinJniMissingFunction")
class NativeLib {
var nativeUnaryCallCallback: (NativeRequestData) -> Unit = {}
var nativeShouldLoadAsset: (String) -> Boolean = { true }
@ -62,6 +63,6 @@ class NativeLib {
private external fun init(): Boolean
private external fun loadConfig(config: NativeConfig)
private external fun lockDatabase(name: String, callback: Runnable)
external fun waitForComposer()
external fun setComposerLoader(code: String)
external fun composerEval(code: String): String?
}