we can see that KASLR, SMEP and KPTI is enabled but not SMAP.
now let's take a look at the challenge, thankfully the author has provided us with the kernel module source code. we can interact with the module through the IOCTL interface
this one uses the plain printk() without any log level (i.e. KERN_INFO, KERN_DEBUG etc), which prints to the program's stdout that provoke it instead of kernel log through dmesg.
staticlongcamping_greet(unsignedlong arg) {char hello[]= KERN_ALERT "camping: Hello, ";char greeting[BUFFER_SIZE +sizeof(hello) +1];memcpy(greeting, hello,sizeof(hello));memcpy(greeting +sizeof(hello) -1,visitor.name, BUFFER_SIZE);printk(greeting);printk(KERN_INFO "camping: I see you're ready for an adventure, let's visit a nice campsite! :)\n");return0;}
KVISIT
visit copies the decoration field to the address at location.
staticlongcamping_visit(unsignedlong arg) {printk(KERN_INFO "camping: So you want to visit that campsite huh, okay here we go!\n");if (!access_ok((void __user *)visitor.location, BUFFER_SIZE)) {printk(KERN_ALERT "camping: Sorry, that campsite is not open yet! ~_~\n");return-EFAULT; }printk(KERN_INFO "camping: It looks a bit plain... let's add some decorations!\n");int len =strnlen(visitor.decoration, BUFFER_SIZE);for (int i =0; i < len; i++) {if (!isalnum(visitor.decoration[i])) {printk(KERN_ALERT "camping: That decoration is... a bit questionable?\n");return-EINVAL; } }printk(KERN_INFO "camping: Decorating...\n");memcpy((void __user *)visitor.location,visitor.decoration, len +1);printk(KERN_INFO "camping: Done! Your campsite is now beautifully decorated :)\n");printk(KERN_INFO "camping: Enjoy your camping experience!\n");return0;}
there are two function that I'm not familiar with here, first is access_ok()
access_ok -- Checks if a user space pointer is valid
which means the location field has to be an address within the user space.
second is isalnum() but I decided to take it for granted for its self explanatory name.
Exploitation
the first thing I take attention of is KASLR, one thing I took notice is printk(greeting); in KGREET which seems to be a format string vulnerability. so I took it to the test
However, even though I kinda already grasp the overall challenge and how to exploit it, this is ultimately where I got stuck because the address leak that we got from is somehow cropped
and so I thought I could use the f'%{offset}$p' format but as I test it, it doesnt seem to work. reading the printk's format documentation it does seems that the $ is not applicable
days after, I realized that is it actually being printed and can be shown if I resize the terminal. it seems that the kernel prints without taking the terminal's dimension into account and not wrap it around as shown in the picture below
after the the competition had ended the challenge author told us that he uses newline (of course, why didn't I think of that) for the work around on this problem and it definitely worked
intmain(int argc,char*argv[]){// ... snippetfor(int i =0x0; i < BUFFER_SIZE/4; i++) {strcat(payload.name,"%lx\n"); }// ... snippet}
I took the address with the higher address i.e. ffffffff00000000 and try to find it's offset from the kernel base.
to make sure it's reliable and not affected by FG-KASLR, I tried running it multiple times and making sure the offset is not changed.
next, using stdin we'll take the address and calculate the kernel base
next to get the flag, we'll going to use modprobe technique, I won't explain it in depth since there are other people who had done the job better than I could've had linked below:
first let's get the modprobe_path address and its offset (also as previously, double check to make sure its not affected by FG-KASLR)
to exploit it, we would need to have arbitrary write primitive, we could've easily had this through KVISIT:
while the other thread will continuously swap the values of location to satisfy access_ok() and decoration to satisfy isalnum() in the hopes that the race will satisfy both of the checks while contains our payload to overwrite modprobe by the time memcpy is called.