天天看点

linux内核漏洞利用初探(1):环境配置!!!注意

主要记录一下学习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文件,首行指定init初始化脚本,可以执行shell,一般ctf题是执行根目录下的"init",初始化网络、创建flag、指定权限等等:

$ 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 cannary:

编辑.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

继续阅读