zoukankan      html  css  js  c++  java
  • ollvm 新增字符串加密功能

    好久没弄ollvm了,可以继续了,今天给ollvm新增了一个pass,用来加密字符串,这个pass是从别的库里面扒出来的。

    本文是基于在Windows 上使用VS2017编译出来的ollvm,在这个基础上来添加。

    第一步:

    寻找两个pass的代码

    头文件

     1 #ifndef _STRING_OBFUSCATION_H_
     2 #define _STRING_OBFUSCATION_H_
     3 
     4 
     5 // LLVM include
     6 #include "llvm/Pass.h"
     7 #include "llvm/IR/Function.h"
     8 #include "llvm/IR/Instructions.h"
     9 #include "llvm/ADT/Statistic.h"
    10 #include "llvm/Transforms/IPO.h"
    11 #include "llvm/IR/Module.h"
    12 #include "llvm/Support/CommandLine.h"
    13 #include "llvm/CryptoUtils.h"
    14 
    15 // Namespace
    16 using namespace llvm;
    17 using namespace std;
    18 
    19 namespace llvm {
    20     Pass *createStringObfuscation(bool flag);
    21 }
    22 
    23 #endif
    View Code

    源文件

      1 #define DEBUG_TYPE "objdiv"
      2 #include <string>
      3 #include <sstream>
      4 
      5 #include "llvm/ADT/Statistic.h"
      6 #include "llvm/IR/Function.h"
      7 #include "llvm/IR/Constants.h"
      8 #include "llvm/IR/Module.h"
      9 #include "llvm/IR/Value.h"
     10 #include "llvm/Pass.h"
     11 #include "llvm/Support/raw_ostream.h"
     12 #include "llvm/CryptoUtils.h"
     13 #include "llvm/Transforms/Obfuscation/StringObfuscation.h"
     14 #include "llvm/IR/IRBuilder.h"
     15 #include "llvm/Transforms/Utils/ModuleUtils.h"
     16 
     17 using namespace llvm;
     18 
     19 STATISTIC(GlobalsEncoded, "Counts number of global variables encoded");
     20 
     21 #define ZooPrint(_F, ...) fprintf(stdout, "File : [%s](%d) " _F, __FILE__, __LINE__, __VA_ARGS__)
     22 
     23 namespace llvm {
     24 
     25     struct encVar {
     26     public:
     27         GlobalVariable *var;
     28         uint8_t key;
     29     };
     30 
     31     class StringObfuscationPass : public llvm::ModulePass {
     32     public:
     33         static char ID; // pass identification
     34         bool is_flag = false;
     35         StringObfuscationPass() : ModulePass(ID) {}
     36         StringObfuscationPass(bool flag) : ModulePass(ID)
     37         {
     38             is_flag = flag;
     39         }
     40 
     41         virtual bool runOnModule(Module &M) {
     42             ZooPrint(" Run On Module : %d 
    ", is_flag);
     43             if (!is_flag)
     44                 return false;
     45             std::vector<GlobalVariable*> toDelConstGlob;
     46             //std::vector<GlobalVariable*> encGlob;
     47             std::vector<encVar*> encGlob;
     48             ZooPrint(" M.Size : %d 
    ", M.size());
     49             int i = 0;
     50             for (Module::global_iterator gi = M.global_begin(), ge = M.global_end(); gi != ge; ++gi)
     51             {
     52 
     53 #if 0
     54                 //    老式代码,原来的样子
     55                 @.str = private unnamed_addr constant[13 x i8] c"E4BDA0E5A5BDE4B896E7958C0", align 1
     56                 @__CFConstantStringClassReference = external global[0 x i32]
     57                 @.str.1 = private unnamed_addr constant[3 x i16][i16 20320, i16 22909, i16 0], section "__TEXT,__ustring", align 2
     58                 //    新式字符串的样子
     59                 @"1??_C@_07CHPFNFHA@123456?6?$AA@" = linkonce_odr unnamed_addr constant [8 x i8] c"123456A0", comdat, align 1
     60                 @"1??_C@_03PMGGPEJJ@?$CFd?6?$AA@" = linkonce_odr unnamed_addr constant [4 x i8] c"%dA0", comdat, align 1
     61                 @__local_stdio_printf_options._OptionsStorage = internal global i64 0, align 8
     62 #endif
     63                 // Loop over all global variables
     64                 GlobalVariable* gv = &(*gi);
     65                 //errs() << "Global var " << gv->getName();
     66                 //std::string::size_type str_idx = gv->getName().str().find(".str.");
     67                 std::string section(gv->getSection());
     68 
     69                 ZooPrint(" %d : String : "%s" , section : "%s" , isConstant : %d , hasInitializer : %d , isa : %d , r : %d 
    ", i++, gv->getName().str().c_str(), section.c_str(), gv->isConstant(), gv->hasInitializer(), isa<ConstantDataSequential>(gv->getInitializer()), gv->getName().str().substr(0, 8) == ""x01??_C@_");
     70                 //    ZooPrint("      0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 
    ", gv->getName()[0] & 0xFF, gv->getName()[1] & 0xFF, gv->getName()[2] & 0xFF, gv->getName()[3] & 0xFF, gv->getName()[4] & 0xFF, gv->getName()[5] & 0xFF, gv->getName()[6] & 0xFF, gv->getName()[7] & 0xFF);
     71 
     72                 // Let's encode the static ones
     73                 //if (gv->getName().str().substr(0, 4) == ".str"&&
     74                 if (gv->getName().str().substr(0, 7) == "x01??_C@_" &&
     75                     gv->isConstant() &&
     76                     gv->hasInitializer() &&
     77                     isa<ConstantDataSequential>(gv->getInitializer()) &&
     78                     section != "llvm.metadata" &&
     79                     section.find("__objc_methname") == std::string::npos
     80                     /*&&gv->getType()->getArrayElementType()->getArrayElementType()->isIntegerTy()*/)
     81                 {
     82                     ZooPrint(" In Global Encode 
    ");
     83                     ++GlobalsEncoded;
     84                     //errs() << " is constant";
     85 
     86                     // Duplicate global variable
     87                     GlobalVariable *dynGV = new GlobalVariable(M,
     88                         gv->getType()->getElementType(),
     89                         !(gv->isConstant()), gv->getLinkage(),
     90                         (Constant*)0, gv->getName(),
     91                         (GlobalVariable*)0,
     92                         gv->getThreadLocalMode(),
     93                         gv->getType()->getAddressSpace());
     94                     // dynGV->copyAttributesFrom(gv);
     95                     dynGV->setInitializer(gv->getInitializer());
     96 
     97                     std::string tmp = gv->getName().str();
     98                     //  errs()<<"GV: "<<*gv<<"
    ";
     99 
    100                     Constant *initializer = gv->getInitializer();
    101                     ConstantDataSequential *cdata = dyn_cast<ConstantDataSequential>(initializer);
    102                     if (cdata) {
    103                         const char *orig = cdata->getRawDataValues().data();
    104                         unsigned len = cdata->getNumElements()*cdata->getElementByteSize();
    105 
    106                         encVar *cur = new encVar();
    107                         cur->var = dynGV;
    108                         cur->key = llvm::cryptoutils->get_uint8_t();
    109                         // casting away const is undef. behavior in C++
    110                         // TODO a clean implementation would retrieve the data, generate a new constant
    111                         // set the correct type, and copy the data over.
    112                         //char *encr = new char[len];
    113                         //Constant *initnew = ConstantDataArray::getString(M.getContext(), encr, true);
    114                         char *encr = const_cast<char *>(orig);
    115                         // Simple xor encoding
    116                         for (unsigned i = 0; i != len; ++i) {
    117                             encr[i] = orig[i] ^ cur->key;
    118                         }
    119 
    120                         // FIXME Second part of the unclean hack.
    121                         dynGV->setInitializer(initializer);
    122 
    123                         // Prepare to add decode function for this variable
    124                         encGlob.push_back(cur);
    125                     }
    126                     else {
    127                         // just copying default initializer for now
    128                         dynGV->setInitializer(initializer);
    129                     }
    130 
    131                     // redirect references to new GV and remove old one
    132                     gv->replaceAllUsesWith(dynGV);
    133                     toDelConstGlob.push_back(gv);
    134 
    135                 }
    136             }
    137 
    138             // actuallte delete marked globals
    139             for (unsigned i = 0, e = toDelConstGlob.size(); i != e; ++i)
    140                 toDelConstGlob[i]->eraseFromParent();
    141 
    142             addDecodeFunction(&M, &encGlob);
    143 
    144 
    145             return true;
    146         }
    147 
    148     private:
    149         void addDecodeFunction(Module *mod, std::vector<encVar*> *gvars) {
    150             ZooPrint(" Add Decode Function 
    ");
    151             // Declare and add the function definition
    152             //errs()<<"Successful enter decode function"<<"
    ";
    153             std::vector<Type*>FuncTy_args;
    154             FunctionType* FuncTy = FunctionType::get(
    155                 /*Result=*/Type::getVoidTy(mod->getContext()),  // returning void
    156                 /*Params=*/FuncTy_args,  // taking no args
    157                 /*isVarArg=*/false);
    158             uint64_t StringObfDecodeRandomName = cryptoutils->get_uint64_t();
    159             std::string  random_str;
    160             std::stringstream random_stream;
    161             random_stream << StringObfDecodeRandomName;
    162             random_stream >> random_str;
    163             StringObfDecodeRandomName++;
    164             Constant* c = mod->getOrInsertFunction(".datadiv_decode" + random_str, FuncTy);
    165             Function* fdecode = cast<Function>(c);
    166             fdecode->setCallingConv(CallingConv::C);
    167 
    168 
    169             BasicBlock* entry = BasicBlock::Create(mod->getContext(), "entry", fdecode);
    170 
    171             IRBuilder<> builder(mod->getContext());
    172             builder.SetInsertPoint(entry);
    173 
    174 
    175             for (unsigned i = 0, e = gvars->size(); i != e; ++i) {
    176                 GlobalVariable *gvar = (*gvars)[i]->var;
    177                 uint8_t key = (*gvars)[i]->key;
    178 
    179                 Constant *init = gvar->getInitializer();
    180                 ConstantDataSequential *cdata = dyn_cast<ConstantDataSequential>(init);
    181 
    182                 unsigned len = cdata->getNumElements()*cdata->getElementByteSize();
    183                 --len;
    184 
    185                 BasicBlock *preHeaderBB = builder.GetInsertBlock();
    186                 BasicBlock* for_body = BasicBlock::Create(mod->getContext(), "for-body", fdecode);
    187                 BasicBlock* for_end = BasicBlock::Create(mod->getContext(), "for-end", fdecode);
    188                 builder.CreateBr(for_body);
    189                 builder.SetInsertPoint(for_body);
    190                 PHINode *variable = builder.CreatePHI(Type::getInt32Ty(mod->getContext()), 2, "i");
    191                 Value *startValue = builder.getInt32(0);
    192                 Value *endValue = builder.getInt32(len);
    193                 variable->addIncoming(startValue, preHeaderBB);
    194                 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    195 
    196                 //LoadInst *Load=builder.CreateLoad(gvar);
    197                 //errs()<<"Load: "<<*(Load->getPointerOperand())<<"
    ";
    198                 Value* indexList[2] = { ConstantInt::get(variable->getType(), 0), variable };
    199                 Value *const_key = builder.getInt8(key);
    200                 Value *GEP = builder.CreateGEP(gvar, ArrayRef<Value*>(indexList, 2), "arrayIdx");
    201                 LoadInst *loadElement = builder.CreateLoad(GEP, false);
    202                 loadElement->setAlignment(1);
    203                 //errs()<<"Type: "<<*loadElement<<"
    ";
    204                 //CastInst* extended = new ZExtInst(const_key, loadElement->getType(), "extended", for_body);
    205                 //Value* extended = builder.CreateZExtOrBitCast(const_key, loadElement->getType(),"extended");
    206                 Value *Xor = builder.CreateXor(loadElement, const_key, "xor");
    207                 StoreInst *Store = builder.CreateStore(Xor, GEP, false);
    208                 Store->setAlignment(1);
    209 
    210                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    211                 Value *stepValue = builder.getInt32(1);
    212                 Value *nextValue = builder.CreateAdd(variable, stepValue, "next-value");
    213                 Value *endCondition = builder.CreateICmpULT(variable, endValue, "end-condition");
    214                 endCondition = builder.CreateICmpNE(endCondition, builder.getInt1(0), "loop-condition");
    215                 BasicBlock *loopEndBB = builder.GetInsertBlock();
    216                 builder.CreateCondBr(endCondition, loopEndBB, for_end);
    217                 builder.SetInsertPoint(for_end);
    218                 variable->addIncoming(nextValue, loopEndBB);
    219 
    220             }
    221             builder.CreateRetVoid();
    222             appendToGlobalCtors(*mod, fdecode, 0);
    223 
    224 
    225         }
    226 
    227     };
    228 
    229     Pass *createStringObfuscation(bool flag);
    230 }
    231 
    232 #if 0
    233 RegisterPass(const char *PassArg, const char *Name, bool CFGOnly = false, bool is_analysis = false)
    234 
    235 上面这个是RegisterPass的构造函数。
    236 参数说明:
    237 
    238 template<typename passName>        :YourPassName;
    239                     PassArg        :opt调用时所用的命行参数;
    240                     Name        :此pass的简要说明;
    241                     CFGOnly        :如果一个遍历CFG而不修改它,那么这个参数被设置为true;
    242                     is_analysis    :如果一个Pass是一个分析Pass,例如dominator tree pass,那么这个参数被设置为true。
    243 例子:
    244 
    245 static RegisterPass<Hello> X("hello", "Hello World Pass", false, false);
    246 #endif
    247 
    248 char StringObfuscationPass::ID = 0;
    249 static RegisterPass<StringObfuscationPass> X("GVDiv", "Global variable (i.e., const char*) diversification pass", false, true);
    250 
    251 Pass * llvm::createStringObfuscation(bool flag) {
    252     ZooPrint("new my pass 
    ");
    253     return new StringObfuscationPass(flag);
    254 }
    View Code

    第二步:

    将头文件放在如下位置:ollvmobfuscator-llvm-4.0includellvmTransformsObfuscationStringObfuscation.h

    将源文件放在如下位置:ollvmobfuscator-llvm-4.0libTransformsObfuscationStringEncode.cpp

    第三步:

    将源文件放到如下工程中

    第四步:

    在此文件中新增代码:ollvmobfuscator-llvm-4.0libTransformsIPOPassManagerBuilder.cpp

    新增导入头文件

     1 #include "llvm/Transforms/Obfuscation/StringObfuscation.h" 

    新增全局变量代码如下

    1 static cl::opt<std::string> Seed("seed", cl::init(""),
    2                             cl::desc("seed for the random"));
    3 
    4 //    全局开关,根据参数判断是否设置
    5 static cl::opt<bool> StringObf("sobf", cl::init(false),
    6                             cl::desc("Enable the string obfuscation"));

    在:PassManagerBuilder::populateModulePassManager 函数中,新增挂载新的pass代码,如下

     1 MPM.add(createStringObfuscation(StringObf)); 

    意义为根据全局开关来判断是否启用当前pass

    经过以上四步,问题全部解决了,直接重新编译ollvm即可。

    后续可以修改pass代码,可以修改解密函数。

    新增其他pass新增步骤也如上。

    使用方式如下

     1 G:ollvmTest>G:ollvmuildRelWithDebInfoinclang.exe -mllvm -sobf -mllvm -fla main.c 

    含义是,开启字符串加密,并且启动代码扁平化

    效果:

    源代码如下

    编译后如下

    已经开启了代码扁平化,原始字符串也已经不一样了,具体情况,

    看data段就好了:

    已经完全没个人样了

    重点在最后,忘了,补充一句,由于字符串在ollvm里面是以UTF8的格式保存的,所以中文字符串天然就是乱码,

    有时间想办法来解决一下中文字符串的乱码问题。

    这个pass挺简单的,我也没怎么改就拿来用了,后续有时间再改一下吧。

  • 相关阅读:
    c# 创建多线程
    使用opencvsharp通过mvvm在image中显示图片
    c# 创建文件/文件夹对话框
    wpf MVVM框架基础
    wpf DataBinding
    layui自动点击下拉列表的一项并选中
    LayUI默认样式调整
    mysql取某个组的前n条数据
    Kali3.0系统切换中文
    JS触发某元素周围元素的样式改变
  • 原文地址:https://www.cnblogs.com/suanguade/p/11386337.html
Copyright © 2011-2022 走看看