use random class names
This commit is contained in:
parent
db7d1b9323
commit
d40191b711
|
|
@ -20,6 +20,7 @@
|
|||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "jni/zygisk.h"
|
||||
#include "logging.h"
|
||||
|
|
|
|||
|
|
@ -24,10 +24,19 @@
|
|||
#include "macros.h"
|
||||
#include <string>
|
||||
#include "logging.h"
|
||||
#include "base/object.h"
|
||||
|
||||
#define JNI_START JNIEnv *env, [[maybe_unused]] jclass clazz
|
||||
|
||||
namespace JNIHelper {
|
||||
template<class, template<class, class...> class>
|
||||
struct is_instance : public std::false_type {
|
||||
};
|
||||
|
||||
template<class...Ts, template<class, class...> class U>
|
||||
struct is_instance<U<Ts...>, U> : public std::true_type {
|
||||
};
|
||||
}
|
||||
|
||||
class JUTFString {
|
||||
public:
|
||||
inline JUTFString(JNIEnv *env, jstring jstr) : JUTFString(env, jstr, nullptr) {
|
||||
|
|
@ -170,7 +179,7 @@ template<typename T>
|
|||
[[maybe_unused]]
|
||||
inline auto unwrap_scope(T &&x) {
|
||||
if constexpr (std::is_same_v<std::decay_t<T>, std::string_view>) return x.data();
|
||||
else if constexpr (lspd::is_instance<std::decay_t<T>, ScopedLocalRef>::value) return x.get();
|
||||
else if constexpr (JNIHelper::is_instance<std::decay_t<T>, ScopedLocalRef>::value) return x.get();
|
||||
else return std::forward<T>(x);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ namespace lspd {
|
|||
|
||||
RegisterResourcesHook(env);
|
||||
RegisterArtClassLinker(env);
|
||||
RegisterYahfa(env);
|
||||
RegisterYahfa(env, obfuscated_signature_);
|
||||
RegisterPendingHooks(env);
|
||||
RegisterNativeAPI(env);
|
||||
}
|
||||
|
|
@ -195,6 +195,7 @@ namespace lspd {
|
|||
instance->HookBridge(*this, env);
|
||||
|
||||
if (binder) {
|
||||
obfuscated_signature_ = std::move(std::get<2>(dex));
|
||||
InstallInlineHooks();
|
||||
Init(env);
|
||||
FindAndCall(env, "forkSystemServerPost", "(Landroid/os/IBinder;)V", binder);
|
||||
|
|
@ -256,6 +257,7 @@ namespace lspd {
|
|||
InstallInlineHooks();
|
||||
auto dex = instance->RequestLSPDex(env, binder);
|
||||
LoadDex(env, std::get<0>(dex), std::get<1>(dex));
|
||||
obfuscated_signature_ = std::move(std::get<2>(dex));
|
||||
Init(env);
|
||||
LOGD("Done prepare");
|
||||
FindAndCall(env, "forkAndSpecializePost",
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ namespace lspd {
|
|||
jclass class_linker_class_ = nullptr;
|
||||
jmethodID post_fixup_static_mid_ = nullptr;
|
||||
bool skip_ = false;
|
||||
std::string obfuscated_signature_;
|
||||
|
||||
struct PreloadedDex {
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ namespace lspd {
|
|||
|
||||
std::vector<std::pair<void *, void*>> jit_movements_;
|
||||
std::shared_mutex jit_movements_lock_;
|
||||
|
||||
std::string obfuscated_signature_;
|
||||
}
|
||||
|
||||
bool isHooked(void *art_method) {
|
||||
|
|
@ -119,7 +121,7 @@ namespace lspd {
|
|||
cbuilder.set_source_file("LSP");
|
||||
|
||||
auto hooker_type =
|
||||
TypeDescriptor::FromClassname("ac.ksmm.notioss.lspdaa.LspHooker");
|
||||
TypeDescriptor::FromClassname(obfuscated_signature_.c_str());
|
||||
|
||||
auto *hooker_field = cbuilder.CreateField("hooker", hooker_type)
|
||||
.access_flags(dex::kAccStatic)
|
||||
|
|
@ -214,7 +216,10 @@ namespace lspd {
|
|||
"(Ljava/lang/ClassLoader;C[CLjava/lang/String;)Ljava/lang/Class;"),
|
||||
};
|
||||
|
||||
void RegisterYahfa(JNIEnv *env) {
|
||||
void RegisterYahfa(JNIEnv *env, std::string obfuscated_signature) {
|
||||
std::replace(obfuscated_signature.begin(), obfuscated_signature.end(), '/', '.');
|
||||
obfuscated_signature_ = obfuscated_signature.substr(1) + ".LspHooker";
|
||||
LOGD("RegisterYahfa: obfuscated_signature_=%s", obfuscated_signature_.c_str());
|
||||
REGISTER_LSP_NATIVE_METHODS(Yahfa);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,6 @@ namespace lspd {
|
|||
|
||||
std::vector<std::pair<void*, void*>> getJitMovements();
|
||||
|
||||
void RegisterYahfa(JNIEnv *);
|
||||
void RegisterYahfa(JNIEnv *, std::string obfuscated_signature);
|
||||
|
||||
} // namespace lspd
|
||||
|
|
|
|||
|
|
@ -120,6 +120,8 @@ namespace lspd {
|
|||
read_long_method_ = JNI_GetMethodID(env, parcel_class_, "readLong", "()J");
|
||||
read_strong_binder_method_ = JNI_GetMethodID(env, parcel_class_, "readStrongBinder",
|
||||
"()Landroid/os/IBinder;");
|
||||
read_string_method_ = JNI_GetMethodID(env, parcel_class_, "readString",
|
||||
"()Ljava/lang/String;");
|
||||
read_file_descriptor_method_ = JNI_GetMethodID(env, parcel_class_, "readFileDescriptor",
|
||||
"()Landroid/os/ParcelFileDescriptor;");
|
||||
// createStringArray_ = env->GetMethodID(parcel_class_, "createStringArray",
|
||||
|
|
@ -307,7 +309,7 @@ namespace lspd {
|
|||
return app_binder;
|
||||
}
|
||||
|
||||
std::tuple<int, size_t> Service::RequestLSPDex(JNIEnv *env, const ScopedLocalRef<jobject> &binder) {
|
||||
std::tuple<int, size_t, std::string> Service::RequestLSPDex(JNIEnv *env, const ScopedLocalRef<jobject> &binder) {
|
||||
auto data = JNI_CallStaticObjectMethod(env, parcel_class_, obtain_method_);
|
||||
auto reply = JNI_CallStaticObjectMethod(env, parcel_class_, obtain_method_);
|
||||
auto res = JNI_CallBooleanMethod(env, binder, transact_method_,
|
||||
|
|
@ -316,15 +318,18 @@ namespace lspd {
|
|||
reply, 0);
|
||||
if (!res) {
|
||||
LOGE("Service::RequestLSPDex: transaction failed?");
|
||||
return {-1, 0};
|
||||
return {-1, 0, ""};
|
||||
}
|
||||
auto parcel_fd = JNI_CallObjectMethod(env, reply, read_file_descriptor_method_);
|
||||
int fd = JNI_CallIntMethod(env, parcel_fd, get_fd_method);
|
||||
auto size = JNI_CallLongMethod(env, reply, read_long_method_);
|
||||
auto signature = JNI_CallObjectMethod(env, reply, read_string_method_);
|
||||
JNI_CallVoidMethod(env, data, recycleMethod_);
|
||||
JNI_CallVoidMethod(env, reply, recycleMethod_);
|
||||
|
||||
LOGD("Service::RequestLSPDex fd=%d, size=%zu", fd, size);
|
||||
return {fd, size};
|
||||
JUTFString sign(env, static_cast<jstring>(signature.get()));
|
||||
|
||||
LOGD("Service::RequestLSPDex fd=%d, size=%zu, sign=%s", fd, size, sign.get());
|
||||
return {fd, size, sign.get()};
|
||||
}
|
||||
} // namespace lspd
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ namespace lspd {
|
|||
|
||||
ScopedLocalRef<jobject> RequestBinderForSystemServer(JNIEnv *env);
|
||||
|
||||
std::tuple<int, size_t> RequestLSPDex(JNIEnv *env, const ScopedLocalRef<jobject> &binder);
|
||||
std::tuple<int, size_t, std::string> RequestLSPDex(JNIEnv *env, const ScopedLocalRef<jobject> &binder);
|
||||
|
||||
private:
|
||||
inline static std::unique_ptr<Service> instance_ = std::make_unique<Service>();
|
||||
|
|
@ -98,6 +98,7 @@ namespace lspd {
|
|||
jmethodID write_strong_binder_method_ = nullptr;
|
||||
jmethodID read_file_descriptor_method_ = nullptr;
|
||||
jmethodID read_long_method_ = nullptr;
|
||||
jmethodID read_string_method_ = nullptr;
|
||||
|
||||
jclass parcel_file_descriptor_class_ = nullptr;
|
||||
jmethodID get_fd_method = nullptr;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ LOCAL_PATH := $(call my-dir)
|
|||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := daemon
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)../../../../core/src/main/cpp/main/include/
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../../core/src/main/cpp/main/include/
|
||||
LOCAL_SRC_FILES := logcat.cpp obfuscation.cpp ../../../../core/src/main/cpp/main/api/config.cpp
|
||||
LOCAL_STATIC_LIBRARIES := cxx dex_builder
|
||||
LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <jni.h>
|
||||
#include <unistd.h>
|
||||
#include <random>
|
||||
#include <unordered_map>
|
||||
#include <sys/mman.h>
|
||||
#include <android/sharedmem.h>
|
||||
|
|
@ -12,8 +13,8 @@
|
|||
#include <fcntl.h>
|
||||
#include "slicer/reader.h"
|
||||
#include "slicer/writer.h"
|
||||
// TODO: BAD
|
||||
#include "../../../../core/src/main/cpp/main/include/config.h"
|
||||
#include "config.h"
|
||||
#include "jni_helper.h"
|
||||
|
||||
class WA: public dex::Writer::Allocator {
|
||||
std::unordered_map<void*, size_t> allocated_;
|
||||
|
|
@ -29,16 +30,51 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
static std::string obfuscated_signature;
|
||||
static const std::string old_signature = "Lde/robv/android/xposed";
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_org_lsposed_lspd_service_ObfuscationManager_getObfuscatedSignature(JNIEnv *env, jclass ) {
|
||||
if (!obfuscated_signature.empty()) {
|
||||
return env->NewStringUTF(obfuscated_signature.c_str());
|
||||
}
|
||||
|
||||
static auto& chrs = "abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
thread_local static std::mt19937 rg{std::random_device{}()};
|
||||
thread_local static std::uniform_int_distribution<std::string::size_type> pick(0, sizeof(chrs) - 2);
|
||||
thread_local static std::uniform_int_distribution<std::string::size_type> choose_slash(0, 10);
|
||||
|
||||
size_t length = old_signature.size();
|
||||
obfuscated_signature.reserve(length);
|
||||
obfuscated_signature += "L";
|
||||
|
||||
for (size_t i = 1; i < length; i++) {
|
||||
if (choose_slash(rg) > 8 && // 80% alphabet + 20% slashes
|
||||
obfuscated_signature[i - 1] != '/' && // slashes could not stick together
|
||||
i != 1 && // the first character should not be slash
|
||||
i != length - 1) { // and the last character
|
||||
obfuscated_signature += "/";
|
||||
} else {
|
||||
obfuscated_signature += chrs[pick(rg)];
|
||||
}
|
||||
}
|
||||
LOGD("ObfuscationManager.getObfuscatedSignature: %s", obfuscated_signature.c_str());
|
||||
return env->NewStringUTF(obfuscated_signature.c_str());
|
||||
}
|
||||
|
||||
using ustring = std::basic_string<uint8_t>;
|
||||
ustring obfuscateDex(void *dex, size_t size) {
|
||||
const char* new_sig = "Lac/ksmm/notioss/lspdaa";
|
||||
const char* new_sig = obfuscated_signature.c_str();
|
||||
dex::Reader reader{reinterpret_cast<dex::u1*>(dex), size};
|
||||
|
||||
reader.CreateFullIr();
|
||||
auto ir = reader.GetIr();
|
||||
for (auto &i: ir->strings) {
|
||||
const char *s = i->c_str();
|
||||
char* p = const_cast<char *>(strstr(s, "Lde/robv/android/xposed"));
|
||||
char* p = const_cast<char *>(strstr(s, old_signature.c_str()));
|
||||
if (p) {
|
||||
memcpy(p, new_sig, strlen(new_sig));
|
||||
}
|
||||
|
|
@ -53,8 +89,6 @@ ustring obfuscateDex(void *dex, size_t size) {
|
|||
return new_dex;
|
||||
}
|
||||
|
||||
static jobject lspdDex = nullptr;
|
||||
|
||||
jobject new_sharedmem(JNIEnv* env, jint size) {
|
||||
jclass clazz = env->FindClass("android/os/SharedMemory");
|
||||
auto *ref = env->NewGlobalRef(clazz);
|
||||
|
|
@ -66,11 +100,14 @@ jobject new_sharedmem(JNIEnv* env, jint size) {
|
|||
return new_mem;
|
||||
}
|
||||
|
||||
static jobject lspdDex = nullptr;
|
||||
static std::mutex dex_lock;
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_lsposed_lspd_service_LSPApplicationService_preloadDex(JNIEnv *env, jclass ) {
|
||||
Java_org_lsposed_lspd_service_ObfuscationManager_preloadDex(JNIEnv *env, jclass ) {
|
||||
using namespace std::string_literals;
|
||||
// TODO: Lock?
|
||||
std::lock_guard lg(dex_lock);
|
||||
if (lspdDex) return ASharedMemory_dupFromJava(env, lspdDex);
|
||||
std::string dex_path = "/data/adb/modules/"s + lspd::moduleName + "/" + lspd::kDexPath;
|
||||
|
||||
|
|
@ -109,7 +146,7 @@ Java_org_lsposed_lspd_service_LSPApplicationService_preloadDex(JNIEnv *env, jcla
|
|||
|
||||
extern "C"
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_org_lsposed_lspd_service_LSPApplicationService_getPreloadedDexSize(JNIEnv *env, jclass ) {
|
||||
Java_org_lsposed_lspd_service_ObfuscationManager_getPreloadedDexSize(JNIEnv *env, jclass ) {
|
||||
if (lspdDex) {
|
||||
auto fd = ASharedMemory_dupFromJava(env, lspdDex);
|
||||
return ASharedMemory_getSize(fd);
|
||||
|
|
@ -119,7 +156,7 @@ Java_org_lsposed_lspd_service_LSPApplicationService_getPreloadedDexSize(JNIEnv *
|
|||
|
||||
extern "C"
|
||||
JNIEXPORT jobject
|
||||
Java_org_lsposed_lspd_service_LSPApplicationService_obfuscateDex(JNIEnv *env, jclass /*clazz*/,
|
||||
Java_org_lsposed_lspd_service_ObfuscationManager_obfuscateDex(JNIEnv *env, jclass /*clazz*/,
|
||||
jobject memory) {
|
||||
int fd = ASharedMemory_dupFromJava(env, memory);
|
||||
auto size = ASharedMemory_getSize(fd);
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ public class ConfigFileManager {
|
|||
var byteBuffer = memory.mapReadWrite();
|
||||
Channels.newChannel(in).read(byteBuffer);
|
||||
SharedMemory.unmap(byteBuffer);
|
||||
memory = LSPApplicationService.obfuscateDex(memory);
|
||||
memory = ObfuscationManager.obfuscateDex(memory);
|
||||
memory.setProtect(OsConstants.PROT_READ);
|
||||
preLoadedDexes.add(memory);
|
||||
} catch (IOException | ErrnoException e) {
|
||||
|
|
|
|||
|
|
@ -51,9 +51,10 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
|
|||
Log.i(TAG, "LSPApplicationService.onTransact: code=" + code);
|
||||
if (code == DEX_TRANSACTION_CODE) {
|
||||
try {
|
||||
ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(preloadDex());
|
||||
ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(ObfuscationManager.preloadDex());
|
||||
reply.writeFileDescriptor(pfd.getFileDescriptor());
|
||||
reply.writeLong(getPreloadedDexSize());
|
||||
reply.writeLong(ObfuscationManager.getPreloadedDexSize());
|
||||
reply.writeString(ObfuscationManager.getObfuscatedSignature());
|
||||
} catch (IOException ignored) {
|
||||
Log.e(TAG, "LSPApplicationService.onTransact: ParcelFileDescriptor.fromFd failed");
|
||||
return false;
|
||||
|
|
@ -87,14 +88,6 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
|
|||
}
|
||||
}
|
||||
|
||||
static native SharedMemory obfuscateDex(SharedMemory memory);
|
||||
|
||||
// preload lspd dex only, on daemon startup.
|
||||
// it will cache the result, so we could obtain it back on startup.
|
||||
static native int preloadDex();
|
||||
|
||||
static native long getPreloadedDexSize();
|
||||
|
||||
@Override
|
||||
public List<Module> getModulesList(String processName) throws RemoteException {
|
||||
ensureRegistered();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
package org.lsposed.lspd.service;
|
||||
|
||||
import android.os.SharedMemory;
|
||||
|
||||
public class ObfuscationManager {
|
||||
// For module dexes
|
||||
static native SharedMemory obfuscateDex(SharedMemory memory);
|
||||
|
||||
// preload lspd dex only, on daemon startup.
|
||||
// it will cache the result, so we could obtain it back on startup.
|
||||
static native int preloadDex();
|
||||
|
||||
static native long getPreloadedDexSize();
|
||||
|
||||
// generates signature
|
||||
static native String getObfuscatedSignature();
|
||||
}
|
||||
|
|
@ -98,7 +98,8 @@ public class ServiceManager {
|
|||
logcatService.start();
|
||||
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
|
||||
LSPApplicationService.preloadDex();
|
||||
ObfuscationManager.getObfuscatedSignature();
|
||||
ObfuscationManager.preloadDex();
|
||||
Looper.prepareMainLooper();
|
||||
mainService = new LSPosedService();
|
||||
applicationService = new LSPApplicationService();
|
||||
|
|
|
|||
Loading…
Reference in New Issue