Android NDK 编译 so 文件 抹除导出符号 反逆向

版权归作者所有,如有转发,请注明文章出处:cyrus-studio.github.io/blog/

前言

NDK 编译 so 默认情况下,所有 public 函数 都会导出,通过 IDA、GHIDRA 可以看到函数名

但除了必须导出的 JNI 函数外,其余 C/C++ 函数符号不导出其实也完全没影响,编译器/链接器内部可以调用,运行时照样可以正常执行。

必须导出的 JNI 函数

函数名 是否必须导出 说明
JNI_OnLoad ✅ 是(总是) 系统通过 dlsym() 查找,初始化用
Java_... ✅ 是(如果用静态注册) Java 层方法通过名称匹配
JNI_OnUnload ❌ 否(可选) 卸载时调用,不导出也不会出错
JNI_OnLoad_LibName(非标准) ❌ 否(特殊系统扩展) Android 未使用
JNI_GetCreatedJavaVMs、JNI_CreateJavaVM ❌ 否 仅在 native 启动 JVM 时使用(一般用不到)

使用 linker version script 精细控制导出

Linker Version Script 是 GNU 链接器(ld)提供的一种机制,用来控制 .so 或 .a 文件中哪些符号可以导出、哪些必须隐藏。

创建 hide.map 文件(仅导出所有 JNI_ 和 Java_ 开头的 JNI 方法)

ini 复制代码
{
    global:
        JNI_*;
        Java_*;

    local:
        *;
};

解释

  • global: 表示这些符号会被导出,可供外部(如 ART)通过 dlsym() 使用。

  • Java_* 会匹配所有以 Java_ 开头的方法 ------ 即静态注册 JNI 方法。

  • local: *; 表示其余全部符号(如内部 C 函数、C++ mangled 符号、加密算法、字符串处理等)一律隐藏,无法通过 IDA 等工具直接查看函数名。

在你的 CMakeLists.txt 中这样写:

bash 复制代码
# 抹除符号
set_target_properties(native-lib PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/hide.map")

参考:android-docs.cn/ndk/guides/...

测试

重新编译运行,使用 IDA Pro 打开 so ,可以看到只导出了 JNI 相关函数

只控制导出符号,不影响内部调用,程序运行时不会出错。

除了增加逆向难度,同时还能减少 so 文件的体积

动态注册 JNI 方法,JNI 方法反跟踪

Android 的 ART 虚拟机会用 dlsym() 查找你导出的 JNI 方法(如Java_com_example_native_NativeUtils_secretMethod),所以这些你不能隐藏,否则会导致运行时崩溃。

如果你用 RegisterNatives 动态注册 JNI 方法,就可以完全避免导出 Java_com_xxx 的方法名:

c 复制代码
#include <jni.h>

// 定义方法签名
static JNINativeMethod methods[] = {
    {"secretMethod", "()V", (void *)secretMethod},
};

// JNI_OnLoad 动态注册方法
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv* env = nullptr;
    vm->GetEnv((void**)&env, JNI_VERSION_1_6);

    jclass clazz = env->FindClass("com/example/native/NativeUtils");
    env->RegisterNatives(clazz, methods, sizeof(methods)/sizeof(methods[0]));

    return JNI_VERSION_1_6;
}

函数名字可以自定义:

javascript 复制代码
void secretMethod(JNIEnv *env, jobject obj) {
    // your native code
}

此时 .so 中不需要导出 Java_com_example_xxx 符号,IDA 也就看不到!

完整源码

开源地址:github.com/CYRUS-STUDI...

相关文章:

相关推荐
lxysbly33 分钟前
n64模拟器安卓版带金手指2026
android
m0_4665252935 分钟前
绿盟科技风云卫AI安全能力平台成果重磅发布
大数据·数据库·人工智能·安全
晚霞的不甘1 小时前
守护智能边界:CANN 的 AI 安全机制深度解析
人工智能·安全·语言模型·自然语言处理·前端框架
枷锁—sha1 小时前
【SRC】SQL注入快速判定与应对策略(一)
网络·数据库·sql·安全·网络安全·系统安全
数字护盾(和中)1 小时前
信创生态 + 国密算法 筑牢数字安全韧性根基
安全
devmoon2 小时前
在 Polkadot 上部署独立区块链Paseo 测试网实战部署指南
开发语言·安全·区块链·polkadot·erc-20·测试网·独立链
成茂峰2 小时前
软考高级·系统架构设计师 | 四、信息技术安全知识
安全·信息安全·系统架构·架构设计师
向哆哆3 小时前
CANN生态安全保障:cann-security-module技术解读
人工智能·安全·cann
wuli_滔滔3 小时前
CANN安全机制源码探秘 仓库中的权限校验与数据加密实现
安全·cann
游戏开发爱好者84 小时前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview