├── .gitignore ├── CMakeLists.txt ├── LICENSE.TXT ├── README.md ├── build.sh ├── obfuscator-llvm ├── BogusControlFlow.cpp ├── BogusControlFlow.h ├── CMakeLists.txt ├── CryptoUtils.cpp ├── CryptoUtils.h ├── Flattening.cpp ├── Flattening.h ├── Obfuscation.cpp ├── SplitBasicBlocks.cpp ├── SplitBasicBlocks.h ├── Substitution.cpp ├── Substitution.h ├── Utils.cpp └── Utils.h ├── test.sh └── test └── test.c /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.ll 3 | *.o 4 | test/test 5 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4) 2 | 3 | find_package(LLVM REQUIRED CONFIG) 4 | add_definitions(${LLVM_DEFINITIONS}) 5 | include_directories(${LLVM_INCLUDE_DIRS}) 6 | link_directories(${LLVM_LIBRARY_DIRS}) 7 | list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") 8 | include(HandleLLVMOptions) 9 | include(AddLLVM) 10 | 11 | add_subdirectory(obfuscator-llvm) 12 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | Obfuscator-LLVM Release License 3 | ============================================================================== 4 | University of Illinois/NCSA 5 | Open Source License 6 | 7 | Copyright (c) 2014 Haute Ecole d'Ingénierie et de Gestion du Canton de Vaud (HEIG-VD). All rights reserved. 8 | 9 | Developed by: 10 | 11 | Obfuscator-LLVM Team 12 | 13 | Haute-Ecole d'Ingénierie et de Gestion du Canton de Vaud (HEIG-VD), a part 14 | of the University of Applied Sciences and Arts Western Switzerland (HES-SO) 15 | 16 | http://o-llvm.org 17 | 18 | Permission is hereby granted, free of charge, to any person obtaining a copy of 19 | this software and associated documentation files (the "Software"), to deal with 20 | the Software without restriction, including without limitation the rights to 21 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 22 | of the Software, and to permit persons to whom the Software is furnished to do 23 | so, subject to the following conditions: 24 | 25 | * Redistributions of source code must retain the above copyright notice, 26 | this list of conditions and the following disclaimers. 27 | 28 | * Redistributions in binary form must reproduce the above copyright notice, 29 | this list of conditions and the following disclaimers in the 30 | documentation and/or other materials provided with the distribution. 31 | 32 | * Neither the names of the Obfuscator-LLVM Team, the Haute Ecole d'Ingénierie 33 | et de Gestion du Canton de Vaud (HEIG-VD), the University of Applied Sciences 34 | and Arts Western Switzerland (HES-SO) nor the names of its contributors 35 | may be used to endorse or promote products derived from this Software 36 | without specific prior written permission. 37 | 38 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 39 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 40 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 41 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 42 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 43 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE 44 | SOFTWARE. 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Obfuscator-LLVM 2 | 3 | Obfuscator-LLVM is a project initiated in June 2010 by the information security group of the University of Applied Sciences and Arts Western Switzerland of Yverdon-les-Bains ([HEIG-VD](http://www.heig-vd.ch/international)). The aim of this project is to provide increased software security through code obfuscation and tamper-proofing. As the obfuscator currently mostly works at the Intermediate Representation (IR) level, the tool is compatible with all programming languages (Ada, C, C++, D, Delphi, Fortran, Haskell, Julia, Objective-C, Rust and Swift) and target platforms (x86, x86-64, PowerPC, PowerPC-64, ARM, RISC-V, Thumb, SPARC, Alpha, CellSPU, MIPS, MSP430, SystemZ, and XCore) currently supported by LLVM version 13. The initially published source code and research paper can be found [here](https://github.com/obfuscator-llvm/obfuscator). This fork makes the obfuscator available as an extension to most available LLVM installations. It doesn't require any changes to existing LLVM installations, unlike the project published by the authors of Obfuscator-LLVM. 4 | 5 | ## Features 6 | 7 | Here is a list of the different features that are currently available: 8 | 9 | * [Instructions Substitution](https://github.com/obfuscator-llvm/obfuscator/wiki/Instructions-Substitution) `-mllvm -sub` (only old PassManager) 10 | * [Bogus Control Flow](https://github.com/obfuscator-llvm/obfuscator/wiki/Bogus-Control-Flow) `-mllvm -bcf` (only old PassManager) 11 | * [Control Flow Flattening](https://github.com/obfuscator-llvm/obfuscator/wiki/Control-Flow-Flattening) `-mllvm -fla` (only old PassManager) 12 | * [Functions annotations](https://github.com/obfuscator-llvm/obfuscator/wiki/Functions-annotations) (any pass manager) 13 | 14 | ## Building 15 | 16 | To build this project it's required to have Clang 3.3+, LLVM 3.3+ and CMake 3.4+ installed. On Ubuntu 18.04+ you can use `sudo apt install clang-7 llvm-7-dev cmake` to install the required softwre. To compile the obfuscator simply run `./build.sh` or execute the following commands in this directory: 17 | 18 | ```bash 19 | mkdir -p build 20 | cd build 21 | cmake ../ 22 | cmake --build . 23 | ``` 24 | 25 | To build for old PassManager add CMake flag `-DLLVM_ENABLE_NEW_PASS_MANAGER=OFF`. 26 | 27 | ## Usage 28 | 29 | Adding the obfuscator to existing projects which use an LLVM compiler is very easy. For the Make (or rather Makefile) buildsystem simply adjust the small example below to fit your needs: 30 | 31 | ```makefile 32 | OBFUSCATOR_FLAGS=-Xclang -load -Xclang /path/to/ObfuscatorLLVM.so 33 | 34 | # ... your targets 35 | 36 | tool: tool.c utils.c helper.c clangtool.so 37 | $(CC) $(CXXFLAGS) $(OBFUSCATOR_FLAGS) -O0 -o test test.c 38 | ``` 39 | 40 | You can also integrate the obfuscator to your existing CMake projects for any project that uses LLVM: 41 | 42 | ```cmake 43 | target_compile_options( PRIVATE -Xclang -load -Xclang /path/to/ObfuscatorLLVM.so) 44 | ``` 45 | 46 | ## Testing 47 | 48 | The [Himeno benchmark](http://accc.riken.jp/en/supercom/documents/himenobmt/) is used to test the effectiveness of the obfuscation techniques. To execute the obfuscator test run `./test.sh`. This will generate LLVM IR from `./test/test.c`, apply obfuscations on it and run the obfuscated program. The obfuscated LLVM IR can be found in `./test/test_obfuscated.ll` and the non-obfuscated LLVM IR in `./test/test.ll`. 49 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p build 4 | cd build 5 | cmake ../ 6 | cmake --build . 7 | -------------------------------------------------------------------------------- /obfuscator-llvm/BogusControlFlow.cpp: -------------------------------------------------------------------------------- 1 | //===- BogusControlFlow.cpp - BogusControlFlow Obfuscation pass ----------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===---------------------------------------------------------------------===// 9 | // 10 | // This file implements BogusControlFlow's pass, inserting bogus control flow. 11 | // It adds bogus flow to a given basic block this way: 12 | // 13 | // Before : 14 | // entry 15 | // | 16 | // ______v______ 17 | // | Original | 18 | // |_____________| 19 | // | 20 | // v 21 | // return 22 | // 23 | // After : 24 | // entry 25 | // | 26 | // ____v_____ 27 | // |condition*| (false) 28 | // |__________|----+ 29 | // (true)| | 30 | // | | 31 | // ______v______ | 32 | // +-->| Original* | | 33 | // | |_____________| (true) 34 | // | (false)| !-----------> return 35 | // | ______v______ | 36 | // | | Altered |<--! 37 | // | |_____________| 38 | // |__________| 39 | // 40 | // * The results of these terminator's branch's conditions are always true, but 41 | // these predicates are 42 | // opacificated. For this, we declare two global values: x and y, and replace 43 | // the FCMP_TRUE predicate with (y < 10 || x * (x + 1) % 2 == 0) (this could 44 | // be improved, as the global values give a hint on where are the opaque 45 | // predicates) 46 | // 47 | // The altered bloc is a copy of the original's one with junk instructions 48 | // added accordingly to the type of instructions we found in the bloc 49 | // 50 | // Each basic block of the function is choosen if a random number in the range 51 | // [0,100] is smaller than the choosen probability rate. The default value 52 | // is 30. This value can be modify using the option -boguscf-prob=[value]. 53 | // Value must be an integer in the range [0, 100], otherwise the default value 54 | // is taken. Exemple: -bcf -bcf_prob=60 55 | // 56 | // The pass can also be loop many times on a function, including on the basic 57 | // blocks added in a previous loop. Be careful if you use a big probability 58 | // number and choose to run the loop many times wich may cause the pass to run 59 | // for a very long time. The default value is one loop, but you can change it 60 | // with -boguscf-loop=[value]. Value must be an integer greater than 1, 61 | // otherwise the default value is taken. Exemple: -bcf -bcf_loop=2 62 | // 63 | // 64 | // Defined debug types: 65 | // - "gen" : general informations 66 | // - "opt" : concerning the given options (parameter) 67 | // - "cfg" : printing the various function's cfg before transformation 68 | // and after transformation if it has been modified, and all 69 | // the functions at end of the pass, after doFinalization. 70 | // 71 | // To use them all, simply use the -debug option. 72 | // To use only one of them, follow the pass' command by -debug-only=name. 73 | // Exemple, -bcf -debug-only=cfg 74 | // 75 | // 76 | // Stats: 77 | // The following statistics will be printed if you use 78 | // the -stats command: 79 | // 80 | // a. Number of functions in this module 81 | // b. Number of times we run on each function 82 | // c. Initial number of basic blocks in this module 83 | // d. Number of modified basic blocks 84 | // e. Number of added basic blocks in this module 85 | // f. Final number of basic blocks in this module 86 | // 87 | // file : lib/Transforms/Obfuscation/BogusControlFlow.cpp 88 | // date : june 2012 89 | // version: 1.0 90 | // author : julie.michielin@gmail.com 91 | // modifications: pjunod, Rinaldini Julien 92 | // project: Obfuscator 93 | // option : -bcf 94 | // 95 | //===---------------------------------------------------------------------===// 96 | 97 | #include "BogusControlFlow.h" 98 | #include "Utils.h" 99 | 100 | // Stats 101 | #define DEBUG_TYPE "BogusControlFlow" 102 | STATISTIC(NumFunction, "a. Number of functions in this module"); 103 | STATISTIC(NumTimesOnFunctions, "b. Number of times we run on each function"); 104 | STATISTIC(InitNumBasicBlocks, 105 | "c. Initial number of basic blocks in this module"); 106 | STATISTIC(NumModifiedBasicBlocks, "d. Number of modified basic blocks"); 107 | STATISTIC(NumAddedBasicBlocks, 108 | "e. Number of added basic blocks in this module"); 109 | STATISTIC(FinalNumBasicBlocks, 110 | "f. Final number of basic blocks in this module"); 111 | 112 | using namespace llvm; 113 | 114 | // Options for the pass 115 | const int defaultObfRate = 30, defaultObfTime = 1; 116 | 117 | static cl::opt BogusControlFlowFlag("bcf", cl::init(false), 118 | cl::desc("Enable bogus control flow")); 119 | 120 | static cl::opt 121 | ObfProbRate("bcf_prob", 122 | cl::desc("Choose the probability [%] each basic blocks will be " 123 | "obfuscated by the -bcf pass"), 124 | cl::value_desc("probability rate"), cl::init(defaultObfRate), 125 | cl::Optional); 126 | 127 | static cl::opt 128 | ObfTimes("bcf_loop", 129 | cl::desc("Choose how many time the -bcf pass loop on a function"), 130 | cl::value_desc("number of times"), cl::init(defaultObfTime), 131 | cl::Optional); 132 | 133 | namespace { 134 | struct BogusControlFlow : public FunctionPass { 135 | static char ID; // Pass identification 136 | BogusControlFlow() : FunctionPass(ID) {} 137 | 138 | /* runOnFunction 139 | * 140 | * Overwrite FunctionPass method to apply the transformation 141 | * to the function. See header for more details. 142 | */ 143 | virtual bool runOnFunction(Function &F) { 144 | // Check if the percentage is correct 145 | auto probs = readAnnotate(&F, ObfProbRate.ArgStr); 146 | if (!probs.empty()) { 147 | int value = ObfProbRate; 148 | if (!probs.getAsInteger(0, value)) 149 | ObfProbRate.setValue(value); 150 | } 151 | auto loops = readAnnotate(&F, ObfTimes.ArgStr); 152 | if (!loops.empty()) { 153 | int value = ObfTimes; 154 | if (!loops.getAsInteger(0, value)) 155 | ObfTimes.setValue(value); 156 | } 157 | if (ObfTimes <= 0) { 158 | errs() << "BogusControlFlow application number -bcf_loop=x must be x > 0"; 159 | return false; 160 | } 161 | 162 | // Check if the number of applications is correct 163 | if (!((ObfProbRate > 0) && (ObfProbRate <= 100))) { 164 | errs() << "BogusControlFlow application basic blocks percentage " 165 | "-bcf_prob=x must be 0 < x <= 100"; 166 | return false; 167 | } 168 | // If fla annotations 169 | if (toObfuscate(BogusControlFlowFlag, &F, "bcf")) { 170 | bogus(F); 171 | doF(*F.getParent()); 172 | return true; 173 | } 174 | 175 | return false; 176 | } // end of runOnFunction() 177 | 178 | void bogus(Function &F) { 179 | // For statistics and debug 180 | ++NumFunction; 181 | int NumBasicBlocks = 0; 182 | bool firstTime = true; // First time we do the loop in this function 183 | bool hasBeenModified = false; 184 | DEBUG_WITH_TYPE("opt", errs() << "bcf: Started on function " << F.getName() 185 | << "\n"); 186 | DEBUG_WITH_TYPE("opt", 187 | errs() << "bcf: Probability rate: " << ObfProbRate << "\n"); 188 | if (ObfProbRate < 0 || ObfProbRate > 100) { 189 | DEBUG_WITH_TYPE("opt", errs() 190 | << "bcf: Incorrect value," 191 | << " probability rate set to default value: " 192 | << defaultObfRate << " \n"); 193 | ObfProbRate = defaultObfRate; 194 | } 195 | DEBUG_WITH_TYPE("opt", errs() 196 | << "bcf: How many times: " << ObfTimes << "\n"); 197 | if (ObfTimes <= 0) { 198 | DEBUG_WITH_TYPE("opt", errs() 199 | << "bcf: Incorrect value," 200 | << " must be greater than 1. Set to default: " 201 | << defaultObfTime << " \n"); 202 | ObfTimes = defaultObfTime; 203 | } 204 | NumTimesOnFunctions = ObfTimes; 205 | int NumObfTimes = ObfTimes; 206 | 207 | // Real begining of the pass 208 | // Loop for the number of time we run the pass on the function 209 | do { 210 | DEBUG_WITH_TYPE("cfg", errs() << "bcf: Function " << F.getName() 211 | << ", before the pass:\n"); 212 | DEBUG_WITH_TYPE("cfg", F.viewCFG()); 213 | // Put all the function's block in a list 214 | std::list basicBlocks; 215 | for (Function::iterator i = F.begin(); i != F.end(); ++i) { 216 | basicBlocks.push_back(&*i); 217 | } 218 | DEBUG_WITH_TYPE( 219 | "gen", errs() << "bcf: Iterating on the Function's Basic Blocks\n"); 220 | 221 | while (!basicBlocks.empty()) { 222 | NumBasicBlocks++; 223 | // Basic Blocks' selection 224 | if ((int)llvm::cryptoutils->get_range(100) <= ObfProbRate) { 225 | DEBUG_WITH_TYPE("opt", errs() << "bcf: Block " << NumBasicBlocks 226 | << " selected. \n"); 227 | hasBeenModified = true; 228 | ++NumModifiedBasicBlocks; 229 | NumAddedBasicBlocks += 3; 230 | FinalNumBasicBlocks += 3; 231 | // Add bogus flow to the given Basic Block (see description) 232 | BasicBlock *basicBlock = basicBlocks.front(); 233 | addBogusFlow(basicBlock, F); 234 | } else { 235 | DEBUG_WITH_TYPE("opt", errs() << "bcf: Block " << NumBasicBlocks 236 | << " not selected.\n"); 237 | } 238 | // remove the block from the list 239 | basicBlocks.pop_front(); 240 | 241 | if (firstTime) { // first time we iterate on this function 242 | ++InitNumBasicBlocks; 243 | ++FinalNumBasicBlocks; 244 | } 245 | } // end of while(!basicBlocks.empty()) 246 | DEBUG_WITH_TYPE("gen", 247 | errs() << "bcf: End of function " << F.getName() << "\n"); 248 | if (hasBeenModified) { // if the function has been modified 249 | DEBUG_WITH_TYPE("cfg", errs() << "bcf: Function " << F.getName() 250 | << ", after the pass: \n"); 251 | DEBUG_WITH_TYPE("cfg", F.viewCFG()); 252 | } else { 253 | DEBUG_WITH_TYPE("cfg", errs() 254 | << "bcf: Function's not been modified \n"); 255 | } 256 | firstTime = false; 257 | } while (--NumObfTimes > 0); 258 | } 259 | 260 | /* addBogusFlow 261 | * 262 | * Add bogus flow to a given basic block, according to the header's 263 | * description 264 | */ 265 | virtual void addBogusFlow(BasicBlock *basicBlock, Function &F) { 266 | 267 | // Split the block: first part with only the phi nodes and debug info and 268 | // terminator 269 | // created by splitBasicBlock. (-> No instruction) 270 | // Second part with every instructions from the original 271 | // block 272 | // We do this way, so we don't have to adjust all the phi nodes, metadatas 273 | // and so on for the first block. We have to let the phi nodes in the first 274 | // part, because they actually are updated in the second part according to 275 | // them. 276 | BasicBlock::iterator i1 = basicBlock->begin(); 277 | if (basicBlock->getFirstNonPHIOrDbgOrLifetime()) 278 | i1 = (BasicBlock::iterator)basicBlock->getFirstNonPHIOrDbgOrLifetime(); 279 | Twine *var; 280 | var = new Twine("originalBB"); 281 | BasicBlock *originalBB = basicBlock->splitBasicBlock(i1, *var); 282 | DEBUG_WITH_TYPE("gen", errs() 283 | << "bcf: First and original basic blocks: ok\n"); 284 | 285 | // Creating the altered basic block on which the first basicBlock will jump 286 | Twine *var3 = new Twine("alteredBB"); 287 | BasicBlock *alteredBB = createAlteredBasicBlock(originalBB, *var3, &F); 288 | DEBUG_WITH_TYPE("gen", errs() << "bcf: Altered basic block: ok\n"); 289 | 290 | // Now that all the blocks are created, 291 | // we modify the terminators to adjust the control flow. 292 | 293 | alteredBB->getTerminator()->eraseFromParent(); 294 | basicBlock->getTerminator()->eraseFromParent(); 295 | DEBUG_WITH_TYPE("gen", errs() << "bcf: Terminator removed from the altered" 296 | << " and first basic blocks\n"); 297 | 298 | // Preparing a condition.. 299 | // For now, the condition is an always true comparaison between 2 float 300 | // This will be complicated after the pass (in doFinalization()) 301 | Value *LHS = ConstantFP::get(Type::getFloatTy(F.getContext()), 1.0); 302 | Value *RHS = ConstantFP::get(Type::getFloatTy(F.getContext()), 1.0); 303 | DEBUG_WITH_TYPE("gen", errs() << "bcf: Value LHS and RHS created\n"); 304 | 305 | // The always true condition. End of the first block 306 | Twine *var4 = new Twine("condition"); 307 | FCmpInst *condition = 308 | new FCmpInst(*basicBlock, FCmpInst::FCMP_TRUE, LHS, RHS, *var4); 309 | DEBUG_WITH_TYPE("gen", errs() << "bcf: Always true condition created\n"); 310 | 311 | // Jump to the original basic block if the condition is true or 312 | // to the altered block if false. 313 | BranchInst::Create(originalBB, alteredBB, (Value *)condition, basicBlock); 314 | DEBUG_WITH_TYPE( 315 | "gen", 316 | errs() << "bcf: Terminator instruction in first basic block: ok\n"); 317 | 318 | // The altered block loop back on the original one. 319 | BranchInst::Create(originalBB, alteredBB); 320 | DEBUG_WITH_TYPE( 321 | "gen", errs() << "bcf: Terminator instruction in altered block: ok\n"); 322 | 323 | // The end of the originalBB is modified to give the impression that 324 | // sometimes it continues in the loop, and sometimes it return the desired 325 | // value (of course it's always true, so it always use the original 326 | // terminator.. 327 | // but this will be obfuscated too;) ) 328 | 329 | // iterate on instruction just before the terminator of the originalBB 330 | BasicBlock::iterator i = originalBB->end(); 331 | 332 | // Split at this point (we only want the terminator in the second part) 333 | Twine *var5 = new Twine("originalBBpart2"); 334 | BasicBlock *originalBBpart2 = originalBB->splitBasicBlock(--i, *var5); 335 | DEBUG_WITH_TYPE("gen", 336 | errs() << "bcf: Terminator part of the original basic block" 337 | << " is isolated\n"); 338 | // the first part go either on the return statement or on the begining 339 | // of the altered block.. So we erase the terminator created when splitting. 340 | originalBB->getTerminator()->eraseFromParent(); 341 | // We add at the end a new always true condition 342 | Twine *var6 = new Twine("condition2"); 343 | FCmpInst *condition2 = 344 | new FCmpInst(*originalBB, CmpInst::FCMP_TRUE, LHS, RHS, *var6); 345 | BranchInst::Create(originalBBpart2, alteredBB, (Value *)condition2, 346 | originalBB); 347 | DEBUG_WITH_TYPE("gen", errs() 348 | << "bcf: Terminator original basic block: ok\n"); 349 | DEBUG_WITH_TYPE("gen", errs() << "bcf: End of addBogusFlow().\n"); 350 | 351 | } // end of addBogusFlow() 352 | 353 | /* createAlteredBasicBlock 354 | * 355 | * This function return a basic block similar to a given one. 356 | * It's inserted just after the given basic block. 357 | * The instructions are similar but junk instructions are added between 358 | * the cloned one. The cloned instructions' phi nodes, metadatas, uses and 359 | * debug locations are adjusted to fit in the cloned basic block and 360 | * behave nicely. 361 | */ 362 | virtual BasicBlock *createAlteredBasicBlock(BasicBlock *basicBlock, 363 | const Twine &Name = "gen", 364 | Function *F = 0) { 365 | // Useful to remap the informations concerning instructions. 366 | ValueToValueMapTy VMap; 367 | BasicBlock *alteredBB = llvm::CloneBasicBlock(basicBlock, VMap, Name, F); 368 | DEBUG_WITH_TYPE("gen", errs() << "bcf: Original basic block cloned\n"); 369 | // Remap operands. 370 | BasicBlock::iterator ji = basicBlock->begin(); 371 | for (BasicBlock::iterator i = alteredBB->begin(), e = alteredBB->end(); 372 | i != e; ++i) { 373 | // Loop over the operands of the instruction 374 | for (User::op_iterator opi = i->op_begin(), ope = i->op_end(); opi != ope; 375 | ++opi) { 376 | // get the value for the operand 377 | Value *v = MapValue(*opi, VMap, RF_None, 0); 378 | if (v != 0) { 379 | *opi = v; 380 | DEBUG_WITH_TYPE("gen", 381 | errs() << "bcf: Value's operand has been setted\n"); 382 | } 383 | } 384 | DEBUG_WITH_TYPE("gen", errs() << "bcf: Operands remapped\n"); 385 | // Remap phi nodes' incoming blocks. 386 | if (PHINode *pn = dyn_cast(i)) { 387 | for (unsigned j = 0, e = pn->getNumIncomingValues(); j != e; ++j) { 388 | Value *v = MapValue(pn->getIncomingBlock(j), VMap, RF_None, 0); 389 | if (v != 0) { 390 | pn->setIncomingBlock(j, cast(v)); 391 | } 392 | } 393 | } 394 | DEBUG_WITH_TYPE("gen", errs() << "bcf: PHINodes remapped\n"); 395 | // Remap attached metadata. 396 | SmallVector, 4> MDs; 397 | i->getAllMetadata(MDs); 398 | DEBUG_WITH_TYPE("gen", errs() << "bcf: Metadatas remapped\n"); 399 | // important for compiling with DWARF, using option -g. 400 | i->setDebugLoc(ji->getDebugLoc()); 401 | ji++; 402 | DEBUG_WITH_TYPE("gen", errs() 403 | << "bcf: Debug information location setted\n"); 404 | 405 | } // The instructions' informations are now all correct 406 | 407 | DEBUG_WITH_TYPE("gen", 408 | errs() << "bcf: The cloned basic block is now correct\n"); 409 | DEBUG_WITH_TYPE( 410 | "gen", 411 | errs() << "bcf: Starting to add junk code in the cloned bloc...\n"); 412 | 413 | // add random instruction in the middle of the bloc. This part can be 414 | // improve 415 | for (BasicBlock::iterator i = alteredBB->begin(), e = alteredBB->end(); 416 | i != e; ++i) { 417 | // in the case we find binary operator, we modify slightly this part by 418 | // randomly insert some instructions 419 | if (i->isBinaryOp()) { // binary instructions 420 | unsigned opcode = i->getOpcode(); 421 | BinaryOperator *op, *op1 = NULL; 422 | UnaryOperator *op2; 423 | Twine *var = new Twine("_"); 424 | // treat differently float or int 425 | // Binary int 426 | if (opcode == Instruction::Add || opcode == Instruction::Sub || 427 | opcode == Instruction::Mul || opcode == Instruction::UDiv || 428 | opcode == Instruction::SDiv || opcode == Instruction::URem || 429 | opcode == Instruction::SRem || opcode == Instruction::Shl || 430 | opcode == Instruction::LShr || opcode == Instruction::AShr || 431 | opcode == Instruction::And || opcode == Instruction::Or || 432 | opcode == Instruction::Xor) { 433 | for (int random = (int)llvm::cryptoutils->get_range(10); random < 10; 434 | ++random) { 435 | switch (llvm::cryptoutils->get_range(4)) { // to improve 436 | case 0: // do nothing 437 | break; 438 | case 1: 439 | op = BinaryOperator::CreateNeg(i->getOperand(0), *var, &*i); 440 | op1 = BinaryOperator::Create(Instruction::Add, op, 441 | i->getOperand(1), "gen", &*i); 442 | break; 443 | case 2: 444 | op1 = BinaryOperator::Create(Instruction::Sub, i->getOperand(0), 445 | i->getOperand(1), *var, &*i); 446 | op = BinaryOperator::Create(Instruction::Mul, op1, 447 | i->getOperand(1), "gen", &*i); 448 | break; 449 | case 3: 450 | op = BinaryOperator::Create(Instruction::Shl, i->getOperand(0), 451 | i->getOperand(1), *var, &*i); 452 | break; 453 | } 454 | } 455 | } 456 | // Binary float 457 | if (opcode == Instruction::FAdd || opcode == Instruction::FSub || 458 | opcode == Instruction::FMul || opcode == Instruction::FDiv || 459 | opcode == Instruction::FRem) { 460 | for (int random = (int)llvm::cryptoutils->get_range(10); random < 10; 461 | ++random) { 462 | switch (llvm::cryptoutils->get_range(3)) { // can be improved 463 | case 0: // do nothing 464 | break; 465 | case 1: 466 | op2 = UnaryOperator::CreateFNeg(i->getOperand(0),*var,&*i); 467 | op1 = BinaryOperator::Create(Instruction::FAdd,op2, 468 | i->getOperand(1),"gen",&*i); 469 | break; 470 | case 2: 471 | op = BinaryOperator::Create(Instruction::FSub, i->getOperand(0), 472 | i->getOperand(1), *var, &*i); 473 | op1 = BinaryOperator::Create(Instruction::FMul, op, 474 | i->getOperand(1), "gen", &*i); 475 | break; 476 | } 477 | } 478 | } 479 | if (opcode == Instruction::ICmp) { // Condition (with int) 480 | ICmpInst *currentI = (ICmpInst *)(&i); 481 | switch (llvm::cryptoutils->get_range(3)) { // must be improved 482 | case 0: // do nothing 483 | break; 484 | case 1: 485 | currentI->swapOperands(); 486 | break; 487 | case 2: // randomly change the predicate 488 | switch (llvm::cryptoutils->get_range(10)) { 489 | case 0: 490 | currentI->setPredicate(ICmpInst::ICMP_EQ); 491 | break; // equal 492 | case 1: 493 | currentI->setPredicate(ICmpInst::ICMP_NE); 494 | break; // not equal 495 | case 2: 496 | currentI->setPredicate(ICmpInst::ICMP_UGT); 497 | break; // unsigned greater than 498 | case 3: 499 | currentI->setPredicate(ICmpInst::ICMP_UGE); 500 | break; // unsigned greater or equal 501 | case 4: 502 | currentI->setPredicate(ICmpInst::ICMP_ULT); 503 | break; // unsigned less than 504 | case 5: 505 | currentI->setPredicate(ICmpInst::ICMP_ULE); 506 | break; // unsigned less or equal 507 | case 6: 508 | currentI->setPredicate(ICmpInst::ICMP_SGT); 509 | break; // signed greater than 510 | case 7: 511 | currentI->setPredicate(ICmpInst::ICMP_SGE); 512 | break; // signed greater or equal 513 | case 8: 514 | currentI->setPredicate(ICmpInst::ICMP_SLT); 515 | break; // signed less than 516 | case 9: 517 | currentI->setPredicate(ICmpInst::ICMP_SLE); 518 | break; // signed less or equal 519 | } 520 | break; 521 | } 522 | } 523 | if (opcode == Instruction::FCmp) { // Conditions (with float) 524 | FCmpInst *currentI = (FCmpInst *)(&i); 525 | switch (llvm::cryptoutils->get_range(3)) { // must be improved 526 | case 0: // do nothing 527 | break; 528 | case 1: 529 | currentI->swapOperands(); 530 | break; 531 | case 2: // randomly change the predicate 532 | switch (llvm::cryptoutils->get_range(10)) { 533 | case 0: 534 | currentI->setPredicate(FCmpInst::FCMP_OEQ); 535 | break; // ordered and equal 536 | case 1: 537 | currentI->setPredicate(FCmpInst::FCMP_ONE); 538 | break; // ordered and operands are unequal 539 | case 2: 540 | currentI->setPredicate(FCmpInst::FCMP_UGT); 541 | break; // unordered or greater than 542 | case 3: 543 | currentI->setPredicate(FCmpInst::FCMP_UGE); 544 | break; // unordered, or greater than, or equal 545 | case 4: 546 | currentI->setPredicate(FCmpInst::FCMP_ULT); 547 | break; // unordered or less than 548 | case 5: 549 | currentI->setPredicate(FCmpInst::FCMP_ULE); 550 | break; // unordered, or less than, or equal 551 | case 6: 552 | currentI->setPredicate(FCmpInst::FCMP_OGT); 553 | break; // ordered and greater than 554 | case 7: 555 | currentI->setPredicate(FCmpInst::FCMP_OGE); 556 | break; // ordered and greater than or equal 557 | case 8: 558 | currentI->setPredicate(FCmpInst::FCMP_OLT); 559 | break; // ordered and less than 560 | case 9: 561 | currentI->setPredicate(FCmpInst::FCMP_OLE); 562 | break; // ordered or less than, or equal 563 | } 564 | break; 565 | } 566 | } 567 | } 568 | } 569 | return alteredBB; 570 | } // end of createAlteredBasicBlock() 571 | 572 | /* doFinalization 573 | * 574 | * Overwrite FunctionPass method to apply the transformations to the whole 575 | * module. This part obfuscate all the always true predicates of the module. 576 | * More precisely, the condition which predicate is FCMP_TRUE. 577 | * It also remove all the functions' basic blocks' and instructions' names. 578 | */ 579 | bool doF(Module &M) { 580 | // In this part we extract all always-true predicate and replace them with 581 | // opaque predicate: For this, we declare two global values: x and y, and 582 | // replace the FCMP_TRUE predicate with (y < 10 || x * (x + 1) % 2 == 0) A 583 | // better way to obfuscate the predicates would be welcome. In the meantime 584 | // we will erase the name of the basic blocks, the instructions and the 585 | // functions. 586 | DEBUG_WITH_TYPE("gen", errs() << "bcf: Starting doFinalization...\n"); 587 | 588 | // The global values 589 | Twine *varX = new Twine("x"); 590 | Twine *varY = new Twine("y"); 591 | Value *x1 = ConstantInt::get(Type::getInt32Ty(M.getContext()), 0, false); 592 | Value *y1 = ConstantInt::get(Type::getInt32Ty(M.getContext()), 0, false); 593 | 594 | GlobalVariable *x = 595 | new GlobalVariable(M, Type::getInt32Ty(M.getContext()), false, 596 | GlobalValue::CommonLinkage, (Constant *)x1, *varX); 597 | GlobalVariable *y = 598 | new GlobalVariable(M, Type::getInt32Ty(M.getContext()), false, 599 | GlobalValue::CommonLinkage, (Constant *)y1, *varY); 600 | 601 | std::vector toEdit, toDelete; 602 | BinaryOperator *op, *op1 = NULL; 603 | LoadInst *opX, *opY; 604 | ICmpInst *condition, *condition2; 605 | // Looking for the conditions and branches to transform 606 | for (Module::iterator mi = M.begin(), me = M.end(); mi != me; ++mi) { 607 | for (Function::iterator fi = mi->begin(), fe = mi->end(); fi != fe; 608 | ++fi) { 609 | // fi->setName(""); 610 | Instruction *tbb = fi->getTerminator(); 611 | if (tbb->getOpcode() == Instruction::Br) { 612 | BranchInst *br = (BranchInst *)(tbb); 613 | if (br->isConditional()) { 614 | FCmpInst *cond = (FCmpInst *)br->getCondition(); 615 | unsigned opcode = cond->getOpcode(); 616 | if (opcode == Instruction::FCmp) { 617 | if (cond->getPredicate() == FCmpInst::FCMP_TRUE) { 618 | DEBUG_WITH_TYPE("gen", 619 | errs() << "bcf: an always true predicate !\n"); 620 | toDelete.push_back(cond); // The condition 621 | toEdit.push_back(tbb); // The branch using the condition 622 | } 623 | } 624 | } 625 | } 626 | /* 627 | for (BasicBlock::iterator bi = fi->begin(), be = fi->end() ; bi != be; 628 | ++bi){ bi->setName(""); // setting the basic blocks' names 629 | } 630 | */ 631 | } 632 | } 633 | // Replacing all the branches we found 634 | for (std::vector::iterator i = toEdit.begin(); 635 | i != toEdit.end(); ++i) { 636 | // if y < 10 || x*(x+1) % 2 == 0 637 | opX = new LoadInst(x->getType()->getElementType(), (Value *)x, "", (*i)); 638 | opY = new LoadInst(y->getType()->getElementType(), (Value *)y, "", (*i)); 639 | 640 | op = BinaryOperator::Create( 641 | Instruction::Sub, (Value *)opX, 642 | ConstantInt::get(Type::getInt32Ty(M.getContext()), 1, false), "", 643 | (*i)); 644 | op1 = 645 | BinaryOperator::Create(Instruction::Mul, (Value *)opX, op, "", (*i)); 646 | op = BinaryOperator::Create( 647 | Instruction::URem, op1, 648 | ConstantInt::get(Type::getInt32Ty(M.getContext()), 2, false), "", 649 | (*i)); 650 | condition = new ICmpInst( 651 | (*i), ICmpInst::ICMP_EQ, op, 652 | ConstantInt::get(Type::getInt32Ty(M.getContext()), 0, false)); 653 | condition2 = new ICmpInst( 654 | (*i), ICmpInst::ICMP_SLT, opY, 655 | ConstantInt::get(Type::getInt32Ty(M.getContext()), 10, false)); 656 | op1 = BinaryOperator::Create(Instruction::Or, (Value *)condition, 657 | (Value *)condition2, "", (*i)); 658 | 659 | BranchInst::Create(((BranchInst *)*i)->getSuccessor(0), 660 | ((BranchInst *)*i)->getSuccessor(1), (Value *)op1, 661 | ((BranchInst *)*i)->getParent()); 662 | DEBUG_WITH_TYPE("gen", errs() << "bcf: Erase branch instruction:" 663 | << *((BranchInst *)*i) << "\n"); 664 | (*i)->eraseFromParent(); // erase the branch 665 | } 666 | // Erase all the associated conditions we found 667 | for (std::vector::iterator i = toDelete.begin(); 668 | i != toDelete.end(); ++i) { 669 | DEBUG_WITH_TYPE("gen", errs() << "bcf: Erase condition instruction:" 670 | << *((Instruction *)*i) << "\n"); 671 | (*i)->eraseFromParent(); 672 | } 673 | 674 | // Only for debug 675 | DEBUG_WITH_TYPE("cfg", errs() << "bcf: End of the pass, here are the " 676 | "graphs after doFinalization\n"); 677 | for (Module::iterator mi = M.begin(), me = M.end(); mi != me; ++mi) { 678 | DEBUG_WITH_TYPE("cfg", errs() 679 | << "bcf: Function " << mi->getName() << "\n"); 680 | DEBUG_WITH_TYPE("cfg", mi->viewCFG()); 681 | } 682 | 683 | return true; 684 | } // end of doFinalization 685 | }; // end of struct BogusControlFlow : public FunctionPass 686 | } // namespace 687 | 688 | char BogusControlFlow::ID = 0; 689 | static RegisterPass X("boguscf", 690 | "inserting bogus control flow"); 691 | 692 | Pass *llvm::createBogus() { return new BogusControlFlow(); } 693 | 694 | PreservedAnalyses BogusControlFlowPass::run(Function& F, FunctionAnalysisManager& AM) { 695 | BogusControlFlow bcf; 696 | if (bcf.runOnFunction(F)) 697 | return PreservedAnalyses::none(); 698 | return PreservedAnalyses::all(); 699 | } 700 | 701 | -------------------------------------------------------------------------------- /obfuscator-llvm/BogusControlFlow.h: -------------------------------------------------------------------------------- 1 | //===- BogusControlFlow.h - bogus control flow obfuscation pass -----------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file contains includes and defines for the bogus control flow pass 11 | // 12 | //===----------------------------------------------------------------------===// 13 | #ifndef _OBFUSCATION_BOGUSCONTROLFLOW_H_ 14 | #define _OBFUSCATION_BOGUSCONTROLFLOW_H_ 15 | 16 | #include "llvm/ADT/Statistic.h" 17 | #include "llvm/CodeGen/ISDOpcodes.h" 18 | #include "llvm/IR/BasicBlock.h" 19 | #include "llvm/IR/Constants.h" 20 | #include "llvm/IR/Function.h" 21 | #include "llvm/IR/GlobalValue.h" 22 | #include "llvm/IR/InstrTypes.h" 23 | #include "llvm/IR/Instructions.h" 24 | #include "llvm/IR/LLVMContext.h" 25 | #include "llvm/IR/Module.h" 26 | #include "llvm/IR/Type.h" 27 | #include "llvm/Pass.h" 28 | #include "llvm/Support/CommandLine.h" 29 | #include "llvm/Support/Debug.h" 30 | #include "llvm/Support/raw_ostream.h" 31 | #include "llvm/Transforms/IPO.h" 32 | #include "CryptoUtils.h" 33 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" 34 | #include "llvm/Transforms/Utils/Cloning.h" 35 | #include "llvm/IR/PassManager.h" // New PassManager 36 | 37 | namespace llvm { 38 | Pass *createBogus(); 39 | class BogusControlFlowPass : public PassInfoMixin{ // New PassManager 40 | public: 41 | PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 42 | 43 | static bool isRequired() { return true; } 44 | }; 45 | } // namespace llvm 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /obfuscator-llvm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LLVM_ENABLE_NEW_PASS_MANAGER ON CACHE BOOL "Use new PM") 2 | 3 | if (LLVM_ENABLE_NEW_PASS_MANAGER) 4 | add_llvm_pass_plugin(ObfuscatorLLVM 5 | Obfuscation.cpp 6 | CryptoUtils.cpp 7 | Substitution.cpp 8 | BogusControlFlow.cpp 9 | SplitBasicBlocks.cpp 10 | Flattening.cpp 11 | Utils.cpp 12 | ) 13 | target_link_libraries(ObfuscatorLLVM 14 | PUBLIC 15 | LLVMSupport 16 | LLVMCore 17 | LLVMipo 18 | LLVMPasses 19 | ) 20 | else() 21 | add_llvm_library(ObfuscatorLLVM MODULE 22 | # List your source files here. 23 | Obfuscation.cpp 24 | CryptoUtils.cpp 25 | Substitution.cpp 26 | BogusControlFlow.cpp 27 | SplitBasicBlocks.cpp 28 | Flattening.cpp 29 | Utils.cpp 30 | PLUGIN_TOOL 31 | opt 32 | ) 33 | endif() 34 | 35 | # Use C++11 to compile your pass (i.e., supply -std=c++11). 36 | target_compile_features(ObfuscatorLLVM PRIVATE cxx_range_for cxx_auto_type) 37 | 38 | # LLVM is (typically) built with no C++ RTTI. We need to match that; 39 | # otherwise, we'll get linker errors about missing RTTI data. 40 | set_target_properties(ObfuscatorLLVM PROPERTIES 41 | COMPILE_FLAGS "-fno-rtti -fPIC" 42 | ) 43 | 44 | # Get proper shared-library behavior (where symbols are not necessarily 45 | # resolved when the shared library is linked) on OS X. 46 | if(APPLE) 47 | set_target_properties(ObfuscatorLLVM PROPERTIES 48 | LINK_FLAGS "-undefined dynamic_lookup" 49 | ) 50 | endif(APPLE) 51 | -------------------------------------------------------------------------------- /obfuscator-llvm/CryptoUtils.cpp: -------------------------------------------------------------------------------- 1 | //===- CryptoUtils.cpp - Cryptographically Secure Pseudo-Random Generator--===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements an AES-CTR-based cryptographically secure 11 | // pseudo-random generator. 12 | // 13 | // Created on: June 22, 2012 14 | // Last modification: November 15, 2013 15 | // Author(s): jrinaldini, pjunod 16 | // 17 | //===----------------------------------------------------------------------===// 18 | 19 | #include "llvm/Support/ManagedStatic.h" 20 | #include "llvm/Support/ErrorHandling.h" 21 | #include "llvm/Support/raw_ostream.h" 22 | #include "llvm/Support/Debug.h" 23 | #include "llvm/IR/LLVMContext.h" 24 | #include "llvm/ADT/Twine.h" 25 | #include "llvm/ADT/Statistic.h" 26 | #include "CryptoUtils.h" 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | // Stats 36 | #define DEBUG_TYPE "CryptoUtils" 37 | STATISTIC(statsGetBytes, "a. Number of calls to get_bytes ()"); 38 | STATISTIC(statsGetChar, "b. Number of calls to get_char ()"); 39 | STATISTIC(statsGetUint8, "c. Number of calls to get_uint8_t ()"); 40 | STATISTIC(statsGetUint32, "d. Number of calls to get_uint32_t ()"); 41 | STATISTIC(statsGetUint64, "e. Number of calls to get_uint64_t ()"); 42 | STATISTIC(statsGetRange, "f. Number of calls to get_range ()"); 43 | STATISTIC(statsPopulate, "g. Number of calls to populate ()"); 44 | STATISTIC(statsAESEncrypt, "h. Number of calls to aes_encrypt ()"); 45 | 46 | using namespace llvm; 47 | 48 | namespace llvm { 49 | ManagedStatic cryptoutils; 50 | } 51 | 52 | const uint32_t AES_RCON[10] = { 0x01000000UL, 0x02000000UL, 0x04000000UL, 53 | 0x08000000UL, 0x10000000UL, 0x20000000UL, 54 | 0x40000000UL, 0x80000000UL, 0x1b000000UL, 55 | 0x36000000UL }; 56 | 57 | const uint32_t AES_PRECOMP_TE0[256] = { 58 | 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL, 0xfff2f20dUL, 59 | 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL, 0x60303050UL, 0x02010103UL, 60 | 0xce6767a9UL, 0x562b2b7dUL, 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 61 | 0xec76769aUL, 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL, 62 | 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL, 0x41adadecUL, 63 | 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL, 0x239c9cbfUL, 0x53a4a4f7UL, 64 | 0xe4727296UL, 0x9bc0c05bUL, 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 65 | 0x4c26266aUL, 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL, 66 | 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL, 0xe2717193UL, 67 | 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL, 0x0804040cUL, 0x95c7c752UL, 68 | 0x46232365UL, 0x9dc3c35eUL, 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 69 | 0x2f9a9ab5UL, 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL, 70 | 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL, 0x1209091bUL, 71 | 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL, 0x361b1b2dUL, 0xdc6e6eb2UL, 72 | 0xb45a5aeeUL, 0x5ba0a0fbUL, 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 73 | 0x7db3b3ceUL, 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL, 74 | 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL, 0x40202060UL, 75 | 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL, 0xd46a6abeUL, 0x8dcbcb46UL, 76 | 0x67bebed9UL, 0x7239394bUL, 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 77 | 0x85cfcf4aUL, 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL, 78 | 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL, 0x8a4545cfUL, 79 | 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL, 0xa05050f0UL, 0x783c3c44UL, 80 | 0x259f9fbaUL, 0x4ba8a8e3UL, 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 81 | 0x058f8f8aUL, 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL, 82 | 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL, 0x20101030UL, 83 | 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL, 0x81cdcd4cUL, 0x180c0c14UL, 84 | 0x26131335UL, 0xc3ecec2fUL, 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 85 | 0x2e171739UL, 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL, 86 | 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL, 0xc06060a0UL, 87 | 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL, 0x44222266UL, 0x542a2a7eUL, 88 | 0x3b9090abUL, 0x0b888883UL, 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 89 | 0x2814143cUL, 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL, 90 | 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL, 0x924949dbUL, 91 | 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL, 0x9fc2c25dUL, 0xbdd3d36eUL, 92 | 0x43acacefUL, 0xc46262a6UL, 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 93 | 0xf279798bUL, 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL, 94 | 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL, 0xd86c6cb4UL, 95 | 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL, 0xca6565afUL, 0xf47a7a8eUL, 96 | 0x47aeaee9UL, 0x10080818UL, 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 97 | 0x5c2e2e72UL, 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL, 98 | 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL, 0x964b4bddUL, 99 | 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL, 0xe0707090UL, 0x7c3e3e42UL, 100 | 0x71b5b5c4UL, 0xcc6666aaUL, 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 101 | 0x1c0e0e12UL, 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL, 102 | 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL, 0xd9e1e138UL, 103 | 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL, 0xd26969bbUL, 0xa9d9d970UL, 104 | 0x078e8e89UL, 0x339494a7UL, 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 105 | 0xc9e9e920UL, 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL, 106 | 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL, 0x65bfbfdaUL, 107 | 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL, 0x824141c3UL, 0x299999b0UL, 108 | 0x5a2d2d77UL, 0x1e0f0f11UL, 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 109 | 0x2c16163aUL 110 | }; 111 | 112 | const uint32_t AES_PRECOMP_TE1[256] = { 113 | 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL, 0x0dfff2f2UL, 114 | 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL, 0x50603030UL, 0x03020101UL, 115 | 0xa9ce6767UL, 0x7d562b2bUL, 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 116 | 0x9aec7676UL, 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL, 117 | 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL, 0xec41adadUL, 118 | 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL, 0xbf239c9cUL, 0xf753a4a4UL, 119 | 0x96e47272UL, 0x5b9bc0c0UL, 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 120 | 0x6a4c2626UL, 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL, 121 | 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL, 0x93e27171UL, 122 | 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL, 0x0c080404UL, 0x5295c7c7UL, 123 | 0x65462323UL, 0x5e9dc3c3UL, 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 124 | 0xb52f9a9aUL, 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL, 125 | 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL, 0x1b120909UL, 126 | 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL, 0x2d361b1bUL, 0xb2dc6e6eUL, 127 | 0xeeb45a5aUL, 0xfb5ba0a0UL, 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 128 | 0xce7db3b3UL, 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL, 129 | 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL, 0x60402020UL, 130 | 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL, 0xbed46a6aUL, 0x468dcbcbUL, 131 | 0xd967bebeUL, 0x4b723939UL, 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 132 | 0x4a85cfcfUL, 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL, 133 | 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL, 0xcf8a4545UL, 134 | 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL, 0xf0a05050UL, 0x44783c3cUL, 135 | 0xba259f9fUL, 0xe34ba8a8UL, 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 136 | 0x8a058f8fUL, 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL, 137 | 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL, 0x30201010UL, 138 | 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL, 0x4c81cdcdUL, 0x14180c0cUL, 139 | 0x35261313UL, 0x2fc3ececUL, 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 140 | 0x392e1717UL, 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL, 141 | 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL, 0xa0c06060UL, 142 | 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL, 0x66442222UL, 0x7e542a2aUL, 143 | 0xab3b9090UL, 0x830b8888UL, 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 144 | 0x3c281414UL, 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL, 145 | 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL, 0xdb924949UL, 146 | 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL, 0x5d9fc2c2UL, 0x6ebdd3d3UL, 147 | 0xef43acacUL, 0xa6c46262UL, 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 148 | 0x8bf27979UL, 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL, 149 | 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL, 0xb4d86c6cUL, 150 | 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL, 0xafca6565UL, 0x8ef47a7aUL, 151 | 0xe947aeaeUL, 0x18100808UL, 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 152 | 0x725c2e2eUL, 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL, 153 | 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL, 0xdd964b4bUL, 154 | 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL, 0x90e07070UL, 0x427c3e3eUL, 155 | 0xc471b5b5UL, 0xaacc6666UL, 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 156 | 0x121c0e0eUL, 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL, 157 | 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL, 0x38d9e1e1UL, 158 | 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL, 0xbbd26969UL, 0x70a9d9d9UL, 159 | 0x89078e8eUL, 0xa7339494UL, 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 160 | 0x20c9e9e9UL, 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL, 161 | 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL, 0xda65bfbfUL, 162 | 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL, 0xc3824141UL, 0xb0299999UL, 163 | 0x775a2d2dUL, 0x111e0f0fUL, 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 164 | 0x3a2c1616UL 165 | }; 166 | 167 | const uint32_t AES_PRECOMP_TE2[256] = { 168 | 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL, 0xf20dfff2UL, 169 | 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL, 0x30506030UL, 0x01030201UL, 170 | 0x67a9ce67UL, 0x2b7d562bUL, 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 171 | 0x769aec76UL, 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL, 172 | 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL, 0xadec41adUL, 173 | 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL, 0x9cbf239cUL, 0xa4f753a4UL, 174 | 0x7296e472UL, 0xc05b9bc0UL, 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 175 | 0x266a4c26UL, 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL, 176 | 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL, 0x7193e271UL, 177 | 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL, 0x040c0804UL, 0xc75295c7UL, 178 | 0x23654623UL, 0xc35e9dc3UL, 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 179 | 0x9ab52f9aUL, 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL, 180 | 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL, 0x091b1209UL, 181 | 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL, 0x1b2d361bUL, 0x6eb2dc6eUL, 182 | 0x5aeeb45aUL, 0xa0fb5ba0UL, 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 183 | 0xb3ce7db3UL, 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL, 184 | 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL, 0x20604020UL, 185 | 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL, 0x6abed46aUL, 0xcb468dcbUL, 186 | 0xbed967beUL, 0x394b7239UL, 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 187 | 0xcf4a85cfUL, 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL, 188 | 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL, 0x45cf8a45UL, 189 | 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL, 0x50f0a050UL, 0x3c44783cUL, 190 | 0x9fba259fUL, 0xa8e34ba8UL, 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 191 | 0x8f8a058fUL, 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL, 192 | 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL, 0x10302010UL, 193 | 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL, 0xcd4c81cdUL, 0x0c14180cUL, 194 | 0x13352613UL, 0xec2fc3ecUL, 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 195 | 0x17392e17UL, 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL, 196 | 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL, 0x60a0c060UL, 197 | 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL, 0x22664422UL, 0x2a7e542aUL, 198 | 0x90ab3b90UL, 0x88830b88UL, 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 199 | 0x143c2814UL, 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL, 200 | 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL, 0x49db9249UL, 201 | 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL, 0xc25d9fc2UL, 0xd36ebdd3UL, 202 | 0xacef43acUL, 0x62a6c462UL, 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 203 | 0x798bf279UL, 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL, 204 | 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL, 0x6cb4d86cUL, 205 | 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL, 0x65afca65UL, 0x7a8ef47aUL, 206 | 0xaee947aeUL, 0x08181008UL, 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 207 | 0x2e725c2eUL, 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL, 208 | 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL, 0x4bdd964bUL, 209 | 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL, 0x7090e070UL, 0x3e427c3eUL, 210 | 0xb5c471b5UL, 0x66aacc66UL, 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 211 | 0x0e121c0eUL, 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL, 212 | 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL, 0xe138d9e1UL, 213 | 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL, 0x69bbd269UL, 0xd970a9d9UL, 214 | 0x8e89078eUL, 0x94a73394UL, 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 215 | 0xe920c9e9UL, 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL, 216 | 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL, 0xbfda65bfUL, 217 | 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL, 0x41c38241UL, 0x99b02999UL, 218 | 0x2d775a2dUL, 0x0f111e0fUL, 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 219 | 0x163a2c16UL 220 | }; 221 | 222 | const uint32_t AES_PRECOMP_TE3[256] = { 223 | 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL, 0xf2f20dffUL, 224 | 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL, 0x30305060UL, 0x01010302UL, 225 | 0x6767a9ceUL, 0x2b2b7d56UL, 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 226 | 0x76769aecUL, 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL, 227 | 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL, 0xadadec41UL, 228 | 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL, 0x9c9cbf23UL, 0xa4a4f753UL, 229 | 0x727296e4UL, 0xc0c05b9bUL, 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 230 | 0x26266a4cUL, 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL, 231 | 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL, 0x717193e2UL, 232 | 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL, 0x04040c08UL, 0xc7c75295UL, 233 | 0x23236546UL, 0xc3c35e9dUL, 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 234 | 0x9a9ab52fUL, 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL, 235 | 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL, 0x09091b12UL, 236 | 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL, 0x1b1b2d36UL, 0x6e6eb2dcUL, 237 | 0x5a5aeeb4UL, 0xa0a0fb5bUL, 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 238 | 0xb3b3ce7dUL, 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL, 239 | 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL, 0x20206040UL, 240 | 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL, 0x6a6abed4UL, 0xcbcb468dUL, 241 | 0xbebed967UL, 0x39394b72UL, 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 242 | 0xcfcf4a85UL, 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL, 243 | 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL, 0x4545cf8aUL, 244 | 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL, 0x5050f0a0UL, 0x3c3c4478UL, 245 | 0x9f9fba25UL, 0xa8a8e34bUL, 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 246 | 0x8f8f8a05UL, 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL, 247 | 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL, 0x10103020UL, 248 | 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL, 0xcdcd4c81UL, 0x0c0c1418UL, 249 | 0x13133526UL, 0xecec2fc3UL, 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 250 | 0x1717392eUL, 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL, 251 | 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL, 0x6060a0c0UL, 252 | 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL, 0x22226644UL, 0x2a2a7e54UL, 253 | 0x9090ab3bUL, 0x8888830bUL, 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 254 | 0x14143c28UL, 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL, 255 | 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL, 0x4949db92UL, 256 | 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL, 0xc2c25d9fUL, 0xd3d36ebdUL, 257 | 0xacacef43UL, 0x6262a6c4UL, 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 258 | 0x79798bf2UL, 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL, 259 | 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL, 0x6c6cb4d8UL, 260 | 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL, 0x6565afcaUL, 0x7a7a8ef4UL, 261 | 0xaeaee947UL, 0x08081810UL, 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 262 | 0x2e2e725cUL, 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL, 263 | 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL, 0x4b4bdd96UL, 264 | 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL, 0x707090e0UL, 0x3e3e427cUL, 265 | 0xb5b5c471UL, 0x6666aaccUL, 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 266 | 0x0e0e121cUL, 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL, 267 | 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL, 0xe1e138d9UL, 268 | 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL, 0x6969bbd2UL, 0xd9d970a9UL, 269 | 0x8e8e8907UL, 0x9494a733UL, 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 270 | 0xe9e920c9UL, 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL, 271 | 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL, 0xbfbfda65UL, 272 | 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL, 0x4141c382UL, 0x9999b029UL, 273 | 0x2d2d775aUL, 0x0f0f111eUL, 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 274 | 0x16163a2cUL 275 | }; 276 | 277 | const uint32_t AES_PRECOMP_TE4_0[256] = { 278 | 0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 279 | 0x0000006bUL, 0x0000006fUL, 0x000000c5UL, 0x00000030UL, 0x00000001UL, 280 | 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 281 | 0x00000076UL, 0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 282 | 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL, 0x000000adUL, 283 | 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 284 | 0x00000072UL, 0x000000c0UL, 0x000000b7UL, 0x000000fdUL, 0x00000093UL, 285 | 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL, 286 | 0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 287 | 0x000000d8UL, 0x00000031UL, 0x00000015UL, 0x00000004UL, 0x000000c7UL, 288 | 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 289 | 0x0000009aUL, 0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 290 | 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL, 0x00000009UL, 291 | 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 292 | 0x0000005aUL, 0x000000a0UL, 0x00000052UL, 0x0000003bUL, 0x000000d6UL, 293 | 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL, 294 | 0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 295 | 0x000000fcUL, 0x000000b1UL, 0x0000005bUL, 0x0000006aUL, 0x000000cbUL, 296 | 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 297 | 0x000000cfUL, 0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 298 | 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL, 0x00000045UL, 299 | 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 300 | 0x0000009fUL, 0x000000a8UL, 0x00000051UL, 0x000000a3UL, 0x00000040UL, 301 | 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL, 302 | 0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 303 | 0x000000ffUL, 0x000000f3UL, 0x000000d2UL, 0x000000cdUL, 0x0000000cUL, 304 | 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 305 | 0x00000017UL, 0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 306 | 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL, 0x00000060UL, 307 | 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 308 | 0x00000090UL, 0x00000088UL, 0x00000046UL, 0x000000eeUL, 0x000000b8UL, 309 | 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL, 310 | 0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 311 | 0x00000006UL, 0x00000024UL, 0x0000005cUL, 0x000000c2UL, 0x000000d3UL, 312 | 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 313 | 0x00000079UL, 0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 314 | 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL, 0x0000006cUL, 315 | 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 316 | 0x000000aeUL, 0x00000008UL, 0x000000baUL, 0x00000078UL, 0x00000025UL, 317 | 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL, 318 | 0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 319 | 0x000000bdUL, 0x0000008bUL, 0x0000008aUL, 0x00000070UL, 0x0000003eUL, 320 | 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 321 | 0x0000000eUL, 0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 322 | 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL, 0x000000e1UL, 323 | 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 324 | 0x0000008eUL, 0x00000094UL, 0x0000009bUL, 0x0000001eUL, 0x00000087UL, 325 | 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL, 326 | 0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 327 | 0x000000e6UL, 0x00000042UL, 0x00000068UL, 0x00000041UL, 0x00000099UL, 328 | 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 329 | 0x00000016UL 330 | }; 331 | 332 | const uint32_t AES_PRECOMP_TE4_1[256] = { 333 | 0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 334 | 0x00006b00UL, 0x00006f00UL, 0x0000c500UL, 0x00003000UL, 0x00000100UL, 335 | 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 336 | 0x00007600UL, 0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 337 | 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL, 0x0000ad00UL, 338 | 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 339 | 0x00007200UL, 0x0000c000UL, 0x0000b700UL, 0x0000fd00UL, 0x00009300UL, 340 | 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL, 341 | 0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 342 | 0x0000d800UL, 0x00003100UL, 0x00001500UL, 0x00000400UL, 0x0000c700UL, 343 | 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 344 | 0x00009a00UL, 0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 345 | 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL, 0x00000900UL, 346 | 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 347 | 0x00005a00UL, 0x0000a000UL, 0x00005200UL, 0x00003b00UL, 0x0000d600UL, 348 | 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL, 349 | 0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 350 | 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL, 0x00006a00UL, 0x0000cb00UL, 351 | 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 352 | 0x0000cf00UL, 0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 353 | 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL, 0x00004500UL, 354 | 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 355 | 0x00009f00UL, 0x0000a800UL, 0x00005100UL, 0x0000a300UL, 0x00004000UL, 356 | 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL, 357 | 0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 358 | 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL, 0x0000cd00UL, 0x00000c00UL, 359 | 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 360 | 0x00001700UL, 0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 361 | 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL, 0x00006000UL, 362 | 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 363 | 0x00009000UL, 0x00008800UL, 0x00004600UL, 0x0000ee00UL, 0x0000b800UL, 364 | 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL, 365 | 0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 366 | 0x00000600UL, 0x00002400UL, 0x00005c00UL, 0x0000c200UL, 0x0000d300UL, 367 | 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 368 | 0x00007900UL, 0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 369 | 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL, 0x00006c00UL, 370 | 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 371 | 0x0000ae00UL, 0x00000800UL, 0x0000ba00UL, 0x00007800UL, 0x00002500UL, 372 | 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL, 373 | 0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 374 | 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL, 0x00007000UL, 0x00003e00UL, 375 | 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 376 | 0x00000e00UL, 0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 377 | 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL, 0x0000e100UL, 378 | 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 379 | 0x00008e00UL, 0x00009400UL, 0x00009b00UL, 0x00001e00UL, 0x00008700UL, 380 | 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL, 381 | 0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 382 | 0x0000e600UL, 0x00004200UL, 0x00006800UL, 0x00004100UL, 0x00009900UL, 383 | 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 384 | 0x00001600UL 385 | }; 386 | 387 | const uint32_t AES_PRECOMP_TE4_2[256] = { 388 | 0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 389 | 0x006b0000UL, 0x006f0000UL, 0x00c50000UL, 0x00300000UL, 0x00010000UL, 390 | 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 391 | 0x00760000UL, 0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 392 | 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL, 0x00ad0000UL, 393 | 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 394 | 0x00720000UL, 0x00c00000UL, 0x00b70000UL, 0x00fd0000UL, 0x00930000UL, 395 | 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL, 396 | 0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 397 | 0x00d80000UL, 0x00310000UL, 0x00150000UL, 0x00040000UL, 0x00c70000UL, 398 | 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 399 | 0x009a0000UL, 0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 400 | 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL, 0x00090000UL, 401 | 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 402 | 0x005a0000UL, 0x00a00000UL, 0x00520000UL, 0x003b0000UL, 0x00d60000UL, 403 | 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL, 404 | 0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 405 | 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL, 0x006a0000UL, 0x00cb0000UL, 406 | 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 407 | 0x00cf0000UL, 0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 408 | 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL, 0x00450000UL, 409 | 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 410 | 0x009f0000UL, 0x00a80000UL, 0x00510000UL, 0x00a30000UL, 0x00400000UL, 411 | 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL, 412 | 0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 413 | 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL, 0x00cd0000UL, 0x000c0000UL, 414 | 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 415 | 0x00170000UL, 0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 416 | 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL, 0x00600000UL, 417 | 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 418 | 0x00900000UL, 0x00880000UL, 0x00460000UL, 0x00ee0000UL, 0x00b80000UL, 419 | 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL, 420 | 0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 421 | 0x00060000UL, 0x00240000UL, 0x005c0000UL, 0x00c20000UL, 0x00d30000UL, 422 | 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 423 | 0x00790000UL, 0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 424 | 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL, 0x006c0000UL, 425 | 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 426 | 0x00ae0000UL, 0x00080000UL, 0x00ba0000UL, 0x00780000UL, 0x00250000UL, 427 | 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL, 428 | 0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 429 | 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL, 0x00700000UL, 0x003e0000UL, 430 | 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 431 | 0x000e0000UL, 0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 432 | 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL, 0x00e10000UL, 433 | 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 434 | 0x008e0000UL, 0x00940000UL, 0x009b0000UL, 0x001e0000UL, 0x00870000UL, 435 | 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL, 436 | 0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 437 | 0x00e60000UL, 0x00420000UL, 0x00680000UL, 0x00410000UL, 0x00990000UL, 438 | 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 439 | 0x00160000UL 440 | }; 441 | 442 | const uint32_t AES_PRECOMP_TE4_3[256] = { 443 | 0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 444 | 0x6b000000UL, 0x6f000000UL, 0xc5000000UL, 0x30000000UL, 0x01000000UL, 445 | 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 446 | 0x76000000UL, 0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 447 | 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL, 0xad000000UL, 448 | 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 449 | 0x72000000UL, 0xc0000000UL, 0xb7000000UL, 0xfd000000UL, 0x93000000UL, 450 | 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL, 451 | 0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 452 | 0xd8000000UL, 0x31000000UL, 0x15000000UL, 0x04000000UL, 0xc7000000UL, 453 | 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 454 | 0x9a000000UL, 0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 455 | 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL, 0x09000000UL, 456 | 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 457 | 0x5a000000UL, 0xa0000000UL, 0x52000000UL, 0x3b000000UL, 0xd6000000UL, 458 | 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL, 459 | 0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 460 | 0xfc000000UL, 0xb1000000UL, 0x5b000000UL, 0x6a000000UL, 0xcb000000UL, 461 | 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 462 | 0xcf000000UL, 0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 463 | 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL, 0x45000000UL, 464 | 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 465 | 0x9f000000UL, 0xa8000000UL, 0x51000000UL, 0xa3000000UL, 0x40000000UL, 466 | 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL, 467 | 0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 468 | 0xff000000UL, 0xf3000000UL, 0xd2000000UL, 0xcd000000UL, 0x0c000000UL, 469 | 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 470 | 0x17000000UL, 0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 471 | 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL, 0x60000000UL, 472 | 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 473 | 0x90000000UL, 0x88000000UL, 0x46000000UL, 0xee000000UL, 0xb8000000UL, 474 | 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL, 475 | 0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 476 | 0x06000000UL, 0x24000000UL, 0x5c000000UL, 0xc2000000UL, 0xd3000000UL, 477 | 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 478 | 0x79000000UL, 0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 479 | 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL, 0x6c000000UL, 480 | 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 481 | 0xae000000UL, 0x08000000UL, 0xba000000UL, 0x78000000UL, 0x25000000UL, 482 | 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL, 483 | 0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 484 | 0xbd000000UL, 0x8b000000UL, 0x8a000000UL, 0x70000000UL, 0x3e000000UL, 485 | 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 486 | 0x0e000000UL, 0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 487 | 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL, 0xe1000000UL, 488 | 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 489 | 0x8e000000UL, 0x94000000UL, 0x9b000000UL, 0x1e000000UL, 0x87000000UL, 490 | 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL, 491 | 0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 492 | 0xe6000000UL, 0x42000000UL, 0x68000000UL, 0x41000000UL, 0x99000000UL, 493 | 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 494 | 0x16000000UL 495 | }; 496 | 497 | const uint32_t masks[32] = { 498 | 0x80000000UL, 0x40000000UL, 0x20000000UL, 0x10000000UL, 0x08000000UL, 499 | 0x04000000UL, 0x02000000UL, 0x01000000UL, 0x00800000UL, 0x00400000UL, 500 | 0x00200000UL, 0x00100000UL, 0x00080000UL, 0x00040000UL, 0x00020000UL, 501 | 0x00010000UL, 0x00008000UL, 0x00004000UL, 0x00002000UL, 0x00001000UL, 502 | 0x00000800UL, 0x00000400UL, 0x00000200UL, 0x00000100UL, 0x00000080UL, 503 | 0x00000040UL, 0x00000020UL, 0x00000010UL, 0x00000008UL, 0x00000004UL, 504 | 0x00000002UL, 0x00000001UL 505 | }; 506 | 507 | CryptoUtils::CryptoUtils() { seeded = false; } 508 | 509 | unsigned CryptoUtils::scramble32(const unsigned in, const char key[16]) { 510 | assert(key != NULL && "CryptoUtils::scramble key=NULL"); 511 | 512 | unsigned tmpA, tmpB; 513 | 514 | // Orr, Nathan or Adi can probably break it, but who cares? 515 | 516 | // Round 1 517 | tmpA = 0x0; 518 | tmpA ^= AES_PRECOMP_TE0[((in >> 24) ^ key[0]) & 0xFF]; 519 | tmpA ^= AES_PRECOMP_TE1[((in >> 16) ^ key[1]) & 0xFF]; 520 | tmpA ^= AES_PRECOMP_TE2[((in >> 8) ^ key[2]) & 0xFF]; 521 | tmpA ^= AES_PRECOMP_TE3[((in >> 0) ^ key[3]) & 0xFF]; 522 | 523 | // Round 2 524 | tmpB = 0x0; 525 | tmpB ^= AES_PRECOMP_TE0[((tmpA >> 24) ^ key[4]) & 0xFF]; 526 | tmpB ^= AES_PRECOMP_TE1[((tmpA >> 16) ^ key[5]) & 0xFF]; 527 | tmpB ^= AES_PRECOMP_TE2[((tmpA >> 8) ^ key[6]) & 0xFF]; 528 | tmpB ^= AES_PRECOMP_TE3[((tmpA >> 0) ^ key[7]) & 0xFF]; 529 | 530 | // Round 3 531 | tmpA = 0x0; 532 | tmpA ^= AES_PRECOMP_TE0[((tmpB >> 24) ^ key[8]) & 0xFF]; 533 | tmpA ^= AES_PRECOMP_TE1[((tmpB >> 16) ^ key[9]) & 0xFF]; 534 | tmpA ^= AES_PRECOMP_TE2[((tmpB >> 8) ^ key[10]) & 0xFF]; 535 | tmpA ^= AES_PRECOMP_TE3[((tmpB >> 0) ^ key[11]) & 0xFF]; 536 | 537 | // Round 4 538 | tmpB = 0x0; 539 | tmpB ^= AES_PRECOMP_TE0[((tmpA >> 24) ^ key[12]) & 0xFF]; 540 | tmpB ^= AES_PRECOMP_TE1[((tmpA >> 16) ^ key[13]) & 0xFF]; 541 | tmpB ^= AES_PRECOMP_TE2[((tmpA >> 8) ^ key[14]) & 0xFF]; 542 | tmpB ^= AES_PRECOMP_TE3[((tmpA >> 0) ^ key[15]) & 0xFF]; 543 | 544 | LOAD32H(tmpA, key); 545 | 546 | return tmpA ^ tmpB; 547 | } 548 | 549 | bool CryptoUtils::prng_seed(const std::string _seed) { 550 | unsigned char s[16]; 551 | unsigned int i = 0; 552 | 553 | /* We accept a prefix "0x" */ 554 | if (!(_seed.size() == 32 || _seed.size() == 34)) { 555 | errs()<<"The AES-CTR PRNG seeding mechanism is expecting a 16-byte value " 556 | "expressed in hexadecimal, like DEAD....BEEF\n"; 557 | return false; 558 | } 559 | 560 | seed = _seed; 561 | 562 | if (_seed.size() == 34) { 563 | // Assuming that the two first characters are "0x" 564 | i = 2; 565 | } 566 | 567 | 568 | for (unsigned int j=0; i < _seed.size(); i += 2, j++) { 569 | std::string byte = _seed.substr(i, 2); 570 | s[j] = (unsigned char)(int)strtol(byte.c_str(), NULL, 16); 571 | } 572 | 573 | // _seed is defined to be the 574 | // key initial value 575 | memcpy(key, s, 16); 576 | DEBUG_WITH_TYPE("cryptoutils", dbgs() << "CPNRG seeded with " << _seed << "\n"); 577 | 578 | // ctr is initialized to all-zeroes 579 | memset(ctr, 0, 16); 580 | 581 | // Once the seed is there, we compute the 582 | // AES128 key-schedule 583 | aes_compute_ks(ks, key); 584 | 585 | seeded = true; 586 | 587 | // We are now ready to fill the pool with 588 | // cryptographically secure pseudo-random 589 | // values. 590 | populate_pool(); 591 | return true; 592 | } 593 | 594 | CryptoUtils::~CryptoUtils() { 595 | // Some wiping work here 596 | memset(key, 0, 16); 597 | memset(ks, 0, 44 * sizeof(uint32_t)); 598 | memset(ctr, 0, 16); 599 | memset(pool, 0, CryptoUtils_POOL_SIZE); 600 | 601 | idx = 0; 602 | } 603 | 604 | void CryptoUtils::populate_pool() { 605 | 606 | statsPopulate++; 607 | 608 | for (int i = 0; i < CryptoUtils_POOL_SIZE; i += 16) { 609 | 610 | // ctr += 1 611 | inc_ctr(); 612 | 613 | // We then encrypt the counter 614 | aes_encrypt(pool + i, ctr, ks); 615 | } 616 | 617 | // Reinitializing the index of the first 618 | // available pseudo-random byte 619 | idx = 0; 620 | } 621 | 622 | bool CryptoUtils::prng_seed() { 623 | 624 | #if defined(__linux__) 625 | std::ifstream devrandom("/dev/urandom"); 626 | #else 627 | std::ifstream devrandom("/dev/random"); 628 | #endif 629 | 630 | if (devrandom) { 631 | 632 | devrandom.read(key, 16); 633 | 634 | if (devrandom.gcount() != 16) { 635 | errs()<<"Cannot read enough bytes in /dev/random\n"; 636 | return false; 637 | } 638 | 639 | devrandom.close(); 640 | DEBUG_WITH_TYPE("cryptoutils", dbgs() << "cryptoutils seeded with /dev/random\n"); 641 | 642 | memset(ctr, 0, 16); 643 | 644 | // Once the seed is there, we compute the 645 | // AES128 key-schedule 646 | aes_compute_ks(ks, key); 647 | 648 | seeded = true; 649 | } else { 650 | errs()<<"Cannot open /dev/random\n"; 651 | return false; 652 | } 653 | return true; 654 | } 655 | 656 | void CryptoUtils::inc_ctr() { 657 | uint64_t iseed; 658 | 659 | LOAD64H(iseed, ctr + 8); 660 | ++iseed; 661 | STORE64H(ctr + 8, iseed); 662 | } 663 | 664 | char *CryptoUtils::get_seed() { 665 | 666 | if (seeded) { 667 | return key; 668 | } else { 669 | return NULL; 670 | } 671 | } 672 | 673 | void CryptoUtils::get_bytes(char *buffer, const int len) { 674 | 675 | int sofar = 0, available = 0; 676 | 677 | assert(buffer != NULL && "CryptoUtils::get_bytes buffer=NULL"); 678 | assert(len > 0 && "CryptoUtils::get_bytes len <= 0"); 679 | 680 | statsGetBytes++; 681 | 682 | if (len > 0) { 683 | 684 | // If the PRNG is not seeded, it the very last time to do it ! 685 | if (!seeded) { 686 | prng_seed(); 687 | populate_pool(); 688 | } 689 | 690 | do { 691 | if (idx + (len - sofar) >= CryptoUtils_POOL_SIZE) { 692 | // We don't have enough bytes ready in the pool, 693 | // so let's use the available ones and repopulate ! 694 | available = CryptoUtils_POOL_SIZE - idx; 695 | memcpy(buffer + sofar, pool + idx, available); 696 | sofar += available; 697 | populate_pool(); 698 | } else { 699 | memcpy(buffer + sofar, pool + idx, len - sofar); 700 | idx += len - sofar; 701 | // This will trigger a loop exit 702 | sofar = len; 703 | } 704 | } while (sofar < (len - 1)); 705 | } 706 | } 707 | 708 | uint8_t CryptoUtils::get_uint8_t() { 709 | char ret; 710 | 711 | statsGetUint8++; 712 | 713 | get_bytes(&ret, 1); 714 | 715 | return (uint8_t)ret; 716 | } 717 | 718 | char CryptoUtils::get_char() { 719 | char ret; 720 | 721 | statsGetChar++; 722 | 723 | get_bytes(&ret, 1); 724 | 725 | return ret; 726 | } 727 | 728 | uint32_t CryptoUtils::get_uint32_t() { 729 | char tmp[4]; 730 | uint32_t ret = 0; 731 | 732 | statsGetUint32++; 733 | 734 | get_bytes(tmp, 4); 735 | 736 | LOAD32H(ret, tmp); 737 | 738 | return ret; 739 | } 740 | 741 | uint64_t CryptoUtils::get_uint64_t() { 742 | char tmp[8]; 743 | uint64_t ret = 0; 744 | 745 | statsGetUint64++; 746 | 747 | get_bytes(tmp, 8); 748 | 749 | LOAD64H(ret, tmp); 750 | 751 | return ret; 752 | } 753 | 754 | uint32_t CryptoUtils::get_range(const uint32_t max) { 755 | uint32_t log, r, mask; 756 | 757 | statsGetRange++; 758 | 759 | if (max == 0) { 760 | return 0; 761 | } else { 762 | // Computing the above power of two 763 | log = 32; 764 | int i = 0; 765 | // This loop will terminate, as there is at least one 766 | // bit set somewhere in max 767 | while (!(max & masks[i++])) { 768 | log -= 1; 769 | } 770 | mask = (0x1UL << log) - 1; 771 | 772 | // This should loop two times in average 773 | do { 774 | r = get_uint32_t() & mask; 775 | } while (r >= max); 776 | 777 | return r; 778 | } 779 | } 780 | 781 | void CryptoUtils::aes_compute_ks(uint32_t *ks, const char *k) { 782 | int i; 783 | uint32_t *p, tmp; 784 | 785 | assert(ks != NULL); 786 | assert(k != NULL); 787 | 788 | LOAD32H(ks[0], k); 789 | LOAD32H(ks[1], k + 4); 790 | LOAD32H(ks[2], k + 8); 791 | LOAD32H(ks[3], k + 12); 792 | 793 | p = ks; 794 | i = 0; 795 | while (1) { 796 | tmp = p[3]; 797 | tmp = ((AES_TE4_3(BYTE(tmp, 2))) ^ (AES_TE4_2(BYTE(tmp, 1))) ^ 798 | (AES_TE4_1(BYTE(tmp, 0))) ^ (AES_TE4_0(BYTE(tmp, 3)))); 799 | 800 | p[4] = p[0] ^ tmp ^ AES_RCON[i]; 801 | p[5] = p[1] ^ p[4]; 802 | p[6] = p[2] ^ p[5]; 803 | p[7] = p[3] ^ p[6]; 804 | if (++i == 10) { 805 | break; 806 | } 807 | p += 4; 808 | } 809 | } 810 | 811 | void CryptoUtils::aes_encrypt(char *out, const char *in, const uint32_t *ks) { 812 | uint32_t state0 = 0, state1 = 0, state2 = 0, state3 = 0; 813 | uint32_t tmp0, tmp1, tmp2, tmp3; 814 | int i; 815 | uint32_t r; 816 | 817 | statsAESEncrypt++; 818 | 819 | r = 0; 820 | LOAD32H(state0, in + 0); 821 | LOAD32H(state1, in + 4); 822 | LOAD32H(state2, in + 8); 823 | LOAD32H(state3, in + 12); 824 | 825 | state0 ^= ks[r + 0]; 826 | state1 ^= ks[r + 1]; 827 | state2 ^= ks[r + 2]; 828 | state3 ^= ks[r + 3]; 829 | 830 | i = 0; 831 | while (1) { 832 | r += 4; 833 | 834 | tmp0 = AES_TE0(BYTE(state0, 3)) ^ AES_TE1(BYTE(state1, 2)) ^ 835 | AES_TE2(BYTE(state2, 1)) ^ AES_TE3(BYTE(state3, 0)) ^ ks[r + 0]; 836 | 837 | tmp1 = AES_TE0(BYTE(state1, 3)) ^ AES_TE1(BYTE(state2, 2)) ^ 838 | AES_TE2(BYTE(state3, 1)) ^ AES_TE3(BYTE(state0, 0)) ^ ks[r + 1]; 839 | 840 | tmp2 = AES_TE0(BYTE(state2, 3)) ^ AES_TE1(BYTE(state3, 2)) ^ 841 | AES_TE2(BYTE(state0, 1)) ^ AES_TE3(BYTE(state1, 0)) ^ ks[r + 2]; 842 | 843 | tmp3 = AES_TE0(BYTE(state3, 3)) ^ AES_TE1(BYTE(state0, 2)) ^ 844 | AES_TE2(BYTE(state1, 1)) ^ AES_TE3(BYTE(state2, 0)) ^ ks[r + 3]; 845 | 846 | if (i == 8) { 847 | break; 848 | } 849 | i++; 850 | state0 = tmp0; 851 | state1 = tmp1; 852 | state2 = tmp2; 853 | state3 = tmp3; 854 | } 855 | 856 | r += 4; 857 | state0 = (AES_TE4_3(BYTE(tmp0, 3))) ^ (AES_TE4_2(BYTE(tmp1, 2))) ^ 858 | (AES_TE4_1(BYTE(tmp2, 1))) ^ (AES_TE4_0(BYTE(tmp3, 0))) ^ ks[r + 0]; 859 | 860 | state1 = (AES_TE4_3(BYTE(tmp1, 3))) ^ (AES_TE4_2(BYTE(tmp2, 2))) ^ 861 | (AES_TE4_1(BYTE(tmp3, 1))) ^ (AES_TE4_0(BYTE(tmp0, 0))) ^ ks[r + 1]; 862 | 863 | state2 = (AES_TE4_3(BYTE(tmp2, 3))) ^ (AES_TE4_2(BYTE(tmp3, 2))) ^ 864 | (AES_TE4_1(BYTE(tmp0, 1))) ^ (AES_TE4_0(BYTE(tmp1, 0))) ^ ks[r + 2]; 865 | 866 | state3 = (AES_TE4_3(BYTE(tmp3, 3))) ^ (AES_TE4_2(BYTE(tmp0, 2))) ^ 867 | (AES_TE4_1(BYTE(tmp1, 1))) ^ (AES_TE4_0(BYTE(tmp2, 0))) ^ ks[r + 3]; 868 | 869 | STORE32H(out + 0, state0); 870 | STORE32H(out + 4, state1); 871 | STORE32H(out + 8, state2); 872 | STORE32H(out + 12, state3); 873 | } 874 | 875 | int CryptoUtils::sha256_process(sha256_state *md, const unsigned char *in, 876 | unsigned long inlen) { 877 | unsigned long n; 878 | int err; 879 | assert(md != NULL && "CryptoUtils::sha256_process md=NULL"); 880 | assert(in != NULL && "CryptoUtils::sha256_process in=NULL"); 881 | 882 | if (md->curlen > sizeof(md->buf)) { 883 | return 1; 884 | } 885 | while (inlen > 0) { 886 | if (md->curlen == 0 && inlen >= 64) { 887 | if ((err = sha256_compress(md, (unsigned char *)in)) != 0) { 888 | return err; 889 | } 890 | md->length += 64 * 8; 891 | in += 64; 892 | inlen -= 64; 893 | } else { 894 | n = MIN(inlen, (64 - md->curlen)); 895 | memcpy(md->buf + md->curlen, in, (size_t)n); 896 | md->curlen += n; 897 | in += n; 898 | inlen -= n; 899 | if (md->curlen == 64) { 900 | if ((err = sha256_compress(md, md->buf)) != 0) { 901 | return err; 902 | } 903 | md->length += 8 * 64; 904 | md->curlen = 0; 905 | } 906 | } 907 | } 908 | return 0; 909 | } 910 | 911 | int CryptoUtils::sha256_compress(sha256_state *md, unsigned char *buf) { 912 | uint32_t S[8], W[64], t0, t1; 913 | int i; 914 | 915 | /* copy state into S */ 916 | for (i = 0; i < 8; i++) { 917 | S[i] = md->state[i]; 918 | } 919 | 920 | /* copy the state into 512-bits into W[0..15] */ 921 | for (i = 0; i < 16; i++) { 922 | LOAD32H(W[i], buf + (4 * i)); 923 | } 924 | 925 | /* fill W[16..63] */ 926 | for (i = 16; i < 64; i++) { 927 | W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; 928 | } 929 | 930 | /* Compress */ 931 | 932 | RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 0, 0x428a2f98); 933 | RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 1, 0x71374491); 934 | RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 2, 0xb5c0fbcf); 935 | RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 3, 0xe9b5dba5); 936 | RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 4, 0x3956c25b); 937 | RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 5, 0x59f111f1); 938 | RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 6, 0x923f82a4); 939 | RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 7, 0xab1c5ed5); 940 | RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 8, 0xd807aa98); 941 | RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 9, 0x12835b01); 942 | RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 10, 0x243185be); 943 | RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 11, 0x550c7dc3); 944 | RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 12, 0x72be5d74); 945 | RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 13, 0x80deb1fe); 946 | RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 14, 0x9bdc06a7); 947 | RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 15, 0xc19bf174); 948 | RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 16, 0xe49b69c1); 949 | RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 17, 0xefbe4786); 950 | RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 18, 0x0fc19dc6); 951 | RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 19, 0x240ca1cc); 952 | RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 20, 0x2de92c6f); 953 | RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 21, 0x4a7484aa); 954 | RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 22, 0x5cb0a9dc); 955 | RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 23, 0x76f988da); 956 | RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 24, 0x983e5152); 957 | RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 25, 0xa831c66d); 958 | RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 26, 0xb00327c8); 959 | RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 27, 0xbf597fc7); 960 | RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 28, 0xc6e00bf3); 961 | RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 29, 0xd5a79147); 962 | RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 30, 0x06ca6351); 963 | RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 31, 0x14292967); 964 | RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 32, 0x27b70a85); 965 | RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 33, 0x2e1b2138); 966 | RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 34, 0x4d2c6dfc); 967 | RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 35, 0x53380d13); 968 | RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 36, 0x650a7354); 969 | RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 37, 0x766a0abb); 970 | RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 38, 0x81c2c92e); 971 | RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 39, 0x92722c85); 972 | RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 40, 0xa2bfe8a1); 973 | RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 41, 0xa81a664b); 974 | RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 42, 0xc24b8b70); 975 | RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 43, 0xc76c51a3); 976 | RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 44, 0xd192e819); 977 | RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 45, 0xd6990624); 978 | RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 46, 0xf40e3585); 979 | RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 47, 0x106aa070); 980 | RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 48, 0x19a4c116); 981 | RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 49, 0x1e376c08); 982 | RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 50, 0x2748774c); 983 | RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 51, 0x34b0bcb5); 984 | RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 52, 0x391c0cb3); 985 | RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 53, 0x4ed8aa4a); 986 | RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 54, 0x5b9cca4f); 987 | RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 55, 0x682e6ff3); 988 | RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 56, 0x748f82ee); 989 | RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 57, 0x78a5636f); 990 | RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 58, 0x84c87814); 991 | RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 59, 0x8cc70208); 992 | RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 60, 0x90befffa); 993 | RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 61, 0xa4506ceb); 994 | RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 62, 0xbef9a3f7); 995 | RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 63, 0xc67178f2); 996 | 997 | /* feedback */ 998 | for (i = 0; i < 8; i++) { 999 | md->state[i] = md->state[i] + S[i]; 1000 | } 1001 | return 0; 1002 | } 1003 | 1004 | /** 1005 | Initialize the hash state 1006 | @param md The hash state you wish to initialize 1007 | @return CRYPT_OK if successful 1008 | */ 1009 | int CryptoUtils::sha256_init(sha256_state *md) { 1010 | assert(md != NULL && "CryptoUtils::sha256_init md=NULL"); 1011 | 1012 | md->curlen = 0; 1013 | md->length = 0; 1014 | md->state[0] = 0x6A09E667UL; 1015 | md->state[1] = 0xBB67AE85UL; 1016 | md->state[2] = 0x3C6EF372UL; 1017 | md->state[3] = 0xA54FF53AUL; 1018 | md->state[4] = 0x510E527FUL; 1019 | md->state[5] = 0x9B05688CUL; 1020 | md->state[6] = 0x1F83D9ABUL; 1021 | md->state[7] = 0x5BE0CD19UL; 1022 | return 0; 1023 | } 1024 | 1025 | /** 1026 | Terminate the hash to get the digest 1027 | @param md The hash state 1028 | @param out [out] The destination of the hash (32 bytes) 1029 | @return CRYPT_OK if successful 1030 | */ 1031 | int CryptoUtils::sha256_done(sha256_state *md, unsigned char *out) { 1032 | int i; 1033 | 1034 | assert(md != NULL && "CryptoUtils::sha256_done md=NULL"); 1035 | assert(out != NULL && "CryptoUtils::sha256_done out=NULL"); 1036 | 1037 | if (md->curlen >= sizeof(md->buf)) { 1038 | return 1; 1039 | } 1040 | 1041 | /* increase the length of the message */ 1042 | md->length += md->curlen * 8; 1043 | 1044 | /* append the '1' bit */ 1045 | md->buf[md->curlen++] = (unsigned char)0x80; 1046 | 1047 | /* if the length is currently above 56 bytes we append zeros 1048 | * then compress. Then we can fall back to padding zeros and length 1049 | * encoding like normal. 1050 | */ 1051 | if (md->curlen > 56) { 1052 | while (md->curlen < 64) { 1053 | md->buf[md->curlen++] = (unsigned char)0; 1054 | } 1055 | sha256_compress(md, md->buf); 1056 | md->curlen = 0; 1057 | } 1058 | 1059 | /* pad upto 56 bytes of zeroes */ 1060 | while (md->curlen < 56) { 1061 | md->buf[md->curlen++] = (unsigned char)0; 1062 | } 1063 | 1064 | /* store length */ 1065 | STORE64H(md->buf + 56, md->length); 1066 | sha256_compress(md, md->buf); 1067 | 1068 | /* copy output */ 1069 | for (i = 0; i < 8; i++) { 1070 | STORE32H(out + (4 * i), md->state[i]); 1071 | } 1072 | return 0; 1073 | } 1074 | 1075 | int CryptoUtils::sha256(const char *msg, unsigned char *hash) { 1076 | unsigned char tmp[32]; 1077 | sha256_state md; 1078 | 1079 | sha256_init(&md); 1080 | sha256_process(&md, (const unsigned char *)msg, 1081 | (unsigned long)strlen((const char *)msg)); 1082 | sha256_done(&md, tmp); 1083 | 1084 | memcpy(hash, tmp, 32); 1085 | return 0; 1086 | } 1087 | -------------------------------------------------------------------------------- /obfuscator-llvm/CryptoUtils.h: -------------------------------------------------------------------------------- 1 | //===- CryptoUtils.h - Cryptographically Secure Pseudo-Random Generator----===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file contains includes and defines for the AES CTR PRNG 11 | // The AES implementation has been derived and adapted 12 | // from libtomcrypt (see http://libtom.org) 13 | // 14 | // Created on: June 22, 2012 15 | // Author(s): jrinaldini, pjunod 16 | // 17 | //===----------------------------------------------------------------------===// 18 | 19 | #ifndef LLVM_CryptoUtils_H 20 | #define LLVM_CryptoUtils_H 21 | 22 | #include "llvm/Support/ManagedStatic.h" 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | namespace llvm { 29 | 30 | class CryptoUtils; 31 | extern ManagedStatic cryptoutils; 32 | 33 | #define BYTE(x, n) (((x) >> (8 * (n))) & 0xFF) 34 | 35 | #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ 36 | defined(INTEL_CC) 37 | 38 | #ifndef ENDIAN_LITTLE 39 | #define ENDIAN_LITTLE 40 | #endif 41 | #define ENDIAN_32BITWORD 42 | #define UNALIGNED 43 | 44 | #elif defined(__alpha) 45 | 46 | #ifndef ENDIAN_LITTLE 47 | #define ENDIAN_LITTLE 48 | #endif 49 | #define ENDIAN_64BITWORD 50 | 51 | #elif defined(__x86_64__) 52 | 53 | #ifndef ENDIAN_LITTLE 54 | #define ENDIAN_LITTLE 55 | #endif 56 | #define ENDIAN_64BITWORD 57 | #define UNALIGNED 58 | 59 | #elif(defined(__R5900) || defined(R5900) || defined(__R5900__)) && \ 60 | (defined(_mips) || defined(__mips__) || defined(mips)) 61 | 62 | #ifndef ENDIAN_LITTLE 63 | #define ENDIAN_LITTLE 64 | #endif 65 | #define ENDIAN_64BITWORD 66 | 67 | #elif defined(__sparc) 68 | 69 | #ifndef ENDIAN_BIG 70 | #define ENDIAN_BIG 71 | #endif 72 | #if defined(__arch64__) 73 | #define ENDIAN_64BITWORD 74 | #else 75 | #define ENDIAN_32BITWORD 76 | #endif 77 | 78 | #endif 79 | 80 | #if defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN) 81 | #define ENDIAN_BIG 82 | #endif 83 | 84 | #if !defined(ENDIAN_BIG) && !defined(ENDIAN_LITTLE) 85 | #error \ 86 | "Unknown endianness of the compilation platform, check this header aes_encrypt.h" 87 | #endif 88 | 89 | #ifdef ENDIAN_LITTLE 90 | 91 | #define STORE32H(y, x) \ 92 | { \ 93 | (y)[0] = (uint8_t)(((x) >> 24) & 0xFF); \ 94 | (y)[1] = (uint8_t)(((x) >> 16) & 0xFF); \ 95 | (y)[2] = (uint8_t)(((x) >> 8) & 0xFF); \ 96 | (y)[3] = (uint8_t)(((x) >> 0) & 0xFF); \ 97 | } 98 | #define LOAD32H(x, y) \ 99 | { \ 100 | (x) = ((uint32_t)((y)[0] & 0xFF) << 24) | \ 101 | ((uint32_t)((y)[1] & 0xFF) << 16) | \ 102 | ((uint32_t)((y)[2] & 0xFF) << 8) | ((uint32_t)((y)[3] & 0xFF) << 0); \ 103 | } 104 | 105 | #define LOAD64H(x, y) \ 106 | { \ 107 | (x) = ((uint64_t)((y)[0] & 0xFF) << 56) | \ 108 | ((uint64_t)((y)[1] & 0xFF) << 48) | \ 109 | ((uint64_t)((y)[2] & 0xFF) << 40) | \ 110 | ((uint64_t)((y)[3] & 0xFF) << 32) | \ 111 | ((uint64_t)((y)[4] & 0xFF) << 24) | \ 112 | ((uint64_t)((y)[5] & 0xFF) << 16) | \ 113 | ((uint64_t)((y)[6] & 0xFF) << 8) | ((uint64_t)((y)[7] & 0xFF) << 0); \ 114 | } 115 | 116 | #define STORE64H(y, x) \ 117 | { \ 118 | (y)[0] = (uint8_t)(((x) >> 56) & 0xFF); \ 119 | (y)[1] = (uint8_t)(((x) >> 48) & 0xFF); \ 120 | (y)[2] = (uint8_t)(((x) >> 40) & 0xFF); \ 121 | (y)[3] = (uint8_t)(((x) >> 32) & 0xFF); \ 122 | (y)[4] = (uint8_t)(((x) >> 24) & 0xFF); \ 123 | (y)[5] = (uint8_t)(((x) >> 16) & 0xFF); \ 124 | (y)[6] = (uint8_t)(((x) >> 8) & 0xFF); \ 125 | (y)[7] = (uint8_t)(((x) >> 0) & 0xFF); \ 126 | } 127 | 128 | #endif /* ENDIAN_LITTLE */ 129 | 130 | #ifdef ENDIAN_BIG 131 | 132 | #define STORE32H(y, x) \ 133 | { \ 134 | (y)[3] = (uint8_t)(((x) >> 24) & 0xFF); \ 135 | (y)[2] = (uint8_t)(((x) >> 16) & 0xFF); \ 136 | (y)[1] = (uint8_t)(((x) >> 8) & 0xFF); \ 137 | (y)[0] = (uint8_t)(((x) >> 0) & 0xFF); \ 138 | } 139 | #define STORE64H(y, x) \ 140 | { \ 141 | (y)[7] = (uint8_t)(((x) >> 56) & 0xFF); \ 142 | (y)[6] = (uint8_t)(((x) >> 48) & 0xFF); \ 143 | (y)[5] = (uint8_t)(((x) >> 40) & 0xFF); \ 144 | (y)[4] = (uint8_t)(((x) >> 32) & 0xFF); \ 145 | (y)[3] = (uint8_t)(((x) >> 24) & 0xFF); \ 146 | (y)[2] = (uint8_t)(((x) >> 16) & 0xFF); \ 147 | (y)[1] = (uint8_t)(((x) >> 8) & 0xFF); \ 148 | (y)[0] = (uint8_t)(((x) >> 0) & 0xFF); \ 149 | } 150 | #define LOAD32H(x, y) \ 151 | { \ 152 | (x) = ((uint32_t)((y)[3] & 0xFF) << 24) | \ 153 | ((uint32_t)((y)[2] & 0xFF) << 16) | \ 154 | ((uint32_t)((y)[1] & 0xFF) << 8) | ((uint32_t)((y)[0] & 0xFF) << 0); \ 155 | } 156 | 157 | #define LOAD64H(x, y) \ 158 | { \ 159 | (x) = ((uint64_t)((y)[7] & 0xFF) << 56) | \ 160 | ((uint64_t)((y)[6] & 0xFF) << 48) | \ 161 | ((uint64_t)((y)[5] & 0xFF) << 40) | \ 162 | ((uint64_t)((y)[4] & 0xFF) << 32) | \ 163 | ((uint64_t)((y)[3] & 0xFF) << 24) | \ 164 | ((uint64_t)((y)[2] & 0xFF) << 16) | \ 165 | ((uint64_t)((y)[1] & 0xFF) << 8) | ((uint64_t)((y)[0] & 0xFF) << 0); \ 166 | } 167 | 168 | #endif /* ENDIAN_BIG */ 169 | 170 | #define AES_TE0(x) AES_PRECOMP_TE0[(x)] 171 | #define AES_TE1(x) AES_PRECOMP_TE1[(x)] 172 | #define AES_TE2(x) AES_PRECOMP_TE2[(x)] 173 | #define AES_TE3(x) AES_PRECOMP_TE3[(x)] 174 | 175 | #define AES_TE4_0(x) AES_PRECOMP_TE4_0[(x)] 176 | #define AES_TE4_1(x) AES_PRECOMP_TE4_1[(x)] 177 | #define AES_TE4_2(x) AES_PRECOMP_TE4_2[(x)] 178 | #define AES_TE4_3(x) AES_PRECOMP_TE4_3[(x)] 179 | 180 | #define CryptoUtils_POOL_SIZE (0x1 << 17) // 2^17 181 | 182 | #define DUMP(x, l, s) \ 183 | fprintf(stderr, "%s :", (s)); \ 184 | for (int ii = 0; ii < (l); ii++) { \ 185 | fprintf(stderr, "%02hhX", *((x) + ii)); \ 186 | } \ 187 | fprintf(stderr, "\n"); 188 | 189 | // SHA256 190 | /* Various logical functions */ 191 | #define Ch(x, y, z) (z ^ (x &(y ^ z))) 192 | #define Maj(x, y, z) (((x | y) & z) | (x &y)) 193 | #define S(x, n) RORc((x), (n)) 194 | #define R1(x, n) (((x) & 0xFFFFFFFFUL) >> (n)) 195 | #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) 196 | #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) 197 | #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R1(x, 3)) 198 | #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R1(x, 10)) 199 | #define MIN(x, y) (((x) < (y)) ? (x) : (y)) 200 | 201 | #define RND(a, b, c, d, e, f, g, h, i, ki) \ 202 | t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ 203 | t1 = Sigma0(a) + Maj(a, b, c); \ 204 | d += t0; \ 205 | h = t0 + t1; 206 | 207 | #define RORc(x, y) \ 208 | (((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \ 209 | ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & \ 210 | 0xFFFFFFFFUL) 211 | 212 | class CryptoUtils { 213 | public: 214 | CryptoUtils(); 215 | ~CryptoUtils(); 216 | 217 | char *get_seed(); 218 | void get_bytes(char *buffer, const int len); 219 | char get_char(); 220 | bool prng_seed(const std::string seed); 221 | 222 | // Returns a uniformly distributed 8-bit value 223 | uint8_t get_uint8_t(); 224 | // Returns a uniformly distributed 32-bit value 225 | uint32_t get_uint32_t(); 226 | // Returns an integer uniformly distributed on [0, max[ 227 | uint32_t get_range(const uint32_t max); 228 | // Returns a uniformly distributed 64-bit value 229 | uint64_t get_uint64_t(); 230 | 231 | // Scramble a 32-bit value depending on a 128-bit value 232 | unsigned scramble32(const unsigned in, const char key[16]); 233 | 234 | int sha256(const char *msg, unsigned char *hash); 235 | 236 | private: 237 | uint32_t ks[44]; 238 | char key[16]; 239 | char ctr[16]; 240 | char pool[CryptoUtils_POOL_SIZE]; 241 | uint32_t idx; 242 | std::string seed; 243 | bool seeded; 244 | 245 | typedef struct { 246 | uint64_t length; 247 | uint32_t state[8], curlen; 248 | unsigned char buf[64]; 249 | } sha256_state; 250 | 251 | void aes_compute_ks(uint32_t *ks, const char *k); 252 | void aes_encrypt(char *out, const char *in, const uint32_t *ks); 253 | bool prng_seed(); 254 | void inc_ctr(); 255 | void populate_pool(); 256 | int sha256_done(sha256_state *md, unsigned char *out); 257 | int sha256_init(sha256_state *md); 258 | static int sha256_compress(sha256_state *md, unsigned char *buf); 259 | int sha256_process(sha256_state *md, const unsigned char *in, 260 | unsigned long inlen); 261 | }; 262 | } 263 | 264 | #endif // LLVM_CryptoUtils_H 265 | 266 | -------------------------------------------------------------------------------- /obfuscator-llvm/Flattening.cpp: -------------------------------------------------------------------------------- 1 | //===- Flattening.cpp - Flattening Obfuscation pass------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements the flattening pass 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "Flattening.h" 15 | #include "llvm/Transforms/Scalar.h" 16 | #include "llvm/Transforms/Utils.h" 17 | #include "CryptoUtils.h" 18 | 19 | #define DEBUG_TYPE "flattening" 20 | 21 | using namespace llvm; 22 | 23 | static cl::opt FlatteningArg("fla", cl::init(false), 24 | cl::desc("Enable the flattening pass")); 25 | 26 | // Stats 27 | STATISTIC(Flattened, "Functions flattened"); 28 | 29 | namespace { 30 | struct Flattening : public FunctionPass { 31 | static char ID; // Pass identification, replacement for typeid 32 | 33 | Flattening() : FunctionPass(ID) {} 34 | 35 | bool runOnFunction(Function &F); 36 | bool flatten(Function *f); 37 | }; 38 | } // namespace 39 | 40 | char Flattening::ID = 0; 41 | static RegisterPass X("flattening", "Call graph flattening"); 42 | Pass *llvm::createFlattening() { return new Flattening(); } 43 | 44 | bool Flattening::runOnFunction(Function &F) { 45 | Function *tmp = &F; 46 | // Do we obfuscate 47 | if (toObfuscate(FlatteningArg, tmp, "fla")) { 48 | if (flatten(tmp)) { 49 | ++Flattened; 50 | } 51 | } 52 | 53 | return false; 54 | } 55 | 56 | PreservedAnalyses FlatteningPass::run(Function &F, FunctionAnalysisManager &AM){ 57 | Flattening fla; 58 | fla.runOnFunction(F); 59 | 60 | return PreservedAnalyses::none(); 61 | } 62 | 63 | bool Flattening::flatten(Function *f) { 64 | std::vector origBB; 65 | BasicBlock *loopEntry; 66 | BasicBlock *loopEnd; 67 | LoadInst *load; 68 | SwitchInst *switchI; 69 | AllocaInst *switchVar; 70 | 71 | // SCRAMBLER 72 | char scrambling_key[16]; 73 | llvm::cryptoutils->get_bytes(scrambling_key, 16); 74 | // END OF SCRAMBLER 75 | 76 | #if LLVM_VERSION_MAJOR >= 9 77 | // >=9.0, LowerSwitchPass depends on LazyValueInfoWrapperPass, which cause AssertError. 78 | // So I move LowerSwitchPass into register function, just before FlatteningPass. 79 | #else 80 | // Lower switch 81 | FunctionPass *lower = createLowerSwitchPass(); 82 | lower->runOnFunction(*f); 83 | #endif 84 | 85 | // Save all original BB 86 | for (Function::iterator i = f->begin(); i != f->end(); ++i) { 87 | BasicBlock *tmp = &*i; 88 | origBB.push_back(tmp); 89 | 90 | BasicBlock *bb = &*i; 91 | if (isa(bb->getTerminator())) { 92 | return false; 93 | } 94 | } 95 | 96 | // Nothing to flatten 97 | if (origBB.size() <= 1) { 98 | return false; 99 | } 100 | 101 | // Remove first BB 102 | origBB.erase(origBB.begin()); 103 | 104 | // Get a pointer on the first BB 105 | Function::iterator tmp = f->begin(); //++tmp; 106 | BasicBlock *insert = &*tmp; 107 | 108 | // If main begin with an if 109 | BranchInst *br = NULL; 110 | if (isa(insert->getTerminator())) { 111 | br = cast(insert->getTerminator()); 112 | } 113 | 114 | if ((br != NULL && br->isConditional()) || 115 | insert->getTerminator()->getNumSuccessors() > 1) { 116 | BasicBlock::iterator i = insert->end(); 117 | --i; 118 | 119 | if (insert->size() > 1) { 120 | --i; 121 | } 122 | 123 | BasicBlock *tmpBB = insert->splitBasicBlock(i, "first"); 124 | origBB.insert(origBB.begin(), tmpBB); 125 | } 126 | 127 | // Remove jump 128 | insert->getTerminator()->eraseFromParent(); 129 | 130 | // Create switch variable and set as it 131 | switchVar = 132 | new AllocaInst(Type::getInt32Ty(f->getContext()), 0, "switchVar", insert); 133 | new StoreInst( 134 | ConstantInt::get(Type::getInt32Ty(f->getContext()), 135 | llvm::cryptoutils->scramble32(0, scrambling_key)), 136 | switchVar, insert); 137 | 138 | // Create main loop 139 | loopEntry = BasicBlock::Create(f->getContext(), "loopEntry", f, insert); 140 | loopEnd = BasicBlock::Create(f->getContext(), "loopEnd", f, insert); 141 | 142 | load = new LoadInst(switchVar->getType()->getElementType(), switchVar, "switchVar", loopEntry); 143 | 144 | // Move first BB on top 145 | insert->moveBefore(loopEntry); 146 | BranchInst::Create(loopEntry, insert); 147 | 148 | // loopEnd jump to loopEntry 149 | BranchInst::Create(loopEntry, loopEnd); 150 | 151 | BasicBlock *swDefault = 152 | BasicBlock::Create(f->getContext(), "switchDefault", f, loopEnd); 153 | BranchInst::Create(loopEnd, swDefault); 154 | 155 | // Create switch instruction itself and set condition 156 | switchI = SwitchInst::Create(&*f->begin(), swDefault, 0, loopEntry); 157 | switchI->setCondition(load); 158 | 159 | // Remove branch jump from 1st BB and make a jump to the while 160 | f->begin()->getTerminator()->eraseFromParent(); 161 | 162 | BranchInst::Create(loopEntry, &*f->begin()); 163 | 164 | // Put all BB in the switch 165 | for (std::vector::iterator b = origBB.begin(); 166 | b != origBB.end(); ++b) { 167 | BasicBlock *i = *b; 168 | ConstantInt *numCase = NULL; 169 | 170 | // Move the BB inside the switch (only visual, no code logic) 171 | i->moveBefore(loopEnd); 172 | 173 | // Add case to switch 174 | numCase = cast(ConstantInt::get( 175 | switchI->getCondition()->getType(), 176 | llvm::cryptoutils->scramble32(switchI->getNumCases(), scrambling_key))); 177 | switchI->addCase(numCase, i); 178 | } 179 | 180 | // Recalculate switchVar 181 | for (std::vector::iterator b = origBB.begin(); 182 | b != origBB.end(); ++b) { 183 | BasicBlock *i = *b; 184 | ConstantInt *numCase = NULL; 185 | 186 | // Ret BB 187 | if (i->getTerminator()->getNumSuccessors() == 0) { 188 | continue; 189 | } 190 | 191 | // If it's a non-conditional jump 192 | if (i->getTerminator()->getNumSuccessors() == 1) { 193 | // Get successor and delete terminator 194 | BasicBlock *succ = i->getTerminator()->getSuccessor(0); 195 | i->getTerminator()->eraseFromParent(); 196 | 197 | // Get next case 198 | numCase = switchI->findCaseDest(succ); 199 | 200 | // If next case == default case (switchDefault) 201 | if (numCase == NULL) { 202 | numCase = cast( 203 | ConstantInt::get(switchI->getCondition()->getType(), 204 | llvm::cryptoutils->scramble32( 205 | switchI->getNumCases() - 1, scrambling_key))); 206 | } 207 | 208 | // Update switchVar and jump to the end of loop 209 | new StoreInst(numCase, load->getPointerOperand(), i); 210 | BranchInst::Create(loopEnd, i); 211 | continue; 212 | } 213 | 214 | // If it's a conditional jump 215 | if (i->getTerminator()->getNumSuccessors() == 2) { 216 | // Get next cases 217 | ConstantInt *numCaseTrue = 218 | switchI->findCaseDest(i->getTerminator()->getSuccessor(0)); 219 | ConstantInt *numCaseFalse = 220 | switchI->findCaseDest(i->getTerminator()->getSuccessor(1)); 221 | 222 | // Check if next case == default case (switchDefault) 223 | if (numCaseTrue == NULL) { 224 | numCaseTrue = cast( 225 | ConstantInt::get(switchI->getCondition()->getType(), 226 | llvm::cryptoutils->scramble32( 227 | switchI->getNumCases() - 1, scrambling_key))); 228 | } 229 | 230 | if (numCaseFalse == NULL) { 231 | numCaseFalse = cast( 232 | ConstantInt::get(switchI->getCondition()->getType(), 233 | llvm::cryptoutils->scramble32( 234 | switchI->getNumCases() - 1, scrambling_key))); 235 | } 236 | 237 | // Create a SelectInst 238 | BranchInst *br = cast(i->getTerminator()); 239 | SelectInst *sel = 240 | SelectInst::Create(br->getCondition(), numCaseTrue, numCaseFalse, "", 241 | i->getTerminator()); 242 | 243 | // Erase terminator 244 | i->getTerminator()->eraseFromParent(); 245 | 246 | // Update switchVar and jump to the end of loop 247 | new StoreInst(sel, load->getPointerOperand(), i); 248 | BranchInst::Create(loopEnd, i); 249 | continue; 250 | } 251 | } 252 | 253 | fixStack(f); 254 | 255 | return true; 256 | } 257 | -------------------------------------------------------------------------------- /obfuscator-llvm/Flattening.h: -------------------------------------------------------------------------------- 1 | //===- FlatteningIncludes.h - Flattening Obfuscation pass------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file contains includes and defines for the flattening pass 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef _OBFUSCATION_FLATTENING_H_ 15 | #define _OBFUSCATION_FLATTENING_H_ 16 | 17 | #include "llvm/ADT/Statistic.h" 18 | #include "llvm/IR/Function.h" 19 | #include "llvm/IR/Module.h" 20 | #include "llvm/Pass.h" 21 | #include "llvm/Support/CommandLine.h" 22 | #include "llvm/Transforms/IPO.h" 23 | #include "CryptoUtils.h" 24 | #include "Utils.h" 25 | #include "llvm/Transforms/Scalar.h" 26 | #include "llvm/Transforms/Utils/Local.h" // For DemoteRegToStack and DemotePHIToStack 27 | #include "llvm/IR/PassManager.h" // New PassManager 28 | 29 | namespace llvm { 30 | Pass *createFlattening(); 31 | class FlatteningPass : public PassInfoMixin{ // New PassManager 32 | public: 33 | PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 34 | 35 | static bool isRequired() { return true; } 36 | }; 37 | } // namespace llvm 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /obfuscator-llvm/Obfuscation.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/LegacyPassManager.h" 2 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 3 | #include "llvm/Passes/PassPlugin.h" 4 | #include "llvm/Passes/PassBuilder.h" 5 | #include "Substitution.h" 6 | #include "Flattening.h" 7 | #include "SplitBasicBlocks.h" 8 | #include "BogusControlFlow.h" 9 | 10 | using namespace llvm; 11 | 12 | // Flags for obfuscation 13 | static cl::opt AesSeed("aesSeed", cl::init(""), cl::desc("seed for the AES-CTR PRNG")); 14 | 15 | static void loadPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { 16 | // Initialization of the global cryptographically 17 | // secure pseudo-random generator 18 | if(!AesSeed.empty()) { 19 | if(!llvm::cryptoutils->prng_seed(AesSeed.c_str())) { 20 | exit(1); 21 | } 22 | } 23 | PM.add(createSplitBasicBlock()); 24 | PM.add(createBogus()); 25 | PM.add(createFlattening()); 26 | PM.add(createSubstitution()); 27 | } 28 | 29 | // These constructors add our pass to a list of global extensions. 30 | static RegisterStandardPasses clangtoolLoader_Ox(PassManagerBuilder::EP_OptimizerLast, loadPass); 31 | static RegisterStandardPasses clangtoolLoader_O0(PassManagerBuilder::EP_EnabledOnOptLevel0, loadPass); 32 | // Note: The location EP_OptimizerLast places this pass at the end of the list 33 | // of *optimizations*. That means on -O0, it does not get run. 34 | // 35 | // In general, adding your pass twice will cause it to run twice, but in this 36 | // particular case, the two are disjoint (EP_EnabledOnOptLevel0 only runs if 37 | // you're in -O0, and EP_OptimizerLast only runs if you're not). You can check 38 | // include/llvm/Transforms/IPO/PassManagerBuilder.h header and 39 | // lib/Transforms/IPO/PassManagerBuilder.cpp file for the exact behavior. 40 | 41 | PassPluginLibraryInfo getObfuscatorLLVMPluginInfo(){ 42 | return {LLVM_PLUGIN_API_VERSION, "ObfuscatorLLVM", LLVM_VERSION_STRING, [](PassBuilder &PB){ 43 | PB.registerVectorizerStartEPCallback([](FunctionPassManager &PM, PassBuilder::OptimizationLevel level){ 44 | if(!AesSeed.empty()) { 45 | if(!llvm::cryptoutils->prng_seed(AesSeed.c_str())) { 46 | exit(1); 47 | } 48 | } 49 | PM.addPass(SplitBasicBlockPass()); 50 | PM.addPass(BogusControlFlowPass()); 51 | PM.addPass(FlatteningPass()); 52 | PM.addPass(SubstitutionPass()); 53 | }); 54 | }}; 55 | } 56 | 57 | extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo 58 | llvmGetPassPluginInfo() { 59 | return getObfuscatorLLVMPluginInfo(); 60 | } 61 | -------------------------------------------------------------------------------- /obfuscator-llvm/SplitBasicBlocks.cpp: -------------------------------------------------------------------------------- 1 | //===- SplitBasicBlock.cpp - SplitBasicBlokc Obfuscation pass--------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements the split basic block pass 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "CryptoUtils.h" 15 | #include "SplitBasicBlocks.h" 16 | #include "Utils.h" 17 | 18 | #define DEBUG_TYPE "split" 19 | 20 | using namespace llvm; 21 | 22 | // Stats 23 | STATISTIC(Split, "Basicblock splitted"); 24 | 25 | static cl::opt SplitFlag("split", cl::init(false), 26 | cl::desc("Enable basic block splitting")); 27 | 28 | static cl::opt SplitNum("split_num", cl::init(2), 29 | cl::desc("Split time each BB")); 30 | 31 | namespace { 32 | struct SplitBasicBlock : public FunctionPass { 33 | static char ID; // Pass identification, replacement for typeid 34 | 35 | SplitBasicBlock() : FunctionPass(ID) {} 36 | 37 | bool runOnFunction(Function &F); 38 | void split(Function *f); 39 | 40 | bool containsPHI(BasicBlock *b); 41 | void shuffle(std::vector &vec); 42 | }; 43 | } // namespace 44 | 45 | char SplitBasicBlock::ID = 0; 46 | static RegisterPass X("splitbbl", "BasicBlock splitting"); 47 | 48 | Pass *llvm::createSplitBasicBlock() { 49 | return new SplitBasicBlock(); 50 | } 51 | 52 | PreservedAnalyses SplitBasicBlockPass::run(Function &F, FunctionAnalysisManager &AM){ 53 | SplitBasicBlock split; 54 | split.runOnFunction(F); 55 | return PreservedAnalyses::none(); 56 | } 57 | 58 | bool SplitBasicBlock::runOnFunction(Function &F) { 59 | Function *tmp = &F; 60 | 61 | // Check if the number of applications is correct 62 | auto nums = readAnnotate(tmp, SplitNum.ArgStr); 63 | if (!nums.empty()) { 64 | int value = SplitNum; 65 | if (!nums.getAsInteger(0, value)) 66 | SplitNum.setValue(value); 67 | } 68 | if (!((SplitNum > 1) && (SplitNum <= 10))) { 69 | errs() << "Split application basic block percentage\ 70 | -split_num=x must be 1 < x <= 10"; 71 | return false; 72 | } 73 | 74 | // Do we obfuscate 75 | if (toObfuscate(SplitFlag, tmp, "split")) { 76 | split(tmp); 77 | ++Split; 78 | } 79 | 80 | return false; 81 | } 82 | 83 | void SplitBasicBlock::split(Function *f) { 84 | std::vector origBB; 85 | int splitN = SplitNum; 86 | 87 | // Save all basic blocks 88 | for (Function::iterator I = f->begin(), IE = f->end(); I != IE; ++I) { 89 | origBB.push_back(&*I); 90 | } 91 | 92 | for (std::vector::iterator I = origBB.begin(), 93 | IE = origBB.end(); 94 | I != IE; ++I) { 95 | BasicBlock *curr = *I; 96 | 97 | // No need to split a 1 inst bb 98 | // Or ones containing a PHI node 99 | if (curr->size() < 2 || containsPHI(curr)) { 100 | continue; 101 | } 102 | 103 | // Check splitN and current BB size 104 | if ((size_t)splitN > curr->size()) { 105 | splitN = curr->size() - 1; 106 | } 107 | 108 | // Generate splits point 109 | std::vector test; 110 | for (unsigned i = 1; i < curr->size(); ++i) { 111 | test.push_back(i); 112 | } 113 | 114 | // Shuffle 115 | if (test.size() != 1) { 116 | shuffle(test); 117 | std::sort(test.begin(), test.begin() + splitN); 118 | } 119 | 120 | // Split 121 | BasicBlock::iterator it = curr->begin(); 122 | BasicBlock *toSplit = curr; 123 | int last = 0; 124 | for (int i = 0; i < splitN; ++i) { 125 | for (int j = 0; j < test[i] - last; ++j) { 126 | ++it; 127 | } 128 | last = test[i]; 129 | if (toSplit->size() < 2) 130 | continue; 131 | toSplit = toSplit->splitBasicBlock(it, toSplit->getName() + ".split"); 132 | } 133 | 134 | ++Split; 135 | } 136 | } 137 | 138 | bool SplitBasicBlock::containsPHI(BasicBlock *b) { 139 | for (BasicBlock::iterator I = b->begin(), IE = b->end(); I != IE; ++I) { 140 | if (isa(I)) { 141 | return true; 142 | } 143 | } 144 | return false; 145 | } 146 | 147 | void SplitBasicBlock::shuffle(std::vector &vec) { 148 | int n = vec.size(); 149 | for (int i = n - 1; i > 0; --i) { 150 | std::swap(vec[i], vec[cryptoutils->get_uint32_t() % (i + 1)]); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /obfuscator-llvm/SplitBasicBlocks.h: -------------------------------------------------------------------------------- 1 | //===- FlatteningIncludes.h - Flattening Obfuscation pass------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file contains includes and defines for the split basicblock pass 11 | // 12 | //===----------------------------------------------------------------------===// 13 | #ifndef _OBFUSCATION_SPLIT_H_ 14 | #define _OBFUSCATION_SPLIT_H_ 15 | 16 | #include "llvm/ADT/Statistic.h" 17 | #include "llvm/IR/BasicBlock.h" 18 | #include "llvm/IR/Module.h" 19 | #include "llvm/Pass.h" 20 | #include "llvm/Support/CommandLine.h" 21 | #include "llvm/Transforms/IPO.h" 22 | #include "CryptoUtils.h" 23 | #include "Utils.h" 24 | #include "llvm/Transforms/Scalar.h" 25 | #include "llvm/Transforms/Utils/Local.h" // For DemoteRegToStack and DemotePHIToStack 26 | #include "llvm/IR/PassManager.h" // New PassManager 27 | 28 | namespace llvm { 29 | Pass *createSplitBasicBlock(); 30 | class SplitBasicBlockPass : public PassInfoMixin{ // New PassManager 31 | public: 32 | PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 33 | 34 | static bool isRequired() { return true; } 35 | }; 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /obfuscator-llvm/Substitution.cpp: -------------------------------------------------------------------------------- 1 | //===- Substitution.cpp - Substitution Obfuscation pass--------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements operators substitution's pass 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "Substitution.h" 15 | #include "llvm/IR/Intrinsics.h" 16 | #include "llvm/IR/LLVMContext.h" 17 | #include "llvm/Support/raw_ostream.h" 18 | #include "Utils.h" 19 | 20 | #define DEBUG_TYPE "substitution" 21 | 22 | using namespace llvm; 23 | 24 | #define NUMBER_ADD_SUBST 4 25 | #define NUMBER_SUB_SUBST 3 26 | #define NUMBER_AND_SUBST 2 27 | #define NUMBER_OR_SUBST 2 28 | #define NUMBER_XOR_SUBST 2 29 | 30 | static cl::opt SubstitutionFlag("sub", cl::init(false), 31 | cl::desc("Enable instruction substitutions")); 32 | 33 | static cl::opt 34 | ObfTimes("sub_loop", 35 | cl::desc("Choose how many time the -sub pass loops on a function"), 36 | cl::value_desc("number of times"), cl::init(1), cl::Optional); 37 | 38 | // Stats 39 | STATISTIC(Add, "Add substitued"); 40 | STATISTIC(Sub, "Sub substitued"); 41 | // STATISTIC(Mul, "Mul substitued"); 42 | // STATISTIC(Div, "Div substitued"); 43 | // STATISTIC(Rem, "Rem substitued"); 44 | // STATISTIC(Shi, "Shift substitued"); 45 | STATISTIC(And, "And substitued"); 46 | STATISTIC(Or, "Or substitued"); 47 | STATISTIC(Xor, "Xor substitued"); 48 | 49 | namespace { 50 | 51 | struct Substitution : public FunctionPass { 52 | static char ID; // Pass identification, replacement for typeid 53 | void (Substitution::*funcAdd[NUMBER_ADD_SUBST])(BinaryOperator *bo); 54 | void (Substitution::*funcSub[NUMBER_SUB_SUBST])(BinaryOperator *bo); 55 | void (Substitution::*funcAnd[NUMBER_AND_SUBST])(BinaryOperator *bo); 56 | void (Substitution::*funcOr[NUMBER_OR_SUBST])(BinaryOperator *bo); 57 | void (Substitution::*funcXor[NUMBER_XOR_SUBST])(BinaryOperator *bo); 58 | 59 | Substitution() : FunctionPass(ID) { 60 | funcAdd[0] = &Substitution::addNeg; 61 | funcAdd[1] = &Substitution::addDoubleNeg; 62 | funcAdd[2] = &Substitution::addRand; 63 | funcAdd[3] = &Substitution::addRand2; 64 | 65 | funcSub[0] = &Substitution::subNeg; 66 | funcSub[1] = &Substitution::subRand; 67 | funcSub[2] = &Substitution::subRand2; 68 | 69 | funcAnd[0] = &Substitution::andSubstitution; 70 | funcAnd[1] = &Substitution::andSubstitutionRand; 71 | 72 | funcOr[0] = &Substitution::orSubstitution; 73 | funcOr[1] = &Substitution::orSubstitutionRand; 74 | 75 | funcXor[0] = &Substitution::xorSubstitution; 76 | funcXor[1] = &Substitution::xorSubstitutionRand; 77 | } 78 | 79 | bool runOnFunction(Function &F); 80 | bool substitute(Function *f); 81 | 82 | void addNeg(BinaryOperator *bo); 83 | void addDoubleNeg(BinaryOperator *bo); 84 | void addRand(BinaryOperator *bo); 85 | void addRand2(BinaryOperator *bo); 86 | 87 | void subNeg(BinaryOperator *bo); 88 | void subRand(BinaryOperator *bo); 89 | void subRand2(BinaryOperator *bo); 90 | 91 | void andSubstitution(BinaryOperator *bo); 92 | void andSubstitutionRand(BinaryOperator *bo); 93 | 94 | void orSubstitution(BinaryOperator *bo); 95 | void orSubstitutionRand(BinaryOperator *bo); 96 | 97 | void xorSubstitution(BinaryOperator *bo); 98 | void xorSubstitutionRand(BinaryOperator *bo); 99 | }; 100 | } // namespace 101 | 102 | char Substitution::ID = 0; 103 | static RegisterPass X("substitution", "operators substitution"); 104 | Pass *llvm::createSubstitution() { return new Substitution(); } 105 | 106 | bool Substitution::runOnFunction(Function &F) { 107 | Function *tmp = &F; 108 | 109 | // Check if the percentage is correct 110 | auto loops = readAnnotate(tmp, ObfTimes.ArgStr); 111 | if (!loops.empty()) { 112 | int value = ObfTimes; 113 | if (!loops.getAsInteger(0, value)) 114 | ObfTimes.setValue(value); 115 | } 116 | if (ObfTimes <= 0) { 117 | errs() << "Substitution application number -sub_loop=x must be x > 0"; 118 | return false; 119 | } 120 | 121 | // Do we obfuscate 122 | if (toObfuscate(SubstitutionFlag, tmp, "sub")) { 123 | substitute(tmp); 124 | return true; 125 | } 126 | return false; 127 | } 128 | 129 | PreservedAnalyses SubstitutionPass::run(Function &F, FunctionAnalysisManager &AM){ 130 | Substitution sub; 131 | if (sub.runOnFunction(F)) { 132 | return PreservedAnalyses::none(); 133 | } 134 | return PreservedAnalyses::all(); 135 | } 136 | 137 | bool Substitution::substitute(Function *f) { 138 | Function *tmp = f; 139 | 140 | // Loop for the number of time we run the pass on the function 141 | int times = ObfTimes; 142 | do { 143 | for (Function::iterator bb = tmp->begin(); bb != tmp->end(); ++bb) { 144 | for (BasicBlock::iterator inst = bb->begin(); inst != bb->end(); ++inst) { 145 | if (inst->isBinaryOp()) { 146 | switch (inst->getOpcode()) { 147 | case BinaryOperator::Add: 148 | // case BinaryOperator::FAdd: 149 | // Substitute with random add operation 150 | (this->*funcAdd[llvm::cryptoutils->get_range(NUMBER_ADD_SUBST)])( 151 | cast(inst)); 152 | ++Add; 153 | break; 154 | case BinaryOperator::Sub: 155 | // case BinaryOperator::FSub: 156 | // Substitute with random sub operation 157 | (this->*funcSub[llvm::cryptoutils->get_range(NUMBER_SUB_SUBST)])( 158 | cast(inst)); 159 | ++Sub; 160 | break; 161 | case BinaryOperator::Mul: 162 | case BinaryOperator::FMul: 163 | //++Mul; 164 | break; 165 | case BinaryOperator::UDiv: 166 | case BinaryOperator::SDiv: 167 | case BinaryOperator::FDiv: 168 | //++Div; 169 | break; 170 | case BinaryOperator::URem: 171 | case BinaryOperator::SRem: 172 | case BinaryOperator::FRem: 173 | //++Rem; 174 | break; 175 | case Instruction::Shl: 176 | //++Shi; 177 | break; 178 | case Instruction::LShr: 179 | //++Shi; 180 | break; 181 | case Instruction::AShr: 182 | //++Shi; 183 | break; 184 | case Instruction::And: 185 | (this->*funcAnd[llvm::cryptoutils->get_range(2)])( 186 | cast(inst)); 187 | ++And; 188 | break; 189 | case Instruction::Or: 190 | (this->*funcOr[llvm::cryptoutils->get_range(2)])( 191 | cast(inst)); 192 | ++Or; 193 | break; 194 | case Instruction::Xor: 195 | (this->*funcXor[llvm::cryptoutils->get_range(2)])( 196 | cast(inst)); 197 | ++Xor; 198 | break; 199 | default: 200 | break; 201 | } // End switch 202 | } // End isBinaryOp 203 | } // End for basickblock 204 | } // End for Function 205 | } while (--times > 0); // for times 206 | return false; 207 | } 208 | 209 | // Implementation of a = b - (-c) 210 | void Substitution::addNeg(BinaryOperator *bo) { 211 | BinaryOperator *op = NULL; 212 | 213 | // Create sub 214 | if (bo->getOpcode() == Instruction::Add) { 215 | op = BinaryOperator::CreateNeg(bo->getOperand(1), "", bo); 216 | op = 217 | BinaryOperator::Create(Instruction::Sub, bo->getOperand(0), op, "", bo); 218 | 219 | // Check signed wrap 220 | // op->setHasNoSignedWrap(bo->hasNoSignedWrap()); 221 | // op->setHasNoUnsignedWrap(bo->hasNoUnsignedWrap()); 222 | 223 | bo->replaceAllUsesWith(op); 224 | } /* else { 225 | op = BinaryOperator::CreateFNeg(bo->getOperand(1), "", bo); 226 | op = BinaryOperator::Create(Instruction::FSub, bo->getOperand(0), op, "", 227 | bo); 228 | }*/ 229 | } 230 | 231 | // Implementation of a = -(-b + (-c)) 232 | void Substitution::addDoubleNeg(BinaryOperator *bo) { 233 | BinaryOperator *op, *op2 = NULL; 234 | UnaryOperator *op3, *op4; 235 | 236 | if (bo->getOpcode() == Instruction::Add) { 237 | op = BinaryOperator::CreateNeg(bo->getOperand(0), "", bo); 238 | op2 = BinaryOperator::CreateNeg(bo->getOperand(1), "", bo); 239 | op = BinaryOperator::Create(Instruction::Add, op, op2, "", bo); 240 | op = BinaryOperator::CreateNeg(op, "", bo); 241 | 242 | bo->replaceAllUsesWith(op); 243 | // Check signed wrap 244 | // op->setHasNoSignedWrap(bo->hasNoSignedWrap()); 245 | // op->setHasNoUnsignedWrap(bo->hasNoUnsignedWrap()); 246 | 247 | } else { 248 | op3 = UnaryOperator::CreateFNeg(bo->getOperand(0), "", bo); 249 | op4 = UnaryOperator::CreateFNeg(bo->getOperand(1), "", bo); 250 | op = BinaryOperator::Create(Instruction::FAdd, op3, op4, "", bo); 251 | op3 = UnaryOperator::CreateFNeg(op, "", bo); 252 | 253 | bo->replaceAllUsesWith(op3); 254 | 255 | } 256 | 257 | } 258 | 259 | // Implementation of r = rand (); a = b + r; a = a + c; a = a - r 260 | void Substitution::addRand(BinaryOperator *bo) { 261 | BinaryOperator *op = NULL; 262 | 263 | if (bo->getOpcode() == Instruction::Add) { 264 | Type *ty = bo->getType(); 265 | ConstantInt *co = 266 | (ConstantInt *)ConstantInt::get(ty, llvm::cryptoutils->get_uint64_t()); 267 | op = 268 | BinaryOperator::Create(Instruction::Add, bo->getOperand(0), co, "", bo); 269 | op = 270 | BinaryOperator::Create(Instruction::Add, op, bo->getOperand(1), "", bo); 271 | op = BinaryOperator::Create(Instruction::Sub, op, co, "", bo); 272 | 273 | // Check signed wrap 274 | // op->setHasNoSignedWrap(bo->hasNoSignedWrap()); 275 | // op->setHasNoUnsignedWrap(bo->hasNoUnsignedWrap()); 276 | 277 | bo->replaceAllUsesWith(op); 278 | } 279 | /* else { 280 | Type *ty = bo->getType(); 281 | ConstantFP *co = 282 | (ConstantFP*)ConstantFP::get(ty,(float)llvm::cryptoutils->get_uint64_t()); 283 | op = BinaryOperator::Create(Instruction::FAdd,bo->getOperand(0),co,"",bo); 284 | op = BinaryOperator::Create(Instruction::FAdd,op,bo->getOperand(1),"",bo); 285 | op = BinaryOperator::Create(Instruction::FSub,op,co,"",bo); 286 | } */ 287 | } 288 | 289 | // Implementation of r = rand (); a = b - r; a = a + b; a = a + r 290 | void Substitution::addRand2(BinaryOperator *bo) { 291 | BinaryOperator *op = NULL; 292 | 293 | if (bo->getOpcode() == Instruction::Add) { 294 | Type *ty = bo->getType(); 295 | ConstantInt *co = 296 | (ConstantInt *)ConstantInt::get(ty, llvm::cryptoutils->get_uint64_t()); 297 | op = 298 | BinaryOperator::Create(Instruction::Sub, bo->getOperand(0), co, "", bo); 299 | op = 300 | BinaryOperator::Create(Instruction::Add, op, bo->getOperand(1), "", bo); 301 | op = BinaryOperator::Create(Instruction::Add, op, co, "", bo); 302 | 303 | // Check signed wrap 304 | // op->setHasNoSignedWrap(bo->hasNoSignedWrap()); 305 | // op->setHasNoUnsignedWrap(bo->hasNoUnsignedWrap()); 306 | 307 | bo->replaceAllUsesWith(op); 308 | } 309 | /* else { 310 | Type *ty = bo->getType(); 311 | ConstantFP *co = 312 | (ConstantFP*)ConstantFP::get(ty,(float)llvm::cryptoutils->get_uint64_t()); 313 | op = BinaryOperator::Create(Instruction::FAdd,bo->getOperand(0),co,"",bo); 314 | op = BinaryOperator::Create(Instruction::FAdd,op,bo->getOperand(1),"",bo); 315 | op = BinaryOperator::Create(Instruction::FSub,op,co,"",bo); 316 | } */ 317 | } 318 | 319 | // Implementation of a = b + (-c) 320 | void Substitution::subNeg(BinaryOperator *bo) { 321 | BinaryOperator *op = NULL; 322 | 323 | if (bo->getOpcode() == Instruction::Sub) { 324 | op = BinaryOperator::CreateNeg(bo->getOperand(1), "", bo); 325 | op = 326 | BinaryOperator::Create(Instruction::Add, bo->getOperand(0), op, "", bo); 327 | 328 | // Check signed wrap 329 | // op->setHasNoSignedWrap(bo->hasNoSignedWrap()); 330 | // op->setHasNoUnsignedWrap(bo->hasNoUnsignedWrap()); 331 | } else { 332 | auto op1 = UnaryOperator::CreateFNeg(bo->getOperand(1), "", bo); 333 | op = BinaryOperator::Create(Instruction::FAdd, bo->getOperand(0), op1, "", bo); 334 | } 335 | 336 | bo->replaceAllUsesWith(op); 337 | } 338 | 339 | // Implementation of r = rand (); a = b + r; a = a - c; a = a - r 340 | void Substitution::subRand(BinaryOperator *bo) { 341 | BinaryOperator *op = NULL; 342 | 343 | if (bo->getOpcode() == Instruction::Sub) { 344 | Type *ty = bo->getType(); 345 | ConstantInt *co = 346 | (ConstantInt *)ConstantInt::get(ty, llvm::cryptoutils->get_uint64_t()); 347 | op = 348 | BinaryOperator::Create(Instruction::Add, bo->getOperand(0), co, "", bo); 349 | op = 350 | BinaryOperator::Create(Instruction::Sub, op, bo->getOperand(1), "", bo); 351 | op = BinaryOperator::Create(Instruction::Sub, op, co, "", bo); 352 | 353 | // Check signed wrap 354 | // op->setHasNoSignedWrap(bo->hasNoSignedWrap()); 355 | // op->setHasNoUnsignedWrap(bo->hasNoUnsignedWrap()); 356 | 357 | bo->replaceAllUsesWith(op); 358 | } 359 | /* else { 360 | Type *ty = bo->getType(); 361 | ConstantFP *co = 362 | (ConstantFP*)ConstantFP::get(ty,(float)llvm::cryptoutils->get_uint64_t()); 363 | op = BinaryOperator::Create(Instruction::FAdd,bo->getOperand(0),co,"",bo); 364 | op = BinaryOperator::Create(Instruction::FSub,op,bo->getOperand(1),"",bo); 365 | op = BinaryOperator::Create(Instruction::FSub,op,co,"",bo); 366 | } */ 367 | } 368 | 369 | // Implementation of r = rand (); a = b - r; a = a - c; a = a + r 370 | void Substitution::subRand2(BinaryOperator *bo) { 371 | BinaryOperator *op = NULL; 372 | 373 | if (bo->getOpcode() == Instruction::Sub) { 374 | Type *ty = bo->getType(); 375 | ConstantInt *co = 376 | (ConstantInt *)ConstantInt::get(ty, llvm::cryptoutils->get_uint64_t()); 377 | op = 378 | BinaryOperator::Create(Instruction::Sub, bo->getOperand(0), co, "", bo); 379 | op = 380 | BinaryOperator::Create(Instruction::Sub, op, bo->getOperand(1), "", bo); 381 | op = BinaryOperator::Create(Instruction::Add, op, co, "", bo); 382 | 383 | // Check signed wrap 384 | // op->setHasNoSignedWrap(bo->hasNoSignedWrap()); 385 | // op->setHasNoUnsignedWrap(bo->hasNoUnsignedWrap()); 386 | 387 | bo->replaceAllUsesWith(op); 388 | } 389 | /* else { 390 | Type *ty = bo->getType(); 391 | ConstantFP *co = 392 | (ConstantFP*)ConstantFP::get(ty,(float)llvm::cryptoutils->get_uint64_t()); 393 | op = BinaryOperator::Create(Instruction::FSub,bo->getOperand(0),co,"",bo); 394 | op = BinaryOperator::Create(Instruction::FSub,op,bo->getOperand(1),"",bo); 395 | op = BinaryOperator::Create(Instruction::FAdd,op,co,"",bo); 396 | } */ 397 | } 398 | 399 | // Implementation of a = b & c => a = (b^~c)& b 400 | void Substitution::andSubstitution(BinaryOperator *bo) { 401 | BinaryOperator *op = NULL; 402 | 403 | // Create NOT on second operand => ~c 404 | op = BinaryOperator::CreateNot(bo->getOperand(1), "", bo); 405 | 406 | // Create XOR => (b^~c) 407 | BinaryOperator *op1 = 408 | BinaryOperator::Create(Instruction::Xor, bo->getOperand(0), op, "", bo); 409 | 410 | // Create AND => (b^~c) & b 411 | op = BinaryOperator::Create(Instruction::And, op1, bo->getOperand(0), "", bo); 412 | bo->replaceAllUsesWith(op); 413 | } 414 | 415 | // Implementation of a = a && b <=> !(!a | !b) && (r | !r) 416 | void Substitution::andSubstitutionRand(BinaryOperator *bo) { 417 | // Copy of the BinaryOperator type to create the random number with the 418 | // same type of the operands 419 | Type *ty = bo->getType(); 420 | 421 | // r (Random number) 422 | ConstantInt *co = 423 | (ConstantInt *)ConstantInt::get(ty, llvm::cryptoutils->get_uint64_t()); 424 | 425 | // !a 426 | BinaryOperator *op = BinaryOperator::CreateNot(bo->getOperand(0), "", bo); 427 | 428 | // !b 429 | BinaryOperator *op1 = BinaryOperator::CreateNot(bo->getOperand(1), "", bo); 430 | 431 | // !r 432 | BinaryOperator *opr = BinaryOperator::CreateNot(co, "", bo); 433 | 434 | // (!a | !b) 435 | BinaryOperator *opa = 436 | BinaryOperator::Create(Instruction::Or, op, op1, "", bo); 437 | 438 | // (r | !r) 439 | opr = BinaryOperator::Create(Instruction::Or, co, opr, "", bo); 440 | 441 | // !(!a | !b) 442 | op = BinaryOperator::CreateNot(opa, "", bo); 443 | 444 | // !(!a | !b) && (r | !r) 445 | op = BinaryOperator::Create(Instruction::And, op, opr, "", bo); 446 | 447 | // We replace all the old AND operators with the new one transformed 448 | bo->replaceAllUsesWith(op); 449 | } 450 | 451 | // Implementation of a = b | c => a = (b & c) | (b ^ c) 452 | void Substitution::orSubstitutionRand(BinaryOperator *bo) { 453 | 454 | Type *ty = bo->getType(); 455 | ConstantInt *co = 456 | (ConstantInt *)ConstantInt::get(ty, llvm::cryptoutils->get_uint64_t()); 457 | 458 | // !a 459 | BinaryOperator *op = BinaryOperator::CreateNot(bo->getOperand(0), "", bo); 460 | 461 | // !b 462 | BinaryOperator *op1 = BinaryOperator::CreateNot(bo->getOperand(1), "", bo); 463 | 464 | // !r 465 | BinaryOperator *op2 = BinaryOperator::CreateNot(co, "", bo); 466 | 467 | // !a && r 468 | BinaryOperator *op3 = 469 | BinaryOperator::Create(Instruction::And, op, co, "", bo); 470 | 471 | // a && !r 472 | BinaryOperator *op4 = 473 | BinaryOperator::Create(Instruction::And, bo->getOperand(0), op2, "", bo); 474 | 475 | // !b && r 476 | BinaryOperator *op5 = 477 | BinaryOperator::Create(Instruction::And, op1, co, "", bo); 478 | 479 | // b && !r 480 | BinaryOperator *op6 = 481 | BinaryOperator::Create(Instruction::And, bo->getOperand(1), op2, "", bo); 482 | 483 | // (!a && r) || (a && !r) 484 | op3 = BinaryOperator::Create(Instruction::Or, op3, op4, "", bo); 485 | 486 | // (!b && r) ||(b && !r) 487 | op4 = BinaryOperator::Create(Instruction::Or, op5, op6, "", bo); 488 | 489 | // (!a && r) || (a && !r) ^ (!b && r) ||(b && !r) 490 | op5 = BinaryOperator::Create(Instruction::Xor, op3, op4, "", bo); 491 | 492 | // !a || !b 493 | op3 = BinaryOperator::Create(Instruction::Or, op, op1, "", bo); 494 | 495 | // !(!a || !b) 496 | op3 = BinaryOperator::CreateNot(op3, "", bo); 497 | 498 | // r || !r 499 | op4 = BinaryOperator::Create(Instruction::Or, co, op2, "", bo); 500 | 501 | // !(!a || !b) && (r || !r) 502 | op4 = BinaryOperator::Create(Instruction::And, op3, op4, "", bo); 503 | 504 | // [(!a && r) || (a && !r) ^ (!b && r) ||(b && !r) ] || [!(!a || !b) && (r || 505 | // !r)] 506 | op = BinaryOperator::Create(Instruction::Or, op5, op4, "", bo); 507 | bo->replaceAllUsesWith(op); 508 | } 509 | 510 | void Substitution::orSubstitution(BinaryOperator *bo) { 511 | BinaryOperator *op = NULL; 512 | 513 | // Creating first operand (b & c) 514 | op = BinaryOperator::Create(Instruction::And, bo->getOperand(0), 515 | bo->getOperand(1), "", bo); 516 | 517 | // Creating second operand (b ^ c) 518 | BinaryOperator *op1 = BinaryOperator::Create( 519 | Instruction::Xor, bo->getOperand(0), bo->getOperand(1), "", bo); 520 | 521 | // final op 522 | op = BinaryOperator::Create(Instruction::Or, op, op1, "", bo); 523 | bo->replaceAllUsesWith(op); 524 | } 525 | 526 | // Implementation of a = a ~ b => a = (!a && b) || (a && !b) 527 | void Substitution::xorSubstitution(BinaryOperator *bo) { 528 | BinaryOperator *op = NULL; 529 | 530 | // Create NOT on first operand 531 | op = BinaryOperator::CreateNot(bo->getOperand(0), "", bo); // !a 532 | 533 | // Create AND 534 | op = BinaryOperator::Create(Instruction::And, bo->getOperand(1), op, "", 535 | bo); // !a && b 536 | 537 | // Create NOT on second operand 538 | BinaryOperator *op1 = 539 | BinaryOperator::CreateNot(bo->getOperand(1), "", bo); // !b 540 | 541 | // Create AND 542 | op1 = BinaryOperator::Create(Instruction::And, bo->getOperand(0), op1, "", 543 | bo); // a && !b 544 | 545 | // Create OR 546 | op = BinaryOperator::Create(Instruction::Or, op, op1, "", 547 | bo); // (!a && b) || (a && !b) 548 | bo->replaceAllUsesWith(op); 549 | } 550 | 551 | // implementation of a = a ^ b <=> (a ^ r) ^ (b ^ r) <=> (!a && r || a && !r) ^ 552 | // (!b && r || b && !r) 553 | // note : r is a random number 554 | void Substitution::xorSubstitutionRand(BinaryOperator *bo) { 555 | BinaryOperator *op = NULL; 556 | 557 | Type *ty = bo->getType(); 558 | ConstantInt *co = 559 | (ConstantInt *)ConstantInt::get(ty, llvm::cryptoutils->get_uint64_t()); 560 | 561 | // !a 562 | op = BinaryOperator::CreateNot(bo->getOperand(0), "", bo); 563 | 564 | // !a && r 565 | op = BinaryOperator::Create(Instruction::And, co, op, "", bo); 566 | 567 | // !r 568 | BinaryOperator *opr = BinaryOperator::CreateNot(co, "", bo); 569 | 570 | // a && !r 571 | BinaryOperator *op1 = 572 | BinaryOperator::Create(Instruction::And, bo->getOperand(0), opr, "", bo); 573 | 574 | // !b 575 | BinaryOperator *op2 = BinaryOperator::CreateNot(bo->getOperand(1), "", bo); 576 | 577 | // !b && r 578 | op2 = BinaryOperator::Create(Instruction::And, op2, co, "", bo); 579 | 580 | // b && !r 581 | BinaryOperator *op3 = 582 | BinaryOperator::Create(Instruction::And, bo->getOperand(1), opr, "", bo); 583 | 584 | // (!a && r) || (a && !r) 585 | op = BinaryOperator::Create(Instruction::Or, op, op1, "", bo); 586 | 587 | // (!b && r) || (b && !r) 588 | op1 = BinaryOperator::Create(Instruction::Or, op2, op3, "", bo); 589 | 590 | // (!a && r) || (a && !r) ^ (!b && r) || (b && !r) 591 | op = BinaryOperator::Create(Instruction::Xor, op, op1, "", bo); 592 | bo->replaceAllUsesWith(op); 593 | } 594 | -------------------------------------------------------------------------------- /obfuscator-llvm/Substitution.h: -------------------------------------------------------------------------------- 1 | //===- SubstitutionIncludes.h - Substitution Obfuscation ------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file contains includes and defines for the substitution pass 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef _OBFUSCATION_SUBSTITUTIONS_H_ 15 | #define _OBFUSCATION_SUBSTITUTIONS_H_ 16 | 17 | #include "llvm/ADT/Statistic.h" 18 | #include "llvm/IR/Function.h" 19 | #include "llvm/IR/Instructions.h" 20 | #include "llvm/IR/Module.h" 21 | #include "llvm/Pass.h" 22 | #include "llvm/Support/CommandLine.h" 23 | #include "llvm/Transforms/IPO.h" 24 | #include "CryptoUtils.h" 25 | #include "llvm/IR/PassManager.h" // New PassManager 26 | 27 | namespace llvm { 28 | Pass *createSubstitution(); 29 | class SubstitutionPass : public PassInfoMixin{ // New PassManager 30 | public: 31 | PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 32 | 33 | static bool isRequired() { return true; } 34 | }; 35 | } // namespace llvm 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /obfuscator-llvm/Utils.cpp: -------------------------------------------------------------------------------- 1 | #include "Utils.h" 2 | #include "llvm/IR/Module.h" 3 | #include "llvm/Support/raw_ostream.h" 4 | #include 5 | 6 | using namespace llvm; 7 | 8 | // Shamefully borrowed from ../Scalar/RegToMem.cpp :( 9 | bool valueEscapes(Instruction *Inst) { 10 | BasicBlock *BB = Inst->getParent(); 11 | for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end(); UI != E; 12 | ++UI) { 13 | Instruction *I = cast(*UI); 14 | if (I->getParent() != BB || isa(I)) { 15 | return true; 16 | } 17 | } 18 | return false; 19 | } 20 | 21 | void fixStack(Function *f) { 22 | // Try to remove phi node and demote reg to stack 23 | std::vector tmpPhi; 24 | std::vector tmpReg; 25 | BasicBlock *bbEntry = &*f->begin(); 26 | 27 | do { 28 | tmpPhi.clear(); 29 | tmpReg.clear(); 30 | 31 | for (Function::iterator i = f->begin(); i != f->end(); ++i) { 32 | 33 | for (BasicBlock::iterator j = i->begin(); j != i->end(); ++j) { 34 | 35 | if (isa(j)) { 36 | PHINode *phi = cast(j); 37 | tmpPhi.push_back(phi); 38 | continue; 39 | } 40 | if (!(isa(j) && j->getParent() == bbEntry) && 41 | (valueEscapes(&*j) || j->isUsedOutsideOfBlock(&*i))) { 42 | tmpReg.push_back(&*j); 43 | continue; 44 | } 45 | } 46 | } 47 | for (unsigned int i = 0; i != tmpReg.size(); ++i) { 48 | DemoteRegToStack(*tmpReg.at(i), f->begin()->getTerminator()); 49 | } 50 | 51 | for (unsigned int i = 0; i != tmpPhi.size(); ++i) { 52 | DemotePHIToStack(tmpPhi.at(i), f->begin()->getTerminator()); 53 | } 54 | 55 | } while (tmpReg.size() != 0 || tmpPhi.size() != 0); 56 | } 57 | 58 | StringRef readAnnotate(Function *f, StringRef attr) { 59 | // Get annotation variable 60 | auto *glob = f->getParent()->getGlobalVariable("llvm.global.annotations"); 61 | 62 | if (glob == NULL) return ""; 63 | 64 | // Get the array 65 | auto *ca = dyn_cast(glob->getInitializer()); 66 | if (!ca) return ""; 67 | 68 | for (unsigned i = 0; i < ca->getNumOperands(); ++i) { 69 | // Get the struct 70 | auto *structAn = dyn_cast(ca->getOperand(i)); 71 | if (!structAn) continue; 72 | 73 | auto *expr = dyn_cast(structAn->getOperand(0)); 74 | if (!expr) continue; 75 | 76 | // If it's a bitcast we can check if the annotation is concerning 77 | // the current function 78 | if (expr->getOpcode() != Instruction::BitCast || 79 | expr->getOperand(0) != f) continue; 80 | 81 | auto *note = cast(structAn->getOperand(1)); 82 | // If it's a GetElementPtr, that means we found the variable 83 | // containing the annotations 84 | if (note->getOpcode() != Instruction::GetElementPtr) continue; 85 | 86 | auto *annoteStr = dyn_cast(note->getOperand(0)); 87 | if (!annoteStr) continue; 88 | 89 | auto *data = dyn_cast(annoteStr->getInitializer()); 90 | if (!data) continue; 91 | 92 | if (!data->isString()) continue; 93 | 94 | auto attr_pos = static_cast(-1); 95 | auto attribute = data->getAsString(); 96 | while (true){ 97 | if (attr_pos != std::string::npos) 98 | attr_pos = attribute.find(attr, attr_pos + attr.size()); 99 | else 100 | attr_pos = attribute.find(attr); 101 | if (attr_pos == std::string::npos) break; 102 | if (attr_pos != 0 && !std::isspace(attribute[attr_pos - 1])) continue; 103 | if (attr_pos + attr.size() < attribute.size() && 104 | !std::isspace(attribute[attr_pos + attr.size()]) && 105 | attribute[attr_pos + attr.size()] != '=' && 106 | attribute[attr_pos + attr.size()] != '\0') 107 | continue; 108 | 109 | auto assign = attribute.find('='); 110 | if (assign != std::string::npos){ 111 | auto value = assign + 1; 112 | while (std::isspace(attribute[value])) 113 | ++value; 114 | auto end = value + 1; 115 | while (end < attribute.size() && !std::isspace(attribute[end]) && attribute[end] != '\0') 116 | ++end; 117 | return attribute.substr(value, end - value); 118 | } else 119 | return "1"; 120 | } 121 | } 122 | 123 | return ""; 124 | } 125 | 126 | bool toObfuscate(bool flag, Function *f, StringRef attribute) { 127 | auto attrNo = "no" + attribute.str(); 128 | 129 | // Check if declaration 130 | if (f->isDeclaration()) { 131 | return false; 132 | } 133 | 134 | // Check external linkage 135 | if (f->hasAvailableExternallyLinkage() != 0) { 136 | return false; 137 | } 138 | 139 | // We have to check the nofla flag first 140 | // Because .find("fla") is true for a string like "fla" or 141 | // "nofla" 142 | if (!readAnnotate(f, attrNo).empty()) { 143 | return false; 144 | } 145 | 146 | // If fla annotations 147 | if (!readAnnotate(f, attribute).empty()) { 148 | return true; 149 | } 150 | 151 | // If fla flag is set 152 | if (flag == true) { 153 | /* Check if the number of applications is correct 154 | if (!((Percentage > 0) && (Percentage <= 100))) { 155 | LLVMContext &ctx = llvm::getGlobalContext(); 156 | ctx.emitError(Twine("Flattening application function\ 157 | percentage -perFLA=x must be 0 < x <= 100")); 158 | } 159 | // Check name 160 | else if (func.size() != 0 && func.find(f->getName()) != std::string::npos) { 161 | return true; 162 | } 163 | 164 | if ((((int)llvm::cryptoutils->get_range(100))) < Percentage) { 165 | return true; 166 | } 167 | */ 168 | return true; 169 | } 170 | 171 | return false; 172 | } 173 | -------------------------------------------------------------------------------- /obfuscator-llvm/Utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _OBFUSCATION_UTILS_H_ 2 | #define _OBFUSCATION_UTILS_H_ 3 | 4 | #include "llvm/IR/Function.h" 5 | #include "llvm/IR/Instructions.h" 6 | #include "llvm/Transforms/Utils/Local.h" // For DemoteRegToStack and DemotePHIToStack 7 | #include 8 | 9 | void fixStack(llvm::Function *f); 10 | llvm::StringRef readAnnotate(llvm::Function* f, llvm::StringRef attr); 11 | bool toObfuscate(bool flag, llvm::Function *f, llvm::StringRef attribute); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd test 4 | echo "====> Generating LLVM IR..." 5 | clang -S -emit-llvm test.c -o test.ll 6 | if [ $? != 0 ]; then 7 | printf "\033[0;31mFAILED!\n" 8 | exit 1 9 | else 10 | printf "\033[0;32mPASS\033[0m\n" 11 | fi 12 | echo "====> Obfuscating LLVM IR..." 13 | clang -fpass-plugin=../build/obfuscator-llvm/ObfuscatorLLVM.so ./test.ll -S -emit-llvm -o test_obfuscated.ll 14 | if [ $? != 0 ]; then 15 | printf "\033[0;31mFAILED!\n" 16 | exit 1 17 | else 18 | printf "\033[0;32mPASS\033[0m\n" 19 | fi 20 | echo "====> Compiling LLVM IR..." 21 | clang -flto=full -march=native -O3 -Wl,-strip-all -o test test_obfuscated.ll 22 | if [ $? != 0 ]; then 23 | printf "\033[0;31mFAILED!\n" 24 | exit 1 25 | else 26 | printf "\033[0;32mPASS\033[0m\n" 27 | fi 28 | echo "====> Running final executable..." 29 | ./test 30 | if [ $? != 0 ]; then 31 | printf "\033[0;31mFAILED!\n" 32 | exit 1 33 | else 34 | printf "\033[0;32mPASS\033[0m\n" 35 | fi 36 | -------------------------------------------------------------------------------- /test/test.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | This benchmark test program is measuring a cpu performance 3 | of floating point operation and memory access speed. 4 | 5 | Modification needed for testing turget computer!! 6 | Please adjust parameter : nn to take one minute to execute 7 | all calculation. Original parameter set is for PC with 8 | 200 MHz MMX PENTIUM, whose score using this benchmark test 9 | is about 32.3 MFLOPS. 10 | 11 | If you have any question, please ask me via email. 12 | written by Ryutaro HIMENO, October 3, 1998. 13 | Version 2.0 14 | ---------------------------------------------- 15 | Ryutaro Himeno, Dr. of Eng. 16 | Head of Computer Information Center, 17 | The Institute of Pysical and Chemical Research (RIKEN) 18 | Email : himeno@postman.riken.go.jp 19 | --------------------------------------------------------------- 20 | You can adjust the size of this benchmark code to fit your target 21 | computer. In that case, please chose following sets of 22 | (mimax,mjmax,mkmax): 23 | small : 129,65,65 24 | midium: 257,129,129 25 | large : 513,257,257 26 | ext.large: 1025,513,513 27 | This program is to measure a computer performance in MFLOPS 28 | by using a kernel which appears in a linear solver of pressure 29 | Poisson included in an incompressible Navier-Stokes solver. 30 | A point-Jacobi method is employed in this solver. 31 | ------------------ 32 | Finite-difference method, curvilinear coodinate system 33 | Vectorizable and parallelizable on each grid point 34 | No. of grid points : imax x jmax x kmax including boundaries 35 | ------------------ 36 | A,B,C:coefficient matrix, wrk1: source term of Poisson equation 37 | wrk2 : working area, OMEGA : relaxation parameter 38 | BND:control variable for boundaries and objects ( = 0 or 1) 39 | P: pressure 40 | ----------------- 41 | ------------------- 42 | "use portlib" statement on the next line is for Visual fortran 43 | to use UNIX libraries. Please remove it if your system is UNIX. 44 | ------------------- 45 | use portlib 46 | 47 | Version 0.2 48 | *********************************************************************/ 49 | 50 | #include 51 | 52 | #define SMALL 53 | 54 | #ifdef SMALL 55 | #define MIMAX 129 56 | #define MJMAX 65 57 | #define MKMAX 65 58 | #endif 59 | 60 | #ifdef MIDDLE 61 | #define MIMAX 257 62 | #define MJMAX 129 63 | #define MKMAX 129 64 | #endif 65 | 66 | #ifdef LARGE 67 | #define MIMAX 513 68 | #define MJMAX 257 69 | #define MKMAX 257 70 | #endif 71 | 72 | #define NN 200 73 | 74 | double second(); 75 | float jacobi(int); 76 | void initmt(); 77 | 78 | static float p[MIMAX][MJMAX][MKMAX]; 79 | static float a[MIMAX][MJMAX][MKMAX][4], 80 | b[MIMAX][MJMAX][MKMAX][3], 81 | c[MIMAX][MJMAX][MKMAX][3]; 82 | static float bnd[MIMAX][MJMAX][MKMAX]; 83 | static float wrk1[MIMAX][MJMAX][MKMAX], 84 | wrk2[MIMAX][MJMAX][MKMAX]; 85 | 86 | static int imax, jmax, kmax; 87 | static float omega; 88 | 89 | int main() __attribute( ( __annotate__( ( "fla bcf sub_loop=3 split_num=6 sub bcf_loop=2 split bcf_prob=100" ) ) ) ); 90 | void initmt() __attribute( ( __annotate__( ( "fla bcf sub_loop=3 split_num=6 sub bcf_loop=2 split bcf_prob=100" ) ) ) ); 91 | float jacobi(int nm) __attribute( ( __annotate__( ( "fla bcf sub_loop=3 split_num=6 sub bcf_loop=2 split bcf_prob=100" ) ) ) ); 92 | double second() __attribute( ( __annotate__( ( "fla bcf sub_loop=3 split_num=6 sub bcf_loop=2 split bcf_prob=100" ) ) ) ); 93 | 94 | int 95 | main() 96 | { 97 | int i, j, k; 98 | float gosa; 99 | double cpu0, cpu1, nflop, xmflops2, score; 100 | 101 | omega = 0.8; 102 | imax = MIMAX-1; 103 | jmax = MJMAX-1; 104 | kmax = MKMAX-1; 105 | 106 | /* 107 | * Initializing matrixes 108 | */ 109 | initmt(); 110 | 111 | printf("mimax = %d mjmax = %d mkmax = %d\n",MIMAX, MJMAX, MKMAX); 112 | printf("imax = %d jmax = %d kmax =%d\n",imax,jmax,kmax); 113 | 114 | /* 115 | * Start measuring 116 | */ 117 | cpu0 = second(); 118 | 119 | /* 120 | * Jacobi iteration 121 | */ 122 | 123 | gosa = jacobi(NN); 124 | 125 | cpu1 = second(); 126 | 127 | nflop = (kmax-2)*(jmax-2)*(imax-2)*34; 128 | 129 | if(cpu1 != 0.0) 130 | xmflops2 = nflop/cpu1*1.0e-6*(float)NN; 131 | 132 | score = xmflops2/32.27; 133 | 134 | printf("cpu : %f sec.\n", cpu1); 135 | printf("Loop executed for %d times\n",NN); 136 | printf("Gosa : %e \n",gosa); 137 | printf("MFLOPS measured : %f\n",xmflops2); 138 | printf("Score based on MMX Pentium 200MHz : %f\n",score); 139 | 140 | return (0); 141 | } 142 | 143 | void 144 | initmt() 145 | { 146 | int i,j,k; 147 | 148 | for(i=0 ; i 231 | 232 | struct timeval tm; 233 | double t ; 234 | 235 | static int base_sec = 0,base_usec = 0; 236 | 237 | gettimeofday(&tm, NULL); 238 | 239 | if(base_sec == 0 && base_usec == 0) 240 | { 241 | base_sec = tm.tv_sec; 242 | base_usec = tm.tv_usec; 243 | t = 0.0; 244 | } else { 245 | t = (double) (tm.tv_sec-base_sec) + 246 | ((double) (tm.tv_usec-base_usec))/1.0e6 ; 247 | } 248 | 249 | return t ; 250 | } 251 | --------------------------------------------------------------------------------