use random class names

This commit is contained in:
kotori0 2022-02-02 00:04:59 +08:00 committed by LoveSy
parent db7d1b9323
commit d40191b711
14 changed files with 106 additions and 34 deletions

View File

@ -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"

View File

@ -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);
}

View File

@ -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",

View File

@ -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 {

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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) {

View File

@ -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();

View File

@ -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();
}

View File

@ -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();