forked from GoSSIP-SJTU/Armariris
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
1,076 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#ifndef _FLATTENING_INCLUDES_ | ||
#define _FLATTENING_INCLUDES_ | ||
|
||
|
||
// LLVM include | ||
#include "llvm/Pass.h" | ||
#include "llvm/IR/Function.h" | ||
#include "llvm/ADT/Statistic.h" | ||
#include "llvm/Transforms/Utils/Local.h" // For DemoteRegToStack and DemotePHIToStack | ||
#include "llvm/Transforms/IPO.h" | ||
#include "llvm/Transforms/Scalar.h" | ||
#include "llvm/IR/Module.h" | ||
#include "llvm/Support/CommandLine.h" | ||
#include "llvm/CryptoUtils.h" | ||
#include "llvm/Transforms/Obfuscation/Utils.h" | ||
|
||
// Namespace | ||
using namespace std; | ||
|
||
namespace llvm { | ||
Pass *createFlattening(); | ||
Pass *createFlattening(bool flag); | ||
} | ||
|
||
#endif | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#ifndef _SUBSTITUTIONS_H_ | ||
#define _SUBSTITUTIONS_H_ | ||
|
||
|
||
// LLVM include | ||
#include "llvm/Pass.h" | ||
#include "llvm/IR/Function.h" | ||
#include "llvm/IR/Instructions.h" | ||
#include "llvm/ADT/Statistic.h" | ||
#include "llvm/Transforms/IPO.h" | ||
#include "llvm/IR/Module.h" | ||
#include "llvm/Support/CommandLine.h" | ||
#include "llvm/CryptoUtils.h" | ||
|
||
// Namespace | ||
using namespace llvm; | ||
using namespace std; | ||
|
||
namespace llvm { | ||
Pass *createSubstitution (); | ||
Pass *createSubstitution (bool flag); | ||
} | ||
|
||
#endif | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#ifndef __UTILS_OBF__ | ||
#define __UTILS_OBF__ | ||
|
||
#include "llvm/IR/Function.h" | ||
#include "llvm/IR/Instructions.h" | ||
#include "llvm/Transforms/Utils/Local.h" // For DemoteRegToStack and DemotePHIToStack | ||
#include <stdio.h> | ||
|
||
using namespace llvm; | ||
|
||
void fixStack(Function *f); | ||
std::string readAnnotate(Function *f); | ||
bool toObfuscate(bool flag, Function *f, std::string attribute); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
add_llvm_library(LLVMObfuscation | ||
CryptoUtils.cpp | ||
StringObfuscation.cpp | ||
Substitution.cpp | ||
Flattening.cpp | ||
Utils.cpp | ||
) | ||
|
||
add_dependencies(LLVMObfuscation intrinsics_gen) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
#include "llvm/Transforms/Obfuscation/Flattening.h" | ||
#include "llvm/Transforms/Scalar.h" | ||
#include "llvm/CryptoUtils.h" | ||
|
||
#define DEBUG_TYPE "flattening" | ||
|
||
using namespace llvm; | ||
|
||
// Stats | ||
STATISTIC(Flattened, "Functions flattened"); | ||
|
||
static cl::opt<string> FunctionName( | ||
"funcFLA", cl::init(""), | ||
cl::desc( | ||
"Flatten only certain functions: -mllvm -funcFLA=\"func1,func2\"")); | ||
|
||
static cl::opt<int> Percentage( | ||
"perFLA", cl::init(100), | ||
cl::desc("Flatten only a certain percentage of functions")); | ||
|
||
namespace { | ||
struct Flattening : public FunctionPass { | ||
static char ID; // Pass identification, replacement for typeid | ||
bool flag; | ||
|
||
Flattening() : FunctionPass(ID) {} | ||
Flattening(bool flag) : FunctionPass(ID) { | ||
this->flag = flag; | ||
// Check if the number of applications is correct | ||
if ( !((Percentage > 0) && (Percentage <= 100)) ) { | ||
LLVMContext ctx; | ||
ctx.emitError(Twine ("Flattening application function percentage -perFLA=x must be 0 < x <= 100")); | ||
} | ||
} | ||
|
||
bool runOnFunction(Function &F); | ||
bool flatten(Function *f); | ||
}; | ||
} | ||
|
||
char Flattening::ID = 0; | ||
static RegisterPass<Flattening> X("flattening", "Call graph flattening"); | ||
Pass *llvm::createFlattening(bool flag) { return new Flattening(flag); } | ||
|
||
bool Flattening::runOnFunction(Function &F) { | ||
Function *tmp = &F; | ||
|
||
// Do we obfuscate | ||
if (toObfuscate(flag, tmp, "fla") && ((int)llvm::cryptoutils->get_range(100) <= Percentage)) { | ||
//errs() << "fla " + F.getName() +"\n"; | ||
if (flatten(tmp)) { | ||
++Flattened; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
bool Flattening::flatten(Function *f) { | ||
vector<BasicBlock *> origBB; | ||
BasicBlock *loopEntry; | ||
BasicBlock *loopEnd; | ||
LoadInst *load; | ||
SwitchInst *switchI; | ||
AllocaInst *switchVar; | ||
|
||
// SCRAMBLER | ||
char scrambling_key[16]; | ||
llvm::cryptoutils->get_bytes(scrambling_key, 16); | ||
// END OF SCRAMBLER | ||
|
||
// Lower switch | ||
FunctionPass *lower = createLowerSwitchPass(); | ||
lower->runOnFunction(*f); | ||
|
||
// Save all original BB | ||
for (Function::iterator i = f->begin(); i != f->end(); ++i) { | ||
BasicBlock *tmp = &*i; | ||
origBB.push_back(tmp); | ||
|
||
BasicBlock *bb = &*i; | ||
if (isa<InvokeInst>(bb->getTerminator())) { | ||
return false; | ||
} | ||
} | ||
|
||
// Nothing to flatten | ||
if (origBB.size() <= 1) { | ||
return false; | ||
} | ||
|
||
// Remove first BB | ||
origBB.erase(origBB.begin()); | ||
|
||
// Get a pointer on the first BB | ||
Function::iterator tmp = f->begin(); //++tmp; | ||
BasicBlock *insert = &*tmp; | ||
|
||
// If main begin with an if | ||
BranchInst *br = NULL; | ||
if (isa<BranchInst>(insert->getTerminator())) { | ||
br = cast<BranchInst>(insert->getTerminator()); | ||
} | ||
|
||
if ((br != NULL && br->isConditional()) || | ||
insert->getTerminator()->getNumSuccessors() > 1) { | ||
BasicBlock::iterator i = insert->back().getIterator(); | ||
|
||
if (insert->size() > 1) { | ||
i--; | ||
} | ||
|
||
BasicBlock *tmpBB = insert->splitBasicBlock(i, "first"); | ||
origBB.insert(origBB.begin(), tmpBB); | ||
} | ||
|
||
// Remove jump | ||
insert->getTerminator()->eraseFromParent(); | ||
|
||
// Create switch variable and set as it | ||
switchVar = | ||
new AllocaInst(Type::getInt32Ty(f->getContext()), 0, "switchVar", insert); | ||
new StoreInst( | ||
ConstantInt::get(Type::getInt32Ty(f->getContext()), | ||
llvm::cryptoutils->scramble32(0, scrambling_key)), | ||
switchVar, insert); | ||
|
||
// Create main loop | ||
loopEntry = BasicBlock::Create(f->getContext(), "loopEntry", f, insert); | ||
loopEnd = BasicBlock::Create(f->getContext(), "loopEnd", f, insert); | ||
|
||
load = new LoadInst(switchVar, "switchVar", loopEntry); | ||
|
||
// Move first BB on top | ||
insert->moveBefore(loopEntry); | ||
BranchInst::Create(loopEntry, insert); | ||
|
||
// loopEnd jump to loopEntry | ||
BranchInst::Create(loopEntry, loopEnd); | ||
|
||
BasicBlock *swDefault = | ||
BasicBlock::Create(f->getContext(), "switchDefault", f, loopEnd); | ||
BranchInst::Create(loopEnd, swDefault); | ||
|
||
// Create switch instruction itself and set condition | ||
switchI = SwitchInst::Create(&*(f->begin()), swDefault, 0, loopEntry); | ||
switchI->setCondition(load); | ||
|
||
// Remove branch jump from 1st BB and make a jump to the while | ||
f->begin()->getTerminator()->eraseFromParent(); | ||
|
||
BranchInst::Create(loopEntry, &*(f->begin())); | ||
|
||
// Put all BB in the switch | ||
for (vector<BasicBlock *>::iterator b = origBB.begin(); b != origBB.end(); | ||
++b) { | ||
BasicBlock *i = *b; | ||
ConstantInt *numCase = NULL; | ||
|
||
// Move the BB inside the switch (only visual, no code logic) | ||
i->moveBefore(loopEnd); | ||
|
||
// Add case to switch | ||
numCase = cast<ConstantInt>(ConstantInt::get( | ||
switchI->getCondition()->getType(), | ||
llvm::cryptoutils->scramble32(switchI->getNumCases(), scrambling_key))); | ||
switchI->addCase(numCase, i); | ||
} | ||
|
||
// Recalculate switchVar | ||
for (vector<BasicBlock *>::iterator b = origBB.begin(); b != origBB.end(); | ||
++b) { | ||
BasicBlock *i = *b; | ||
ConstantInt *numCase = NULL; | ||
|
||
// Ret BB | ||
if (i->getTerminator()->getNumSuccessors() == 0) { | ||
continue; | ||
} | ||
|
||
// If it's a non-conditional jump | ||
if (i->getTerminator()->getNumSuccessors() == 1) { | ||
// Get successor and delete terminator | ||
BasicBlock *succ = i->getTerminator()->getSuccessor(0); | ||
i->getTerminator()->eraseFromParent(); | ||
|
||
// Get next case | ||
numCase = switchI->findCaseDest(succ); | ||
|
||
// If next case == default case (switchDefault) | ||
if (numCase == NULL) { | ||
numCase = cast<ConstantInt>( | ||
ConstantInt::get(switchI->getCondition()->getType(), | ||
llvm::cryptoutils->scramble32( | ||
switchI->getNumCases() - 1, scrambling_key))); | ||
} | ||
|
||
// Update switchVar and jump to the end of loop | ||
new StoreInst(numCase, load->getPointerOperand(), i); | ||
BranchInst::Create(loopEnd, i); | ||
continue; | ||
} | ||
|
||
// If it's a conditional jump | ||
if (i->getTerminator()->getNumSuccessors() == 2) { | ||
// Get next cases | ||
ConstantInt *numCaseTrue = | ||
switchI->findCaseDest(i->getTerminator()->getSuccessor(0)); | ||
ConstantInt *numCaseFalse = | ||
switchI->findCaseDest(i->getTerminator()->getSuccessor(1)); | ||
|
||
// Check if next case == default case (switchDefault) | ||
if (numCaseTrue == NULL) { | ||
numCaseTrue = cast<ConstantInt>( | ||
ConstantInt::get(switchI->getCondition()->getType(), | ||
llvm::cryptoutils->scramble32( | ||
switchI->getNumCases() - 1, scrambling_key))); | ||
} | ||
|
||
if (numCaseFalse == NULL) { | ||
numCaseFalse = cast<ConstantInt>( | ||
ConstantInt::get(switchI->getCondition()->getType(), | ||
llvm::cryptoutils->scramble32( | ||
switchI->getNumCases() - 1, scrambling_key))); | ||
} | ||
|
||
// Create a SelectInst | ||
BranchInst *br = cast<BranchInst>(i->getTerminator()); | ||
SelectInst *sel = | ||
SelectInst::Create(br->getCondition(), numCaseTrue, numCaseFalse, "", | ||
i->getTerminator()); | ||
|
||
// Erase terminator | ||
i->getTerminator()->eraseFromParent(); | ||
|
||
// Update switchVar and jump to the end of loop | ||
new StoreInst(sel, load->getPointerOperand(), i); | ||
BranchInst::Create(loopEnd, i); | ||
continue; | ||
} | ||
} | ||
|
||
fixStack(f); | ||
|
||
return true; | ||
} |
Oops, something went wrong.