[core] Runtime dex obfuscation implementation

This commit is contained in:
kotori0 2022-01-30 23:20:55 +08:00 committed by LoveSy
parent 9130d13576
commit 30d1c1b551
10 changed files with 162 additions and 8 deletions

View File

@ -5,9 +5,9 @@ endef
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_MODULE := lspd 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)) 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 LOCAL_STATIC_LIBRARIES := cxx riru yahfa dobby dex_builder
ifeq ($(API), riru) ifeq ($(API), riru)
LOCAL_SRC_FILES += api/riru_main.cpp LOCAL_SRC_FILES += api/riru_main.cpp

View File

@ -30,6 +30,10 @@
#include "jni/native_api.h" #include "jni/native_api.h"
#include "service.h" #include "service.h"
#include "symbol_cache.h" #include "symbol_cache.h"
#include "slicer/reader.h"
#include "slicer/writer.h"
#include "slicer/dex_utf8.h"
#include "Obfuscation.h"
#include <linux/fs.h> #include <linux/fs.h>
#include <fcntl.h> #include <fcntl.h>
@ -64,20 +68,40 @@ namespace lspd {
} }
Context::PreloadedDex::PreloadedDex(int fd, std::size_t size) { 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; addr_ = addr;
size_ = size; size_ = size;
} else { } 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() { Context::PreloadedDex::~PreloadedDex() {
if (*this) munmap(addr_, size_); 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::u1*>(dex_.data()), dex.size());
}
void Context::PreLoadDex(int fd, std::size_t size) { void Context::PreLoadDex(int fd, std::size_t size) {
dex_ = PreloadedDex{fd, size}; dex_ = PreloadedDex{fd, size};
ObfuscateDex();
} }
void Context::PreLoadDex(std::string_view dex_path) { void Context::PreLoadDex(std::string_view dex_path) {

View File

@ -97,6 +97,9 @@ namespace lspd {
other.size_ = 0; other.size_ = 0;
}; };
// Use with caution!
PreloadedDex(void* addr, size_t size) : addr_(addr), size_(size) {};
operator bool() const { return addr_ && size_; } operator bool() const { return addr_ && size_; }
auto size() const { return size_; } auto size() const { return size_; }
@ -112,6 +115,8 @@ namespace lspd {
PreloadedDex dex_{}; PreloadedDex dex_{};
void ObfuscateDex();
Context() {} Context() {}
void LoadDex(JNIEnv *env); void LoadDex(JNIEnv *env);

View File

@ -119,7 +119,7 @@ namespace lspd {
cbuilder.set_source_file("LSP"); cbuilder.set_source_file("LSP");
auto hooker_type = 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) auto *hooker_field = cbuilder.CreateField("hooker", hooker_type)
.access_flags(dex::kAccStatic) .access_flags(dex::kAccStatic)

View File

@ -0,0 +1,47 @@
//
// Created by Kotori0 on 2021/12/2.
//
#include <cstddef>
#include <sys/mman.h>
#include <unordered_map>
#include "slicer/reader.h"
#include "slicer/writer.h"
#include "Obfuscation.h"
class WA: public dex::Writer::Allocator {
std::unordered_map<void*, size_t> 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::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"));
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;
}

View File

@ -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<unsigned char>;
class Obfuscation {
public:
static ustring obfuscateDex(void* dex, size_t size);
};
#endif //LSPOSED_OBFUSCATION_H

View File

@ -2,10 +2,12 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_MODULE := daemon LOCAL_MODULE := daemon
LOCAL_SRC_FILES := logcat.cpp LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../../core/src/main/cpp/shared/
LOCAL_STATIC_LIBRARIES := cxx 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_ALLOW_UNDEFINED_SYMBOLS := true
LOCAL_LDLIBS := -llog LOCAL_LDLIBS := -llog -landroid
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)
include ../core/src/main/cpp/external/DexBuilder/Android.mk
$(call import-module,prefab/cxx) $(call import-module,prefab/cxx)

View File

@ -0,0 +1,49 @@
//
// Created by Kotori2 on 2021/12/1.
//
#include <jni.h>
#include <unistd.h>
#include <sys/mman.h>
#include <android/sharedmem.h>
#include <android/sharedmem_jni.h>
#include <slicer/dex_utf8.h>
#include <fcntl.h>
#include "slicer/reader.h"
#include "slicer/writer.h"
#include "Obfuscation.h"
#include <jni.h>
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<jint>(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;
}

View File

@ -296,6 +296,7 @@ public class ConfigFileManager {
var byteBuffer = memory.mapReadWrite(); var byteBuffer = memory.mapReadWrite();
Channels.newChannel(in).read(byteBuffer); Channels.newChannel(in).read(byteBuffer);
SharedMemory.unmap(byteBuffer); SharedMemory.unmap(byteBuffer);
memory = ObfuscationService.obfuscateDex(memory);
memory.setProtect(OsConstants.PROT_READ); memory.setProtect(OsConstants.PROT_READ);
preLoadedDexes.add(memory); preLoadedDexes.add(memory);
} catch (IOException | ErrnoException e) { } catch (IOException | ErrnoException e) {

View File

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