박우진

Add Return Obfuscation Pass

...@@ -26,7 +26,7 @@ struct ARMReturnObfuscation : public MachineFunctionPass { ...@@ -26,7 +26,7 @@ struct ARMReturnObfuscation : public MachineFunctionPass {
26 26
27 bool runOnMachineFunction(MachineFunction &MF) override { 27 bool runOnMachineFunction(MachineFunction &MF) override {
28 //if( MF.getFunction().getName().equals("setup") ) { 28 //if( MF.getFunction().getName().equals("setup") ) {
29 - 29 + MachineRegisterInfo *MRI = &MF.getRegInfo();
30 if (true) { 30 if (true) {
31 srand(time(NULL)); 31 srand(time(NULL));
32 ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 32 ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
...@@ -47,11 +47,13 @@ struct ARMReturnObfuscation : public MachineFunctionPass { ...@@ -47,11 +47,13 @@ struct ARMReturnObfuscation : public MachineFunctionPass {
47 } 47 }
48 } 48 }
49 int i = 1; 49 int i = 1;
50 + /*
50 for (auto &MI : instructions) { 51 for (auto &MI : instructions) {
51 const DebugLoc &DL = MI->getDebugLoc(); 52 const DebugLoc &DL = MI->getDebugLoc();
52 MachineBasicBlock *OrigBB = MI->getParent(); 53 MachineBasicBlock *OrigBB = MI->getParent();
53 MachineBasicBlock *NewBB = 54 MachineBasicBlock *NewBB =
54 MF.CreateMachineBasicBlock(OrigBB->getBasicBlock()); 55 MF.CreateMachineBasicBlock(OrigBB->getBasicBlock());
56 +
55 if (i == 1 || i == instructions.size()) 57 if (i == 1 || i == instructions.size())
56 MF.insert(++OrigBB->getIterator(), NewBB); 58 MF.insert(++OrigBB->getIterator(), NewBB);
57 else { 59 else {
...@@ -61,8 +63,8 @@ struct ARMReturnObfuscation : public MachineFunctionPass { ...@@ -61,8 +63,8 @@ struct ARMReturnObfuscation : public MachineFunctionPass {
61 } 63 }
62 MF.insert(ite, NewBB); 64 MF.insert(ite, NewBB);
63 } 65 }
66 + //MF.insert(++OrigBB->getIterator(), NewBB);
64 i++; 67 i++;
65 -
66 NewBB->splice(NewBB->end(), OrigBB, MI->getIterator(), OrigBB->end()); 68 NewBB->splice(NewBB->end(), OrigBB, MI->getIterator(), OrigBB->end());
67 69
68 // TII->insertUnconditionalBranch(*OrigBB, NewBB, DebugLoc()); 70 // TII->insertUnconditionalBranch(*OrigBB, NewBB, DebugLoc());
...@@ -71,6 +73,7 @@ struct ARMReturnObfuscation : public MachineFunctionPass { ...@@ -71,6 +73,7 @@ struct ARMReturnObfuscation : public MachineFunctionPass {
71 73
72 //NewBB->updateTerminator(); 74 //NewBB->updateTerminator();
73 //OrigBB->updateTerminator(); 75 //OrigBB->updateTerminator();
76 +
74 if (AFI->isThumb2Function()) { 77 if (AFI->isThumb2Function()) {
75 BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::t2B)).addMBB(NewBB).addImm(ARMCC::AL).addReg(0); 78 BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::t2B)).addMBB(NewBB).addImm(ARMCC::AL).addReg(0);
76 } else if (AFI->isThumbFunction()) { 79 } else if (AFI->isThumbFunction()) {
...@@ -78,15 +81,48 @@ struct ARMReturnObfuscation : public MachineFunctionPass { ...@@ -78,15 +81,48 @@ struct ARMReturnObfuscation : public MachineFunctionPass {
78 } else { 81 } else {
79 BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::B)).addMBB(NewBB); 82 BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::B)).addMBB(NewBB);
80 } 83 }
84 +
85 +
86 +
87 + srand(time(NULL));
88 + int randimm = rand()%10+1;
89 +
90 + if (AFI->isThumb2Function()) {
91 + BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tMOVi8), ARM::NoRegister)
92 + .addImm(randimm);
93 +
94 + BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tCMPi8))
95 + .addReg(ARM::NoRegister, RegState::Kill)
96 + .addImm(randimm);
97 + BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tBcc))
98 + .addMBB(NewBB)
99 + .addImm(ARMCC::EQ)
100 + .addReg(ARM::CPSR);
101 + } else if (AFI->isThumbFunction()) {
102 + BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tMOVi8), ARM::NoRegister)
103 + .addImm(randimm);
104 +
105 + BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tCMPi8))
106 + .addReg(ARM::NoRegister)
107 + .addImm(randimm);
108 + BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tBcc))
109 + .addMBB(NewBB)
110 + .addImm(ARMCC::EQ)
111 + .addReg(ARM::CPSR);
112 + } else {
113 + BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::B)).addMBB(NewBB);
114 + }
115 +
81 LivePhysRegs LiveRegs; 116 LivePhysRegs LiveRegs;
82 computeAndAddLiveIns(LiveRegs, *NewBB); 117 computeAndAddLiveIns(LiveRegs, *NewBB);
83 // BuildMI(MBB, MI2, DL, TII->get(ARM::B)).addMBB(BBB); 118 // BuildMI(MBB, MI2, DL, TII->get(ARM::B)).addMBB(BBB);
84 //BuildMI(MBB, MBB.end(), DL, TII->get(ARM::MOVr), ARM::R10) 119 //BuildMI(MBB, MBB.end(), DL, TII->get(ARM::MOVr), ARM::R10)
85 //.addReg(ARM::R10) 120 //.addReg(ARM::R10)
86 //.addImm(ARMCC::AL).addReg(0).addReg(0); 121 //.addImm(ARMCC::AL).addReg(0).addReg(0);
87 - outs() << "HOHOHOO: \n"; 122 + //outs() << "HOHOHOO: \n";
88 - MI->dump(); 123 + //MI->dump();
89 } 124 }
125 + */
90 /* 126 /*
91 if (!returns.empty()) { 127 if (!returns.empty()) {
92 128
...@@ -120,6 +156,7 @@ struct ARMReturnObfuscation : public MachineFunctionPass { ...@@ -120,6 +156,7 @@ struct ARMReturnObfuscation : public MachineFunctionPass {
120 } 156 }
121 */ 157 */
122 for (auto &MBB : MF) { 158 for (auto &MBB : MF) {
159 + /*
123 outs() << "Contents of MachineBasicBlock:\n"; 160 outs() << "Contents of MachineBasicBlock:\n";
124 outs() << MBB << "\n"; 161 outs() << MBB << "\n";
125 const BasicBlock *BB = MBB.getBasicBlock(); 162 const BasicBlock *BB = MBB.getBasicBlock();
...@@ -130,6 +167,7 @@ struct ARMReturnObfuscation : public MachineFunctionPass { ...@@ -130,6 +167,7 @@ struct ARMReturnObfuscation : public MachineFunctionPass {
130 const Instruction *ii = &*i; 167 const Instruction *ii = &*i;
131 errs() << *ii << "\n"; 168 errs() << *ii << "\n";
132 } 169 }
170 + */
133 } 171 }
134 return true; 172 return true;
135 } 173 }
......
...@@ -492,8 +492,6 @@ void ARMPassConfig::addPreRegAlloc() { ...@@ -492,8 +492,6 @@ void ARMPassConfig::addPreRegAlloc() {
492 if (!DisableA15SDOptimization) 492 if (!DisableA15SDOptimization)
493 addPass(createA15SDOptimizerPass()); 493 addPass(createA15SDOptimizerPass());
494 } 494 }
495 -
496 - addPass(createARMReturnObfuscationPass());
497 } 495 }
498 496
499 void ARMPassConfig::addPreSched2() { 497 void ARMPassConfig::addPreSched2() {
...@@ -541,11 +539,12 @@ void ARMPassConfig::addPreEmitPass() { ...@@ -541,11 +539,12 @@ void ARMPassConfig::addPreEmitPass() {
541 // Don't optimize barriers at -O0. 539 // Don't optimize barriers at -O0.
542 if (getOptLevel() != CodeGenOpt::None) 540 if (getOptLevel() != CodeGenOpt::None)
543 addPass(createARMOptimizeBarriersPass()); 541 addPass(createARMOptimizeBarriersPass());
544 - 542 + addPass(createARMReturnObfuscationPass());
545 addPass(createARMConstantIslandPass()); 543 addPass(createARMConstantIslandPass());
546 addPass(createARMLowOverheadLoopsPass()); 544 addPass(createARMLowOverheadLoopsPass());
547 545
548 // Identify valid longjmp targets for Windows Control Flow Guard. 546 // Identify valid longjmp targets for Windows Control Flow Guard.
549 if (TM->getTargetTriple().isOSWindows()) 547 if (TM->getTargetTriple().isOSWindows())
550 addPass(createCFGuardLongjmpPass()); 548 addPass(createCFGuardLongjmpPass());
549 +
551 } 550 }
......
...@@ -9,3 +9,4 @@ add_subdirectory(Hello) ...@@ -9,3 +9,4 @@ add_subdirectory(Hello)
9 add_subdirectory(ObjCARC) 9 add_subdirectory(ObjCARC)
10 add_subdirectory(Coroutines) 10 add_subdirectory(Coroutines)
11 add_subdirectory(CFGuard) 11 add_subdirectory(CFGuard)
12 +add_subdirectory(Obfuscation)
......
1 +add_llvm_library( LLVMObfuscation MODULE
2 + ReturnObfuscation.cpp
3 +
4 + DEPENDS
5 + intrinsics_gen
6 + PLUGIN_TOOL
7 + opt
8 + )
...\ No newline at end of file ...\ No newline at end of file
1 +#include "llvm/Pass.h"
2 +#include "llvm/IR/Function.h"
3 +#include "llvm/IR/Module.h"
4 +#include "llvm/IR/Instructions.h"
5 +#include "llvm/Support/Alignment.h"
6 +#include "llvm/Support/raw_ostream.h"
7 +#include "llvm/IR/CFG.h"
8 +using namespace llvm;
9 +
10 +namespace {
11 + struct ReturnObfuscation : public FunctionPass {
12 + static char ID;
13 + ReturnObfuscation() : FunctionPass(ID) {}
14 + bool runOnFunction(Function &F) override {
15 + Module* mod = F.getParent();
16 + /*
17 + if (!F.getName().contains("setup") && !F.getName().contains("test")) {
18 + return false;
19 + }*/
20 + ArrayType* return_array = ArrayType::get(IntegerType::get(mod->getContext(), 8), 12);
21 + PointerType* return_array_ptr = PointerType::get(return_array, 0);
22 + PointerType* ret_func_ptr = PointerType::get(IntegerType::get(mod->getContext(), 8), 0);
23 + ConstantInt* const_int_1 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("1"), 10));
24 + ConstantInt* const_int_0 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("0"), 10));
25 + ConstantInt* const_int_20 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("12"), 10));
26 + ConstantInt* const_int32_133 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("133"), 10));
27 + AllocaInst* ptr_ret_array;
28 + AllocaInst* ptr_this_ret;
29 + AllocaInst* ret_array_ptr;
30 + AllocaInst* ptr_i;
31 + std::vector<Instruction *> instructions;
32 + std::vector<BasicBlock *> RetBlocks;
33 + bool inserted = false;
34 + bool splitted = false;
35 + for (auto &BB : F) {
36 + for (auto &I : BB) {
37 + if(!inserted) {
38 + ptr_ret_array = new AllocaInst(return_array, NULL, "ret_ptr", &I);
39 + ptr_ret_array->setAlignment(MaybeAlign(1));
40 + ptr_this_ret = new AllocaInst(ret_func_ptr, NULL, "ptr", &I);
41 + ret_array_ptr = new AllocaInst(ret_func_ptr, NULL, "ptr2", &I);
42 + ptr_i = new AllocaInst(IntegerType::get(mod->getContext(), 32), NULL, "i", &I);
43 +
44 + inserted=true;
45 + IndirectBrInst *a;
46 +
47 + }
48 + if (I.getOpcode() == Instruction::Ret) {
49 + instructions.push_back(&I);
50 + }
51 + }
52 + }
53 +
54 + for (auto &I : instructions) {
55 + BasicBlock *BB = I->getParent();
56 + // One Instruction Basic Block has only one ret instructions
57 + if (!BB->size() < 2)
58 + {
59 + BasicBlock *retblock = BB->splitBasicBlock(I->getIterator(), BB->getName() + ".RetBlock");
60 + RetBlocks.push_back(retblock);
61 + } else {
62 + RetBlocks.push_back(BB);
63 + }
64 +
65 + }
66 +
67 + for (auto &BB : RetBlocks) {
68 + Constant* retBlockAddress = BlockAddress::get(BB);
69 +
70 + BasicBlock* decrypt_start = BasicBlock::Create(mod->getContext(), "dec_start", &F, BB);
71 + for (BasicBlock* preds : predecessors(BB)) {
72 + preds->getTerminator()->eraseFromParent();
73 + BranchInst::Create(decrypt_start, preds);
74 + }
75 +
76 +
77 + std::vector<Value*> ptr_to_retarray_indices;
78 + ptr_to_retarray_indices.push_back(const_int_0);
79 + ptr_to_retarray_indices.push_back(const_int_0);
80 + GetElementPtrInst* ptr_to_retarray = GetElementPtrInst::Create(return_array, ptr_ret_array, ptr_to_retarray_indices, "arrayidx", decrypt_start);
81 + ptr_to_retarray->setIsInBounds(true);
82 + StoreInst* store_to_ret_ptr = new StoreInst(ptr_to_retarray, ret_array_ptr, false, decrypt_start);
83 +
84 + store_to_ret_ptr->setAlignment(MaybeAlign(4));
85 +
86 + StoreInst* void_17 = new StoreInst(retBlockAddress, ptr_this_ret, false, decrypt_start);
87 +
88 + ptr_this_ret->setAlignment(MaybeAlign(4));
89 + ret_array_ptr->setAlignment(MaybeAlign(4));
90 + ptr_i->setAlignment(MaybeAlign(4));
91 + void_17->setAlignment(MaybeAlign(4));
92 +
93 +
94 +
95 + StoreInst* store_i_0 = new StoreInst(const_int_0, ptr_i, false, decrypt_start);
96 + store_i_0->setAlignment(MaybeAlign(4));
97 +
98 +
99 +
100 + BasicBlock* decrypt_cond = BasicBlock::Create(mod->getContext(), "dec_cond", &F, BB);
101 +
102 + BranchInst::Create(decrypt_cond, decrypt_start);
103 +
104 + LoadInst* ldr_i_data = new LoadInst(ptr_i, "", false, decrypt_cond);
105 + ldr_i_data->setAlignment(MaybeAlign(4));
106 + ICmpInst* cmp_i_with_20 = new ICmpInst(*decrypt_cond, ICmpInst::ICMP_SLT, ldr_i_data, const_int_20, "cmp");
107 +
108 + BasicBlock* decrypt_ing = BasicBlock::Create(mod->getContext(), "dec_ing", &F, BB);
109 + BasicBlock* decrypt_add = BasicBlock::Create(mod->getContext(), "dec_add", &F, BB);
110 + BasicBlock* decrypt_end = BasicBlock::Create(mod->getContext(), "dec_end", &F, BB);
111 + BranchInst::Create(decrypt_ing, decrypt_end, cmp_i_with_20, decrypt_cond);
112 +
113 + LoadInst* ldr_i_data_2 = new LoadInst(ptr_i, "", false, decrypt_ing);
114 + ldr_i_data_2->setAlignment(MaybeAlign(4));
115 + LoadInst* ldr_ptr_this_ret = new LoadInst(ptr_this_ret, "", false, decrypt_ing);
116 + ldr_ptr_this_ret->setAlignment(MaybeAlign(4));
117 + 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);
118 + get_func_ptr_idx->setIsInBounds(true);
119 + LoadInst* ldr_func_ptr_idx = new LoadInst(get_func_ptr_idx, "", false, decrypt_ing);
120 + ldr_func_ptr_idx->setAlignment(MaybeAlign(1));
121 +
122 + LoadInst* ldr_i_data_3 = new LoadInst(ptr_i, "", false, decrypt_ing);
123 + ldr_i_data_3->setAlignment(MaybeAlign(4));
124 +
125 + std::vector<Value*> ptr_retn_array_indices;
126 + ptr_retn_array_indices.push_back(const_int_0);
127 + ptr_retn_array_indices.push_back(ldr_i_data_3);
128 + GetElementPtrInst* get_retn_array_data_idx = GetElementPtrInst::Create(return_array, ptr_ret_array, ptr_retn_array_indices, "arrayidx2", decrypt_ing);
129 + get_retn_array_data_idx->setIsInBounds(true);
130 + StoreInst* str_retn_array_data_idx = new StoreInst(ldr_func_ptr_idx, get_retn_array_data_idx, false, decrypt_ing);
131 + str_retn_array_data_idx->setAlignment(MaybeAlign(1));
132 +
133 + LoadInst* ldr_i_data_4 = new LoadInst(ptr_i, "", false, decrypt_ing);
134 + ldr_i_data_4->setAlignment(MaybeAlign(4));
135 +
136 + std::vector<Value*> ptr_retn_array_indices2;
137 + ptr_retn_array_indices2.push_back(const_int_0);
138 + ptr_retn_array_indices2.push_back(ldr_i_data_4);
139 + GetElementPtrInst* get_retn_array_data_idx2 = GetElementPtrInst::Create(return_array, ptr_ret_array, ptr_retn_array_indices2, "arrayidx3", decrypt_ing);
140 + get_retn_array_data_idx2->setIsInBounds(true);
141 + LoadInst* ldr_retn_array_data_idx2 = new LoadInst(get_retn_array_data_idx2, "", false, decrypt_ing);
142 + ldr_retn_array_data_idx2->setAlignment(MaybeAlign(1));
143 +
144 + CastInst* cast_retn_array_data_idx2 = new ZExtInst(ldr_retn_array_data_idx2, IntegerType::get(mod->getContext(), 32), "conv", decrypt_ing);
145 + BinaryOperator* xor_retn_array_data_idx2 = BinaryOperator::Create(Instruction::Xor, cast_retn_array_data_idx2, const_int32_133, "xor", decrypt_ing);
146 +
147 + CastInst* trun_retn_array_data_idx2 = new TruncInst(xor_retn_array_data_idx2, IntegerType::get(mod->getContext(), 8), "conv4", decrypt_ing);
148 +
149 +
150 + LoadInst* ldr_i_data_5 = new LoadInst(ptr_i, "", false, decrypt_ing);
151 + ldr_i_data_5->setAlignment(MaybeAlign(4));
152 +
153 + std::vector<Value*> ptr_retn_array_indices4;
154 + ptr_retn_array_indices4.push_back(const_int_0);
155 + ptr_retn_array_indices4.push_back(ldr_i_data_5);
156 + GetElementPtrInst* get_retn_array_data_idx4 = GetElementPtrInst::Create(return_array, ptr_ret_array, ptr_retn_array_indices4, "arrayidx5", decrypt_ing);
157 + get_retn_array_data_idx4->setIsInBounds(true);
158 + StoreInst* str_retn_array_data_idx4 = new StoreInst(trun_retn_array_data_idx2, get_retn_array_data_idx4, false, decrypt_ing);
159 + str_retn_array_data_idx4->setAlignment(MaybeAlign(1));
160 +
161 +
162 + BranchInst::Create(decrypt_add, decrypt_ing);
163 +
164 + LoadInst* ldr_i_data_6 = new LoadInst(ptr_i, "", false, decrypt_add);
165 + ldr_i_data_6->setAlignment(MaybeAlign(4));
166 + BinaryOperator* add_i_data_4 = BinaryOperator::Create(Instruction::Add, ldr_i_data_6, const_int_1, "", decrypt_add);
167 + StoreInst* str_i_data_4 = new StoreInst(add_i_data_4, ptr_i, false, decrypt_add);
168 + str_i_data_4->setAlignment(MaybeAlign(4));
169 + BranchInst::Create(decrypt_cond, decrypt_add);
170 +
171 + LoadInst* ldr_ret_array = new LoadInst(ret_array_ptr, "", false, decrypt_end);
172 + ldr_ret_array->setAlignment(MaybeAlign(4));
173 +
174 + BasicBlock* dec_jmp = BasicBlock::Create(mod->getContext(), "dec_jmp", &F, BB);
175 + BranchInst::Create(dec_jmp, decrypt_end);
176 +
177 + PHINode* ptr_40 = PHINode::Create(ret_func_ptr, 1, "", dec_jmp);
178 + ptr_40->addIncoming(ldr_ret_array, decrypt_end);
179 + IndirectBrInst *void_41 = IndirectBrInst::Create(ldr_ret_array, 1, dec_jmp);
180 + void_41->addDestination(BB);
181 + errs().write_escaped(F.getName()) << " " << F.getParent()->getName() << '\n';
182 + }
183 + return true;
184 + }
185 +
186 + }; // end of struct Hello
187 +} // end of anonymous namespace
188 +
189 +char ReturnObfuscation::ID = 0;
190 +
191 +static RegisterPass<ReturnObfuscation> X("rof", "Hello World Pass",
192 + false /* Only looks at CFG */,
193 + false /* Analysis Pass */);
...\ No newline at end of file ...\ No newline at end of file