REinject's Blog

我们的功夫再棒,也敌不过洋枪


glibc all in one

/* 目录 */

下载 glibc-all-in-one:

git clone https://github.com/matrix1001/glibc-all-in-one
cd glibc-all-in-one

判断题目给出的 libc 版本:

strings libc.so.6 | grep "GNU C Library"

两种方式获取指定版本的 glibc 库:

编译 glibc

apt install build-essential libssl-dev libgdbm-dev libdb-dev libexpat-dev libncurses5-dev libbz2-dev zlib1g-dev gawk bison binutils texinfo

./build 2.27 amd64

直接下载安装包提取

./download 2.27-3ubuntu1_amd64

ls -alh ./libs/

两种方式使 elf 加载指定 libc:

使用 patchelf 修改 elf 文件加载指定的 libc

下载 patchelf

patchelf --add-needed /root/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc.so.6 ./ezheap
patchelf --set-interpreter /root/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/ld-linux-x86-64.so.2 ./ezheap

原文件会被直接修改。

使用 LD_PRELOAD 环境变量加载指定的 libc

在脚本中利用 LD_PRELOAD 加载指定的 libc,不直接修改 ELF 文件:

libc_version = '2.27-3ubuntu1.6'
file = './ezheap'
p = process([f"/root/glibc-all-in-one/libs/{libc_version}/ld-linux-x86-64.so.2",
             file], env={"LD_PRELOAD": f"/root/glibc-all-in-one/libs/{libc_version}/libc.so.6"})

使用指定版本编译

使用我修改后的 glibc-all-in-one,下载指定版本的 glibc:

./download 2.27-3ubuntu1_amd64

使用此 Makefile 编译 (需要使用对应适配的 gcc 编译器,版本太高会报错):

# 指定编译器
CXX := g++-9

# 源文件
SRC := main.cpp

# 输出可执行文件名称
TARGET := main

# 自定义 glibc 的路径
GLIBC_INCLUDE := /root/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/.dev/usr/include
GLIBC_LIB := /root/glibc-all-in-one/libs/2.27-3ubuntu1_amd64

# 编译选项
CXXFLAGS := -I$(GLIBC_INCLUDE) -std=c++11 -D__STRICT_ANSI__
LDFLAGS := -L$(GLIBC_LIB) -Wl,-rpath=$(GLIBC_LIB) -Wl,--dynamic-linker=$(GLIBC_LIB)/ld-linux-x86-64.so.2

# 目标规则
$(TARGET): $(SRC)
        $(CXX) $(CXXFLAGS) $< -o $@ $(LDFLAGS) -ldl -lpthread -lm -nostartfiles

# 清理生成的文件
.PHONY: clean
clean:
        rm -f $(TARGET)

或者 g++ 命令:

g++-9 -I/root/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/.dev/usr/include -L/root/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/ -Wl,--rpath=/root/glibc-all-in-one/libs/2.27-3ubuntu1_amd64 -Wl,--dynamic-linker=/root/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/ld-linux-x86-64.so.2 -nostartfiles -o main main.cpp