iOS一点通LLVM

LLVM 进阶一:符号混淆(LTO)

2021-11-16  本文已影响0人  鸣人的大哥

更新:编译参数添加对静态库的说明
二次更新:实际业务中意义不是很大

一、目的:

实现链接时符号混淆
参考文档:
https://llvm.org/docs/LinkTimeOptimization.html
https://mayuyu.io/2017/06/01/LLVMHacking-0x1/#more

二、思路:

三、实现流程:

从这篇文章开始基于LLVM13.0,pass的注册与实现不同于以前的版本,反复折腾,QAQ;

1、pass代码:
不再使用runOnModule实现,我参考了 StripSymbols.cpp 的实现方式,官方在老的pass里加入了新的pass流程,官方都支持,我这里使用了新的pass调用方式,如下:

#include "llvm/IR/PassManager.h"
namespace llvm {
    struct SymbolObfuscationPass : PassInfoMixin<SymbolObfuscationPass> {
      PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
    };
}

#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/SymbolObfuscation/SymbolObfuscation.h"
#include <string>
#include <iostream>
#include <cstdlib>

using namespace llvm;
using namespace std;

static string obfcharacters="-_.|/\\`+,=()*:";

int seed = 0;
string randomString(int length){
    string name;
    name.resize(length);
    srand(seed);
    seed++;
    for(int i=0;i<length;i++){
        name[i]=obfcharacters[rand()%(obfcharacters.length())];
    }
    return "f_" + name;
}

PreservedAnalyses SymbolObfuscationPass::run(Module &M, ModuleAnalysisManager &AM) {
    //F.setName(randomString(16));
    errs()<<"Start Symbol Rewrite!\n";
    for(Module::iterator Fun=M.begin();Fun!=M.end();Fun++){
        Function &F=*Fun;
        if (F.getName().str().compare("main")==0){
            errs()<<"Skipping main\n";
        }
        else if(F.empty()==false){
            //Rename
            string newname = randomString(16);
            errs()<<"Renaming Function: "<<F.getName()<<"\n";
            errs()<<"New Function Name: "<<newname<<"\n";
            F.setName(newname);
        }
        else{
            errs()<<"Skipping External Function: "<<F.getName()<<"\n";
        }
    }
  return PreservedAnalyses::all();
}

2、如何添加该pass:
llvm/LTO/LTOBackend.cpp文件添加,选择在这里添加是因为我们的目的是实现链接时优化。

四、测试:

确保原始ios项目运行没问题后,只需要添加几个参数即可使用,替换掉xcode的clang就可以了
1、xcode添加编译参数:

2、xcode添加链接参数:


image.png

3、编译,首先查看链接日志如下,说明链接时pass执行成功了:

image.png

4、自测运行该app正常,二进制包大小也没有变化:
没有做过批量测试
5、nm查看二进制符号如下:


image.png
上一篇下一篇

猜你喜欢

热点阅读