天天看點

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

繼續閱讀