LLVM

llvm学习日记十四:Xcode 调试开发 Pass

2021-09-15  本文已影响0人  鸣人的大哥

参考:https://mayuyu.io/2017/06/01/LLVMHacking-0x1/

一、目的:

使用xcode更方便的调试和开发pass

二、创建llvm的xcode工程:

cmake指定生成xcode工程之前,先创建一个新的空的pass,然后在cmake生成xcode工程,在xcode项目中可以看到新模块,我使用的版本是llvm9.0.0

  1. 创建空文件:
  1. cmake指定xcode工程:
mkdir build_xcode
cd build_xcode
cmake -G Xcode CMAKE_BUILD_TYPE="Debug" ../llvm
  1. 打开xcode工程:

三、pass的调试与开发:

  1. 完善头文件与cpp文件内容,我这里参考张总的教程,创建一个简单符号混淆的pass

#include "llvm/Pass.h"

#define DEBUG_TYPE "symbolobf"

namespace llvm {
    ModulePass* createSymbolObfuscationPass();
//    void initializeSymbolObfuscationPass(PassRegistry &Registry);
}


#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/Obfuscation/SymbolObfuscation.h"
#include <string>
#include <iostream>
#include <cstdlib>

using namespace llvm;
using namespace std;
static string obfcharacters="qwertyuiopasdfghjklzxcvbnm1234567890";
namespace llvm{
    struct SymbolObfuscation : public ModulePass {
        static char ID;
        int seed = 0;
        SymbolObfuscation() : ModulePass(ID) {}
        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 name;
        }
        bool runOnModule(Module &M) override {
            //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()<<" --> New Name: "<<newname<<"\n";
                    F.setName(newname);
                }
                else{
                    errs()<<"Skipping External Function: "<<F.getName()<<"\n";
                }
            }
            
            return true;
        }
    };
    ModulePass * createSymbolObfuscationPass() {return new SymbolObfuscation();}
}

char SymbolObfuscation::ID = 0;
//INITIALIZE_PASS(SymbolObfuscation, "symbolobf", "Rewrite Symbols",
//                false, false)
static RegisterPass<SymbolObfuscation> X("symbolobf", "Rewrite Symbols", false, false);

  1. 单独调试这一个pass需要使用opt模块调用:

输入的 .ll 文件时自己写的一个测试代码,如下:

#include <stdio.h>

static int add(int x, int y) {
    return x + y;
}

int sub(int x, int y) {
    return x - y;
}

int main(){
    printf("%d",add(3,4));
    printf("%d",sub(5,4));
    return 0;
}

生成 .ll 文件:
clang -c test_symbolobf.c -o test_symbolobf.ll -emit-llvm -S

  1. 查看符号替换的结果:

四、扩展:

符号混淆是一个比较难处理的点,涉及系统函数以及导出函数,所以 hikari 也并没有开放这个功能,作为学习还不错;
现在 llvm 在utils目录下有自带的 SymbolRewriter.cpp Pass,下一节章节分析一下。

上一篇 下一篇

猜你喜欢

热点阅读