维护网站英语,怎么做下载类网站,泉州百度开户,成都房价版权归作者所有#xff0c;如有转发#xff0c;请注明文章出处#xff1a;https://cyrus-studio.github.io/blog/ OLLVM、LLVM 与 Android NDK
在 Android NDK 中#xff0c;LLVM/Clang 是默认的编译器。自 Android NDK r18 开始#xff0c;Google 弃用了 GCC#xff0c… 版权归作者所有如有转发请注明文章出处https://cyrus-studio.github.io/blog/ OLLVM、LLVM 与 Android NDK
在 Android NDK 中LLVM/Clang 是默认的编译器。自 Android NDK r18 开始Google 弃用了 GCC全面转向使用 LLVM/Clang 作为 NDK 的编译工具链。
NDK 中 LLVM 所在路径/toolchains/llvm/prebuilt//bin/ 查看 clang 版本这里版本是 18.0.2
(base) PS D:\App\android\sdk\ndk\27.1.12297006\toolchains\llvm\prebuilt\windows-x86_64\bin ./clang --versionAndroid (12285214, based on r522817b) clang version 18.0.2 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)
Target: x86_64-w64-windows-gnu
Thread model: posix
InstalledDir: D:/App/android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/windows-x86_64/bin下载和编译与 NDK 中版本相近的 LLVM具体可以参考这篇文章【编译 LLVM 源码使用 Clion 调试 clang】
OLLVM 是 LLVM 的一个分支增加了代码混淆功能如控制流平坦化、指令替换主要用于保护二进制代码的安全性。
关于如何移植 OLLVM 到 LLVM 可以参考下面的文章 移植 OLLVM 到 LLVM 18CC代码混淆 移植 OLLVM 到 LLVM18修复控制流平坦化报错
编译 LLVM
1. 构建环境设置
创建并进入构建目录
mkdir build cd build配置编译目标
cmake -G Ninja -DCMAKE_BUILD_TYPERelease -DCMAKE_CXX_FLAGS/utf-8 -DLLVM_ENABLE_RTTION -DLLVM_ENABLE_EHON -DLLVM_ENABLE_PROJECTSclang;lld ../llvm2. 编译
编译目标设置完成后执行 ninja 开始编译。
D:\Projects\llvm-project\buildninja
[1651/2426] Building CXX object tools\lld\ELF\CMakeFiles\lldELF.dir\Arch\LoongArch.cpp.obj
D:\Projects\llvm-project\lld\ELF\Arch\LoongArch.cpp(705): warning C4334: “”: 32 位移位的结果被隐式转换为 64 位(是否希望进行 64 位移位?)
[2426/2426] Linking CXX executaset PATH%PATH%;D:\Projects\llvm-project\build\bin移植 OLLVM 到 Android NDK 这是 Android NDK 中 toolchains\llvm\prebuilt\windows-x86_64 目录下的文件夹结构
其中主要几个文件夹 bin包含可执行文件例如编译器clang、clang、链接器ld等主要用于 NDK 工具链的操作。 include包含头文件提供编译时所需的接口定义。例如标准 C/C 库的头文件以及与 Android 平台相关的头文件。 lib包含静态库和动态库提供编译和链接时使用的库文件。例如支持标准 C/C 函数的实现库。
这些文件共同组成了 Android NDK 的工具链用于开发和调试 Android native 代码。
当我们成功把 OLLVM 移植到 LLVM并编译完成后可以在构建目录下看到同样也有相关目录 复制并替换 bin、include、lib 目录到 ndk 中 Android Studio 中使用 OLLVM
1. 创建 native 工程 2. 配置 OLLVM NDK
编辑 local.properties 添加 ndk.dir 配置为 ollvm ndk 路径
ndk.dirD\:\\App\\android\\sdk\\ndk\\27.1.122970063. 代码实现
创建 OLLVMActivity定义并调用 native 方法
/*** 移植 OLLVM 到 Android NDK*/
class OLLVMActivity : AppCompatActivity() {// 声明 native 方法external fun sub(a: Int, b: Int): Intexternal fun bcf(input: String?): String?external fun fla(x: Int, y: Int): String?override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_ollvmactivity)// 加载本地库System.loadLibrary(ollvm-lib);// 调用 native 方法并显示结果val textView findViewByIdTextView(R.id.textView)val subResult sub(10, 5)val bcfResult bcf(Hello OLLVM!)val flaResult fla(3, 2)val resultText sub(10, 5) $subResultbcf(Hello OLLVM!) $bcfResultfla(x, y) $flaResult.trimIndent()textView.text resultText}}创建 ollvm-lib.cpp 实现 native 方法
#include jni.h
#include string// sub 方法两个整数相减
extern C JNIEXPORT jint JNICALL
Java_com_cyrus_example_ollvm_OLLVMActivity_sub(JNIEnv* env, jobject, jint a, jint b) {return a - b;
}// bcf 方法接收字符串并返回拼接后的字符串
extern C JNIEXPORT jstring JNICALL
Java_com_cyrus_example_ollvm_OLLVMActivity_bcf(JNIEnv* env, jobject, jstring input) {const char* inputStr env-GetStringUTFChars(input, nullptr);std::string result std::string(BCF: ) inputStr;env-ReleaseStringUTFChars(input, inputStr);return env-NewStringUTF(result.c_str());
}// fla 方法两个int相加判断大小并返回结果字符串
extern C JNIEXPORT jstring JNICALL
Java_com_cyrus_example_ollvm_OLLVMActivity_fla(JNIEnv *env, jobject , jint x, jint y) {int sum x y;// 使用字符串流拼接结果std::ostringstream result;if (sum 5) {result x x , y y , x y 小于 5;} else if(sum 5){result x x , y y , x y 等于 5;} else{result x x , y y , x y 大于 5;}// 返回拼接好的字符串return env-NewStringUTF(result.str().c_str());
}编辑 CMakeLists.txt添加动态库 ollvm-lib
add_library( # 设置库的名称ollvm-lib# 设置库的类型SHARED# 设置源文件路径ollvm-lib.cpp)4. 全局混淆
编辑 CMakeLists.txt添加如下配置启用 OLLVM 混淆
# 全局启用指令替换
add_definitions(-mllvm -sub)通过 -mllvm 选项开启 OLLVM 的代码混淆功能 -mllvm -bcf启用基本块控制流混淆。 -mllvm -fla启用控制流平坦化。 -mllvm -sub启用指令替换。
5. 动态库混淆
编辑 CMakeLists.txt只为 ollvm-lib 动态库启用虚假控制流
# 为 ollvm-lib 动态库启用虚假控制流
target_compile_options(ollvm-libPRIVATE-mllvm -bcf)如果有多个编译项
target_compile_options(ollvm-libPRIVATE-mllvm -bcf # 启用 Bogus Control Flow 混淆-mllvm -sub # 启用 Substitution 混淆-mllvm -fla # 启用 Flattening 混淆
)6. 函数混淆
通过注解为 fla 方法禁用虚假控制流和启用控制流平坦化
extern C JNIEXPORT jstring JNICALL
__attribute__((annotate(nobcf,fla))) Java_com_cyrus_example_ollvm_OLLVMActivity_fla(JNIEnv *env, jobject, jint x, jint y) {int sum x y;// 使用字符串流拼接结果std::ostringstream result;if (sum 5) {result x x , y y , x y 小于 5;} else if(sum 5){result x x , y y , x y 等于 5;} else{result x x , y y , x y 大于 5;}// 返回拼接好的字符串return env-NewStringUTF(result.str().c_str());
}7. 测试
编译运行正常 把 apk 中的 so 文件解压出来 使用 IDA 打开 libollvm-lib.so可以看到 sub 函数反汇编视图如下启用虚假控制流指令替换 bcf 函数反汇编视图启用虚假控制流指令替换 fla 函数反汇编视图禁用虚假控制流并启用控制流平坦化 其他动态库中函数未启用 OLLVM 混淆 源码 OLLVM 源码https://github.com/CYRUS-STUDIO/LLVM Android OLLVM Demo 源码https://github.com/CYRUS-STUDIO/AndroidExample