The module disable write protection, and replace original syscall such as sys_open to sys_open_hooked by write syscall table(0xc15fa020).
The sys_open_hooked syscall will check whether the string of the filename has a flag substring. If there not, then the original sys_open is called. If there is, it returns a fd with a value of -1, then the file opening failed.
Of cource, other sys_call such as sys_symlink will failed also.
1 2 3
/tmp # ln -s ../flag ./ [ 5234.521789] You will not see the flag... ln: ./flag: Operation not permitted
Thanks to pwnable.kr, we are login as root :), mean that we have permission to load a custom kernel module by command insmod.
/tmp # uname -r 3.7.1
I tried to compile a new kernel module to restore the original sys_open address to the sys_call_table, but it failed, because of some reason(maybe my GCC is too new, maybe the kernel 3.7.1 is too old, I really don’t know).
So, I decided to patch the .ko file directly:
Patching the module name, so that the kernel allows the new module be loaded.
Patching the flag string, then opening the flag file will no longer trigger substring verification.
Patching the way to get the original sys_open address, because the sys_open address in syscall table was modified by the module rootkit.
sed 's/rootkit/tiktoor/g' -i rootkit.ko
sed 's/flag/galf/g' -i rootkit.ko
get the original sys_open
/proc/kallsysms have symbols of dynamically loaded modules as well static code, we should read sys_open address from /proc/kallsyms instead of the syscall table.