首页
论坛
课程
招聘
[原创]一种将LLVM Pass集成到NDK中的通用方法
2022-1-24 23:10 31694

[原创]一种将LLVM Pass集成到NDK中的通用方法

2022-1-24 23:10
31694

关于“如何将自己写的LLVM Pass集成到NDK中”这个问题,目前网上并没有很完美的方法,并且大多数已经过时。经过我的一番折腾,最终摸索出了一种比较简单实用的方法,可供参考。

0x00. 概览

简单来说,本文要介绍的方法是下载NDK中llvm-android部分的源码,在llvm-android中的llvm-project子项目中加入自己的Pass后与整个项目一起编译,用编译好的文件替换掉NDK中的工具链。
该方法有以下优点:

  • Windows、macOS、Linux通用,各NDK版本也通用
  • 理论上加入自己的Pass后不会出现不兼容的问题
  • 操作过程简单易懂

当然也有缺点:

  • 无法直接照搬OLLVM、Hikari、Armariris等现成项目的源码,需要手动做一些迁移
  • 第一次编译比较耗时

0x01. 操作流程

本文并不是直接将最终的操作方法摆在大家面前,还讲解了为什么要这么操作,因此过程会显得较冗长,需要有一点耐心看下去。

1. 环境准备

如果是Windows,首先需要准备Linux虚拟机进行交叉编译,因为NDK不支持在Windows上直接编译,我这里使用的是Ubuntu 20.04.3;macOS则不需要。NDK版本我选择的是23.1.7779620
本文以Windows+Linux虚拟机为例讲解,macOS下的操作大同小异。
以下使用的指令全部以root权限执行。

2. 下载 llvm-android 源代码

NDK使用的是git-repo这一工具管理,而不是git,所以首先需要安装git-repo

1
2
curl https://storage.googleapis.com/git-repo-downloads/repo > /usr/bin/repo
chmod a+x /usr/bin/repo

上面这个地址需要科学上网才能访问,我们可以换成国内的清华源:

1
2
curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > /usr/bin/repo
chmod a+x /usr/bin/repo

$NDK_PATH\toolchains\llvm\prebuilt\windows-x86_64\AndroidVersion.txt中查看NDK使用的LLVM版本,在我使用的NDK中,AndroidVersion.txt 的内容是:

1
2
12.0.8
based on r416183c1

https://android.googlesource.com/toolchain/llvm_android/中找到对应版本的 llvm-android 源码:
图片描述
Google的文档中给出了下载 llvm-android 源代码的方法,但这里默认下载的是最新版本:

1
2
3
mkdir llvm-toolchain && cd llvm-toolchain
repo init -u https://android.googlesource.com/platform/manifest -b llvm-toolchain
repo sync -c

我们需要做一些操作来换成我们想要的版本,在$NDK_PATH\toolchains\llvm\prebuilt\windows-x86_64目录下找到一个 manifest_xxxx.xml 文件,我这里是 manifest_7714059.xml。执行完下列指令后:

1
2
mkdir llvm-toolchain && cd llvm-toolchain
repo init -u

将 manifest_7714059.xml 复制到.repo/mainifests文件夹中(注意.repo是隐藏文件夹,并且从Windows复制到Linux会有格式转换的问题,这里建议使用VSCode的SSH-Remote插件避免上述问题):
图片描述
继续执行:

1
2
repo init -m manifest_7714059.xml
repo sync -c

这里也要把Google的地址换成清华源,替换规则见 Android 镜像使用帮助,替换后完整的指令如下:

1
2
3
4
5
mkdir llvm-toolchain && cd llvm-toolchain
repo init -u
https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b llvm-toolchain
repo init -m manifest_7714059.xml
repo sync -c

并且 manifest_7714059.xml 中的包含地址也要替换,否则即使科学上网,在下载的时候也非常慢:
图片描述
repo sync -c指令会下载一大堆的源代码和预编译文件,需要耗费十来分钟的样子,喝杯茶慢慢等吧。

3. 编译 llvm-android 源代码

在编译之前需要提前安装一些环境,否则编译会出错:

1
apt install cmake bison

如果是在Ubuntu 20.04.3下还需要做一个软链接,否则会报错ImportError: libffi.so.6: cannot open shared object file: No such file or directory。具体操作如下:
图片描述
然后就可以开始愉快且漫长的编译了(大概需要一两个小时,取决于机器性能):

1
python toolchain/llvm_android/build.py --no-build linux

因为我是在Windows环境使用NDK,所以无需编译Linux下的toolchain,这里加上--no-build linux参数。
另外编译的时候最好把虚拟机内存开到8G以上,我开的是8G内存,编译的时候还会因为内存不足时不时中断,如果中断了重新运行编译指令就好。
编译结束后可以在out文件夹中找到编译好的内容:
图片描述

4. 加入自己的 Pass 并重新编译

在这里我要推销一下我的项目Pluto-Obfuscator ,如果使用的是OLLVM, Armariris等,需要注意一下版本适配的问题。
此时我们需要向toolchain/llvm-project/llvm/lib/Transforms/Obfuscation/中加入自己的代码:
图片描述
toolchain/llvm-project/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp中加入几段代码:
图片描述
图片描述
修改toolchain/llvm-project/llvm/lib/Transforms/IPO/CMakeLists.txt
图片描述
改好之后重新编译,重新编译的速度会快很多,一分钟左右就能搞定:

1
python toolchain/llvm_android/build.py --no-build linux

编译好后out/install/windows-x86/clang-dev中对应的就是NDK中的toolchains\llvm\prebuilt\windows-x86_64部分:
图片描述
图片描述
少了一些东西,但是无关紧要,我们直接替换就好。

0x03. 效果测试

我复制了一份NDK,命名为pluto-r23,并将其中toolchains\llvm\prebuilt\windows-x86_64文件夹里的内容替换成我们刚刚编译的内容:
图片描述
随便写一个Native项目测试:
图片描述
设置NDK地址:
图片描述
加上混淆参数:
图片描述
编译然后查看混淆效果:
图片描述
X86架构和ARM架构均混淆成功:
图片描述
图片描述


看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

最后于 2022-3-28 21:41 被34r7hm4n编辑 ,原因:
收藏
点赞6
打赏
分享
最新回复 (23)
雪    币: 4689
活跃值: 活跃值 (2075)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
mudebug 活跃值 2022-1-25 04:13
2
0
感谢分享
雪    币: 2690
活跃值: 活跃值 (1850)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caolinkai 活跃值 2022-1-25 08:58
3
0
感谢分享
雪    币: 5407
活跃值: 活跃值 (3913)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
GitRoy 活跃值 3 2022-1-25 09:53
4
0
ma
雪    币: 1457
活跃值: 活跃值 (4543)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
至尊小仙侠 活跃值 2022-1-25 12:10
5
0
感谢分享
雪    币: 184
活跃值: 活跃值 (255)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Ssage泓清 活跃值 2022-2-17 17:02
6
0

大佬您好,在向您进行学习的过程中,遇到了一些小问题

已提交至GitHub的issues

也希望有关大佬可以指点一二

雪    币: 4521
活跃值: 活跃值 (2136)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
LeadroyaL 活跃值 1 2022-2-18 10:03
7
2

哥们,你既下载了源码、修改了llvm源码、编译了llvm、还替换了NDK,和大家公开的方案区别就在 “下载源码”和 “编译llvm” 的过程不一样吧。

我的优点我也列出来了:
不需要编译llvm
仅依赖NDK,不需要额外的其他环境
不会遇到配置引起的符号NotFound问题
不污染NDK

因此,我没有明白你哪来的自信说我方案的不优雅。

最后于 2022-2-18 10:04 被LeadroyaL编辑 ,原因:
雪    币: 435
活跃值: 活跃值 (1054)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
pareto 活跃值 2022-2-18 10:10
8
1
感谢分享,这个思路就是重新编译一份完整的llvm,leadroyal的方案是直接使用ndk环境做pass,对ndk环境的破坏来看,可能leadroyal的更好点。但是重新编译完整llvm,目前也没有出现什么问题。
雪    币: 12476
活跃值: 活跃值 (7739)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
34r7hm4n 活跃值 7 2022-2-18 11:31
9
0
LeadroyaL 哥们,你既下载了源码、修改了llvm源码、编译了llvm、还替换了NDK,和大家公开的方案区别就在 “下载源码”和 “编译llvm” 的过程不一样吧。我的优点我也列出来了:不需要编译 ...
冒犯到你不好意思,我并没有要贬低什么的意思,只是与其他方法做一个对比。原文已经删除。
雪    币: 184
活跃值: 活跃值 (255)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Ssage泓清 活跃值 2022-2-18 20:49
10
0
Ssage泓清 大佬您好,在向您进行学习的过程中,遇到了一些小问题已提交至GitHub的issues也希望有关大佬可以指点一二

issues问题已经解决,建议使用服务器环境对楼主方法进行复现的朋友 

严格注意文件格式问题,否则在移植ndk-r23b版本的过程中 

很可能出现因为文件格式损坏而导致的报错~ 详细请参考issues

最后于 2022-2-18 20:50 被Ssage泓清编辑 ,原因:
雪    币: 12476
活跃值: 活跃值 (7739)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
34r7hm4n 活跃值 7 2022-2-18 21:53
11
0
Ssage泓清 Ssage泓清 大佬您好,在向您进行学习的过程中,遇到了一些小问题已提交至GitHub的issues也希望有关大佬可以指点一二 issues问题 ...
感谢你的详细解释。TrapAngr和RandomControlFlow都需要插入rand函数,应该是这个原因导致在ARM下编译失败,我之后会排查一下。
雪    币: 25
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_ipugnluu 活跃值 2022-3-11 15:10
12
0
整合后用
       
python toolchain/llvm_android/build.py --no-build linux

出现的错误

已经安装了libz3-dev

/home/x/ollvm/llvm-toolchain/out/llvm-project/llvm/include/llvm/Transforms/Obfuscation/MBAUtils.h:1:10: fatal error: 'z3++.h' file not found
#include "z3++.h"
雪    币: 12476
活跃值: 活跃值 (7739)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
34r7hm4n 活跃值 7 2022-3-11 15:15
13
0
mb_ipugnluu 整合后用 python toolchain/llvm_android/build.py --no-build linux 出现的错误 已经安装了libz3-dev /home ...
安装依赖
sudo apt install libz3-dev 
雪    币: 25
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_ipugnluu 活跃值 2022-3-11 15:22
14
0
34r7hm4n 安装依赖 sudo apt install libz3-dev
已经安装过了
但是还是报错
雪    币: 25
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_ipugnluu 活跃值 2022-3-11 15:23
15
0
libz3-dev 已经是最新版 (4.8.7-4build1)
雪    币: 12476
活跃值: 活跃值 (7739)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
34r7hm4n 活跃值 7 2022-3-11 15:52
16
1
mb_ipugnluu 已经安装过了 但是还是报错
可能在NDK的环境下会有问题,我之后去试试
雪    币: 25
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_ipugnluu 活跃值 2022-3-11 17:17
17
0
34r7hm4n 可能在NDK的环境下会有问题,我之后去试试
大佬加油
雪    币: 25
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_ipugnluu 活跃值 2022-3-13 10:15
18
0
34r7hm4n 可能在NDK的环境下会有问题,我之后去试试
大佬,有解决办法吗
雪    币: 159
活跃值: 活跃值 (1936)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huaerxiela 活跃值 2022-3-20 17:07
19
0
请教下
直接mac编译https://github.com/bluesadi/Pluto-Obfuscator master分支后,移植到ndk 23.1.7779620后
报错ld: error: unable to find library -latomic
find了一下这个文件,没有可用的呀
雪    币: 12476
活跃值: 活跃值 (7739)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
34r7hm4n 活跃值 7 2022-3-26 22:40
20
0
mb_ipugnluu 大佬,有解决办法吗
最近有点忙,会尽快解决的
雪    币: 25
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_ipugnluu 活跃值 2022-3-28 22:11
21
0
34r7hm4n 最近有点忙,会尽快解决的
加油
雪    币: 12476
活跃值: 活跃值 (7739)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
34r7hm4n 活跃值 7 2022-4-6 22:13
22
0
mb_ipugnluu libz3-dev 已经是最新版 (4.8.7-4build1)
已修复:
见 https://github.com/bluesadi/Pluto-Obfuscator/issues/12
雪    币: 25
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_ipugnluu 活跃值 2022-4-10 22:33
23
0
34r7hm4n 已修复: 见 https://github.com/bluesadi/Pluto-Obfuscator/issues/12
楼主,你源码里面有个MBAUtils copy.cpp的文件没删除,如果没删除的话,编译必报错
雪    币: 12476
活跃值: 活跃值 (7739)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
34r7hm4n 活跃值 7 2022-4-10 23:25
24
0
mb_ipugnluu 楼主,你源码里面有个MBAUtils copy.cpp的文件没删除,如果没删除的话,编译必报错
这个可以删掉
游客
登录 | 注册 方可回帖
返回