kernel-tips
Basic information
exploit technique
ret2user
Execute a prepared function from kernel space to run the function with kernel privileges. Call functions like commit_cred(&init_cred) to perform LPE. When returning from kernel to user space, the instructions swapgs
and iretq
should be executed. swapgs
swaps the contents of the GS register between kernel and user mode. The iretq
instruction pops values from the stack in order and sets them to the RIP, CS, rflags, RSP, SS
registers to return to user space. Therefore, the function called from kernel should have the following stack structure before calling iretq
to return to user space.
Created LPE and ret2user based on https://pawnyable.cafe/linux-kernel/LK01/stack_overflow.html. tips: Assembly functions in C language
SMEP can be disabled by updating the CR4 register value, so it's possible to perform ret2user after disabling CR4 through ROP. https://ctf-wiki.org/pwn/linux/kernel-mode/exploitation/rop/bypass-smep/
Kernel Return Oriented Programming
When KPTI is disabled, there's no need to update the CR3 register, so LPE can be achieved by constructing the following chain:
Kernel Return Oriented Programming kpti trampoline
To bypass KPTI, swapgs_restore_regs_and_return_to_usermode
to construct a ROP chain that bypasses KPTI. Refer to the article for detailed call stacks, and construct the following ROP chain. During the process, there are pop rax and pop rdi instructions, so add 128-bit padding. The symbol swapgs_restore_regs_and_return_to_usermode
is publicly available and can be found in /proc/kallsyms
.
tips
Identifying kbase
Identifying init_cred
Since Linux kernel 6.2, NULL cannot be passed to prepare_kernel_cred. Therefore, LPE using the above method is no longer possible.
The solution is simple - use the above method instead.
However, since the address of init_cred cannot be directly identified from a stripped vmlinux, it's easier to trace from somewhere where symbols are exported. Verified on linux kernel 6.9.12.
init_cred-elixir- Followed the following xRef using elixir:
When examining the instructions of kernel_read_file_from_path_initns
in IDA, the rdi passed to the first call instruction is init_task.fs
.

The task_struct looks like this, and from here the offset of init_cred can be determined. According to the task_struct structure, near fs, there exists a string called comm and real_cred and cred that hold init_cred. comm is a distinctive byte sequence, making it quite easy to identify.
Identifying modprobe_path
This modprobe_path
is also a global variable used in exploits. modprobe_path By rewriting it to a path of a prepared eval script, it can be executed with kernel privileges. Note that modprobe_path was removed in a commit in the latter half of 2024. https://theori.io/blog/reviving-the-modprobe-path-technique-overcoming-search-binary-handler-patch
Since direct identification from a stripped vmlinux is impossible, here's a memo on how to identify modprobe_path.
__request_module
has its symbol exported and references modprobe_path, so it should work. Get the address of __request_module from kallsyms
and disassemble it with gdb.


The usage location of modprobe_path is in the following validation, and as shown, looking at the cmp BYTE PTR [], 0x0
instruction reveals the address of modprobe_path.
Identifying core_pattern
Assembly functions in C language
The asm()
function included in stdlib.h
is written as follows:
volatile
Prevents optimization.
output operand
Used to return the execution result of assembly instructions to variables.
Format is "constraint"(variable), for example
"=r"(dest)
meansoutput value using any register and put that value into variable dest
.= indicates write-only.
Reference assembly and output operands with %n (%0,%1,...).
input operand
Specifies variables to be used within assembly instructions.
Format is
"constraint"(variable)
, for example"r"(src)
meansplace variable src in any register
.
assembly
Write assembly code.
%0
etc. used to reference input operands and output operands are continuous from input operands -> output operands.