NDK集成OLLVM模块流程记录




集成流程


具体的编译NDK的LLVM的流程可参考文章:编译NDK特定的LLVM版本的流程记录https://bbs.kanxue.com/thread-277727.htm

获取 ollvm 混淆部分代码:https://github.com/isrc-cas/flounder

1.复制混淆部分 pass 到 llvm12 中:
flounder/llvm/include/llvm/Transforms/Obfuscation -> toolchain/llvm-project/llvm/include/llvm/Transforms/Obfuscation
flounder/llvm/lib/Transforms/Obfuscation -> toolchain/llvm-project/llvm/lib/Transforms/Obfuscation


2.添加下面这行到 llvm-projectllvmlibTransformsCMakeLists.txt 的第13行:
add_subdirectory(Obfuscation)


NDK集成OLLVM模块流程记录


3.添加下面这行到 llvm-projectllvmlibTransformsIPOCMakeLists.txt 的 73 行:
Obfuscation


NDK集成OLLVM模块流程记录

4.在llvm-projectllvmlibTransformsIPOPassManagerBuilder.cpp导入头文件:
#include "llvm/Transforms/Obfuscation/BogusControlFlow.h"#include "llvm/Transforms/Obfuscation/Flattening.h"#include "llvm/Transforms/Obfuscation/Split.h"#include "llvm/Transforms/Obfuscation/Substitution.h"#include "llvm/Transforms/Obfuscation/CryptoUtils.h"#include "llvm/Transforms/Obfuscation/StringObfuscation.h"


NDK集成OLLVM模块流程记录

在同一个文件的第 93 行:
// Flags for obfuscationstatic cl::opt<std::string> Seed("seed", cl::init(""), cl::desc("seed for the random"));static cl::opt<std::string> AesSeed("aesSeed", cl::init(""), cl::desc("seed for the AES-CTR PRNG"));static cl::opt<bool> StringObf("sobf", cl::init(false), cl::desc("Enable the string obfuscation"));  static cl::opt<bool> Flattening("fla", cl::init(false), cl::desc("Enable the flattening pass"));static cl::opt<bool> BogusControlFlow("bcf", cl::init(false), cl::desc("Enable bogus control flow"));static cl::opt<bool> Substitution("sub", cl::init(false), cl::desc("Enable instruction substitutions"));static cl::opt<bool> Split("split", cl::init(false), cl::desc("Enable basic block splitting"));// Flags for obfuscation


NDK集成OLLVM模块流程记录

在同一个文件的第 569 行:
//obfuscation related passMPM.add(createSplitBasicBlockPass(Split));MPM.add(createBogusPass(BogusControlFlow));MPM.add(createFlatteningPass(Flattening));MPM.add(createStringObfuscationPass(StringObf));MPM.add(createSubstitutionPass(Substitution));


NDK集成OLLVM模块流程记录


5.在llvm-projectllvmlibTransformsObfuscationStringObfuscation.cpp文件:
NDK集成OLLVM模块流程记录


在第 15 行加入:
#include "llvm/IR/Instructions.h"


NDK集成OLLVM模块流程记录

在同一个文件的第 174 处(共三处地方):
LoadInst *ptr_19 = new LoadInst(gvar->getType()->getArrayElementType(),                                gvar, "", false, label_for_body);ptr_19->setAlignment(Align(8));...LoadInst* int8_20 = new LoadInst(ptr_arrayidx->getType()->getArrayElementType(), ptr_arrayidx, "", false, label_for_body);int8_20->setAlignment(Align(1));...void_21->setAlignment(Align(1));


NDK集成OLLVM模块流程记录


6.在llvm-projectllvmlibTransformsObfuscationSubstitution.cpp文件的第 215 行:
// Implementation of a = -(-b + (-c))void Substitution::addDoubleNeg(BinaryOperator *bo) {  BinaryOperator *op, *op2 = NULL;  UnaryOperator *op3, *op4;  if (bo->getOpcode() == Instruction::Add) {    op = BinaryOperator::CreateNeg(bo->getOperand(0), "", bo);    op2 = BinaryOperator::CreateNeg(bo->getOperand(1), "", bo);    op = BinaryOperator::Create(Instruction::Add, op, op2, "", bo);    op = BinaryOperator::CreateNeg(op, "", bo);    bo->replaceAllUsesWith(op);    // Check signed wrap    //op->setHasNoSignedWrap(bo->hasNoSignedWrap());    //op->setHasNoUnsignedWrap(bo->hasNoUnsignedWrap());  } else {    op3 = UnaryOperator::CreateFNeg(bo->getOperand(0), "", bo);    op4 = UnaryOperator::CreateFNeg(bo->getOperand(1), "", bo);    op = BinaryOperator::Create(Instruction::FAdd, op3, op4, "", bo);    op3 = UnaryOperator::CreateFNeg(op, "", bo);    bo->replaceAllUsesWith(op3);  }  }


NDK集成OLLVM模块流程记录


在第 319 行(原 299 行)修改 Substitution::subNeg 函数:
// Implementation of a = b + (-c)void Substitution::subNeg(BinaryOperator *bo) {  BinaryOperator *op = NULL;    if (bo->getOpcode() == Instruction::Sub) {    op = BinaryOperator::CreateNeg(bo->getOperand(1), "", bo);    op = BinaryOperator::Create(Instruction::Add, bo->getOperand(0), op, "", bo);    // Check signed wrap    //op->setHasNoSignedWrap(bo->hasNoSignedWrap());    //op->setHasNoUnsignedWrap(bo->hasNoUnsignedWrap());  } else {    auto op1 = UnaryOperator::CreateFNeg(bo->getOperand(1), "", bo);    op = BinaryOperator::Create(Instruction::FAdd, bo->getOperand(0), op1, "", bo);  }  bo->replaceAllUsesWith(op);}


NDK集成OLLVM模块流程记录


7.在文件llvm-projectllvmlibTransformsObfuscationBogusControlFlow.cpp文件 380 添加:
UnaryOperator *op2;


NDK集成OLLVM模块流程记录

在同一个文件的 422 行:
case 1: op2 = UnaryOperator::CreateFNeg(i->getOperand(0),*var,&*i);


NDK集成OLLVM模块流程记录

在同一个文件的 573 行:
opX = new LoadInst (x->getType()->getElementType(), (Value *)x, "", (*i));opY = new LoadInst (x->getType()->getElementType(), (Value *)y, "", (*i));


NDK集成OLLVM模块流程记录

在文件 llvm-projectllvmincludellvmInitializePasses.h 的第 453 行添加:
void initializeFlatteningPass(PassRegistry&);


NDK集成OLLVM模块流程记录


在文件 llvm-projectllvmlibTransformsObfuscationFlattening.cpp 的 17 行添加:
#include "llvm/InitializePasses.h"


NDK集成OLLVM模块流程记录


在相同文件的 123 修改:
load = new LoadInst(switchVar->getType()->getElementType(), switchVar, "switchVar", loopEntry);


NDK集成OLLVM模块流程记录

在相同文件的 239 修改:
NDK集成OLLVM模块流程记录




混淆效果


Android.mk的参数配置(全局):

LOCAL_CFLAGS += -mllvm -bcf -mllvm -bcf_loop=4 -mllvm -bcf_prob=100 -mllvm -sub -mllvm -sub_loop=2 -mllvm -fla -mllvm -sobf -mllvm -split

指定函数(局部):

int binaryInsertionSort() __attribute((__annotate__(("bcf"))));

CMakeLists.txt的参数配置(全局):

set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mllvm -sub -mllvm -sobf -mllvm -fla ")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mllvm -sub -mllvm -sobf -mllvm -fla")

set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -mllvm -sub -mllvm -sobf -mllvm -fla" )
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mllvm -sub -mllvm -sobf -mllvm -fla" )

指定函数混淆(局部):

__attribute((__annotate__("bcf")))
__attribute((__annotate__("fla")))
__attribute((__annotate__("sub")))
__attribute((__annotate__("split")))
__attribute((__annotate__("sobf")))
void binaryInsertionSort(int arr[], int n) {}

混淆效果:

NDK集成OLLVM模块流程记录

NDK集成OLLVM模块流程记录





总结


这里只是参考网上的帖子对 ollvm 整个源码下载,到编译集成到特定的 NDK 版本的过程做一个学习记录,但具体每个 pass 的性能、具体的防护效果、以及可能存在的问题在这里是暂还没深入考究,这个系列待后续继续待补充完善。


参考资料

https://github.com/0x3f97/ollvm-12.x
https://github.com/yangyiyu08/ollvm-project
https://android.googlesource.com/toolchain/llvm-project


NDK集成OLLVM模块流程记录


看雪ID:blx2024

https://bbs.kanxue.com/user-home-928718.htm

*本文为看雪论坛优秀文章,由 blx2024 原创,转载请注明来自看雪社区

NDK集成OLLVM模块流程记录


# 往期推荐

1、ELF文件脱壳纪事

2、Glibc-2.35下对tls_dtor_list的利用详解

3、对旅行APP的检测以及参数计算分析【Simplesign篇】

4、2023强网杯warmup题解

5、Directory Opus 13.2 逆向分析

6、Pwn-oneday题目解析


NDK集成OLLVM模块流程记录

NDK集成OLLVM模块流程记录

球分享

NDK集成OLLVM模块流程记录

球点赞

NDK集成OLLVM模块流程记录

球在看



NDK集成OLLVM模块流程记录

点击阅读原文查看更多

原文始发于微信公众号(看雪学苑):NDK集成OLLVM模块流程记录

版权声明:admin 发表于 2024年3月15日 下午6:29。
转载请注明:NDK集成OLLVM模块流程记录 | CTF导航

相关文章