环境配置: app/src/main/cpp/CMakeLists.txt camke版本:
# 指定项目所需的最低 CMake 版本为 3.30.5。
cmake_minimum_required(VERSION 3.30.5)
# 定义项目名称为 app。
project(app)
# 启用 C 语言和汇编语言。
enable_language(ASM)
# 检查 DEPENDENCY_ON_LOCAL_LIBRARY 变量的值。如果为真,则包含本地依赖配置。
if(DEPENDENCY_ON_LOCAL_LIBRARY)
# 包含本地依赖配置文件。
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../../shadowhook/local_dependency.cmake)
else()
# 如果 DEPENDENCY_ON_LOCAL_LIBRARY 为假,则查找 shadowhook 包。查找 shadowhook 包,并将其标记为必需
find_package(shadowhook REQUIRED CONFIG)
endif()
# 检查当前 Android ABI 是否为 arm64-v8a(64 位 ARM 架构)。
if(${ANDROID_ABI} STREQUAL "arm64-v8a")
# 如果 ABI 是 arm64-v8a,则设置 ARCH 变量为 "arm64"
set(ARCH "arm64")
# 设置链接器标志 ARCH_LINK_FLAGS 为 "-Wl,-z,max-page-size=16384",用于指定最大页大小为 16KB。
set(ARCH_LINK_FLAGS "-Wl,-z,max-page-size=16384")
elseif(${ANDROID_ABI} STREQUAL "armeabi-v7a")
# 如果 ABI 是 armeabi-v7a,则设置 ARCH 变量为 "arm"。
set(ARCH "arm")
# 设置链接器标志 ARCH_LINK_FLAGS 为空字符串,因为 32 位 ARM 架构不需要特殊的链接器标志。
set(ARCH_LINK_FLAGS "")
endif()
# libthread_hook.so
# 定义目标库的名称为 "thread_hook"。
set(TARGET "thread_hook")
# 查找当前目录下的所有 C 源文件,并将它们存储在变量 "SRC" 中。
file(GLOB SRC hookprint/*.c)
# 添加一个共享库目标,名为 "thread_hook",包含 "SRC" 中的源文件。
add_library(${TARGET} SHARED ${SRC})
# 查找 Android 的 log 库,并将其存储在 log-lib 变量中。
find_library(log-lib log)
# 为目标库 "thread_hook" 设置编译特性,包括 C 标准 17。
target_compile_features(${TARGET} PUBLIC c_std_17)
# 设置编译选项,包括使用 C17 标准、启用所有警告并将警告视为错误
target_compile_options(${TARGET} PUBLIC -std=c17 -Weverything -Werror)
myhook.c文件:
//
// Created by User on 2025/2/25.
//
#include <android/log.h>
#include <dlfcn.h>
#include <jni.h>
#define HACKER_JNI_VERSION JNI_VERSION_1_6
#define HACKER_JNI_CLASS_NAME "com/example/signal/NativeTest"
static int unittest_jni_hook_sym_addr(JNIEnv *env, jobject thiz, jint api_level) {
// 显式忽略未使用的参数,避免编译器警告
(void)env;
(void)thiz;
return 2 * api_level;
}
/**
* 这是JNI(Java Native Interface)的标准入口函数,在Java层加载native库时自动调用
* 这个函数是Java层和native层之间的桥梁,确保Java层可以正确调用native层的函数实现。
* 1.初始化JNI环境,获取 JNIEnv 指针
* 2.查找Java类 com/example/signal/NativeTest
* 3.定义并注册native方法,将Java层的native方法与C层的实现函数进行绑定
* 4.返回JNI版本号 JNI_VERSION_1_6
*/
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
// 显式忽略未使用的参数,避免编译器警告
(void)reserved;
// 检查JavaVM指针是否为空
if (NULL == vm) return JNI_ERR;
// 获取JNIEnv指针
JNIEnv *env;
if (JNI_OK != (*vm)->GetEnv(vm, (void **)&env, HACKER_JNI_VERSION)) return JNI_ERR;
if (NULL == env || NULL == *env) return JNI_ERR;
// 查找Java类
jclass cls;
if (NULL == (cls = (*env)->FindClass(env, HACKER_JNI_CLASS_NAME))) return JNI_ERR;
// 定义要注册的native方法
JNINativeMethod m[] = {{"nativeHookSymAddr2", "(I)I", (void *)unittest_jni_hook_sym_addr}};
// 注册native方法
if (0 != (*env)->RegisterNatives(env, cls, m, sizeof(m) / sizeof(m[0]))) return JNI_ERR;
// 返回JNI版本号
return HACKER_JNI_VERSION;
}
NativeTest.java代码
public class NativeTest {
public static native int nativeHookSymAddr2(int apiLevel);
}
简单实现了java侧调用native代码的功能