bluesadi / Pluto

Obfuscator based on LLVM 14.0.6
831 stars 185 forks source link

字符串混淆移植到llvm14.x失败 #53

Open Dfault0 opened 1 year ago

Dfault0 commented 1 year ago

就还挺奇怪的,我也不知道为什么在14.x上会出现这个错误:'common' global must have a zero initializer! 恳请大家帮忙看看,感谢感谢。 系统环境:mac os 13.2 代码: GlobalEncryption.h

#ifndef LLVM_TRANSFORMS_OBFUSCATION_GLOBALENCRYPTION_H
#define LLVM_TRANSFORMS_OBFUSCATION_GLOBALENCRYPTION_H
#include "llvm/IR/PassManager.h"

namespace llvm {
class  GlobalEncryptionPass: public PassInfoMixin<GlobalEncryptionPass> {
public:
  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);

  static bool isRequired() { return true; }
};
} // namespace llvm

#endif // LLVM_TRANSFORMS_OBFUSCATION_GLOBALENCRYPTION_H

GlobalEncryption.cpp:

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/SHA1.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"

#include <iomanip>
#include <sstream>
#include <vector>

#include "llvm/Transforms/Obfuscation/CryptoUtils.h"
#include "llvm/Transforms/Obfuscation/GlobalEncryption.h"

using namespace llvm;

struct EncryptedGV {
  GlobalVariable *GV;
  uint64_t key;
  uint32_t len;
};
namespace {

static cl::opt<bool> GlobalEncryption("sobf", cl::init(false),
                                      cl::desc("Enable String"));

static cl::opt<int>
    ObfuTimes("gvobfus-times", cl::init(1),
              cl::desc("Run GlobalsEncryption pass <gvobfus-times> time(s)"));

static cl::opt<bool> OnlyStr("onlystr", cl::init(false),
                             cl::desc("Encrypt string variable only"));

LLVMContext *ctx = nullptr;

 void InsertIntDecryption(Module &M, EncryptedGV encGV);
 void InsertArrayDecryption(Module &M, EncryptedGV encGV);

std::string GenHashedName(GlobalVariable *GV) {
  Module &M = *GV->getParent();
  std::string funcName =
      formatv("{0}_{1:x-}", M.getName(), M.getMDKindID(GV->getName()));
  SHA1 sha1;
  sha1.update(funcName);
  StringRef digest = sha1.final();

  std::stringstream ss;
  ss << std::hex;

  for (size_t i = 0; i < digest.size(); i++) {
    ss << std::setw(2) << std::setfill('0') << (unsigned)(digest[i] & 0xFF);
  }

  return ss.str();
}

void InsertIntDecryption(Module &M, EncryptedGV encGV) {
  std::vector<Type *> funcArgs;
  FunctionType *funcType =
      FunctionType::get(Type::getVoidTy(M.getContext()), funcArgs, false);
  std::string funcName = GenHashedName(encGV.GV);
  FunctionCallee callee = M.getOrInsertFunction(funcName, funcType);
  Function *func = cast<Function>(callee.getCallee());

  BasicBlock *entry = BasicBlock::Create(*ctx, "entry", func);
  IRBuilder<> builder(*ctx);
  builder.SetInsertPoint(entry);
  LoadInst *val = builder.CreateLoad(encGV.GV->getValueType(),encGV.GV);
  Value *xorVal = builder.CreateXor(
      val, ConstantInt::get(encGV.GV->getValueType(), encGV.key));
  builder.CreateStore(xorVal, encGV.GV);
  builder.CreateRetVoid();
  appendToGlobalCtors(M, func, 0);
}

void InsertArrayDecryption(Module &M, EncryptedGV encGV) {
  std::vector<Type *> funcArgs;
  FunctionType *funcType =
      FunctionType::get(Type::getVoidTy(M.getContext()), funcArgs, false);
  std::string funcName = GenHashedName(encGV.GV);
  FunctionCallee callee = M.getOrInsertFunction(funcName, funcType);
  Function *func = cast<Function>(callee.getCallee());

  BasicBlock *entry = BasicBlock::Create(*ctx, "entry", func);
  BasicBlock *forCond = BasicBlock::Create(*ctx, "for.cond", func);
  BasicBlock *forBody = BasicBlock::Create(*ctx, "for.body", func);
  BasicBlock *forInc = BasicBlock::Create(*ctx, "for.inc", func);
  BasicBlock *forEnd = BasicBlock::Create(*ctx, "for.inc", func);

  IRBuilder<> builder(*ctx);
  Type *Int32Ty = builder.getInt32Ty();
  builder.SetInsertPoint(entry);
  AllocaInst *indexPtr =
      builder.CreateAlloca(Int32Ty, ConstantInt::get(Int32Ty, 1, false), "i");
  builder.CreateStore(ConstantInt::get(Int32Ty, 0), indexPtr);
  builder.CreateBr(forCond);
  builder.SetInsertPoint(forCond);
  LoadInst *index = builder.CreateLoad(Int32Ty, indexPtr);
  ICmpInst *cond = cast<ICmpInst>(
      builder.CreateICmpSLT(index, ConstantInt::get(Int32Ty, encGV.len)));
  builder.CreateCondBr(cond, forBody, forEnd);
  builder.SetInsertPoint(forBody);
  Value *indexList[2] = {ConstantInt::get(Int32Ty, 0), index};
  Value *ele = builder.CreateGEP(encGV.GV->getValueType(),encGV.GV, ArrayRef<Value *>(indexList, 2));
  ArrayType *arrTy = cast<ArrayType>(encGV.GV->getValueType());
  Type *eleTy = arrTy->getElementType();
  Value *encEle = builder.CreateXor(builder.CreateLoad(eleTy,ele),
                                    ConstantInt::get(eleTy, encGV.key));
  builder.CreateStore(encEle, ele);
  builder.CreateBr(forInc);
  builder.SetInsertPoint(forInc);
  builder.CreateStore(builder.CreateAdd(index, ConstantInt::get(Int32Ty, 1)),
                      indexPtr);
  builder.CreateBr(forCond);

  builder.SetInsertPoint(forEnd);
  builder.CreateRetVoid();
  appendToGlobalCtors(M, func, 0);
}
} // namespace
PreservedAnalyses GlobalEncryptionPass::run(Module &M, ModuleAnalysisManager &MAM) {
  outs() << "Pass start...\n";

//  if(!GlobalEncryption){
//    return PreservedAnalyses::all();
//  }
  ctx = &M.getContext();
  std::vector<GlobalVariable *> GVs;

  for (auto &GV : M.globals()) {
    GVs.push_back(&GV);
  }

  for (int i = 0; i < ObfuTimes; i++) {
    outs() << "Current ObfuTimes: " << i << "\n";
    for (auto *GV : GVs) {
      // 只对Integer和Array类型进行加密
      if (!GV->getValueType()->isIntegerTy() &&
          !GV->getValueType()->isArrayTy()) {
        continue;
      }
      // 筛出".str"全局变量,LLVM IR的metadata同样也要保留
      if (GV->hasInitializer() && GV->getInitializer() &&
          (GV->getName().contains(".str") || !OnlyStr) &&
          !GV->getName().contains("llvm.metadata")) {
        Constant *initializer = GV->getInitializer();
        ConstantInt *intData = dyn_cast<ConstantInt>(initializer);
        ConstantDataArray *arrayData = dyn_cast<ConstantDataArray>(initializer);
        // 处理数组
        if (arrayData) {
          // 获取数组的长度和数组元素的大小
          outs() << "Get global arraydata\n";
          uint32_t eleSize = arrayData->getElementByteSize();
          uint32_t eleNum = arrayData->getNumElements();
          uint32_t arrLen = eleNum * eleSize;
          outs() << "Global Variable: " << *GV << "\n"
                 << "Array Length: " << eleSize << " * " << eleNum << " = "
                 << arrLen << "\n";
          char *data = const_cast<char *>(arrayData->getRawDataValues().data());
          char *dataCopy = new char[arrLen];
          memcpy(dataCopy, data, arrLen);
          // 生成密钥
          uint64_t key = cryptoutils->get_uint64_t();
          for (uint32_t i = 0; i < arrLen; i++) {
            dataCopy[i] ^= ((char *)&key)[i % eleSize];
          }
          outs()<<"setInitializer before\n";
          GV->setInitializer(
              ConstantDataArray::getRaw(StringRef(dataCopy, arrLen), eleNum,
                                        arrayData->getElementType()));
          outs()<<"setInitializer after\n";

          GV->setConstant(false);
          InsertArrayDecryption(M, {GV, key, eleNum});
        }
        // 处理整数
        else if (intData) {
          uint64_t key = cryptoutils->get_uint64_t();
          outs()<<"\nintData->getType():"<<intData->getType()<<",key:"<<key<<",intData->getZExtValue():"<<intData->getZExtValue();

          ConstantInt *enc = ConstantInt::get(intData->getType(),
                                              key ^ intData->getZExtValue());
          outs()<<"\nenv:"<<enc->getZExtValue();
          GV->setInitializer(enc);
          InsertIntDecryption(M, {GV, key, 1LL});
        }
      }
    }
  }

  outs() << "Pass end...\n";
  return PreservedAnalyses::all();
}

注册代码pass代码:

#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"

#include "llvm/Transforms/Obfuscation/GlobalEncryption.h"
using namespace llvm;

llvm::PassPluginLibraryInfo getObfuscationPluginInfo() {
  return {
      LLVM_PLUGIN_API_VERSION, "Obfuscation", LLVM_VERSION_STRING,
      [](PassBuilder &PB) {
        PB.registerPipelineStartEPCallback(
            [](llvm::ModulePassManager &MPM, llvm::OptimizationLevel) {
              MPM.addPass(GlobalEncryptionPass());
            });
        }};
}
#ifndef LLVM_OBFUSCATION_LINK_INTO_TOOLS
extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
  return getObfuscationPluginInfo();
}
#endif

cmakelist.txt

add_llvm_pass_plugin(Obfuscation
  CryptoUtils.cpp
  Plugin.cpp
  GlobalEncryption.cpp
  ADDITIONAL_HEADER_DIRS
  ${PROJECT_SOURCE_DIR}

  DEPENDS
  intrinsics_gen

  LINK_COMPONENTS
        Core
        Support
        Analysis
        TransformUtils
  )

能够编译成功,但是最后会报错:

[~/Documents/文档/ollvm/test/mine]$ $clangPath/clang -isysroot `xcrun --show-sdk-path` -arch arm64 -mllvm -sobf -emit-llvm -S ../hello_ollvm.c -o hello_sobf.ll
registerPipelineStartEPCallback
registerOptimizerLastEPCallback
BogusControlFlow ing:funca
Pass start...
Current ObfuTimes: 0
Get global arraydata
Global Variable: @.str = private unnamed_addr constant [16 x i8] c"this is func a\0A\00", align 1
Array Length: 1 * 16 = 16
setInitializer before
setInitializer after
Get global arraydata
Global Variable: @.str.1 = private unnamed_addr constant [4 x i8] c"bcf\00", section "llvm.metadata"
Array Length: 1 * 4 = 4
setInitializer before
setInitializer after
Get global arraydata
Global Variable: @.str.2 = private unnamed_addr constant [17 x i8] c"../hello_ollvm.c\00", section "llvm.metadata"
Array Length: 1 * 17 = 17
setInitializer before
setInitializer after
Get global arraydata
Global Variable: @.str.3 = private unnamed_addr constant [16 x i8] c"this is func b\0A\00", align 1
Array Length: 1 * 16 = 16
setInitializer before
setInitializer after
Get global arraydata
Global Variable: @.str.4 = private unnamed_addr constant [4 x i8] c"fla\00", section "llvm.metadata"
Array Length: 1 * 4 = 4
setInitializer before
setInitializer after
Get global arraydata
Global Variable: @.str.5 = private unnamed_addr constant [16 x i8] c"this is func c\0A\00", align 1
Array Length: 1 * 16 = 16
setInitializer before
setInitializer after
Get global arraydata
Global Variable: @.str.6 = private unnamed_addr constant [5 x i8] c"sobf\00", section "llvm.metadata"
Array Length: 1 * 5 = 5
setInitializer before
setInitializer after
Get global arraydata
Global Variable: @.str.7 = private unnamed_addr constant [20 x i8] c"func a res is : %d\0A\00", align 1
Array Length: 1 * 20 = 20
setInitializer before
setInitializer after
Get global arraydata
Global Variable: @.str.8 = private unnamed_addr constant [20 x i8] c"func b res is : %d\0A\00", align 1
Array Length: 1 * 20 = 20
setInitializer before
setInitializer after

intData->getType():0x132024908,key:10951636861935028358,intData->getZExtValue():0
env:2696284294
intData->getType():0x132024908,key:14553880688145529733,intData->getZExtValue():0
env:1213528965Pass end...
'common' global must have a zero initializer!
i32* @x
'common' global must have a zero initializer!
i32* @y
fatal error: error in backend: Broken module found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.  Program arguments: /Users/xxx/work/ollvm/build/mine/debug_14/bin/clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -arch arm64 -mllvm -sobf -emit-llvm -S ../hello_ollvm.c -o hello_sobf.ll
1.  <eof> parser at end of file
2.  Optimizer
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  clang-14 0x00000001089d78ec llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 80
1  clang-14 0x00000001089d7e90 PrintStackTraceSignalHandler(void*) + 28
2  clang-14 0x00000001089d5f18 llvm::sys::RunSignalHandlers() + 148
3  clang-14 0x00000001089d70a0 llvm::sys::CleanupOnSignal(unsigned long) + 116
4  clang-14 0x000000010886c410 (anonymous namespace)::CrashRecoveryContextImpl::HandleCrash(int, unsigned long) + 200
5  clang-14 0x000000010886c330 llvm::CrashRecoveryContext::HandleExit(int) + 136
6  clang-14 0x00000001089d1490 llvm::sys::Process::Exit(int, bool) + 68
7  clang-14 0x0000000104b41a70 clang::CompilerInstance::getDiagnostics() const + 0
8  clang-14 0x000000010887ed8c llvm::report_fatal_error(llvm::Twine const&, bool) + 176
9  clang-14 0x000000010887ecdc llvm::report_fatal_error(llvm::Twine const&, bool) + 0
10 clang-14 0x0000000107a97b38 llvm::VerifierPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) + 120
11 clang-14 0x0000000108f92854 llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module> >::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) + 52
12 clang-14 0x0000000107a24c44 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module> >::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) + 304
13 clang-14 0x0000000108f78f00 (anonymous namespace)::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction, std::__1::unique_ptr<llvm::raw_pwrite_stream, std::__1::default_delete<llvm::raw_pwrite_stream> >&, std::__1::unique_ptr<llvm::ToolOutputFile, std::__1::default_delete<llvm::ToolOutputFile> >&) + 5140
14 clang-14 0x0000000108f64c04 (anonymous namespace)::EmitAssemblyHelper::EmitAssembly(clang::BackendAction, std::__1::unique_ptr<llvm::raw_pwrite_stream, std::__1::default_delete<llvm::raw_pwrite_stream> >) + 348
15 clang-14 0x0000000108f63830 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, std::__1::unique_ptr<llvm::raw_pwrite_stream, std::__1::default_delete<llvm::raw_pwrite_stream> >) + 992
16 clang-14 0x00000001095155bc clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) + 1572
17 clang-14 0x000000010c4e1da8 clang::ParseAST(clang::Sema&, bool, bool) + 820
18 clang-14 0x0000000109c7d80c clang::ASTFrontendAction::ExecuteAction() + 296
19 clang-14 0x0000000109513bc4 clang::CodeGenAction::ExecuteAction() + 92
20 clang-14 0x0000000109c7cee8 clang::FrontendAction::Execute() + 124
21 clang-14 0x0000000109b10968 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 920
22 clang-14 0x0000000109d8b41c clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 1060
23 clang-14 0x0000000104b40f20 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) + 1180
24 clang-14 0x0000000104b3280c ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&) + 304
25 clang-14 0x00000001098cbbbc clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, bool*) const::$_1::operator()() const + 40
26 clang-14 0x00000001098cbb88 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, bool*) const::$_1>(long) + 24
27 clang-14 0x000000010886c29c llvm::function_ref<void ()>::operator()() const + 32
28 clang-14 0x000000010886c220 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) + 260
29 clang-14 0x00000001098c953c clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, bool*) const + 380
30 clang-14 0x00000001098725a0 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&) const + 680
31 clang-14 0x000000010987281c clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::__1::pair<int, clang::driver::Command const*> >&) const + 144
32 clang-14 0x000000010988ad80 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::__1::pair<int, clang::driver::Command const*> >&) + 288
33 clang-14 0x0000000104b31e6c main + 2976
34 dyld     0x00000001af7c3e50 start + 2544
clang-14: error: clang frontend command failed with exit code 70 (use -v to see invocation)
clang version 14.0.6 (https://github.com/llvm/llvm-project.git f28c006a5895fc0e329fe15fead81e37457cb1d1)
Target: arm64-apple-darwin22.3.0
Thread model: posix
InstalledDir: /Users/xxx/work/ollvm/build/mine/debug_14/bin
clang-14: note: diagnostic msg: 
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang-14: note: diagnostic msg: /var/folders/vk/p3665v4j5_l3194pb3w5lqdc0000gp/T/hello_ollvm-a7e6b6.c
clang-14: note: diagnostic msg: /var/folders/vk/p3665v4j5_l3194pb3w5lqdc0000gp/T/hello_ollvm-a7e6b6.sh
clang-14: note: diagnostic msg: Crash backtrace is located in
clang-14: note: diagnostic msg: /Users/xxx/Library/Logs/DiagnosticReports/clang-14_<YYYY-MM-DD-HHMMSS>_<hostname>.crash
clang-14: note: diagnostic msg: (choose the .crash file that corresponds to your crash)
clang-14: note: diagnostic msg: 

********************