Windows下LLVM6.0集成并编译OLLVM中的Obfuscator的各个pass

参考

参考上一节《LLVM在Windows下使用VisualStudio2017编译pass - 朱皮特个人博客》,上次是创建的很简单的pass,但是有了这个基础,再集成和创建复杂点的pass就轻松一点,这次集成开源的OLLVMArmariris的各个pass。

据说Armariris是在OLLVM基础上修改的,想必代码会有改进吧,所以我们优先使用Armariris的pass,如果没有的在使用OLLVM的pass。后面不区分Armariris和OLLVM,后简称参考源码。

GitHub上打开后,直接找到lib/Transforms/Obfuscation目录下,可以看到大概有四个混淆作用的pass:

pass作用
BogusControlFlow虚假控制流程
StringObfuscation字符串混淆
Flattening扁平化
Substitution指令替换

下面开始详细解释步骤。

步骤1 创建头文件

在本地LLVM源码目录include/llvm/Transforms下创建一个Obfuscator文件夹,用来做为头文件引用。

GitHub上下载参考源码的这些.h文件:
- StringObfuscation.h
- Substitution.h
- Flattening.h
- BogusControlFlow.h
- Utils.h
- CryptoUtils.h

其中CryptoUtils.h文件,参考源码是放在include/llvm目录下的,个人觉得不是很合理,把它按上面的组织结构存放了,当然后面引用该头文件的地方要相应地修改为:

#include "llvm/Transforms/Obfuscator/CryptoUtils.h"

可以想象,原作者这么组织的本意是把CryptoUtils作为一个通用的模块来调用,不只是混淆的pass,否则在别的地方(不在pass中)按上述方法包含头文件就感觉很奇怪。但是,经过实际搜索代码发现,也只有这些pass使用了该头文件,为了保持修改的变动最小化,所以我就按上面的方式组织了。

然后创建一个自己的头文件Obfuscator.h,主要来管理其他混淆pass,内容如下:

#pragma once

//管理多个混淆pass
#include "Utils.h"
#include "Substitution.h"
#include "StringObfuscation.h"
#include "Flattening.h"
#include "BogusControlFlow.h"
#include "llvm/IR/LegacyPassManager.h"

namespace llvm {
    // 在里面创建其他多个pass
    FunctionPass *createObfuscatorPasses(bool flag);

    //必须放在llvm命名空间下
    void initializeFlatteningPass(PassRegistry&);
    void initializeSubstitutionPass(PassRegistry&);
    void initializeBogusControlFlowPass(PassRegistry&);
    void initializeStringObfuscationPassPass(PassRegistry&);
}

修改include/llvm/InitializePasses.h,在llvm命名空间中声明函数:

void initializeObfuscator(PassRegistry&);

修改include/llvm/LinkAllPasses.h,添加代码:

#include "llvm/Transforms/Obfuscator/Obfuscator.h"
……
(void) llvm::createObfuscatorPasses(true);

步骤2 创建源文件

本地LLVM源码目录lib/Transforms下创建一个Obfuscator文件夹,用以包含其他的混淆pass。

GitHub上下载参考源码的这些CPP文件:
- StringObfuscation.cpp
- Substitution.cpp
- Flattening.cpp
- BogusControlFlow.cpp
- Utils.cpp
- CryptoUtils.cpp

然后创建一个自己的源码文件Obfuscator.cpp,主要来管理其他混淆pass,内容如下:

#include "llvm/Transforms/Obfuscator/Obfuscator.h"

#include "llvm/InitializePasses.h"
#include "llvm-c/Initialization.h"
#include "llvm/InitializePasses.h"
#include "llvm/PassRegistry.h"
using namespace llvm;

// initializeObfuscator - Initialize all passes in the Custom library
void llvm::initializeObfuscator(PassRegistry &Registry) {
    initializeSubstitutionPass(Registry);
    initializeFlatteningPass(Registry);
    initializeStringObfuscationPassPass(Registry);
    initializeBogusControlFlowPass(Registry);
}

FunctionPass *llvm::createObfuscatorPasses(bool flag) {
    createFlattening(flag);
    createStringObfuscation(flag);
    createSubstitution(flag);
    createBogus(flag);
    return NULL;
}

创建CMakeLists.txt,内容如下:

# If we don't need RTTI or EH, there's no reason to export anything
# from the Obfuscator plugin.


add_llvm_library(LLVMObfuscator
  Obfuscator.cpp
  CryptoUtils.cpp
  StringObfuscation.cpp
  Substitution.cpp
  Flattening.cpp
  BogusControlFlow.cpp
  Utils.cpp
  )

add_dependencies(LLVMObfuscator intrinsics_gen)

创建LLVMBuild.txt(原参考只有Makefile,不适用),内容如下:

[component_0]
type = Library
name = Obfuscator
parent = Transforms
library_name = Obfuscator

步骤3 修改混淆pass源码

每个pass的CPP中头文件包含添加:

#include "llvm/Transforms/Obfuscator/Obfuscator.h"

把对CryptoUtils.h的头文件包含代码修改为:

#include "llvm/Transforms/Obfuscator/CryptoUtils.h"

把源代码:

static RegisterPass<Flattening> X("flattening", "Call graph flattening");
static RegisterPass<BogusControlFlow> X("boguscf", "inserting bogus control flow");
static RegisterPass<StringObfuscationPass> X("GVDiv", "Global variable (i.e., const char*) diversification pass", false, true);
static RegisterPass<Substitution> X("substitution", "operators substitution");

替换为:

INITIALIZE_PASS(Flattening, "flattening", "Call graph flattening", false, false)
INITIALIZE_PASS(BogusControlFlow, "boguscf", "inserting bogus control flow", false, false)
INITIALIZE_PASS(StringObfuscationPass, "GVDiv", "Global variable (i.e., const char*) diversification pass", false, true)
INITIALIZE_PASS(Substitution, "substitution", "operators substitution", false, false)

之前是LLVM4.0,现在LLVM6.0要换种写法。

步骤4 把混淆pass添加到主工程

  • lib/Transforms/CMakeLists.txt内容追加:
add_subdirectory(Obfuscator)
  • lib/Transforms/LLVMBuild.txt的subdirectories字段添加Obfuscator

  • tools/bugpoint/CMakeLists.txt内容添加:Obfuscator

  • tools/bugpoint/LLVMBuild.txt内容添加:Obfuscator
  • tools/opt/CMakeLists.txt内容添加:Obfuscator
  • tools/opt/LLVMBuild.txt内容添加:Obfuscator
  • tools/opt/opt.cpp的main函数添加调用代码:
initializeObfuscator(Registry);

然后用CMakeGUI重新生成一下VisualStudio的工程,因为有缓存所以比较快。

步骤5 编译

VisualStudio2017重新加载解决方案,只编译opt,大约半个多小时,最终成功编译opt,命令:opt -help查看,发现有这些pass:

-GVDiv          - Global variable (i.e., const char*) diversification pass

-boguscf        - inserting bogus control flow

-substitution   - operators substitution

-flattening     - Call graph flattening

说明集成成功了。

集成到clang

完成上面的步骤,可以把pass集成到opt中,但是如果使用clang的话是没有这些功能的,所以仍需要做些处理。
- llvm/lib/Transforms/IPO/PassManagerBuilder.cpp

#include "llvm/Transforms/Obfuscator/Obfuscator.h"

static cl::opt<bool>
StringObfuscationPass("GVDiv", cl::init(false), cl::Hidden,
    cl::ZeroOrMore, cl::desc("Global variable (i.e., const char*) diversification pass"));

static cl::opt<bool>
Flattening("flattening", cl::init(false), cl::Hidden,
    cl::ZeroOrMore, cl::desc("Call graph flattening"));

static cl::opt<bool>
Substitution("substitution", cl::init(false), cl::Hidden,
    cl::ZeroOrMore, cl::desc("operators substitution"));

static cl::opt<bool>
BogusControlFlow("boguscf", cl::init(false), cl::Hidden,
    cl::ZeroOrMore, cl::desc("inserting bogus control flow"));

在PassManagerBuilder::populateModulePassManager函数中添加:

MPM.add(createFlattening(Flattening));
MPM.add(createStringObfuscation(StringObfuscationPass));
MPM.add(createSubstitution(Substitution));
MPM.add(createBogus(BogusControlFlow));

这里设计的是一个开关,当用户使用了-mllvm -GVDiv参数的时候,StringObfuscationPass为true,相当于启用了该pass。

  • llvm/lib/Transforms/IPO/LLVMBuild.txt添加Obfuscator
  • llvm/lib/Target/X86/LLVMBuild.txt添加Obfuscator

最后记住用CMkaeGUI重新生成一下解决方案,然后VisualStudio只编译clang模块即可。

使用clang时开启该pass:

clang.exe -mllvm -GVDiv example.c -o example.exe

其他

编译错误解决

tools/opt/opt.cpp在编译中出现错误:

error C2668 llvm::make_unique

修改代码:

BOS = make_unique<raw_svector_ostream>(Buffer);

添加命名空间llvm调用:

BOS = llvm::make_unique<raw_svector_ostream>(Buffer);
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

asmcvc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值