我可以欺骗 libc (GLIBC_2.13) 加载它没有的符号(来自 GLIBC_2.15)吗?

2024-03-07

在我尝试让“Steam for Linux”在 Debian 上运行时,我遇到了一个问题。libcef(Chromium 嵌入式框架)可以很好地工作GLIBC_2.13(Debian 测试中的eglibc 可以提供),但是需要一个讨厌的额外功能GLIBC_2.15(eglibc 无法提供):

$ readelf -s libcef.so | grep -E "@GLIBC_2\.1[4567]"
1037: 00000000     0 FUNC    GLOBAL DEFAULT  UND __fdelt_chk@GLIBC_2.15 (49)
2733: 00000000     0 FUNC    GLOBAL DEFAULT  UND __fdelt_chk@@GLIBC_2.15

我的攻击计划是LD_PRELOAD一个只提供这些功能的垫片库。这似乎不起作用。我真的想避免安装GLIBC_2.17(因为它是在 Debian 实验中;甚至 Debian sid 仍然有GLIBC_2.13).


这是我尝试过的。

fdelt_chk.c基本上被盗了来自 GNU C 库 http://repo.or.cz/w/glibc.git/blob/a0f33f996f7986dbf37631a4577f8565b42df29e:/debug/fdelt_chk.c:

#include <sys/select.h>

# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
# define _strong_alias(name, aliasname) \
  extern __typeof (name) aliasname __attribute__ ((alias (#name)));

unsigned long int
__fdelt_chk (unsigned long int d)
{
  if (d >= FD_SETSIZE)
    __chk_fail ();

  return d / __NFDBITS;
}
strong_alias (__fdelt_chk, __fdelt_warn)

My Versions脚本如下所示:

GLIBC_2.15 {
    __fdelt_chk; __fdelt_warn;
};

然后我按如下方式构建库:

$ gcc -m32 -c -fPIC fdelt_chk.c -o fdelt_chk.o
$ gcc -m32 -shared -nostartfiles -Wl,-s -Wl,--version-script Versions -o fdelt_chk.so fdelt_chk.o

然而,如果我随后运行 Steam(使用一堆额外的东西让它首先工作),加载程序仍然拒绝找到该符号:

% LD_LIBRARY_PATH="/home/tinctorius/.local/share/Steam/ubuntu12_32" LD_PRELOAD=./fdelt_chk.so:./steamui.so ./steam 
./steam: /lib/i386-linux-gnu/i686/cmov/libc.so.6: version `GLIBC_2.15' not found (required by /home/tinctorius/.local/share/Steam/ubuntu12_32/libcef.so)    

但是,版本符号也由.so我刚刚构建:

% readelf -s fdelt_chk.so

Symbol table '.dynsym' contains 8 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 FUNC    GLOBAL DEFAULT  UND __chk_fail@GLIBC_2.3.4 (3)
     2: 0000146c     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
     3: 0000146c     0 NOTYPE  GLOBAL DEFAULT  ABS _end
     4: 00000310    44 FUNC    GLOBAL DEFAULT   11 __fdelt_warn@@GLIBC_2.15
     5: 00000310    44 FUNC    GLOBAL DEFAULT   11 __fdelt_chk@@GLIBC_2.15
     6: 00000000     0 OBJECT  GLOBAL DEFAULT  ABS GLIBC_2.15
     7: 0000146c     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start

此时,我不知道如何才能欺骗加载程序(谁?)选择我的符号。我的方向完全正确吗?


我也遇到过同样的问题,不过不是在 Steam 上。我试图运行的东西2.15 for fdelt_chk虽然我的系统有2.14。我找到了一个针对像我们这样的简单情况的解决方案,我们可以轻松地为缺少的功能提供我们自己的实现。

我从您尝试实现功能的解决方案开始,LD_PRELOAD荷兰国际集团它。使用LD_DEBUG=all(如 osgx 所建议的)表明链接器仍在寻找2.15,所以仅仅拥有正确的符号是不够的,并且在某处还有其他一些版本控制机制。我注意到objdump -p and readelf -V两者都显示了对2.15,所以我查了一下ELF的文档,发现有关版本要求的信息 http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/symversion.html.

所以我的新目标是将引用转变为2.15变成对其他东西的引用。我可以覆盖引用的结构似乎是合理的2.15具有引用某些较低版本的结构,例如2.1。最后,经过一番尝试和错误,我发现只需编辑正确的Elfxx_Vernaux(是?) 在.gnu.version_r已经足够了,但我想还是要注意黑客。

The .gnu.version_r节是一个16字节的列表Elfxx_Verneeds 和 16 字节Elfxx_Vernauxes.每个Elfxx_Verneed条目后面跟着相关的Elfxx_Vernauxes.据我所知,vn_file实际上是有多少关联的Elfxx_Vernaux有,尽管文档说number of associated verneed array entries。不过,这可能只是我的一个误会。

因此,为了开始进行编辑,让我们看一下来自的一些信息readelf -V。我剪掉了我们不关心的部分。

$ readelf -V mybinary
<snip stuff before .gnu.version_r>
Version needs section '.gnu.version_r' contains 5 entries:
 Addr: 0x00000000000021ac  Offset: 0x0021ac  Link: 4 (.dynstr)
<snip libraries that don't refer to GLIBC_2.15>
  0x00c0: Version: 1  File: libc.so.6  Cnt: 10
  0x00d0:   Name: GLIBC_2.3  Flags: none  Version: 19
  0x00e0:   Name: GLIBC_2.7  Flags: none  Version: 16
  0x00f0:   Name: GLIBC_2.2  Flags: none  Version: 15
  0x0100:   Name: GLIBC_2.2.4  Flags: none  Version: 14
  0x0110:   Name: GLIBC_2.1.3  Flags: none  Version: 13
  0x0120:   Name: GLIBC_2.15  Flags: none  Version: 12
  0x0130:   Name: GLIBC_2.4  Flags: none  Version: 10
  0x0140:   Name: GLIBC_2.1  Flags: none  Version: 9
  0x0150:   Name: GLIBC_2.3.4  Flags: none  Version: 4
  0x0160:   Name: GLIBC_2.0  Flags: none  Version: 2

从这里我们看到该部分开始于0x21ac。列出的每个文件都会有一个Elfxx_Verneed随后是一个Elfxx_Vernaux对于每个子条目(例如GLIBC_2.3)。我假设输出中信息的顺序始终与文件中的顺序匹配,因为readelf只是倾倒结构。这是我的entire .gnu.version_r部分。

000021A0                                          01 00 02 00
000021B0   A3 0C 00 00  10 00 00 00  30 00 00 00  11 69 69 0D
000021C0   00 00 11 00  32 0D 00 00  10 00 00 00  10 69 69 0D
000021D0   00 00 0B 00  3C 0D 00 00  00 00 00 00  01 00 02 00
000021E0   BE 0C 00 00  10 00 00 00  30 00 00 00  13 69 69 0D
000021F0   00 00 08 00  46 0D 00 00  10 00 00 00  10 69 69 0D
00002200   00 00 07 00  3C 0D 00 00  00 00 00 00  01 00 02 00
00002210   99 0C 00 00  10 00 00 00  30 00 00 00  11 69 69 0D
00002220   00 00 06 00  32 0D 00 00  10 00 00 00  10 69 69 0D
00002230   00 00 05 00  3C 0D 00 00  00 00 00 00  01 00 02 00
00002240   AE 0C 00 00  10 00 00 00  30 00 00 00  11 69 69 0D
00002250   00 00 12 00  32 0D 00 00  10 00 00 00  10 69 69 0D
00002260   00 00 03 00  3C 0D 00 00  00 00 00 00  01 00 0A 00
00002270   FF 0C 00 00  10 00 00 00  00 00 00 00  13 69 69 0D
00002280   00 00 13 00  46 0D 00 00  10 00 00 00  17 69 69 0D
00002290   00 00 10 00  50 0D 00 00  10 00 00 00  12 69 69 0D
000022A0   00 00 0F 00  5A 0D 00 00  10 00 00 00  74 1A 69 09
000022B0   00 00 0E 00  64 0D 00 00  10 00 00 00  73 1F 69 09
000022C0   00 00 0D 00  70 0D 00 00  10 00 00 00  95 91 96 06
000022D0   00 00 0C 00  7C 0D 00 00  10 00 00 00  14 69 69 0D
000022E0   00 00 0A 00  87 0D 00 00  10 00 00 00  11 69 69 0D
000022F0   00 00 09 00  32 0D 00 00  10 00 00 00  74 19 69 09
00002300   00 00 04 00  91 0D 00 00  10 00 00 00  10 69 69 0D
00002310   00 00 02 00  3C 0D 00 00  00 00 00 00

简单说一下这里的结构,首先是一个Elfxx_Verneed。根据文档,我们可以看到会有 2Elfxx_Vernauxes,一个偏移16字节,下一个Elfxx_Verneed偏移量为 48 字节。这些偏移量是从当前结构的开始处开始的。技术上看起来像是相关的Elfxx_Vernauxes 可能在当前之后不相邻Elfxx_Verneed但在我翻阅的所有文件中实际上都是如此。

由此我们可以通过几种不同的方式找到我们想要的文件(libc.so.6)。交叉引用字符串(我不会涉及),找到Elfxx_Verneed计数为0A 00(10、匹配我们的readelf上面的输出),或者找到最后一个Elfxx_Verneed因为这是最后一篇readelf输出。无论如何,适合我的文件的位置是0x226C。它的第一个Elfxx_Vernaux开始于0x227C.

我们想要找到Elfxx_Vernaux与一个版本0C 00(12,再次匹配我们的readelf输出如上)。我们看到Elfxx_Vernaux匹配的是0x22CC整个结构是95 91 96 06 00 00 0C 00 7C 0D 00 00 10 00 00 00。我们将覆盖前 12 个字节,以便保留偏移量。毕竟,我们只是修改数据,而不是移动结构。

要选择要覆盖的数据,我们只需从不同的地方复制它Elfxx_Vernaux对于glibc的一个版本我们可以满足。我选了一个2.1,这是在0x22EC在我的文件中,包含数据11 69 69 0D 00 00 09 00 32 0D 00 00 10 00 00 00。因此,从中取出前 12 个字节并覆盖上面的前 12 个字节,这就是十六进制编辑。

当然,您可能有多个参考文献需要处理。您的程序可能有多个二进制文件需要编辑。

此时,我们的程序仍然无法运行。但不是被告知类似的事情GLIBC_2.15 not found它应该抱怨失踪__fdelt_chk。现在我们做垫片并LD_PRELOAD问题中描述的,除了我们的实现版本化为2.15,我们使用十六进制编辑时选择的版本。此时程序应该运行。

此方法取决于是否能够为缺失的内容提供实现。我们的__fdelt_chk非常简单,但我毫不怀疑在某些情况下提供实现可能比仅仅升级系统的 libc 更困难。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我可以欺骗 libc (GLIBC_2.13) 加载它没有的符号(来自 GLIBC_2.15)吗? 的相关文章

  • 如何分发带有依赖库的 Mac OS X?

    我有一个程序 特别是我的条目SO DevDays 倒计时应用挑战 https meta stackexchange com questions 20420 countdown app for devdays 21659 21659 它依赖于
  • 使用 UCLIBC 交叉编译 PHP

    这是一个转发 之前的帖子已关闭 移至 SERVERFAULT 并再次关闭 我认为这篇文章是一个有效的堆栈溢出问题 因为我认为它是由一些 automake 编译 链接错误引起的 这是一个编程问题而不是服务器管理问题 我会检查 uClibc 的
  • 如何更改 GCC 的默认搜索目录 crti.o?

    我想指定 GCC 的搜索目录startfile and endfile crt1 o crti o and crtn o 通过 B在命令行上 GCC 驱动程序可以工作 但不方便 如何修改规格 文件 lib gcc x86 64 unknow
  • 使用 glibc 而不是默认库编译的 C 程序:执行时权限被拒绝

    这是我在 stackoverflow 上的第一个问题 所以我会尽力做好 Context 我想提供一个可以在每个 Linux 发行版上运行的程序 例如 一个将使用 C 11 的程序 在没有 C 11 库的系统上运行 为此 我想复制我的程序使用
  • OpenCL C/C++ 动态绑定库(win32 及更多)

    我正在尝试 OpenCL 为了将其投入生产 我希望能够动态绑定到 OpenCL DLL 在 Windows 下 以便 优雅地 处理没有 OpenCL 的情况安装在主机上 是否有任何可用的库 或代码片段 可以在 C 或 C 中处理这种动态绑定
  • 最新SDK的SDKROOT路径

    我正在使用 Xcode 构建旧代码并指定SDKROOT Developer SDKs MacOSX HOST VERSION sdk 我想为系统上预安装 的最新 SDK 指定 SDKROOT 例如我在10 8已经并且我想指定SDKROOT与
  • 我可以欺骗 libc (GLIBC_2.13) 加载它没有的符号(来自 GLIBC_2.15)吗?

    在我尝试让 Steam for Linux 在 Debian 上运行时 我遇到了一个问题 libcef Chromium 嵌入式框架 可以很好地工作GLIBC 2 13 Debian 测试中的eglibc 可以提供 但是需要一个讨厌的额外功
  • 何时使用动态库与静态库

    在 C 中创建类库时 可以选择动态 dll so 和静态 lib a 图书馆 它们之间有什么区别 什么时候适合使用哪个 静态库会增加二进制文件中代码的大小 它们总是被加载 并且无论您编译的代码版本是什么 都是将运行的代码版本 动态库单独存储
  • -symbolic 和 -shared GCC 标志之间有什么区别?

    从文档的描述来看 它们似乎做了同样的事情 除了 并非所有系统 支持共享并且 只有某些系统 支持符号 尚不清楚这些是否是同一组系统 共享 生成一个共享对象 然后可以将其与其他对象链接起来 形成可执行文件 并非所有系统 支持这个选项 对于可预测
  • 强制链接与库不同的 SONAME

    如何以与具有冲突 SONAME 的库的两个现有版本兼容的方式链接二进制文件 这两个版本不共享相同的 SONAME 前缀 一个是 libcapi10 so 3 另一个是 libcapi10 so 4 我无法重新编译它们 因为我将它们作为二进制
  • 如何将 2 个部分放入 1 个段(使用 ld 脚本)

    我有以下链接器脚本 SECTIONS arora exec free space 4399531 text rodata data rel ro local arora data free space ADDR arora exec fre
  • dlclose 上不会调用共享库中全局静态变量的析构函数

    在主程序中 我dlopen and dlclose LoadLibrary and FreeLibrary分别 一个共享库 共享库包含一个实例化的静态变量dlopen 并销毁于dlclose 此行为在 MSVC 2008 和 2013 GC
  • Lua:C++模块无法互相引用,未定义的符号

    我创建了两个模块 共享对象 CPU 和 SaveState 作为模拟器的一部分 两者都独立编译成 so 单独文件 并在运行时由 Lua 脚本使用 require 加载 IE SaveState require SaveState CPU r
  • 数学库现在包含在 glibc 中吗?

    当我尝试从终端编译这个简单的代码时 include
  • 为什么 Linux/gnu 链接器选择地址 0x400000?

    我正在 Linux x86 64 上试验 ELF 可执行文件和 gnu 工具链 我已经链接并剥离 手动 Hello World 测试 global start text start mov 1 rax 转换为 267 字节 ELF64 可执
  • 函数插入仅适用于 malloc 而不是 free

    我在通过使用函数插入来监视 malloc 和 free 时遇到了一个小问题 当仅对 malloc 执行函数插入时 它按预期工作 然而 当尝试插入 free 时 它 最终会陷入循环 我似乎 free 被递归调用 但我只是不知道为什么 这是 m
  • 符号 __module_registered 错误的重复定义

    我从 GHCi 收到一条关于 符号 module registered 的重复定义 的错误消息 如下所示 GHCi runtime linker fatal error I found a duplicate definition for
  • 使用动态链接器包装 glibc 函数

    我正在尝试包装 GLIBCfstat通过将我的库注入可执行文件来实现函数 可以是任何其他 这只是概念证明 我通过将我的库放置在可执行文件的位置来做到这一点RPATH用名字指着libc so 6 我的库的源代码如下 define GNU SO
  • __libc_start_main 发生了什么?

    我真的很想理解从高级代码到可执行文件的步骤 但是遇到了一些困难 我写了一个空的int main C 文件并尝试通过以下方式破译反汇编objdump d 这是发生的事情 in start 设置对齐方式 将参数压入堆栈 调用 libc star
  • 强制动态链接库中静态变量的预初始化

    C 11 标准第 3 6 2 条 第 4 条规定 具有静态存储持续时间的非局部变量的动态初始化是否在 main 的第一个语句之前完成是由实现定义的 C 标准将静态初始化与动态初始化区分开来 静态初始化仅需要计算编译时常量 我相信急切静态初始

随机推荐

  • 带 ref/Pointer 参数的 C# 反射调用方法

    我想通过反射调用类的每个方法 但无法使用指针作为引用来调用方法 通常我可以为我找到的每个指针传递 null 一切都会好起来的 问题是当函数尝试访问我传递的指针时 该指针将是对内存地址 0 的引用 这显然对我的程序来说会立即崩溃 所以我需要传
  • Spring 集成 TCP

    我想设置 Spring TCP 服务器客户端应用程序 我需要一个服务器侦听端口上的传入消息 例如 6666 并且客户端在不同的端口上发送消息 例如 7777 我已遵循文档 http docs spring io spring integra
  • 在 cocoa/iPhone 中将纪元时间转换为 NSDate

    我有纪元时间的值 比如 123456789 现在我想将其转换为NSDate在可可框架中 谁能告诉我吗 thanks 文档 http developer apple com iphone library documentation Cocoa
  • 使用 Firestore,如何使用 java 类序列化文档中的引用类型字段?

    如果我有一个包含 引用 类型字段的 Firestore 文档 那么在使用自动 POJO Java 对象序列化时如何读取和写入该字段 POJO 类型字段文档参考 https firebase google com docs reference
  • WPF 相当于 TextRenderer

    我用过TextRenderer测量字符串的长度 从而适当调整控件的大小 WPF 中是否有等效项或者我可以简单地使用TextRendered MeasureString 谢谢纪修 阅读您的链接后 我想到了以下两个内容 它们都适合我
  • Python将整列添加到csv文件中,而不读取文件内容

    我需要使用 Python 将列添加到 csv 文件 我能想到的唯一方法是读取整个文件 编辑每一行以添加 1 个元素 然后再次写入文件 然而 我真的不想这样做 因为文件的大小 超过 32000 行 每次我想添加列时似乎需要大量的读写 即使使用
  • 如何从 fgets 中检测空字符串

    我试图将 stdin 中的 fgets 输入检测为空 当我按 Enter 键而不输入任何内容时 这是我的程序 int main char input 1000 printf Enter fgets input 1000 stdin inpu
  • 如何使用 box2d 在 libgdx 中拖动对象?

    我已将对象添加到box2d世界在libgdx 我想知道是否可以用鼠标拖动对象 如果是这样 怎么办 thanks 这里有几个选项 您可以使用鼠标关节 也可以使用运动体并手动设置其位置 看看如何使用鼠标关节的一个很好的例子 http code
  • 图像作为绘制形状的“背景”

    是否可以使用图像而不是颜色来 填充 HTML5 画布上的形状 我画了一堆形状 各个角以 45 度角切掉的正方形 我希望能够用图像而不是颜色来 填充 这些形状 目前我有一行指出 context fillStyle 123456 example
  • 如何使用 Meteor.js、Twitter 和 Oauth 发布推文

    我在使用 Meteor 和 Twitter 时遇到了一些问题 我想做的就是通过点击按钮发布一条推文 为此 我必须通过 Oauth 向 Twitter 服务验证自己的身份 目前 我正在以一种非常复杂的方式进行身份验证 从客户端到服务器并返回
  • 适用于 Android 的本机 OpenCV 示例抛出 UnsatisfiedLinkError

    我尝试在模拟器上运行 opencv android 示例 带有本机代码的示例 例如示例 教程 2 高级 1 添加本机 OpenCV 失败 我有一个Win7 x86系统 我可以构建本机库 但如果运行示例 我总是会遇到以下异常 10 04 08
  • 每个线程组的概率

    如果我的测试计划中有 3 个线程组 如何为每个组设置恒定概率 请求权重 我是 JMeter 的新手 您能在屏幕截图上显示您的设置吗 只需将每组的线程数设置为测试总线程数的一个因子即可 如果有 100 个 VU 则 g1 设置为 50 g2
  • 我如何使用 iOS 中的 Fabric 框架从我的应用程序中注销 Twitter

    在我的 iOS 应用程序中 我使用集成 Twitter 登录织物框架 TWTR作曲家 第一次登录并在 Twitter 上发布推文时 它工作正常 但我无法在我的应用程序中从 Twitter 注销 当我第二次尝试登录时 twitterlogin
  • LINQ 和递归

    考虑以下 public class Box public BoxSize Size get set public IEnumerable
  • 无法在 django 模板中使用 unicode 字符串

    我在 django 模板中使用了 B M N TO N 字符串 它引发了错误 utf8 编解码器无法解码位置 569 中的字节 0xd4 无效的连续字节 但是当我使用 BO MON TOAN 字符串时 它不会引发错误 所以 我在模板中使用了
  • 红宝石:能被4整除

    这工作正常 但我想让它更漂亮 并容纳所有能被 4 整除的值 if i 4 i 8 i 12 i 16 i 20 i 24 i 28 i 32 end 有什么聪明 简短的方法可以做到这一点吗 尝试这个 if i 4 0 这被称为 模运算符 h
  • 对于 C++ 插件系统来说什么是安全的?

    C 中的插件系统很困难 因为 ABI 没有正确定义 并且每个编译器 或其版本 都遵循自己的规则 然而 Windows 上的 COM 表明创建一个最小的插件系统是可能的 该系统允许具有不同编译器的程序员使用简单的接口为主机应用程序创建插件 让
  • 使用声明的可变基类无法在 MSVC 中编译

    我正在尝试实现一个可变访问者类 template
  • 如何以Python方式将 scipy.optimize.OptimizeResult 结果对象保存到文件中以便以后轻松访问?

    从 scipy optimize OptimizeResult 保存结果对象的最佳方法是什么 以便可以从保存的文件轻松访问其参数 我目前正在将结果保存为字符串 但这样 当我需要再次引用它时 我需要解析整个字符串来识别参数数组或函数值等对象
  • 我可以欺骗 libc (GLIBC_2.13) 加载它没有的符号(来自 GLIBC_2.15)吗?

    在我尝试让 Steam for Linux 在 Debian 上运行时 我遇到了一个问题 libcef Chromium 嵌入式框架 可以很好地工作GLIBC 2 13 Debian 测试中的eglibc 可以提供 但是需要一个讨厌的额外功