搭建一个windows 下应用层能够快捷使用的 llvm 工具链,文中将会解释为什么要这么做,以及阐述其他方式可能会遇到的坑点,同时这个文章只是一个实践文,并不涉及具体原理,只为了提供一个windows 下搭建llvm的最佳实践方案。
为什么不使用 VS2019 自带的llvm进行使用?
不编译的话,就无法编译生成Pass,你只能利用clang去编译生成exe,比起VS2019 自带的cl并没有明显优势,作为一个小白,并不清楚支持llvm的原因。而Pass相当于一个插件,起到中间层实际执行混淆的作用,相当于我们这个功能的核心,所以必须要它。
为什么不用 VS2019 进行项目编译?
经过在12.0.1 / 12.0.0 / 15.0.6 几个版本的实践,会遇到各种问题,其中最主要的问题是,如果不使用12.0.0 ,你编译出来的llvm 集成到VS 2019中使用时,会出现各种意想不到的错误。另外用MSVC 编译llvm时,不支持开启BUILD_SHARED_LIBS 选项,但可以使用LLVM_EXPORT_SYMBOLS_FOR_PLUGINS
选项或LLVM_ENABLE_PLUGINS
选项,但这样会出现一个问题,编译后的pass仅能使用new Pass语法,而且必须使用opt 进行加载插件使用,实际只有registerPipelineParsingCallback
回调函数可以正常使用
既然我们需要的只是Pass,也就是一个dll文件,那么我们是否能生成12.0.0 版本的llvm pass,然后就直接用VS 2019 自带的llvm进行编译集成呢?
我也尝试过,但没有成功,不是自己编译出来的llvm pass 和 自己编译出来的 llvm clang-cl 在使用时会报无法加载模块,0x7E的错误,实在不想在windows下试图调试llvm 源码找出报错原因,因为这样也许还要被折磨几周。
基础环境
windows 10
https://github.com/llvm/llvm-project/releases/tag/llvmorg-12.0.0
CMake (https://cmake.org/download/)
VS 2019 16.11.10
MSYS2
Python
Git
安装MSYS2
PS:llvm 是支持 VS 2019直接去生成llvm的,不用安装这些东西,官方有相关文章(https://llvm.org/docs/GettingStartedVS.html),编译很快,但编出来不会写相关Pass并利用,这里用gcc + vs2019 构造工具链,欢迎踩完坑后分享~
官网:https://www.msys2.org/
详细安装步骤:https://bbs.kanxue.com/thread-272346.htm#msg_header_h3_1
安装后安装gcc工具链
1
|
pacman
-
S
-
-
needed base
-
devel mingw
-
w64
-
x86_64
-
toolchain mingw
-
w64
-
i686
-
toolchain cmake
|
在VS 2019 中安装clang cmake 等工具
https://github.com/llvm/llvm-project/releases/tag/llvmorg-12.0.0
将源码解压,文件树如下:PS:其中build* 文件夹是我运行bat文件后产生的目录,lld 可以不用下载,是之前踩坑的产物
编译源码:
x64_gcc_build.bat 文件内容
1
2
3
4
5
6
7
8
9
10
|
cd C:\Users\admin\Documents\llvmProject12
set
PATH
=
%
PATH
%
;C:\msys64\mingw64\
bin
gcc
-
-
version
cmake
-
G
"MinGW Makefiles"
-
S .
/
llvm
-
B .
/
build_dyn_x64 ^
-
DCMAKE_BUILD_TYPE
=
Release
-
DLLVM_ENABLE_PROJECTS
=
"clang;"
^
-
DLLVM_TARGETS_TO_BUILD
=
"X86"
-
DBUILD_SHARED_LIBS
=
ON ^
-
DLLVM_INCLUDE_TESTS
=
OFF
-
DLLVM_BUILD_TESTS
=
OFF ^
-
DLLVM_INCLUDE_BENCHMARKS
=
OFF
-
DLLVM_BUILD_BENCHMARKS
=
OFF
-
DLLVM_ENABLE_DUMP
=
ON
cmake
-
-
build .
/
build_dyn_x64
-
j
4
cmake
-
DCMAKE_INSTALL_PREFIX
=
"C:\Program Files\LLVM\llvm12\llvm12_dyn_x64"
-
P .\build_dyn_x64\cmake_install.cmake
|
x86_gcc_build.bat 文件内容
1
2
3
4
5
6
7
8
9
10
|
cd C:\Users\admin\Documents\llvmProject12
set
PATH
=
%
PATH
%
;C:\msys64\mingw32\
bin
gcc
-
-
version
cmake
-
G
"MinGW Makefiles"
-
S .
/
llvm
-
B .
/
build_dyn_x32 ^
-
DCMAKE_BUILD_TYPE
=
Release
-
DLLVM_ENABLE_PROJECTS
=
"clang;"
^
-
DLLVM_TARGETS_TO_BUILD
=
"X86"
-
DBUILD_SHARED_LIBS
=
ON ^
-
DLLVM_INCLUDE_TESTS
=
OFF
-
DLLVM_BUILD_TESTS
=
OFF ^
-
DLLVM_INCLUDE_BENCHMARKS
=
OFF
-
DLLVM_BUILD_BENCHMARKS
=
OFF
-
DLLVM_ENABLE_DUMP
=
ON
cmake
-
-
build .
/
build_dyn_x32
-
j
4
cmake
-
DCMAKE_INSTALL_PREFIX
=
"C:\Program Files\LLVM\llvm12\llvm12_dyn_x32"
-
P .\build_dyn_x32\cmake_install.cmake
|
运行 bat 文件即可编译对应的 llvm
编译安装完成之后可以在下面两个目录中找到编译好的clang 文件
1
2
|
C:\Program Files\LLVM\llvm12\llvm12_dyn_x64
C:\Program Files\LLVM\llvm12\llvm12_dyn_x32
|
C:\msys64\mingw64\bin
去寻找,并且复制到C:\Program Files\LLVM\llvm12\llvm12_dyn_x64\bin
中
1
2
3
4
|
libstdc
+
+
-
6.dll
libgcc_s_seh
-
1.dll
libwinpthread
-
1.dll
zlib1.dll
|
C:\msys64\mingw32\bin
去寻找,并且复制到C:\Program Files\LLVM\llvm12\llvm12_dyn_x32\bin
中
1
2
3
4
|
libstdc
+
+
-
6.dll
libgcc_s_dw2
-
1.dll
(这个库名称不一样)
libwinpthread
-
1.dll
zlib1.dll
|
C:\Users\admin\Documents\llvmProject12\build_dyn_x32\lib
或者C:\Users\admin\Documents\llvmProject12\build_dyn_x64\lib
中,将所有a文件添加到对应目录下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
project(mydemo)
cmake_minimum_required(VERSION
3.10
)
if
(NOT DEFINED ENV{LLVM_HOME})
# User must define the LLVM_HOME environment that point to the root installation dir of llvm
message(FATAL_ERROR
"Environment variable $LLVM_HOME is not defined, user should define it before running cmake!"
)
endif()
message(STATUS
"LLVM_HOME = [$ENV{LLVM_HOME}]"
)
if
(NOT DEFINED ENV{LLVM_DIR})
# Default llvm config file path
set
(ENV{LLVM_DIR} $ENV{LLVM_HOME}
/
lib
/
cmake
/
llvm)
endif()
# Check the path
if
(NOT EXISTS $ENV{LLVM_DIR})
message(STATUS
"Path ($ENV{LLVM_DIR}) not found!"
)
# If default llvm config path not found, try this one,
# which is config with [-DLLVM_LIBDIR_SUFFIX=64] before building llvm
set
(ENV{LLVM_DIR} $ENV{LLVM_HOME}
/
lib64
/
cmake
/
llvm)
if
(NOT EXISTS $ENV{LLVM_DIR})
message(FATAL_ERROR
"Path ($ENV{LLVM_DIR}) not found!"
)
else
()
message(STATUS
"Path ($ENV{LLVM_DIR}) found!"
)
endif()
else
()
message(STATUS
"Path ($ENV{LLVM_DIR}) found!"
)
endif()
# Enable verbose output for debug,
# Same as: cmake -D CMAKE_VERBOSE_MAKEFILE=ON or make VERBOSE=1
# set(CMAKE_VERBOSE_MAKEFILE on)
find_package(LLVM REQUIRED CONFIG)
add_definitions(${LLVM_DEFINITIONS})
include_directories(${LLVM_INCLUDE_DIRS})
link_directories(${LLVM_LIBRARY_DIRS})
# Debug
message(STATUS
"LLVM_DEFINITIONS : ${LLVM_DEFINITIONS}"
)
message(STATUS
"LLVM_INCLUDE_DIRS : ${LLVM_INCLUDE_DIRS}"
)
message(STATUS
"LLVM_LIBRARY_DIRS : ${LLVM_LIBRARY_DIRS}"
)
add_library(mydemo SHARED
# Add your source file here, header file is not neccessary
.
/
src
/
mydemo.cpp
)
# Use C++11 to compile your pass (i.e., supply -std=c++11).
target_compile_features(mydemo PRIVATE cxx_range_for cxx_auto_type)
include_directories(.
/
include)
# LLVM is (typically) built with no C++ RTTI. We need to match that;
# otherwise, we'll get linker errors about missing RTTI data.
set_target_properties(mydemo PROPERTIES COMPILE_FLAGS
"-fno-rtti"
)
# Get proper shared-library behavior (where symbols are not necessarily
# resolved when the shared library is linked) on OS X.
if
(APPLE)
set_target_properties(mydemo PROPERTIES LINK_FLAGS
"-undefined dynamic_lookup"
)
endif(APPLE)
target_link_libraries(mydemo
libLLVMCore.dll.a
libLLVMSupport.dll.a
libLLVMipo.dll.a
libLLVMDemangle.dll.a
libLLVMTransformUtils.dll.a
libLLVMAnalysis.dll.a
libpthread.a
)
|
3 . bat文件的内容如下(x86 就是将前面的环境设置为x86的即可):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
cd C:\Users\admin\Documents\llvmProject\ollvm
+
+
::
Set
MSYS2 env
set
PATH
=
%
PATH
%
;C:\msys64\mingw64\
bin
::
Set
LLVM_HOME
set
LLVM_HOME
=
%
PROGRAMFILES
%
/
LLVM
/
llvm12
/
llvm12_dyn_x64
set
CC
=
%
LLVM_HOME
%
/
bin
/
clang.exe
set
CXX
=
%
LLVM_HOME
%
/
bin
/
clang
+
+
.exe
set
OPT
=
%
LLVM_HOME
%
/
bin
/
opt.exe
set
LLC
=
%
LLVM_HOME
%
/
bin
/
llc.exe
rd
/
Q
/
S .\Build
:: Build release version
cmake
-
S .
/
Transforms
-
B .
/
Build
-
DCMAKE_BUILD_TYPE
=
Release
-
DLLVM_ENABLE_ASSERTIONS
=
ON
-
G
"MinGW Makefiles"
:: Build debug version
:: cmake
-
S .
/
Transforms
-
B .
/
Build
-
DCMAKE_BUILD_TYPE
=
Debug
-
DLLVM_ENABLE_ASSERTIONS
=
ON
:: Build project
cmake
-
-
build .
/
Build
-
j
4
copy .\Build\libmypass.dll .\
Bin
\libmypassx64.dll
"%CC%"
-
Xclang
-
load
-
Xclang .\
Bin
\libmypassx64.dll .\TestProgram\TestProgram.cpp
-
o .\TestProgram\
Bin
\TestProgram.exe
::
/
D LLVM
-
mrdrnd
-
Xclang
-
load
-
Xclang
"C:\\Users\\admin\\Desktop\\Work\\ollvm++\\Build\\libmypass.dll"
.\TestProgram\
Bin
\TestProgram.exe flag{s1mpl3_11vm_d3m0}
|
4 . TestProgram.cpp的内容,是一道简单的re逆向题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#include <cstdio>
#include <cstring>
char
input
[
100
]
=
{
0
};
char enc[
100
]
=
"\x86\x8a\x7d\x87\x93\x8b\x4d\x81\x80\x8a\
\x43\x7f\x49\x49\x86\x71\x7f\x62\x53\x69\x28\x9d";
void encrypt(unsigned char
*
dest, char
*
src){
int
len
=
strlen(src);
for
(
int
i
=
0
;i <
len
;i
+
+
){
dest[i]
=
(src[i]
+
(
32
-
i)) ^ i;
}
}
/
/
flag{s1mpl3_11vm_d3m0}
int
main(
int
_argc, char
*
_argv[]){
/
/
scanf(
"%s"
,
input
);
if
(_argc <
=
1
){
return
0
;
}
strcpy(
input
,_argv[
1
]);
printf(
"Please input your flag: %s\n"
,
input
);
unsigned char dest[
100
]
=
{
0
};
encrypt(dest,
input
);
bool
result
=
strlen(
input
)
=
=
22
&& !memcmp(dest, enc,
22
);
if
(result){
printf(
"Congratulations~\n"
);
}
else
{
printf(
"Sorry try again.\n"
);
}
}
|
5 . 配置好之后,直接运行bat文件就能编译测试:
我使用的是vs 2019,在之前下载了llvm 12.0 ,并且我们编译替换成自己的,做好准备工作之后,只需要在命令行选项中加入调用语句即可。
1
|
-
Xclang
-
load
-
Xclang
"C:\\Users\\admin\\Desktop\\Work\\ollvm++\\Build\\libmypass.dll"
|
使用前还需要将平台工具集先改了
更多【 在 Windows下搭建LLVM 使用环境】相关视频教程:www.yxfzedu.com