Skip to content

Commit

Permalink
Add BogusControlFlow (Doesn't support C++ yet) & Change the way that …
Browse files Browse the repository at this point in the history
…Pluto is built
  • Loading branch information
bluesadi committed Dec 28, 2023
1 parent 3eab1f9 commit 085c1be
Show file tree
Hide file tree
Showing 17 changed files with 151 additions and 65 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/c-cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ jobs:
run: sudo apt install ninja-build -y
- name: Install z3
run: sudo apt install libz3-dev -y
- name: Install lld
run: sudo apt install lld -y
- name: git submodule update --init
run: git submodule update --init
- name: make install
run: make install
- name: ./build.sh
run: ./build.sh
- name: Test tiny-aes
run: ./tests/test-aes.sh
- name: Test jsoncpp
Expand Down
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.20)
project(Pluto)

set(LLVM_ENABLE_PROJECTS "clang;lld")
set(LLVM_TARGETS_TO_BUILD "X86")
set(LLVM_ENABLE_LLD ON)
set(LLVM_INCLUDE_BENCHMARKS OFF)
add_subdirectory(llvm)
39 changes: 0 additions & 39 deletions Makefile

This file was deleted.

20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@ Download source code:
```
$ git clone https://github.com/bluesadi/Pluto.git
```
### Dependencies
### Ubuntu
Install z3 (required by MbaObfuscation):
```
$ wget https://github.com/Z3Prover/z3/archive/refs/tags/z3-4.12.2.zip
$ tar xvf z3-4.12.2.zip
$ cd z3-z3-4.12.2
$ ./configure
$ cd build
$ make install
$ sudo apt install libz3-dev
```
(Optional) Install lld:
```
// This is an optional depencency to speed up the linking stage when building LLVM.
// If you don't want to install this dependency, remove the line `set(LLVM_ENABLE_LLD ON)` in CMakeLists.txt
$ sudo apt install lld
```
### Ubuntu
Install Ninja and other dependencies:
```
$ sudo apt install ninja-build cmake python3 gcc g++
```
Build and install to `./install` directory:
Build and install Pluto to the ./install directory:
```
$ make
$ ./build.sh
```
7 changes: 7 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mkdir -p build
cmake -G Ninja -S . -B build \
-DCMAKE_C_COMPILER="gcc" \
-DCMAKE_CXX_COMPILER="g++" \
-DCMAKE_INSTALL_PREFIX="install" \
-DCMAKE_BUILD_TYPE=Release
ninja -j`nproc` -C build install
15 changes: 15 additions & 0 deletions llvm/include/llvm/Transforms/Obfuscation/BogusControlFlow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include "llvm/Passes/PassBuilder.h"

using namespace llvm;

namespace Pluto {

struct BogusControlFlow : PassInfoMixin<BogusControlFlow> {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);

static bool isRequired() { return true; }
};

}; // namespace Pluto
89 changes: 89 additions & 0 deletions llvm/lib/Transforms/Obfuscation/BogusControlFlow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include "llvm/Transforms/Obfuscation/BogusControlFlow.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <vector>

using namespace llvm;

namespace Pluto {

BasicBlock *cloneBasicBlock(BasicBlock *BB) {
ValueToValueMapTy VMap;
BasicBlock *cloneBB = CloneBasicBlock(BB, VMap, "cloneBB", BB->getParent());
BasicBlock::iterator origI = BB->begin();
// 对克隆基本块的引用进行修复
for (Instruction &I : *cloneBB) {
for (int i = 0; i < I.getNumOperands(); i++) {
Value *V = MapValue(I.getOperand(i), VMap);
if (V) {
I.setOperand(i, V);
}
}
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
I.getAllMetadata(MDs);
for (std::pair<unsigned, MDNode *> pair : MDs) {
MDNode *MD = MapMetadata(pair.second, VMap);
if (MD) {
I.setMetadata(pair.first, MD);
}
}
I.setDebugLoc(origI->getDebugLoc());
origI++;
}
return cloneBB;
}

Value *createBogusCmp(BasicBlock *insertAfter) {
// if((y < 10 || x * (x + 1) % 2 == 0))
// 等价于 if(true)
Module *M = insertAfter->getModule();
LLVMContext &context = M->getContext();
GlobalVariable *xptr = new GlobalVariable(*M, Type::getInt32Ty(context), false, GlobalValue::CommonLinkage,
ConstantInt::get(Type::getInt32Ty(context), 0), "x");
GlobalVariable *yptr = new GlobalVariable(*M, Type::getInt32Ty(context), false, GlobalValue::CommonLinkage,
ConstantInt::get(Type::getInt32Ty(context), 0), "y");
LoadInst *x = new LoadInst(Type::getInt32Ty(context), xptr, "", insertAfter);
LoadInst *y = new LoadInst(Type::getInt32Ty(context), yptr, "", insertAfter);
ICmpInst *cond1 = new ICmpInst(*insertAfter, CmpInst::ICMP_SLT, y, ConstantInt::get(Type::getInt32Ty(context), 10));
BinaryOperator *op1 = BinaryOperator::CreateAdd(x, ConstantInt::get(Type::getInt32Ty(context), 1), "", insertAfter);
BinaryOperator *op2 = BinaryOperator::CreateMul(op1, x, "", insertAfter);
BinaryOperator *op3 =
BinaryOperator::CreateURem(op2, ConstantInt::get(Type::getInt32Ty(context), 2), "", insertAfter);
ICmpInst *cond2 = new ICmpInst(*insertAfter, CmpInst::ICMP_EQ, op3, ConstantInt::get(Type::getInt32Ty(context), 0));
return BinaryOperator::CreateOr(cond1, cond2, "", insertAfter);
}

PreservedAnalyses Pluto::BogusControlFlow::run(Function &F, FunctionAnalysisManager &AM) {
std::vector<BasicBlock *> origBB;
for (BasicBlock &BB : F) {
origBB.push_back(&BB);
}
for (BasicBlock *BB : origBB) {
// 第一步,拆分得到 headBB, bodyBB, endBB
// 其中所有的 PHI 指令都在 entryBB(如果有的话)
// endBB 只包含一条终结指令
BasicBlock *headBB = BB;
BasicBlock *bodyBB = BB->splitBasicBlock(BB->getFirstNonPHIOrDbgOrLifetime(), "bodyBB");
BasicBlock *tailBB = bodyBB->splitBasicBlock(bodyBB->getTerminator(), "endBB");
// 第二步,克隆 bodyBB 得到克隆块 cloneBB
BasicBlock *cloneBB = cloneBasicBlock(bodyBB);

// 第三步,构造虚假跳转
// 1. 将 entryBB, bodyBB, cloneBB 末尾的绝对跳转移除
BB->getTerminator()->eraseFromParent();
bodyBB->getTerminator()->eraseFromParent();
cloneBB->getTerminator()->eraseFromParent();
// 2. 在 entryBB 和 bodyBB 的末尾插入条件恒为真的虚假比较指令
Value *cond1 = createBogusCmp(BB);
Value *cond2 = createBogusCmp(bodyBB);
// 3. 将 entryBB 到 bodyBB 的绝对跳转改为条件跳转
BranchInst::Create(bodyBB, cloneBB, cond1, BB);
// 4. 将 bodyBB 到 endBB的绝对跳转改为条件跳转
BranchInst::Create(tailBB, cloneBB, cond2, bodyBB);
// 5. 添加 bodyBB.clone 到 bodyBB 的绝对跳转
BranchInst::Create(bodyBB, cloneBB);
}
return PreservedAnalyses::all();
}

}; // namespace Pluto
1 change: 1 addition & 0 deletions llvm/lib/Transforms/Obfuscation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_llvm_component_library(LLVMObfuscation
MBAObfuscation.cpp
Substitution.cpp
IndirectCall.cpp
BogusControlFlow.cpp
Pipeline.cpp

LINK_COMPONENTS
Expand Down
3 changes: 0 additions & 3 deletions llvm/lib/Transforms/Obfuscation/HelloWorld.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#include "llvm/Transforms/Obfuscation/HelloWorld.h"

#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Transforms/Utils/LowerSwitch.h"

namespace Pluto {

PreservedAnalyses Pluto::HelloWorld::run(Function &F, FunctionAnalysisManager &AM) {
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Transforms/Obfuscation/IndirectCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ PreservedAnalyses Pluto::IndirectCall::run(Module &M, ModuleAnalysisManager &AM)
}
}
}

return PreservedAnalyses::all();
PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>();
return PA;
}

}; // namespace Pluto
4 changes: 3 additions & 1 deletion llvm/lib/Transforms/Obfuscation/MBAObfuscation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ PreservedAnalyses Pluto::MbaObfuscation::run(Function &F, FunctionAnalysisManage
}
}
}
return PreservedAnalyses::all();
PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>();
return PA;
}

void Pluto::MbaObfuscation::substituteConstant(Instruction *I, int i) {
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Transforms/Obfuscation/Pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "llvm/IR/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/Obfuscation/BogusControlFlow.h"
#include "llvm/Transforms/Obfuscation/Flattening.h"
#include "llvm/Transforms/Obfuscation/HelloWorld.h"
#include "llvm/Transforms/Obfuscation/IndirectCall.h"
Expand Down Expand Up @@ -29,8 +30,8 @@ ModulePassManager buildObfuscationPipeline() {
FPM.addPass(Substitution());
} else if (pass == "mba") {
FPM.addPass(MbaObfuscation());
} else if (pass == "idc") {
MPM.addPass(IndirectCall());
} else if (pass == "bcf") {
FPM.addPass(BogusControlFlow());
}
}
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/Transforms/Obfuscation/Substitution.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#include "llvm/Transforms/Obfuscation/Substitution.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Obfuscation/CryptoUtils.h"
#include "llvm/Transforms/Obfuscation/Substitution.h"
#include <vector>

using namespace llvm;
Expand All @@ -24,7 +24,9 @@ PreservedAnalyses Pluto::Substitution::run(Function &F, FunctionAnalysisManager
}
}
}
return PreservedAnalyses::all();
PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>();
return PA;
}

void Pluto::Substitution::substitute(BinaryOperator *BI) {
Expand Down
2 changes: 1 addition & 1 deletion tests/test-aes.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
cd tests/tiny-AES-c
../../install/bin/clang -O3 -flto -fuse-ld=lld -mllvm -passes=mba,fla,sub -Xlinker -mllvm -Xlinker -passes=hlw,idc test.c aes.c -o test.elf
../../install/bin/clang -O3 -flto -fuse-ld=lld -mllvm -passes=mba,sub,bcf,fla -Xlinker -mllvm -Xlinker -passes=hlw,idc test.c aes.c -o test.elf
./test.elf
2 changes: 1 addition & 1 deletion tests/test-json.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CXX=`pwd`/install/bin/clang++
CXX_FLAGS="-flto -fuse-ld=lld -O3 -mllvm -passes=mba,fla,sub -Xlinker -mllvm -Xlinker -passes=hlw,idc -Wno-unused-command-line-argument"
CXX_FLAGS="-flto -fuse-ld=lld -O3 -mllvm -passes=mba,sub,fla -Xlinker -mllvm -Xlinker -passes=hlw,idc -Wno-unused-command-line-argument"

cd tests/json
rm -rf build
Expand Down
2 changes: 1 addition & 1 deletion tests/test-jsoncpp.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CXX="`pwd`/install/bin/clang++"
CXX_FLAGS="-flto -fuse-ld=lld -O3 -mllvm -passes=mba,fla,sub -Xlinker -mllvm -Xlinker -passes=hlw,idc -Wno-unused-command-line-argument"
CXX_FLAGS="-flto -fuse-ld=lld -O3 -mllvm -passes=mba,sub,fla -Xlinker -mllvm -Xlinker -passes=hlw,idc -Wno-unused-command-line-argument"

cd tests/jsoncpp
rm -rf build
Expand Down
2 changes: 1 addition & 1 deletion tests/test-openssl.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
cd tests/openssl
CC=../../install/bin/clang CFLAGS="-flto -fuse-ld=lld -O3 -mllvm -passes=mba,fla,sub -Xlinker -mllvm -Xlinker -passes=hlw,idc -Wno-unused-command-line-argument" ./Configure
CC=../../install/bin/clang CFLAGS="-flto -fuse-ld=lld -O3 -mllvm -passes=mba,sub,bcf,fla -Xlinker -mllvm -Xlinker -passes=hlw,idc -Wno-unused-command-line-argument" ./Configure
make -j`nproc` tests

0 comments on commit 085c1be

Please sign in to comment.