mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-05-28 12:30:12 +02:00
fix: native crash
This commit is contained in:
parent
94b519614d
commit
fe9164b423
@ -135,8 +135,8 @@ class SnapEnhance {
|
||||
reloadConfig()
|
||||
actionManager.init()
|
||||
initConfigListener()
|
||||
initNative()
|
||||
scope.launch(Dispatchers.IO) {
|
||||
initNative()
|
||||
translation.userLocale = getConfigLocale()
|
||||
translation.loadFromCallback { locale ->
|
||||
bridgeClient.fetchLocales(locale)
|
||||
@ -170,16 +170,23 @@ class SnapEnhance {
|
||||
private fun initNative() {
|
||||
// don't initialize native when not logged in
|
||||
if (!appContext.database.hasArroyo()) return
|
||||
appContext.native.apply {
|
||||
if (appContext.config.experimental.nativeHooks.globalState != true) return@apply
|
||||
initOnce(appContext.androidContext.classLoader)
|
||||
nativeUnaryCallCallback = { request ->
|
||||
if (appContext.config.experimental.nativeHooks.globalState != true) return
|
||||
|
||||
lateinit var unhook: () -> Unit
|
||||
Runtime::class.java.declaredMethods.first {
|
||||
it.name == "loadLibrary0" && it.parameterTypes.contentEquals(arrayOf(ClassLoader::class.java, Class::class.java, String::class.java))
|
||||
}.hook(HookStage.AFTER) { param ->
|
||||
val libName = param.arg<String>(2)
|
||||
if (libName != "client") return@hook
|
||||
unhook()
|
||||
appContext.native.initOnce(appContext.androidContext.classLoader)
|
||||
appContext.native.nativeUnaryCallCallback = { request ->
|
||||
appContext.event.post(NativeUnaryCallEvent(request.uri, request.buffer)) {
|
||||
request.buffer = buffer
|
||||
request.canceled = canceled
|
||||
}
|
||||
}
|
||||
}
|
||||
}.also { unhook = { it.unhook() } }
|
||||
}
|
||||
|
||||
private fun initConfigListener() {
|
||||
|
@ -71,11 +71,10 @@ static void *unaryCall_hook(void *unk1, const char *uri, grpc::grpc_byte_buffer
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto new_buffer = env->GetObjectField(native_request_data_object, env->GetFieldID(native_request_data_class, "buffer", "[B"));
|
||||
auto new_buffer_length = env->GetArrayLength((jbyteArray)new_buffer);
|
||||
auto new_buffer_data = env->GetByteArrayElements((jbyteArray)new_buffer, nullptr);
|
||||
auto new_buffer = (jbyteArray)env->GetObjectField(native_request_data_object, env->GetFieldID(native_request_data_class, "buffer", "[B"));
|
||||
auto new_buffer_length = env->GetArrayLength(new_buffer);
|
||||
auto new_buffer_data = env->GetByteArrayElements(new_buffer, nullptr);
|
||||
|
||||
LOGD("rewrote request for %s (length: %d)", uri, new_buffer_length);
|
||||
//we need to allocate a new ref_counter struct and copy the old ref_counter and the new_buffer to it
|
||||
const static auto ref_counter_struct_size = (uintptr_t)slice_buffer->data - (uintptr_t)slice_buffer->ref_counter;
|
||||
|
||||
@ -119,17 +118,13 @@ void JNICALL init(JNIEnv *env, jobject clazz, jobject classloader) {
|
||||
native_lib_on_unary_call_method = env->GetMethodID(env->GetObjectClass(clazz), "onNativeUnaryCall", "(Ljava/lang/String;[B)L" BUILD_NAMESPACE "/NativeRequestData;");
|
||||
native_lib_on_asset_load = env->GetMethodID(env->GetObjectClass(clazz), "shouldLoadAsset", "(Ljava/lang/String;)Z");
|
||||
|
||||
// load libclient.so
|
||||
util::load_library(env, classloader, "client");
|
||||
auto client_module = util::get_module("libclient.so");
|
||||
|
||||
if (client_module.base == 0) {
|
||||
LOGE("libclient not found");
|
||||
LOGE("libclient not loaded!");
|
||||
return;
|
||||
}
|
||||
|
||||
// client_module.base -= 0x1000;
|
||||
// debugging purposes
|
||||
LOGD("libclient.so base=0x%0lx, size=0x%0lx", client_module.base, client_module.size);
|
||||
|
||||
// hooks
|
||||
@ -142,6 +137,7 @@ void JNICALL init(JNIEnv *env, jobject clazz, jobject classloader) {
|
||||
);
|
||||
|
||||
if (unaryCall_func != 0) {
|
||||
LOGD("found unaryCall at 0x%0lx", unaryCall_func);
|
||||
DobbyHook((void *)unaryCall_func, (void *)unaryCall_hook, (void **)&unaryCall_original);
|
||||
} else {
|
||||
LOGE("can't find unaryCall signature");
|
||||
|
@ -8,25 +8,11 @@ namespace util {
|
||||
size_t size;
|
||||
} module_info_t;
|
||||
|
||||
static void hexDump(void *ptr, uint8_t line_length, uint32_t lines) {
|
||||
auto *p = (unsigned char *) ptr;
|
||||
for (uint8_t i = 0; i < lines; i++) {
|
||||
std::string line;
|
||||
for (uint8_t j = 0; j < line_length; j++) {
|
||||
char buf[3];
|
||||
sprintf(buf, "%02x", p[i * line_length + j]);
|
||||
line += buf;
|
||||
line += " ";
|
||||
}
|
||||
LOGI("%s", line.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
static module_info_t get_module(const char *libname) {
|
||||
char buff[256];
|
||||
int len_libname = strlen(libname);
|
||||
uintptr_t addr = 0;
|
||||
size_t size = 0;
|
||||
uintptr_t start_offset = 0;
|
||||
uintptr_t end_offset = 0;
|
||||
|
||||
auto file = fopen("/proc/self/smaps", "rt");
|
||||
if (file == NULL)
|
||||
@ -47,25 +33,20 @@ namespace util {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (addr == 0 && flags[0] == 'r' && flags[2] == 'x') {
|
||||
addr = start - offset;
|
||||
if (flags[0] != 'r' || flags[2] != 'x') {
|
||||
continue;
|
||||
}
|
||||
if (addr != 0) {
|
||||
size += end - start;
|
||||
|
||||
if (start_offset == 0) {
|
||||
start_offset = start;
|
||||
}
|
||||
end_offset = end;
|
||||
}
|
||||
fclose(file);
|
||||
return {addr, size};
|
||||
}
|
||||
|
||||
void load_library(JNIEnv *env, jobject classLoader, const char *libName) {
|
||||
auto runtimeClass = env->FindClass("java/lang/Runtime");
|
||||
auto getRuntimeMethod = env->GetStaticMethodID(runtimeClass, "getRuntime",
|
||||
"()Ljava/lang/Runtime;");
|
||||
auto runtime = env->CallStaticObjectMethod(runtimeClass, getRuntimeMethod);
|
||||
auto loadLibraryMethod = env->GetMethodID(runtimeClass, "loadLibrary0",
|
||||
"(Ljava/lang/ClassLoader;Ljava/lang/String;)V");
|
||||
env->CallVoidMethod(runtime, loadLibraryMethod, classLoader, env->NewStringUTF(libName));
|
||||
if (start_offset == 0) {
|
||||
return {0, 0};
|
||||
}
|
||||
return { start_offset, end_offset - start_offset };
|
||||
}
|
||||
|
||||
uintptr_t find_signature(uintptr_t module_base, uintptr_t size, const std::string &pattern, int offset = 0) {
|
||||
@ -96,35 +77,4 @@ namespace util {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uintptr_t> find_signatures(uintptr_t module_base, uintptr_t size, const std::string &pattern, int offset = 0) {
|
||||
std::vector<uintptr_t> results;
|
||||
std::vector<char> bytes;
|
||||
std::vector<char> mask;
|
||||
|
||||
for (size_t i = 0; i < pattern.size(); i += 3) {
|
||||
if (pattern[i] == '?') {
|
||||
bytes.push_back(0);
|
||||
mask.push_back('?');
|
||||
} else {
|
||||
bytes.push_back(std::stoi(pattern.substr(i, 2), nullptr, 16));
|
||||
mask.push_back('x');
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
bool found = true;
|
||||
for (size_t j = 0; j < bytes.size(); j++) {
|
||||
if (mask[j] == '?' || bytes[j] == *(char *) (module_base + i + j)) {
|
||||
continue;
|
||||
}
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
if (found) {
|
||||
results.push_back(module_base + i + offset);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user