准确识别ELF文件使用的libc.so版本,LibcSearcher 工具的使用

一、问题起因

在做 ctf-wiki 的x86栈溢出的 ret2libc 的例题3时,使用作者的 exp 拿不到 shell,个人认为解题思路没有问题,应该是 LibcSearcher 这个python 库不太靠谱的问题,尝试网页查询 libc ,结果跟LibcSearcher 库的结果一样。


二、解决办法

找到自己系统使用的 libc 版本全名(一般在系统里面就是 libc.so.6 ,就一个主版本号,致命的是还没有软连接指向它,使用 github 上的 LibcSearcher 项目的功能,能够识别到真正的 libc 的全名!!),再做其他操作(比如查各个函数的地址啥的)


三、实验

第一步:先看可执行文件加载的是系统的那一个 libc.so 文件

我刚开始就是一个 ldd 命令,以为用的是/lib32/libc.so.6 这个共享库文件,但我发现这样不够准确后面我就先加载可执行文件,再看他的地址映射信息,这里面的共享库信息总不可能错结果路径是 /usr/lib32/libc.so.6,而且这个文件也只有主版本号,没有软链接指向它

第二步:使用 LibcSearcher 工具识别 本机的 libc 共享库

网上有很多识别 libc 版本的方法,比如直接执行 libc、ldd --version、getconf GNU_LIBC_VERSION等但是查询出来的信息跟 LibcSearcher  数据库中的名称完全对不上LibcSearcher  这个工具识别 libc 版本的思路很简单,就是它维护了一个 版本名与hash值的键值对,通过对本机的共享库计算hash,再去数据库中查hash值相同的那个共享库是啥就ok了(这个原理是我自己的推测,因为LibcSearch 这个工具依赖 MD5 、hash等工具,具体部署请浏览 github的readme),这种方式就会很准确,下面是使用方式:

step 1:识别

命令:    ./identify  +  共享库绝对路径

可以看见平台架构、主次版本、系统都出来了,至此的话识别就结束了(其他库的应该也是一样的操作,我自己没有试)

step 2:简单查看泄露符号的地址

命令:   ./dump + 上一步查到的共享库全称

如果说这一步的结果中,没有你想要的符号,你可以把共享库下载下来,用 objdump 查看所有符号

step 3:下载,查看所有符号

命令:   ./download + 上一步查到的共享库全称

 下载会单独放在一个目录中,进入这个目录中就可以 随便调试了,所有函数的文件偏移(应该是在elf文件中偏移,我没有理解错的话)都可以看见了

### 加载或操作 ELF 文件格式的 libc.so.6 在 Linux 系统中,`libc.so.6` 是 GNU C 库 (glibc) 的共享对象文件,它提供了标准 C 函数以及 POSIX 接口的支持。如果需要加载或操作该文件作为 ELF 类型的对象,则可以借助一些工具和库来实现。 #### 使用 Python 和 `ctypes` 模块动态加载 Python 中可以通过 `ctypes` 模块加载共享库并调用其中定义的功能函数。以下是具体的操作方式: ```python import ctypes # 动态加载 libc.so.6 libc = ctypes.CDLL("/lib/x86_64-linux-gnu/libc.so.6") # 调用 printf 函数测试 message = "Hello, world from libc!\n" libc.printf(message.encode('utf-8')) ``` 上述代码通过 `CDLL` 方法加载了 `/lib/x86_64-linux-gnu/libc.so.6` 并调用了其内部的 `printf` 函数[^1]。 --- #### 使用 `readelf` 工具解析 ELF 文件结构 对于更深入地了解 `libc.so.6` 的内容及其依赖关系,可以使用命令行工具 `readelf` 来解析它的元数据信息。 运行以下命令可查看符号表、节头以及其他重要部分的信息: ```bash readelf --all /lib/x86_64-linux-gnu/libc.so.6 ``` 这一步可以帮助开发者确认目标文件中的导出符号是否存在特定错误或者缺失的情况[^2]。 --- #### 编写自定义程序读取 ELF 头部信息 为了进一步控制对 ELF 文件的操作过程,还可以编写一段简单的 C/C++ 代码手动提取头部字段值。下面给出一个基本示例用于演示如何访问这些基本信息: ```cpp #include <iostream> #include <fstream> #include <elf.h> int main() { std::ifstream file("/lib/x86_64-linux-gnu/libc.so.6", std::ios::binary); Elf64_Ehdr header; file.read(reinterpret_cast<char*>(&header), sizeof(header)); if (!file || header.e_ident[EI_MAG0] != ELFMAG0 || header.e_ident[EI_CLASS] != ELFCLASS64) { std::cerr << "Invalid or unsupported ELF format." << std::endl; return EXIT_FAILURE; } std::cout << "ELF Header Information:" << std::endl; std::cout << "- Type: " << header.e_type << std::endl; std::cout << "- Machine architecture: " << header.e_machine << std::endl; std::cout << "- Entry point address: " << reinterpret_cast<void*>(header.e_entry) << std::endl; return EXIT_SUCCESS; } ``` 此片段展示了怎样利用 `<elf.h>` 定义的数据类型去解码指定路径下的 `.so` 文件,并打印几个关键属性到终端屏幕上[^3]。 --- #### 更新 GLIBC 版本以匹配需求 当遇到诸如 “version `GLIBC_X.XX' not found” 这样的提示时,意味着当前系统的 glibc 版本低于应用程序所期望的标准版本号。此时需考虑升级整个发行版的基础环境或者是单独重新编译定制化版本满足特殊场景的要求[^4]。 注意,在执行任何更改之前务必做好充分备份以防万一出现问题影响正常使用体验! --- ### 总结 综上所述,无论是采用高级脚本语言还是低级系统编程技术都可以有效地处理涉及 `libc.so.6` 的各类任务;同时也要留意不同平台间可能存在的兼容性差异以免引入新的麻烦源码冲突等问题发生。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值