Debugging a kernel challenge.
This post is created so that I can come back if I forget how to do any of these. Also someone might find it useful someday.
These are the steps that I take when I get a kernel challenge during a ctf. I will
be using the challenge Sharedhouse
from ASIS 2020 Quals. Pretty much the same steps
apply for any other challenge.
Given Files
Let’s see what all files are provided to us.
- bzImage: Compressed kernel linux kernel. We can extract it using this.
- rootfs.cpio: This is used as the file system by the kernel. The vulnmod is likely to be inside it.
You can extract it using the following:
$ file rootfs.cpio
rootfs.cpio: ASCII cpio archive (SVR4 with no CRC)
$ mkdir rootfs && cd rootfs
$ cat ../rootfs.cpio | cpio --extract
- start.sh: Script that runs qemu with the proper parameters.
#!/bin/sh
qemu-system-x86_64 \
-m 256M \
-kernel ./bzImage \
-initrd ./rootfs.cpio \
-append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 kaslr pti=off quiet" \
-cpu qemu64,+smep \
-monitor /dev/null \
-nographic
We can see that only kaslr and smep are enabled and smap and kpti are disabled.
rootfs
If we check inside the rootfs, we can see that the module named note.ko
is given.
Another file we have to looks at is the init
file. This is a script that changes
the permission of files and then inserts the module.
First thing I does is remove the folllowing lines from the init
. It might
not be the same for other challenge.
echo 1 > /proc/sys/kernel/kptr_restrict
echo 1 > /proc/sys/kernel/dmesg_restrict
This will help later when we want to view dmesg
and /proc/kallsyms
. Another thing
to change is the start.sh
. Change the kaslr
to nokaslr
and add -s
as another
parameter. First one disables kaslr which will be really useful when we want to debug
and the -s
option creates a gdb server at localhost:1234
which we will use to debug
the module. For ease of use, we can compile our exploit and put it in the rootfs directory,
compress it and use.
$ cd rootfs
$ find . | cpio -o -H newc > ../rootfs.cpio
GDB
Extract the kernel using the extract.sh
./extract.sh ./bzImage > vmlinux
Now we can open it in gdb. Before doing that, run the start.sh
.
gdb ./vmlinux
Now we connect to the server using target remote: 1234
.
If we want to set breakpoints in the module, we have to add it in gdb.
To do this, we need the base address of the module.
/ # cat /proc/modules
note 16384 0 - Live 0xffffffffc0000000 (O)
/ #
After this, run the following from gdb.
add-symbol-file note.ko 0xffffffffc0000000
Sometimes we might need address of some functions. To get this, we can use the /proc/kallsyms
and
grep
it’s contents. Also it is better to do everything while you are root and then change it
once your exploit is finished. To change this, change the id
set by init
by editing the init
.
Conclusion
This post was about how to start debugging a kernel challenge in a ctf. Exploitation of the challenge will depends on the challenge. But the initial steps should be similar to what I have said.
Let me know what you think of this article on twitter @3agl31!