修改高版本glibc编译出的elf以支持低版本glibc环境客户机执行

今天写了个小代码做个小实验,想要放到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整到低版本的机器上测试,完美运行!

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值