@@ -18,33 +18,48 @@
# include <sys/stat.h>
//#include <asm-generic/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 ;
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 ] ;
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 ) ;
// 构建源文件路径
char src_path [ 256 ] ;
snprintf ( src_path , sizeof ( src_path ) , " /data/local/tmp/%s.so " , soname ) ;
// 打开源文件
// 复制 /sdcard/test.so 到 game_data_dir 并重命名
const char * src_path = " /data/local/tmp/test.so " ;
int src_fd = open ( src_path , O_RDONLY ) ;
if ( src_fd < 0 ) {
LOGE ( " Failed to open %s: %s (errno: %d) " , src_path , strerror ( errno ) , errno ) ;
return ;
}
// 打开目标文件
int dest_fd = open ( new_so_path , O_WRONLY | O_CREAT | O_TRUNC , 0644 ) ;
if ( dest_fd < 0 ) {
LOGE ( " Failed to open %s " , new_so_path ) ;
close ( src_fd ) ;
return ;
}
// 复制文件内容
char buffer [ 4096 ] ;
ssize_t bytes ;
@@ -57,51 +72,104 @@ void load_so(const char *game_data_dir, JavaVM *vm, const char *soname) {
}
}
// 关闭文件描述符
close ( src_fd ) ;
close ( dest_fd ) ;
// 修改文件权限
if ( chmod ( new_so_path , 0755 ) ! = 0 ) {
LOGE ( " Failed to change permissions on %s: %s (errno: %d) " , new_so_path , strerror ( errno ) , errno ) ;
return ;
} else {
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 文件
void * handl e;
JNIEnv * env = nullptr ;
bool needDetach = fals e;
jint getEnvStat = vm - > GetEnv ( ( void * * ) & env , JNI_VERSION_1_6 ) ;
if ( getEnvStat = = JNI_EDETACHED ) {
LOGI ( " Thread not attached, attaching... " ) ;
if ( vm - > AttachCurrentThread ( & env , NULL ) ! = 0 ) {
LOGE ( " Failed to attach current thread " ) ;
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 {
jmethodID loadMethod = env - > GetStaticMethodID ( systemClass , " load " , " (Ljava/lang/String;)V " ) ;
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 ) {
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 " , new_so_path ) ;
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 ( " %s.so not found in thread %d" , soname , gettid ( ) ) ;
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 ) {
@@ -262,7 +330,7 @@ void hack_prepare(const char *_data_dir, void *data, size_t length) {
# if defined(__i386__) || defined(__x86_64__)
if ( ! NativeBridgeLoad ( _data_dir , api_level , data , length ) ) {
# endif
hack_start ( _data_dir , nullptr );
hack_start ( _data_dir ) ;
# if defined(__i386__) || defined(__x86_64__)
}
# 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 ) {
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 ( ) ;
return JNI_VERSION_1_6 ;
}