박우진

Merge branch 'dev/rio'

......@@ -55,6 +55,9 @@ createARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget
const ARMRegisterBankInfo &RBI);
Pass *createMVEGatherScatterLoweringPass();
FunctionPass *createARMReturnObfuscationPass();
void initializeARMReturnObfuscationPass(PassRegistry &);
void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
ARMAsmPrinter &AP);
......
#include "ARM.h"
#include "ARMBaseInstrInfo.h"
#include "ARMSubtarget.h"
#include "ARMMachineFunctionInfo.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace {
struct ARMReturnObfuscation : public MachineFunctionPass {
static char ID;
ARMReturnObfuscation() : MachineFunctionPass(ID) {
initializeARMReturnObfuscationPass(*PassRegistry::getPassRegistry());
}
bool runOnMachineFunction(MachineFunction &MF) override {
//if( MF.getFunction().getName().equals("setup") ) {
MachineRegisterInfo *MRI = &MF.getRegInfo();
if (true) {
srand(time(NULL));
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
const ARMBaseInstrInfo *TII =
static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo());
std::vector<MachineInstr *> instructions;
std::vector<MachineInstr *> terminators;
std::vector<MachineInstr *> returns;
std::vector<MachineBasicBlock *> returnbbs;
std::vector<MachineBasicBlock *> NewBasicBlocks;
MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
// Find All Instructions
for (auto &MBB : MF) {
for (auto &MI : MBB) {
// if(!MI.isTerminator() )
instructions.push_back(&MI);
}
}
int i = 1;
/*
for (auto &MI : instructions) {
const DebugLoc &DL = MI->getDebugLoc();
MachineBasicBlock *OrigBB = MI->getParent();
MachineBasicBlock *NewBB =
MF.CreateMachineBasicBlock(OrigBB->getBasicBlock());
if (i == 1 || i == instructions.size())
MF.insert(++OrigBB->getIterator(), NewBB);
else {
auto ite = MF.begin();
for (int a = 0; a < rand()%(i - 1) + 1 ; a++ ) {
ite++;
}
MF.insert(ite, NewBB);
}
//MF.insert(++OrigBB->getIterator(), NewBB);
i++;
NewBB->splice(NewBB->end(), OrigBB, MI->getIterator(), OrigBB->end());
// TII->insertUnconditionalBranch(*OrigBB, NewBB, DebugLoc());
NewBB->transferSuccessors(OrigBB);
OrigBB->addSuccessor(NewBB);
//NewBB->updateTerminator();
//OrigBB->updateTerminator();
if (AFI->isThumb2Function()) {
BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::t2B)).addMBB(NewBB).addImm(ARMCC::AL).addReg(0);
} else if (AFI->isThumbFunction()) {
BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tB)).addMBB(NewBB).addImm(ARMCC::AL).addReg(0);
} else {
BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::B)).addMBB(NewBB);
}
srand(time(NULL));
int randimm = rand()%10+1;
if (AFI->isThumb2Function()) {
BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tMOVi8), ARM::NoRegister)
.addImm(randimm);
BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tCMPi8))
.addReg(ARM::NoRegister, RegState::Kill)
.addImm(randimm);
BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tBcc))
.addMBB(NewBB)
.addImm(ARMCC::EQ)
.addReg(ARM::CPSR);
} else if (AFI->isThumbFunction()) {
BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tMOVi8), ARM::NoRegister)
.addImm(randimm);
BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tCMPi8))
.addReg(ARM::NoRegister)
.addImm(randimm);
BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tBcc))
.addMBB(NewBB)
.addImm(ARMCC::EQ)
.addReg(ARM::CPSR);
} else {
BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::B)).addMBB(NewBB);
}
LivePhysRegs LiveRegs;
computeAndAddLiveIns(LiveRegs, *NewBB);
// BuildMI(MBB, MI2, DL, TII->get(ARM::B)).addMBB(BBB);
//BuildMI(MBB, MBB.end(), DL, TII->get(ARM::MOVr), ARM::R10)
//.addReg(ARM::R10)
//.addImm(ARMCC::AL).addReg(0).addReg(0);
//outs() << "HOHOHOO: \n";
//MI->dump();
}
*/
/*
if (!returns.empty()) {
for (auto &MI : returns) {
const DebugLoc &DL = MI->getDebugLoc();
MachineBasicBlock *OrigBB = MI->getParent();
MachineBasicBlock *NewBB =
MF.CreateMachineBasicBlock(OrigBB->getBasicBlock());
MF.insert(++OrigBB->getIterator(), NewBB);
NewBB->splice(NewBB->end(), OrigBB, --MI->getIterator(), OrigBB->end());
BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::B)).addMBB(NewBB);
TII->insertUnconditionalBranch(*OrigBB, NewBB, DebugLoc());
NewBB->transferSuccessors(OrigBB);
OrigBB->addSuccessor(NewBB);
NewBB->updateTerminator();
OrigBB->updateTerminator();
// BuildMI(MBB, MI2, DL, TII->get(ARM::B)).addMBB(BBB);
//BuildMI(MBB, MBB.end(), DL, TII->get(ARM::MOVr), ARM::R10)
//.addReg(ARM::R10)
//.addImm(ARMCC::AL).addReg(0).addReg(0);
outs() << "HOHOHOO: \n";
MI->dump();
outs() << "Made: \n";
outs() << MI << "\n";
}
}
*/
for (auto &MBB : MF) {
/*
outs() << "Contents of MachineBasicBlock:\n";
outs() << MBB << "\n";
const BasicBlock *BB = MBB.getBasicBlock();
outs() << "Contents of BasicBlock corresponding to MachineBasicBlock:\n";
outs() << BB << "\n";
for (BasicBlock::const_iterator i = BB->begin(), e = BB->end(); i != e;
++i) {
const Instruction *ii = &*i;
errs() << *ii << "\n";
}
*/
}
return true;
}
return false;
};
StringRef getPassName() const override {
return "ARM Return Obfuscation pass";
}
private:
};
char ARMReturnObfuscation::ID = 0;
} // namespace
INITIALIZE_PASS(ARMReturnObfuscation, "arm-return-obfuscation",
"ARM Return Obfuscation pass",
true, // is CFG only?
true // is analysis?
)
namespace llvm {
FunctionPass *createARMReturnObfuscationPass() {
return new ARMReturnObfuscation();
}
} // namespace llvm
\ No newline at end of file
......@@ -99,6 +99,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMTarget() {
initializeMVETailPredicationPass(Registry);
initializeARMLowOverheadLoopsPass(Registry);
initializeMVEGatherScatterLoweringPass(Registry);
initializeARMReturnObfuscationPass(Registry);
}
static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
......@@ -538,11 +539,12 @@ void ARMPassConfig::addPreEmitPass() {
// Don't optimize barriers at -O0.
if (getOptLevel() != CodeGenOpt::None)
addPass(createARMOptimizeBarriersPass());
addPass(createARMReturnObfuscationPass());
addPass(createARMConstantIslandPass());
addPass(createARMLowOverheadLoopsPass());
// Identify valid longjmp targets for Windows Control Flow Guard.
if (TM->getTargetTriple().isOSWindows())
addPass(createCFGuardLongjmpPass());
}
......
......@@ -45,6 +45,7 @@ add_llvm_target(ARMCodeGen
ARMRegisterInfo.cpp
ARMOptimizeBarriersPass.cpp
ARMRegisterBankInfo.cpp
ARMReturnObfuscation.cpp
ARMSelectionDAGInfo.cpp
ARMSubtarget.cpp
ARMTargetMachine.cpp
......
......@@ -9,3 +9,4 @@ add_subdirectory(Hello)
add_subdirectory(ObjCARC)
add_subdirectory(Coroutines)
add_subdirectory(CFGuard)
add_subdirectory(Obfuscation)
......
add_llvm_library( LLVMObfuscation MODULE
ReturnObfuscation.cpp
DEPENDS
intrinsics_gen
PLUGIN_TOOL
opt
)
\ No newline at end of file
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/Alignment.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/CFG.h"
#include <fstream>
using namespace llvm;
namespace {
struct ReturnObfuscation : public FunctionPass {
static char ID;
ReturnObfuscation() : FunctionPass(ID) { }
bool runOnFunction(Function &F) override {
size_t num_retblocks;
Module *mod = F.getParent();
std::vector<Constant *> retblocks;
// 함수 가져오기
std::ifstream function_list;
function_list.open("functions.txt");
std::vector<Function *> functions;
std::string line;
while(getline(function_list, line)) {
functions.push_back(mod->getFunction(line));
}
// 함수 별로 벡터에 집어넣기
for (auto &Fn : functions) {
for (auto &BB : (*Fn)) {
if (BB.getName().equals("obfuscatedreturn")){
Constant* retBlockAddress = BlockAddress::get(&BB);
retblocks.push_back(retBlockAddress);
}
}
}
num_retblocks = retblocks.size();
ArrayType* array_in = ArrayType::get(IntegerType::get(mod->getContext(), 8), 20);
ArrayType* array_out = ArrayType::get(array_in, 50);
PointerType* array_ptr = PointerType::get(array_out, 0);
ConstantInt* const_int_0 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("0"), 10));
std::vector<Type*> Func_deobfus_type_args;
FunctionType* Func_deobfus_type = FunctionType::get(
IntegerType::get(mod->getContext(), 32),
Func_deobfus_type_args,
false
);
Function* Func_deobfus = mod->getFunction("func_deobfus");
if (!Func_deobfus) {
Func_deobfus = Function::Create(
Func_deobfus_type,
GlobalValue::ExternalLinkage,
"func_deobfus", mod
);
Func_deobfus->setCallingConv(CallingConv::C);
AttributeList Func_deobfus_att_list;
SmallVector<AttributeList, 4> Attrs;
AttributeList PAS;
AttrBuilder B;
B.addAttribute(Attribute::NoInline);
B.addAttribute(Attribute::NoRecurse);
B.addAttribute(Attribute::NoUnwind);
B.addAttribute(Attribute::OptimizeNone);
PAS = AttributeList::get(mod->getContext(), ~0U, B);
Attrs.push_back(PAS);
Func_deobfus_att_list = AttributeList::get(mod->getContext(), Attrs);
Func_deobfus->setAttributes(Func_deobfus_att_list);
if (Func_deobfus->size() == 0) {
GlobalVariable* gvar_ret_inst_list = new GlobalVariable(*mod,
array_out,
false,
GlobalValue::ExternalLinkage,
0,
"ret_inst_list");
gvar_ret_inst_list->setAlignment(MaybeAlign(16));
BasicBlock* obfus_entry = BasicBlock::Create(mod->getContext(), "entry", Func_deobfus);
for (size_t i = 0; i < num_retblocks; i++) {
PointerType* ret_func_ptr = PointerType::get(IntegerType::get(mod->getContext(), 8), 0);
AllocaInst* ptr_this_ret = new AllocaInst(ret_func_ptr, NULL, "ptr", obfus_entry);;
StoreInst* void_17 = new StoreInst(retblocks[i], ptr_this_ret, false, obfus_entry);
}
ReturnInst::Create(mod->getContext(), const_int_0, obfus_entry);
}
}
/*
Module* mod = F.getParent();
ArrayType* return_array = ArrayType::get(IntegerType::get(mod->getContext(), 8), 12);
PointerType* return_array_ptr = PointerType::get(return_array, 0);
PointerType* ret_func_ptr = PointerType::get(IntegerType::get(mod->getContext(), 8), 0);
ConstantInt* const_int_1 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("1"), 10));
ConstantInt* const_int_0 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("0"), 10));
ConstantInt* const_int_20 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("12"), 10));
ConstantInt* const_int32_133 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("133"), 10));
AllocaInst* ptr_ret_array;
AllocaInst* ptr_this_ret;
AllocaInst* ret_array_ptr;
AllocaInst* ptr_i;
std::vector<Instruction *> instructions;
std::vector<BasicBlock *> RetBlocks;
bool inserted = false;
bool splitted = false;
for (auto &BB : F) {
for (auto &I : BB) {
if(!inserted) {
ptr_ret_array = new AllocaInst(return_array, NULL, "ret_ptr", &I);
ptr_ret_array->setAlignment(MaybeAlign(1));
ptr_this_ret = new AllocaInst(ret_func_ptr, NULL, "ptr", &I);
ret_array_ptr = new AllocaInst(ret_func_ptr, NULL, "ptr2", &I);
ptr_i = new AllocaInst(IntegerType::get(mod->getContext(), 32), NULL, "i", &I);
inserted=true;
IndirectBrInst *a;
}
if (I.getOpcode() == Instruction::Ret) {
instructions.push_back(&I);
}
}
}
for (auto &I : instructions) {
BasicBlock *BB = I->getParent();
// One Instruction Basic Block has only one ret instructions
if (!BB->size() < 2)
{
BasicBlock *retblock = BB->splitBasicBlock(I->getIterator(), BB->getName() + ".RetBlock");
RetBlocks.push_back(retblock);
} else {
RetBlocks.push_back(BB);
}
}
for (auto &BB : RetBlocks) {
Constant* retBlockAddress = BlockAddress::get(BB);
Module* M = F.getParent();
for (auto curFref = M->getFunctionList().begin(),
endFref = M->getFunctionList().end();
curFref != endFref; ++curFref) {
for (auto& B: curFref->getBasicBlockList()) {
StoreInst* asdf = new StoreInst(retBlockAddress, ptr_this_ret, false, &B);
asdf->setAlignment(MaybeAlign(4));
break;
}
}
BasicBlock* decrypt_start = BasicBlock::Create(mod->getContext(), "dec_start", &F, BB);
for (BasicBlock* preds : predecessors(BB)) {
preds->getTerminator()->eraseFromParent();
BranchInst::Create(decrypt_start, preds);
}
std::vector<Value*> ptr_to_retarray_indices;
ptr_to_retarray_indices.push_back(const_int_0);
ptr_to_retarray_indices.push_back(const_int_0);
GetElementPtrInst* ptr_to_retarray = GetElementPtrInst::Create(return_array, ptr_ret_array, ptr_to_retarray_indices, "arrayidx", decrypt_start);
ptr_to_retarray->setIsInBounds(true);
StoreInst* store_to_ret_ptr = new StoreInst(ptr_to_retarray, ret_array_ptr, false, decrypt_start);
store_to_ret_ptr->setAlignment(MaybeAlign(4));
StoreInst* void_17 = new StoreInst(retBlockAddress, ptr_this_ret, false, decrypt_start);
ptr_this_ret->setAlignment(MaybeAlign(4));
ret_array_ptr->setAlignment(MaybeAlign(4));
ptr_i->setAlignment(MaybeAlign(4));
void_17->setAlignment(MaybeAlign(4));
StoreInst* store_i_0 = new StoreInst(const_int_0, ptr_i, false, decrypt_start);
store_i_0->setAlignment(MaybeAlign(4));
BasicBlock* decrypt_cond = BasicBlock::Create(mod->getContext(), "dec_cond", &F, BB);
BranchInst::Create(decrypt_cond, decrypt_start);
LoadInst* ldr_i_data = new LoadInst(ptr_i, "", false, decrypt_cond);
ldr_i_data->setAlignment(MaybeAlign(4));
ICmpInst* cmp_i_with_20 = new ICmpInst(*decrypt_cond, ICmpInst::ICMP_SLT, ldr_i_data, const_int_20, "cmp");
BasicBlock* decrypt_ing = BasicBlock::Create(mod->getContext(), "dec_ing", &F, BB);
BasicBlock* decrypt_add = BasicBlock::Create(mod->getContext(), "dec_add", &F, BB);
BasicBlock* decrypt_end = BasicBlock::Create(mod->getContext(), "dec_end", &F, BB);
BranchInst::Create(decrypt_ing, decrypt_end, cmp_i_with_20, decrypt_cond);
LoadInst* ldr_i_data_2 = new LoadInst(ptr_i, "", false, decrypt_ing);
ldr_i_data_2->setAlignment(MaybeAlign(4));
LoadInst* ldr_ptr_this_ret = new LoadInst(ptr_this_ret, "", false, decrypt_ing);
ldr_ptr_this_ret->setAlignment(MaybeAlign(4));
GetElementPtrInst* get_func_ptr_idx = GetElementPtrInst::Create(cast<PointerType>(ldr_ptr_this_ret->getType()->getScalarType())->getElementType(), ldr_ptr_this_ret, ldr_i_data_2, "arrayidx1", decrypt_ing);
get_func_ptr_idx->setIsInBounds(true);
LoadInst* ldr_func_ptr_idx = new LoadInst(get_func_ptr_idx, "", false, decrypt_ing);
ldr_func_ptr_idx->setAlignment(MaybeAlign(1));
LoadInst* ldr_i_data_3 = new LoadInst(ptr_i, "", false, decrypt_ing);
ldr_i_data_3->setAlignment(MaybeAlign(4));
std::vector<Value*> ptr_retn_array_indices;
ptr_retn_array_indices.push_back(const_int_0);
ptr_retn_array_indices.push_back(ldr_i_data_3);
GetElementPtrInst* get_retn_array_data_idx = GetElementPtrInst::Create(return_array, ptr_ret_array, ptr_retn_array_indices, "arrayidx2", decrypt_ing);
get_retn_array_data_idx->setIsInBounds(true);
StoreInst* str_retn_array_data_idx = new StoreInst(ldr_func_ptr_idx, get_retn_array_data_idx, false, decrypt_ing);
str_retn_array_data_idx->setAlignment(MaybeAlign(1));
LoadInst* ldr_i_data_4 = new LoadInst(ptr_i, "", false, decrypt_ing);
ldr_i_data_4->setAlignment(MaybeAlign(4));
std::vector<Value*> ptr_retn_array_indices2;
ptr_retn_array_indices2.push_back(const_int_0);
ptr_retn_array_indices2.push_back(ldr_i_data_4);
GetElementPtrInst* get_retn_array_data_idx2 = GetElementPtrInst::Create(return_array, ptr_ret_array, ptr_retn_array_indices2, "arrayidx3", decrypt_ing);
get_retn_array_data_idx2->setIsInBounds(true);
LoadInst* ldr_retn_array_data_idx2 = new LoadInst(get_retn_array_data_idx2, "", false, decrypt_ing);
ldr_retn_array_data_idx2->setAlignment(MaybeAlign(1));
CastInst* cast_retn_array_data_idx2 = new ZExtInst(ldr_retn_array_data_idx2, IntegerType::get(mod->getContext(), 32), "conv", decrypt_ing);
BinaryOperator* xor_retn_array_data_idx2 = BinaryOperator::Create(Instruction::Xor, cast_retn_array_data_idx2, const_int32_133, "xor", decrypt_ing);
CastInst* trun_retn_array_data_idx2 = new TruncInst(xor_retn_array_data_idx2, IntegerType::get(mod->getContext(), 8), "conv4", decrypt_ing);
LoadInst* ldr_i_data_5 = new LoadInst(ptr_i, "", false, decrypt_ing);
ldr_i_data_5->setAlignment(MaybeAlign(4));
std::vector<Value*> ptr_retn_array_indices4;
ptr_retn_array_indices4.push_back(const_int_0);
ptr_retn_array_indices4.push_back(ldr_i_data_5);
GetElementPtrInst* get_retn_array_data_idx4 = GetElementPtrInst::Create(return_array, ptr_ret_array, ptr_retn_array_indices4, "arrayidx5", decrypt_ing);
get_retn_array_data_idx4->setIsInBounds(true);
StoreInst* str_retn_array_data_idx4 = new StoreInst(trun_retn_array_data_idx2, get_retn_array_data_idx4, false, decrypt_ing);
str_retn_array_data_idx4->setAlignment(MaybeAlign(1));
BranchInst::Create(decrypt_add, decrypt_ing);
LoadInst* ldr_i_data_6 = new LoadInst(ptr_i, "", false, decrypt_add);
ldr_i_data_6->setAlignment(MaybeAlign(4));
BinaryOperator* add_i_data_4 = BinaryOperator::Create(Instruction::Add, ldr_i_data_6, const_int_1, "", decrypt_add);
StoreInst* str_i_data_4 = new StoreInst(add_i_data_4, ptr_i, false, decrypt_add);
str_i_data_4->setAlignment(MaybeAlign(4));
BranchInst::Create(decrypt_cond, decrypt_add);
LoadInst* ldr_ret_array = new LoadInst(ret_array_ptr, "", false, decrypt_end);
ldr_ret_array->setAlignment(MaybeAlign(4));
BasicBlock* dec_jmp = BasicBlock::Create(mod->getContext(), "dec_jmp", &F, BB);
BranchInst::Create(dec_jmp, decrypt_end);
PHINode* ptr_40 = PHINode::Create(ret_func_ptr, 1, "", dec_jmp);
ptr_40->addIncoming(ldr_ret_array, decrypt_end);
IndirectBrInst *void_41 = IndirectBrInst::Create(ldr_ret_array, 1, dec_jmp);
void_41->addDestination(BB);
errs().write_escaped(F.getName()) << " " << F.getParent()->getName() << '\n';
}
*/
return true;
}
}; // end of struct Hello
} // end of anonymous namespace
char ReturnObfuscation::ID = 0;
static RegisterPass<ReturnObfuscation> X("rof", "Hello World Pass",
false /* Only looks at CFG */,
false /* Analysis Pass */);
\ No newline at end of file