OLLVM移植LLVM18控制流平坦化调试修复指南
时间:2026-08-20 | 作者:318050 | 阅读:0版权归作者所有,如有转发,请注明文章出处:cyrus-studio.github.io/blog/
前言
把 OLLVM 移植到 LLVM18 后,发现 -fla(控制流平坦化)不能正常使用。
关于移植过程参考这篇文章:OLLVM 移植 LLVM 18 实战,轻松实现 C&C++ 代码混淆
测试代码 fla.c
#include
int main(int argc, char** argv) {
int a = atoi(argv[1]);
if(a == 0)
return 1;
else
return 10;
return 0;
}
使用 clang 编译并启用 Control Flow Flattening(控制流平坦化)报错如下:
D:Projectsllvm-projectbuild>clang -mllvm -fla fla.c -o fla.exe
[OLLVM] run.PipelineStartEPCallback
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: D:Projectsllvm-projectbuildbinclang.exe -cc1 -triple x86_64-pc-windows-msvc19.42.34433 -emit-obj -mrelax-all -mincremental-linker-compatible -dumpdir fla.exe- -disable-free -clear-ast-before-backend -main-file-name fla.c -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -fdebug-compilation-dir=D:Projectsllvm-projectbuild -fcoverage-compilation-dir=D:Projectsllvm-projectbuild -resource-dir D:Projectsllvm-projectbuildlibclang18 -internal-isystem D:Projectsllvm-projectbuildlibclang18include -internal-isystem D:AppVisualStudioIDEVCToolsMSVC14.42.34433include -internal-isystem D:AppVisualStudioIDEVCToolsMSVC14.42.34433ATLMFCinclude -internal-isystem D:AppVisualStudioIDEVCAuxiliaryVSinclude -internal-isystem "C:Program Files (x86)Windows Kits10include10.0.22621.0ucrt" -internal-isystem "C:Program Files (x86)Windows Kits10\include10.0.22621.0\um" -internal-isystem "C:Program Files (x86)Windows Kits10\include10.0.22621.0\shared" -internal-isystem "C:Program Files (x86)Windows Kits10\include10.0.22621.0\winrt" -internal-isystem "C:Program Files (x86)Windows Kits10\include10.0.22621.0\cppwinrt" -internal-isystem D:AppVisualStudioIDEVCToolsMSVC14.42.34433include -internal-isystem D:AppVisualStudioIDEVCToolsMSVC14.42.34433ATLMFCinclude -internal-isystem D:AppVisualStudioIDEVCAuxiliaryVSinclude -internal-isystem "C:Program Files (x86)Windows Kits10include10.0.22621.0ucrt" -internal-isystem "C:Program Files (x86)Windows Kits10\include10.0.22621.0\um" -internal-isystem "C:Program Files (x86)Windows Kits10\include10.0.22621.0\shared" -internal-isystem "C:Program Files (x86)Windows Kits10\include10.0.22621.0\winrt" -internal-isystem "C:Program Files (x86)Windows Kits10\include10.0.22621.0\cppwinrt" -ferror-limit 19 -fmessage-length=133 -fno-use-cxa-atexit -fms-extensions -fms-compatibility -fms-compatibility-version=19.42.34433 -fskip-odr-check-in-gmf -fdelayed-template-parsing -fcolor-diagnostics -mllvm -fla -faddrsig -o C:Users17759AppDataLocalTempfla-6c1e10.o -x c fla.c
1. parser at end of file
2. Optimizer
Exception Code: 0xC0000005
#0 0x00007ff627d441ff llvm::Instruction::handleMarkerRemoval(void) D:Projectsllvm-projectllvmlibIRInstruction.cpp:87:0
#1 0x00007ff627d443d9 llvm::Instruction::eraseFromParent(void) D:Projectsllvm-projectllvmlibIRInstruction.cpp:94:0
#2 0x00007ff62bb26d39 llvm::FlatteningPass::flatten(class llvm::Function &) D:Projectsllvm-projectllvmlibPassesObfuscationFlattening.cpp:101:0
#3 0x00007ff62bb26316 llvm::FlatteningPass::run(class llvm::Function &, class llvm::AnalysisManagerllvm::Function> &) D:Projectsllvm-projectllvmlibPassesObfuscationFlattening.cpp:20:0
#4 0x00007ff62ba9ab18 llvm::detail::PassModelllvm::Function, class llvm::FlatteningPass, class llvm::PreservedAnalyses, class llvm::AnalysisManagerllvm::Function>>::run(class llvm::Function &, class llvm::AnalysisManagerllvm::Function> &) D:Projectsllvm-projectllvmincludellvmIRPassManagerInternal.h:89:0
#5 0x00007ff623887eb1 llvm::PassManagerllvm::Function, class llvm::AnalysisManagerllvm::Function>>::run(class llvm::Function &, class llvm::AnalysisManagerllvm::Function> &) D:Projectsllvm-projectllvmincludellvmIRPassManager.h:543:0
#6 0x00007ff6238884e8 llvm::detail::PassModelllvm::Function, class llvm::PassManagerllvm::Function, class llvm::AnalysisManagerllvm::Function>>, class llvm::PreservedAnalyses, class llvm::AnalysisManagerllvm::Function>>::run(class llvm::Function &, class llvm::AnalysisManagerllvm::Function> &) D:Projectsllvm-projectllvmincludellvmIRPassManagerInternal.h:89:0
#7 0x00007ff627f3661f llvm::ModuleToFunctionPassAdaptor::run(class llvm::Module &, class llvm::AnalysisManagerllvm::Module> &) D:Projectsllvm-projectllvmlibIRPassManager.cpp:123:0
#8 0x00007ff623888be8 llvm::detail::PassModelllvm::Module, class llvm::ModuleToFunctionPassAdaptor, class llvm::PreservedAnalyses, class llvm::AnalysisManagerllvm::Module>>::run(class llvm::Module &, class llvm::AnalysisManagerllvm::Module> &) D:Projectsllvm-projectllvmincludellvmIRPassManagerInternal.h:89:0
#9 0x00007ff627f4bf21 llvm::PassManagerllvm::Module, class llvm::AnalysisManagerllvm::Module>>::run(class llvm::Module &, class llvm::AnalysisManagerllvm::Module> &) D:Projectsllvm-projectllvmincludellvmIRPassManager.h:543:0
#10 0x00007ff6294ff0ff `anonymous namespace'::EmitAssemblyHelper::RunOptimizationPipeline D:Projectsllvm-projectclanglibCodeGenBackendUtil.cpp:1150:0
#11 0x00007ff6294ffafc `anonymous namespace'::EmitAssemblyHelper::EmitAssembly D:Projectsllvm-projectclanglibCodeGenBackendUtil.cpp:1216:0
#12 0x00007ff6294fa859 clang::EmitBackendOutput(class clang::DiagnosticsEngine &, class clang::HeaderSearchOptions const &, class clang::CodeGenOptions const &, class clang::TargetOptions const &, class clang::LangOptions const &, class llvm::StringRef, class llvm::Module *, enum clang::BackendAction, class llvm::IntrusiveRefCntPtrllvm::vfs::FileSystem>, class std::unique_ptrllvm::raw_pwrite_stream, struct std::default_deletellvm::raw_pwrite_stream>>, class clang::BackendConsumer *) D:Projectsllvm-projectclanglibCodeGenBackendUtil.cpp:1377:0
#13 0x00007ff62a0c0090 clang::BackendConsumer::HandleTranslationUnit(class clang::ASTContext &) D:Projectsllvm-projectclanglibCodeGenCodeGenAction.cpp:379:0
#14 0x00007ff62e5cf6be clang::ParseAST(class clang::Sema &, bool, bool) D:Projectsllvm-projectclanglibParseParseAST.cpp:183:0
#15 0x00007ff62a57dfd2 clang::ASTFrontendAction::ExecuteAction(void) D:Projectsllvm-projectclanglibFrontendFrontendAction.cpp:1183:0
#16 0x00007ff62a0bd227 clang::CodeGenAction::ExecuteAction(void) D:Projectsllvm-projectclanglibCodeGenCodeGenAction.cpp:1153:0
#17 0x00007ff62a57d80c clang::FrontendAction::Execute(void) D:Projectsllvm-projectclanglibFrontendFrontendAction.cpp:1069:0
#18 0x00007ff62a53a7a4 clang::CompilerInstance::ExecuteAction(class clang::FrontendAction &) D:Projectsllvm-projectclanglibFrontendCompilerInstance.cpp:1057:0
#19 0x00007ff62a811c06 clang::ExecuteCompilerInvocation(class clang::CompilerInstance *) D:Projectsllvm-projectclanglibFrontendToolExecuteCompilerInvocation.cpp:272:0
#20 0x00007ff622ef44ca cc1_main(class llvm::ArrayRef, char const *, void *) D:Projectsllvm-projectclangtoolsdrivercc1_main.cpp:294:0
#21 0x00007ff622eda94f ExecuteCC1Tool D:Projectsllvm-projectclangtoolsdriverdriver.cpp:365:0
#22 0x00007ff622edb195 clang_main(int, char **, struct llvm::ToolContext const &) D:Projectsllvm-projectclangtoolsdriverdriver.cpp:405:0
#23 0x00007ff622f27b46 main D:Projectsllvm-projectbuildtoolsclangtoolsdriverclang-driver.cpp:17:0
#24 0x00007ff6329637d9 invoke_main D:a_work1ssrcvctoolscrtvcstartupsrcstartupexe_common.inl:79:0
#25 0x00007ff6329636c2 __scrt_common_main_seh D:a_work1ssrcvctoolscrtvcstartupsrcstartupexe_common.inl:288:0
#26 0x00007ff63296357e __scrt_common_main D:a_work1ssrcvctoolscrtvcstartupsrcstartupexe_common.inl:331:0
#27 0x00007ff63296386e mainCRTStartup D:a_work1ssrcvctoolscrtvcstartupsrcstartupexe_main.cpp:17:0
#28 0x00007ffb44e4259d (C:WindowsSystem32KERNEL32.DLL+0x1259d)
#29 0x00007ffb456eaf38 (C:WindowsSYSTEM32ntdll.dll+0x5af38)
clang: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 18.1.8 (https://github.com/CYRUS-STUDIO/LLVM.git 98e0b5c7f1277be725f8150102b88a992f65d196)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: D:Projectsllvm-projectbuildbin
clang: note: diagnostic msg:
********************
PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: C:UserscyrusAppDataLocalTempfla-7f9157.c
clang: note: diagnostic msg: C:UserscyrusAppDataLocalTempfla-7f9157.sh
clang: note: diagnostic msg:
********************
由报错信息可知,Flattening.cpp的第101行代码在运行时出现异常,具体的错误类型为访问权限冲突(0xC0000005),这通常表示代码尝试访问了无效或空的内存指针。
使用 CLion 调试 Flattening
使用 Clion 断点调试一下 Flattening.cpp。
1、在 CLion 中打开 llvm 工程
2、设置 CMake
- 设置 LLVM_DIR 、 禁用 llvm-gtest
-DCMAKE_PREFIX_PATH="D:/Projects/llvm-project/build" -DLLVM_INCLUDE_TESTS=OFF
- 工具链选择 Visual Studio
关于如何编译调试 LLVM 参考:LLVM 全面解析:NDK 为什么离不开它?如何亲手编译调试 clang
3、新增运行配置 ollvm-fla ,添加程序实参:
- 编译可执行程序
-mllvm -fla "D:Projectsllvm-projectbuildfla.c" -o "D:Projectsllvm-projectbuildfla.exe"
- 或者编译 IR 文件
-mllvm -fla -S -emit-llvm "D:Projectsllvm-projectbuildfla.c" -o "D:Projectsllvm-projectbuildfla.ll"
效果如下:
4、下断点并运行调试
通过断点调试发现崩溃的位置发生在:entryBB.getTerminator()->eraseFromParent();
问题分析与解决
在 Flattening.cpp 中 65 行和 97 行都调用了 entryBB.getTerminator()->eraseFromParent();
if (bEntryBB_isConditional) {
entryBB.getTerminator()->eraseFromParent();
}
-
entryBB 是一个 BasicBlock。
-
getTerminator()会返回这个基本块的终结指令,它是最后一条控制流指令,例如br、ret、switch等。
-
eraseFromParent() 的作用是:把这条指令 从所属基本块里移除并销毁 。
问题原因:重复调用 eraseFromParent 从 entryBB 中移除终止指令导致的空指针异常。
把 Flattening.cpp 中 97行的代码
if (bEntryBB_isConditional) {
entryBB.getTerminator()->eraseFromParent();
}
改为
BB->getTerminator()->eraseFromParent();
修改完成执行 ninja 命令重新编译 llvm 即可。
测试
使用 clang 并启用 -fla(控制流平坦化)编译 fla.c
clang -mllvm -fla fla.c -o fla.exe
测试 fla.exe 正常运行
使用 IDA 打开编译后的可执行程序,下面是未使用混淆时的反汇编视图
经过控制流平坦化后











