ios 中集成ollvm12.x
作者:互联网
一. 前言
最近工作中遇到 ios 代码需要做混淆的需求,因此硬着头皮专研怎么将 ollvm 移植到 xcode 中使用。在网上查到的 ios 集成 ollvm的方法大多是说:“将 ollvm4.0 编译结果制作成一个xcode插件”,但这种应该只适用较老的xcode版本,在xcode10以上的版本并不适用。本人需要移植的是 xcode12.4,对应的 clang 版本是12.0.0,因此那种方法并不适用,且经过尝试,确实没有成功(当然也不排除本人操作不当的可能)。
移植环境:
- xcode版本:12.4
- llvm版本:12.0.0
- Mac OS版本:10.15.7 Catalina
二. ollvm移植(mac、linux通用,window上应该也通用)
移植的方法网上比较多,主要是从官网上 ollvm4.0 移植对应的 Obfuscation pass 到高版本 llvm上。如果llvm版本相差太大,可能有的结构体或者方法会有些许改变,编译的时候就会报错,本人的解决方法是将LLVM工程导入到 CLion 中,针对报错的代码,对比高低版本llvm使用的改变(Find in file功能),然后将 Obfuscation pass 中报错代码修正。
1. 导入步骤:
-
用 CLion 打开 Obfuscate/llvm/CMakeLists.txt ,选择 open as project;
-
在 File | Settings | Build, Execution, Deployment | CMake 的 CMake options 中配置编译选项,Build Type选Release就快一些,编译选项如下:
# 使用 ninja -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_INCLUDE_TESTS=Off # 默认使用 make -DCMAKE_BUILD_TYPE=Release -DLLVM_INCLUDE_TESTS=Off # 如果要移植到的 NDK 或者 xcode 的toolchain中包含 lib64,则还需添加 # -DLLVM_LIBDIR_SUFFIX=64
-
在 File | Settings | Build, Execution, Deployment | Toolchains 中配置 C++编译器是使用 g++还是clang++,C编译器是使用 g 还是 clang,Make是选择 make 还是ninja。这一步其实默认就可以。
cmake 完成后,开始 Build-Build Project 构建工程,如果有报错会在下边栏中给出错误信息和错误代码位置,点过去就可,方便排查错误。另外用CLion的好处还有就是可以跟踪符号,直接点击便可跳转代码。
2. 具体的移植步骤
- llvm-project/llvm/include/llvm/Transforms/Obfuscation -----> llvm12_root/ ; (目录层级得一样,下同)
- llvm-project/llvm/lib/llvm/Transforms/Obfuscation -----> llvm12_root/ ;
- llvm-project/llvm/include/llvm/CryptoUtils.h -----> llvm12_root/ ;
- llvm-project/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp 中添加
// Flags for obfuscation
static cl::opt<bool> Flattening("fla", cl::init(false),
cl::desc("Enable the flattening pass"));
static cl::opt<bool> BogusControlFlow("bcf", cl::init(false),
cl::desc("Enable bogus control flow"));
static cl::opt<bool> Substitution("sub", cl::init(false),
cl::desc("Enable instruction substitutions"));
static cl::opt<std::string> AesSeed("aesSeed", cl::init(""),
cl::desc("seed for the AES-CTR PRNG"));
static cl::opt<bool> Split("split", cl::init(false),
cl::desc("Enable basic block splitting"));
static cl::opt<bool> StringObf("sobf", cl::init(false),
cl::desc("Enable the string obfuscation"));
PassManagerBuilder::PassManagerBuilder() {
OptLevel = 2;
...
CallGraphProfile = true;
//ollvm add begin
// Initialization of the global cryptographically
// secure pseudo-random generator
if (!AesSeed.empty()) {
if (!llvm::cryptoutils->prng_seed(AesSeed.c_str()))
exit(1);
}
//ollvm add end
}
void PassManagerBuilder::addLTOOptimizationPasses(legacy::PassManagerBase &PM) {
// Load sample profile before running the LTO optimization pipeline.
...
// Infer attributes about declarations if possible.
PM.add(createInferFunctionAttrsLegacyPass());
//ollvm add begin
PM.add(createSplitBasicBlock(Split));
PM.add(createBogus(BogusControlFlow));
if (Flattening) {
// Lower switch
PM.add(createLowerSwitchPass());
}
PM.add(createFlattening(Flattening));
PM.add(createSubstitution(Substitution));
PM.add(createStringObfuscation(StringObf));
//ollvm add end
if (OptLevel > 1) {
...
}
PM.add(createJumpThreadingPass(/*FreezeSelectCond*/ true));
}
- llvm-project/llvm/lib/Transforms/CMakeLists.txt 中添加:
add_subdirectory(Obfuscation)
-
llvm-project/llvm/lib/Transforms/IPO/CMakeLists.txt 中添加:
add_llvm_component_library( ... Obfuscation )
llvm12中已经弃用 LLVMBuild.txt,这一项本来是加在 llvm-project/llvm/lib/Transforms/IPO/LLVMBuild.txt 中,现在改到加在这里。
移植的 ollvm12.x (兼 Armariris 字符串加密)已上传至:https://github.com/Chenyangming9/llvm-project/tree/release/ollvm12.x
三. ollvm 整合到工具链中使用
不管是哪个平台,最好先事先看下原来的llvm的版本 (命令:clang --version),然后将ollvm移植到对应的llvm版本中。
1. Android NDK
git clone ollvm代码地址
mkdir llvm_root/build_release # CLion中默认生成在 cmake-build-release 或 cmake-build-debug
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS='clang' -DLLVM_INCLUDE_TESTS=OFF -DLLVM_LIBDIR_SUFFIX=64 ../llvm #大多的NDK中有 lib64,所以添加-DLLVM_LIBDIR_SUFFIX=64,xcode中没有,不用加。为什么加 -DLLVM_ENABLE_PROJECTS='clang',因为 Obfuscation pass会编译进 clang,所以要加该项
ninja -j7
# 如果有命令找不到,则按照 官网 [https://releases.llvm.org/12.0.0/docs/GettingStarted.html](https://releases.llvm.org/12.0.0/docs/GettingStarted.html) 中说明配置
编译完成后,将 llvm_root/build_release 中 bin 、include、lib、lib64 覆盖拷贝到 android-ndk/toolchains/llvm/prebuilt/linux-x86_64 中即可。
2. xcode 中集成
(1)编译
git clone ollvm代码地址
mkdir llvm_root/build_release # CLion中默认生成在 cmake-build-release 或 cmake-build-debug
cmake -DLLVM_CREATE_XCODE_TOOLCHAIN=ON -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS='clang' -DLLVM_INCLUDE_TESTS=OFF ../llvm #大多的NDK中有 lib64,所以添加-DLLVM_LIBDIR_SUFFIX=64,xcode中没有,不用加。为什么加 -DLLVM_ENABLE_PROJECTS='clang',因为 Obfuscation pass会编译进 clang,所以要加该项
make install-xcode-toolchain -j10
# 编译完成后生成的工具链位于 /usr/local/Toolchains,将其移动到 /Library/Developer/ 目录
sudo mv /usr/local/Toolchains /Library/Developer/
DLLVM_CREATE_XCODE_TOOLCHAIN 选项参考:https://llvm.org/docs/CMake.html#llvm-related-variables
说明: 之前尝试使用 -G “Xcode”,则可以在 xcode 中打开工程,但报错如下:
CMake Error in utils/benchmark/CMakeLists.txt:
The custom command generating
/usr/local/Toolchains/LLVM12.0.0.xctoolchain
is attached to multiple targets:
install-xcode-toolchain
install-xcode-toolchain-stripped
but none of these is a common dependency of the other(s). This is not
allowed by the Xcode "new build system".
找不到解决方法,就弃用了,哎。
(3)xcode 中使用
打开后 xcode 后,在 Xcode-Preferences-Components-Toolchains看到生成好的工具链,如下图:
或者:Xcode-Toolchains中查看到,如下图:
更换工具链,在以上两个位置都可以更换。使用新工具链编译 Xcode 项目,报错unknown argument: ‘-index-store-path’,需要到项目 Build Settings 关闭 Index-While-Building,应该是这个参数在开源的 LLVM 项目中没有实现。如下:
关闭该选项,如下图:
添加 ollvm 编译选项,-mllvm -fla -mllvm -sub -mllvm -bcf -mllvm -sobf
(4)xcode 中混淆后的效果
混淆前:
混淆后:
如果文章不错,也请多支持,如果有不对的地方,也请多指正~
四. 参考
标签:集成,llvm,cl,xcode,ios,add,ollvm,ollvm12,DLLVM 来源: https://blog.csdn.net/Denny_Chen_/article/details/122480182