VDSO hijacking
mitre T1055.014
這是 mitre 上面提到的 linux 獨有的 process injection 方式,不過從 reference 來看好像沒有已知的攻擊是用這種方式(我覺得是太麻煩的緣故 XD),但他的確是一個可行的攻擊技巧
作者原文
本質上是透過 ptrace
達到加載 shared library 和修改 GOT table 達到劫持的目的
kernel pwn 的 vdso hijacking
如果直接 google vdso hijacking ,可能會找到某個 kernel pwn 的題目,雖然都叫 vdso hijacking ,但兩者可以說是天差地遠,一個是在 kernel 層去修改 vdso 的執行流程,另一個則是在 user space 透過 ptrace 去攔截 syscall 並加以利用
其實對 vdso hijacking 這個技術的講解看上面的作者原文就夠了,畢竟根本沒什麼人在討論這個手法,大概也找不到其他比較有價值的文章
攻擊流程
這個攻擊很大部分是在繞過一個叫 GRSEC 的 kernel patch ,他的功用影響比較大的有:
- NX protection
- maps file blank
- 不確定 blank 是 blank 哪些地址還是全部都 blank
- 從文中來看 process 載入地址應該是固定的,可能是 2009 年 PIE 技術還不流行
NX 是現在 linux 發行版應該都有的保護, maps file blank 就比較麻煩,不過我沒花時間去弄這個 patch …
- 透過讀取
/proc/<pid>/maps
拿到 process 地址資訊
- 如果拿不到地址,我覺得 x86 環境下用 ptrace + egg hunter 技巧慢慢找應該還是找的到
- 利用地址資訊和 parsing elf 的格式,找到 got 地址
- 用
ptrace
attach program
- 利用
PTRACE_SYSCALL
在進入離開 syscall 會被暫停的功能找到位於 vdso 的 sysenter
- x86 模式下暫停的時候 pc 暫存器位在 vdso sysenter 指令附近
- x64 應該就直接停在 libc 的 syscall 附近
- 因為指令不是固定的,定位起來比較麻煩,但用 ptrace 的讀取前面的記憶體加上反組譯應該還是找的到
- 保存本來要送去 syscall 的暫存器資料
- 將暫存器改成 open shared library 並且執行 sysenter
- 將暫存器改成 mmap shared library 並且執行 sysenter ,執行後拿返回的 mmap 地址,這個是 shared library 地址
- 這步驟要執行兩次,一次是 mmap text segment ,另一次是 data segment ,因為權限不同所以要分開執行
- 回復之前保存的暫存器並執行 sysenter
- 在 tracee process 裡面搜尋想要執行的 evil function 地址
- 保存 tracee process 中想要攔截的 GOT 地址
- 將 GOT 地址改成 evil function
- Full relro 的話會失敗,不過 process 內應該很多 function pointer 可以 hijack
- 將 evil function 結尾修改成步驟 10 保存的 GOT 地址
- 結束
對 code 的修正
作者給的 code 不知道是在哪個環境下實驗的,我用 ubuntu 20.04 或是 9.04 都執行失敗,推測應該是編譯器編譯出來的 machine code 長的不一樣導致,建議自己根據自己的環境編譯出來的 code 做修改,以下提到幾個要改的部分:
- tracee text segment 在 ubuntu 20.04 下 offset 不再是 0x0
- mmap 第一個地址盡量自己指定
- 我遇到不指定地址,結果第一個 text segment 被 map 到 libc 和 ld 中間,導致後續 data segment 和 text segment 不連續,這樣會在之後定位 evil function 的步驟出了點問題(不過看起來可以來硬的寫死在裡面)
- evilsig
- 其實就是 evil function 前幾個 bytes ,因為編譯器關係長的會跟文中的 code 不一樣
- tc
- 這個 array 是放 evil function 要跳轉回正常 function 的 machine code ,同樣會因為編譯器關係導致偏移不一樣