在新的 Linux 系統上編譯的動態庫,在一些老的 Linux 上面運行,有時候會報下列錯誤
/lib64/libc.so.6: version 'GLIBC_2.14' not found
這一般是因爲老的系統沒有最新的 GLIBC_2.14
,而創建動態庫的機器上使用的是 GLIB2 2.14
的 memcpy
, 這個庫函數爲了解決重疊拷貝問題而進行了修正。如果用到的只是這一個函數的話,可以通過修改動態庫中的版本標識,讓其可以老系統上面運行。
首先查看一下動態庫依賴的 GLIBC
版本信息
readelf -V /path/to/_pytransform.so
...
Version needs section '.gnu.version_r' contains 2 entries:
Addr: 0x00000000000056e8 Offset: 0x0056e8 Link: 4 (.dynstr)
000000: Version: 1 File: libdl.so.2 Cnt: 1
0x0010: Name: GLIBC_2.2.5 Flags: none Version: 7
0x0020: Version: 1 File: libc.so.6 Cnt: 6
0x0030: Name: GLIBC_2.7 Flags: none Version: 8
0x0040: Name: GLIBC_2.14 Flags: none Version: 6
0x0050: Name: GLIBC_2.4 Flags: none Version: 5
0x0060: Name: GLIBC_2.3.4 Flags: none Version: 4
0x0070: Name: GLIBC_2.2.5 Flags: none Version: 3
0x0080: Name: GLIBC_2.3 Flags: none Version: 2
我們需要做的就是把 GLIBC_2.14
這一項的版本號替換成爲 GLIBC_2.2.5
。這就需要對二進制文件進行打補丁,把段內偏移 0x0010
處的相關內容拷貝到 0x0040
處,比較方便的方式就是使用命令 xxd
先看看偏移0x0010
處的信息,一個版本描述項目佔用16個字節(參考 ELF 文件格式中版本定義),版本段的在文件內的偏移是 0x0056e8
,下面的命令顯示從 0x56e8
+ 0x10
= 0x56f8
開始的16個字節
xxd -s 0x56f8 -l 16 _pytransform.so
000056f8: 751a 6909 0000 0700 b219 0000 0000 0000 u.i.............
需要拷貝的是前四個字節751a 6909
,以及偏移爲8處的四個字節b219 0000
而目標地址在偏移0x00040
處,所以前四個字節的目標地址爲 0x56e8
+ 0x40
= 0x5728
,後四個字節的目標地址是0x5730
那麼使用 xxd
打補丁的命令如下
xxd -s 0x56f8 -l 4 _pytransform.so | sed "s/56f8/5728/" | xxd -r - _pytransform.so
xxd -s 0x5700 -l 4 _pytransform.so | sed "s/5700/5730/" | xxd -r - _pytransform.so
其中,管道命令的第一步是打印出需要拷貝的四個字節數據
xxd -s 0x56f8 -l 4 _pytransform.so
000056f8: 751a 6909 u.i
第二步是把原來的地址替換成爲目標地址
xxd -s 0x56f8 -l 4 _pytransform.so | sed "s/56f8/5728/"
00005728: 751a 6909 u.i.
第三步是使用 xxd -r
把新的數據寫入到二進制文件,等價於
echo "00005728: 751a 6909" | xxd -r - _pytransform.so
簡單的說, xxd -r
可以通過指定偏移量的方式來直接修改二進制文件。