busybox最小Linux体系

打印 上一主题 下一主题

主题 900|帖子 900|积分 2700

情况

WSL(Ubuntu 22.04)
创建磁盘映像

可以使用fallocate为磁盘映像分配一块空间,或者使用dd if=/dev/zero of=$img bs=1M count=$size_in_MB直接得到一个大小为$size_in_MB大小的文件。
使用mkfs.ext4格式化映像文件,并使用mount -o loop $img mnt将文件挂载。
如果想要在磁盘映像中分区,则可以先使用fdisk或cfdisk对磁盘映像进行分区,然后使用losetup -fP $img将文件挂载为回环设备。这里-f参数表现自动寻找可以挂载的回环设备号,-P参数表现探测文件中的分区并分别挂载为回环设备。挂载为回环设备后,再使用mount $loop1 $mnt1等下令挂载回环设备。
构建busybox

下载busybox源码并构建,这里使用的是busybox-1.36.1版本
这里采用的构建选项有
构建静态文件:
  1. Symbol: STATIC [=y]
  2. Prompt: Build static binary (no shared libs)
  3.         Defined at Config.in:362
  4.         Location:
  5.                 -> Settings
复制代码
这个版本默认支持了Unicode,可以不用更改
  1. Symbol: UNICODE_SUPPORT [=y]
  2.         Prompt: Support Unicode
  3.         Defined at libbb/Config.in:311
  4.         Location:
  5.                 -> Settings
复制代码
添加了Unicode宽字符支持
  1. Symbol: UNICODE_WIDE_WCHARS [=y]
  2.         Prompt: Allow wide Unicode characters on output
  3.         Defined at libbb/Config.in:390
  4.                 Depends on: UNICODE_SUPPORT
  5.                 Location:
  6.                 -> Settings
  7.                         -> Support Unicode (UNICODE_SUPPORT [=y])
复制代码
其他构建选项均可以不更改
使用make构建后,再使用make install即可将完整的busybox、busybox符号链接等文件安装到busybox源码目次下的_install目次内。或者可以通过make install CONFIG_PREFIX=$install将busybox安装到指定目次中。好比这里我们可以使用make install CONFIG_PREFIX=$mnt将busybox安装到已经挂载的磁盘映像中。
构建Linux内核

下载Linux内核源码,这里使用Linux-6.12.7版本
根据自己喜好配置即可
创建rootfs

这里需要创建一个rootfs来作为Linux运行的情况。
查看busybox的安装目次可以发现,如今只有bin,sbin和usr三个目次和linuxrc一个符号链接。对比我们自己的Linux根目次可以发现,我们大概有以下目次
  1. bin boot dev etc home lib mnt opt proc root run sbin sys tmp usr var
复制代码
那么我们在$mnt目次下创建这些目次即可。
由于mount需要sudo,$mnt目次下的文件很大概是root权限,后面一系列操作大概都需要root权限。
如今可以chroot到$mnt目次下试试能否使用shell。
运行假造机

这里我们使用qemu假造机。
将启动下令写成一个脚本
  1. #!/bin/sh
  2. /usr/bin/qemu-system-x86_64\
  3.   -kernel path/to/bzImage\
  4.   -hda path/to/rootfs.img\
  5.   -nographic\
  6.   -append "console=ttyS0 root=/dev/sda init=/linuxrc"
复制代码

  • -kernel选项表现设置Linux kernel为bzImage
  • -hda选项表现选择磁盘映像
  • -nographic表现不使用qemu窗口,而是将输出重定向到终端
  • -append表现传递给Linux内核的参数

    • console=ttyS0表现将输出重定向到串口设备ttyS0,这将使qemu将启动阶段的信息输出到终端
    • root=/dev/sda表现根文件体系的位置,假造机中一般是sda
    • init=linuxrc表现使用linuxrc作为init进程,也就是Linux下的第一个进程启动,这个linuxrc其实就是我们的busybox

启动配置

此时如果直接运行脚本启动假造机大概会报错,由于我们没有配置busybox作为init进程时的活动。
linuxrc会读取/etc/inittab文件,我们将该文件配置如下
  1. ::sysinit:/etc/init.d/rcS
  2. ::respawn:-/bin/sh
  3. ::restart:/sbin/init
  4. ::ctrlaltdel:/sbin/reboot
  5. ::shutdown:/bin/umount -a -r
复制代码
该文件内每行有四个字段,格式为:::

  • 指编号,不重复即可
  • 指运行级别,可以不指定,指定时表现运行级别为n时激活改行的规则
  • 包含一系列动作,表现对登记的在肯定条件下执行的动作
  • 即要运行的进程,前面加上-表现以交互方式运行
包含以下动作
action含义respawn当process停止后立刻启动一个新的wait当进入指定的runlevels后process才会启动一次,而且到离开这个runlevels停止initdefault设定默认的运行级别,即我们开机之后默认进入的运行级别,不能是0,6,你懂的sysinit体系初始化,只有体系开机或重新启动的时候,这个process才会被执行一次powerwait当init吸收到电源失败信号的时候执行相应的process,而且如果init有进程在运行,会等候这个进程完成之后,再执行相应的processpowerfail当init吸收到电源失败信号的时候执行相应的process,而且如果init有进程在运行,不会等候这个进程完成,它会直接执行相应的processpowerokwait电源已经故障,但是在等候执行对应操作的时候突然来电了就执行对应的processpowerfailnow当电源故障而且init被通知UPS电源已经快耗尽执行相对应的processctrlaltdel当用户按下ctrl+alt+del这个组合键的时候执行对应的processboot只有在引导过程中,才执行该进程,但不等候该进程的竣事;当该进程死亡时,也不重新启动该进程bootwait只有在引导过程中,才执行该进程,并等候进程的竣事;当该进程死亡时,也不重新启动该进程off如果process正在运行,那么就发出一个警告信号,等候20秒后,再通过杀死信号强行停止该process。如果process并不存在那么就忽略该登记项once启动相应的进程,但不等候该进程竣事便继续处理/etc/inittab文件中的下一个登记项;当该进程死亡时,init也不重新启动该进程inittab第一行表如今体系启动时,运行/etc/init.d/rcS脚本里的内容。这也是没有inittab时linuxrc的默认动作。
接下来我们配置/etc/init.d/rcS脚本的内容
  1. #!/bin/sh
  2. PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
  3. LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
  4. runlevel=S
  5. umask 022
  6. export PATH LD_LIBRARY_PATH runlevel
  7. # devices
  8. mount -a
  9. mkdir /dev/pts
  10. mount -t devpts devpts /dev/pts
  11. mount -o remount,rw /
  12. mdev -s
复制代码
我们的脚本配置了情况变量,设备等,需要在体系启动时进行的配置,开启的服务,都可以在该文件中进行配置。
配置完成后肯定要赋予/etc/init.d/rcS运行权限,否则启动过程中会报错。
此时启动假造机可以看到,我们已经进入了shell。
其他配置文件

虽然我们的Linux已经正常启动,但是不要高兴的太早。
我们在shell中执行export PS1='\u@\h \W',重新登陆,我们预期会显示root@host ~,但是,这里并没有我们的用户名和主机名。
此时我们执行id和hostname下令会发现,我们如今虽然是uid=0 gid=0的用户,但是我们没有用户名,主机名也是(none)。执行ifconfig会发现,我们也没有可用网络。
接下来我们将进行这些方面的配置。
我们的Linux已经可以启动,而且busybox内置了vi作为编辑器,接下来的配置可以不通过宿主机,直接在假造机中完成。
用户配置

由于root用户本来就存在,我们不能用adduser创建用户,于是我们手动创建用户属性文件。
Linux通过辨认/etc/passwd中的用户来判断用户名,我们手动创建这个文件。
添加以下内容
  1. root:x:0:0::/root:/bin/sh
复制代码
这个文件有7个字段,格式为::::::。
其中字段内容为加密后的密码,如果设为空则表现不需要密码也可以登录,如果为x表现密码存储在/etc/shadow文件中。
如果我们不创建/etc/shadow文件,passwd下令会将加密的密码存储在/etc/passwd中,所以我们打算创建一个/etc/passwd。
我们的Linux和busybox都支持剖析/etc/shadow文件,接下来我们手动创建这个文件。
添加以下内容
  1. root::1::::::
复制代码
这个文件内每行9个字段,格式为login:encyrptedpassword:lastchangedate:min_age:max_age:warning:inactivity:expiration_date:reserved,第一个字段为用户名,第二个字段为加密后的密码,如果为空会登录失败,为*或!时情况不确定,Linux console上写*和!表现没有密码,但现实测试后发现,为这两个符号时,busybox的login会提示bad salt。
后面的几个字段都与密码修改时间有关,分别为

  • lastchange表现前次修改密码的日期的时间,如果该值为0,则表现用户下次登录时必须更改密码
  • minage表现更改密码的间隔日期,为空或为0表现随时可以更改密码
  • maxage表现必须更改密码的日期
  • warning表如今密码到期前n天警告用户需要更改密码
  • inactivity表现密码逾期后,n天内可以再更改密码
  • expiration_date表现到期日期,到期后无法再登录
  • reserved最后一个字段为保留字段
有这个文件后我们就可以使用passwd下令更改密码,然后再查看/etc/shadow可以发现密码已经改变了。
然后我们就可以通过登录的方式进入操作体系。
更改/etc/inittab如下
  1. ::sysinit:/etc/init.d/rcS
  2. ::respawn:/sbin/getty -L console 0 vt100
  3. ::restart:/sbin/init
  4. ::ctrlaltdel:/sbin/reboot
  5. ::shutdown:/bin/umount -a -r
复制代码
这表现不直接打开一个shell,而是在console这个tty上打开一个login。
主机配置

一般我们将主机名写在/etc/hostname中,但是busybox不自动读取这个文件。
于是我们添加配置到/etc/init.d/rcS中
  1. #!/bin/sh
  2. ...
  3. # hostname
  4. hostname -F /etc/hostname
复制代码
这代表从/etc/hostname加载主机名
网络配置

同样在/etc/init.d/rcS中添加以下配置
  1. # network
  2. ifconfig lo up
  3. ifconfig eth0 192.168.1.100 netmask 255.255.255.0 up
  4. route add default gw 192.168.1.1 eth0
复制代码
ip地址随意填写,网关地址填写为qemu外部提供的网卡地址
网卡配置

在WSL中,需要创建一张假造网卡设备作为假造机的网关。
我们创建一张tap设备,向网卡配置脚本中写入以下内容
  1. ip tuntap add dev tap0 mode tap
  2. ip link set dev tap0 up
  3. ip a add dev tap0 192.168.1.1/24
  4. iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.1/24 -j MASQUERADE
  5. echo 1 > /proc/sys/net/ipv4/ip_forward
复制代码
这个脚本创建了一张tap0网卡,并分配了ip地址192.168.1.1,就是我们的假造机的网关地址。
iptables下令创建了一条nat规则,将内部发出的源地址为192.168.1.0/24网段的数据包改为从eth0发出,这样就可以让假造机连接到外部网络了。
此时进入假造机,执行ping 192.168.1.1发现有网络连接。
然后执行cat nameserver 8.8.8.8 > /etc/resolv.conf配置域名剖析服务器。
此时执行ping www.baidu.com就可以ping通了。
由于busybox没有自带curl,执行echo -e "GET / HTTP/1.1\r\nHost:www.baidu.com\r\n\r\n" | nc www.baidu.com 80代替,可以收到html网页内容。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

数据人与超自然意识

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表