Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
Dfault0 opened this issue Oct 26, 2023 · 0 comments
Open

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

Dfault0 opened this issue Oct 26, 2023 · 0 comments

Comments

@Dfault0
Copy link

Dfault0 commented Oct 26, 2023

就还挺奇怪的,我也不知道为什么在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: 

********************
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant