Linux Kernel pwn
Inspection
取得 symbol address
方便下斷點觀察
從 bzImage 萃取 vmlinux
取得 vmlinux 後, 就能再用 ROPgadget 取得各種 gadget
使用 Linux 內建的腳本 extract-vmlinux 就能完成
取得 gadget
- 對 vmlinux 用 ROPgadget 即可, 注意要設定 range 以取出有執行權限的 gadget
- 用 ropper 跑比較久, 但比較準
ropper --nocolor --file ./vmlinux > ropper_gadget
取得 kASLR offset
若有啟用 kASLR, 則還需要換算 gadget address
取得 memory info
查看 slab/slub 記憶體分配資訊
防禦機制
SMEP
- Kernel 不能執行 user code
- 紀錄在 cr4
SMAP
- Kernel 不能讀寫 user memory
- 紀錄在 cr4
KPTI
- 效果類似 SMEP + SMAP
- 拿來擋 meltdown 的 side channel attack
- 回 user mode 時要修 cr3
- 可以呼叫
swapgs_restore_regs_and_return_to_usermode
這個 function, 直接幫你修好 cr3
常用 structure
tty_struct
(0x2e0, 0x2c0) base, heap
- 定義
- Allocate
int pfd = open("/dev/ptmx", O_RDWR|O_NOCTTY);
- Release
- Write
write(pfd, garbage, sizeof(garbage)
- Control flow
- 控制
tty_operations
vtable, 有機會控執行流
- 相關 offset
- offset 0: 需要為 MAGIC
- offset 0x18: 為 tty_operations 結構, 以下是此結構 offset
- offset 0x56: 為 write 的 function pointer
shm_file_data
(0x20) base, heap
seq_operations
(0x20) base
msg_msg
(0x30 ~ 0x1000) heap
subprocess_info
(0x60) base, heap
- 參考
Common Vulns
Double fetch
- kernel space 和 user space 的 race condition
- kernel 存取兩次同樣的 user space data, 之間產生 race condition 的空隙 (第一次存取給你 A, 第二次存取給你 B)
各種 Exploit
提權
- 執行到 commit_creds(prepare_kernel_cred(0)) 完成提權
- 回到 user mode
- 並執行 /bin/sh
- iretq 排好 gadget, 依序是
- rip
- user_cs
- user_eflags
- user_sp
- user_ss
- 可用以下函數儲存使用者暫存器
modprobe_path
- 其為 kernel global variable
/proc/sys/kernel/modprobe
- 執行一個 kernel 認不得的執行檔格式時, kernel 會去執行
modprobe_path
字串所寫的程式
- trace code 流程
- sys_execve
- do_execve
- do_execveat_common
- bprm_execve
- exec_binprm
- search_binary_handler
- request_module
- call_modprobe
- call_usermodehelper_exec
- 利用方式
- 改掉 modprobe_path, 改成自己的惡意程式
- 執行一個不是執行檔的東西, 讓 kernel 認不得
- kernel 就會去執行你的惡意程式 :)
- 利用方式 2
- 但是改掉後繼續跑會 panic
- 沒關係, 改掉後讓程式進無窮迴圈就好, 讓程式在背景執行
- 不會炸裂 + 還是有改到
modprobe_path
- 補充冷知識
setxattr & userfaultfd
userfaultfd
- 為某段記憶體註冊 page fault handler
copy_from_user
copy_to_user
也會踩到 page fault
- 製造 race condition
setxattr
- 注意裡面調用
kvmalloc
copy_from_user
kfree
的部分
- 任意時機調用
kvmalloc
(size 1 ~ 0x10000)
- 會從 user land 複製 data 到 chunk (
copy_from_user
)
- 搭配
userfaultfd
可以任意控制 kfree
時機
mmap
- 可以用
mmap
申請記憶體
- 配合類似
mov esp, eax
的 gadget, 讓 stack migrate 到 mmap
申請到的空間, 在只能控一次執行流時, 能以此將問題變成 ROP
- 使用範例
signal
- 回到 user mode 卻發生異常?
signal(SIGSEGV, get_shell);
Other notes
current gs:off_14D00
Kernel 中用 current
代表著現在的 task
查看以下 code
(v4.19.98| __do_page_fault#1206)
其對應的 x64 組語如下
可以看得出來 gs:off_14D00
就存著 current
gdb debug
- 若 module 有帶 symbol, 可以這樣 load symbol
Source code tracing
copy_from_user -> … -> copy_user_generic
cpio
./compile_exp_and_compress_cpio.sh exploit.c
Kernel Memory Layout