修改 Linux so 檔相依的 glibc 版本

目前平台用的gcc太舊,似乎無法用Google depot tools去編譯PDFium。網路上有好心人幫忙編了arm32平台的binaryhttps://github.com/bblanchon/pdfium-binaries),但是在目前平台編譯會出現找不到getauxval@GLIBC_2.16(目前平台用glibc 2.15)。

 後來找到可以造假一個so,利用LD_PRELOAD的方式先載入這個so,讓libpdfium.so找到這個symbol。但dlopen時,透過設定LD_DEBUG=bindings仍可以看到載入時還是會去找glibc 2.16

 於是底下的方式,目的是去修改so檔,讓它不相依glibc 2.16,原本要的getauxval@GLIBC_2.16就直接用假的so檔。

 參考資料:https://stackoverflow.com/questions/14879644/can-i-trick-libc-glibc-2-13-into-loading-a-symbol-it-doesnt-have-from-glibc

 先建一個aux.c,內容只有下面:

unsigned long int getauxval (unsigned long int type)

{

  return 0;

}

 產生一個檔案Versions,內容如下:

GLIBC_2.16 {

    getauxval;

};

 然後透過以下方式將它編成aux.so 

arm-linux-gnueabihf-gcc -c -fPIC aux.c -o aux.o

arm-linux-gnueabihf-gcc -shared -Wl,-s -Wl,--version-script Versions -o  aux.so aux.o

 readelf -s aux.sosymbol table

so做好了,接著是去改libpdfium.so內容,讓它不用去找glibc 2.16

readelf -V libpdfium.so

因為系統的glibc2.15,所以目標是讓它在載入時會去找glibc 2.16的行為改掉。

上述結果中先找到offset 0x36f8。我們用HxD打開我們的so檔跳至0x36f8

接著我們在readelf結果中找libc.so.6後頭的Cnt,這邊顯示是4。接著我們由0x36f8往下找01 00 04 00地方,如圖所示是在位址0x3728開始:

這時候我們看這個so所需的glibc,共有2.4/2.7/2.11/2.16,它最後的版本都不一樣,分別是2/9/7/8。對照上一張圖,我們可以看到這個神秘的順序:

半夢半醒,似懂非懂之下,我們假定這就是我們要的。那目前我們要將glibc 2.16的部份改成2.11,也就是將0x37A8接下來的16 bytes複製到0x37B8接下來的16 bytes

改完,用readelf再看一下:

噢!看起來有改成功。

 實際再用dlopen載入so,就不會叫找不到glibc 2.16了。目前做PDF的顯示、旋轉、縮放看起來都正常,只是執行程式時要加上LD_PRELOAD=aux.so或設其於環境變數內。

留言

熱門文章