2 Commits

Author SHA1 Message Date
张晨
855f86591f 解决files目录不存在问题 2024-10-10 14:56:24 +08:00
张晨
08c7af5e1c 增加java注入api,注入失败后尝试dlopen注册,兼容更多机型 2024-10-10 14:47:03 +08:00
4 changed files with 112 additions and 48 deletions

View File

@@ -4,6 +4,6 @@ ext {
moduleName = "myinjector" moduleName = "myinjector"
moduleAuthor = "jiqiu2021" moduleAuthor = "jiqiu2021"
moduleDescription = "注入任意SO到指定APP内" moduleDescription = "注入任意SO到指定APP内"
moduleVersion = "v0.01" moduleVersion = "v0.02"
moduleVersionCode = 1 moduleVersionCode = 1
} }

View File

@@ -5,6 +5,6 @@
#ifndef ZYGISK_IL2CPPDUMPER_GAME_H #ifndef ZYGISK_IL2CPPDUMPER_GAME_H
#define ZYGISK_IL2CPPDUMPER_GAME_H #define ZYGISK_IL2CPPDUMPER_GAME_H
#define AimPackageName "com.tencent.mobileqq" #define AimPackageName "re.pwnme"
#endif //ZYGISK_IL2CPPDUMPER_GAME_H #endif //ZYGISK_IL2CPPDUMPER_GAME_H

View File

@@ -18,33 +18,48 @@
#include <sys/stat.h> #include <sys/stat.h>
//#include <asm-generic/fcntl.h> //#include <asm-generic/fcntl.h>
#include <fcntl.h> #include <fcntl.h>
void load_so(const char *game_data_dir, JavaVM *vm, const char *soname) {
void hack_start(const char *game_data_dir) {
bool load = false; bool load = false;
LOGI("hack_start %s", game_data_dir); LOGI("hack_start %s", game_data_dir);
// 构建 files 目录路径
char files_dir[256];
snprintf(files_dir, sizeof(files_dir), "%s/files", game_data_dir);
// 构建新文件路径,使用传入的 soname 参数 // 检查 files 目录是否存在
struct stat st = {0};
if (stat(files_dir, &st) == -1) {
LOGI("%s directory does not exist, creating...", files_dir);
// 创建目录并赋予 0755 权限
if (mkdir(files_dir, 0755) != 0) {
LOGE("Failed to create directory %s: %s (errno: %d)", files_dir, strerror(errno), errno);
return;
} else {
LOGI("Successfully created directory %s with 0755 permissions", files_dir);
}
} else {
LOGI("Directory %s already exists", files_dir);
}
// 构建新文件路径
char new_so_path[256]; char new_so_path[256];
snprintf(new_so_path, sizeof(new_so_path), "%s/files/%s.so", game_data_dir, soname); snprintf(new_so_path, sizeof(new_so_path), "%s/test.so", files_dir);
// 构建源文件路径 // 复制 /sdcard/test.so 到 game_data_dir 并重命名
char src_path[256]; const char *src_path = "/data/local/tmp/test.so";
snprintf(src_path, sizeof(src_path), "/data/local/tmp/%s.so", soname);
// 打开源文件
int src_fd = open(src_path, O_RDONLY); int src_fd = open(src_path, O_RDONLY);
if (src_fd < 0) { if (src_fd < 0) {
LOGE("Failed to open %s: %s (errno: %d)", src_path, strerror(errno), errno); LOGE("Failed to open %s: %s (errno: %d)", src_path, strerror(errno), errno);
return; return;
} }
// 打开目标文件
int dest_fd = open(new_so_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); int dest_fd = open(new_so_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (dest_fd < 0) { if (dest_fd < 0) {
LOGE("Failed to open %s", new_so_path); LOGE("Failed to open %s", new_so_path);
close(src_fd); close(src_fd);
return; return;
} }
// 复制文件内容 // 复制文件内容
char buffer[4096]; char buffer[4096];
ssize_t bytes; ssize_t bytes;
@@ -57,51 +72,104 @@ void load_so(const char *game_data_dir, JavaVM *vm, const char *soname) {
} }
} }
// 关闭文件描述符
close(src_fd); close(src_fd);
close(dest_fd); close(dest_fd);
// 修改文件权限
if (chmod(new_so_path, 0755) != 0) { if (chmod(new_so_path, 0755) != 0) {
LOGE("Failed to change permissions on %s: %s (errno: %d)", new_so_path, strerror(errno), errno); LOGE("Failed to change permissions on %s: %s (errno: %d)", new_so_path, strerror(errno), errno);
return; return;
} else { } else {
LOGI("Successfully changed permissions to 755 on %s", new_so_path); LOGI("Successfully changed permissions to 755 on %s", new_so_path);
} }
JavaVM* vm;
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];
jsize num_vms;
jint status = JNI_GetCreatedJavaVMs(vms_buf, 1, &num_vms);
if (status == JNI_OK && num_vms > 0) {
vm = vms_buf[0];
} else {
LOGE("GetCreatedJavaVMs error");
return ;
}
// 加载 .so 文件 JNIEnv *env = nullptr;
void *handle; bool needDetach = false;
for (int i = 0; i < 10; i++) { jint getEnvStat = vm->GetEnv((void **)&env, JNI_VERSION_1_6);
handle = dlopen(new_so_path, RTLD_NOW | RTLD_LOCAL); if (getEnvStat == JNI_EDETACHED) {
if (handle) { LOGI("Thread not attached, attaching...");
LOGI("Successfully loaded %s", new_so_path); if (vm->AttachCurrentThread(&env, NULL) != 0) {
load = true; LOGE("Failed to attach current thread");
break; return;
}
needDetach = true;
} else if (getEnvStat == JNI_OK) {
LOGI("Thread already attached");
} else if (getEnvStat == JNI_EVERSION) {
LOGE("JNI version not supported");
return;
} else {
LOGE("Failed to get the environment using GetEnv, error code: %d", getEnvStat);
return;
}
if (env != nullptr) {
jclass systemClass = env->FindClass("java/lang/System");
if (systemClass == NULL) {
LOGE("Failed to find java/lang/System class");
} else { } else {
LOGE("Failed to load %s: %s", new_so_path, dlerror()); jmethodID loadMethod = env->GetStaticMethodID(systemClass, "load", "(Ljava/lang/String;)V");
sleep(1); if (loadMethod == NULL) {
LOGE("Failed to find System.load method");
} else {
jstring jLibPath = env->NewStringUTF(new_so_path);
env->CallStaticVoidMethod(systemClass, loadMethod, jLibPath);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
LOGE("Exception occurred while calling System.load %s",new_so_path);
env->ExceptionClear();
} else {
LOGI("Successfully loaded %s using System.load", new_so_path);
load = true;
}
env->DeleteLocalRef(jLibPath);
}
env->DeleteLocalRef(systemClass);
} }
} }
// 如果加载失败
if (!load) { if (!load) {
LOGI("%s.so not found in thread %d", soname, gettid()); LOGI("Attempting to load %s using dlopen", new_so_path);
void * handle;
for (int i = 0; i < 10; i++) {
handle = dlopen(new_so_path, RTLD_NOW | RTLD_LOCAL);
if (handle) {
LOGI("Successfully loaded %s using dlopen", new_so_path);
load = true;
void (*JNI_OnLoad)(JavaVM *, void *);
*(void **) (&JNI_OnLoad) = dlsym(handle, "JNI_OnLoad");
if (JNI_OnLoad) {
LOGI("JNI_OnLoad symbol found, calling JNI_OnLoad.");
JNI_OnLoad(vm, NULL);
} else {
LOGE("JNI_OnLoad symbol not found in %s", new_so_path);
}
break;
} else {
LOGE("Failed to load %s: %s", new_so_path, dlerror());
sleep(1);
}
}
}
if (!load) {
LOGI("Failed to load test.so in thread %d", gettid());
return;
} }
// 查找 JNI_OnLoad 并调用
// void (*setupSignalHandler)();
// *(void **) (&setupSignalHandler) = dlsym(handle, "setupSignalHandler");
//
// if (setupSignalHandler) {
// LOGI("setupSignalHandler symbol found, calling setupSignalHandler.");
// setupSignalHandler(); // 调用找到的函数
// } else {
// LOGE("setupSignalHandler symbol not found in %s", new_so_path);
// }
}
void hack_start(const char *game_data_dir,JavaVM *vm) {
load_so(game_data_dir,vm,"test");
//如果要注入多个so那么就在这里不断的添加load_so函数即可
} }
std::string GetLibDir(JavaVM *vms) { std::string GetLibDir(JavaVM *vms) {
@@ -262,7 +330,7 @@ void hack_prepare(const char *_data_dir, void *data, size_t length) {
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
if (!NativeBridgeLoad(_data_dir, api_level, data, length)) { if (!NativeBridgeLoad(_data_dir, api_level, data, length)) {
#endif #endif
hack_start(_data_dir, nullptr); hack_start(_data_dir);
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
} }
#endif #endif
@@ -272,7 +340,7 @@ void hack_prepare(const char *_data_dir, void *data, size_t length) {
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
auto game_data_dir = (const char *) reserved; auto game_data_dir = (const char *) reserved;
std::thread hack_thread(hack_start, game_data_dir,vm); std::thread hack_thread(hack_start, game_data_dir);
hack_thread.detach(); hack_thread.detach();
return JNI_VERSION_1_6; return JNI_VERSION_1_6;
} }

View File

@@ -25,11 +25,7 @@ public:
void preAppSpecialize(AppSpecializeArgs *args) override { void preAppSpecialize(AppSpecializeArgs *args) override {
auto package_name = env->GetStringUTFChars(args->nice_name, nullptr); auto package_name = env->GetStringUTFChars(args->nice_name, nullptr);
auto app_data_dir = env->GetStringUTFChars(args->app_data_dir, nullptr); auto app_data_dir = env->GetStringUTFChars(args->app_data_dir, nullptr);
// if (strcmp(package_name, AimPackageName) == 0){ LOGI("preAppSpecialize %s %s", package_name, app_data_dir);
// args->runtime_flags=8451;
// }
LOGI("preAppSpecialize %s %s %d", package_name, app_data_dir,args->runtime_flags);
preSpecialize(package_name, app_data_dir); preSpecialize(package_name, app_data_dir);
env->ReleaseStringUTFChars(args->nice_name, package_name); env->ReleaseStringUTFChars(args->nice_name, package_name);
env->ReleaseStringUTFChars(args->app_data_dir, app_data_dir); env->ReleaseStringUTFChars(args->app_data_dir, app_data_dir);