WINDOWS+CMAKE+VS2017编译OLLVM并整合到VS2017 NDK

        OLLVM全称Obfuscator-LLVM,即基于LLVM框架的源码级别混淆工具,相比机器指令混淆,源码级别混淆无需关心底层指令差异(由编译器生成),因而更具兼容性和拓展性,对程序流程的控制更为全面,同时也易于理论研究的展开。

        本文编译的OLLVM来自Github上的开源项目https://github.com/Qrilee/Obfuscator-LLVM,作者博文https://qtfreet.com/?p=313,该框架基于LLVM 6.0,结合 Ollvm 上海交通大学密码与计算机安全实验室维护的Armariris,支持指令替换、控制流伪造、平展以及字符串混淆等;本文编译环境Windows 10 x64 + VS2017 + CMake

        首先使用CMake生成VS的项目文件,基本没什么问题,但是需要注意的是llvmbuild需要Python 2.x,如果你只有或CMake优先选择了Python 3.x,则会导致以下错误:

ModuleNotFoundError: No module named 'llvmbuild'

        此时手动指定PYTHON_EXECUTABLE变量地址即可。另外由于CMake的VS生成器默认使用x86编译器,建议指定-Thost=x64,否则你可能会遇到以下警告:

Visual Studio generators use the x86 host compiler by default, even for64-bit targets.  This can result in linker instability and out of memoryerrors.  To use the 64-bit host compiler, pass -Thost=x64 on the CMakecommand line.

WINDOWS+CMAKE+VS2017编译OLLVM并整合到VS2017 NDK_第1张图片

        打开生成好VS项目,生成解决方案,然后等就是了,LLVM比较庞大,把TEST、DOC、EXAMPLE之类的东西全部取消勾选,只保留ARM、AARCH64、X86等几个target,也有187个项目,需要点时间,最后生成的东西在目录build\release\下面。

        其中有两个项目LLVMObfuscation和LLVMipo会编译失败,看错误源llvm/CryptoUtils.h是大小端未指定造成的(根源是VS中并不会定义__x86_64__),看来生成的项目似乎有点问题,不过问题不大,把__x86_64__加到上述项目的预处理器定义即可。

        此外CryptoUtils.cpp的CryptoUtils::prng_seed并未提供windows版本,对此我发了patch,可以在这里https://github.com/rrrfff/Obfuscator-LLVM/blob/master/lib/Transforms/Obfuscation/CryptoUtils.cpp找到。

        到此就能成功编译出OLLVM了,跑下clang --version应该能得到以下输出:

Obfuscator-LLVM clang version 6.0.0 (trunk) (based on Obfuscator-LLVM 6.0.0)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: E:\android-ndk\r13b\toolchains\llvm\prebuilt\windows-x86_64\bin

  Registered Targets:
    aarch64    - AArch64 (little endian)
    aarch64_be - AArch64 (big endian)
    arm        - ARM
    arm64      - ARM64 (little endian)
    armeb      - ARM (big endian)
    thumb      - Thumb
    thumbeb    - Thumb (big endian)
    x86        - 32-bit X86: Pentium-Pro and above

        为了让VS2017能使用上OLLVM,我们需要拷贝到NDK目录的相应目录,然后新建一个工具链,但是其实OLLVM完全具备LLVM的全套功能,所以更简单的做法是直接替换原有的llvm。以NDK 13b为例,把目录build\release\下面的东西替换到E:\android-ndk\r13b\toolchains\llvm\prebuilt\windows-x86_64\目录下即可。

        随便打开一个Android项目,把编译工具切换到Clang,测试编译,发现找不到jni.h,和之前切换到NDK r14b的现象一致,应该是VS不支持导致的,深究发现是clang对于clang @tmp.rsp形式传入的参数,如果rsp文件中的路径被引号包括,其中的\就会被转义,导致路径出错,解决方案就是自己写一个clang替换,在里面把路径中的\替换成\\,然后传递给真正的clang即可。

        默认情况下,混淆是关闭的,行为和普通编译器一致,开启混淆有两种方式,一种是追加命令行(前缀-mllvm),如-mllvm -sub -mllvm -sub_loop=3 -mllvm -bcf -mllvm -bcf_loop=3 -mllvm -bcf_prob=40 -mllvm -fla -mllvm -split -mllvm -sobf,另一种是 函数属性声明。

你可能感兴趣的:(C/C++,Windows,Android)