当前位置: 首页 > news >正文

LLVM的混淆之旅(六)-字符串加密

简介

在上一个教学中,学习了如何写一个LLVM Pass示例来进行控制流平坦化,这篇文章,来学习如何二利用LLVM实现字符串的加密。

案例

需要加密的对象

这是一个经典的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 PassInfoMixin<mypass>{const uint8_t KEY = 0x42;Function *createDecryptFunc(Module *M){LLVMContext &Ctx = M->getContext();std::vector<Type*> 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::vector<GlobalVariable*> EncryptedGlobals;for(GlobalVariable &GV : M.globals()){if (!GV.hasInitializer() || !GV.isConstant() || GV.getName().contains("llvm.")) continue;Constant *Init = GV.getInitializer();ConstantDataArray* DataArray = dyn_cast<ConstantDataArray>(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::vector<Instruction*> user;for(User *U: GV->users()){Instruction* ins = dyn_cast<Instruction>(U);if(ins->getFunction() == DecryptFunc) continue;user.push_back(ins);}for(Instruction *ins : user){IRBuilder<> builder(ins);ConstantDataArray* DataArray = dyn_cast<ConstantDataArray>(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, ArrayRef<PassBuilder::PipelineElement>){if(Name == "mypass"){MPM.addPass(mypass());return true;}return false;});}};
}

代码解释

看到上面的pass代码,我们会感到头晕目眩,没关系,下面我们一步步拆解。
上面的代码分主要分为两部分:

  1. 构建异或的解密函数(createDecryptFunc
  2. 加密字符串,并且将上面构建的解密函数插入代码。

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

原始

根据上面的图片,可以看到,上面使用的pass,成功将HelloWorld加密了。

如果❤喜欢❤本系列教程,就点个关注吧,后续不定期更新~

http://www.jsqmd.com/news/378610/

相关文章:

  • 分析2026年写作业用拉远镜费用情况及推荐品牌 - mypinpai
  • 2026年比较好的人型机器人机械加工/五轴机械加工怎么选实力厂家推荐 - 品牌宣传支持者
  • 2026年小篆打印机排名揭晓,性价比高的打印设备全解析 - myqiye
  • 探讨福州数智化应用,捷宇科技研发能力强且客户评价好吗 - 工业品网
  • 基于微信小程序的大学生体质测试管理系统的设计与实现
  • PPH储罐专业厂家怎么选,新疆甘肃等地靠谱品牌推荐 - 工业品牌热点
  • 2026年比较好的冷库挤塑板/国标挤塑板高评价直销厂家采购指南推荐(高评价) - 品牌宣传支持者
  • 基于微信小程序的CET助手设计与实现
  • 聊聊有实力的公司注册企业,上海地区靠谱之选盘点 - 工业推荐榜
  • 访客云(FonkaLink)联系方式:系统部署与数据安全注意事项 - 品牌推荐
  • txtsetup.sif文件SetupData节DisableAsr的值和setupldr!SlCheckASRKeypress函数的关系和检测F2键进入ASR
  • 基于微信小程序的工厂生产流程与库存管理一体化系统
  • 2026年口碑好的工业制冷压缩机/国产制冷压缩机实用公司采购参考怎么联系 - 品牌宣传支持者
  • 分析京津冀轮胎专业制造商总代理,如何选择合适的? - 工业设备
  • 闭眼入!千笔·专业降AIGC智能体,碾压级的降AI率网站
  • AgentScope和LangGraph协同开发
  • 2026年北京别墅装修设计十大品牌费用如何,为你分析 - 工业品网
  • 基于微信小程序的高校设备报修系统
  • 一个提前预知期刊编辑意见的方法
  • Rust中 引用类型 VS 裸指针
  • 2026年质量好的坐骑式割草机/草坪割草机生产商推荐怎么选(可靠) - 品牌宣传支持者
  • Python Any类型注解(Ptyhon typing.Any、Python类型提示、万能类型提示、typing模块、Any陷阱、# type: ignore)
  • 青椒三年期间养成的六个科研习惯
  • 应用游击战术于家庭子女教育的作业辅导问题
  • 2026年比较好的特种纸印刷/特种纸包装生产厂家采购指南帮我推荐几家 - 品牌宣传支持者
  • 微信小程序登录+支付
  • 加油卡闲置不用?靠谱回收平台让你快速提现! - 团团收购物卡回收
  • 研究生真的没必要害怕导师
  • Cursor开发智能体demo初体验
  • 预训练目标的统一性框架:从对比学习到生成式建模的理论收敛