macOS安装调试llvm入门

admin 2020年12月30日02:32:30评论63 views字数 12951阅读43分10秒阅读模式

macOS安装调试llvm入门

本文为看雪论优秀文章

看雪论坛作者ID:新萌



题目出自3W班9月第一题:编译llvm,动态调试Pass报告。老师的课件不是基于macos的,所以这篇文章算是自己踩坑之后的一个学习记录。


macOS安装调试llvm入门

下载llvm源码

macOS安装调试llvm入门


# 查看你的Android ndk版本$ ./clang -vAndroid (6454773 based on r365631c2) clang version 9.0.8 (https://android.googlesource.com/toolchain/llvm-project 98c855489587874b2a325e7a516b99d838599c6f) (based on LLVM 9.0.8svn)Target: x86_64-apple-darwin19.6.0Thread model: posixInstalledDir: /Volumes/Work/SDK/AndroidSDK/ndk/21.3.6528147/toolchains/llvm/prebuilt/darwin-x86_64/bin/.# 下载依赖$ brew install cmake zlib ninja# 可以看到版本是clang version 9.0.8,所以我们去github寻找差不多的版本下载,这里我们找到了9.0.1,下载它# 从这个地址下载源码:$ https://github.com/llvm/llvm-project/releases# 下载好后用clion打开项目,然后找到llvm文件夹中的CMakelist.txt双击打开,按照clion提示,点击同步# clion-preferences-build,execution,deployment-cmake对debug与release设置cmake options-G Ninja -DLLVM_ENABLE_PROJECTS="clang"# 等待同步完成后,跳转到cmake-build-debug文件夹$ ninja -j8



macOS安装调试llvm入门

写第一个demo

macOS安装调试llvm入门

打开clion新建一个项目,先写一个demo:
# main.c#include <stdio.h> void test(){    printf("this is Test!n");} void test01(){    printf("test01n");}int main() {    test();    test01();    return 0;}

尝试用你编译出来的clang来编译这个demo:
# 配置clang地址$ export PATH=/Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug/bin/:$PATH# 尝试编译$ clang main.cpp -o main_clang

编译报错:
$ clang main.cpp -o main_clang clang-9: error: no such file or directory: 'main.cpp'clang-9: error: no input files# 解决$ export SDKROOT=$(xcrun --sdk macosx --show-sdk-path)

重新编译:
$ clang main.c -o main_clang$ ./main_clangthis is Test!test01# 生成ll文件$ clang -emit-llvm main.c -S -o main.ll# 生成bc文件$ llvm-as main.ll -o main.bc

macOS安装调试llvm入门

编写第一个llvm pass

macOS安装调试llvm入门


这是介绍:https://llvm.org/docs/WritingAnLLVMPass.html#writing-an-llvm-pass-basiccode


Pass
// /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/lib/Transforms/EncodeFunctionName/EncodeFunctionName.cpp#include "llvm/IR/Function.h"#include "llvm/Pass.h"#include "llvm/Support/raw_ostream.h" #include "llvm/IR/LegacyPassManager.h"#include "llvm/Transforms/IPO/PassManagerBuilder.h" using namespace llvm; namespace llvm {    struct EncodeFunctionName : public FunctionPass {        static char ID; // Pass identification, replacement for typeid        EncodeFunctionName() : FunctionPass(ID) {};         bool runOnFunction(Function &F) override {            errs() << "EncodeFunctionName";            errs().write_escaped(F.getName()) << 'n';            return false;        }    };} char EncodeFunctionName::ID = 0;static RegisterPass<EncodeFunctionName> X("encode", "Hello EncodeFunctionName Pass"); static llvm::RegisterStandardPasses Y(        llvm::PassManagerBuilder::EP_EarlyAsPossible,        [](const llvm::PassManagerBuilder &Builder,           llvm::legacy::PassManagerBase &PM) { PM.add(new EncodeFunctionName()); });

Cmakelists
# /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/lib/Transforms/EncodeFunctionName/CMakeLists.txtadd_llvm_library( LLVMEncodeFunctionName MODULE BUILDTREE_ONLY  EncodeFunctionName.cpp   DEPENDS  intrinsics_gen  PLUGIN_TOOL  opt  )

编译
$ cd /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug$ ninja LLVMEncodeFunctionName

使用opt打印
# opt -load passpath -encode llfile -o bcfile$ opt -load /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug/lib/LLVMEncodeFunctionName.dylib -encode main.ll -o main.bc

加密方法名


// /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/lib/Transforms/EncodeFunctionName/EncodeFunctionName.cpp#include "llvm/IR/Function.h"#include "llvm/Pass.h"#include "llvm/Support/raw_ostream.h" #include "llvm/IR/LegacyPassManager.h"#include "llvm/Transforms/IPO/PassManagerBuilder.h" using namespace llvm; namespace llvm {    struct EncodeFunctionName : public FunctionPass {        static char ID; // Pass identification, replacement for typeid        EncodeFunctionName() : FunctionPass(ID) {};         bool runOnFunction(Function &F) override {            errs() << "EncodeFunctionName: " << F.getName() << " -> ";             if(F.getName().compare("main") !=0){ # 过滤方法名,main方法名不能改,其他方法可以                llvm::MD5 Hasher; # 使用md5算法修改方法名称                llvm::MD5::MD5Result Hash; # 使用md5算法修改方法名称                Hasher.update(F.getName()); # 使用md5算法修改方法名称                Hasher.update("NewFunctionName"); # 使用md5算法修改方法名称                Hasher.final(Hash); # 使用md5算法修改方法名称                 SmallString<32> HexString; # 使用md5算法修改方法名称                llvm::MD5::stringifyResult(Hash, HexString);# 使用md5算法修改方法名称                F.setName(HexString); # 修改方法名称            }            errs().write_escaped(F.getName()) << 'n';            return false;        }    };} char EncodeFunctionName::ID = 0;static RegisterPass<EncodeFunctionName> X("encode", "Hello EncodeFunctionName Pass"); static llvm::RegisterStandardPasses Y(        llvm::PassManagerBuilder::EP_EarlyAsPossible,        [](const llvm::PassManagerBuilder &Builder,           llvm::legacy::PassManagerBase &PM) { PM.add(new EncodeFunctionName()); });


Cmakelists
add_llvm_library( LLVMEncodeFunctionName MODULE BUILDTREE_ONLY  EncodeFunctionName.cpp   DEPENDS  intrinsics_gen  PLUGIN_TOOL  opt  )

编译:
$ cd /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug$ ninja LLVMEncodeFunctionName[2/2] Linking CXX shared module lib/LLVMEncodeFunctionName.dylib

使用
# 配置临时环境变量$ export PATH=/Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug/bin/:$PATH# 查看版本信息$ clang --versionclang version 9.0.1Target: x86_64-apple-darwin19.6.0Thread model: posixInstalledDir: /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug/bin# 编译ll文件$ clang -emit-llvm main.c -S -o main.ll# 产生bc文件$ opt -load /Volumes/Work/CLion/Projects/llvm-project-llvmorg-9.0.1/llvm/cmake-build-debug/lib/LLVMEncodeFunctionName.dylib -encode main.ll -o main.bcEncodeFunctionName: test -> 5087472e3f661e2a53ecdb4d8dc398a7EncodeFunctionName: test01 -> e63ae3cc6d7f9892993496b04573c87cEncodeFunctionName: main -> main# bc文件转可执行文件$ clang main.bc -o main_clang

逆向
int __cdecl main(int argc, const char **argv, const char **envp){  5087472e3f661e2a53ecdb4d8dc398a7();  e63ae3cc6d7f9892993496b04573c87c();  return 0;}

macOS安装调试llvm入门

将pass注册到clang

macOS安装调试llvm入门

以编写ObfString为例
# 创建ObfPass文件夹并编写ObfString.h# llvm/include/llvm/Transforms/ObfPass/ObfString.h #ifndef LLVM_OBFSTRING_H#define LLVM_OBFSTRING_H  namespace llvm{    Pass* createObfString(bool flag);} #endif //LLVM_OBFSTRING_H # 创建ObfPass文件夹并编写ObfString.cpp# llvm/lib/Transforms/ObfPass/ObfString.cpp #include <llvm/IR/Constants.h>#include <llvm/IR/Instructions.h>#include <llvm/IR/IRBuilder.h>#include "llvm/Pass.h"#include "llvm/Support/raw_ostream.h"#include "llvm/IR/Module.h"  #include "llvm/IR/LegacyPassManager.h"#include "llvm/Transforms/IPO/PassManagerBuilder.h"#include "llvm/Transforms/ObfPass/ObfString.h"#include "llvm/CryptoUtils.h" using namespace llvm;namespace {    struct ObfString : public ModulePass {        static char ID;        bool flag;         ObfString() : ModulePass(ID) {};         ObfString(bool flag) : ModulePass(ID) {            this->flag = flag;        };         bool runOnModule(Module &M) override {            return false;        };    };} char ObfString::ID = 0;static RegisterPass<ObfString> X("obfstr", "String encrypt Pass",                                 false /* Only looks at CFG */,                                 false /* Analysis Pass */); Pass *llvm::createObfString(bool flag) {    return new ObfString(flag);} # 同文件夹下编写CMakeLists.txt与LLVMBuild.txt# CMakeLists.txtadd_llvm_library(LLVMObfPass        CryptoUtils.cpp        ObfString.cpp        ) add_dependencies(LLVMObfPass intrinsics_gen) # LLVMBuild.txt[component_0]type = Libraryname = ObfPassparent = Transformslibrary_name = ObfPass # llvm/lib/Transforms/CMakeLists.txt添加add_subdirectory(ObfPass)# llvm/lib/Transforms/LLVMBuild.txt添加ObfPass# llvm/lib/Transforms/IPO/LLVMBuild.txt添加ObfPass # llvm/lib/Transforms/IPO/PassManagerBuilder.cpp添加 #include "llvm/Transforms/ObfPass/ObfString.h"......static cl::opt<bool> ObfString("obfstr", cl::init(false),                               cl::desc("Enable string obf")); ......void PassManagerBuilder::populateModulePassManager( MPM.add(createObfString(ObfString)); # clion-preferences-build,excution,deployment-cmake-debug-cmake options-G Ninja -DLLVM_ENABLE_PROJECTS="clang"

编译通过。

macOS安装调试llvm入门

调试

macOS安装调试llvm入门

在代码中编写一个错误代码:
bool runOnModule(Module &M) override {  int *err = (int *)8; # 编写一个错误  *err = 9; # 编写一个错误

编译
$ cd /Volumes/Work/CLion/Projects/llvm9.0.1/llvm/cmake-build-debug$ ninja LLVMObfPass$ ninja clang

编写一个测试main.cpp尝试调试
#include <iostream>  int main(int argc, char const *argv[]) {    std::string cppstr = "adkngk222中国";    std::cout << cppstr << std::endl;     return 0;} /** * export PATH=/Volumes/Work/CLion/Projects/llvm9.0.1/llvm/cmake-build-debug/bin:$PATH * clang -mllvm -sub main.c -o main_clang * clang -mllvm -sub -mllvm -sub_loop=3 main.c -o main_clang * clang -mllvm -bcf main.c -o main_clang * clang -mllvm -bcf -mllvm -bcf_loop=3 main.c -o main_clang * clang -mllvm -bcf -mllvm -bcf_prob=60 main.c -o main_clang * clang -mllvm -fla main.c -o main_clang * clang -mllvm -fla -mllvm -split main.c -o main_clang * clang -mllvm -fla -mllvm -split -mllvm -split_num=10 main.c -o main_clang * clang -mllvm -sub -mllvm -sub_loop=3 -mllvm -bcf -mllvm -bcf_prob=60 -mllvm -fla -mllvm -split -mllvm -split_num=10 main.c -o main_clang * clang -mllvm -enable-encode-function-name -mllvm -sub -mllvm -sub_loop=3 -mllvm -bcf -mllvm -bcf_prob=60 -mllvm -fla -mllvm -split -mllvm -split_num=10 main.c -o main_clang * export C_INCLUDE_PATH=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include * export CPLUS_INCLUDE_PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1 * clang++ -Wall -std=c++11 -S -emit-llvm main.cpp -o main.ll * clang++ -Wall -std=c++11 -mllvm -obfstr -S -emit-llvm main.cpp -o main_strobf.ll */

打开shell尝试编译
$ export PATH=/Volumes/Work/CLion/Projects/llvm9.0.1/llvm/cmake-build-debug/bin:$PATH$ export CPLUS_INCLUDE_PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1$ export C_INCLUDE_PATH=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include # 编译$ clang++ -Wall -std=c++11 main.cpp -o main.test# 报错Stack dump:0.    Program arguments: /Volumes/Work/CLion/Projects/llvm9.0.1/llvm/cmake-build-debug/bin/clang-9 -cc1 -triple x86_64-apple-macosx10.15.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -emit-obj -mrelax-all -disable-free -main-file-name main.cpp -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -masm-verbose -munwind-tables -target-sdk-version=10.15.6 -target-cpu penryn -dwarf-column-info -debugger-tuning=lldb -ggnu-pubnames -target-linker-version 609 -resource-dir /Volumes/Work/CLion/Projects/llvm9.0.1/llvm/cmake-build-debug/lib/clang/9.0.1 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -c-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include -cxx-isystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1 -stdlib=libc++ -internal-isystem /Volumes/Work/CLion/Projects/llvm9.0.1/llvm/cmake-build-debug/bin/../include/c++/v1 -internal-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1 -internal-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/local/include -internal-isystem /Volumes/Work/CLion/Projects/llvm9.0.1/llvm/cmake-build-debug/lib/clang/9.0.1/include -internal-externc-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include -Wall -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /Volumes/Work/CLion/Projects/Test -ferror-limit 19 -fmessage-length 80 -stack-protector 1 -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fobjc-runtime=macosx-10.15.0 -fcxx-exceptions -fexceptions -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -o /var/folders/vh/l2bql3ns2d5g5w6w2rk1q16m0000gn/T/main-6e5ff9.o -x c++ main.cpp1.    <eof> parser at end of file2.    Per-module optimization passes3.    Running pass 'String encrypt Pass' on module 'main.cpp'.

可以看出clang++的编译实际上是使用了clang-9做的编译,那么修改clion编译配置,尝试调试:
clion-run-edit configurations左边选择clang,右边executable选择clang-9, program arguments配置: -cc1 -triple x86_64-apple-macosx10.15.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -emit-obj -mrelax-all -disable-free -main-file-name main.cpp -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -masm-verbose -munwind-tables -target-sdk-version=10.15.6 -target-cpu penryn -dwarf-column-info -debugger-tuning=lldb -ggnu-pubnames -target-linker-version 609 -resource-dir /Volumes/Work/CLion/Projects/llvm9.0.1/llvm/cmake-build-debug/lib/clang/9.0.1 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -c-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include -cxx-isystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1 -stdlib=libc++ -internal-isystem /Volumes/Work/CLion/Projects/llvm9.0.1/llvm/cmake-build-debug/bin/../include/c++/v1 -internal-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1 -internal-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/local/include -internal-isystem /Volumes/Work/CLion/Projects/llvm9.0.1/llvm/cmake-build-debug/lib/clang/9.0.1/include -internal-externc-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include -Wall -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /Volumes/Work/CLion/Projects/Test -ferror-limit 19 -fmessage-length 80 -stack-protector 1 -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fobjc-runtime=macosx-10.15.0 -fcxx-exceptions -fexceptions -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -o /var/folders/vh/l2bql3ns2d5g5w6w2rk1q16m0000gn/T/main-6e5ff9.o -x c++ /Volumes/Work/CLion/Projects/Test/main.cpp

就可以调试了。



macOS安装调试llvm入门

- End -


macOS安装调试llvm入门


看雪ID:新萌

https://bbs.pediy.com/user-home-811222.htm

 

 *本文由看雪论坛 新萌 原创,转载请注明来自看雪社区。



 安卓应用层抓包通杀脚本发布!

《高研班》2021年3月班火热招生中!👇


macOS安装调试llvm入门

* 戳图片了解详情




# 往期推荐






macOS安装调试llvm入门
公众号ID:ikanxue
官方微博:看雪安全
商务合作:[email protected]



macOS安装调试llvm入门

球分享

macOS安装调试llvm入门

球点赞

macOS安装调试llvm入门

球在看



macOS安装调试llvm入门

点击“阅读原文”,了解更多!

本文始发于微信公众号(看雪学院):macOS安装调试llvm入门

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2020年12月30日02:32:30
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   macOS安装调试llvm入门http://cn-sec.com/archives/225552.html

发表评论

匿名网友 填写信息