主要記錄一下學習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