Hello everyone, this will be a solution for a root-me challenge. The challenge is null pointer dereference in linux kernel through a module.
I grabbed this opportunity to make this in rust, so i can get more familiar and better at it since i was debating with myself what should i learn? C or Rust? I ended up with Rust. Let’s explain vulnerability. So for null pointer deref vulnerability to exist, a developer must point after some action to NULL. Basically by being able to trigger the function to go to NULL, if we already have mapped the 0x00000000 page of the memory and put some delic.. i mean malicious code then it will be executed.
Source code is already provided for us from the module, so we can track, detect and exploit. Below we see the important parts of the code, so we can trigger the vulnerability.
Latest highlight say that for the whole thing to happen and somehow point the execution to NULL, we need to actually read the device. This will be the last step before executing an actual escalated shell. To actually manage and get to the vulnerable line(l.199), we need to actually write on the device according to the first highlight. Writing to the device is as simple opening it and send some data. The name of the device is called tostring and it can be found at /dev/tostring path. In the picture, there is a function copying from user space to kernel space. We need to have the right input to be able to lead the execution the l.199. For this to happen the input requires as to send 10 asterisks acccording to the highlight of the for loop. In addition, we need to set after the asterisks, S, as it will get us into the S case and the vulnerable function and last but not least a null byte at the end. If we will be able to send this plus our shellcode then we should be done! Now questions is what kind of shellcode do we send? According to the “linux msdn”, there are 2 functions that are always being called to assign the correct privileges in the linux system commit_creds() and prepare_kernel_cred(). We would need to find the addresses of these 2 functions, simple task to achieve indeed.
Now we need to write the shellcode accordingly. The shellcode basically needs to do commit_creds(prepare_kernel_cred(0)) . Shellcode:
xor eax,eax call c10711f0 <—-prepare_kernel_cred() call c1070e80 <—-commit_creds() ret
We null the eax, so it will be passed as a parameter to prepare_kernel_cred according to the calling convention and then, call commit creds as well with the return value of the prepare_kernel_cred to assign the 0 privileges aka root privileges.
By assembling the above assembly, you will get this shellcode: “\x31\xc0\xe8\xe9\x11\x07\xc1\xe8\x74\x0e\x07\xc1\xc3”
Now for the exploit part in rust:
And the result in the actual server is: