2025 TRX CTF - /dev/mem - part 2
Author : 堇姬 Naup
前言
繼承上一篇
https://naupjjin.github.io/2025/04/11/Linux-Kernel-2025-TRX-CTF-devmem/
這邊來講講另一個思想
analyze
這次主要針對 /usr/sbin/chall,先放一下他的保護機制,沒有開 PIE
並且他是 static linking
再來去檢查這個 binary 發現他有 SUID
1 | ~ # ls -l /usr/sbin/chall |
他在跑的時候他會用 root 權限來去執行他
因為 chall 會去針對 /dev/mem 來去做操作
/dev/mem 是 Linux 提供的一個字符設備,映射了系統的物理記憶體(主記憶體)整體空間
這個 driver 既然是針對 physical address 來做操作的,其 binary 必定需要高權限
另外 qemu 環境內通常不會有 libc,所以題目的 ELF 也必然包成了 static
這就讓這題在 userspace 有了操作空間
到這邊先回去細看一次題目給的內容
1 | naup@naup-virtual-machine:~/Desktop/pwn/devmem$ cat run.sh |
他給了一份啟動腳本,會把 initramfs.cpio.gz 用 -initrd 的方式作為 file system
init ram disk
initrd 的全稱是 initial ram disk,作用是在開機的早期提供系統一些必要的設定檔與工具程式,以利系統進一步開啟與掛載像是檔案系統等重要的子系統
https://www.kernel.org/doc/html/v6.14/admin-guide/initrd.html
他會在 boot 階段就被 load 進 physical address 中
並且這塊區域並不會受到 KASLR 影響
當我們去執行同一個 ELF (initrd 內的) 時候,有一塊仍舊會 mapping 到同一塊 physical address 在 initrd load 的地方,那塊是 readonly 的 segment
像是 rodata 就不會變
通過 gdb 直接觀察可以發現,就算 virtual address 不一樣
每次都會有一樣的 physical address (rodata)
無論重開多少次 qemu
get shell 思想
首先我們來回去看看 /usr/sbin/chall
1 |
|
就跟之前說的一樣,這份 code 主要是通過 /dev/mem 來實現對 physical address 的任意寫
也就是說他會去 open /dev/mem
而這個 /dev/mem 的 string 是一個 rodata 段的東西
可以看到這裡
根據前面所述的,這塊位置在每次啟動時候 physical address 都一樣
所以可以改寫,這邊想法是寫成 /proc/self/mem 來對自己 ELF 執行時候可以控制執行流程
因為題目的 code 是跑在 root,所以說如果能通過他,就可以讀 flag
不過 /proc/self/mem 太長了,所以改用 /tmp/c 弄個 symlink 指向 /proc/self/mem
最後的思想是要把 flag 讀出來
剛好因為是 static link 的關係,所以有足夠多 gadget 可以用來堆 ROP
這邊決定堆 open read write,再去改寫 asm 來跳到 ROP 上
以下是攻擊流程
- 先通過 physical aaw 把 ROP 跟 flag.txt 寫上去 rodata 段
- 建立一個 /tmp/c 作為 symlink 指向 /proc/self/mem
- 通過 physical aaw 把 rodata 段上的 /dev/mem 改寫成 /tmp/c
- 通過 /proc/self/mem 的任意寫來把 write 之後的結尾寫成
mov esp, rop_addr; ret - 跳上去執行 open read write 把 flag 讀出來
exploit
記得選擇寫入的地方一定要對其 0x8
1 |
|