使用 xxd 修改二進制文件

在新的 Linux 系統上編譯的動態庫,在一些老的 Linux 上面運行,有時候會報下列錯誤

/lib64/libc.so.6: version 'GLIBC_2.14' not found

這一般是因爲老的系統沒有最新的 GLIBC_2.14,而創建動態庫的機器上使用的是 GLIB2 2.14memcpy, 這個庫函數爲了解決重疊拷貝問題而進行了修正。如果用到的只是這一個函數的話,可以通過修改動態庫中的版本標識,讓其可以老系統上面運行。

首先查看一下動態庫依賴的 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 可以通過指定偏移量的方式來直接修改二進制文件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章