Skip to content

Commit

Permalink
Add GlobalEncryption
Browse files Browse the repository at this point in the history
  • Loading branch information
bluesadi committed Jan 3, 2024
1 parent 7e81213 commit 290583b
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 5 deletions.
19 changes: 19 additions & 0 deletions llvm/include/llvm/Transforms/Obfuscation/GlobalEncryption.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include "llvm/Passes/PassBuilder.h"

using namespace llvm;

namespace Pluto {

struct GlobalEncryption : PassInfoMixin<GlobalEncryption> {
void insertArrayDecryption(Module &M, GlobalVariable *GV, uint64_t key, uint64_t eleNum);

void insertIntDecryption(Module &M, GlobalVariable *GV, uint64_t key);

PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);

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

}; // 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 @@ -7,6 +7,7 @@ add_llvm_component_library(LLVMObfuscation
Substitution.cpp
IndirectCall.cpp
BogusControlFlow.cpp
GlobalEncryption.cpp
Pipeline.cpp

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

#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Transforms/Obfuscation/CryptoUtils.h"
#include "llvm/Transforms/Utils/LowerSwitch.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include <vector>

namespace Pluto {

PreservedAnalyses GlobalEncryption::run(Module &M, ModuleAnalysisManager &AM) {
std::vector<GlobalVariable *> GVs;
for (auto &GV : M.getGlobalList()) {
if (!GV.getName().startswith("llvm.")) {
GVs.push_back(&GV);
}
}
for (auto &GV : GVs) {
if (!GV->getValueType()->isIntegerTy() &&
(!GV->getValueType()->isArrayTy() ||
!cast<ArrayType>(GV->getValueType())->getElementType()->isIntegerTy())) {
continue;
}
if (GV->hasInitializer() && GV->getInitializer() && !GV->hasSection()) {
if (ConstantDataArray *dataArray = dyn_cast<ConstantDataArray>(GV->getInitializer())) {
uint64_t eleByteSize = dataArray->getElementByteSize();
uint64_t eleNum = dataArray->getNumElements();
const char *data = dataArray->getRawDataValues().data();
uint64_t dataSize = eleByteSize * eleNum;
if (data && eleByteSize <= 8) {
char *dataCopy = new char[dataSize];
memcpy(dataCopy, data, dataSize);
uint64_t key = cryptoutils->get_uint64_t();
// A simple xor encryption
for (uint32_t i = 0; i < dataSize; i++) {
dataCopy[i] ^= ((char *)&key)[i % eleByteSize];
}
GV->setInitializer(
ConstantDataArray::getRaw(StringRef(dataCopy, dataSize), eleNum, dataArray->getElementType()));
GV->setConstant(false);
insertArrayDecryption(M, GV, key, eleNum);
}
} else if (ConstantInt *dataInt = dyn_cast<ConstantInt>(GV->getInitializer())) {
uint64_t key = cryptoutils->get_uint64_t();
ConstantInt *enc = ConstantInt::get(dataInt->getType(), key ^ dataInt->getZExtValue());
GV->setInitializer(enc);
GV->setConstant(false);
insertIntDecryption(M, GV, key);
}
}
}
return PreservedAnalyses::all();
}

static uint64_t cnt = 0;

void GlobalEncryption::insertArrayDecryption(Module &M, GlobalVariable *GV, uint64_t key, uint64_t eleNum) {
LLVMContext &context = M.getContext();
FunctionType *funcType = FunctionType::get(Type::getVoidTy(context), false);
std::string funcName = formatv("decrypt.{0:d}", cnt++);
FunctionCallee callee = M.getOrInsertFunction(funcName, funcType);
Function *func = cast<Function>(callee.getCallee());
func->setLinkage(GlobalValue::LinkageTypes::PrivateLinkage);
BasicBlock *head = BasicBlock::Create(context, "head", func);
BasicBlock *forCond = BasicBlock::Create(context, "for.cond", func);
BasicBlock *forBody = BasicBlock::Create(context, "for.body", func);
BasicBlock *forInc = BasicBlock::Create(context, "for.inc", func);
BasicBlock *forEnd = BasicBlock::Create(context, "for.inc", func);

IRBuilder<> builder(context);

builder.SetInsertPoint(head);
AllocaInst *indexPtr = builder.CreateAlloca(Type::getInt32Ty(context));
builder.CreateStore(ConstantInt::get(Type::getInt32Ty(context), 0), indexPtr);
builder.CreateBr(forCond);

builder.SetInsertPoint(forCond);
LoadInst *index = builder.CreateLoad(Type::getInt32Ty(context), indexPtr);
Value *cond = builder.CreateICmpSLT(index, ConstantInt::get(Type::getInt32Ty(context), eleNum));
builder.CreateCondBr(cond, forBody, forEnd);

builder.SetInsertPoint(forBody);

Value *elePtr = builder.CreateGEP(GV->getValueType(), GV, {ConstantInt::get(Type::getInt32Ty(context), 0), index});
Type *eleType = cast<ArrayType>(GV->getValueType())->getElementType();
builder.CreateStore(builder.CreateXor(builder.CreateLoad(eleType, elePtr), ConstantInt::get(eleType, key)), elePtr);
builder.CreateBr(forInc);

builder.SetInsertPoint(forInc);
builder.CreateStore(builder.CreateAdd(index, ConstantInt::get(Type::getInt32Ty(context), 1)), indexPtr);
builder.CreateBr(forCond);

builder.SetInsertPoint(forEnd);
builder.CreateRetVoid();

appendToGlobalCtors(M, func, 0);
}

void GlobalEncryption::insertIntDecryption(Module &M, GlobalVariable *GV, uint64_t key) {
LLVMContext &context = M.getContext();
FunctionType *funcType = FunctionType::get(Type::getVoidTy(context), false);
std::string funcName = formatv("decrypt.{0:d}", cnt++);
FunctionCallee callee = M.getOrInsertFunction(funcName, funcType);
Function *func = cast<Function>(callee.getCallee());
func->setLinkage(GlobalValue::LinkageTypes::PrivateLinkage);

BasicBlock *BB = BasicBlock::Create(context, "BB", func);

IRBuilder<> builder(context);
builder.SetInsertPoint(BB);
LoadInst *val = builder.CreateLoad(GV->getValueType(), GV);
builder.CreateStore(builder.CreateXor(val, ConstantInt::get(GV->getValueType(), key)), GV);
builder.CreateRetVoid();

appendToGlobalCtors(M, func, 0);
}

}; // namespace Pluto
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Obfuscation/MBAUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ static int8_t truthTables[15][4] = {
int64_t *MBAUtils::generateLinearMBA(int numExprs) {
#ifdef USE_CACHE
static std::queue<int64_t *> cached_coeffs;
if (cached_coeffs.size() >= 200) {
if (cached_coeffs.size() >= 50) {
int64_t *coeffs = cached_coeffs.front();
cached_coeffs.pop();
int64_t *coeffs_copy = new int64_t[15];
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/Obfuscation/Pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/Obfuscation/BogusControlFlow.h"
#include "llvm/Transforms/Obfuscation/Flattening.h"
#include "llvm/Transforms/Obfuscation/GlobalEncryption.h"
#include "llvm/Transforms/Obfuscation/HelloWorld.h"
#include "llvm/Transforms/Obfuscation/IndirectCall.h"
#include "llvm/Transforms/Obfuscation/MBAObfuscation.h"
Expand Down Expand Up @@ -36,6 +37,8 @@ ModulePassManager buildObfuscationPipeline() {
FPM.addPass(MbaObfuscation());
} else if (pass == "bcf") {
FPM.addPass(BogusControlFlow());
} else if (pass == "gle") {
MPM.addPass(GlobalEncryption());
}
}
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
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,sub,bcf,fla -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,gle -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="-O0 -flto -fuse-ld=lld -mllvm -passes=mba,sub,fla -Wno-unused-command-line-argument"
CXX_FLAGS="-O0 -flto -fuse-ld=lld -mllvm -passes=mba,sub,fla,gle -Xlinker -mllvm -Xlinker -passes=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,sub,fla,bcf -Xlinker -mllvm -Xlinker -passes=hlw,idc -Wno-unused-command-line-argument"
CXX_FLAGS="-flto -fuse-ld=lld -O3 -mllvm -passes=mba,sub,fla,bcf,gle -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,4 +1,4 @@
cd tests/openssl
CC=../../install/bin/clang CFLAGS="-O0 -mllvm -passes=mba,sub,idc,fla,bcf" ./Configure
CC=../../install/bin/clang CFLAGS="-O0 -mllvm -passes=mba,sub,idc,fla,bcf,gle" ./Configure
make clean
make -j8 tests

0 comments on commit 290583b

Please sign in to comment.