本文最后更新于:星期五, 二月 15日 2019, 9:29 上午

跟着大佬的博客,开始学习搭建内核环境。开篇文章记录一下。

获取内核

获取内核的方法有两种,一种是自己下载源码,然后编译,另一种是通过apt直接下载内核

编译内核

  • 下载源码

    • 通过官网下载

      https://www.kernel.org/ 上下载,最初我下的是2.6.0版本,发下编译会遇到很多问题……然后就放弃了,下了一个4.1.1版本

      https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.1.1.tar.gz

      ubuntu上可以通过wget来下载

        wget https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.1.1.tar.gz
      
    • 通过apt来下载

      1. 根据内核版本搜索,例如

        sudo apt search linux-headers-4.

        但是我没有发现我下的4.1.1版本的….能下的最低版本都是4.10.0-1004,但是问题不大,随便挑了个4.10.1来下

        1548935592900

      2. 下载源码

        sudo apt install linux-headers-4.10.0-1004

        最后下载的源码会在/usr/src目录下

  • 安装需要的依赖

      sudo apt-get update
      sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc
    
  • 解压源码,进入源码目录

    输入

      make menuconfig
    

    然后就会见到这个界面,按照大佬的做法

      进入kernel hacking
      勾选以下项目
      Kernel debugging
      Compile-time checks and compiler options —> Compile the kernel with debug info和Compile the kernel with frame pointers
      KGDB
      然后保存退出
    

    1548930451951

  • 生成bzImage

      make bzImage
    

    经过漫长的等待,出现下图的信息,说明编译成功。然后bzImage在 /arch/x86/boot中,vmlinux在当前路径下

    1548933686339

    解释下几个名词

    vmlinux是未压缩的内核

    vmlinuz是vmlinux的压缩文件。

    vmlinux 是ELF文件,即编译出来的最原始的文件。

    vmlinuz应该是由ELF文件vmlinux经过OBJCOPY后,并经过压缩后的文件

    zImage是vmlinuz经过gzip压缩后的文件,适用于小内核

    bzImage是vmlinuz经过gzip压缩后的文件,适用于大内核

下载内核

  1. 根据版本号搜索

    sudo apt search linux-image-

    1548935980438

  2. 挑个喜欢的下载

    sudo apt download linux-image-4.10.0-1004-gcp

    这个下载下来的是一个deb文件,解压后镜像在data.tar.xz中

    1548943917235

编译busybox

用来生成简易的文件镜像

busybox简介

BusyBox是一个遵循GPL协议、以自由软件形式发行的应用程序。Busybox在单一的可执行文件中提供了精简的Unix工具集,可运行于多款POSIX环境的操作系统,例如Linux(包括Android[6])、Hurd[7]、FreeBSD[8][9]等等。由于BusyBox可执行文件的文件大小比较小、并通常使用Linux内核,这使得它非常适合使用于嵌入式系统。作者将BusyBox称为“嵌入式Linux的瑞士军刀”。[10] —摘自维基百科

  1. busybox是Linux上的一个应用程序
  2. 它整合了许多Linux上常用的工具和命令

IBM的一篇关于busybox的文章 文章地址,写的很详细。

编译busybox

  • 从官网上下载源代码https://busybox.net/

    我下的是busybox-1.30.0

  • 解压,进入根目录

    • 执行命令 make menuconfig,然后会出现一个界面

      1548945130949

      这里在Settings中勾选Build static binary (no shared libs),然后save就可以了

    • 编译,执行make install

      1548945519706

    • 编译完后会多出一个_install文件夹,这是编译后的结果

      • 进入_install,然后输入如下命令

          mkdir proc
          mkdir sys
          touch init
          chmod +x init
        
      • 在init写入下面的内容,用于内核初始化

          #!/bin/sh
          echo "{==DBG==} INIT SCRIPT"
          mkdir /tmp
          mount -t proc none /proc
          mount -t sysfs none /sys
          mount -t debugfs none /sys/kernel/debug
          mount -t tmpfs none /tmp
          # insmod /xxx.ko # 加载模块
          mdev -s # We need this to find /dev/sda later
          echo -e "{==DBG==} Boot took $(cut -d' ' -f1 /proc/uptime) seconds"
          setsid /bin/cttyhack setuidgid 1000 /bin/sh #normal user
          # exec /bin/sh #root
        
      • 打包成镜像

          #在busybox的_install目录下输入下面的命令
          find . | cpio -o --format=newc > ./rootfs.img
        

启动系统

这里用qemu来运行

qemu简介

QEMU(quick emulator)是一款由Fabrice Bellard等人编写的免费的可执行硬件虚拟化的(hardware virtualization)开源托管虚拟机(VMM)。其与Bochs,PearPC类似,但拥有高速(配合KVM),跨平台的特性。QEMU是一个托管的虚拟机镜像,它通过动态的二进制转换,模拟CPU,并且提供一组设备模型,使它能够运行多种未修改的客户机OS,可以通过与KVM(kernel-based virtual machine开源加速器)一起使用进而接近本地速度运行虚拟机(接近真实计算机的速度)。QEMU还可以为user-level的进程执行CPU仿真,进而允许了为一种架构编译的程序在另外一中架构上面运行(借由VMM的形式)。                             ---摘自维基百科

qemu的官方文档链接地址

启动脚本

  • 将生成的rootfs.img和编译的内核bzImage文件放在同一文件夹下,新建一个启动脚本boot.sh,这是我是直接拿大佬的脚本来用的,加了一点注释,参数的具体意义可以参照qemu的官方文档。

      #! /bin/sh
    
      qemu-system-x86_64 \
      -m 128M \            #指定虚拟机的RAM大小
      -kernel ./bzImage \    #指定内核
      -initrd  ./rootfs.img \    #用于提供 INITRD镜像
      -append "root=/dev/ram rw  oops=panic panic=1 kalsr" \    #
      -netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \    #配置用户模式的网络
      -monitor /dev/null \    #将监视器重定向到主机设备/dev/null
      -smp cores=2,threads=1 \ #用于声明所有可能用到的cpus, i.e. sockets * cores * threads = maxcpus.
      -cpu kvm64,+smep \         #设置CPU的安全选项
    
      #-S 启动gdb调试
      #-gdb tcp:1234 等待gdb调试
    

    运行这个脚本,启动qemu,等一下就可以了

    1549012968632

编译ko

内核环境搭好了,来学习下怎么编译模块文件

源码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>


static int __init init_fun(void)
{
    printk("<1>Hello,World! from the kernel space…\n");
    return 0;
}

static void __exit exit_fun(void)
{
    printk("<1>Goodbye, World! leaving kernel space…\n");
}

module_init(init_fun);
module_exit(exit_fun);
MODULE_LICENSE("GPL");    

Makefile

obj-m := hello.o

KERNELDR := /home/zs0zrc/linux-4.1.1

PWD := $(shell pwd)  

modules:  
    $(MAKE) -C $(KERNELDR) M=$(PWD) modules  

moduels_install:  
    $(MAKE) -C $(KERNELDR) M=$(PWD) modules_install  

clean:  
    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

然后编译,将编译后的得到的ko文件放入 _install目录下,并修改init文件。重新打包一下镜像

1549013935556

最后用qemu运行,可以发现多出了模块的输出

1549014072043

reference


Linux_Kernel      pwn kernel

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!