linux库说明以及如何修改动态链接库
2020-12-16 12:12:04 Author: www.freebuf.com(查看原文) 阅读量:137 收藏

原文来自SecIN社区—作者:tower 

说明

在ctf中共享库的问题一直是一个非常非常非常恶心的问题,这里将会介绍动态链接库的命名以及如何修改一个程序依赖的动态链接库

命名

0x7f387805e000     0x7f3878091000 r-xp    33000 0      /lib/x86_64-linux-gnu/libseccomp.so.2.4.3

  • lib表示库文件
  • so表示动态链接
  • 2.4.3中2表示主本号,4表示次版本,3表示发布版本

主版本是重大升级,不会向上兼容(如python2和3)
次版本是增量升级,添加一些新的接口
发布版本是进行一些错误修正,性能改进等

SO-NAME命名与软链接

用SO-NAME机制来记录共享库的依赖关系

每个库都有自己的SO-NAME知名库名字和主版本号如libc.so.2

SO-NAME相同的两个次版本号不同的库,次版本号大的兼容小的

在linux系统中,系统会为每个共享库在它所在的目录创建一个跟SO-NAME相同并且指向它的软连接如系统中存在共享库/lib/libfoo.so.2.6.1那么linux共享库管理程序会为它创建一个指向它的软链接/lib/libfoo.so.2

也有一些不标准的命名,如libc.so.6 还有ld-2.6.1.so被命名为ld-linux.so

libc.so.6

SO-NAME的好处

  • 每个最新的库覆盖掉旧的,保持在主版本号内最新
  • 可执行文件pwn如果依赖于libc.2.23.so会在.dynamic段DT_NEED字段写入libc.so.6写入SO-NAME可以避免库更新之后不能运行

NEEDED字段

编译时链接

在运行时需要链接一个程序可以加 -lxxx,如-lpthread编译器会根据当前环境在系统中的相关路径查找最新版本的库一般用-L指定搜索路径

对于链接方式分为动态和静态链接在ld使用-static选项时会搜索静态链接库(如libc.a.2.23)默认是动态

共享库的路径

  • /lib存放系统最关键的共享库,一般是/bin,/sbin目录下程序需要的库还有系统启动时需要的库
  • /usr/lib开发时可能用到的库
  • /usr/local/lib跟操作系统本身不十分相关的库,一些第三方软件安装的库

共享库查找过程

如果DT_NEED存放绝对路径就从这个路径找

如果没有会在/lib,/usr/lib由 /etc/ld.so.conf配置文件指定的目录中查找共享库。

为了加快遍历速度,有一个叫ldconfig的程序各个共享库创建删除或更新相应的SO-NAME,把这些SO-NAME集中起来放到/etc/ld.so.cache

所以正常更新或替换共享库需要运行一次ldconfig

共享库创建和安装

编译

-share选项表示输出结果是共享库类型

-Wl选项可以传递给连接器选项 -Wl,-soname,my_soname可以指定SO-NAME(如果不指定这个库就没有soname,用ldconfig也没用)

安装

包含两步1.创建SO-NAME软连接。 2.告诉编译器和程序如何查找共享库

  • 把共享库复制到/lib或者/usr/lib等然后运行ldconfig
  • ldconfig -n shared_library_directory在编译程序时提供-L-lLD_LIBRARY_PATH也可以用来指定

共享库替换

修改环境变量替换

LD_LIBRARY_PATH临时改变某个应用程序的共享库查找路径而不会影响系统中其他程序
类似于/lib/ld-linux.so.2 -binary-path /home/user /bin/ls

LD_PRELOAD优先级更高,无论程序是否依赖动态库,被指定的动态库都会被加载

系统将会从下面搜索库

  • LD_PRELOAD
  • LD_LIBRARY_PATH指定的路径
  • /etc/ld.so.cache指定的路径
  • 默认共享目录,/usr/lib /lib等

修改二进制文件更改libc版本

有一个项目可以下载很多版本的libc
https://github.com/matrix1001/glibc-all-in-one

➜  git clone https://github.com/matrix1001/glibc-all-in-one.git
➜  glibc-all-in-one ./update_list
➜  glibc-all-in-one cat list  可以看到获取到的库名字
➜  glibc-all-in-one ./download 2.23-0ubuntu10_i386  后面的库名字是上一条命令看到的任意一个

然后需要创建目录,拷贝文件到对应目录

➜  glibc-all-in-one sduo mkdir -p /glibc/2.27/64/lib/
➜  glibc-all-in-one sudo cp ./libs/2.27-3ubuntu1.2_amd64/* /glibc/2.27/64/lib

为了完成上面的操作写了一个简单的脚本,完成更新列表,下载库,拷贝的过程

import os

def download(LibcNameList):
    for item in LibcNameList:
        os.system("./download {}".format(item))

def mkDir(name):
    for item in name:
        os.system("sudo mkdir -p /glibc/{}/64/lib/".format(item))
        os.system("sudo mkdir -p /glibc/{}/32/lib/".format(item))

def getName(LibcNameList):
    name=[]
    for item in LibcNameList:
        if item.split("-")[0] in name or item.split("-")[0]=="" :
            continue
        else:
            name.append(item.split("-")[0])
    print("name:",name)
    return name

os.system("./update_list")

f=open("./list","r")
content=f.read()

print(content)
LibcNameList=content.split("\n")

name=getName(LibcNameList)
mkDir(name)


download(LibcNameList)
for LibcName in LibcNameList:
    

    for item in name:
        
        if (item in  LibcName) and ("amd64" in LibcName):
            
            os.system("sudo cp ./libs/{}/* /glibc/{}/64/lib/".format(LibcName,item))
        if (item in LibcName) and ("i386" in LibcName):
            os.system("sudo cp ./libs/{}/* /glibc/{}/32/lib/".format(LibcName,item))

clibc

#!/bin/bash

FILE_NAME=$1
LIBC_VERSION=$2
WORKDIR=$(pwd)

LIBC_DIR=/glibc
LIBC_DIR=$(find $LIBC_DIR -name "$LIBC_VERSION*")
if [ "$LIBC_DIR" = "" ];then
    echo "Not support version or your $LIBC_DIR don't have libc"
    exit
fi

EBIT=$(file $FILE_NAME |awk '{print$3}'|cut -c 1-2)
if [ $EBIT -eq "32" ];then
    libc_dir=$LIBC_DIR/32/lib
elif [ $EBIT -eq "64" ];then
    libc_dir=$LIBC_DIR/64/lib
else
    echo "It's not a elf file"
    exit
fi

if  [ "$3" ] 
then
	patchelf --set-interpreter $libc_dir/ld-$LIBC_VERSION.so --set-rpath $WORKDIR/ $1
else
	patchelf --set-interpreter $libc_dir/ld-$LIBC_VERSION.so --set-rpath $libc_dir/ $1
fi
echo "success!!!"
clibc filename 2.23

修改二进制文件

测试结果.png

上图可以看到用clibc修改之后(左图)和Ubuntu16自带的libc2.23加载空间没有什么区别
注:图中看到的ld-2.23.so是链接器

https://github.com/tower111/pwn-change-libc


文章来源: https://www.freebuf.com/sectool/257977.html
如有侵权请联系:admin#unsafe.sh