My Kernel Notes (Old)
I had some notes from a while back, here is a dump of them. It is very disorganised and not meant to be pedagogical.
my kernel exploration
Run the following as root
make
insmod hello-1.ko
dmesg -w # preferably in another window
rmmod hello-1.ko
make clean
git status
for the char device testing
make test
./cdev_test
make clean
For inverting screen colors
apt install libx11-dev libxxf86vm-dev libxrandr-dev
make invert
If things don’t work, try
sudo systemctl restart display-manager
xhost +
Writing assembly
gcc -S helloworld.c # compiler
vim helloworld.s # modify stuff
gcc helloworld.s # assembler and linker
./a.out
Compile the kernel
Method 1 (worked for me)
# download from kernel.org
apt install -y libncurses5 libncurses5-dev bison flex
make menuconfig
vim .config # remove debian things
apt install -y libssl-dev libelf-dev
make -j2
make modules_install
make install
Method 2 (didn’t work for me)
apt-get source linux-image-`uname -r`
cd folder
fakeroot debian/rules clean
Cross compiling the kernel
Getting binutils and gcc from apt
Do this if you’re a noob
apt-get install binutils-riscv64-linux-gnu gcc-riscv64-linux-gnu
riscv64-linux-gnu-ld --version
riscv64-linux-gnu-gcc --version
Building binutils from source
export TARGET=aarch64-unknown-linux-gnu # replace with your intended target
export PREFIX="$HOME/opt/cross/aarch64" # replace with your intended path
export PATH="$PREFIX/bin:$PATH"
wget ftp://ftp.gnu.org/gnu/binutils/binutils-2.29.1.tar.xz
tar -xf binutils-2.29.1.tar.xz
cd binutils-2.29.1
./configure \
--target=$TARGET \
--prefix=$PREFIX \
--with-sysroot \
--disable-nls \
--disable-werror
make
make install
$TARGET-ld --version
Cross compiling the kernel
make ARCH=riscv O=kernel_build defconfig
export TARGET=aarch64-unknown-linux-gnu-
make ARCH=riscv CROSS_COMPILE=$TARGET modules
Contributing to mailing list
git clone --depth=1 https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git/
cd bluetooth-next
# compile kernel as per usual
git checkout <for-next>
# obtain patch from email
git am update.patch
patch -p1 < update.patch # do this cos git apply doesnt work (insert 1h of vulgarities)
git am --continue
Make our initramfs
Either use
$ mkinitramfs -o ramdisk.img # doesn't work right now
OR make your own
$ mkdir vfs && cd vfs
$ cat << EOF > hello-kernel.c
#include <stdio.h>
int main(){
printf("Hello, kernel!\n");
sleep(9999999999999);
}
EOF
$ gcc --static hello-kernel.c -o init
$ find . | cpio -o -H newc | gzip > root.cpio.gz
Making a hard disk (for root)
$ dd if=/dev/zero of=roorfs.ext2 bs=1024k count=256
$ mkfs.ext2 rootfs.ext2
Booting
# for booting hello-kernel
$ qemu-system-x86_64 -kernel arch/x86/boot/bzImage -nographic --append "console=tty0 console=ttyS0 panic=1 root=/dev/sda rootfstype=ext2" -hda rootfs.ext2 -m 1024 -vga none -display none -serial mon:stdio -no-reboot -initrd vfs/root.cpio.gz
# for booting busybox
$ qemu-system-x86_64 -kernel arch/x86/boot/bzImage -nographic --append "console=tty0 console=ttyS0 panic=1 root=/dev/sda rootfstype=ext2" -hda rootfs.ext2 -m 1024 -vga none -display none -serial mon:stdio -no-reboot -initrd initrd/root.cpio.gz
# qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -initrd vfs/root.cpio.gz -nographic --append "console=tty0 console=ttyS0 panic=1" -m 512 -vga none -d isplay none -serial mon:stdio -no-reboot
# qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd vfs/root.cpio.gz -nographic --append "console=tty0 console=ttyS0 panic=1 root=/dev/sda" -hda rootfs.ext2 -m 512 -vga none -display none -serial mon:stdio -no-reboot
My own init works now
Running the Kernel on Hardware
If you’re on ubuntu, you can do
$ update-grub2 # make sure you're using the grub bootloader
$ make modules_install
$ make install
When booting up, press and hold <Shift>
to go to the grub menu, then go to advanced options to select the kernel you want to boot with.
#Debugging the Kernel using GDB
Using instructions from here
vim .config # edit some stuff
make -j32
Running time!
qemu-system-x86_64 -gdb tcp::1234 -S # the rest of the stuff
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -nographic --append "console=tty0 console=ttyS0 panic=1 root=/dev/sda rootfstype=ext2 nokaslr" -hda rootfs.ext2 -m 1024 -vga none -display none -serial mon:stdio -no-reboot -initrd initrd/root.cpio.gz -gdb tcp::1234 -S
target remote :1234
continue
Use ^C
to SIGINT the kernel.
Interrupting Startup
target remote :1234
hbreak start_kernel
i b # info breakpoints
c
Looking at the proces struct
(gdb) lx-ps
TASK PID COMM
0xffffffff828169c0 0 swapper
(gdb) p ((struct task_struct *) 0xffffffff828169c0)
$11 = (struct task_struct *) 0xffffffff828169c0 <init_task>
(gdb) p $11->pid
$13 = 0
Interrupts
The first impt thing to do is learn how to interrupts work
(gdb) monitor info registers
(gdb) set $idtr=0xfffffe0000000000
(gdb) print /x *(uint64_t*)$idtr
$15 = 0x81e08e00001008f0
(gdb) define idt_entry
>set $tmp = *(uint64_t*)($idtr + 8 * $arg0)
>print (void *)(($tmp>>48<<16)|($tmp&0xffff))
>end
(gdb) set $i=0
(gdb) idt_entry $i++
System calls
Let’s pay some attention to
syscalls_64.h
and arch/x86/entry/syscall_64.c
.
The syscall_64.c
file generates code using extern
.
The definition for the function is provided by the
fs/read_write.c
. Namely,
SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence)
{
return ksys_lseek(fd, offset, whence);
}
Pwn stuff
gdb a.out
disassemble main
r
si
show reg
^x ^a # to open up TUI mode
layout next # use the assembly view
Bypassing license key
break main
r a
ni # until the 2nd jne
set $eflags ^= (1<<6)
c
Format string (stonks)
just spam %x
to print stuff on the stack
Buffer Overflow (buffer overflow 1)
It seems like get_return_address()
is an internal picoCTF function in asm.h
source.
Using Radare2,
aaa
s main
ood
pd
VV p
dc
<F7> # to step
. # to return to %rip
Cache me outside
Attempting the picoctf challenge. Binary will not execute because it has the wrong libc