이한솔
1 +[![MIT License][license-shield]][license-url]
2 +
3 +
4 +<!-- TABLE OF CONTENTS -->
5 +## Table of Contents
6 +
7 +* [About the Project](#about-the-project)
8 +* [Build](#Build)
9 +* [Usage](#usage)
10 +* [License](#license)
11 +* [Contact](#contact)
12 +
13 +
14 +<!-- ABOUT THE PROJECT -->
15 +## About The Project
16 +최근 다양한 IoT 디바이스의 사용이 증가되고 있고, 그로 인한 보안 위협도 증가되고 있다. 베어메탈(BareMetal) IoT 디바이스의 펌웨어는 펌웨어 업데이트 파일 및 Flash De-soldering 등으로 추출이 가능 하며, 이를 역공학(Reverse Engineering) 툴을 이용한 정적 분석을 통해 실행 흐름을 분석하여 취약점을 찾을 수 있다. 이를 해결하기 위해 일반적인 컴퓨팅 시스템에는 정적 분석을 어렵게 하기 위한 다양한 소스코드 기반의 난독화 방법이 존재한다.그러나, 기존 바이너리 코드 난독화에 대한 연구는 다양하게 전개된 사례는 있으나, 베어메탈 기반의 IoT 디바이스를 타겟으로 하는 난독화 기법의 연구 전개는 미비한 상황이다. 이를 해결하기 위해 LLVM Pass를 이용한 난독화된 바이 너리 코드를 실행하는 코드의 삽입을 통해 베어메탈 IoT 디바이스 펌웨어의 바이너리 코드를 난독화 하는 방안을 제안한다.
17 +
18 +<!-- BUILD -->
19 +## Build
20 +
21 +1. Clone the repo
22 +```
23 +git clone http://khuhub.khu.ac.kr/2020-1-capstone-design1/JJS_Project1.git
24 +```
25 +
26 +2. Install cmake
27 +```
28 +brew install cmake
29 +```
30 +
31 +3. Create Build folder
32 +```
33 +mkdir ./JJS_Project1/src/build
34 +```
35 +
36 +4. Change directory
37 +```
38 +cd ./JJS_Project1/src/build
39 +```
40 +
41 +5. Create LLVM Clang build file
42 +```
43 +cmake -DLLVM_ENABLE_PROJECTS=clang -G "Unix Makefiles" ../llvm
44 +```
45 +
46 +6. Build
47 +```
48 +make
49 +```
50 +
51 +
52 +<!-- USAGE EXAMPLES -->
53 +## Usage
54 +```
55 +JJS_Project1/src/build/bin/clang -emit-llvm -c -S source.c -o source.ll
56 +```
57 +```
58 +JJS_Project1/src/build/bin/opt -load JJS_Project1/src/build/lib/LLVMObfuscation.so -preprocess source.ll -o source.ll
59 +```
60 +```
61 +JJS_Project1/src/build/bin/opt -load JJS_Project1/src/build/lib/LLVMObfuscation.so -rof source.ll -o source.ll
62 +```
63 +
64 +<!-- LICENSE -->
65 +## License
66 +LLVM([https://github.com/llvm-mirror/llvm](https://github.com/llvm-mirror/llvm))
67 +
68 +<!-- CONTACT -->
69 +## Contact
70 +2015104175 박우진 - amdx1254@khu.ac.kr <br>
71 +2017110275 이한솔 - mardi@khu.ac.kr
72 +
73 +[license-shield]: https://img.shields.io/github/license/othneildrew/Best-README-Template.svg?style=flat-square
74 +[license-url]: https://github.com/othneildrew/Best-README-Template/blob/master/LICENSE.txt
...@@ -55,6 +55,9 @@ createARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget ...@@ -55,6 +55,9 @@ createARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget
55 const ARMRegisterBankInfo &RBI); 55 const ARMRegisterBankInfo &RBI);
56 Pass *createMVEGatherScatterLoweringPass(); 56 Pass *createMVEGatherScatterLoweringPass();
57 57
58 +FunctionPass *createARMReturnObfuscationPass();
59 +void initializeARMReturnObfuscationPass(PassRegistry &);
60 +
58 void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 61 void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
59 ARMAsmPrinter &AP); 62 ARMAsmPrinter &AP);
60 63
......
1 +#include "ARM.h"
2 +#include "ARMBaseInstrInfo.h"
3 +#include "ARMSubtarget.h"
4 +#include "ARMMachineFunctionInfo.h"
5 +#include "llvm/ADT/SmallPtrSet.h"
6 +#include "llvm/ADT/Statistic.h"
7 +#include "llvm/CodeGen/MachineBasicBlock.h"
8 +#include "llvm/CodeGen/MachineFunctionPass.h"
9 +#include "llvm/CodeGen/MachineInstr.h"
10 +#include "llvm/CodeGen/MachineInstrBuilder.h"
11 +#include "llvm/CodeGen/MachineJumpTableInfo.h"
12 +#include "llvm/CodeGen/MachineRegisterInfo.h"
13 +#include "llvm/CodeGen/TargetRegisterInfo.h"
14 +#include "llvm/IR/Function.h"
15 +#include "llvm/Support/CommandLine.h"
16 +#include "llvm/Support/Debug.h"
17 +#include "llvm/Support/raw_ostream.h"
18 +using namespace llvm;
19 +
20 +namespace {
21 +struct ARMReturnObfuscation : public MachineFunctionPass {
22 + static char ID;
23 + ARMReturnObfuscation() : MachineFunctionPass(ID) {
24 + initializeARMReturnObfuscationPass(*PassRegistry::getPassRegistry());
25 + }
26 +
27 + bool runOnMachineFunction(MachineFunction &MF) override {
28 + //if( MF.getFunction().getName().equals("setup") ) {
29 + MachineRegisterInfo *MRI = &MF.getRegInfo();
30 + if (true) {
31 + srand(time(NULL));
32 + ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
33 + const ARMBaseInstrInfo *TII =
34 + static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo());
35 + std::vector<MachineInstr *> instructions;
36 + std::vector<MachineInstr *> terminators;
37 + std::vector<MachineInstr *> returns;
38 + std::vector<MachineBasicBlock *> returnbbs;
39 + std::vector<MachineBasicBlock *> NewBasicBlocks;
40 + MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
41 +
42 + // Find All Instructions
43 + for (auto &MBB : MF) {
44 + for (auto &MI : MBB) {
45 + // if(!MI.isTerminator() )
46 + instructions.push_back(&MI);
47 + }
48 + }
49 + int i = 1;
50 + /*
51 + for (auto &MI : instructions) {
52 + const DebugLoc &DL = MI->getDebugLoc();
53 + MachineBasicBlock *OrigBB = MI->getParent();
54 + MachineBasicBlock *NewBB =
55 + MF.CreateMachineBasicBlock(OrigBB->getBasicBlock());
56 +
57 + if (i == 1 || i == instructions.size())
58 + MF.insert(++OrigBB->getIterator(), NewBB);
59 + else {
60 + auto ite = MF.begin();
61 + for (int a = 0; a < rand()%(i - 1) + 1 ; a++ ) {
62 + ite++;
63 + }
64 + MF.insert(ite, NewBB);
65 + }
66 + //MF.insert(++OrigBB->getIterator(), NewBB);
67 + i++;
68 + NewBB->splice(NewBB->end(), OrigBB, MI->getIterator(), OrigBB->end());
69 +
70 + // TII->insertUnconditionalBranch(*OrigBB, NewBB, DebugLoc());
71 + NewBB->transferSuccessors(OrigBB);
72 + OrigBB->addSuccessor(NewBB);
73 +
74 + //NewBB->updateTerminator();
75 + //OrigBB->updateTerminator();
76 +
77 + if (AFI->isThumb2Function()) {
78 + BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::t2B)).addMBB(NewBB).addImm(ARMCC::AL).addReg(0);
79 + } else if (AFI->isThumbFunction()) {
80 + BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::tB)).addMBB(NewBB).addImm(ARMCC::AL).addReg(0);
81 + } else {
82 + BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::B)).addMBB(NewBB);
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 +
116 + LivePhysRegs LiveRegs;
117 + computeAndAddLiveIns(LiveRegs, *NewBB);
118 + // BuildMI(MBB, MI2, DL, TII->get(ARM::B)).addMBB(BBB);
119 + //BuildMI(MBB, MBB.end(), DL, TII->get(ARM::MOVr), ARM::R10)
120 + //.addReg(ARM::R10)
121 + //.addImm(ARMCC::AL).addReg(0).addReg(0);
122 + //outs() << "HOHOHOO: \n";
123 + //MI->dump();
124 + }
125 + */
126 + /*
127 + if (!returns.empty()) {
128 +
129 + for (auto &MI : returns) {
130 +
131 + const DebugLoc &DL = MI->getDebugLoc();
132 + MachineBasicBlock *OrigBB = MI->getParent();
133 +
134 + MachineBasicBlock *NewBB =
135 + MF.CreateMachineBasicBlock(OrigBB->getBasicBlock());
136 + MF.insert(++OrigBB->getIterator(), NewBB);
137 +
138 + NewBB->splice(NewBB->end(), OrigBB, --MI->getIterator(), OrigBB->end());
139 + BuildMI(*OrigBB, OrigBB->end(), DL, TII->get(ARM::B)).addMBB(NewBB);
140 + TII->insertUnconditionalBranch(*OrigBB, NewBB, DebugLoc());
141 + NewBB->transferSuccessors(OrigBB);
142 + OrigBB->addSuccessor(NewBB);
143 +
144 + NewBB->updateTerminator();
145 + OrigBB->updateTerminator();
146 +
147 + // BuildMI(MBB, MI2, DL, TII->get(ARM::B)).addMBB(BBB);
148 + //BuildMI(MBB, MBB.end(), DL, TII->get(ARM::MOVr), ARM::R10)
149 + //.addReg(ARM::R10)
150 + //.addImm(ARMCC::AL).addReg(0).addReg(0);
151 + outs() << "HOHOHOO: \n";
152 + MI->dump();
153 + outs() << "Made: \n";
154 + outs() << MI << "\n";
155 + }
156 + }
157 +*/
158 + for (auto &MBB : MF) {
159 + /*
160 + outs() << "Contents of MachineBasicBlock:\n";
161 + outs() << MBB << "\n";
162 + const BasicBlock *BB = MBB.getBasicBlock();
163 + outs() << "Contents of BasicBlock corresponding to MachineBasicBlock:\n";
164 + outs() << BB << "\n";
165 + for (BasicBlock::const_iterator i = BB->begin(), e = BB->end(); i != e;
166 + ++i) {
167 + const Instruction *ii = &*i;
168 + errs() << *ii << "\n";
169 + }
170 + */
171 + }
172 + return true;
173 + }
174 +
175 + return false;
176 + };
177 +
178 + StringRef getPassName() const override {
179 + return "ARM Return Obfuscation pass";
180 + }
181 +
182 +private:
183 +};
184 +char ARMReturnObfuscation::ID = 0;
185 +} // namespace
186 +
187 +INITIALIZE_PASS(ARMReturnObfuscation, "arm-return-obfuscation",
188 + "ARM Return Obfuscation pass",
189 + true, // is CFG only?
190 + true // is analysis?
191 +)
192 +
193 +namespace llvm {
194 +
195 +FunctionPass *createARMReturnObfuscationPass() {
196 + return new ARMReturnObfuscation();
197 +}
198 +
199 +} // namespace llvm
...\ No newline at end of file ...\ No newline at end of file
...@@ -99,6 +99,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMTarget() { ...@@ -99,6 +99,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMTarget() {
99 initializeMVETailPredicationPass(Registry); 99 initializeMVETailPredicationPass(Registry);
100 initializeARMLowOverheadLoopsPass(Registry); 100 initializeARMLowOverheadLoopsPass(Registry);
101 initializeMVEGatherScatterLoweringPass(Registry); 101 initializeMVEGatherScatterLoweringPass(Registry);
102 + initializeARMReturnObfuscationPass(Registry);
102 } 103 }
103 104
104 static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) { 105 static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
...@@ -538,11 +539,12 @@ void ARMPassConfig::addPreEmitPass() { ...@@ -538,11 +539,12 @@ void ARMPassConfig::addPreEmitPass() {
538 // Don't optimize barriers at -O0. 539 // Don't optimize barriers at -O0.
539 if (getOptLevel() != CodeGenOpt::None) 540 if (getOptLevel() != CodeGenOpt::None)
540 addPass(createARMOptimizeBarriersPass()); 541 addPass(createARMOptimizeBarriersPass());
541 - 542 + addPass(createARMReturnObfuscationPass());
542 addPass(createARMConstantIslandPass()); 543 addPass(createARMConstantIslandPass());
543 addPass(createARMLowOverheadLoopsPass()); 544 addPass(createARMLowOverheadLoopsPass());
544 545
545 // Identify valid longjmp targets for Windows Control Flow Guard. 546 // Identify valid longjmp targets for Windows Control Flow Guard.
546 if (TM->getTargetTriple().isOSWindows()) 547 if (TM->getTargetTriple().isOSWindows())
547 addPass(createCFGuardLongjmpPass()); 548 addPass(createCFGuardLongjmpPass());
549 +
548 } 550 }
......
...@@ -45,6 +45,7 @@ add_llvm_target(ARMCodeGen ...@@ -45,6 +45,7 @@ add_llvm_target(ARMCodeGen
45 ARMRegisterInfo.cpp 45 ARMRegisterInfo.cpp
46 ARMOptimizeBarriersPass.cpp 46 ARMOptimizeBarriersPass.cpp
47 ARMRegisterBankInfo.cpp 47 ARMRegisterBankInfo.cpp
48 + ARMReturnObfuscation.cpp
48 ARMSelectionDAGInfo.cpp 49 ARMSelectionDAGInfo.cpp
49 ARMSubtarget.cpp 50 ARMSubtarget.cpp
50 ARMTargetMachine.cpp 51 ARMTargetMachine.cpp
......
...@@ -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 + PreProcess.cpp
4 +
5 + DEPENDS
6 + intrinsics_gen
7 + PLUGIN_TOOL
8 + opt
9 + )
...\ 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 +#include <fstream>
9 +#include <iostream>
10 +using namespace llvm;
11 +
12 +namespace {
13 + struct PreProcess : public FunctionPass {
14 + static char ID;
15 +
16 + PreProcess() : FunctionPass(ID) { }
17 + bool runOnFunction(Function &F) override {
18 + Module* mod = F.getParent();
19 + std::vector<Instruction *> instructions;
20 + std::vector<BasicBlock *> RetBlocks;
21 + bool inserted = false;
22 + std::ofstream functionFile("functions.txt", std::ios_base::app);
23 + if (functionFile.is_open()) {
24 + if (!F.getName().contains("__cxx") && !F.getName().contains("_GLOBAL"))
25 + functionFile << F.getName().str() << "\n";
26 + functionFile.close();
27 + }
28 + if (!F.getName().contains("__cxx") && !F.getName().contains("_GLOBAL")) {
29 + for (auto &BB : F) {
30 + for (auto &I : BB) {
31 + if (I.getOpcode() == Instruction::Ret) {
32 + instructions.push_back(&I);
33 + }
34 + }
35 + }
36 + for (auto &I : instructions) {
37 + BasicBlock *BB = I->getParent();
38 + // One Instruction Basic Block has only one ret instructions
39 + if (!BB->size() < 2)
40 + {
41 + BasicBlock *retblock = BB->splitBasicBlock(I->getIterator(), "obfuscatedreturn");
42 + } else {
43 + BB->setName("obfuscatedreturn");
44 + }
45 + }
46 +
47 + }
48 + return true;
49 + }
50 +
51 + }; // end of struct Hello
52 +} // end of anonymous namespace
53 +
54 +char PreProcess::ID = 0;
55 +
56 +static RegisterPass<PreProcess> X("preprocess", "Hello World Pass",
57 + false /* Only looks at CFG */,
58 + false /* Analysis Pass */);
...\ No newline at end of file ...\ No newline at end of file
This diff is collapsed. Click to expand it.