exploitation
一題在 ctf-wiki 當作範例的 kernel use after free 題目,做完之後覺得也不是很難,但很多東西沒摸過要弄出來滿有挑戰性的
其實放題目的 repo 內已經有 babydriver.ko 了,不過為了要多學一點東西,我們還是按步驟來
之前找了一堆 cpio 解壓縮的方法都會出現亂碼,結果看了 ctk-wiki 上面的操作就好了…這啥鬼做法?
有了整個 file system ,可以看一下 kernel 啟動後會幹嘛,主要是透過 init 這個 script:
可以看到 line 10 把 driver 給 load 起來,除此之外好像沒啥特別的
老樣子用 ida 來分析
由於前兩個實驗都是自己寫 driver 然後自己 pwn ,所以我其實沒用 IDA 分析過 driver 的經驗…,這次算是不錯的體驗
可以看到裡面的 function
init 和 exit 不用多說,前者是 insmod 把 module load 進 kernel 會跑的 function ,後者則是 rmmod 會跑的,那其他的呢?
我第一個遇到的問題就是不知道 function 呼叫先後順序,其實這個 driver 裡面的 function 比較像是用來呼叫的 API (其他 driver 我不敢亂說XD)
char device driver 提供一系列跟 file 類似操作,換句話說可以對這個 device 做 open, read, write 等等操作,原理是 char device driver 裡面有個結構 fops 放各種操作的 function pointer ,在 init 時就透過 chdev_init 注冊 fops ,當使用 open(/path/to/driver, 2); 就會去 fops 裡面跟 open 做對應的是哪個 function 再呼叫
可以看到控制 device 的 babyioctl 定義了 0x10001 的命令,具體來說就是
可以簡單想成在 kernel 內申請任意大小的 memory
另外 babywrite, babyread 則分別透過 copy_from_user(從 user 複製資料進到 kernel) 和 copy_to_user(反向操作)達成
另外看到 release ,猜測應該是對應的 close 部分,就是簡單的 kfree 而已
一個 device driver load 到 kernel ,則整個 kernel 裡面就只有這個 process ,不論有幾個程式去使用這個 device 都只有一個 device driver 在工作,所以資源也是共享的,我一開始以為是數個程式工作會將資源區隔開來
babydriver.ko 裡面有一個 babydev_struct 結構體,最重要的是他是全域變數
假若有兩個程式同時跟 babydriver 互動,兩者用的 babydev_struct 是同一個,這就會出現一個問題:
程式 A free 掉 babydev_struct 中的 buf 後程式 B 依然能讀取寫入 babydev_struct 中的 buf,這邊就出現了一個 uaf 漏洞
當然未必要兩個程式,一個程式 open 兩次也是一樣
要如何利用這個 uaf 呢?按照老套路肯定是要修改 struct cred 內的 uid gid 等變數,而一個程式剛生出來的時候也會需要申請一塊空間來存放該結構,那就很清楚了:
我想了下 parent 可不可以提權,思考後覺得不妥,因為若由 parent 改寫 struct cred , child 要弄出 shell 的時間很難抓,倒不如由 child 自己改寫後再開 shell 來的簡單
exploit:
寫好並用 static 編譯好後將執行檔放入 file system ,在 file system 根目錄下用以下命令打包:
再用 boot.sh 啟動即可
嚴格來說不太能算是一個完整的 debug ,畢竟我沒看到最後,但 debug 過程中我遇到一些問題:
因為想著要 debug 必須 add-symbol-file 然後要給 text address , text address 可以透過 lsmod 或是 /sys/modules/babydriver/sections/.text 獲得