移植 OLLVM 到 Android NDK,Android Studio 中使用 OLLVM
版权归作者所有,如有转发,请注明文章出处: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 18,C&C++代码混淆
-
移植 OLLVM 到 LLVM18,修复控制流平坦化报错
编译 LLVM
1. 构建环境设置
创建并进入构建目录
mkdir build && cd build
配置编译目标
cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="/utf-8" -DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_EH=ON -DLLVM_ENABLE_PROJECTS="clang;lld" ../llvm
2. 编译
编译目标设置完成后,执行 ninja 开始编译。
D:\Projects\llvm-project\build>ninja
[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.dir=D\:\\App\\android\\sdk\\ndk\\27.1.12297006
3. 代码实现
创建 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 = findViewById<TextView>(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
相关文章:

移植 OLLVM 到 Android NDK,Android Studio 中使用 OLLVM
版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/ OLLVM、LLVM 与 Android NDK 在 Android NDK 中,LLVM/Clang 是默认的编译器。自 Android NDK r18 开始,Google 弃用了 GCC,…...

DAY36|动态规划Part04|LeetCode:1049. 最后一块石头的重量 II、494. 目标和、474.一和零
目录 LeetCode:1049. 最后一块石头的重量 II 基本思路 C代码 LeetCode:494. 目标和 基本思路 C代码 LeetCode:474.一和零 基本思路 C代码 LeetCode:1049. 最后一块石头的重量 II 力扣代码链接 文字讲解:LeetCode:1049. 最后一块石头的重量 II 视频讲解&…...

Linux 下SVN新手操作手册
下面来介绍Linux 下 SVN操作方法: 1、SVN的安装 Centos 7 安装Subversion sudo yum -y install subversion Ubuntu 安装Subversion sudo apt-get install subversion 自定义安装,官方地址:https://subversion.apache.org/ 2、SVN的使用…...

障碍感知 | 基于KD树的障碍物快速处理(附案例分析与ROS C++仿真)
目录 1 障碍处理与KD树2 KD树核心原理2.1 KD树的构造2.2 KD树的查找 3 仿真实现3.1 KD树基本算法3.2 ROS C仿真 1 障碍处理与KD树 在机器人感知系统中,传感器(如激光雷达、摄像头等)会采集周围的环境数据,例如代价地图、八叉树地…...
Electron -- Electron Fiddle(一)
Electron Fiddle 是一个由 Electron 团队开发的开源工具,它允许开发者快速创建、运行和调试 Electron 应用。这个工具提供了一个简洁的界面,使用户无需配置复杂的开发环境,就能快速体验和学习 Electron。强烈建议将其安装为学习工具。 学习它…...

详解Redis的常用命令
目录 KEYS 语法 EXISTS 语法 DEL 语法 EXPIRE 语法 TTL 语法 TYPE 语法 Redis数据结构和内部编码 KEYS 返回所有满⾜样式(pattern)的 key。 返回值:匹配 pattern 的所有 key。 语法 ⽀持如下统配样式: h?llo matches hello, ha…...
elasticache备份
Elasticsearch 本地快照操作流程 配置快照存储路径 在 elasticsearch.yml 文件中配置以下字段以指定数据、日志和快照存储路径:path:data: /data/data # 数据存储路径logs: /data/log # 日志存储路径repo: /data/snapshot # 快照存储路径确保路径 /dat…...
Tomcat负载均衡全解析
一、Java项目概述 (一)Java语言特点 Java是一种计算机应用语言,在开发王者和管理系统等方面有着广泛的应用。它具有开源免费的特性,不过需要注意的是,虽然语言本身开源,但是后期开发工具可能会收取费用。 (二)、JDK和Tomcat 1,JDK:作为Java语言的开发工具,在Linu…...
[LeetCode-Python版] 定长滑动窗口8——2461. 长度为 K 子数组中的最大和
题目 给你一个整数数组 nums 和一个整数 k 。请你从 nums 中满足下述条件的全部子数组中找出最大子数组和: 子数组的长度是 k,且 子数组中的所有元素 各不相同 。 返回满足题面要求的最大子数组和。如果不存在子数组满足这些条件,返回 0 。…...

springboot476基于vue篮球联盟管理系统(论文+源码)_kaic
摘 要 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统篮球联盟管理系统信息管理难度大,容错率低&am…...

预约参观华为基地,见证行业巅峰
✨ 大家好呀!今天要跟大家分享一个超酷的体验,关于华为的参观学习之旅!🚀 华为成立于1987年,位于深圳,是全球领先的信息与通信技术(ICT)解决方案供应商哦!他们专注于科技…...

【Flink-scala】DataSet编程模型介绍及数据源
DataStream 学习 1.DataStream编程模型总结 文章目录 DataStream 学习介绍一、DataSet编程模型二、数据源1.文件类数据源2.集合类数据源3.通用类数据源4第三方文件系统 介绍 Flink把批处理看成是一个流处理的特例,因此可以在底层统一的流处理引擎上,同…...

Odrive源码分析(四) 位置爬坡算法
Odrive中自带一个简单的梯形速度爬坡算法,本文分析下这部分代码。 代码如下: #include <cmath> #include "odrive_main.h" #include "utils.hpp"// A sign function where input 0 has positive sign (not 0) float sign_ha…...
[Unity Shader][图形渲染] Shader数学基础11 - 复合变换详解
在图形学与Shader编程中,复合变换是将平移、旋转和缩放等基本几何变换组合在一起,从而实现更复杂的物体变换效果。复合变换的本质是通过矩阵的串联操作,依次应用多个变换。 本文将介绍复合变换的数学原理、矩阵计算方法及注意事项,并结合实际编程中的实现细节帮助你掌握其…...
使用Python实现智能家居控制系统:开启智慧生活的钥匙
友友们好! 我的新专栏《Python进阶》正式启动啦!这是一个专为那些渴望提升Python技能的朋友们量身打造的专栏,无论你是已经有一定基础的开发者,还是希望深入挖掘Python潜力的爱好者,这里都将是你不可错过的宝藏。 在这个专栏中,你将会找到: ● 深入解析:每一篇文章都将…...

使用 HTML5 Canvas 实现动态蜈蚣动画
使用 HTML5 Canvas 实现动态蜈蚣动画 1. 项目概述 我们将通过 HTML 和 JavaScript 创建一个动态蜈蚣。蜈蚣由多个节段组成,每个节段看起来像一个小圆形,并且每个节段上都附带有“脚”。蜈蚣的头部会在画布上随机移动。 完整代码在底部!&…...

计算机视觉目标检测——DETR(End-to-End Object Detection with Transformers)
计算机视觉目标检测——DETR(End-to-End Object Detection with Transformers) 文章目录 计算机视觉目标检测——DETR(End-to-End Object Detection with Transformers)摘要Abstract一、DETR算法1. 摘要(Abstract)2. 引言(Introduction&#…...

uniapp .gitignore
打开HBuilderX,在项目根目录下新建文件 .gitignore复制下面内容 #忽略unpackge目录下除了res目录的所有目录 unpackage/* !unpackage/res/#忽略.hbuilderx目录 .hbuilderx# 忽略node_modules目录下的所有文件 node_modules/# 忽略锁文件 package-lock.json yarn.l…...

JavaWeb Servlet的反射优化、Dispatcher优化、视图(重定向)优化、方法参数值获取优化
目录 1. 背景2. 实现2.1 pom.xml2.2 FruitController.java2.3 DispatcherServlet.java2.4 applicationContext.xml 3. 测试 1. 背景 前面我们做了Servlet的一个案例。但是存在很多问题,现在我们要做优化,优化的步骤如下: 每个Fruit请求都需…...
备忘一个FDBatchMove数据转存的问题
使用FDBatchMove的SQL导入excel表到sql表,设置条件时一头雾水,函数不遵守sql的规则。 比如替换字段的TAB键值为空,replace(字段名,char(9),)竟然提示错误,百思不得其解。 试遍了几乎所有的函数,竟然是chr(9)。 这个…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...