使用Xcode编译测试OLLVM的BogusControlFlow功能

2,628 阅读2分钟

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部分代码

           地址:github.com/luoyanbei/o…

          此处的代码适配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)下断点调试

此时运行项目,可成功停在断点,可调试代码