2015年9月21日 星期一

攔截 dynamic library 裡面的函數 - 3

前面的文章中
Part 1 說明了如何用 LD_PRELOAD 替換掉 dynamic library 的函數
Part 2 說明了如果是 dlopen 開啟的 dynamic library 要如何處理

理論上前兩個部份應該涵蓋了所有可能性了
不過事實上 part 2 的方法大部分的情形下可能不管用
原因是出在 dynamic library 為了為相容性
編譯 so 檔的時候會指定一個 soname
例如說編譯原版的 libtest.so 的時候會多加一個編譯參數

gcc test.c -shared -fPIC -o libtest.o -Wl,-soname,libtest.so

我們可以用 ldd 看我們編譯出來的假 library 的變化:

# Without the -soname flag
$ ldd hook/libtest.so
        linux-vdso.so.1 =>  (0x00007ffff73c3000)
        libTEST.so => not found
        ...
# With the -soname flag
$ ldd hook/libtest.so
        linux-vdso.so.1 =>  (0x00007ffff73c3000)
        libtest.so => not found
        ...

加了 soname 之後,不論我們怎麼改檔名
linker 都會以 soname 為主
也就是 part 2 的方法不管用

幸好 elf 格式中連結的資訊很好修改
我們可以改我們自己的 binary 去竄改那個名字
最簡單的方法可以直接用 vim binary mode (vim -b) 開啟檔案
找到第一個(應該吧) libtest.so 的字串,改掉之後存檔就好了

比較可靠的方法是
其實這個資訊存在 .dynstr 下 section
而 libtest.so 這個字串就存在這個 section 下面
可以透過這兩個步驟讀取

$ readelf -WS hook/libtest.so | grep .dynstr
  [ 4] .dynstr           STRTAB          00000000000003b0...
$ readelf -p .dynstr hook/libtest.so | grep libtest.so
  [    85]  libtest.so

命令列中要改成正確的 library 名稱
上面兩行也就是說在 0x3b0+0x85=0x435 這個位置下
有我們想改的字串
用 hd 看看

00000430 |est3.libtest.so.|

發現那個位置的確是我們想改的字串
另外,這個字串是 null-terminated 的
知道了以上事項
我們就可以用 bash regex, dd 寫一個(有點難寫的) script 來自動處理了
不過缺點是這個方法只能改成相同長度的字串

沒有留言:

張貼留言