OLLVM混淆环境搭建与去平坦化
之前遇到了很多次ollvm平坦化的题目,所以想学习一下,参照了很多前人的方法,特此记录一下。## 环境
vmware虚拟机,ubuntu20.04
## ollvm定义
LLVM(Low Level Virtual Machine)是一个开源的编译器基础架构,它包含了一组模块化、可重用的编译器和工具,支持多种编程语言和目标架构,包括x86、ARM和MIPS等。LLVM的核心思想是将编译器分为前端和后端两个部分,前端负责将源代码转换为中间表示(IR),后端负责将中间表示转换为目标机器的汇编代码。这种设计使得LLVM可以支持多种编程语言,因为只需要为每种语言编写一个前端,就可以利用后端的通用性支持多种目标架构。
OLLVM(Obfuscator-LLVM)是瑞士西北应用科技大学安全实验室于2010年6月份发起的一个项目,这个项目的目标是提供一个LLVM编译套件的开源分支,能够通过代码混淆和防篡改,所使用的编译器是clang。
## 搭建ollvm环境
ollvm github仓库
```
https://github.com/obfuscator-llvm/obfuscator
```
### git下载ollvm源码
```git
git clone -b llvm-4.0 --depth=1 https://github.com/obfuscator-llvm/obfuscator.git
```
### 配置编译工具
```
cmake , gcc , g++
```
#### cmake
去官网下载(https://cmake.org/download/)或者直接sudo安装
```shell
sudo apt install cmake
```
#### 安装 gcc-8 g++-8 降低版本
查看gcc和g++版本,若为9则要降低版本
##### 安装gcc-8和g++-8
```shell
sudo apt-get install gcc-8 g++-8 -y
```
配置软件的优先级,可以根据需要去选择默认的版本
```shell
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 8
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-8 8
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 9
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 9
```
##### gcc切换版本 默认gcc 8
```shell
sudo update-alternatives --config gcc
```
输入选择版本的数字
##### g++切换版本 默认g++ 8
```shell
sudo update-alternatives --config g++
```
### 修改ollvm源码
进入 ollvm目录/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
定位到第690行 把char 改成 uint_8t
在`config.guess`文件中存在一些DOS行结尾(DOS line endings),需要将其转换为Unix行结尾。
```shell
sudo apt-get install dos2unix
dos2unix obfuscator/cmake/config.guess
```
### 编译 ollvm
```shell
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_INCLUDE_TESTS=OFF ../obfuscator/
```
```shell
make -j4
```
这个过程会很久
```
[ 97%] Built target llvm-objdump
[ 97%] Linking CXX executable ../../bin/llvm-mc
[ 97%] Built target llvm-mc
[ 97%] Linking CXX executable ../../bin/llvm-dwp
[ 97%] Linking CXX executable ../../bin/llvm-lto2
[ 97%] Built target llvm-dwp
[ 97%] Built target llvm-lto2
make: *** Error 2
```
可能是环境配置出了问题,编译到97%时就停止了,几个主要的clang文件都没编译成功
试了好几次都卡在这个
查阅资料,猜测是swap区空间不够,增加swap区空间为4g,扩大虚拟机容量为60g
**如果卡住了,不要慌,不要删,继续`make -j`**
### 混淆
两种方法,一种是配置ndk环境混淆,另一种是直接将clang作为程序进行混淆。推荐第二种,第一种无法控制混淆的方法。
**注意,混淆时一定要采用gcc8和g++8,9以上的环境会混淆失败。**
#### 配置ndk环境
执行命令,打开配置文件
```shell
gedit ~/.bashrc
```
把下面这两行粘贴到文件末尾, 注意,替换路径成自己下载的ndk路径
```shell
export NDK_HOME=/home/bag/android/android-ndk-r16b/
export PATH=$NDK_HOME:$PATH
```
最后执行命令,使配置文件生效
```shell
source ~/.bashrc
```
##### 复制编译好的4个 clang 文件到ndk目录
clang,clang++,clang-4.0,clang-format
粘贴到ndk目录
```
ndk目录/toolchains/llvm/prebuilt/linux-x86_64/bin
```
##### 复制build目录的 3个头文件到ndk目录
```
fatal error 'Stddef.h' file not found
fatal error 'Stdarg.h' file not found
fatal error '__stddef_max_align_t.h' file not found
```
ndk目录
```
android-ndk-r16b/sources/cxx-stl/system/include
```
新建jni文件夹(名字改了的话在对应的配置文件得该指定路径方式)
在文件夹中新建`Android.mk`,`Application.mk`,`try.cpp`
Android.mk
```
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := bag
LOCAL_SRC_FILES := try.cpp
include $(BUILD_EXECUTABLE)
```
Application.mk
```
APP_ABI := armeabi-v7a arm64-v8a
APP_PIE := true
APP_CPPFLAGS := -frtti -std=c++11 -mllvm -fla -mllvm -bcf -mllvm -sub
```
try.cpp
```cpp
#include<cstdio>
int main()
{
int d;
scanf("%d",&d);
if(d==1)printf("d = 1");
else if(d==2)printf("d = 2");
else printf("not 1 or 2");
return 0;
}
```
在jni的上级路径,输入ndk-build
成功了!
混淆后的文件在libs内
在ida中查看混淆效果
#### clang混淆
这里对源文件进行**平坦化混淆**处理。
来到build/bin目录下,将待混淆的源文件放在该目录下。
命令格式为
```shell
./clang -mllvm -fla 源文件 -o 目标文件
```
```shell
./clang -mllvm -fla try.cpp -o try
```
成功生成混淆后的文件,用ida查看效果
## 去平坦化
### 虚拟环境
安装虚拟环境
```shell
pip install virtualenv
```
配置环境变量
```shell
export WORKON_HOME=$HOME/.virtualenvs
export PROJECT_HOME=$HOME/workspace
source /usr/local/bin/virtualenvwrapper.sh
```
打开虚拟环境
```shell
source ~/.local/bin/virtualenvwrapper.sh
```
创建新的虚拟环境
```shell
mkvirtualenv demo
```
展示当前虚拟环境
```shell
workon
```
进入虚拟环境
```shell
workon demo
```
### 使用脚本
由于脚本需要angr,在当前虚拟环境中安装
```shell
pip install angr
```
脚本github地址:(https://github.com/cq674350529/deflat)
将脚本中的`am_graph.py`和`util.py`文件复制到下级
在ida中找到平坦化的入口地址,一般而言入口前都会存在大量var_(局部变量),下图入口地址为0x401140
去平坦化命令格式为
```shell
python3 deflat.py -f filename --addr address(入口地址,一般为main入口)
```
```shell
python3 deflat.py -f try --addr 0x401140
```
去平坦化成功后,会在当前目录下生成`源文件_recovered`
在ida中查看去平坦化后效果
### 总结
1. 定位入口地址
2. 在`./deflat-master/flat_control_flow/`路径下启动虚拟环境
```shell
source ~/.local/bin/virtualenvwrapper.sh
workon
workon demo
```
3. 使用去平坦化命令
```shell
python3 deflat.py -f filename --addr address(入口地址,一般为main入口)
```
## 参考文章
1. (https://blog.csdn.net/weixin_51732593/article/details/126707046)
2. [跟着铁头干混淆2 ubuntu20.04编译ollvm - 简书 (jianshu.com)](https://www.jianshu.com/p/9136f7257e46)
3. (https://www.52pojie.cn/thread-1601573-1-1.html) 按教程一直编译不过去,搜了下博客教程,第690行,应该是uint8_t ,不是uint_8t{:1_906:}
Expected<std::vector<uint8_t>> readMem(char *Dst, JITTargetAddress Src,
uint64_t Size) {
一下就编译过去了;www 大佬,先收藏了,以后会用到的 收藏吃灰 一个比较典型的例子就是mame的编译吧
收藏吃灰 LLVM有没有通俗易懂的解释? 收藏吃灰
收藏吃灰
收藏吃灰 哦豁,你的帖子很好,现在是我的了
页:
[1]
2