OLLVM混淆初始及环境搭建
OLLVM混淆初识及环境搭建(Ubuntu22.04)
前言
前些日子在国赛华中分区赛上,碰到了蛮多OLLVM混淆的题目,当时用IDA的D-810没去掉,借此机会,学习学习OLLVM。
介绍:
OLLVM就不细讲了,需要了解的直接看
https://blog.quarkslab.com/deobfuscation-recovering-an-ollvm-protected-program.html
环境搭建:
我自己用的环境:
Ubuntu22.04,之前用来搭PWN的环境,2个U,内存4G,硬盘20G+10G(怕OLLVM构建项目时卡死,多分配点swap分区)
首先换国内源
- cp /etc/apt/source.list /etc/apt/source.list.bak
- vim /etc/apt/source.list
- 然后换源,我自己换的是阿里源(因为cmake)
Ubuntu硬盘扩容:
注意,这里的扩容网上有很多教程,都没细说。
LLVM在进行交叉编译的时候会出现空间不足,或者swap分区占用100%的情况。所以我们需要进行扩容。
这里要分二步,先进行硬盘扩容然后进行swap分区扩容,确保
硬盘扩容
详细教程:https://blog.csdn.net/qq_34160841/article/details/113058756
这里我的硬盘一开始是20GB,而且之前装了PWN的环境,剩余的也不多,做了个扩容。
swap分区扩容
最终效果:
更新软件源
- sudo apt update && sudo apt upgrade -y
安装gcc和g++的8.x版本以及cmake
安装cmake
- sudo apt-get install cmake -y
安装gcc和g++
- sudo apt-get install gcc-8
- sudo apt-get install g++-8
调整gcc和g++的优先级
gcc的9.x版本是无法编译的,我们需要通过以下命令来调整gcc和g++的优先级
- 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 --version
查看g++版本
- g++ --version
gcc切换版本,我们需要切换到gcc8
- sudo update-alternatives --config gcc
g++切换版本,我们需要切换到g++8
- sudo update-alternatives --config gcc
最终效果图
Git LLVM源码
提前安装git:
sudo apt install git
下载源码:
git clone -b llvm-4.0 https://github.com/obfuscator-llvm/obfuscator.git
踩坑的点:
需要对源码进行修改
vim ollvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
有些人是把char改成了uint_8,这是错误的。
编译
先在obfuscator的同级的目录,创建build目录,命令如下:
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_INCLUDE_TESTS=OFF ../obfuscator/
make
sudo make install
如果出现卡死,多半是交叉编译时,内存不够引起的。
处理方法可以用make -j8.
编译成功了之后,我们就可以进行混淆了。
1、控制流扁平化
clang -mllvm -fla test.c -o test1
2、指令替换
clang -mllvm -sub test.c -o test2
3、控制流伪造
clang -mllvm -bcf test.c -o test
出现报错
原因是我需要到build/bin目录下,通过编译好的程序clang,进行OLLVM混淆。
练习代码:
#include <stdio.h>
#include <stdlib.h>
int encryptFunc(int inputNum_1,int inputNum_2){
int tmpNum_1 = 666, tmpNum_2 = 888, tmpNum_3 = 777;
return tmpNum_1 ^ tmpNum_2 + tmpNum_3 * inputNum_1 - inputNum_2;
}
int main(int argc,char *argv[]){
int printNum = 55;
if (argc > 1)
{
printNum = encryptFunc(printNum, atoi(argv[1]));
}else{
printNum = encryptFunc(printNum, argc);
}
printf("Hello OLLVM %d\r\n", printNum);
return 0;
}
编译成功。
我们再用普通的GCC去编译这个程序,最后用IDA看一看。
最终效果
混淆后
混淆前
OLLVM用法:
参考链接:https://blog.csdn.net/weixin_51732593/article/details/126707046
踩坑日记:
构建项目时,在%96时出现报错
报错情况如下:
Consolidate compiler generated dependencies of target lli
[ 96%] Building CXX object tools/lli/CMakeFiles/lli.dir/lli.cpp.o
In file included from /media/babypwn/qqq/ollvm/obfuscator/include/llvm/CodeGen/LinkAllCodegenComponents.h:20,
from /media/babypwn/qqq/ollvm/obfuscator/tools/lli/lli.cpp:22:
/media/babypwn/qqq/ollvm/obfuscator/include/llvm/CodeGen/SchedulerRegistry.h: In constructor ‘llvm::RegisterScheduler::RegisterScheduler(const char*, const char*, llvm::RegisterScheduler::FunctionPassCtor)’:
/media/babypwn/qqq/ollvm/obfuscator/include/llvm/CodeGen/SchedulerRegistry.h:42:52: warning: cast between incompatible function types from ‘llvm::RegisterScheduler::FunctionPassCtor’ {aka ‘llvm::ScheduleDAGSDNodes* (*)(llvm::SelectionDAGISel*, llvm::CodeGenOpt::Level)’} to ‘llvm::MachinePassCtor’ {aka ‘void* (*)()’} [-Wcast-function-type]
: MachinePassRegistryNode(N, D, (MachinePassCtor)C)
^
In file included from /media/babypwn/qqq/ollvm/obfuscator/tools/lli/lli.cpp:30:
/media/babypwn/qqq/ollvm/obfuscator/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h: In member function ‘llvm::Expected<std::vector<char> > llvm::orc::remote::OrcRemoteTargetClient<ChannelT>::readMem(uint8_t*, llvm::JITTargetAddress, uint64_t)’:
/media/babypwn/qqq/ollvm/obfuscator/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h:696:26: error: could not convert ‘((llvm::orc::remote::OrcRemoteTargetClient<ChannelT>*)this)->callB<llvm::orc::remote::OrcRemoteTargetRPCAPI::ReadMem>(Src, Size)’ from ‘Expected<vector<unsigned char,allocator<unsigned char>>>’ to ‘Expected<vector<char,allocator<char>>>’
return callB<ReadMem>(Src, Size);
~~~~~~~~~~~~~~^~~~~~~~~~~
In file included from /media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/Twine.h:13,
from /media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/Triple.h:13,
from /media/babypwn/qqq/ollvm/obfuscator/tools/lli/OrcLazyJIT.h:18,
from /media/babypwn/qqq/ollvm/obfuscator/tools/lli/lli.cpp:16:
/media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/SmallVector.h: In instantiation of ‘void llvm::SmallVectorTemplateBase<T, true>::push_back(const T&) [with T = std::pair<void*, long unsigned int>]’:
/media/babypwn/qqq/ollvm/obfuscator/include/llvm/Support/Allocator.h:241:33: required from ‘void* llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold>::Allocate(size_t, size_t) [with AllocatorT = llvm::MallocAllocator; long unsigned int SlabSize = 4096; long unsigned int SizeThreshold = 4096; size_t = long unsigned int]’
/media/babypwn/qqq/ollvm/obfuscator/include/llvm/MC/MCContext.h:548:44: required from here
/media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/SmallVector.h:309:11: warning: ‘void* memcpy(void*, const void*, size_t)’ writing to an object of type ‘struct std::pair<void*, long unsigned int>’ with no trivial copy-assignment; use copy-assignment or copy-initialization instead [-Wclass-memaccess]
memcpy(this->end(), &Elt, sizeof(T));
~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/8/utility:70,
from /media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/iterator_range.h:22,
from /media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/SmallVector.h:17,
from /media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/Twine.h:13,
from /media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/Triple.h:13,
from /media/babypwn/qqq/ollvm/obfuscator/tools/lli/OrcLazyJIT.h:18,
from /media/babypwn/qqq/ollvm/obfuscator/tools/lli/lli.cpp:16:
/usr/include/c++/8/bits/stl_pair.h:208:12: note: ‘struct std::pair<void*, long unsigned int>’ declared here
struct pair
^~~~
In file included from /media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/Twine.h:13,
from /media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/Triple.h:13,
from /media/babypwn/qqq/ollvm/obfuscator/tools/lli/OrcLazyJIT.h:18,
from /media/babypwn/qqq/ollvm/obfuscator/tools/lli/lli.cpp:16:
/media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/SmallVector.h: In instantiation of ‘static void llvm::SmallVectorTemplateBase<T, true>::uninitialized_copy(T1*, T1*, T2*, typename std::enable_if<std::is_same<typename std::remove_const<T1>::type, T2>::value>::type*) [with T1 = const std::pair<const llvm::MCSymbol*, const llvm::MCSymbol*>; T2 = std::pair<const llvm::MCSymbol*, const llvm::MCSymbol*>; T = std::pair<const llvm::MCSymbol*, const llvm::MCSymbol*>; typename std::enable_if<std::is_same<typename std::remove_const<T1>::type, T2>::value>::type = void]’:
/media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/SmallVector.h:399:5: required from ‘void llvm::SmallVectorImpl<T>::append(in_iter, in_iter) [with in_iter = const std::pair<const llvm::MCSymbol*, const llvm::MCSymbol*>*; T = std::pair<const llvm::MCSymbol*, const llvm::MCSymbol*>]’
/media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/SmallVector.h:858:5: required from ‘llvm::SmallVector<T, N>::SmallVector(ItTy, ItTy) [with ItTy = const std::pair<const llvm::MCSymbol*, const llvm::MCSymbol*>*; T = std::pair<const llvm::MCSymbol*, const llvm::MCSymbol*>; unsigned int N = 2]’
/media/babypwn/qqq/ollvm/obfuscator/include/llvm/MC/MCFragment.h:546:42: required from here
/media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/SmallVector.h:296:13: warning: ‘void* memcpy(void*, const void*, size_t)’ writing to an object of type ‘struct std::pair<const llvm::MCSymbol*, const llvm::MCSymbol*>’ with no trivial copy-assignment; use copy-assignment or copy-initialization instead [-Wclass-memaccess]
memcpy(Dest, I, (E - I) * sizeof(T));
~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/8/utility:70,
from /media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/iterator_range.h:22,
from /media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/SmallVector.h:17,
from /media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/Twine.h:13,
from /media/babypwn/qqq/ollvm/obfuscator/include/llvm/ADT/Triple.h:13,
from /media/babypwn/qqq/ollvm/obfuscator/tools/lli/OrcLazyJIT.h:18,
from /media/babypwn/qqq/ollvm/obfuscator/tools/lli/lli.cpp:16:
/usr/include/c++/8/bits/stl_pair.h:208:12: note: ‘struct std::pair<const llvm::MCSymbol*, const llvm::MCSymbol*>’ declared here
struct pair
^~~~
make[2]: *** [tools/lli/CMakeFiles/lli.dir/build.make:76:tools/lli/CMakeFiles/lli.dir/lli.cpp.o] 错误 1
make[1]: *** [CMakeFiles/Makefile2:18697:tools/lli/CMakeFiles/lli.dir/all] 错误 2
make: *** [Makefile:156:all] 错误 2
原因
ollvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h的690行,只改了一个char,没有全部改掉
解决方法:
两个char都改为uint8_t
重新make或者make -j8
-j,相当于调用多线程进行编译,速度更快,前提是你内存够,不然容易卡死,导致报错
参考链接:
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步