主要记录一下学习muhe师傅的系列教程,记录其中的坑点。 muhe师傅的教程是在32位ubuntu环境下测试的,本文是在64位环境下测试,有很多地方需要修改,故记录本文,以供后来者学习。
附件在文末下载。

环境说明:

内核版本2.6.32.1
busybox版本1.19.4
gcc版本4.7
实验环境ubuntu16.04 64位

1.更新gcc

内核2.6.x只支持gcc 3.x和4.x.y,可能是较高版本的gcc不支持老版本kernel的某些语法格式。
gcc下降:

sudo apt-get install -y gcc-4.7
sudo apt-get install -y g++-4.7
# 重新建立软连接
cd /usr/bin    #进入/usr/bin文件夹下
sudo rm -r gcc  #移除之前的软连接
sudo ln -sf gcc-4.7 gcc #建立gcc4.7的软连接
sudo rm -r g++  #同gcc
sudo ln -sf g++-4.7 g++

安装依赖:

$ sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc qemu qemu-system
$ sudo apt-get install bison flex libncurses5-dev

2.下载源码

官网:https://mirrors.edge.kernel.org/pub/linux/kernel/
国内镜像(速度超快):https://mirrors.tuna.tsinghua.edu.cn/kernel/

# 最好还是从国内镜像上下载
$ wget https://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.32.1.tar.gz -O linux-2.6.32.1.tar.gz
$ tar -xvf linux-2.6.32.1.tar.gz

3.编译过程

$ cd linux-2.6.32.1/
$ make menuconfig
$ make
$ make all
$ make modules

问题1:
include/linux/compiler-gcc.h:86:30: fatal error: linux/compiler-gcc5.h: No such file or directory
include/linux/compiler-gcc.h:86:1: fatal error: linux/compiler-gcc9.h: No such file or directory
解决1-1:
https://blog.csdn.net/u014525494/article/details/53573298
把当前linux系统/usr/src的compiler-gcc.h拷贝到要编译的linux源码目录中。
$ cp /usr/src/linux-headers-4.4.0-103-generic/include/linux/compiler-gcc.h ./linux-2.6.32.1/include/linux/compiler-gcc5.h
还是报错。
解决1-2:
原因:编译的内核版本比较低,而gcc版本比较高。
gcc下降到4.7。 貌似没有问题了。

问题2:
遇到文中所说的4个问题,可能是老版本内核代码有问题,对照以下一一解决即可。(除了第2个问题)
https://www.anquanke.com/post/id/85837

4.增加syscall

https://o0xmuhe.github.io/2017/02/08/Adding-your-own-syscall-in-linux-kernel/
https://arvindsraj.wordpress.com/2012/10/05/adding-hello-world-system-call-to-linux/
(1)在syscall table中添加信息
文件arch/x86/kernel/syscall_table_32.S中添加自己的调用

.long sys_muhe_test
.long sys_hello

(2)定义syscall的宏
32位
文件arch/x86/include/asm/unistd_32.h中添加

#define __NR_hello 337
#define __NR_muhe_test 338
#ifdef __KERNEL__
#define NR_syscalls 339

要注意NR_syscalls要修改成现有的调用数目,比如原来有0~336一共337个调用,现在增加了两个,那就改成339。

64位
修改arch/x86/include/asm/unistd_64.h

#define __NR_hello 299
__SYSCALL(__NR_hello,sys_hello)
#define __NR_muhe_test 300
__SYSCALL(__NR_muhe_test,sys_muhe_test)

(3)添加函数定义
文件include/linux/syscalls.h

asmlinkage long sys_muhe_test(int arg0);
asmlinkage long sys_hello(void);

(4)编写syscall代码
新建目录放自定义syscall的代码,./linux-2.6.32.1/muhe_test

# muhe @ ubuntu in ~/linux_kernel/linux-2.6.32.1/linux-2.6.32.1/muhe_test [2:43:06] 
$ cat muhe_test.c
#include <linux/kernel.h>
asmlinkage long sys_muhe_test(int arg0){
    printk("I am syscall");
    printk("syscall arg %d",arg0);
    return ((long)arg0);
}
asmlinkage long sys_hello(void){
    printk("hello my kernel worldn");
    return 0;
}
# muhe @ ubuntu in ~/linux_kernel/linux-2.6.32.1/linux-2.6.32.1/muhe_test [2:43:12] 
$ cat Makefile
obj-y := muhe_test.o

(5)修改Makefile

# muhe @ ubuntu in ~/linux_kernel/linux-2.6.32.1/linux-2.6.32.1 [2:44:59] 
$ cat Makefile| grep muhe
ifeq ($(KBUILD_EXTMOD),)
core-y      += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ muhe_test/

!!!!!!注意:这一句一定要修改原句“core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/”。

(6)编译

$ make -j2

5.busybox编译配置

(1)编译步骤
大坑:make menuconfig时一定要选择静态编译。

$ make menuconfig
$ make
$ make install

(2)报错
busybox1.19版本会出错,修改两处即可;用最新的1.31没报错。
(2-1)问题:linux/ext2_fs.h: 没有那个文件或目录
make menuconfig时 Linux System Utilities ---> 选空[ ] mkfs_ext2 和 [ ] mkfs_vfat
(2-2)问题:‘RLIMIT_FSIZE’ undeclared
$ vim include/libbb.h 添加#include <sys/resource.h>

(3)配置
(3-1)方案1

$ cd _install
$ mkdir -pv {bin,sbin,etc,proc,sys,usr/{bin,sbin}}
$ cat init
#!/bin/sh
echo "INIT SCRIPT"
mount -t proc none /proc
mount -t sysfs none /sys
mount -t debugfs none /sys/kernel/debug
mkdir /tmp
mount -t tmpfs none /tmp
mdev -s # We need this to find /dev/sda later
echo -e "nBoot took $(cut -d' ' -f1 /proc/uptime) secondsn"
exec /bin/sh
$ chmod +x init
$ find . | cpio -o --format=newc > ../rootfs.cpio
$ qemu-system-x86_64 -kernel ./arch/x86/boot/bzImage -initrd ../rootfs.cpio

问题:总是报错——kernel panic - not syncing no init found. try passing init= option to kernel
解决:用ctf题中的clio文件就能正常运行,应该是busy box的问题。只要make menuconfig的时候选择静态编译就行(Busybox Settings -> Build Options -> Build BusyBox as a static binary),因为在这里我们希望生成的文件不对当先主机系统的共享目录产生依赖,我们希望生成的文件时静态库文件而非是动态库文件。
http://www.dataguru.cn/thread-475271-1-1.html

(3-2)方案2
目录结构和之前差不多,添加inittab文件:

$ cat etc/inittab 
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/ash
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
::restart:/sbin/init

添加rcS文件

$ cat etc/init.d/rcS 
#!/bin/sh
#!/bin/sh
mount -t proc none /proc
mount -t sys none /sys
/bin/mount -n -t sysfs none /sys
/bin/mount -t ramfs none /dev
/sbin/mdev -s
$ chmod +x ./etc/init.d/rcS

配置下dev目录

$ mkdir dev
$ sudo mknod dev/ttyAMA0 c 204 64
$ sudo mknod dev/null c 1 3
$ sudo mknod dev/console c 5 1
$ find . | cpio -o --format=newc > ../rootfs2-1.img
$ qemu-system-x86_64 -kernel ./arch/x86/boot/bzImage -initrd ../rootfs2-1.img -append "root=/dev/ram rdinit=/sbin/init"

6.测试系统调用

$ cat muhe_test_syscall_lib.c
#include <stdio.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
int main(int argc,char **argv)
{
        printf("n Diving to kernel levelnn");
        syscall(300,1337);
        return 0;
}
$ gcc muhe_test_syscall_lib.c -o muhe -static

一定要静态链接,因为你进busybox链接库那些是没有的。

$ cp muhe_test_syscall_lib/muhe ../busybox-1.19.4/_install/usr/muhe
$ find . | cpio -o --format=newc > ../rootfs_test_syscall.img
$ qemu-system-x86_64 -kernel ./arch/x86/boot/bzImage -initrd ../rootfs_test_syscall.img -append "root=/dev/ram rdinit=/sbin/init"

报错:
/bin/sh can't access tty job control turned off
解决:
https://blog.csdn.net/qq_26093511/article/details/53464468
加上这一句:console::askfirst:-/bin/sh (注意:我之前写的是console::askfirst:/bin/sh,缺少了-,所以才报错)。因为,uboot的启动参数指定了console = ttySAC0 ,也就是串口控制台。所以要在/bin/sh 前加 - 。


!!!注意

鼠标退出QEMU界面:

ctl+alt+鼠标点击

保护机制关闭方法:

mmap_min_addr:
$ sysctl -w vm.mmap_min_addr="0"
kernel canary:
编辑.config文件,注释掉CONFIG_CC_STACKPROTECTOR这一行,再重新编译内核。

编译driver:

1.为了能够加载自己写的driver
编译内核时make menuconfig -> Enable loadable module support ->Forced module loading 关闭Source checksum for all modules
$ make
2.编译driver时的Makefile
本机编译时指向/usr/src/linux-headers-4.4.0-103-generic
测试qemu时指向下载的kernel源码目录,如~/Desktop/kernel/linux-2.6.32.1/


参考:

https://www.anquanke.com/post/id/85837
https://www.anquanke.com/post/id/85840
https://www.anquanke.com/post/id/85848

file.zip (1.982 MB) 下载附件
点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖