很久没更新了,最近准备研究逆向和加固,于是跟着看雪hanbing老师学习彻底搞懂ollvm,终于把所有流程跑通了,中间遇到了太多的坑,所以必须记录一下,能避免自己和帮助他人最好。
环境搭建太重要了,折腾了好几遍,老师的视频里对初始环境说得太少了,吃了太多这方面的亏,这里我是在windows中添加虚拟机完成的,原以为mac上应该也可以,但后面发现还是很多地方走不通。
系统使用VirtualBox-7.0.12-159484-Win和ubuntu-2204.3,从目前来说都是最新的,
virturalBox 下载地址:https://www.virtualbox.org/wiki/Downloadshttps://www.virtualbox.org/wiki/Downloads
ubuntu 下载地址 :
https://releases.ubuntu.com/jammy/ubuntu-22.04.3-desktop-amd64.isohttps://releases.ubuntu.com/jammy/ubuntu-22.04.3-desktop-amd64.iso
先安装虚拟机环境并配好网络,整个下载和安装过程大部分时间就是等
下载好这两个文件后,可以开始安装了
我准备了一个空盘,465G,为了防止llvm编译时内存报错,搞得很大
VirtualBox 安装,配置内存24000MB,差不多20G,处理器8,硬盘给到360G,因为llvm编译很容易内存溢出,所以硬件还是要跟上,这里我是吃过亏的。
配置完毕后,等待一段时间的安装,检查Terminal应用是否正常,默认浏览器是否能上网。
terminal无法打开的问题解决:
CTRL + ALT + F3 # 进入命令行模式(需要返回桌面时CTRL + ALT + F1)
cd /etc/default
sudo nano locale
# 把文件中的 “en_US” 改成 “en_US.UTF-8”
#注意是所有的en_US,我这边发现了两处
# 保存退出
sudo locale-gen --purge
reboot # 重启虚拟机
安装git,去官网下载llvm 9.0.1版本源代码,注意是linux的版本,然后上传到一个自己的git仓库,这里上传是为了后面有用,这里很重要,后面要做代码分支切换。
下载地址:https://github.com/llvm/llvm-project/releases/download/llvmorg-9.0.1/llvm-project-9.0.1.tar.xz
git 添加ssh命令
ssh-keygen -t ed25519 -C "your_email@example.com"
安装llvm编译命令,同Android源码编译的命令相同:
sudo apt-get install git-core gnupg flex bison build-essential zip curl zlib1g-dev libc6-dev-i386 libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig
安装完毕后可以编译安卓源码也可以编译llvm。
安装cmake, sudo apt install cmake
安装ninja , sudo apt-get install ninja-build
两个工具安装完毕后,mkdir build-debug cd build-debug
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DLLVM_ENABLE_PROJECTS="clang" ../llvm
目录结构如上,命令正常后执行,ninja -j8,然后等待编译完成。3000多个文件,至少半个小时吧。
同样的操作,再编译release目录,先创建build-release文件夹,再执行
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang" ../llvm
同样执行 ninja -j8。
然后就是在clion中编译llvm了,先去官网下clion并安装,注意下载的是linux的版本,
clion下载地址:
Download CLion: A Smart Cross-Platform IDE for C and C++
打开llvm项目,目录为/home/nowind/llvm/llvm-project-9.0.1/llvm /CMakeLists.txt,然后手动配置CMake参数:
Debug和Release,-G Ninja -DLLVM_ENABLE_PROJECTS="clang",在llvm目录下会自动生成
cmake-build-debug和cmake-build-release目录,再使用命令行进入这两个目录,执行ninja -j8
debug模式在编译llc文件的时候,我等了将近半个小时,也是这里容易将内存给崩了,需要随时查看free -m,查看剩余内存还够不够,不够就添加swap内存。这个文件非常难过,编译完成后直接吞掉了我近100G,编译后debug包的大小有65G
这里我添加了40G的swap内存
sudo swapoff -asudo rm /swapfilesudo dd if=/dev/zero of=/swapfile bs=1M count=40960sudo chmod 600 /swapfilesudo mkswap /swapfilesudo swapon /swapfilesudo swapon --show
以上是在外层生成的编译文件,但我在后面看老师讲解的时候,并没有用到这个,所以很奇怪,为啥多这一步,如果时间不足可以先往后看,有空再来编译这边的。
终于编译完了。
编译遇到错误:
llvm-project-9.0.1/llvm/utils/benchmark/src/benchmark_register.h:17:30: error: ‘numeric_limits’ is not a member of ‘std’ 17 | static const T kmax = std::numeric_limits<T>::max();
需要在llvm-project-9.0.1/llvm/utils/benchmark/src/benchmark_register.h中增加
#include <limits>
无论在clion中编译还是使用cmake直接编译,都是后续的第一步,这步遇到问题,一定是要解决的
接下来我们使用编译后的clang和llvm来执行c文件
先配置环境变量:
export PATH=/home/nowind/llvm/llvm-project-9.0.1/llvm/cmake-build-debug/bin:$PATH
clang -emit-llvm -S hello_clang.c -o hello_clang.ll 其中ll文件可以直接修改,改字符串名字和长度
lli hello_clang.ll
llvm-as hello_clang.ll -o hello_clang.bc
llc hello_clang.bc -o hello_clang.s 转化成汇编
clang hello_clang.s -o hello_clang_s 汇编转可执行文件
llvm-dis hello_clang.bc -o hello_clang_re.ll 同样可以把bc文件转ll文件,和上面使用clang的结果是一样的
opt --print-bb hello_clang.bc 打印内容
熟悉下c文件编译后的几种格式 灵活运用
clion断点调试,
使用clang命令行:
clang /home/nowind/llvm/pro/pro1/hello_clang.c -o /home/nowind/llvm/pro/pro1/hello_clang_s
使用clang 断点:clion 切换到Clang Debug模式,配置参数
/home/nowind/llvm/pro/pro1/hello_clang.c -o /home/nowind/llvm/pro/pro1/hello_clang_s
然后断点打在/home/nowind/llvm/llvm-project-9.0.1/clang/tools/driver/driver.cpp的main函数中,这里是clang的入口
使用pass:
bc或者ll文件使用hello pass
opt 命令行运行
opt -load '/home/nowind/llvm/llvm-project-9.0.1/build-debug/lib/LLVMHello.so' -hello hello.bc
clion调试opt 切换至 opt debug,进行断点 在 llvm/lib/Transform/Hello/hello.cpp
配置参数
-load /home/nowind/llvm/llvm-project-9.0.1/build-debug/lib/LLVMHello.so -hello hello.bc
以上基本是第一课的所有内容了,并不复杂,但编译时间会比较长,遇到相关问题也可以一起讨论