├── .gitignore ├── LICENSE ├── LLVMPassBuild ├── LLVMPassBuild │ ├── .LLVMDomTreePass.cpp.un~ │ ├── CMakeLists.txt │ ├── LLVMBuild.txt │ ├── LLVMDomTreePass.cpp │ ├── LLVMDomTreePass.cpp~ │ └── Makefile ├── apply_patches.sh ├── build.sh ├── partial_build.sh └── patches │ ├── InitializePasses.patch │ └── build_less_tools.patch ├── README.md ├── base_case.c ├── complete_test_addition.sh ├── complete_test_base_case.sh ├── complete_test_subtraction.sh ├── complete_test_xor.sh ├── llvm2z3.py ├── partial_build.sh ├── quick_setup.sh ├── test.s ├── test_addition.c ├── test_addition.sh ├── test_base_case.c ├── test_base_case.sh ├── test_subtraction.c ├── test_subtraction.sh ├── test_xor.c ├── test_xor.sh └── z3Conditions.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Trail of Bits 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LLVMPassBuild/LLVMPassBuild/.LLVMDomTreePass.cpp.un~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trailofbits/DomTreSat/aa02a688f0b29377be2d444db610fccfe1722328/LLVMPassBuild/LLVMPassBuild/.LLVMDomTreePass.cpp.un~ -------------------------------------------------------------------------------- /LLVMPassBuild/LLVMPassBuild/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_llvm_loadable_module( LLVMMAST 2 | LLVMDomTreePass.cpp 3 | ) 4 | 5 | add_dependencies(LLVMMAST intrinsics_gen) 6 | -------------------------------------------------------------------------------- /LLVMPassBuild/LLVMPassBuild/LLVMBuild.txt: -------------------------------------------------------------------------------- 1 | ;===- ./lib/Transforms/MAST/LLVMBuild.txt ----------------------*- Conf -*--===; 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 | ; 11 | ; This is an LLVMBuild description file for the components in this subdirectory. 12 | ; 13 | ; For more information on the LLVMBuild system, please see: 14 | ; 15 | ; http://llvm.org/docs/LLVMBuild.html 16 | ; 17 | ;===------------------------------------------------------------------------===; 18 | 19 | [component_0] 20 | type = Library 21 | name = LLVMPassBuild 22 | parent = Transforms 23 | library_name = dotre 24 | required_libraries = Analysis Core Support TransformUtils 25 | -------------------------------------------------------------------------------- /LLVMPassBuild/LLVMPassBuild/LLVMDomTreePass.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #define DEBUG_TYPE "mast" 3 | #include "llvm/IR/DerivedTypes.h" 4 | #include "llvm/IR/Constant.h" 5 | #include "llvm/IR/GlobalVariable.h" 6 | #include "llvm/Pass.h" 7 | #include "llvm/IR/Module.h" 8 | #include "llvm/IR/Function.h" 9 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" 10 | #include "llvm/IR/IRBuilder.h" 11 | #include "llvm/Support/raw_ostream.h" 12 | #include "llvm/Support/FileSystem.h" 13 | #include "llvm/IR/InstIterator.h" 14 | #include "llvm/ADT/Statistic.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "llvm/Transforms/Utils/Cloning.h" 21 | #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" 22 | #include "llvm/IR/Dominators.h" 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | 32 | using namespace llvm; 33 | std::vector>> z3_con; 34 | 35 | namespace { 36 | 37 | struct DoTrePass: public ModulePass { 38 | DoTrePass() : ModulePass(ID) { } 39 | 40 | static char ID; 41 | bool first_hit; 42 | void getAnalysisUsage(AnalysisUsage &AU) const override { 43 | ModulePass::getAnalysisUsage(AU); 44 | AU.addRequired(); 45 | } 46 | 47 | virtual const char *getPassName() const override 48 | { 49 | return "Create Dominator Tree and Associated Use-Define Chain Analysis"; 50 | } 51 | 52 | virtual bool runOnFunction(Function &F) 53 | { 54 | 55 | //DominatorTree *DT = &getAnalysis().getDomTree(); 56 | outs()<<"<-- Run on Full Module to Successfully Generate the Dominator Tree --> \n\n"; 57 | return true; 58 | } 59 | 60 | 61 | // function recursively checks for operations applied to the variable, climbing backwards up the Use-Def Chain until a return or end of operation indicator is hit 62 | bool recursiveEndCheck(Instruction *inst, std::unordered_set &used_insts, std::vector> &new_arg) 63 | { 64 | if (std::find(used_insts.begin(), used_insts.end(), inst) == used_insts.end()) 65 | { 66 | used_insts.insert(inst); 67 | outs()<<"\t\t\t[-] RECURSING THROUGH OPERATION\n"; 68 | if(inst->getOpcode() == Instruction::Xor) 69 | { 70 | ConstantInt *_xor = cast(inst->getOperand(1)); 71 | outs()<<"\t\t\t\t==> Found Operator: Xor :: "<<_xor->getZExtValue()<<"\n"; 72 | std::tuple base_cmp2( "^", (int)_xor->getZExtValue()); 73 | new_arg.push_back(base_cmp2); 74 | }else if(inst->getOpcode() == Instruction::Add ) 75 | { 76 | ConstantInt *_add = cast(inst->getOperand(1)); 77 | outs()<<"\t\t\t\t==> Found Operator: Add :: "<<_add->getZExtValue()<<"\n"; 78 | std::tuple base_cmp2( "+", (int)_add->getZExtValue()); 79 | new_arg.push_back(base_cmp2); 80 | }else if(inst->getOpcode() == Instruction::Sub ) 81 | { 82 | ConstantInt *_sub = cast(inst->getOperand(1)); 83 | outs()<<"\t\t\t\t==> Found Operator: Sub :: "<<_sub->getZExtValue()<<"\n"; 84 | std::tuple base_cmp2( "-", (int)_sub->getZExtValue()); 85 | new_arg.push_back(base_cmp2); 86 | } 87 | return false; 88 | }else{ 89 | return true; 90 | } 91 | } 92 | 93 | // TODO: add support for more conditions such as finite for loops 94 | // 95 | // This recursive function tells us where our variable got its value. Aka an allocation, a store instruction, or is it a command line argument. 96 | // This tool automcatically focuses on command line input but can be modified to target variables with controllable input from a variety of methods` 97 | void recursiveValueTracer(Instruction* delme, std::unordered_set &used_insts, std::vector> &new_arg) 98 | { 99 | 100 | for(Instruction::op_iterator it = delme->op_begin(); it != delme->op_end(); it++) 101 | { 102 | 103 | if (AllocaInst *All = dyn_cast(it)) 104 | { 105 | if(std::find(used_insts.begin(), used_insts.end(), All) == used_insts.end()){ 106 | outs()<<"\t[!] FOUND TERMINATING ALLOCATION\n\n"; 107 | recursiveEndCheck(All, used_insts, new_arg); 108 | outs()<<"\t\t[ TRACING BACK HISTORY OF OPERAND VALUE ]\n"; 109 | for(Instruction::user_iterator all_user = All->user_begin(); all_user != All->user_end(); all_user++){ 110 | if(StoreInst *all_str = dyn_cast(*all_user)){ 111 | outs()<<"\t\t[+] Found StoreInst to trace\n"; 112 | recursiveValueTracer(all_str, used_insts, new_arg); 113 | } 114 | } 115 | } 116 | } 117 | else if(Instruction *Inst = dyn_cast(it)) 118 | { 119 | 120 | if(std::find(used_insts.begin(), used_insts.end(), Inst) == used_insts.end()){ 121 | recursiveEndCheck(Inst, used_insts, new_arg); 122 | recursiveValueTracer(Inst, used_insts, new_arg); 123 | } 124 | } 125 | else 126 | { 127 | if(first_hit){ 128 | first_hit = false; 129 | outs()<<"\t\t.... Potential find. Store took value from :: argv\n\n"; 130 | } 131 | } 132 | } 133 | 134 | recursiveEndCheck(delme, used_insts, new_arg); 135 | 136 | } 137 | 138 | 139 | 140 | virtual bool runOnModule(Module &M) override 141 | { 142 | 143 | for(Module::iterator F = M.begin(), E = M.end(); F != E; ++F) 144 | { 145 | if(F->getName().str() == "main"){ 146 | outs()<<"\n<-- Starting analysis from main() --> \n"; 147 | if (!F->empty()){ 148 | DominatorTree &DT = getAnalysis(*F).getDomTree(); 149 | 150 | // we know we only need to trace the most dominated path for the example binary 151 | // TODO: for future test binarys, dynamically choose a dominated path or analayze all dominated paths 152 | outs()<<"\t[+] Tracing first path of DominatorTree\n\n\n"; 153 | 154 | for (auto node = GraphTraits::nodes_begin(&DT); node != GraphTraits::nodes_end(&DT); ++node) 155 | { 156 | // iterate through all blocks in the most dominated path 157 | // check if an ending block, if not analyze, if it is an ending block, save constraints for this one sub-path 158 | 159 | // TODO: add support for paths with multiple returns 160 | // (i.e. function calls and returns from functions which still operate on the variables of interest) 161 | 162 | BasicBlock *BB = node->getBlock(); 163 | if(( (BB->getName()).str().find("end") == std::string::npos) && ( (BB->getName()).str().find("return") == std::string::npos)){ 164 | // pulls out the values and operations for controlled variables through each basic block 165 | for(BasicBlock::iterator Ins = BB->begin(), E = BB->end(); Ins != E; ++Ins){ 166 | if(isa(Ins)){ 167 | sleep(1); 168 | outs()<<"[ COMPARE FOUND ]\n"; 169 | std::vector> new_arg; 170 | std::string cmp_op = ""; 171 | 172 | // switch case for compare instuction types 173 | // easy 'conditions' to pull out that our controllabe variables must satisfy 174 | if(cast(Ins)->getPredicate() == CmpInst::ICMP_EQ) 175 | { 176 | outs()<<"\tComparison Operator: IS EQUAL (==)\n\n"; 177 | cmp_op = "=="; 178 | } 179 | else if(cast(Ins)->getPredicate() == CmpInst::ICMP_NE) 180 | { 181 | outs()<<"\tComparison Operator: IS EQUAL (!=)\n\n"; 182 | cmp_op = "!="; 183 | } 184 | else 185 | { 186 | outs()<<"\t[-] WARNING INSERT UNSUPPORTED PREDICATE\n\n"; 187 | return false; 188 | } 189 | first_hit = true; 190 | 191 | outs()<<"\n\n\t[+] VALUE TWO: \n"; 192 | if(Instruction *op_inst = dyn_cast(Ins->getOperand(1))){ 193 | std::unordered_set used_2; 194 | outs()<<"\tReovering variable operations and starting value....\n"; 195 | // uses recursion to recover the 'history' of our variables 196 | // i.e. the dominating operations 197 | recursiveValueTracer(op_inst, used_2, new_arg); 198 | }else{ 199 | if(ConstantInt *con = dyn_cast(Ins->getOperand(1))){ 200 | outs()<<"\t\t\t\t==> Found Constant Operand: Integer :: "<< con->getZExtValue() <<"\n\n\n"; 201 | std::tuple base_cmp( cmp_op, (int)con->getZExtValue()); 202 | new_arg.push_back(base_cmp); 203 | } 204 | } 205 | outs()<<"\n\n\t[+] VALUE ONE: \n\n"; 206 | if(Instruction *op_inst = dyn_cast(Ins->getOperand(0))){ 207 | std::unordered_set used_1; 208 | outs()<<"\tReovering variable operations and starting value....\n"; 209 | recursiveValueTracer(op_inst, used_1, new_arg); 210 | }else{ 211 | if(ConstantInt *con = dyn_cast(Ins->getOperand(0))){ 212 | outs()<<"\t\t\t\t==> Found Constant Operand: Integer :: "<< con->getZExtValue() <<"\n"; 213 | std::tuple base_cmp2( cmp_op, (int)con->getZExtValue()); 214 | new_arg.push_back(base_cmp2); 215 | } 216 | } 217 | z3_con.push_back(new_arg); 218 | } 219 | } 220 | } 221 | else 222 | { 223 | outs()<<"Breaking at end of first path with # of children\n"; 224 | outs()<<"[ CHECK ]: 0 == "<< node->getNumChildren()<<"\n\n"; 225 | break; 226 | } 227 | } 228 | 229 | 230 | 231 | } 232 | } 233 | } 234 | outs()<<"<-- Successfully Traversed Dominator Tree --> \n"; 235 | outs()<<"[+] The below arguments are operated upon, then this redefinition must finally be equal to the comparisons shown below.\n\n"; 236 | 237 | int i = 0; 238 | std::vector> >::iterator vvt_iterator; 239 | std::vector>::iterator vt_iterator; 240 | // dump contents of path conditions in order of argument to be read into z3 241 | std::ofstream z3File; 242 | z3File.open("z3Conditions.txt"); 243 | 244 | for(vvt_iterator = z3_con.begin(); vvt_iterator != z3_con.end(); ++(vvt_iterator)){ 245 | outs()<<"argv["<((*vt_iterator))<<" "<((*vt_iterator)); 250 | z3File<<";"<((*vt_iterator))<<" "<((*vt_iterator)); 251 | } 252 | outs()<<"\n"; 253 | z3File<<"\n"; 254 | } 255 | z3File.close(); 256 | return true; 257 | } 258 | 259 | }; 260 | 261 | } 262 | char DoTrePass::ID = 0; 263 | static RegisterPass X("dotrepass", "Dominator Tree Path Solver : Export to satisfiability", false, false); 264 | 265 | -------------------------------------------------------------------------------- /LLVMPassBuild/LLVMPassBuild/LLVMDomTreePass.cpp~: -------------------------------------------------------------------------------- 1 | #include 2 | #define DEBUG_TYPE "mast" 3 | #include "llvm/IR/DerivedTypes.h" 4 | #include "llvm/IR/Constant.h" 5 | #include "llvm/IR/GlobalVariable.h" 6 | #include "llvm/Pass.h" 7 | #include "llvm/IR/Module.h" 8 | #include "llvm/IR/Function.h" 9 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" 10 | #include "llvm/IR/IRBuilder.h" 11 | #include "llvm/Support/raw_ostream.h" 12 | #include "llvm/Support/FileSystem.h" 13 | #include "llvm/IR/InstIterator.h" 14 | #include "llvm/ADT/Statistic.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "llvm/Transforms/Utils/Cloning.h" 21 | #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" 22 | #include "llvm/IR/Dominators.h" 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | 32 | using namespace llvm; 33 | std::vector>> z3_con; 34 | 35 | namespace { 36 | 37 | struct DoTrePass: public ModulePass { 38 | DoTrePass() : ModulePass(ID) { } 39 | 40 | static char ID; 41 | bool first_hit; 42 | void getAnalysisUsage(AnalysisUsage &AU) const override { 43 | ModulePass::getAnalysisUsage(AU); 44 | AU.addRequired(); 45 | } 46 | 47 | virtual const char *getPassName() const override 48 | { 49 | return "Remove All Obfuscator Symbols"; 50 | } 51 | 52 | virtual bool runOnFunction(Function &F) 53 | { 54 | 55 | //DominatorTree *DT = &getAnalysis().getDomTree(); 56 | outs()<<"<-- Run on Full Module to Successfully Generate the Dominator Tree --> \n\n"; 57 | return true; 58 | } 59 | 60 | 61 | // function recursively checks for operations applied to the variable, climbing backwards up the Use-Def Chain until a return or end of operation indicator is hit 62 | bool recursiveEndCheck(Instruction *inst, std::unordered_set &used_insts, std::vector> &new_arg) 63 | { 64 | if (std::find(used_insts.begin(), used_insts.end(), inst) == used_insts.end()) 65 | { 66 | used_insts.insert(inst); 67 | outs()<<"\t\t\t[-] RECURSING THROUGH OPERATION\n"; 68 | if(inst->getOpcode() == Instruction::Xor) 69 | { 70 | ConstantInt *_xor = cast(inst->getOperand(1)); 71 | outs()<<"\t\t\t\t==> Found Operator: Xor :: "<<_xor->getZExtValue()<<"\n"; 72 | std::tuple base_cmp2( "^", (int)_xor->getZExtValue()); 73 | new_arg.push_back(base_cmp2); 74 | }else if(inst->getOpcode() == Instruction::Add ) 75 | { 76 | ConstantInt *_add = cast(inst->getOperand(1)); 77 | outs()<<"\t\t\t\t==> Found Operator: Add :: "<<_add->getZExtValue()<<"\n"; 78 | std::tuple base_cmp2( "+", (int)_add->getZExtValue()); 79 | new_arg.push_back(base_cmp2); 80 | }else if(inst->getOpcode() == Instruction::Sub ) 81 | { 82 | ConstantInt *_sub = cast(inst->getOperand(1)); 83 | outs()<<"\t\t\t\t==> Found Operator: Sub :: "<<_sub->getZExtValue()<<"\n"; 84 | std::tuple base_cmp2( "-", (int)_sub->getZExtValue()); 85 | new_arg.push_back(base_cmp2); 86 | } 87 | return false; 88 | }else{ 89 | return true; 90 | } 91 | } 92 | 93 | // TODO: add support for more conditions such as finite for loops 94 | // 95 | // This recursive function tells us where our variable got its value. Aka an allocation, a store instruction, or is it a command line argument. 96 | // This tool automcatically focuses on command line input but can be modified to target variables with controllable input from a variety of methods` 97 | void recursiveValueTracer(Instruction* delme, std::unordered_set &used_insts, std::vector> &new_arg) 98 | { 99 | 100 | for(Instruction::op_iterator it = delme->op_begin(); it != delme->op_end(); it++) 101 | { 102 | 103 | if (AllocaInst *All = dyn_cast(it)) 104 | { 105 | if(std::find(used_insts.begin(), used_insts.end(), All) == used_insts.end()){ 106 | outs()<<"\t[!] FOUND TERMINATING ALLOCATION\n\n"; 107 | recursiveEndCheck(All, used_insts, new_arg); 108 | outs()<<"\t\t[ TRACING BACK HISTORY OF OPERAND VALUE ]\n"; 109 | for(Instruction::user_iterator all_user = All->user_begin(); all_user != All->user_end(); all_user++){ 110 | if(StoreInst *all_str = dyn_cast(*all_user)){ 111 | outs()<<"\t\t[+] Found StoreInst to trace\n"; 112 | recursiveValueTracer(all_str, used_insts, new_arg); 113 | } 114 | } 115 | } 116 | } 117 | else if(Instruction *Inst = dyn_cast(it)) 118 | { 119 | 120 | if(std::find(used_insts.begin(), used_insts.end(), Inst) == used_insts.end()){ 121 | recursiveEndCheck(Inst, used_insts, new_arg); 122 | recursiveValueTracer(Inst, used_insts, new_arg); 123 | } 124 | } 125 | else 126 | { 127 | if(first_hit){ 128 | first_hit = false; 129 | outs()<<"\t\t.... Potential find. Store took value from :: argv\n\n"; 130 | } 131 | } 132 | } 133 | 134 | recursiveEndCheck(delme, used_insts, new_arg); 135 | 136 | } 137 | 138 | 139 | 140 | virtual bool runOnModule(Module &M) override 141 | { 142 | 143 | for(Module::iterator F = M.begin(), E = M.end(); F != E; ++F) 144 | { 145 | if(F->getName().str() == "main"){ 146 | outs()<<"\n<-- Starting analysis from main() --> \n"; 147 | if (!F->empty()){ 148 | DominatorTree &DT = getAnalysis(*F).getDomTree(); 149 | 150 | // we know we only need to trace the most dominated path for the example binary 151 | // TODO: for future test binarys, dynamically choose a dominated path or analayze all dominated paths 152 | outs()<<"\t[+] Tracing first path of DominatorTree\n\n\n"; 153 | 154 | for (auto node = GraphTraits::nodes_begin(&DT); node != GraphTraits::nodes_end(&DT); ++node) 155 | { 156 | // iterate through all blocks in the most dominated path 157 | // check if an ending block, if not analyze, if it is an ending block, save constraints for this one sub-path 158 | 159 | // TODO: add support for paths with multiple returns 160 | // (i.e. function calls and returns from functions which still operate on the variables of interest) 161 | 162 | BasicBlock *BB = node->getBlock(); 163 | if(( (BB->getName()).str().find("end") == std::string::npos) && ( (BB->getName()).str().find("return") == std::string::npos)){ 164 | // pulls out the values and operations for controlled variables through each basic block 165 | for(BasicBlock::iterator Ins = BB->begin(), E = BB->end(); Ins != E; ++Ins){ 166 | if(isa(Ins)){ 167 | sleep(1); 168 | outs()<<"[ COMPARE FOUND ]\n"; 169 | std::vector> new_arg; 170 | std::string cmp_op = ""; 171 | 172 | // switch case for compare instuction types 173 | // easy 'conditions' to pull out that our controllabe variables must satisfy 174 | if(cast(Ins)->getPredicate() == CmpInst::ICMP_EQ) 175 | { 176 | outs()<<"\tComparison Operator: IS EQUAL (==)\n\n"; 177 | cmp_op = "=="; 178 | } 179 | else if(cast(Ins)->getPredicate() == CmpInst::ICMP_NE) 180 | { 181 | outs()<<"\tComparison Operator: IS EQUAL (!=)\n\n"; 182 | cmp_op = "!="; 183 | } 184 | else 185 | { 186 | outs()<<"\t[-] WARNING INSERT UNSUPPORTED PREDICATE\n\n"; 187 | return false; 188 | } 189 | first_hit = true; 190 | 191 | outs()<<"\n\n\t[+] VALUE TWO: \n"; 192 | if(Instruction *op_inst = dyn_cast(Ins->getOperand(1))){ 193 | std::unordered_set used_2; 194 | outs()<<"\tReovering variable operations and starting value....\n"; 195 | // uses recursion to recover the 'history' of our variables 196 | // i.e. the dominating operations 197 | recursiveValueTracer(op_inst, used_2, new_arg); 198 | }else{ 199 | if(ConstantInt *con = dyn_cast(Ins->getOperand(1))){ 200 | outs()<<"\t\t\t\t==> Found Constant Operand: Integer :: "<< con->getZExtValue() <<"\n\n\n"; 201 | std::tuple base_cmp( cmp_op, (int)con->getZExtValue()); 202 | new_arg.push_back(base_cmp); 203 | } 204 | } 205 | outs()<<"\n\n\t[+] VALUE ONE: \n\n"; 206 | if(Instruction *op_inst = dyn_cast(Ins->getOperand(0))){ 207 | std::unordered_set used_1; 208 | outs()<<"\tReovering variable operations and starting value....\n"; 209 | recursiveValueTracer(op_inst, used_1, new_arg); 210 | }else{ 211 | if(ConstantInt *con = dyn_cast(Ins->getOperand(0))){ 212 | outs()<<"\t\t\t\t==> Found Constant Operand: Integer :: "<< con->getZExtValue() <<"\n"; 213 | std::tuple base_cmp2( cmp_op, (int)con->getZExtValue()); 214 | new_arg.push_back(base_cmp2); 215 | } 216 | } 217 | z3_con.push_back(new_arg); 218 | } 219 | } 220 | } 221 | else 222 | { 223 | outs()<<"Breaking at end of first path with # of children\n"; 224 | outs()<<"[ CHECK ]: 0 == "<< node->getNumChildren()<<"\n\n"; 225 | break; 226 | } 227 | } 228 | 229 | 230 | 231 | } 232 | } 233 | } 234 | outs()<<"<-- Successfully Traversed Dominator Tree --> \n"; 235 | outs()<<"[+] The below arguments are operated upon, then this redefinition must finally be equal to the comparisons shown below.\n\n"; 236 | 237 | int i = 0; 238 | std::vector> >::iterator vvt_iterator; 239 | std::vector>::iterator vt_iterator; 240 | // dump contents of path conditions in order of argument to be read into z3 241 | std::ofstream z3File; 242 | z3File.open("z3Conditions.txt"); 243 | 244 | for(vvt_iterator = z3_con.begin(); vvt_iterator != z3_con.end(); ++(vvt_iterator)){ 245 | outs()<<"argv["<((*vt_iterator))<<" "<((*vt_iterator)); 250 | z3File<<";"<((*vt_iterator))<<" "<((*vt_iterator)); 251 | } 252 | outs()<<"\n"; 253 | z3File<<"\n"; 254 | } 255 | z3File.close(); 256 | return true; 257 | } 258 | 259 | }; 260 | 261 | } 262 | char DoTrePass::ID = 0; 263 | static RegisterPass X("dotrepass", "Dominator Tree Path Solver : Export to satisfiability", false, false); 264 | 265 | -------------------------------------------------------------------------------- /LLVMPassBuild/LLVMPassBuild/Makefile: -------------------------------------------------------------------------------- 1 | LEVEL= ../.. 2 | LIBRARYNAME= LLVMPassBuild 3 | SHARED_LIBRARY= 1 4 | LOADABLE_MODULE= 1 5 | LINK_LIBS_IN_SHARED= 1 6 | ENABLE_OPTIMIZED= 1 7 | include $(LEVEL)/Makefile.common 8 | 9 | LDFLAGS += 10 | 11 | CXXFLAGS += -fexceptions -fPIC 12 | CXXFLAGS += -std=c++11 -g -O3 13 | -------------------------------------------------------------------------------- /LLVMPassBuild/apply_patches.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "[PATCH] Applying patches to llvm/include/llvm/InitializePasses.h" 4 | patch llvm-3.7.1/include/llvm/InitializePasses.h < patches/InitializePasses.patch 5 | if [ "$?" -ne "0" ] 6 | then 7 | echo "[!] Failed to apply InitializePasses patch" 8 | exit 1 9 | fi 10 | 11 | echo "[PATCH] Applying patches to llvm/tools/CMakeLists.txt" 12 | patch llvm-3.7.1/tools/CMakeLists.txt < patches/build_less_tools.patch 13 | if [ "$?" -ne "0" ] 14 | then 15 | echo "[!] Failed to apply CMakeLists patch" 16 | #exit 1 17 | fi 18 | -------------------------------------------------------------------------------- /LLVMPassBuild/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ROOT=$PWD 4 | DTS_BUILD_DIR=$PWD/DTS_BUILD 5 | mkdir -p $DTS_BUILD_DIR 6 | 7 | LLVM_VERSION=3.7.1 8 | LLVM_DOWNLOAD_PATH="http://llvm.org/releases/$LLVM_VERSION/" 9 | LLVM_SRC_DIR=$DTS_BUILD_DIR/llvm-$LLVM_VERSION 10 | 11 | 12 | echo "" 13 | echo "Downloading llvm $LLVM_version" 14 | wget $LLVM_DOWNLOAD_PATH"llvm-"$LLVM_VERSION".src.tar.xz"; 15 | if [ "$?" -ne "0" ] 16 | then 17 | echo "[!] Failed to download LLVM" 18 | exit 1 19 | fi 20 | echo "" 21 | echo "Downloading clang $LLVM_version" 22 | wget $LLVM_DOWNLOAD_PATH"cfe-"$LLVM_VERSION".src.tar.xz"; 23 | if [ "$?" -ne "0" ] 24 | then 25 | echo "[!] Failed to download LLVM" 26 | exit 1 27 | fi 28 | echo "" 29 | echo "Downloading compiler-rt $LLVM_version" 30 | wget $LLVM_DOWNLOAD_PATH"compiler-rt-"$LLVM_VERSION".src.tar.xz"; 31 | if [ "$?" -ne "0" ] 32 | then 33 | echo "[!] Failed to download LLVM" 34 | exit 1 35 | fi 36 | 37 | echo "" 38 | echo "Unpacking LLVM..." 1>&2 39 | tar xf llvm-$LLVM_VERSION.src.tar.xz 40 | if [ "$?" -ne "0" ] 41 | then 42 | echo "[!] Failed to unpack LLVM" 43 | exit 1 44 | fi 45 | 46 | echo "Moving LLVM..." 1>&2 47 | mv llvm-$LLVM_VERSION.src $LLVM_SRC_DIR 48 | if [ "$?" -ne "0" ] 49 | then 50 | echo "[!] Failed to move src directory" 51 | exit 1 52 | fi 53 | 54 | echo "" 55 | echo "Unpacking Clang into tools..." 1>&2 56 | tar -xf cfe-$LLVM_VERSION.src.tar.xz 57 | mv cfe-$LLVM_VERSION.src $LLVM_SRC_DIR/tools/clang 58 | 59 | 60 | echo "" 61 | echo "Unpacking Compiler-RT into projects..." 1>&2 62 | tar -xf compiler-rt-$LLVM_VERSION.src.tar.xz 63 | mv compiler-rt-$LLVM_VERSION.src $LLVM_SRC_DIR/projects/compiler-rt 64 | 65 | 66 | 67 | 68 | echo "" 69 | echo "Copying DTS pass sources" 1>&2 70 | echo "into LLVM source tree..." 1>&2 71 | cp -r LLVMPassBuild $LLVM_SRC_DIR/projects/ 72 | if [ "$?" -ne "0" ] 73 | then 74 | echo "[!] Failed to copy in DTS project" 75 | exit 1 76 | fi 77 | 78 | mkdir $LLVM_SRC_DIR/build 79 | cd $LLVM_SRC_DIR/build 80 | LLVM_BUILD_DIR=$PWD 81 | export CC=gcc 82 | export CXX=g++ 83 | ../configure --enable-optimized 84 | 85 | REQUIRES_RTTI=1 make -j5 86 | if [ "$?" -ne "0" ] 87 | then 88 | echo "[!] Failed to build project" 89 | fi 90 | 91 | exit 92 | 93 | echo "" 94 | echo "Installing LLVM..." 1>&2 95 | mkdir $DTS_BUILD_DIR/build 96 | cd $DTS_BUILD_DIR/build 97 | 98 | 99 | 100 | LLVM_BUILD_DIR=$PWD 101 | export CC=gcc 102 | export CXX=g++ 103 | cmake -DLLVM_INCLUDE_TOOLS=ON \ 104 | -DLLVM_BUILD_TOOLS=ON \ 105 | -DLLVM_INCLUDE_UTILS=OFF \ 106 | -DLLVM_BUILD_EXAMPLES=OFF \ 107 | -DLLVM_INCLUDE_EXAMPLES=OFF \ 108 | -DLLVM_INCLUDE_TESTS=OFF \ 109 | -DLLVM_BUILD_DOCS=OFF \ 110 | -DLLVM_INCLUDE_DOCS=OFF \ 111 | -DLLVM_TARGETS_TO_BUILD="X86;ARM;AArch64" \ 112 | -DCMAKE_BUILD_TYPE=Release $LLVM_SRC_DIR 113 | if [ "$?" -ne "0" ] 114 | then 115 | echo "[!] Failed to run CMake" 116 | fi 117 | 118 | 119 | -------------------------------------------------------------------------------- /LLVMPassBuild/partial_build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | MAST_BUILD_DIR=$PWD/DTS_BUILD 4 | LLVM_VERSION=3.7.1 5 | LLVM_SRC_DIR=$MAST_BUILD_DIR/llvm-$LLVM_VERSION 6 | 7 | echo "" 8 | echo "Copying pass sources" 1>&2 9 | echo "into the LLVM source tree..." 1>&2 10 | cp LLVMPassBuild/* $LLVM_SRC_DIR/projects/LLVMPassBuild/ 11 | if [ "$?" -ne "0" ] 12 | then 13 | echo "[!] Failed to copy in MAST project" 14 | exit 1 15 | fi 16 | 17 | echo "" 18 | echo "Building only the DomTreSat Pass..." 1>&2 19 | cd $LLVM_SRC_DIR/build 20 | REQUIRES_RTTI=1 make 21 | if [ "$?" -ne "0" ] 22 | then 23 | echo "[!] Failed to build project" 24 | exit 1 25 | fi 26 | -------------------------------------------------------------------------------- /LLVMPassBuild/patches/InitializePasses.patch: -------------------------------------------------------------------------------- 1 | 64a65,67 2 | > // initializeDoTreAnalysis - Initializes all passes linked into the Dominator Tree Satisfiability library. 3 | > void initializeDoTreAnalysis(PassRegistry&); 4 | > 5 | 289a293,303 6 | > 7 | > 8 | > 9 | > // Trail of Bits Dominator Tree Satisfiability Analizer 10 | > void initializeDoTrePass(PassRegistry&); 11 | > //void initializePredicateInserterPass(PassRegistry&); 12 | > //void initializeCodeDiffuserPass(PassRegistry&); 13 | > //void initializeCodeDiffuserPrepPass(PassRegistry&); 14 | > //void initializeJailbreakDetectionPass(PassRegistry&); 15 | > // 16 | > // 17 | -------------------------------------------------------------------------------- /LLVMPassBuild/patches/build_less_tools.patch: -------------------------------------------------------------------------------- 1 | 18,20c18,20 2 | < add_llvm_tool_subdirectory(llvm-as) 3 | < add_llvm_tool_subdirectory(llvm-dis) 4 | < add_llvm_tool_subdirectory(llvm-mc) 5 | --- 6 | > #add_llvm_tool_subdirectory(llvm-as) 7 | > #add_llvm_tool_subdirectory(llvm-dis) 8 | > #add_llvm_tool_subdirectory(llvm-mc) 9 | 23,25c23,25 10 | < add_llvm_tool_subdirectory(llvm-ar) 11 | < add_llvm_tool_subdirectory(llvm-nm) 12 | < add_llvm_tool_subdirectory(llvm-size) 13 | --- 14 | > #add_llvm_tool_subdirectory(llvm-ar) 15 | > #add_llvm_tool_subdirectory(llvm-nm) 16 | > #add_llvm_tool_subdirectory(llvm-size) 17 | 27,28c27,28 18 | < add_llvm_tool_subdirectory(llvm-cov) 19 | < add_llvm_tool_subdirectory(llvm-profdata) 20 | --- 21 | > #add_llvm_tool_subdirectory(llvm-cov) 22 | > #add_llvm_tool_subdirectory(llvm-profdata) 23 | 32,40c32,40 24 | < add_llvm_tool_subdirectory(llvm-extract) 25 | < add_llvm_tool_subdirectory(llvm-diff) 26 | < add_llvm_tool_subdirectory(macho-dump) 27 | < add_llvm_tool_subdirectory(llvm-objdump) 28 | < add_llvm_tool_subdirectory(llvm-readobj) 29 | < add_llvm_tool_subdirectory(llvm-rtdyld) 30 | < add_llvm_tool_subdirectory(llvm-dwarfdump) 31 | < add_llvm_tool_subdirectory(dsymutil) 32 | < add_llvm_tool_subdirectory(llvm-vtabledump) 33 | --- 34 | > #add_llvm_tool_subdirectory(llvm-extract) 35 | > #add_llvm_tool_subdirectory(llvm-diff) 36 | > #add_llvm_tool_subdirectory(macho-dump) 37 | > #add_llvm_tool_subdirectory(llvm-objdump) 38 | > #add_llvm_tool_subdirectory(llvm-readobj) 39 | > #add_llvm_tool_subdirectory(llvm-rtdyld) 40 | > #add_llvm_tool_subdirectory(llvm-dwarfdump) 41 | > #add_llvm_tool_subdirectory(dsymutil) 42 | > #add_llvm_tool_subdirectory(llvm-vtabledump) 43 | 47,51c47,51 44 | < add_llvm_tool_subdirectory(bugpoint) 45 | < add_llvm_tool_subdirectory(bugpoint-passes) 46 | < add_llvm_tool_subdirectory(llvm-bcanalyzer) 47 | < add_llvm_tool_subdirectory(llvm-stress) 48 | < add_llvm_tool_subdirectory(llvm-mcmarkup) 49 | --- 50 | > #add_llvm_tool_subdirectory(bugpoint) 51 | > #add_llvm_tool_subdirectory(bugpoint-passes) 52 | > #add_llvm_tool_subdirectory(llvm-bcanalyzer) 53 | > #add_llvm_tool_subdirectory(llvm-stress) 54 | > #add_llvm_tool_subdirectory(llvm-mcmarkup) 55 | 53c53 56 | < add_llvm_tool_subdirectory(verify-uselistorder) 57 | --- 58 | > #add_llvm_tool_subdirectory(verify-uselistorder) 59 | 55c55 60 | < add_llvm_tool_subdirectory(llvm-symbolizer) 61 | --- 62 | > #add_llvm_tool_subdirectory(llvm-symbolizer) 63 | 57c57 64 | < add_llvm_tool_subdirectory(llvm-c-test) 65 | --- 66 | > #add_llvm_tool_subdirectory(llvm-c-test) 67 | 59,60c59,60 68 | < add_llvm_tool_subdirectory(obj2yaml) 69 | < add_llvm_tool_subdirectory(yaml2obj) 70 | --- 71 | > #add_llvm_tool_subdirectory(obj2yaml) 72 | > #add_llvm_tool_subdirectory(yaml2obj) 73 | 62c62 74 | < add_llvm_tool_subdirectory(llvm-go) 75 | --- 76 | > #add_llvm_tool_subdirectory(llvm-go) 77 | 72c72 78 | < add_llvm_tool_subdirectory(gold) 79 | --- 80 | > #add_llvm_tool_subdirectory(gold) 81 | 83c83 82 | < add_llvm_implicit_external_projects() 83 | --- 84 | > # add_llvm_implicit_external_projects() 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DomTreSat 2 | DomTreSat (DTS) is a static analysis system that takes source code as input and automatically produces path satisfiability reports for paths gathered from a created Dominator Tree structure. It obtains maximal code coverage with minimal human intervention. DomTreSat creates a dominator tree of user-controlled variables, then outputs constraints and operations placed on their values to be fed to a satisfiability solver. This generates potential points of interest in the program for vulnerability discovery. 3 | 4 | ## Primary Motivation 5 | The main use of this tool is determine reachability of controllable input to a target in the program, as well as what this input needs to be to get there. The target is automatically set to be the most dominated path of the tree. This helps an auditor identify a path to vulnerable code through a series of checks like the diagram below. In programs like these, it is the most-dominated path that we want to buid and analyze the Use-Define Chain for. 6 | 7 | ``` 8 | INPUT 9 | \ 10 | CHECK 11 | / | 12 | FAIL CHECK 13 | / | 14 | FAIL CHECK 15 | / | 16 | FAIL VULNERABILITY 17 | ``` 18 | 19 | ## Analysis Theory 20 | ### Dominator Trees 21 | This tool defaults to analyzing the most dominated paths first. These paths can be described as those with variables that are acted upon the most. This can be changed based on need and a quick recompilation script is in place to generate altered libraries. 22 | 23 | ### Use-Define Chains 24 | Use-Define Chains (Use-Def) are a data structure that consists of a use of a variable, and all the definitions of that variable that can reach that use without any other intervening definitions. 25 | 26 | This tool relies on pulling these data structures from the Most Dominated Path which is found through the Dominator Tree created. The basic idea is that given a targeted Use, i.e. the use of a variable to either get to or cause a vulnerability, we can trace this variable up through all of its (re-)definitions and determine A) if it is user controllable, and B) what operations are done on this input before it is used in the vulnerability (these become our constraints). 27 | 28 | ## Building 29 | 30 | DomTreSat has been tested on LLVM 3.7.1. 31 | 32 | 1. Install dependencies 33 | * OS X: `brew install z3` 34 | * Linux/Windows: follow instructions on [Z3Prover/z3](https://github.com/Z3Prover/z3) 35 | 2. `$./quick_setup.sh` to build and run tests 36 | 3. `$./partial_build.sh` to perform an incremental rebuild after altering analysis methods 37 | 38 | ## Usage 39 | This section describes how to run tests and feed them to the SAT solver. 40 | 41 | ### Base case test 42 | 43 | Tests for tracing definitions of variables (their Use-Def chains) through the most dominated path 44 | 45 | `$./test_base_case.sh` 46 | 47 | To run this test with z3 for generating input to satisfy target path: 48 | 49 | `$./complete_test_base_case.sh` 50 | 51 | ### Addition operator test 52 | 53 | Tests for tracing definitions of variables (their Use-Def chains) through the most dominated path, where the Use-Def Chain now contains re-definitions after addition operations are applied to the variable. 54 | 55 | `$./test_addition.sh` 56 | 57 | To run pass and z3 for generating input to satisfy target path: 58 | 59 | `$./complete_test_addition.sh` 60 | 61 | ### Subtraction operator test 62 | 63 | Tests for tracing definitions of variables (their Use-Def chains) through the most dominated path, where the Use-Def Chain now contains re-definitions after subtraction operations are applied to the variable. 64 | 65 | `$./test_subtraction.sh` 66 | 67 | To run pass and z3 for generating input to satisfy target path: 68 | 69 | `$./complete_test_subtraction.sh` 70 | 71 | ### XOR operator test 72 | 73 | Tests for tracing definitions of variables (their Use-Def chains) through the most dominated path, where the Use-Def Chain now contains re-definitions after xor operations are applied to the variable. 74 | 75 | `$./test_xor.sh` 76 | 77 | To run pass and z3 for generating input to satisfy target path: 78 | 79 | `$./complete_test_xor.sh` 80 | 81 | ### Expected Output For Addition Operator Run 82 | 83 | ``` 84 | $./complete_test_base_case.sh 85 | 86 | 87 | ...Starting LLVM to Z3 Solver... 88 | 89 | [+] Starting Base Case Test 90 | 91 | [ CLANG COMPILING TEST APP SOURCES ] 92 | 93 | 94 | [ RUNNING DOMINATOR TREE PASS ] 95 | 96 | 97 | <-- Starting analysis from main() --> 98 | [+] Tracing first path of DominatorTree 99 | 100 | 101 | [ COMPARE FOUND ] 102 | Comparison Operator: IS EQUAL (==) 103 | 104 | 105 | 106 | [+] VALUE TWO: 107 | ==> Found Constant Operand: Integer :: 69 108 | 109 | 110 | 111 | 112 | [+] VALUE ONE: 113 | 114 | Reovering variable operations and starting value.... 115 | [-] RECURSING THROUGH OPERATION 116 | [!] FOUND TERMINATING ALLOCATION 117 | 118 | [-] RECURSING THROUGH OPERATION 119 | [ TRACING BACK HISTORY OF OPERAND VALUE ] 120 | [+] Found StoreInst to trace 121 | [-] RECURSING THROUGH OPERATION 122 | [-] RECURSING THROUGH OPERATION 123 | [-] RECURSING THROUGH OPERATION 124 | [!] FOUND TERMINATING ALLOCATION 125 | 126 | [-] RECURSING THROUGH OPERATION 127 | [ TRACING BACK HISTORY OF OPERAND VALUE ] 128 | [+] Found StoreInst to trace 129 | [-] RECURSING THROUGH OPERATION 130 | [-] RECURSING THROUGH OPERATION 131 | [-] RECURSING THROUGH OPERATION 132 | [!] FOUND TERMINATING ALLOCATION 133 | 134 | [-] RECURSING THROUGH OPERATION 135 | [ TRACING BACK HISTORY OF OPERAND VALUE ] 136 | [+] Found StoreInst to trace 137 | .... Potential find. Store took value from :: argv 138 | 139 | [-] RECURSING THROUGH OPERATION 140 | [-] RECURSING THROUGH OPERATION 141 | [-] RECURSING THROUGH OPERATION 142 | [-] RECURSING THROUGH OPERATION 143 | [ COMPARE FOUND ] 144 | Comparison Operator: IS EQUAL (==) 145 | 146 | 147 | 148 | [+] VALUE TWO: 149 | ==> Found Constant Operand: Integer :: 68 150 | 151 | 152 | 153 | 154 | [+] VALUE ONE: 155 | 156 | Reovering variable operations and starting value.... 157 | [-] RECURSING THROUGH OPERATION 158 | [!] FOUND TERMINATING ALLOCATION 159 | 160 | [-] RECURSING THROUGH OPERATION 161 | [ TRACING BACK HISTORY OF OPERAND VALUE ] 162 | [+] Found StoreInst to trace 163 | [-] RECURSING THROUGH OPERATION 164 | [-] RECURSING THROUGH OPERATION 165 | [-] RECURSING THROUGH OPERATION 166 | [!] FOUND TERMINATING ALLOCATION 167 | 168 | [-] RECURSING THROUGH OPERATION 169 | [ TRACING BACK HISTORY OF OPERAND VALUE ] 170 | [+] Found StoreInst to trace 171 | [-] RECURSING THROUGH OPERATION 172 | [-] RECURSING THROUGH OPERATION 173 | [-] RECURSING THROUGH OPERATION 174 | [!] FOUND TERMINATING ALLOCATION 175 | 176 | [-] RECURSING THROUGH OPERATION 177 | [ TRACING BACK HISTORY OF OPERAND VALUE ] 178 | [+] Found StoreInst to trace 179 | .... Potential find. Store took value from :: argv 180 | 181 | [-] RECURSING THROUGH OPERATION 182 | [-] RECURSING THROUGH OPERATION 183 | [-] RECURSING THROUGH OPERATION 184 | [-] RECURSING THROUGH OPERATION 185 | [ COMPARE FOUND ] 186 | Comparison Operator: IS EQUAL (==) 187 | 188 | 189 | 190 | [+] VALUE TWO: 191 | ==> Found Constant Operand: Integer :: 67 192 | 193 | 194 | 195 | 196 | [+] VALUE ONE: 197 | 198 | Reovering variable operations and starting value.... 199 | [-] RECURSING THROUGH OPERATION 200 | [!] FOUND TERMINATING ALLOCATION 201 | 202 | [-] RECURSING THROUGH OPERATION 203 | [ TRACING BACK HISTORY OF OPERAND VALUE ] 204 | [+] Found StoreInst to trace 205 | [-] RECURSING THROUGH OPERATION 206 | [-] RECURSING THROUGH OPERATION 207 | [-] RECURSING THROUGH OPERATION 208 | [!] FOUND TERMINATING ALLOCATION 209 | 210 | [-] RECURSING THROUGH OPERATION 211 | [ TRACING BACK HISTORY OF OPERAND VALUE ] 212 | [+] Found StoreInst to trace 213 | [-] RECURSING THROUGH OPERATION 214 | [-] RECURSING THROUGH OPERATION 215 | [-] RECURSING THROUGH OPERATION 216 | [!] FOUND TERMINATING ALLOCATION 217 | 218 | [-] RECURSING THROUGH OPERATION 219 | [ TRACING BACK HISTORY OF OPERAND VALUE ] 220 | [+] Found StoreInst to trace 221 | .... Potential find. Store took value from :: argv 222 | 223 | [-] RECURSING THROUGH OPERATION 224 | [-] RECURSING THROUGH OPERATION 225 | [-] RECURSING THROUGH OPERATION 226 | [-] RECURSING THROUGH OPERATION 227 | [ COMPARE FOUND ] 228 | Comparison Operator: IS EQUAL (==) 229 | 230 | 231 | 232 | [+] VALUE TWO: 233 | ==> Found Constant Operand: Integer :: 66 234 | 235 | 236 | 237 | 238 | [+] VALUE ONE: 239 | 240 | Reovering variable operations and starting value.... 241 | [-] RECURSING THROUGH OPERATION 242 | [!] FOUND TERMINATING ALLOCATION 243 | 244 | [-] RECURSING THROUGH OPERATION 245 | [ TRACING BACK HISTORY OF OPERAND VALUE ] 246 | [+] Found StoreInst to trace 247 | [-] RECURSING THROUGH OPERATION 248 | [-] RECURSING THROUGH OPERATION 249 | [-] RECURSING THROUGH OPERATION 250 | [!] FOUND TERMINATING ALLOCATION 251 | 252 | [-] RECURSING THROUGH OPERATION 253 | [ TRACING BACK HISTORY OF OPERAND VALUE ] 254 | [+] Found StoreInst to trace 255 | [-] RECURSING THROUGH OPERATION 256 | [-] RECURSING THROUGH OPERATION 257 | [-] RECURSING THROUGH OPERATION 258 | [!] FOUND TERMINATING ALLOCATION 259 | 260 | [-] RECURSING THROUGH OPERATION 261 | [ TRACING BACK HISTORY OF OPERAND VALUE ] 262 | [+] Found StoreInst to trace 263 | .... Potential find. Store took value from :: argv 264 | 265 | [-] RECURSING THROUGH OPERATION 266 | [-] RECURSING THROUGH OPERATION 267 | [-] RECURSING THROUGH OPERATION 268 | [-] RECURSING THROUGH OPERATION 269 | Breaking at end of first path with # of children 270 | [ CHECK ]: 0 == 0 271 | 272 | <-- Successfully Traversed Dominator Tree --> 273 | [+] The below arguments are operated upon, then this redefinition must finally be equal to the comparisons shown below. 274 | 275 | argv[0];== 69 276 | argv[1];== 68 277 | argv[2];== 67 278 | argv[3];== 66 279 | 280 | [ FINISHED ] 281 | 282 | 283 | [ LLVM Ported to Z3 ] 284 | ['argv[0]', '== 69'] 285 | [ BUILDING EQUATION ] 286 | x == 69 287 | [+] Added all conditions to z3 288 | [+] Checking Satisfiability 289 | sat 290 | argv[0]: 69 291 | 292 | ['argv[1]', '== 68'] 293 | [ BUILDING EQUATION ] 294 | x == 68 295 | [+] Added all conditions to z3 296 | [+] Checking Satisfiability 297 | sat 298 | argv[1]: 68 299 | 300 | ['argv[2]', '== 67'] 301 | [ BUILDING EQUATION ] 302 | x == 67 303 | [+] Added all conditions to z3 304 | [+] Checking Satisfiability 305 | sat 306 | argv[2]: 67 307 | 308 | ['argv[3]', '== 66'] 309 | [ BUILDING EQUATION ] 310 | x == 66 311 | [+] Added all conditions to z3 312 | [+] Checking Satisfiability 313 | sat 314 | argv[3]: 66 315 | 316 | 317 | [ KEY FOUND ] 318 | 319 | EDCB 320 | 321 | 322 | ...Solver Finished... 323 | ``` 324 | -------------------------------------------------------------------------------- /base_case.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]){ 6 | printf("HELLO WORLD\n"); 7 | if(argv[0]!="test"){ 8 | if(argv[0]!="lol"){ 9 | if(argv[0]=="hi"){ 10 | printf("it was just..\n"); 11 | 12 | return 1; 13 | } 14 | } 15 | 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /complete_test_addition.sh: -------------------------------------------------------------------------------- 1 | echo 2 | echo "...Starting LLVM to Z3 Solver..." 3 | echo 4 | echo "[+] Starting Addition Case Test" 5 | ./test_addition.sh 6 | python llvm2z3.py 7 | echo 8 | echo "...Solver Finished..." 9 | -------------------------------------------------------------------------------- /complete_test_base_case.sh: -------------------------------------------------------------------------------- 1 | echo 2 | echo "...Starting LLVM to Z3 Solver..." 3 | echo 4 | echo "[+] Starting Base Case Test" 5 | ./test_base_case.sh 6 | python llvm2z3.py 7 | echo 8 | echo "...Solver Finished..." 9 | -------------------------------------------------------------------------------- /complete_test_subtraction.sh: -------------------------------------------------------------------------------- 1 | echo 2 | echo "...Starting LLVM to Z3 Solver..." 3 | echo 4 | echo "[+] Starting Subtraction Case Test" 5 | ./test_subtraction.sh 6 | python llvm2z3.py 7 | echo 8 | echo "...Solver Finished..." 9 | -------------------------------------------------------------------------------- /complete_test_xor.sh: -------------------------------------------------------------------------------- 1 | echo 2 | echo "...Starting LLVM to Z3 Solver..." 3 | echo 4 | echo "[+] Starting Xor Case Test" 5 | ./test_xor.sh 6 | python llvm2z3.py 7 | echo 8 | echo "...Solver Finished..." 9 | -------------------------------------------------------------------------------- /llvm2z3.py: -------------------------------------------------------------------------------- 1 | from z3 import * 2 | import time 3 | def main(): 4 | print 5 | print "[ LLVM Ported to Z3 ] " 6 | key = [] 7 | lines = [line.rstrip('\n') for line in open('z3Conditions.txt')] 8 | for line in lines: 9 | line_arr = line.split(';') 10 | 11 | # assuming input must be in ASCII range 12 | s = Solver() 13 | if not s: 14 | print '[!] failure in z3 installation' 15 | exit(-1) 16 | 17 | x = Int('x') 18 | s.add( x > 33 ) 19 | s.add( x < 126 ) 20 | 21 | i = 0 22 | print line_arr 23 | final_comp = 0 24 | # building the equation for user controlled variable i 25 | print '[ BUILDING EQUATION ]' 26 | for arg in line_arr: 27 | if i == 0: 28 | pass 29 | elif '==' in arg: 30 | final_comp = int(arg[3:]) 31 | elif '-' in arg: 32 | final_comp = final_comp + int(arg[2:]) 33 | elif '+' in arg: 34 | final_comp = final_comp - int(arg[2:]) 35 | elif '^' in arg: 36 | final_comp = final_comp ^ int(arg[2:]) 37 | i += 1 38 | 39 | foo = "x == " + str(final_comp) 40 | print foo 41 | s.add(eval(foo)) 42 | print '[+] Added all conditions to z3' 43 | time.sleep(0.5) 44 | print "\t[+] Checking Satisfiability" 45 | print "\t"+str(s.check()) 46 | m = s.model() 47 | print str(line_arr[0]) + ": " + str(m[x]) + "\n" 48 | key.append(chr(eval(str(m[x])))) 49 | print 50 | print "[ KEY FOUND ]" 51 | print 52 | print ''.join(key) 53 | print 54 | 55 | 56 | if __name__ == "__main__": 57 | main() 58 | -------------------------------------------------------------------------------- /partial_build.sh: -------------------------------------------------------------------------------- 1 | echo "Building the Pass Libraries" 2 | cd LLVMPassBuild/ 3 | ./partial_build.sh 4 | -------------------------------------------------------------------------------- /quick_setup.sh: -------------------------------------------------------------------------------- 1 | python -c "import z3; a = z3.Solver()" 2 | if [ $? -ne 0 ]; then 3 | echo "[!] Please install Microsoft's Z3 solver!" 4 | exit 1 5 | fi 6 | 7 | echo "Building the Pass Libraries" 8 | cd LLVMPassBuild/ 9 | ./build.sh 10 | cd ../ 11 | ./complete_test.sh 12 | -------------------------------------------------------------------------------- /test.s: -------------------------------------------------------------------------------- 1 | .section __TEXT,__text,regular,pure_instructions 2 | .macosx_version_min 10, 10 3 | .globl _main 4 | .align 4, 0x90 5 | _main: ## @main 6 | .cfi_startproc 7 | ## BB#0: ## %entry 8 | pushq %rbp 9 | Ltmp0: 10 | .cfi_def_cfa_offset 16 11 | Ltmp1: 12 | .cfi_offset %rbp, -16 13 | movq %rsp, %rbp 14 | Ltmp2: 15 | .cfi_def_cfa_register %rbp 16 | pushq %rbx 17 | pushq %rax 18 | Ltmp3: 19 | .cfi_offset %rbx, -24 20 | movq %rsi, %rbx 21 | leaq L_str(%rip), %rdi 22 | callq _puts 23 | movq (%rbx), %rcx 24 | movzbl (%rcx), %edx 25 | xorl %eax, %eax 26 | cmpl $8, %edx 27 | je LBB0_5 28 | ## BB#1: ## %if.then 29 | movzbl 1(%rcx), %edx 30 | cmpl $21, %edx 31 | je LBB0_5 32 | ## BB#2: ## %if.then12 33 | movzbl 2(%rcx), %edx 34 | cmpl $44, %edx 35 | jne LBB0_5 36 | ## BB#3: ## %if.then20 37 | movzbl 3(%rcx), %ecx 38 | cmpl $32, %ecx 39 | jne LBB0_5 40 | ## BB#4: ## %if.then28 41 | leaq L_str2(%rip), %rdi 42 | callq _puts 43 | movl $1, %eax 44 | LBB0_5: ## %return 45 | addq $8, %rsp 46 | popq %rbx 47 | popq %rbp 48 | retq 49 | .cfi_endproc 50 | 51 | .section __TEXT,__cstring,cstring_literals 52 | L_str: ## @str 53 | .asciz "HELLO WORLD" 54 | 55 | L_str2: ## @str2 56 | .asciz "it was just.." 57 | 58 | 59 | .subsections_via_symbols 60 | -------------------------------------------------------------------------------- /test_addition.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]){ 6 | printf("HELLO WORLD\n"); 7 | char *b = argv[0]; 8 | char f = (b[0]+'B'); 9 | if(f==0x70){ 10 | char l = (b[1]+'E'); 11 | if(l==0x7d){ 12 | char a = (b[2]+'E'); 13 | if(a==0x72){ 14 | char g = (b[3]+'P'); 15 | if(g==0x74){ 16 | //target code block 17 | printf("it was just..\n"); 18 | return 1; 19 | } 20 | } 21 | } 22 | 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /test_addition.sh: -------------------------------------------------------------------------------- 1 | DIR=".//LLVMPassBuild/DTS_BUILD/llvm-3.7.1/build/Release+Asserts/" 2 | echo 3 | echo "[ CLANG COMPILING TEST APP SOURCES ]" 4 | echo 5 | $DIR/bin/clang -cc1 -emit-llvm test_addition.c -o test_addition.bc 6 | echo 7 | echo "[ RUNNING DOMINATOR TREE PASS ]" 8 | echo 9 | $DIR/bin/opt -load $DIR/lib/LLVMPassBuild.* -dotrepass test_addition.bc -o test_addition.bc 10 | echo 11 | echo "[ FINISHED ]" 12 | echo 13 | -------------------------------------------------------------------------------- /test_base_case.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]){ 6 | printf("HELLO WORLD\n"); 7 | char *b = argv[0]; 8 | 9 | // move variables away from their definitions 10 | char f = b[0]; 11 | char l = b[1]; 12 | char a = b[2]; 13 | char g = b[3]; 14 | 15 | // check variables for satisfiable conditions 16 | if(f==0x45){ 17 | if(l==0x44){ 18 | if(a==0x43){ 19 | if(g==0x42){ 20 | //target code block 21 | printf("it was just..\n"); 22 | return 1; 23 | } 24 | } 25 | } 26 | 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /test_base_case.sh: -------------------------------------------------------------------------------- 1 | DIR=".//LLVMPassBuild/DTS_BUILD/llvm-3.7.1/build/Release+Asserts/" 2 | echo 3 | echo "[ CLANG COMPILING TEST APP SOURCES ]" 4 | echo 5 | $DIR/bin/clang -cc1 -emit-llvm test_base_case.c -o test_base_case.bc 6 | echo 7 | echo "[ RUNNING DOMINATOR TREE PASS ]" 8 | echo 9 | $DIR/bin/opt -load $DIR/lib/LLVMPassBuild.* -dotrepass test_base_case.bc -o test_base_case.bc 10 | echo 11 | echo "[ FINISHED ]" 12 | echo 13 | -------------------------------------------------------------------------------- /test_subtraction.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]){ 6 | printf("HELLO WORLD\n"); 7 | char *b = argv[0]; 8 | char f = (b[0]-'A'); 9 | if(f==0x20){ 10 | char l = (b[1]-'B'); 11 | if(l==0x20){ 12 | char a = (b[2]-'C'); 13 | if(a==0x20){ 14 | char g = (b[3]-'D'); 15 | if(g==0x20){ 16 | //target code block 17 | printf("it was just..\n"); 18 | return 1; 19 | } 20 | } 21 | } 22 | 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /test_subtraction.sh: -------------------------------------------------------------------------------- 1 | DIR=".//LLVMPassBuild/DTS_BUILD/llvm-3.7.1/build/Release+Asserts/" 2 | echo 3 | echo "[ CLANG COMPILING TEST APP SOURCES ]" 4 | echo 5 | $DIR/bin/clang -cc1 -emit-llvm test_subtraction.c -o test_subtraction.bc 6 | echo 7 | echo "[ RUNNING DOMINATOR TREE PASS ]" 8 | echo 9 | $DIR/bin/opt -load $DIR/lib/LLVMPassBuild.* -dotrepass test_subtraction.bc -o test_subtraction.bc 10 | echo 11 | echo "[ FINISHED ]" 12 | echo 13 | -------------------------------------------------------------------------------- /test_xor.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]){ 6 | printf("HELLO WORLD\n"); 7 | char *b = argv[0]; 8 | char f = (b[0]^'B'); 9 | if(f==0x70){ 10 | char l = (b[1]^'E'); 11 | if(l==0x7d){ 12 | char a = (b[2]^'E'); 13 | if(a==0x72){ 14 | char g = (b[3]^'P'); 15 | if(g==0x74){ 16 | //target code block 17 | printf("it was just..\n"); 18 | return 1; 19 | } 20 | } 21 | } 22 | 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /test_xor.sh: -------------------------------------------------------------------------------- 1 | DIR=".//LLVMPassBuild/DTS_BUILD/llvm-3.7.1/build/Release+Asserts/" 2 | echo 3 | echo "[ CLANG COMPILING TEST APP SOURCES ]" 4 | echo 5 | $DIR/bin/clang -cc1 -emit-llvm test_xor.c -o test_xor.bc 6 | echo 7 | echo "[ RUNNING DOMINATOR TREE PASS ]" 8 | echo 9 | $DIR/bin/opt -load $DIR/lib/LLVMPassBuild.* -dotrepass test_xor.bc -o test_xor.bc 10 | echo 11 | echo "[ FINISHED ]" 12 | echo 13 | -------------------------------------------------------------------------------- /z3Conditions.txt: -------------------------------------------------------------------------------- 1 | argv[0];== 107 2 | argv[1];== 80 3 | argv[2];== 96 4 | argv[3];== 112 5 | --------------------------------------------------------------------------------