- 平坦化一句话概括就是重组原始代码执行流程,把原本易于阅读的代码流程重组成一个switch case形式的代码执行流程,大大降低代码的直观可读性
- 平坦化这么做的目的就是要大幅度降低代码的可读性,从而达到防破解的目的
- 下面我画一个粗略的图来形象的展示一下:
25 namespace { 26 struct Flattening : public FunctionPass { 27 static char ID; // Pass identification, replacement for typeid 28 bool flag; 29 30 Flattening() : FunctionPass(ID) {} 31 Flattening(bool flag) : FunctionPass(ID) { this->flag = flag; } 32 33 bool runOnFunction(Function &F); 34 bool flatten(Function *f); 35 }; 36 }
42 bool Flattening::runOnFunction(Function &F) { 43 Function *tmp = &F; 44 // Do we obfuscate 45 if (toObfuscate(flag, tmp, "fla")) { 46 47 if (flatten(tmp)) { 48 ++Flattened; 49 } 50 } 51 52 return false; 53 }
55 bool Flattening::flatten(Function *f) { 56 vector<BasicBlock *> origBB; 57 BasicBlock *loopEntry; 58 BasicBlock *loopEnd; 59 LoadInst *load; 60 SwitchInst *switchI; 61 AllocaInst *switchVar; 62 63 // SCRAMBLER 64 char scrambling_key[16]; 65 llvm::cryptoutils->get_bytes(scrambling_key, 16); 66 // END OF SCRAMBLER 67 68 // Lower switch 69 FunctionPass *lower = createLowerSwitchPass(); 70 lower->runOnFunction(*f); 71 72 // Save all original BB 73 for (Function::iterator i = f->begin(); i != f->end(); ++i) { 74 BasicBlock *tmp = &*i; 75 origBB.push_back(tmp); 76 ...这里省略了一些代码 81 } 82
88 // Remove first BB 89 origBB.erase(origBB.begin()); 90 91 // Get a pointer on the first BB 92 Function::iterator tmp = f->begin(); //++tmp; 93 BasicBlock *insert = &*tmp; 94 95 // If main begin with an if 96 BranchInst *br = NULL; 97 if (isa<BranchInst>(insert->getTerminator())) { 98 br = cast<BranchInst>(insert->getTerminator()); 99 } 100 101 if ((br != NULL && br->isConditional()) || 102 insert->getTerminator()->getNumSuccessors() > 1) { 103 BasicBlock::iterator i = insert->end(); 104 --i; 105 106 if (insert->size() > 1) { 107 --i; 108 } 109 110 BasicBlock *tmpBB = insert->splitBasicBlock(i, "first"); 111 origBB.insert(origBB.begin(), tmpBB); 112 }
117 // Create switch variable and set as it 118 switchVar = 119 new AllocaInst(Type::getInt32Ty(f->getContext()), 0, "switchVar", insert); 120 new StoreInst( 121 ConstantInt::get(Type::getInt32Ty(f->getContext()), 122 llvm::cryptoutils->scramble32(0, scrambling_key)), 123 switchVar, insert); 124 125 // Create main loop 126 loopEntry = BasicBlock::Create(f->getContext(), "loopEntry", f, insert); 127 loopEnd = BasicBlock::Create(f->getContext(), "loopEnd", f, insert); 128 129 load = new LoadInst(switchVar, "switchVar", loopEntry); 130 131 // Move first BB on top 132 insert->moveBefore(loopEntry); 133 BranchInst::Create(loopEntry, insert); 134 135 // loopEnd jump to loopEntry 136 BranchInst::Create(loopEntry, loopEnd); 137 138 BasicBlock *swDefault = 139 BasicBlock::Create(f->getContext(), "switchDefault", f, loopEnd); 140 BranchInst::Create(loopEnd, swDefault); 141 142 // Create switch instruction itself and set condition 143 switchI = SwitchInst::Create(&*f->begin(), swDefault, 0, loopEntry); 144 switchI->setCondition(load); 145 146 // Remove branch jump from 1st BB and make a jump to the while 147 f->begin()->getTerminator()->eraseFromParent(); 148 149 BranchInst::Create(loopEntry, &*f->begin());
151 // Put all BB in the switch 152 for (vector<BasicBlock *>::iterator b = origBB.begin(); b != origBB.end(); 153 ++b) { 154 BasicBlock *i = *b; 155 ConstantInt *numCase = NULL; 156 157 // Move the BB inside the switch (only visual, no code logic) 158 i->moveBefore(loopEnd); 159 160 // Add case to switch 161 numCase = cast<ConstantInt>(ConstantInt::get( 162 switchI->getCondition()->getType(), 163 llvm::cryptoutils->scramble32(switchI->getNumCases(), scrambling_key))); 164 switchI->addCase(numCase, i); 165 }
接下来的操作分三种情况来进行
case中代码块只有一个后续块,也就是一个无条件跳转分支,直接更新成后续块对应的case即可
178 // If it's a non-conditional jump 179 if (i->getTerminator()->getNumSuccessors() == 1) { 180 // Get successor and delete terminator 181 BasicBlock *succ = i->getTerminator()->getSuccessor(0); 182 i->getTerminator()->eraseFromParent(); 183 184 // Get next case 185 numCase = switchI->findCaseDest(succ); 186 187 // If next case == default case (switchDefault) 188 if (numCase == NULL) { 189 numCase = cast<ConstantInt>( 190 ConstantInt::get(switchI->getCondition()->getType(), 191 llvm::cryptoutils->scramble32( 192 switchI->getNumCases() - 1, scrambling_key))); 193 } 194 195 // Update switchVar and jump to the end of loop 196 new StoreInst(numCase, load->getPointerOperand(), i); 197 BranchInst::Create(loopEnd, i); 198 continue; 199 }
201 // If it's a conditional jump 202 if (i->getTerminator()->getNumSuccessors() == 2) { 203 // Get next cases 204 ConstantInt *numCaseTrue = 205 switchI->findCaseDest(i->getTerminator()->getSuccessor(0)); 206 ConstantInt *numCaseFalse = 207 switchI->findCaseDest(i->getTerminator()->getSuccessor(1)); 208 209 // Check if next case == default case (switchDefault) 210 if (numCaseTrue == NULL) { 211 numCaseTrue = cast<ConstantInt>( 212 ConstantInt::get(switchI->getCondition()->getType(), 213 llvm::cryptoutils->scramble32( 214 switchI->getNumCases() - 1, scrambling_key))); 215 } 216 217 if (numCaseFalse == NULL) { 218 numCaseFalse = cast<ConstantInt>( 219 ConstantInt::get(switchI->getCondition()->getType(), 220 llvm::cryptoutils->scramble32( 221 switchI->getNumCases() - 1, scrambling_key))); 222 } 223 224 // Create a SelectInst 225 BranchInst *br = cast<BranchInst>(i->getTerminator()); 226 SelectInst *sel = 227 SelectInst::Create(br->getCondition(), numCaseTrue, numCaseFalse, "", 228 i->getTerminator()); 229 230 // Erase terminator 231 i->getTerminator()->eraseFromParent(); 232 233 // Update switchVar and jump to the end of loop 234 new StoreInst(sel, load->getPointerOperand(), i); 235 BranchInst::Create(loopEnd, i); 236 continue; 237 } 238 }
1 2 #include<stdio.h> 3 4 int add(int a, int b) __attribute__((__annotate__(("fla")))){ 5 if(a > b){ 6 printf("a>b,print\n"); 7 return a + b; 8 }else{ 9 printf("a<=b, print2\n"); 10 return b; 11 } 12 }