今天写了个小代码做个小实验,想要放到nas上跑跑看,结果报
/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
大致是因为编译的环境glibc版本过高导致的原因,因为编译环境是最新的wsl的ubuntu22,查了下解决办法大致是指定低版本的glibc,重新编译之类的,对我来说都太麻烦了不太想那么操作。
后面转念想,我又没有用过什么比较新的func,函数签名啥的应该都没啥变化,有没有一种可能就只修改libc的version依赖?
于是我就以“修改elf 兼容glibc”为关键字搜索,看了下,Uranus Zhou的《Linux修改ELF解决glibc兼容性问题》这篇文章最符合我的想法,讲的也很好,这里谢谢下博主。
从文章里了解到,elf文件信息里.gnu.version_r段记录了函数对应的glibc版本,需要将对应的版本改为低版本,原本的信息为:
(venv) ➜ test_elf readelf -V main
Version symbols section '.gnu.version' contains 11 entries:
地址:0x00000000000005fc Offset: 0x0005fc Link: 6 (.dynsym)
000: 0 (*本地*) 1 (*全局*) 3 (GLIBC_2.34) 2 (GLIBC_2.2.5)
004: 4 (GLIBCXX_3.4) 1 (*全局*) 1 (*全局*) 1 (*全局*)
008: 1 (*全局*) 4 (GLIBCXX_3.4) 2 (GLIBC_2.2.5)
Version needs section '.gnu.version_r' contains 2 entries:
地址:0x0000000000000618 Offset: 0x000618 Link: 7 (.dynstr)
000000: Version: 1 文件:libstdc++.so.6 计数:1
0x0010: Name: GLIBCXX_3.4 标志:无 版本:4
0x0020: Version: 1 文件:libc.so.6 计数:2
0x0030: Name: GLIBC_2.34 标志:无 版本:3
0x0040: Name: GLIBC_2.2.5 标志:无 版本:2
这里看到对glibc的版本有一个是GLIBC_2.34,我们将之改为0x0040处的低版本试试看,这里我推荐试用lief工具(lief-project),具体修改代码如下:
#!/usr/bin/env python3
# coding=utf-8
__author__ = 'wp'
import lief
if __name__ == "__main__":
bi = lief.parse('main')
print(bi)
# 经测试,不改符号表里的版本信息也是可以运行的,可能是只在加载elf的时候判断libc.so的版本信息
# for _ in bi.symbols:
# if _.symbol_version:
# if 'start_main' in _.name:
# # 修改高版本方法符号表对应的版本,
# _.symbol_version.value = 2
glibc_2_2_5 = None
# 查看 .gnu.version_r 信息
for _ in bi.symbols_version_requirement:
print(_.name, _.version)
for _s in _.get_auxiliary_symbols():
print('\t', _s)
print('\t', _s.flags, _s.hash, _s.name, _s.other)
if _s.name == 'GLIBC_2.2.5':
glibc_2_2_5 = _s
for _ in bi.symbols_version_requirement:
if 'libc.so.6' in _.name:
for _v in _.get_auxiliary_symbols():
if _v.name == 'GLIBC_2.34':
_v.flags = glibc_2_2_5.flags
_v.hash = glibc_2_2_5.hash
_v.name = glibc_2_2_5.name
_v.other = glibc_2_2_5.other
break
bi.write('main_new')
修改后查看版本依赖信息:
(venv) ➜ test_elf readelf -V main_new
Version symbols section '.gnu.version' contains 11 entries:
地址:0x00000000000015fc Offset: 0x0015fc Link: 6 (.dynsym)
000: 0 (*本地*) 1 (*全局*) 3 2 (GLIBC_2.2.5)
004: 4 (GLIBCXX_3.4) 1 (*全局*) 1 (*全局*) 1 (*全局*)
008: 1 (*全局*) 4 (GLIBCXX_3.4) 2 (GLIBC_2.2.5)
Version needs section '.gnu.version_r' contains 2 entries:
地址:0x0000000000001618 Offset: 0x001618 Link: 7 (.dynstr)
000000: Version: 1 文件:libstdc++.so.6 计数:1
0x0010: Name: GLIBCXX_3.4 标志:无 版本:4
0x0020: Version: 1 文件:libc.so.6 计数:2
0x0030: Name: GLIBC_2.2.5 标志:无 版本:2
0x0040: Name: GLIBC_2.2.5 标志:无 版本:2
可以看到版本信息已经变了, 然后吧main_new整到低版本的机器上测试,完美运行!