案例需要加密的对象这是一个经典的c语言样例目的是输出字符串hello world#include stdio.h int main(){ printf(hello world\n); return 0; }加密pass编写下面是完整的pass代码代码的目的是让字符串在编译的过程中进行异或加密并且在运行的过程中动态解密。#include llvm/Passes/PassBuilder.h #include llvm/Passes/PassPlugin.h #include llvm/Support/raw_ostream.h #include llvm/IR/Function.h #include llvm/IR/Instructions.h #include llvm/IR/IRBuilder.h #include llvm/IR/PassManager.h #include llvm/IR/GlobalVariable.h #include llvm/IR/Constants.h using namespace llvm; namespace{ struct mypass : public PassInfoMixinmypass{ const uint8_t KEY 0x42; Function *createDecryptFunc(Module *M){ LLVMContext Ctx M-getContext(); std::vectorType* paramTypes { PointerType::getUnqual(Ctx), Type::getInt32Ty(Ctx) }; FunctionType *funcType FunctionType::get(Type::getVoidTy(Ctx),paramTypes,false); Function *Func Function::Create(funcType, GlobalValue::InternalLinkage, my_decrypt_func, M); Argument *ArgData Func-getArg(0); Argument *ArgLen Func-getArg(1); BasicBlock *EntryBB BasicBlock::Create(Ctx, entry, Func); BasicBlock *LoopCheckBB BasicBlock::Create(Ctx, loop_check, Func); BasicBlock *LoopBodyBB BasicBlock::Create(Ctx, loop_body, Func); BasicBlock *ExitBB BasicBlock::Create(Ctx, exit, Func); IRBuilder builder(EntryBB); builder.CreateBr(LoopCheckBB); builder.SetInsertPoint(LoopCheckBB); PHINode *LoopVar builder.CreatePHI(Type::getInt32Ty(Ctx), 2, i); LoopVar-addIncoming(builder.getInt32(0), EntryBB); Value *Cond builder.CreateICmpSLT(LoopVar, ArgLen, cond); builder.CreateCondBr(Cond, LoopBodyBB, ExitBB); builder.SetInsertPoint(LoopBodyBB); Value *Ptr builder.CreateInBoundsGEP(builder.getInt8Ty(), ArgData, LoopVar); Value *ByteVal builder.CreateLoad(builder.getInt8Ty(), Ptr); Value *XorVal builder.CreateXor(ByteVal, builder.getInt8(KEY)); builder.CreateStore(XorVal, Ptr); Value *NextVar builder.CreateAdd(LoopVar, builder.getInt32(1)); LoopVar-addIncoming(NextVar, LoopBodyBB); builder.CreateBr(LoopCheckBB); builder.SetInsertPoint(ExitBB); builder.CreateRetVoid(); return Func; } PreservedAnalyses run(Module M, ModuleAnalysisManager AM){ errs() Running On-Demand String Encryption Pass...\n; std::vectorGlobalVariable* EncryptedGlobals; for(GlobalVariable GV : M.globals()){ if (!GV.hasInitializer() || !GV.isConstant() || GV.getName().contains(llvm.)) continue; Constant *Init GV.getInitializer(); ConstantDataArray* DataArray dyn_castConstantDataArray(Init); if(DataArray DataArray-isString()){ StringRef OriginalString DataArray-getAsString(); if(OriginalString.size() 2) continue; errs() Encrypting string: OriginalString \n; std::string EncryptedStr OriginalString.str(); for(int i 0; i EncryptedStr.size(); i){ EncryptedStr[i] ^ KEY; } Constant *NewInit ConstantDataArray::getString(M.getContext(), EncryptedStr, false); GV.setInitializer(NewInit); GV.setConstant(false); EncryptedGlobals.push_back(GV); } } if(EncryptedGlobals.empty()) return PreservedAnalyses::all(); Function *DecryptFunc createDecryptFunc(M); for(GlobalVariable *GV : EncryptedGlobals){ std::vectorInstruction* user; for(User *U: GV-users()){ Instruction* ins dyn_castInstruction(U); if(ins-getFunction() DecryptFunc) continue; user.push_back(ins); } for(Instruction *ins : user){ IRBuilder builder(ins); ConstantDataArray* DataArray dyn_castConstantDataArray(GV-getInitializer()); int len DataArray-getNumElements(); builder.CreateCall(DecryptFunc, {GV, builder.getInt32(len)}); } } return PreservedAnalyses::none(); } }; } extern C LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo(){ return{ LLVM_PLUGIN_API_VERSION, mypass, v0.1, [](PassBuilder PB){ PB.registerPipelineParsingCallback( [](StringRef Name, ModulePassManager MPM, ArrayRefPassBuilder::PipelineElement){ if(Name mypass){ MPM.addPass(mypass()); return true; } return false; } ); } }; }代码解释看到上面的pass代码我们会感到头晕目眩没关系下面我们一步步拆解。上面的代码分主要分为两部分构建异或的解密函数createDecryptFunc加密字符串并且将上面构建的解密函数插入代码。CMakeLists.txt编译可以直接用下面的cmake配置文件编译过程在之前文章详细讲解cmake_minimum_required(VERSION 4.1.1) project(mypass) set(LLVM_DIR D:/LLVM/llvm-project/build/lib/cmake/llvm) find_package(LLVM REQUIRED CONFIG) list(APPEND CMAKE_MODULE_PATH ${LLVM_CMAKE_DIR}) include(AddLLVM) include_directories(${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_library(mypass MODULE mypass.cpp) set_target_properties(mypass PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) target_link_libraries(mypass LLVMCore LLVMSupport) target_compile_options(mypass PRIVATE /utf-8)#用中文使用效果展示编译并执行图片中可以看出可以正常运行反编译查看区别原始test.exe加密test_opt.exe