基于Buildroot的嵌入式系统交叉编译技巧

IoT 2年前 (2022) admin
821 0 0

一、介绍

现如今IOT设备安全研究需要面对不同设备不同架构的产品,鉴于不同架构的编译也是从业者所需要掌握的技能。现如今主流设备架构主要以x86_64armmips架构为主,不同架构不同指令集的编译以及错误处理如何解决,也是本篇文章所探讨的话题。

1.1  工具


Buildroot 是一个简单、高效、易用的工具,通过交叉编译生成嵌入式 Linux 系统。
下载地址: https://buildroot.org/download.html

1.2  界面


配置交叉编译工具设置(makemenuconfig),如图1-1 配置界面

基于Buildroot的嵌入式系统交叉编译技巧

1-1 配置界面

2.3 选项功能


TargetOptions 设备架构(如图1-2 设备架构)

基于Buildroot的嵌入式系统交叉编译技巧

1-2 设备架构

Build Options 编译选项(如图1-3 编译选项)
主要在libraries设置居多(both static and shared),静态编译及动态编译

基于Buildroot的嵌入式系统交叉编译技巧

1-3 编译选项

Toolchain 编译工具链(如图1-4 编译工具链)
主要gcc版本、内核版本、宽字符及C++配置选项设置

基于Buildroot的嵌入式系统交叉编译技巧

1-4 编译工具链

System configuration 系统配置(如图1-5 系统配置)
主要构建文件系统需要配置,默认选项

基于Buildroot的嵌入式系统交叉编译技巧

1-5 系统配置

Linux Kernel 内核配置(如图1-6 内核配置)
主要系统内核进行配置,默认选项

基于Buildroot的嵌入式系统交叉编译技巧

1-6 内核配置

Target Packages 程序依赖库(如图1-7 程序依赖库)
主要对编译程序依赖库进行配置

基于Buildroot的嵌入式系统交叉编译技巧

1-7 程序依赖库

Filesystem image 文件系统镜像
Bootloaders Boot引导
Host utilities 本地工具
Leagcy config Options  Leagcy 配置
以上四个默认不需要配置,不做具体阐述
 

1.3  编译


选择target options 指定架构后保存
不能使用make-jN,因为Buildroot不支持top-levelparallel make , 反之 , 使用BR2_JLEVEL选项来告诉Buildroot运行编译每一个package使用make -JN
Make BR_JLEVEL=4 V=s
编译完成后,生成的交叉编译工具链主要存于output/host/bin目录中(如图1-8 交叉编译工具链)

基于Buildroot的嵌入式系统交叉编译技巧

1-8 交叉编译工具链

二.    交叉编译实测

实际工作中主要以编译静态程序为主(本次例子以MIPS为主,ARM同理)

2.1  Hello World


Hello.c
#include  <stdio.h>
 
int  main(){
prnitf(“Hello  World!n”);
return 0;
}
交叉编译(如图2-1 hello)

基于Buildroot的嵌入式系统交叉编译技巧

2-1 hello

2.2  NetCat


下载地址: https://github.com/mirror/busybox.git
Make menuconfig 保存生成配置文件
!!!注意所有的编译信息都存在于Makefile文件
工具支持CROSS_COMPILE不需要单独对编译选项进行修改
Makefile(如图2-2 Makefile文件)

基于Buildroot的嵌入式系统交叉编译技巧

2-2 Makefile文件

编译命令(如图2-3 编译命令)

基于Buildroot的嵌入式系统交叉编译技巧

2-3 编译命令

查看编译文件(如图2-4 Busybox_MIPS)

基于Buildroot的嵌入式系统交叉编译技巧

2-4 Busybox_MIPS

2.3  巧获编译信息


部分产品由于编译过程依赖库较多so文件就会导致无法获知哪些依赖库,这边可通过打印详细gcc编译信息,获取make构建中传递给gcc编译器参数。
Golang
package main
 
import (
    “fmt”
    “os”
    “os/exec”
    “strings”
)
 
func CheckExists(path string) bool {
    _, err :=  os.Stat(path)
    if err == nil {
         return true
    }
    if  os.IsNotExist(err) {
         return false
    }
    return false
}
 
func main() {
    var file *os.File
    var err error
    name :=  “/tmp/cmd.txt”
 
    cmds := os.Args
    fmt.Println(“print  gcc args:”, cmds)
 
    //将获取参数内容打印到文件中
    if CheckExists(name)  {
         file, err =  os.OpenFile(name, os.O_APPEND|os.O_WRONLY, os.ModePerm)
         if err != nil {
             fmt.Println(err.Error())
             return
         }
         defer  file.Close()
    } else {
         file, err =  os.Create(name)
         if err != nil {
             fmt.Println(err.Error())
         }
    }
 
    file.WriteString(strings.Join(cmds,  ” “))
 
  //保持gcc原有的逻辑不变
    cmd :=  exec.Command(“gcc”, cmds[1:]…)
    cmd.Stdout =  os.Stdout //正常输出
    cmd.Stderr =  os.Stderr //异常输出
    err = cmd.Run()
    if err != nil {
         fmt.Println(err.Error())
         return
    }
 
    out, err :=  cmd.Output()
    if err != nil {
         fmt.Println(err.Error())
         return
    }
 
    fmt.Println(string(out))
}
 
#编译
go build main.go -o gcc
#将程序命令为gcc,替换当前的gcc,达到劫持编译信息的目的

三.    总结

交叉编译所涉及的知识点较多,本片文章仅起到入门作用,让大家对交叉编译这个概念有初步的认识。

基于Buildroot的嵌入式系统交叉编译技巧

原文始发于微信公众号(山石网科安全技术研究院):基于Buildroot的嵌入式系统交叉编译技巧

版权声明:admin 发表于 2022年5月19日 上午9:28。
转载请注明:基于Buildroot的嵌入式系统交叉编译技巧 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...