BogusControlFlow的功能是为函数增加新的虚假控制流和添加垃圾指令。
1、环境
MacOS 10.15.3
Xcode 11.3
LLVM 8.0.0
2、准备
(1)下载LLVM8.0.0
地址:releases.llvm.org/download.ht…
(2)下载OLLVM的Obfuscation部分代码
此处的代码适配llvm8.0.0,但不保证在你的新环境中运行正常,可根据运行时的错误提示,自行修改。
(3)复制OLLVM代码到LLVM的对应路径下
头文件存放位置:/llvm_8.0.0/include/llvm/Transforms/Tollvm
CPP文件存放位置:/llvm_8.0.0/lib/Transforms/Tollvm
(4)修改配置文件内容
为/llvm_8.0.0/lib/Transforms/CMakeLists.txt文件增加add_subdirectory(Tollvm):
add_subdirectory(Utils)
add_subdirectory(Instrumentation)
add_subdirectory(AggressiveInstCombine)
add_subdirectory(InstCombine)
add_subdirectory(Scalar)
add_subdirectory(IPO)
add_subdirectory(Vectorize)
add_subdirectory(Hello)
add_subdirectory(ObjCARC)
add_subdirectory(Coroutines)
add_subdirectory(Tollvm)
为/llvm_8.0.0/lib/Transforms/LLVMBuild.txt增加Tollvm:
[common]
subdirectories = AggressiveInstCombine Coroutines IPO InstCombine Instrumentation Scalar Utils Vectorize ObjCARC Tollvm
[component_0]
type = Group
name = Transforms
parent = Libraries
(5)将LLVM源码生成Xcode项目,用Xcode运行编译LLVM
在执行完以上四个步骤后,再执行以下命令,生成xcode项目代码:
cmake -G Xcode CMAKE_BUILD_TYPE="Debug" ../llvm_8.0.0
详细方法可参考上篇文章:juejin.cn/post/693200…
打开Xcode工程,可以看到Tollvm的代码:
Comd+B 编译生成Tollvm.dylib, 在工程目录下的/Debug/lib/中:
3、测试代码
test.c代码:
void f1(){
printf("f1--printf\n");
}
int f2(){
printf("f2---printf\n");
int a =5;
int b = 93;
int d = a*b;
if(d>100)
{
printf("a=%d\n", a);
}
else
{
printf("b=%d\n", b);
}
return 0;
}
int main()
{
f2();
return 0;
}
4、为可执行文件增加虚假控制流(BogusControlFlow)
(1)终端先cd到test.c所在的测试路径下
cd /path/to/tmp/
(2) 使用clang将test.c编译成中间码格式, 生成 test_0224.bc
/Applications/Xcode11.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -emit-llvm -c ./test.c -o ./test_0224.bc
请把clang的路径替换成你的。
(3)在LLVM的Xcode项目中,选择ALL_BUILD,并编译全部Targets,就可以找到所需的opt程序了
opt 加载 Tollvm.dylib 对 test_0224.bc 做优化,“-boguscf”代表启用名为 boguscf 的Pass,boguscf 是我们在 BogusControlFlow.cpp 中注册的Pass名称:
/path/to/xcode_build_8.0_2/Debug/bin/opt -load /path/to/Tollvm.dylib -boguscf ./test_0224.bc -o ./test_0224_2.bc
test_0224_2.bc 是用Pass处理后生成的中间码文件。
(4)clang把中间码 test_0224_2.bc 生成可执行文件
/Applications/Xcode11.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang ./test_0224_2.bc -o ./wjtest
5、比较BogusControlFlow效果
用IDA分析可执行文件,test.c 中的 f2() 方法:
加固前:
加固后:
可以看到 f2() 方法增加了虚假的无用分支,证明本次加固是有效的。
6、Xcode调试Pass
(1)设置opt运行的参数
点击"opt"
找到"Edit Scheme..."
添加参数:
参数解释:
-load=../lib/Tollvm.dylib
是opt运行时加载Tollvm.dylib
-boguscf
是要调用的pass名称。
-disable-output
是指不输出,这个可以不选,因为下面设置了输出文件。
/Users/test/wj_llvm/Tmp/testHikari/test_str.bc
是你的测试.bc文件的全路径。
/Users/test/wj_llvm/Tmp/testHikari/test_str_r.bc
是pass处理后的输出文件的全路径。
(2)设置opt的依赖
在当前Xcode的llvm工程中,找到Tools下的opt中的CMakeLists.txt文件,添加"Tollvm"依赖,CMakeLists.txt文件内容如下:
set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
AggressiveInstCombine
Analysis
BitWriter
CodeGen
Core
Coroutines
IPO
IRReader
InstCombine
Instrumentation
MC
ObjCARCOpts
ScalarOpts
Support
Target
TransformUtils
Vectorize
Passes
)
# Support plugins.
set(LLVM_NO_DEAD_STRIP 1)
add_llvm_tool(opt
AnalysisWrappers.cpp
BreakpointPrinter.cpp
Debugify.cpp
GraphPrinters.cpp
NewPMDriver.cpp
PassPrinters.cpp
PrintSCC.cpp
opt.cpp
DEPENDS
intrinsics_gen
Tollvm
)
export_executable_symbols(opt)
if(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
target_link_libraries(opt PRIVATE Polly)
endif(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
(3)下断点调试
此时运行项目,可成功停在断点,可调试代码