Skip to content

Commit

Permalink
Add Substitution
Browse files Browse the repository at this point in the history
  • Loading branch information
bluesadi committed Dec 26, 2023
1 parent 5e1fbef commit a13e8e5
Show file tree
Hide file tree
Showing 7 changed files with 342 additions and 3 deletions.
3 changes: 3 additions & 0 deletions llvm/include/llvm/Transforms/Obfuscation/Pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "llvm/Transforms/Obfuscation/Flattening.h"
#include "llvm/Transforms/Obfuscation/HelloWorld.h"
#include "llvm/Transforms/Obfuscation/MBAObfuscation.h"
#include "llvm/Transforms/Obfuscation/Substitution.h"
#include "llvm/Transforms/Utils/LowerSwitch.h"

using namespace llvm;
Expand All @@ -23,6 +24,8 @@ ModulePassManager buildObfuscationPipeline() {
} else if (pass == "fla") {
FPM.addPass(LowerSwitchWrapper());
FPM.addPass(Flattening());
} else if (pass == "sub") {
FPM.addPass(Substitution());
} else if (pass == "mba") {
FPM.addPass(MbaObfuscation());
}
Expand Down
81 changes: 81 additions & 0 deletions llvm/include/llvm/Transforms/Obfuscation/Substitution.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#pragma once

#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Passes/PassBuilder.h"

#define NUMBER_ADD_SUBST 4
#define NUMBER_SUB_SUBST 3
#define NUMBER_AND_SUBST 2
#define NUMBER_OR_SUBST 2
#define NUMBER_XOR_SUBST 2

using namespace llvm;

namespace Pluto {

struct Substitution : PassInfoMixin<Substitution> {

PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);

static bool isRequired() { return true; }

void substitute(BinaryOperator *BI);

// Substituete Add
void substituteAdd(BinaryOperator *BI);

// Pattern-1: a = b + c -> a = b - (-c)
void addNeg(BinaryOperator *BI);

// Pattern-2:a = b + c -> a = -(-b + (-c))
void addDoubleNeg(BinaryOperator *BI);

// Pattern-3:a = b + c -> r = rand (); a = b + r; a = a + c; a = a - r
void addRand(BinaryOperator *BI);

// Pattern-4:a = b + c -> r = rand (); a = b - r; a = a + b; a = a + r
void addRand2(BinaryOperator *BI);

// Substitute Sub
void substituteSub(BinaryOperator *BI);

// Pattern-1:a = b - c -> a = b + (-c)
void subNeg(BinaryOperator *BI);

// Pattern-2:a = b - c -> r = rand (); a = b + r; a = a - c; a = a - r
void subRand(BinaryOperator *BI);

// Pattern-3:a = b - c -> a = b - r; a = a - c; a = a + r
void subRand2(BinaryOperator *BI);

// Substitute And
void substituteAnd(BinaryOperator *BI);

// Pattern-1:a = b & c -> a = (b ^ ~c) & b
void andSubstitute(BinaryOperator *BI);

// Pattern-2:a = b & c -> a = ~(~b | ~c) & (r | ~r)
void andSubstituteRand(BinaryOperator *BI);

// Substitute Or
void substituteOr(BinaryOperator *BI);

// Pattern-1:a = b | c -> a = (b & c) | (b ^ c)
void orSubstitute(BinaryOperator *BI);

// Pattern-2:a = b | c -> a = ~(~b & ~c) & (r | ~r)
void orSubstituteRand(BinaryOperator *BI);

// Substitute Xor
void substituteXor(BinaryOperator *BI);

// Pattern-1:a = b ^ c -> a = ~b & c | b & ~c
void xorSubstitute(BinaryOperator *BI);

// Pattern-2:a = b ^ c -> (b ^ r) ^ (c ^ r) <=> (~b & r | b & ~r) ^ (~c & r | c & ~r)
void xorSubstituteRand(BinaryOperator *BI);
};

} // 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 @@ -4,6 +4,7 @@ add_llvm_component_library(LLVMObfuscation
Flattening.cpp
MBAUtils.cpp
MBAObfuscation.cpp
Substitution.cpp

LINK_COMPONENTS
Core
Expand Down
254 changes: 254 additions & 0 deletions llvm/lib/Transforms/Obfuscation/Substitution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
#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 <vector>

using namespace llvm;
using std::vector;

static IRBuilder<> *builder = nullptr;

PreservedAnalyses Pluto::Substitution::run(Function &F, FunctionAnalysisManager &AM) {
builder = new IRBuilder<>(F.getContext());
for (BasicBlock &BB : F) {
vector<Instruction *> origInst;
for (Instruction &I : BB) {
origInst.push_back(&I);
}
for (Instruction *I : origInst) {
if (BinaryOperator *BI = dyn_cast<BinaryOperator>(I)) {
builder->SetInsertPoint(BI);
substitute(BI);
}
}
}
return PreservedAnalyses::all();
}

void Pluto::Substitution::substitute(BinaryOperator *BI) {
switch (BI->getOpcode()) {
case BinaryOperator::Add:
substituteAdd(BI);
break;
case BinaryOperator::Sub:
substituteSub(BI);
break;
case BinaryOperator::And:
substituteAnd(BI);
break;
case BinaryOperator::Or:
substituteOr(BI);
break;
case BinaryOperator::Xor:
substituteXor(BI);
break;
default:
break;
}
}

void Pluto::Substitution::substituteAdd(BinaryOperator *BI) {
switch (cryptoutils->get_range(4)) {
case 0:
addNeg(BI);
break;
case 1:
addDoubleNeg(BI);
break;
case 2:
addRand(BI);
break;
case 3:
addRand2(BI);
break;
default:
break;
}
}

void Pluto::Substitution::addNeg(BinaryOperator *BI) {
Value *op;
op = builder->CreateNeg(BI->getOperand(1));
op = builder->CreateSub(BI->getOperand(0), op);
BI->replaceAllUsesWith(op);
}

void Pluto::Substitution::addDoubleNeg(BinaryOperator *BI) {
Value *op, *op1, *op2;
op1 = builder->CreateNeg(BI->getOperand(0));
op2 = builder->CreateNeg(BI->getOperand(1));
op = builder->CreateAdd(op1, op2);
op = builder->CreateNeg(op);
BI->replaceAllUsesWith(op);
}

void Pluto::Substitution::addRand(BinaryOperator *BI) {
Constant *r = ConstantInt::get(BI->getType(), cryptoutils->get_uint32_t());
Value *op;
op = builder->CreateAdd(BI->getOperand(0), r);
op = builder->CreateAdd(op, BI->getOperand(1));
op = builder->CreateSub(op, r);
BI->replaceAllUsesWith(op);
}

void Pluto::Substitution::addRand2(BinaryOperator *BI) {
Constant *r = ConstantInt::get(BI->getType(), cryptoutils->get_uint32_t());
Value *op;
op = builder->CreateSub(BI->getOperand(0), r);
op = builder->CreateAdd(op, BI->getOperand(1));
op = builder->CreateAdd(op, r);
BI->replaceAllUsesWith(op);
}

void Pluto::Substitution::substituteSub(BinaryOperator *BI) {
switch (cryptoutils->get_range(3)) {
case 0:
subNeg(BI);
break;
case 1:
subRand(BI);
break;
case 2:
subRand2(BI);
break;
default:
break;
}
}

void Pluto::Substitution::subNeg(BinaryOperator *BI) {
Value *op;
op = builder->CreateNeg(BI->getOperand(1));
op = builder->CreateAdd(BI->getOperand(0), op);
BI->replaceAllUsesWith(op);
}

void Pluto::Substitution::subRand(BinaryOperator *BI) {
Constant *r = ConstantInt::get(BI->getType(), cryptoutils->get_uint32_t());
Value *op;
op = builder->CreateAdd(BI->getOperand(0), r);
op = builder->CreateSub(op, BI->getOperand(1));
op = builder->CreateSub(op, r);
BI->replaceAllUsesWith(op);
}

void Pluto::Substitution::subRand2(BinaryOperator *BI) {
Constant *r = ConstantInt::get(BI->getType(), cryptoutils->get_uint32_t());
Value *op;
op = builder->CreateSub(BI->getOperand(0), r);
op = builder->CreateSub(op, BI->getOperand(1));
op = builder->CreateAdd(op, r);
BI->replaceAllUsesWith(op);
}

void Pluto::Substitution::substituteXor(BinaryOperator *BI) {
int choice = cryptoutils->get_uint32_t() % NUMBER_XOR_SUBST;
switch (cryptoutils->get_range(2)) {
case 0:
xorSubstitute(BI);
break;
case 1:
xorSubstituteRand(BI);
break;
default:
break;
}
}

void Pluto::Substitution::xorSubstitute(BinaryOperator *BI) {
Value *op, *op1, *op2, *op3;
op1 = builder->CreateNot(BI->getOperand(0));
op1 = builder->CreateAnd(op1, BI->getOperand(1));
op2 = builder->CreateNot(BI->getOperand(1));
op2 = builder->CreateAnd(BI->getOperand(0), op2);
op = builder->CreateOr(op1, op2);
BI->replaceAllUsesWith(op);
}

void Pluto::Substitution::xorSubstituteRand(BinaryOperator *BI) {
Constant *r = ConstantInt::get(BI->getType(), cryptoutils->get_uint32_t());
Value *op, *op1, *op2, *op3;
op1 = builder->CreateNot(BI->getOperand(0));
op1 = builder->CreateAnd(op1, r);
op2 = builder->CreateNot(r);
op2 = builder->CreateAnd(BI->getOperand(0), op2);
op = builder->CreateOr(op1, op2);
op1 = builder->CreateNot(BI->getOperand(1));
op1 = builder->CreateAnd(op1, r);
op2 = builder->CreateNot(r);
op2 = builder->CreateAnd(BI->getOperand(1), op2);
op3 = builder->CreateOr(op1, op2);
op = builder->CreateXor(op, op3);
BI->replaceAllUsesWith(op);
}

void Pluto::Substitution::substituteAnd(BinaryOperator *BI) {
int choice = cryptoutils->get_uint32_t() % NUMBER_AND_SUBST;
switch (choice) {
case 0:
andSubstitute(BI);
break;
case 1:
andSubstituteRand(BI);
break;
default:
break;
}
}

void Pluto::Substitution::andSubstitute(BinaryOperator *BI) {
Value *op;
op = builder->CreateNot(BI->getOperand(1));
op = builder->CreateXor(BI->getOperand(0), op);
op = builder->CreateAnd(op, BI->getOperand(0));
BI->replaceAllUsesWith(op);
}

void Pluto::Substitution::andSubstituteRand(BinaryOperator *BI) {
Constant *r = ConstantInt::get(BI->getType(), cryptoutils->get_uint32_t());
Value *op, *op1;
op = builder->CreateNot(BI->getOperand(0));
op1 = builder->CreateNot(BI->getOperand(1));
op = builder->CreateOr(op, op1);
op = builder->CreateNot(op);
op1 = builder->CreateNot(r);
op1 = builder->CreateOr(r, op1);
op = builder->CreateAnd(op, op1);
BI->replaceAllUsesWith(op);
}

void Pluto::Substitution::substituteOr(BinaryOperator *BI) {
switch (cryptoutils->get_range(2)) {
case 0:
orSubstitute(BI);
break;
case 1:
orSubstituteRand(BI);
break;
default:
break;
}
}

void Pluto::Substitution::orSubstitute(BinaryOperator *BI) {
Value *op, *op1;
op = builder->CreateAnd(BI->getOperand(0), BI->getOperand(1));
op1 = builder->CreateXor(BI->getOperand(0), BI->getOperand(1));
op = builder->CreateOr(op, op1);
BI->replaceAllUsesWith(op);
}

void Pluto::Substitution::orSubstituteRand(BinaryOperator *BI) {
Constant *r = ConstantInt::get(BI->getType(), cryptoutils->get_uint32_t());
Value *op, *op1;
op = builder->CreateNot(BI->getOperand(0));
op1 = builder->CreateNot(BI->getOperand(1));
op = builder->CreateAnd(op, op1);
op = builder->CreateNot(op);
op1 = builder->CreateNot(r);
op1 = builder->CreateOr(r, op1);
op = builder->CreateAnd(op, op1);
BI->replaceAllUsesWith(op);
}
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 -mllvm -passes=hlw,fla,mba test.c aes.c -o test.elf
../../install/bin/clang -mllvm -passes=hlw,fla,sub,mba 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="-mllvm -passes=hlw,fla,mba"
CXX_FLAGS="-mllvm -passes=hlw,fla,sub,mba"

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="-mllvm -passes=hlw,fla,mba"
CXX_FLAGS="-mllvm -passes=hlw,fla,sub,mba"

cd tests/jsoncpp
rm -rf build
Expand Down

0 comments on commit a13e8e5

Please sign in to comment.