Skip to content

Commit

Permalink
添加abi版本判断
Browse files Browse the repository at this point in the history
  • Loading branch information
Perfare committed May 22, 2023
1 parent 9c0ecac commit d2c4c9c
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 57 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.2'
classpath 'com.android.tools.build:gradle:7.4.2'
}
}

Expand Down
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Fri Feb 03 09:19:49 CST 2023
#Mon May 22 11:22:38 CST 2023
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
2 changes: 1 addition & 1 deletion module.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ ext {
moduleName = "Il2CppDumper"
moduleAuthor = "Perfare"
moduleDescription = "Il2CppDumper Zygisk version."
moduleVersion = "v1.1.0"
moduleVersion = "v1.2.0"
moduleVersionCode = 1
}
2 changes: 1 addition & 1 deletion module/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ apply from: file(rootProject.file('module.gradle'))

android {
compileSdkVersion rootProject.ext.targetSdkVersion
ndkVersion '25.1.8937393'
ndkVersion '25.2.9519653'
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
Expand Down
10 changes: 8 additions & 2 deletions module/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,17 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_FLAGS} ${CXX_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")

include_directories(xdl/include)
include_directories(
xdl/include
)

aux_source_directory(xdl xdl-src)

add_library(${MODULE_NAME} SHARED main.cpp hack.cpp il2cpp_dump.cpp ${xdl-src})
add_library(${MODULE_NAME} SHARED
main.cpp
hack.cpp
il2cpp_dump.cpp
${xdl-src})
target_link_libraries(${MODULE_NAME} log)

if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
Expand Down
138 changes: 110 additions & 28 deletions module/src/main/cpp/hack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@
#include <linux/unistd.h>
#include <array>

static std::string GetNativeBridgeLibrary() {
auto value = std::array<char, PROP_VALUE_MAX>();
__system_property_get("ro.dalvik.vm.native.bridge", value.data());
return {value.data()};
}

void hack_start(const char *game_data_dir) {
bool load = false;
for (int i = 0; i < 10; i++) {
Expand All @@ -41,6 +35,60 @@ void hack_start(const char *game_data_dir) {
}
}

std::string GetLibDir(JavaVM *vms) {
JNIEnv *env = nullptr;
vms->AttachCurrentThread(&env, nullptr);
jclass activity_thread_clz = env->FindClass("android/app/ActivityThread");
if (activity_thread_clz != nullptr) {
jmethodID currentApplicationId = env->GetStaticMethodID(activity_thread_clz,
"currentApplication",
"()Landroid/app/Application;");
if (currentApplicationId) {
jobject application = env->CallStaticObjectMethod(activity_thread_clz,
currentApplicationId);
jclass application_clazz = env->GetObjectClass(application);
if (application_clazz) {
jmethodID get_application_info = env->GetMethodID(application_clazz,
"getApplicationInfo",
"()Landroid/content/pm/ApplicationInfo;");
if (get_application_info) {
jobject application_info = env->CallObjectMethod(application,
get_application_info);
jfieldID native_library_dir_id = env->GetFieldID(
env->GetObjectClass(application_info), "nativeLibraryDir",
"Ljava/lang/String;");
if (native_library_dir_id) {
auto native_library_dir_jstring = (jstring) env->GetObjectField(
application_info, native_library_dir_id);
auto path = env->GetStringUTFChars(native_library_dir_jstring, nullptr);
LOGI("lib dir %s", path);
std::string lib_dir(path);
env->ReleaseStringUTFChars(native_library_dir_jstring, path);
return lib_dir;
} else {
LOGE("nativeLibraryDir not found");
}
} else {
LOGE("getApplicationInfo not found");
}
} else {
LOGE("application class not found");
}
} else {
LOGE("currentApplication not found");
}
} else {
LOGE("ActivityThread not found");
}
return {};
}

static std::string GetNativeBridgeLibrary() {
auto value = std::array<char, PROP_VALUE_MAX>();
__system_property_get("ro.dalvik.vm.native.bridge", value.data());
return {value.data()};
}

struct NativeBridgeCallbacks {
uint32_t version;
void *initialize;
Expand All @@ -63,15 +111,46 @@ struct NativeBridgeCallbacks {
void *(*loadLibraryExt)(const char *libpath, int flag, void *ns);
};

void hack_prepare(const char *game_data_dir, void *data, size_t length) {
LOGI("hack thread: %d", gettid());
int api_level = android_get_device_api_level();
LOGI("api level: %d", api_level);

#if defined(__i386__) || defined(__x86_64__)
bool NativeBridgeLoad(const char *game_data_dir, int api_level, ArmLoader *loader) {
//TODO 等待houdini初始化
sleep(5);

auto libart = dlopen("libart.so", RTLD_NOW);
auto JNI_GetCreatedJavaVMs = (jint (*)(JavaVM **, jsize, jsize *)) dlsym(libart,
"JNI_GetCreatedJavaVMs");
LOGI("JNI_GetCreatedJavaVMs %p", JNI_GetCreatedJavaVMs);
JavaVM *vms_buf[1];
JavaVM *vms;
jsize num_vms;
jint status = JNI_GetCreatedJavaVMs(vms_buf, 1, &num_vms);
if (status == JNI_OK && num_vms > 0) {
vms = vms_buf[0];
} else {
LOGE("GetCreatedJavaVMs error");
return false;
}

void *data;
size_t length;
auto lib_dir = GetLibDir(vms);
if (lib_dir.empty()) {
LOGE("GetLibDir error");
return false;
}
if (lib_dir.find("arm64") != std::string::npos) {
LOGI("load arm64");
data = loader->arm64;
length = loader->arm64_length;
} else if (lib_dir.find("arm") != std::string::npos) {
LOGI("load arm");
data = loader->arm;
length = loader->arm_length;
} else {
//TODO 可能有x86_64载入x86游戏的情况?
LOGI("no need NativeBridge");
return false;
}

auto nb = dlopen("libhoudini.so", RTLD_NOW);
if (!nb) {
auto native_bridge = GetNativeBridgeLibrary();
Expand All @@ -85,17 +164,12 @@ void hack_prepare(const char *game_data_dir, void *data, size_t length) {
LOGI("NativeBridgeLoadLibrary %p", callbacks->loadLibrary);
LOGI("NativeBridgeLoadLibraryExt %p", callbacks->loadLibraryExt);
LOGI("NativeBridgeGetTrampoline %p", callbacks->getTrampoline);
auto libart = dlopen("libart.so", RTLD_NOW);
auto JNI_GetCreatedJavaVMs = (jint (*)(JavaVM **, jsize, jsize *)) dlsym(libart,
"JNI_GetCreatedJavaVMs");
LOGI("JNI_GetCreatedJavaVMs %p", JNI_GetCreatedJavaVMs);

int fd = syscall(__NR_memfd_create, "anon", MFD_CLOEXEC);
ftruncate(fd, (off_t) length);
void *mem = mmap(nullptr, length, PROT_WRITE, MAP_SHARED, fd, 0);
memcpy(mem, data, length);
munmap(mem, length);
munmap(data, length);
char path[PATH_MAX];
snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd);
LOGI("arm path %s", path);
Expand All @@ -108,24 +182,32 @@ void hack_prepare(const char *game_data_dir, void *data, size_t length) {
}
if (arm_handle) {
LOGI("arm handle %p", arm_handle);
JavaVM *vms_buf[1];
jsize num_vms;
jint status = JNI_GetCreatedJavaVMs(vms_buf, 1, &num_vms);
if (status == JNI_OK && num_vms > 0) {
auto init = (void (*)(JavaVM *, void *)) callbacks->getTrampoline(arm_handle,
"JNI_OnLoad",
nullptr, 0);
LOGI("JNI_OnLoad %p", init);
init(vms_buf[0], (void *) game_data_dir);
}
auto init = (void (*)(JavaVM *, void *)) callbacks->getTrampoline(arm_handle,
"JNI_OnLoad",
nullptr, 0);
LOGI("JNI_OnLoad %p", init);
init(vms, (void *) game_data_dir);
return true;
}
close(fd);
}
} else {
}
return false;
}

void hack_prepare(const char *game_data_dir, ArmLoader *loader) {
LOGI("hack thread: %d", gettid());
int api_level = android_get_device_api_level();
LOGI("api level: %d", api_level);

#if defined(__i386__) || defined(__x86_64__)
if (!NativeBridgeLoad(game_data_dir, api_level, loader)) {
#endif
hack_start(game_data_dir);
#if defined(__i386__) || defined(__x86_64__)
}
munmap(loader->arm, loader->arm_length);
munmap(loader->arm64, loader->arm64_length);
#endif
}

Expand Down
9 changes: 8 additions & 1 deletion module/src/main/cpp/hack.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@

#include <stddef.h>

void hack_prepare(const char *game_data_dir, void *data, size_t length);
struct ArmLoader {
void *arm;
size_t arm_length;
void *arm64;
size_t arm64_length;
};

void hack_prepare(const char *game_data_dir, ArmLoader *loader);

#endif //ZYGISK_IL2CPPDUMPER_HACK_H
40 changes: 19 additions & 21 deletions module/src/main/cpp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class MyModule : public zygisk::ModuleBase {

void postAppSpecialize(const AppSpecializeArgs *) override {
if (enable_hack) {
std::thread hack_thread(hack_prepare, game_data_dir, data, length);
std::thread hack_thread(hack_prepare, game_data_dir, loader);
hack_thread.detach();
}
}
Expand All @@ -42,34 +42,32 @@ class MyModule : public zygisk::ModuleBase {
JNIEnv *env;
bool enable_hack;
char *game_data_dir;
void *data;
size_t length;
ArmLoader *loader;

void loadSo(const char *path, void *&data, size_t &length) {
int dirfd = api->getModuleDir();
int fd = openat(dirfd, path, O_RDONLY);
if (fd != -1) {
struct stat sb{};
fstat(fd, &sb);
length = sb.st_size;
data = mmap(nullptr, length, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
} else {
LOGW("Unable to open %s", path);
}
}

void preSpecialize(const char *package_name, const char *app_data_dir) {
if (strcmp(package_name, GamePackageName) == 0) {
LOGI("detect game: %s", package_name);
enable_hack = true;
game_data_dir = new char[strlen(app_data_dir) + 1];
strcpy(game_data_dir, app_data_dir);

#if defined(__i386__)
auto path = "zygisk/armeabi-v7a.so";
#endif
#if defined(__x86_64__)
auto path = "zygisk/arm64-v8a.so";
#endif
#if defined(__i386__) || defined(__x86_64__)
int dirfd = api->getModuleDir();
int fd = openat(dirfd, path, O_RDONLY);
if (fd != -1) {
struct stat sb{};
fstat(fd, &sb);
length = sb.st_size;
data = mmap(nullptr, length, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
} else {
LOGW("Unable to open arm file");
}
loader = new ArmLoader();
loadSo("zygisk/armeabi-v7a.so", loader->arm, loader->arm_length);
loadSo("zygisk/arm64-v8a.so", loader->arm64, loader->arm64_length);
#endif
} else {
api->setOption(zygisk::Option::DLCLOSE_MODULE_LIBRARY);
Expand Down

0 comments on commit d2c4c9c

Please sign in to comment.