交叉编译实践
什么是交叉编译
在本架构的主机上编译出另一种架构的可执行文件。
为什么需要交叉编译?
可执行文件有确定的架构,如x86、MIPS、ARM等,这些可执行文件只能在对应架构的CPU上运行。一般而言,我们只需要编译出能够在自己主机架构上运行的程序。但是像路由器这些固件一般是MIPS、ARM架构的,我们要想在X64的电脑上调试这些文件,就需要用到交叉编译,常用的工具是BuildRoot。
实验目的
- 学会使用Buildroot构建交叉编译工具链
- 掌握LD_PRELOAD使用
实验内容
完成交叉编译工具链生成
制作MIPS32 小端的BuildRoot
编译完成:
MIPS32 大端
配置类似,这是编译结果:
完成静态编译Busybox工具
编译BusyBox MIPS小端
把BuildRoot的bin添加到环境变量中
设置交叉编译头
静态编译
测试:
大端
同理:
先把大端BuildBoot的bin添加到环境变量
重新解压一份busybox,重命名
-mipsel是刚才的小端busybox
修改交叉编译头
编译完成:
这个是动态编译的
设置为静态编译:
启动编译
编译成功
测试
编译libpcap
大端libpcap
官网查看编译教程
https://github.com/the-tcpdump-group/libpcap/blob/master/INSTALL.md
没有make menuconfig,需要在命令行中配置
我们需要配置的有:
这个是输出的目录,默认会放到/usr/bin/local之类的地方,会全局可用。我们会准备多个版本的libpcap,自然不能添加到全局。使用—prefix=/home/szl/lib指定输出目录
–host是一个目标三元组,用于描述交叉编译工具链的目标架构和环境。我们应该使用mips-linux-gnu
CC是编译器,我们的是mips-linux-gcc,这个已经是全局变量
CFALGS是头文件、优化级别、警告级别,我们只用于添加头文件
LDFLAGS指定了链接库和是否静态编译,我们添加链接库
遇到报错:
更详细的报错在config.log中
说是需要c99,但是添加了c99或gnu99都无法解决
参考:
https://lore.kernel.org/all/20210123164535.515E78151B@busybox.osuosl.org/T/
通过硬编码ac_cv_prog_cc_c99来避免wchar_t检查问题
然后make
这是因为之前留下了一些x86的libpcap文件
clean掉就可以
然后重新make,make install
去我们设置的prefix中查看
动态大端libpcap编译完成
编译静态的libpcap失败:
配置–static表示静态编译libpcap
然后make会报错:
即使添加-fPIC也不行
相同的报错,老师说动态的libpcap也可以,遂放弃编译静态libpcap
编译大端tcpdump
然后make,make install
测试tcpdump
失败
在普通环境和chroot中都失败了
参考:https://github.com/docker/for-mac/issues/6707
似乎qemu中的tcpdump会有问题
编译小端libpcap
先make clean一下
然后make, make install
编译mips小端tcpdump
和编译libpcap类似
小端tcpdump
然后make,make clean
静态MIPS小端的tcpdump编译完成
LD_PRELOAD劫持随机数生成
这里提取出来的suqashfs-root是空的
上面提示我们没有安装sasquatch,接下来安装这个
PPT中虽然给了对应的解决办法
这个deps.sh在binwalk下面,最终目的还是为了解决binwalk的安装问题。但我们之前的Binwalk是可以正常运行的,只是现在报错了。
我们可以找一下其他的解决办法:
https://github.com/devttys0/sasquatch/issues/48#issuecomment-1267506233
这个是采用了:https://github.com/devttys0/sasquatch/pull/47中的一个patch文件来进行补丁。
命令:
现在正常了:
需要采用32位小端MIPS
编译test.c
在squashfs-root中修改文件需要root权限,我们在外面把test和so编译好再拷到squashfs-root中
编译libnvram.so
完整的学号有13位,超过了%d的范围,我们只使用学号的后9位
-fPIC表示生成与位置无关的代码,创建共享库需要这个。
-shared:指示编译器生成共享库。
再把qemu-mipsel-static移过来
运行
劫持成功
命令解释:
chroot .把根目录改为了当前文件夹。我们要用到uClibc,这个文件在提取出来的/lib下面,如果不使用chroot的话会找不到uClibc
-E是qemu用来设置环境变量的,LD_PRELOAD是一个环境变量,用于在运行时加载指定的共享库。这样test在调用rand函数时就会调用libnvram.so中的rand函数,完成劫持。