diff --git a/core/src/main/cpp/main/Android.mk b/core/src/main/cpp/main/Android.mk index bf47e448..19c2e984 100644 --- a/core/src/main/cpp/main/Android.mk +++ b/core/src/main/cpp/main/Android.mk @@ -5,9 +5,9 @@ endef include $(CLEAR_VARS) LOCAL_MODULE := lspd -LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/src +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/src $(LOCAL_PATH)/../shared/ FILE_LIST := $(filter %.cpp, $(call walk, $(LOCAL_PATH)/src)) -LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%) api/config.cpp +LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%) api/config.cpp ../shared/Obfuscation.cpp LOCAL_STATIC_LIBRARIES := cxx riru yahfa dobby dex_builder ifeq ($(API), riru) LOCAL_SRC_FILES += api/riru_main.cpp diff --git a/core/src/main/cpp/main/src/context.cpp b/core/src/main/cpp/main/src/context.cpp index f1767413..d4e56a67 100644 --- a/core/src/main/cpp/main/src/context.cpp +++ b/core/src/main/cpp/main/src/context.cpp @@ -30,6 +30,10 @@ #include "jni/native_api.h" #include "service.h" #include "symbol_cache.h" +#include "slicer/reader.h" +#include "slicer/writer.h" +#include "slicer/dex_utf8.h" +#include "Obfuscation.h" #include #include @@ -64,20 +68,40 @@ namespace lspd { } Context::PreloadedDex::PreloadedDex(int fd, std::size_t size) { - if (auto addr = mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0); addr) { + auto *old = mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0); + auto *addr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + if (old != MAP_FAILED && addr != MAP_FAILED) { + memmove(addr, old, size); addr_ = addr; size_ = size; } else { - LOGE("Read dex failed"); + if (old == MAP_FAILED) LOGE("Old failed"); + if (addr == MAP_FAILED) LOGE("addr failed"); + LOGE("Read dex failed: %s", strerror(errno)); } + munmap(old, size); } Context::PreloadedDex::~PreloadedDex() { if (*this) munmap(addr_, size_); } + void Context::ObfuscateDex() { + if (!dex_) [[unlikely]] return; + + auto dex = Obfuscation::obfuscateDex(dex_.data(), dex_.size()); + // TODO: multiple memory copy prevention + auto *mem = mmap(nullptr, dex.size(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + memmove(mem, dex.data(), dex.size()); + PreloadedDex new_dex(mem, dex.size()); + std::swap(dex_, new_dex); + LOGD("Context::ObfuscateDex: %p, size=%zu", reinterpret_cast(dex_.data()), dex.size()); + } + void Context::PreLoadDex(int fd, std::size_t size) { dex_ = PreloadedDex{fd, size}; + ObfuscateDex(); } void Context::PreLoadDex(std::string_view dex_path) { diff --git a/core/src/main/cpp/main/src/context.h b/core/src/main/cpp/main/src/context.h index ea44134d..dabc39b0 100644 --- a/core/src/main/cpp/main/src/context.h +++ b/core/src/main/cpp/main/src/context.h @@ -97,6 +97,9 @@ namespace lspd { other.size_ = 0; }; + // Use with caution! + PreloadedDex(void* addr, size_t size) : addr_(addr), size_(size) {}; + operator bool() const { return addr_ && size_; } auto size() const { return size_; } @@ -112,6 +115,8 @@ namespace lspd { PreloadedDex dex_{}; + void ObfuscateDex(); + Context() {} void LoadDex(JNIEnv *env); diff --git a/core/src/main/cpp/main/src/jni/yahfa.cpp b/core/src/main/cpp/main/src/jni/yahfa.cpp index f9e7d8ce..a2732584 100644 --- a/core/src/main/cpp/main/src/jni/yahfa.cpp +++ b/core/src/main/cpp/main/src/jni/yahfa.cpp @@ -119,7 +119,7 @@ namespace lspd { cbuilder.set_source_file("LSP"); auto hooker_type = - TypeDescriptor::FromClassname("de.robv.android.xposed.LspHooker"); + TypeDescriptor::FromClassname("ac.ksmm.notioss.lspdaa.LspHooker"); auto *hooker_field = cbuilder.CreateField("hooker", hooker_type) .access_flags(dex::kAccStatic) diff --git a/core/src/main/cpp/shared/Obfuscation.cpp b/core/src/main/cpp/shared/Obfuscation.cpp new file mode 100644 index 00000000..25ba2319 --- /dev/null +++ b/core/src/main/cpp/shared/Obfuscation.cpp @@ -0,0 +1,47 @@ +// +// Created by Kotori0 on 2021/12/2. +// + +#include +#include +#include +#include "slicer/reader.h" +#include "slicer/writer.h" +#include "Obfuscation.h" + +class WA: public dex::Writer::Allocator { + std::unordered_map allocated_; +public: + void* Allocate(size_t size) override { + auto *mem = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + allocated_[mem] = size; + return mem; + } + void Free(void* ptr) override { + munmap(ptr, allocated_[ptr]); + allocated_.erase(ptr); + } +}; + +ustring Obfuscation::obfuscateDex(void *dex, size_t size) { + const char* new_sig = "Lac/ksmm/notioss/lspdaa"; + dex::Reader reader{reinterpret_cast(dex), size}; + + reader.CreateFullIr(); + auto ir = reader.GetIr(); + for (auto &i: ir->strings) { + const char *s = i->c_str(); + char* p = const_cast(strstr(s, "Lde/robv/android/xposed")); + if (p) { + memcpy(p, new_sig, strlen(new_sig)); + } + } + dex::Writer writer(ir); + + size_t new_size; + WA allocator; + auto *p_dex = writer.CreateImage(&allocator, &new_size); + ustring new_dex(p_dex, new_size); + allocator.Free(p_dex); + return new_dex; +} \ No newline at end of file diff --git a/core/src/main/cpp/shared/Obfuscation.h b/core/src/main/cpp/shared/Obfuscation.h new file mode 100644 index 00000000..12e692e4 --- /dev/null +++ b/core/src/main/cpp/shared/Obfuscation.h @@ -0,0 +1,17 @@ +// +// Created by Kotori0 on 2021/12/2. +// + +#ifndef LSPOSED_OBFUSCATION_H +#define LSPOSED_OBFUSCATION_H +#include "slicer/writer.h" + +using ustring = std::basic_string; + +class Obfuscation { +public: + static ustring obfuscateDex(void* dex, size_t size); +}; + + +#endif //LSPOSED_OBFUSCATION_H \ No newline at end of file diff --git a/daemon/src/main/cpp/Android.mk b/daemon/src/main/cpp/Android.mk index f60d3961..ad54eb5b 100644 --- a/daemon/src/main/cpp/Android.mk +++ b/daemon/src/main/cpp/Android.mk @@ -2,10 +2,12 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := daemon -LOCAL_SRC_FILES := logcat.cpp -LOCAL_STATIC_LIBRARIES := cxx +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../../core/src/main/cpp/shared/ +LOCAL_SRC_FILES := logcat.cpp obfuscation.cpp ../../../../core/src/main/cpp/shared/Obfuscation.cpp +LOCAL_STATIC_LIBRARIES := cxx dex_builder LOCAL_ALLOW_UNDEFINED_SYMBOLS := true -LOCAL_LDLIBS := -llog +LOCAL_LDLIBS := -llog -landroid include $(BUILD_SHARED_LIBRARY) +include ../core/src/main/cpp/external/DexBuilder/Android.mk $(call import-module,prefab/cxx) \ No newline at end of file diff --git a/daemon/src/main/cpp/obfuscation.cpp b/daemon/src/main/cpp/obfuscation.cpp new file mode 100644 index 00000000..1db6eb65 --- /dev/null +++ b/daemon/src/main/cpp/obfuscation.cpp @@ -0,0 +1,49 @@ +// +// Created by Kotori2 on 2021/12/1. +// + +#include +#include +#include +#include +#include +#include +#include +#include "slicer/reader.h" +#include "slicer/writer.h" +#include "Obfuscation.h" +#include + +extern "C" +JNIEXPORT jobject +Java_org_lsposed_lspd_service_ObfuscationService_obfuscateDex(JNIEnv *env, jclass /*clazz*/, + jobject memory) { + int fd = ASharedMemory_dupFromJava(env, memory); + auto size = ASharedMemory_getSize(fd); + ustring mem_wrapper; + mem_wrapper.resize(size); + read(fd, mem_wrapper.data(), size); + + void *mem = mem_wrapper.data(); + + auto new_dex = Obfuscation::obfuscateDex(mem, size); + + // create new SharedMem since it cannot be resized + jclass clazz = env->FindClass("android/os/SharedMemory"); + auto *ref = env->NewGlobalRef(clazz); + jmethodID mid = env->GetStaticMethodID(clazz, "create", "(Ljava/lang/String;I)Landroid/os/SharedMemory;"); + jstring empty_str = env->NewStringUTF(""); + jobject new_mem = env->CallStaticObjectMethod(clazz, mid, empty_str, static_cast(new_dex.size())); + int new_fd = ASharedMemory_dupFromJava(env, new_mem); + + env->DeleteGlobalRef(ref); + env->DeleteLocalRef(empty_str); + + mem = mmap(nullptr, new_dex.size(), PROT_READ | PROT_WRITE, MAP_SHARED, new_fd, 0); + if (mem == MAP_FAILED) { + // LOGE("Failed to map new dex to memory?"); + } + memcpy(mem, new_dex.data(), new_dex.size()); + ASharedMemory_setProt(fd, PROT_READ); + return new_mem; +} \ No newline at end of file diff --git a/daemon/src/main/java/org/lsposed/lspd/service/ConfigFileManager.java b/daemon/src/main/java/org/lsposed/lspd/service/ConfigFileManager.java index f6fcdbeb..85a8676f 100644 --- a/daemon/src/main/java/org/lsposed/lspd/service/ConfigFileManager.java +++ b/daemon/src/main/java/org/lsposed/lspd/service/ConfigFileManager.java @@ -296,6 +296,7 @@ public class ConfigFileManager { var byteBuffer = memory.mapReadWrite(); Channels.newChannel(in).read(byteBuffer); SharedMemory.unmap(byteBuffer); + memory = ObfuscationService.obfuscateDex(memory); memory.setProtect(OsConstants.PROT_READ); preLoadedDexes.add(memory); } catch (IOException | ErrnoException e) { diff --git a/daemon/src/main/java/org/lsposed/lspd/service/ObfuscationService.java b/daemon/src/main/java/org/lsposed/lspd/service/ObfuscationService.java new file mode 100644 index 00000000..a342056a --- /dev/null +++ b/daemon/src/main/java/org/lsposed/lspd/service/ObfuscationService.java @@ -0,0 +1,9 @@ +package org.lsposed.lspd.service; + +import android.os.SharedMemory; + +import java.nio.ByteBuffer; + +public class ObfuscationService { + static native SharedMemory obfuscateDex(SharedMemory memory); +} \ No newline at end of file